From 978ae0a650f8d0584ad9b2b904261a6e95cff0cf Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 20 Mar 2019 18:04:59 +0000 Subject: [PATCH 0001/1594] [Java] Use type safe Java version in build script. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 358d489170..8ce655307b 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ defaultTasks 'clean', 'build', 'shadowJar', 'install' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() -def sbeJavaVersion = '1.8' +def sbeJavaVersion = JavaVersion.VERSION_1_8 group = sbeGroup version = sbeVersion From 221ee6ad2b6187ddfbcc1147ca517b9de83bacd3 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Mon, 25 Mar 2019 12:47:56 +0900 Subject: [PATCH 0002/1594] [C] Fix compliance to C. Initializing struct return values by initialization lists is not allowed in C. --- .../java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 4e6fdea6af..5d70dcf181 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -555,9 +555,11 @@ private CharSequence generateVarData( " if (!%5$s_set_sbe_position(\n" + " codec, %5$s_sbe_position(codec) + %3$d + length_field_value))\n" + " {\n" + - " return {NULL, 0};\n" + + " struct %6$s_string_view ret = {NULL, 0};\n" + + " return ret;\n" + " }\n" + - " return {field_ptr, length_field_value};\n" + + " struct %6$s_string_view ret = {field_ptr, length_field_value};\n" + + " return ret;\n" + "}\n", propertyName, generateStringViewNotPresentCondition(token.version()), From c8614b6b0743e7d8f9467088eb9883f3c9df8b45 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Fri, 1 Feb 2019 16:22:45 +0900 Subject: [PATCH 0003/1594] [C] Add a dummy source to check compliance. Since the tests are still C++ sources, the C headers are compiled with a C++ compiler. This makes it difficult to notice breaking C compatibility. --- sbe-tool/src/test/c/CComplianceTest.c | 10 ++++++++++ sbe-tool/src/test/c/CMakeLists.txt | 9 +++++++++ 2 files changed, 19 insertions(+) create mode 100644 sbe-tool/src/test/c/CComplianceTest.c diff --git a/sbe-tool/src/test/c/CComplianceTest.c b/sbe-tool/src/test/c/CComplianceTest.c new file mode 100644 index 0000000000..671dac9fe4 --- /dev/null +++ b/sbe-tool/src/test/c/CComplianceTest.c @@ -0,0 +1,10 @@ +#include +#include + +#include +#include +#include +#include + +int main() { +} diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index c4bb461d69..1134cd2f4f 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -55,3 +55,12 @@ add_custom_target(c_codecs DEPENDS ${GENERATED_CODECS}) sbe_test(BoundsCheckTest c_codecs) sbe_test(CodeGenTest c_codecs) sbe_test(GroupWithDataTest c_codecs) + +# Compile a dummy C source to test C compliance of generated headers. +add_executable(CComplianceTest CComplianceTest.c) + +target_include_directories(CComplianceTest + PRIVATE ${C_CODEC_TARGET_DIR} +) + +add_dependencies(CComplianceTest c_codecs) From c98346264c9562e7f42d8bbed4507452c6e36977 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Tue, 19 Mar 2019 12:04:02 +0900 Subject: [PATCH 0004/1594] [C++] Fix the formatting of the generated code. --- .../sbe/generation/cpp/CppGenerator.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index d4aa228a5f..db8b40a635 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -212,7 +212,7 @@ private static void generateGroupClassHeader( indent + "public:\n", formatClassName(groupName), dimensionsClassName)); - sb.append(String.format("\n" + + sb.append(String.format( indent + " inline void wrapForDecode(char *buffer, std::uint64_t *pos," + " const std::uint64_t actingVersion, const std::uint64_t bufferLength)\n" + indent + " {\n" + @@ -356,7 +356,7 @@ private static CharSequence generateGroupProperty( className, propertyName)); - sb.append(String.format("\n" + + sb.append(String.format( indent + " static SBE_CONSTEXPR std::uint16_t %1$sId() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + @@ -640,7 +640,7 @@ private void generateChoiceSet(final List tokens) throws IOException out.append(generateClassDeclaration(bitSetName)); out.append(generateFixedFlyweightCode(bitSetName, tokens.get(0).encodedLength())); - out.append(String.format( + out.append(String.format("\n" + " %1$s &clear()\n" + " {\n" + " %2$s zero = 0;\n" + @@ -679,8 +679,8 @@ private void generateEnum(final List tokens) throws IOException out.append(generateEnumLookupMethod(tokens.subList(1, tokens.size() - 1), enumToken)); - out.append("};\n"); - out.append(CppUtil.closingBraces(ir.namespaces().length)).append("#endif\n"); + out.append("};\n\n"); + out.append(CppUtil.closingBraces(ir.namespaces().length)).append("\n#endif\n"); } } @@ -698,8 +698,8 @@ private void generateComposite(final List tokens) throws IOException out.append(generateCompositePropertyElements( compositeName, tokens.subList(1, tokens.size() - 1), BASE_INDENT)); - out.append("};\n"); - out.append(CppUtil.closingBraces(ir.namespaces().length)).append("#endif\n"); + out.append("};\n\n"); + out.append(CppUtil.closingBraces(ir.namespaces().length)).append("\n#endif\n"); } } @@ -793,7 +793,7 @@ private CharSequence generateEnumValues(final List tokens, final Token en final Encoding encoding = encodingToken.encoding(); sb.append( - " enum Value \n" + + " enum Value\n" + " {\n"); for (final Token token : tokens) @@ -1040,7 +1040,7 @@ private static CharSequence generateClassDeclaration(final String className) private static CharSequence generateEnumDeclaration(final String name) { - return "class " + name + "\n{\npublic:\n\n"; + return "class " + name + "\n{\npublic:\n"; } private CharSequence generateCompositePropertyElements( @@ -2085,7 +2085,7 @@ private static Object generateBitsetProperty(final String propertyName, final To bitsetName, propertyName)); - sb.append(String.format("\n" + + sb.append(String.format( indent + " %1$s &%2$s()\n" + indent + " {\n" + indent + " m_%2$s.wrap(m_buffer, m_offset + %3$d, m_actingVersion, m_bufferLength);\n" + @@ -2121,7 +2121,7 @@ private static Object generateCompositeProperty(final String propertyName, final compositeName, propertyName)); - sb.append(String.format("\n" + + sb.append(String.format( indent + " %1$s &%2$s()\n" + indent + " {\n" + indent + " m_%2$s.wrap(m_buffer, m_offset + %3$d, m_actingVersion, m_bufferLength);\n" + From caf1aae1f7a42b2b81f64227edf9f1da2f901cc0 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Tue, 19 Mar 2019 13:35:54 +0900 Subject: [PATCH 0005/1594] [C] Remove unused types from choice sets. --- .../sbe/generation/c/CGenerator.java | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 5d70dcf181..c08372432c 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -681,27 +681,6 @@ private void generateChoiceSet(final CharSequence[] scope, final List tok final String bitSetName = formatScopedName(scope, bitsetToken.applicableTypeName()); out.append(generateFileHeader(bitSetName, null)); out.append(generateFixedFlyweightStruct(bitSetName)); - out.append(String.format("\n" + - "enum %1$s_meta_attribute\n" + - "{\n" + - " %1$s_meta_attribute_EPOCH,\n" + - " %1$s_meta_attribute_TIME_UNIT,\n" + - " %1$s_meta_attribute_SEMANTIC_TYPE,\n" + - " %1$s_meta_attribute_PRESENCE\n" + - "};\n\n" + - - "union %1$s_float_as_uint\n" + - "{\n" + - " float fp_value;\n" + - " uint32_t uint_value;\n" + - "};\n\n" + - - "union %1$s_double_as_uint\n" + - "{\n" + - " double fp_value;\n" + - " uint64_t uint_value;\n" + - "};\n", - bitSetName)); out.append(generateFixedFlyweightCodeFunctions(bitSetName, bitsetToken.encodedLength())); out.append(String.format("\n" + From f1c40d15373cf30a515d573f8f86fb9a64def9a3 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Tue, 19 Mar 2019 14:44:43 +0900 Subject: [PATCH 0006/1594] [C] Fix bitset property encoding length function name. --- .../java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index c08372432c..3106a7b833 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -2227,10 +2227,11 @@ private static void generateBitsetPropertyFunctions( containingStructName)); sb.append(String.format("\n" + - "SBE_ONE_DEF size_t %1$s_encoding_length(void)\n" + + "SBE_ONE_DEF size_t %s_%s_encoding_length(void)\n" + "{\n" + - " return %2$d;\n" + + " return %d;\n" + "}\n", + containingStructName, propertyName, token.encoding().primitiveType().size())); } From a34388cc78192e0630f329999db98c2a43d126dd Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Tue, 19 Mar 2019 14:47:03 +0900 Subject: [PATCH 0007/1594] [C] Fix bitset property accessor function storage-class. --- .../main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 3106a7b833..2cd0552d5b 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -2212,7 +2212,7 @@ private static void generateBitsetPropertyFunctions( final int offset = token.offset(); sb.append(String.format("\n" + - "struct %1$s *%4$s_%2$s(struct %4$s *const codec, struct %1$s *const bitset)\n" + + "SBE_ONE_DEF struct %1$s *%4$s_%2$s(struct %4$s *const codec, struct %1$s *const bitset)\n" + "{\n" + " return %1$s_wrap(\n" + " bitset,\n" + From fd90d24e06f81b8b06c02e87097b1aed555bda31 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Tue, 19 Mar 2019 17:19:17 +0900 Subject: [PATCH 0008/1594] [C++] Const qualify arguments of array property methods. --- .../co/real_logic/sbe/generation/cpp/CppGenerator.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index db8b40a635..749fe66d90 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1322,7 +1322,7 @@ private CharSequence generateArrayProperty( indent); sb.append(String.format("\n" + - indent + " %1$s %2$s(std::uint64_t index) const\n" + + indent + " %1$s %2$s(const std::uint64_t index) const\n" + indent + " {\n" + indent + " if (index >= %3$d)\n" + indent + " {\n" + @@ -1344,7 +1344,7 @@ private CharSequence generateArrayProperty( indent); sb.append(String.format("\n" + - indent + " %1$s %2$s(std::uint64_t index, %3$s value)\n" + + indent + " %1$s %2$s(const std::uint64_t index, const %3$s value)\n" + indent + " {\n" + indent + " if (index >= %4$d)\n" + indent + " {\n" + @@ -1361,7 +1361,7 @@ private CharSequence generateArrayProperty( storeValue)); sb.append(String.format("\n" + - indent + " std::uint64_t get%1$s(char *dst, std::uint64_t length) const\n" + + indent + " std::uint64_t get%1$s(char *const dst, const std::uint64_t length) const\n" + indent + " {\n" + indent + " if (length > %2$d)\n" + indent + " {\n" + @@ -1379,7 +1379,7 @@ private CharSequence generateArrayProperty( cppTypeName)); sb.append(String.format("\n" + - indent + " %1$s &put%2$s(const char *src) SBE_NOEXCEPT\n" + + indent + " %1$s &put%2$s(const char *const src) SBE_NOEXCEPT\n" + indent + " {\n" + indent + " std::memcpy(m_buffer + m_offset + %3$d, src, sizeof(%4$s) * %5$d);\n" + indent + " return *this;\n" + @@ -1426,7 +1426,7 @@ private CharSequence generateArrayProperty( sb.append(String.format("\n" + indent + " #if __cplusplus >= 201703L\n" + - indent + " %1$s &put%2$s(std::string_view str)\n" + + indent + " %1$s &put%2$s(const std::string_view str)\n" + indent + " {\n" + indent + " const size_t srcLength = str.length();\n" + indent + " if (srcLength > %4$d)\n" + From cc7aecacbe800a38bd042dd4dfd8192d9fc8e3bd Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Tue, 19 Mar 2019 17:21:30 +0900 Subject: [PATCH 0009/1594] [C++] Return a reference from array property setter. --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 749fe66d90..953c45f25c 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1344,7 +1344,7 @@ private CharSequence generateArrayProperty( indent); sb.append(String.format("\n" + - indent + " %1$s %2$s(const std::uint64_t index, const %3$s value)\n" + + indent + " %1$s &%2$s(const std::uint64_t index, const %3$s value)\n" + indent + " {\n" + indent + " if (index >= %4$d)\n" + indent + " {\n" + From 1d92f70137821fd2d9e5c736b9863ecad81748f0 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 25 Mar 2019 09:37:17 +0000 Subject: [PATCH 0010/1594] [C] Tidy up. --- sbe-tool/src/test/c/CodeGenTest.cpp | 37 ++++++++++++++--------- sbe-tool/src/test/c/GroupWithDataTest.cpp | 8 ++--- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index edca8e1dc7..628e27bdee 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -20,6 +20,7 @@ #include #include +#include #define CGT(name) code_generation_test_##name @@ -486,7 +487,8 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeHeaderPlusCarCorrectly) const char *bp = buffer; std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer)); - std::uint64_t carSz = encodeCar(buffer, CGT(messageHeader_encoded_length)(), sizeof(buffer) - CGT(messageHeader_encoded_length)()); + std::uint64_t carSz = encodeCar( + buffer, CGT(messageHeader_encoded_length)(), sizeof(buffer) - CGT(messageHeader_encoded_length)()); EXPECT_EQ(hdrSz, expectedHeaderSize); EXPECT_EQ(carSz, expectedCarSize); @@ -498,12 +500,13 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeHeaderPlusCarCorrectly) EXPECT_EQ(std::string(bp + activationCodePosition, ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); } -TEST_F(CodeGenTest, shouldbeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) +TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) { char buffer[BUFFER_LEN]; std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer)); - std::uint64_t carSz = encodeCar(buffer, CGT(messageHeader_encoded_length)(), sizeof(buffer) - CGT(messageHeader_encoded_length)()); + std::uint64_t carSz = encodeCar( + buffer, CGT(messageHeader_encoded_length)(), sizeof(buffer) - CGT(messageHeader_encoded_length)()); EXPECT_EQ(hdrSz, expectedHeaderSize); EXPECT_EQ(carSz, expectedCarSize); @@ -533,12 +536,12 @@ TEST_F(CodeGenTest, shouldbeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) EXPECT_EQ(CGT(car_serialNumber)(&m_carDecoder), SERIAL_NUMBER); EXPECT_EQ(CGT(car_modelYear)(&m_carDecoder), MODEL_YEAR); { - CGT(booleanType) out; + CGT(booleanType) out = CGT(booleanType_NULL_VALUE); ASSERT_TRUE(CGT(car_available)(&m_carDecoder, &out)); EXPECT_EQ(out, AVAILABLE); } { - CGT(model) out; + CGT(model) out = CGT(model_NULL_VALUE); ASSERT_TRUE(CGT(car_code)(&m_carDecoder, &out)); EXPECT_EQ(out, CODE); } @@ -549,7 +552,9 @@ TEST_F(CodeGenTest, shouldbeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) } EXPECT_EQ(CGT(car_vehicleCode_length)(), VEHICLE_CODE_LENGTH); - EXPECT_EQ(std::string(CGT(car_vehicleCode_buffer)(&m_carDecoder), VEHICLE_CODE_LENGTH), std::string(VEHICLE_CODE, VEHICLE_CODE_LENGTH)); + EXPECT_EQ( + std::string(CGT(car_vehicleCode_buffer)(&m_carDecoder), VEHICLE_CODE_LENGTH), + std::string(VEHICLE_CODE, VEHICLE_CODE_LENGTH)); CGT(optionalExtras) extras; if (!CGT(car_extras)(&m_carDecoder, &extras)) @@ -572,9 +577,7 @@ TEST_F(CodeGenTest, shouldbeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) EXPECT_EQ(CGT(engine_maxRpm)(), 9000); EXPECT_EQ(CGT(engine_manufacturerCode_length)(), MANUFACTURER_CODE_LENGTH); EXPECT_EQ( - std::string( - CGT(engine_manufacturerCode_buffer)(&engine), - MANUFACTURER_CODE_LENGTH), + std::string(CGT(engine_manufacturerCode_buffer)(&engine), MANUFACTURER_CODE_LENGTH), std::string(MANUFACTURER_CODE, MANUFACTURER_CODE_LENGTH)); EXPECT_EQ(CGT(engine_fuel_length)(), 6u); EXPECT_EQ(std::string(CGT(engine_fuel)(), 6), std::string("Petrol")); @@ -588,21 +591,27 @@ TEST_F(CodeGenTest, shouldbeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) EXPECT_EQ(CGT(car_fuelFigures_speed)(&fuelFigures), fuel1Speed); EXPECT_EQ(CGT(car_fuelFigures_mpg)(&fuelFigures), fuel1Mpg); EXPECT_EQ(CGT(car_fuelFigures_usageDescription_length)(&fuelFigures), FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH); - EXPECT_EQ(std::string(CGT(car_fuelFigures_usageDescription)(&fuelFigures), FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH), FUEL_FIGURES_1_USAGE_DESCRIPTION); + EXPECT_EQ( + std::string(CGT(car_fuelFigures_usageDescription)(&fuelFigures), FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH), + FUEL_FIGURES_1_USAGE_DESCRIPTION); ASSERT_TRUE(CGT(car_fuelFigures_has_next)(&fuelFigures)); CGT(car_fuelFigures_next)(&fuelFigures); EXPECT_EQ(CGT(car_fuelFigures_speed)(&fuelFigures), fuel2Speed); EXPECT_EQ(CGT(car_fuelFigures_mpg)(&fuelFigures), fuel2Mpg); EXPECT_EQ(CGT(car_fuelFigures_usageDescription_length)(&fuelFigures), FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH); - EXPECT_EQ(std::string(CGT(car_fuelFigures_usageDescription)(&fuelFigures), FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH), FUEL_FIGURES_2_USAGE_DESCRIPTION); + EXPECT_EQ( + std::string(CGT(car_fuelFigures_usageDescription)(&fuelFigures), FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH), + FUEL_FIGURES_2_USAGE_DESCRIPTION); ASSERT_TRUE(CGT(car_fuelFigures_has_next)(&fuelFigures)); CGT(car_fuelFigures_next)(&fuelFigures); EXPECT_EQ(CGT(car_fuelFigures_speed)(&fuelFigures), fuel3Speed); EXPECT_EQ(CGT(car_fuelFigures_mpg)(&fuelFigures), fuel3Mpg); EXPECT_EQ(CGT(car_fuelFigures_usageDescription_length)(&fuelFigures), FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH); - EXPECT_EQ(std::string(CGT(car_fuelFigures_usageDescription)(&fuelFigures), FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH), FUEL_FIGURES_3_USAGE_DESCRIPTION); + EXPECT_EQ( + std::string(CGT(car_fuelFigures_usageDescription)(&fuelFigures), FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH), + FUEL_FIGURES_3_USAGE_DESCRIPTION); CGT(car_performanceFigures) performanceFigures; CGT(car_get_performanceFigures)(&m_carDecoder, &performanceFigures); @@ -672,7 +681,7 @@ struct CallbacksForEach CallbacksForEach() : countOfFuelFigures(0), countOfPerformanceFigures(0), countOfAccelerations(0) {} }; -TEST_F(CodeGenTest, shouldbeAbleUseOnStackCodecsAndGroupForEach) +TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) { char buffer[BUFFER_LEN]; CGT(messageHeader) hdr; @@ -816,7 +825,7 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) std::string activationCode(ACTIVATION_CODE, ACTIVATION_CODE_LENGTH); char buffer[BUFFER_LEN]; - std::uint64_t baseOffset = CGT(messageHeader_encoded_length)(); + std::uint64_t baseOffset = static_cast(CGT(messageHeader_encoded_length)()); CGT(car) car; if (!CGT(car_wrap_for_encode)(&car, buffer, baseOffset, sizeof(buffer))) { diff --git a/sbe-tool/src/test/c/GroupWithDataTest.cpp b/sbe-tool/src/test/c/GroupWithDataTest.cpp index f00c856e11..c6f59c13c6 100644 --- a/sbe-tool/src/test/c/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/c/GroupWithDataTest.cpp @@ -286,7 +286,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage1Correctly) EXPECT_EQ(sz, offset); } -TEST_F(GroupWithDataTest, shouldbeAbleToEncodeAndDecodeTestMessage1Correctly) +TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage1Correctly) { char buffer[2048]; std::uint64_t sz = encodeTestMessage1(buffer, 0, sizeof(buffer)); @@ -375,7 +375,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage2Correctly) EXPECT_EQ(sz, offset); } -TEST_F(GroupWithDataTest, shouldbeAbleToEncodeAndDecodeTestMessage2Correctly) +TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage2Correctly) { char buffer[2048]; std::uint64_t sz = encodeTestMessage2(buffer, 0, sizeof(buffer)); @@ -514,7 +514,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage3Correctly) EXPECT_EQ(sz, offset); } -TEST_F(GroupWithDataTest, shouldbeAbleToEncodeAndDecodeTestMessage3Correctly) +TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage3Correctly) { char buffer[2048]; std::uint64_t sz = encodeTestMessage3(buffer, 0, sizeof(buffer)); @@ -648,7 +648,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage4Correctly) EXPECT_EQ(sz, offset); } -TEST_F(GroupWithDataTest, shouldbeAbleToEncodeAndDecodeTestMessage4Correctly) +TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage4Correctly) { char buffer[2048]; std::uint64_t sz = encodeTestMessage4(buffer, 0, sizeof(buffer)); From 6ffbd10ffa70820b989d3f867d682dbe9b8be9c8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 25 Mar 2019 09:45:13 +0000 Subject: [PATCH 0011/1594] [C] Add new line to the end of generated C files. --- .../uk/co/real_logic/sbe/generation/c/CGenerator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 2cd0552d5b..0e59112086 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -163,7 +163,7 @@ public void generate() throws IOException generateGroups(sb, ir.namespaces(), groups, structName, structName); out.append(sb); out.append(generateVarData(structName, structName, varData)); - out.append("\n#endif"); + out.append("\n#endif\n"); } } } @@ -704,7 +704,7 @@ private void generateChoiceSet(final CharSequence[] scope, final List tok cTypeName(bitsetToken.encoding().primitiveType()))); out.append(generateChoices(bitSetName, tokens.subList(1, tokens.size() - 1))); - out.append("\n#endif"); + out.append("\n#endif\n"); } } @@ -722,7 +722,7 @@ private void generateEnum(final CharSequence[] scope, final List tokens) out.append(generateEnumLookupFunction(scope, tokens.subList(1, tokens.size() - 1), enumToken)); - out.append("\n#endif"); + out.append("\n#endif\n"); } } @@ -770,7 +770,7 @@ private void generateComposite(final CharSequence[] scope, final List tok out.append(generateCompositePropertyFunctions( scope, compositeName, tokens.subList(1, tokens.size() - 1))); - out.append("\n#endif"); + out.append("\n#endif\n"); } } From ce60d0b009cbbfca4eb8ec9b3d889ec5eb8198c1 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Tue, 26 Mar 2019 20:56:12 +0900 Subject: [PATCH 0012/1594] [C] Suppress maybe-uninitialized warnings in GCC. GCC is known to emit false positives when it cannot detect if a variable is initialized. --- .../sbe/generation/c/CGenerator.java | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 0e59112086..2c65adbb7a 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -337,7 +337,14 @@ private static void generateGroupHeaderFunctions( "SBE_ONE_DEF uint64_t %3$s_sbe_position(const struct %3$s *const codec)\n" + "{\n" + + "#if defined(__GNUG__) && !defined(__clang__)\n" + + "#pragma GCC diagnostic push\n" + + "#pragma GCC diagnostic ignored \"-Wmaybe-uninitialized\"\n" + + "#endif\n" + " return *codec->position_ptr;\n" + + "#if defined(__GNUG__) && !defined(__clang__)\n" + + "#pragma GCC diagnostic pop\n" + + "#endif\n" + "}\n\n" + "SBE_ONE_DEF bool %3$s_set_sbe_position(struct %3$s *const codec, const uint64_t position)\n" + @@ -358,14 +365,28 @@ private static void generateGroupHeaderFunctions( "SBE_ONE_DEF bool %3$s_has_next(const struct %3$s *const codec)\n" + "{\n" + + "#if defined(__GNUG__) && !defined(__clang__)\n" + + "#pragma GCC diagnostic push\n" + + "#pragma GCC diagnostic ignored \"-Wmaybe-uninitialized\"\n" + + "#endif\n" + " return codec->index + 1 < codec->count;\n" + + "#if defined(__GNUG__) && !defined(__clang__)\n" + + "#pragma GCC diagnostic pop\n" + + "#endif\n" + "}\n\n" + "SBE_ONE_DEF struct %3$s *%3$s_next(struct %3$s *const codec)\n" + "{\n" + " codec->offset = *codec->position_ptr;\n" + + "#if defined(__GNUG__) && !defined(__clang__)\n" + + "#pragma GCC diagnostic push\n" + + "#pragma GCC diagnostic ignored \"-Wmaybe-uninitialized\"\n" + + "#endif\n" + " if (SBE_BOUNDS_CHECK_EXPECT(((codec->offset + codec->block_length) " + "> codec->buffer_length), false))\n" + + "#if defined(__GNUG__) && !defined(__clang__)\n" + + "#pragma GCC diagnostic pop\n" + + "#endif\n" + " {\n" + " errno = E108;\n" + " return NULL;\n" + @@ -1341,7 +1362,14 @@ private CharSequence generateLoadValue( { sb.append(String.format( " %1$s val;\n" + + "#if defined(__GNUG__) && !defined(__clang__)\n" + + "#pragma GCC diagnostic push\n" + + "#pragma GCC diagnostic ignored \"-Wmaybe-uninitialized\"\n" + + "#endif\n" + " memcpy(&val, codec->buffer + codec->offset + %2$s, sizeof(%1$s));\n" + + "#if defined(__GNUG__) && !defined(__clang__)\n" + + "#pragma GCC diagnostic pop\n" + + "#endif\n" + " %4$s %3$s(val);", cTypeName, offsetStr, @@ -1400,7 +1428,14 @@ private CharSequence generateStoreValue( { sb.append(String.format( " %1$s val = %2$s(value);\n" + - " memcpy(codec->buffer + codec->offset + %3$s, &val, sizeof(%1$s));", + "#if defined(__GNUG__) && !defined(__clang__)\n" + + "#pragma GCC diagnostic push\n" + + "#pragma GCC diagnostic ignored \"-Wmaybe-uninitialized\"\n" + + "#endif\n" + + " memcpy(codec->buffer + codec->offset + %3$s, &val, sizeof(%1$s));\n" + + "#if defined(__GNUG__) && !defined(__clang__)\n" + + "#pragma GCC diagnostic pop\n" + + "#endif", cTypeName, byteOrderStr, offsetStr)); From fe75ad1dd5d4c4fa80d8081cc9e4b5b67bafeb1b Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Tue, 26 Mar 2019 20:58:27 +0900 Subject: [PATCH 0013/1594] [C/C++] Turn on warnings as errors in tests for AppleClang, Clang and GCC. --- sbe-tool/src/test/c/CMakeLists.txt | 3 +++ sbe-tool/src/test/cpp/CMakeLists.txt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index 1134cd2f4f..d5d2a85b53 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -20,6 +20,9 @@ function(sbe_test name) PRIVATE ${GTEST_SOURCE_DIR}/googletest/include PRIVATE ${C_CODEC_TARGET_DIR} ) + target_compile_options("C${name}" PRIVATE $<$:-Werror>) + target_compile_options("C${name}" PRIVATE $<$:-Werror>) + target_compile_options("C${name}" PRIVATE $<$:-Werror>) target_link_libraries("C${name}" ${GTEST_LIBS} ${CMAKE_THREAD_LIBS_INIT}) add_test(NAME C${name} COMMAND C${name} WORKING_DIRECTORY ${C_CODEC_TARGET_DIR}) add_dependencies(C${name} gtest) diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index c946466424..c3531029e4 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -20,6 +20,9 @@ function(sbe_test name) PRIVATE ${GTEST_SOURCE_DIR}/googletest/include PRIVATE ${CXX_CODEC_TARGET_DIR} ) + target_compile_options("${name}" PRIVATE $<$:-Werror>) + target_compile_options("${name}" PRIVATE $<$:-Werror>) + target_compile_options("${name}" PRIVATE $<$:-Werror>) target_link_libraries("${name}" sbe ${GTEST_LIBS} ${CMAKE_THREAD_LIBS_INIT}) add_test(NAME ${name} COMMAND ${name} WORKING_DIRECTORY ${CXX_CODEC_TARGET_DIR}) add_dependencies(${name} gtest) From 77d8782848a233dabf43125bee8dda2d11f0bb37 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Mon, 25 Mar 2019 21:04:23 +0900 Subject: [PATCH 0014/1594] [C++] Fix the indentation of generated code. --- .../sbe/generation/cpp/CppGenerator.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 953c45f25c..cefe9976b1 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -387,7 +387,7 @@ private static CharSequence generateGroupProperty( sb.append(String.format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + indent + " {\n" + - indent + " return %2$d;\n" + + indent + " return %2$d;\n" + indent + " }\n\n" + indent + " bool %1$sInActingVersion() const SBE_NOEXCEPT\n" + @@ -437,11 +437,11 @@ private CharSequence generateVarData(final String className, final List t indent + " const char *%1$s()\n" + indent + " {\n" + "%2$s" + - indent + " %4$s lengthFieldValue;\n" + - indent + " std::memcpy(&lengthFieldValue, m_buffer + sbePosition(), sizeof(%4$s));\n" + - indent + " const char *fieldPtr = m_buffer + sbePosition() + %3$d;\n" + - indent + " sbePosition(sbePosition() + %3$d + %5$s(lengthFieldValue));\n" + - indent + " return fieldPtr;\n" + + indent + " %4$s lengthFieldValue;\n" + + indent + " std::memcpy(&lengthFieldValue, m_buffer + sbePosition(), sizeof(%4$s));\n" + + indent + " const char *fieldPtr = m_buffer + sbePosition() + %3$d;\n" + + indent + " sbePosition(sbePosition() + %3$d + %5$s(lengthFieldValue));\n" + + indent + " return fieldPtr;\n" + indent + " }\n", formatPropertyName(propertyName), generateTypeFieldNotPresentCondition(token.version(), indent), @@ -539,7 +539,7 @@ private CharSequence generateVarData(final String className, final List t indent + " {\n" + indent + " if (str.length() > %6$d)\n" + indent + " {\n" + - indent + " throw std::runtime_error(\"std::string too long for length type [E109]\");\n" + + indent + " throw std::runtime_error(\"std::string too long for length type [E109]\");\n" + indent + " }\n" + indent + " std::uint64_t lengthOfLengthField = %3$d;\n" + indent + " std::uint64_t lengthPosition = sbePosition();\n" + @@ -585,7 +585,7 @@ private void generateVarDataDescriptors( sb.append(String.format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + indent + " {\n" + - indent + " return %2$d;\n" + + indent + " return %2$d;\n" + indent + " }\n\n" + indent + " bool %1$sInActingVersion() SBE_NOEXCEPT\n" + @@ -1365,7 +1365,7 @@ private CharSequence generateArrayProperty( indent + " {\n" + indent + " if (length > %2$d)\n" + indent + " {\n" + - indent + " throw std::runtime_error(\"length too large for get%1$s [E106]\");\n" + + indent + " throw std::runtime_error(\"length too large for get%1$s [E106]\");\n" + indent + " }\n\n" + "%3$s" + @@ -1431,7 +1431,7 @@ private CharSequence generateArrayProperty( indent + " const size_t srcLength = str.length();\n" + indent + " if (srcLength > %4$d)\n" + indent + " {\n" + - indent + " throw std::runtime_error(\"string too large for put%2$s [E106]\");\n" + + indent + " throw std::runtime_error(\"string too large for put%2$s [E106]\");\n" + indent + " }\n\n" + indent + " size_t length = srcLength < %4$d ? srcLength : %4$d;\n" + @@ -1449,7 +1449,7 @@ private CharSequence generateArrayProperty( indent + " const size_t srcLength = str.length();\n" + indent + " if (srcLength > %4$d)\n" + indent + " {\n" + - indent + " throw std::runtime_error(\"string too large for put%2$s [E106]\");\n" + + indent + " throw std::runtime_error(\"string too large for put%2$s [E106]\");\n" + indent + " }\n\n" + indent + " size_t length = srcLength < %4$d ? srcLength : %4$d;\n" + @@ -1791,8 +1791,8 @@ private CharSequence generateMessageFlyweightCode(final String className, final " }\n\n" + " %10$s &wrapForDecode(\n" + - " char *buffer, const std::uint64_t offset, const std::uint64_t actingBlockLength,\n" + - " const std::uint64_t actingVersion, const std::uint64_t bufferLength)\n" + + " char *buffer, const std::uint64_t offset, const std::uint64_t actingBlockLength,\n" + + " const std::uint64_t actingVersion, const std::uint64_t bufferLength)\n" + " {\n" + " return *this = %10$s(buffer, offset, bufferLength, actingBlockLength, actingVersion);\n" + " }\n\n" + @@ -1916,7 +1916,7 @@ private void generateFieldCommonMethods( sb.append(String.format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + indent + " {\n" + - indent + " return %2$d;\n" + + indent + " return %2$d;\n" + indent + " }\n\n" + indent + " bool %1$sInActingVersion() SBE_NOEXCEPT\n" + @@ -1936,7 +1936,7 @@ private void generateFieldCommonMethods( sb.append(String.format("\n" + indent + " static SBE_CONSTEXPR std::size_t %1$sEncodingOffset() SBE_NOEXCEPT\n" + indent + " {\n" + - indent + " return %2$d;\n" + + indent + " return %2$d;\n" + indent + " }\n", propertyName, encodingToken.offset())); From 5b76f730117904c729c80300df1431fd44206396 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 27 Mar 2019 14:11:08 +0000 Subject: [PATCH 0015/1594] [Java] Add module opens to avoid warnings on reflective access. --- build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.gradle b/build.gradle index 8ce655307b..c6ca59e29d 100644 --- a/build.gradle +++ b/build.gradle @@ -154,6 +154,11 @@ subprojects { } test { + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + jvmArgs('--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED') + jvmArgs('--add-opens', 'java.base/sun.nio.ch=ALL-UNNAMED') + } + testLogging { showStandardStreams = true exceptionFormat = 'full' From 1ccb982aa1b72cde7adb181cf9efac822f2039d2 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Thu, 28 Mar 2019 13:34:16 +0000 Subject: [PATCH 0016/1594] [Java] Upgrade to Gradle 5.3.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 55190 -> 55616 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 18 +++++++++++++++++- gradlew.bat | 18 +++++++++++++++++- 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index c6ca59e29d..b04416779b 100644 --- a/build.gradle +++ b/build.gradle @@ -764,6 +764,6 @@ task uploadToMavenCentral { } wrapper { - gradleVersion = '5.2.1' + gradleVersion = '5.3.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 87b738cbd051603d91cc39de6cb000dd98fe6b02..5c2d1cf016b3885f6930543d57b744ea8c220a1a 100644 GIT binary patch delta 3320 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 Date: Thu, 28 Mar 2019 15:00:22 +0000 Subject: [PATCH 0017/1594] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7ac7084289..66cef0f118 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.12.3 +    1.12.4 ``` @@ -65,7 +65,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.12.4-SNAPSHOT.jar my_sbe_input.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.12.5-SNAPSHOT.jar my_sbe_input.xml C++ Build using CMake From 2ec0148794fb9e815d9179cc9020e5d91e85af9f Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Thu, 28 Mar 2019 08:48:17 -0700 Subject: [PATCH 0018/1594] 1.12.4 released. --- build.gradle | 2 +- version.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b04416779b..280331a4f1 100644 --- a/build.gradle +++ b/build.gradle @@ -128,7 +128,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.18' - compile 'org.agrona:agrona:0.9.34' + compile 'org.agrona:agrona:0.9.35' testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:2.25.1' diff --git a/version.txt b/version.txt index c5c89918bc..89c881bc9c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.12.4-SNAPSHOT +1.12.4 From 0b49e9775402cf08b1dcff512fcc991e2c583dee Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Thu, 28 Mar 2019 09:38:53 -0700 Subject: [PATCH 0019/1594] post releaqse bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 89c881bc9c..f7820aaa85 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.12.4 +1.12.5-SNAPSHOT From 94fb51651a56d02e14c4f892eced39dbb55fd622 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Thu, 28 Mar 2019 14:20:49 -0700 Subject: [PATCH 0020/1594] [C++]: add output-on-failure to ctest args. --- cppbuild/cppbuild | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppbuild/cppbuild b/cppbuild/cppbuild index 51a2faa084..88763c769c 100755 --- a/cppbuild/cppbuild +++ b/cppbuild/cppbuild @@ -22,4 +22,4 @@ fi mkdir -p $BUILD_DIR -(cd $BUILD_DIR && cmake -G "Unix Makefiles" $SOURCE_DIR && make clean && make -j "$ncpus" all && ctest -C Release) +(cd $BUILD_DIR && cmake -G "Unix Makefiles" $SOURCE_DIR && make clean && make -j "$ncpus" all && ctest -C Release --output-on-failure) From a754cd790ea8ad11319f2681d49927d3dd878da1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 5 Apr 2019 21:47:16 +0100 Subject: [PATCH 0021/1594] [Java] Upgrade to javadoc-links to 3.2.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 280331a4f1..6a9e2efbc1 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.github.johnrengelman.shadow' version '5.0.0' apply false - id "io.freefair.javadoc-links" version "3.1.4" apply false + id "io.freefair.javadoc-links" version "3.2.0" apply false } defaultTasks 'clean', 'build', 'shadowJar', 'install' From 33b6fc041fce60a54d77abfb824f0c21d9e0d11c Mon Sep 17 00:00:00 2001 From: billsegall Date: Sat, 6 Apr 2019 10:51:43 +1000 Subject: [PATCH 0022/1594] Issue #660. Add Length() and GetBytes() methods for VarStrings --- csharp/sbe-samples/CarExample.cs | 5 ++++ .../generation/csharp/CSharpGenerator.java | 30 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/csharp/sbe-samples/CarExample.cs b/csharp/sbe-samples/CarExample.cs index c7239fe4c9..4a8807d05a 100644 --- a/csharp/sbe-samples/CarExample.cs +++ b/csharp/sbe-samples/CarExample.cs @@ -126,14 +126,18 @@ public static int Encode(Car car, DirectBuffer directBuffer, int bufferOffset) fuelFigures.Next(); // move to the first element fuelFigures.Speed = 30; fuelFigures.Mpg = 35.9f; + fuelFigures.SetUsageDescription(Encoding.GetEncoding(Car.FuelFiguresGroup.UsageDescriptionCharacterEncoding).GetBytes("Urban Cycle")); fuelFigures.Next(); // second fuelFigures.Speed = 55; fuelFigures.Mpg = 49.0f; + fuelFigures.SetUsageDescription(Encoding.GetEncoding(Car.FuelFiguresGroup.UsageDescriptionCharacterEncoding).GetBytes("Combined Cycle")); fuelFigures.Next(); fuelFigures.Speed = 75; fuelFigures.Mpg = 40.0f; + fuelFigures.SetUsageDescription(Encoding.GetEncoding(Car.FuelFiguresGroup.UsageDescriptionCharacterEncoding).GetBytes("Highway Cycle")); + Car.PerformanceFiguresGroup perfFigures = car.PerformanceFiguresCount(2); // demonstrates how to create a nested group perfFigures.Next(); @@ -237,6 +241,7 @@ public static void Decode(Car car, var fuelFigures = fuelFiguresGroup.Next(); sb.Append("\ncar.fuelFigures.speed=").Append(fuelFigures.Speed); sb.Append("\ncar.fuelFigures.mpg=").Append(fuelFigures.Mpg); + sb.Append("\ncar.fuelFigures.UsageDescription=").Append(Encoding.GetEncoding(Car.FuelFiguresGroup.UsageDescriptionCharacterEncoding).GetString(fuelFigures.GetUsageDescriptionBytes())); } // The second way to access a repeating group is to use an iterator diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 1840190591..01243ab104 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -359,6 +359,17 @@ private CharSequence generateVarData(final List tokens, final String inde propertyName, sizeOfLengthField)); + sb.append(String.format(indent + "\n" + + indent + "public int %1$sLength()\n" + + indent + "{\n" + + indent + INDENT + "_buffer.CheckLimit(_parentMessage.Limit + %2$d);\n" + + indent + INDENT + "return (int)_buffer.%3$sGet%4$s(_parentMessage.Limit);\n" + + indent + "}\n", + propertyName, + sizeOfLengthField, + lengthTypePrefix, + byteOrderStr)); + sb.append(String.format("\n" + indent + "public int Get%1$s(byte[] dst, int dstOffset, int length) =>\n" + indent + INDENT + "Get%1$s(new Span(dst, dstOffset, length));\n", @@ -383,6 +394,25 @@ private CharSequence generateVarData(final List tokens, final String inde lengthTypePrefix, byteOrderStr)); + sb.append(String.format(indent + "\n" + + indent + "// Allocates and returns a new byte array\n" + + indent + "public byte[] Get%1$sBytes()\n" + + indent + "{\n" + + indent + INDENT + "const int sizeOfLengthField = %2$d;\n" + + indent + INDENT + "int limit = _parentMessage.Limit;\n" + + indent + INDENT + "_buffer.CheckLimit(limit + sizeOfLengthField);\n" + + indent + INDENT + "int dataLength = (int)_buffer.%3$sGet%4$s(limit);\n" + + indent + INDENT + "byte[] data = new byte[dataLength];\n" + + indent + INDENT + "_parentMessage.Limit = limit + sizeOfLengthField + dataLength;\n" + + + indent + INDENT + "_buffer.GetBytes(limit + sizeOfLengthField, data);\n\n" + + indent + INDENT + "return data;\n" + + indent + "}\n", + propertyName, + sizeOfLengthField, + lengthTypePrefix, + byteOrderStr)); + sb.append(String.format("\n" + indent + "public int Set%1$s(byte[] src, int srcOffset, int length) =>\n" + indent + INDENT + "Set%1$s(new ReadOnlySpan(src, srcOffset, length));\n", From 1240dd7a986fdc0f774d10568ccccbcb19cffb18 Mon Sep 17 00:00:00 2001 From: billsegall Date: Sat, 6 Apr 2019 12:01:31 +1000 Subject: [PATCH 0023/1594] Work around checkStyleMain's arbitrary method length rule --- .../real_logic/sbe/generation/csharp/CSharpGenerator.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 01243ab104..3c96b1c1df 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -339,7 +339,6 @@ private CharSequence generateVarData(final List tokens, final String inde if (token.signal() == Signal.BEGIN_VAR_DATA) { generateFieldIdMethod(sb, token, indent); - final Token varDataToken = Generators.findFirst("varData", tokens, i); final String characterEncoding = varDataToken.encoding().characterEncoding(); generateCharacterEncodingMethod(sb, token.name(), characterEncoding, indent); @@ -358,7 +357,6 @@ private CharSequence generateVarData(final List tokens, final String inde indent + "public const int %sHeaderSize = %d;\n", propertyName, sizeOfLengthField)); - sb.append(String.format(indent + "\n" + indent + "public int %1$sLength()\n" + indent + "{\n" + @@ -369,12 +367,10 @@ private CharSequence generateVarData(final List tokens, final String inde sizeOfLengthField, lengthTypePrefix, byteOrderStr)); - sb.append(String.format("\n" + indent + "public int Get%1$s(byte[] dst, int dstOffset, int length) =>\n" + indent + INDENT + "Get%1$s(new Span(dst, dstOffset, length));\n", propertyName)); - sb.append(String.format("\n" + indent + "public int Get%1$s(Span dst)\n" + indent + "{\n" + @@ -393,7 +389,6 @@ private CharSequence generateVarData(final List tokens, final String inde sizeOfLengthField, lengthTypePrefix, byteOrderStr)); - sb.append(String.format(indent + "\n" + indent + "// Allocates and returns a new byte array\n" + indent + "public byte[] Get%1$sBytes()\n" + @@ -412,12 +407,10 @@ private CharSequence generateVarData(final List tokens, final String inde sizeOfLengthField, lengthTypePrefix, byteOrderStr)); - sb.append(String.format("\n" + indent + "public int Set%1$s(byte[] src, int srcOffset, int length) =>\n" + indent + INDENT + "Set%1$s(new ReadOnlySpan(src, srcOffset, length));\n", propertyName)); - sb.append(String.format("\n" + indent + "public int Set%1$s(ReadOnlySpan src)\n" + indent + "{\n" + @@ -435,7 +428,6 @@ private CharSequence generateVarData(final List tokens, final String inde byteOrderStr)); } } - return sb; } From 63f29118a84103256c72349aa7df1a268895cfa8 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sat, 6 Apr 2019 09:29:19 +0100 Subject: [PATCH 0024/1594] [Java] Tidy up after merge of PR #622. --- .../sbe/generation/csharp/CSharpGenerator.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 3c96b1c1df..e13e734a21 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -35,6 +35,7 @@ import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; +@SuppressWarnings("MethodLength") public class CSharpGenerator implements CodeGenerator { private static final String META_ATTRIBUTE_ENUM = "MetaAttribute"; @@ -357,6 +358,7 @@ private CharSequence generateVarData(final List tokens, final String inde indent + "public const int %sHeaderSize = %d;\n", propertyName, sizeOfLengthField)); + sb.append(String.format(indent + "\n" + indent + "public int %1$sLength()\n" + indent + "{\n" + @@ -367,10 +369,12 @@ private CharSequence generateVarData(final List tokens, final String inde sizeOfLengthField, lengthTypePrefix, byteOrderStr)); + sb.append(String.format("\n" + indent + "public int Get%1$s(byte[] dst, int dstOffset, int length) =>\n" + indent + INDENT + "Get%1$s(new Span(dst, dstOffset, length));\n", propertyName)); + sb.append(String.format("\n" + indent + "public int Get%1$s(Span dst)\n" + indent + "{\n" + @@ -389,6 +393,7 @@ private CharSequence generateVarData(final List tokens, final String inde sizeOfLengthField, lengthTypePrefix, byteOrderStr)); + sb.append(String.format(indent + "\n" + indent + "// Allocates and returns a new byte array\n" + indent + "public byte[] Get%1$sBytes()\n" + @@ -407,10 +412,12 @@ private CharSequence generateVarData(final List tokens, final String inde sizeOfLengthField, lengthTypePrefix, byteOrderStr)); + sb.append(String.format("\n" + indent + "public int Set%1$s(byte[] src, int srcOffset, int length) =>\n" + indent + INDENT + "Set%1$s(new ReadOnlySpan(src, srcOffset, length));\n", propertyName)); + sb.append(String.format("\n" + indent + "public int Set%1$s(ReadOnlySpan src)\n" + indent + "{\n" + @@ -492,7 +499,7 @@ private CharSequence generateCompositePropertyElements(final List tokens, final Token token = tokens.get(i); final String propertyName = formatPropertyName(token.name()); - // FIXME: do I need to pass classname down here for disambiguation + // FIXME: do I need to pass class name down here for disambiguation switch (token.signal()) { case ENCODING: From f8aa62f2773054043b11ca2fb6489a2d5ad360d1 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sat, 6 Apr 2019 09:47:53 +0100 Subject: [PATCH 0025/1594] [Java] Upgrade to Checkstyle 8.19 and Mockito 2.26.0. --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 6a9e2efbc1..fddc5029f9 100644 --- a/build.gradle +++ b/build.gradle @@ -126,17 +126,17 @@ subprojects { jar.enabled = true dependencies { - checkstyle 'com.puppycrawl.tools:checkstyle:8.18' + checkstyle 'com.puppycrawl.tools:checkstyle:8.19' compile 'org.agrona:agrona:0.9.35' testCompile 'junit:junit:4.12' - testCompile 'org.mockito:mockito-core:2.25.1' + testCompile 'org.mockito:mockito-core:2.26.0' testCompile 'org.hamcrest:hamcrest-library:1.3' } checkstyle { - toolVersion = '8.18' + toolVersion = '8.19' } compileJava { From 5e8324479e81abda7507e41aa30c994336b67018 Mon Sep 17 00:00:00 2001 From: billsegall Date: Sat, 6 Apr 2019 19:59:18 +1000 Subject: [PATCH 0026/1594] Issue#661 Always return a valid bitset type Cope with the case where actionVersion is less than sinceVersion by returning a value of '(bitset)0' --- .gitignore | 1 + build.gradle | 1 + .../generation/csharp/CSharpGenerator.java | 27 ++++++++++++------- sbe-tool/src/test/resources/issue661.xml | 25 +++++++++++++++++ 4 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 sbe-tool/src/test/resources/issue661.xml diff --git a/.gitignore b/.gitignore index 41f4464ce4..24701042d3 100644 --- a/.gitignore +++ b/.gitignore @@ -101,6 +101,7 @@ csharp/sbe-generated/extension csharp/sbe-generated/issue435 csharp/sbe-generated/issue483 csharp/sbe-generated/issue560 +csharp/sbe-generated/issue661 csharp/sbe-generated/since-deprecated csharp/sbe-generated/mktdata/*.cs csharp/sbe-generated/uk_co_real_logic_sbe_benchmarks_fix diff --git a/build.gradle b/build.gradle index fddc5029f9..ab20c34b15 100644 --- a/build.gradle +++ b/build.gradle @@ -656,6 +656,7 @@ task generateGolangCodecsWithXSD(type: JavaExec) { 'sbe-tool/src/test/resources/issue483.xml', 'sbe-tool/src/test/resources/issue488.xml', 'sbe-tool/src/test/resources/issue560.xml', + 'sbe-tool/src/test/resources/issue661.xml', 'sbe-tool/src/test/resources/since-deprecated-test-schema.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', 'gocode/resources/example-composite.xml', diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index e13e734a21..9107c2c5fd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -35,7 +35,6 @@ import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; -@SuppressWarnings("MethodLength") public class CSharpGenerator implements CodeGenerator { private static final String META_ATTRIBUTE_ENUM = "MetaAttribute"; @@ -358,7 +357,6 @@ private CharSequence generateVarData(final List tokens, final String inde indent + "public const int %sHeaderSize = %d;\n", propertyName, sizeOfLengthField)); - sb.append(String.format(indent + "\n" + indent + "public int %1$sLength()\n" + indent + "{\n" + @@ -369,12 +367,10 @@ private CharSequence generateVarData(final List tokens, final String inde sizeOfLengthField, lengthTypePrefix, byteOrderStr)); - sb.append(String.format("\n" + indent + "public int Get%1$s(byte[] dst, int dstOffset, int length) =>\n" + indent + INDENT + "Get%1$s(new Span(dst, dstOffset, length));\n", propertyName)); - sb.append(String.format("\n" + indent + "public int Get%1$s(Span dst)\n" + indent + "{\n" + @@ -393,7 +389,6 @@ private CharSequence generateVarData(final List tokens, final String inde sizeOfLengthField, lengthTypePrefix, byteOrderStr)); - sb.append(String.format(indent + "\n" + indent + "// Allocates and returns a new byte array\n" + indent + "public byte[] Get%1$sBytes()\n" + @@ -412,12 +407,10 @@ private CharSequence generateVarData(final List tokens, final String inde sizeOfLengthField, lengthTypePrefix, byteOrderStr)); - sb.append(String.format("\n" + indent + "public int Set%1$s(byte[] src, int srcOffset, int length) =>\n" + indent + INDENT + "Set%1$s(new ReadOnlySpan(src, srcOffset, length));\n", propertyName)); - sb.append(String.format("\n" + indent + "public int Set%1$s(ReadOnlySpan src)\n" + indent + "{\n" + @@ -499,7 +492,7 @@ private CharSequence generateCompositePropertyElements(final List tokens, final Token token = tokens.get(i); final String propertyName = formatPropertyName(token.name()); - // FIXME: do I need to pass class name down here for disambiguation + // FIXME: do I need to pass classname down here for disambiguation switch (token.signal()) { case ENCODING: @@ -765,6 +758,22 @@ private CharSequence generateArrayFieldNotPresentCondition( sinceVersion); } + private CharSequence generateBitSetNotPresentCondition( + final int sinceVersion, + final String indent, + final String bitSetName) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + INDENT + INDENT + INDENT + "if (_actingVersion < %1$d) return (%2$s)0;\n\n", + sinceVersion, + bitSetName); + } + private CharSequence generateTypeFieldNotPresentCondition( final int sinceVersion, final String indent) @@ -1223,7 +1232,7 @@ private String generateBitSetProperty(final String propertyName, final Token tok indent + INDENT + "}\n", bitSetName, toUpperFirstChar(propertyName), - generateTypeFieldNotPresentCondition(token.version(), indent), + generateBitSetNotPresentCondition(token.version(), indent, bitSetName), bitSetName, typePrefix, offset, diff --git a/sbe-tool/src/test/resources/issue661.xml b/sbe-tool/src/test/resources/issue661.xml new file mode 100644 index 0000000000..d0c29a0c83 --- /dev/null +++ b/sbe-tool/src/test/resources/issue661.xml @@ -0,0 +1,25 @@ + + + + + 0 + 1 + + + + + + + + + + + + + From 55f0b3f2bea1aaef6314f4417ba6d087325be7c4 Mon Sep 17 00:00:00 2001 From: billsegall Date: Sat, 6 Apr 2019 22:40:07 +1000 Subject: [PATCH 0027/1594] Have the benchmarks create a binary. --- csharp/sbe-benchmarks/sbe-benchmarks.csproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/csharp/sbe-benchmarks/sbe-benchmarks.csproj b/csharp/sbe-benchmarks/sbe-benchmarks.csproj index 57801c577e..4205732737 100644 --- a/csharp/sbe-benchmarks/sbe-benchmarks.csproj +++ b/csharp/sbe-benchmarks/sbe-benchmarks.csproj @@ -8,6 +8,9 @@ Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. SBE + + Exe + From ba88b2f7b46d3a9de30fcd56ab4d41d4e1f406ab Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Wed, 27 Mar 2019 17:10:10 +0900 Subject: [PATCH 0028/1594] [C] Add missing storage class specifier. --- .../main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 2c65adbb7a..0219f89034 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -2282,7 +2282,7 @@ private static void generateCompositePropertyFunction( final int offset = token.offset(); sb.append(String.format("\n" + - "struct %1$s *%4$s_%2$s(struct %4$s *const codec, struct %1$s *const composite)\n" + + "SBE_ONE_DEF struct %1$s *%4$s_%2$s(struct %4$s *const codec, struct %1$s *const composite)\n" + "{\n" + " return %1$s_wrap(\n" + " composite,\n" + From 54252c4e3a99000ad3c441ea6c3c80025657729e Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Mon, 8 Apr 2019 20:55:19 +0100 Subject: [PATCH 0029/1594] [Java] Generate overloaded encoder for arrays of 1-4 in length to elide bounds check and extra function calls in encoding. This is useful for values like UUIDs. --- .../resources/example-extension-schema.xml | 4 +- .../sbe/generation/java/JavaGenerator.java | 40 +++++++++++++++++-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/sbe-samples/src/main/resources/example-extension-schema.xml b/sbe-samples/src/main/resources/example-extension-schema.xml index 9c718eda0f..e6b2b0ccfa 100644 --- a/sbe-samples/src/main/resources/example-extension-schema.xml +++ b/sbe-samples/src/main/resources/example-extension-schema.xml @@ -47,6 +47,7 @@ 1 2 + @@ -59,7 +60,8 @@ - + + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index fed3a5d366..519a74d7a2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2067,13 +2067,15 @@ private CharSequence generatePrimitiveArrayPropertyEncode( final String containingClassName, final String propertyName, final Token token, final String indent) { final Encoding encoding = token.encoding(); - final String javaTypeName = javaTypeName(encoding.primitiveType()); + final PrimitiveType primitiveType = encoding.primitiveType(); + final String javaTypeName = javaTypeName(primitiveType); final int offset = token.offset(); final String byteOrderStr = byteOrderString(encoding); final int fieldLength = token.arrayLength(); final int typeSize = sizeOfPrimitive(encoding); final StringBuilder sb = new StringBuilder(); + final String className = formatClassName(containingClassName); generateArrayLengthMethod(propertyName, indent, fieldLength, sb); @@ -2088,15 +2090,45 @@ private CharSequence generatePrimitiveArrayPropertyEncode( indent + " %s;\n\n" + indent + " return this;\n" + indent + " }\n", - formatClassName(containingClassName), + className, propertyName, javaTypeName, fieldLength, offset, typeSize, - generatePut(encoding.primitiveType(), "pos", "value", byteOrderStr))); + generatePut(primitiveType, "pos", "value", byteOrderStr))); - if (encoding.primitiveType() == PrimitiveType.CHAR) + if (fieldLength > 0 && fieldLength <= 4) + { + sb.append(indent) + .append(" public ") + .append(className) + .append(' ').append(propertyName) + .append("(final ").append(javaTypeName).append(" value0"); + + for (int i = 1; i < fieldLength; i++) + { + sb.append(", final ").append(javaTypeName).append(" value").append(i); + } + + sb.append(")\n"); + sb.append(indent).append(" {\n"); + + for (int i = 0; i < fieldLength; i++) + { + final String indexStr = "this.offset + " + (offset + (typeSize * i)); + + sb.append(indent).append(" ") + .append(generatePut(primitiveType, indexStr, "value" + i, byteOrderStr)) + .append(";\n"); + } + + sb.append("\n"); + sb.append(indent).append(" return this;\n"); + sb.append(indent).append(" }\n"); + } + + if (primitiveType == PrimitiveType.CHAR) { generateCharArrayEncodeMethods( containingClassName, propertyName, indent, encoding, offset, fieldLength, sb); From 86ffe958791628c8add586e5e05efb3a8116c843 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 9 Apr 2019 09:24:34 +0100 Subject: [PATCH 0030/1594] [Java] Naming. --- .../sbe/generation/java/JavaGenerator.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 519a74d7a2..d9d8d06264 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2071,13 +2071,13 @@ private CharSequence generatePrimitiveArrayPropertyEncode( final String javaTypeName = javaTypeName(primitiveType); final int offset = token.offset(); final String byteOrderStr = byteOrderString(encoding); - final int fieldLength = token.arrayLength(); + final int arrayLength = token.arrayLength(); final int typeSize = sizeOfPrimitive(encoding); final StringBuilder sb = new StringBuilder(); final String className = formatClassName(containingClassName); - generateArrayLengthMethod(propertyName, indent, fieldLength, sb); + generateArrayLengthMethod(propertyName, indent, arrayLength, sb); sb.append(String.format( indent + " public %s %s(final int index, final %s value)\n" + @@ -2093,12 +2093,12 @@ private CharSequence generatePrimitiveArrayPropertyEncode( className, propertyName, javaTypeName, - fieldLength, + arrayLength, offset, typeSize, generatePut(primitiveType, "pos", "value", byteOrderStr))); - if (fieldLength > 0 && fieldLength <= 4) + if (arrayLength > 0 && arrayLength <= 4) { sb.append(indent) .append(" public ") @@ -2106,7 +2106,7 @@ private CharSequence generatePrimitiveArrayPropertyEncode( .append(' ').append(propertyName) .append("(final ").append(javaTypeName).append(" value0"); - for (int i = 1; i < fieldLength; i++) + for (int i = 1; i < arrayLength; i++) { sb.append(", final ").append(javaTypeName).append(" value").append(i); } @@ -2114,7 +2114,7 @@ private CharSequence generatePrimitiveArrayPropertyEncode( sb.append(")\n"); sb.append(indent).append(" {\n"); - for (int i = 0; i < fieldLength; i++) + for (int i = 0; i < arrayLength; i++) { final String indexStr = "this.offset + " + (offset + (typeSize * i)); @@ -2131,7 +2131,7 @@ private CharSequence generatePrimitiveArrayPropertyEncode( if (primitiveType == PrimitiveType.CHAR) { generateCharArrayEncodeMethods( - containingClassName, propertyName, indent, encoding, offset, fieldLength, sb); + containingClassName, propertyName, indent, encoding, offset, arrayLength, sb); } return sb; From 3aee0d479adab01f807f03f2f73eabcad32605c2 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 9 Apr 2019 10:07:59 +0100 Subject: [PATCH 0031/1594] [C++] Generate overloaded put encoder for arrays of 2-4 in length to elide bounds check and extra function calls in encoding. This is useful for values like UUIDs. --- .../sbe/generation/cpp/CppGenerator.java | 67 ++++++++++++++----- .../sbe/generation/java/JavaGenerator.java | 4 +- 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index cefe9976b1..09762c222e 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1206,6 +1206,7 @@ private CharSequence generateLoadValue( private CharSequence generateStoreValue( final PrimitiveType primitiveType, + final String valueSuffix, final String offsetStr, final ByteOrder byteOrder, final String indent) @@ -1220,11 +1221,12 @@ private CharSequence generateStoreValue( "union sbe_float_as_uint_u" : "union sbe_double_as_uint_u"; sb.append(String.format( - indent + " %1$s val;\n" + - indent + " val.fp_value = value;\n" + - indent + " val.uint_value = %2$s(val.uint_value);\n" + - indent + " std::memcpy(m_buffer + m_offset + %3$s, &val, sizeof(%4$s));\n", + indent + " %1$s val%2$s;\n" + + indent + " val%2$s.fp_value = value%2$s;\n" + + indent + " val%2$s.uint_value = %3$s(val%2$s.uint_value);\n" + + indent + " std::memcpy(m_buffer + m_offset + %4$s, &val%2$s, sizeof(%5$s));\n", stackUnion, + valueSuffix, byteOrderStr, offsetStr, cppTypeName)); @@ -1232,9 +1234,10 @@ private CharSequence generateStoreValue( else { sb.append(String.format( - indent + " %1$s val = %2$s(value);\n" + - indent + " std::memcpy(m_buffer + m_offset + %3$s, &val, sizeof(%1$s));\n", + indent + " %1$s val%2$s = %3$s(value%2$s);\n" + + indent + " std::memcpy(m_buffer + m_offset + %4$s, &val%2$s, sizeof(%1$s));\n", cppTypeName, + valueSuffix, byteOrderStr, offsetStr)); } @@ -1262,7 +1265,7 @@ private CharSequence generateSingleValueProperty( generateLoadValue(primitiveType, Integer.toString(offset), token.encoding().byteOrder(), indent))); final CharSequence storeValue = generateStoreValue( - primitiveType, Integer.toString(offset), token.encoding().byteOrder(), indent); + primitiveType, "", Integer.toString(offset), token.encoding().byteOrder(), indent); sb.append(String.format("\n" + indent + " %1$s &%2$s(const %3$s value)\n" + @@ -1287,13 +1290,14 @@ private CharSequence generateArrayProperty( final StringBuilder sb = new StringBuilder(); + final int arrayLength = token.arrayLength(); sb.append(String.format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t %1$sLength() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n", propertyName, - token.arrayLength())); + arrayLength)); sb.append(String.format("\n" + indent + " const char *%1$s() const SBE_NOEXCEPT\n" + @@ -1333,12 +1337,13 @@ private CharSequence generateArrayProperty( indent + " }\n", cppTypeName, propertyName, - token.arrayLength(), + arrayLength, generateFieldNotPresentCondition(token.version(), token.encoding(), indent), loadValue)); final CharSequence storeValue = generateStoreValue( primitiveType, + "", String.format("%d + (index * %d)", offset, primitiveType.size()), token.encoding().byteOrder(), indent); @@ -1357,7 +1362,7 @@ private CharSequence generateArrayProperty( containingClassName, propertyName, cppTypeName, - token.arrayLength(), + arrayLength, storeValue)); sb.append(String.format("\n" + @@ -1373,7 +1378,7 @@ private CharSequence generateArrayProperty( indent + " return length;\n" + indent + " }\n", toUpperFirstChar(propertyName), - token.arrayLength(), + arrayLength, generateArrayFieldNotPresentCondition(token.version(), indent), offset, cppTypeName)); @@ -1388,7 +1393,39 @@ private CharSequence generateArrayProperty( toUpperFirstChar(propertyName), offset, cppTypeName, - token.arrayLength())); + arrayLength)); + + if (arrayLength > 1 && arrayLength <= 4) + { + sb.append("\n") + .append(indent) + .append(" ") + .append(containingClassName) + .append(" &put").append(toUpperFirstChar(propertyName)) + .append("(const ").append(cppTypeName).append(" value0"); + + for (int i = 1; i < arrayLength; i++) + { + sb.append(", const ").append(cppTypeName).append(" value").append(i); + } + + sb.append(")\n"); + sb.append(indent).append(" {\n"); + + for (int i = 0; i < arrayLength; i++) + { + sb.append(generateStoreValue( + primitiveType, + Integer.toString(i), + String.format("%d + (%d * %d)", offset, i, primitiveType.size()), + token.encoding().byteOrder(), + indent)); + } + + sb.append("\n"); + sb.append(indent).append(" return *this;\n"); + sb.append(indent).append(" }\n"); + } if (token.encoding().primitiveType() == PrimitiveType.CHAR) { @@ -1405,7 +1442,7 @@ private CharSequence generateArrayProperty( indent + " }\n", toUpperFirstChar(propertyName), offset, - token.arrayLength())); + arrayLength)); sb.append(String.format("\n" + indent + " #if __cplusplus >= 201703L\n" + @@ -1422,7 +1459,7 @@ private CharSequence generateArrayProperty( indent + " #endif\n", toUpperFirstChar(propertyName), offset, - token.arrayLength())); + arrayLength)); sb.append(String.format("\n" + indent + " #if __cplusplus >= 201703L\n" + @@ -1465,7 +1502,7 @@ private CharSequence generateArrayProperty( containingClassName, toUpperFirstChar(propertyName), offset, - token.arrayLength())); + arrayLength)); } return sb; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index d9d8d06264..82b54ddec3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2098,12 +2098,12 @@ private CharSequence generatePrimitiveArrayPropertyEncode( typeSize, generatePut(primitiveType, "pos", "value", byteOrderStr))); - if (arrayLength > 0 && arrayLength <= 4) + if (arrayLength > 1 && arrayLength <= 4) { sb.append(indent) .append(" public ") .append(className) - .append(' ').append(propertyName) + .append(" put").append(Generators.toUpperFirstChar(propertyName)) .append("(final ").append(javaTypeName).append(" value0"); for (int i = 1; i < arrayLength; i++) From a13f677e8a06a60d25e2bcbb1f2d70471a3578b5 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 9 Apr 2019 10:08:46 +0100 Subject: [PATCH 0032/1594] [Java] Resolve conflict with overloads in name for put encoders on arrays and provide example usage. --- .../real_logic/sbe/examples/ExampleUsingGeneratedStub.java | 5 +---- sbe-samples/src/main/resources/example-extension-schema.xml | 4 ++-- sbe-samples/src/main/resources/example-schema.xml | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java index 7bde807e66..6f24c618ca 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java @@ -109,10 +109,7 @@ public static int encode( .code(Model.A) .putVehicleCode(VEHICLE_CODE, 0); - for (int i = 0, size = CarEncoder.someNumbersLength(); i < size; i++) - { - car.someNumbers(i, i); - } + car.putSomeNumbers(1, 2, 3, 4); car.extras() .clear() diff --git a/sbe-samples/src/main/resources/example-extension-schema.xml b/sbe-samples/src/main/resources/example-extension-schema.xml index e6b2b0ccfa..a55e464cbb 100644 --- a/sbe-samples/src/main/resources/example-extension-schema.xml +++ b/sbe-samples/src/main/resources/example-extension-schema.xml @@ -12,7 +12,7 @@ - + @@ -47,7 +47,7 @@ 1 2 - + diff --git a/sbe-samples/src/main/resources/example-schema.xml b/sbe-samples/src/main/resources/example-schema.xml index c01a6f581f..7894e903a3 100644 --- a/sbe-samples/src/main/resources/example-schema.xml +++ b/sbe-samples/src/main/resources/example-schema.xml @@ -12,7 +12,7 @@ - + From c1c351029ca08d11b2b1d56daa731080a1fd0878 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 9 Apr 2019 10:15:22 +0100 Subject: [PATCH 0033/1594] [C++] Add SBE_NOEXCEPT to generated put array overload. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 09762c222e..f97b499669 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1402,14 +1402,16 @@ private CharSequence generateArrayProperty( .append(" ") .append(containingClassName) .append(" &put").append(toUpperFirstChar(propertyName)) - .append("(const ").append(cppTypeName).append(" value0"); + .append("(\n") + .append(indent).append(" ") + .append("const ").append(cppTypeName).append(" value0"); for (int i = 1; i < arrayLength; i++) { sb.append(", const ").append(cppTypeName).append(" value").append(i); } - sb.append(")\n"); + sb.append(") SBE_NOEXCEPT\n"); sb.append(indent).append(" {\n"); for (int i = 0; i < arrayLength; i++) From 23447ef8d66a2756f494e9c1140628bb96f59989 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 11 Apr 2019 10:37:25 +0100 Subject: [PATCH 0034/1594] [Java] Upgrade to Mockito 2.27.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ab20c34b15..b986b76d33 100644 --- a/build.gradle +++ b/build.gradle @@ -131,7 +131,7 @@ subprojects { compile 'org.agrona:agrona:0.9.35' testCompile 'junit:junit:4.12' - testCompile 'org.mockito:mockito-core:2.26.0' + testCompile 'org.mockito:mockito-core:2.27.0' testCompile 'org.hamcrest:hamcrest-library:1.3' } From 521e19c58149fe6979bbda7c33743a26221a06f7 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 11 Apr 2019 11:27:32 +0100 Subject: [PATCH 0035/1594] [C++] Remove redundant code for issue #668. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index f97b499669..fdfebba34c 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1473,8 +1473,7 @@ private CharSequence generateArrayProperty( indent + " throw std::runtime_error(\"string too large for put%2$s [E106]\");\n" + indent + " }\n\n" + - indent + " size_t length = srcLength < %4$d ? srcLength : %4$d;\n" + - indent + " std::memcpy(m_buffer + m_offset + %3$d, str.data(), length);\n" + + indent + " std::memcpy(m_buffer + m_offset + %3$d, str.data(), srcLength);\n" + indent + " for (size_t start = srcLength; start < %4$d; ++start)\n" + indent + " {\n" + indent + " m_buffer[m_offset + %3$d + start] = 0;\n" + @@ -1491,8 +1490,7 @@ private CharSequence generateArrayProperty( indent + " throw std::runtime_error(\"string too large for put%2$s [E106]\");\n" + indent + " }\n\n" + - indent + " size_t length = srcLength < %4$d ? srcLength : %4$d;\n" + - indent + " std::memcpy(m_buffer + m_offset + %3$d, str.c_str(), length);\n" + + indent + " std::memcpy(m_buffer + m_offset + %3$d, str.c_str(), srcLength);\n" + indent + " for (size_t start = srcLength; start < %4$d; ++start)\n" + indent + " {\n" + indent + " m_buffer[m_offset + %3$d + start] = 0;\n" + From a98194e8ff4acf5c2194c896c956e169d03fdb4a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 11 Apr 2019 14:15:49 +0100 Subject: [PATCH 0036/1594] [C++] Improve codec formatting. --- .../sbe/generation/cpp/CppGenerator.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index fdfebba34c..e766b6c645 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1397,18 +1397,19 @@ private CharSequence generateArrayProperty( if (arrayLength > 1 && arrayLength <= 4) { - sb.append("\n") - .append(indent) - .append(" ") - .append(containingClassName) - .append(" &put").append(toUpperFirstChar(propertyName)) - .append("(\n") - .append(indent).append(" ") - .append("const ").append(cppTypeName).append(" value0"); - - for (int i = 1; i < arrayLength; i++) + sb.append("\n").append(indent).append(" ") + .append(containingClassName).append(" &put").append(toUpperFirstChar(propertyName)) + .append("(\n"); + + for (int i = 0; i < arrayLength; i++) { - sb.append(", const ").append(cppTypeName).append(" value").append(i); + sb.append(indent).append(" ") + .append("const ").append(cppTypeName).append(" value").append(i); + + if (i < (arrayLength - 1)) + { + sb.append(",\n"); + } } sb.append(") SBE_NOEXCEPT\n"); @@ -1419,7 +1420,7 @@ private CharSequence generateArrayProperty( sb.append(generateStoreValue( primitiveType, Integer.toString(i), - String.format("%d + (%d * %d)", offset, i, primitiveType.size()), + Integer.toString(offset + (i * primitiveType.size())), token.encoding().byteOrder(), indent)); } @@ -1823,7 +1824,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final " buffer + offset + MessageHeader::encodedLength(),\n" + " 0,\n" + " bufferLength - MessageHeader::encodedLength(),\n" + - " sbeBlockLength()\n," + + " sbeBlockLength(),\n" + " sbeSchemaVersion());\n" + " }\n\n" + From eea0139b2be26a7888ab89bc084449a6292d056e Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Thu, 18 Apr 2019 14:18:13 +0100 Subject: [PATCH 0037/1594] [Java] Remove dead code. --- .../sbe/generation/golang/GolangUtil.java | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java index e5bd06eec4..d514b9f5ce 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java @@ -19,7 +19,6 @@ import uk.co.real_logic.sbe.SbeTool; import uk.co.real_logic.sbe.util.ValidationUtil; -import java.nio.ByteOrder; import java.util.EnumMap; import java.util.Map; @@ -143,34 +142,4 @@ public static String formatTypeName(final String value) { return toUpperFirstChar(value); } - - /** - * Return the Golang formatted byte order encoding string to use for a given byte order and primitiveType - * - * @param byteOrder of the {@link uk.co.real_logic.sbe.ir.Token} - * @param primitiveType of the {@link uk.co.real_logic.sbe.ir.Token} - * @return the string formatted as the byte ordering encoding - */ - public static String formatByteOrderEncoding(final ByteOrder byteOrder, final PrimitiveType primitiveType) - { - switch (primitiveType.size()) - { - case 2: - return "binary.Write(buf, order, obj)"; - - case 4: - return "binary.Write(buf, order, obj)"; - - case 8: - return "binary.Write(buf, order, obj)"; - - default: - return ""; - } - } - - public static String closingBraces(final int count) - { - return new String(new char[count]).replace("\0", "}\n"); - } } From 9613148d955b9dde774658a6b0ec3aed6a3445a6 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Thu, 18 Apr 2019 13:16:46 -0700 Subject: [PATCH 0038/1594] [Java]: issue #670. Check field token for constant encoding on enum. --- .../sbe/generation/java/JavaGenerator.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 82b54ddec3..c202264119 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1323,7 +1323,7 @@ private void generateComposite(final List tokens) throws IOException case BEGIN_ENUM: out.append(sb).append(generateEnumEncoder( - encoderName, propertyName, encodingToken, BASE_INDENT)); + encoderName, encodingToken, propertyName, encodingToken, BASE_INDENT)); break; case BEGIN_SET: @@ -2615,7 +2615,8 @@ private CharSequence generateEncoderFields( break; case BEGIN_ENUM: - sb.append(generateEnumEncoder(containingClassName, propertyName, typeToken, indent)); + sb.append(generateEnumEncoder( + containingClassName, fieldToken, propertyName, typeToken, indent)); break; case BEGIN_SET: @@ -2792,16 +2793,20 @@ private CharSequence generateEnumDecoder( } private CharSequence generateEnumEncoder( - final String containingClassName, final String propertyName, final Token token, final String indent) + final String containingClassName, + final Token fieldToken, + final String propertyName, + final Token typeToken, + final String indent) { - if (token.isConstantEncoding()) + if (fieldToken.isConstantEncoding()) { return ""; } - final String enumName = formatClassName(token.applicableTypeName()); - final Encoding encoding = token.encoding(); - final int offset = token.offset(); + final String enumName = formatClassName(typeToken.applicableTypeName()); + final Encoding encoding = typeToken.encoding(); + final int offset = typeToken.offset(); return String.format("\n" + indent + " public %s %s(final %s value)\n" + From dd7a2282d4300faa6857fa3d1378536cebfa8606 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 19 Apr 2019 12:47:37 +0100 Subject: [PATCH 0039/1594] [Java] Naming. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index e766b6c645..2e7b9bdc9d 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2030,7 +2030,7 @@ private static CharSequence generateEnumFieldNotPresentCondition( private CharSequence generateEnumProperty( final String containingClassName, - final Token signalToken, + final Token fieldToken, final String propertyName, final Token token, final String indent) @@ -2047,11 +2047,11 @@ private CharSequence generateEnumProperty( indent + " return %2$d;\n" + indent + " }\n", propertyName, - signalToken.encodedLength())); + fieldToken.encodedLength())); - if (signalToken.isConstantEncoding()) + if (fieldToken.isConstantEncoding()) { - final String constValue = signalToken.encoding().constValue().toString(); + final String constValue = fieldToken.encoding().constValue().toString(); sb.append(String.format("\n" + indent + " static SBE_CONSTEXPR %1$s::Value %2$sConstValue() SBE_NOEXCEPT\n" + From 45dc0a3348cdcf695fe8a1ee71d8df744ca5adc7 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Thu, 25 Apr 2019 19:23:13 +0100 Subject: [PATCH 0040/1594] [Java] Drop Oracle Java 8 from Travis tests. --- .travis.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 816d315ca0..dacc58a259 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,6 @@ sudo: false matrix: include: - - name: "Oracle Java 8" - language: java - jdk: oraclejdk8 - os: linux - script: ./gradlew - - name: "OpenJDK 8" language: java jdk: openjdk8 From 09d7d9e4767237f132a8df47dcf146c302b5862a Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 26 Apr 2019 12:39:50 +0100 Subject: [PATCH 0041/1594] [Java] Upgrade to Gradle 5.4.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b986b76d33..8c63dfc97c 100644 --- a/build.gradle +++ b/build.gradle @@ -765,6 +765,6 @@ task uploadToMavenCentral { } wrapper { - gradleVersion = '5.3.1' + gradleVersion = '5.4.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 51fb1c466d..ee69dd68d1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.3.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 9a7be490c86d98f0e430e4189bc6c8c4fbef658b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 30 Apr 2019 12:24:23 +0100 Subject: [PATCH 0042/1594] Update build for Ubuntu 16.04 LTS. --- .travis.yml | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index dacc58a259..20d8cf235f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,19 +7,21 @@ matrix: language: java jdk: openjdk8 os: linux + dist: xenial script: ./gradlew - name: "OpenJDK 11" language: java jdk: openjdk11 os: linux + dist: xenial script: ./gradlew - env: COMPILER=g++-6 language: cpp compiler: gcc os: linux - jdk: openjdk8 + dist: xenial addons: apt: packages: @@ -33,7 +35,7 @@ matrix: language: cpp compiler: gcc os: linux - jdk: openjdk8 + dist: xenial addons: apt: packages: @@ -47,7 +49,7 @@ matrix: language: cpp compiler: gcc os: linux - jdk: openjdk8 + dist: xenial addons: apt: packages: @@ -57,59 +59,58 @@ matrix: - ubuntu-toolchain-r-test script: ./cppbuild/cppbuild - - env: COMPILER=clang++-4.0 + - env: COMPILER=clang++-5.0 language: cpp compiler: clang os: linux - jdk: openjdk8 + dist: xenial addons: apt: packages: - - clang-4.0 - - libstdc++-6-dev + - clang-5.0 + - libstdc++-7-dev - libsparsehash-dev sources: - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-4.0 + - llvm-toolchain-xenial-5.0 script: ./cppbuild/cppbuild - - env: COMPILER=clang++-5.0 + - env: COMPILER=clang++-6.0 language: cpp compiler: clang os: linux - jdk: openjdk8 + dist: xenial addons: apt: packages: - - clang-5.0 + - clang-6.0 - libstdc++-7-dev - libsparsehash-dev sources: - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-5.0 + - llvm-toolchain-xenial-6.0 script: ./cppbuild/cppbuild - - env: COMPILER=clang++-6.0 + - env: COMPILER=clang++-7 language: cpp compiler: clang os: linux - jdk: openjdk8 + dist: xenial addons: apt: packages: - - clang-6.0 + - clang-7 - libstdc++-7-dev - libsparsehash-dev sources: - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-6.0 + - llvm-toolchain-xenial-7 script: ./cppbuild/cppbuild - env: COMPILER=clang++ language: c++ compiler: clang os: osx - jdk: openjdk8 script: ./cppbuild/cppbuild before_cache: From 810ba6ce0b3f3798158120f5148fea291d433580 Mon Sep 17 00:00:00 2001 From: Egor Seredin Date: Thu, 2 May 2019 11:49:14 +0700 Subject: [PATCH 0043/1594] [C++] Fix bound check in wrapAndApplyHeader --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 2e7b9bdc9d..094eb68581 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1812,7 +1812,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final " %10$s &wrapAndApplyHeader(" + "char *buffer, const std::uint64_t offset, const std::uint64_t bufferLength)\n" + " {\n" + - " MessageHeader hdr(buffer + offset, bufferLength, sbeSchemaVersion());\n\n" + + " MessageHeader hdr(buffer, offset, bufferLength, sbeSchemaVersion());\n\n" + " hdr\n" + " .blockLength(sbeBlockLength())\n" + @@ -1821,9 +1821,9 @@ private CharSequence generateMessageFlyweightCode(final String className, final " .version(sbeSchemaVersion());\n\n" + " return *this = %10$s(\n" + - " buffer + offset + MessageHeader::encodedLength(),\n" + - " 0,\n" + - " bufferLength - MessageHeader::encodedLength(),\n" + + " buffer,\n" + + " offset + MessageHeader::encodedLength(),\n" + + " bufferLength,\n" + " sbeBlockLength(),\n" + " sbeSchemaVersion());\n" + " }\n\n" + From 5732ab5e0f1ed7a42370795427b499945146a968 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Thu, 2 May 2019 14:32:10 +0100 Subject: [PATCH 0044/1594] [Java] Upgrade to io.freefair.javadoc-links 3.2.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8c63dfc97c..f400947684 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.github.johnrengelman.shadow' version '5.0.0' apply false - id "io.freefair.javadoc-links" version "3.2.0" apply false + id "io.freefair.javadoc-links" version "3.2.1" apply false } defaultTasks 'clean', 'build', 'shadowJar', 'install' From 20f4e0ccbcf2a48ad4d1f3dbb6a5eb278ab3a3f0 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 3 May 2019 08:54:23 +0100 Subject: [PATCH 0045/1594] [Java] Upgrade to Checkstyle 8.20. --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index f400947684..98c5c7fcf3 100644 --- a/build.gradle +++ b/build.gradle @@ -126,7 +126,7 @@ subprojects { jar.enabled = true dependencies { - checkstyle 'com.puppycrawl.tools:checkstyle:8.19' + checkstyle 'com.puppycrawl.tools:checkstyle:8.20' compile 'org.agrona:agrona:0.9.35' @@ -136,7 +136,7 @@ subprojects { } checkstyle { - toolVersion = '8.19' + toolVersion = '8.20' } compileJava { @@ -158,7 +158,7 @@ subprojects { jvmArgs('--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED') jvmArgs('--add-opens', 'java.base/sun.nio.ch=ALL-UNNAMED') } - + testLogging { showStandardStreams = true exceptionFormat = 'full' From f0ce21d355eae8b738aba3a66fc9b57af904c1a3 Mon Sep 17 00:00:00 2001 From: Egor Seredin Date: Fri, 3 May 2019 13:53:18 +0700 Subject: [PATCH 0046/1594] [C++] Remove the dimension member from the codec classes. --- .../sbe/generation/cpp/CppGenerator.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 094eb68581..1f1e1eac42 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -201,8 +201,7 @@ private static void generateGroupClassHeader( indent + " std::uint64_t m_count;\n" + indent + " std::uint64_t m_index;\n" + indent + " std::uint64_t m_offset;\n" + - indent + " std::uint64_t m_actingVersion;\n" + - indent + " %2$s m_dimensions;\n\n" + + indent + " std::uint64_t m_actingVersion;\n\n" + indent + " std::uint64_t *sbePositionPtr() SBE_NOEXCEPT\n" + indent + " {\n" + @@ -210,23 +209,24 @@ private static void generateGroupClassHeader( indent + " }\n\n" + indent + "public:\n", - formatClassName(groupName), dimensionsClassName)); + formatClassName(groupName))); sb.append(String.format( indent + " inline void wrapForDecode(char *buffer, std::uint64_t *pos," + " const std::uint64_t actingVersion, const std::uint64_t bufferLength)\n" + indent + " {\n" + + indent + " %2$s dimensions;\n" + indent + " m_buffer = buffer;\n" + indent + " m_bufferLength = bufferLength;\n" + - indent + " m_dimensions.wrap(m_buffer, *pos, actingVersion, bufferLength);\n" + - indent + " m_blockLength = m_dimensions.blockLength();\n" + - indent + " m_count = m_dimensions.numInGroup();\n" + + indent + " dimensions.wrap(m_buffer, *pos, actingVersion, bufferLength);\n" + + indent + " m_blockLength = dimensions.blockLength();\n" + + indent + " m_count = dimensions.numInGroup();\n" + indent + " m_index = -1;\n" + indent + " m_actingVersion = actingVersion;\n" + indent + " m_positionPtr = pos;\n" + indent + " *m_positionPtr = *m_positionPtr + %1$d;\n" + indent + " }\n", - dimensionHeaderLength)); + dimensionHeaderLength, dimensionsClassName)); final long minCount = numInGroupToken.encoding().applicableMinValue().longValue(); final String minCheck = minCount > 0 ? "count < " + minCount + " || " : ""; @@ -235,6 +235,7 @@ private static void generateGroupClassHeader( indent + " inline void wrapForEncode(char *buffer, const %3$s count," + " std::uint64_t *pos, const std::uint64_t actingVersion, const std::uint64_t bufferLength)\n" + indent + " {\n" + + indent + " %7$s dimensions;\n" + indent + "#if defined(__GNUG__) && !defined(__clang__)\n" + indent + "#pragma GCC diagnostic push\n" + indent + "#pragma GCC diagnostic ignored \"-Wtype-limits\"\n" + @@ -248,9 +249,9 @@ private static void generateGroupClassHeader( indent + "#endif\n" + indent + " m_buffer = buffer;\n" + indent + " m_bufferLength = bufferLength;\n" + - indent + " m_dimensions.wrap(m_buffer, *pos, actingVersion, bufferLength);\n" + - indent + " m_dimensions.blockLength((%1$s)%2$d);\n" + - indent + " m_dimensions.numInGroup((%3$s)count);\n" + + indent + " dimensions.wrap(m_buffer, *pos, actingVersion, bufferLength);\n" + + indent + " dimensions.blockLength((%1$s)%2$d);\n" + + indent + " dimensions.numInGroup((%3$s)count);\n" + indent + " m_index = -1;\n" + indent + " m_count = count;\n" + indent + " m_blockLength = %2$d;\n" + @@ -260,7 +261,8 @@ private static void generateGroupClassHeader( indent + " }\n", cppTypeForBlockLength, blockLength, cppTypeForNumInGroup, dimensionHeaderLength, minCheck, - numInGroupToken.encoding().applicableMaxValue().longValue())); + numInGroupToken.encoding().applicableMaxValue().longValue(), + dimensionsClassName)); sb.append(String.format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t sbeHeaderSize() SBE_NOEXCEPT\n" + From 9233964a6078333ee4e0487a8806edc4c3a5cda0 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 3 May 2019 10:17:52 +0100 Subject: [PATCH 0047/1594] [C++] Use constructor rather than wrap method for dimensions of group and tidy up formatting after merge of PR #674. --- .../sbe/generation/cpp/CppGenerator.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 1f1e1eac42..6e279dda26 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -212,13 +212,15 @@ private static void generateGroupClassHeader( formatClassName(groupName))); sb.append(String.format( - indent + " inline void wrapForDecode(char *buffer, std::uint64_t *pos," + - " const std::uint64_t actingVersion, const std::uint64_t bufferLength)\n" + + indent + " inline void wrapForDecode(\n" + + indent + " char *buffer,\n" + + indent + " std::uint64_t *pos,\n" + + indent + " const std::uint64_t actingVersion,\n" + + indent + " const std::uint64_t bufferLength)\n" + indent + " {\n" + - indent + " %2$s dimensions;\n" + + indent + " %2$s dimensions(buffer, *pos, bufferLength, actingVersion);\n" + indent + " m_buffer = buffer;\n" + indent + " m_bufferLength = bufferLength;\n" + - indent + " dimensions.wrap(m_buffer, *pos, actingVersion, bufferLength);\n" + indent + " m_blockLength = dimensions.blockLength();\n" + indent + " m_count = dimensions.numInGroup();\n" + indent + " m_index = -1;\n" + @@ -232,10 +234,13 @@ private static void generateGroupClassHeader( final String minCheck = minCount > 0 ? "count < " + minCount + " || " : ""; sb.append(String.format("\n" + - indent + " inline void wrapForEncode(char *buffer, const %3$s count," + - " std::uint64_t *pos, const std::uint64_t actingVersion, const std::uint64_t bufferLength)\n" + + indent + " inline void wrapForEncode(\n" + + indent + " char *buffer,\n" + + indent + " const %3$s count,\n" + + indent + " std::uint64_t *pos,\n" + + indent + " const std::uint64_t actingVersion,\n" + + indent + " const std::uint64_t bufferLength)\n" + indent + " {\n" + - indent + " %7$s dimensions;\n" + indent + "#if defined(__GNUG__) && !defined(__clang__)\n" + indent + "#pragma GCC diagnostic push\n" + indent + "#pragma GCC diagnostic ignored \"-Wtype-limits\"\n" + @@ -249,7 +254,7 @@ private static void generateGroupClassHeader( indent + "#endif\n" + indent + " m_buffer = buffer;\n" + indent + " m_bufferLength = bufferLength;\n" + - indent + " dimensions.wrap(m_buffer, *pos, actingVersion, bufferLength);\n" + + indent + " %7$s dimensions(buffer, *pos, bufferLength, actingVersion);\n" + indent + " dimensions.blockLength((%1$s)%2$d);\n" + indent + " dimensions.numInGroup((%3$s)count);\n" + indent + " m_index = -1;\n" + From 8624394edb290aab922c112dde179d4e21ffb13e Mon Sep 17 00:00:00 2001 From: Vadim Platonov Date: Fri, 3 May 2019 13:13:19 +0200 Subject: [PATCH 0048/1594] [Rust] Generate NullVal enum values Mimic the Java generator in generating null enum values. The `NullVal` values are generated even if the enum type is not optional. --- .../real_logic/sbe/generation/rust/RustGenerator.java | 10 ++++++++++ .../sbe/generation/rust/RustGeneratorTest.java | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 41ec20aa82..b71cd1df2f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1356,6 +1356,16 @@ private static void generateEnum(final List enumTokens, final OutputManag .append(",\n"); } + // null value + final Token token = messageBody.get(0); + final Encoding encoding = token.encoding(); + final CharSequence nullVal = generateRustLiteral( + encoding.primitiveType(), encoding.applicableNullValue().toString()); + indent(writer, 1).append("NullVal") + .append(" = ") + .append(nullVal) + .append(",\n"); + writer.append("}\n"); } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java index 2dece0092a..c4c564c5cb 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java @@ -124,6 +124,7 @@ private void assertContainsNumericEnum(final String generatedRust) "pub enum ENUM {\n" + " Value1 = 1u8,\n" + " Value10 = 10u8,\n" + + " NullVal = 255u8,\n" + "}\n"; assertTrue(generatedRust.contains(expectedDeclaration)); } @@ -144,6 +145,7 @@ public void fullGenerateBroadUseCase() throws IOException, InterruptedException "pub enum BooleanType {\n" + " F = 0u8,\n" + " T = 1u8,\n" + + " NullVal = 255u8,\n" + "}\n"; assertTrue(generatedRust.contains(expectedBooleanTypeDeclaration)); final String expectedCharTypeDeclaration = @@ -153,6 +155,7 @@ public void fullGenerateBroadUseCase() throws IOException, InterruptedException " A = 65i8,\n" + " B = 66i8,\n" + " C = 67i8,\n" + + " NullVal = 0i8,\n" + "}\n"; assertTrue(generatedRust.contains(expectedCharTypeDeclaration)); assertRustBuildable(generatedRust, Optional.of("example-schema")); @@ -283,6 +286,7 @@ public void constantEnumFields() throws IOException, InterruptedException " A = 65i8,\n" + " B = 66i8,\n" + " C = 67i8,\n" + + " NullVal = 0i8,\n" + "}\n"; assertContains(rust, expectedCharTypeDeclaration); assertContains(rust, "pub struct ConstantEnumsFields {\n}"); @@ -313,6 +317,7 @@ public void constantFieldsCase() throws IOException, InterruptedException " A = 65i8,\n" + " B = 66i8,\n" + " C = 67i8,\n" + + " NullVal = 0i8,\n" + "}\n"; assertContains(rust, expectedCharTypeDeclaration); final String expectedComposite = From a48c0a6c6d1912d95bfc1d7f8cc25b8c8a8efa79 Mon Sep 17 00:00:00 2001 From: Vadim Platonov Date: Fri, 3 May 2019 15:22:23 +0200 Subject: [PATCH 0049/1594] [Rust] Remove unnecessary mut qualifier in after_member --- .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index b71cd1df2f..c3c0d6dfd7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -648,7 +648,7 @@ private static void writeGroupDecoderTopTypes( indent(out).append("}\n"); indent(out).append("#[inline]\n"); - indent(out, 1, "fn after_member(mut self) -> %s {\n", groupLevelNextDecoderType); + indent(out, 1, "fn after_member(self) -> %s {\n", groupLevelNextDecoderType); indent(out, 2).append("if self.index <= self.max_index {\n"); indent(out, 3).append("Either::Left(self)\n"); indent(out, 2).append("} else {\n").append(INDENT).append(INDENT).append(INDENT) From 2139ea114c540c926f0479f0bd3dbb39ce5d4a4f Mon Sep 17 00:00:00 2001 From: Vadim Platonov Date: Fri, 3 May 2019 15:23:49 +0200 Subject: [PATCH 0050/1594] [Rust] Do not derive Debug on packed struct See [#46043](https://github.com/rust-lang/rust/issues/46043). --- .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index c3c0d6dfd7..05f1975ce6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -197,7 +197,7 @@ private static void generateSingleBitSet(final List tokens, final OutputM final String setType = formatTypeName(beginToken.applicableTypeName()); try (Writer writer = outputManager.createOutput(setType + " bit set")) { - writer.append("#[derive(Debug,Default)]\n"); + writer.append("#[derive(Default)]\n"); writer.append("#[repr(C,packed)]\n"); final String rustPrimitiveType = rustTypeName(beginToken.encoding().primitiveType()); writer.append(format("pub struct %s(pub %s);\n", setType, rustPrimitiveType)); From f736a4fd2b04e5bbc817a15363b6fb0fa42a1a03 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 3 May 2019 17:02:19 +0100 Subject: [PATCH 0051/1594] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 66cef0f118..9e1645e348 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.12.4 +    1.12.5 ``` @@ -65,7 +65,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.12.5-SNAPSHOT.jar my_sbe_input.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.12.6-SNAPSHOT.jar my_sbe_input.xml C++ Build using CMake From 69b5485cf4fdcd8be278ac67c2d7216afd82827c Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 3 May 2019 09:44:04 -0700 Subject: [PATCH 0052/1594] 1.12.5 released. --- build.gradle | 2 +- version.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 98c5c7fcf3..d90af9b12b 100644 --- a/build.gradle +++ b/build.gradle @@ -128,7 +128,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.20' - compile 'org.agrona:agrona:0.9.35' + compile 'org.agrona:agrona:1.0.0' testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:2.27.0' diff --git a/version.txt b/version.txt index f7820aaa85..e0a6b34fb0 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.12.5-SNAPSHOT +1.12.5 From 2eca607ea6d960651ba4988a415ab0c417b79d1e Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 3 May 2019 09:45:57 -0700 Subject: [PATCH 0053/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index e0a6b34fb0..82c1e3710b 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.12.5 +1.12.6-SNAPSHOT From 1f856e44ffd68502ceeec24183a6d4e764c086b1 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 3 May 2019 18:51:07 +0100 Subject: [PATCH 0054/1594] [Java] Remove the need to open module dependencies in test now that Agrona is updated for CompilerUtil. --- build.gradle | 5 ----- 1 file changed, 5 deletions(-) diff --git a/build.gradle b/build.gradle index d90af9b12b..ab35c0fc80 100644 --- a/build.gradle +++ b/build.gradle @@ -154,11 +154,6 @@ subprojects { } test { - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { - jvmArgs('--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED') - jvmArgs('--add-opens', 'java.base/sun.nio.ch=ALL-UNNAMED') - } - testLogging { showStandardStreams = true exceptionFormat = 'full' From c85dd0bac145e382999710461bbbed92211c0e25 Mon Sep 17 00:00:00 2001 From: Vadim Platonov Date: Mon, 6 May 2019 17:02:18 +0200 Subject: [PATCH 0055/1594] [Rust] Pad struct fields when needed Fails on non-standard message header as it's currently generated separately. --- .../sbe/generation/rust/RustGenerator.java | 42 ++++++++++++++++--- .../generation/rust/RustGeneratorTest.java | 2 +- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 05f1975ce6..c48b78ac2b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1399,9 +1399,24 @@ private static void generateSingleComposite(final List tokens, final Outp } } + private static final class RustStructField + { + final boolean isPub; + final String name; + final String value; + + private RustStructField(boolean isPub, String name, String value) { + this.isPub = isPub; + this.name = name; + this.value = value; + } + } + private static void appendStructFields(final Appendable appendable, final List namedTokens) throws IOException { + final List fields = new ArrayList<>(); + int totalSize = 0; for (final NamedToken namedToken : namedTokens) { final Token typeToken = namedToken.typeToken(); @@ -1411,20 +1426,27 @@ private static void appendStructFields(final Appendable appendable, final List 1) { - rustType = format("[%s;%s]", rustPrimitiveType, encodingToken.arrayLength()); + rustType = getRustStaticArrayString(rustPrimitiveType, encodingToken.arrayLength()); } else { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java index c4c564c5cb..0616555225 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java @@ -234,7 +234,7 @@ private void assertRustBuildable(final String generatedRust, final Optional Date: Mon, 6 May 2019 19:08:46 +0200 Subject: [PATCH 0056/1594] Configure build scan plugin --- .travis.yml | 6 +++--- build.gradle | 6 ++++++ gradle.properties | 2 ++ gradle/build-scans.gradle | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 gradle.properties create mode 100644 gradle/build-scans.gradle diff --git a/.travis.yml b/.travis.yml index 20d8cf235f..ad74089fdf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,14 +8,14 @@ matrix: jdk: openjdk8 os: linux dist: xenial - script: ./gradlew + script: ./gradlew --scan - name: "OpenJDK 11" language: java jdk: openjdk11 os: linux dist: xenial - script: ./gradlew + script: ./gradlew --scan - env: COMPILER=g++-6 language: cpp @@ -120,4 +120,4 @@ before_cache: cache: directories: - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ \ No newline at end of file + - $HOME/.gradle/wrapper/ diff --git a/build.gradle b/build.gradle index ab35c0fc80..88ef9cdfff 100644 --- a/build.gradle +++ b/build.gradle @@ -20,11 +20,17 @@ buildscript { } plugins { + id 'com.gradle.build-scan' version '2.3' id 'java' id 'com.github.johnrengelman.shadow' version '5.0.0' apply false id "io.freefair.javadoc-links" version "3.2.1" apply false } +buildScan { + termsOfServiceUrl = 'https://gradle.com/terms-of-service' + apply from: 'gradle/build-scans.gradle' +} + defaultTasks 'clean', 'build', 'shadowJar', 'install' def sbeGroup = 'uk.co.real-logic' diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000000..e163055e76 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.daemon = true +org.gradle.caching = true diff --git a/gradle/build-scans.gradle b/gradle/build-scans.gradle new file mode 100644 index 0000000000..d30daf921d --- /dev/null +++ b/gradle/build-scans.gradle @@ -0,0 +1,33 @@ +def acceptFile = new File(gradle.gradleUserHomeDir, "build-scans/sbe/gradle-scans-license-agree.txt") +def env = System.getenv() +boolean isCI = env.CI || env.TRAVIS +boolean hasAccepted = isCI || env.SBE_GRADLE_SCANS_ACCEPT=='yes' || acceptFile.exists() && acceptFile.text.trim() == 'yes' +boolean hasRefused = env.SBE_GRADLE_SCANS_ACCEPT=='no' || acceptFile.exists() && acceptFile.text.trim() == 'no' + +buildScan { + if (hasAccepted) { + termsOfServiceAgree = 'yes' + } else if (!hasRefused) { + gradle.buildFinished { + println """ +This build uses Gradle Build Scans to gather statistics, share information about +failures, environmental issues, dependencies resolved during the build and more. +Build scans will be published after each build, if you accept the terms of +service, and in particular the privacy policy. + +Please read + + https://gradle.com/terms-of-service + https://gradle.com/legal/privacy + +and then: + + - set the `SBE_GRADLE_SCANS_ACCEPT` to `yes`/`no` if you agree with/refuse the TOS + - or create the ${acceptFile} file with `yes`/`no` in it if you agree with/refuse + +And we'll not bother you again. Note that build scans are only made public if +you share the URL at the end of the build. +""" + } + } +} From 02437c84e7ced4c76fae74954b8eec4a0524bbf4 Mon Sep 17 00:00:00 2001 From: Vadim Platonov Date: Mon, 6 May 2019 19:21:05 +0200 Subject: [PATCH 0057/1594] [Rust] Pad struct fields - basic AST --- .../sbe/generation/rust/RustGenerator.java | 194 +++++++++++++++--- .../generation/rust/RustGeneratorTest.java | 22 +- 2 files changed, 183 insertions(+), 33 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index c48b78ac2b..0dd8a83563 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -106,9 +106,10 @@ private void generateGroupFieldRepresentations( { for (final GroupTreeNode node : groupTree) { - appendStructHeader(appendable, node.contextualName + "Member", true); - appendStructFields(appendable, node.simpleNamedFields); - appendable.append("}\n"); + final RustStruct struct = RustStruct.fromTokens(node.contextualName + "Member", + node.simpleNamedFields, + EnumSet.of(RustStruct.Modifier.PACKED)); + struct.appendDefinitionTo(appendable); generateConstantAccessorImpl(appendable, node.contextualName + "Member", node.rawFields); @@ -138,9 +139,10 @@ private static Optional generateFieldsRepresentatio final String representationStruct = messageTypeName + "Fields"; try (Writer writer = outputManager.createOutput(messageTypeName + " Fixed-size Fields")) { - appendStructHeader(writer, representationStruct, true); - appendStructFields(writer, namedFieldTokens); - writer.append("}\n"); + final RustStruct struct = RustStruct.fromTokens(representationStruct, namedFieldTokens, + EnumSet.of(RustStruct.Modifier.PACKED)); + struct.appendDefinitionTo(writer); + writer.append("\n"); generateConstantAccessorImpl(writer, representationStruct, components.fields); } @@ -1391,29 +1393,166 @@ private static void generateSingleComposite(final List tokens, final Outp try (Writer writer = outputManager.createOutput(formattedTypeName)) { - appendStructHeader(writer, formattedTypeName, true); - appendStructFields(writer, splitTokens.nonConstantEncodingTokens()); - writer.append("}\n"); + final RustStruct struct = RustStruct.fromTokens(formattedTypeName, + splitTokens.nonConstantEncodingTokens(), + EnumSet.of(RustStruct.Modifier.PACKED)); + struct.appendDefinitionTo(writer); generateConstantAccessorImpl(writer, formattedTypeName, getMessageBody(tokens)); } } + private interface RustTypeDescriptor + { + String name(); + String literal(String valueRep); + } + + private static final class RustArrayType implements RustTypeDescriptor + { + private final RustTypeDescriptor componentType; + private final int length; + + private RustArrayType(RustTypeDescriptor component, int length) { + this.componentType = component; + this.length = length; + } + + @Override + public String name() + { + return getRustStaticArrayString(componentType.name(), length); + } + + @Override + public String literal(String valueRep) + { + return getRustStaticArrayString(valueRep + componentType.name(), length); + } + } + + private static final class RustPrimitiveType implements RustTypeDescriptor + { + private final String name; + + private RustPrimitiveType(String name) { + this.name = name; + } + + @Override + public String name() + { + return name; + } + + @Override + public String literal(String valueRep) + { + return valueRep + name; + } + } + + private static final class AnyRustType implements RustTypeDescriptor + { + private final String name; + + private AnyRustType(String name) { + this.name = name; + } + + @Override + public String name() + { + return name; + } + + @Override + public String literal(String valueRep) + { + final String msg = String.format("Cannot produce a literal value %s of type %s!", valueRep, name); + throw new UnsupportedOperationException(msg); + } + } + + private static final class RustTypes + { + static final RustTypeDescriptor u8 = new RustPrimitiveType("u8"); + + static RustTypeDescriptor ofPrimitiveToken(Token token) + { + final PrimitiveType primitiveType = token.encoding().primitiveType(); + final String rustPrimitiveType = RustUtil.rustTypeName(primitiveType); + final RustPrimitiveType type = new RustPrimitiveType(rustPrimitiveType); + if (token.arrayLength() > 1) { + return new RustArrayType(type, token.arrayLength()); + } + return type; + } + + static RustTypeDescriptor ofGeneratedToken(Token token) + { + return new AnyRustType(formatTypeName(token.applicableTypeName())); + } + + static RustTypeDescriptor arrayOf(RustTypeDescriptor type, int len) + { + return new RustArrayType(type, len); + } + } + + private static final class RustStruct + { + enum Modifier { + PACKED + } + + final String name; + final List fields; + final EnumSet modifiers; + + private RustStruct(String name, List fields, EnumSet modifiers) { + this.name = name; + this.fields = fields; + this.modifiers = modifiers; + } + + public static RustStruct fromTokens(String name, List tokens, EnumSet modifiers) { + return new RustStruct(name, collectStructFields(tokens), modifiers); + } + + void appendDefinitionTo(final Appendable appendable) throws IOException { + appendStructHeader(appendable, name, modifiers.contains(Modifier.PACKED)); + for (RustStructField field: fields) { + indent(appendable); + if (field.modifiers.contains(RustStructField.Modifier.PUBLIC)) appendable.append("pub "); + appendable.append(field.name).append(":").append(field.type.name()).append(",\n"); + } + appendable.append("}"); + } + } + private static final class RustStructField { - final boolean isPub; + enum Modifier { + PUBLIC + } + final String name; - final String value; + final RustTypeDescriptor type; + final EnumSet modifiers; - private RustStructField(boolean isPub, String name, String value) { - this.isPub = isPub; + private RustStructField(String name, RustTypeDescriptor type, EnumSet modifiers) { this.name = name; - this.value = value; + this.type = type; + this.modifiers = modifiers; + } + + private RustStructField(String name, RustTypeDescriptor type) { + this(name, type, EnumSet.noneOf(Modifier.class)); } } - private static void appendStructFields(final Appendable appendable, final List namedTokens) - throws IOException + private static List collectStructFields(final List namedTokens) { final List fields = new ArrayList<>(); int totalSize = 0; @@ -1430,37 +1569,32 @@ private static void appendStructFields(final Appendable appendable, final List Date: Mon, 6 May 2019 22:26:05 +0200 Subject: [PATCH 0058/1594] [Rust] Generate custom message header with padding --- .../sbe/generation/rust/RustGenerator.java | 114 +++++++++++------- 1 file changed, 72 insertions(+), 42 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 0dd8a83563..23ff358733 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1405,7 +1405,12 @@ private static void generateSingleComposite(final List tokens, final Outp private interface RustTypeDescriptor { String name(); - String literal(String valueRep); + String literalValue(String valueRep); + + default String defaultValue() + { + return "Default::default()"; + } } private static final class RustArrayType implements RustTypeDescriptor @@ -1413,7 +1418,8 @@ private static final class RustArrayType implements RustTypeDescriptor private final RustTypeDescriptor componentType; private final int length; - private RustArrayType(RustTypeDescriptor component, int length) { + private RustArrayType(RustTypeDescriptor component, int length) + { this.componentType = component; this.length = length; } @@ -1425,7 +1431,7 @@ public String name() } @Override - public String literal(String valueRep) + public String literalValue(String valueRep) { return getRustStaticArrayString(valueRep + componentType.name(), length); } @@ -1435,7 +1441,8 @@ private static final class RustPrimitiveType implements RustTypeDescriptor { private final String name; - private RustPrimitiveType(String name) { + private RustPrimitiveType(String name) + { this.name = name; } @@ -1446,7 +1453,7 @@ public String name() } @Override - public String literal(String valueRep) + public String literalValue(String valueRep) { return valueRep + name; } @@ -1456,7 +1463,8 @@ private static final class AnyRustType implements RustTypeDescriptor { private final String name; - private AnyRustType(String name) { + private AnyRustType(String name) + { this.name = name; } @@ -1467,7 +1475,7 @@ public String name() } @Override - public String literal(String valueRep) + public String literalValue(String valueRep) { final String msg = String.format("Cannot produce a literal value %s of type %s!", valueRep, name); throw new UnsupportedOperationException(msg); @@ -1502,7 +1510,8 @@ static RustTypeDescriptor arrayOf(RustTypeDescriptor type, int len) private static final class RustStruct { - enum Modifier { + enum Modifier + { PACKED } @@ -1510,30 +1519,66 @@ enum Modifier { final List fields; final EnumSet modifiers; - private RustStruct(String name, List fields, EnumSet modifiers) { + private RustStruct(String name, List fields, EnumSet modifiers) + { this.name = name; this.fields = fields; this.modifiers = modifiers; } - public static RustStruct fromTokens(String name, List tokens, EnumSet modifiers) { + static RustStruct fromHeader(HeaderStructure header) + { + final List tokens = header.tokens(); + final String originalTypeName = tokens.get(0).applicableTypeName(); + final String formattedTypeName = formatTypeName(originalTypeName); + final SplitCompositeTokens splitTokens = SplitCompositeTokens.splitInnerTokens(tokens); + return RustStruct.fromTokens(formattedTypeName, + splitTokens.nonConstantEncodingTokens(), + EnumSet.of(RustStruct.Modifier.PACKED)); + } + + static RustStruct fromTokens(String name, List tokens, EnumSet modifiers) + { return new RustStruct(name, collectStructFields(tokens), modifiers); } - void appendDefinitionTo(final Appendable appendable) throws IOException { + void appendDefinitionTo(final Appendable appendable) throws IOException + { appendStructHeader(appendable, name, modifiers.contains(Modifier.PACKED)); - for (RustStructField field: fields) { + for (RustStructField field: fields) + { indent(appendable); if (field.modifiers.contains(RustStructField.Modifier.PUBLIC)) appendable.append("pub "); appendable.append(field.name).append(":").append(field.type.name()).append(",\n"); } appendable.append("}"); } + + void appendInstanceTo(final Appendable appendable, int indent, Map values) throws IOException + { + appendable.append("MessageHeader {\n"); + for (RustStructField field: fields) { + final String value; + if (values.containsKey(field.name)) + { + value = field.type.literalValue(values.get(field.name)); + } + else + { + value = field.type.defaultValue(); + } + + indent(appendable, indent + 1, "%s: %s,\n", formatMethodName(field.name), value); + } + indent(appendable, indent, "}\n"); + } + } private static final class RustStructField { - enum Modifier { + enum Modifier + { PUBLIC } @@ -1541,13 +1586,15 @@ enum Modifier { final RustTypeDescriptor type; final EnumSet modifiers; - private RustStructField(String name, RustTypeDescriptor type, EnumSet modifiers) { + private RustStructField(String name, RustTypeDescriptor type, EnumSet modifiers) + { this.name = name; this.type = type; this.modifiers = modifiers; } - private RustStructField(String name, RustTypeDescriptor type) { + private RustStructField(String name, RustTypeDescriptor type) + { this(name, type, EnumSet.noneOf(Modifier.class)); } } @@ -1604,6 +1651,8 @@ private void generateMessageHeaderDefault( throws IOException { final HeaderStructure header = ir.headerStructure(); + final RustStruct rustHeader = RustStruct.fromHeader(header); + final String messageTypeName = formatTypeName(messageToken.name()); final String wrapperName = messageTypeName + "MessageHeader"; @@ -1617,33 +1666,14 @@ private void generateMessageHeaderDefault( indent(writer, 1, "fn default() -> %s {\n", wrapperName); indent(writer, 2, "%s {\n", wrapperName); - indent(writer, 3, "message_header: MessageHeader {\n"); - indent(writer, 4, "%s: %s,\n", formatMethodName("blockLength"), - generateRustLiteral(header.blockLengthType(), Integer.toString(messageToken.encodedLength()))); - indent(writer, 4, "%s: %s,\n", formatMethodName("templateId"), - generateRustLiteral(header.templateIdType(), Integer.toString(messageToken.id()))); - indent(writer, 4, "%s: %s,\n", formatMethodName("schemaId"), - generateRustLiteral(header.schemaIdType(), Integer.toString(ir.id()))); - indent(writer, 4, "%s: %s,\n", formatMethodName("version"), - generateRustLiteral(header.schemaVersionType(), Integer.toString(ir.version()))); - - // Technically the spec seems to allow non-standard fields in the message header, so we attempt - // to provide some sort of default for them - final Set reserved = new HashSet<>(Arrays.asList("blockLength", "templateId", "schemaId", - "version")); - - final List nonReservedNamedTokens = SplitCompositeTokens.splitInnerTokens(header.tokens()) - .nonConstantEncodingTokens() - .stream() - .filter((namedToken) -> !reserved.contains(namedToken.name())) - .collect(Collectors.toList()); - - for (final NamedToken namedToken : nonReservedNamedTokens) - { - indent(writer, 4, "%s: Default::default(),\n", formatMethodName(namedToken.name())); - } - - indent(writer, 3, "}\n"); + indent(writer, 3, "message_header: "); + rustHeader.appendInstanceTo(writer, 3, + new HashMap() {{ + put("block_length", Integer.toString(messageToken.encodedLength())); + put("template_id", Integer.toString(messageToken.id())); + put("schema_id", Integer.toString(ir.id())); + put("version", Integer.toString(ir.version())); + }}); indent(writer, 2, "}\n"); indent(writer, 1, "}\n"); From 09b3155fefca37756e1315bda59c3c299f487ae0 Mon Sep 17 00:00:00 2001 From: Vadim Platonov Date: Tue, 7 May 2019 08:25:47 +0200 Subject: [PATCH 0059/1594] [Rust] Correctly determine struct size --- .../sbe/generation/rust/RustGenerator.java | 119 +++++++----------- .../generation/rust/RustGeneratorTest.java | 16 +++ 2 files changed, 62 insertions(+), 73 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 23ff358733..2d4d06110e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -25,7 +25,6 @@ import java.io.IOException; import java.io.Writer; import java.util.*; -import java.util.stream.Collectors; import java.util.stream.IntStream; import static java.lang.String.format; @@ -69,16 +68,15 @@ public void generate() throws IOException final MessageComponents components = MessageComponents.collectMessageComponents(tokens); final String messageTypeName = formatTypeName(components.messageToken.name()); - final Optional fieldsRepresentation = - generateFieldsRepresentation(messageTypeName, components, outputManager); + final RustStruct fieldStruct = generateMessageFieldStruct(messageTypeName, components, outputManager); generateMessageHeaderDefault(ir, outputManager, components.messageToken); // Avoid the work of recomputing the group tree twice per message final List groupTree = buildGroupTrees(messageTypeName, components.groups); generateGroupFieldRepresentations(outputManager, groupTree); - generateMessageDecoder(outputManager, components, groupTree, fieldsRepresentation, headerSize); - generateMessageEncoder(outputManager, components, groupTree, fieldsRepresentation, headerSize); + generateMessageDecoder(outputManager, components, groupTree, fieldStruct, headerSize); + generateMessageEncoder(outputManager, components, groupTree, fieldStruct, headerSize); } } @@ -117,19 +115,7 @@ private void generateGroupFieldRepresentations( } } - private static final class FieldsRepresentationSummary - { - final String typeName; - final int numBytes; - - private FieldsRepresentationSummary(final String typeName, final int numBytes) - { - this.typeName = typeName; - this.numBytes = numBytes; - } - } - - private static Optional generateFieldsRepresentation( + private static RustStruct generateMessageFieldStruct( final String messageTypeName, final MessageComponents components, final OutputManager outputManager) throws IOException @@ -137,48 +123,18 @@ private static Optional generateFieldsRepresentatio final List namedFieldTokens = NamedToken.gatherNamedNonConstantFieldTokens(components.fields); final String representationStruct = messageTypeName + "Fields"; - try (Writer writer = outputManager.createOutput(messageTypeName + " Fixed-size Fields")) + final RustStruct struct = RustStruct.fromTokens(representationStruct, namedFieldTokens, + EnumSet.of(RustStruct.Modifier.PACKED)); + + try (Writer writer = outputManager.createOutput( + messageTypeName + " Fixed-size Fields (" + struct.sizeBytes() + " bytes)")) { - final RustStruct struct = RustStruct.fromTokens(representationStruct, namedFieldTokens, - EnumSet.of(RustStruct.Modifier.PACKED)); struct.appendDefinitionTo(writer); writer.append("\n"); - generateConstantAccessorImpl(writer, representationStruct, components.fields); } - // Compute the total static size in bytes of the fields representation - int numBytes = 0; - for (int i = 0, size = components.fields.size(); i < size;) - { - final Token fieldToken = components.fields.get(i); - if (fieldToken.signal() == Signal.BEGIN_FIELD) - { - final int fieldEnd = i + fieldToken.componentTokenCount(); - if (!fieldToken.isConstantEncoding()) - { - for (int j = i; j < fieldEnd; j++) - { - final Token t = components.fields.get(j); - if (t.isConstantEncoding()) - { - continue; - } - if (t.signal() == ENCODING || t.signal() == BEGIN_ENUM || t.signal() == BEGIN_SET) - { - numBytes += t.encodedLength(); - } - } - } - i += fieldToken.componentTokenCount(); - } - else - { - throw new IllegalStateException("field tokens must include bounding BEGIN_FIELD and END_FIELD tokens"); - } - } - - return Optional.of(new FieldsRepresentationSummary(representationStruct, numBytes)); + return struct; } private static void generateBitSets(final Ir ir, final OutputManager outputManager) throws IOException @@ -246,7 +202,7 @@ private static void generateMessageEncoder( final OutputManager outputManager, final MessageComponents components, final List groupTree, - final Optional fieldsRepresentation, + final RustStruct fieldStruct, final int headerSize) throws IOException { @@ -256,7 +212,7 @@ private static void generateMessageEncoder( String topType = codecType.generateDoneCoderType(outputManager, messageTypeName); topType = generateTopVarDataCoders(messageTypeName, components.varData, outputManager, topType, codecType); topType = generateGroupsCoders(groupTree, outputManager, topType, codecType); - topType = generateFixedFieldCoder(messageTypeName, outputManager, topType, fieldsRepresentation, codecType); + topType = generateFixedFieldCoder(messageTypeName, outputManager, topType, fieldStruct, codecType); topType = codecType.generateMessageHeaderCoder(messageTypeName, outputManager, topType, headerSize); generateEntryPoint(messageTypeName, outputManager, topType, codecType); } @@ -265,7 +221,7 @@ private static void generateMessageDecoder( final OutputManager outputManager, final MessageComponents components, final List groupTree, - final Optional fieldsRepresentation, + final RustStruct fieldStruct, final int headerSize) throws IOException { @@ -275,7 +231,7 @@ private static void generateMessageDecoder( String topType = codecType.generateDoneCoderType(outputManager, messageTypeName); topType = generateTopVarDataCoders(messageTypeName, components.varData, outputManager, topType, codecType); topType = generateGroupsCoders(groupTree, outputManager, topType, codecType); - topType = generateFixedFieldCoder(messageTypeName, outputManager, topType, fieldsRepresentation, codecType); + topType = generateFixedFieldCoder(messageTypeName, outputManager, topType, fieldStruct, codecType); topType = codecType.generateMessageHeaderCoder(messageTypeName, outputManager, topType, headerSize); generateEntryPoint(messageTypeName, outputManager, topType, codecType); } @@ -308,24 +264,17 @@ private static String generateFixedFieldCoder( final String messageTypeName, final OutputManager outputManager, final String topType, - final Optional fieldsRepresentationOptional, + final RustStruct fieldStruct, final RustCodecType codecType) throws IOException { - if (!fieldsRepresentationOptional.isPresent()) - { - return topType; - } - - final FieldsRepresentationSummary fieldsRepresentation = fieldsRepresentationOptional.get(); try (Writer writer = outputManager.createOutput(messageTypeName + " Fixed fields " + codecType.name())) { - final String representationStruct = fieldsRepresentation.typeName; - final String decoderName = representationStruct + codecType.name(); + final String decoderName = fieldStruct.name + codecType.name(); codecType.appendScratchWrappingStruct(writer, decoderName); appendImplWithLifetimeHeader(writer, decoderName); codecType.appendWrapMethod(writer, decoderName); codecType.appendDirectCodeMethods(writer, formatMethodName(messageTypeName) + "_fields", - representationStruct, topType, fieldsRepresentation.numBytes); + fieldStruct.name, topType, fieldStruct.sizeBytes()); writer.append("}\n"); // TODO - Move read position further if in-message blockLength exceeds fixed fields representation size // will require piping some data from the previously-read message header @@ -1406,6 +1355,7 @@ private interface RustTypeDescriptor { String name(); String literalValue(String valueRep); + int sizeBytes(); default String defaultValue() { @@ -1435,15 +1385,22 @@ public String literalValue(String valueRep) { return getRustStaticArrayString(valueRep + componentType.name(), length); } + + @Override + public int sizeBytes() { + return componentType.sizeBytes() * length; + } } private static final class RustPrimitiveType implements RustTypeDescriptor { private final String name; + private final int sizeBytes; - private RustPrimitiveType(String name) + private RustPrimitiveType(String name, int sizeBytes) { this.name = name; + this.sizeBytes = sizeBytes; } @Override @@ -1457,15 +1414,22 @@ public String literalValue(String valueRep) { return valueRep + name; } + + @Override + public int sizeBytes() { + return sizeBytes; + } } private static final class AnyRustType implements RustTypeDescriptor { private final String name; + private final int sizeBytes; - private AnyRustType(String name) + private AnyRustType(String name, int sizeBytes) { this.name = name; + this.sizeBytes = sizeBytes; } @Override @@ -1480,17 +1444,22 @@ public String literalValue(String valueRep) final String msg = String.format("Cannot produce a literal value %s of type %s!", valueRep, name); throw new UnsupportedOperationException(msg); } + + @Override + public int sizeBytes() { + return sizeBytes; + } } private static final class RustTypes { - static final RustTypeDescriptor u8 = new RustPrimitiveType("u8"); + static final RustTypeDescriptor u8 = new RustPrimitiveType("u8", 1); static RustTypeDescriptor ofPrimitiveToken(Token token) { final PrimitiveType primitiveType = token.encoding().primitiveType(); final String rustPrimitiveType = RustUtil.rustTypeName(primitiveType); - final RustPrimitiveType type = new RustPrimitiveType(rustPrimitiveType); + final RustPrimitiveType type = new RustPrimitiveType(rustPrimitiveType, primitiveType.size()); if (token.arrayLength() > 1) { return new RustArrayType(type, token.arrayLength()); } @@ -1499,7 +1468,7 @@ static RustTypeDescriptor ofPrimitiveToken(Token token) static RustTypeDescriptor ofGeneratedToken(Token token) { - return new AnyRustType(formatTypeName(token.applicableTypeName())); + return new AnyRustType(formatTypeName(token.applicableTypeName()), token.encodedLength()); } static RustTypeDescriptor arrayOf(RustTypeDescriptor type, int len) @@ -1526,6 +1495,10 @@ private RustStruct(String name, List fields, EnumSet this.modifiers = modifiers; } + public int sizeBytes() { + return fields.stream().mapToInt(v -> v.type.sizeBytes()).sum(); + } + static RustStruct fromHeader(HeaderStructure header) { final List tokens = header.tokens(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java index e00a7e602c..1811ae30ad 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java @@ -290,6 +290,22 @@ public void checkValidRustFromAllExampleSchema() throws IOException, Interrupted } } + @Test + public void messageWithOffsets() + { + final String rust = fullGenerateForResource(outputManager, "composite-offsets-schema"); + final String expectedHeader = + "pub struct MessageHeader {\n" + + " pub block_length:u16,\n" + + " template_id_padding:[u8;2],\n" + + " pub template_id:u16,\n" + + " schema_id_padding:[u8;2],\n" + + " pub schema_id:u16,\n" + + " pub version:u16,\n" + + "}"; + assertContains(rust, expectedHeader); + } + @Test public void constantEnumFields() throws IOException, InterruptedException { From 24d781dc4804d46ef1d83839c9eb7d1a8be659b0 Mon Sep 17 00:00:00 2001 From: Vadim Platonov Date: Tue, 7 May 2019 08:26:24 +0200 Subject: [PATCH 0060/1594] [Rust] Generate impl Default for field structs Without a default value, structs with paddings become tedious to construct. --- .../sbe/generation/rust/RustGenerator.java | 59 +++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 2d4d06110e..fa371561c9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1318,6 +1318,11 @@ private static void generateEnum(final List enumTokens, final OutputManag .append(",\n"); writer.append("}\n"); + + // Default implementation to support Default in other structs + indent(writer, 0, "impl Default for %s {\n", enumRustName); + indent(writer, 1, "fn default() -> Self { %s::%s }\n", enumRustName, "NullVal"); + indent(writer, 0, "}\n"); } } @@ -1387,9 +1392,35 @@ public String literalValue(String valueRep) } @Override - public int sizeBytes() { + public int sizeBytes() + { return componentType.sizeBytes() * length; } + + @Override + public String defaultValue() + { + final String defaultValue = RustTypeDescriptor.super.defaultValue(); + if (length <= 32) + { + return defaultValue; + } + else + { + StringBuilder result = new StringBuilder(); + result.append('['); + for (int i = 0; i < length; i++) + { + result.append(defaultValue); + result.append(", "); + if (i % 4 == 0) { // ~80 char lines + result.append('\n'); + } + } + result.append(']'); + return result.toString(); + } + } } private static final class RustPrimitiveType implements RustTypeDescriptor @@ -1515,6 +1546,20 @@ static RustStruct fromTokens(String name, List tokens, EnumSet Self {\n"); + + appendInstanceTo(appendable, 2); + + indent(appendable, 1, "}\n"); + + appendable.append("}\n"); + } + void appendDefinitionTo(final Appendable appendable) throws IOException { appendStructHeader(appendable, name, modifiers.contains(Modifier.PACKED)); @@ -1524,12 +1569,18 @@ void appendDefinitionTo(final Appendable appendable) throws IOException if (field.modifiers.contains(RustStructField.Modifier.PUBLIC)) appendable.append("pub "); appendable.append(field.name).append(":").append(field.type.name()).append(",\n"); } - appendable.append("}"); + appendable.append("}\n"); + appendDefaultConstructorTo(appendable); + } + + void appendInstanceTo(final Appendable appendable, int indent) throws IOException + { + appendInstanceTo(appendable, indent, Collections.emptyMap()); } void appendInstanceTo(final Appendable appendable, int indent, Map values) throws IOException { - appendable.append("MessageHeader {\n"); + indent(appendable, indent, "%s {\n", name); for (RustStructField field: fields) { final String value; if (values.containsKey(field.name)) @@ -1635,7 +1686,7 @@ private void generateMessageHeaderDefault( indent(writer, 1, "pub message_header: MessageHeader\n"); writer.append("}\n"); - indent(writer, 1, "impl Default for %s {\n", wrapperName); + indent(writer, 0, "impl Default for %s {\n", wrapperName); indent(writer, 1, "fn default() -> %s {\n", wrapperName); indent(writer, 2, "%s {\n", wrapperName); From 7e000991c78f2e4cd2440ea6351e9d485f77e773 Mon Sep 17 00:00:00 2001 From: Vadim Platonov Date: Tue, 7 May 2019 08:53:48 +0200 Subject: [PATCH 0061/1594] [Rust] Move dimension-related fields to a separate class --- .../sbe/generation/rust/RustGenerator.java | 85 ++++++++++++------- 1 file changed, 54 insertions(+), 31 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index fa371561c9..8780b2c346 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -409,7 +409,7 @@ private static String writeGroupEncoderTopTypes( try (Writer out = outputManager.createOutput(node.contextualName + " Encoder for fields and header")) { appendStructHeader(out, withLifetime(memberCoderType), false); - final String rustCountType = rustTypeName(node.numInGroupType); + final String rustCountType = rustTypeName(node.dimensionsNumInGroupType()); final String contentProperty; final String contentBearingType; if (node.parent.isPresent()) @@ -453,7 +453,7 @@ private static String writeGroupEncoderTopTypes( indent(out, 1, "pub fn done_with_%s(mut self) -> CodecResult<%s> {\n", formatMethodName(node.originalName), withLifetime(afterGroupCoderType)); indent(out, 2, "%s.write_at_position::<%s>(self.count_write_pos, &self.count, %s)?;\n", - scratchChain, rustCountType, node.numInGroupType.size()); + scratchChain, rustCountType, node.dimensionsNumInGroupType().size()); indent(out, 2, "Ok(%s)\n", atEndOfParent ? "self.parent" : format("%s::wrap(self.%s)", afterGroupCoderType, contentProperty)); indent(out).append("}\n").append("}\n"); @@ -473,12 +473,12 @@ private static String writeGroupEncoderTopTypes( indent(out, 1, "pub fn %s_individually(mut self) -> CodecResult<%s> {\n", formatMethodName(node.originalName), withLifetime(memberCoderType)); indent(out, 2, "%s.write_type::<%s>(&%s, %s)?; // block length\n", - scratchChain, rustTypeName(node.blockLengthType), - generateRustLiteral(node.blockLengthType, Integer.toString(node.blockLength)), - node.blockLengthType.size()); + scratchChain, rustTypeName(node.dimensionsBlockLengthType()), + generateRustLiteral(node.dimensionsBlockLengthType(), Integer.toString(node.blockLength)), + node.dimensionsBlockLengthType().size()); indent(out, 2, "let count_pos = %s.pos;\n", scratchChain); indent(out, 2, "%s.write_type::<%s>(&0, %s)?; // preliminary group member count\n", - scratchChain, rustCountType, node.numInGroupType.size()); + scratchChain, rustCountType, node.dimensionsNumInGroupType().size()); indent(out, 2, "Ok(%s::new(self.%s, count_pos))\n", memberCoderType, contentProperty); indent(out, 1).append("}\n"); @@ -510,11 +510,11 @@ private static void appendFixedSizeMemberGroupEncoderMethods( formatMethodName(node.originalName), rustCountType, DATA_LIFETIME, fieldsType, withLifetime(afterGroupCoderType)); indent(out, 2, "%s.write_type::<%s>(&%s, %s)?; // block length\n", - scratchChain, rustTypeName(node.blockLengthType), - generateRustLiteral(node.blockLengthType, Integer.toString(node.blockLength)), - node.blockLengthType.size()); + scratchChain, rustTypeName(node.dimensionsBlockLengthType()), + generateRustLiteral(node.dimensionsBlockLengthType(), Integer.toString(node.blockLength)), + node.dimensionsBlockLengthType().size()); indent(out, 2, "%s.write_type::<%s>(&count, %s)?; // group count\n", - scratchChain, rustCountType, node.numInGroupType.size()); + scratchChain, rustCountType, node.dimensionsNumInGroupType().size()); indent(out, 2, "let c = count as usize;\n"); indent(out, 2, "let group_slice = %s.writable_slice::<%s>(c, %s)?;\n", scratchChain, fieldsType, node.blockLength); @@ -527,15 +527,15 @@ scratchChain, rustTypeName(node.blockLengthType), formatMethodName(node.originalName), fieldsType, withLifetime(afterGroupCoderType)); indent(out, 2, "%s.write_type::<%s>(&%s, %s)?; // block length\n", - scratchChain, rustTypeName(node.blockLengthType), - generateRustLiteral(node.blockLengthType, Integer.toString(node.blockLength)), - node.blockLengthType.size()); + scratchChain, rustTypeName(node.dimensionsBlockLengthType()), + generateRustLiteral(node.dimensionsBlockLengthType(), Integer.toString(node.blockLength)), + node.dimensionsBlockLengthType().size()); indent(out, 2, "let count = s.len();\n"); - indent(out, 2, "if count > %s {\n", node.numInGroupType.maxValue()); + indent(out, 2, "if count > %s {\n", node.dimensionsNumInGroupType().maxValue()); indent(out, 3).append("return Err(CodecErr::SliceIsLongerThanAllowedBySchema)\n"); indent(out, 2).append("}\n"); indent(out, 2, "%s.write_type::<%s>(&(count as %s), %s)?; // group count\n", - scratchChain, rustCountType, rustCountType, node.numInGroupType.size()); + scratchChain, rustCountType, rustCountType, node.dimensionsNumInGroupType().size()); indent(out, 2, "%s.write_slice_without_count::<%s>(s, %s)?;\n", scratchChain, fieldsType, node.blockLength); indent(out, 2, "Ok(%s)\n", atEndOfParent ? "self.parent" : @@ -557,7 +557,7 @@ private static void writeGroupDecoderTopTypes( try (Writer out = outputManager.createOutput(node.contextualName + " Decoder for fields and header")) { appendStructHeader(out, withLifetime(memberDecoderType), false); - final String rustCountType = rustTypeName(node.numInGroupType); + final String rustCountType = rustTypeName(node.dimensionsNumInGroupType()); final String contentProperty; final String contentBearingType; if (node.parent.isPresent()) @@ -618,9 +618,10 @@ private static void writeGroupDecoderTopTypes( indent(out, 1, "pub fn %s_individually(mut self) -> CodecResult<%s> {\n", formatMethodName(node.originalName), groupLevelNextDecoderType); indent(out, 2, "%s.skip_bytes(%s)?; // Skip reading block length for now\n", - toScratchChain(node), node.blockLengthType.size()); + toScratchChain(node), node.dimensionsBlockLengthType().size()); indent(out, 2, "let count = *%s.read_type::<%s>(%s)?;\n", - toScratchChain(node), rustTypeName(node.numInGroupType), node.numInGroupType.size()); + toScratchChain(node), rustTypeName(node.dimensionsNumInGroupType()), + node.dimensionsNumInGroupType().size()); indent(out, 2).append("if count > 0 {\n"); indent(out, 3, "Ok(Either::Left(%s::new(self.%s, count)))\n", memberDecoderType, contentProperty).append(INDENT).append(INDENT).append("} else {\n"); @@ -659,9 +660,10 @@ private static void appendFixedSizeMemberGroupDecoderMethods( initialNextDecoderType.startsWith("Either") ? initialNextDecoderType : withLifetime(initialNextDecoderType)); indent(out, 2, "%s.skip_bytes(%s)?; // Skip reading block length for now\n", toScratchChain(node), - node.blockLengthType.size()); + node.dimensionsBlockLengthType().size()); indent(out, 2, "let count = *%s.read_type::<%s>(%s)?;\n", - toScratchChain(node), rustTypeName(node.numInGroupType), node.numInGroupType.size()); + toScratchChain(node), rustTypeName(node.dimensionsNumInGroupType()), + node.dimensionsNumInGroupType().size()); indent(out, 2, "let s = %s.read_slice::<%s>(count as usize, %s)?;\n", toScratchChain(node), node.contextualName + "Member", node.blockLength); indent(out, 2, "Ok((s,%s))\n", atEndOfParent ? "self.parent.after_member()" : @@ -738,10 +740,8 @@ private static List buildGroupTrees( final Token dimensionsToken = groupsTokens.get(i); final int groupHeaderTokenCount = dimensionsToken.componentTokenCount(); final List dimensionsTokens = groupsTokens.subList(i, i + groupHeaderTokenCount); - final PrimitiveType numInGroupType = findPrimitiveByTokenName(dimensionsTokens, "numInGroup"); - final Token blockLengthToken = findPrimitiveTokenByTokenName(dimensionsTokens, "blockLength"); + final GroupDimensions dimensions = GroupDimensions.ofTokens(dimensionsTokens); final int blockLength = groupToken.encodedLength(); - final PrimitiveType blockLengthType = blockLengthToken.encoding().primitiveType(); i += groupHeaderTokenCount; final List fields = new ArrayList<>(); @@ -758,8 +758,7 @@ private static List buildGroupTrees( parent, originalName, contextualName, - numInGroupType, - blockLengthType, + dimensions, blockLength, fields, varDataSummaries); @@ -791,13 +790,31 @@ private static Token findPrimitiveTokenByTokenName(final List tokens, fin throw new IllegalStateException(format("%s not specified for group", targetName)); } + private static class GroupDimensions + { + final String typeName; + final PrimitiveType numInGroupType; + final PrimitiveType blockLengthType; + + private GroupDimensions(String typeName, PrimitiveType numInGroupType, PrimitiveType blockLengthType) { + this.typeName = typeName; + this.numInGroupType = numInGroupType; + this.blockLengthType = blockLengthType; + } + + public static GroupDimensions ofTokens(List dimensionsTokens) { + final PrimitiveType numInGroupType = findPrimitiveByTokenName(dimensionsTokens, "numInGroup"); + final PrimitiveType blockLengthType = findPrimitiveByTokenName(dimensionsTokens, "blockLength"); + return new GroupDimensions(dimensionsTokens.get(0).name(), numInGroupType, blockLengthType); + } + } + static class GroupTreeNode { final Optional parent; final String originalName; final String contextualName; - final PrimitiveType numInGroupType; - final PrimitiveType blockLengthType; + final GroupDimensions dimensions; final int blockLength; final List rawFields; final List simpleNamedFields; @@ -808,8 +825,7 @@ static class GroupTreeNode final Optional parent, final String originalName, final String contextualName, - final PrimitiveType numInGroupType, - final PrimitiveType blockLengthType, + final GroupDimensions dimensions, final int blockLength, final List fields, final List varData) @@ -817,8 +833,7 @@ static class GroupTreeNode this.parent = parent; this.originalName = originalName; this.contextualName = contextualName; - this.numInGroupType = numInGroupType; - this.blockLengthType = blockLengthType; + this.dimensions = dimensions; this.blockLength = blockLength; this.rawFields = fields; this.simpleNamedFields = NamedToken.gatherNamedNonConstantFieldTokens(fields); @@ -849,6 +864,14 @@ boolean hasFixedSizeMembers() { return groups.isEmpty() && varData.isEmpty(); } + + public PrimitiveType dimensionsNumInGroupType() { + return dimensions.numInGroupType; + } + + public PrimitiveType dimensionsBlockLengthType() { + return dimensions.blockLengthType; + } } static class VarDataSummary From 5f0a7ba5a31abc08fcf9bc11551349480e4b15d6 Mon Sep 17 00:00:00 2001 From: Vadim Platonov Date: Tue, 7 May 2019 09:20:46 +0200 Subject: [PATCH 0062/1594] [Rust] Decode non-standard group dimensions --- .../sbe/generation/rust/RustGenerator.java | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 8780b2c346..f9c09550cf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -617,13 +617,12 @@ private static void writeGroupDecoderTopTypes( indent(out, 1, "pub fn %s_individually(mut self) -> CodecResult<%s> {\n", formatMethodName(node.originalName), groupLevelNextDecoderType); - indent(out, 2, "%s.skip_bytes(%s)?; // Skip reading block length for now\n", - toScratchChain(node), node.dimensionsBlockLengthType().size()); - indent(out, 2, "let count = *%s.read_type::<%s>(%s)?;\n", - toScratchChain(node), rustTypeName(node.dimensionsNumInGroupType()), - node.dimensionsNumInGroupType().size()); - indent(out, 2).append("if count > 0 {\n"); - indent(out, 3, "Ok(Either::Left(%s::new(self.%s, count)))\n", + indent(out, 2, "let dim = %s.read_type::<%s>(%s)?;\n", + toScratchChain(node), + formatTypeName(node.dimensionsTypeName()), + node.dimensionsTypeSize()); + indent(out, 2).append("if dim.num_in_group > 0 {\n"); + indent(out, 3, "Ok(Either::Left(%s::new(self.%s, dim.num_in_group)))\n", memberDecoderType, contentProperty).append(INDENT).append(INDENT).append("} else {\n"); if (atEndOfParent) @@ -659,12 +658,11 @@ private static void appendFixedSizeMemberGroupDecoderMethods( formatMethodName(node.originalName), DATA_LIFETIME, node.contextualName + "Member", initialNextDecoderType.startsWith("Either") ? initialNextDecoderType : withLifetime(initialNextDecoderType)); - indent(out, 2, "%s.skip_bytes(%s)?; // Skip reading block length for now\n", toScratchChain(node), - node.dimensionsBlockLengthType().size()); - indent(out, 2, "let count = *%s.read_type::<%s>(%s)?;\n", - toScratchChain(node), rustTypeName(node.dimensionsNumInGroupType()), - node.dimensionsNumInGroupType().size()); - indent(out, 2, "let s = %s.read_slice::<%s>(count as usize, %s)?;\n", + indent(out, 2, "let dim = %s.read_type::<%s>(%s)?;\n", + toScratchChain(node), + formatTypeName(node.dimensionsTypeName()), + node.dimensionsTypeSize()); + indent(out, 2, "let s = %s.read_slice::<%s>(dim.num_in_group as usize, %s)?;\n", toScratchChain(node), node.contextualName + "Member", node.blockLength); indent(out, 2, "Ok((s,%s))\n", atEndOfParent ? "self.parent.after_member()" : format("%s::wrap(self.%s)", initialNextDecoderType, contentProperty)); @@ -793,19 +791,25 @@ private static Token findPrimitiveTokenByTokenName(final List tokens, fin private static class GroupDimensions { final String typeName; + final int typeSize; final PrimitiveType numInGroupType; final PrimitiveType blockLengthType; - private GroupDimensions(String typeName, PrimitiveType numInGroupType, PrimitiveType blockLengthType) { + private GroupDimensions(String typeName, int typeSize, + PrimitiveType numInGroupType, PrimitiveType blockLengthType) + { this.typeName = typeName; + this.typeSize = typeSize; this.numInGroupType = numInGroupType; this.blockLengthType = blockLengthType; } - public static GroupDimensions ofTokens(List dimensionsTokens) { + public static GroupDimensions ofTokens(List dimensionsTokens) + { final PrimitiveType numInGroupType = findPrimitiveByTokenName(dimensionsTokens, "numInGroup"); final PrimitiveType blockLengthType = findPrimitiveByTokenName(dimensionsTokens, "blockLength"); - return new GroupDimensions(dimensionsTokens.get(0).name(), numInGroupType, blockLengthType); + return new GroupDimensions(dimensionsTokens.get(0).name(), dimensionsTokens.get(0).encodedLength(), + numInGroupType, blockLengthType); } } @@ -872,6 +876,14 @@ public PrimitiveType dimensionsNumInGroupType() { public PrimitiveType dimensionsBlockLengthType() { return dimensions.blockLengthType; } + + public String dimensionsTypeName() { + return dimensions.typeName; + } + + public int dimensionsTypeSize() { + return dimensions.typeSize; + } } static class VarDataSummary From dc55547b631a7b5c30f615b8b56c702c496afb24 Mon Sep 17 00:00:00 2001 From: Vadim Platonov Date: Tue, 7 May 2019 10:04:46 +0200 Subject: [PATCH 0063/1594] [Rust] Handle messages with blockLength > fixed field size --- .../sbe/generation/rust/RustCodecType.java | 30 +++++++++++++++---- .../sbe/generation/rust/RustGenerator.java | 22 ++++++++++---- .../generation/rust/RustGeneratorTest.java | 11 +++++++ 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java index 9ae2e8139b..aba65bebbf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java @@ -44,12 +44,18 @@ void appendDirectCodeMethods( final String methodName, final String representationType, final String nextCoderType, - final int numBytes) throws IOException + final int numBytes, + final int trailingBytes) throws IOException { indent(appendable, 1, "pub fn %s(mut self) -> CodecResult<(&%s %s, %s)> {\n", methodName, DATA_LIFETIME, representationType, RustGenerator.withLifetime(nextCoderType)); indent(appendable, 2, "let v = self.%s.read_type::<%s>(%s)?;\n", RustCodecType.Decoder.scratchProperty(), representationType, numBytes); + if (trailingBytes > 0) + { + indent(appendable, 2, "self.%s.skip_bytes(%s)?;\n", + RustCodecType.Decoder.scratchProperty(), trailingBytes); + } indent(appendable, 2, "Ok((v, %s::wrap(self.%s)))\n", nextCoderType, RustCodecType.Decoder.scratchProperty()); indent(appendable).append("}\n"); @@ -78,15 +84,20 @@ void appendDirectCodeMethods( final String methodName, final String representationType, final String nextCoderType, - final int numBytes) throws IOException + final int numBytes, + final int trailingBytes) throws IOException { indent(appendable, 1, "\n/// Create a mutable struct reference overlaid atop the data buffer\n"); indent(appendable, 1, "/// such that changes to the struct directly edit the buffer. \n"); indent(appendable, 1, "/// Note that the initial content of the struct's fields may be garbage.\n"); indent(appendable, 1, "pub fn %s(mut self) -> CodecResult<(&%s mut %s, %s)> {\n", methodName, DATA_LIFETIME, representationType, RustGenerator.withLifetime(nextCoderType)); - indent(appendable, 2, "let v = self.%s.writable_overlay::<%s>(%s)?;\n", - RustCodecType.Encoder.scratchProperty(), representationType, numBytes); + if (trailingBytes > 0) + { + indent(appendable, 2, "// add trailing bytes to extend the end position of the scratch buffer\n"); + } + indent(appendable, 2, "let v = self.%s.writable_overlay::<%s>(%s+%s)?;\n", + RustCodecType.Encoder.scratchProperty(), representationType, numBytes, trailingBytes); indent(appendable, 2, "Ok((v, %s::wrap(self.%s)))\n", nextCoderType, RustCodecType.Encoder.scratchProperty()); indent(appendable).append("}\n\n"); @@ -97,6 +108,12 @@ void appendDirectCodeMethods( indent(appendable, 2) .append(format("self.%s.write_type::<%s>(t, %s)?;\n", RustCodecType.Encoder.scratchProperty(), representationType, numBytes)); + if (trailingBytes > 0) + { + indent(appendable, 2, "// fixed message length > sum of field lengths\n"); + indent(appendable, 2, "self.%s.skip_bytes(%s)?;\n", + RustCodecType.Decoder.scratchProperty(), trailingBytes); + } indent(appendable, 2).append(format("Ok(%s::wrap(self.%s))\n", nextCoderType, RustCodecType.Encoder.scratchProperty())); indent(appendable).append("}\n"); @@ -125,7 +142,8 @@ abstract void appendDirectCodeMethods( String methodName, String representationType, String nextCoderType, - int numBytes) throws IOException; + int numBytes, + int trailingBytes) throws IOException; abstract String gerund(); @@ -175,7 +193,7 @@ String generateMessageHeaderCoder( appendScratchWrappingStruct(writer, headerCoderType); RustGenerator.appendImplWithLifetimeHeader(writer, headerCoderType); appendWrapMethod(writer, headerCoderType); - appendDirectCodeMethods(writer, "header", messageHeaderRepresentation, topType, headerSize); + appendDirectCodeMethods(writer, "header", messageHeaderRepresentation, topType, headerSize, 0); writer.append("}\n"); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index f9c09550cf..f4945caa95 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -212,7 +212,7 @@ private static void generateMessageEncoder( String topType = codecType.generateDoneCoderType(outputManager, messageTypeName); topType = generateTopVarDataCoders(messageTypeName, components.varData, outputManager, topType, codecType); topType = generateGroupsCoders(groupTree, outputManager, topType, codecType); - topType = generateFixedFieldCoder(messageTypeName, outputManager, topType, fieldStruct, codecType); + topType = generateFixedFieldCoder(messageTypeName, msgToken.encodedLength(), outputManager, topType, fieldStruct, codecType); topType = codecType.generateMessageHeaderCoder(messageTypeName, outputManager, topType, headerSize); generateEntryPoint(messageTypeName, outputManager, topType, codecType); } @@ -231,7 +231,7 @@ private static void generateMessageDecoder( String topType = codecType.generateDoneCoderType(outputManager, messageTypeName); topType = generateTopVarDataCoders(messageTypeName, components.varData, outputManager, topType, codecType); topType = generateGroupsCoders(groupTree, outputManager, topType, codecType); - topType = generateFixedFieldCoder(messageTypeName, outputManager, topType, fieldStruct, codecType); + topType = generateFixedFieldCoder(messageTypeName, msgToken.encodedLength(), outputManager, topType, fieldStruct, codecType); topType = codecType.generateMessageHeaderCoder(messageTypeName, outputManager, topType, headerSize); generateEntryPoint(messageTypeName, outputManager, topType, codecType); } @@ -262,6 +262,7 @@ static String withLifetime(final String typeName) private static String generateFixedFieldCoder( final String messageTypeName, + final int messageEncodedLength, final OutputManager outputManager, final String topType, final RustStruct fieldStruct, @@ -274,10 +275,9 @@ private static String generateFixedFieldCoder( appendImplWithLifetimeHeader(writer, decoderName); codecType.appendWrapMethod(writer, decoderName); codecType.appendDirectCodeMethods(writer, formatMethodName(messageTypeName) + "_fields", - fieldStruct.name, topType, fieldStruct.sizeBytes()); + fieldStruct.name, topType, fieldStruct.sizeBytes(), + messageEncodedLength - fieldStruct.sizeBytes()); writer.append("}\n"); - // TODO - Move read position further if in-message blockLength exceeds fixed fields representation size - // will require piping some data from the previously-read message header return decoderName; } } @@ -1151,6 +1151,18 @@ static void generateEncoderScratchStruct(final Ir ir, final OutputManager output indent(writer, 2).append("}\n"); indent(writer).append("}\n\n"); + indent(writer, 1, "/// Advances the `pos` index by a set number of bytes.\n"); + indent(writer).append("#[inline]\n"); + indent(writer).append("fn skip_bytes(&mut self, num_bytes: usize) -> CodecResult<()> {\n"); + indent(writer, 2).append("let end = self.pos + num_bytes;\n"); + indent(writer, 2).append("if end <= self.data.len() {\n"); + indent(writer, 3).append("self.pos = end;\n"); + indent(writer, 3).append("Ok(())\n"); + indent(writer, 2).append("} else {\n"); + indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n"); + indent(writer, 2).append("}\n"); + indent(writer).append("}\n\n"); + indent(writer, 1, "/// Create a struct reference overlaid atop the data buffer\n"); indent(writer, 1, "/// such that changes to the struct directly edit the buffer. \n"); indent(writer, 1, "/// Note that the initial content of the struct's fields may be garbage.\n"); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java index 1811ae30ad..625df5da0b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java @@ -306,6 +306,17 @@ public void messageWithOffsets() assertContains(rust, expectedHeader); } + @Test + public void messageBlockLengthExceedingSumOfFieldLengths() + { + final String rust = fullGenerateForResource(outputManager, "message-block-length-test"); + final String expectedEncoderSegment = "let v = self.scratch.writable_overlay::(9+2)?;"; + assertContains(rust, expectedEncoderSegment); + final String expectedDecoderSegment = "let v = self.scratch.read_type::(9)?;\n" + + " self.scratch.skip_bytes(2)?;"; + assertContains(rust, expectedDecoderSegment); + } + @Test public void constantEnumFields() throws IOException, InterruptedException { From 8eadca87d5e39af87d591b65d74f3f0aabc51967 Mon Sep 17 00:00:00 2001 From: Vadim Platonov Date: Tue, 7 May 2019 10:34:58 +0200 Subject: [PATCH 0064/1594] [Rust] Fix Checkstyle errors --- .../sbe/generation/rust/RustCodecType.java | 4 +- .../sbe/generation/rust/RustGenerator.java | 136 ++++++++++-------- .../generation/rust/RustGeneratorTest.java | 30 ++-- 3 files changed, 99 insertions(+), 71 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java index aba65bebbf..55f71d5bc4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java @@ -54,7 +54,7 @@ void appendDirectCodeMethods( if (trailingBytes > 0) { indent(appendable, 2, "self.%s.skip_bytes(%s)?;\n", - RustCodecType.Decoder.scratchProperty(), trailingBytes); + RustCodecType.Decoder.scratchProperty(), trailingBytes); } indent(appendable, 2, "Ok((v, %s::wrap(self.%s)))\n", nextCoderType, RustCodecType.Decoder.scratchProperty()); @@ -112,7 +112,7 @@ void appendDirectCodeMethods( { indent(appendable, 2, "// fixed message length > sum of field lengths\n"); indent(appendable, 2, "self.%s.skip_bytes(%s)?;\n", - RustCodecType.Decoder.scratchProperty(), trailingBytes); + RustCodecType.Decoder.scratchProperty(), trailingBytes); } indent(appendable, 2).append(format("Ok(%s::wrap(self.%s))\n", nextCoderType, RustCodecType.Encoder.scratchProperty())); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index f4945caa95..39aec1be89 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -105,8 +105,8 @@ private void generateGroupFieldRepresentations( for (final GroupTreeNode node : groupTree) { final RustStruct struct = RustStruct.fromTokens(node.contextualName + "Member", - node.simpleNamedFields, - EnumSet.of(RustStruct.Modifier.PACKED)); + node.simpleNamedFields, + EnumSet.of(RustStruct.Modifier.PACKED)); struct.appendDefinitionTo(appendable); generateConstantAccessorImpl(appendable, node.contextualName + "Member", node.rawFields); @@ -124,10 +124,10 @@ private static RustStruct generateMessageFieldStruct( final String representationStruct = messageTypeName + "Fields"; final RustStruct struct = RustStruct.fromTokens(representationStruct, namedFieldTokens, - EnumSet.of(RustStruct.Modifier.PACKED)); + EnumSet.of(RustStruct.Modifier.PACKED)); try (Writer writer = outputManager.createOutput( - messageTypeName + " Fixed-size Fields (" + struct.sizeBytes() + " bytes)")) + messageTypeName + " Fixed-size Fields (" + struct.sizeBytes() + " bytes)")) { struct.appendDefinitionTo(writer); writer.append("\n"); @@ -208,11 +208,12 @@ private static void generateMessageEncoder( { final Token msgToken = components.messageToken; final String messageTypeName = formatTypeName(msgToken.name()); + final int msgLen = msgToken.encodedLength(); final RustCodecType codecType = RustCodecType.Encoder; String topType = codecType.generateDoneCoderType(outputManager, messageTypeName); topType = generateTopVarDataCoders(messageTypeName, components.varData, outputManager, topType, codecType); topType = generateGroupsCoders(groupTree, outputManager, topType, codecType); - topType = generateFixedFieldCoder(messageTypeName, msgToken.encodedLength(), outputManager, topType, fieldStruct, codecType); + topType = generateFixedFieldCoder(messageTypeName, msgLen, outputManager, topType, fieldStruct, codecType); topType = codecType.generateMessageHeaderCoder(messageTypeName, outputManager, topType, headerSize); generateEntryPoint(messageTypeName, outputManager, topType, codecType); } @@ -227,11 +228,12 @@ private static void generateMessageDecoder( { final Token msgToken = components.messageToken; final String messageTypeName = formatTypeName(msgToken.name()); + final int msgLen = msgToken.encodedLength(); final RustCodecType codecType = RustCodecType.Decoder; String topType = codecType.generateDoneCoderType(outputManager, messageTypeName); topType = generateTopVarDataCoders(messageTypeName, components.varData, outputManager, topType, codecType); topType = generateGroupsCoders(groupTree, outputManager, topType, codecType); - topType = generateFixedFieldCoder(messageTypeName, msgToken.encodedLength(), outputManager, topType, fieldStruct, codecType); + topType = generateFixedFieldCoder(messageTypeName, msgLen, outputManager, topType, fieldStruct, codecType); topType = codecType.generateMessageHeaderCoder(messageTypeName, outputManager, topType, headerSize); generateEntryPoint(messageTypeName, outputManager, topType, codecType); } @@ -275,8 +277,8 @@ private static String generateFixedFieldCoder( appendImplWithLifetimeHeader(writer, decoderName); codecType.appendWrapMethod(writer, decoderName); codecType.appendDirectCodeMethods(writer, formatMethodName(messageTypeName) + "_fields", - fieldStruct.name, topType, fieldStruct.sizeBytes(), - messageEncodedLength - fieldStruct.sizeBytes()); + fieldStruct.name, topType, fieldStruct.sizeBytes(), + messageEncodedLength - fieldStruct.sizeBytes()); writer.append("}\n"); return decoderName; } @@ -618,9 +620,9 @@ private static void writeGroupDecoderTopTypes( indent(out, 1, "pub fn %s_individually(mut self) -> CodecResult<%s> {\n", formatMethodName(node.originalName), groupLevelNextDecoderType); indent(out, 2, "let dim = %s.read_type::<%s>(%s)?;\n", - toScratchChain(node), - formatTypeName(node.dimensionsTypeName()), - node.dimensionsTypeSize()); + toScratchChain(node), + formatTypeName(node.dimensionsTypeName()), + node.dimensionsTypeSize()); indent(out, 2).append("if dim.num_in_group > 0 {\n"); indent(out, 3, "Ok(Either::Left(%s::new(self.%s, dim.num_in_group)))\n", memberDecoderType, contentProperty).append(INDENT).append(INDENT).append("} else {\n"); @@ -659,9 +661,9 @@ private static void appendFixedSizeMemberGroupDecoderMethods( initialNextDecoderType.startsWith("Either") ? initialNextDecoderType : withLifetime(initialNextDecoderType)); indent(out, 2, "let dim = %s.read_type::<%s>(%s)?;\n", - toScratchChain(node), - formatTypeName(node.dimensionsTypeName()), - node.dimensionsTypeSize()); + toScratchChain(node), + formatTypeName(node.dimensionsTypeName()), + node.dimensionsTypeSize()); indent(out, 2, "let s = %s.read_slice::<%s>(dim.num_in_group as usize, %s)?;\n", toScratchChain(node), node.contextualName + "Member", node.blockLength); indent(out, 2, "Ok((s,%s))\n", atEndOfParent ? "self.parent.after_member()" : @@ -788,15 +790,15 @@ private static Token findPrimitiveTokenByTokenName(final List tokens, fin throw new IllegalStateException(format("%s not specified for group", targetName)); } - private static class GroupDimensions + private static final class GroupDimensions { final String typeName; final int typeSize; final PrimitiveType numInGroupType; final PrimitiveType blockLengthType; - private GroupDimensions(String typeName, int typeSize, - PrimitiveType numInGroupType, PrimitiveType blockLengthType) + private GroupDimensions(final String typeName, final int typeSize, + final PrimitiveType numInGroupType, final PrimitiveType blockLengthType) { this.typeName = typeName; this.typeSize = typeSize; @@ -804,7 +806,7 @@ private GroupDimensions(String typeName, int typeSize, this.blockLengthType = blockLengthType; } - public static GroupDimensions ofTokens(List dimensionsTokens) + public static GroupDimensions ofTokens(final List dimensionsTokens) { final PrimitiveType numInGroupType = findPrimitiveByTokenName(dimensionsTokens, "numInGroup"); final PrimitiveType blockLengthType = findPrimitiveByTokenName(dimensionsTokens, "blockLength"); @@ -869,19 +871,23 @@ boolean hasFixedSizeMembers() return groups.isEmpty() && varData.isEmpty(); } - public PrimitiveType dimensionsNumInGroupType() { + public PrimitiveType dimensionsNumInGroupType() + { return dimensions.numInGroupType; } - public PrimitiveType dimensionsBlockLengthType() { + public PrimitiveType dimensionsBlockLengthType() + { return dimensions.blockLengthType; } - public String dimensionsTypeName() { + public String dimensionsTypeName() + { return dimensions.typeName; } - public int dimensionsTypeSize() { + public int dimensionsTypeSize() + { return dimensions.typeSize; } } @@ -1395,8 +1401,8 @@ private static void generateSingleComposite(final List tokens, final Outp try (Writer writer = outputManager.createOutput(formattedTypeName)) { final RustStruct struct = RustStruct.fromTokens(formattedTypeName, - splitTokens.nonConstantEncodingTokens(), - EnumSet.of(RustStruct.Modifier.PACKED)); + splitTokens.nonConstantEncodingTokens(), + EnumSet.of(RustStruct.Modifier.PACKED)); struct.appendDefinitionTo(writer); generateConstantAccessorImpl(writer, formattedTypeName, getMessageBody(tokens)); @@ -1406,7 +1412,9 @@ private static void generateSingleComposite(final List tokens, final Outp private interface RustTypeDescriptor { String name(); + String literalValue(String valueRep); + int sizeBytes(); default String defaultValue() @@ -1420,7 +1428,7 @@ private static final class RustArrayType implements RustTypeDescriptor private final RustTypeDescriptor componentType; private final int length; - private RustArrayType(RustTypeDescriptor component, int length) + private RustArrayType(final RustTypeDescriptor component, final int length) { this.componentType = component; this.length = length; @@ -1433,7 +1441,7 @@ public String name() } @Override - public String literalValue(String valueRep) + public String literalValue(final String valueRep) { return getRustStaticArrayString(valueRep + componentType.name(), length); } @@ -1454,13 +1462,14 @@ public String defaultValue() } else { - StringBuilder result = new StringBuilder(); + final StringBuilder result = new StringBuilder(); result.append('['); for (int i = 0; i < length; i++) { result.append(defaultValue); result.append(", "); - if (i % 4 == 0) { // ~80 char lines + if (i % 4 == 0) // ~80 char lines + { result.append('\n'); } } @@ -1475,7 +1484,7 @@ private static final class RustPrimitiveType implements RustTypeDescriptor private final String name; private final int sizeBytes; - private RustPrimitiveType(String name, int sizeBytes) + private RustPrimitiveType(final String name, final int sizeBytes) { this.name = name; this.sizeBytes = sizeBytes; @@ -1488,13 +1497,14 @@ public String name() } @Override - public String literalValue(String valueRep) + public String literalValue(final String valueRep) { return valueRep + name; } @Override - public int sizeBytes() { + public int sizeBytes() + { return sizeBytes; } } @@ -1504,7 +1514,7 @@ private static final class AnyRustType implements RustTypeDescriptor private final String name; private final int sizeBytes; - private AnyRustType(String name, int sizeBytes) + private AnyRustType(final String name, final int sizeBytes) { this.name = name; this.sizeBytes = sizeBytes; @@ -1517,39 +1527,41 @@ public String name() } @Override - public String literalValue(String valueRep) + public String literalValue(final String valueRep) { final String msg = String.format("Cannot produce a literal value %s of type %s!", valueRep, name); throw new UnsupportedOperationException(msg); } @Override - public int sizeBytes() { + public int sizeBytes() + { return sizeBytes; } } private static final class RustTypes { - static final RustTypeDescriptor u8 = new RustPrimitiveType("u8", 1); + static final RustTypeDescriptor U_8 = new RustPrimitiveType("u8", 1); - static RustTypeDescriptor ofPrimitiveToken(Token token) + static RustTypeDescriptor ofPrimitiveToken(final Token token) { final PrimitiveType primitiveType = token.encoding().primitiveType(); final String rustPrimitiveType = RustUtil.rustTypeName(primitiveType); final RustPrimitiveType type = new RustPrimitiveType(rustPrimitiveType, primitiveType.size()); - if (token.arrayLength() > 1) { + if (token.arrayLength() > 1) + { return new RustArrayType(type, token.arrayLength()); } return type; } - static RustTypeDescriptor ofGeneratedToken(Token token) + static RustTypeDescriptor ofGeneratedToken(final Token token) { return new AnyRustType(formatTypeName(token.applicableTypeName()), token.encodedLength()); } - static RustTypeDescriptor arrayOf(RustTypeDescriptor type, int len) + static RustTypeDescriptor arrayOf(final RustTypeDescriptor type, final int len) { return new RustArrayType(type, len); } @@ -1566,18 +1578,19 @@ enum Modifier final List fields; final EnumSet modifiers; - private RustStruct(String name, List fields, EnumSet modifiers) + private RustStruct(final String name, final List fields, final EnumSet modifiers) { this.name = name; this.fields = fields; this.modifiers = modifiers; } - public int sizeBytes() { + public int sizeBytes() + { return fields.stream().mapToInt(v -> v.type.sizeBytes()).sum(); } - static RustStruct fromHeader(HeaderStructure header) + static RustStruct fromHeader(final HeaderStructure header) { final List tokens = header.tokens(); final String originalTypeName = tokens.get(0).applicableTypeName(); @@ -1588,7 +1601,8 @@ static RustStruct fromHeader(HeaderStructure header) EnumSet.of(RustStruct.Modifier.PACKED)); } - static RustStruct fromTokens(String name, List tokens, EnumSet modifiers) + static RustStruct fromTokens(final String name, final List tokens, + final EnumSet modifiers) { return new RustStruct(name, collectStructFields(tokens), modifiers); } @@ -1596,7 +1610,8 @@ static RustStruct fromTokens(String name, List tokens, EnumSet Self {\n"); @@ -1610,25 +1625,30 @@ void appendDefaultConstructorTo(final Appendable appendable) throws IOException void appendDefinitionTo(final Appendable appendable) throws IOException { appendStructHeader(appendable, name, modifiers.contains(Modifier.PACKED)); - for (RustStructField field: fields) + for (final RustStructField field: fields) { indent(appendable); - if (field.modifiers.contains(RustStructField.Modifier.PUBLIC)) appendable.append("pub "); + if (field.modifiers.contains(RustStructField.Modifier.PUBLIC)) + { + appendable.append("pub "); + } appendable.append(field.name).append(":").append(field.type.name()).append(",\n"); } appendable.append("}\n"); appendDefaultConstructorTo(appendable); } - void appendInstanceTo(final Appendable appendable, int indent) throws IOException + void appendInstanceTo(final Appendable appendable, final int indent) throws IOException { appendInstanceTo(appendable, indent, Collections.emptyMap()); } - void appendInstanceTo(final Appendable appendable, int indent, Map values) throws IOException + void appendInstanceTo(final Appendable appendable, final int indent, + final Map values) throws IOException { indent(appendable, indent, "%s {\n", name); - for (RustStructField field: fields) { + for (final RustStructField field: fields) + { final String value; if (values.containsKey(field.name)) { @@ -1657,14 +1677,14 @@ enum Modifier final RustTypeDescriptor type; final EnumSet modifiers; - private RustStructField(String name, RustTypeDescriptor type, EnumSet modifiers) - { + private RustStructField(final String name, final RustTypeDescriptor type, final EnumSet modifiers) + { this.name = name; this.type = type; this.modifiers = modifiers; } - private RustStructField(String name, RustTypeDescriptor type) + private RustStructField(final String name, final RustTypeDescriptor type) { this(name, type, EnumSet.noneOf(Modifier.class)); } @@ -1686,8 +1706,9 @@ private static List collectStructFields(final List // need padding when field offsets imply gaps final int offset = typeToken.offset(); - if (offset != totalSize) { - final RustTypeDescriptor type = RustTypes.arrayOf(RustTypes.u8, offset - totalSize); + if (offset != totalSize) + { + final RustTypeDescriptor type = RustTypes.arrayOf(RustTypes.U_8, offset - totalSize); fields.add(new RustStructField(propertyName + "_padding", type)); } totalSize = offset + typeToken.encodedLength(); @@ -1739,12 +1760,15 @@ private void generateMessageHeaderDefault( indent(writer, 3, "message_header: "); rustHeader.appendInstanceTo(writer, 3, - new HashMap() {{ + new HashMap() + { + { put("block_length", Integer.toString(messageToken.encodedLength())); put("template_id", Integer.toString(messageToken.id())); put("schema_id", Integer.toString(ir.id())); put("version", Integer.toString(ir.version())); - }}); + } + }); indent(writer, 2, "}\n"); indent(writer, 1, "}\n"); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java index 625df5da0b..0e645525f7 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java @@ -187,12 +187,13 @@ private File writeCargoFolderWrapper(final String name, final String generatedRu return folder; } - private static class CargoCheckResult + private static final class CargoCheckResult { final boolean isSuccess; final String error; - private CargoCheckResult(boolean isSuccess, String error) { + private CargoCheckResult(final boolean isSuccess, final String error) + { this.isSuccess = isSuccess; this.error = error; } @@ -218,7 +219,9 @@ private static CargoCheckResult cargoCheckInDirectory(final File folder) throws if (line == null) { break; - } else { + } + else + { errorString.append(line); errorString.append('\n'); } @@ -250,7 +253,8 @@ private void assertRustBuildable(final String generatedRust, final Optional Date: Tue, 7 May 2019 11:29:46 +0200 Subject: [PATCH 0065/1594] [Rust] Fix example, use sbe-samples schema --- build.gradle | 3 ++- rust/car_example/src/main.rs | 36 ++++++++++++++++++------------------ 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/build.gradle b/build.gradle index ab35c0fc80..ede820b334 100644 --- a/build.gradle +++ b/build.gradle @@ -533,9 +533,10 @@ task generateRustCarExample(type: JavaExec) { classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'rust/car_example/src', + 'sbe.xinclude.aware': 'true', 'sbe.target.language': 'uk.co.real_logic.sbe.generation.rust.Rust', 'sbe.target.namespace': 'car_example_generated_codec') - args = ['sbe-tool/src/test/resources/example-schema.xml'] + args = ['sbe-samples/src/main/resources/example-schema.xml'] } task generateCarExampleDataFile(type: JavaExec) { diff --git a/rust/car_example/src/main.rs b/rust/car_example/src/main.rs index 5562a1eb5a..fcc980edb4 100644 --- a/rust/car_example/src/main.rs +++ b/rust/car_example/src/main.rs @@ -45,11 +45,11 @@ impl std::convert::From for IoError { fn decode_car_and_assert_expected_content(buffer: &[u8]) -> CodecResult<()> { let (h, dec_fields) = start_decoding_car(&buffer).header()?; - assert_eq!(49u16, h.block_length); + assert_eq!(45u16, {h.block_length}); assert_eq!(h.block_length as usize, ::std::mem::size_of::()); - assert_eq!(1u16, h.template_id); - assert_eq!(1u16, h.schema_id); - assert_eq!(0u16, h.version); + assert_eq!(1u16, {h.template_id}); + assert_eq!(1u16, {h.schema_id}); + assert_eq!(0u16, {h.version}); println!("Header read"); assert_eq!(Model::C, CarFields::discounted_model()); @@ -59,16 +59,16 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> CodecResult<()> { let mut found_fuel_figures = Vec::::with_capacity(EXPECTED_FUEL_FIGURES.len()); let (fields, dec_fuel_figures_header) = dec_fields.car_fields()?; - assert_eq!(1234, fields.serial_number); - assert_eq!(2013, fields.model_year); - assert_eq!(BooleanType::T, fields.available); - assert_eq!([97_i8, 98, 99, 100, 101, 102], fields.vehicle_code); // abcdef - assert_eq!([0_u32, 1, 2, 3, 4], fields.some_numbers); + assert_eq!(1234, {fields.serial_number}); + assert_eq!(2013, {fields.model_year}); + assert_eq!(BooleanType::T, {fields.available}); + assert_eq!([97_i8, 98, 99, 100, 101, 102], {fields.vehicle_code}); // abcdef + assert_eq!([1, 2, 3, 4], {fields.some_numbers}); assert_eq!(6, fields.extras.0); assert!(fields.extras.get_cruise_control()); assert!(fields.extras.get_sports_pack()); assert!(!fields.extras.get_sun_roof()); - assert_eq!(2000, fields.engine.capacity); + assert_eq!(2000, {fields.engine.capacity}); assert_eq!(4, fields.engine.num_cylinders); assert_eq!(BoostType::NITROUS, fields.engine.booster.boost_type); assert_eq!(200, fields.engine.booster.horse_power); @@ -82,12 +82,12 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> CodecResult<()> { let (usage_description, next_step) = dec_usage_description.usage_description()?; let usage_str = std::str::from_utf8(usage_description).unwrap(); println!("Fuel Figure: Speed: {0}, MPG: {1}, Usage: {2}", - ff_fields.speed, - ff_fields.mpg, + {ff_fields.speed}, + {ff_fields.mpg}, usage_str); found_fuel_figures.push(FuelFigure { - speed: ff_fields.speed, - mpg: ff_fields.mpg, + speed: {ff_fields.speed}, + mpg: {ff_fields.mpg}, usage_description: usage_str, }); match next_step { @@ -117,8 +117,8 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> CodecResult<()> { let (accel_slice, next_step) = dec_acceleration_header.acceleration_as_slice()?; for accel_fields in accel_slice { println!("Acceleration: MPH: {0}, Seconds: {1}", - accel_fields.mph, - accel_fields.seconds); + {accel_fields.mph}, + {accel_fields.seconds}); } match next_step { Either::Left(more_members) => dec_pf_members = more_members, @@ -165,7 +165,7 @@ fn encode_car_from_scratch() -> CodecResult> { fields.available = BooleanType::T; fields.code = Model::A; fields.vehicle_code = [97_i8, 98, 99, 100, 101, 102]; // abcdef - fields.some_numbers = [0_u32, 1, 2, 3, 4]; + fields.some_numbers = [1, 2, 3, 4]; fields.extras = OptionalExtras::new(); fields.extras.set_cruise_control(true) .set_sports_pack(true) @@ -274,4 +274,4 @@ const EXPECTED_PERF_FIXTURES: &'static [PerfFigure] = &[PerfFigure { mph: 100, seconds: 11.8, }], - }]; \ No newline at end of file + }]; From fb64c017f90de62e455417877412e6cb026d5034 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 7 May 2019 11:18:50 +0100 Subject: [PATCH 0066/1594] [Java] Only run buildScan in CI. --- build.gradle | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index 88ef9cdfff..a33c74e768 100644 --- a/build.gradle +++ b/build.gradle @@ -20,19 +20,22 @@ buildscript { } plugins { - id 'com.gradle.build-scan' version '2.3' id 'java' - id 'com.github.johnrengelman.shadow' version '5.0.0' apply false + id 'com.gradle.build-scan' version '2.3' id "io.freefair.javadoc-links" version "3.2.1" apply false -} - -buildScan { - termsOfServiceUrl = 'https://gradle.com/terms-of-service' - apply from: 'gradle/build-scans.gradle' + id 'com.github.johnrengelman.shadow' version '5.0.0' apply false } defaultTasks 'clean', 'build', 'shadowJar', 'install' +def env = System.getenv() +if (env.CI || env.TRAVIS) { + buildScan { + termsOfServiceUrl = 'https://gradle.com/terms-of-service' + apply from: 'gradle/build-scans.gradle' + } +} + def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() def sbeJavaVersion = JavaVersion.VERSION_1_8 From 25ef95f64fdb3790ee4658d3df71b37639819c83 Mon Sep 17 00:00:00 2001 From: Vadim Platonov Date: Tue, 7 May 2019 13:03:53 +0200 Subject: [PATCH 0067/1594] [Rust] Derive Default when possible --- .../sbe/generation/rust/RustGenerator.java | 85 +++++++++++++------ .../generation/rust/RustGeneratorTest.java | 4 +- 2 files changed, 61 insertions(+), 28 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 39aec1be89..b0c3aec4e9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -106,7 +106,7 @@ private void generateGroupFieldRepresentations( { final RustStruct struct = RustStruct.fromTokens(node.contextualName + "Member", node.simpleNamedFields, - EnumSet.of(RustStruct.Modifier.PACKED)); + EnumSet.of(RustStruct.Modifier.PACKED, RustStruct.Modifier.DEFAULT)); struct.appendDefinitionTo(appendable); generateConstantAccessorImpl(appendable, node.contextualName + "Member", node.rawFields); @@ -124,7 +124,7 @@ private static RustStruct generateMessageFieldStruct( final String representationStruct = messageTypeName + "Fields"; final RustStruct struct = RustStruct.fromTokens(representationStruct, namedFieldTokens, - EnumSet.of(RustStruct.Modifier.PACKED)); + EnumSet.of(RustStruct.Modifier.PACKED, RustStruct.Modifier.DEFAULT)); try (Writer writer = outputManager.createOutput( messageTypeName + " Fixed-size Fields (" + struct.sizeBytes() + " bytes)")) @@ -410,7 +410,7 @@ private static String writeGroupEncoderTopTypes( final String headerCoderType = node.contextualName + "HeaderEncoder"; try (Writer out = outputManager.createOutput(node.contextualName + " Encoder for fields and header")) { - appendStructHeader(out, withLifetime(memberCoderType), false); + appendStructHeader(out, withLifetime(memberCoderType)); final String rustCountType = rustTypeName(node.dimensionsNumInGroupType()); final String contentProperty; final String contentBearingType; @@ -460,7 +460,7 @@ private static String writeGroupEncoderTopTypes( format("%s::wrap(self.%s)", afterGroupCoderType, contentProperty)); indent(out).append("}\n").append("}\n"); - appendStructHeader(out, withLifetime(headerCoderType), false); + appendStructHeader(out, withLifetime(headerCoderType)); indent(out, 1, "%s: %s,\n", contentProperty, contentBearingType); out.append("}\n"); @@ -558,7 +558,7 @@ private static void writeGroupDecoderTopTypes( { try (Writer out = outputManager.createOutput(node.contextualName + " Decoder for fields and header")) { - appendStructHeader(out, withLifetime(memberDecoderType), false); + appendStructHeader(out, withLifetime(memberDecoderType)); final String rustCountType = rustTypeName(node.dimensionsNumInGroupType()); final String contentProperty; final String contentBearingType; @@ -609,7 +609,7 @@ private static void writeGroupDecoderTopTypes( format("%s::wrap(self.%s)", initialNextDecoderType, contentProperty))); indent(out, 2).append("}\n").append(INDENT).append("}\n").append("}\n"); - appendStructHeader(out, withLifetime(headerDecoderType), false); + appendStructHeader(out, withLifetime(headerDecoderType)); indent(out, 1, "%s: %s,\n", contentProperty, contentBearingType).append("}\n"); appendImplWithLifetimeHeader(out, headerDecoderType); @@ -922,7 +922,7 @@ String generateVarDataEncoder( final String decoderType = parentContextualName + formatTypeName(name) + codecType.name(); try (Writer writer = outputManager.createOutput(name + " variable-length data")) { - appendStructHeader(writer, withLifetime(decoderType), false); + appendStructHeader(writer, withLifetime(decoderType)); final String contentPropertyName = groupDepth > 0 ? "parent" : codecType.scratchProperty(); indent(writer, 1, "%s: %s,\n", contentPropertyName, withLifetime(contentType)); writer.append("}\n"); @@ -973,7 +973,7 @@ String generateVarDataDecoder( final String decoderType = parentContextualName + formatTypeName(name) + "Decoder"; try (Writer writer = outputManager.createOutput(name + " variable-length data")) { - appendStructHeader(writer, withLifetime(decoderType), false); + appendStructHeader(writer, withLifetime(decoderType)); final String contentPropertyName = groupDepth > 0 ? "parent" : SCRATCH_DECODER_PROPERTY; indent(writer, 1, "%s: %s,\n", contentPropertyName, withLifetime(contentType)); writer.append("}\n"); @@ -1402,7 +1402,7 @@ private static void generateSingleComposite(final List tokens, final Outp { final RustStruct struct = RustStruct.fromTokens(formattedTypeName, splitTokens.nonConstantEncodingTokens(), - EnumSet.of(RustStruct.Modifier.PACKED)); + EnumSet.of(RustStruct.Modifier.PACKED, RustStruct.Modifier.DEFAULT)); struct.appendDefinitionTo(writer); generateConstantAccessorImpl(writer, formattedTypeName, getMessageBody(tokens)); @@ -1411,6 +1411,8 @@ private static void generateSingleComposite(final List tokens, final Outp private interface RustTypeDescriptor { + String DEFAULT_VALUE = "Default::default()"; + String name(); String literalValue(String valueRep); @@ -1419,7 +1421,7 @@ private interface RustTypeDescriptor default String defaultValue() { - return "Default::default()"; + return DEFAULT_VALUE; } } @@ -1571,7 +1573,7 @@ private static final class RustStruct { enum Modifier { - PACKED + PACKED, DEFAULT } final String name; @@ -1598,7 +1600,7 @@ static RustStruct fromHeader(final HeaderStructure header) final SplitCompositeTokens splitTokens = SplitCompositeTokens.splitInnerTokens(tokens); return RustStruct.fromTokens(formattedTypeName, splitTokens.nonConstantEncodingTokens(), - EnumSet.of(RustStruct.Modifier.PACKED)); + EnumSet.of(Modifier.PACKED, Modifier.DEFAULT)); } static RustStruct fromTokens(final String name, final List tokens, @@ -1609,13 +1611,13 @@ static RustStruct fromTokens(final String name, final List tokens, // No way to create struct with default values. // Rust RFC: https://github.com/Centril/rfcs/pull/19 - // TODO: #[derive(Default)] ? + // Used when struct contains a field which doesn't have a Default impl void appendDefaultConstructorTo(final Appendable appendable) throws IOException { indent(appendable, 0, "impl Default for %s {\n", name); indent(appendable, 1, "fn default() -> Self {\n"); - appendInstanceTo(appendable, 2); + appendInstanceTo(appendable, 2, Collections.emptyMap()); indent(appendable, 1, "}\n"); @@ -1624,7 +1626,17 @@ void appendDefaultConstructorTo(final Appendable appendable) throws IOException void appendDefinitionTo(final Appendable appendable) throws IOException { - appendStructHeader(appendable, name, modifiers.contains(Modifier.PACKED)); + final boolean needsDefault = modifiers.contains(Modifier.DEFAULT); + final boolean canDeriveDefault = fields.stream() + .allMatch(v -> v.type.defaultValue() == RustTypeDescriptor.DEFAULT_VALUE); + + final Set modifiers = this.modifiers.clone(); + if (needsDefault && !canDeriveDefault) + { + modifiers.remove(Modifier.DEFAULT); + } + + appendStructHeader(appendable, name, modifiers); for (final RustStructField field: fields) { indent(appendable); @@ -1635,12 +1647,11 @@ void appendDefinitionTo(final Appendable appendable) throws IOException appendable.append(field.name).append(":").append(field.type.name()).append(",\n"); } appendable.append("}\n"); - appendDefaultConstructorTo(appendable); - } - void appendInstanceTo(final Appendable appendable, final int indent) throws IOException - { - appendInstanceTo(appendable, indent, Collections.emptyMap()); + if (needsDefault && !canDeriveDefault) + { + appendDefaultConstructorTo(appendable); + } } void appendInstanceTo(final Appendable appendable, final int indent, @@ -1708,8 +1719,18 @@ private static List collectStructFields(final List final int offset = typeToken.offset(); if (offset != totalSize) { - final RustTypeDescriptor type = RustTypes.arrayOf(RustTypes.U_8, offset - totalSize); - fields.add(new RustStructField(propertyName + "_padding", type)); + int rem = offset - totalSize; + int idx = 1; + while (rem > 0) + { + // split padding arrays to 32 as larger arrays do not have an `impl Default` + final int padding = Math.min(rem, 32); + final RustTypeDescriptor type = RustTypes.arrayOf(RustTypes.U_8, padding); + fields.add(new RustStructField(propertyName + "_padding_" + idx, type)); + + idx += 1; + rem -= padding; + } } totalSize = offset + typeToken.encodedLength(); @@ -1750,7 +1771,7 @@ private void generateMessageHeaderDefault( try (Writer writer = outputManager.createOutput(messageTypeName + " specific Message Header ")) { - appendStructHeader(writer, wrapperName, true); + appendStructHeader(writer, wrapperName, EnumSet.of(RustStruct.Modifier.PACKED)); indent(writer, 1, "pub message_header: MessageHeader\n"); writer.append("}\n"); @@ -1777,14 +1798,26 @@ private void generateMessageHeaderDefault( } } + private static void appendStructHeader(final Appendable appendable, final String structName) throws IOException + { + appendStructHeader(appendable, structName, EnumSet.noneOf(RustStruct.Modifier.class)); + } + private static void appendStructHeader( final Appendable appendable, final String structName, - final boolean packedCRepresentation) throws IOException + final Set modifiers) throws IOException { - if (packedCRepresentation) + if (!modifiers.isEmpty()) { - appendable.append("#[repr(C,packed)]\n"); + if (modifiers.contains(RustStruct.Modifier.PACKED)) + { + appendable.append("#[repr(C,packed)]\n"); + } + if (modifiers.contains(RustStruct.Modifier.DEFAULT)) + { + appendable.append("#[derive(Default)]\n"); + } } appendable.append(format("pub struct %s {\n", structName)); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java index 0e645525f7..9727aa35ed 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java @@ -301,9 +301,9 @@ public void messageWithOffsets() final String expectedHeader = "pub struct MessageHeader {\n" + " pub block_length:u16,\n" + - " template_id_padding:[u8;2],\n" + + " template_id_padding_1:[u8;2],\n" + " pub template_id:u16,\n" + - " schema_id_padding:[u8;2],\n" + + " schema_id_padding_1:[u8;2],\n" + " pub schema_id:u16,\n" + " pub version:u16,\n" + "}"; From 39e394715d8a6c588d3d32048bd156aa5ab52a9e Mon Sep 17 00:00:00 2001 From: Vadim Platonov Date: Tue, 7 May 2019 13:44:00 +0200 Subject: [PATCH 0068/1594] [Rust] Generate Debug for bit set --- .../sbe/generation/rust/RustGenerator.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index b0c3aec4e9..b7e32323fd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -196,6 +196,34 @@ private static void generateSingleBitSet(final List tokens, final OutputM writer.append("}\n"); } + + try (Writer writer = outputManager.createOutput(setType + " bit set debug")) + { + indent(writer, 0, "impl core::fmt::Debug for %s {\n", setType); + indent(writer, 1, "fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {\n"); + indent(writer, 2, "write!(fmt, \"%s[", setType); + + final StringBuilder string = new StringBuilder(); + final StringBuilder arguments = new StringBuilder(); + for (final Token token : tokens) + { + if (Signal.CHOICE != token.signal()) + { + continue; + } + + final String choiceName = formatMethodName(token.name()); + final String choiceBitIndex = token.encoding().constValue().toString(); + + string.append(choiceName + "(" + choiceBitIndex + ")={},"); + arguments.append("self.get_" + choiceName + "(),"); + } + + writer.append(string.toString() + "]\",\n"); + indent(writer, 3, arguments.toString() + ")\n"); + indent(writer, 1, "}\n"); + writer.append("}\n"); + } } private static void generateMessageEncoder( From a93029904f313c87ba5fe4004d50c976a6372e42 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 7 May 2019 15:39:40 +0100 Subject: [PATCH 0069/1594] [Java] Tidy up after merge to of PR #679. --- .../sbe/generation/rust/RustGenerator.java | 72 +++++++++---------- .../generation/rust/RustGeneratorTest.java | 13 ++-- 2 files changed, 39 insertions(+), 46 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index b7e32323fd..22a491be6c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -53,10 +53,10 @@ public RustGenerator(final Ir ir, final OutputManager outputManager) public void generate() throws IOException { - generateSharedImports(ir, outputManager); + generateSharedImports(outputManager); generateResultEnums(outputManager); generateDecoderScratchStruct(outputManager); - generateEncoderScratchStruct(ir, outputManager); + generateEncoderScratchStruct(outputManager); generateEitherEnum(outputManager); generateEnums(ir, outputManager); generateComposites(ir, outputManager); @@ -203,7 +203,7 @@ private static void generateSingleBitSet(final List tokens, final OutputM indent(writer, 1, "fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {\n"); indent(writer, 2, "write!(fmt, \"%s[", setType); - final StringBuilder string = new StringBuilder(); + final StringBuilder builder = new StringBuilder(); final StringBuilder arguments = new StringBuilder(); for (final Token token : tokens) { @@ -215,11 +215,11 @@ private static void generateSingleBitSet(final List tokens, final OutputM final String choiceName = formatMethodName(token.name()); final String choiceBitIndex = token.encoding().constValue().toString(); - string.append(choiceName + "(" + choiceBitIndex + ")={},"); - arguments.append("self.get_" + choiceName + "(),"); + builder.append(choiceName).append("(").append(choiceBitIndex).append(")={},"); + arguments.append("self.get_").append(choiceName).append("(),"); } - writer.append(string.toString() + "]\",\n"); + writer.append(builder.toString()).append("]\",\n"); indent(writer, 3, arguments.toString() + ")\n"); indent(writer, 1, "}\n"); writer.append("}\n"); @@ -308,6 +308,7 @@ private static String generateFixedFieldCoder( fieldStruct.name, topType, fieldStruct.sizeBytes(), messageEncodedLength - fieldStruct.sizeBytes()); writer.append("}\n"); + return decoderName; } } @@ -535,6 +536,9 @@ private static void appendFixedSizeMemberGroupEncoderMethods( final String fieldsType, final String scratchChain) throws IOException { + final String s = atEndOfParent ? + "self.parent" : format("%s::wrap(self.%s)", afterGroupCoderType, contentProperty); + indent(out).append("#[inline]\n"); indent(out, 1, "pub fn %s_as_slice(mut self, count: %s) -> CodecResult<(&%s mut [%s], %s)> {\n", formatMethodName(node.originalName), rustCountType, DATA_LIFETIME, fieldsType, @@ -548,8 +552,8 @@ scratchChain, rustTypeName(node.dimensionsBlockLengthType()), indent(out, 2, "let c = count as usize;\n"); indent(out, 2, "let group_slice = %s.writable_slice::<%s>(c, %s)?;\n", scratchChain, fieldsType, node.blockLength); - indent(out, 2, "Ok((group_slice, %s))\n", atEndOfParent ? - "self.parent" : format("%s::wrap(self.%s)", afterGroupCoderType, contentProperty)); + + indent(out, 2, "Ok((group_slice, %s))\n", s); indent(out, 1).append("}\n"); indent(out).append("#[inline]\n"); @@ -568,8 +572,7 @@ scratchChain, rustTypeName(node.dimensionsBlockLengthType()), scratchChain, rustCountType, rustCountType, node.dimensionsNumInGroupType().size()); indent(out, 2, "%s.write_slice_without_count::<%s>(s, %s)?;\n", scratchChain, fieldsType, node.blockLength); - indent(out, 2, "Ok(%s)\n", atEndOfParent ? "self.parent" : - format("%s::wrap(self.%s)", afterGroupCoderType, contentProperty)); + indent(out, 2, "Ok(%s)\n", s); indent(out, 1).append("}\n"); } @@ -1129,7 +1132,7 @@ private static void generateEnums(final Ir ir, final OutputManager outputManager } } - static void generateSharedImports(final Ir ir, final OutputManager outputManager) throws IOException + static void generateSharedImports(final OutputManager outputManager) throws IOException { try (Writer writer = outputManager.createOutput("Imports core rather than std to broaden usable environments.")) { @@ -1155,7 +1158,7 @@ static void generateResultEnums(final OutputManager outputManager) throws IOExce } } - static void generateEncoderScratchStruct(final Ir ir, final OutputManager outputManager) throws IOException + static void generateEncoderScratchStruct(final OutputManager outputManager) throws IOException { try (Writer writer = outputManager.createOutput("Scratch Encoder Data Wrapper - codec internal use only")) { @@ -1464,25 +1467,21 @@ private RustArrayType(final RustTypeDescriptor component, final int length) this.length = length; } - @Override public String name() { return getRustStaticArrayString(componentType.name(), length); } - @Override public String literalValue(final String valueRep) { return getRustStaticArrayString(valueRep + componentType.name(), length); } - @Override public int sizeBytes() { return componentType.sizeBytes() * length; } - @Override public String defaultValue() { final String defaultValue = RustTypeDescriptor.super.defaultValue(); @@ -1504,6 +1503,7 @@ public String defaultValue() } } result.append(']'); + return result.toString(); } } @@ -1520,19 +1520,16 @@ private RustPrimitiveType(final String name, final int sizeBytes) this.sizeBytes = sizeBytes; } - @Override public String name() { return name; } - @Override public String literalValue(final String valueRep) { return valueRep + name; } - @Override public int sizeBytes() { return sizeBytes; @@ -1550,20 +1547,17 @@ private AnyRustType(final String name, final int sizeBytes) this.sizeBytes = sizeBytes; } - @Override public String name() { return name; } - @Override public String literalValue(final String valueRep) { final String msg = String.format("Cannot produce a literal value %s of type %s!", valueRep, name); throw new UnsupportedOperationException(msg); } - @Override public int sizeBytes() { return sizeBytes; @@ -1583,6 +1577,7 @@ static RustTypeDescriptor ofPrimitiveToken(final Token token) { return new RustArrayType(type, token.arrayLength()); } + return type; } @@ -1617,7 +1612,7 @@ private RustStruct(final String name, final List fields, final public int sizeBytes() { - return fields.stream().mapToInt(v -> v.type.sizeBytes()).sum(); + return fields.stream().mapToInt((v) -> v.type.sizeBytes()).sum(); } static RustStruct fromHeader(final HeaderStructure header) @@ -1626,13 +1621,15 @@ static RustStruct fromHeader(final HeaderStructure header) final String originalTypeName = tokens.get(0).applicableTypeName(); final String formattedTypeName = formatTypeName(originalTypeName); final SplitCompositeTokens splitTokens = SplitCompositeTokens.splitInnerTokens(tokens); - return RustStruct.fromTokens(formattedTypeName, - splitTokens.nonConstantEncodingTokens(), - EnumSet.of(Modifier.PACKED, Modifier.DEFAULT)); + + return RustStruct.fromTokens( + formattedTypeName, + splitTokens.nonConstantEncodingTokens(), + EnumSet.of(Modifier.PACKED, Modifier.DEFAULT)); } - static RustStruct fromTokens(final String name, final List tokens, - final EnumSet modifiers) + static RustStruct fromTokens( + final String name, final List tokens, final EnumSet modifiers) { return new RustStruct(name, collectStructFields(tokens), modifiers); } @@ -1656,7 +1653,7 @@ void appendDefinitionTo(final Appendable appendable) throws IOException { final boolean needsDefault = modifiers.contains(Modifier.DEFAULT); final boolean canDeriveDefault = fields.stream() - .allMatch(v -> v.type.defaultValue() == RustTypeDescriptor.DEFAULT_VALUE); + .allMatch((v) -> v.type.defaultValue() == RustTypeDescriptor.DEFAULT_VALUE); final Set modifiers = this.modifiers.clone(); if (needsDefault && !canDeriveDefault) @@ -1682,8 +1679,8 @@ void appendDefinitionTo(final Appendable appendable) throws IOException } } - void appendInstanceTo(final Appendable appendable, final int indent, - final Map values) throws IOException + void appendInstanceTo(final Appendable appendable, final int indent, final Map values) + throws IOException { indent(appendable, indent, "%s {\n", name); for (final RustStructField field: fields) @@ -1702,7 +1699,6 @@ void appendInstanceTo(final Appendable appendable, final int indent, } indent(appendable, indent, "}\n"); } - } private static final class RustStructField @@ -1778,8 +1774,7 @@ private static List collectStructFields(final List break; default: - throw new IllegalStateException( - format("Unsupported struct property from %s", typeToken.toString())); + throw new IllegalStateException(format("Unsupported struct property from %s", typeToken)); } } return fields; @@ -1832,9 +1827,8 @@ private static void appendStructHeader(final Appendable appendable, final String } private static void appendStructHeader( - final Appendable appendable, - final String structName, - final Set modifiers) throws IOException + final Appendable appendable, final String structName, final Set modifiers) + throws IOException { if (!modifiers.isEmpty()) { @@ -1873,9 +1867,7 @@ private static String getRustTypeForPrimitivePossiblyArray( } private static void generateConstantAccessorImpl( - final Appendable writer, - final String formattedTypeName, - final List unfilteredFields) throws IOException + final Appendable writer, final String formattedTypeName, final List unfilteredFields) throws IOException { writer.append(format("%nimpl %s {\n", formattedTypeName)); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java index 9727aa35ed..c5a229ad25 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java @@ -39,8 +39,8 @@ public void setUp() private static Ir generateIrForResource(final String localResourceName) { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final String xmlLocalResourceName = localResourceName.endsWith(".xml") ? localResourceName : - localResourceName + ".xml"; + final String xmlLocalResourceName = localResourceName.endsWith(".xml") ? + localResourceName : localResourceName + ".xml"; final MessageSchema schema; try @@ -72,7 +72,7 @@ public void nullIrTossesNpe() @Test public void generateSharedImports() throws IOException { - RustGenerator.generateSharedImports(generateIrForResource(BROAD_USE_CASES_SCHEMA), outputManager); + RustGenerator.generateSharedImports(outputManager); assertContainsSharedImports(outputManager.toString()); } @@ -85,13 +85,12 @@ private static void assertContainsSharedImports(final String generatedRust) @Test public void generateBasicEnum() throws IOException { - RustGenerator.generateSharedImports(generateIrForResource(BASIC_TYPES_SCHEMA), outputManager); + RustGenerator.generateSharedImports(outputManager); assertContainsSharedImports(outputManager.toString()); } private static String fullGenerateForResource( - final SingleStringOutputManager outputManager, - final String localResourceName) + final SingleStringOutputManager outputManager, final String localResourceName) { outputManager.clear(); @@ -139,6 +138,7 @@ public void fullGenerateBroadUseCase() throws IOException, InterruptedException " let v = self.scratch.read_type::(49)?;\n" + " Ok((v, CarFuelFiguresHeaderDecoder::wrap(self.scratch)))\n" + " }"); + final String expectedBooleanTypeDeclaration = "#[derive(Clone,Copy,Debug,PartialEq,Eq,PartialOrd,Ord,Hash)]\n" + "#[repr(u8)]\n" + @@ -148,6 +148,7 @@ public void fullGenerateBroadUseCase() throws IOException, InterruptedException " NullVal = 255u8,\n" + "}\n"; assertTrue(generatedRust.contains(expectedBooleanTypeDeclaration)); + final String expectedCharTypeDeclaration = "#[derive(Clone,Copy,Debug,PartialEq,Eq,PartialOrd,Ord,Hash)]\n" + "#[repr(i8)]\n" + From 0f308f4224b9fada1411b0a593bdf0587f6577ad Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 8 May 2019 08:47:21 +0100 Subject: [PATCH 0070/1594] [Java] Upgrade to javadoc-links 3.3.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8d7030d26b..8f31ee7c64 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.3' - id "io.freefair.javadoc-links" version "3.2.1" apply false + id "io.freefair.javadoc-links" version "3.3.1" apply false id 'com.github.johnrengelman.shadow' version '5.0.0' apply false } From ea35e4edc01a9de92529170c59681567d88a16a9 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 8 May 2019 15:29:23 +0100 Subject: [PATCH 0071/1594] [Java] Upgrade to hamcrest 2.1. --- build.gradle | 4 ++-- .../co/real_logic/sbe/generation/java/JavaGeneratorTest.java | 2 +- .../real_logic/sbe/generation/java/SchemaExtensionTest.java | 2 +- .../co/real_logic/sbe/generation/rust/RustGeneratorTest.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 8f31ee7c64..d2ee90d498 100644 --- a/build.gradle +++ b/build.gradle @@ -139,9 +139,9 @@ subprojects { compile 'org.agrona:agrona:1.0.0' - testCompile 'junit:junit:4.12' + testCompile 'org.hamcrest:hamcrest:2.1' testCompile 'org.mockito:mockito-core:2.27.0' - testCompile 'org.hamcrest:hamcrest-library:1.3' + testCompile 'junit:junit:4.12' } checkstyle { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index c39fa0adcc..1180a460d3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -33,7 +33,7 @@ import java.nio.ByteOrder; import java.util.Map; -import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.hasToString; import static org.hamcrest.Matchers.startsWith; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index 2c5bf3b5f4..65714cec13 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -30,7 +30,7 @@ import java.util.Map; -import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.*; import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.get; import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.set; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java index c5a229ad25..8c95ec1ace 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java @@ -14,7 +14,7 @@ import java.util.Optional; import java.util.concurrent.TimeUnit; -import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static uk.co.real_logic.sbe.generation.rust.RustTest.minimalDummyIr; From cedd6b675f6663baffc194238bbe30fff2bb9d67 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Thu, 9 May 2019 21:05:13 +0900 Subject: [PATCH 0072/1594] [C] Suppress maybe-uninitialized warnings in tests. --- sbe-tool/src/test/c/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index d5d2a85b53..47f0aba0db 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -22,7 +22,7 @@ function(sbe_test name) ) target_compile_options("C${name}" PRIVATE $<$:-Werror>) target_compile_options("C${name}" PRIVATE $<$:-Werror>) - target_compile_options("C${name}" PRIVATE $<$:-Werror>) + target_compile_options("C${name}" PRIVATE $<$:-Werror -Wno-maybe-uninitialized>) target_link_libraries("C${name}" ${GTEST_LIBS} ${CMAKE_THREAD_LIBS_INIT}) add_test(NAME C${name} COMMAND C${name} WORKING_DIRECTORY ${C_CODEC_TARGET_DIR}) add_dependencies(C${name} gtest) From fca6783f7da4b855207920b07926bb67a6bf8219 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Wed, 10 Apr 2019 16:05:49 +0900 Subject: [PATCH 0073/1594] [C] Add blank line after length check block. --- .../java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 0219f89034..1d8fe1584d 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1595,7 +1595,8 @@ private CharSequence generateArrayProperty( " {\n" + " errno = E105;\n" + " return NULL;\n" + - " }\n" + + " }\n\n" + + "%5$s\n" + " return codec;\n" + "}\n", From d779017287071ff1e2d29bb2829665297066e8d8 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Sat, 4 May 2019 15:05:04 +0900 Subject: [PATCH 0074/1594] [C] Remove the dimension member from the codec classes. --- .../sbe/generation/c/CGenerator.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 1d8fe1584d..8107b6e8e4 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -217,10 +217,8 @@ private static void generateGroupStruct( final List tokens, final int index) { - final String dimensionsStructName = formatScopedName(scope, tokens.get(index + 1).name()); - sb.append(String.format("\n" + - "struct %1$s\n" + + "struct %s\n" + "{\n" + " char *buffer;\n" + " uint64_t buffer_length;\n" + @@ -230,9 +228,8 @@ private static void generateGroupStruct( " uint64_t index;\n" + " uint64_t offset;\n" + " uint64_t acting_version;\n" + - " struct %2$s dimensions;\n" + "};\n", - groupName, dimensionsStructName)); + groupName)); } private static void generateGroupHeaderFunctions( @@ -265,12 +262,13 @@ private static void generateGroupHeaderFunctions( "{\n" + " codec->buffer = buffer;\n" + " codec->buffer_length = buffer_length;\n" + - " if (!%2$s_wrap(&codec->dimensions, codec->buffer, *pos, acting_version, buffer_length))\n" + + " struct %2$s dimensions;\n" + + " if (!%2$s_wrap(&dimensions, codec->buffer, *pos, acting_version, buffer_length))\n" + " {\n" + " return NULL;\n" + " }\n" + - " codec->block_length = %2$s_blockLength(&codec->dimensions);\n" + - " codec->count = %2$s_numInGroup(&codec->dimensions);\n" + + " codec->block_length = %2$s_blockLength(&dimensions);\n" + + " codec->count = %2$s_numInGroup(&dimensions);\n" + " codec->index = -1;\n" + " codec->acting_version = acting_version;\n" + " codec->position_ptr = pos;\n" + @@ -305,12 +303,13 @@ private static void generateGroupHeaderFunctions( "#endif\n" + " codec->buffer = buffer;\n" + " codec->buffer_length = buffer_length;\n" + - " if (!%5$s_wrap(&codec->dimensions, codec->buffer, *pos, acting_version, buffer_length))\n" + + " struct %5$s dimensions;\n" + + " if (!%5$s_wrap(&dimensions, codec->buffer, *pos, acting_version, buffer_length))\n" + " {\n" + " return NULL;\n" + " }\n" + - " %5$s_set_blockLength(&codec->dimensions, (%2$s)%3$d);\n" + - " %5$s_set_numInGroup(&codec->dimensions, (%4$s)count);\n" + + " %5$s_set_blockLength(&dimensions, (%2$s)%3$d);\n" + + " %5$s_set_numInGroup(&dimensions, (%4$s)count);\n" + " codec->index = -1;\n" + " codec->count = count;\n" + " codec->block_length = %3$d;\n" + From cc9e2a065fa7c54f5adb127cc64397f27572ac7d Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Thu, 9 May 2019 20:36:05 +0100 Subject: [PATCH 0075/1594] [C] Tidy up for CGenerator. --- .../sbe/generation/c/CGenerator.java | 47 ++++++------------- sbe-tool/src/test/c/CComplianceTest.c | 3 +- sbe-tool/src/test/c/GroupWithDataTest.cpp | 2 +- 3 files changed, 17 insertions(+), 35 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 8107b6e8e4..03cb3ecfbe 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -187,7 +187,7 @@ private void generateGroups( final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, i); final String cTypeForNumInGroup = cTypeName(numInGroupToken.encoding().primitiveType()); - generateGroupStruct(sb, scope, groupName, tokens, i); + generateGroupStruct(sb, groupName); generateGroupHeaderFunctions(sb, scope, groupName, tokens, i); ++i; @@ -210,12 +210,7 @@ private void generateGroups( } } - private static void generateGroupStruct( - final StringBuilder sb, - final CharSequence[] scope, - final String groupName, - final List tokens, - final int index) + private static void generateGroupStruct(final StringBuilder sb, final String groupName) { sb.append(String.format("\n" + "struct %s\n" + @@ -484,9 +479,7 @@ private static CharSequence generateGroupPropertyFunctions( } private CharSequence generateVarData( - final String structName, - final String outermostStruct, - final List tokens) + final String structName, final String outermostStruct, final List tokens) { final StringBuilder sb = new StringBuilder(); @@ -755,8 +748,7 @@ private void generateComposite(final CharSequence[] scope, final List tok final String compositeName = formatScopedName(scope, compositeToken.applicableTypeName()); out.append(generateFileHeader( - compositeName, - generateTypesToIncludes(tokens.subList(1, tokens.size() - 1)))); + compositeName, generateTypesToIncludes(tokens.subList(1, tokens.size() - 1)))); out.append(generateFixedFlyweightStruct(compositeName)); out.append(String.format("\n" + "enum %1$s_meta_attribute\n" + @@ -882,9 +874,7 @@ private CharSequence generateChoices(final String bitsetStructName, final List tokens, - final Token encodingToken) + final CharSequence[] scope, final List tokens, final Token encodingToken) { final StringBuilder sb = new StringBuilder(); final Encoding encoding = encodingToken.encoding(); @@ -917,9 +907,7 @@ private CharSequence generateEnumValues( } private static CharSequence generateEnumLookupFunction( - final CharSequence[] scope, - final List tokens, - final Token encodingToken) + final CharSequence[] scope, final List tokens, final Token encodingToken) { final String enumName = formatScopedName(scope, encodingToken.applicableTypeName()); final StringBuilder sb = new StringBuilder(); @@ -958,8 +946,7 @@ private static CharSequence generateEnumLookupFunction( return sb; } - private CharSequence generateFieldNotPresentCondition( - final int sinceVersion, final Encoding encoding) + private CharSequence generateFieldNotPresentCondition(final int sinceVersion, final Encoding encoding) { if (0 == sinceVersion) { @@ -1020,9 +1007,7 @@ private static CharSequence generateTypeFieldNotPresentCondition(final int since sinceVersion); } - private static CharSequence generateFileHeader( - final String structName, - final List typesToInclude) + private static CharSequence generateFileHeader(final String structName, final List typesToInclude) { final StringBuilder sb = new StringBuilder(); @@ -1111,7 +1096,7 @@ private static CharSequence generateFileHeader( "#define SBE_NULLVALUE_UINT64 UINT64_MAX\n\n" + "#define E100 -50100 // E_BUF_SHORT\n" + - "#define E103 -50103 // VAL_UNKNWN_ENUM\n" + + "#define E103 -50103 // VAL_UNKNOWN_ENUM\n" + "#define E104 -50104 // I_OUT_RANGE_NUM\n" + "#define E105 -50105 // I_OUT_RANGE_NUM\n" + "#define E106 -50106 // I_OUT_RANGE_NUM\n" + @@ -1204,9 +1189,7 @@ private void generatePropertyFunctions( } private CharSequence generateCompositePropertyFunctions( - final CharSequence[] scope, - final String containingStructName, - final List tokens) + final CharSequence[] scope, final String containingStructName, final List tokens) { final StringBuilder sb = new StringBuilder(); @@ -1220,12 +1203,14 @@ private CharSequence generateCompositePropertyFunctions( fieldToken, containingStructName, containingStructName); + generateFieldCommonFunctions( sb, fieldToken, fieldToken, propertyName, containingStructName); + generatePropertyFunctions( sb, scope, @@ -1834,9 +1819,7 @@ private CharSequence generateMessageFlyweightStruct(final String structName) } private CharSequence generateMessageFlyweightFunctions( - final String structName, - final Token token, - final CharSequence[] scope) + final String structName, final Token token, final CharSequence[] scope) { final String blockLengthType = cTypeName(ir.headerStructure().blockLengthType()); final String templateIdType = cTypeName(ir.headerStructure().templateIdType()); @@ -2137,9 +2120,7 @@ private static void generateFieldMetaAttributeFunction( outermostStruct)); } - private static CharSequence generateEnumFieldNotPresentCondition( - final int sinceVersion, - final String enumName) + private static CharSequence generateEnumFieldNotPresentCondition(final int sinceVersion, final String enumName) { if (0 == sinceVersion) { diff --git a/sbe-tool/src/test/c/CComplianceTest.c b/sbe-tool/src/test/c/CComplianceTest.c index 671dac9fe4..5e7d93c89a 100644 --- a/sbe-tool/src/test/c/CComplianceTest.c +++ b/sbe-tool/src/test/c/CComplianceTest.c @@ -6,5 +6,6 @@ #include #include -int main() { +int main() +{ } diff --git a/sbe-tool/src/test/c/GroupWithDataTest.cpp b/sbe-tool/src/test/c/GroupWithDataTest.cpp index c6f59c13c6..318ecf6cb2 100644 --- a/sbe-tool/src/test/c/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/c/GroupWithDataTest.cpp @@ -296,7 +296,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage1Correctly) GWD(testMessage1) msg1Decoder; if (!GWD(testMessage1_reset)(&msg1Decoder, buffer, 0, sizeof(buffer), GWD(testMessage1_sbe_block_length)(), GWD(testMessage1_sbe_schema_version)())) { - throw std::runtime_error(sbe_strerror(errno)); + throw std::runtime_error(sbe_strerror(errno)); } EXPECT_EQ(GWD(testMessage1_tag1)(&msg1Decoder), TAG_1); From 73430af5e7edb5ecf298dc1784b1ef332e4e17ff Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 20 May 2019 12:32:03 +0100 Subject: [PATCH 0076/1594] [Java] Upgrade to javadoc-links 3.5.4. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d2ee90d498..6b9cadd247 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.3' - id "io.freefair.javadoc-links" version "3.3.1" apply false + id "io.freefair.javadoc-links" version "3.5.4" apply false id 'com.github.johnrengelman.shadow' version '5.0.0' apply false } From 48be9f9eeb128a02c918c3816de4934f21080d26 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Mon, 20 May 2019 18:30:42 +0100 Subject: [PATCH 0077/1594] [Java] Upgrade to javadoc-links 3.6.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6b9cadd247..a867175a3e 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.3' - id "io.freefair.javadoc-links" version "3.5.4" apply false + id "io.freefair.javadoc-links" version "3.6.1" apply false id 'com.github.johnrengelman.shadow' version '5.0.0' apply false } From 78a47e9920777fd5d5d4a19495a4a78c344efcb0 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 22 May 2019 17:14:40 +0100 Subject: [PATCH 0078/1594] [Java] Upgrade to javadoc-links 3.6.4. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a867175a3e..3d873079b7 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.3' - id "io.freefair.javadoc-links" version "3.6.1" apply false + id "io.freefair.javadoc-links" version "3.6.4" apply false id 'com.github.johnrengelman.shadow' version '5.0.0' apply false } From 6ee1fc603ef4a2a8e1b603a9353c61734dbc20f7 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sat, 25 May 2019 17:26:23 +0100 Subject: [PATCH 0079/1594] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9e1645e348..9c58eb2151 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.12.5 +    1.12.6 ``` @@ -65,7 +65,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.12.6-SNAPSHOT.jar my_sbe_input.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.12.7-SNAPSHOT.jar my_sbe_input.xml C++ Build using CMake From effe2be7a44b6baa1ddaf960d7ce17d07c681bb7 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 25 May 2019 10:02:46 -0700 Subject: [PATCH 0080/1594] 1.12.6 released. --- build.gradle | 2 +- version.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 3d873079b7..e1f7ad7cbf 100644 --- a/build.gradle +++ b/build.gradle @@ -137,7 +137,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.20' - compile 'org.agrona:agrona:1.0.0' + compile 'org.agrona:agrona:1.0.1' testCompile 'org.hamcrest:hamcrest:2.1' testCompile 'org.mockito:mockito-core:2.27.0' diff --git a/version.txt b/version.txt index 82c1e3710b..456e5c4ad8 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.12.6-SNAPSHOT +1.12.6 From 26dbebce5326e6adeab5dc2a952fed5dfa9a8207 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 25 May 2019 10:04:31 -0700 Subject: [PATCH 0081/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 456e5c4ad8..95278c42f7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.12.6 +1.12.7-SNAPSHOT From 93804afc7dbb73d81249baf08ab1c4261cdb8fd5 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 26 May 2019 10:22:56 +0100 Subject: [PATCH 0082/1594] [Java] Truncate IR file it it already exists when generating. Issue #682. --- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java index 1030027fc7..c421bea537 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java @@ -59,6 +59,7 @@ public IrEncoder(final String fileName, final Ir ir) try { channel = FileChannel.open(Paths.get(fileName), READ, WRITE, CREATE); + channel.truncate(0); resultBuffer = null; buffer = ByteBuffer.allocateDirect(CAPACITY); directBuffer = new UnsafeBuffer(buffer); From af07da6a2276fa599d7162cf332ab0d02e19cad0 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sun, 26 May 2019 18:16:36 +0100 Subject: [PATCH 0083/1594] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9c58eb2151..8558d6c2bd 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.12.6 +    1.12.7 ``` @@ -65,7 +65,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.12.7-SNAPSHOT.jar my_sbe_input.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.12.8-SNAPSHOT.jar my_sbe_input.xml C++ Build using CMake From 91196d7577f1a34c80d5e88e7488509e2b4a4558 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sun, 26 May 2019 10:27:56 -0700 Subject: [PATCH 0084/1594] 1.12.7 released --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 95278c42f7..41c8a73d48 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.12.7-SNAPSHOT +1.12.7 From cf0c2f305686d58bae6ca309c2382bf8cc7e8cb2 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sun, 26 May 2019 10:29:04 -0700 Subject: [PATCH 0085/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 41c8a73d48..029a7711b1 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.12.7 +1.12.9-SNAPSHOT From 54291b696b8eacf31d8b6c3c2dcecb4846fb6bf5 Mon Sep 17 00:00:00 2001 From: Egor Seredin Date: Sun, 19 May 2019 19:36:33 +0700 Subject: [PATCH 0086/1594] [C++] Generate message pretty printers --- .../src/main/cpp/GeneratedStubExample.cpp | 1 + .../sbe/generation/cpp/CppGenerator.java | 385 ++++++++++++++++++ 2 files changed, 386 insertions(+) diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index 33936efad2..17e7fb671d 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -309,6 +309,7 @@ int main(int argc, const char* argv[]) std::size_t encodeMsgLength = encodeCar(car, buffer, hdr.encodedLength(), sizeof(buffer)); cout << "Encoded Lengths are " << encodeHdrLength << " + " << encodeMsgLength << endl; + cout << "Encoded json: '" << car << "'" << endl; std::size_t decodeHdrLength = decodeHdr(hdr, buffer, 0, sizeof(buffer)); std::size_t decodeMsgLength = decodeCar(car, buffer, hdr.encodedLength(), hdr.blockLength(), hdr.version(), sizeof(buffer)); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 6e279dda26..897056b74f 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -136,6 +136,7 @@ public void generate() throws IOException generateGroups(sb, groups, BASE_INDENT); out.append(sb); out.append(generateVarData(className, varData, BASE_INDENT)); + out.append(generateDisplay(msgToken.name(), fields, groups, varData, BASE_INDENT + INDENT)); out.append("};\n"); out.append(CppUtil.closingBraces(ir.namespaces().length)).append("#endif\n"); } @@ -174,6 +175,8 @@ private void generateGroups(final StringBuilder sb, final List tokens, fi i = collectVarData(tokens, i, varData); sb.append(generateVarData(formatClassName(groupName), varData, indent + INDENT)); + sb.append(generateGroupDisplay(groupName, fields, groups, varData, indent + INDENT + INDENT)); + sb.append(indent).append(" };\n"); sb.append(generateGroupProperty(groupName, groupToken, cppTypeForNumInGroup, indent)); } @@ -667,6 +670,7 @@ private void generateChoiceSet(final List tokens) throws IOException cppTypeName(tokens.get(0).encoding().primitiveType()))); out.append(generateChoices(bitSetName, tokens.subList(1, tokens.size() - 1))); + out.append(generateChoicesDisplay(bitSetName, tokens.subList(1, tokens.size() - 1))); out.append("};\n"); out.append(CppUtil.closingBraces(ir.namespaces().length)).append("#endif\n"); } @@ -686,6 +690,8 @@ private void generateEnum(final List tokens) throws IOException out.append(generateEnumLookupMethod(tokens.subList(1, tokens.size() - 1), enumToken)); + out.append(generateEnumDisplay(tokens.subList(1, tokens.size() - 1), enumToken)); + out.append("};\n\n"); out.append(CppUtil.closingBraces(ir.namespaces().length)).append("\n#endif\n"); } @@ -705,6 +711,11 @@ private void generateComposite(final List tokens) throws IOException out.append(generateCompositePropertyElements( compositeName, tokens.subList(1, tokens.size() - 1), BASE_INDENT)); + out.append(generateCompositeDisplay( + tokens.get(0).applicableTypeName(), + tokens.subList(1, tokens.size() - 1), + BASE_INDENT + INDENT)); + out.append("};\n\n"); out.append(CppUtil.closingBraces(ir.namespaces().length)).append("\n#endif\n"); } @@ -975,6 +986,7 @@ private static CharSequence generateFileHeader( "#include \n" + "#include \n" + "#include \n\n" + + "#include \n\n" + "#if defined(WIN32) || defined(_WIN32)\n" + "# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)\n" + @@ -2257,4 +2269,377 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu return literal; } + + private CharSequence generateDisplay( + final String name, + final List fields, + final List groups, + final List varData, + final String indent) + { + final StringBuilder sb = new StringBuilder(); + + sb.append(String.format("\n" + + indent + "template\n" + + indent + "friend std::basic_ostream& operator<<(\n" + + indent + " std::basic_ostream& builder, %1$s _writer)\n" + + indent + "{\n" + + indent + " %1$s writer(_writer.m_buffer, _writer.m_offset,\n" + + indent + " _writer.m_bufferLength, _writer.sbeBlockLength(), _writer.m_actingVersion);\n" + + indent + " builder << '{';\n" + + indent + " builder << \"\\\"Name\\\": \\\"%1$s\\\", \";\n" + + indent + " builder << \"\\\"sbeTemplateId\\\": \";\n" + + indent + " builder << writer.sbeTemplateId();\n" + + indent + " builder << \", \";\n\n" + + "%2$s" + + indent + " builder << '}';\n" + + indent + " return builder;\n" + + indent + "}\n", + formatClassName(name), + appendDisplay(fields, groups, varData, indent + INDENT))); + + return sb.toString(); + } + + private CharSequence generateGroupDisplay( + final String name, + final List fields, + final List groups, + final List varData, + final String indent) + { + final StringBuilder sb = new StringBuilder(); + sb.append(String.format("\n" + + indent + "template\n" + + indent + "friend std::basic_ostream& operator<<(\n" + + indent + " std::basic_ostream& builder, %1$s writer)\n" + + indent + "{\n" + + indent + " builder << '{';\n" + + "%2$s" + + indent + " builder << '}';\n" + + indent + " return builder;\n" + + indent + "}\n", + formatClassName(name), + appendDisplay(fields, groups, varData, indent + INDENT))); + + return sb.toString(); + } + + private CharSequence generateCompositeDisplay( + final String name, + final List tokens, + final String indent) + { + final StringBuilder sb = new StringBuilder(); + final boolean[] atLeastOne = {false}; + sb.append(String.format("\n" + + indent + "template\n" + + indent + "friend std::basic_ostream& operator<<(\n" + + indent + " std::basic_ostream& builder, %1$s writer)\n" + + indent + "{\n" + + indent + " builder << '{';\n" + + "%2$s" + + indent + " builder << '}';\n" + + indent + " return builder;\n" + + indent + "}\n\n", + formatClassName(name), + appendDisplay(tokens, new ArrayList<>(), new ArrayList<>(), indent + INDENT))); + + return sb.toString(); + } + + private CharSequence appendDisplay( + final List fields, + final List groups, + final List varData, + final String indent) + { + final StringBuilder sb = new StringBuilder(); + final boolean[] atLeastOne = {false}; + for (int i = 0, size = fields.size(); i < size;) + { + final Token fieldToken = fields.get(i); + + if (fieldToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = fields.get(i + 1); + + sb.append( + writeTokenDisplay(fieldToken.name(), encodingToken, atLeastOne, indent) + "\n"); + + i += fieldToken.componentTokenCount(); + } + else + { + final Token encodingToken = fields.get(i); + + sb.append( + writeTokenDisplay(fieldToken.name(), encodingToken, atLeastOne, indent) + "\n"); + + i += fieldToken.componentTokenCount(); + } + } + + for (int i = 0, size = groups.size(); i < size; i++) + { + final Token groupToken = groups.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + sb.append(indent + "//" + groupToken + "\n"); + + if (atLeastOne[0]) + { + sb.append( + indent + "builder << \", \";\n"); + } + atLeastOne[0] = true; + + sb.append(String.format( + indent + "{\n" + + indent + " bool atLeastOne = false;\n" + + indent + " builder << \"\\\"%3$s\\\": [\";\n" + + indent + " writer.%2$s().forEach([&](%1$s& %2$s)\n" + + indent + " {\n" + + indent + " if (atLeastOne)\n" + + indent + " builder << \", \";\n" + + indent + " atLeastOne = true;\n" + + indent + " builder << %2$s;\n" + + indent + " });\n" + + indent + " builder << ']';\n" + + indent + "}\n\n", + formatClassName(groupToken.name()), + formatPropertyName(groupToken.name()), + groupToken.name())); + + + i = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); + } + + for (int i = 0, size = varData.size(); i < size;) + { + final Token varDataToken = varData.get(i); + if (varDataToken.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); + } + + sb.append(indent + "//" + varDataToken + "\n"); + + if (atLeastOne[0]) + { + sb.append( + indent + "builder << \", \";\n"); + } + atLeastOne[0] = true; + + final String characterEncoding = varData.get(i + 3).encoding().characterEncoding(); + final String getAsStringFunction = "get" + toUpperFirstChar(varDataToken.name()) + "AsString().c_str()"; + sb.append(indent + "builder << \"\\\"" + varDataToken.name() + "\\\": \";\n"); + if (null == characterEncoding) + { + sb.append( + indent + "builder << '\"' <<\n" + + indent + INDENT + "writer." + getAsStringFunction + " << '\"';\n\n"); + /*sb.append(indent + "builder << " + varDataName + "Length() << \" bytes of raw data\";\n"); + append(sb, indent, + "parentMessage.limit(parentMessage.limit() + " + varDataName + "HeaderLength() + " + + varDataName + "Length());");*/ + } + else + { + sb.append( + indent + "builder << '\"' <<\n" + + indent + INDENT + "writer." + getAsStringFunction + " << '\"';\n\n"); + } + + i += varDataToken.componentTokenCount(); + } + return sb.toString(); + } + + private CharSequence writeTokenDisplay( + final String fieldTokenName, + final Token typeToken, + final boolean[] atLeastOne, + final String indent) + { + final StringBuilder sb = new StringBuilder(); + final String fieldName = "writer." + formatPropertyName(fieldTokenName); + + sb.append(indent + "//" + typeToken + "\n"); + + if (typeToken.encodedLength() <= 0 || typeToken.isConstantEncoding()) + { + return sb.toString(); + } + + if (atLeastOne[0]) + { + sb.append( + indent + "builder << \", \";\n"); + } + else + { + atLeastOne[0] = true; + } + + sb.append(indent + "builder << \"\\\"" + fieldTokenName + "\\\": \";\n"); + + switch (typeToken.signal()) + { + case ENCODING: + if (typeToken.arrayLength() > 1) + { + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + sb.append( + indent + "builder << '\"';\n" + + indent + "for (size_t i = 0;\n" + + indent + " i < " + fieldName + "Length() && " + fieldName + "(i) > 0;\n" + + indent + " i++)\n" + + indent + "{\n" + + indent + " builder << (char)" + fieldName + "(i);\n" + + indent + "}\n" + + indent + "builder << '\"';\n"); + } + else + { + sb.append( + indent + "builder << '[';\n" + + indent + "if (" + fieldName + "Length() > 0)\n" + + indent + "{\n" + + indent + " for (size_t i = 0; i < " + fieldName + "Length(); i++)\n" + + indent + " {\n" + + indent + " if (i)\n" + + indent + " builder << ',';\n" + + indent + " builder << +" + fieldName + "(i);\n" + + indent + " }\n" + + indent + "}\n" + + indent + "builder << ']';\n"); + } + } + else + { + // have to duplicate because of checkstyle :/ + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + sb.append(indent + "builder << '\"' << (char)" + fieldName + "() << '\"';\n"); + } + else + { + sb.append(indent + "builder << +" + fieldName + "();\n"); + } + } + break; + + case BEGIN_ENUM: + sb.append(indent + "builder << '\"' << " + fieldName + "() << '\"';\n"); + break; + case BEGIN_SET: + sb.append(indent + "builder << " + fieldName + "();\n"); + break; + case BEGIN_COMPOSITE: + sb.append(indent + "builder << " + fieldName + "();\n"); + break; + } + + return sb.toString(); + } + + private CharSequence generateChoicesDisplay(final String name, final List tokens) + { + final String indent = INDENT; + final StringBuilder sb = new StringBuilder(); + final List choiceTokens = new ArrayList<>(); + + collect(Signal.CHOICE, tokens, 0, choiceTokens); + + sb.append(String.format("\n" + + indent + "template\n" + + indent + "friend std::basic_ostream& operator<<(" + + indent + " std::basic_ostream& builder, %1$s writer)\n" + + indent + "{\n" + + indent + " builder << '[';\n", + name)); + + if (choiceTokens.size() > 1) + { + sb.append(indent + " bool atLeastOne = false;\n"); + } + + for (int i = 0, size = choiceTokens.size(); i < size; i++) + { + final Token token = choiceTokens.get(i); + sb.append(indent + " //" + token + "\n"); + final String choiceName = "writer." + formatPropertyName(token.name()); + sb.append( + indent + " if (" + choiceName + "())\n" + + indent + " {\n"); + if (i > 0) + { + sb.append( + indent + " if (atLeastOne)\n" + + indent + " {\n" + + indent + " builder << \",\";\n" + + indent + " }\n"); + } + sb.append( + indent + " builder << \"\\\"" + formatPropertyName(token.name()) + "\\\"\";\n"); + if (i < (size - 1)) + { + sb.append(indent + " atLeastOne = true;\n"); + } + sb.append( + indent + " }\n"); + } + + sb.append( + indent + " builder << ']';\n" + + indent + " return builder;\n" + + indent + "}\n"); + + return sb.toString(); + } + + private CharSequence generateEnumDisplay(final List tokens, final Token encodingToken) + { + final String enumName = formatClassName(encodingToken.applicableTypeName()); + final StringBuilder sb = new StringBuilder(); + + sb.append(String.format("\n" + + " static const char* c_str(const %1$s::Value value)\n" + + " {\n" + + " switch (value)\n" + + " {\n", + enumName + )); + + for (final Token token : tokens) + { + sb.append(String.format( + " case %1$s: return \"%1$s\";\n", + token.name()) + ); + } + + sb.append(String.format( + " case NULL_VALUE: return \"NULL_VALUE\";\n" + + " }\n\n" + + " throw std::runtime_error(\"unknown value for enum %1$s [E103]:\");\n" + + " }\n\n" + + + " template\n" + + " friend std::basic_ostream& operator<<(\n" + + " std::basic_ostream& os, %1$s::Value m)\n" + + " {\n" + + " return os << %1$s::c_str(m);\n" + + " }\n", + enumName + )); + + return sb; + } } From 6e576695eba9ee14d195ffd9c68ab371f6940527 Mon Sep 17 00:00:00 2001 From: "Ian P. Cooke" Date: Fri, 31 May 2019 03:06:43 -0500 Subject: [PATCH 0087/1594] change 'event' to something valid for C# --- sbe-tool/src/test/resources/message-block-length-test.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/test/resources/message-block-length-test.xml b/sbe-tool/src/test/resources/message-block-length-test.xml index 2a82684c91..ea789940fe 100644 --- a/sbe-tool/src/test/resources/message-block-length-test.xml +++ b/sbe-tool/src/test/resources/message-block-length-test.xml @@ -15,7 +15,7 @@ - + 0 1 2 @@ -28,7 +28,7 @@ - + From b679485617ce797e8d2a4198f2af5c018ddad0b4 Mon Sep 17 00:00:00 2001 From: "Ian P. Cooke" Date: Fri, 31 May 2019 03:11:50 -0500 Subject: [PATCH 0088/1594] add generateMessageHeaderDecoder to Rust generator. this can be used to decode a header and then match on template_id to call the correct FieldDecoder's wrap method. --- .gitignore | 3 +- build.gradle | 3 +- .../sbe/generation/rust/RustCodecType.java | 2 +- .../sbe/generation/rust/RustGenerator.java | 49 ++++++++++++++++--- .../generation/rust/RustGeneratorTest.java | 2 +- 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 24701042d3..4912d28ade 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,7 @@ # Build tools build-local.properties deps -/bin +*/bin build .gradle target @@ -23,6 +23,7 @@ GPATH prop out .vs/ +.vscode # cmake diff --git a/build.gradle b/build.gradle index e1f7ad7cbf..229ccf9512 100644 --- a/build.gradle +++ b/build.gradle @@ -569,7 +569,8 @@ def cargo_exists() { try { def result = project.exec { executable = 'cargo' - args = '-v' + args = [ '-V' ] + standardOutput = new ByteArrayOutputStream() } return result.exitValue == 0 } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java index 55f71d5bc4..456f4f765e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java @@ -173,7 +173,7 @@ void appendWrapMethod(final Appendable appendable, final String structName) throws IOException { appendable.append("\n").append(INDENT).append(String.format( - "fn wrap(%s: %s) -> %s {%n", scratchProperty(), RustGenerator.withLifetime(scratchType()), + "pub fn wrap(%s: %s) -> %s {%n", scratchProperty(), RustGenerator.withLifetime(scratchType()), RustGenerator.withLifetime(structName))); indent(appendable, 2, "%s { %s: %s }\n", structName, scratchProperty(), scratchProperty()); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 22a491be6c..802bca0c87 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -53,6 +53,8 @@ public RustGenerator(final Ir ir, final OutputManager outputManager) public void generate() throws IOException { + final int headerSize = totalByteSize(ir.headerStructure()); + generateSharedImports(outputManager); generateResultEnums(outputManager); generateDecoderScratchStruct(outputManager); @@ -61,7 +63,7 @@ public void generate() throws IOException generateEnums(ir, outputManager); generateComposites(ir, outputManager); generateBitSets(ir, outputManager); - final int headerSize = totalByteSize(ir.headerStructure()); + generateMessageHeaderDecoder(outputManager, headerSize); for (final List tokens : ir.messages()) { @@ -285,6 +287,27 @@ private static void generateEntryPoint( } } + static void generateMessageHeaderDecoder( + final OutputManager outputManager, + final int headerSize) throws IOException + { + String messageTypeName = "MessageHeader"; + RustCodecType codecType = RustCodecType.Decoder; + try (Writer writer = outputManager.createOutput(messageTypeName + format(" %s entry point", codecType.name()))) + { + final String gerund = codecType.gerund(); + writer.append(format("pub fn start_%s_%s<%s>(data: &%s%s [u8]) -> CodecResult<(&%s %s, %s)> {\n", gerund, + formatMethodName(messageTypeName), DATA_LIFETIME, DATA_LIFETIME, + codecType == RustCodecType.Encoder ? " mut" : "", + DATA_LIFETIME, messageTypeName, + withLifetime(codecType.scratchType()))); + indent(writer, 1, format("let mut scratch = %s { data: data, pos: 0 };\n", codecType.scratchType())); + indent(writer, 1, format("let v = scratch.read_type::<%s>(%s)?;\n", messageTypeName, headerSize)); + indent(writer, 1, "Ok((v, scratch))\n"); + writer.append("}\n"); + } + } + static String withLifetime(final String typeName) { return format("%s<%s>", typeName, DATA_LIFETIME); @@ -1163,7 +1186,7 @@ static void generateEncoderScratchStruct(final OutputManager outputManager) thro try (Writer writer = outputManager.createOutput("Scratch Encoder Data Wrapper - codec internal use only")) { writer.append("#[derive(Debug)]\n"); - writer.append(format("struct %s<%s> {\n", SCRATCH_ENCODER_TYPE, DATA_LIFETIME)); + writer.append(format("pub struct %s<%s> {\n", SCRATCH_ENCODER_TYPE, DATA_LIFETIME)); indent(writer, 1, "data: &%s mut [u8],\n", DATA_LIFETIME); indent(writer).append("pos: usize,\n"); writer.append("}\n"); @@ -1291,7 +1314,7 @@ private static void generateDecoderScratchStruct(final OutputManager outputManag try (Writer writer = outputManager.createOutput("Scratch Decoder Data Wrapper - codec internal use only")) { writer.append("#[derive(Debug)]\n"); - writer.append(format("struct %s<%s> {\n", SCRATCH_DECODER_TYPE, DATA_LIFETIME)); + writer.append(format("pub struct %s<%s> {\n", SCRATCH_DECODER_TYPE, DATA_LIFETIME)); indent(writer, 1, "data: &%s [u8],\n", DATA_LIFETIME); indent(writer).append("pos: usize,\n"); writer.append("}\n"); @@ -1798,6 +1821,18 @@ private void generateMessageHeaderDefault( indent(writer, 1, "pub message_header: MessageHeader\n"); writer.append("}\n"); + final String blockLength = Integer.toString(messageToken.encodedLength()); + final String templateId = Integer.toString(messageToken.id()); + final String schemaId = Integer.toString(ir.id()); + final String version = Integer.toString(ir.version()); + + indent(writer, 0, "impl %s {\n", wrapperName); + indent(writer, 1, "pub const BLOCK_LENGTH : u16 = " + blockLength + ";\n"); + indent(writer, 1, "pub const TEMPLATE_ID : u16 = " + templateId + ";\n"); + indent(writer, 1, "pub const SCHEMA_ID : u16 = " + schemaId + ";\n"); + indent(writer, 1, "pub const VERSION : u16 = " + version + ";\n"); + indent(writer, 0, "}\n"); + indent(writer, 0, "impl Default for %s {\n", wrapperName); indent(writer, 1, "fn default() -> %s {\n", wrapperName); indent(writer, 2, "%s {\n", wrapperName); @@ -1807,10 +1842,10 @@ private void generateMessageHeaderDefault( new HashMap() { { - put("block_length", Integer.toString(messageToken.encodedLength())); - put("template_id", Integer.toString(messageToken.id())); - put("schema_id", Integer.toString(ir.id())); - put("version", Integer.toString(ir.version())); + put("block_length", blockLength); + put("template_id", templateId); + put("schema_id", schemaId); + put("version", version); } }); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java index 8c95ec1ace..420d2868e9 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java @@ -237,7 +237,7 @@ private static boolean cargoExists() { try { - final ProcessBuilder builder = new ProcessBuilder("cargo", "-v"); + final ProcessBuilder builder = new ProcessBuilder("cargo", "-V"); final Process process = builder.start(); process.waitFor(5, TimeUnit.SECONDS); return process.exitValue() == 0; From b1f55fdff08d8df41dd3e069410f57ef44671275 Mon Sep 17 00:00:00 2001 From: "Ian P. Cooke" Date: Fri, 31 May 2019 03:57:13 -0500 Subject: [PATCH 0089/1594] cleanup style errors --- .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 802bca0c87..69b54fd88b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -291,8 +291,8 @@ static void generateMessageHeaderDecoder( final OutputManager outputManager, final int headerSize) throws IOException { - String messageTypeName = "MessageHeader"; - RustCodecType codecType = RustCodecType.Decoder; + final String messageTypeName = "MessageHeader"; + final RustCodecType codecType = RustCodecType.Decoder; try (Writer writer = outputManager.createOutput(messageTypeName + format(" %s entry point", codecType.name()))) { final String gerund = codecType.gerund(); @@ -1821,7 +1821,7 @@ private void generateMessageHeaderDefault( indent(writer, 1, "pub message_header: MessageHeader\n"); writer.append("}\n"); - final String blockLength = Integer.toString(messageToken.encodedLength()); + final String blockLength = Integer.toString(messageToken.encodedLength()); final String templateId = Integer.toString(messageToken.id()); final String schemaId = Integer.toString(ir.id()); final String version = Integer.toString(ir.version()); From 048fb058f1fd2dcd9fa9f2d9fbe6927bdcd9c49f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 1 Jun 2019 11:41:46 +0100 Subject: [PATCH 0090/1594] [Java] Upgrade to Checkstyle 8.21 and Mockito 2.28.2. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index e1f7ad7cbf..6a16d0e93a 100644 --- a/build.gradle +++ b/build.gradle @@ -135,12 +135,12 @@ subprojects { jar.enabled = true dependencies { - checkstyle 'com.puppycrawl.tools:checkstyle:8.20' + checkstyle 'com.puppycrawl.tools:checkstyle:8.21' compile 'org.agrona:agrona:1.0.1' testCompile 'org.hamcrest:hamcrest:2.1' - testCompile 'org.mockito:mockito-core:2.27.0' + testCompile 'org.mockito:mockito-core:2.28.2' testCompile 'junit:junit:4.12' } From 1588387980c05c2de9e3794cd1479ba7b3402453 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 1 Jun 2019 11:43:27 +0100 Subject: [PATCH 0091/1594] [Java] Upgrade to Checkstyle 8.21 and Mockito 2.28.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6a16d0e93a..e48f10dd86 100644 --- a/build.gradle +++ b/build.gradle @@ -145,7 +145,7 @@ subprojects { } checkstyle { - toolVersion = '8.20' + toolVersion = '8.21' } compileJava { From a6ef907be4f753abb20b92db2c7edbf9eeaf5288 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sun, 2 Jun 2019 12:09:46 +0100 Subject: [PATCH 0092/1594] [Java] Change enum type name in test to avoid warning. --- sbe-tool/src/test/resources/message-block-length-test.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/test/resources/message-block-length-test.xml b/sbe-tool/src/test/resources/message-block-length-test.xml index 2a82684c91..c31f00899d 100644 --- a/sbe-tool/src/test/resources/message-block-length-test.xml +++ b/sbe-tool/src/test/resources/message-block-length-test.xml @@ -15,7 +15,7 @@ - + 0 1 2 @@ -28,7 +28,7 @@ - + From 471c7a81014e3fccf1e673444754bc0661274bf6 Mon Sep 17 00:00:00 2001 From: "Ian P. Cooke" Date: Sun, 2 Jun 2019 11:44:26 -0500 Subject: [PATCH 0093/1594] Revert "change 'event' to something valid for C#" This reverts commit 6e576695eba9ee14d195ffd9c68ab371f6940527. --- sbe-tool/src/test/resources/message-block-length-test.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/test/resources/message-block-length-test.xml b/sbe-tool/src/test/resources/message-block-length-test.xml index ea789940fe..2a82684c91 100644 --- a/sbe-tool/src/test/resources/message-block-length-test.xml +++ b/sbe-tool/src/test/resources/message-block-length-test.xml @@ -15,7 +15,7 @@ - + 0 1 2 @@ -28,7 +28,7 @@ - + From 9cbfc69358f235787d7a3a74d8946ede74add939 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Mon, 3 Jun 2019 18:11:13 +0900 Subject: [PATCH 0094/1594] [C++] Use raw string literals. --- .../real_logic/sbe/generation/cpp/CppGenerator.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 897056b74f..6fbf1d3c8d 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2287,8 +2287,8 @@ private CharSequence generateDisplay( indent + " %1$s writer(_writer.m_buffer, _writer.m_offset,\n" + indent + " _writer.m_bufferLength, _writer.sbeBlockLength(), _writer.m_actingVersion);\n" + indent + " builder << '{';\n" + - indent + " builder << \"\\\"Name\\\": \\\"%1$s\\\", \";\n" + - indent + " builder << \"\\\"sbeTemplateId\\\": \";\n" + + indent + " builder << R\"(\"Name\": \"%1$s\", )\";\n" + + indent + " builder << R\"(\"sbeTemplateId\": )\";\n" + indent + " builder << writer.sbeTemplateId();\n" + indent + " builder << \", \";\n\n" + "%2$s" + @@ -2400,7 +2400,7 @@ private CharSequence appendDisplay( sb.append(String.format( indent + "{\n" + indent + " bool atLeastOne = false;\n" + - indent + " builder << \"\\\"%3$s\\\": [\";\n" + + indent + " builder << R\"(\"%3$s\": [)\";\n" + indent + " writer.%2$s().forEach([&](%1$s& %2$s)\n" + indent + " {\n" + indent + " if (atLeastOne)\n" + @@ -2437,7 +2437,7 @@ private CharSequence appendDisplay( final String characterEncoding = varData.get(i + 3).encoding().characterEncoding(); final String getAsStringFunction = "get" + toUpperFirstChar(varDataToken.name()) + "AsString().c_str()"; - sb.append(indent + "builder << \"\\\"" + varDataToken.name() + "\\\": \";\n"); + sb.append(indent + "builder << R\"(\"" + varDataToken.name() + "\": )\";\n"); if (null == characterEncoding) { sb.append( @@ -2486,7 +2486,7 @@ private CharSequence writeTokenDisplay( atLeastOne[0] = true; } - sb.append(indent + "builder << \"\\\"" + fieldTokenName + "\\\": \";\n"); + sb.append(indent + "builder << R\"(\"" + fieldTokenName + "\": )\";\n"); switch (typeToken.signal()) { @@ -2587,7 +2587,7 @@ private CharSequence generateChoicesDisplay(final String name, final List indent + " }\n"); } sb.append( - indent + " builder << \"\\\"" + formatPropertyName(token.name()) + "\\\"\";\n"); + indent + " builder << R\"(\"" + formatPropertyName(token.name()) + "\")\";\n"); if (i < (size - 1)) { sb.append(indent + " atLeastOne = true;\n"); From 644ccde92aef3a4db1cd7242ca335920955f56fe Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sat, 8 Jun 2019 09:23:10 +0100 Subject: [PATCH 0095/1594] [Java] Upgrade to javadoc-links 3.6.6. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 11339b8f58..9cd92c1d2b 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.3' - id "io.freefair.javadoc-links" version "3.6.4" apply false + id "io.freefair.javadoc-links" version "3.6.6" apply false id 'com.github.johnrengelman.shadow' version '5.0.0' apply false } From 81327b9443ecbc89eb2aae1ba8bad69fa81599ba Mon Sep 17 00:00:00 2001 From: Erik Rigtorp Date: Sun, 9 Jun 2019 23:20:37 -0500 Subject: [PATCH 0096/1594] Move linux distro selection to global scope --- .travis.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index ad74089fdf..37c8d11547 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ +dist: xenial + sudo: false matrix: @@ -7,21 +9,18 @@ matrix: language: java jdk: openjdk8 os: linux - dist: xenial script: ./gradlew --scan - name: "OpenJDK 11" language: java jdk: openjdk11 os: linux - dist: xenial script: ./gradlew --scan - env: COMPILER=g++-6 language: cpp compiler: gcc os: linux - dist: xenial addons: apt: packages: @@ -35,7 +34,6 @@ matrix: language: cpp compiler: gcc os: linux - dist: xenial addons: apt: packages: @@ -49,7 +47,6 @@ matrix: language: cpp compiler: gcc os: linux - dist: xenial addons: apt: packages: @@ -63,7 +60,6 @@ matrix: language: cpp compiler: clang os: linux - dist: xenial addons: apt: packages: @@ -79,7 +75,6 @@ matrix: language: cpp compiler: clang os: linux - dist: xenial addons: apt: packages: @@ -95,7 +90,6 @@ matrix: language: cpp compiler: clang os: linux - dist: xenial addons: apt: packages: From a730646490f53540054ae2111d2e78677716e855 Mon Sep 17 00:00:00 2001 From: Erik Rigtorp Date: Sun, 9 Jun 2019 23:24:06 -0500 Subject: [PATCH 0097/1594] Add more C++ compilers to build matrix --- .travis.yml | 58 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 37c8d11547..1d367428fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,19 @@ matrix: os: linux script: ./gradlew --scan + - env: COMPILER=g++-5 + language: cpp + compiler: gcc + os: linux + addons: + apt: + packages: + - g++-5 + - libsparsehash-dev + sources: + - ubuntu-toolchain-r-test + script: ./cppbuild/cppbuild + - env: COMPILER=g++-6 language: cpp compiler: gcc @@ -56,6 +69,32 @@ matrix: - ubuntu-toolchain-r-test script: ./cppbuild/cppbuild + - env: COMPILER=g++-9 + language: cpp + compiler: gcc + os: linux + addons: + apt: + packages: + - g++-9 + - libsparsehash-dev + sources: + - ubuntu-toolchain-r-test + script: ./cppbuild/cppbuild + + - env: COMPILER=clang++-4.0 + language: cpp + compiler: clang + os: linux + addons: + apt: + packages: + - clang-4.0 + - libsparsehash-dev + sources: + - llvm-toolchain-xenial-4.0 + script: ./cppbuild/cppbuild + - env: COMPILER=clang++-5.0 language: cpp compiler: clang @@ -64,10 +103,8 @@ matrix: apt: packages: - clang-5.0 - - libstdc++-7-dev - libsparsehash-dev sources: - - ubuntu-toolchain-r-test - llvm-toolchain-xenial-5.0 script: ./cppbuild/cppbuild @@ -79,10 +116,8 @@ matrix: apt: packages: - clang-6.0 - - libstdc++-7-dev - libsparsehash-dev sources: - - ubuntu-toolchain-r-test - llvm-toolchain-xenial-6.0 script: ./cppbuild/cppbuild @@ -94,13 +129,24 @@ matrix: apt: packages: - clang-7 - - libstdc++-7-dev - libsparsehash-dev sources: - - ubuntu-toolchain-r-test - llvm-toolchain-xenial-7 script: ./cppbuild/cppbuild + - env: COMPILER=clang++-8 + language: cpp + compiler: clang + os: linux + addons: + apt: + packages: + - clang-8 + - libsparsehash-dev + sources: + - llvm-toolchain-xenial-8 + script: ./cppbuild/cppbuild + - env: COMPILER=clang++ language: c++ compiler: clang From 092fa342b3cc547f6efe03197cffa52d7ea10ee8 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 12 Jun 2019 20:00:33 +0100 Subject: [PATCH 0098/1594] [Java] Upgrade to Agrona 1.0.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9cd92c1d2b..8510332ff1 100644 --- a/build.gradle +++ b/build.gradle @@ -137,7 +137,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.21' - compile 'org.agrona:agrona:1.0.1' + compile 'org.agrona:agrona:1.0.2' testCompile 'org.hamcrest:hamcrest:2.1' testCompile 'org.mockito:mockito-core:2.28.2' From 1bbfd31bf379257d5e074782e4e1fb062aaa14cc Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 13 Jun 2019 12:43:30 +0100 Subject: [PATCH 0099/1594] [Java] Use Agrona DirectBuffer.getStringWithoutLengthAscii to Appendable for more efficient reading of var data and return length copied. --- .../src/main/resources/common-types.xml | 4 ++ .../resources/example-extension-schema.xml | 2 +- .../src/main/resources/example-schema.xml | 2 +- .../sbe/generation/java/JavaGenerator.java | 51 ++++++++----------- 4 files changed, 28 insertions(+), 31 deletions(-) diff --git a/sbe-samples/src/main/resources/common-types.xml b/sbe-samples/src/main/resources/common-types.xml index 0f21ce29a6..11fc391880 100644 --- a/sbe-samples/src/main/resources/common-types.xml +++ b/sbe-samples/src/main/resources/common-types.xml @@ -14,6 +14,10 @@ + + + + diff --git a/sbe-samples/src/main/resources/example-extension-schema.xml b/sbe-samples/src/main/resources/example-extension-schema.xml index a55e464cbb..f3c95b7b65 100644 --- a/sbe-samples/src/main/resources/example-extension-schema.xml +++ b/sbe-samples/src/main/resources/example-extension-schema.xml @@ -76,6 +76,6 @@ - + diff --git a/sbe-samples/src/main/resources/example-schema.xml b/sbe-samples/src/main/resources/example-schema.xml index 7894e903a3..820f51bdfe 100644 --- a/sbe-samples/src/main/resources/example-schema.xml +++ b/sbe-samples/src/main/resources/example-schema.xml @@ -72,6 +72,6 @@ - + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index c202264119..2754a1e05c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -36,6 +36,7 @@ import static uk.co.real_logic.sbe.generation.java.JavaUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.*; +@SuppressWarnings("MethodLength") public class JavaGenerator implements CodeGenerator { enum CodecType @@ -910,26 +911,16 @@ private void generateDataDecodeMethods( if (characterEncoding.contains("ASCII")) { sb.append(String.format("\n" + - indent + " public void get%1$s(final Appendable value)\n" + + indent + " public int get%1$s(final Appendable appendable)\n" + indent + " {\n" + "%2$s" + indent + " final int headerLength = %3$d;\n" + indent + " final int limit = parentMessage.limit();\n" + indent + " final int dataLength = (int)%4$s;\n" + - indent + " final int dataOffset = limit + headerLength;\n" + + indent + " final int dataOffset = limit + headerLength;\n\n" + indent + " parentMessage.limit(dataOffset + dataLength);\n" + - indent + " for (int i = 0; i < dataLength; ++i)\n" + - indent + " {\n" + - indent + " try\n" + - indent + " {\n" + - indent + " final int c = buffer.getByte(dataOffset + i) & 0xFF;\n" + - indent + " value.append(c > 127 ? '?' : (char)c);\n" + - indent + " }\n" + - indent + " catch (final java.io.IOException e)\n" + - indent + " {\n" + - indent + " throw new java.io.UncheckedIOException(e);\n" + - indent + " }\n" + - indent + " }\n" + + indent + " buffer.getStringWithoutLengthAscii(dataOffset, dataLength, appendable);\n\n" + + indent + " return dataLength;\n" + indent + " }\n", Generators.toUpperFirstChar(propertyName), generateStringNotPresentConditionForAppendable(token.version(), indent), @@ -1898,7 +1889,7 @@ private static CharSequence generateStringNotPresentConditionForAppendable( return String.format( indent + " if (parentMessage.actingVersion < %d)\n" + indent + " {\n" + - indent + " return;\n" + + indent + " return 0;\n" + indent + " }\n\n", sinceVersion); } @@ -2010,36 +2001,40 @@ private CharSequence generatePrimitiveArrayPropertyDecode( indent + " }\n\n", propertyName, generateStringNotPresentCondition(propertyToken.version(), indent), - fieldLength, offset, - fieldLength, fieldLength, + fieldLength, + offset, + fieldLength, + fieldLength, charset(encoding.characterEncoding()))); if (encoding.characterEncoding().contains("ASCII")) { sb.append(String.format("\n" + - indent + " public void get%s(final Appendable value)\n" + + indent + " public int get%1$s(final Appendable value)\n" + indent + " {\n" + - "%s" + - indent + " for (int i = 0; i < %d ; ++i)\n" + + "%2$s" + + indent + " for (int i = 0; i < %3$d; ++i)\n" + indent + " {\n" + - indent + " final int c = buffer.getByte(this.offset + %d + i) & 0xFF;\n" + + indent + " final int c = buffer.getByte(this.offset + %4$d + i) & 0xFF;\n" + indent + " if (c == 0)\n" + indent + " {\n" + - indent + " break;\n" + - indent + " }\n" + + indent + " return i;\n" + + indent + " }\n\n" + indent + " try\n" + indent + " {\n" + indent + " value.append(c > 127 ? '?' : (char)c);\n" + indent + " }\n" + - indent + " catch (final java.io.IOException e)\n" + + indent + " catch (final java.io.IOException ex)\n" + indent + " {\n" + - indent + " throw new java.io.UncheckedIOException(e);\n" + + indent + " throw new java.io.UncheckedIOException(ex);\n" + indent + " }\n" + - indent + " }\n" + + indent + " }\n\n" + + indent + " return %3$d;\n" + indent + " }\n\n", Generators.toUpperFirstChar(propertyName), generateStringNotPresentConditionForAppendable(propertyToken.version(), indent), - fieldLength, offset)); + fieldLength, + offset)); } } @@ -2409,8 +2404,6 @@ private CharSequence generateFixedFlyweightCode( generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), schemaIdAccessorType, schemaVersionAccessorType); - - } private CharSequence generateDecoderFlyweightCode(final String className, final Token token) From 968e479716004a51b0e155fc84dbba9c71dcb8da Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Mon, 24 Jun 2019 07:44:02 +0100 Subject: [PATCH 0100/1594] [Java] Upgrade to javadoc-links 3.7.5. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8510332ff1..99c434999e 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.3' - id "io.freefair.javadoc-links" version "3.6.6" apply false + id "io.freefair.javadoc-links" version "3.7.5" apply false id 'com.github.johnrengelman.shadow' version '5.0.0' apply false } From e664ebc2173acc29cb304096a94c056754fcd7de Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Mon, 24 Jun 2019 14:08:18 +0100 Subject: [PATCH 0101/1594] [Java] Add Javadoc for IR. --- .../co/real_logic/sbe/ir/HeaderStructure.java | 82 +++++++++++++------ .../uk/co/real_logic/sbe/ir/IrDecoder.java | 21 +++++ .../uk/co/real_logic/sbe/ir/IrEncoder.java | 23 ++++++ .../java/uk/co/real_logic/sbe/ir/IrUtil.java | 3 + .../real_logic/sbe/ir/MessageComponents.java | 3 + .../sbe/ir/generated/ByteOrderCodec.java | 3 + .../sbe/ir/generated/PresenceCodec.java | 3 + .../sbe/ir/generated/PrimitiveTypeCodec.java | 3 + .../sbe/ir/generated/SignalCodec.java | 3 + .../sbe/ir/generated/TokenCodecDecoder.java | 8 +- .../ir/generated/VarDataEncodingDecoder.java | 3 + .../ir/generated/VarDataEncodingEncoder.java | 3 + sbe-tool/src/main/resources/sbe-ir.xml | 12 +-- 13 files changed, 134 insertions(+), 36 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java index fe08134aee..87aa9bc4f9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java @@ -21,7 +21,8 @@ import java.util.List; /** - * Metadata description for a message headerStructure + * Metadata description for a message header structure expected before messages to understand the type requiring + * decoding. */ public class HeaderStructure { @@ -36,6 +37,10 @@ public class HeaderStructure private PrimitiveType schemaIdType; private PrimitiveType schemaVersionType; + /** + * Construct the header structure from a list of tokens containing the minimum expected set of fields. + * @param tokens for the header structure. + */ public HeaderStructure(final List tokens) { Verify.notNull(tokens, "tokens"); @@ -49,53 +54,78 @@ public HeaderStructure(final List tokens) Verify.notNull(schemaVersionType, "schemaVersionType"); } - private void captureEncodings(final List tokens) - { - for (final Token token : tokens) - { - switch (token.name()) - { - case BLOCK_LENGTH: - blockLengthType = token.encoding().primitiveType(); - break; - - case TEMPLATE_ID: - templateIdType = token.encoding().primitiveType(); - break; - - case SCHEMA_ID: - schemaIdType = token.encoding().primitiveType(); - break; - - case SCHEMA_VERSION: - schemaVersionType = token.encoding().primitiveType(); - break; - } - } - } - + /** + * The IR tokens for the header. + * + * @return the IR tokens for the header. + */ public List tokens() { return tokens; } + /** + * The declared data type for the block length field. + * + * @return the declared data type for the block length field. + */ public PrimitiveType blockLengthType() { return blockLengthType; } + /** + * The declared data type for the template id field. + * + * @return the declared data type for the template id field. + */ public PrimitiveType templateIdType() { return templateIdType; } + /** + * The declared data type for the SBE schema id field. + * + * @return the declared data type for the SBE schema id field. + */ public PrimitiveType schemaIdType() { return schemaIdType; } + /** + * The declared data type for the SBE schema version field. + * + * @return the declared data type for the SBE schema version field. + */ public PrimitiveType schemaVersionType() { return schemaVersionType; } + + private void captureEncodings(final List tokens) + { + for (final Token token : tokens) + { + switch (token.name()) + { + case BLOCK_LENGTH: + blockLengthType = token.encoding().primitiveType(); + break; + + case TEMPLATE_ID: + templateIdType = token.encoding().primitiveType(); + break; + + case SCHEMA_ID: + schemaIdType = token.encoding().primitiveType(); + break; + + case SCHEMA_VERSION: + schemaVersionType = token.encoding().primitiveType(); + break; + } + } + } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index 1700127239..9d466e4519 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -34,6 +34,9 @@ import static java.nio.file.StandardOpenOption.READ; import static uk.co.real_logic.sbe.ir.IrUtil.*; +/** + * Decoder for encoded {@link Ir} representing an SBE schema which can be read from a buffer or file. + */ public class IrDecoder implements AutoCloseable { private static final int CAPACITY = 4096; @@ -53,6 +56,11 @@ public class IrDecoder implements AutoCloseable private final byte[] valArray = new byte[CAPACITY]; private final MutableDirectBuffer valBuffer = new UnsafeBuffer(valArray); + /** + * Construct a {@link Ir} decoder by opening a file for a given name. + * + * @param fileName containing the encoded {@link Ir}. + */ public IrDecoder(final String fileName) { try @@ -70,6 +78,11 @@ public IrDecoder(final String fileName) } } + /** + * Construct a {@link Ir} decoder for data encoded in a {@link ByteBuffer}. + * + * @param buffer containing the serialised {@link Ir}. + */ public IrDecoder(final ByteBuffer buffer) { channel = null; @@ -78,11 +91,19 @@ public IrDecoder(final ByteBuffer buffer) offset = 0; } + /** + * {@inheritDoc} + */ public void close() { CloseHelper.quietClose(channel); } + /** + * Decode the serialised {@link Ir} and return the decoded instance. + * + * @return the decoded serialised {@link Ir} instance. + */ public Ir decode() { decodeFrame(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java index c421bea537..78cbd6db6a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java @@ -39,6 +39,9 @@ import static uk.co.real_logic.sbe.ir.generated.FrameCodecEncoder.semanticVersionCharacterEncoding; import static uk.co.real_logic.sbe.ir.generated.TokenCodecEncoder.*; +/** + * Encoder for {@link Ir} representing an SBE schema which can be written to a buffer or file. + */ public class IrEncoder implements AutoCloseable { private static final int CAPACITY = 4096; @@ -54,6 +57,12 @@ public class IrEncoder implements AutoCloseable private final UnsafeBuffer valBuffer = new UnsafeBuffer(valArray); private int totalLength = 0; + /** + * Construct an encoder for {@link Ir} to a file. An existing file will be overwritten. + * + * @param fileName into which the {@link Ir} will be encoded. + * @param ir to be encoded into the file. + */ public IrEncoder(final String fileName, final Ir ir) { try @@ -71,6 +80,12 @@ public IrEncoder(final String fileName, final Ir ir) } } + /** + * Construct an encoder for {@link Ir} to a {@link ByteBuffer}. + * + * @param buffer into which the {@link Ir} will be encoded. + * @param ir to be encoded into the buffer. + */ public IrEncoder(final ByteBuffer buffer, final Ir ir) { channel = null; @@ -80,11 +95,19 @@ public IrEncoder(final ByteBuffer buffer, final Ir ir) this.ir = ir; } + /** + * {@inheritDoc} + */ public void close() { CloseHelper.quietClose(channel); } + /** + * Encode the provided {@link Ir} and return the length in bytes encoded. + * + * @return encode the provided {@link Ir} and return the length in bytes encoded. + */ public int encode() { Verify.notNull(ir, "ir"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java index dbdfd828f7..4dad83419b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java @@ -27,6 +27,9 @@ import java.io.UnsupportedEncodingException; import java.nio.ByteOrder; +/** + * Utility functions for working with {@link Ir}. + */ public class IrUtil { public static final byte[] EMPTY_BUFFER = new byte[0]; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java index 22a8a20ca3..83e75a774f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java @@ -19,6 +19,9 @@ import java.util.Collections; import java.util.List; +/** + * Collect the message components (fields, groups, data) to help with generating codecs. + */ public class MessageComponents { public final Token messageToken; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java index e65a040d90..15b85e6551 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java @@ -1,6 +1,9 @@ /* Generated SBE (Simple Binary Encoding) message codec */ package uk.co.real_logic.sbe.ir.generated; +/** + * Number encoding byte order + */ public enum ByteOrderCodec { SBE_LITTLE_ENDIAN((short)0), diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java index 24d83fd0b5..66d8f68a13 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java @@ -1,6 +1,9 @@ /* Generated SBE (Simple Binary Encoding) message codec */ package uk.co.real_logic.sbe.ir.generated; +/** + * Field presence declaration + */ public enum PresenceCodec { SBE_REQUIRED((short)0), diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java index a90a650da6..04f4affb2e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java @@ -1,6 +1,9 @@ /* Generated SBE (Simple Binary Encoding) message codec */ package uk.co.real_logic.sbe.ir.generated; +/** + * Primitive types in type system + */ public enum PrimitiveTypeCodec { NONE((short)0), diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java index d909551355..62ecbafd3c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java @@ -1,6 +1,9 @@ /* Generated SBE (Simple Binary Encoding) message codec */ package uk.co.real_logic.sbe.ir.generated; +/** + * Token signal type in IR + */ public enum SignalCodec { BEGIN_MESSAGE((short)1), diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index ffa3d03d45..5196c8a366 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -1723,22 +1723,22 @@ public StringBuilder appendTo(final StringBuilder builder) builder.append(componentTokenCount()); builder.append('|'); //Token{signal=BEGIN_FIELD, name='signal', referencedName='null', description='null', id=6, version=0, deprecated=0, encodedLength=1, offset=20, componentTokenCount=21, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=BEGIN_ENUM, name='SignalCodec', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=1, offset=20, componentTokenCount=19, encoding=Encoding{presence=REQUIRED, primitiveType=UINT8, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} + //Token{signal=BEGIN_ENUM, name='SignalCodec', referencedName='null', description='Token signal type in IR', id=-1, version=0, deprecated=0, encodedLength=1, offset=20, componentTokenCount=19, encoding=Encoding{presence=REQUIRED, primitiveType=UINT8, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("signal="); builder.append(signal()); builder.append('|'); //Token{signal=BEGIN_FIELD, name='primitiveType', referencedName='null', description='null', id=7, version=0, deprecated=0, encodedLength=1, offset=21, componentTokenCount=16, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=BEGIN_ENUM, name='PrimitiveTypeCodec', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=1, offset=21, componentTokenCount=14, encoding=Encoding{presence=REQUIRED, primitiveType=UINT8, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} + //Token{signal=BEGIN_ENUM, name='PrimitiveTypeCodec', referencedName='null', description='Primitive types in type system', id=-1, version=0, deprecated=0, encodedLength=1, offset=21, componentTokenCount=14, encoding=Encoding{presence=REQUIRED, primitiveType=UINT8, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("primitiveType="); builder.append(primitiveType()); builder.append('|'); //Token{signal=BEGIN_FIELD, name='byteOrder', referencedName='null', description='null', id=8, version=0, deprecated=0, encodedLength=1, offset=22, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=BEGIN_ENUM, name='ByteOrderCodec', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=1, offset=22, componentTokenCount=4, encoding=Encoding{presence=REQUIRED, primitiveType=UINT8, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} + //Token{signal=BEGIN_ENUM, name='ByteOrderCodec', referencedName='null', description='Number encoding byte order', id=-1, version=0, deprecated=0, encodedLength=1, offset=22, componentTokenCount=4, encoding=Encoding{presence=REQUIRED, primitiveType=UINT8, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("byteOrder="); builder.append(byteOrder()); builder.append('|'); //Token{signal=BEGIN_FIELD, name='presence', referencedName='null', description='null', id=9, version=0, deprecated=0, encodedLength=1, offset=23, componentTokenCount=7, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=BEGIN_ENUM, name='PresenceCodec', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=1, offset=23, componentTokenCount=5, encoding=Encoding{presence=REQUIRED, primitiveType=UINT8, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} + //Token{signal=BEGIN_ENUM, name='PresenceCodec', referencedName='null', description='Field presence declaration', id=-1, version=0, deprecated=0, encodedLength=1, offset=23, componentTokenCount=5, encoding=Encoding{presence=REQUIRED, primitiveType=UINT8, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("presence="); builder.append(presence()); builder.append('|'); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java index 581cdf7dca..64c33db3d3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java @@ -3,6 +3,9 @@ import org.agrona.DirectBuffer; +/** + * Header for var data fields + */ @SuppressWarnings("all") public class VarDataEncodingDecoder { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java index 358041e46f..3c8a5d279a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java @@ -3,6 +3,9 @@ import org.agrona.MutableDirectBuffer; +/** + * Header for var data fields + */ @SuppressWarnings("all") public class VarDataEncodingEncoder { diff --git a/sbe-tool/src/main/resources/sbe-ir.xml b/sbe-tool/src/main/resources/sbe-ir.xml index d4bc78f09a..4f2776fbd3 100644 --- a/sbe-tool/src/main/resources/sbe-ir.xml +++ b/sbe-tool/src/main/resources/sbe-ir.xml @@ -12,15 +12,15 @@ - + - + - + 0 1 2 @@ -34,7 +34,7 @@ 10 11 - + 1 2 3 @@ -53,11 +53,11 @@ 16 17 - + 0 1 - + 0 1 2 From 7c5253585c19701497cc2b0713b38de504832b3f Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 26 Jun 2019 19:59:37 +0100 Subject: [PATCH 0102/1594] [Java] Upgrade to Checkstyle 8.22. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 99c434999e..4c30259890 100644 --- a/build.gradle +++ b/build.gradle @@ -135,7 +135,7 @@ subprojects { jar.enabled = true dependencies { - checkstyle 'com.puppycrawl.tools:checkstyle:8.21' + checkstyle 'com.puppycrawl.tools:checkstyle:8.22' compile 'org.agrona:agrona:1.0.2' @@ -145,7 +145,7 @@ subprojects { } checkstyle { - toolVersion = '8.21' + toolVersion = '8.22' } compileJava { From bd19ff6775e3c97150d20f503273cab0999a068c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 29 Jun 2019 13:43:37 +0100 Subject: [PATCH 0103/1594] [Java] Rather than call truncate pass in TRUNCATE_EXISTING when generating a IR. Issue #682. --- .../src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java index 78cbd6db6a..6a6d082fe4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java @@ -30,9 +30,7 @@ import java.nio.file.Paths; import java.util.List; -import static java.nio.file.StandardOpenOption.CREATE; -import static java.nio.file.StandardOpenOption.READ; -import static java.nio.file.StandardOpenOption.WRITE; +import static java.nio.file.StandardOpenOption.*; import static uk.co.real_logic.sbe.ir.IrUtil.*; import static uk.co.real_logic.sbe.ir.generated.FrameCodecEncoder.namespaceNameCharacterEncoding; import static uk.co.real_logic.sbe.ir.generated.FrameCodecEncoder.packageNameCharacterEncoding; @@ -67,8 +65,7 @@ public IrEncoder(final String fileName, final Ir ir) { try { - channel = FileChannel.open(Paths.get(fileName), READ, WRITE, CREATE); - channel.truncate(0); + channel = FileChannel.open(Paths.get(fileName), READ, WRITE, CREATE, TRUNCATE_EXISTING); resultBuffer = null; buffer = ByteBuffer.allocateDirect(CAPACITY); directBuffer = new UnsafeBuffer(buffer); From 368ddff70fb0ba8147a92c4c6062c983e8ff4ba8 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sun, 30 Jun 2019 14:40:33 +0100 Subject: [PATCH 0104/1594] [Java] Upgrade to Shadow 5.1.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4c30259890..c738699d6f 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ plugins { id 'java' id 'com.gradle.build-scan' version '2.3' id "io.freefair.javadoc-links" version "3.7.5" apply false - id 'com.github.johnrengelman.shadow' version '5.0.0' apply false + id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } defaultTasks 'clean', 'build', 'shadowJar', 'install' From a2f3be7a381a6dacd2d8f2c044e058662ceeacac Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 12 Jul 2019 16:44:47 +0100 Subject: [PATCH 0105/1594] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8558d6c2bd..55ab9bcd4e 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.12.7 +    1.12.8 ``` @@ -65,7 +65,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.12.8-SNAPSHOT.jar my_sbe_input.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.12.9-SNAPSHOT.jar my_sbe_input.xml C++ Build using CMake From eb5e8774a44aaf52c6d4a16d8749f09f4d8e00fc Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 12 Jul 2019 08:49:05 -0700 Subject: [PATCH 0106/1594] 1.12.8 released. --- build.gradle | 2 +- version.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index c738699d6f..775186091e 100644 --- a/build.gradle +++ b/build.gradle @@ -137,7 +137,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.22' - compile 'org.agrona:agrona:1.0.2' + compile 'org.agrona:agrona:1.0.3' testCompile 'org.hamcrest:hamcrest:2.1' testCompile 'org.mockito:mockito-core:2.28.2' diff --git a/version.txt b/version.txt index 029a7711b1..f61e31516e 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.12.9-SNAPSHOT +1.12.8 From eb644dfda09cb5e31522bfc71edb9ab2ba0fdecb Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 12 Jul 2019 08:51:21 -0700 Subject: [PATCH 0107/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index f61e31516e..029a7711b1 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.12.8 +1.12.9-SNAPSHOT From ad5a1cf220c3ce933d0cf33b59b3b8476964f96a Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sat, 13 Jul 2019 19:41:25 +0100 Subject: [PATCH 0108/1594] [Java] Add Javadoc to MetaAttribute generation. --- .../sbe/generation/java/JavaGenerator.java | 23 +++++++++++++++---- .../sbe/ir/generated/MetaAttribute.java | 20 +++++++++++++++- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 2754a1e05c..5087af26e4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1657,13 +1657,28 @@ private void generateMetaAttributeEnum() throws IOException try (Writer out = outputManager.createOutput(META_ATTRIBUTE_ENUM)) { out.append(String.format( - "/* Generated SBE (Simple Binary Encoding) message codec */\n" + + "/* Generated SBE (Simple Binary Encoding) message codec. */\n" + "package %s;\n\n" + + "/**\n" + + " * Meta attribute enum for selecting a particular meta attribute value.\n" + + " */\n" + "public enum MetaAttribute\n" + "{\n" + - " EPOCH,\n" + - " TIME_UNIT,\n" + - " SEMANTIC_TYPE,\n" + + " /**\n" + + " * The epoch or start of time. Default is 'UNIX' which is midnight January 1, 1970 UTC\n" + + " */\n" + + " EPOCH,\n\n" + + " /**\n" + + " * Time unit applied to the epoch. Can be second, millisecond, microsecond, or nanosecond.\n" + + " */\n" + + " TIME_UNIT,\n\n" + + " /**\n" + + " * The type relationship to a FIX tag value encoded type. For reference only.\n" + + " */\n" + + " SEMANTIC_TYPE,\n\n" + + " /**\n" + + " * Field presence indication. Can be optional, required, or constant.\n" + + " */\n" + " PRESENCE\n" + "}\n", ir.applicableNamespace())); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MetaAttribute.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MetaAttribute.java index 0bfd354260..af22473d99 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MetaAttribute.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MetaAttribute.java @@ -1,10 +1,28 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ +/* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; +/** + * Meta attribute enum for selecting a particular meta attribute value. + */ public enum MetaAttribute { + /** + * The epoch or start of time. Default is 'UNIX' which is midnight January 1, 1970 UTC + */ EPOCH, + + /** + * Time unit applied to the epoch. Can be second, millisecond, microsecond, or nanosecond. + */ TIME_UNIT, + + /** + * The type relationship to a FIX tag value encoded type. For reference only. + */ SEMANTIC_TYPE, + + /** + * Field presence indication. Can be optional, required, or constant. + */ PRESENCE } From 217a07c51befe97b7d4bf9b60ffafb18c5a7fc13 Mon Sep 17 00:00:00 2001 From: Dan Shechter Date: Tue, 16 Jul 2019 15:38:01 +0300 Subject: [PATCH 0109/1594] Use throwhelper to increase change of inlining - Add a ThrowHelper utility class that provides non-returning methods for throwing exceptions, this in turn helps to reduce the code size, there-by increasing the chances of inlining simple (getter/setter) methods, which has cascading CQ improvments in its own. (See: https://github.com/dotnet/coreclr/pull/6103) - Convert checks in the form of `(x < 0 || x > max)` to `(uint) x > max` to further reduce code-size and increase inlining chances - Update MSTest package deps - Drop netfx.props (which I introduces in a previous PR to support building on linux) and replace with the now standard/canonical way of referencing NetFX BCL on all platforms with a - closes #588 --- csharp/netfx.props | 26 ---------- csharp/sbe-dll/ThrowHelper.cs | 47 +++++++++++++++++++ csharp/sbe-dll/sbe-dll.csproj | 5 +- csharp/sbe-tests/sbe-tests.csproj | 9 ++-- .../generation/csharp/CSharpGenerator.java | 26 +++++----- 5 files changed, 66 insertions(+), 47 deletions(-) delete mode 100644 csharp/netfx.props create mode 100644 csharp/sbe-dll/ThrowHelper.cs diff --git a/csharp/netfx.props b/csharp/netfx.props deleted file mode 100644 index ca22ebeb7c..0000000000 --- a/csharp/netfx.props +++ /dev/null @@ -1,26 +0,0 @@ - - - - - true - - - /Library/Frameworks/Mono.framework/Versions/Current/lib/mono - /usr/lib/mono - /usr/local/lib/mono - - - $(MonoBasePath)/4.5-api - $(MonoBasePath)/4.5.1-api - $(MonoBasePath)/4.5.2-api - $(MonoBasePath)/4.6-api - $(MonoBasePath)/4.6.1-api - $(MonoBasePath)/4.6.2-api - $(MonoBasePath)/4.7-api - $(MonoBasePath)/4.7.1-api - true - - - $(FrameworkPathOverride)/Facades;$(AssemblySearchPaths) - - diff --git a/csharp/sbe-dll/ThrowHelper.cs b/csharp/sbe-dll/ThrowHelper.cs new file mode 100644 index 0000000000..30ca008c9c --- /dev/null +++ b/csharp/sbe-dll/ThrowHelper.cs @@ -0,0 +1,47 @@ +using System; + +namespace Org.SbeTool.Sbe.Dll +{ + /// + /// Helper class that provides non-returning methods that throw common exception + /// from the generated C# code + /// + public class ThrowHelper + { + /// + /// Throws a when the "count" parameter is out of range + /// + /// the parameter that triggered the exception + public static void ThrowCountOutOfRangeException(int count) => + throw new ArgumentOutOfRangeException("count", $"Outside allowed range: count={count}"); + + /// + /// Throws a when an invalid operation is invoked on a message (for example: enumerating a group past it's maximal count) + /// + public static void ThrowInvalidOperationException() => + throw new InvalidOperationException(); + + /// + /// Throws a when the "index" parameter is out of range + /// + /// the parameter that triggered the exception + public static void ThrowIndexOutOfRangeException(int index) => + throw new IndexOutOfRangeException($"index out of range: index={index}"); + + /// + /// Throws a when a too-small + /// is provided to a getter + /// + /// The length of the too-small Span + public static void ThrowWhenSpanLengthTooSmall(int length) => + throw new ArgumentOutOfRangeException("dst", $"dst.Length={length} is too small."); + + /// + /// Throws a when a too-large + /// is provided to a setter + /// + /// The length of the too-large Span + public static void ThrowWhenSpanLengthTooLarge(int length) => + throw new ArgumentOutOfRangeException("src", $"src.Length={length} is too large."); + } +} \ No newline at end of file diff --git a/csharp/sbe-dll/sbe-dll.csproj b/csharp/sbe-dll/sbe-dll.csproj index a556ea09fd..252b6d9f3f 100644 --- a/csharp/sbe-dll/sbe-dll.csproj +++ b/csharp/sbe-dll/sbe-dll.csproj @@ -1,6 +1,4 @@  - - net45;netstandard2.0 True @@ -23,7 +21,8 @@ - + + diff --git a/csharp/sbe-tests/sbe-tests.csproj b/csharp/sbe-tests/sbe-tests.csproj index 53eaca7da5..caf0e97279 100644 --- a/csharp/sbe-tests/sbe-tests.csproj +++ b/csharp/sbe-tests/sbe-tests.csproj @@ -1,6 +1,4 @@  - - net45;netcoreapp2.1 Org.SbeTool.Sbe.Tests @@ -25,9 +23,10 @@ - - - + + + + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 9107c2c5fd..303474b9d7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -210,14 +210,16 @@ private void generateGroupClassHeader( final String typeForBlockLength = cSharpTypeName(tokens.get(index + 2).encoding().primitiveType()); final String typeForNumInGroup = cSharpTypeName(numInGroupToken.encoding().primitiveType()); + final String throwCondition = numInGroupToken.encoding().applicableMinValue().longValue() == 0 ? + "if ((uint) count > %3$d)\n" : + "if (count < %2$d || count > %3$d)\n"; + sb.append(String.format("\n" + indent + INDENT + "public void WrapForEncode(%1$s parentMessage, DirectBuffer buffer, int count)\n" + indent + INDENT + "{\n" + - indent + INDENT + INDENT + "if (count < %2$d || count > %3$d)\n" + + indent + INDENT + INDENT + throwCondition + indent + INDENT + INDENT + "{\n" + - indent + INDENT + INDENT + INDENT + "throw new ArgumentOutOfRangeException(\"count\",\n" + - indent + INDENT + INDENT + INDENT + INDENT + "\"Outside allowed range: count=\" + count +\n" + - indent + INDENT + INDENT + INDENT + INDENT + "\", min=%2$d, max=%3$d\");\n" + + indent + INDENT + INDENT + INDENT + "ThrowHelper.ThrowCountOutOfRangeException(count);\n" + indent + INDENT + INDENT + "}\n\n" + indent + INDENT + INDENT + "_parentMessage = parentMessage;\n" + indent + INDENT + INDENT + "_buffer = buffer;\n" + @@ -258,7 +260,7 @@ private void generateGroupEnumerator(final StringBuilder sb, final String groupN indent + INDENT + "{\n" + indent + INDENT + INDENT + "if (_index + 1 >= _count)\n" + indent + INDENT + INDENT + "{\n" + - indent + INDENT + INDENT + INDENT + "throw new InvalidOperationException();\n" + + indent + INDENT + INDENT + INDENT + "ThrowHelper.ThrowInvalidOperationException();\n" + indent + INDENT + INDENT + "}\n\n" + indent + INDENT + INDENT + "_offset = _parentMessage.Limit;\n" + indent + INDENT + INDENT + "_parentMessage.Limit = _offset + _blockLength;\n" + @@ -811,9 +813,9 @@ private CharSequence generateArrayProperty( sb.append(String.format("\n" + indent + "public %1$s Get%2$s(int index)\n" + indent + "{\n" + - indent + INDENT + "if (index < 0 || index >= %3$d)\n" + + indent + INDENT + "if ((uint) index >= %3$d)\n" + indent + INDENT + "{\n" + - indent + INDENT + INDENT + "throw new IndexOutOfRangeException(\"index out of range: index=\" + index);\n" + + indent + INDENT + INDENT + "ThrowHelper.ThrowIndexOutOfRangeException(index);\n" + indent + INDENT + "}\n\n" + "%4$s" + indent + INDENT + "return _buffer.%5$sGet%8$s(_offset + %6$d + (index * %7$d));\n" + @@ -825,9 +827,9 @@ private CharSequence generateArrayProperty( sb.append(String.format("\n" + indent + "public void Set%1$s(int index, %2$s value)\n" + indent + "{\n" + - indent + INDENT + "if (index < 0 || index >= %3$d)\n" + + indent + INDENT + "if ((uint) index >= %3$d)\n" + indent + INDENT + "{\n" + - indent + INDENT + INDENT + "throw new IndexOutOfRangeException(\"index out of range: index=\" + index);\n" + + indent + INDENT + INDENT + "ThrowHelper.ThrowIndexOutOfRangeException(index);\n" + indent + INDENT + "}\n\n" + indent + INDENT + "_buffer.%4$sPut%7$s(_offset + %5$d + (index * %6$d), value);\n" + indent + "}\n", @@ -852,8 +854,7 @@ private CharSequence generateArrayProperty( indent + INDENT + "const int length = %2$d;\n" + indent + INDENT + "if (dst.Length < length)\n" + indent + INDENT + "{\n" + - indent + INDENT + INDENT + - "throw new ArgumentOutOfRangeException($\"dst.Length={dst.Length} is too large.\");\n" + + indent + INDENT + INDENT + "ThrowHelper.ThrowWhenSpanLengthTooSmall(dst.Length);\n" + indent + INDENT + "}\n\n" + "%3$s" + indent + INDENT + "_buffer.GetBytes(_offset + %4$d, dst);\n" + @@ -874,8 +875,7 @@ private CharSequence generateArrayProperty( indent + INDENT + "const int length = %2$d;\n" + indent + INDENT + "if (src.Length > length)\n" + indent + INDENT + "{\n" + - indent + INDENT + INDENT + - "throw new ArgumentOutOfRangeException($\"src.Length={src.Length} is too large.\");\n" + + indent + INDENT + INDENT + "ThrowHelper.ThrowWhenSpanLengthTooLarge(src.Length);\n" + indent + INDENT + "}\n\n" + indent + INDENT + "_buffer.SetBytes(_offset + %3$d, src);\n" + indent + "}\n", From 6163f5432c4045e9f412db4598f6a4617ae37537 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Thu, 18 Jul 2019 19:17:44 +0900 Subject: [PATCH 0110/1594] [C++] Use [[nodiscard]] attribute where applicable. --- .../sbe/generation/cpp/CppGenerator.java | 100 ++++++++++-------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 6fbf1d3c8d..1c3ab70b27 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -206,7 +206,7 @@ private static void generateGroupClassHeader( indent + " std::uint64_t m_offset;\n" + indent + " std::uint64_t m_actingVersion;\n\n" + - indent + " std::uint64_t *sbePositionPtr() SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD std::uint64_t *sbePositionPtr() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return m_positionPtr;\n" + indent + " }\n\n" + @@ -283,7 +283,7 @@ private static void generateGroupClassHeader( indent + " return %2$d;\n" + indent + " }\n\n" + - indent + " std::uint64_t sbePosition() const\n" + + indent + " SBE_NODISCARD std::uint64_t sbePosition() const\n" + indent + " {\n" + indent + " return *m_positionPtr;\n" + indent + " }\n\n" + @@ -302,12 +302,12 @@ private static void generateGroupClassHeader( indent + " *m_positionPtr = sbeCheckPosition(position);\n" + indent + " }\n\n" + - indent + " inline std::uint64_t count() const SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD inline std::uint64_t count() const SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return m_count;\n" + indent + " }\n\n" + - indent + " inline bool hasNext() const SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD inline bool hasNext() const SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return m_index + 1 < m_count;\n" + indent + " }\n\n" + @@ -367,7 +367,7 @@ private static CharSequence generateGroupProperty( propertyName)); sb.append(String.format( - indent + " static SBE_CONSTEXPR std::uint16_t %1$sId() SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::uint16_t %1$sId() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n", @@ -375,7 +375,7 @@ private static CharSequence generateGroupProperty( token.id())); sb.append(String.format("\n" + - indent + " inline %1$s &%2$s()\n" + + indent + " SBE_NODISCARD inline %1$s &%2$s()\n" + indent + " {\n" + indent + " m_%2$s.wrapForDecode(m_buffer, sbePositionPtr(), m_actingVersion, m_bufferLength);\n" + indent + " return m_%2$s;\n" + @@ -395,12 +395,12 @@ private static CharSequence generateGroupProperty( cppTypeForNumInGroup)); sb.append(String.format("\n" + - indent + " static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n\n" + - indent + " bool %1$sInActingVersion() const SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD bool %1$sInActingVersion() const SBE_NOEXCEPT\n" + indent + " {\n" + indent + "#if defined(__clang__)\n" + indent + "#pragma clang diagnostic push\n" + @@ -444,7 +444,7 @@ private CharSequence generateVarData(final String className, final List t sb, token, propertyName, characterEncoding, lengthToken, lengthOfLengthField, lengthCppType, indent); sb.append(String.format("\n" + - indent + " const char *%1$s()\n" + + indent + " SBE_NODISCARD const char *%1$s()\n" + indent + " {\n" + "%2$s" + indent + " %4$s lengthFieldValue;\n" + @@ -661,7 +661,7 @@ private void generateChoiceSet(final List tokens) throws IOException cppTypeName(tokens.get(0).encoding().primitiveType()))); out.append(String.format("\n" + - " bool isEmpty() const\n" + + " SBE_NODISCARD bool isEmpty() const\n" + " {\n" + " %1$s val;\n" + " std::memcpy(&val, m_buffer + m_offset, sizeof(%1$s));\n" + @@ -771,7 +771,7 @@ private CharSequence generateChoices(final String bitsetClassName, final List= 201703L\n" + + "# define SBE_NODISCARD [[nodiscard]]\n" + + "#else\n" + + "# define SBE_NODISCARD\n" + + "#endif\n\n" + + "#if !defined(__STDC_LIMIT_MACROS)\n" + "# define __STDC_LIMIT_MACROS 1\n" + "#endif\n" + @@ -1273,7 +1279,7 @@ private CharSequence generateSingleValueProperty( final StringBuilder sb = new StringBuilder(); sb.append(String.format("\n" + - indent + " %1$s %2$s() const\n" + + indent + " SBE_NODISCARD %1$s %2$s() const\n" + indent + " {\n" + "%3$s" + "%4$s" + @@ -1319,7 +1325,7 @@ private CharSequence generateArrayProperty( arrayLength)); sb.append(String.format("\n" + - indent + " const char *%1$s() const SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD const char *%1$s() const SBE_NOEXCEPT\n" + indent + " {\n" + "%2$s" + indent + " return m_buffer + m_offset + %3$d;\n" + @@ -1329,7 +1335,7 @@ private CharSequence generateArrayProperty( offset)); sb.append(String.format("\n" + - indent + " char *%1$s() SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD char *%1$s() SBE_NOEXCEPT\n" + indent + " {\n" + "%2$s" + indent + " return m_buffer + m_offset + %3$d;\n" + @@ -1345,7 +1351,7 @@ private CharSequence generateArrayProperty( indent); sb.append(String.format("\n" + - indent + " %1$s %2$s(const std::uint64_t index) const\n" + + indent + " SBE_NODISCARD %1$s %2$s(const std::uint64_t index) const\n" + indent + " {\n" + indent + " if (index >= %3$d)\n" + indent + " {\n" + @@ -1536,7 +1542,7 @@ private CharSequence generateConstPropertyMethods( if (token.encoding().primitiveType() != PrimitiveType.CHAR) { return String.format("\n" + - indent + " static SBE_CONSTEXPR %1$s %2$s() SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD static SBE_CONSTEXPR %1$s %2$s() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %3$s;\n" + indent + " }\n", @@ -1568,7 +1574,7 @@ private CharSequence generateConstPropertyMethods( constantValue.length)); sb.append(String.format("\n" + - indent + " const char *%1$s() const\n" + + indent + " SBE_NODISCARD const char *%1$s() const\n" + indent + " {\n" + indent + " static std::uint8_t %1$sValues[] = {%2$s};\n\n" + @@ -1674,42 +1680,42 @@ private CharSequence generateFixedFlyweightCode(final String className, final in " return *this = %1$s(buffer, offset, bufferLength, actingVersion);\n" + " }\n\n" + - " static SBE_CONSTEXPR std::uint64_t encodedLength() SBE_NOEXCEPT\n" + + " SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t encodedLength() SBE_NOEXCEPT\n" + " {\n" + " return %2$s;\n" + " }\n\n" + - " std::uint64_t offset() const SBE_NOEXCEPT\n" + + " SBE_NODISCARD std::uint64_t offset() const SBE_NOEXCEPT\n" + " {\n" + " return m_offset;\n" + " }\n\n" + - " const char * buffer() const SBE_NOEXCEPT\n" + + " SBE_NODISCARD const char * buffer() const SBE_NOEXCEPT\n" + " {\n" + " return m_buffer;\n" + " }\n\n" + - " char * buffer() SBE_NOEXCEPT\n" + + " SBE_NODISCARD char * buffer() SBE_NOEXCEPT\n" + " {\n" + " return m_buffer;\n" + " }\n\n" + - " std::uint64_t bufferLength() const SBE_NOEXCEPT\n" + + " SBE_NODISCARD std::uint64_t bufferLength() const SBE_NOEXCEPT\n" + " {\n" + " return m_bufferLength;\n" + " }\n\n" + - " std::uint64_t actingVersion() const SBE_NOEXCEPT\n" + + " SBE_NODISCARD std::uint64_t actingVersion() const SBE_NOEXCEPT\n" + " {\n" + " return m_actingVersion;\n" + " }\n\n" + - " static SBE_CONSTEXPR %3$s sbeSchemaId() SBE_NOEXCEPT\n" + + " SBE_NODISCARD static SBE_CONSTEXPR %3$s sbeSchemaId() SBE_NOEXCEPT\n" + " {\n" + " return %4$s;\n" + " }\n\n" + - " static SBE_CONSTEXPR %5$s sbeSchemaVersion() SBE_NOEXCEPT\n" + + " SBE_NODISCARD static SBE_CONSTEXPR %5$s sbeSchemaVersion() SBE_NOEXCEPT\n" + " {\n" + " return %6$s;\n" + " }\n", @@ -1793,32 +1799,32 @@ private CharSequence generateMessageFlyweightCode(final String className, final " };\n\n" + "%11$s" + - " static SBE_CONSTEXPR %1$s sbeBlockLength() SBE_NOEXCEPT\n" + + " SBE_NODISCARD static SBE_CONSTEXPR %1$s sbeBlockLength() SBE_NOEXCEPT\n" + " {\n" + " return %2$s;\n" + " }\n\n" + - " static SBE_CONSTEXPR %3$s sbeTemplateId() SBE_NOEXCEPT\n" + + " SBE_NODISCARD static SBE_CONSTEXPR %3$s sbeTemplateId() SBE_NOEXCEPT\n" + " {\n" + " return %4$s;\n" + " }\n\n" + - " static SBE_CONSTEXPR %5$s sbeSchemaId() SBE_NOEXCEPT\n" + + " SBE_NODISCARD static SBE_CONSTEXPR %5$s sbeSchemaId() SBE_NOEXCEPT\n" + " {\n" + " return %6$s;\n" + " }\n\n" + - " static SBE_CONSTEXPR %7$s sbeSchemaVersion() SBE_NOEXCEPT\n" + + " SBE_NODISCARD static SBE_CONSTEXPR %7$s sbeSchemaVersion() SBE_NOEXCEPT\n" + " {\n" + " return %8$s;\n" + " }\n\n" + - " static SBE_CONSTEXPR const char * sbeSemanticType() SBE_NOEXCEPT\n" + + " SBE_NODISCARD static SBE_CONSTEXPR const char * sbeSemanticType() SBE_NOEXCEPT\n" + " {\n" + " return \"%9$s\";\n" + " }\n\n" + - " std::uint64_t offset() const SBE_NOEXCEPT\n" + + " SBE_NODISCARD std::uint64_t offset() const SBE_NOEXCEPT\n" + " {\n" + " return m_offset;\n" + " }\n\n" + @@ -1854,7 +1860,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final " return *this = %10$s(buffer, offset, bufferLength, actingBlockLength, actingVersion);\n" + " }\n\n" + - " std::uint64_t sbePosition() const SBE_NOEXCEPT\n" + + " SBE_NODISCARD std::uint64_t sbePosition() const SBE_NOEXCEPT\n" + " {\n" + " return m_position;\n" + " }\n\n" + @@ -1873,27 +1879,27 @@ private CharSequence generateMessageFlyweightCode(final String className, final " m_position = sbeCheckPosition(position);\n" + " }\n\n" + - " std::uint64_t encodedLength() const SBE_NOEXCEPT\n" + + " SBE_NODISCARD std::uint64_t encodedLength() const SBE_NOEXCEPT\n" + " {\n" + " return sbePosition() - m_offset;\n" + " }\n\n" + - " const char * buffer() const SBE_NOEXCEPT\n" + + " SBE_NODISCARD const char * buffer() const SBE_NOEXCEPT\n" + " {\n" + " return m_buffer;\n" + " }\n\n" + - " char * buffer() SBE_NOEXCEPT\n" + + " SBE_NODISCARD char * buffer() SBE_NOEXCEPT\n" + " {\n" + " return m_buffer;\n" + " }\n\n" + - " std::uint64_t bufferLength() const SBE_NOEXCEPT\n" + + " SBE_NODISCARD std::uint64_t bufferLength() const SBE_NOEXCEPT\n" + " {\n" + " return m_bufferLength;\n" + " }\n\n" + - " std::uint64_t actingVersion() const SBE_NOEXCEPT\n" + + " SBE_NODISCARD std::uint64_t actingVersion() const SBE_NOEXCEPT\n" + " {\n" + " return m_actingVersion;\n" + " }\n", @@ -1971,12 +1977,12 @@ private void generateFieldCommonMethods( } sb.append(String.format("\n" + - indent + " static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n\n" + - indent + " bool %1$sInActingVersion() SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD bool %1$sInActingVersion() SBE_NOEXCEPT\n" + indent + " {\n" + indent + "#if defined(__clang__)\n" + indent + "#pragma clang diagnostic push\n" + @@ -1991,7 +1997,7 @@ private void generateFieldCommonMethods( fieldToken.version())); sb.append(String.format("\n" + - indent + " static SBE_CONSTEXPR std::size_t %1$sEncodingOffset() SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::size_t %1$sEncodingOffset() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n", @@ -2008,7 +2014,7 @@ private static void generateFieldMetaAttributeMethod( final String semanticType = encoding.semanticType() == null ? "" : encoding.semanticType(); sb.append(String.format("\n" + - indent + " static const char * %sMetaAttribute(const MetaAttribute metaAttribute)" + + indent + " SBE_NODISCARD static const char * %sMetaAttribute(const MetaAttribute metaAttribute)" + " SBE_NOEXCEPT\n" + indent + " {\n" + indent + " switch (metaAttribute)\n" + @@ -2061,7 +2067,7 @@ private CharSequence generateEnumProperty( final StringBuilder sb = new StringBuilder(); sb.append(String.format("\n" + - indent + " static SBE_CONSTEXPR std::size_t %1$sEncodingLength() SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::size_t %1$sEncodingLength() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n", @@ -2073,7 +2079,7 @@ private CharSequence generateEnumProperty( final String constValue = fieldToken.encoding().constValue().toString(); sb.append(String.format("\n" + - indent + " static SBE_CONSTEXPR %1$s::Value %2$sConstValue() SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD static SBE_CONSTEXPR %1$s::Value %2$sConstValue() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %1$s::Value::%3$s;\n" + indent + " }\n", @@ -2082,7 +2088,7 @@ private CharSequence generateEnumProperty( constValue.substring(constValue.indexOf(".") + 1))); sb.append(String.format("\n" + - indent + " %1$s::Value %2$s() const SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD %1$s::Value %2$s() const SBE_NOEXCEPT\n" + indent + " {\n" + "%3$s" + indent + " return %1$s::Value::%4$s;\n" + @@ -2095,7 +2101,7 @@ private CharSequence generateEnumProperty( else { sb.append(String.format("\n" + - indent + " %1$s::Value %2$s() const\n" + + indent + " SBE_NODISCARD %1$s::Value %2$s() const\n" + indent + " {\n" + "%3$s" + indent + " %5$s val;\n" + @@ -2143,7 +2149,7 @@ private static Object generateBitsetProperty(final String propertyName, final To propertyName)); sb.append(String.format( - indent + " %1$s &%2$s()\n" + + indent + " SBE_NODISCARD %1$s &%2$s()\n" + indent + " {\n" + indent + " m_%2$s.wrap(m_buffer, m_offset + %3$d, m_actingVersion, m_bufferLength);\n" + indent + " return m_%2$s;\n" + @@ -2179,7 +2185,7 @@ private static Object generateCompositeProperty(final String propertyName, final propertyName)); sb.append(String.format( - indent + " %1$s &%2$s()\n" + + indent + " SBE_NODISCARD %1$s &%2$s()\n" + indent + " {\n" + indent + " m_%2$s.wrap(m_buffer, m_offset + %3$d, m_actingVersion, m_bufferLength);\n" + indent + " return m_%2$s;\n" + From a45bfa20e85506ae921fa8d4f985eeaf27f56a6c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 19 Jul 2019 15:28:30 +0100 Subject: [PATCH 0111/1594] [Java] Upgrade to Gradle 5.5.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- gradlew.bat | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 775186091e..c4050506f6 100644 --- a/build.gradle +++ b/build.gradle @@ -771,6 +771,6 @@ task uploadToMavenCentral { } wrapper { - gradleVersion = '5.4.1' + gradleVersion = '5.5.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ee69dd68d1..430dfabc5c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index b0d6d0ab5d..8e25e6c19d 100755 --- a/gradlew +++ b/gradlew @@ -7,7 +7,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, diff --git a/gradlew.bat b/gradlew.bat index 9991c50326..9618d8d960 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -5,7 +5,7 @@ @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem -@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, From 37978dd1b5fd09605ee756074402e8ee6845defa Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 19 Jul 2019 15:55:53 +0100 Subject: [PATCH 0112/1594] Update licence references to https. --- CMakeLists.txt | 2 +- LICENSE | 2 +- README.md | 2 +- build.gradle | 4 ++-- csharp/.nuget/examples/CarExample.cs | 2 +- csharp/.nuget/examples/Program.cs | 2 +- csharp/sbe-benchmarks/Program.cs | 2 +- csharp/sbe-samples/CarExample.cs | 2 +- csharp/sbe-samples/ExtensionExample.cs | 2 +- csharp/sbe-samples/Program.cs | 2 +- csharp/sbe-tests/BigEndianTests.cs | 2 +- csharp/sbe-tests/DirectBufferTests.cs | 2 +- csharp/sbe-tests/EndianessConverterTests.cs | 2 +- csharp/sbe-tests/InteropTests.cs | 2 +- csharp/sbe-tests/Issue435Tests.cs | 2 +- csharp/sbe-tests/Issue483Tests.cs | 2 +- csharp/sbe-tests/Issue560Tests.cs | 2 +- csharp/sbe-tests/SinceDeprecatedTests.cs | 2 +- sbe-benchmarks/src/main/cpp/CMakeLists.txt | 2 +- sbe-benchmarks/src/main/cpp/CarBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/CodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/MarketDataBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/benchlet-main.cpp | 2 +- sbe-benchmarks/src/main/cpp/benchlet.h | 2 +- .../src/main/java/uk/co/real_logic/sbe/CarBenchmark.java | 2 +- .../main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java | 2 +- sbe-samples/src/main/cpp/CMakeLists.txt | 2 +- sbe-samples/src/main/cpp/GeneratedStubExample.cpp | 2 +- sbe-samples/src/main/cpp/OtfExample.cpp | 2 +- .../uk/co/real_logic/sbe/examples/ExampleTokenListener.java | 2 +- .../co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java | 2 +- .../sbe/examples/ExampleUsingGeneratedStubExtension.java | 2 +- .../main/java/uk/co/real_logic/sbe/examples/OtfExample.java | 2 +- sbe-tool/src/main/cpp/CMakeLists.txt | 2 +- sbe-tool/src/main/cpp/otf/Encoding.h | 2 +- sbe-tool/src/main/cpp/otf/IrDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/Token.h | 2 +- .../src/main/java/uk/co/real_logic/sbe/PrimitiveType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java | 2 +- .../main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java | 2 +- .../java/uk/co/real_logic/sbe/codec/java/MethodSelector.java | 2 +- .../java/uk/co/real_logic/sbe/generation/CodeGenerator.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/Generators.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/NamedToken.java | 2 +- .../uk/co/real_logic/sbe/generation/TargetCodeGenerator.java | 2 +- .../real_logic/sbe/generation/TargetCodeGeneratorLoader.java | 2 +- .../java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 2 +- .../uk/co/real_logic/sbe/generation/c/COutputManager.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/c/CUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java | 2 +- .../real_logic/sbe/generation/cpp/NamespaceOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/csharp/CSharp.java | 2 +- .../co/real_logic/sbe/generation/csharp/CSharpGenerator.java | 2 +- .../sbe/generation/csharp/CSharpNamespaceOutputManager.java | 2 +- .../uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java | 2 +- .../co/real_logic/sbe/generation/golang/GolangGenerator.java | 2 +- .../real_logic/sbe/generation/golang/GolangOutputManager.java | 2 +- .../uk/co/real_logic/sbe/generation/golang/GolangUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/JavaUtil.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/rust/Rust.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/RustCodecType.java | 2 +- .../sbe/generation/rust/RustFlatFileOutputManager.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/RustUtil.java | 2 +- .../real_logic/sbe/generation/rust/SplitCompositeTokens.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java | 2 +- .../main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java | 2 +- .../main/java/uk/co/real_logic/sbe/ir/MessageComponents.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java | 2 +- .../java/uk/co/real_logic/sbe/json/JsonTokenListener.java | 2 +- .../java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java | 2 +- .../main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java | 2 +- .../main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java | 2 +- .../main/java/uk/co/real_logic/sbe/util/ValidationUtil.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java | 2 +- .../resources/golang/templates/SbeMarshallingBigEndian.go | 2 +- .../resources/golang/templates/SbeMarshallingLittleEndian.go | 2 +- sbe-tool/src/test/c/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/c/CMakeLists.txt | 2 +- sbe-tool/src/test/c/CodeGenTest.cpp | 2 +- sbe-tool/src/test/c/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/cpp/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/cpp/CMakeLists.txt | 2 +- sbe-tool/src/test/cpp/CodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeElementsTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp | 2 +- sbe-tool/src/test/cpp/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp | 2 +- sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp | 2 +- .../test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java | 2 +- .../java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/TestTargetLanguage.java | 2 +- sbe-tool/src/test/java/uk/co/real_logic/sbe/TestUtil.java | 2 +- .../test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java | 2 +- .../sbe/generation/java/CompositeElementsGenerationTest.java | 2 +- .../real_logic/sbe/generation/java/ConstantCharArrayTest.java | 2 +- .../real_logic/sbe/generation/java/GenerateFixBinaryTest.java | 2 +- .../co/real_logic/sbe/generation/java/JavaGeneratorTest.java | 2 +- .../sbe/generation/java/PackageOutputManagerTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/ReflectionUtil.java | 2 +- .../real_logic/sbe/generation/java/SchemaExtensionTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/ToStringTest.java | 2 +- .../uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java | 2 +- .../co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java | 2 +- 151 files changed, 152 insertions(+), 152 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cd4c899c9..960ba6d2cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, diff --git a/LICENSE b/LICENSE index 37ec93a14f..e060f18461 100644 --- a/LICENSE +++ b/LICENSE @@ -182,7 +182,7 @@ third-party archives. you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/README.md b/README.md index 55ab9bcd4e..7b090b502b 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/build.gradle b/build.gradle index c4050506f6..7a4afce1b5 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -70,7 +70,7 @@ def projectPom = { licenses { license { name = 'The Apache License, Version 2.0' - url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' } } diff --git a/csharp/.nuget/examples/CarExample.cs b/csharp/.nuget/examples/CarExample.cs index c7239fe4c9..be6720b911 100644 --- a/csharp/.nuget/examples/CarExample.cs +++ b/csharp/.nuget/examples/CarExample.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/csharp/.nuget/examples/Program.cs b/csharp/.nuget/examples/Program.cs index 49120e9b27..52811dc550 100644 --- a/csharp/.nuget/examples/Program.cs +++ b/csharp/.nuget/examples/Program.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/csharp/sbe-benchmarks/Program.cs b/csharp/sbe-benchmarks/Program.cs index c739a8cc67..fbacc9b642 100644 --- a/csharp/sbe-benchmarks/Program.cs +++ b/csharp/sbe-benchmarks/Program.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/csharp/sbe-samples/CarExample.cs b/csharp/sbe-samples/CarExample.cs index 4a8807d05a..a43b045490 100644 --- a/csharp/sbe-samples/CarExample.cs +++ b/csharp/sbe-samples/CarExample.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/csharp/sbe-samples/ExtensionExample.cs b/csharp/sbe-samples/ExtensionExample.cs index a68ff3ba2f..831598f523 100644 --- a/csharp/sbe-samples/ExtensionExample.cs +++ b/csharp/sbe-samples/ExtensionExample.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/csharp/sbe-samples/Program.cs b/csharp/sbe-samples/Program.cs index 727776f338..28e8d35221 100644 --- a/csharp/sbe-samples/Program.cs +++ b/csharp/sbe-samples/Program.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/csharp/sbe-tests/BigEndianTests.cs b/csharp/sbe-tests/BigEndianTests.cs index 0979977a49..a850e56041 100644 --- a/csharp/sbe-tests/BigEndianTests.cs +++ b/csharp/sbe-tests/BigEndianTests.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/csharp/sbe-tests/DirectBufferTests.cs b/csharp/sbe-tests/DirectBufferTests.cs index 386ef14ff9..51ab649ac2 100644 --- a/csharp/sbe-tests/DirectBufferTests.cs +++ b/csharp/sbe-tests/DirectBufferTests.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/csharp/sbe-tests/EndianessConverterTests.cs b/csharp/sbe-tests/EndianessConverterTests.cs index d3abdd9b6f..dd19591bf5 100644 --- a/csharp/sbe-tests/EndianessConverterTests.cs +++ b/csharp/sbe-tests/EndianessConverterTests.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/csharp/sbe-tests/InteropTests.cs b/csharp/sbe-tests/InteropTests.cs index bca93efcc5..8d48dd183b 100644 --- a/csharp/sbe-tests/InteropTests.cs +++ b/csharp/sbe-tests/InteropTests.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/csharp/sbe-tests/Issue435Tests.cs b/csharp/sbe-tests/Issue435Tests.cs index 54cb07f72d..26b78e572b 100644 --- a/csharp/sbe-tests/Issue435Tests.cs +++ b/csharp/sbe-tests/Issue435Tests.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/csharp/sbe-tests/Issue483Tests.cs b/csharp/sbe-tests/Issue483Tests.cs index bd6f9b0640..4a6cc78b84 100644 --- a/csharp/sbe-tests/Issue483Tests.cs +++ b/csharp/sbe-tests/Issue483Tests.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/csharp/sbe-tests/Issue560Tests.cs b/csharp/sbe-tests/Issue560Tests.cs index d86aa74f88..d1e58d1655 100644 --- a/csharp/sbe-tests/Issue560Tests.cs +++ b/csharp/sbe-tests/Issue560Tests.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/csharp/sbe-tests/SinceDeprecatedTests.cs b/csharp/sbe-tests/SinceDeprecatedTests.cs index b34f648872..747fe4a059 100644 --- a/csharp/sbe-tests/SinceDeprecatedTests.cs +++ b/csharp/sbe-tests/SinceDeprecatedTests.cs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-benchmarks/src/main/cpp/CMakeLists.txt b/sbe-benchmarks/src/main/cpp/CMakeLists.txt index 0dfecbd0a5..efd9407019 100644 --- a/sbe-benchmarks/src/main/cpp/CMakeLists.txt +++ b/sbe-benchmarks/src/main/cpp/CMakeLists.txt @@ -5,7 +5,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-benchmarks/src/main/cpp/CarBench.cpp b/sbe-benchmarks/src/main/cpp/CarBench.cpp index 3a44d224ce..7fe2943261 100644 --- a/sbe-benchmarks/src/main/cpp/CarBench.cpp +++ b/sbe-benchmarks/src/main/cpp/CarBench.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-benchmarks/src/main/cpp/CodecBench.h b/sbe-benchmarks/src/main/cpp/CodecBench.h index 968440c902..f7eee1ce47 100644 --- a/sbe-benchmarks/src/main/cpp/CodecBench.h +++ b/sbe-benchmarks/src/main/cpp/CodecBench.h @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp index 86f5b25ade..13887ade4b 100644 --- a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp +++ b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h index 203d5fdb78..c2f2cf4f9a 100644 --- a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h index d52753bee8..6bff1943c0 100644 --- a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp index ba7e768377..a8bb92cfb5 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp +++ b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-benchmarks/src/main/cpp/benchlet.h b/sbe-benchmarks/src/main/cpp/benchlet.h index e9a11cc6ce..32ad219c59 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet.h +++ b/sbe-benchmarks/src/main/cpp/benchlet.h @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java index c49af8d914..855659cf5a 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java index 7dc25aed5a..064fd8308b 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-samples/src/main/cpp/CMakeLists.txt b/sbe-samples/src/main/cpp/CMakeLists.txt index 3e2c75760f..8ea4e437d7 100644 --- a/sbe-samples/src/main/cpp/CMakeLists.txt +++ b/sbe-samples/src/main/cpp/CMakeLists.txt @@ -5,7 +5,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index 17e7fb671d..b7abaf1d97 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-samples/src/main/cpp/OtfExample.cpp b/sbe-samples/src/main/cpp/OtfExample.cpp index 8801d99477..cc1a6b90a4 100644 --- a/sbe-samples/src/main/cpp/OtfExample.cpp +++ b/sbe-samples/src/main/cpp/OtfExample.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java index 58a0124168..cfdbe23862 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java index 6f24c618ca..787b950066 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java index 016dff938d..43c51632b8 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java index cf9aa5d526..6440554997 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/cpp/CMakeLists.txt b/sbe-tool/src/main/cpp/CMakeLists.txt index 7fa5c0adbb..6370fc6307 100644 --- a/sbe-tool/src/main/cpp/CMakeLists.txt +++ b/sbe-tool/src/main/cpp/CMakeLists.txt @@ -5,7 +5,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/cpp/otf/Encoding.h b/sbe-tool/src/main/cpp/otf/Encoding.h index 09315e65ac..1dea6949b4 100644 --- a/sbe-tool/src/main/cpp/otf/Encoding.h +++ b/sbe-tool/src/main/cpp/otf/Encoding.h @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index 36bddefa7d..e91a475ebe 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h index 3dda594c0f..64fc7636d1 100644 --- a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h index f5bf4ce007..ad9668a3ef 100644 --- a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/cpp/otf/Token.h b/sbe-tool/src/main/cpp/otf/Token.h index c015abdda9..760ea45ca8 100644 --- a/sbe-tool/src/main/cpp/otf/Token.h +++ b/sbe-tool/src/main/cpp/otf/Token.h @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java index ff32a1fc5e..cea3f50fa8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index e2b64760fa..b9f4ee7e9c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index 0d519a6383..6a24abadc3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java index 30ed8d7e6a..73ba37d545 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java index 8214e5fbf5..5a008d8abd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java index d020edafe8..e2386ee6f3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java index 2d9b73c6a4..5b5bd69c21 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/NamedToken.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/NamedToken.java index 4ba67d69f4..488973e952 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/NamedToken.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/NamedToken.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java index 867b348a80..43052e9aa0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index b90813af2a..19a6f0d658 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 03cb3ecfbe..50bd245236 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java index 7b5acba642..e298d5cc50 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java index 9dce9ba46a..5d3ff4c62a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 1c3ab70b27..3f4d56fca8 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index cd2d250dac..8158cd46b6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java index 8af97de33a..1665e47da0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java index 7d56149562..a8feda1e8f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 303474b9d7..949da1894a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java index f6b99c6497..32514eebde 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index 1ab34e0107..33e37d2551 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index 7477c42c86..a16fdbb741 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java index a441be3e51..e543a37771 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java index d514b9f5ce..45dc74d6c5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 5087af26e4..dc455f1223 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index fc070079a5..32e1c2af91 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/Rust.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/Rust.java index 89526a62d2..0959f6ec0c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/Rust.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/Rust.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java index 456f4f765e..bd57d24a6e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManager.java index 822fb20b14..a35dedc1b6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManager.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 69b54fd88b..d882c85fc6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index e387b31d22..62f8b19762 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SplitCompositeTokens.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SplitCompositeTokens.java index 1677cfea93..9d65ed96cd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SplitCompositeTokens.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SplitCompositeTokens.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java index 048c882144..1add1f0b24 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java index a1ec6d96c1..881660b8a7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java index 87aa9bc4f9..c43b5d3ca3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java index b5fdd198ac..aef7c71f5b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index 9d466e4519..45371de92c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java index 6a6d082fe4..92e8b67e30 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java index 4dad83419b..10c13028ca 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java index 83e75a774f..b376a62506 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java index 55e1375ac0..80827c50fc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index 49908d5643..b913d1814a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java index 8839e7916d..fa26223540 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index dc712ea6e9..0252cdfa2d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java index 1027d431b1..16c82c71ec 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java index 493df3d029..59671f61fb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java index 2c7d11d7e5..8faab2d090 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java index 93c71cf9ff..1401214b4d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java index 702cbc5915..41e994a97d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/util/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/util/ValidationUtil.java index 662c9c219d..fa08859339 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/util/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/util/ValidationUtil.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index dffa921e80..9e09db8ced 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index 7d0dfdbb20..e63ff5d36a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index 6ee63ff163..d2588082b9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java index e250609ff9..f707ed2eaf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java index 307701a449..f8e190f6d5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index f3a0d00dcd..37c94c5e33 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java index c524b90403..7f374c07ea 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index 3d8fca3760..e13fb37539 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java index 9f99ab6fcf..0bcfefa768 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java index cb3d2d4569..5668831df3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index c30a585fe8..43972fafce 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java index 4bad4aa177..7bd0aa8da0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 4928330497..0afe2b1cc7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/resources/golang/templates/SbeMarshallingBigEndian.go b/sbe-tool/src/main/resources/golang/templates/SbeMarshallingBigEndian.go index 29d38a0470..d3f95a7155 100755 --- a/sbe-tool/src/main/resources/golang/templates/SbeMarshallingBigEndian.go +++ b/sbe-tool/src/main/resources/golang/templates/SbeMarshallingBigEndian.go @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/main/resources/golang/templates/SbeMarshallingLittleEndian.go b/sbe-tool/src/main/resources/golang/templates/SbeMarshallingLittleEndian.go index 302f4f3503..b6037343f3 100755 --- a/sbe-tool/src/main/resources/golang/templates/SbeMarshallingLittleEndian.go +++ b/sbe-tool/src/main/resources/golang/templates/SbeMarshallingLittleEndian.go @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/c/BoundsCheckTest.cpp b/sbe-tool/src/test/c/BoundsCheckTest.cpp index d3f72d245b..2a2794f2ab 100644 --- a/sbe-tool/src/test/c/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/c/BoundsCheckTest.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index 47f0aba0db..b803232528 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -5,7 +5,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index 628e27bdee..e21f738567 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/c/GroupWithDataTest.cpp b/sbe-tool/src/test/c/GroupWithDataTest.cpp index 318ecf6cb2..86ca19852f 100644 --- a/sbe-tool/src/test/c/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/c/GroupWithDataTest.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp index cc903b39eb..f72223f86a 100644 --- a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index c3531029e4..04acddf5a1 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -5,7 +5,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index 9090ef46af..d5cda13f4c 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp index efdfb571ad..0cd94abe36 100644 --- a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp index cee06bd6d3..93c7615eb1 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp index 6bbed4e32f..fed1b77956 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp index 204e76d256..09aff16b65 100644 --- a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp index bc12f55612..c26d5417df 100644 --- a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp +++ b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp index 8903cba557..6487ce8ea3 100644 --- a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp +++ b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java index fd3ac84374..317452b7ff 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java index 3838da0651..aacf5ab3e1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java index bcb476fa33..116dbdbda2 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestUtil.java index 3b3ba768ac..f721dcda45 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestUtil.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java index 8f9e76bf36..a0c245ec6f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java index 88ca7b450a..ea2a9921ee 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java index 763bc50552..2317aafbac 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java index 897875158b..ad3b8f9e6a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 1180a460d3..1b01d099eb 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java index 70961cbfa2..207ebb76d2 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java index 673071d9fd..8b4738f814 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index 65714cec13..b2fca44468 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java index 310905b7e6..1b63202d41 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index 979d3a7777..04b32f9e8f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java index 0e5af650fb..0ccf66ee70 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java index e35b95ce90..76a0960a1d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java index fce87ffc94..0395b7002e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index fa86c115e0..149de3dc70 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java index 90b701ba9a..4ef371a1d3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java index f93e8fbd99..d26b71bd34 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java index a491ae2953..0d76fde8a6 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java index 184cfd5f2d..eb03e6ca7f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java index 47c8a800f4..2aa8d89293 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java index 4045103877..3ecd6af946 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java index 4bb42bf9da..7267ce24ab 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java index 8b0462addb..e0a6f90724 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index d29ce3115a..8315020c78 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index 77b4cbd0b6..bd584c0999 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index a9ddd37677..1dfc9d1b6e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java index f14ee49e10..0e38562d5c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java index 0752578711..a37a024458 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java index 0b6bed3511..cb4bc180a5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index 8664450409..54176e1a90 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, From bac1fc8b0ae986846a7edb43d88ac00d9081ffec Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 19 Jul 2019 16:16:07 +0100 Subject: [PATCH 0113/1594] [Java] Upgrade to javadoc-links 3.8.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7a4afce1b5..8822de42b9 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.3' - id "io.freefair.javadoc-links" version "3.7.5" apply false + id "io.freefair.javadoc-links" version "3.8.0" apply false id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } From fe86d06befbaa62453eef4a627f8a07bc9e8c55b Mon Sep 17 00:00:00 2001 From: Dan Shechter Date: Thu, 18 Jul 2019 10:49:20 +0300 Subject: [PATCH 0114/1594] Reorg C# code for 2019 - Unit tests actually pass now - runtest.sh will generate a test file from the java sample and use that for interop tests rather than hardcoding the byte stream - travis builds the project, runs tests and generates a nuget (that goes no-where for now) - nuget generated from .csproj, no more clunky release script or manual .nuspec - samples split into folders --- .gitignore | 10 +- .travis.yml | 15 + ExampleUsingGeneratedStub.sbe | Bin 0 -> 207 bytes build.gradle | 3 + csharp/.nuget/SBE.nuspec | 26 - csharp/.nuget/do-release.sh | 24 - csharp/.nuget/examples/App.config | 6 - csharp/.nuget/examples/CarExample.cs | 274 ----- csharp/.nuget/examples/Program.cs | 29 - .../examples/Properties/AssemblyInfo.cs | 36 - .../.nuget/examples/baseline/BooleanType.cs | 15 - csharp/.nuget/examples/baseline/BoostType.cs | 17 - csharp/.nuget/examples/baseline/Booster.cs | 54 - csharp/.nuget/examples/baseline/Car.cs | 1086 ----------------- csharp/.nuget/examples/baseline/Engine.cs | 180 --- .../examples/baseline/GroupSizeEncoding.cs | 58 - .../.nuget/examples/baseline/MessageHeader.cs | 92 -- .../.nuget/examples/baseline/MetaAttribute.cs | 15 - csharp/.nuget/examples/baseline/Model.cs | 16 - .../examples/baseline/OptionalExtras.cs | 16 - .../examples/baseline/VarStringEncoding.cs | 45 - csharp/.nuget/examples/example-schema.xml | 95 -- csharp/.nuget/examples/packages.config | 4 - csharp/.nuget/examples/sbe-example.sln | 22 - csharp/.nuget/examples/sbe-samples-car.csproj | 89 -- csharp/build.sh | 7 + csharp/csharp.sln | 4 +- csharp/pack.sh | 5 + csharp/runtests.sh | 7 +- csharp/sbe-benchmarks/sbe-benchmarks.csproj | 9 +- .../{.nuget/readme.txt => sbe-dll/README.txt} | 0 csharp/sbe-dll/sbe-dll.csproj | 35 +- csharp/{.nuget => sbe-dll}/sbe-tool.sh | 0 csharp/sbe-generated/sbe-generated.csproj | 7 +- .../CarExample.cs | 0 .../Program.cs | 0 .../sbe-samples-car.csproj | 13 +- .../ExtensionExample.cs | 0 .../sbe-samples-extension.csproj | 14 +- csharp/sbe-samples/app.config | 3 - csharp/sbe-tests/InteropTests.cs | 16 +- csharp/sbe-tests/sbe-tests.csproj | 15 +- 42 files changed, 96 insertions(+), 2266 deletions(-) create mode 100644 ExampleUsingGeneratedStub.sbe delete mode 100644 csharp/.nuget/SBE.nuspec delete mode 100644 csharp/.nuget/do-release.sh delete mode 100644 csharp/.nuget/examples/App.config delete mode 100644 csharp/.nuget/examples/CarExample.cs delete mode 100644 csharp/.nuget/examples/Program.cs delete mode 100644 csharp/.nuget/examples/Properties/AssemblyInfo.cs delete mode 100644 csharp/.nuget/examples/baseline/BooleanType.cs delete mode 100644 csharp/.nuget/examples/baseline/BoostType.cs delete mode 100644 csharp/.nuget/examples/baseline/Booster.cs delete mode 100644 csharp/.nuget/examples/baseline/Car.cs delete mode 100644 csharp/.nuget/examples/baseline/Engine.cs delete mode 100644 csharp/.nuget/examples/baseline/GroupSizeEncoding.cs delete mode 100644 csharp/.nuget/examples/baseline/MessageHeader.cs delete mode 100644 csharp/.nuget/examples/baseline/MetaAttribute.cs delete mode 100644 csharp/.nuget/examples/baseline/Model.cs delete mode 100644 csharp/.nuget/examples/baseline/OptionalExtras.cs delete mode 100644 csharp/.nuget/examples/baseline/VarStringEncoding.cs delete mode 100644 csharp/.nuget/examples/example-schema.xml delete mode 100644 csharp/.nuget/examples/packages.config delete mode 100644 csharp/.nuget/examples/sbe-example.sln delete mode 100644 csharp/.nuget/examples/sbe-samples-car.csproj create mode 100755 csharp/build.sh create mode 100755 csharp/pack.sh rename csharp/{.nuget/readme.txt => sbe-dll/README.txt} (100%) rename csharp/{.nuget => sbe-dll}/sbe-tool.sh (100%) rename csharp/{sbe-samples => sbe-samples-car}/CarExample.cs (100%) rename csharp/{sbe-samples => sbe-samples-car}/Program.cs (100%) rename csharp/{sbe-samples => sbe-samples-car}/sbe-samples-car.csproj (55%) rename csharp/{sbe-samples => sbe-samples-extension}/ExtensionExample.cs (100%) rename csharp/{sbe-samples => sbe-samples-extension}/sbe-samples-extension.csproj (61%) delete mode 100644 csharp/sbe-samples/app.config diff --git a/.gitignore b/.gitignore index 4912d28ade..8c5c1918f9 100644 --- a/.gitignore +++ b/.gitignore @@ -86,16 +86,8 @@ gocode/src/extension2 # csharp csharp/*/bin csharp/*/obj -csharp/.nuget/nuget.exe -csharp/.nuget/sbe-tool*.nupkg -csharp/.nuget/sbe-tool-all.jar -csharp/.nuget/examples/bin -csharp/.nuget/examples/obj -csharp/.nuget/examples/packages -csharp/.nuget/examples/.vs csharp/.vs csharp/TestResults -csharp/packages csharp/sbe-generated/baseline csharp/sbe-generated/baseline-bigendian csharp/sbe-generated/extension @@ -106,6 +98,8 @@ csharp/sbe-generated/issue661 csharp/sbe-generated/since-deprecated csharp/sbe-generated/mktdata/*.cs csharp/sbe-generated/uk_co_real_logic_sbe_benchmarks_fix +csharp/sbe-tests/*.sbe +csharp/nuget/ # rust rust/car_example/.vscode diff --git a/.travis.yml b/.travis.yml index 1d367428fb..0af3e44c2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,20 @@ matrix: os: linux script: ./gradlew --scan + - name: "C#" + language: csharp + jdk: openjdk8 + dotnet: 2.2 + os: linux + mono: latest + global: + - DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true + - DOTNET_CLI_TELEMETRY_OPTOUT=1 + script: + - ./csharp/build.sh + - ./csharp/runtests.sh + - ./csharp/pack.sh + - env: COMPILER=g++-5 language: cpp compiler: gcc @@ -153,6 +167,7 @@ matrix: os: osx script: ./cppbuild/cppbuild + before_cache: - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ diff --git a/ExampleUsingGeneratedStub.sbe b/ExampleUsingGeneratedStub.sbe new file mode 100644 index 0000000000000000000000000000000000000000..0fd6c7e013786ac15e784a2e80cafadcb6121d21 GIT binary patch literal 207 zcmdO8U<5)2hD$6!0toK1GdhC!OhC*G#313sq~w&;G`0)uEQUtL%8Y&|*nm=U46|nP zJ8=W0LyM9U^AwyblXFtdfm|0SJ|O9wpPQ7Kmzn|*_Xdh6IPn5WkIeLp^2ADrFeA{K zc!*&P3=Ix8K=}_2DGbKO&W_0tVPoTBps=y=W1#TaGd7N_AS3egQW80V4Cl - - - sbe-tool - 0.1.12.1-beta-1 - Simple Binary Encoding for .NET - Bill Segall, MarketFactory Inc, Adaptive Consulting - Bill Segall, MarketFactory Inc, Adaptive Consulting - Apache-2.0 - https://github.com/real-logic/simple-binary-encoding - false - This package contains all you need to define SBE messages and generate C# encoders and decoders. See https://github.com/real-logic/simple-binary-encoding for more detailed instructions - - Simple Binary Encoding (SBE) for .NET - C# - Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive Consulting 2013 - SBE Marshaling Low Latency Simple Binary Encoding - - - - - - - - - diff --git a/csharp/.nuget/do-release.sh b/csharp/.nuget/do-release.sh deleted file mode 100644 index 164f4cc926..0000000000 --- a/csharp/.nuget/do-release.sh +++ /dev/null @@ -1,24 +0,0 @@ -#! /usr/bin/env bash - - -# Ideally we'd get this from top level version.txt but this release is -# done outside the release process so we end up doing this by hand. -ROOTDIR=`dirname $0` -VERSIONTXT=`cat $ROOTDIR/../../version.txt` -VERSION=${VERSIONTXT%-SNAPSHOT} # Seems to be what's used - -echo "Version check" -echo "version.txt=$VERSION" -echo "SBE.nuspec=`grep '' SBE.nuspec`" -echo - -# Copy in the jar -cp $ROOTDIR/../../sbe-tool/build/libs/sbe-tool-$VERSIONTXT.jar $ROOTDIR/sbe-tool-all.jar - -# Build the nuget package -NUGET=$ROOTDIR/nuget.exe -if [ ! -f $NUGET ]; then echo nuget.exe not found. Obtain it from https://dist.nuget.org/index.html; exit 1; fi - -$NUGET pack $ROOTDIR/sbe.nuspec - - diff --git a/csharp/.nuget/examples/App.config b/csharp/.nuget/examples/App.config deleted file mode 100644 index 8e15646352..0000000000 --- a/csharp/.nuget/examples/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/csharp/.nuget/examples/CarExample.cs b/csharp/.nuget/examples/CarExample.cs deleted file mode 100644 index be6720b911..0000000000 --- a/csharp/.nuget/examples/CarExample.cs +++ /dev/null @@ -1,274 +0,0 @@ -// Portions Copyright (C) 2017 MarketFactory, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Text; -using Baseline; -using Org.SbeTool.Sbe.Dll; - -class Example -{ - public static void ExampleMain() - { - // This byte array is used for encoding and decoding, this is what you would send on the wire or save to disk - var byteBuffer = new byte[4096]; - // You need to "wrap" the array with a DirectBuffer, this class is used by the generated code to read and write efficiently to the underlying byte array - var directBuffer = new DirectBuffer(byteBuffer); - const short SchemaVersion = 0; - int bufferOffset = 0; - - var MessageHeader = new MessageHeader(); - var Car = new Car(); - - // Before encoding a message we need to create a SBE header which specify what we are going to encode (this will allow the decoder to detect that it's an encoded 'car' object) - // We will probably simplify this part soon, so the header gets applied automatically, but for now it's manual - MessageHeader.Wrap(directBuffer, bufferOffset, Car.SchemaVersion); // position the MessageHeader on the DirectBuffer, at the correct position - MessageHeader.BlockLength = Car.BlockLength; // size that a car takes on the wire - MessageHeader.SchemaId = Car.SchemaId; - MessageHeader.TemplateId = Car.TemplateId; // identifier for the car object (SBE template ID) - MessageHeader.Version = Car.SchemaVersion; // this can be overriden if we want to support different versions of the car object (advanced functionality) - - // Now that we have encoded the header in the byte array we can encode the car object itself - bufferOffset += MessageHeader.Size; - CarExample.Encode(Car, directBuffer, bufferOffset); - - - // Now we have encoded the message is the byte array, we are going to decode it - - // first we decode the header (in a real world scenario you would need the header to decide which SBE decoder you are going to use - bufferOffset = 0; - // position the MessageHeader object at the beginning of the array - MessageHeader.Wrap(directBuffer, bufferOffset, SchemaVersion); - - // Extract info from the header - // In a real app you would use that to lookup the applicable flyweight to decode this type of message based on templateId and version. - int actingBlockLength = MessageHeader.BlockLength; - int actingVersion = MessageHeader.Version; - - bufferOffset += MessageHeader.Size; - // now we decode the message - CarExample.Decode(Car, directBuffer, bufferOffset, actingBlockLength, actingVersion); - - } -} - -namespace Baseline -{ - public static class CarExample - { - private static readonly byte[] VehicleCode; - private static readonly byte[] ManufacturerCode; - private static readonly byte[] Manufacturer; - private static readonly byte[] Model; - private static readonly byte[] ActivationCode; - - - static CarExample() - { - try - { - // convert some sample strings to the correct encoding for this sample - VehicleCode = Encoding.GetEncoding(Car.VehicleCodeCharacterEncoding).GetBytes("abcdef"); - ManufacturerCode = Encoding.GetEncoding(Engine.ManufacturerCodeCharacterEncoding).GetBytes("123"); - Manufacturer = Encoding.GetEncoding(Car.ManufacturerCharacterEncoding).GetBytes("Honda"); - Model = Encoding.GetEncoding(Car.ModelCharacterEncoding).GetBytes("Civic VTi"); - ActivationCode = Encoding.GetEncoding(Car.ActivationCodeCharacterEncoding).GetBytes("abcdef"); - } - catch (Exception ex) - { - throw new Exception("An error occured while reading encodings", ex); - } - } - - - - public static int Encode(Car car, DirectBuffer directBuffer, int bufferOffset) - { - const int srcOffset = 0; - - // we position the car encoder on the direct buffer, at the correct offset (ie. just after the header) - car.WrapForEncode(directBuffer, bufferOffset); - car.SerialNumber = 1234; // we set the different fields, just as normal properties and they get written straight to the underlying byte buffer - car.ModelYear = 2013; - car.Available = BooleanType.T; // enums are directly supported - car.Code = Baseline.Model.A; - car.SetVehicleCode(VehicleCode, srcOffset); // we set a constant string - - for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) - { - car.SetSomeNumbers(i, (uint)i); // this property is defined as a constant length array of integers - } - - car.Extras = OptionalExtras.CruiseControl | OptionalExtras.SportsPack; // bit set (flag enums in C#) are supported - - car.Engine.Capacity = 2000; - car.Engine.NumCylinders = 4; - car.Engine.SetManufacturerCode(ManufacturerCode, srcOffset); - car.Engine.Efficiency = 35; - car.Engine.BoosterEnabled = BooleanType.T; - car.Engine.Booster.BoostType = BoostType.NITROUS; - car.Engine.Booster.HorsePower = 200; - - // we have written all the constant length fields, now we can write the repeatable groups - - var fuelFigures = car.FuelFiguresCount(3); // we specify that we are going to write 3 FueldFigures (the API is not very .NET friendly yet, we will address that) - fuelFigures.Next(); // move to the first element - fuelFigures.Speed = 30; - fuelFigures.Mpg = 35.9f; - - fuelFigures.Next(); // second - fuelFigures.Speed = 55; - fuelFigures.Mpg = 49.0f; - - fuelFigures.Next(); - fuelFigures.Speed = 75; - fuelFigures.Mpg = 40.0f; - - Car.PerformanceFiguresGroup perfFigures = car.PerformanceFiguresCount(2); // demonstrates how to create a nested group - perfFigures.Next(); - perfFigures.OctaneRating = 95; - - Car.PerformanceFiguresGroup.AccelerationGroup acceleration = perfFigures.AccelerationCount(3).Next(); // this group is going to be nested in the first element of the previous group - acceleration.Mph = 30; - acceleration.Seconds = 4.0f; - - acceleration.Next(); - acceleration.Mph = 60; - acceleration.Seconds = 7.5f; - - acceleration.Next(); - acceleration.Mph = 100; - acceleration.Seconds = 12.2f; - - perfFigures.Next(); - perfFigures.OctaneRating = 99; - acceleration = perfFigures.AccelerationCount(3).Next(); - - acceleration.Mph = 30; - acceleration.Seconds = 3.8f; - - acceleration.Next(); - acceleration.Mph = 60; - acceleration.Seconds = 7.1f; - - acceleration.Next(); - acceleration.Mph = 100; - acceleration.Seconds = 11.8f; - - // once we have written all the repeatable groups we can write the variable length properties (you would use that for strings, byte[], etc) - - car.SetManufacturer(Manufacturer, srcOffset, Manufacturer.Length); - car.SetModel(Model, srcOffset, Model.Length); - car.SetActivationCode(ActivationCode, srcOffset, ActivationCode.Length); - - return car.Size; - } - - public static void Decode(Car car, - DirectBuffer directBuffer, - int bufferOffset, - int actingBlockLength, - int actingVersion) - { - var buffer = new byte[128]; - var sb = new StringBuilder(); - - // position the car flyweight just after the header on the DirectBuffer - car.WrapForDecode(directBuffer, bufferOffset, actingBlockLength, actingVersion); - - // decode the car properties on by one, directly from the buffer - sb.Append("\ncar.templateId=").Append(Car.TemplateId); - sb.Append("\ncar.schemaVersion=").Append(Car.SchemaVersion); - sb.Append("\ncar.serialNumber=").Append(car.SerialNumber); - sb.Append("\ncar.modelYear=").Append(car.ModelYear); - sb.Append("\ncar.available=").Append(car.Available); - sb.Append("\ncar.code=").Append(car.Code); - - sb.Append("\ncar.someNumbers="); - for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) - { - sb.Append(car.GetSomeNumbers(i)).Append(", "); - } - - sb.Append("\ncar.vehicleCode="); - var vehicleCode = new byte[Car.VehicleCodeLength]; - car.GetVehicleCode(vehicleCode, 0); - sb.Append(Encoding.GetEncoding(Car.VehicleCodeCharacterEncoding).GetString(vehicleCode, 0, Car.VehicleCodeLength)); - - OptionalExtras extras = car.Extras; - sb.Append("\ncar.extras.cruiseControl=").Append((extras & OptionalExtras.CruiseControl) == OptionalExtras.CruiseControl); // this is how you can find out if a specific flag is set in a flag enum - sb.Append("\ncar.extras.sportsPack=").Append((extras & OptionalExtras.SportsPack) == OptionalExtras.SportsPack); - sb.Append("\ncar.extras.sunRoof=").Append((extras & OptionalExtras.SunRoof) == OptionalExtras.SunRoof); - - Engine engine = car.Engine; - sb.Append("\ncar.engine.capacity=").Append(engine.Capacity); - sb.Append("\ncar.engine.numCylinders=").Append(engine.NumCylinders); - sb.Append("\ncar.engine.maxRpm=").Append(engine.MaxRpm); - sb.Append("\ncar.engine.manufacturerCode="); - for (int i = 0, size = Engine.ManufacturerCodeLength; i < size; i++) - { - sb.Append((char)engine.GetManufacturerCode(i)); - } - - int length = engine.GetFuel(buffer, 0, buffer.Length); - - sb.Append("\ncar.engine.fuel=").Append(Encoding.ASCII.GetString(buffer, 0, length)); // string requires a bit of work to decode - - sb.Append("\ncar.engine.Efficiency=").Append(engine.Efficiency); - sb.Append("\ncar.engine.BoosterEnabled=").Append(engine.BoosterEnabled); - sb.Append("\ncar.engine.Booster.BoostType=").Append(engine.Booster.BoostType); - sb.Append("\ncar.engine.Booster.HorsePower=").Append(engine.Booster.HorsePower); - - // The first way to access a repeating group is by using Next() - var fuelFiguresGroup = car.FuelFigures; - while (fuelFiguresGroup.HasNext) - { - var fuelFigures = fuelFiguresGroup.Next(); - sb.Append("\ncar.fuelFigures.speed=").Append(fuelFigures.Speed); - sb.Append("\ncar.fuelFigures.mpg=").Append(fuelFigures.Mpg); - } - - // The second way to access a repeating group is to use an iterator - foreach (Car.PerformanceFiguresGroup performanceFigures in car.PerformanceFigures) - { - sb.Append("\ncar.performanceFigures.octaneRating=").Append(performanceFigures.OctaneRating); - - // The third way to access a repeating group is loop over the count of elements - var accelerationGroup = performanceFigures.Acceleration; - for (int i = 0; i < accelerationGroup.Count; i++) - { - var acceleration = accelerationGroup.Next(); - sb.Append("\ncar.performanceFigures.acceleration.mph=").Append(acceleration.Mph); - sb.Append("\ncar.performanceFigures.acceleration.seconds=").Append(acceleration.Seconds); - } - } - - // variable length fields - sb.Append("\ncar.manufacturer.semanticType=").Append(Car.ManufacturerMetaAttribute(MetaAttribute.SemanticType)); - length = car.GetManufacturer(buffer, 0, buffer.Length); - sb.Append("\ncar.manufacturer=").Append(Encoding.GetEncoding(Car.ManufacturerCharacterEncoding).GetString(buffer, 0, length)); - - length = car.GetModel(buffer, 0, buffer.Length); - sb.Append("\ncar.model=").Append(Encoding.GetEncoding(Car.ModelCharacterEncoding).GetString(buffer, 0, length)); - - length = car.GetActivationCode(buffer, 0, buffer.Length); - sb.Append("\ncar.activationcode=").Append(Encoding.GetEncoding(Car.ActivationCodeCharacterEncoding).GetString(buffer, 0, length)); - - sb.Append("\ncar.size=").Append(car.Size); - - Console.WriteLine(sb.ToString()); - } - } -} - diff --git a/csharp/.nuget/examples/Program.cs b/csharp/.nuget/examples/Program.cs deleted file mode 100644 index 52811dc550..0000000000 --- a/csharp/.nuget/examples/Program.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Portions Copyright (C) 2017 MarketFactory, Inc -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; - -namespace Baseline -{ - class Program - { - public static void Main() - { - Example.Main(); - - Console.WriteLine("Press a key to continue..."); - Console.ReadKey(); - } - } -} diff --git a/csharp/.nuget/examples/Properties/AssemblyInfo.cs b/csharp/.nuget/examples/Properties/AssemblyInfo.cs deleted file mode 100644 index d7cb4e23e0..0000000000 --- a/csharp/.nuget/examples/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SBE Car Example")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SBE Car Example")] -[assembly: AssemblyCopyright("Copyright © MarketFactory 2017")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("b151297a-ab50-48eb-b50a-fba0cd076b49")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.1.7.0")] -[assembly: AssemblyFileVersion("0.1.7.0")] diff --git a/csharp/.nuget/examples/baseline/BooleanType.cs b/csharp/.nuget/examples/baseline/BooleanType.cs deleted file mode 100644 index 4d561632e1..0000000000 --- a/csharp/.nuget/examples/baseline/BooleanType.cs +++ /dev/null @@ -1,15 +0,0 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ - -#pragma warning disable 1591 // disable warning on missing comments -using System; -using Org.SbeTool.Sbe.Dll; - -namespace Baseline -{ - public enum BooleanType : byte - { - F = 0, - T = 1, - NULL_VALUE = 255 - } -} diff --git a/csharp/.nuget/examples/baseline/BoostType.cs b/csharp/.nuget/examples/baseline/BoostType.cs deleted file mode 100644 index 7c237f71f0..0000000000 --- a/csharp/.nuget/examples/baseline/BoostType.cs +++ /dev/null @@ -1,17 +0,0 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ - -#pragma warning disable 1591 // disable warning on missing comments -using System; -using Org.SbeTool.Sbe.Dll; - -namespace Baseline -{ - public enum BoostType : byte - { - TURBO = 84, - SUPERCHARGER = 83, - NITROUS = 78, - KERS = 75, - NULL_VALUE = 0 - } -} diff --git a/csharp/.nuget/examples/baseline/Booster.cs b/csharp/.nuget/examples/baseline/Booster.cs deleted file mode 100644 index 0efa956195..0000000000 --- a/csharp/.nuget/examples/baseline/Booster.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ - -#pragma warning disable 1591 // disable warning on missing comments -using System; -using Org.SbeTool.Sbe.Dll; - -namespace Baseline -{ - public sealed partial class Booster - { - private DirectBuffer _buffer; - private int _offset; - private int _actingVersion; - - public void Wrap(DirectBuffer buffer, int offset, int actingVersion) - { - _offset = offset; - _actingVersion = actingVersion; - _buffer = buffer; - } - - public const int Size = 2; - - public BoostType BoostType - { - get - { - return (BoostType)_buffer.CharGet(_offset + 0); - } - set - { - _buffer.CharPut(_offset + 0, (byte)value); - } - } - - - public const byte HorsePowerNullValue = (byte)255; - public const byte HorsePowerMinValue = (byte)0; - public const byte HorsePowerMaxValue = (byte)254; - - public byte HorsePower - { - get - { - return _buffer.Uint8Get(_offset + 1); - } - set - { - _buffer.Uint8Put(_offset + 1, value); - } - } - - } -} diff --git a/csharp/.nuget/examples/baseline/Car.cs b/csharp/.nuget/examples/baseline/Car.cs deleted file mode 100644 index 6490bf3bdb..0000000000 --- a/csharp/.nuget/examples/baseline/Car.cs +++ /dev/null @@ -1,1086 +0,0 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ - -#pragma warning disable 1591 // disable warning on missing comments -using System; -using Org.SbeTool.Sbe.Dll; - -namespace Baseline -{ - public sealed partial class Car - { - public const ushort BlockLength = (ushort)49; - public const ushort TemplateId = (ushort)1; - public const ushort SchemaId = (ushort)1; - public const ushort SchemaVersion = (ushort)0; - public const string SemanticType = ""; - - private readonly Car _parentMessage; - private DirectBuffer _buffer; - private int _offset; - private int _limit; - private int _actingBlockLength; - private int _actingVersion; - - public int Offset { get { return _offset; } } - - public Car() - { - _parentMessage = this; - } - - public void WrapForEncode(DirectBuffer buffer, int offset) - { - _buffer = buffer; - _offset = offset; - _actingBlockLength = BlockLength; - _actingVersion = SchemaVersion; - Limit = offset + _actingBlockLength; - } - - public void WrapForDecode(DirectBuffer buffer, int offset, int actingBlockLength, int actingVersion) - { - _buffer = buffer; - _offset = offset; - _actingBlockLength = actingBlockLength; - _actingVersion = actingVersion; - Limit = offset + _actingBlockLength; - } - - public int Size - { - get - { - return _limit - _offset; - } - } - - public int Limit - { - get - { - return _limit; - } - set - { - _buffer.CheckLimit(value); - _limit = value; - } - } - - - public const int SerialNumberId = 1; - public const int SerialNumberSinceVersion = 0; - public const int SerialNumberDeprecated = 0; - public bool SerialNumberInActingVersion() - { - return _actingVersion >= SerialNumberSinceVersion; - } - - public static string SerialNumberMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public const ulong SerialNumberNullValue = 0xffffffffffffffffUL; - public const ulong SerialNumberMinValue = 0x0UL; - public const ulong SerialNumberMaxValue = 0xfffffffffffffffeUL; - - public ulong SerialNumber - { - get - { - return _buffer.Uint64GetLittleEndian(_offset + 0); - } - set - { - _buffer.Uint64PutLittleEndian(_offset + 0, value); - } - } - - - public const int ModelYearId = 2; - public const int ModelYearSinceVersion = 0; - public const int ModelYearDeprecated = 0; - public bool ModelYearInActingVersion() - { - return _actingVersion >= ModelYearSinceVersion; - } - - public static string ModelYearMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public const ushort ModelYearNullValue = (ushort)65535; - public const ushort ModelYearMinValue = (ushort)0; - public const ushort ModelYearMaxValue = (ushort)65534; - - public ushort ModelYear - { - get - { - return _buffer.Uint16GetLittleEndian(_offset + 8); - } - set - { - _buffer.Uint16PutLittleEndian(_offset + 8, value); - } - } - - - public const int AvailableId = 3; - public const int AvailableSinceVersion = 0; - public const int AvailableDeprecated = 0; - public bool AvailableInActingVersion() - { - return _actingVersion >= AvailableSinceVersion; - } - - public static string AvailableMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public BooleanType Available - { - get - { - return (BooleanType)_buffer.Uint8Get(_offset + 10); - } - set - { - _buffer.Uint8Put(_offset + 10, (byte)value); - } - } - - - public const int CodeId = 4; - public const int CodeSinceVersion = 0; - public const int CodeDeprecated = 0; - public bool CodeInActingVersion() - { - return _actingVersion >= CodeSinceVersion; - } - - public static string CodeMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public Model Code - { - get - { - return (Model)_buffer.CharGet(_offset + 11); - } - set - { - _buffer.CharPut(_offset + 11, (byte)value); - } - } - - - public const int SomeNumbersId = 5; - public const int SomeNumbersSinceVersion = 0; - public const int SomeNumbersDeprecated = 0; - public bool SomeNumbersInActingVersion() - { - return _actingVersion >= SomeNumbersSinceVersion; - } - - public static string SomeNumbersMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public const uint SomeNumbersNullValue = 4294967295U; - public const uint SomeNumbersMinValue = 0U; - public const uint SomeNumbersMaxValue = 4294967294U; - - public const int SomeNumbersLength = 5; - - public uint GetSomeNumbers(int index) - { - if (index < 0 || index >= 5) - { - throw new IndexOutOfRangeException("index out of range: index=" + index); - } - - return _buffer.Uint32GetLittleEndian(_offset + 12 + (index * 4)); - } - - public void SetSomeNumbers(int index, uint value) - { - if (index < 0 || index >= 5) - { - throw new IndexOutOfRangeException("index out of range: index=" + index); - } - - _buffer.Uint32PutLittleEndian(_offset + 12 + (index * 4), value); - } - - public const int VehicleCodeId = 6; - public const int VehicleCodeSinceVersion = 0; - public const int VehicleCodeDeprecated = 0; - public bool VehicleCodeInActingVersion() - { - return _actingVersion >= VehicleCodeSinceVersion; - } - - public static string VehicleCodeMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public const byte VehicleCodeNullValue = (byte)0; - public const byte VehicleCodeMinValue = (byte)32; - public const byte VehicleCodeMaxValue = (byte)126; - - public const int VehicleCodeLength = 6; - - public byte GetVehicleCode(int index) - { - if (index < 0 || index >= 6) - { - throw new IndexOutOfRangeException("index out of range: index=" + index); - } - - return _buffer.CharGet(_offset + 32 + (index * 1)); - } - - public void SetVehicleCode(int index, byte value) - { - if (index < 0 || index >= 6) - { - throw new IndexOutOfRangeException("index out of range: index=" + index); - } - - _buffer.CharPut(_offset + 32 + (index * 1), value); - } - - public const string VehicleCodeCharacterEncoding = "ASCII"; - - public int GetVehicleCode(byte[] dst, int dstOffset) - { - const int length = 6; - if (dstOffset < 0 || dstOffset > (dst.Length - length)) - { - throw new IndexOutOfRangeException("dstOffset out of range for copy: offset=" + dstOffset); - } - - _buffer.GetBytes(_offset + 32, dst, dstOffset, length); - return length; - } - - public void SetVehicleCode(byte[] src, int srcOffset) - { - const int length = 6; - if (srcOffset < 0 || srcOffset > src.Length) - { - throw new IndexOutOfRangeException("srcOffset out of range for copy: offset=" + srcOffset); - } - - if (src.Length > length) - { - throw new ArgumentOutOfRangeException($"src.Length={src.Length} is too large."); - } - - _buffer.SetBytes(_offset + 32, src, srcOffset, src.Length - srcOffset); - } - - public const int ExtrasId = 7; - public const int ExtrasSinceVersion = 0; - public const int ExtrasDeprecated = 0; - public bool ExtrasInActingVersion() - { - return _actingVersion >= ExtrasSinceVersion; - } - - public static string ExtrasMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public OptionalExtras Extras - { - get - { - return (OptionalExtras)_buffer.Uint8Get(_offset + 38); - } - set - { - _buffer.Uint8Put(_offset + 38, (byte)value); - } - } - - public const int DiscountedModelId = 8; - public const int DiscountedModelSinceVersion = 0; - public const int DiscountedModelDeprecated = 0; - public bool DiscountedModelInActingVersion() - { - return _actingVersion >= DiscountedModelSinceVersion; - } - - public static string DiscountedModelMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public Model DiscountedModel - { - get - { - return (Model)_buffer.CharGet(_offset + 39); - } - set - { - _buffer.CharPut(_offset + 39, (byte)value); - } - } - - - public const int EngineId = 9; - public const int EngineSinceVersion = 0; - public const int EngineDeprecated = 0; - public bool EngineInActingVersion() - { - return _actingVersion >= EngineSinceVersion; - } - - public static string EngineMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - private readonly Engine _engine = new Engine(); - - public Engine Engine - { - get - { - _engine.Wrap(_buffer, _offset + 39, _actingVersion); - return _engine; - } - } - - private readonly FuelFiguresGroup _fuelFigures = new FuelFiguresGroup(); - - public const long FuelFiguresId = 10; - public const int FuelFiguresSinceVersion = 0; - public const int FuelFiguresDeprecated = 0; - public bool FuelFiguresInActingVersion() - { - return _actingVersion >= FuelFiguresSinceVersion; - } - - public FuelFiguresGroup FuelFigures - { - get - { - _fuelFigures.WrapForDecode(_parentMessage, _buffer, _actingVersion); - return _fuelFigures; - } - } - - public FuelFiguresGroup FuelFiguresCount(int count) - { - _fuelFigures.WrapForEncode(_parentMessage, _buffer, count); - return _fuelFigures; - } - - public sealed partial class FuelFiguresGroup - { - private readonly GroupSizeEncoding _dimensions = new GroupSizeEncoding(); - private Car _parentMessage; - private DirectBuffer _buffer; - private int _blockLength; - private int _actingVersion; - private int _count; - private int _index; - private int _offset; - - public void WrapForDecode(Car parentMessage, DirectBuffer buffer, int actingVersion) - { - _parentMessage = parentMessage; - _buffer = buffer; - _dimensions.Wrap(buffer, parentMessage.Limit, actingVersion); - _blockLength = _dimensions.BlockLength; - _count = _dimensions.NumInGroup; - _actingVersion = actingVersion; - _index = -1; - _parentMessage.Limit = parentMessage.Limit + SbeHeaderSize; - } - - public void WrapForEncode(Car parentMessage, DirectBuffer buffer, int count) - { - _parentMessage = parentMessage; - _buffer = buffer; - _dimensions.Wrap(buffer, parentMessage.Limit, _actingVersion); - _dimensions.BlockLength = (ushort)6; - _dimensions.NumInGroup = (ushort)count; - _index = -1; - _count = count; - _blockLength = 6; - parentMessage.Limit = parentMessage.Limit + SbeHeaderSize; - } - - public const int SbeBlockLength = 6; - public const int SbeHeaderSize = 4; - public int ActingBlockLength { get { return _blockLength; } } - - public int Count { get { return _count; } } - - public bool HasNext { get { return (_index + 1) < _count; } } - - public FuelFiguresGroup Next() - { - if (_index + 1 >= _count) - { - throw new InvalidOperationException(); - } - - _offset = _parentMessage.Limit; - _parentMessage.Limit = _offset + _blockLength; - ++_index; - - return this; - } - - public System.Collections.IEnumerator GetEnumerator() - { - while (this.HasNext) - { - yield return this.Next(); - } - } - - public const int SpeedId = 11; - public const int SpeedSinceVersion = 0; - public const int SpeedDeprecated = 0; - public bool SpeedInActingVersion() - { - return _actingVersion >= SpeedSinceVersion; - } - - public static string SpeedMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public const ushort SpeedNullValue = (ushort)65535; - public const ushort SpeedMinValue = (ushort)0; - public const ushort SpeedMaxValue = (ushort)65534; - - public ushort Speed - { - get - { - return _buffer.Uint16GetLittleEndian(_offset + 0); - } - set - { - _buffer.Uint16PutLittleEndian(_offset + 0, value); - } - } - - - public const int MpgId = 12; - public const int MpgSinceVersion = 0; - public const int MpgDeprecated = 0; - public bool MpgInActingVersion() - { - return _actingVersion >= MpgSinceVersion; - } - - public static string MpgMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public const float MpgNullValue = float.NaN; - public const float MpgMinValue = 1.401298464324817E-45f; - public const float MpgMaxValue = 3.4028234663852886E38f; - - public float Mpg - { - get - { - return _buffer.FloatGetLittleEndian(_offset + 2); - } - set - { - _buffer.FloatPutLittleEndian(_offset + 2, value); - } - } - - - public const int UsageDescriptionId = 200; - public const int UsageDescriptionSinceVersion = 0; - public const int UsageDescriptionDeprecated = 0; - public bool UsageDescriptionInActingVersion() - { - return _actingVersion >= UsageDescriptionSinceVersion; - } - - public const string UsageDescriptionCharacterEncoding = "UTF-8"; - - - public static string UsageDescriptionMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public const int UsageDescriptionHeaderSize = 4; - - public int GetUsageDescription(byte[] dst, int dstOffset, int length) - { - const int sizeOfLengthField = 4; - int limit = _parentMessage.Limit; - _buffer.CheckLimit(limit + sizeOfLengthField); - int dataLength = (int)_buffer.Uint32GetLittleEndian(limit); - int bytesCopied = Math.Min(length, dataLength); - _parentMessage.Limit = limit + sizeOfLengthField + dataLength; - _buffer.GetBytes(limit + sizeOfLengthField, dst, dstOffset, bytesCopied); - - return bytesCopied; - } - - public int SetUsageDescription(byte[] src, int srcOffset, int length) - { - const int sizeOfLengthField = 4; - int limit = _parentMessage.Limit; - _parentMessage.Limit = limit + sizeOfLengthField + length; - _buffer.Uint32PutLittleEndian(limit, (uint)length); - _buffer.SetBytes(limit + sizeOfLengthField, src, srcOffset, length); - - return length; - } - } - - private readonly PerformanceFiguresGroup _performanceFigures = new PerformanceFiguresGroup(); - - public const long PerformanceFiguresId = 13; - public const int PerformanceFiguresSinceVersion = 0; - public const int PerformanceFiguresDeprecated = 0; - public bool PerformanceFiguresInActingVersion() - { - return _actingVersion >= PerformanceFiguresSinceVersion; - } - - public PerformanceFiguresGroup PerformanceFigures - { - get - { - _performanceFigures.WrapForDecode(_parentMessage, _buffer, _actingVersion); - return _performanceFigures; - } - } - - public PerformanceFiguresGroup PerformanceFiguresCount(int count) - { - _performanceFigures.WrapForEncode(_parentMessage, _buffer, count); - return _performanceFigures; - } - - public sealed partial class PerformanceFiguresGroup - { - private readonly GroupSizeEncoding _dimensions = new GroupSizeEncoding(); - private Car _parentMessage; - private DirectBuffer _buffer; - private int _blockLength; - private int _actingVersion; - private int _count; - private int _index; - private int _offset; - - public void WrapForDecode(Car parentMessage, DirectBuffer buffer, int actingVersion) - { - _parentMessage = parentMessage; - _buffer = buffer; - _dimensions.Wrap(buffer, parentMessage.Limit, actingVersion); - _blockLength = _dimensions.BlockLength; - _count = _dimensions.NumInGroup; - _actingVersion = actingVersion; - _index = -1; - _parentMessage.Limit = parentMessage.Limit + SbeHeaderSize; - } - - public void WrapForEncode(Car parentMessage, DirectBuffer buffer, int count) - { - _parentMessage = parentMessage; - _buffer = buffer; - _dimensions.Wrap(buffer, parentMessage.Limit, _actingVersion); - _dimensions.BlockLength = (ushort)1; - _dimensions.NumInGroup = (ushort)count; - _index = -1; - _count = count; - _blockLength = 1; - parentMessage.Limit = parentMessage.Limit + SbeHeaderSize; - } - - public const int SbeBlockLength = 1; - public const int SbeHeaderSize = 4; - public int ActingBlockLength { get { return _blockLength; } } - - public int Count { get { return _count; } } - - public bool HasNext { get { return (_index + 1) < _count; } } - - public PerformanceFiguresGroup Next() - { - if (_index + 1 >= _count) - { - throw new InvalidOperationException(); - } - - _offset = _parentMessage.Limit; - _parentMessage.Limit = _offset + _blockLength; - ++_index; - - return this; - } - - public System.Collections.IEnumerator GetEnumerator() - { - while (this.HasNext) - { - yield return this.Next(); - } - } - - public const int OctaneRatingId = 14; - public const int OctaneRatingSinceVersion = 0; - public const int OctaneRatingDeprecated = 0; - public bool OctaneRatingInActingVersion() - { - return _actingVersion >= OctaneRatingSinceVersion; - } - - public static string OctaneRatingMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public const byte OctaneRatingNullValue = (byte)255; - public const byte OctaneRatingMinValue = (byte)90; - public const byte OctaneRatingMaxValue = (byte)110; - - public byte OctaneRating - { - get - { - return _buffer.Uint8Get(_offset + 0); - } - set - { - _buffer.Uint8Put(_offset + 0, value); - } - } - - - private readonly AccelerationGroup _acceleration = new AccelerationGroup(); - - public const long AccelerationId = 15; - public const int AccelerationSinceVersion = 0; - public const int AccelerationDeprecated = 0; - public bool AccelerationInActingVersion() - { - return _actingVersion >= AccelerationSinceVersion; - } - - public AccelerationGroup Acceleration - { - get - { - _acceleration.WrapForDecode(_parentMessage, _buffer, _actingVersion); - return _acceleration; - } - } - - public AccelerationGroup AccelerationCount(int count) - { - _acceleration.WrapForEncode(_parentMessage, _buffer, count); - return _acceleration; - } - - public sealed partial class AccelerationGroup - { - private readonly GroupSizeEncoding _dimensions = new GroupSizeEncoding(); - private Car _parentMessage; - private DirectBuffer _buffer; - private int _blockLength; - private int _actingVersion; - private int _count; - private int _index; - private int _offset; - - public void WrapForDecode(Car parentMessage, DirectBuffer buffer, int actingVersion) - { - _parentMessage = parentMessage; - _buffer = buffer; - _dimensions.Wrap(buffer, parentMessage.Limit, actingVersion); - _blockLength = _dimensions.BlockLength; - _count = _dimensions.NumInGroup; - _actingVersion = actingVersion; - _index = -1; - _parentMessage.Limit = parentMessage.Limit + SbeHeaderSize; - } - - public void WrapForEncode(Car parentMessage, DirectBuffer buffer, int count) - { - _parentMessage = parentMessage; - _buffer = buffer; - _dimensions.Wrap(buffer, parentMessage.Limit, _actingVersion); - _dimensions.BlockLength = (ushort)6; - _dimensions.NumInGroup = (ushort)count; - _index = -1; - _count = count; - _blockLength = 6; - parentMessage.Limit = parentMessage.Limit + SbeHeaderSize; - } - - public const int SbeBlockLength = 6; - public const int SbeHeaderSize = 4; - public int ActingBlockLength { get { return _blockLength; } } - - public int Count { get { return _count; } } - - public bool HasNext { get { return (_index + 1) < _count; } } - - public AccelerationGroup Next() - { - if (_index + 1 >= _count) - { - throw new InvalidOperationException(); - } - - _offset = _parentMessage.Limit; - _parentMessage.Limit = _offset + _blockLength; - ++_index; - - return this; - } - - public System.Collections.IEnumerator GetEnumerator() - { - while (this.HasNext) - { - yield return this.Next(); - } - } - - public const int MphId = 16; - public const int MphSinceVersion = 0; - public const int MphDeprecated = 0; - public bool MphInActingVersion() - { - return _actingVersion >= MphSinceVersion; - } - - public static string MphMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public const ushort MphNullValue = (ushort)65535; - public const ushort MphMinValue = (ushort)0; - public const ushort MphMaxValue = (ushort)65534; - - public ushort Mph - { - get - { - return _buffer.Uint16GetLittleEndian(_offset + 0); - } - set - { - _buffer.Uint16PutLittleEndian(_offset + 0, value); - } - } - - - public const int SecondsId = 17; - public const int SecondsSinceVersion = 0; - public const int SecondsDeprecated = 0; - public bool SecondsInActingVersion() - { - return _actingVersion >= SecondsSinceVersion; - } - - public static string SecondsMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public const float SecondsNullValue = float.NaN; - public const float SecondsMinValue = 1.401298464324817E-45f; - public const float SecondsMaxValue = 3.4028234663852886E38f; - - public float Seconds - { - get - { - return _buffer.FloatGetLittleEndian(_offset + 2); - } - set - { - _buffer.FloatPutLittleEndian(_offset + 2, value); - } - } - - } - } - - public const int ManufacturerId = 18; - public const int ManufacturerSinceVersion = 0; - public const int ManufacturerDeprecated = 0; - public bool ManufacturerInActingVersion() - { - return _actingVersion >= ManufacturerSinceVersion; - } - - public const string ManufacturerCharacterEncoding = "UTF-8"; - - - public static string ManufacturerMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public const int ManufacturerHeaderSize = 4; - - public int GetManufacturer(byte[] dst, int dstOffset, int length) - { - const int sizeOfLengthField = 4; - int limit = _parentMessage.Limit; - _buffer.CheckLimit(limit + sizeOfLengthField); - int dataLength = (int)_buffer.Uint32GetLittleEndian(limit); - int bytesCopied = Math.Min(length, dataLength); - _parentMessage.Limit = limit + sizeOfLengthField + dataLength; - _buffer.GetBytes(limit + sizeOfLengthField, dst, dstOffset, bytesCopied); - - return bytesCopied; - } - - public int SetManufacturer(byte[] src, int srcOffset, int length) - { - const int sizeOfLengthField = 4; - int limit = _parentMessage.Limit; - _parentMessage.Limit = limit + sizeOfLengthField + length; - _buffer.Uint32PutLittleEndian(limit, (uint)length); - _buffer.SetBytes(limit + sizeOfLengthField, src, srcOffset, length); - - return length; - } - - public const int ModelId = 19; - public const int ModelSinceVersion = 0; - public const int ModelDeprecated = 0; - public bool ModelInActingVersion() - { - return _actingVersion >= ModelSinceVersion; - } - - public const string ModelCharacterEncoding = "UTF-8"; - - - public static string ModelMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public const int ModelHeaderSize = 4; - - public int GetModel(byte[] dst, int dstOffset, int length) - { - const int sizeOfLengthField = 4; - int limit = _parentMessage.Limit; - _buffer.CheckLimit(limit + sizeOfLengthField); - int dataLength = (int)_buffer.Uint32GetLittleEndian(limit); - int bytesCopied = Math.Min(length, dataLength); - _parentMessage.Limit = limit + sizeOfLengthField + dataLength; - _buffer.GetBytes(limit + sizeOfLengthField, dst, dstOffset, bytesCopied); - - return bytesCopied; - } - - public int SetModel(byte[] src, int srcOffset, int length) - { - const int sizeOfLengthField = 4; - int limit = _parentMessage.Limit; - _parentMessage.Limit = limit + sizeOfLengthField + length; - _buffer.Uint32PutLittleEndian(limit, (uint)length); - _buffer.SetBytes(limit + sizeOfLengthField, src, srcOffset, length); - - return length; - } - - public const int ActivationCodeId = 20; - public const int ActivationCodeSinceVersion = 0; - public const int ActivationCodeDeprecated = 0; - public bool ActivationCodeInActingVersion() - { - return _actingVersion >= ActivationCodeSinceVersion; - } - - public const string ActivationCodeCharacterEncoding = "UTF-8"; - - - public static string ActivationCodeMetaAttribute(MetaAttribute metaAttribute) - { - switch (metaAttribute) - { - case MetaAttribute.Epoch: return "unix"; - case MetaAttribute.TimeUnit: return "nanosecond"; - case MetaAttribute.SemanticType: return ""; - } - - return ""; - } - - public const int ActivationCodeHeaderSize = 4; - - public int GetActivationCode(byte[] dst, int dstOffset, int length) - { - const int sizeOfLengthField = 4; - int limit = _parentMessage.Limit; - _buffer.CheckLimit(limit + sizeOfLengthField); - int dataLength = (int)_buffer.Uint32GetLittleEndian(limit); - int bytesCopied = Math.Min(length, dataLength); - _parentMessage.Limit = limit + sizeOfLengthField + dataLength; - _buffer.GetBytes(limit + sizeOfLengthField, dst, dstOffset, bytesCopied); - - return bytesCopied; - } - - public int SetActivationCode(byte[] src, int srcOffset, int length) - { - const int sizeOfLengthField = 4; - int limit = _parentMessage.Limit; - _parentMessage.Limit = limit + sizeOfLengthField + length; - _buffer.Uint32PutLittleEndian(limit, (uint)length); - _buffer.SetBytes(limit + sizeOfLengthField, src, srcOffset, length); - - return length; - } - } -} diff --git a/csharp/.nuget/examples/baseline/Engine.cs b/csharp/.nuget/examples/baseline/Engine.cs deleted file mode 100644 index 3020bfcbf1..0000000000 --- a/csharp/.nuget/examples/baseline/Engine.cs +++ /dev/null @@ -1,180 +0,0 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ - -#pragma warning disable 1591 // disable warning on missing comments -using System; -using Org.SbeTool.Sbe.Dll; - -namespace Baseline -{ - public sealed partial class Engine - { - private DirectBuffer _buffer; - private int _offset; - private int _actingVersion; - - public void Wrap(DirectBuffer buffer, int offset, int actingVersion) - { - _offset = offset; - _actingVersion = actingVersion; - _buffer = buffer; - } - - public const int Size = 10; - - public const ushort CapacityNullValue = (ushort)65535; - public const ushort CapacityMinValue = (ushort)0; - public const ushort CapacityMaxValue = (ushort)65534; - - public ushort Capacity - { - get - { - return _buffer.Uint16GetLittleEndian(_offset + 0); - } - set - { - _buffer.Uint16PutLittleEndian(_offset + 0, value); - } - } - - - public const byte NumCylindersNullValue = (byte)255; - public const byte NumCylindersMinValue = (byte)0; - public const byte NumCylindersMaxValue = (byte)254; - - public byte NumCylinders - { - get - { - return _buffer.Uint8Get(_offset + 2); - } - set - { - _buffer.Uint8Put(_offset + 2, value); - } - } - - - public const ushort MaxRpmNullValue = (ushort)65535; - public const ushort MaxRpmMinValue = (ushort)0; - public const ushort MaxRpmMaxValue = (ushort)65534; - - public ushort MaxRpm { get { return (ushort)9000; } } - - public const byte ManufacturerCodeNullValue = (byte)0; - public const byte ManufacturerCodeMinValue = (byte)32; - public const byte ManufacturerCodeMaxValue = (byte)126; - - public const int ManufacturerCodeLength = 3; - - public byte GetManufacturerCode(int index) - { - if (index < 0 || index >= 3) - { - throw new IndexOutOfRangeException("index out of range: index=" + index); - } - - return _buffer.CharGet(_offset + 3 + (index * 1)); - } - - public void SetManufacturerCode(int index, byte value) - { - if (index < 0 || index >= 3) - { - throw new IndexOutOfRangeException("index out of range: index=" + index); - } - - _buffer.CharPut(_offset + 3 + (index * 1), value); - } - - public const string ManufacturerCodeCharacterEncoding = "US-ASCII"; - - public int GetManufacturerCode(byte[] dst, int dstOffset) - { - const int length = 3; - if (dstOffset < 0 || dstOffset > (dst.Length - length)) - { - throw new IndexOutOfRangeException("dstOffset out of range for copy: offset=" + dstOffset); - } - - _buffer.GetBytes(_offset + 3, dst, dstOffset, length); - return length; - } - - public void SetManufacturerCode(byte[] src, int srcOffset) - { - const int length = 3; - if (srcOffset < 0 || srcOffset > src.Length) - { - throw new IndexOutOfRangeException("srcOffset out of range for copy: offset=" + srcOffset); - } - - if (src.Length > length) - { - throw new ArgumentOutOfRangeException($"src.Length={src.Length} is too large."); - } - - _buffer.SetBytes(_offset + 3, src, srcOffset, src.Length - srcOffset); - } - - public const byte FuelNullValue = (byte)0; - public const byte FuelMinValue = (byte)32; - public const byte FuelMaxValue = (byte)126; - - private static readonly byte[] _FuelValue = { 80, 101, 116, 114, 111, 108 }; - - public const int FuelLength = 6; - public byte Fuel(int index) - { - return _FuelValue[index]; - } - - public int GetFuel(byte[] dst, int offset, int length) - { - int bytesCopied = Math.Min(length, 6); - Array.Copy(_FuelValue, 0, dst, offset, bytesCopied); - return bytesCopied; - } - - public const sbyte EfficiencyNullValue = (sbyte)-128; - public const sbyte EfficiencyMinValue = (sbyte)0; - public const sbyte EfficiencyMaxValue = (sbyte)100; - - public sbyte Efficiency - { - get - { - return _buffer.Int8Get(_offset + 6); - } - set - { - _buffer.Int8Put(_offset + 6, value); - } - } - - - public BooleanType BoosterEnabled - { - get - { - return (BooleanType)_buffer.Uint8Get(_offset + 7); - } - set - { - _buffer.Uint8Put(_offset + 7, (byte)value); - } - } - - - private readonly Booster _booster = new Booster(); - - public Booster Booster - { - get - { - _booster.Wrap(_buffer, _offset + 8, _actingVersion); - return _booster; - } - } - } -} diff --git a/csharp/.nuget/examples/baseline/GroupSizeEncoding.cs b/csharp/.nuget/examples/baseline/GroupSizeEncoding.cs deleted file mode 100644 index fc2ca0d9d7..0000000000 --- a/csharp/.nuget/examples/baseline/GroupSizeEncoding.cs +++ /dev/null @@ -1,58 +0,0 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ - -#pragma warning disable 1591 // disable warning on missing comments -using System; -using Org.SbeTool.Sbe.Dll; - -namespace Baseline -{ - public sealed partial class GroupSizeEncoding - { - private DirectBuffer _buffer; - private int _offset; - private int _actingVersion; - - public void Wrap(DirectBuffer buffer, int offset, int actingVersion) - { - _offset = offset; - _actingVersion = actingVersion; - _buffer = buffer; - } - - public const int Size = 4; - - public const ushort BlockLengthNullValue = (ushort)65535; - public const ushort BlockLengthMinValue = (ushort)0; - public const ushort BlockLengthMaxValue = (ushort)65534; - - public ushort BlockLength - { - get - { - return _buffer.Uint16GetLittleEndian(_offset + 0); - } - set - { - _buffer.Uint16PutLittleEndian(_offset + 0, value); - } - } - - - public const ushort NumInGroupNullValue = (ushort)65535; - public const ushort NumInGroupMinValue = (ushort)0; - public const ushort NumInGroupMaxValue = (ushort)65534; - - public ushort NumInGroup - { - get - { - return _buffer.Uint16GetLittleEndian(_offset + 2); - } - set - { - _buffer.Uint16PutLittleEndian(_offset + 2, value); - } - } - - } -} diff --git a/csharp/.nuget/examples/baseline/MessageHeader.cs b/csharp/.nuget/examples/baseline/MessageHeader.cs deleted file mode 100644 index 4112aa2628..0000000000 --- a/csharp/.nuget/examples/baseline/MessageHeader.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ - -#pragma warning disable 1591 // disable warning on missing comments -using System; -using Org.SbeTool.Sbe.Dll; - -namespace Baseline -{ - public sealed partial class MessageHeader - { - private DirectBuffer _buffer; - private int _offset; - private int _actingVersion; - - public void Wrap(DirectBuffer buffer, int offset, int actingVersion) - { - _offset = offset; - _actingVersion = actingVersion; - _buffer = buffer; - } - - public const int Size = 8; - - public const ushort BlockLengthNullValue = (ushort)65535; - public const ushort BlockLengthMinValue = (ushort)0; - public const ushort BlockLengthMaxValue = (ushort)65534; - - public ushort BlockLength - { - get - { - return _buffer.Uint16GetLittleEndian(_offset + 0); - } - set - { - _buffer.Uint16PutLittleEndian(_offset + 0, value); - } - } - - - public const ushort TemplateIdNullValue = (ushort)65535; - public const ushort TemplateIdMinValue = (ushort)0; - public const ushort TemplateIdMaxValue = (ushort)65534; - - public ushort TemplateId - { - get - { - return _buffer.Uint16GetLittleEndian(_offset + 2); - } - set - { - _buffer.Uint16PutLittleEndian(_offset + 2, value); - } - } - - - public const ushort SchemaIdNullValue = (ushort)65535; - public const ushort SchemaIdMinValue = (ushort)0; - public const ushort SchemaIdMaxValue = (ushort)65534; - - public ushort SchemaId - { - get - { - return _buffer.Uint16GetLittleEndian(_offset + 4); - } - set - { - _buffer.Uint16PutLittleEndian(_offset + 4, value); - } - } - - - public const ushort VersionNullValue = (ushort)65535; - public const ushort VersionMinValue = (ushort)0; - public const ushort VersionMaxValue = (ushort)65534; - - public ushort Version - { - get - { - return _buffer.Uint16GetLittleEndian(_offset + 6); - } - set - { - _buffer.Uint16PutLittleEndian(_offset + 6, value); - } - } - - } -} diff --git a/csharp/.nuget/examples/baseline/MetaAttribute.cs b/csharp/.nuget/examples/baseline/MetaAttribute.cs deleted file mode 100644 index 966705526f..0000000000 --- a/csharp/.nuget/examples/baseline/MetaAttribute.cs +++ /dev/null @@ -1,15 +0,0 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ - -#pragma warning disable 1591 // disable warning on missing comments -using System; -using Org.SbeTool.Sbe.Dll; - -namespace Baseline -{ - public enum MetaAttribute - { - Epoch, - TimeUnit, - SemanticType - } -} diff --git a/csharp/.nuget/examples/baseline/Model.cs b/csharp/.nuget/examples/baseline/Model.cs deleted file mode 100644 index 1bbd43d595..0000000000 --- a/csharp/.nuget/examples/baseline/Model.cs +++ /dev/null @@ -1,16 +0,0 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ - -#pragma warning disable 1591 // disable warning on missing comments -using System; -using Org.SbeTool.Sbe.Dll; - -namespace Baseline -{ - public enum Model : byte - { - A = 65, - B = 66, - C = 67, - NULL_VALUE = 0 - } -} diff --git a/csharp/.nuget/examples/baseline/OptionalExtras.cs b/csharp/.nuget/examples/baseline/OptionalExtras.cs deleted file mode 100644 index b6c8475cb9..0000000000 --- a/csharp/.nuget/examples/baseline/OptionalExtras.cs +++ /dev/null @@ -1,16 +0,0 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ - -#pragma warning disable 1591 // disable warning on missing comments -using System; -using Org.SbeTool.Sbe.Dll; - -namespace Baseline -{ - [Flags] - public enum OptionalExtras : byte - { - SunRoof = 1, - SportsPack = 2, - CruiseControl = 4, - } -} diff --git a/csharp/.nuget/examples/baseline/VarStringEncoding.cs b/csharp/.nuget/examples/baseline/VarStringEncoding.cs deleted file mode 100644 index e10143a59e..0000000000 --- a/csharp/.nuget/examples/baseline/VarStringEncoding.cs +++ /dev/null @@ -1,45 +0,0 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ - -#pragma warning disable 1591 // disable warning on missing comments -using System; -using Org.SbeTool.Sbe.Dll; - -namespace Baseline -{ - public sealed partial class VarStringEncoding - { - private DirectBuffer _buffer; - private int _offset; - private int _actingVersion; - - public void Wrap(DirectBuffer buffer, int offset, int actingVersion) - { - _offset = offset; - _actingVersion = actingVersion; - _buffer = buffer; - } - - public const int Size = -1; - - public const uint LengthNullValue = 4294967295U; - public const uint LengthMinValue = 0U; - public const uint LengthMaxValue = 1073741824U; - - public uint Length - { - get - { - return _buffer.Uint32GetLittleEndian(_offset + 0); - } - set - { - _buffer.Uint32PutLittleEndian(_offset + 0, value); - } - } - - - public const byte VarDataNullValue = (byte)255; - public const byte VarDataMinValue = (byte)0; - public const byte VarDataMaxValue = (byte)254; - } -} diff --git a/csharp/.nuget/examples/example-schema.xml b/csharp/.nuget/examples/example-schema.xml deleted file mode 100644 index c6090866ac..0000000000 --- a/csharp/.nuget/examples/example-schema.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - T - S - N - K - - - - - - - 9000 - - Petrol - - - - - - 0 - 1 - - - A - B - C - - - 0 - 1 - 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/csharp/.nuget/examples/packages.config b/csharp/.nuget/examples/packages.config deleted file mode 100644 index feecc94bd5..0000000000 --- a/csharp/.nuget/examples/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/csharp/.nuget/examples/sbe-example.sln b/csharp/.nuget/examples/sbe-example.sln deleted file mode 100644 index e0c6031487..0000000000 --- a/csharp/.nuget/examples/sbe-example.sln +++ /dev/null @@ -1,22 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26403.7 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sbe-samples-car", "sbe-samples-car.csproj", "{1B325F15-0C54-49F5-A4B9-16088222CC0E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1B325F15-0C54-49F5-A4B9-16088222CC0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1B325F15-0C54-49F5-A4B9-16088222CC0E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1B325F15-0C54-49F5-A4B9-16088222CC0E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1B325F15-0C54-49F5-A4B9-16088222CC0E}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/csharp/.nuget/examples/sbe-samples-car.csproj b/csharp/.nuget/examples/sbe-samples-car.csproj deleted file mode 100644 index db37a6c495..0000000000 --- a/csharp/.nuget/examples/sbe-samples-car.csproj +++ /dev/null @@ -1,89 +0,0 @@ - - - - - Debug - AnyCPU - {1B325F15-0C54-49F5-A4B9-16088222CC0E} - Exe - Properties - Org.SbeTool.Sbe.Example.Car - Org.SbeTool.Sbe.Example.Car - v4.5 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - x86 - false - - - Baseline.Program - - - - packages\sbe-tool.0.1.7-alpha-1\lib\net45\Release\SBE.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/csharp/build.sh b/csharp/build.sh new file mode 100755 index 0000000000..82b872690c --- /dev/null +++ b/csharp/build.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +DIR="$(dirname "${BASH_SOURCE[0]}")" +cd $DIR +(cd ../ && ./gradlew generateCSharpCodecs) +dotnet build -c debug +dotnet build -c release diff --git a/csharp/csharp.sln b/csharp/csharp.sln index 13edbee07c..2567baba19 100644 --- a/csharp/csharp.sln +++ b/csharp/csharp.sln @@ -5,9 +5,9 @@ VisualStudioVersion = 15.0.26430.6 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sbe-dll", "sbe-dll\sbe-dll.csproj", "{CE883FD9-14A5-409C-AEBC-86BEA4E3C502}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sbe-samples-car", "sbe-samples\sbe-samples-car.csproj", "{1B325F15-0C54-49F5-A4B9-16088222CC0E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sbe-samples-car", "sbe-samples-car\sbe-samples-car.csproj", "{1B325F15-0C54-49F5-A4B9-16088222CC0E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sbe-samples-extension", "sbe-samples\sbe-samples-extension.csproj", "{3B325F15-0C54-49F5-A4B9-16088222CC0E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sbe-samples-extension", "sbe-samples-extension\sbe-samples-extension.csproj", "{3B325F15-0C54-49F5-A4B9-16088222CC0E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sbe-benchmarks", "sbe-benchmarks\sbe-benchmarks.csproj", "{B4A22C65-AC09-43A7-B7D6-141A0B9EC0E0}" EndProject diff --git a/csharp/pack.sh b/csharp/pack.sh new file mode 100755 index 0000000000..421cf256fc --- /dev/null +++ b/csharp/pack.sh @@ -0,0 +1,5 @@ +#!/bin/bash +DIR="$(dirname "${BASH_SOURCE[0]}")" +cd $DIR +(cd .. && ./gradlew build) +(cd sbe-dll && dotnet pack -c release -o ../nuget) diff --git a/csharp/runtests.sh b/csharp/runtests.sh index 66e32b2399..4a1d539a50 100755 --- a/csharp/runtests.sh +++ b/csharp/runtests.sh @@ -1,2 +1,5 @@ -MSTEST='/c/Program Files (x86)/Microsoft Visual Studio 14.0/Common7/IDE/MSTest.exe' -"$MSTEST" /testcontainer:sbe-tests/bin/Release/net45/Org.SbeTool.Sbe.UnitTests.dll +#!/bin/bash +DIR="$(dirname "${BASH_SOURCE[0]}")" +cd $DIR +(cd ../; ./gradlew runExampleUsingGeneratedStub -Dsbe.encoding.filename=csharp/sbe-tests/ExampleUsingGeneratedStub.sbe) +(cd sbe-tests && dotnet test) diff --git a/csharp/sbe-benchmarks/sbe-benchmarks.csproj b/csharp/sbe-benchmarks/sbe-benchmarks.csproj index 4205732737..5a7f039f31 100644 --- a/csharp/sbe-benchmarks/sbe-benchmarks.csproj +++ b/csharp/sbe-benchmarks/sbe-benchmarks.csproj @@ -1,16 +1,13 @@  - net45 + net45;netcoreapp2.2 Org.SbeTool.Sbe.Benchmarks Org.SbeTool.Sbe.Benchmarks exe Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. - SBE - Exe - @@ -18,4 +15,8 @@ + + + + diff --git a/csharp/.nuget/readme.txt b/csharp/sbe-dll/README.txt similarity index 100% rename from csharp/.nuget/readme.txt rename to csharp/sbe-dll/README.txt diff --git a/csharp/sbe-dll/sbe-dll.csproj b/csharp/sbe-dll/sbe-dll.csproj index 252b6d9f3f..0adb2d09d6 100644 --- a/csharp/sbe-dll/sbe-dll.csproj +++ b/csharp/sbe-dll/sbe-dll.csproj @@ -6,16 +6,37 @@ Org.SbeTool.Sbe.Dll Org.SbeTool.Sbe.Dll Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. + true + Bill Segall, MarketFactory Inc, Adaptive Consulting + Apache-2.0 + https://github.com/real-logic/simple-binary-encoding + https://github.com/real-logic/simple-binary-encoding + SBE;Marshaling;Low;Latency;Simple;Binary;Encoding + sbe-dll + 0.1.12.1-beta-2 + Simple Binary Encoding for .NET + This package contains all you need to define SBE messages and generate C# encoders and decoders. See https://github.com/real-logic/simple-binary-encoding for more detailed instructions + git - - bin\release\net45\SBE.xml - + + + true + \ + + + + + + true + tools/sbe-tool.sh + + + true + tools/sbe-tool-all.jar + + - - bin\release\netstandard2.0\SBE.xml - - diff --git a/csharp/.nuget/sbe-tool.sh b/csharp/sbe-dll/sbe-tool.sh similarity index 100% rename from csharp/.nuget/sbe-tool.sh rename to csharp/sbe-dll/sbe-tool.sh diff --git a/csharp/sbe-generated/sbe-generated.csproj b/csharp/sbe-generated/sbe-generated.csproj index 0e39871b8b..6b4fc7bdbc 100644 --- a/csharp/sbe-generated/sbe-generated.csproj +++ b/csharp/sbe-generated/sbe-generated.csproj @@ -1,11 +1,10 @@  - net45 + net45;netstandard2.0 Org.SbeTool.Sbe.Generated Org.SbeTool.Sbe.Generated Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. - @@ -13,7 +12,7 @@ - + - + diff --git a/csharp/sbe-samples/CarExample.cs b/csharp/sbe-samples-car/CarExample.cs similarity index 100% rename from csharp/sbe-samples/CarExample.cs rename to csharp/sbe-samples-car/CarExample.cs diff --git a/csharp/sbe-samples/Program.cs b/csharp/sbe-samples-car/Program.cs similarity index 100% rename from csharp/sbe-samples/Program.cs rename to csharp/sbe-samples-car/Program.cs diff --git a/csharp/sbe-samples/sbe-samples-car.csproj b/csharp/sbe-samples-car/sbe-samples-car.csproj similarity index 55% rename from csharp/sbe-samples/sbe-samples-car.csproj rename to csharp/sbe-samples-car/sbe-samples-car.csproj index efef889dea..88cb672179 100644 --- a/csharp/sbe-samples/sbe-samples-car.csproj +++ b/csharp/sbe-samples-car/sbe-samples-car.csproj @@ -1,20 +1,13 @@  - - exe - - - net45 + net45;netcoreapp2.2 exe Org.SbeTool.Sbe.Example.Car Org.SbeTool.Sbe.Example.Car - - - @@ -24,7 +17,7 @@ - + - \ No newline at end of file + diff --git a/csharp/sbe-samples/ExtensionExample.cs b/csharp/sbe-samples-extension/ExtensionExample.cs similarity index 100% rename from csharp/sbe-samples/ExtensionExample.cs rename to csharp/sbe-samples-extension/ExtensionExample.cs diff --git a/csharp/sbe-samples/sbe-samples-extension.csproj b/csharp/sbe-samples-extension/sbe-samples-extension.csproj similarity index 61% rename from csharp/sbe-samples/sbe-samples-extension.csproj rename to csharp/sbe-samples-extension/sbe-samples-extension.csproj index b5aa8705ef..97899b3aa4 100644 --- a/csharp/sbe-samples/sbe-samples-extension.csproj +++ b/csharp/sbe-samples-extension/sbe-samples-extension.csproj @@ -1,24 +1,15 @@  - - exe - - - net45 + net45;netstandard2.0 exe Org.SbeTool.Sbe.Example.Extension Org.SbeTool.Sbe.Example.Extension Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. - - SBE - - - @@ -27,7 +18,8 @@ - + + diff --git a/csharp/sbe-samples/app.config b/csharp/sbe-samples/app.config deleted file mode 100644 index 51278a4563..0000000000 --- a/csharp/sbe-samples/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/csharp/sbe-tests/InteropTests.cs b/csharp/sbe-tests/InteropTests.cs index 8d48dd183b..e03d31c5a6 100644 --- a/csharp/sbe-tests/InteropTests.cs +++ b/csharp/sbe-tests/InteropTests.cs @@ -13,6 +13,7 @@ // limitations under the License. using System; +using System.IO; using Microsoft.VisualStudio.TestTools.UnitTesting; using Org.SbeTool.Sbe.Dll; using Baseline; @@ -25,9 +26,11 @@ namespace Org.SbeTool.Sbe.Tests [TestClass] public unsafe class InteropTests { + public TestContext TestContext { get; set; } + // The byte array is from the java example for interop test made by // running with -Dsbe.encoding.filename and then decoded using od -tu1 - static byte[] _decodeBuffer = { 49, 0, 1, 0, 1, 0, 0, 0, 210, 4, 0, 0, 0, 0, 0, 0, 221, 7, 1, 65, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 97, 98, 99, 100, 101, 102, 6, 208, 7, 4, 49, 50, 51, 35, 1, 78, 200, 6, 0, 3, 0, 30, 0, 154, 153, 15, 66, 11, 0, 0, 0, 85, 114, 98, 97, 110, 32, 67, 121, 99, 108, 101, 55, 0, 0, 0, 68, 66, 14, 0, 0, 0, 67, 111, 109, 98, 105, 110, 101, 100, 32, 67, 121, 99, 108, 101, 75, 0, 0, 0, 32, 66, 13, 0, 0, 0, 72, 105, 103, 104, 119, 97, 121, 32, 67, 121, 99, 108, 101, 1, 0, 2, 0, 95, 6, 0, 3, 0, 30, 0, 0, 0, 128, 64, 60, 0, 0, 0, 240, 64, 100, 0, 51, 51, 67, 65, 99, 6, 0, 3, 0, 30, 0, 51, 51, 115, 64, 60, 0, 51, 51, 227, 64, 100, 0, 205, 204, 60, 65, 5, 0, 0, 0, 72, 111, 110, 100, 97, 9, 0, 0, 0, 67, 105, 118, 105, 99, 32, 86, 84, 105, 6, 0, 0, 0, 97, 98, 99, 100, 101, 102 }; + static byte[] _decodeBuffer; static byte[] _encodeBuffer; static DirectBuffer _directBuffer; @@ -35,7 +38,12 @@ public unsafe class InteropTests static Car Car; [TestInitialize] - public void Setup() { + public void Setup() + { + const string interopFile = "../../../ExampleUsingGeneratedStub.sbe"; + if (!File.Exists(interopFile)) + Assert.Inconclusive($"Could not read interop file: {interopFile}"); + _decodeBuffer = File.ReadAllBytes(interopFile); _encodeBuffer = new byte[_decodeBuffer.Length]; _messageHeader = new MessageHeader(); } @@ -55,7 +63,7 @@ public void InteropDecodeTest() Assert.AreEqual(Model.A, Car.Code); for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) { - Assert.AreEqual(Car.GetSomeNumbers(i), (uint)i); + Assert.AreEqual(Car.GetSomeNumbers(i), (uint)i+1); } var btmp = new byte[6]; @@ -166,7 +174,7 @@ public void InteropEncodeTest() Car.Code = Model.A; for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) { - Car.SetSomeNumbers(i, (uint)i); + Car.SetSomeNumbers(i, (uint)i+1); } Car.SetVehicleCode(System.Text.Encoding.ASCII.GetBytes("abcdef"), 0); Car.Extras = OptionalExtras.CruiseControl | OptionalExtras.SportsPack; diff --git a/csharp/sbe-tests/sbe-tests.csproj b/csharp/sbe-tests/sbe-tests.csproj index caf0e97279..b1e73946dc 100644 --- a/csharp/sbe-tests/sbe-tests.csproj +++ b/csharp/sbe-tests/sbe-tests.csproj @@ -1,20 +1,15 @@  - net45;netcoreapp2.1 + net45;netcoreapp2.2 Org.SbeTool.Sbe.Tests Org.SbeTool.Sbe.UnitTests True Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. - - - issue435.xml - - - since-deprecated-test-schema.xml - + + @@ -29,8 +24,4 @@ - - - - From 04a471a6a045cdbddef3d3f715644c17f9e06110 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 20 Jul 2019 14:52:38 +0100 Subject: [PATCH 0115/1594] [Java] Update minor version. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 029a7711b1..e9172f4ccf 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.12.9-SNAPSHOT +1.13.0-SNAPSHOT From 4d8726d835d9b19a9e3f9694881b8482b71092fa Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 21 Jul 2019 11:52:48 +0100 Subject: [PATCH 0116/1594] Remove binary checked-in in error by PR #699. --- ExampleUsingGeneratedStub.sbe | Bin 207 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 ExampleUsingGeneratedStub.sbe diff --git a/ExampleUsingGeneratedStub.sbe b/ExampleUsingGeneratedStub.sbe deleted file mode 100644 index 0fd6c7e013786ac15e784a2e80cafadcb6121d21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 207 zcmdO8U<5)2hD$6!0toK1GdhC!OhC*G#313sq~w&;G`0)uEQUtL%8Y&|*nm=U46|nP zJ8=W0LyM9U^AwyblXFtdfm|0SJ|O9wpPQ7Kmzn|*_Xdh6IPn5WkIeLp^2ADrFeA{K zc!*&P3=Ix8K=}_2DGbKO&W_0tVPoTBps=y=W1#TaGd7N_AS3egQW80V4Cl Date: Tue, 23 Jul 2019 11:53:22 +0100 Subject: [PATCH 0117/1594] [Java] Disable javadoc-links plugin. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6f9505c9f8..aca9bb6cdf 100644 --- a/build.gradle +++ b/build.gradle @@ -127,7 +127,7 @@ subprojects { apply plugin: 'signing' apply plugin: 'checkstyle' apply plugin: 'eclipse' - apply plugin: 'io.freefair.javadoc-links' + //apply plugin: 'io.freefair.javadoc-links' group = sbeGroup version = sbeVersion From c8e4f3dc615ee529bb6bc561f07b3d62be46ef2f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 24 Jul 2019 08:47:02 +0100 Subject: [PATCH 0118/1594] [Java] Enable javadoc-links plugin now javadoc.io is back. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index aca9bb6cdf..6f9505c9f8 100644 --- a/build.gradle +++ b/build.gradle @@ -127,7 +127,7 @@ subprojects { apply plugin: 'signing' apply plugin: 'checkstyle' apply plugin: 'eclipse' - //apply plugin: 'io.freefair.javadoc-links' + apply plugin: 'io.freefair.javadoc-links' group = sbeGroup version = sbeVersion From ae95907e6dafeedc1d734b471a3fcced0efeded8 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Thu, 25 Jul 2019 09:16:28 +0100 Subject: [PATCH 0119/1594] [Java] Upgrade to javadoc-links 3.8.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6f9505c9f8..037cf8431e 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.3' - id "io.freefair.javadoc-links" version "3.8.0" apply false + id "io.freefair.javadoc-links" version "3.8.1" apply false id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } From e618a87121d6337ec44a967e91b2bd8dd0f076e3 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Thu, 25 Jul 2019 11:20:57 +0100 Subject: [PATCH 0120/1594] [Java] Contributing page. --- CONTRIBUTING.md | 33 +++++++++++++++++++++++++++++++++ README.md | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..31c8c7695a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,33 @@ +# Contributing to SBE + +If you would like to contribute code you can do so through GitHub by sending a pull request or raising an issue with an attached patch. + +When submitting code, please make every effort to follow existing conventions and style in order to keep the code as readable as possible. + +## License + +By contributing your code, you agree to license your contribution under the terms of the APLv2: + +https://github.com/real-logic/simple-binary-encoding/blob/master/LICENSE + +All files are made available under the Apache 2.0 license. + +If you are adding a new file it should have the following header: + +``` +/* + * Copyright 2013-2019 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + ``` \ No newline at end of file diff --git a/README.md b/README.md index 7b090b502b..44f993d414 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ Developers wishing to enhance the CSharp generator should see the [developer doc License (See LICENSE file for full license) ------------------------------------------- -Copyright 2014-2019 Real Logic Limited +Copyright 2013-2019 Real Logic Limited Copyright 2017 MarketFactory Inc Licensed under the Apache License, Version 2.0 (the "License"); From ad0e94d073acd603e6758f5d75cb3ab812d54a7f Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Thu, 25 Jul 2019 11:27:29 +0100 Subject: [PATCH 0121/1594] [C++] Drop clang 4 build from Travis. --- .travis.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0af3e44c2d..174a881997 100644 --- a/.travis.yml +++ b/.travis.yml @@ -96,19 +96,6 @@ matrix: - ubuntu-toolchain-r-test script: ./cppbuild/cppbuild - - env: COMPILER=clang++-4.0 - language: cpp - compiler: clang - os: linux - addons: - apt: - packages: - - clang-4.0 - - libsparsehash-dev - sources: - - llvm-toolchain-xenial-4.0 - script: ./cppbuild/cppbuild - - env: COMPILER=clang++-5.0 language: cpp compiler: clang From 28a0487b4ec94a8582fa815c128500fa925dfe54 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 26 Jul 2019 14:52:39 +0100 Subject: [PATCH 0122/1594] [Java] Upgrade to Mockito 3.0.0. --- build.gradle | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 037cf8431e..386d62fcd6 100644 --- a/build.gradle +++ b/build.gradle @@ -140,13 +140,11 @@ subprojects { compile 'org.agrona:agrona:1.0.3' testCompile 'org.hamcrest:hamcrest:2.1' - testCompile 'org.mockito:mockito-core:2.28.2' + testCompile 'org.mockito:mockito-core:3.0.0' testCompile 'junit:junit:4.12' } - checkstyle { - toolVersion = '8.22' - } + checkstyle.toolVersion = '8.22' compileJava { sourceCompatibility = sbeJavaVersion From e8f2677e41e898543e66c32202dd121fc92892d6 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 29 Jul 2019 07:54:11 +0100 Subject: [PATCH 0123/1594] [Java] Upgrade to Checkstyle 8.23. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 386d62fcd6..a6a6620505 100644 --- a/build.gradle +++ b/build.gradle @@ -135,7 +135,7 @@ subprojects { jar.enabled = true dependencies { - checkstyle 'com.puppycrawl.tools:checkstyle:8.22' + checkstyle 'com.puppycrawl.tools:checkstyle:8.23' compile 'org.agrona:agrona:1.0.3' @@ -144,7 +144,7 @@ subprojects { testCompile 'junit:junit:4.12' } - checkstyle.toolVersion = '8.22' + checkstyle.toolVersion = '8.23' compileJava { sourceCompatibility = sbeJavaVersion From 88091b81b4ab514f5d7b7903133f54d868e4f512 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Mon, 29 Jul 2019 18:53:15 +0100 Subject: [PATCH 0124/1594] [Java] Upgrade to Agrona 1.0.4. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a6a6620505..ba5c864486 100644 --- a/build.gradle +++ b/build.gradle @@ -137,7 +137,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.23' - compile 'org.agrona:agrona:1.0.3' + compile 'org.agrona:agrona:1.0.4' testCompile 'org.hamcrest:hamcrest:2.1' testCompile 'org.mockito:mockito-core:3.0.0' From 76d85e1c44df075fcd7ce599d6c87b6aee52b5f2 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Mon, 29 Jul 2019 21:32:36 +0100 Subject: [PATCH 0125/1594] [Java] Upgrade to Agrona 1.0.5. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ba5c864486..10adab6b1b 100644 --- a/build.gradle +++ b/build.gradle @@ -137,7 +137,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.23' - compile 'org.agrona:agrona:1.0.4' + compile 'org.agrona:agrona:1.0.5' testCompile 'org.hamcrest:hamcrest:2.1' testCompile 'org.mockito:mockito-core:3.0.0' From 311bd6656853c7998b006f5207d0c1e4fbc57840 Mon Sep 17 00:00:00 2001 From: Dan Shechter Date: Tue, 30 Jul 2019 13:05:21 +0300 Subject: [PATCH 0126/1594] Add csharp code-gen time property that allows squashing of namespace folder generation --- csharp/sbe-dll/sbe-dll.csproj | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java | 8 ++++++++ .../generation/csharp/CSharpNamespaceOutputManager.java | 9 ++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/csharp/sbe-dll/sbe-dll.csproj b/csharp/sbe-dll/sbe-dll.csproj index 0adb2d09d6..c695a2b072 100644 --- a/csharp/sbe-dll/sbe-dll.csproj +++ b/csharp/sbe-dll/sbe-dll.csproj @@ -13,7 +13,7 @@ https://github.com/real-logic/simple-binary-encoding SBE;Marshaling;Low;Latency;Simple;Binary;Encoding sbe-dll - 0.1.12.1-beta-2 + 0.1.12.1-beta-3 Simple Binary Encoding for .NET This package contains all you need to define SBE messages and generate C# encoders and decoders. See https://github.com/real-logic/simple-binary-encoding for more detailed instructions git diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index 6a24abadc3..d2c9ef79f6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -66,6 +66,8 @@ *
  • * sbe.java.generate.group-order.annotation: Should the GroupOrder annotation be added to generated stubs. *
  • + *
  • sbe.csharp.generate.namespace.dir: Should a directory be created for the namespace under + * the output directory? Defaults to true
  • *
  • sbe.keyword.append.token: Token to be appended to keywords.
  • *
  • sbe.decode.unknown.enum.values: Support unknown decoded enum values.
  • *
  • sbe.xinclude.aware: Is XInclude supported for the schema. Defaults to false.
  • @@ -163,6 +165,12 @@ public class SbeTool */ public static final String JAVA_GROUP_ORDER_ANNOTATION = "sbe.java.generate.group-order.annotation"; + /** + * Boolean system property to turn on or off generation of namespace directories during csharp code generation. + * Defaults to true + */ + public static final String CSHARP_GENERATE_NAMESPACE_DIR = "sbe.csharp.generate.namespace.dir"; + /** * Specifies token that should be appended to keywords to avoid compilation errors. *

    diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java index 32514eebde..8892f669fa 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java @@ -24,6 +24,7 @@ import java.nio.file.Files; import static java.io.File.separatorChar; +import static uk.co.real_logic.sbe.SbeTool.CSHARP_GENERATE_NAMESPACE_DIR; /** * {@link OutputManager} for managing the creation of C# source files @@ -48,7 +49,13 @@ public CSharpNamespaceOutputManager(final String baseDirName, final String packa Verify.notNull(packageName, "packageName"); final String dirName = baseDirName.endsWith("" + separatorChar) ? baseDirName : baseDirName + separatorChar; - final String packageDirName = dirName + packageName.replace('.', '_'); + + final String packageComponment = + Boolean.parseBoolean(System.getProperty(CSHARP_GENERATE_NAMESPACE_DIR, "true")) ? + packageName.replace('.', '_') : + ""; + + final String packageDirName = dirName + packageComponment; outputDir = new File(packageDirName); if (!outputDir.exists() && !outputDir.mkdirs()) From 3746586ecab3ef26916115f4fe895668c479ae2c Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 30 Jul 2019 11:18:22 +0100 Subject: [PATCH 0127/1594] [Java] Tidy up after merge of PR #702. --- .../csharp/CSharpNamespaceOutputManager.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java index 8892f669fa..6a7b8baef6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java @@ -49,13 +49,9 @@ public CSharpNamespaceOutputManager(final String baseDirName, final String packa Verify.notNull(packageName, "packageName"); final String dirName = baseDirName.endsWith("" + separatorChar) ? baseDirName : baseDirName + separatorChar; - - final String packageComponment = - Boolean.parseBoolean(System.getProperty(CSHARP_GENERATE_NAMESPACE_DIR, "true")) ? - packageName.replace('.', '_') : - ""; - - final String packageDirName = dirName + packageComponment; + final boolean genNamespace = Boolean.parseBoolean(System.getProperty(CSHARP_GENERATE_NAMESPACE_DIR, "true")); + final String packageComponent = genNamespace ? packageName.replace('.', '_') : ""; + final String packageDirName = dirName + packageComponent; outputDir = new File(packageDirName); if (!outputDir.exists() && !outputDir.mkdirs()) From 457e1e74ec2846f9252bf078aa2e6bdfa4f0c920 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 31 Jul 2019 22:53:21 +0100 Subject: [PATCH 0128/1594] [Java] Upgrade to Agrona 1.0.6. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 10adab6b1b..8d10e53618 100644 --- a/build.gradle +++ b/build.gradle @@ -137,7 +137,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.23' - compile 'org.agrona:agrona:1.0.5' + compile 'org.agrona:agrona:1.0.6' testCompile 'org.hamcrest:hamcrest:2.1' testCompile 'org.mockito:mockito-core:3.0.0' From f58f4c5e6800d3cf773e68ebfb1301482e18b32b Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 2 Aug 2019 17:33:44 +0100 Subject: [PATCH 0129/1594] [Java] Version ref in readme. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 44f993d414..d0417c7f4b 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.12.8 +    1.13.0 ``` @@ -65,7 +65,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.12.9-SNAPSHOT.jar my_sbe_input.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.13.1-SNAPSHOT.jar my_sbe_input.xml C++ Build using CMake From 9c6f91448415fbddb379fbbccb7baca858b8ad86 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 2 Aug 2019 09:40:36 -0700 Subject: [PATCH 0130/1594] 1.13.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index e9172f4ccf..feaae22bac 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.13.0-SNAPSHOT +1.13.0 From c05b2fcd6fa1ec1e8eac331c2972512f161f94f8 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 2 Aug 2019 09:42:31 -0700 Subject: [PATCH 0131/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index feaae22bac..b99622a410 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.13.0 +1.13.1-SNAPSHOT From 67b3f3bf425cbc88229f557d0e31854a76cfa616 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sun, 4 Aug 2019 13:46:14 +0100 Subject: [PATCH 0132/1594] [Java] Upgrade to javadoc-links 3.8.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8d10e53618..44d12af7a6 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.3' - id "io.freefair.javadoc-links" version "3.8.1" apply false + id "io.freefair.javadoc-links" version "3.8.2" apply false id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } From 578ac135fa81e825a4f778e384cc2cdb413bec6a Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sun, 4 Aug 2019 14:54:53 +0100 Subject: [PATCH 0133/1594] [Java] Generate package-info.java for codecs. Issue #703. --- build.gradle | 1 - .../resources/example-extension-schema.xml | 2 +- .../src/main/resources/example-schema.xml | 2 +- .../sbe/generation/java/JavaGenerator.java | 24 +++++++++++++++---- .../main/java/uk/co/real_logic/sbe/ir/Ir.java | 16 ++++++++++++- .../uk/co/real_logic/sbe/ir/IrDecoder.java | 3 ++- .../sbe/ir/generated/package-info.java | 5 ++++ .../uk/co/real_logic/sbe/xml/IrGenerator.java | 1 + sbe-tool/src/main/resources/sbe-ir.xml | 2 +- .../sbe/generation/rust/RustTest.java | 2 +- 10 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/package-info.java diff --git a/build.gradle b/build.gradle index 44d12af7a6..b11bcba321 100644 --- a/build.gradle +++ b/build.gradle @@ -409,7 +409,6 @@ project(':sbe-samples') { classpath = sourceSets.main.runtimeClasspath main = 'uk.co.real_logic.sbe.examples.OtfExample' workingDir = 'src/main/resources' - systemProperties System.getProperties() } task runJavaExamples { diff --git a/sbe-samples/src/main/resources/example-extension-schema.xml b/sbe-samples/src/main/resources/example-extension-schema.xml index f3c95b7b65..c9989d8e4a 100644 --- a/sbe-samples/src/main/resources/example-extension-schema.xml +++ b/sbe-samples/src/main/resources/example-extension-schema.xml @@ -5,7 +5,7 @@ id="1" version="1" semanticVersion="5.2" - description="Example schema with extension" + description="Example schema which extends baseline schema." byteOrder="littleEndian"> diff --git a/sbe-samples/src/main/resources/example-schema.xml b/sbe-samples/src/main/resources/example-schema.xml index 820f51bdfe..898ea241e4 100644 --- a/sbe-samples/src/main/resources/example-schema.xml +++ b/sbe-samples/src/main/resources/example-schema.xml @@ -5,7 +5,7 @@ id="1" version="0" semanticVersion="5.2" - description="Example schema" + description="Example base schema which can be extended." byteOrder="littleEndian"> diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index dc455f1223..f8d4e93674 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -46,6 +46,7 @@ enum CodecType } private static final String META_ATTRIBUTE_ENUM = "MetaAttribute"; + private static final String PACKAGE_INFO = "package-info"; private static final String BASE_INDENT = ""; private static final String INDENT = " "; private static final String FLYWEIGHT = "Flyweight"; @@ -165,6 +166,7 @@ public void generateTypeStubs() throws IOException public void generate() throws IOException { + generatePackageInfo(); generateTypeStubs(); generateMessageHeaderStub(); @@ -1652,13 +1654,28 @@ private static CharSequence generateDeclaration( implementsString); } + private void generatePackageInfo() throws IOException + { + try (Writer out = outputManager.createOutput(PACKAGE_INFO)) + { + out.append( + "/* Generated SBE (Simple Binary Encoding) message codecs.*/\n" + + "/**\n" + + " * ").append(ir.description()).append("\n") + .append( + " */\n" + + "package ").append(ir.applicableNamespace()).append(";\n"); + } + } + private void generateMetaAttributeEnum() throws IOException { try (Writer out = outputManager.createOutput(META_ATTRIBUTE_ENUM)) { - out.append(String.format( + out.append( "/* Generated SBE (Simple Binary Encoding) message codec. */\n" + - "package %s;\n\n" + + "package ").append(ir.applicableNamespace()).append(";\n\n") + .append( "/**\n" + " * Meta attribute enum for selecting a particular meta attribute value.\n" + " */\n" + @@ -1680,8 +1697,7 @@ private void generateMetaAttributeEnum() throws IOException " * Field presence indication. Can be optional, required, or constant.\n" + " */\n" + " PRESENCE\n" + - "}\n", - ir.applicableNamespace())); + "}\n"); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java index aef7c71f5b..e1cd5358d1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java @@ -33,6 +33,7 @@ public class Ir private final String namespaceName; private final int id; private final int version; + private final String description; private final String semanticVersion; private final ByteOrder byteOrder; @@ -48,7 +49,8 @@ public class Ir * @param packageName that should be applied to generated code. * @param namespaceName that should be applied to generated code. * @param id identifier for the schema. - * @param version of the schema + * @param version of the schema. + * @param description of the schema. * @param semanticVersion semantic version for mapping to the application domain. * @param byteOrder byte order for all types in the schema. * @param headerTokens representing the message headerStructure. @@ -58,6 +60,7 @@ public Ir( final String namespaceName, final int id, final int version, + final String description, final String semanticVersion, final ByteOrder byteOrder, final List headerTokens) @@ -69,6 +72,7 @@ public Ir( this.namespaceName = namespaceName; this.id = id; this.version = version; + this.description = description; this.semanticVersion = semanticVersion; this.byteOrder = byteOrder; this.headerStructure = new HeaderStructure(new ArrayList<>(headerTokens)); @@ -203,6 +207,16 @@ public int version() return version; } + /** + * Get the description for the schema. + * + * @return the description for the schema. + */ + public String description() + { + return description; + } + /** * Get the semantic version of the schema. * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index 45371de92c..51f4d8ff1d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -121,7 +121,8 @@ public Ir decode() } final ByteOrder byteOrder = tokens.size() > 0 ? tokens.get(0).encoding().byteOrder() : null; - final Ir ir = new Ir(irPackageName, irNamespaceName, irId, irVersion, semanticVersion, byteOrder, irHeader); + final Ir ir = new Ir( + irPackageName, irNamespaceName, irId, irVersion, null, semanticVersion, byteOrder, irHeader); for (int size = tokens.size(); i < size; i++) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/package-info.java new file mode 100644 index 0000000000..f6493c6b2f --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/package-info.java @@ -0,0 +1,5 @@ +/* Generated SBE (Simple Binary Encoding) message codecs.*/ +/** + * SBE IR Serialization Codecs. + */ +package uk.co.real_logic.sbe.ir.generated; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index 37c94c5e33..7091536df6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -50,6 +50,7 @@ public Ir generate(final MessageSchema schema, final String namespace) namespace, schema.id(), schema.version(), + schema.description(), schema.semanticVersion(), schema.byteOrder(), headerTokens); diff --git a/sbe-tool/src/main/resources/sbe-ir.xml b/sbe-tool/src/main/resources/sbe-ir.xml index 4f2776fbd3..4aa581e49c 100644 --- a/sbe-tool/src/main/resources/sbe-ir.xml +++ b/sbe-tool/src/main/resources/sbe-ir.xml @@ -4,7 +4,7 @@ id="1" version="0" byteOrder="littleEndian" - description="SBE IR Serialization"> + description="SBE IR Serialization Codecs."> diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustTest.java index ae524aa811..30a7425dd5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustTest.java @@ -43,7 +43,7 @@ public void happyPathRustGeneratorThatThrowsNoExceptions() throws IOException static Ir minimalDummyIr() { - return new Ir("a", "b", 0, 1, "2", ByteOrder.BIG_ENDIAN, + return new Ir("a", "b", 0, 1, null, "2", ByteOrder.BIG_ENDIAN, Arrays.asList( dummyToken(Signal.ENCODING, HeaderStructure.BLOCK_LENGTH), dummyToken(Signal.ENCODING, HeaderStructure.SCHEMA_ID), From d76eb90121cdef9fdd7f6aa2b6d634addc6c5666 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sun, 4 Aug 2019 16:18:55 +0100 Subject: [PATCH 0134/1594] [Java] Reduce copying when generating codecs. --- .../sbe/generation/java/JavaGenerator.java | 124 ++++++++---------- .../sbe/generation/java/JavaUtil.java | 14 +- 2 files changed, 63 insertions(+), 75 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index f8d4e93674..711ce3430e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -207,13 +207,13 @@ private void generateEncoder( generateAnnotations(indent, className, groups, out, 0, this::encoderName); out.append(generateDeclaration(className, implementsString, msgToken)); out.append(generateEncoderFlyweightCode(className, msgToken)); - out.append(generateEncoderFields(className, fields, indent)); final StringBuilder sb = new StringBuilder(); + generateEncoderFields(sb, className, fields, indent); generateEncoderGroups(sb, className, groups, indent, false); - out.append(sb); + generateEncoderVarData(sb, className, varData, indent); - out.append(generateEncoderVarData(className, varData, indent)); + out.append(sb); out.append(generateEncoderDisplay(formatClassName(decoderName(msgToken.name())), indent)); @@ -238,14 +238,13 @@ private void generateDecoder( generateAnnotations(indent, className, groups, out, 0, this::decoderName); out.append(generateDeclaration(className, implementsString, msgToken)); out.append(generateDecoderFlyweightCode(className, msgToken)); - out.append(generateDecoderFields(fields, indent)); final StringBuilder sb = new StringBuilder(); + generateDecoderFields(sb, fields, indent); generateDecoderGroups(sb, className, groups, indent, false); + generateDecoderVarData(sb, varData, indent); out.append(sb); - out.append(generateDecoderVarData(varData, indent)); - out.append(generateDecoderDisplay(msgToken.name(), fields, groups, varData, indent)); out.append("}\n"); @@ -283,13 +282,13 @@ private void generateDecoderGroups( final List varData = new ArrayList<>(); i = collectVarData(tokens, i, varData); - sb.append(generateGroupDecoderProperty(groupName, groupToken, indent, isSubGroup)); + generateGroupDecoderProperty(sb, groupName, groupToken, indent, isSubGroup); generateAnnotations(indent + INDENT, groupName, tokens, sb, groupIndex + 1, this::decoderName); generateGroupDecoderClassHeader(sb, groupName, outerClassName, tokens, groups, groupIndex, indent + INDENT); - sb.append(generateDecoderFields(fields, indent + INDENT)); + generateDecoderFields(sb, fields, indent + INDENT); generateDecoderGroups(sb, outerClassName, groups, indent + INDENT, true); - sb.append(generateDecoderVarData(varData, indent + INDENT)); + generateDecoderVarData(sb, varData, indent + INDENT); appendGroupInstanceDecoderDisplay(sb, fields, groups, varData, indent + INDENT); @@ -329,13 +328,13 @@ private void generateEncoderGroups( final List varData = new ArrayList<>(); i = collectVarData(tokens, i, varData); - sb.append(generateGroupEncoderProperty(groupName, groupToken, indent, isSubGroup)); + generateGroupEncoderProperty(sb, groupName, groupToken, indent, isSubGroup); generateAnnotations(indent + INDENT, groupClassName, tokens, sb, groupIndex + 1, this::encoderName); generateGroupEncoderClassHeader(sb, groupName, outerClassName, tokens, groups, groupIndex, indent + INDENT); - sb.append(generateEncoderFields(groupClassName, fields, indent + INDENT)); + generateEncoderFields(sb, groupClassName, fields, indent + INDENT); generateEncoderGroups(sb, outerClassName, groups, indent + INDENT, true); - sb.append(generateEncoderVarData(groupClassName, varData, indent + INDENT)); + generateEncoderVarData(sb, groupClassName, varData, indent + INDENT); sb.append(indent).append(" }\n"); } @@ -549,19 +548,18 @@ private void generateGroupDecoderClassDeclaration( { final String className = formatClassName(groupName); + generateTypeJavadoc(sb, indent, groupToken); sb.append(String.format("\n" + - "%1$s" + - indent + "public static class %2$s\n" + - indent + " implements Iterable<%2$s>, java.util.Iterator<%2$s>\n" + + indent + "public static class %1$s\n" + + indent + " implements Iterable<%1$s>, java.util.Iterator<%1$s>\n" + indent + "{\n" + - indent + " public static final int HEADER_SIZE = %3$d;\n" + - indent + " private final %4$s parentMessage;\n" + - indent + " private %5$s buffer;\n" + + indent + " public static final int HEADER_SIZE = %2$d;\n" + + indent + " private final %3$s parentMessage;\n" + + indent + " private %4$s buffer;\n" + indent + " private int count;\n" + indent + " private int index;\n" + indent + " private int offset;\n" + indent + " private int blockLength;\n", - generateTypeJavadoc(indent, groupToken), className, dimensionHeaderSize, parentMessageClassName, @@ -604,17 +602,16 @@ private void generateGroupEncoderClassDeclaration( { final String className = formatClassName(encoderName(groupName)); + generateTypeJavadoc(sb, indent, groupToken); sb.append(String.format("\n" + - "%1$s" + - indent + "public static class %2$s\n" + + indent + "public static class %1$s\n" + indent + "{\n" + - indent + " public static final int HEADER_SIZE = %3$d;\n" + - indent + " private final %4$s parentMessage;\n" + - indent + " private %5$s buffer;\n" + + indent + " public static final int HEADER_SIZE = %2$d;\n" + + indent + " private final %3$s parentMessage;\n" + + indent + " private %4$s buffer;\n" + indent + " private int count;\n" + indent + " private int index;\n" + indent + " private int offset;\n", - generateTypeJavadoc(indent, groupToken), className, dimensionHeaderSize, parentMessageClassName, @@ -646,10 +643,13 @@ private void generateGroupEncoderClassDeclaration( sb.append(indent).append(" }\n\n"); } - private static CharSequence generateGroupDecoderProperty( - final String groupName, final Token token, final String indent, final boolean isSubGroup) + private static void generateGroupDecoderProperty( + final StringBuilder sb, + final String groupName, + final Token token, + final String indent, + final boolean isSubGroup) { - final StringBuilder sb = new StringBuilder(); final String className = formatClassName(groupName); final String propertyName = formatPropertyName(token.name()); @@ -699,14 +699,15 @@ private static CharSequence generateGroupDecoderProperty( className, propertyName, actingVersionGuard)); - - return sb; } - private CharSequence generateGroupEncoderProperty( - final String groupName, final Token token, final String indent, final boolean isSubGroup) + private void generateGroupEncoderProperty( + final StringBuilder sb, + final String groupName, + final Token token, + final String indent, + final boolean isSubGroup) { - final StringBuilder sb = new StringBuilder(); final String className = formatClassName(encoderName(groupName)); final String propertyName = formatPropertyName(groupName); @@ -737,14 +738,11 @@ private CharSequence generateGroupEncoderProperty( generateGroupEncodePropertyJavadoc(indent + INDENT, token, className), className, propertyName)); - - return sb; } - private CharSequence generateDecoderVarData(final List tokens, final String indent) + private void generateDecoderVarData( + final StringBuilder sb, final List tokens, final String indent) { - final StringBuilder sb = new StringBuilder(); - for (int i = 0, size = tokens.size(); i < size;) { final Token token = tokens.get(i); @@ -791,14 +789,11 @@ private CharSequence generateDecoderVarData(final List tokens, final Stri i += token.componentTokenCount(); } - - return sb; } - private CharSequence generateEncoderVarData(final String className, final List tokens, final String indent) + private void generateEncoderVarData( + final StringBuilder sb, final String className, final List tokens, final String indent) { - final StringBuilder sb = new StringBuilder(); - for (int i = 0, size = tokens.size(); i < size;) { final Token token = tokens.get(i); @@ -841,8 +836,6 @@ private CharSequence generateEncoderVarData(final String className, final List tokens) { final Encoding encoding = token.encoding(); final CharSequence constVal = generateLiteral(encoding.primitiveType(), encoding.constValue().toString()); - sb.append(generateTypeJavadoc(INDENT, token)); + generateTypeJavadoc(sb, INDENT, token); sb.append(INDENT).append(token.name()).append('(').append(constVal).append("),\n\n"); } @@ -1644,14 +1637,14 @@ else if (tokens.get(index).signal() == Signal.END_GROUP && --level < 0) private static CharSequence generateDeclaration( final String className, final String implementsString, final Token typeToken) { - return String.format( - "%s" + - "@SuppressWarnings(\"all\")\n" + - "public class %s%s\n" + - "{\n", - generateTypeJavadoc(BASE_INDENT, typeToken), - className, - implementsString); + final StringBuilder sb = new StringBuilder(); + + generateTypeJavadoc(sb, BASE_INDENT, typeToken); + sb.append("@SuppressWarnings(\"all\")\n") + .append("public class ").append(className).append(implementsString).append('\n') + .append("{\n"); + + return sb.toString(); } private void generatePackageInfo() throws IOException @@ -1703,9 +1696,12 @@ private void generateMetaAttributeEnum() throws IOException private static CharSequence generateEnumDeclaration(final String name, final Token typeToken) { - return - generateTypeJavadoc(BASE_INDENT, typeToken) + - "public enum " + name + "\n{\n"; + final StringBuilder sb = new StringBuilder(); + + generateTypeJavadoc(sb, BASE_INDENT, typeToken); + sb.append("public enum ").append(name).append("\n{\n"); + + return sb.toString(); } private CharSequence generatePrimitiveDecoder( @@ -2614,11 +2610,9 @@ private CharSequence generateEncoderFlyweightCode(final String className, final CodecType.ENCODER, className, token, wrapMethod + wrapAndApplyMethod, mutableBuffer); } - private CharSequence generateEncoderFields( - final String containingClassName, final List tokens, final String indent) + private void generateEncoderFields( + final StringBuilder sb, final String containingClassName, final List tokens, final String indent) { - final StringBuilder sb = new StringBuilder(); - Generators.forEachField( tokens, (fieldToken, typeToken) -> @@ -2654,14 +2648,10 @@ private CharSequence generateEncoderFields( break; } }); - - return sb; } - private CharSequence generateDecoderFields(final List tokens, final String indent) + private void generateDecoderFields(final StringBuilder sb, final List tokens, final String indent) { - final StringBuilder sb = new StringBuilder(); - Generators.forEachField( tokens, (fieldToken, typeToken) -> @@ -2696,8 +2686,6 @@ private CharSequence generateDecoderFields(final List tokens, final Strin break; } }); - - return sb; } private static void generateFieldIdMethod(final StringBuilder sb, final Token token, final String indent) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 32e1c2af91..ba3b042545 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -252,22 +252,22 @@ public static String generateLiteral(final PrimitiveType type, final String valu /** * Generate the Javadoc comment header for a type. * + * @param sb to append to. * @param indent level for the comment. * @param typeToken for the type. - * @return a string representation of the Javadoc comment. */ - public static String generateTypeJavadoc(final String indent, final Token typeToken) + public static void generateTypeJavadoc( + final StringBuilder sb, final String indent, final Token typeToken) { final String description = typeToken.description(); if (null == description || description.isEmpty()) { - return ""; + return; } - return - indent + "/**\n" + - indent + " * " + description + '\n' + - indent + " */\n"; + sb.append(indent).append("/**\n") + .append(indent).append(" * ").append(description).append('\n') + .append(indent).append(" */\n"); } /** From bf648c01edb86e77a1d9f1a43785a55f19329bf1 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sun, 4 Aug 2019 16:37:56 +0100 Subject: [PATCH 0135/1594] [Java] Warnings clean up. --- .../sbe/generation/java/JavaGenerator.java | 66 ++++++++----------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 711ce3430e..f2e75e4668 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -185,17 +185,14 @@ public void generate() throws IOException final List varData = new ArrayList<>(); collectVarData(messageBody, i, varData); - generateDecoder(BASE_INDENT, fields, groups, varData, msgToken); - generateEncoder(BASE_INDENT, fields, groups, varData, msgToken); + generateDecoder(fields, groups, varData, msgToken); + generateEncoder(fields, groups, varData, msgToken); } } private void generateEncoder( - final String indent, - final List fields, - final List groups, - final List varData, - final Token msgToken) throws IOException + final List fields, final List groups, final List varData, final Token msgToken) + throws IOException { final String className = formatClassName(encoderName(msgToken.name())); final String implementsString = implementsInterface(MESSAGE_ENCODER_FLYWEIGHT); @@ -204,29 +201,26 @@ private void generateEncoder( { out.append(generateMainHeader(ir.applicableNamespace())); - generateAnnotations(indent, className, groups, out, 0, this::encoderName); + generateAnnotations(BASE_INDENT, className, groups, out, 0, this::encoderName); out.append(generateDeclaration(className, implementsString, msgToken)); out.append(generateEncoderFlyweightCode(className, msgToken)); final StringBuilder sb = new StringBuilder(); - generateEncoderFields(sb, className, fields, indent); - generateEncoderGroups(sb, className, groups, indent, false); - generateEncoderVarData(sb, className, varData, indent); + generateEncoderFields(sb, className, fields, BASE_INDENT); + generateEncoderGroups(sb, className, groups, BASE_INDENT, false); + generateEncoderVarData(sb, className, varData, BASE_INDENT); out.append(sb); - out.append(generateEncoderDisplay(formatClassName(decoderName(msgToken.name())), indent)); + out.append(generateEncoderDisplay(formatClassName(decoderName(msgToken.name())))); out.append("}\n"); } } private void generateDecoder( - final String indent, - final List fields, - final List groups, - final List varData, - final Token msgToken) throws IOException + final List fields, final List groups, final List varData, final Token msgToken) + throws IOException { final String className = formatClassName(decoderName(msgToken.name())); final String implementsString = implementsInterface(MESSAGE_DECODER_FLYWEIGHT); @@ -235,17 +229,17 @@ private void generateDecoder( { out.append(generateMainHeader(ir.applicableNamespace())); - generateAnnotations(indent, className, groups, out, 0, this::decoderName); + generateAnnotations(BASE_INDENT, className, groups, out, 0, this::decoderName); out.append(generateDeclaration(className, implementsString, msgToken)); out.append(generateDecoderFlyweightCode(className, msgToken)); final StringBuilder sb = new StringBuilder(); - generateDecoderFields(sb, fields, indent); - generateDecoderGroups(sb, className, groups, indent, false); - generateDecoderVarData(sb, varData, indent); + generateDecoderFields(sb, fields, BASE_INDENT); + generateDecoderGroups(sb, className, groups, BASE_INDENT, false); + generateDecoderVarData(sb, varData, BASE_INDENT); out.append(sb); - out.append(generateDecoderDisplay(msgToken.name(), fields, groups, varData, indent)); + out.append(generateDecoderDisplay(msgToken.name(), fields, groups, varData)); out.append("}\n"); } @@ -1280,7 +1274,7 @@ private void generateComposite(final List tokens) throws IOException i += encodingToken.componentTokenCount(); } - out.append(generateCompositeDecoderDisplay(tokens, BASE_INDENT)); + out.append(generateCompositeDecoderDisplay(tokens)); out.append("}\n"); } @@ -1326,7 +1320,7 @@ private void generateComposite(final List tokens) throws IOException i += encodingToken.componentTokenCount(); } - out.append(generateCompositeEncoderDisplay(decoderName, BASE_INDENT)); + out.append(generateCompositeEncoderDisplay(decoderName)); out.append("}\n"); } } @@ -3033,11 +3027,7 @@ private String generateStaticChoiceGet(final PrimitiveType type, final String bi switch (type) { case UINT8: - return "0 != (value & (1 << " + bitIndex + "))"; - case UINT16: - return "0 != (value & (1 << " + bitIndex + "))"; - case UINT32: return "0 != (value & (1 << " + bitIndex + "))"; @@ -3104,9 +3094,9 @@ private String generateStaticChoicePut(final PrimitiveType type, final String bi throw new IllegalArgumentException("primitive type not supported: " + type); } - private CharSequence generateEncoderDisplay(final String decoderName, final String baseIndent) + private CharSequence generateEncoderDisplay(final String decoderName) { - final String indent = baseIndent + INDENT; + final String indent = INDENT; final StringBuilder sb = new StringBuilder(); sb.append('\n'); @@ -3123,9 +3113,9 @@ private CharSequence generateEncoderDisplay(final String decoderName, final Stri return sb.toString(); } - private CharSequence generateCompositeEncoderDisplay(final String decoderName, final String baseIndent) + private CharSequence generateCompositeEncoderDisplay(final String decoderName) { - final String indent = baseIndent + INDENT; + final String indent = INDENT; final StringBuilder sb = new StringBuilder(); appendToString(sb, indent); sb.append('\n'); @@ -3140,9 +3130,9 @@ private CharSequence generateCompositeEncoderDisplay(final String decoderName, f return sb.toString(); } - private CharSequence generateCompositeDecoderDisplay(final List tokens, final String baseIndent) + private CharSequence generateCompositeDecoderDisplay(final List tokens) { - final String indent = baseIndent + INDENT; + final String indent = INDENT; final StringBuilder sb = new StringBuilder(); appendToString(sb, indent); @@ -3212,13 +3202,9 @@ private CharSequence generateChoiceDisplay(final List tokens) } private CharSequence generateDecoderDisplay( - final String name, - final List tokens, - final List groups, - final List varData, - final String baseIndent) + final String name, final List tokens, final List groups, final List varData) { - final String indent = baseIndent + INDENT; + final String indent = INDENT; final StringBuilder sb = new StringBuilder(); sb.append('\n'); From d77b7318744309f1b6c688d01486842773417b6c Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Mon, 5 Aug 2019 11:42:29 +0100 Subject: [PATCH 0136/1594] [Java] Further reduction in copying in JavaGenerator. --- .../src/main/resources/common-types.xml | 10 +-- .../resources/example-extension-schema.xml | 6 +- .../src/main/resources/example-schema.xml | 6 +- .../sbe/generation/java/JavaGenerator.java | 88 ++++++++++--------- .../sbe/generation/java/JavaUtil.java | 77 ++++++++-------- .../co/real_logic/sbe/ir/GenerationUtil.java | 13 --- 6 files changed, 94 insertions(+), 106 deletions(-) diff --git a/sbe-samples/src/main/resources/common-types.xml b/sbe-samples/src/main/resources/common-types.xml index 11fc391880..fe94289a51 100644 --- a/sbe-samples/src/main/resources/common-types.xml +++ b/sbe-samples/src/main/resources/common-types.xml @@ -1,24 +1,24 @@ - + - + - + - + - + diff --git a/sbe-samples/src/main/resources/example-extension-schema.xml b/sbe-samples/src/main/resources/example-extension-schema.xml index c9989d8e4a..3255bb6fd4 100644 --- a/sbe-samples/src/main/resources/example-extension-schema.xml +++ b/sbe-samples/src/main/resources/example-extension-schema.xml @@ -33,9 +33,9 @@ - - 0 - 1 + + 0 + 1 A diff --git a/sbe-samples/src/main/resources/example-schema.xml b/sbe-samples/src/main/resources/example-schema.xml index 898ea241e4..c251dbe55c 100644 --- a/sbe-samples/src/main/resources/example-schema.xml +++ b/sbe-samples/src/main/resources/example-schema.xml @@ -33,9 +33,9 @@ - - 0 - 1 + + 0 + 1 A diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index f2e75e4668..4edf5fda32 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -681,15 +681,14 @@ private static void generateGroupDecoderProperty( indent + " return " + propertyName + ";\n" + indent + " }\n\n"; + generateFlyweightPropertyJavadoc(sb, indent + INDENT, token, className); sb.append(String.format("\n" + - "%1$s" + - indent + " public %2$s %3$s()\n" + + indent + " public %1$s %2$s()\n" + indent + " {\n" + - "%4$s" + - indent + " %3$s.wrap(buffer);\n" + - indent + " return %3$s;\n" + + "%3$s" + + indent + " %2$s.wrap(buffer);\n" + + indent + " return %2$s;\n" + indent + " }\n", - generateFlyweightPropertyJavadoc(indent + INDENT, token, className), className, propertyName, actingVersionGuard)); @@ -722,14 +721,13 @@ private void generateGroupEncoderProperty( formatPropertyName(groupName), token.id())); + generateGroupEncodePropertyJavadoc(sb, indent + INDENT, token, className); sb.append(String.format("\n" + - "%1$s" + - indent + " public %2$s %3$sCount(final int count)\n" + + indent + " public %1$s %2$sCount(final int count)\n" + indent + " {\n" + - indent + " %3$s.wrap(buffer, count);\n" + - indent + " return %3$s;\n" + + indent + " %2$s.wrap(buffer, count);\n" + + indent + " return %2$s;\n" + indent + " }\n", - generateGroupEncodePropertyJavadoc(indent + INDENT, token, className), className, propertyName)); } @@ -1347,10 +1345,11 @@ private CharSequence generateChoiceClear(final String bitSetClassName, final Tok private CharSequence generateChoiceDecoders(final List tokens) { - return concatTokens( - tokens, - Signal.CHOICE, - (token) -> + final StringBuilder sb = new StringBuilder(); + + for (final Token token : tokens) + { + if (token.signal() == Signal.CHOICE) { final String choiceName = formatPropertyName(token.name()); final Encoding encoding = token.encoding(); @@ -1359,30 +1358,33 @@ private CharSequence generateChoiceDecoders(final List tokens) final PrimitiveType primitiveType = encoding.primitiveType(); final String argType = bitsetArgType(primitiveType); - return String.format("\n" + - "%1$s" + - " public boolean %2$s()\n" + + generateOptionDecodeJavadoc(sb, INDENT, token); + sb.append(String.format("\n" + + " public boolean %1$s()\n" + " {\n" + - " return %3$s;\n" + + " return %2$s;\n" + " }\n\n" + - " public static boolean %2$s(final %4$s value)\n" + + " public static boolean %1$s(final %3$s value)\n" + " {\n" + - " return %5$s;\n" + + " return %4$s;\n" + " }\n", - generateOptionDecodeJavadoc(INDENT, token), choiceName, generateChoiceGet(primitiveType, choiceBitIndex, byteOrderStr), argType, - generateStaticChoiceGet(primitiveType, choiceBitIndex)); - }); + generateStaticChoiceGet(primitiveType, choiceBitIndex))); + } + } + + return sb; } private CharSequence generateChoiceEncoders(final String bitSetClassName, final List tokens) { - return concatTokens( - tokens, - Signal.CHOICE, - (token) -> + final StringBuilder sb = new StringBuilder(); + + for (final Token token : tokens) + { + if (token.signal() == Signal.CHOICE) { final String choiceName = formatPropertyName(token.name()); final Encoding encoding = token.encoding(); @@ -1391,24 +1393,26 @@ private CharSequence generateChoiceEncoders(final String bitSetClassName, final final PrimitiveType primitiveType = encoding.primitiveType(); final String argType = bitsetArgType(primitiveType); - return String.format("\n" + - "%1$s" + - " public %2$s %3$s(final boolean value)\n" + + generateOptionEncodeJavadoc(sb, INDENT, token); + sb.append(String.format("\n" + + " public %1$s %2$s(final boolean value)\n" + " {\n" + - "%4$s\n" + + "%3$s\n" + " return this;\n" + " }\n\n" + - " public static %5$s %3$s(final %5$s bits, final boolean value)\n" + + " public static %4$s %2$s(final %4$s bits, final boolean value)\n" + " {\n" + - "%6$s" + + "%5$s" + " }\n", - generateOptionEncodeJavadoc(INDENT, token), bitSetClassName, choiceName, generateChoicePut(encoding.primitiveType(), choiceBitIndex, byteOrderStr), argType, - generateStaticChoicePut(encoding.primitiveType(), choiceBitIndex)); - }); + generateStaticChoicePut(encoding.primitiveType(), choiceBitIndex))); + } + } + + return sb; } private String bitsetArgType(final PrimitiveType primitiveType) @@ -1638,7 +1642,7 @@ private static CharSequence generateDeclaration( .append("public class ").append(className).append(implementsString).append('\n') .append("{\n"); - return sb.toString(); + return sb; } private void generatePackageInfo() throws IOException @@ -1695,7 +1699,7 @@ private static CharSequence generateEnumDeclaration(final String name, final Tok generateTypeJavadoc(sb, BASE_INDENT, typeToken); sb.append("public enum ").append(name).append("\n{\n"); - return sb.toString(); + return sb; } private CharSequence generatePrimitiveDecoder( @@ -2843,15 +2847,14 @@ private CharSequence generateBitSetProperty( propertyName, bitSetName)); + generateFlyweightPropertyJavadoc(sb, indent + INDENT, propertyToken, bitSetName); sb.append(String.format("\n" + - "%s" + indent + " public %s %s()\n" + indent + " {\n" + "%s" + indent + " %s.wrap(buffer, offset + %d);\n" + indent + " return %s;\n" + indent + " }\n", - generateFlyweightPropertyJavadoc(indent + INDENT, propertyToken, bitSetName), bitSetName, propertyName, generatePropertyNotPresentCondition(inComposite, codecType, propertyToken, null, indent), @@ -2879,15 +2882,14 @@ private CharSequence generateCompositeProperty( propertyName, compositeName)); + generateFlyweightPropertyJavadoc(sb, indent + INDENT, propertyToken, compositeName); sb.append(String.format("\n" + - "%s" + indent + " public %s %s()\n" + indent + " {\n" + "%s" + indent + " %s.wrap(buffer, offset + %d);\n" + indent + " return %s;\n" + indent + " }\n", - generateFlyweightPropertyJavadoc(indent + INDENT, propertyToken, compositeName), compositeName, propertyName, generatePropertyNotPresentCondition(inComposite, codecType, propertyToken, null, indent), diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index ba3b042545..33e118d88f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -273,97 +273,96 @@ public static void generateTypeJavadoc( /** * Generate the Javadoc comment header for a bitset choice option decode method. * + * @param sb to append to. * @param indent level for the comment. * @param optionToken for the type. - * @return a string representation of the Javadoc comment. */ - public static String generateOptionDecodeJavadoc(final String indent, final Token optionToken) + public static void generateOptionDecodeJavadoc( + final StringBuilder sb, final String indent, final Token optionToken) { final String description = optionToken.description(); if (null == description || description.isEmpty()) { - return ""; + return; } - return - indent + "/**\n" + - indent + " * " + description + '\n' + - indent + " *\n" + - indent + " * @return true if " + optionToken.name() + " is set or false if not\n" + - indent + " */\n"; + sb.append(indent).append("/**\n") + .append(indent).append(" * ").append(description).append('\n') + .append(indent).append(" *\n") + .append(indent).append(" * @return true if ").append(optionToken.name()).append(" is set or false if not\n") + .append(indent).append(" */\n"); } /** * Generate the Javadoc comment header for a bitset choice option encode method. * + * @param sb to append to. * @param indent level for the comment. * @param optionToken for the type. - * @return a string representation of the Javadoc comment. */ - public static String generateOptionEncodeJavadoc(final String indent, final Token optionToken) + public static void generateOptionEncodeJavadoc( + final StringBuilder sb, final String indent, final Token optionToken) { final String description = optionToken.description(); if (null == description || description.isEmpty()) { - return ""; + return; } - return - indent + "/**\n" + - indent + " * " + description + '\n' + - indent + " *\n" + - indent + " * @param value true if " + optionToken.name() + " is set or false if not\n" + - indent + " */\n"; + final String name = optionToken.name(); + sb.append(indent).append("/**\n") + .append(indent).append(" * ").append(description).append('\n') + .append(indent).append(" *\n") + .append(indent).append(" * @param value true if ").append(name).append(" is set or false if not.\n") + .append(indent).append(" */\n"); } /** * Generate the Javadoc comment header for flyweight property. * + * @param sb to append to. * @param indent level for the comment. * @param propertyToken for the property name. * @param typeName for the property type. - * @return a string representation of the Javadoc comment. */ - public static String generateFlyweightPropertyJavadoc( - final String indent, final Token propertyToken, final String typeName) + public static void generateFlyweightPropertyJavadoc( + final StringBuilder sb, final String indent, final Token propertyToken, final String typeName) { final String description = propertyToken.description(); if (null == description || description.isEmpty()) { - return ""; + return; } - return - indent + "/**\n" + - indent + " * " + description + '\n' + - indent + " *\n" + - indent + " * @return " + typeName + " : " + description + "\n" + - indent + " */\n"; + sb.append(indent).append("/**\n") + .append(indent).append(" * ").append(description).append('\n') + .append(indent).append(" *\n") + .append(indent).append(" * @return ").append(typeName).append(" : ").append(description).append("\n") + .append(indent).append(" */\n"); } /** * Generate the Javadoc comment header for group encode property. * + * @param sb to append to. * @param indent level for the comment. * @param propertyToken for the property name. * @param typeName for the property type. - * @return a string representation of the Javadoc comment. */ - public static String generateGroupEncodePropertyJavadoc( - final String indent, final Token propertyToken, final String typeName) + public static void generateGroupEncodePropertyJavadoc( + final StringBuilder sb, final String indent, final Token propertyToken, final String typeName) { final String description = propertyToken.description(); if (null == description || description.isEmpty()) { - return ""; + return; } - return - indent + "/**\n" + - indent + " * " + description + "\n" + - indent + " *\n" + - indent + " * @param count of times the group will be encoded\n" + - indent + " * @return " + typeName + " : encoder for the group\n" + - indent + " */\n"; + sb.append(indent).append("/**\n") + .append(indent).append(" * ").append(description).append("\n") + .append(indent).append(" *\n") + .append(indent).append(" * @param count of times the group will be encoded\n") + .append(indent).append(" * @return ").append(typeName).append(" : encoder for the group\n") + .append(indent).append(" */\n"); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java index 881660b8a7..92cdf7fa2b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java @@ -17,9 +17,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.function.Function; - -import static java.util.stream.Collectors.joining; /** * Common code generation utility functions to be used by the different language specific backends. @@ -68,16 +65,6 @@ public static List getMessageBody(final List tokens) return tokens.subList(1, tokens.size() - 1); } - public static CharSequence concatTokens( - final List tokens, final Signal signal, final Function mapper) - { - return tokens - .stream() - .filter((token) -> token.signal() == signal) - .map(mapper) - .collect(joining()); - } - public static int findEndSignal( final List tokens, final int startIndex, final Signal signal, final String name) { From 6edbc4d147668982d89c2871feccc440bf16c829 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 6 Aug 2019 10:50:55 +0100 Subject: [PATCH 0137/1594] [Java] Further reduction in copying and allocation for JavaGenerator. --- .../sbe/generation/java/JavaGenerator.java | 320 +++++++++--------- .../sbe/generation/java/JavaUtil.java | 17 +- 2 files changed, 165 insertions(+), 172 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 4edf5fda32..7357f728ce 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -27,6 +27,7 @@ import java.io.IOException; import java.io.Writer; import java.util.ArrayList; +import java.util.Formatter; import java.util.List; import java.util.function.Function; @@ -210,10 +211,9 @@ private void generateEncoder( generateEncoderGroups(sb, className, groups, BASE_INDENT, false); generateEncoderVarData(sb, className, varData, BASE_INDENT); - out.append(sb); - - out.append(generateEncoderDisplay(formatClassName(decoderName(msgToken.name())))); + generateEncoderDisplay(sb, formatClassName(decoderName(msgToken.name()))); + out.append(sb); out.append("}\n"); } } @@ -237,10 +237,10 @@ private void generateDecoder( generateDecoderFields(sb, fields, BASE_INDENT); generateDecoderGroups(sb, className, groups, BASE_INDENT, false); generateDecoderVarData(sb, varData, BASE_INDENT); - out.append(sb); - out.append(generateDecoderDisplay(msgToken.name(), fields, groups, varData)); + generateDecoderDisplay(sb, msgToken.name(), fields, groups, varData); + out.append(sb); out.append("}\n"); } } @@ -368,7 +368,7 @@ private void generateGroupDecoderClassHeader( indent, dimensionHeaderLen); - sb.append(String.format( + new Formatter(sb).format("\n" + indent + " public void wrap(final %s buffer)\n" + indent + " {\n" + indent + " if (buffer != this.buffer)\n" + @@ -383,7 +383,7 @@ private void generateGroupDecoderClassHeader( indent + " }\n\n", readOnlyBuffer, blockLengthGet, - numInGroupGet)); + numInGroupGet); final int blockLength = tokens.get(index).encodedLength(); @@ -392,14 +392,14 @@ private void generateGroupDecoderClassHeader( .append(indent).append(" return HEADER_SIZE;\n") .append(indent).append(" }\n"); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public static int sbeBlockLength()\n" + indent + " {\n" + indent + " return %d;\n" + indent + " }\n", - blockLength)); + blockLength); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public int actingBlockLength()\n" + indent + " {\n" + indent + " return blockLength;\n" + @@ -420,9 +420,9 @@ private void generateGroupDecoderClassHeader( indent + " {\n" + indent + " return (index + 1) < count;\n" + indent + " }\n", - formatClassName(groupName))); + formatClassName(groupName)); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public %s next()\n" + indent + " {\n" + indent + " if (index + 1 >= count)\n" + @@ -434,7 +434,7 @@ private void generateGroupDecoderClassHeader( indent + " ++index;\n\n" + indent + " return this;\n" + indent + " }\n", - formatClassName(groupName))); + formatClassName(groupName)); } private void generateGroupEncoderClassHeader( @@ -474,7 +474,7 @@ private void generateGroupEncoderClassHeader( final String numInGroupPut = generatePut( numInGroupType, numInGroupOffset, numInGroupValue, byteOrderString(numInGroupToken.encoding())); - sb.append(String.format( + new Formatter(sb).format("\n" + ind + " public void wrap(final %2$s buffer, final int count)\n" + ind + " {\n" + ind + " if (count < %3$d || count > %4$d)\n" + @@ -497,21 +497,21 @@ private void generateGroupEncoderClassHeader( numInGroupToken.encoding().applicableMinValue().longValue(), numInGroupToken.encoding().applicableMaxValue().longValue(), blockLengthPut, - numInGroupPut)); + numInGroupPut); sb.append(ind).append(" public static int sbeHeaderSize()\n") .append(ind).append(" {\n") .append(ind).append(" return HEADER_SIZE;\n") .append(ind).append(" }\n"); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + ind + " public static int sbeBlockLength()\n" + ind + " {\n" + ind + " return %d;\n" + ind + " }\n", - blockLength)); + blockLength); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + ind + " public %s next()\n" + ind + " {\n" + ind + " if (index + 1 >= count)\n" + @@ -523,7 +523,7 @@ private void generateGroupEncoderClassHeader( ind + " ++index;\n\n" + ind + " return this;\n" + ind + " }\n", - formatClassName(encoderName(groupName)))); + formatClassName(encoderName(groupName))); } private static String primitiveTypeName(final Token token) @@ -543,7 +543,7 @@ private void generateGroupDecoderClassDeclaration( final String className = formatClassName(groupName); generateTypeJavadoc(sb, indent, groupToken); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + "public static class %1$s\n" + indent + " implements Iterable<%1$s>, java.util.Iterator<%1$s>\n" + indent + "{\n" + @@ -557,7 +557,7 @@ private void generateGroupDecoderClassDeclaration( className, dimensionHeaderSize, parentMessageClassName, - readOnlyBuffer)); + readOnlyBuffer); for (final String subGroupName : subGroupNames) { @@ -597,7 +597,7 @@ private void generateGroupEncoderClassDeclaration( final String className = formatClassName(encoderName(groupName)); generateTypeJavadoc(sb, indent, groupToken); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + "public static class %1$s\n" + indent + "{\n" + indent + " public static final int HEADER_SIZE = %2$d;\n" + @@ -609,7 +609,7 @@ private void generateGroupEncoderClassDeclaration( className, dimensionHeaderSize, parentMessageClassName, - mutableBuffer)); + mutableBuffer); for (final String subGroupName : subGroupNames) { @@ -649,28 +649,28 @@ private static void generateGroupDecoderProperty( if (!isSubGroup) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " private final %s %s = new %s(this);\n", className, propertyName, - className)); + className); } - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public static long %sId()\n" + indent + " {\n" + indent + " return %d;\n" + indent + " }\n", formatPropertyName(groupName), - token.id())); + token.id()); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public static int %sSinceVersion()\n" + indent + " {\n" + indent + " return %d;\n" + indent + " }\n", formatPropertyName(groupName), - token.version())); + token.version()); final String actingVersionGuard = token.version() == 0 ? "" : @@ -682,7 +682,7 @@ private static void generateGroupDecoderProperty( indent + " }\n\n"; generateFlyweightPropertyJavadoc(sb, indent + INDENT, token, className); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public %1$s %2$s()\n" + indent + " {\n" + "%3$s" + @@ -691,7 +691,7 @@ private static void generateGroupDecoderProperty( indent + " }\n", className, propertyName, - actingVersionGuard)); + actingVersionGuard); } private void generateGroupEncoderProperty( @@ -706,30 +706,30 @@ private void generateGroupEncoderProperty( if (!isSubGroup) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " private final %s %s = new %s(this);\n", className, propertyName, - className)); + className); } - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public static long %sId()\n" + indent + " {\n" + indent + " return %d;\n" + indent + " }\n", formatPropertyName(groupName), - token.id())); + token.id()); generateGroupEncodePropertyJavadoc(sb, indent + INDENT, token, className); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public %1$s %2$sCount(final int count)\n" + indent + " {\n" + indent + " %2$s.wrap(buffer, count);\n" + indent + " return %2$s;\n" + indent + " }\n", className, - propertyName)); + propertyName); } private void generateDecoderVarData( @@ -757,15 +757,15 @@ private void generateDecoderVarData( final PrimitiveType lengthType = lengthEncoding.primitiveType(); final String byteOrderStr = byteOrderString(lengthEncoding); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public static int %sHeaderLength()\n" + indent + " {\n" + indent + " return %d;\n" + indent + " }\n", Generators.toLowerFirstChar(propertyName), - sizeOfLengthField)); + sizeOfLengthField); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public int %sLength()\n" + indent + " {\n" + "%s" + @@ -774,7 +774,7 @@ private void generateDecoderVarData( indent + " }\n", Generators.toLowerFirstChar(propertyName), generateArrayFieldNotPresentCondition(token.version(), indent), - generateGet(lengthType, "limit", byteOrderStr))); + generateGet(lengthType, "limit", byteOrderStr)); generateDataDecodeMethods( sb, token, propertyName, sizeOfLengthField, lengthType, byteOrderStr, characterEncoding, indent); @@ -807,13 +807,13 @@ private void generateEncoderVarData( final int maxLengthValue = (int)lengthEncoding.applicableMaxValue().longValue(); final String byteOrderStr = byteOrderString(lengthEncoding); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public static int %sHeaderLength()\n" + indent + " {\n" + indent + " return %d;\n" + indent + " }\n", Generators.toLowerFirstChar(propertyName), - sizeOfLengthField)); + sizeOfLengthField); generateDataEncodeMethods( sb, @@ -864,7 +864,7 @@ private void generateDataDecodeMethods( if (null != characterEncoding) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public String %1$s()\n" + indent + " {\n" + "%2$s" + @@ -893,11 +893,11 @@ private void generateDataDecodeMethods( generateStringNotPresentCondition(token.version(), indent), sizeOfLengthField, generateGet(lengthType, "limit", byteOrderStr), - characterEncoding)); + characterEncoding); if (characterEncoding.contains("ASCII")) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public int get%1$s(final Appendable appendable)\n" + indent + " {\n" + "%2$s" + @@ -913,7 +913,7 @@ private void generateDataDecodeMethods( generateStringNotPresentConditionForAppendable(token.version(), indent), sizeOfLengthField, generateGet(lengthType, "limit", byteOrderStr), - byteOrderStr)); + byteOrderStr); } } } @@ -927,7 +927,7 @@ private void generateVarDataWrapDecoder( final String byteOrderStr, final String indent) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public void wrap%s(final %s wrapBuffer)\n" + indent + " {\n" + "%s" + @@ -941,7 +941,7 @@ private void generateVarDataWrapDecoder( readOnlyBuffer, generateVarWrapFieldNotPresentCondition(token.version(), indent), sizeOfLengthField, - generateGet(lengthType, "limit", byteOrderStr))); + generateGet(lengthType, "limit", byteOrderStr)); } private void generateDataEncodeMethods( @@ -1005,7 +1005,7 @@ private void generateCharArrayEncodeMethods( { if (characterEncoding.contains("ASCII")) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final String value)\n" + indent + " {\n" + indent + " final int length = null == value ? 0 : value.length();\n" + @@ -1024,9 +1024,9 @@ private void generateCharArrayEncodeMethods( formatPropertyName(propertyName), maxLengthValue, sizeOfLengthField, - generatePut(lengthType, "limit", "length", byteOrderStr))); + generatePut(lengthType, "limit", "length", byteOrderStr)); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final CharSequence value)\n" + indent + " {\n" + indent + " final int length = null == value ? 0 : value.length();\n" + @@ -1050,11 +1050,11 @@ private void generateCharArrayEncodeMethods( formatPropertyName(propertyName), maxLengthValue, sizeOfLengthField, - generatePut(lengthType, "limit", "length", byteOrderStr))); + generatePut(lengthType, "limit", "length", byteOrderStr)); } else { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final String value)\n" + indent + " {\n" + indent + " final byte[] bytes;\n" + @@ -1084,7 +1084,7 @@ private void generateCharArrayEncodeMethods( characterEncoding, maxLengthValue, sizeOfLengthField, - generatePut(lengthType, "limit", "length", byteOrderStr))); + generatePut(lengthType, "limit", "length", byteOrderStr)); } } @@ -1098,7 +1098,7 @@ private void generateVarDataTypedDecoder( final String byteOrderStr, final String indent) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public int get%s(final %s dst, final int dstOffset, final int length)\n" + indent + " {\n" + "%s" + @@ -1114,7 +1114,7 @@ private void generateVarDataTypedDecoder( exchangeType, generateArrayFieldNotPresentCondition(token.version(), indent), sizeOfLengthField, - generateGet(lengthType, "limit", byteOrderStr))); + generateGet(lengthType, "limit", byteOrderStr)); } private void generateDataTypedEncoder( @@ -1128,7 +1128,7 @@ private void generateDataTypedEncoder( final String byteOrderStr, final String indent) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public %1$s put%2$s(final %3$s src, final int srcOffset, final int length)\n" + indent + " {\n" + indent + " if (length > %4$d)\n" + @@ -1147,7 +1147,7 @@ private void generateDataTypedEncoder( exchangeType, maxLengthValue, sizeOfLengthField, - generatePut(lengthType, "limit", "length", byteOrderStr))); + generatePut(lengthType, "limit", "length", byteOrderStr)); } private void generateBitSet(final List tokens) throws IOException @@ -1161,27 +1161,27 @@ private void generateBitSet(final List tokens) throws IOException try (Writer out = outputManager.createOutput(decoderName)) { - generateFixedFlyweightHeader(token, decoderName, implementsString, out, readOnlyBuffer, fqReadOnlyBuffer); + generateFixedFlyweightHeader(out, token, decoderName, implementsString, readOnlyBuffer, fqReadOnlyBuffer); out.append(generateChoiceIsEmpty(token.encoding().primitiveType())); - out.append(generateChoiceDecoders(messageBody)); + generateChoiceDecoders(out, messageBody); out.append(generateChoiceDisplay(messageBody)); out.append("}\n"); } try (Writer out = outputManager.createOutput(encoderName)) { - generateFixedFlyweightHeader(token, encoderName, implementsString, out, mutableBuffer, fqMutableBuffer); - out.append(generateChoiceClear(encoderName, token)); - out.append(generateChoiceEncoders(encoderName, messageBody)); + generateFixedFlyweightHeader(out, token, encoderName, implementsString, mutableBuffer, fqMutableBuffer); + generateChoiceClear(out, encoderName, token); + generateChoiceEncoders(out, encoderName, messageBody); out.append("}\n"); } } private void generateFixedFlyweightHeader( + final Writer out, final Token token, final String typeName, final String implementsString, - final Writer out, final String buffer, final String fqBuffer) throws IOException { @@ -1323,30 +1323,25 @@ private void generateComposite(final List tokens) throws IOException } } - private CharSequence generateChoiceClear(final String bitSetClassName, final Token token) + private void generateChoiceClear(final Appendable out, final String bitSetClassName, final Token token) { - final StringBuilder sb = new StringBuilder(); - final Encoding encoding = token.encoding(); final String literalValue = generateLiteral(encoding.primitiveType(), "0"); final String byteOrderStr = byteOrderString(encoding); - sb.append(String.format("\n" + + new Formatter(out).format("\n" + " public %s clear()\n" + " {\n" + " %s;\n" + " return this;\n" + " }\n", bitSetClassName, - generatePut(encoding.primitiveType(), "offset", literalValue, byteOrderStr))); - - return sb; + generatePut(encoding.primitiveType(), "offset", literalValue, byteOrderStr)); } - private CharSequence generateChoiceDecoders(final List tokens) + private void generateChoiceDecoders(final Appendable out, final List tokens) + throws IOException { - final StringBuilder sb = new StringBuilder(); - for (final Token token : tokens) { if (token.signal() == Signal.CHOICE) @@ -1358,8 +1353,8 @@ private CharSequence generateChoiceDecoders(final List tokens) final PrimitiveType primitiveType = encoding.primitiveType(); final String argType = bitsetArgType(primitiveType); - generateOptionDecodeJavadoc(sb, INDENT, token); - sb.append(String.format("\n" + + generateOptionDecodeJavadoc(out, INDENT, token); + new Formatter(out).format("\n" + " public boolean %1$s()\n" + " {\n" + " return %2$s;\n" + @@ -1371,17 +1366,14 @@ private CharSequence generateChoiceDecoders(final List tokens) choiceName, generateChoiceGet(primitiveType, choiceBitIndex, byteOrderStr), argType, - generateStaticChoiceGet(primitiveType, choiceBitIndex))); + generateStaticChoiceGet(primitiveType, choiceBitIndex)); } } - - return sb; } - private CharSequence generateChoiceEncoders(final String bitSetClassName, final List tokens) + private void generateChoiceEncoders(final Appendable out, final String bitSetClassName, final List tokens) + throws IOException { - final StringBuilder sb = new StringBuilder(); - for (final Token token : tokens) { if (token.signal() == Signal.CHOICE) @@ -1393,8 +1385,8 @@ private CharSequence generateChoiceEncoders(final String bitSetClassName, final final PrimitiveType primitiveType = encoding.primitiveType(); final String argType = bitsetArgType(primitiveType); - generateOptionEncodeJavadoc(sb, INDENT, token); - sb.append(String.format("\n" + + generateOptionEncodeJavadoc(out, INDENT, token); + new Formatter(out).format("\n" + " public %1$s %2$s(final boolean value)\n" + " {\n" + "%3$s\n" + @@ -1408,11 +1400,9 @@ private CharSequence generateChoiceEncoders(final String bitSetClassName, final choiceName, generateChoicePut(encoding.primitiveType(), choiceBitIndex, byteOrderStr), argType, - generateStaticChoicePut(encoding.primitiveType(), choiceBitIndex))); + generateStaticChoicePut(encoding.primitiveType(), choiceBitIndex)); } } - - return sb; } private String bitsetArgType(final PrimitiveType primitiveType) @@ -1492,27 +1482,27 @@ private CharSequence generateEnumLookupMethod(final List tokens, final St final StringBuilder sb = new StringBuilder(); final PrimitiveType primitiveType = tokens.get(0).encoding().primitiveType(); - sb.append(String.format( + new Formatter(sb).format("\n" + " public static %s get(final %s value)\n" + " {\n" + " switch (value)\n" + " {\n", enumName, - javaTypeName(primitiveType))); + javaTypeName(primitiveType)); for (final Token token : tokens) { - sb.append(String.format( + new Formatter(sb).format("\n" + " case %s: return %s;\n", token.encoding().constValue().toString(), - token.name())); + token.name()); } final String handleUnknownLogic = shouldDecodeUnknownEnumValues ? INDENT + INDENT + "return SBE_UNKNOWN;\n" : INDENT + INDENT + "throw new IllegalArgumentException(\"Unknown value: \" + value);\n"; - sb.append(String.format( + new Formatter(sb).format("\n" + " }\n\n" + " if (%s == value)\n" + " {\n" + @@ -1521,7 +1511,7 @@ private CharSequence generateEnumLookupMethod(final List tokens, final St "%s" + " }\n", generateLiteral(primitiveType, tokens.get(0).encoding().applicableNullValue().toString()), - handleUnknownLogic)); + handleUnknownLogic); return sb; } @@ -1778,25 +1768,25 @@ private CharSequence generatePrimitiveFieldMetaData( final String javaTypeName = javaTypeName(primitiveType); final String formattedPropertyName = formatPropertyName(propertyName); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public static %s %sNullValue()\n" + indent + " {\n" + indent + " return %s;\n" + indent + " }\n", javaTypeName, formattedPropertyName, - generateLiteral(primitiveType, token.encoding().applicableNullValue().toString()))); + generateLiteral(primitiveType, token.encoding().applicableNullValue().toString())); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public static %s %sMinValue()\n" + indent + " {\n" + indent + " return %s;\n" + indent + " }\n", javaTypeName, formattedPropertyName, - generateLiteral(primitiveType, token.encoding().applicableMinValue().toString()))); + generateLiteral(primitiveType, token.encoding().applicableMinValue().toString())); - sb.append(String.format( + new Formatter(sb).format("\n" + "\n" + indent + " public static %s %sMaxValue()\n" + indent + " {\n" + @@ -1804,7 +1794,7 @@ private CharSequence generatePrimitiveFieldMetaData( indent + " }\n", javaTypeName, formattedPropertyName, - generateLiteral(primitiveType, token.encoding().applicableMaxValue().toString()))); + generateLiteral(primitiveType, token.encoding().applicableMaxValue().toString())); return sb; } @@ -1973,7 +1963,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( generateArrayLengthMethod(propertyName, indent, fieldLength, sb); - sb.append(String.format( + new Formatter(sb).format("\n" + indent + " public %s %s(final int index)\n" + indent + " {\n" + indent + " if (index < 0 || index >= %d)\n" + @@ -1990,13 +1980,13 @@ private CharSequence generatePrimitiveArrayPropertyDecode( generateFieldNotPresentCondition(inComposite, propertyToken.version(), encoding, indent), offset, typeSize, - generateGet(encoding.primitiveType(), "pos", byteOrderStr))); + generateGet(encoding.primitiveType(), "pos", byteOrderStr)); if (encoding.primitiveType() == PrimitiveType.CHAR) { generateCharacterEncodingMethod(sb, propertyName, encoding.characterEncoding(), indent); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public int get%s(final byte[] dst, final int dstOffset)\n" + indent + " {\n" + indent + " final int length = %d;\n" + @@ -2012,9 +2002,9 @@ private CharSequence generatePrimitiveArrayPropertyDecode( Generators.toUpperFirstChar(propertyName), fieldLength, generateArrayFieldNotPresentCondition(propertyToken.version(), indent), - offset)); + offset); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public String %s()\n" + indent + " {\n" + "%s" + @@ -2030,11 +2020,11 @@ private CharSequence generatePrimitiveArrayPropertyDecode( offset, fieldLength, fieldLength, - charset(encoding.characterEncoding()))); + charset(encoding.characterEncoding())); if (encoding.characterEncoding().contains("ASCII")) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public int get%1$s(final Appendable value)\n" + indent + " {\n" + "%2$s" + @@ -2059,7 +2049,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( Generators.toUpperFirstChar(propertyName), generateStringNotPresentConditionForAppendable(propertyToken.version(), indent), fieldLength, - offset)); + offset); } } @@ -2069,13 +2059,13 @@ private CharSequence generatePrimitiveArrayPropertyDecode( private static void generateArrayLengthMethod( final String propertyName, final String indent, final int fieldLength, final StringBuilder sb) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public static int %sLength()\n" + indent + " {\n" + indent + " return %d;\n" + indent + " }\n\n", formatPropertyName(propertyName), - fieldLength)); + fieldLength); } private String byteOrderString(final Encoding encoding) @@ -2099,7 +2089,7 @@ private CharSequence generatePrimitiveArrayPropertyEncode( generateArrayLengthMethod(propertyName, indent, arrayLength, sb); - sb.append(String.format( + new Formatter(sb).format("\n" + indent + " public %s %s(final int index, final %s value)\n" + indent + " {\n" + indent + " if (index < 0 || index >= %d)\n" + @@ -2116,7 +2106,7 @@ private CharSequence generatePrimitiveArrayPropertyEncode( arrayLength, offset, typeSize, - generatePut(primitiveType, "pos", "value", byteOrderStr))); + generatePut(primitiveType, "pos", "value", byteOrderStr)); if (arrayLength > 1 && arrayLength <= 4) { @@ -2168,7 +2158,7 @@ private void generateCharArrayEncodeMethods( { generateCharacterEncodingMethod(sb, propertyName, encoding.characterEncoding(), indent); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public %s put%s(final byte[] src, final int srcOffset)\n" + indent + " {\n" + indent + " final int length = %d;\n" + @@ -2183,11 +2173,11 @@ private void generateCharArrayEncodeMethods( formatClassName(containingClassName), Generators.toUpperFirstChar(propertyName), fieldLength, - offset)); + offset); if (encoding.characterEncoding().contains("ASCII")) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final String src)\n" + indent + " {\n" + indent + " final int length = %3$d;\n" + @@ -2207,8 +2197,9 @@ private void generateCharArrayEncodeMethods( formatClassName(containingClassName), propertyName, fieldLength, - offset)); - sb.append(String.format("\n" + + offset); + + new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final CharSequence src)\n" + indent + " {\n" + indent + " final int length = %3$d;\n" + @@ -2233,11 +2224,11 @@ private void generateCharArrayEncodeMethods( formatClassName(containingClassName), propertyName, fieldLength, - offset)); + offset); } else { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public %s %s(final String src)\n" + indent + " {\n" + indent + " final int length = %d;\n" + @@ -2259,7 +2250,7 @@ private void generateCharArrayEncodeMethods( fieldLength, charset(encoding.characterEncoding()), offset, - offset)); + offset); } } @@ -2273,13 +2264,13 @@ private static void generateCharacterEncodingMethod( { if (null != characterEncoding) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public static String %sCharacterEncoding()\n" + indent + " {\n" + indent + " return \"%s\";\n" + indent + " }\n", formatPropertyName(propertyName), - characterEncoding)); + characterEncoding); } } @@ -2307,22 +2298,22 @@ private CharSequence generateConstPropertyMethods( final CharSequence values = generateByteLiteralList( encoding.constValue().byteArrayValue(encoding.primitiveType())); - sb.append(String.format( + new Formatter(sb).format("\n" + "\n" + indent + " private static final byte[] %s_VALUE = { %s };\n", propertyName.toUpperCase(), - values)); + values); generateArrayLengthMethod(formattedPropertyName, indent, constBytes.length, sb); - sb.append(String.format( + new Formatter(sb).format("\n" + indent + " public %s %s(final int index)\n" + indent + " {\n" + indent + " return %s_VALUE[index];\n" + indent + " }\n\n", javaTypeName, formattedPropertyName, - propertyName.toUpperCase())); + propertyName.toUpperCase()); sb.append(String.format( indent + " public int get%s(final byte[] dst, final int offset, final int length)\n" + @@ -2337,23 +2328,23 @@ private CharSequence generateConstPropertyMethods( if (constBytes.length > 1) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public String %s()\n" + indent + " {\n" + indent + " return \"%s\";\n" + indent + " }\n\n", formattedPropertyName, - encoding.constValue())); + encoding.constValue()); } else { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public byte %s()\n" + indent + " {\n" + indent + " return (byte)%s;\n" + indent + " }\n\n", formattedPropertyName, - encoding.constValue())); + encoding.constValue()); } return sb; @@ -2688,52 +2679,52 @@ private void generateDecoderFields(final StringBuilder sb, final List tok private static void generateFieldIdMethod(final StringBuilder sb, final Token token, final String indent) { - sb.append(String.format( + new Formatter(sb).format("\n" + "\n" + indent + " public static int %sId()\n" + indent + " {\n" + indent + " return %d;\n" + indent + " }\n", formatPropertyName(token.name()), - token.id())); + token.id()); } private static void generateEncodingOffsetMethod( final StringBuilder sb, final String name, final int offset, final String indent) { - sb.append(String.format( + new Formatter(sb).format("\n" + "\n" + indent + " public static int %sEncodingOffset()\n" + indent + " {\n" + indent + " return %d;\n" + indent + " }\n", formatPropertyName(name), - offset)); + offset); } private static void generateEncodingLengthMethod( final StringBuilder sb, final String name, final int length, final String indent) { - sb.append(String.format( + new Formatter(sb).format("\n" + "\n" + indent + " public static int %sEncodingLength()\n" + indent + " {\n" + indent + " return %d;\n" + indent + " }\n", formatPropertyName(name), - length)); + length); } private static void generateFieldSinceVersionMethod(final StringBuilder sb, final Token token, final String indent) { - sb.append(String.format( + new Formatter(sb).format("\n" + "\n" + indent + " public static int %sSinceVersion()\n" + indent + " {\n" + indent + " return %d;\n" + indent + " }\n", formatPropertyName(token.name()), - token.version())); + token.version()); } private static void generateFieldMetaAttributeMethod(final StringBuilder sb, final Token token, final String indent) @@ -2743,7 +2734,7 @@ private static void generateFieldMetaAttributeMethod(final StringBuilder sb, fin final String timeUnit = encoding.timeUnit() == null ? "" : encoding.timeUnit(); final String semanticType = encoding.semanticType() == null ? "" : encoding.semanticType(); - sb.append(String.format( + new Formatter(sb).format("\n" + "\n" + indent + " public static String %sMetaAttribute(final MetaAttribute metaAttribute)\n" + indent + " {\n" + @@ -2760,7 +2751,7 @@ private static void generateFieldMetaAttributeMethod(final StringBuilder sb, fin epoch, timeUnit, semanticType, - encoding.presence().toString().toLowerCase())); + encoding.presence().toString().toLowerCase()); } private CharSequence generateEnumDecoder( @@ -2841,14 +2832,14 @@ private CharSequence generateBitSetProperty( { final StringBuilder sb = new StringBuilder(); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " private final %s %s = new %s();\n", bitSetName, propertyName, - bitSetName)); + bitSetName); generateFlyweightPropertyJavadoc(sb, indent + INDENT, propertyToken, bitSetName); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public %s %s()\n" + indent + " {\n" + "%s" + @@ -2860,7 +2851,7 @@ private CharSequence generateBitSetProperty( generatePropertyNotPresentCondition(inComposite, codecType, propertyToken, null, indent), propertyName, bitsetToken.offset(), - propertyName)); + propertyName); return sb; } @@ -2876,14 +2867,14 @@ private CharSequence generateCompositeProperty( { final StringBuilder sb = new StringBuilder(); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " private final %s %s = new %s();\n", compositeName, propertyName, - compositeName)); + compositeName); generateFlyweightPropertyJavadoc(sb, indent + INDENT, propertyToken, compositeName); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " public %s %s()\n" + indent + " {\n" + "%s" + @@ -2895,7 +2886,7 @@ private CharSequence generateCompositeProperty( generatePropertyNotPresentCondition(inComposite, codecType, propertyToken, null, indent), propertyName, compositeToken.offset(), - propertyName)); + propertyName); return sb; } @@ -3096,11 +3087,9 @@ private String generateStaticChoicePut(final PrimitiveType type, final String bi throw new IllegalArgumentException("primitive type not supported: " + type); } - private CharSequence generateEncoderDisplay(final String decoderName) + private void generateEncoderDisplay(final StringBuilder sb, final String decoderName) { final String indent = INDENT; - final StringBuilder sb = new StringBuilder(); - sb.append('\n'); appendToString(sb, indent); sb.append('\n'); @@ -3111,8 +3100,6 @@ private CharSequence generateEncoderDisplay(final String decoderName) sb.append('\n'); append(sb, indent, " return writer.appendTo(builder);"); append(sb, indent, "}"); - - return sb.toString(); } private CharSequence generateCompositeEncoderDisplay(final String decoderName) @@ -3129,7 +3116,7 @@ private CharSequence generateCompositeEncoderDisplay(final String decoderName) append(sb, indent, " return writer.appendTo(builder);"); append(sb, indent, "}"); - return sb.toString(); + return sb; } private CharSequence generateCompositeDecoderDisplay(final List tokens) @@ -3163,7 +3150,7 @@ private CharSequence generateCompositeDecoderDisplay(final List tokens) append(sb, indent, " return builder;"); append(sb, indent, "}"); - return sb.toString(); + return sb; } private CharSequence generateChoiceDisplay(final List tokens) @@ -3178,10 +3165,9 @@ private CharSequence generateChoiceDisplay(final List tokens) Separators.BEGIN_SET.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); append(sb, indent, " boolean atLeastOne = false;"); - tokens - .stream() - .filter((token) -> token.signal() == Signal.CHOICE) - .forEach((token) -> + for (final Token token : tokens) + { + if (token.signal() == Signal.CHOICE) { final String choiceName = formatPropertyName(token.name()); append(sb, indent, " if (" + choiceName + "())"); @@ -3193,21 +3179,25 @@ private CharSequence generateChoiceDisplay(final List tokens) append(sb, indent, " builder.append(\"" + choiceName + "\");"); append(sb, indent, " atLeastOne = true;"); append(sb, indent, " }"); - }); + } + } Separators.END_SET.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); sb.append('\n'); append(sb, indent, " return builder;"); append(sb, indent, "}"); - return sb.toString(); + return sb; } - private CharSequence generateDecoderDisplay( - final String name, final List tokens, final List groups, final List varData) + private void generateDecoderDisplay( + final StringBuilder sb, + final String name, + final List tokens, + final List groups, + final List varData) { final String indent = INDENT; - final StringBuilder sb = new StringBuilder(); sb.append('\n'); appendToString(sb, indent); @@ -3241,8 +3231,6 @@ private CharSequence generateDecoderDisplay( sb.append('\n'); append(sb, indent, " return builder;"); append(sb, indent, "}"); - - return sb.toString(); } private void appendGroupInstanceDecoderDisplay( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 33e118d88f..cb8877de1f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -21,6 +21,7 @@ import uk.co.real_logic.sbe.ir.Token; import uk.co.real_logic.sbe.util.ValidationUtil; +import java.io.IOException; import java.lang.reflect.Field; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -273,12 +274,14 @@ public static void generateTypeJavadoc( /** * Generate the Javadoc comment header for a bitset choice option decode method. * - * @param sb to append to. + * @param out to append to. * @param indent level for the comment. * @param optionToken for the type. + * @throws IOException on failing to write to output. */ public static void generateOptionDecodeJavadoc( - final StringBuilder sb, final String indent, final Token optionToken) + final Appendable out, final String indent, final Token optionToken) + throws IOException { final String description = optionToken.description(); if (null == description || description.isEmpty()) @@ -286,7 +289,7 @@ public static void generateOptionDecodeJavadoc( return; } - sb.append(indent).append("/**\n") + out.append(indent).append("/**\n") .append(indent).append(" * ").append(description).append('\n') .append(indent).append(" *\n") .append(indent).append(" * @return true if ").append(optionToken.name()).append(" is set or false if not\n") @@ -296,12 +299,14 @@ public static void generateOptionDecodeJavadoc( /** * Generate the Javadoc comment header for a bitset choice option encode method. * - * @param sb to append to. + * @param out to append to. * @param indent level for the comment. * @param optionToken for the type. + * @throws IOException on failing to write to output. */ public static void generateOptionEncodeJavadoc( - final StringBuilder sb, final String indent, final Token optionToken) + final Appendable out, final String indent, final Token optionToken) + throws IOException { final String description = optionToken.description(); if (null == description || description.isEmpty()) @@ -310,7 +315,7 @@ public static void generateOptionEncodeJavadoc( } final String name = optionToken.name(); - sb.append(indent).append("/**\n") + out.append(indent).append("/**\n") .append(indent).append(" * ").append(description).append('\n') .append(indent).append(" *\n") .append(indent).append(" * @param value true if ").append(name).append(" is set or false if not.\n") From 3fed8115fb1b4af0aaaa17f71075f15974f4d25e Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 6 Aug 2019 15:38:28 +0100 Subject: [PATCH 0138/1594] [Java] Further reduction in copying and allocation for JavaGenerator. --- .../sbe/generation/java/JavaGenerator.java | 309 ++++++++---------- 1 file changed, 138 insertions(+), 171 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 7357f728ce..63d803dcbf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -392,12 +392,11 @@ private void generateGroupDecoderClassHeader( .append(indent).append(" return HEADER_SIZE;\n") .append(indent).append(" }\n"); - new Formatter(sb).format("\n" + - indent + " public static int sbeBlockLength()\n" + - indent + " {\n" + - indent + " return %d;\n" + - indent + " }\n", - blockLength); + sb.append("\n") + .append(indent).append(" public static int sbeBlockLength()\n") + .append(indent).append(" {\n") + .append(indent).append(" return ").append(blockLength).append(";\n") + .append(indent).append(" }\n"); new Formatter(sb).format("\n" + indent + " public int actingBlockLength()\n" + @@ -504,12 +503,11 @@ private void generateGroupEncoderClassHeader( .append(ind).append(" return HEADER_SIZE;\n") .append(ind).append(" }\n"); - new Formatter(sb).format("\n" + - ind + " public static int sbeBlockLength()\n" + - ind + " {\n" + - ind + " return %d;\n" + - ind + " }\n", - blockLength); + sb.append("\n") + .append(ind).append(" public static int sbeBlockLength()\n") + .append(ind).append(" {\n") + .append(ind).append(" return ").append(blockLength).append(";\n") + .append(ind).append(" }\n"); new Formatter(sb).format("\n" + ind + " public %s next()\n" + @@ -582,7 +580,7 @@ private void generateGroupDecoderClassDeclaration( .append(field).append(" = new ").append(type).append("(parentMessage);\n"); } - sb.append(indent).append(" }\n\n"); + sb.append(indent).append(" }\n"); } private void generateGroupEncoderClassDeclaration( @@ -634,7 +632,7 @@ private void generateGroupEncoderClassDeclaration( .append(field).append(" = new ").append(type).append("(parentMessage);\n"); } - sb.append(indent).append(" }\n\n"); + sb.append(indent).append(" }\n"); } private static void generateGroupDecoderProperty( @@ -756,25 +754,22 @@ private void generateDecoderVarData( final Encoding lengthEncoding = lengthToken.encoding(); final PrimitiveType lengthType = lengthEncoding.primitiveType(); final String byteOrderStr = byteOrderString(lengthEncoding); - - new Formatter(sb).format("\n" + - indent + " public static int %sHeaderLength()\n" + - indent + " {\n" + - indent + " return %d;\n" + - indent + " }\n", - Generators.toLowerFirstChar(propertyName), - sizeOfLengthField); - - new Formatter(sb).format("\n" + - indent + " public int %sLength()\n" + - indent + " {\n" + - "%s" + - indent + " final int limit = parentMessage.limit();\n" + - indent + " return (int)%s;\n" + - indent + " }\n", - Generators.toLowerFirstChar(propertyName), - generateArrayFieldNotPresentCondition(token.version(), indent), - generateGet(lengthType, "limit", byteOrderStr)); + final String methodPropName = Generators.toLowerFirstChar(propertyName); + + sb.append("\n") + .append(indent).append(" public static int ").append(methodPropName).append("HeaderLength()\n") + .append(indent).append(" {\n") + .append(indent).append(" return ").append(sizeOfLengthField).append(";\n") + .append(indent).append(" }\n"); + + sb.append("\n") + .append(indent).append(" public int ").append(methodPropName).append("Length()\n") + .append(indent).append(" {\n") + .append(generateArrayFieldNotPresentCondition(token.version(), indent)) + .append(indent).append(" final int limit = parentMessage.limit();\n") + .append(indent).append(" return (int)") + .append(generateGet(lengthType, "limit", byteOrderStr)).append(";\n") + .append(indent).append(" }\n"); generateDataDecodeMethods( sb, token, propertyName, sizeOfLengthField, lengthType, byteOrderStr, characterEncoding, indent); @@ -807,13 +802,13 @@ private void generateEncoderVarData( final int maxLengthValue = (int)lengthEncoding.applicableMaxValue().longValue(); final String byteOrderStr = byteOrderString(lengthEncoding); - new Formatter(sb).format("\n" + - indent + " public static int %sHeaderLength()\n" + - indent + " {\n" + - indent + " return %d;\n" + - indent + " }\n", - Generators.toLowerFirstChar(propertyName), - sizeOfLengthField); + final String methodPropName = Generators.toLowerFirstChar(propertyName); + sb.append("\n") + .append(indent).append(" public static int ").append(methodPropName).append("HeaderLength()\n") + .append(indent).append(" {\n") + .append(indent).append(" return ") + .append(sizeOfLengthField).append(";\n") + .append(indent).append(" }\n"); generateDataEncodeMethods( sb, @@ -1324,19 +1319,19 @@ private void generateComposite(final List tokens) throws IOException } private void generateChoiceClear(final Appendable out, final String bitSetClassName, final Token token) + throws IOException { final Encoding encoding = token.encoding(); final String literalValue = generateLiteral(encoding.primitiveType(), "0"); final String byteOrderStr = byteOrderString(encoding); - new Formatter(out).format("\n" + - " public %s clear()\n" + - " {\n" + - " %s;\n" + - " return this;\n" + - " }\n", - bitSetClassName, - generatePut(encoding.primitiveType(), "offset", literalValue, byteOrderStr)); + final String clearStr = generatePut(encoding.primitiveType(), "offset", literalValue, byteOrderStr); + out.append("\n") + .append(" public ").append(bitSetClassName).append(" clear()\n") + .append(" {\n") + .append(" ").append(clearStr).append(";\n") + .append(" return this;\n") + .append(" }\n"); } private void generateChoiceDecoders(final Appendable out, final List tokens) @@ -1472,7 +1467,7 @@ private CharSequence generateEnumBody(final Token token, final String enumName) " public %1$s value()\n" + " {\n" + " return value;\n" + - " }\n\n", + " }\n", javaEncodingType, enumName); } @@ -1482,48 +1477,41 @@ private CharSequence generateEnumLookupMethod(final List tokens, final St final StringBuilder sb = new StringBuilder(); final PrimitiveType primitiveType = tokens.get(0).encoding().primitiveType(); - new Formatter(sb).format("\n" + - " public static %s get(final %s value)\n" + - " {\n" + - " switch (value)\n" + - " {\n", - enumName, - javaTypeName(primitiveType)); + sb.append("\n").append(" public static ").append(enumName) + .append(" get(final ").append(javaTypeName(primitiveType)).append(" value)\n").append(" {\n") + .append(" switch (value)\n").append(" {\n"); for (final Token token : tokens) { - new Formatter(sb).format("\n" + - " case %s: return %s;\n", - token.encoding().constValue().toString(), - token.name()); + final String constStr = token.encoding().constValue().toString(); + final String name = token.name(); + sb.append(" case ").append(constStr).append(": return ").append(name).append(";\n"); } final String handleUnknownLogic = shouldDecodeUnknownEnumValues ? INDENT + INDENT + "return SBE_UNKNOWN;\n" : INDENT + INDENT + "throw new IllegalArgumentException(\"Unknown value: \" + value);\n"; - new Formatter(sb).format("\n" + - " }\n\n" + - " if (%s == value)\n" + - " {\n" + - " return NULL_VAL;\n" + - " }\n\n" + - "%s" + - " }\n", - generateLiteral(primitiveType, tokens.get(0).encoding().applicableNullValue().toString()), - handleUnknownLogic); + final String nullValue = tokens.get(0).encoding().applicableNullValue().toString(); + sb.append(" }\n\n") + .append(" if (").append(generateLiteral(primitiveType, nullValue)).append(" == value)\n") + .append(" {\n") + .append(" return NULL_VAL;\n") + .append(" }\n\n") + .append(handleUnknownLogic) + .append(" }\n"); return sb; } - private CharSequence interfaceImportLine() + private String interfaceImportLine() { if (!shouldGenerateInterfaces) { return "\n"; } - return String.format("import %s.*;\n\n", JAVA_INTERFACE_PACKAGE); + return "import " + JAVA_INTERFACE_PACKAGE + ".*;\n\n"; } private CharSequence generateFileHeader(final String packageName, final String fqBuffer) @@ -1687,7 +1675,7 @@ private static CharSequence generateEnumDeclaration(final String name, final Tok final StringBuilder sb = new StringBuilder(); generateTypeJavadoc(sb, BASE_INDENT, typeToken); - sb.append("public enum ").append(name).append("\n{\n"); + sb.append("public enum ").append(name).append("\n{\n"); return sb; } @@ -1702,11 +1690,11 @@ private CharSequence generatePrimitiveDecoder( final StringBuilder sb = new StringBuilder(); final String formattedPropertyName = formatPropertyName(propertyName); - sb.append(generatePrimitiveFieldMetaData(formattedPropertyName, encodingToken, indent)); + generatePrimitiveFieldMetaMethod(sb, formattedPropertyName, encodingToken, indent); if (encodingToken.isConstantEncoding()) { - sb.append(generateConstPropertyMethods(formattedPropertyName, encodingToken, indent)); + generateConstPropertyMethods(sb, formattedPropertyName, encodingToken, indent); } else { @@ -1723,7 +1711,7 @@ private CharSequence generatePrimitiveEncoder( final StringBuilder sb = new StringBuilder(); final String formattedPropertyName = formatPropertyName(propertyName); - sb.append(generatePrimitiveFieldMetaData(formattedPropertyName, token, indent)); + generatePrimitiveFieldMetaMethod(sb, formattedPropertyName, token, indent); if (!token.isConstantEncoding()) { @@ -1732,7 +1720,7 @@ private CharSequence generatePrimitiveEncoder( } else { - sb.append(generateConstPropertyMethods(formattedPropertyName, token, indent)); + generateConstPropertyMethods(sb, formattedPropertyName, token, indent); } return sb; @@ -1759,44 +1747,37 @@ private CharSequence generatePrimitivePropertyEncodeMethods( () -> generatePrimitiveArrayPropertyEncode(containingClassName, propertyName, token, indent)); } - private CharSequence generatePrimitiveFieldMetaData( - final String propertyName, final Token token, final String indent) + private void generatePrimitiveFieldMetaMethod( + final StringBuilder sb, final String propertyName, final Token token, final String indent) { - final StringBuilder sb = new StringBuilder(); - final PrimitiveType primitiveType = token.encoding().primitiveType(); final String javaTypeName = javaTypeName(primitiveType); final String formattedPropertyName = formatPropertyName(propertyName); - new Formatter(sb).format("\n" + - indent + " public static %s %sNullValue()\n" + - indent + " {\n" + - indent + " return %s;\n" + - indent + " }\n", - javaTypeName, - formattedPropertyName, - generateLiteral(primitiveType, token.encoding().applicableNullValue().toString())); + final String nullValue = generateLiteral(primitiveType, token.encoding().applicableNullValue().toString()); + generatePrimitiveFieldMetaMethod(sb, indent, javaTypeName, formattedPropertyName, "Null", nullValue); - new Formatter(sb).format("\n" + - indent + " public static %s %sMinValue()\n" + - indent + " {\n" + - indent + " return %s;\n" + - indent + " }\n", - javaTypeName, - formattedPropertyName, - generateLiteral(primitiveType, token.encoding().applicableMinValue().toString())); + final String minValue = generateLiteral(primitiveType, token.encoding().applicableMinValue().toString()); + generatePrimitiveFieldMetaMethod(sb, indent, javaTypeName, formattedPropertyName, "Min", minValue); - new Formatter(sb).format("\n" + - "\n" + - indent + " public static %s %sMaxValue()\n" + - indent + " {\n" + - indent + " return %s;\n" + - indent + " }\n", - javaTypeName, - formattedPropertyName, - generateLiteral(primitiveType, token.encoding().applicableMaxValue().toString())); + final String maxValue = generateLiteral(primitiveType, token.encoding().applicableMaxValue().toString()); + generatePrimitiveFieldMetaMethod(sb, indent, javaTypeName, formattedPropertyName, "Max", maxValue); + } - return sb; + private void generatePrimitiveFieldMetaMethod( + final StringBuilder sb, + final String indent, + final String javaTypeName, + final String formattedPropertyName, + final String metaType, + final String retValue) + { + sb.append("\n") + .append(indent).append(" public static ") + .append(javaTypeName).append(" ").append(formattedPropertyName).append(metaType).append("Value()\n") + .append(indent).append(" {\n") + .append(indent).append(" return ").append(retValue).append(";\n") + .append(indent).append(" }\n"); } private CharSequence generatePrimitivePropertyDecode( @@ -2059,13 +2040,12 @@ private CharSequence generatePrimitiveArrayPropertyDecode( private static void generateArrayLengthMethod( final String propertyName, final String indent, final int fieldLength, final StringBuilder sb) { - new Formatter(sb).format("\n" + - indent + " public static int %sLength()\n" + - indent + " {\n" + - indent + " return %d;\n" + - indent + " }\n\n", - formatPropertyName(propertyName), - fieldLength); + final String formatPropertyName = formatPropertyName(propertyName); + sb.append("\n") + .append(indent).append(" public static int ").append(formatPropertyName).append("Length()\n") + .append(indent).append(" {\n") + .append(indent).append(" return ").append(fieldLength).append(";\n") + .append(indent).append(" }\n\n"); } private String byteOrderString(final Encoding encoding) @@ -2274,14 +2254,14 @@ private static void generateCharacterEncodingMethod( } } - private CharSequence generateConstPropertyMethods( - final String propertyName, final Token token, final String indent) + private void generateConstPropertyMethods( + final StringBuilder sb, final String propertyName, final Token token, final String indent) { final String formattedPropertyName = formatPropertyName(propertyName); final Encoding encoding = token.encoding(); if (encoding.primitiveType() != PrimitiveType.CHAR) { - return String.format("\n" + + new Formatter(sb).format("\n" + indent + " public %s %s()\n" + indent + " {\n" + indent + " return %s;\n" + @@ -2289,9 +2269,9 @@ private CharSequence generateConstPropertyMethods( javaTypeName(encoding.primitiveType()), formattedPropertyName, generateLiteral(encoding.primitiveType(), encoding.constValue().toString())); - } - final StringBuilder sb = new StringBuilder(); + return; + } final String javaTypeName = javaTypeName(encoding.primitiveType()); final byte[] constBytes = encoding.constValue().byteArrayValue(encoding.primitiveType()); @@ -2346,8 +2326,6 @@ private CharSequence generateConstPropertyMethods( formattedPropertyName, encoding.constValue()); } - - return sb; } private static CharSequence generateByteLiteralList(final byte[] bytes) @@ -2679,52 +2657,44 @@ private void generateDecoderFields(final StringBuilder sb, final List tok private static void generateFieldIdMethod(final StringBuilder sb, final Token token, final String indent) { - new Formatter(sb).format("\n" + - "\n" + - indent + " public static int %sId()\n" + - indent + " {\n" + - indent + " return %d;\n" + - indent + " }\n", - formatPropertyName(token.name()), - token.id()); + final String propertyName = formatPropertyName(token.name()); + sb.append("\n") + .append(indent).append(" public static int ").append(propertyName).append("Id()\n") + .append(indent).append(" {\n") + .append(indent).append(" return ").append(token.id()).append(";\n") + .append(indent).append(" }\n"); } private static void generateEncodingOffsetMethod( final StringBuilder sb, final String name, final int offset, final String indent) { - new Formatter(sb).format("\n" + - "\n" + - indent + " public static int %sEncodingOffset()\n" + - indent + " {\n" + - indent + " return %d;\n" + - indent + " }\n", - formatPropertyName(name), - offset); + final String propertyName = formatPropertyName(name); + sb.append("\n") + .append(indent).append(" public static int ").append(propertyName).append("EncodingOffset()\n") + .append(indent).append(" {\n") + .append(indent).append(" return ").append(offset).append(";\n") + .append(indent).append(" }\n"); } private static void generateEncodingLengthMethod( final StringBuilder sb, final String name, final int length, final String indent) { - new Formatter(sb).format("\n" + - "\n" + - indent + " public static int %sEncodingLength()\n" + - indent + " {\n" + - indent + " return %d;\n" + - indent + " }\n", - formatPropertyName(name), - length); + final String propertyName = formatPropertyName(name); + sb.append("\n") + .append(indent).append(" public static int ").append(propertyName).append("EncodingLength()\n") + .append(indent).append(" {\n") + .append(indent).append(" return ").append(length).append(";\n") + .append(indent).append(" }\n"); } private static void generateFieldSinceVersionMethod(final StringBuilder sb, final Token token, final String indent) { - new Formatter(sb).format("\n" + - "\n" + - indent + " public static int %sSinceVersion()\n" + - indent + " {\n" + - indent + " return %d;\n" + - indent + " }\n", - formatPropertyName(token.name()), - token.version()); + final String propertyName = formatPropertyName(token.name()); + sb.append("\n") + .append(indent).append(" public static int ").append(propertyName).append("SinceVersion()\n") + .append(indent).append(" {\n") + .append(indent).append(" return ").append(token.version()).append(";\n") + .append(indent).append(" }\n"); } private static void generateFieldMetaAttributeMethod(final StringBuilder sb, final Token token, final String indent) @@ -2733,25 +2703,22 @@ private static void generateFieldMetaAttributeMethod(final StringBuilder sb, fin final String epoch = encoding.epoch() == null ? "" : encoding.epoch(); final String timeUnit = encoding.timeUnit() == null ? "" : encoding.timeUnit(); final String semanticType = encoding.semanticType() == null ? "" : encoding.semanticType(); + final String presence = encoding.presence().toString().toLowerCase(); + final String propertyName = formatPropertyName(token.name()); - new Formatter(sb).format("\n" + - "\n" + - indent + " public static String %sMetaAttribute(final MetaAttribute metaAttribute)\n" + - indent + " {\n" + - indent + " switch (metaAttribute)\n" + - indent + " {\n" + - indent + " case EPOCH: return \"%s\";\n" + - indent + " case TIME_UNIT: return \"%s\";\n" + - indent + " case SEMANTIC_TYPE: return \"%s\";\n" + - indent + " case PRESENCE: return \"%s\";\n" + - indent + " }\n\n" + - indent + " return \"\";\n" + - indent + " }\n", - formatPropertyName(token.name()), - epoch, - timeUnit, - semanticType, - encoding.presence().toString().toLowerCase()); + sb.append("\n") + .append(indent).append(" public static String ") + .append(propertyName).append("MetaAttribute(final MetaAttribute metaAttribute)\n") + .append(indent).append(" {\n") + .append(indent).append(" switch (metaAttribute)\n") + .append(indent).append(" {\n") + .append(indent).append(" case EPOCH: return \"").append(epoch).append("\";\n") + .append(indent).append(" case TIME_UNIT: return \"").append(timeUnit).append("\";\n") + .append(indent).append(" case SEMANTIC_TYPE: return \"").append(semanticType).append("\";\n") + .append(indent).append(" case PRESENCE: return \"").append(presence).append("\";\n") + .append(indent).append(" }\n\n") + .append(indent).append(" return \"\";\n") + .append(indent).append(" }\n"); } private CharSequence generateEnumDecoder( From af24534d057d9484600111f7cd35adba83d853c2 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 6 Aug 2019 16:49:42 +0100 Subject: [PATCH 0139/1594] [Java] Further reduction in copying and allocation for JavaGenerator. --- .../sbe/generation/java/JavaGenerator.java | 326 ++++++++---------- 1 file changed, 147 insertions(+), 179 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 63d803dcbf..9594485fdf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -368,72 +368,67 @@ private void generateGroupDecoderClassHeader( indent, dimensionHeaderLen); - new Formatter(sb).format("\n" + - indent + " public void wrap(final %s buffer)\n" + - indent + " {\n" + - indent + " if (buffer != this.buffer)\n" + - indent + " {\n" + - indent + " this.buffer = buffer;\n" + - indent + " }\n" + - indent + " index = -1;\n" + - indent + " final int limit = parentMessage.limit();\n" + - indent + " parentMessage.limit(limit + HEADER_SIZE);\n" + - indent + " blockLength = (int)%s;\n" + - indent + " count = (int)%s;\n" + - indent + " }\n\n", - readOnlyBuffer, - blockLengthGet, - numInGroupGet); - - final int blockLength = tokens.get(index).encodedLength(); + sb.append("\n") + .append(indent).append(" public void wrap(final ").append(readOnlyBuffer).append(" buffer)\n") + .append(indent).append(" {\n") + .append(indent).append(" if (buffer != this.buffer)\n") + .append(indent).append(" {\n") + .append(indent).append(" this.buffer = buffer;\n") + .append(indent).append(" }\n") + .append(indent).append(" index = -1;\n") + .append(indent).append(" final int limit = parentMessage.limit();\n") + .append(indent).append(" parentMessage.limit(limit + HEADER_SIZE);\n") + .append(indent).append(" blockLength = (int)").append(blockLengthGet).append(";\n") + .append(indent).append(" count = (int)").append(numInGroupGet).append(";\n") + .append(indent).append(" }\n"); - sb.append(indent).append(" public static int sbeHeaderSize()\n") - .append(indent).append(" {\n") - .append(indent).append(" return HEADER_SIZE;\n") - .append(indent).append(" }\n"); + sb.append("\n") + .append(indent).append(" public static int sbeHeaderSize()\n") + .append(indent).append(" {\n") + .append(indent).append(" return HEADER_SIZE;\n") + .append(indent).append(" }\n"); sb.append("\n") .append(indent).append(" public static int sbeBlockLength()\n") .append(indent).append(" {\n") - .append(indent).append(" return ").append(blockLength).append(";\n") + .append(indent).append(" return ").append(tokens.get(index).encodedLength()).append(";\n") .append(indent).append(" }\n"); - new Formatter(sb).format("\n" + - indent + " public int actingBlockLength()\n" + - indent + " {\n" + - indent + " return blockLength;\n" + - indent + " }\n\n" + - indent + " public int count()\n" + - indent + " {\n" + - indent + " return count;\n" + - indent + " }\n\n" + - indent + " public java.util.Iterator<%s> iterator()\n" + - indent + " {\n" + - indent + " return this;\n" + - indent + " }\n\n" + - indent + " public void remove()\n" + - indent + " {\n" + - indent + " throw new UnsupportedOperationException();\n" + - indent + " }\n\n" + - indent + " public boolean hasNext()\n" + - indent + " {\n" + - indent + " return (index + 1) < count;\n" + - indent + " }\n", - formatClassName(groupName)); + final String className = formatClassName(groupName); + sb.append("\n") + .append(indent).append(" public int actingBlockLength()\n") + .append(indent).append(" {\n") + .append(indent).append(" return blockLength;\n") + .append(indent).append(" }\n\n") + .append(indent).append(" public int count()\n") + .append(indent).append(" {\n") + .append(indent).append(" return count;\n") + .append(indent).append(" }\n\n") + .append(indent).append(" public java.util.Iterator<").append(className).append("> iterator()\n") + .append(indent).append(" {\n") + .append(indent).append(" return this;\n") + .append(indent).append(" }\n\n") + .append(indent).append(" public void remove()\n") + .append(indent).append(" {\n") + .append(indent).append(" throw new UnsupportedOperationException();\n") + .append(indent).append(" }\n\n") + .append(indent).append(" public boolean hasNext()\n") + .append(indent).append(" {\n") + .append(indent).append(" return (index + 1) < count;\n") + .append(indent).append(" }\n"); - new Formatter(sb).format("\n" + - indent + " public %s next()\n" + - indent + " {\n" + - indent + " if (index + 1 >= count)\n" + - indent + " {\n" + - indent + " throw new java.util.NoSuchElementException();\n" + - indent + " }\n\n" + - indent + " offset = parentMessage.limit();\n" + - indent + " parentMessage.limit(offset + blockLength);\n" + - indent + " ++index;\n\n" + - indent + " return this;\n" + - indent + " }\n", - formatClassName(groupName)); + sb.append("\n") + .append(indent).append(" public ").append(className).append(" next()\n") + .append(indent).append(" {\n") + .append(indent).append(" if (index + 1 >= count)\n") + .append(indent).append(" {\n") + .append(indent).append(" throw new java.util.NoSuchElementException();\n") + .append(indent).append(" }\n\n") + .append(indent).append(" offset = parentMessage.limit();\n") + .append(indent).append(" parentMessage.limit(offset + blockLength);\n") + .append(indent).append(" ++index;\n\n") + .append(indent).append(" return this;\n") + .append(indent).append(" }\n"); } private void generateGroupEncoderClassHeader( @@ -509,19 +504,18 @@ private void generateGroupEncoderClassHeader( .append(ind).append(" return ").append(blockLength).append(";\n") .append(ind).append(" }\n"); - new Formatter(sb).format("\n" + - ind + " public %s next()\n" + - ind + " {\n" + - ind + " if (index + 1 >= count)\n" + - ind + " {\n" + - ind + " throw new java.util.NoSuchElementException();\n" + - ind + " }\n\n" + - ind + " offset = parentMessage.limit();\n" + - ind + " parentMessage.limit(offset + sbeBlockLength());\n" + - ind + " ++index;\n\n" + - ind + " return this;\n" + - ind + " }\n", - formatClassName(encoderName(groupName))); + sb.append("\n") + .append(ind).append(" public ").append(formatClassName(encoderName(groupName))).append(" next()\n") + .append(ind).append(" {\n") + .append(ind).append(" if (index + 1 >= count)\n") + .append(ind).append(" {\n") + .append(ind).append(" throw new java.util.NoSuchElementException();\n") + .append(ind).append(" }\n\n") + .append(ind).append(" offset = parentMessage.limit();\n") + .append(ind).append(" parentMessage.limit(offset + sbeBlockLength());\n") + .append(ind).append(" ++index;\n\n") + .append(ind).append(" return this;\n") + .append(ind).append(" }\n"); } private static String primitiveTypeName(final Token token) @@ -1349,19 +1343,17 @@ private void generateChoiceDecoders(final Appendable out, final List toke final String argType = bitsetArgType(primitiveType); generateOptionDecodeJavadoc(out, INDENT, token); - new Formatter(out).format("\n" + - " public boolean %1$s()\n" + - " {\n" + - " return %2$s;\n" + - " }\n\n" + - " public static boolean %1$s(final %3$s value)\n" + - " {\n" + - " return %4$s;\n" + - " }\n", - choiceName, - generateChoiceGet(primitiveType, choiceBitIndex, byteOrderStr), - argType, - generateStaticChoiceGet(primitiveType, choiceBitIndex)); + final String choiceGet = generateChoiceGet(primitiveType, choiceBitIndex, byteOrderStr); + final String staticChoiceGet = generateStaticChoiceGet(primitiveType, choiceBitIndex); + out.append("\n") + .append(" public boolean ").append(choiceName).append("()\n") + .append(" {\n") + .append(" return ").append(choiceGet).append(";\n") + .append(" }\n\n") + .append(" public static boolean ").append(choiceName) + .append("(final ").append(argType).append(" value)\n") + .append(" {\n").append(" return ").append(staticChoiceGet).append(";\n") + .append(" }\n"); } } } @@ -1381,21 +1373,20 @@ private void generateChoiceEncoders(final Appendable out, final String bitSetCla final String argType = bitsetArgType(primitiveType); generateOptionEncodeJavadoc(out, INDENT, token); - new Formatter(out).format("\n" + - " public %1$s %2$s(final boolean value)\n" + - " {\n" + - "%3$s\n" + - " return this;\n" + - " }\n\n" + - " public static %4$s %2$s(final %4$s bits, final boolean value)\n" + - " {\n" + - "%5$s" + - " }\n", - bitSetClassName, - choiceName, - generateChoicePut(encoding.primitiveType(), choiceBitIndex, byteOrderStr), - argType, - generateStaticChoicePut(encoding.primitiveType(), choiceBitIndex)); + final String choicePut = generateChoicePut(encoding.primitiveType(), choiceBitIndex, byteOrderStr); + final String staticChoicePut = generateStaticChoicePut(encoding.primitiveType(), choiceBitIndex); + out.append("\n") + .append(" public ").append(bitSetClassName).append(" ").append(choiceName) + .append("(final boolean value)\n") + .append(" {\n") + .append(choicePut).append("\n") + .append(" return this;\n") + .append(" }\n\n") + .append(" public static ").append(argType).append(" ").append(choiceName) + .append("(final ").append(argType).append(" bits, final boolean value)\n") + .append(" {\n") + .append(staticChoicePut) + .append(" }\n"); } } } @@ -1458,18 +1449,16 @@ private CharSequence generateEnumBody(final Token token, final String enumName) { final String javaEncodingType = primitiveTypeName(token); - return String.format( - " private final %1$s value;\n\n" + - " %2$s(final %1$s value)\n" + + return + " private final " + javaEncodingType + " value;\n\n" + + " " + enumName + "(final " + javaEncodingType + " value)\n" + " {\n" + " this.value = value;\n" + " }\n\n" + - " public %1$s value()\n" + + " public " + javaEncodingType + " value()\n" + " {\n" + " return value;\n" + - " }\n", - javaEncodingType, - enumName); + " }\n"; } private CharSequence generateEnumLookupMethod(final List tokens, final String enumName) @@ -1516,41 +1505,31 @@ private String interfaceImportLine() private CharSequence generateFileHeader(final String packageName, final String fqBuffer) { - return String.format( + return "/* Generated SBE (Simple Binary Encoding) message codec */\n" + - "package %s;\n\n" + - "import %s;\n" + - "%s", - packageName, - fqBuffer, - interfaceImportLine()); + "package " + packageName + ";\n\n" + + "import " + fqBuffer + ";\n" + + interfaceImportLine(); } private CharSequence generateMainHeader(final String packageName) { if (fqMutableBuffer.equals(fqReadOnlyBuffer)) { - return String.format( + return "/* Generated SBE (Simple Binary Encoding) message codec */\n" + - "package %s;\n\n" + - "import %s;\n" + - "%s", - packageName, - fqMutableBuffer, - interfaceImportLine()); + "package " + packageName + ";\n\n" + + "import " + fqMutableBuffer + ";\n" + + interfaceImportLine(); } else { - return String.format( + return "/* Generated SBE (Simple Binary Encoding) message codec */\n" + - "package %s;\n\n" + - "import %s;\n" + - "import %s;\n" + - "%s", - packageName, - fqMutableBuffer, - fqReadOnlyBuffer, - interfaceImportLine()); + "package " + packageName + ";\n\n" + + "import " + fqMutableBuffer + ";\n" + + "import " + fqReadOnlyBuffer + ";\n" + + interfaceImportLine(); } } @@ -1834,12 +1813,11 @@ private CharSequence generateVarWrapFieldNotPresentCondition(final int sinceVers return ""; } - return String.format( - indent + " if (parentMessage.actingVersion < %d)\n" + + return + indent + " if (parentMessage.actingVersion < " + sinceVersion + ")\n" + indent + " {\n" + indent + " wrapBuffer.wrap(buffer, offset, 0);\n" + - indent + " }\n\n", - sinceVersion); + indent + " }\n\n"; } private CharSequence generateFieldNotPresentCondition( @@ -1850,13 +1828,12 @@ private CharSequence generateFieldNotPresentCondition( return ""; } - return String.format( - indent + " if (parentMessage.actingVersion < %d)\n" + + final String nullValue = generateLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString()); + return + indent + " if (parentMessage.actingVersion < " + sinceVersion + ")\n" + indent + " {\n" + - indent + " return %s;\n" + - indent + " }\n\n", - sinceVersion, - generateLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString())); + indent + " return " + nullValue + ";\n" + + indent + " }\n\n"; } private static CharSequence generateArrayFieldNotPresentCondition(final int sinceVersion, final String indent) @@ -1866,12 +1843,11 @@ private static CharSequence generateArrayFieldNotPresentCondition(final int sinc return ""; } - return String.format( - indent + " if (parentMessage.actingVersion < %d)\n" + + return + indent + " if (parentMessage.actingVersion < " + sinceVersion + ")\n" + indent + " {\n" + indent + " return 0;\n" + - indent + " }\n\n", - sinceVersion); + indent + " }\n\n"; } private static CharSequence generateStringNotPresentConditionForAppendable( @@ -1882,12 +1858,11 @@ private static CharSequence generateStringNotPresentConditionForAppendable( return ""; } - return String.format( - indent + " if (parentMessage.actingVersion < %d)\n" + + return + indent + " if (parentMessage.actingVersion < " + sinceVersion + ")\n" + indent + " {\n" + indent + " return 0;\n" + - indent + " }\n\n", - sinceVersion); + indent + " }\n\n"; } private static CharSequence generateStringNotPresentCondition(final int sinceVersion, final String indent) @@ -1897,12 +1872,11 @@ private static CharSequence generateStringNotPresentCondition(final int sinceVer return ""; } - return String.format( - indent + " if (parentMessage.actingVersion < %d)\n" + + return + indent + " if (parentMessage.actingVersion < " + sinceVersion + ")\n" + indent + " {\n" + indent + " return \"\";\n" + - indent + " }\n\n", - sinceVersion); + indent + " }\n\n"; } private static CharSequence generatePropertyNotPresentCondition( @@ -1917,13 +1891,12 @@ private static CharSequence generatePropertyNotPresentCondition( return ""; } - return String.format( - indent + " if (parentMessage.actingVersion < %d)\n" + + final String nullValue = enumName == null ? "null" : (enumName + ".NULL_VAL"); + return + indent + " if (parentMessage.actingVersion < " + propertyToken.version() + ")\n" + indent + " {\n" + - indent + " return %s;\n" + - indent + " }\n\n", - propertyToken.version(), - enumName == null ? "null" : (enumName + ".NULL_VAL")); + indent + " return " + nullValue + ";\n" + + indent + " }\n\n"; } private CharSequence generatePrimitiveArrayPropertyDecode( @@ -2244,13 +2217,12 @@ private static void generateCharacterEncodingMethod( { if (null != characterEncoding) { - new Formatter(sb).format("\n" + - indent + " public static String %sCharacterEncoding()\n" + - indent + " {\n" + - indent + " return \"%s\";\n" + - indent + " }\n", - formatPropertyName(propertyName), - characterEncoding); + final String propName = formatPropertyName(propertyName); + sb.append("\n") + .append(indent).append(" public static String ").append(propName).append("CharacterEncoding()\n") + .append(indent).append(" {\n") + .append(indent).append(" return \"").append(characterEncoding).append("\";\n") + .append(indent).append(" }\n"); } } @@ -2402,9 +2374,12 @@ private CharSequence generateFixedFlyweightCode( private CharSequence generateDecoderFlyweightCode(final String className, final Token token) { - final String wrapMethod = String.format( - " public %1$s wrap(\n" + - " final %2$s buffer, final int offset, final int actingBlockLength, final int actingVersion)\n" + + final String wrapMethod = + " public " + className + " wrap(\n" + + " final " + readOnlyBuffer + " buffer,\n" + + " final int offset,\n" + + " final int actingBlockLength,\n" + + " final int actingVersion)\n" + " {\n" + " if (buffer != this.buffer)\n" + " {\n" + @@ -2415,9 +2390,7 @@ private CharSequence generateDecoderFlyweightCode(final String className, final " this.actingVersion = actingVersion;\n" + " limit(offset + actingBlockLength);\n\n" + " return this;\n" + - " }\n\n", - className, - readOnlyBuffer); + " }\n\n"; return generateFlyweightCode(DECODER, className, token, wrapMethod, readOnlyBuffer); } @@ -2519,8 +2492,8 @@ private CharSequence generateFlyweightCode( private CharSequence generateEncoderFlyweightCode(final String className, final Token token) { - final String wrapMethod = String.format( - " public %1$s wrap(final %2$s buffer, final int offset)\n" + + final String wrapMethod = + " public " + className + " wrap(final " + mutableBuffer + " buffer, final int offset)\n" + " {\n" + " if (buffer != this.buffer)\n" + " {\n" + @@ -2529,9 +2502,7 @@ private CharSequence generateEncoderFlyweightCode(final String className, final " this.offset = offset;\n" + " limit(offset + BLOCK_LENGTH);\n\n" + " return this;\n" + - " }\n\n", - className, - mutableBuffer); + " }\n\n"; final StringBuilder builder = new StringBuilder( " public %1$s wrapAndApplyHeader(\n" + @@ -3320,10 +3291,7 @@ private void appendDecoderDisplay( } private int writeTokenDisplay( - final String fieldName, - final Token typeToken, - final StringBuilder sb, - final String indent) + final String fieldName, final Token typeToken, final StringBuilder sb, final String indent) { append(sb, indent, "//" + typeToken); From ae12b5f4e27f2e81a33444ebc562844d08229228 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 6 Aug 2019 19:06:08 +0100 Subject: [PATCH 0140/1594] [Java] Upgrade to javadoc-links 3.8.4. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b11bcba321..bb88adcff0 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.3' - id "io.freefair.javadoc-links" version "3.8.2" apply false + id "io.freefair.javadoc-links" version "3.8.4" apply false id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } From b49f8cb1cc15e52b6bebad158e2edf0389fefa8c Mon Sep 17 00:00:00 2001 From: billsegall Date: Wed, 7 Aug 2019 04:37:30 +0100 Subject: [PATCH 0141/1594] Release-1.13 changes and release notes --- csharp/README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/csharp/README.md b/csharp/README.md index 44156f2d47..13c60fa5c4 100644 --- a/csharp/README.md +++ b/csharp/README.md @@ -11,7 +11,7 @@ Java and gradlew are used to build the generator. git bash and shell scripts are used for scripting. -The C# code is built using Visual Studio Community 2017. +The C# code was originally built using Visual Studio Community 2017. The code, samples, tests and nuget package can be built/run using the [dotnet core sdk](https://www.microsoft.com/net/download): @@ -20,6 +20,13 @@ The code, samples, tests and nuget package can be built/run using the [dotnet co ## Release Notes +### 0.13 + +* Many build system improvements +* Better inlining support +* Issue #660 Add Length() and GetBytes() methods for VarStrings +* Add csharp code-gen time property that allows squashing of namespace + ### 0.1.8.1-beta-2 C# Span support has been added to the code generation, and a set of corresponding utilities added to sbe-dll `DirectBuffer`. It is now possible to copy to/from a `Span` where previously only `byte[]` types were supported. This introduces a dependency on the [`System.Memory`](https://www.nuget.org/packages/System.Memory/) nuget package both for sbe-dll and generated code produced by sbe-tool. @@ -78,8 +85,6 @@ For now you can: * build the SBE csharp generator using `gradlew` * generate the csharp codecs using `gradlew GenerateCSharpCodecs` - * Use the [Visual Studio 2017 Community solution](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/csharp.sln) to build the solution, run the unit tests, examples and benchmarks - * Use the command script - * [csharpbuild.cmd](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/csharpbuild.cmd) to build the dotnet core support + * Use the bash script [build.sh](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/build.sh) to run the tests * Use the bash script [runtests.sh](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/runtests.sh) to run the tests - * Build the nuget package via [do-release.sh](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/.nuget/do-release.sh) although this remains a largely manual process. + * Use the bash script [pack.sh](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/pack.sh) to create the nuget package From 23896cc470a8273c038262a2afcc3997dca4f966 Mon Sep 17 00:00:00 2001 From: billsegall Date: Wed, 7 Aug 2019 04:42:32 +0100 Subject: [PATCH 0142/1594] bump version to 1.3.0 --- csharp/README.md | 2 +- csharp/sbe-dll/sbe-dll.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/README.md b/csharp/README.md index 13c60fa5c4..67e970927a 100644 --- a/csharp/README.md +++ b/csharp/README.md @@ -20,7 +20,7 @@ The code, samples, tests and nuget package can be built/run using the [dotnet co ## Release Notes -### 0.13 +### 1.13.0 * Many build system improvements * Better inlining support diff --git a/csharp/sbe-dll/sbe-dll.csproj b/csharp/sbe-dll/sbe-dll.csproj index c695a2b072..2d6e6ae101 100644 --- a/csharp/sbe-dll/sbe-dll.csproj +++ b/csharp/sbe-dll/sbe-dll.csproj @@ -13,7 +13,7 @@ https://github.com/real-logic/simple-binary-encoding SBE;Marshaling;Low;Latency;Simple;Binary;Encoding sbe-dll - 0.1.12.1-beta-3 + 1.13.0 Simple Binary Encoding for .NET This package contains all you need to define SBE messages and generate C# encoders and decoders. See https://github.com/real-logic/simple-binary-encoding for more detailed instructions git From 07ff3fbfe853c5d3f52655fbf00723a29dd6e643 Mon Sep 17 00:00:00 2001 From: billsegall Date: Wed, 7 Aug 2019 04:48:50 +0100 Subject: [PATCH 0143/1594] Have the csharp section reflect current reality --- README.md | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index d0417c7f4b..9b7745b5cb 100644 --- a/README.md +++ b/README.md @@ -113,18 +113,9 @@ documentation](https://github.com/real-logic/simple-binary-encoding/blob/master/ C# Build -------- -As of May 2017, the CSharp build is considered a preview release. API stability is not yet guaranteed. User and Developer guides are not yet released or are incomplete. +Users of CSharp generated code should see the [user documentation](https://github.com/real-logic/simple-binary-encoding/wiki/Csharp-User-Guide). -First build using Gradle to generate the SBE jar and then use it to generate the C# code used for testing and the examples. - - $ ./gradlew - $ ./gradlew generateCSharpCodecs - -You can then use the [Visual Studio 2017 Community solution](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/csharp.sln) to build and explore the example. This solution also builds some tests which can be run via the provided [runtests.sh](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/runtests.sh) script. - -Users of CSharp generated code should see the [user documentation (coming)](https://github.com/real-logic/simple-binary-encoding/wiki/Csharp-User-Guide). - -Developers wishing to enhance the CSharp generator should see the [developer documentation (coming)](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/README.md) +Developers wishing to enhance the CSharp generator should see the [developer documentation](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/README.md) License (See LICENSE file for full license) From 75dc6d9aa07adc7265fdb0b26144e20bf616a9e1 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 7 Aug 2019 08:29:59 +0100 Subject: [PATCH 0144/1594] Update README.md --- csharp/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/csharp/README.md b/csharp/README.md index 67e970927a..ce103fb5da 100644 --- a/csharp/README.md +++ b/csharp/README.md @@ -68,8 +68,7 @@ The csharp generator is as of March 2018 a beta release. The current roadmap con Nuget Package ------------- -The nuget package can be built using ~csharp/.nuget/do-release.sh. It has a dependency on the [nuget.exe] -(https://dist.nuget.org/index.html). +The nuget package can be built using ~csharp/.nuget/do-release.sh. It has a dependency on the [nuget.exe](https://dist.nuget.org/index.html). Before release it will probbalty be necessary to copy in changed files for the example contained in the published nuget package. This is a manual process for now. From 02a0b98dd380a498c6e42f402bc43e004ea26d88 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 7 Aug 2019 08:30:38 +0100 Subject: [PATCH 0145/1594] Update README.md --- csharp/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/README.md b/csharp/README.md index ce103fb5da..0cdc47e9e0 100644 --- a/csharp/README.md +++ b/csharp/README.md @@ -68,7 +68,7 @@ The csharp generator is as of March 2018 a beta release. The current roadmap con Nuget Package ------------- -The nuget package can be built using ~csharp/.nuget/do-release.sh. It has a dependency on the [nuget.exe](https://dist.nuget.org/index.html). +The nuget package can be built using ~csharp/.nuget/do-release.sh. It has a dependency on the [nuget](https://dist.nuget.org/index.html). Before release it will probbalty be necessary to copy in changed files for the example contained in the published nuget package. This is a manual process for now. From 67e2c36497980a1dca279fa18a3fb3bc87184893 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 7 Aug 2019 08:31:11 +0100 Subject: [PATCH 0146/1594] Update README.md --- csharp/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/README.md b/csharp/README.md index 0cdc47e9e0..ce103fb5da 100644 --- a/csharp/README.md +++ b/csharp/README.md @@ -68,7 +68,7 @@ The csharp generator is as of March 2018 a beta release. The current roadmap con Nuget Package ------------- -The nuget package can be built using ~csharp/.nuget/do-release.sh. It has a dependency on the [nuget](https://dist.nuget.org/index.html). +The nuget package can be built using ~csharp/.nuget/do-release.sh. It has a dependency on the [nuget.exe](https://dist.nuget.org/index.html). Before release it will probbalty be necessary to copy in changed files for the example contained in the published nuget package. This is a manual process for now. From ef6b036446e4b6933c29a28184ba9264f86f0b8a Mon Sep 17 00:00:00 2001 From: Feras Date: Wed, 10 Apr 2019 02:11:24 -0400 Subject: [PATCH 0147/1594] [Java] Python generator implementation #665 --- build.gradle | 33 + python/tests/__init__.py | 0 python/tests/gen/.gitignore | 2 + python/tests/test_car_example.py | 189 +++ .../sbe/generation/python/PyGenerator.java | 1368 +++++++++++++++++ .../generation/python/PyOutputManager.java | 71 + .../sbe/generation/python/PyUtil.java | 242 +++ .../sbe/generation/python/Python.java | 35 + .../generation/python/PyGeneratorTest.java | 39 + 9 files changed, 1979 insertions(+) create mode 100644 python/tests/__init__.py create mode 100644 python/tests/gen/.gitignore create mode 100644 python/tests/test_car_example.py create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyOutputManager.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java diff --git a/build.gradle b/build.gradle index bb88adcff0..220fe1be48 100644 --- a/build.gradle +++ b/build.gradle @@ -770,6 +770,39 @@ task uploadToMavenCentral { 'sbe-all:uploadShadow' } +/** + * Python tests and benchmarks + */ +task generatePythonCarExample(type: JavaExec) { + main = 'uk.co.real_logic.sbe.SbeTool' + classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'python/tests', + 'sbe.target.language': 'uk.co.real_logic.sbe.generation.python.Python', + 'sbe.target.namespace': 'gen.car_example') + args = ['sbe-tool/src/test/resources/example-schema.xml'] +} + +task generatePythonExampleDataFile(type: JavaExec) { + main = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub' + classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath + systemProperties('sbe.encoding.filename': 'python/tests/gen/car_example/car_example_data.sbe') + args = [] + standardOutput = new FileOutputStream("python/tests/gen/car_example/car_example_decode.out") +} + +task generatePythonCodecs { + description = 'Generate python test codecs' + dependsOn 'generatePythonCarExample', 'generatePythonExampleDataFile' +} + +task runPythonTests(type: Exec) { + workingDir = './python/' + executable = 'python' + args = ['-m','unittest','discover'] + dependsOn 'generatePythonCodecs' +} + wrapper { gradleVersion = '5.5.1' distributionType = 'ALL' diff --git a/python/tests/__init__.py b/python/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/python/tests/gen/.gitignore b/python/tests/gen/.gitignore new file mode 100644 index 0000000000..c96a04f008 --- /dev/null +++ b/python/tests/gen/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/python/tests/test_car_example.py b/python/tests/test_car_example.py new file mode 100644 index 0000000000..d821423ecf --- /dev/null +++ b/python/tests/test_car_example.py @@ -0,0 +1,189 @@ +import unittest +from pathlib import Path + +from tests.gen.car_example import MessageHeader, Car, BooleanType, Model, Engine, BoostType + + +class TestCarExample(unittest.TestCase): + REFERENCE_FILE_ENCODE = Path(__file__).resolve().parent / Path('gen') / 'car_example' / 'car_example_data.sbe' + + VEHICLE_CODE = "abcdef".encode(Car.VEHICLE_CODE_CHAR_ENCODING) + MANUFACTURER_CODE = "123".encode(Engine.MANUFACTURER_CODE_CHAR_ENCODING) + MANUFACTURER = "Honda".encode(Car.MANUFACTURER_CHAR_ENCODING) + MODEL = "Civic VTi".encode(Car.MODEL_CHAR_ENCODING) + ACTIVATION_CODE = "abcdef".encode(Car.ACTIVATION_CODE_CHAR_ENCODING) + + CAR = Car() + MESSAGE_HEADER = MessageHeader() + + def test_encoding(self): + with open(self.REFERENCE_FILE_ENCODE, 'rb') as f: + buffer = f.read() + py_buf = bytearray(4096) + self._encode(py_buf, self.MESSAGE_HEADER, self.CAR) + # Encoded message should match + self.assertEqual(buffer, py_buf[:211]) + # The empty part of the buffer should be all 0's + self.assertEqual(bytes(len(py_buf) - len(buffer)), py_buf[len(buffer):]) + self.assertEqual(211, len(buffer)) + + def test_decoding(self): + self.maxDiff = None + with open(self.REFERENCE_FILE_ENCODE, 'rb') as f: + buffer = f.read() + py_buf = bytearray(4096) + self._encode(py_buf, self.MESSAGE_HEADER, self.CAR) + self._decode(py_buf, self.MESSAGE_HEADER, self.CAR) + self._decode(buffer, self.MESSAGE_HEADER, self.CAR) + + def _encode(self, buf: bytes, header: MessageHeader, car: Car): + offset = 0 + header.wrap(buf, offset) + header.set_block_length(Car.BLOCK_LENGTH) + header.set_schema_id(Car.SCHEMA_ID) + header.set_template_id(Car.SCHEMA_ID) + header.set_version(Car.SCHEMA_VERSION) + + car.wrap_encode(buf, offset + MessageHeader.SIZE) + car.set_serial_number(1234) + car.set_model_year(2013) + car.set_available(BooleanType.T) + car.set_code(Model.A) + car.set_vehicle_code(self.VEHICLE_CODE) + + for i in range(Car.SOME_NUMBERS_LENGTH): + car.put_some_numbers(i, i) + + car.set_extras() \ + .clear() \ + .set_cruise_control(True) \ + .set_sports_pack(True) \ + .set_sun_roof(False) + + car.set_engine() \ + .set_capacity(2000) \ + .set_num_cylinders(4) \ + .set_manufacturer_code(self.MANUFACTURER_CODE) \ + .set_efficiency(35) \ + .set_booster_enabled(BooleanType.T) \ + .set_booster() \ + .set_boost_type(BoostType.NITROUS) \ + .set_horse_power(200) + + ff = car.set_fuel_figures_count(3) + ff.next().set_speed(30).set_mpg(35.9).set_usage_description("Urban Cycle".encode(Car.FuelFiguresGroup.USAGE_DESCRIPTION_CHAR_ENCODING)) + ff.next().set_speed(55).set_mpg(49.0).set_usage_description("Combined Cycle".encode(Car.FuelFiguresGroup.USAGE_DESCRIPTION_CHAR_ENCODING)) + ff.next().set_speed(75).set_mpg(40.0).set_usage_description("Highway Cycle".encode(Car.FuelFiguresGroup.USAGE_DESCRIPTION_CHAR_ENCODING)) + + figures = car.set_performance_figures_count(2) + figures.next().set_octane_rating(95).set_acceleration_count(3) \ + .next().set_mph(30).set_seconds(4.0) \ + .next().set_mph(60).set_seconds(7.5) \ + .next().set_mph(100).set_seconds(12.2) + + figures.next().set_octane_rating(99).set_acceleration_count(3) \ + .next().set_mph(30).set_seconds(3.8) \ + .next().set_mph(60).set_seconds(7.1) \ + .next().set_mph(100).set_seconds(11.8) + + car.set_manufacturer(self.MANUFACTURER).set_model(self.MODEL).set_activation_code(self.ACTIVATION_CODE) + + return MessageHeader.SIZE + car.size() + + def _decode(self, buf: bytes, header: MessageHeader, car: Car): + offset = 0 + out = "" + header.wrap(buf, offset) + template_id = header.get_template_id() + if template_id != Car.TEMPLATE_ID: + raise Exception("Template ID missmatch") + acting_block_length = header.get_block_length() + acting_block_version = header.get_version() + offset += header.SIZE + + car.wrap_decode(buf, offset, acting_block_length, acting_block_version) + self.assertEqual(1234, car.get_serial_number()) + self.assertEqual(2013, car.get_model_year()) + self.assertEqual(BooleanType.T, car.get_available()) + self.assertEqual(Model.A, car.get_code()) + self.assertEqual((0, 1, 2, 3, 4), car.get_multi_some_numbers()) + self.assertEqual(0, car.get_some_numbers(0)) + self.assertEqual(1, car.get_some_numbers(1)) + self.assertEqual(2, car.get_some_numbers(2)) + self.assertEqual(3, car.get_some_numbers(3)) + self.assertEqual(4, car.get_some_numbers(4)) + index_oob = False + try: + car.get_some_numbers(55) + except IndexError as e: + index_oob = True + self.assertEqual(IndexError, type(e)) + self.assertTrue(index_oob) + + self.assertEqual("abcdef", str(car.get_multi_vehicle_code(), car.VEHICLE_CODE_CHAR_ENCODING)) + + extras = car.get_extras() + self.assertTrue(extras.has_cruise_control()) + self.assertTrue(extras.has_sports_pack()) + self.assertFalse(extras.has_sun_roof()) + + self.assertEqual("C", car.get_discounted_model().name) + + engine = car.get_engine() + self.assertEqual(2000, engine.get_capacity()) + self.assertEqual(4, engine.get_num_cylinders()) + self.assertEqual(9000, engine.get_max_rpm) + self.assertEqual("123", str(engine.get_multi_manufacturer_code(), Engine.MANUFACTURER_CODE_CHAR_ENCODING)) + self.assertEqual(35, engine.get_efficiency()) + self.assertEqual(BooleanType.T, engine.get_booster_enabled()) + self.assertEqual(BoostType.NITROUS, engine.get_booster().get_boost_type()) + self.assertEqual(200, engine.get_booster().get_horse_power()) + + self.assertEqual("Petrol", str(engine.get_fuel(0, len(buf)).tobytes().decode())) + + ff = car.get_fuel_figures() + ff.next() + self.assertEqual(30, ff.get_speed()) + self.assertAlmostEqual(35.9, ff.get_mpg(), places=5) + self.assertEqual("Urban Cycle", ff.get_usage_description().tobytes().decode(Car.FuelFiguresGroup.USAGE_DESCRIPTION_CHAR_ENCODING)) + ff.next() + self.assertEqual(55, ff.get_speed()) + self.assertAlmostEqual(49.0, ff.get_mpg(), places=5) + self.assertEqual("Combined Cycle", ff.get_usage_description().tobytes().decode(Car.FuelFiguresGroup.USAGE_DESCRIPTION_CHAR_ENCODING)) + ff.next() + self.assertEqual(75, ff.get_speed()) + self.assertAlmostEqual(40.0, ff.get_mpg(), places=5) + self.assertEqual("Highway Cycle", ff.get_usage_description().tobytes().decode(Car.FuelFiguresGroup.USAGE_DESCRIPTION_CHAR_ENCODING)) + + pf = car.get_performance_figures() + pf.next() + self.assertEqual(95, pf.get_octane_rating()) + pfa = pf.get_acceleration() + pfa.next() + self.assertEqual(30, pfa.get_mph()) + self.assertAlmostEqual(4.0, pfa.get_seconds(), places=5) + pfa.next() + self.assertEqual(60, pfa.get_mph()) + self.assertAlmostEqual(7.5, pfa.get_seconds(), places=5) + pfa.next() + self.assertEqual(100, pfa.get_mph()) + self.assertAlmostEqual(12.2, pfa.get_seconds(), places=5) + + pf.next() + self.assertEqual(99, pf.get_octane_rating()) + pfa = pf.get_acceleration() + pfa.next() + self.assertEqual(30, pfa.get_mph()) + self.assertAlmostEqual(3.8, pfa.get_seconds(), places=5) + pfa.next() + self.assertEqual(60, pfa.get_mph()) + self.assertAlmostEqual(7.1, pfa.get_seconds(), places=5) + pfa.next() + self.assertEqual(100, pfa.get_mph()) + self.assertAlmostEqual(11.8, pfa.get_seconds(), places=5) + + self.assertEqual("Honda", car.get_manufacturer().tobytes().decode(Car.MANUFACTURER_CHAR_ENCODING)) + self.assertEqual("Civic VTi", car.get_model().tobytes().decode(Car.MODEL_CHAR_ENCODING)) + self.assertEqual("abcdef", car.get_activation_code().tobytes().decode(Car.ACTIVATION_CODE_CHAR_ENCODING)) + self.assertEqual(203, car.size()) + return out diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java new file mode 100644 index 0000000000..415c75c573 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java @@ -0,0 +1,1368 @@ +/* + * Copyright 2013-2019 Real Logic Ltd. + * Copyright (C) 2017 MarketFactory, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.python; + +import org.agrona.Verify; +import org.agrona.generation.OutputManager; +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.PrimitiveValue; +import uk.co.real_logic.sbe.generation.CodeGenerator; +import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.generation.csharp.CSharpUtil; +import uk.co.real_logic.sbe.generation.java.JavaUtil; +import uk.co.real_logic.sbe.ir.Encoding; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.ir.Signal; +import uk.co.real_logic.sbe.ir.Token; + +import java.io.IOException; +import java.io.Writer; +import java.nio.ByteOrder; +import java.util.*; + +import static uk.co.real_logic.sbe.generation.java.JavaUtil.generateLiteral; +import static uk.co.real_logic.sbe.generation.python.PyUtil.*; +import static uk.co.real_logic.sbe.ir.GenerationUtil.*; + +public class PyGenerator implements CodeGenerator { + private static final String META_ATTRIBUTE_ENUM = "MetaAttribute"; + private static final String INDENT = " "; + private static final String BASE_INDENT = INDENT; + + private final Ir ir; + private final OutputManager outputManager; + + public PyGenerator(final Ir ir, final OutputManager outputManager) { + Verify.notNull(ir, "ir"); + Verify.notNull(outputManager, "outputManager"); + + this.ir = ir; + this.outputManager = outputManager; + } + + public void generateMessageHeaderStub(final List modules) throws IOException { + generateComposite(ir.headerStructure().tokens(), modules); + } + + public void generateTypeStubs(List modules) throws IOException { + generateMetaAttributeEnum(); + + for (final List tokens : ir.types()) { + switch (tokens.get(0).signal()) { + case BEGIN_ENUM: + generateEnum(tokens, modules); + break; + + case BEGIN_SET: + generateBitSet(tokens, modules); + break; + + case BEGIN_COMPOSITE: + generateComposite(tokens, modules); + break; + } + } + } + + public void generate() throws IOException { + List modules = new ArrayList<>(); + generateMessageHeaderStub(modules); + generateTypeStubs(modules); + for (final List tokens : ir.messages()) { + final Token msgToken = tokens.get(0); + final String className = formatClassName(msgToken.name()); + String pyModuleName = camToSnake(className); + try (Writer out = outputManager.createOutput(pyModuleName)) { + modules.add(pyModuleName); + final List messageBody = getMessageBody(tokens); + int offset = 0; + + final List fields = new ArrayList<>(); + offset = collectFields(messageBody, offset, fields); + + out.append(generateFileHeader(ir.applicableNamespace(), messageBody, true)); + out.append(generateClassDeclaration(className)); + out.append(generateMessageFlyweightCode(className, msgToken, BASE_INDENT, fields)); + + out.append(generateFields(fields, BASE_INDENT, className)); + + final StringBuilder sb = new StringBuilder(); + final List groups = new ArrayList<>(); + offset = collectGroups(messageBody, offset, groups); + generateGroups(sb, className, groups, BASE_INDENT); + out.append(sb); + + final List varData = new ArrayList<>(); + collectVarData(messageBody, offset, varData); + out.append(generateVarData(varData, BASE_INDENT, className)); + } + } + generateStructParsers(); + generatePackageDefinition(modules); + } + + public void generatePackageDefinition(List modules) throws IOException { + try (Writer out = outputManager.createOutput("__init__")) { + out.append(generateFileHeader(ir.applicableNamespace(), new ArrayList<>(), false)); + for (String m : modules) { + out.append("from ." + m + " import *\n"); + } + out.append("from .meta_attribute import *\n"); + } + } + + private void generateGroups( + final StringBuilder sb, + final String parentMessageClassName, + final List tokens, + final String indent) { + for (int i = 0, size = tokens.size(); i < size; i++) { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + final String groupName = groupToken.name(); + + generateGroupClassHeader(sb, groupName, parentMessageClassName, tokens, i, indent); + i++; + i += tokens.get(i).componentTokenCount(); + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + sb.append(generateFields(fields, indent + INDENT, parentMessageClassName + "." + formatClassName(groupName) + "Group")); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + generateGroups(sb, parentMessageClassName + "." + formatClassName(groupName) + "Group", groups, indent + INDENT); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + sb.append(generateVarData(varData, indent + INDENT, parentMessageClassName + "." + formatClassName(groupName) + "Group")); + + sb.append(generateGroupProperty(groupName, groupToken, indent, parentMessageClassName)); + + } + } + + private void generateGroupClassHeader( + final StringBuilder sb, + final String groupName, + final String parentMessageClassName, + final List tokens, + final int index, + final String indent) { + final String dimensionsClassName = formatClassName(tokens.get(index + 1).name()); + final int dimensionHeaderLength = tokens.get(index + 1).encodedLength(); + String topLevelParentMessageClassName = parentMessageClassName.split("\\.")[0]; + sb.append(String.format("\n" + + indent + "class %1$sGroup:\n" + + indent + INDENT + "__slots__ = '_dimensions', '_parent_message', '_buffer', '_block_length', '_acting_version', '_count', '_index', '_offset'\n\n" + + indent + INDENT + "def __init__(self):\n" + + indent + INDENT + INDENT + "self._dimensions: '%2$s' = %2$s()\n" + + indent + INDENT + INDENT + "self._parent_message: '%3$s'\n" + + indent + INDENT + INDENT + "self._buffer: Union[bytes, bytearray, memoryview]\n" + + indent + INDENT + INDENT + "self._block_length: int\n" + + indent + INDENT + INDENT + "self._acting_version: int\n" + + indent + INDENT + INDENT + "self._count: int\n" + + indent + INDENT + INDENT + "self._index: int\n" + + indent + INDENT + INDENT + "self._offset: int\n", + formatClassName(groupName), + dimensionsClassName, + topLevelParentMessageClassName)); + + final int blockLength = tokens.get(index).encodedLength(); + sb.append(String.format("\n" + + indent + INDENT + "SBE_BLOCK_LENGTH: int = %d\n" + + indent + INDENT + "SBE_HEADER_SIZE: int = %d\n", + blockLength, + dimensionHeaderLength)); + + final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); + + sb.append(String.format("\n" + + indent + INDENT + "def wrap_decode(self, parent_message: '%1$s' , buffer: Union[bytes, bytearray, memoryview], acting_version: int):\n" + + indent + INDENT + INDENT + "self._parent_message = parent_message\n" + + indent + INDENT + INDENT + "self._buffer = buffer\n" + + indent + INDENT + INDENT + "self._dimensions.wrap(buffer, parent_message.limit)\n" + + indent + INDENT + INDENT + "self._block_length = self._dimensions.get_block_length()\n" + + indent + INDENT + INDENT + "self._count = self._dimensions.get_num_in_group()\n" + + indent + INDENT + INDENT + "self._acting_version = acting_version\n" + + indent + INDENT + INDENT + "self._index = -1\n" + + indent + INDENT + INDENT + "self._parent_message.set_limit(self._parent_message.limit + self.SBE_HEADER_SIZE)\n" + + indent + INDENT + INDENT + "return self\n", + topLevelParentMessageClassName, + formatClassName(groupName))); + + final String typeForBlockLength = pythonTypeName(tokens.get(index + 2).encoding().primitiveType()); + final String typeForNumInGroup = pythonTypeName(numInGroupToken.encoding().primitiveType()); + + sb.append(String.format("\n" + + indent + INDENT + "def wrap_encode(self, parent_message: '%1$s', buffer: Union[bytes, bytearray, memoryview], count: int):\n" + + indent + INDENT + INDENT + "if count < %2$d or count > %3$d:\n" + + indent + INDENT + INDENT + INDENT + "raise IndexError('Count Outside allowed range: count='+ str(count) +', min=%2$d, max=%3$d')\n" + + indent + INDENT + INDENT + "self._parent_message = parent_message\n" + + indent + INDENT + INDENT + "self._buffer = buffer\n" + + indent + INDENT + INDENT + "self._dimensions.wrap(buffer, parent_message.limit)\n" + + indent + INDENT + INDENT + "self._dimensions.set_block_length(%4$s(%5$d))\n" + + indent + INDENT + INDENT + "self._dimensions.set_num_in_group(%6$s(count))\n" + + indent + INDENT + INDENT + "self._index = -1\n" + + indent + INDENT + INDENT + "self._count = count\n" + + indent + INDENT + INDENT + "self._block_length = %5$d\n" + + indent + INDENT + INDENT + "self._acting_version = self._parent_message.SCHEMA_VERSION\n" + + indent + INDENT + INDENT + "self._parent_message.set_limit(parent_message.limit + self.SBE_HEADER_SIZE)\n" + + indent + INDENT + INDENT + "return self\n", + topLevelParentMessageClassName, + numInGroupToken.encoding().applicableMinValue().longValue(), + numInGroupToken.encoding().applicableMaxValue().longValue(), + typeForBlockLength, + blockLength, + typeForNumInGroup)); + + + sb.append("\n"); + generateGroupEnumerator(sb, groupName, indent + INDENT, parentMessageClassName); + } + + private void generateGroupEnumerator(final StringBuilder sb, final String groupName, final String indent, final String parentClassName) { + sb.append(indent + "@property\n" + + indent + "def acting_block_length(self) -> int:\n" + + indent + INDENT + "return self._block_length\n\n" + + indent + "@property\n" + + indent + "def count(self) -> int:\n" + + indent + INDENT + "return self._count\n\n" + + indent + "@property\n" + + indent + "def has_next(self) -> bool:\n" + + indent + INDENT + "return (self._index + 1) < self._count\n"); + + sb.append(String.format("\n" + + indent + "def next(self) -> '%2$s.%1$sGroup':\n" + + indent + INDENT + "if self._index + 1 >= self._count:\n" + + indent + INDENT + INDENT + "raise IndexError()\n" + + indent + INDENT + "self._offset = self._parent_message.limit\n" + + indent + INDENT + "self._parent_message.set_limit(self._offset + self._block_length)\n" + + indent + INDENT + "self._index += 1\n" + + indent + INDENT + "return self\n", + formatClassName(groupName), parentClassName)); + + sb.append(String.format("\n" + + indent + "def generator(self) -> Generator['%2$s.%1$sGroup', None, None]:\n" + + indent + INDENT + "while self.has_next:\n" + + indent + INDENT + INDENT + "yield self.next()\n", + formatClassName(groupName), parentClassName + )); + } + + private CharSequence generateGroupProperty(final String groupName, final Token token, final String indent, final String parentMessageClassName) { + final StringBuilder sb = new StringBuilder(); + + final String className = CSharpUtil.formatClassName(groupName); + + sb.append(String.format("\n" + + indent + "%S_ID: int = %d\n", + camToSnake(groupName), + token.id())); + + sb.append(String.format("\n" + + indent + "_%1$s_group: '%2$sGroup' = %2$sGroup()\n", + camToSnake(groupName), + formatClassName(groupName), + token.id())); + + generateSinceActingDeprecated(sb, indent, toUpperFirstChar(groupName), token); + + sb.append(String.format("\n" + + indent + "def get_%2$s(self) -> '" + parentMessageClassName + ".%1$sGroup':\n" + + indent + INDENT + "self._%3$s_group.wrap_decode(self._parent_message, self._buffer, self._parent_message.SCHEMA_VERSION)\n" + + indent + INDENT + "return self._%3$s_group\n", + className, + camToSnake(groupName), + camToSnake(groupName))); + + sb.append(String.format("\n" + + indent + "def set_%2$s_count(self, count:int) -> '" + parentMessageClassName + ".%1$sGroup':\n" + + indent + INDENT + "self._%3$s_group.wrap_encode(self._parent_message, self._buffer, count)\n" + + indent + INDENT + "return self._%3$s_group\n", + className, + camToSnake(groupName), + camToSnake(groupName))); + + return sb; + } + + private CharSequence generateVarData(final List tokens, final String indent, String parentClassName) { + final StringBuilder sb = new StringBuilder(); + + for (int i = 0, size = tokens.size(); i < size; i++) { + final Token token = tokens.get(i); + if (token.signal() == Signal.BEGIN_VAR_DATA) { + generateFieldIdMethod(sb, token, indent); + + final Token varDataToken = Generators.findFirst("varData", tokens, i); + final String characterEncoding = varDataToken.encoding().characterEncoding(); + generateCharacterEncodingMethod(sb, token.name(), characterEncoding, indent); + generateFieldMetaAttributeMethod(sb, token, indent); + + final String propertyName = toUpperFirstChar(token.name()); + final Token lengthToken = Generators.findFirst("length", tokens, i); + final int sizeOfLengthField = lengthToken.encodedLength(); + final Encoding lengthEncoding = lengthToken.encoding(); + final String lengthCSharpType = pythonTypeName(lengthEncoding.primitiveType()); + final String lengthTypePrefix = toUpperFirstChar(lengthEncoding.primitiveType().primitiveName()); + final ByteOrder byteOrder = lengthEncoding.byteOrder(); + final String byteOrderStr = byteOrder.toString(); + + sb.append(String.format("\n" + + indent + "%1$S_HEADER_SIZE: int = %2$d\n", + camToSnake(propertyName), + sizeOfLengthField)); + + sb.append(String.format("\n" + + indent + "def get_%1$s(self) -> memoryview:\n" + + "%2$s" + + indent + INDENT + "size_of_len_field: int = %3$d\n" + + indent + INDENT + "limit:int = self._parent_message.limit\n" + + indent + INDENT + "#self._buffer.CheckLimit(limit + size_of_len_field);\n" + + indent + INDENT + "data_length: int = %4$S_%5$S.unpack_from(self._buffer, limit)[0]\n" + + indent + INDENT + "self._parent_message.set_limit(limit + size_of_len_field + data_length)\n" + + indent + INDENT + "return memoryview(self._buffer)[limit + size_of_len_field:limit + size_of_len_field+data_length]\n", + camToSnake(propertyName), + generateArrayFieldNotPresentCondition(token.version(), indent), + sizeOfLengthField, + lengthTypePrefix, + byteOrderStr)); + + sb.append(String.format("\n" + + indent + "def set_%1$s(self, data: Union[bytes, bytearray, memoryview]) -> '%7$s':\n" + + indent + INDENT + "size_of_len_field: int = %2$d\n" + + indent + INDENT + "limit:int = self._parent_message.limit\n" + + indent + INDENT + "self._parent_message.set_limit(limit + size_of_len_field + len(data))\n" + + indent + INDENT + "data_len = len(data)\n" + + indent + INDENT + "%3$S_%5$S.pack_into(self._buffer, limit, %4$s(data_len))\n" + + indent + INDENT + "struct.pack_into('%6$s%%ds' %% (data_len,), self._buffer, limit + size_of_len_field, data)\n" + + indent + INDENT + "return self\n\n", + camToSnake(propertyName), + sizeOfLengthField, + lengthTypePrefix, + lengthCSharpType, + byteOrderStr, + pythonEndianCode(byteOrder), + parentClassName)); + } + } + + return sb; + } + + private void generateBitSet(final List tokens, final List modules) throws IOException { + final Token bitSetToken = tokens.get(0); + final String bitSetName = formatClassName(bitSetToken.applicableTypeName()); + List messageBody = getMessageBody(tokens); + try (Writer out = outputManager.createOutput(camToSnake(bitSetName))) { + modules.add(camToSnake(bitSetName)); + out.append(generateFileHeader(ir.applicableNamespace(), messageBody, true)); + out.append(generateClassDeclaration(bitSetName)); + out.append(generateMessageFlyweightCode(bitSetName, bitSetToken, BASE_INDENT, new ArrayList<>())); + out.append(generateChoiceIsEmpty(bitSetToken.encoding().primitiveType(), bitSetToken.encoding().byteOrder())); + out.append(generateChoiceDecoders(messageBody)); + out.append(generateChoiceDisplay(messageBody)); + out.append(generateChoiceClear(bitSetName, bitSetToken)); + out.append(generateChoiceEncoders(bitSetName, messageBody)); + + } + } + + private void generateEnum(final List tokens, final List modules) throws IOException { + final Token enumToken = tokens.get(0); + final String enumName = formatClassName(enumToken.applicableTypeName()); + List messageBody = getMessageBody(tokens); + try (Writer out = outputManager.createOutput(camToSnake(enumName))) { + modules.add(camToSnake(enumName)); + out.append(generateFileHeader(ir.applicableNamespace(), messageBody, true)); + final String enumPrimitiveType = pythonTypeName(enumToken.encoding().primitiveType()); + out.append(generateEnumDeclaration(enumName, enumPrimitiveType)); + out.append(generateEnumValues(messageBody, enumToken)); + } + } + + private void generateComposite(final List tokens, final List modules) throws IOException { + final String compositeName = formatClassName(tokens.get(0).applicableTypeName()); + + try (Writer out = outputManager.createOutput(camToSnake(compositeName))) { + modules.add(camToSnake(compositeName)); + out.append(generateFileHeader(ir.applicableNamespace(), getMessageBody(tokens), true)); + out.append(generateClassDeclaration(compositeName)); + out.append(generateFixedFlyweightCode(tokens.get(0).encodedLength(), getMessageBody(tokens))); + out.append(generateCompositePropertyElements(getMessageBody(tokens), BASE_INDENT, compositeName)); + + } + } + + private CharSequence generateCompositePropertyElements(final List tokens, final String indent, String className) { + final StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < tokens.size(); ) { + final Token token = tokens.get(i); + final String propertyName = formatPropertyName(token.name()); + + // FIXME: do I need to pass classname down here for disambiguation + switch (token.signal()) { + case ENCODING: + sb.append(generatePrimitiveProperty(propertyName, token, indent, className)); + break; + + case BEGIN_ENUM: + sb.append(generateEnumProperty(propertyName, token, null, indent, className)); + break; + + case BEGIN_SET: + sb.append(generateBitSetProperty(propertyName, token, indent)); + break; + + case BEGIN_COMPOSITE: + sb.append(generateCompositeProperty(propertyName, token, indent)); + break; + } + + i += tokens.get(i).componentTokenCount(); + } + + return sb; + } + + private CharSequence generateChoiceEncoders(final String bitSetClassName, final List tokens) { + return concatTokens( + tokens, + Signal.CHOICE, + (token) -> + { + final String choiceName = formatPropertyName(token.name()); + final Encoding encoding = token.encoding(); + final String choiceBitIndex = encoding.constValue().toString(); + final PrimitiveType primitiveType = encoding.primitiveType(); + + return String.format("\n" + + INDENT + "def set_%2$s(self, value: bool) -> '%1$s':\n" + + "%3$s\n\n" + + INDENT + "@staticmethod\n" + + INDENT + "def apply_%2$s(bits: '%4$s', value: bool) -> '%4$s':\n" + + "%5$s\n", + bitSetClassName, + camToSnake(choiceName), + generateChoicePut(primitiveType, choiceBitIndex, encoding.byteOrder()), + "int", + generateStaticChoicePut(primitiveType, choiceBitIndex)); + }); + } + + private CharSequence generateChoiceDisplay(final List tokens) { + final String indent = INDENT; + final StringBuilder sb = new StringBuilder(); + + sb.append('\n'); + sb.append(indent + "def __repr__(self):\n"); + sb.append(indent + indent + "at_least_one = False\n"); + sb.append(indent + indent + "out = \"{\"\n"); + tokens + .stream() + .filter((token) -> token.signal() == Signal.CHOICE) + .forEach((token) -> + { + final String choiceName = formatPropertyName(token.name()); + sb.append(indent + indent + "if self.has_" + camToSnake(choiceName) + "():\n"); + sb.append(indent + indent + indent + "if at_least_one:\n"); + sb.append(indent + indent + indent + indent + "out += \",\"\n"); + sb.append(indent + indent + indent + "out += \"" + choiceName + "\"\n"); + sb.append(indent + indent + indent + "at_least_one = True\n"); + }); + sb.append(indent + indent + "out += \"}\"\n"); + sb.append('\n'); + sb.append(indent + indent + "return out\n"); + + return sb.toString(); + } + + private CharSequence generateChoiceDecoders(final List tokens) { + return concatTokens( + tokens, + Signal.CHOICE, + (token) -> + { + final String choiceName = formatPropertyName(token.name()); + final Encoding encoding = token.encoding(); + final String choiceBitIndex = encoding.constValue().toString(); + final PrimitiveType primitiveType = encoding.primitiveType(); + + return String.format("\n" + + " def has_%1$s(self) -> bool:\n" + + " return %2$s\n\n" + + " @staticmethod\n" + + " def check_%1$s(value: '%3$s') -> bool:\n" + + " return %4$s\n" + + " \n", + camToSnake(choiceName), + generateChoiceGet(primitiveType, choiceBitIndex, encoding.byteOrder()), + "int", + generateStaticChoiceGet(primitiveType, choiceBitIndex)); + }); + } + + private String generateChoiceIsEmpty(final PrimitiveType type, final ByteOrder byteOrder) { + return "\n" + + " @property\n" + + " def is_empty(self) -> bool:\n" + + " return " + generateChoiceIsEmptyInner(type, byteOrder) + "\n" + + " \n"; + } + + private String generateChoiceIsEmptyInner(final PrimitiveType type, final ByteOrder byteOrder) { + switch (type) { + case UINT8: + return "0 == " + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + ".unpack_from(self._buffer, self._offset)[0]"; + } + + throw new IllegalArgumentException("primitive type not supported: " + type); + } + + private String generateChoicePut(final PrimitiveType type, final String bitIdx, final ByteOrder byteOrder) { + switch (type) { + case UINT8: + case UINT16: + case UINT32: + case UINT64: + return + INDENT + INDENT + "bits = " + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + ".unpack_from(self._buffer, self._offset)[0]\n" + + INDENT + INDENT + "bits = (bits | (1 << " + bitIdx + ")) if value else (bits & ~(1 << " + bitIdx + "))\n" + + INDENT + INDENT + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + ".pack_into(self._buffer, self._offset, bits)\n" + + INDENT + INDENT + "return self\n"; + + } + + throw new IllegalArgumentException("primitive type not supported: " + type); + } + + private String generateStaticChoicePut(final PrimitiveType type, final String bitIdx) { + switch (type) { + case UINT8: + case UINT16: + case UINT32: + case UINT64: + return INDENT + INDENT + "return (bits | (1 << " + bitIdx + ")) if value else (bits & ~(1 << " + bitIdx + "))\n"; + } + + throw new IllegalArgumentException("primitive type not supported: " + type); + } + + private String generateStaticChoiceGet(final PrimitiveType type, final String bitIndex) { + switch (type) { + case UINT8: + case UINT16: + case UINT32: + case UINT64: + return "0 != (value & (1 << " + bitIndex + "))"; + } + + throw new IllegalArgumentException("primitive type not supported: " + type); + } + + private String generateChoiceGet(final PrimitiveType type, final String bitIndex, final ByteOrder byteOrder) { + String ending = byteOrder.toString().toUpperCase(); + switch (type) { + case UINT8: + case UINT16: + case UINT32: + case UINT64: + return "0 != (" + type.primitiveName().toUpperCase() + "_" + ending + ".unpack_from(self._buffer, self._offset)[0] & (1 << " + bitIndex + "))"; + } + + throw new IllegalArgumentException("primitive type not supported: " + type); + } + + private CharSequence generateChoiceClear(final String bitSetClassName, final Token token) { + final StringBuilder sb = new StringBuilder(); + + final Encoding encoding = token.encoding(); + final String literalValue = generateLiteral(encoding.primitiveType(), "0"); + + sb.append(String.format("\n" + + " def clear(self) -> '%s':\n" + + " %2$S_%4$S.pack_into(self._buffer, self._offset, %3$s)\n" + + " return self\n" + + " \n", + bitSetClassName, + encoding.primitiveType().primitiveName(), + literalValue, + encoding.byteOrder())); + + return sb; + } + + private CharSequence generateEnumValues(final List tokens, final Token encodingToken) { + final StringBuilder sb = new StringBuilder(); + final Encoding encoding = encodingToken.encoding(); + + for (final Token token : tokens) { + sb.append(INDENT).append(token.name()).append(" = ") + .append(token.encoding().constValue()).append("\n"); + } + + final PrimitiveValue nullVal = encoding.applicableNullValue(); + + sb.append(INDENT).append("NULL_VALUE = ").append(nullVal).append("\n"); + + return sb; + } + + private CharSequence generateFileHeader(final String packageName, List tokens, boolean imports) { + StringBuilder sb = new StringBuilder("\"\"\"\n Generated SBE (Simple Binary Encoding) message codec\n"); + sb.append("Package: ").append(packageName); + sb.append("\"\"\"\n\n"); + if (imports) { + sb.append(generateImports(tokens)); + } + sb.append("\n"); + return sb; + } + + private CharSequence generateImports(List tokens) { + StringBuilder sb = new StringBuilder(); + Set processed = new HashSet<>(); + sb.append("from typing import *\n"); + sb.append("import struct\n"); + sb.append("from ._struct_defs import *\n"); + sb.append("from .meta_attribute import MetaAttribute\n"); + for (Token t : tokens) { + if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET || t.signal() == Signal.BEGIN_ENUM) { + String importName = t.referencedName() != null ? formatClassName(t.referencedName()) : formatClassName(t.name()); + if (processed.contains(importName)) { + continue; + } + sb.append("from .").append(camToSnake(importName)).append(" import ").append(importName).append("\n"); + processed.add(importName); + } + } + return sb; + } + + private void generateStructParsers() throws IOException { + try (Writer out = outputManager.createOutput("_struct_defs")) { + out.append(generateFileHeader(ir.applicableNamespace(), new ArrayList<>(), false)); + out.append("from struct import Struct\n\n"); + StringBuilder builder = new StringBuilder(); + for (Map.Entry order : BYTE_ORDER_STRING_MAP.entrySet()) { + for (Map.Entry type : PRIMITIVE_TYPE_STRUCT_ENUM_MAP.entrySet()) { + builder.append(String.format("%1$S_%2$S: Struct = Struct('%3$s%4$s')\n", + type.getKey().primitiveName(), + order.getKey().toString(), + pythonEndianCode(order.getKey()), + pythonTypeCode(type.getKey()))); + } + //edge case to handle char[] unpacking + builder.append(String.format("%1$S_%2$S: Struct = Struct('%3$s%4$s')\n", + "CHARS", + order.getKey().toString(), + pythonEndianCode(order.getKey()), + "s")); + } + + builder.append("\n"); + out.append(builder.toString()); + } + } + + private CharSequence generateClassDeclaration(final String className) { + return String.format("class %s:\n", className); + } + + private void generateMetaAttributeEnum() throws IOException { + try (Writer out = outputManager.createOutput(camToSnake(META_ATTRIBUTE_ENUM))) { + out.append(generateFileHeader(ir.applicableNamespace(), new ArrayList<>(), false)); + out.append( + "from enum import IntEnum \n\n" + + "class MetaAttribute(IntEnum):\n" + + INDENT + "Epoch = 1\n" + + INDENT + "TimeUnit = 2\n" + + INDENT + "SemanticType = 3\n" + + INDENT + "Presence = 4\n"); + } + } + + private CharSequence generateEnumDeclaration(final String name, final String primitiveType) { + + return "from enum import IntEnum \n\n" + + "class " + name + "(IntEnum):\n"; + } + + private CharSequence generatePrimitiveProperty(final String propertyName, final Token token, final String indent, String parentClassName) { + final StringBuilder sb = new StringBuilder(); + + sb.append(generatePrimitiveFieldMetaData(propertyName, token, indent)); + + if (token.isConstantEncoding()) { + sb.append(generateConstPropertyMethods(propertyName, token, indent)); + } else { + sb.append(generatePrimitivePropertyMethods(propertyName, token, indent, parentClassName)); + } + + return sb; + } + + private CharSequence generatePrimitivePropertyMethods( + final String propertyName, + final Token token, + final String indent, + final String parentClassName) { + final int arrayLength = token.arrayLength(); + + if (arrayLength == 1) { + return generateSingleValueProperty(propertyName, token, indent, parentClassName); + } else if (arrayLength > 1) { + return generateArrayProperty(propertyName, token, indent, parentClassName); + } + + return ""; + } + + private CharSequence generatePrimitiveFieldMetaData( + final String propertyName, + final Token token, + final String indent) { + final PrimitiveType primitiveType = token.encoding().primitiveType(); + final String typeName = pythonTypeName(primitiveType); + + return String.format( + "\n" + + indent + "%2$s_NULL_VALUE: '%1$s' = %3$s\n" + + indent + "%2$s_MIN_VALUE: '%1$s' = %4$s\n" + + indent + "%2$s_MAX_VALUE: '%1$s' = %5$s\n", + typeName, + camToSnake(propertyName).toUpperCase(), + generateLiteral(primitiveType, token.encoding().applicableNullValue().toString()), + generateLiteral(primitiveType, token.encoding().applicableMinValue().toString()), + generateLiteral(primitiveType, token.encoding().applicableMaxValue().toString())); + } + + private CharSequence generateSingleValueProperty( + final String propertyName, + final Token token, + final String indent, + final String parentClassName) { + final String typeName = pythonTypeName(token.encoding().primitiveType()); + final String typePrefix = toUpperFirstChar(token.encoding().primitiveType().primitiveName()); + final int offset = token.offset(); + final ByteOrder byteOrder = token.encoding().byteOrder(); + final String byteOrderStr = byteOrder.toString(); + + String getter = String.format("\n" + + indent + "def get_%2$s(self) -> '%1$s':\n" + + "%3$s" + + indent + INDENT + "return %4$S_%6$S.unpack_from(self._buffer, self._offset + %5$d)[0]", + typeName, + camToSnake(propertyName), + generateFieldNotPresentCondition(token.version(), token.encoding(), indent), + typePrefix.toUpperCase(), + offset, + byteOrderStr); + + String setter = String.format("\n" + + indent + "def set_%2$s(self, value:%1$s) -> '%3$s':\n" + + indent + INDENT + "%4$S_%6$s.pack_into(self._buffer, self._offset + %5$d, value)\n" + + indent + INDENT + "return self\n", + typeName, + camToSnake(propertyName), + formatClassName(parentClassName), + typePrefix.toUpperCase(), + offset, + byteOrderStr); + return getter + "\n" + setter + "\n"; + } + + private CharSequence generateFieldNotPresentCondition( + final int sinceVersion, + final Encoding encoding, + final String indent) { + if (0 == sinceVersion) { + return ""; + } + + final String literal; + if (sinceVersion > 0) { + literal = generateLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString()); + } else { + literal = "(byte)0"; + } + + return String.format( + indent + "if self._acting_version < %1$d: return %2$s\n\n", + sinceVersion, + literal); + } + + private CharSequence generateArrayFieldNotPresentCondition( + final int sinceVersion, + final String indent) { + if (0 == sinceVersion) { + return ""; + } + + return String.format( + indent + "if self._acting_version < %d: return 0\n\n", + sinceVersion); + } + + private CharSequence generateTypeFieldNotPresentCondition( + final int sinceVersion, + final String indent) { + if (0 == sinceVersion) { + return ""; + } + + return String.format( + indent + "if self._acting_version < %d: return None\n\n", + sinceVersion); + } + + private CharSequence generateArrayProperty( + final String propertyName, + final Token token, + final String indent, + final String parentClassName) { + final String typeName = pythonTypeName(token.encoding().primitiveType()); + final String typePrefix = toUpperFirstChar(token.encoding().primitiveType().primitiveName()); + final int offset = token.offset(); + final ByteOrder byteOrder = token.encoding().byteOrder(); + final String byteOrderStr = byteOrder.toString(); + final int fieldLength = token.arrayLength(); + final int typeSize = token.encoding().primitiveType().size(); + final String propName = toUpperFirstChar(propertyName); + + final StringBuilder sb = new StringBuilder(); + + sb.append(String.format("\n" + + indent + "%1$S_LENGTH = %2$d\n", + camToSnake(propName), fieldLength)); + + String structParserMulti = String.format("A_%1$S_%2$S_%3$S", camToSnake(propName), typePrefix, byteOrderStr); + + sb.append(String.format("\n" + + indent + structParserMulti + " = Struct('%1$s%2$d%3$s') \n", + pythonEndianCode(byteOrder), fieldLength, + pythonTypeCode(token.encoding().primitiveType()))); + + if (token.encoding().primitiveType() == PrimitiveType.CHAR) { + generateCharacterEncodingMethod(sb, propertyName, token.encoding().characterEncoding(), indent); + //Properties for multi item assignment + sb.append(String.format("\n" + + indent + "def get_multi_%2$s(self) -> bytes:\n" + + "%4$s" + + indent + INDENT + "return self." + structParserMulti + ".unpack_from(self._buffer, self._offset + %5$d)[0]\n", + typeName, camToSnake(propName), fieldLength, + generateFieldNotPresentCondition(token.version(), token.encoding(), indent), + offset, typeSize)); + } else { + //Properties for multi item assignment + sb.append(String.format("\n" + + indent + "def get_multi_%2$s(self) -> Tuple['%1$s']:\n" + + "%4$s" + + indent + INDENT + "return self." + structParserMulti + ".unpack_from(self._buffer, self._offset + %5$d)\n", + typeName, camToSnake(propName), fieldLength, + generateFieldNotPresentCondition(token.version(), token.encoding(), indent), + offset, typeSize)); + } + + + sb.append(String.format("\n" + + indent + "def set_%1$s(self, value:%2$s) -> '%4$s':\n" + + indent + INDENT + "self." + structParserMulti + ".pack_into(self._buffer, self._offset + %3$d, value)\n" + + indent + INDENT + "return self\n", + camToSnake(propName), typeName, offset, parentClassName)); + + //Properties for single assigment + sb.append(String.format("\n" + + indent + "def get_%2$s(self, index: int) -> '%1$s':\n" + + indent + INDENT + "if index < 0 or index >= %3$d:\n" + + indent + INDENT + INDENT + "raise IndexError(\"index out of range: index=\" + str(index))\n\n" + + "%4$s" + + indent + INDENT + "return %5$S_%8$S.unpack_from(self._buffer, self._offset + %6$d + (index * %7$d))[0]\n", + typeName, camToSnake(propName), fieldLength, + generateFieldNotPresentCondition(token.version(), token.encoding(), indent), typePrefix, + offset, typeSize, byteOrder)); + + sb.append(String.format("\n" + + indent + "def put_%1$s(self, index:int, value:%2$s) -> '%8$s':\n" + + indent + INDENT + "if index < 0 or index >= %3$d:\n" + + indent + INDENT + INDENT + "raise IndexError(\"index out of range: index=\" + str(index))\n\n" + + indent + INDENT + "%4$S_%7$S.pack_into(self._buffer, self._offset + %5$d + (index * %6$d), value)\n" + + indent + INDENT + "return self\n", + camToSnake(propName), typeName, fieldLength, typePrefix, offset, typeSize, byteOrder, parentClassName)); + + + return sb; + } + + private void generateCharacterEncodingMethod( + final StringBuilder sb, + final String propertyName, + final String encoding, + final String indent) { + sb.append(String.format("\n" + + indent + "%S_CHAR_ENCODING = \"%s\"\n\n", + camToSnake(formatPropertyName(propertyName)), + encoding)); + } + + private CharSequence generateConstPropertyMethods( + final String propertyName, + final Token token, + final String indent) { + if (token.encoding().primitiveType() != PrimitiveType.CHAR) { + // ODE: we generate a property here because the constant could + // become a field in a newer version of the protocol + return String.format("\n" + + indent + "@property\n" + + indent + "def get_%2$s(self) -> '%1$s':\n" + + indent + INDENT + " return %3$s\n", + pythonTypeName(token.encoding().primitiveType()), + camToSnake(propertyName), + generateLiteral(token.encoding().primitiveType(), token.encoding().constValue().toString())); + } + + final StringBuilder sb = new StringBuilder(); + + final String pyTypeName = pythonTypeName(token.encoding().primitiveType()); + final byte[] constantValue = token.encoding().constValue().byteArrayValue(token.encoding().primitiveType()); + final CharSequence values = generateByteLiteralList( + token.encoding().constValue().byteArrayValue(token.encoding().primitiveType())); + + sb.append(String.format( + "\n" + + indent + "_%1$S_VALUE: Union[bytes, bytearray, memoryview] = bytes([ %2$s ])\n", + camToSnake(propertyName), + values)); + + sb.append(String.format( + "\n" + + indent + "%1$S_LENGTH: int = %2$d\n", + camToSnake(propertyName).toUpperCase(), + constantValue.length)); + sb.append("\n"); + sb.append(String.format( + indent + "def %2$s(self, index: int) -> '%1$s':\n" + + indent + INDENT + "return self._%3$s_VALUE[index]\n", + pyTypeName, + camToSnake(propertyName), + camToSnake(propertyName).toUpperCase())); + sb.append("\n"); + + sb.append(String.format( + indent + "def get_%1$s(self, offset: int, length: int) -> memoryview:\n" + + indent + INDENT + "last = min(length, %2$d)\n" + + indent + INDENT + "offset = min(abs(offset), %3$d)\n" + + indent + INDENT + "return memoryview(self._%4$S_VALUE)[offset:last]\n", + camToSnake(propertyName), + constantValue.length, + constantValue.length - 1, + propertyName)); + + return sb; + } + + private CharSequence generateByteLiteralList(final byte[] bytes) { + final StringBuilder values = new StringBuilder(); + for (final byte b : bytes) { + values.append(b).append(", "); + } + + if (values.length() > 0) { + values.setLength(values.length() - 2); + } + + return values; + } + + private CharSequence generateFixedFlyweightCode(final int size, final List tokens) { + //reserve __slots__ to improve performance for instance fields + StringBuilder builder = new StringBuilder(); + Map fieldTypes = new LinkedHashMap<>(); + for (Token t : tokens) { + if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET) { + fieldTypes.put("_" + t.name(), t.referencedName()); + } + } + List fields = new ArrayList<>(fieldTypes.keySet()); + builder.append(INDENT + "__slots__ = '_offset', '_buffer'"); + if (fields.size() > 0) { + builder.append(", '" + String.join("', '", fields) + "'"); + } + builder.append("\n\n"); + builder.append(String.format( + INDENT + "SIZE: int = %d \n\n" + + INDENT + "def __init__(self):\n" + + INDENT + INDENT + "self._offset: int \n" + + INDENT + INDENT + "self._buffer: int \n", size)); + for (Map.Entry field : fieldTypes.entrySet()) { + builder.append(INDENT + INDENT + "self." + field.getKey() + ": '" + field.getValue() + "' = " + field.getValue() + "()\n"); + } + builder.append("\n"); + + builder.append(INDENT + "def wrap(self, buffer: Union[bytes, bytearray, memoryview], offset: int):\n" + + INDENT + INDENT + "self._offset = offset\n" + + INDENT + INDENT + "self._buffer = buffer\n" + + INDENT + INDENT + "return self\n"); + return builder.toString(); + } + + + private CharSequence generateMessageFlyweightCode(final String className, final Token token, final String indent, + final List fields) { + final String blockLengthType = pythonTypeName(ir.headerStructure().blockLengthType()); + final String templateIdType = pythonTypeName(ir.headerStructure().templateIdType()); + final String schemaIdType = pythonTypeName(ir.headerStructure().schemaIdType()); + final String schemaVersionType = pythonTypeName(ir.headerStructure().schemaVersionType()); + final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); + StringBuilder builder = new StringBuilder(); + Map fieldTypes = new LinkedHashMap<>(); + for (Token t : fields) { + if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET) { + fieldTypes.put("_" + camToSnake(t.name()), t.referencedName() != null ? t.referencedName() : t.name()); + } + } + builder.append(String.format( + indent + "BLOCK_LENGTH: '%1$s' = %2$s\n" + + indent + "TEMPLATE_ID: '%3$s' = %4$s\n" + + indent + "SCHEMA_ID: '%5$s' = %6$s\n" + + indent + "SCHEMA_VERSION: '%7$s' = %8$s\n" + + indent + "SEMANTIC_TYPE: str = \"%9$s\"\n\n", + blockLengthType, + generateLiteral(ir.headerStructure().blockLengthType(), Integer.toString(token.encodedLength())), + templateIdType, + generateLiteral(ir.headerStructure().templateIdType(), Integer.toString(token.id())), + schemaIdType, + generateLiteral(ir.headerStructure().schemaIdType(), Integer.toString(ir.id())), + schemaVersionType, + generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), + semanticType)); + + builder.append(indent + "__slots__ = '_parent_message', '_buffer', '_offset', '_limit', '_acting_block_length', '_acting_version'"); + if (fieldTypes.size() > 0) { + builder.append(", '" + String.join("', '", fieldTypes.keySet()) + "'"); + } + builder.append("\n\n"); + + builder.append(String.format(indent + "def __init__(self):\n" + + indent + INDENT + "self._parent_message: '%1$s' = self\n" + + indent + INDENT + "self._buffer: Union[bytes, bytearray, memoryview]\n" + + indent + INDENT + "self._offset: int\n" + + indent + INDENT + "self._limit: int\n" + + indent + INDENT + "self._acting_block_length: int\n" + + indent + INDENT + "self._acting_version: int\n", className)); + for (Map.Entry ft : fieldTypes.entrySet()) { + builder.append(indent + INDENT + "self." + ft.getKey() + ": '" + ft.getValue() + "' = " + ft.getValue() + "()\n"); + } + builder.append("\n"); + + builder.append( + indent + "@property\n" + + indent + "def offset(self) -> int:\n" + + indent + INDENT + "return self._offset\n\n" + + indent + "def wrap_encode(self, buffer: Union[bytes, bytearray, memoryview], offset: int):\n" + + indent + INDENT + "self._buffer = buffer\n" + + indent + INDENT + "self._offset = offset\n" + + indent + INDENT + "self._acting_block_length = self.BLOCK_LENGTH\n" + + indent + INDENT + "self._acting_version = self.SCHEMA_VERSION\n" + + indent + INDENT + "self.set_limit(offset + self._acting_block_length)\n" + + indent + INDENT + "return self\n"); + builder.append("\n"); + + builder.append( + indent + "def wrap_decode(self,buffer: Union[bytes, bytearray, memoryview], offset: int, " + + "acting_block_length: int, acting_version:int):\n" + + indent + INDENT + "self._buffer = buffer\n" + + indent + INDENT + "self._offset = offset\n" + + indent + INDENT + "self._acting_block_length = acting_block_length\n" + + indent + INDENT + "self._acting_version = acting_version\n" + + indent + INDENT + "self.set_limit(offset + self._acting_block_length)\n" + + indent + INDENT + "return self\n"); + builder.append("\n"); + + builder.append( + indent + "def size(self) -> int:\n" + + indent + INDENT + "return self._limit - self._offset\n" + + indent + "\n\n" + + indent + "@property\n" + + indent + "def limit(self) -> int:\n" + + indent + INDENT + "return self._limit\n"); + builder.append("\n"); + + builder.append( + indent + "def set_limit(self, value):\n" + + //TODO: make sure the capacity is checked either wrap in bytearray + indent + INDENT + "#self._buffer.CheckLimit(value);\n" + + indent + INDENT + "self._limit = value\n" + + indent + INDENT + "return self\n"); + + return builder.toString(); + } + + private CharSequence generateFields(final List tokens, final String indent, final String parentClassName) { + final StringBuilder sb = new StringBuilder(); + + for (int i = 0, size = tokens.size(); i < size; i++) { + final Token signalToken = tokens.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) { + final Token encodingToken = tokens.get(i + 1); + final String propertyName = signalToken.name(); + + generateFieldIdMethod(sb, signalToken, indent); + generateFieldMetaAttributeMethod(sb, signalToken, indent); + + switch (encodingToken.signal()) { + case ENCODING: + sb.append(generatePrimitiveProperty(propertyName, encodingToken, indent, parentClassName)); + break; + + case BEGIN_ENUM: + sb.append(generateEnumProperty(propertyName, encodingToken, signalToken, indent, parentClassName)); + break; + + case BEGIN_SET: + sb.append(generateBitSetProperty(propertyName, encodingToken, indent)); + break; + + case BEGIN_COMPOSITE: + sb.append(generateCompositeProperty(propertyName, encodingToken, indent)); + break; + } + } + } + + return sb; + } + + private void generateFieldIdMethod(final StringBuilder sb, final Token token, final String indent) { + sb.append(String.format("\n" + + indent + "%S_ID: int = %d\n", + camToSnake(token.name()), + token.id())); + + generateSinceActingDeprecated(sb, indent, token.name(), token); + } + + private void generateFieldMetaAttributeMethod(final StringBuilder sb, final Token token, final String indent) { + final Encoding encoding = token.encoding(); + final String epoch = encoding.epoch() == null ? "" : encoding.epoch(); + final String timeUnit = encoding.timeUnit() == null ? "" : encoding.timeUnit(); + final String semanticType = encoding.semanticType() == null ? "" : encoding.semanticType(); + final String presence = encoding.presence() == null ? "" : encoding.presence().toString().toLowerCase(); + + sb.append(String.format("\n" + + indent + "@staticmethod\n" + + indent + "def %s_meta_attribute(meta_attribute: 'MetaAttribute') -> str:\n" + + indent + INDENT + "if meta_attribute == MetaAttribute.Epoch: return '%s'\n" + + indent + INDENT + "if meta_attribute == MetaAttribute.TimeUnit: return '%s'\n" + + indent + INDENT + "if meta_attribute == MetaAttribute.SemanticType: return '%s'\n" + + indent + INDENT + "if meta_attribute == MetaAttribute.Presence: return '%s'\n" + + indent + INDENT + "return ''\n", + camToSnake(token.name()), + epoch, + timeUnit, + semanticType, + presence)); + } + + private CharSequence generateEnumFieldNotPresentCondition( + final int sinceVersion, + final String enumName, + final String indent) { + if (0 == sinceVersion) { + return ""; + } + + return String.format( + indent + "if self._acting_version < %d: return %s.NULL_VALUE\n\n", + sinceVersion, + enumName); + } + + private CharSequence generateEnumProperty( + final String propertyName, + final Token token, + final Token signalToken, + final String indent, + final String parentClassName) { + final String enumName = formatClassName(token.applicableTypeName()); + final String typePrefix = toUpperFirstChar(token.encoding().primitiveType().primitiveName()); + final String typeName = pythonTypeName(token.encoding().primitiveType()); + final String enumUnderlyingType = pythonTypeName(token.encoding().primitiveType()); + final int offset = token.offset(); + final ByteOrder byteOrder = token.encoding().byteOrder(); + final String byteOrderStr = byteOrder.toString(); + + if (signalToken != null && signalToken.isConstantEncoding()) { + final String constValue = signalToken.encoding().constValue().toString(); + + return String.format("\n" + + indent + "@staticmethod\n" + + indent + "def get_%2$s() -> '%1$s':\n" + + indent + INDENT + "return %3$s\n", + enumName, + camToSnake(propertyName), + constValue); + } else { + String enumStructType = typePrefix; + if (typePrefix.toUpperCase().equals("CHAR")) { + enumStructType = "INT8"; + } + String getter = String.format( + indent + "def get_%2$s(self) -> '%1$s':\n" + + "%3$s" + + indent + INDENT + "return %4$s(%5$S_%7$S.unpack_from(self._buffer, self._offset + %6$d)[0])\n\n", + enumName, + camToSnake(propertyName), + generateEnumFieldNotPresentCondition(token.version(), enumName, indent), + enumName, + enumStructType, + offset, + byteOrderStr, + enumUnderlyingType); + + String cast = enumUnderlyingType + "(value)"; + if (enumUnderlyingType.equals("bytes") && enumStructType.equals("INT8")) { + cast = "value"; + } else if (enumUnderlyingType.equals("bytes")) { + cast = "bytes([value])"; + } + String setter = String.format("\n" + + indent + "def set_%2$s(self, value: '%4$s') -> '%9$s':\n" + + "%3$s" + + indent + INDENT + "%5$S_%8$S.pack_into(self._buffer, self._offset + %7$d, %10$s)\n" + + indent + INDENT + "return self\n\n", + enumName, + camToSnake(propertyName), + generateEnumFieldNotPresentCondition(token.version(), enumName, indent), + enumName, + enumStructType, + typeName, + offset, + byteOrderStr, + parentClassName, + cast); + return getter + setter; + } + } + + private String generateBitSetProperty(final String propertyName, final Token token, final String indent) { + final String bitSetName = formatClassName(token.applicableTypeName()); + final int offset = token.offset(); + + String getter = String.format("\n" + + indent + "def get_%2$s(self) -> '%1$s':\n" + + "%3$s" + + indent + INDENT + "return self._%5$s.wrap_decode(self._buffer, self._offset + %4$d, self._acting_block_length, self._acting_version)\n", + bitSetName, + camToSnake(propertyName), + generateTypeFieldNotPresentCondition(token.version(), indent), + offset, + camToSnake(bitSetName)); + + String setter = String.format("\n" + + indent + "def set_%3$s(self) -> '%1$s':\n" + + indent + INDENT + "return self._%2$s.wrap_encode(self._buffer, self._offset + %4$d)\n", + bitSetName, + camToSnake(bitSetName), + camToSnake(propertyName), + offset); + return getter + setter; + } + + private Object generateCompositeProperty(final String propertyName, final Token token, final String indent) { + final String compositeName = formatClassName(token.applicableTypeName()); + final int offset = token.offset(); + final StringBuilder sb = new StringBuilder(); + + sb.append(String.format("\n" + + indent + "def set_%2$s(self) -> '%1$s':\n" + + "%3$s" + + indent + INDENT + "self._%4$s.wrap(self._buffer, self._offset + %5$d)\n" + + indent + INDENT + "return self._%4$s\n", + compositeName, + camToSnake(propertyName), + generateTypeFieldNotPresentCondition(token.version(), indent), + camToSnake(propertyName), + offset)); + + sb.append(String.format("\n" + + indent + "def get_%2$s(self) -> '%1$s':\n" + + "%3$s" + + indent + INDENT + "self._%4$s.wrap(self._buffer, self._offset + %5$d)\n" + + indent + INDENT + "return self._%4$s\n", + compositeName, + camToSnake(propertyName), + generateTypeFieldNotPresentCondition(token.version(), indent), + camToSnake(propertyName), + offset)); + + return sb; + } + + private void generateSinceActingDeprecated( + final StringBuilder sb, + final String indent, + final String propertyName, + final Token token) { + sb.append(String.format( + indent + "%1$S_SINCE_VERSION: int = %2$d\n" + + indent + "%1$S_DEPRECATED: int = %3$d\n\n" + + indent + "@property\n" + + indent + "def %1$s_in_acting_version(self) -> bool:\n" + + indent + INDENT + "return self._acting_version >= self.%1$S_SINCE_VERSION\n", + camToSnake(propertyName), + token.version(), + token.deprecated())); + } + + private String generateLiteral(final PrimitiveType type, final String value) { + String literal = ""; + + switch (type) { + case CHAR: + literal = "\"" + value + "\""; + break; + case UINT8: + case INT8: + case INT16: + case UINT16: + case UINT32: + case INT64: + case INT32: + literal = value; + break; + case UINT64: + literal = Long.toUnsignedString(Long.parseLong(value)); + break; + case FLOAT: + case DOUBLE: + if (value.endsWith("NaN")) { + literal = "float('nan')"; + } else { + literal = value; + } + break; + } + + return literal; + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyOutputManager.java new file mode 100644 index 0000000000..fe2fe8d3c0 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyOutputManager.java @@ -0,0 +1,71 @@ +/* + * Copyright 2013-2019 Real Logic Ltd. + * Copyright (C) 2017 MarketFactory, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.python; + +import org.agrona.Verify; +import org.agrona.generation.OutputManager; + +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; + +import static java.io.File.separatorChar; + +/** + * The character encoding for the {@link Writer} is UTF-8. + */ +public class PyOutputManager implements OutputManager { + private final File outputDir; + + /** + * Create a new {@link OutputManager} for generating C# source + * files into a given package. + * + * @param baseDirName for the generated source code. + * @param packageName for the generated source code relative to the baseDirName. + */ + public PyOutputManager(final String baseDirName, final String packageName) { + Verify.notNull(baseDirName, "baseDirName"); + Verify.notNull(packageName, "packageName"); + final String dirName = baseDirName.endsWith("" + separatorChar) ? baseDirName : baseDirName + separatorChar; + final String packageDirName = dirName + packageName.replace('.', File.separatorChar); + + outputDir = new File(packageDirName); + if (!outputDir.exists() && !outputDir.mkdirs()) { + throw new IllegalStateException("Unable to create directory: " + packageDirName); + } + + } + + /** + * Create a new output which will be a C# source file in the given package. + *

    + * The {@link Writer} should be closed once the caller has finished with it. The Writer is + * buffer for efficient IO operations. + * + * @param name the name of the C# class. + * @return a {@link Writer} to which the source code should be written. + * @throws IOException if an issue occurs when creating the file. + */ + public Writer createOutput(final String name) throws IOException { + final File targetFile = new File(outputDir, name + ".py"); + return Files.newBufferedWriter(targetFile.toPath(), StandardCharsets.UTF_8); + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java new file mode 100644 index 0000000000..0d24dd32ea --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java @@ -0,0 +1,242 @@ +/* + * Copyright 2013-2019 Real Logic Ltd. + * Copyright (C) 2017 MarketFactory, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.python; + +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.ir.Token; + +import java.nio.ByteOrder; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * Utilities for mapping between IR and Python + */ +public class PyUtil +{ + public static final Map PRIMITIVE_TYPE_STRING_ENUM_MAP = new EnumMap<>(PrimitiveType.class); + public static final Map PRIMITIVE_TYPE_STRUCT_ENUM_MAP = new EnumMap<>(PrimitiveType.class); + public static final Map PRIMITIVE_TYPE_SIZE_ENUM_MAP = new EnumMap<>(PrimitiveType.class); + public static final Map BYTE_ORDER_STRING_MAP = new HashMap<>(); + public static final Pattern CAM_SNAKE_PATTERN = Pattern.compile("([a-z])([A-Z]+)"); + + // Ref: https://docs.python.org/3.7/library/struct.html#format-characters + static + { + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.CHAR, "bytes"); + PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.CHAR, "s"); + PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.CHAR, 1); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.INT8, "int"); + PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.INT8, "b"); + PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.INT8, 1); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.INT16, "int"); + PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.INT16, "h"); + PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.INT16, 2); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.INT32, "int"); + PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.INT32, "i"); + PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.INT32, 4); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.INT64, "int"); + PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.INT64, "q"); + PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.INT64, 8); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.UINT8, "int"); + PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.UINT8, "B"); + PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.UINT8, 1); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.UINT16, "int"); + PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.UINT16, "H"); + PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.UINT16, 2); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.UINT32, "int"); + PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.UINT32, "I"); + PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.UINT32, 4); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.UINT64, "int"); + PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.UINT64, "Q"); + PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.UINT64, 8); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.FLOAT, "float"); + PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.FLOAT, "f"); + PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.FLOAT, 4); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.DOUBLE, "float"); + PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.DOUBLE, "d"); + PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.DOUBLE, 8); + BYTE_ORDER_STRING_MAP.put(ByteOrder.LITTLE_ENDIAN, "<"); + BYTE_ORDER_STRING_MAP.put(ByteOrder.BIG_ENDIAN, ">"); + } + + /** + * Map the name of a {@link PrimitiveType} to a Python C primitive type name. + * + * @param primitiveType to map. + * @return the name of the Python struct primitive that most closely maps. + */ + public static String pythonTypeName(final PrimitiveType primitiveType) + { + return PRIMITIVE_TYPE_STRING_ENUM_MAP.get(primitiveType); + } + + /** + * https://docs.python.org/3/library/struct.html + * @param primitiveType + * @return A string representation for python c struct unpacking + */ + public static String pythonTypeCode(final PrimitiveType primitiveType){ + return PRIMITIVE_TYPE_STRUCT_ENUM_MAP.get(primitiveType); + } + + /** + * https://docs.python.org/3/library/struct.html + * @param byteOrder + * @return python struct unpacking code for endianess + */ + public static String pythonEndianCode(final ByteOrder byteOrder){ + return BYTE_ORDER_STRING_MAP.get(byteOrder); + } + + /** + * Uppercase the first character of a given String. + * + * @param str to have the first character upper cased. + * @return a new String with the first character in uppercase. + */ + public static String toUpperFirstChar(final String str) + { + return Character.toUpperCase(str.charAt(0)) + str.substring(1); + } + + /** + * Lowercase the first character of a given String. + * + * @param str to have the first character upper cased. + * @return a new String with the first character in uppercase. + */ + public static String toLowerFirstChar(final String str) + { + return Character.toLowerCase(str.charAt(0)) + str.substring(1); + } + + /** + * Format a String as a property name. + * + * @param str to be formatted. + * @return the string formatted as a property name. + */ + public static String formatPropertyName(final String str) + { + return toUpperFirstChar(str); + } + + /** + * Format a String as a class name. + * + * @param str to be formatted. + * @return the string formatted as a class name. + */ + public static String formatClassName(final String str) + { + return toUpperFirstChar(str); + } + + /** + * Converts CamelCase to snake_case, which is the recommended python case + * @param str + * @param toUpperFirst + * @return + */ + public static String camToSnake(final String str, boolean toUpperFirst){ + if(toUpperFirst){ + return CAM_SNAKE_PATTERN.matcher(toUpperFirstChar(str)).replaceAll("$1_$2").toLowerCase(); + } + return CAM_SNAKE_PATTERN.matcher(str).replaceAll("$1_$2").toLowerCase(); + } + + /** + * @see {@link #camToSnake} + */ + public static String camToSnake(final String str){ + return camToSnake(str, true); + } + + /** + * Generate the Pydoc comment header for a type. + * + * @param indent level for the comment. + * @param typeToken for the type. + * @return a string representation of the Javadoc comment. + */ + public static String generateTypePydoc(final String indent, final Token typeToken) + { + final String description = typeToken.description(); + if (null == description || description.isEmpty()) + { + return ""; + } + + return + indent + "\"\"\"\n" + + indent + " " + description + '\n' + + indent + "\"\"\"\n"; + } + + /** + * Generate the Pydoc comment header for flyweight property. + * + * @param indent level for the comment. + * @param propertyToken for the property name. + * @param typeName for the property type. + * @return a string representation of the Javadoc comment. + */ + public static String generateFlyweightPropertyPydoc( + final String indent, final Token propertyToken, final String typeName) + { + final String description = propertyToken.description(); + if (null == description || description.isEmpty()) + { + return ""; + } + + return + indent + "\"\"\"\n" + + indent + description + '\n' + + indent + "@return " + typeName + " : " + description + "\n" + + indent + " \"\"\"\n"; + } + + /** + * Generate the Javadoc comment header for group encode property. + * + * @param indent level for the comment. + * @param propertyToken for the property name. + * @param typeName for the property type. + * @return a string representation of the Javadoc comment. + */ + public static String generateGroupEncodePropertyPydoc( + final String indent, final Token propertyToken, final String typeName) + { + final String description = propertyToken.description(); + if (null == description || description.isEmpty()) + { + return ""; + } + + return + indent + "/**\n" + + indent + " * " + description + "\n" + + indent + " *\n" + + indent + " * @param count of times the group will be encoded\n" + + indent + " * @return " + typeName + " : encoder for the group\n" + + indent + " */\n"; + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java new file mode 100644 index 0000000000..10f582a81e --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2019 Real Logic Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.python; + +import uk.co.real_logic.sbe.generation.CodeGenerator; +import uk.co.real_logic.sbe.generation.TargetCodeGenerator; +import uk.co.real_logic.sbe.ir.Ir; + +/** + * This class is present largely to enable the dynamic-loading style pattern + * of specifying a TargetCodeGenerator Java class name rather than the language + * name. + */ +public class Python implements TargetCodeGenerator { + public CodeGenerator newInstance(final Ir ir, final String outputDir) { + return defaultPythonGenerator(ir, outputDir); + } + + public static CodeGenerator defaultPythonGenerator(final Ir ir, final String outputDir) { + return new PyGenerator(ir, new PyOutputManager(outputDir, ir.applicableNamespace())); + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java new file mode 100644 index 0000000000..59451ea887 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java @@ -0,0 +1,39 @@ +package uk.co.real_logic.sbe.generation.python; + +import org.agrona.generation.StringWriterOutputManager; +import org.junit.Test; +import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +public class PyGeneratorTest { + @Test() + public void codeGenerationSchemaTest() throws Exception { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(TestUtil.getLocalResource("example-schema.xml"), options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + final PyGenerator generator = new PyGenerator(ir, outputManager); + generator.generate(); + assertEquals(13, outputManager.getSources().size()); + assertTrue(outputManager.getSources().containsKey("null.engine")); + assertTrue(outputManager.getSources().containsKey("null.optional_extras")); + assertTrue(outputManager.getSources().containsKey("null.booster")); + assertTrue(outputManager.getSources().containsKey("null.message_header")); + assertTrue(outputManager.getSources().containsKey("null.boolean_type")); + assertTrue(outputManager.getSources().containsKey("null.model")); + assertTrue(outputManager.getSources().containsKey("null.var_string_encoding")); + assertTrue(outputManager.getSources().containsKey("null.boost_type")); + assertTrue(outputManager.getSources().containsKey("null._struct_defs")); + assertTrue(outputManager.getSources().containsKey("null.group_size_encoding")); + assertTrue(outputManager.getSources().containsKey("null.meta_attribute")); + assertTrue(outputManager.getSources().containsKey("null.__init__")); + } +} From 89c5395f3fe1d7afc3b8651afea4c970eaef712c Mon Sep 17 00:00:00 2001 From: Feras Date: Wed, 10 Apr 2019 10:20:33 -0400 Subject: [PATCH 0148/1594] [Java] Python generator, cleanup javadocs --- .../co/real_logic/sbe/generation/python/PyUtil.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java index 0d24dd32ea..bf5696f2cd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java @@ -89,7 +89,7 @@ public static String pythonTypeName(final PrimitiveType primitiveType) /** * https://docs.python.org/3/library/struct.html - * @param primitiveType + * @param primitiveType SBE primitive type * @return A string representation for python c struct unpacking */ public static String pythonTypeCode(final PrimitiveType primitiveType){ @@ -98,7 +98,7 @@ public static String pythonTypeCode(final PrimitiveType primitiveType){ /** * https://docs.python.org/3/library/struct.html - * @param byteOrder + * @param byteOrder byte order for convertion from Java enum to python string * @return python struct unpacking code for endianess */ public static String pythonEndianCode(final ByteOrder byteOrder){ @@ -151,9 +151,9 @@ public static String formatClassName(final String str) /** * Converts CamelCase to snake_case, which is the recommended python case - * @param str - * @param toUpperFirst - * @return + * @param str string to transform + * @param toUpperFirst whether to make the first char upper case first + * @return transformed string */ public static String camToSnake(final String str, boolean toUpperFirst){ if(toUpperFirst){ @@ -163,7 +163,7 @@ public static String camToSnake(final String str, boolean toUpperFirst){ } /** - * @see {@link #camToSnake} + * @return transformed strings with toUpper applied */ public static String camToSnake(final String str){ return camToSnake(str, true); From feae05de022e35d2681d3d3d8d6506fe596b3284 Mon Sep 17 00:00:00 2001 From: Feras Date: Wed, 10 Apr 2019 11:01:40 -0400 Subject: [PATCH 0149/1594] [Java] Python generator, fix gradle tasks --- build.gradle | 2 +- .../java/uk/co/real_logic/sbe/generation/python/PyUtil.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 220fe1be48..de43f86aa8 100644 --- a/build.gradle +++ b/build.gradle @@ -784,11 +784,11 @@ task generatePythonCarExample(type: JavaExec) { } task generatePythonExampleDataFile(type: JavaExec) { + mkdir "python/tests/gen/car_example" main = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub' classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath systemProperties('sbe.encoding.filename': 'python/tests/gen/car_example/car_example_data.sbe') args = [] - standardOutput = new FileOutputStream("python/tests/gen/car_example/car_example_decode.out") } task generatePythonCodecs { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java index bf5696f2cd..9a1267b44c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java @@ -163,6 +163,7 @@ public static String camToSnake(final String str, boolean toUpperFirst){ } /** + * @param str string to transform * @return transformed strings with toUpper applied */ public static String camToSnake(final String str){ From 478f30ef7242e0161a9340c076b2292b07f66e51 Mon Sep 17 00:00:00 2001 From: Feras Date: Wed, 10 Apr 2019 16:46:50 -0400 Subject: [PATCH 0150/1594] [Java] Python generator, fix checkstyle --- .../sbe/generation/python/PyGenerator.java | 1441 +++++++++-------- .../generation/python/PyOutputManager.java | 13 +- .../sbe/generation/python/PyUtil.java | 52 +- .../sbe/generation/python/Python.java | 9 +- .../generation/python/PyGeneratorTest.java | 6 +- 5 files changed, 844 insertions(+), 677 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java index 415c75c573..e489f22d99 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java @@ -23,7 +23,6 @@ import uk.co.real_logic.sbe.generation.CodeGenerator; import uk.co.real_logic.sbe.generation.Generators; import uk.co.real_logic.sbe.generation.csharp.CSharpUtil; -import uk.co.real_logic.sbe.generation.java.JavaUtil; import uk.co.real_logic.sbe.ir.Encoding; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.ir.Signal; @@ -34,11 +33,11 @@ import java.nio.ByteOrder; import java.util.*; -import static uk.co.real_logic.sbe.generation.java.JavaUtil.generateLiteral; import static uk.co.real_logic.sbe.generation.python.PyUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.*; -public class PyGenerator implements CodeGenerator { +public class PyGenerator implements CodeGenerator +{ private static final String META_ATTRIBUTE_ENUM = "MetaAttribute"; private static final String INDENT = " "; private static final String BASE_INDENT = INDENT; @@ -46,7 +45,8 @@ public class PyGenerator implements CodeGenerator { private final Ir ir; private final OutputManager outputManager; - public PyGenerator(final Ir ir, final OutputManager outputManager) { + public PyGenerator(final Ir ir, final OutputManager outputManager) + { Verify.notNull(ir, "ir"); Verify.notNull(outputManager, "outputManager"); @@ -54,15 +54,19 @@ public PyGenerator(final Ir ir, final OutputManager outputManager) { this.outputManager = outputManager; } - public void generateMessageHeaderStub(final List modules) throws IOException { + public void generateMessageHeaderStub(final List modules) throws IOException + { generateComposite(ir.headerStructure().tokens(), modules); } - public void generateTypeStubs(List modules) throws IOException { + public void generateTypeStubs(final List modules) throws IOException + { generateMetaAttributeEnum(); - for (final List tokens : ir.types()) { - switch (tokens.get(0).signal()) { + for (final List tokens : ir.types()) + { + switch (tokens.get(0).signal()) + { case BEGIN_ENUM: generateEnum(tokens, modules); break; @@ -78,15 +82,18 @@ public void generateTypeStubs(List modules) throws IOException { } } - public void generate() throws IOException { - List modules = new ArrayList<>(); + public void generate() throws IOException + { + final List modules = new ArrayList<>(); generateMessageHeaderStub(modules); generateTypeStubs(modules); - for (final List tokens : ir.messages()) { + for (final List tokens : ir.messages()) + { final Token msgToken = tokens.get(0); final String className = formatClassName(msgToken.name()); - String pyModuleName = camToSnake(className); - try (Writer out = outputManager.createOutput(pyModuleName)) { + final String pyModuleName = camToSnake(className); + try (Writer out = outputManager.createOutput(pyModuleName)) + { modules.add(pyModuleName); final List messageBody = getMessageBody(tokens); int offset = 0; @@ -115,10 +122,13 @@ public void generate() throws IOException { generatePackageDefinition(modules); } - public void generatePackageDefinition(List modules) throws IOException { - try (Writer out = outputManager.createOutput("__init__")) { + public void generatePackageDefinition(final List modules) throws IOException + { + try (Writer out = outputManager.createOutput("__init__")) + { out.append(generateFileHeader(ir.applicableNamespace(), new ArrayList<>(), false)); - for (String m : modules) { + for (final String m : modules) + { out.append("from ." + m + " import *\n"); } out.append("from .meta_attribute import *\n"); @@ -126,13 +136,16 @@ public void generatePackageDefinition(List modules) throws IOException { } private void generateGroups( - final StringBuilder sb, - final String parentMessageClassName, - final List tokens, - final String indent) { - for (int i = 0, size = tokens.size(); i < size; i++) { + final StringBuilder sb, + final String parentMessageClassName, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { final Token groupToken = tokens.get(i); - if (groupToken.signal() != Signal.BEGIN_GROUP) { + if (groupToken.signal() != Signal.BEGIN_GROUP) + { throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); } final String groupName = groupToken.name(); @@ -143,15 +156,18 @@ private void generateGroups( final List fields = new ArrayList<>(); i = collectFields(tokens, i, fields); - sb.append(generateFields(fields, indent + INDENT, parentMessageClassName + "." + formatClassName(groupName) + "Group")); + sb.append(generateFields(fields, indent + INDENT, parentMessageClassName + "." + + formatClassName(groupName) + "Group")); final List groups = new ArrayList<>(); i = collectGroups(tokens, i, groups); - generateGroups(sb, parentMessageClassName + "." + formatClassName(groupName) + "Group", groups, indent + INDENT); + generateGroups(sb, parentMessageClassName + "." + formatClassName(groupName) + + "Group", groups, indent + INDENT); final List varData = new ArrayList<>(); i = collectVarData(tokens, i, varData); - sb.append(generateVarData(varData, indent + INDENT, parentMessageClassName + "." + formatClassName(groupName) + "Group")); + sb.append(generateVarData(varData, indent + INDENT, parentMessageClassName + "." + + formatClassName(groupName) + "Group")); sb.append(generateGroupProperty(groupName, groupToken, indent, parentMessageClassName)); @@ -159,156 +175,169 @@ private void generateGroups( } private void generateGroupClassHeader( - final StringBuilder sb, - final String groupName, - final String parentMessageClassName, - final List tokens, - final int index, - final String indent) { + final StringBuilder sb, + final String groupName, + final String parentMessageClassName, + final List tokens, + final int index, + final String indent) + { final String dimensionsClassName = formatClassName(tokens.get(index + 1).name()); final int dimensionHeaderLength = tokens.get(index + 1).encodedLength(); - String topLevelParentMessageClassName = parentMessageClassName.split("\\.")[0]; + final String topLevelParentMessageClassName = parentMessageClassName.split("\\.")[0]; sb.append(String.format("\n" + - indent + "class %1$sGroup:\n" + - indent + INDENT + "__slots__ = '_dimensions', '_parent_message', '_buffer', '_block_length', '_acting_version', '_count', '_index', '_offset'\n\n" + - indent + INDENT + "def __init__(self):\n" + - indent + INDENT + INDENT + "self._dimensions: '%2$s' = %2$s()\n" + - indent + INDENT + INDENT + "self._parent_message: '%3$s'\n" + - indent + INDENT + INDENT + "self._buffer: Union[bytes, bytearray, memoryview]\n" + - indent + INDENT + INDENT + "self._block_length: int\n" + - indent + INDENT + INDENT + "self._acting_version: int\n" + - indent + INDENT + INDENT + "self._count: int\n" + - indent + INDENT + INDENT + "self._index: int\n" + - indent + INDENT + INDENT + "self._offset: int\n", - formatClassName(groupName), - dimensionsClassName, - topLevelParentMessageClassName)); + indent + "class %1$sGroup:\n" + + indent + INDENT + "__slots__ = '_dimensions', '_parent_message', '_buffer', '_block_length', " + + "'_acting_version', '_count', '_index', '_offset'\n\n" + + indent + INDENT + "def __init__(self):\n" + + indent + INDENT + INDENT + "self._dimensions: '%2$s' = %2$s()\n" + + indent + INDENT + INDENT + "self._parent_message: '%3$s'\n" + + indent + INDENT + INDENT + "self._buffer: Union[bytes, bytearray, memoryview]\n" + + indent + INDENT + INDENT + "self._block_length: int\n" + + indent + INDENT + INDENT + "self._acting_version: int\n" + + indent + INDENT + INDENT + "self._count: int\n" + + indent + INDENT + INDENT + "self._index: int\n" + + indent + INDENT + INDENT + "self._offset: int\n", + formatClassName(groupName), + dimensionsClassName, + topLevelParentMessageClassName)); final int blockLength = tokens.get(index).encodedLength(); sb.append(String.format("\n" + - indent + INDENT + "SBE_BLOCK_LENGTH: int = %d\n" + - indent + INDENT + "SBE_HEADER_SIZE: int = %d\n", - blockLength, - dimensionHeaderLength)); + indent + INDENT + "SBE_BLOCK_LENGTH: int = %d\n" + + indent + INDENT + "SBE_HEADER_SIZE: int = %d\n", + blockLength, + dimensionHeaderLength)); final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); sb.append(String.format("\n" + - indent + INDENT + "def wrap_decode(self, parent_message: '%1$s' , buffer: Union[bytes, bytearray, memoryview], acting_version: int):\n" + - indent + INDENT + INDENT + "self._parent_message = parent_message\n" + - indent + INDENT + INDENT + "self._buffer = buffer\n" + - indent + INDENT + INDENT + "self._dimensions.wrap(buffer, parent_message.limit)\n" + - indent + INDENT + INDENT + "self._block_length = self._dimensions.get_block_length()\n" + - indent + INDENT + INDENT + "self._count = self._dimensions.get_num_in_group()\n" + - indent + INDENT + INDENT + "self._acting_version = acting_version\n" + - indent + INDENT + INDENT + "self._index = -1\n" + - indent + INDENT + INDENT + "self._parent_message.set_limit(self._parent_message.limit + self.SBE_HEADER_SIZE)\n" + - indent + INDENT + INDENT + "return self\n", - topLevelParentMessageClassName, - formatClassName(groupName))); + indent + " def wrap_decode(self, parent_message: '%1$s' , buffer: Union[bytes, bytearray," + + " memoryview" + "], acting_version: int):\n" + + indent + " self._parent_message = parent_message\n" + + indent + " self._buffer = buffer\n" + + indent + " self._dimensions.wrap(buffer, parent_message.limit)\n" + + indent + " self._block_length = self._dimensions.get_block_length()\n" + + indent + " self._count = self._dimensions.get_num_in_group()\n" + + indent + " self._acting_version = acting_version\n" + + indent + " self._index = -1\n" + + indent + " self._parent_message.set_limit(self._parent_message.limit + self.SBE_HEADER_SIZE)\n" + + indent + " return self\n", + topLevelParentMessageClassName, + formatClassName(groupName))); final String typeForBlockLength = pythonTypeName(tokens.get(index + 2).encoding().primitiveType()); final String typeForNumInGroup = pythonTypeName(numInGroupToken.encoding().primitiveType()); sb.append(String.format("\n" + - indent + INDENT + "def wrap_encode(self, parent_message: '%1$s', buffer: Union[bytes, bytearray, memoryview], count: int):\n" + - indent + INDENT + INDENT + "if count < %2$d or count > %3$d:\n" + - indent + INDENT + INDENT + INDENT + "raise IndexError('Count Outside allowed range: count='+ str(count) +', min=%2$d, max=%3$d')\n" + - indent + INDENT + INDENT + "self._parent_message = parent_message\n" + - indent + INDENT + INDENT + "self._buffer = buffer\n" + - indent + INDENT + INDENT + "self._dimensions.wrap(buffer, parent_message.limit)\n" + - indent + INDENT + INDENT + "self._dimensions.set_block_length(%4$s(%5$d))\n" + - indent + INDENT + INDENT + "self._dimensions.set_num_in_group(%6$s(count))\n" + - indent + INDENT + INDENT + "self._index = -1\n" + - indent + INDENT + INDENT + "self._count = count\n" + - indent + INDENT + INDENT + "self._block_length = %5$d\n" + - indent + INDENT + INDENT + "self._acting_version = self._parent_message.SCHEMA_VERSION\n" + - indent + INDENT + INDENT + "self._parent_message.set_limit(parent_message.limit + self.SBE_HEADER_SIZE)\n" + - indent + INDENT + INDENT + "return self\n", - topLevelParentMessageClassName, - numInGroupToken.encoding().applicableMinValue().longValue(), - numInGroupToken.encoding().applicableMaxValue().longValue(), - typeForBlockLength, - blockLength, - typeForNumInGroup)); + indent + " def wrap_encode(self, parent_message: '%1$s', buffer: Union[bytes, bytearray, memoryview]," + + " count: int):\n" + + indent + " if count < %2$d or count > %3$d:\n" + + indent + " raise IndexError('Count Outside allowed range: count='+ str(count) +', min=%2$d, " + + "max=%3$d')\n" + + indent + " self._parent_message = parent_message\n" + + indent + " self._buffer = buffer\n" + + indent + " self._dimensions.wrap(buffer, parent_message.limit)\n" + + indent + " self._dimensions.set_block_length(%4$s(%5$d))\n" + + indent + " self._dimensions.set_num_in_group(%6$s(count))\n" + + indent + " self._index = -1\n" + + indent + " self._count = count\n" + + indent + " self._block_length = %5$d\n" + + indent + " self._acting_version = self._parent_message.SCHEMA_VERSION\n" + + indent + " self._parent_message.set_limit(parent_message.limit + self.SBE_HEADER_SIZE)\n" + + indent + " return self\n", + topLevelParentMessageClassName, + numInGroupToken.encoding().applicableMinValue().longValue(), + numInGroupToken.encoding().applicableMaxValue().longValue(), + typeForBlockLength, + blockLength, + typeForNumInGroup)); sb.append("\n"); generateGroupEnumerator(sb, groupName, indent + INDENT, parentMessageClassName); } - private void generateGroupEnumerator(final StringBuilder sb, final String groupName, final String indent, final String parentClassName) { + private void generateGroupEnumerator(final StringBuilder sb, final String groupName, final String indent, + final String parentClassName) + { sb.append(indent + "@property\n" + - indent + "def acting_block_length(self) -> int:\n" + - indent + INDENT + "return self._block_length\n\n" + - indent + "@property\n" + - indent + "def count(self) -> int:\n" + - indent + INDENT + "return self._count\n\n" + - indent + "@property\n" + - indent + "def has_next(self) -> bool:\n" + - indent + INDENT + "return (self._index + 1) < self._count\n"); + indent + "def acting_block_length(self) -> int:\n" + + indent + " return self._block_length\n\n" + + indent + "@property\n" + + indent + "def count(self) -> int:\n" + + indent + " return self._count\n\n" + + indent + "@property\n" + + indent + "def has_next(self) -> bool:\n" + + indent + " return (self._index + 1) < self._count\n"); sb.append(String.format("\n" + - indent + "def next(self) -> '%2$s.%1$sGroup':\n" + - indent + INDENT + "if self._index + 1 >= self._count:\n" + - indent + INDENT + INDENT + "raise IndexError()\n" + - indent + INDENT + "self._offset = self._parent_message.limit\n" + - indent + INDENT + "self._parent_message.set_limit(self._offset + self._block_length)\n" + - indent + INDENT + "self._index += 1\n" + - indent + INDENT + "return self\n", - formatClassName(groupName), parentClassName)); + indent + "def next(self) -> '%2$s.%1$sGroup':\n" + + indent + " if self._index + 1 >= self._count:\n" + + indent + " raise IndexError()\n" + + indent + " self._offset = self._parent_message.limit\n" + + indent + " self._parent_message.set_limit(self._offset + self._block_length)\n" + + indent + " self._index += 1\n" + + indent + " return self\n", + formatClassName(groupName), parentClassName)); sb.append(String.format("\n" + - indent + "def generator(self) -> Generator['%2$s.%1$sGroup', None, None]:\n" + - indent + INDENT + "while self.has_next:\n" + - indent + INDENT + INDENT + "yield self.next()\n", - formatClassName(groupName), parentClassName + indent + "def generator(self) -> Generator['%2$s.%1$sGroup', None, None]:\n" + + indent + " while self.has_next:\n" + + indent + " yield self.next()\n", + formatClassName(groupName), parentClassName )); } - private CharSequence generateGroupProperty(final String groupName, final Token token, final String indent, final String parentMessageClassName) { + private CharSequence generateGroupProperty(final String groupName, final Token token, final String indent, + final String parentMessageClassName) + { final StringBuilder sb = new StringBuilder(); final String className = CSharpUtil.formatClassName(groupName); sb.append(String.format("\n" + - indent + "%S_ID: int = %d\n", - camToSnake(groupName), - token.id())); + indent + "%S_ID: int = %d\n", + camToSnake(groupName), + token.id())); sb.append(String.format("\n" + - indent + "_%1$s_group: '%2$sGroup' = %2$sGroup()\n", - camToSnake(groupName), - formatClassName(groupName), - token.id())); + indent + "_%1$s_group: '%2$sGroup' = %2$sGroup()\n", + camToSnake(groupName), + formatClassName(groupName), + token.id())); generateSinceActingDeprecated(sb, indent, toUpperFirstChar(groupName), token); sb.append(String.format("\n" + - indent + "def get_%2$s(self) -> '" + parentMessageClassName + ".%1$sGroup':\n" + - indent + INDENT + "self._%3$s_group.wrap_decode(self._parent_message, self._buffer, self._parent_message.SCHEMA_VERSION)\n" + - indent + INDENT + "return self._%3$s_group\n", - className, - camToSnake(groupName), - camToSnake(groupName))); + indent + "def get_%2$s(self) -> '" + parentMessageClassName + ".%1$sGroup':\n" + + indent + " self._%3$s_group.wrap_decode(self._parent_message, self._buffer, " + + "self._parent_message.SCHEMA_VERSION)\n" + + indent + " return self._%3$s_group\n", + className, + camToSnake(groupName), + camToSnake(groupName))); sb.append(String.format("\n" + - indent + "def set_%2$s_count(self, count:int) -> '" + parentMessageClassName + ".%1$sGroup':\n" + - indent + INDENT + "self._%3$s_group.wrap_encode(self._parent_message, self._buffer, count)\n" + - indent + INDENT + "return self._%3$s_group\n", - className, - camToSnake(groupName), - camToSnake(groupName))); + indent + "def set_%2$s_count(self, count:int) -> '" + parentMessageClassName + ".%1$sGroup':\n" + + indent + " self._%3$s_group.wrap_encode(self._parent_message, self._buffer, count)\n" + + indent + " return self._%3$s_group\n", + className, + camToSnake(groupName), + camToSnake(groupName))); return sb; } - private CharSequence generateVarData(final List tokens, final String indent, String parentClassName) { + private CharSequence generateVarData(final List tokens, final String indent, final String parentClassName) + { final StringBuilder sb = new StringBuilder(); - for (int i = 0, size = tokens.size(); i < size; i++) { + for (int i = 0, size = tokens.size(); i < size; i++) + { final Token token = tokens.get(i); - if (token.signal() == Signal.BEGIN_VAR_DATA) { + if (token.signal() == Signal.BEGIN_VAR_DATA) + { generateFieldIdMethod(sb, token, indent); final Token varDataToken = Generators.findFirst("varData", tokens, i); @@ -326,57 +355,62 @@ private CharSequence generateVarData(final List tokens, final String inde final String byteOrderStr = byteOrder.toString(); sb.append(String.format("\n" + - indent + "%1$S_HEADER_SIZE: int = %2$d\n", - camToSnake(propertyName), - sizeOfLengthField)); + indent + "%1$S_HEADER_SIZE: int = %2$d\n", + camToSnake(propertyName), + sizeOfLengthField)); sb.append(String.format("\n" + - indent + "def get_%1$s(self) -> memoryview:\n" + - "%2$s" + - indent + INDENT + "size_of_len_field: int = %3$d\n" + - indent + INDENT + "limit:int = self._parent_message.limit\n" + - indent + INDENT + "#self._buffer.CheckLimit(limit + size_of_len_field);\n" + - indent + INDENT + "data_length: int = %4$S_%5$S.unpack_from(self._buffer, limit)[0]\n" + - indent + INDENT + "self._parent_message.set_limit(limit + size_of_len_field + data_length)\n" + - indent + INDENT + "return memoryview(self._buffer)[limit + size_of_len_field:limit + size_of_len_field+data_length]\n", - camToSnake(propertyName), - generateArrayFieldNotPresentCondition(token.version(), indent), - sizeOfLengthField, - lengthTypePrefix, - byteOrderStr)); + indent + "def get_%1$s(self) -> memoryview:\n" + + "%2$s" + + indent + " size_of_len_field: int = %3$d\n" + + indent + " limit:int = self._parent_message.limit\n" + + indent + " #self._buffer.CheckLimit(limit + size_of_len_field);\n" + + indent + " data_length: int = %4$S_%5$S.unpack_from(self._buffer, limit)[0]\n" + + indent + " self._parent_message.set_limit(limit + size_of_len_field + data_length)\n" + + indent + " return memoryview(self._buffer)[limit + size_of_len_field:limit + " + + "size_of_len_field+data_length]\n", + camToSnake(propertyName), + generateArrayFieldNotPresentCondition(token.version(), indent), + sizeOfLengthField, + lengthTypePrefix, + byteOrderStr)); sb.append(String.format("\n" + - indent + "def set_%1$s(self, data: Union[bytes, bytearray, memoryview]) -> '%7$s':\n" + - indent + INDENT + "size_of_len_field: int = %2$d\n" + - indent + INDENT + "limit:int = self._parent_message.limit\n" + - indent + INDENT + "self._parent_message.set_limit(limit + size_of_len_field + len(data))\n" + - indent + INDENT + "data_len = len(data)\n" + - indent + INDENT + "%3$S_%5$S.pack_into(self._buffer, limit, %4$s(data_len))\n" + - indent + INDENT + "struct.pack_into('%6$s%%ds' %% (data_len,), self._buffer, limit + size_of_len_field, data)\n" + - indent + INDENT + "return self\n\n", - camToSnake(propertyName), - sizeOfLengthField, - lengthTypePrefix, - lengthCSharpType, - byteOrderStr, - pythonEndianCode(byteOrder), - parentClassName)); + indent + "def set_%1$s(self, data: Union[bytes, bytearray, memoryview]) -> '%7$s':\n" + + indent + " size_of_len_field: int = %2$d\n" + + indent + " limit:int = self._parent_message.limit\n" + + indent + " self._parent_message.set_limit(limit + size_of_len_field + len(data))\n" + + indent + " data_len = len(data)\n" + + indent + " %3$S_%5$S.pack_into(self._buffer, limit, %4$s(data_len))\n" + + indent + " struct.pack_into('%6$s%%ds' %% (data_len,), self._buffer, limit + size_of_len_field, " + + "data)\n" + + indent + " return self\n\n", + camToSnake(propertyName), + sizeOfLengthField, + lengthTypePrefix, + lengthCSharpType, + byteOrderStr, + pythonEndianCode(byteOrder), + parentClassName)); } } return sb; } - private void generateBitSet(final List tokens, final List modules) throws IOException { + private void generateBitSet(final List tokens, final List modules) throws IOException + { final Token bitSetToken = tokens.get(0); final String bitSetName = formatClassName(bitSetToken.applicableTypeName()); - List messageBody = getMessageBody(tokens); - try (Writer out = outputManager.createOutput(camToSnake(bitSetName))) { + final List messageBody = getMessageBody(tokens); + try (Writer out = outputManager.createOutput(camToSnake(bitSetName))) + { modules.add(camToSnake(bitSetName)); out.append(generateFileHeader(ir.applicableNamespace(), messageBody, true)); out.append(generateClassDeclaration(bitSetName)); out.append(generateMessageFlyweightCode(bitSetName, bitSetToken, BASE_INDENT, new ArrayList<>())); - out.append(generateChoiceIsEmpty(bitSetToken.encoding().primitiveType(), bitSetToken.encoding().byteOrder())); + out.append(generateChoiceIsEmpty(bitSetToken.encoding().primitiveType(), + bitSetToken.encoding().byteOrder())); out.append(generateChoiceDecoders(messageBody)); out.append(generateChoiceDisplay(messageBody)); out.append(generateChoiceClear(bitSetName, bitSetToken)); @@ -385,11 +419,13 @@ private void generateBitSet(final List tokens, final List modules } } - private void generateEnum(final List tokens, final List modules) throws IOException { + private void generateEnum(final List tokens, final List modules) throws IOException + { final Token enumToken = tokens.get(0); final String enumName = formatClassName(enumToken.applicableTypeName()); - List messageBody = getMessageBody(tokens); - try (Writer out = outputManager.createOutput(camToSnake(enumName))) { + final List messageBody = getMessageBody(tokens); + try (Writer out = outputManager.createOutput(camToSnake(enumName))) + { modules.add(camToSnake(enumName)); out.append(generateFileHeader(ir.applicableNamespace(), messageBody, true)); final String enumPrimitiveType = pythonTypeName(enumToken.encoding().primitiveType()); @@ -398,10 +434,12 @@ private void generateEnum(final List tokens, final List modules) } } - private void generateComposite(final List tokens, final List modules) throws IOException { + private void generateComposite(final List tokens, final List modules) throws IOException + { final String compositeName = formatClassName(tokens.get(0).applicableTypeName()); - try (Writer out = outputManager.createOutput(camToSnake(compositeName))) { + try (Writer out = outputManager.createOutput(camToSnake(compositeName))) + { modules.add(camToSnake(compositeName)); out.append(generateFileHeader(ir.applicableNamespace(), getMessageBody(tokens), true)); out.append(generateClassDeclaration(compositeName)); @@ -411,15 +449,19 @@ private void generateComposite(final List tokens, final List modu } } - private CharSequence generateCompositePropertyElements(final List tokens, final String indent, String className) { + private CharSequence generateCompositePropertyElements(final List tokens, final String indent, + final String className) + { final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < tokens.size(); ) { + for (int i = 0; i < tokens.size(); ) + { final Token token = tokens.get(i); final String propertyName = formatPropertyName(token.name()); // FIXME: do I need to pass classname down here for disambiguation - switch (token.signal()) { + switch (token.signal()) + { case ENCODING: sb.append(generatePrimitiveProperty(propertyName, token, indent, className)); break; @@ -443,32 +485,34 @@ private CharSequence generateCompositePropertyElements(final List tokens, return sb; } - private CharSequence generateChoiceEncoders(final String bitSetClassName, final List tokens) { + private CharSequence generateChoiceEncoders(final String bitSetClassName, final List tokens) + { return concatTokens( - tokens, - Signal.CHOICE, - (token) -> - { - final String choiceName = formatPropertyName(token.name()); - final Encoding encoding = token.encoding(); - final String choiceBitIndex = encoding.constValue().toString(); - final PrimitiveType primitiveType = encoding.primitiveType(); - - return String.format("\n" + - INDENT + "def set_%2$s(self, value: bool) -> '%1$s':\n" + - "%3$s\n\n" + - INDENT + "@staticmethod\n" + - INDENT + "def apply_%2$s(bits: '%4$s', value: bool) -> '%4$s':\n" + - "%5$s\n", - bitSetClassName, - camToSnake(choiceName), - generateChoicePut(primitiveType, choiceBitIndex, encoding.byteOrder()), - "int", - generateStaticChoicePut(primitiveType, choiceBitIndex)); - }); + tokens, + Signal.CHOICE, + (token) -> + { + final String choiceName = formatPropertyName(token.name()); + final Encoding encoding = token.encoding(); + final String choiceBitIndex = encoding.constValue().toString(); + final PrimitiveType primitiveType = encoding.primitiveType(); + + return String.format("\n" + + INDENT + "def set_%2$s(self, value: bool) -> '%1$s':\n" + + "%3$s\n\n" + + INDENT + "@staticmethod\n" + + INDENT + "def apply_%2$s(bits: '%4$s', value: bool) -> '%4$s':\n" + + "%5$s\n", + bitSetClassName, + camToSnake(choiceName), + generateChoicePut(primitiveType, choiceBitIndex, encoding.byteOrder()), + "int", + generateStaticChoicePut(primitiveType, choiceBitIndex)); + }); } - private CharSequence generateChoiceDisplay(final List tokens) { + private CharSequence generateChoiceDisplay(final List tokens) + { final String indent = INDENT; final StringBuilder sb = new StringBuilder(); @@ -477,17 +521,17 @@ private CharSequence generateChoiceDisplay(final List tokens) { sb.append(indent + indent + "at_least_one = False\n"); sb.append(indent + indent + "out = \"{\"\n"); tokens - .stream() - .filter((token) -> token.signal() == Signal.CHOICE) - .forEach((token) -> - { - final String choiceName = formatPropertyName(token.name()); - sb.append(indent + indent + "if self.has_" + camToSnake(choiceName) + "():\n"); - sb.append(indent + indent + indent + "if at_least_one:\n"); - sb.append(indent + indent + indent + indent + "out += \",\"\n"); - sb.append(indent + indent + indent + "out += \"" + choiceName + "\"\n"); - sb.append(indent + indent + indent + "at_least_one = True\n"); - }); + .stream() + .filter((token) -> token.signal() == Signal.CHOICE) + .forEach((token) -> + { + final String choiceName = formatPropertyName(token.name()); + sb.append(indent + indent + "if self.has_" + camToSnake(choiceName) + "():\n"); + sb.append(indent + indent + indent + "if at_least_one:\n"); + sb.append(indent + indent + indent + indent + "out += \",\"\n"); + sb.append(indent + indent + indent + "out += \"" + choiceName + "\"\n"); + sb.append(indent + indent + indent + "at_least_one = True\n"); + }); sb.append(indent + indent + "out += \"}\"\n"); sb.append('\n'); sb.append(indent + indent + "return out\n"); @@ -495,79 +539,92 @@ private CharSequence generateChoiceDisplay(final List tokens) { return sb.toString(); } - private CharSequence generateChoiceDecoders(final List tokens) { + private CharSequence generateChoiceDecoders(final List tokens) + { return concatTokens( - tokens, - Signal.CHOICE, - (token) -> - { - final String choiceName = formatPropertyName(token.name()); - final Encoding encoding = token.encoding(); - final String choiceBitIndex = encoding.constValue().toString(); - final PrimitiveType primitiveType = encoding.primitiveType(); - - return String.format("\n" + - " def has_%1$s(self) -> bool:\n" + - " return %2$s\n\n" + - " @staticmethod\n" + - " def check_%1$s(value: '%3$s') -> bool:\n" + - " return %4$s\n" + - " \n", - camToSnake(choiceName), - generateChoiceGet(primitiveType, choiceBitIndex, encoding.byteOrder()), - "int", - generateStaticChoiceGet(primitiveType, choiceBitIndex)); - }); + tokens, + Signal.CHOICE, + (token) -> + { + final String choiceName = formatPropertyName(token.name()); + final Encoding encoding = token.encoding(); + final String choiceBitIndex = encoding.constValue().toString(); + final PrimitiveType primitiveType = encoding.primitiveType(); + + return String.format("\n" + + " def has_%1$s(self) -> bool:\n" + + " return %2$s\n\n" + + " @staticmethod\n" + + " def check_%1$s(value: '%3$s') -> bool:\n" + + " return %4$s\n" + + " \n", + camToSnake(choiceName), + generateChoiceGet(primitiveType, choiceBitIndex, encoding.byteOrder()), + "int", + generateStaticChoiceGet(primitiveType, choiceBitIndex)); + }); } - private String generateChoiceIsEmpty(final PrimitiveType type, final ByteOrder byteOrder) { + private String generateChoiceIsEmpty(final PrimitiveType type, final ByteOrder byteOrder) + { return "\n" + - " @property\n" + - " def is_empty(self) -> bool:\n" + - " return " + generateChoiceIsEmptyInner(type, byteOrder) + "\n" + - " \n"; + " @property\n" + + " def is_empty(self) -> bool:\n" + + " return " + generateChoiceIsEmptyInner(type, byteOrder) + "\n" + + " \n"; } - private String generateChoiceIsEmptyInner(final PrimitiveType type, final ByteOrder byteOrder) { - switch (type) { + private String generateChoiceIsEmptyInner(final PrimitiveType type, final ByteOrder byteOrder) + { + switch (type) + { case UINT8: - return "0 == " + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + ".unpack_from(self._buffer, self._offset)[0]"; + return "0 == " + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + + ".unpack_from(self._buffer, self._offset)[0]"; } throw new IllegalArgumentException("primitive type not supported: " + type); } - private String generateChoicePut(final PrimitiveType type, final String bitIdx, final ByteOrder byteOrder) { - switch (type) { + private String generateChoicePut(final PrimitiveType type, final String bitIdx, final ByteOrder byteOrder) + { + switch (type) + { case UINT8: case UINT16: case UINT32: case UINT64: - return - INDENT + INDENT + "bits = " + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + ".unpack_from(self._buffer, self._offset)[0]\n" + - INDENT + INDENT + "bits = (bits | (1 << " + bitIdx + ")) if value else (bits & ~(1 << " + bitIdx + "))\n" + - INDENT + INDENT + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + ".pack_into(self._buffer, self._offset, bits)\n" + - INDENT + INDENT + "return self\n"; + return INDENT + INDENT + "bits = " + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + + ".unpack_from(self._buffer, self._offset)[0]\n" + + " bits = (bits | (1 << " + bitIdx + ")) if value else (bits & ~(1 << " + bitIdx + "))\n" + + INDENT + INDENT + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + + ".pack_into(self._buffer, self._offset, bits)\n" + + INDENT + INDENT + "return self\n"; } throw new IllegalArgumentException("primitive type not supported: " + type); } - private String generateStaticChoicePut(final PrimitiveType type, final String bitIdx) { - switch (type) { + private String generateStaticChoicePut(final PrimitiveType type, final String bitIdx) + { + switch (type) + { case UINT8: case UINT16: case UINT32: case UINT64: - return INDENT + INDENT + "return (bits | (1 << " + bitIdx + ")) if value else (bits & ~(1 << " + bitIdx + "))\n"; + return INDENT + INDENT + "return (bits | (1 << " + bitIdx + ")) " + + "if value else (bits & ~(1 << " + bitIdx + "))\n"; } throw new IllegalArgumentException("primitive type not supported: " + type); } - private String generateStaticChoiceGet(final PrimitiveType type, final String bitIndex) { - switch (type) { + private String generateStaticChoiceGet(final PrimitiveType type, final String bitIndex) + { + switch (type) + { case UINT8: case UINT16: case UINT32: @@ -578,45 +635,51 @@ private String generateStaticChoiceGet(final PrimitiveType type, final String bi throw new IllegalArgumentException("primitive type not supported: " + type); } - private String generateChoiceGet(final PrimitiveType type, final String bitIndex, final ByteOrder byteOrder) { - String ending = byteOrder.toString().toUpperCase(); - switch (type) { + private String generateChoiceGet(final PrimitiveType type, final String bitIndex, final ByteOrder byteOrder) + { + final String ending = byteOrder.toString().toUpperCase(); + switch (type) + { case UINT8: case UINT16: case UINT32: case UINT64: - return "0 != (" + type.primitiveName().toUpperCase() + "_" + ending + ".unpack_from(self._buffer, self._offset)[0] & (1 << " + bitIndex + "))"; + return "0 != (" + type.primitiveName().toUpperCase() + "_" + ending + + ".unpack_from(self._buffer, self._offset)[0] & (1 << " + bitIndex + "))"; } throw new IllegalArgumentException("primitive type not supported: " + type); } - private CharSequence generateChoiceClear(final String bitSetClassName, final Token token) { + private CharSequence generateChoiceClear(final String bitSetClassName, final Token token) + { final StringBuilder sb = new StringBuilder(); final Encoding encoding = token.encoding(); final String literalValue = generateLiteral(encoding.primitiveType(), "0"); sb.append(String.format("\n" + - " def clear(self) -> '%s':\n" + - " %2$S_%4$S.pack_into(self._buffer, self._offset, %3$s)\n" + - " return self\n" + - " \n", - bitSetClassName, - encoding.primitiveType().primitiveName(), - literalValue, - encoding.byteOrder())); + " def clear(self) -> '%s':\n" + + " %2$S_%4$S.pack_into(self._buffer, self._offset, %3$s)\n" + + " return self\n" + + " \n", + bitSetClassName, + encoding.primitiveType().primitiveName(), + literalValue, + encoding.byteOrder())); return sb; } - private CharSequence generateEnumValues(final List tokens, final Token encodingToken) { + private CharSequence generateEnumValues(final List tokens, final Token encodingToken) + { final StringBuilder sb = new StringBuilder(); final Encoding encoding = encodingToken.encoding(); - for (final Token token : tokens) { + for (final Token token : tokens) + { sb.append(INDENT).append(token.name()).append(" = ") - .append(token.encoding().constValue()).append("\n"); + .append(token.encoding().constValue()).append("\n"); } final PrimitiveValue nullVal = encoding.applicableNullValue(); @@ -626,28 +689,36 @@ private CharSequence generateEnumValues(final List tokens, final Token en return sb; } - private CharSequence generateFileHeader(final String packageName, List tokens, boolean imports) { - StringBuilder sb = new StringBuilder("\"\"\"\n Generated SBE (Simple Binary Encoding) message codec\n"); + private CharSequence generateFileHeader(final String packageName, final List tokens, final boolean imports) + { + final StringBuilder sb = new StringBuilder("\"\"\"\n Generated SBE (Simple Binary Encoding) message codec\n"); sb.append("Package: ").append(packageName); sb.append("\"\"\"\n\n"); - if (imports) { + if (imports) + { sb.append(generateImports(tokens)); } sb.append("\n"); return sb; } - private CharSequence generateImports(List tokens) { - StringBuilder sb = new StringBuilder(); - Set processed = new HashSet<>(); + private CharSequence generateImports(final List tokens) + { + final StringBuilder sb = new StringBuilder(); + final Set processed = new HashSet<>(); sb.append("from typing import *\n"); sb.append("import struct\n"); sb.append("from ._struct_defs import *\n"); sb.append("from .meta_attribute import MetaAttribute\n"); - for (Token t : tokens) { - if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET || t.signal() == Signal.BEGIN_ENUM) { - String importName = t.referencedName() != null ? formatClassName(t.referencedName()) : formatClassName(t.name()); - if (processed.contains(importName)) { + for (final Token t : tokens) + { + if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET || + t.signal() == Signal.BEGIN_ENUM) + { + final String importName = t.referencedName() != null ? formatClassName(t.referencedName()) : + formatClassName(t.name()); + if (processed.contains(importName)) + { continue; } sb.append("from .").append(camToSnake(importName)).append(" import ").append(importName).append("\n"); @@ -657,25 +728,29 @@ private CharSequence generateImports(List tokens) { return sb; } - private void generateStructParsers() throws IOException { - try (Writer out = outputManager.createOutput("_struct_defs")) { + private void generateStructParsers() throws IOException + { + try (Writer out = outputManager.createOutput("_struct_defs")) + { out.append(generateFileHeader(ir.applicableNamespace(), new ArrayList<>(), false)); out.append("from struct import Struct\n\n"); - StringBuilder builder = new StringBuilder(); - for (Map.Entry order : BYTE_ORDER_STRING_MAP.entrySet()) { - for (Map.Entry type : PRIMITIVE_TYPE_STRUCT_ENUM_MAP.entrySet()) { + final StringBuilder builder = new StringBuilder(); + for (final Map.Entry order : BYTE_ORDER_STRING_MAP.entrySet()) + { + for (final Map.Entry type : PRIMITIVE_TYPE_STRUCT_ENUM_MAP.entrySet()) + { builder.append(String.format("%1$S_%2$S: Struct = Struct('%3$s%4$s')\n", - type.getKey().primitiveName(), - order.getKey().toString(), - pythonEndianCode(order.getKey()), - pythonTypeCode(type.getKey()))); + type.getKey().primitiveName(), + order.getKey().toString(), + pythonEndianCode(order.getKey()), + pythonTypeCode(type.getKey()))); } //edge case to handle char[] unpacking builder.append(String.format("%1$S_%2$S: Struct = Struct('%3$s%4$s')\n", - "CHARS", - order.getKey().toString(), - pythonEndianCode(order.getKey()), - "s")); + "CHARS", + order.getKey().toString(), + pythonEndianCode(order.getKey()), + "s")); } builder.append("\n"); @@ -683,37 +758,46 @@ private void generateStructParsers() throws IOException { } } - private CharSequence generateClassDeclaration(final String className) { + private CharSequence generateClassDeclaration(final String className) + { return String.format("class %s:\n", className); } - private void generateMetaAttributeEnum() throws IOException { - try (Writer out = outputManager.createOutput(camToSnake(META_ATTRIBUTE_ENUM))) { + private void generateMetaAttributeEnum() throws IOException + { + try (Writer out = outputManager.createOutput(camToSnake(META_ATTRIBUTE_ENUM))) + { out.append(generateFileHeader(ir.applicableNamespace(), new ArrayList<>(), false)); out.append( - "from enum import IntEnum \n\n" + - "class MetaAttribute(IntEnum):\n" + - INDENT + "Epoch = 1\n" + - INDENT + "TimeUnit = 2\n" + - INDENT + "SemanticType = 3\n" + - INDENT + "Presence = 4\n"); + "from enum import IntEnum \n\n" + + "class MetaAttribute(IntEnum):\n" + + " Epoch = 1\n" + + " TimeUnit = 2\n" + + " SemanticType = 3\n" + + " Presence = 4\n"); } } - private CharSequence generateEnumDeclaration(final String name, final String primitiveType) { + private CharSequence generateEnumDeclaration(final String name, final String primitiveType) + { return "from enum import IntEnum \n\n" + - "class " + name + "(IntEnum):\n"; + "class " + name + "(IntEnum):\n"; } - private CharSequence generatePrimitiveProperty(final String propertyName, final Token token, final String indent, String parentClassName) { + private CharSequence generatePrimitiveProperty(final String propertyName, final Token token, final String indent, + final String parentClassName) + { final StringBuilder sb = new StringBuilder(); sb.append(generatePrimitiveFieldMetaData(propertyName, token, indent)); - if (token.isConstantEncoding()) { + if (token.isConstantEncoding()) + { sb.append(generateConstPropertyMethods(propertyName, token, indent)); - } else { + } + else + { sb.append(generatePrimitivePropertyMethods(propertyName, token, indent, parentClassName)); } @@ -721,15 +805,19 @@ private CharSequence generatePrimitiveProperty(final String propertyName, final } private CharSequence generatePrimitivePropertyMethods( - final String propertyName, - final Token token, - final String indent, - final String parentClassName) { + final String propertyName, + final Token token, + final String indent, + final String parentClassName) + { final int arrayLength = token.arrayLength(); - if (arrayLength == 1) { + if (arrayLength == 1) + { return generateSingleValueProperty(propertyName, token, indent, parentClassName); - } else if (arrayLength > 1) { + } + else if (arrayLength > 1) + { return generateArrayProperty(propertyName, token, indent, parentClassName); } @@ -737,109 +825,121 @@ private CharSequence generatePrimitivePropertyMethods( } private CharSequence generatePrimitiveFieldMetaData( - final String propertyName, - final Token token, - final String indent) { + final String propertyName, + final Token token, + final String indent) + { final PrimitiveType primitiveType = token.encoding().primitiveType(); final String typeName = pythonTypeName(primitiveType); return String.format( - "\n" + - indent + "%2$s_NULL_VALUE: '%1$s' = %3$s\n" + - indent + "%2$s_MIN_VALUE: '%1$s' = %4$s\n" + - indent + "%2$s_MAX_VALUE: '%1$s' = %5$s\n", - typeName, - camToSnake(propertyName).toUpperCase(), - generateLiteral(primitiveType, token.encoding().applicableNullValue().toString()), - generateLiteral(primitiveType, token.encoding().applicableMinValue().toString()), - generateLiteral(primitiveType, token.encoding().applicableMaxValue().toString())); + "\n" + + indent + "%2$s_NULL_VALUE: '%1$s' = %3$s\n" + + indent + "%2$s_MIN_VALUE: '%1$s' = %4$s\n" + + indent + "%2$s_MAX_VALUE: '%1$s' = %5$s\n", + typeName, + camToSnake(propertyName).toUpperCase(), + generateLiteral(primitiveType, token.encoding().applicableNullValue().toString()), + generateLiteral(primitiveType, token.encoding().applicableMinValue().toString()), + generateLiteral(primitiveType, token.encoding().applicableMaxValue().toString())); } private CharSequence generateSingleValueProperty( - final String propertyName, - final Token token, - final String indent, - final String parentClassName) { + final String propertyName, + final Token token, + final String indent, + final String parentClassName) + { final String typeName = pythonTypeName(token.encoding().primitiveType()); final String typePrefix = toUpperFirstChar(token.encoding().primitiveType().primitiveName()); final int offset = token.offset(); final ByteOrder byteOrder = token.encoding().byteOrder(); final String byteOrderStr = byteOrder.toString(); - String getter = String.format("\n" + - indent + "def get_%2$s(self) -> '%1$s':\n" + - "%3$s" + - indent + INDENT + "return %4$S_%6$S.unpack_from(self._buffer, self._offset + %5$d)[0]", - typeName, - camToSnake(propertyName), - generateFieldNotPresentCondition(token.version(), token.encoding(), indent), - typePrefix.toUpperCase(), - offset, - byteOrderStr); - - String setter = String.format("\n" + - indent + "def set_%2$s(self, value:%1$s) -> '%3$s':\n" + - indent + INDENT + "%4$S_%6$s.pack_into(self._buffer, self._offset + %5$d, value)\n" + - indent + INDENT + "return self\n", - typeName, - camToSnake(propertyName), - formatClassName(parentClassName), - typePrefix.toUpperCase(), - offset, - byteOrderStr); + final String getter = String.format("\n" + + indent + "def get_%2$s(self) -> '%1$s':\n" + + "%3$s" + + indent + " return %4$S_%6$S.unpack_from(self._buffer, self._offset + %5$d)[0]", + typeName, + camToSnake(propertyName), + generateFieldNotPresentCondition(token.version(), token.encoding(), indent), + typePrefix.toUpperCase(), + offset, + byteOrderStr); + + final String setter = String.format("\n" + + indent + "def set_%2$s(self, value:%1$s) -> '%3$s':\n" + + indent + " %4$S_%6$s.pack_into(self._buffer, self._offset + %5$d, value)\n" + + indent + " return self\n", + typeName, + camToSnake(propertyName), + formatClassName(parentClassName), + typePrefix.toUpperCase(), + offset, + byteOrderStr); return getter + "\n" + setter + "\n"; } private CharSequence generateFieldNotPresentCondition( - final int sinceVersion, - final Encoding encoding, - final String indent) { - if (0 == sinceVersion) { + final int sinceVersion, + final Encoding encoding, + final String indent) + { + if (0 == sinceVersion) + { return ""; } final String literal; - if (sinceVersion > 0) { + if (sinceVersion > 0) + { literal = generateLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString()); - } else { + } + else + { literal = "(byte)0"; } return String.format( - indent + "if self._acting_version < %1$d: return %2$s\n\n", - sinceVersion, - literal); + indent + "if self._acting_version < %1$d: return %2$s\n\n", + sinceVersion, + literal); } private CharSequence generateArrayFieldNotPresentCondition( - final int sinceVersion, - final String indent) { - if (0 == sinceVersion) { + final int sinceVersion, + final String indent) + { + if (0 == sinceVersion) + { return ""; } return String.format( - indent + "if self._acting_version < %d: return 0\n\n", - sinceVersion); + indent + "if self._acting_version < %d: return 0\n\n", + sinceVersion); } private CharSequence generateTypeFieldNotPresentCondition( - final int sinceVersion, - final String indent) { - if (0 == sinceVersion) { + final int sinceVersion, + final String indent) + { + if (0 == sinceVersion) + { return ""; } return String.format( - indent + "if self._acting_version < %d: return None\n\n", - sinceVersion); + indent + "if self._acting_version < %d: return None\n\n", + sinceVersion); } private CharSequence generateArrayProperty( - final String propertyName, - final Token token, - final String indent, - final String parentClassName) { + final String propertyName, + final Token token, + final String indent, + final String parentClassName) + { final String typeName = pythonTypeName(token.encoding().primitiveType()); final String typePrefix = toUpperFirstChar(token.encoding().primitiveType().primitiveName()); final int offset = token.offset(); @@ -852,92 +952,100 @@ private CharSequence generateArrayProperty( final StringBuilder sb = new StringBuilder(); sb.append(String.format("\n" + - indent + "%1$S_LENGTH = %2$d\n", - camToSnake(propName), fieldLength)); + indent + "%1$S_LENGTH = %2$d\n", + camToSnake(propName), fieldLength)); - String structParserMulti = String.format("A_%1$S_%2$S_%3$S", camToSnake(propName), typePrefix, byteOrderStr); + final String structParserMulti = String.format("A_%1$S_%2$S_%3$S", camToSnake(propName), typePrefix, + byteOrderStr); sb.append(String.format("\n" + - indent + structParserMulti + " = Struct('%1$s%2$d%3$s') \n", - pythonEndianCode(byteOrder), fieldLength, - pythonTypeCode(token.encoding().primitiveType()))); + indent + structParserMulti + " = Struct('%1$s%2$d%3$s') \n", + pythonEndianCode(byteOrder), fieldLength, + pythonTypeCode(token.encoding().primitiveType()))); - if (token.encoding().primitiveType() == PrimitiveType.CHAR) { + if (token.encoding().primitiveType() == PrimitiveType.CHAR) + { generateCharacterEncodingMethod(sb, propertyName, token.encoding().characterEncoding(), indent); //Properties for multi item assignment sb.append(String.format("\n" + - indent + "def get_multi_%2$s(self) -> bytes:\n" + - "%4$s" + - indent + INDENT + "return self." + structParserMulti + ".unpack_from(self._buffer, self._offset + %5$d)[0]\n", - typeName, camToSnake(propName), fieldLength, - generateFieldNotPresentCondition(token.version(), token.encoding(), indent), - offset, typeSize)); - } else { + indent + "def get_multi_%2$s(self) -> bytes:\n" + + "%4$s" + + indent + " return self." + structParserMulti + ".unpack_from(self._buffer, self._offset + %5$d)[0]" + + "\n", + typeName, camToSnake(propName), fieldLength, + generateFieldNotPresentCondition(token.version(), token.encoding(), indent), + offset, typeSize)); + } + else + { //Properties for multi item assignment sb.append(String.format("\n" + - indent + "def get_multi_%2$s(self) -> Tuple['%1$s']:\n" + - "%4$s" + - indent + INDENT + "return self." + structParserMulti + ".unpack_from(self._buffer, self._offset + %5$d)\n", - typeName, camToSnake(propName), fieldLength, - generateFieldNotPresentCondition(token.version(), token.encoding(), indent), - offset, typeSize)); + indent + "def get_multi_%2$s(self) -> Tuple['%1$s']:\n" + + "%4$s" + + indent + " return self." + structParserMulti + ".unpack_from(self._buffer, self._offset + %5$d)\n", + typeName, camToSnake(propName), fieldLength, + generateFieldNotPresentCondition(token.version(), token.encoding(), indent), + offset, typeSize)); } sb.append(String.format("\n" + - indent + "def set_%1$s(self, value:%2$s) -> '%4$s':\n" + - indent + INDENT + "self." + structParserMulti + ".pack_into(self._buffer, self._offset + %3$d, value)\n" + - indent + INDENT + "return self\n", - camToSnake(propName), typeName, offset, parentClassName)); + indent + "def set_%1$s(self, value:%2$s) -> '%4$s':\n" + + indent + " self." + structParserMulti + ".pack_into(self._buffer, self._offset + %3$d, value)\n" + + indent + " return self\n", + camToSnake(propName), typeName, offset, parentClassName)); //Properties for single assigment sb.append(String.format("\n" + - indent + "def get_%2$s(self, index: int) -> '%1$s':\n" + - indent + INDENT + "if index < 0 or index >= %3$d:\n" + - indent + INDENT + INDENT + "raise IndexError(\"index out of range: index=\" + str(index))\n\n" + - "%4$s" + - indent + INDENT + "return %5$S_%8$S.unpack_from(self._buffer, self._offset + %6$d + (index * %7$d))[0]\n", - typeName, camToSnake(propName), fieldLength, - generateFieldNotPresentCondition(token.version(), token.encoding(), indent), typePrefix, - offset, typeSize, byteOrder)); + indent + "def get_%2$s(self, index: int) -> '%1$s':\n" + + indent + " if index < 0 or index >= %3$d:\n" + + indent + " raise IndexError(\"index out of range: index=\" + str(index))\n\n" + + "%4$s" + + indent + " return %5$S_%8$S.unpack_from(self._buffer, self._offset + %6$d + (index * %7$d))[0]\n", + typeName, camToSnake(propName), fieldLength, + generateFieldNotPresentCondition(token.version(), token.encoding(), indent), typePrefix, + offset, typeSize, byteOrder)); sb.append(String.format("\n" + - indent + "def put_%1$s(self, index:int, value:%2$s) -> '%8$s':\n" + - indent + INDENT + "if index < 0 or index >= %3$d:\n" + - indent + INDENT + INDENT + "raise IndexError(\"index out of range: index=\" + str(index))\n\n" + - indent + INDENT + "%4$S_%7$S.pack_into(self._buffer, self._offset + %5$d + (index * %6$d), value)\n" + - indent + INDENT + "return self\n", - camToSnake(propName), typeName, fieldLength, typePrefix, offset, typeSize, byteOrder, parentClassName)); + indent + "def put_%1$s(self, index:int, value:%2$s) -> '%8$s':\n" + + indent + " if index < 0 or index >= %3$d:\n" + + indent + " raise IndexError(\"index out of range: index=\" + str(index))\n\n" + + indent + " %4$S_%7$S.pack_into(self._buffer, self._offset + %5$d + (index * %6$d), value)\n" + + indent + " return self\n", + camToSnake(propName), typeName, fieldLength, typePrefix, offset, typeSize, byteOrder, parentClassName)); return sb; } private void generateCharacterEncodingMethod( - final StringBuilder sb, - final String propertyName, - final String encoding, - final String indent) { + final StringBuilder sb, + final String propertyName, + final String encoding, + final String indent) + { sb.append(String.format("\n" + - indent + "%S_CHAR_ENCODING = \"%s\"\n\n", - camToSnake(formatPropertyName(propertyName)), - encoding)); + indent + "%S_CHAR_ENCODING = \"%s\"\n\n", + camToSnake(formatPropertyName(propertyName)), + encoding)); } private CharSequence generateConstPropertyMethods( - final String propertyName, - final Token token, - final String indent) { - if (token.encoding().primitiveType() != PrimitiveType.CHAR) { + final String propertyName, + final Token token, + final String indent) + { + if (token.encoding().primitiveType() != PrimitiveType.CHAR) + { // ODE: we generate a property here because the constant could // become a field in a newer version of the protocol return String.format("\n" + - indent + "@property\n" + - indent + "def get_%2$s(self) -> '%1$s':\n" + - indent + INDENT + " return %3$s\n", - pythonTypeName(token.encoding().primitiveType()), - camToSnake(propertyName), - generateLiteral(token.encoding().primitiveType(), token.encoding().constValue().toString())); + indent + "@property\n" + + indent + "def get_%2$s(self) -> '%1$s':\n" + + indent + " return %3$s\n", + pythonTypeName(token.encoding().primitiveType()), + camToSnake(propertyName), + generateLiteral(token.encoding().primitiveType(), token.encoding().constValue().toString())); } final StringBuilder sb = new StringBuilder(); @@ -945,197 +1053,219 @@ private CharSequence generateConstPropertyMethods( final String pyTypeName = pythonTypeName(token.encoding().primitiveType()); final byte[] constantValue = token.encoding().constValue().byteArrayValue(token.encoding().primitiveType()); final CharSequence values = generateByteLiteralList( - token.encoding().constValue().byteArrayValue(token.encoding().primitiveType())); + token.encoding().constValue().byteArrayValue(token.encoding().primitiveType())); sb.append(String.format( - "\n" + - indent + "_%1$S_VALUE: Union[bytes, bytearray, memoryview] = bytes([ %2$s ])\n", - camToSnake(propertyName), - values)); + "\n" + + indent + "_%1$S_VALUE: Union[bytes, bytearray, memoryview] = bytes([ %2$s ])\n", + camToSnake(propertyName), + values)); sb.append(String.format( - "\n" + - indent + "%1$S_LENGTH: int = %2$d\n", - camToSnake(propertyName).toUpperCase(), - constantValue.length)); + "\n" + + indent + "%1$S_LENGTH: int = %2$d\n", + camToSnake(propertyName).toUpperCase(), + constantValue.length)); sb.append("\n"); sb.append(String.format( - indent + "def %2$s(self, index: int) -> '%1$s':\n" + - indent + INDENT + "return self._%3$s_VALUE[index]\n", - pyTypeName, - camToSnake(propertyName), - camToSnake(propertyName).toUpperCase())); + indent + "def %2$s(self, index: int) -> '%1$s':\n" + + indent + " return self._%3$s_VALUE[index]\n", + pyTypeName, + camToSnake(propertyName), + camToSnake(propertyName).toUpperCase())); sb.append("\n"); sb.append(String.format( - indent + "def get_%1$s(self, offset: int, length: int) -> memoryview:\n" + - indent + INDENT + "last = min(length, %2$d)\n" + - indent + INDENT + "offset = min(abs(offset), %3$d)\n" + - indent + INDENT + "return memoryview(self._%4$S_VALUE)[offset:last]\n", - camToSnake(propertyName), - constantValue.length, - constantValue.length - 1, - propertyName)); + indent + "def get_%1$s(self, offset: int, length: int) -> memoryview:\n" + + indent + " last = min(length, %2$d)\n" + + indent + " offset = min(abs(offset), %3$d)\n" + + indent + " return memoryview(self._%4$S_VALUE)[offset:last]\n", + camToSnake(propertyName), + constantValue.length, + constantValue.length - 1, + propertyName)); return sb; } - private CharSequence generateByteLiteralList(final byte[] bytes) { + private CharSequence generateByteLiteralList(final byte[] bytes) + { final StringBuilder values = new StringBuilder(); - for (final byte b : bytes) { + for (final byte b : bytes) + { values.append(b).append(", "); } - if (values.length() > 0) { + if (values.length() > 0) + { values.setLength(values.length() - 2); } return values; } - private CharSequence generateFixedFlyweightCode(final int size, final List tokens) { + private CharSequence generateFixedFlyweightCode(final int size, final List tokens) + { //reserve __slots__ to improve performance for instance fields - StringBuilder builder = new StringBuilder(); - Map fieldTypes = new LinkedHashMap<>(); - for (Token t : tokens) { - if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET) { + final StringBuilder builder = new StringBuilder(); + final Map fieldTypes = new LinkedHashMap<>(); + for (final Token t : tokens) + { + if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET) + { fieldTypes.put("_" + t.name(), t.referencedName()); } } - List fields = new ArrayList<>(fieldTypes.keySet()); + final List fields = new ArrayList<>(fieldTypes.keySet()); builder.append(INDENT + "__slots__ = '_offset', '_buffer'"); - if (fields.size() > 0) { + if (fields.size() > 0) + { builder.append(", '" + String.join("', '", fields) + "'"); } builder.append("\n\n"); builder.append(String.format( - INDENT + "SIZE: int = %d \n\n" + - INDENT + "def __init__(self):\n" + - INDENT + INDENT + "self._offset: int \n" + - INDENT + INDENT + "self._buffer: int \n", size)); - for (Map.Entry field : fieldTypes.entrySet()) { - builder.append(INDENT + INDENT + "self." + field.getKey() + ": '" + field.getValue() + "' = " + field.getValue() + "()\n"); + " SIZE: int = %d \n\n" + + " def __init__(self):\n" + + " self._offset: int \n" + + " self._buffer: int \n", size)); + for (final Map.Entry field : fieldTypes.entrySet()) + { + builder.append(INDENT + INDENT + "self." + field.getKey() + ": '" + field.getValue() + "' = " + + field.getValue() + "()\n"); } builder.append("\n"); builder.append(INDENT + "def wrap(self, buffer: Union[bytes, bytearray, memoryview], offset: int):\n" + - INDENT + INDENT + "self._offset = offset\n" + - INDENT + INDENT + "self._buffer = buffer\n" + - INDENT + INDENT + "return self\n"); + INDENT + INDENT + "self._offset = offset\n" + + INDENT + INDENT + "self._buffer = buffer\n" + + INDENT + INDENT + "return self\n"); return builder.toString(); } private CharSequence generateMessageFlyweightCode(final String className, final Token token, final String indent, - final List fields) { + final List fields) + { final String blockLengthType = pythonTypeName(ir.headerStructure().blockLengthType()); final String templateIdType = pythonTypeName(ir.headerStructure().templateIdType()); final String schemaIdType = pythonTypeName(ir.headerStructure().schemaIdType()); final String schemaVersionType = pythonTypeName(ir.headerStructure().schemaVersionType()); final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); - StringBuilder builder = new StringBuilder(); - Map fieldTypes = new LinkedHashMap<>(); - for (Token t : fields) { - if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET) { + final StringBuilder builder = new StringBuilder(); + final Map fieldTypes = new LinkedHashMap<>(); + for (final Token t : fields) + { + if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET) + { fieldTypes.put("_" + camToSnake(t.name()), t.referencedName() != null ? t.referencedName() : t.name()); } } builder.append(String.format( - indent + "BLOCK_LENGTH: '%1$s' = %2$s\n" + - indent + "TEMPLATE_ID: '%3$s' = %4$s\n" + - indent + "SCHEMA_ID: '%5$s' = %6$s\n" + - indent + "SCHEMA_VERSION: '%7$s' = %8$s\n" + - indent + "SEMANTIC_TYPE: str = \"%9$s\"\n\n", - blockLengthType, - generateLiteral(ir.headerStructure().blockLengthType(), Integer.toString(token.encodedLength())), - templateIdType, - generateLiteral(ir.headerStructure().templateIdType(), Integer.toString(token.id())), - schemaIdType, - generateLiteral(ir.headerStructure().schemaIdType(), Integer.toString(ir.id())), - schemaVersionType, - generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), - semanticType)); - - builder.append(indent + "__slots__ = '_parent_message', '_buffer', '_offset', '_limit', '_acting_block_length', '_acting_version'"); - if (fieldTypes.size() > 0) { + indent + "BLOCK_LENGTH: '%1$s' = %2$s\n" + + indent + "TEMPLATE_ID: '%3$s' = %4$s\n" + + indent + "SCHEMA_ID: '%5$s' = %6$s\n" + + indent + "SCHEMA_VERSION: '%7$s' = %8$s\n" + + indent + "SEMANTIC_TYPE: str = \"%9$s\"\n\n", + blockLengthType, + generateLiteral(ir.headerStructure().blockLengthType(), Integer.toString(token.encodedLength())), + templateIdType, + generateLiteral(ir.headerStructure().templateIdType(), Integer.toString(token.id())), + schemaIdType, + generateLiteral(ir.headerStructure().schemaIdType(), Integer.toString(ir.id())), + schemaVersionType, + generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), + semanticType)); + + builder.append(indent + "__slots__ = '_parent_message', '_buffer', '_offset', '_limit', " + + "'_acting_block_length', '_acting_version'"); + if (fieldTypes.size() > 0) + { builder.append(", '" + String.join("', '", fieldTypes.keySet()) + "'"); } builder.append("\n\n"); - builder.append(String.format(indent + "def __init__(self):\n" + - indent + INDENT + "self._parent_message: '%1$s' = self\n" + - indent + INDENT + "self._buffer: Union[bytes, bytearray, memoryview]\n" + - indent + INDENT + "self._offset: int\n" + - indent + INDENT + "self._limit: int\n" + - indent + INDENT + "self._acting_block_length: int\n" + - indent + INDENT + "self._acting_version: int\n", className)); - for (Map.Entry ft : fieldTypes.entrySet()) { - builder.append(indent + INDENT + "self." + ft.getKey() + ": '" + ft.getValue() + "' = " + ft.getValue() + "()\n"); + builder.append(String.format( + indent + "def __init__(self):\n" + + indent + " self._parent_message: '%1$s' = self\n" + + indent + " self._buffer: Union[bytes, bytearray, memoryview]\n" + + indent + " self._offset: int\n" + + indent + " self._limit: int\n" + + indent + " self._acting_block_length: int\n" + + indent + " self._acting_version: int\n", className)); + for (final Map.Entry ft : fieldTypes.entrySet()) + { + builder.append(indent + INDENT + "self." + ft.getKey() + ": '" + ft.getValue() + "' = " + + ft.getValue() + "()\n"); } builder.append("\n"); builder.append( - indent + "@property\n" + - indent + "def offset(self) -> int:\n" + - indent + INDENT + "return self._offset\n\n" + - indent + "def wrap_encode(self, buffer: Union[bytes, bytearray, memoryview], offset: int):\n" + - indent + INDENT + "self._buffer = buffer\n" + - indent + INDENT + "self._offset = offset\n" + - indent + INDENT + "self._acting_block_length = self.BLOCK_LENGTH\n" + - indent + INDENT + "self._acting_version = self.SCHEMA_VERSION\n" + - indent + INDENT + "self.set_limit(offset + self._acting_block_length)\n" + - indent + INDENT + "return self\n"); + indent + "@property\n" + + indent + "def offset(self) -> int:\n" + + indent + " return self._offset\n\n" + + indent + "def wrap_encode(self, buffer: Union[bytes, bytearray, memoryview], offset: int):\n" + + indent + " self._buffer = buffer\n" + + indent + " self._offset = offset\n" + + indent + " self._acting_block_length = self.BLOCK_LENGTH\n" + + indent + " self._acting_version = self.SCHEMA_VERSION\n" + + indent + " self.set_limit(offset + self._acting_block_length)\n" + + indent + " return self\n"); builder.append("\n"); builder.append( - indent + "def wrap_decode(self,buffer: Union[bytes, bytearray, memoryview], offset: int, " + - "acting_block_length: int, acting_version:int):\n" + - indent + INDENT + "self._buffer = buffer\n" + - indent + INDENT + "self._offset = offset\n" + - indent + INDENT + "self._acting_block_length = acting_block_length\n" + - indent + INDENT + "self._acting_version = acting_version\n" + - indent + INDENT + "self.set_limit(offset + self._acting_block_length)\n" + - indent + INDENT + "return self\n"); + indent + "def wrap_decode(self,buffer: Union[bytes, bytearray, memoryview], offset: int, " + + "acting_block_length: int, acting_version:int):\n" + + indent + " self._buffer = buffer\n" + + indent + " self._offset = offset\n" + + indent + " self._acting_block_length = acting_block_length\n" + + indent + " self._acting_version = acting_version\n" + + indent + " self.set_limit(offset + self._acting_block_length)\n" + + indent + " return self\n"); builder.append("\n"); builder.append( - indent + "def size(self) -> int:\n" + - indent + INDENT + "return self._limit - self._offset\n" + - indent + "\n\n" + - indent + "@property\n" + - indent + "def limit(self) -> int:\n" + - indent + INDENT + "return self._limit\n"); + indent + "def size(self) -> int:\n" + + indent + " return self._limit - self._offset\n" + + indent + "\n\n" + + indent + "@property\n" + + indent + "def limit(self) -> int:\n" + + indent + " return self._limit\n"); builder.append("\n"); builder.append( - indent + "def set_limit(self, value):\n" + - //TODO: make sure the capacity is checked either wrap in bytearray - indent + INDENT + "#self._buffer.CheckLimit(value);\n" + - indent + INDENT + "self._limit = value\n" + - indent + INDENT + "return self\n"); + indent + "def set_limit(self, value):\n" + + //TODO: make sure the capacity is checked either wrap in bytearray + indent + " #self._buffer.CheckLimit(value);\n" + + indent + " self._limit = value\n" + + indent + " return self\n"); return builder.toString(); } - private CharSequence generateFields(final List tokens, final String indent, final String parentClassName) { + private CharSequence generateFields(final List tokens, final String indent, final String parentClassName) + { final StringBuilder sb = new StringBuilder(); - for (int i = 0, size = tokens.size(); i < size; i++) { + for (int i = 0, size = tokens.size(); i < size; i++) + { final Token signalToken = tokens.get(i); - if (signalToken.signal() == Signal.BEGIN_FIELD) { + if (signalToken.signal() == Signal.BEGIN_FIELD) + { final Token encodingToken = tokens.get(i + 1); final String propertyName = signalToken.name(); generateFieldIdMethod(sb, signalToken, indent); generateFieldMetaAttributeMethod(sb, signalToken, indent); - switch (encodingToken.signal()) { + switch (encodingToken.signal()) + { case ENCODING: sb.append(generatePrimitiveProperty(propertyName, encodingToken, indent, parentClassName)); break; case BEGIN_ENUM: - sb.append(generateEnumProperty(propertyName, encodingToken, signalToken, indent, parentClassName)); + sb.append(generateEnumProperty(propertyName, encodingToken, signalToken, indent, + parentClassName)); break; case BEGIN_SET: @@ -1152,16 +1282,18 @@ private CharSequence generateFields(final List tokens, final String inden return sb; } - private void generateFieldIdMethod(final StringBuilder sb, final Token token, final String indent) { + private void generateFieldIdMethod(final StringBuilder sb, final Token token, final String indent) + { sb.append(String.format("\n" + - indent + "%S_ID: int = %d\n", - camToSnake(token.name()), - token.id())); + indent + "%S_ID: int = %d\n", + camToSnake(token.name()), + token.id())); generateSinceActingDeprecated(sb, indent, token.name(), token); } - private void generateFieldMetaAttributeMethod(final StringBuilder sb, final Token token, final String indent) { + private void generateFieldMetaAttributeMethod(final StringBuilder sb, final Token token, final String indent) + { final Encoding encoding = token.encoding(); final String epoch = encoding.epoch() == null ? "" : encoding.epoch(); final String timeUnit = encoding.timeUnit() == null ? "" : encoding.timeUnit(); @@ -1169,40 +1301,43 @@ private void generateFieldMetaAttributeMethod(final StringBuilder sb, final Toke final String presence = encoding.presence() == null ? "" : encoding.presence().toString().toLowerCase(); sb.append(String.format("\n" + - indent + "@staticmethod\n" + - indent + "def %s_meta_attribute(meta_attribute: 'MetaAttribute') -> str:\n" + - indent + INDENT + "if meta_attribute == MetaAttribute.Epoch: return '%s'\n" + - indent + INDENT + "if meta_attribute == MetaAttribute.TimeUnit: return '%s'\n" + - indent + INDENT + "if meta_attribute == MetaAttribute.SemanticType: return '%s'\n" + - indent + INDENT + "if meta_attribute == MetaAttribute.Presence: return '%s'\n" + - indent + INDENT + "return ''\n", - camToSnake(token.name()), - epoch, - timeUnit, - semanticType, - presence)); + indent + "@staticmethod\n" + + indent + "def %s_meta_attribute(meta_attribute: 'MetaAttribute') -> str:\n" + + indent + " if meta_attribute == MetaAttribute.Epoch: return '%s'\n" + + indent + " if meta_attribute == MetaAttribute.TimeUnit: return '%s'\n" + + indent + " if meta_attribute == MetaAttribute.SemanticType: return '%s'\n" + + indent + " if meta_attribute == MetaAttribute.Presence: return '%s'\n" + + indent + " return ''\n", + camToSnake(token.name()), + epoch, + timeUnit, + semanticType, + presence)); } private CharSequence generateEnumFieldNotPresentCondition( - final int sinceVersion, - final String enumName, - final String indent) { - if (0 == sinceVersion) { + final int sinceVersion, + final String enumName, + final String indent) + { + if (0 == sinceVersion) + { return ""; } return String.format( - indent + "if self._acting_version < %d: return %s.NULL_VALUE\n\n", - sinceVersion, - enumName); + indent + "if self._acting_version < %d: return %s.NULL_VALUE\n\n", + sinceVersion, + enumName); } private CharSequence generateEnumProperty( - final String propertyName, - final Token token, - final Token signalToken, - final String indent, - final String parentClassName) { + final String propertyName, + final Token token, + final Token signalToken, + final String indent, + final String parentClassName) + { final String enumName = formatClassName(token.applicableTypeName()); final String typePrefix = toUpperFirstChar(token.encoding().primitiveType().primitiveName()); final String typeName = pythonTypeName(token.encoding().primitiveType()); @@ -1211,133 +1346,146 @@ private CharSequence generateEnumProperty( final ByteOrder byteOrder = token.encoding().byteOrder(); final String byteOrderStr = byteOrder.toString(); - if (signalToken != null && signalToken.isConstantEncoding()) { + if (signalToken != null && signalToken.isConstantEncoding()) + { final String constValue = signalToken.encoding().constValue().toString(); return String.format("\n" + - indent + "@staticmethod\n" + - indent + "def get_%2$s() -> '%1$s':\n" + - indent + INDENT + "return %3$s\n", - enumName, - camToSnake(propertyName), - constValue); - } else { + indent + "@staticmethod\n" + + indent + "def get_%2$s() -> '%1$s':\n" + + indent + " return %3$s\n", + enumName, + camToSnake(propertyName), + constValue); + } + else + { String enumStructType = typePrefix; - if (typePrefix.toUpperCase().equals("CHAR")) { + if (typePrefix.toUpperCase().equals("CHAR")) + { enumStructType = "INT8"; } - String getter = String.format( - indent + "def get_%2$s(self) -> '%1$s':\n" + - "%3$s" + - indent + INDENT + "return %4$s(%5$S_%7$S.unpack_from(self._buffer, self._offset + %6$d)[0])\n\n", - enumName, - camToSnake(propertyName), - generateEnumFieldNotPresentCondition(token.version(), enumName, indent), - enumName, - enumStructType, - offset, - byteOrderStr, - enumUnderlyingType); + final String getter = String.format( + indent + "def get_%2$s(self) -> '%1$s':\n" + + "%3$s" + + indent + " return %4$s(%5$S_%7$S.unpack_from(self._buffer, self._offset + %6$d)[0])\n\n", + enumName, + camToSnake(propertyName), + generateEnumFieldNotPresentCondition(token.version(), enumName, indent), + enumName, + enumStructType, + offset, + byteOrderStr, + enumUnderlyingType); String cast = enumUnderlyingType + "(value)"; - if (enumUnderlyingType.equals("bytes") && enumStructType.equals("INT8")) { + if (enumUnderlyingType.equals("bytes") && enumStructType.equals("INT8")) + { cast = "value"; - } else if (enumUnderlyingType.equals("bytes")) { + } + else if (enumUnderlyingType.equals("bytes")) + { cast = "bytes([value])"; } - String setter = String.format("\n" + - indent + "def set_%2$s(self, value: '%4$s') -> '%9$s':\n" + - "%3$s" + - indent + INDENT + "%5$S_%8$S.pack_into(self._buffer, self._offset + %7$d, %10$s)\n" + - indent + INDENT + "return self\n\n", - enumName, - camToSnake(propertyName), - generateEnumFieldNotPresentCondition(token.version(), enumName, indent), - enumName, - enumStructType, - typeName, - offset, - byteOrderStr, - parentClassName, - cast); + final String setter = String.format("\n" + + indent + "def set_%2$s(self, value: '%4$s') -> '%9$s':\n" + + "%3$s" + + indent + " %5$S_%8$S.pack_into(self._buffer, self._offset + %7$d, %10$s)\n" + + indent + " return self\n\n", + enumName, + camToSnake(propertyName), + generateEnumFieldNotPresentCondition(token.version(), enumName, indent), + enumName, + enumStructType, + typeName, + offset, + byteOrderStr, + parentClassName, + cast); return getter + setter; } } - private String generateBitSetProperty(final String propertyName, final Token token, final String indent) { + private String generateBitSetProperty(final String propertyName, final Token token, final String indent) + { final String bitSetName = formatClassName(token.applicableTypeName()); final int offset = token.offset(); - String getter = String.format("\n" + - indent + "def get_%2$s(self) -> '%1$s':\n" + - "%3$s" + - indent + INDENT + "return self._%5$s.wrap_decode(self._buffer, self._offset + %4$d, self._acting_block_length, self._acting_version)\n", - bitSetName, - camToSnake(propertyName), - generateTypeFieldNotPresentCondition(token.version(), indent), - offset, - camToSnake(bitSetName)); - - String setter = String.format("\n" + - indent + "def set_%3$s(self) -> '%1$s':\n" + - indent + INDENT + "return self._%2$s.wrap_encode(self._buffer, self._offset + %4$d)\n", - bitSetName, - camToSnake(bitSetName), - camToSnake(propertyName), - offset); + final String getter = String.format("\n" + + indent + "def get_%2$s(self) -> '%1$s':\n" + + "%3$s" + + indent + " return self._%5$s.wrap_decode(self._buffer, self._offset + %4$d, " + + "self._acting_block_length, self._acting_version)\n", + bitSetName, + camToSnake(propertyName), + generateTypeFieldNotPresentCondition(token.version(), indent), + offset, + camToSnake(bitSetName)); + + final String setter = String.format("\n" + + indent + "def set_%3$s(self) -> '%1$s':\n" + + indent + " return self._%2$s.wrap_encode(self._buffer, self._offset + %4$d)\n", + bitSetName, + camToSnake(bitSetName), + camToSnake(propertyName), + offset); return getter + setter; } - private Object generateCompositeProperty(final String propertyName, final Token token, final String indent) { + private Object generateCompositeProperty(final String propertyName, final Token token, final String indent) + { final String compositeName = formatClassName(token.applicableTypeName()); final int offset = token.offset(); final StringBuilder sb = new StringBuilder(); sb.append(String.format("\n" + - indent + "def set_%2$s(self) -> '%1$s':\n" + - "%3$s" + - indent + INDENT + "self._%4$s.wrap(self._buffer, self._offset + %5$d)\n" + - indent + INDENT + "return self._%4$s\n", - compositeName, - camToSnake(propertyName), - generateTypeFieldNotPresentCondition(token.version(), indent), - camToSnake(propertyName), - offset)); + indent + "def set_%2$s(self) -> '%1$s':\n" + + "%3$s" + + indent + " self._%4$s.wrap(self._buffer, self._offset + %5$d)\n" + + indent + " return self._%4$s\n", + compositeName, + camToSnake(propertyName), + generateTypeFieldNotPresentCondition(token.version(), indent), + camToSnake(propertyName), + offset)); sb.append(String.format("\n" + - indent + "def get_%2$s(self) -> '%1$s':\n" + - "%3$s" + - indent + INDENT + "self._%4$s.wrap(self._buffer, self._offset + %5$d)\n" + - indent + INDENT + "return self._%4$s\n", - compositeName, - camToSnake(propertyName), - generateTypeFieldNotPresentCondition(token.version(), indent), - camToSnake(propertyName), - offset)); + indent + "def get_%2$s(self) -> '%1$s':\n" + + "%3$s" + + indent + " self._%4$s.wrap(self._buffer, self._offset + %5$d)\n" + + indent + " return self._%4$s\n", + compositeName, + camToSnake(propertyName), + generateTypeFieldNotPresentCondition(token.version(), indent), + camToSnake(propertyName), + offset)); return sb; } private void generateSinceActingDeprecated( - final StringBuilder sb, - final String indent, - final String propertyName, - final Token token) { + final StringBuilder sb, + final String indent, + final String propertyName, + final Token token) + { sb.append(String.format( - indent + "%1$S_SINCE_VERSION: int = %2$d\n" + - indent + "%1$S_DEPRECATED: int = %3$d\n\n" + - indent + "@property\n" + - indent + "def %1$s_in_acting_version(self) -> bool:\n" + - indent + INDENT + "return self._acting_version >= self.%1$S_SINCE_VERSION\n", - camToSnake(propertyName), - token.version(), - token.deprecated())); + indent + "%1$S_SINCE_VERSION: int = %2$d\n" + + indent + "%1$S_DEPRECATED: int = %3$d\n\n" + + indent + "@property\n" + + indent + "def %1$s_in_acting_version(self) -> bool:\n" + + indent + " return self._acting_version >= self.%1$S_SINCE_VERSION\n", + camToSnake(propertyName), + token.version(), + token.deprecated())); } - private String generateLiteral(final PrimitiveType type, final String value) { + private String generateLiteral(final PrimitiveType type, final String value) + { String literal = ""; - switch (type) { + switch (type) + { case CHAR: literal = "\"" + value + "\""; break; @@ -1355,9 +1503,12 @@ private String generateLiteral(final PrimitiveType type, final String value) { break; case FLOAT: case DOUBLE: - if (value.endsWith("NaN")) { + if (value.endsWith("NaN")) + { literal = "float('nan')"; - } else { + } + else + { literal = value; } break; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyOutputManager.java index fe2fe8d3c0..bfdf3e00b5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyOutputManager.java @@ -24,14 +24,14 @@ import java.io.Writer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.nio.file.StandardOpenOption; import static java.io.File.separatorChar; /** * The character encoding for the {@link Writer} is UTF-8. */ -public class PyOutputManager implements OutputManager { +public class PyOutputManager implements OutputManager +{ private final File outputDir; /** @@ -41,14 +41,16 @@ public class PyOutputManager implements OutputManager { * @param baseDirName for the generated source code. * @param packageName for the generated source code relative to the baseDirName. */ - public PyOutputManager(final String baseDirName, final String packageName) { + public PyOutputManager(final String baseDirName, final String packageName) + { Verify.notNull(baseDirName, "baseDirName"); Verify.notNull(packageName, "packageName"); final String dirName = baseDirName.endsWith("" + separatorChar) ? baseDirName : baseDirName + separatorChar; final String packageDirName = dirName + packageName.replace('.', File.separatorChar); outputDir = new File(packageDirName); - if (!outputDir.exists() && !outputDir.mkdirs()) { + if (!outputDir.exists() && !outputDir.mkdirs()) + { throw new IllegalStateException("Unable to create directory: " + packageDirName); } @@ -64,7 +66,8 @@ public PyOutputManager(final String baseDirName, final String packageName) { * @return a {@link Writer} to which the source code should be written. * @throws IOException if an issue occurs when creating the file. */ - public Writer createOutput(final String name) throws IOException { + public Writer createOutput(final String name) throws IOException + { final File targetFile = new File(outputDir, name + ".py"); return Files.newBufferedWriter(targetFile.toPath(), StandardCharsets.UTF_8); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java index 9a1267b44c..f2c304e69f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java @@ -89,19 +89,23 @@ public static String pythonTypeName(final PrimitiveType primitiveType) /** * https://docs.python.org/3/library/struct.html + * * @param primitiveType SBE primitive type * @return A string representation for python c struct unpacking */ - public static String pythonTypeCode(final PrimitiveType primitiveType){ + public static String pythonTypeCode(final PrimitiveType primitiveType) + { return PRIMITIVE_TYPE_STRUCT_ENUM_MAP.get(primitiveType); } /** * https://docs.python.org/3/library/struct.html + * * @param byteOrder byte order for convertion from Java enum to python string - * @return python struct unpacking code for endianess + * @return python struct unpacking code for endianess */ - public static String pythonEndianCode(final ByteOrder byteOrder){ + public static String pythonEndianCode(final ByteOrder byteOrder) + { return BYTE_ORDER_STRING_MAP.get(byteOrder); } @@ -151,12 +155,15 @@ public static String formatClassName(final String str) /** * Converts CamelCase to snake_case, which is the recommended python case - * @param str string to transform + * + * @param str string to transform * @param toUpperFirst whether to make the first char upper case first * @return transformed string */ - public static String camToSnake(final String str, boolean toUpperFirst){ - if(toUpperFirst){ + public static String camToSnake(final String str, final boolean toUpperFirst) + { + if (toUpperFirst) + { return CAM_SNAKE_PATTERN.matcher(toUpperFirstChar(str)).replaceAll("$1_$2").toLowerCase(); } return CAM_SNAKE_PATTERN.matcher(str).replaceAll("$1_$2").toLowerCase(); @@ -166,7 +173,8 @@ public static String camToSnake(final String str, boolean toUpperFirst){ * @param str string to transform * @return transformed strings with toUpper applied */ - public static String camToSnake(final String str){ + public static String camToSnake(final String str) + { return camToSnake(str, true); } @@ -186,9 +194,9 @@ public static String generateTypePydoc(final String indent, final Token typeToke } return - indent + "\"\"\"\n" + - indent + " " + description + '\n' + - indent + "\"\"\"\n"; + indent + "\"\"\"\n" + + indent + " " + description + '\n' + + indent + "\"\"\"\n"; } /** @@ -200,7 +208,7 @@ public static String generateTypePydoc(final String indent, final Token typeToke * @return a string representation of the Javadoc comment. */ public static String generateFlyweightPropertyPydoc( - final String indent, final Token propertyToken, final String typeName) + final String indent, final Token propertyToken, final String typeName) { final String description = propertyToken.description(); if (null == description || description.isEmpty()) @@ -209,10 +217,10 @@ public static String generateFlyweightPropertyPydoc( } return - indent + "\"\"\"\n" + - indent + description + '\n' + - indent + "@return " + typeName + " : " + description + "\n" + - indent + " \"\"\"\n"; + indent + "\"\"\"\n" + + indent + description + '\n' + + indent + "@return " + typeName + " : " + description + "\n" + + indent + " \"\"\"\n"; } /** @@ -224,7 +232,7 @@ public static String generateFlyweightPropertyPydoc( * @return a string representation of the Javadoc comment. */ public static String generateGroupEncodePropertyPydoc( - final String indent, final Token propertyToken, final String typeName) + final String indent, final Token propertyToken, final String typeName) { final String description = propertyToken.description(); if (null == description || description.isEmpty()) @@ -233,11 +241,11 @@ public static String generateGroupEncodePropertyPydoc( } return - indent + "/**\n" + - indent + " * " + description + "\n" + - indent + " *\n" + - indent + " * @param count of times the group will be encoded\n" + - indent + " * @return " + typeName + " : encoder for the group\n" + - indent + " */\n"; + indent + "/**\n" + + indent + " * " + description + "\n" + + indent + " *\n" + + indent + " * @param count of times the group will be encoded\n" + + indent + " * @return " + typeName + " : encoder for the group\n" + + indent + " */\n"; } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java index 10f582a81e..a6565ab37f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java @@ -24,12 +24,15 @@ * of specifying a TargetCodeGenerator Java class name rather than the language * name. */ -public class Python implements TargetCodeGenerator { - public CodeGenerator newInstance(final Ir ir, final String outputDir) { +public class Python implements TargetCodeGenerator +{ + public CodeGenerator newInstance(final Ir ir, final String outputDir) + { return defaultPythonGenerator(ir, outputDir); } - public static CodeGenerator defaultPythonGenerator(final Ir ir, final String outputDir) { + public static CodeGenerator defaultPythonGenerator(final Ir ir, final String outputDir) + { return new PyGenerator(ir, new PyOutputManager(outputDir, ir.applicableNamespace())); } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java index 59451ea887..9a37431728 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java @@ -12,9 +12,11 @@ import static org.junit.Assert.assertTrue; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class PyGeneratorTest { +public class PyGeneratorTest +{ @Test() - public void codeGenerationSchemaTest() throws Exception { + public void codeGenerationSchemaTest() throws Exception + { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); final MessageSchema schema = parse(TestUtil.getLocalResource("example-schema.xml"), options); final IrGenerator irg = new IrGenerator(); From 487b2265be2b5bf93962a3a32aa60c18cb4760ce Mon Sep 17 00:00:00 2001 From: Feras Date: Sun, 28 Apr 2019 22:47:39 -0400 Subject: [PATCH 0151/1594] [Java] Python generator, additional unit tests, readme updated --- README.md | 12 ++ build.gradle | 46 +++++++- python/tests/gen/.gitignore | 2 - python/tests/test_car_example.py | 4 +- python/tests/test_issue435.py | 42 +++++++ python/tests/test_issue483.py | 13 +++ python/tests/test_issue560.py | 20 ++++ .../sbe/generation/python/PyGenerator.java | 107 ++++++++++-------- .../sbe/generation/python/PyUtil.java | 72 ------------ 9 files changed, 193 insertions(+), 125 deletions(-) delete mode 100644 python/tests/gen/.gitignore create mode 100644 python/tests/test_issue435.py create mode 100644 python/tests/test_issue483.py create mode 100644 python/tests/test_issue560.py diff --git a/README.md b/README.md index 9b7745b5cb..3e96e66683 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,18 @@ Users of CSharp generated code should see the [user documentation](https://githu Developers wishing to enhance the CSharp generator should see the [developer documentation](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/README.md) +Python Build +------------ +Python support is experimental and tested against Python >= 3.6. Other python versions and implementations +should also work, given that they have support for the `struct` package and the `buffer protocol`, but they aren't +officially supported. + +Use the following the build the java stub generator and execute the python tests: +```bash +$ ./gradlew +$ ./gradlew runPythonTests +``` + License (See LICENSE file for full license) ------------------------------------------- Copyright 2013-2019 Real Logic Limited diff --git a/build.gradle b/build.gradle index de43f86aa8..dfcdc6699c 100644 --- a/build.gradle +++ b/build.gradle @@ -783,6 +783,48 @@ task generatePythonCarExample(type: JavaExec) { args = ['sbe-tool/src/test/resources/example-schema.xml'] } +task generatePythonIssue435Codecs(type: JavaExec) { + main = 'uk.co.real_logic.sbe.SbeTool' + classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'python/tests', + 'sbe.target.language': 'uk.co.real_logic.sbe.generation.python.Python', + 'sbe.target.namespace': 'gen.issue435') + args = ['sbe-tool/src/test/resources/issue435.xml'] +} + +task generatePythonIssue483Codecs(type: JavaExec) { + main = 'uk.co.real_logic.sbe.SbeTool' + classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'python/tests', + 'sbe.target.language': 'uk.co.real_logic.sbe.generation.python.Python', + 'sbe.target.namespace': 'gen.issue483') + args = ['sbe-tool/src/test/resources/issue483.xml'] +} + +task generatePythonIssue560Codecs(type: JavaExec) { + main = 'uk.co.real_logic.sbe.SbeTool' + classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'python/tests', + 'sbe.target.language': 'uk.co.real_logic.sbe.generation.python.Python', + 'sbe.target.namespace': 'gen.issue560') + args = ['sbe-tool/src/test/resources/issue560.xml'] +} + +task generatePythonFixBinaryCodecs(type: JavaExec) { + main = 'uk.co.real_logic.sbe.SbeTool' + classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'python/tests', + 'sbe.target.language': 'uk.co.real_logic.sbe.generation.python.Python', + 'sbe.target.namespace': 'gen.fix_binary') + args = [ + 'sbe-tool/src/test/resources/FixBinary.xml', + ] +} + task generatePythonExampleDataFile(type: JavaExec) { mkdir "python/tests/gen/car_example" main = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub' @@ -793,7 +835,9 @@ task generatePythonExampleDataFile(type: JavaExec) { task generatePythonCodecs { description = 'Generate python test codecs' - dependsOn 'generatePythonCarExample', 'generatePythonExampleDataFile' + delete 'python/tests/gen' + dependsOn 'generatePythonCarExample', 'generatePythonExampleDataFile', 'generatePythonIssue435Codecs', + 'generatePythonIssue483Codecs', 'generatePythonIssue560Codecs', 'generatePythonFixBinaryCodecs' } task runPythonTests(type: Exec) { diff --git a/python/tests/gen/.gitignore b/python/tests/gen/.gitignore deleted file mode 100644 index c96a04f008..0000000000 --- a/python/tests/gen/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/python/tests/test_car_example.py b/python/tests/test_car_example.py index d821423ecf..aac8aa2f33 100644 --- a/python/tests/test_car_example.py +++ b/python/tests/test_car_example.py @@ -38,7 +38,7 @@ def test_decoding(self): def _encode(self, buf: bytes, header: MessageHeader, car: Car): offset = 0 - header.wrap(buf, offset) + header.wrap(buf, offset, Car.SCHEMA_VERSION) header.set_block_length(Car.BLOCK_LENGTH) header.set_schema_id(Car.SCHEMA_ID) header.set_template_id(Car.SCHEMA_ID) @@ -93,7 +93,7 @@ def _encode(self, buf: bytes, header: MessageHeader, car: Car): def _decode(self, buf: bytes, header: MessageHeader, car: Car): offset = 0 out = "" - header.wrap(buf, offset) + header.wrap(buf, offset, Car.SCHEMA_VERSION) template_id = header.get_template_id() if template_id != Car.TEMPLATE_ID: raise Exception("Template ID missmatch") diff --git a/python/tests/test_issue435.py b/python/tests/test_issue435.py new file mode 100644 index 0000000000..f33030aed7 --- /dev/null +++ b/python/tests/test_issue435.py @@ -0,0 +1,42 @@ +import unittest + +from tests.gen.issue435 import * + + +class TestIssue435(unittest.TestCase): + + def setUp(self) -> None: + self._buffer = bytearray(4096) + self._messageHeader = MessageHeader() + self._issue435 = Issue435() + self._messageHeader.wrap(self._buffer, 0, Issue435.SCHEMA_VERSION) + self._messageHeader.set_version(Issue435.SCHEMA_VERSION) + + self._messageHeader.set_block_length(Issue435.BLOCK_LENGTH) + self._messageHeader.set_schema_id(Issue435.SCHEMA_ID) + self._messageHeader.set_template_id(Issue435.TEMPLATE_ID) + self._messageHeader.set_version(Issue435.SCHEMA_VERSION) + + #< ref > element in non - standard + set_s = self._messageHeader.set_s() + set_s.set_one(True) + + def test_non_standard_header_size(self): + self.assertEqual(9, self._messageHeader.SIZE) + + def test_issue435_ref_test(self): + self._issue435.wrap_encode(self._buffer, MessageHeader.SIZE) + ex = self._issue435.set_example() + ex.set_e(EnumRef.Two) + self.assertEqual(1, Issue435.BLOCK_LENGTH) + self._messageHeader.wrap(self._buffer, 0, Issue435.SCHEMA_VERSION) + self.assertEqual(Issue435.BLOCK_LENGTH, self._messageHeader.get_block_length(), "Incorrect BlockLength"); + self.assertEqual(Issue435.SCHEMA_ID, self._messageHeader.get_schema_id(), "Incorrect SchemaId"); + self.assertEqual(Issue435.TEMPLATE_ID, self._messageHeader.get_template_id(), "Incorrect TemplateId"); + self.assertEqual(Issue435.SCHEMA_VERSION, self._messageHeader.get_version(), "Incorrect SchemaVersion"); + self.assertTrue(self._messageHeader.get_s().has_one(), "Incorrect SetRef.One"); + + self._issue435.wrap_decode(self._buffer, MessageHeader.SIZE, self._messageHeader.get_block_length(), + self._messageHeader.get_version()) + + self.assertEqual(EnumRef.Two, self._issue435.get_example().get_e(), "Incorrect EnuRef"); diff --git a/python/tests/test_issue483.py b/python/tests/test_issue483.py new file mode 100644 index 0000000000..1e20a57049 --- /dev/null +++ b/python/tests/test_issue483.py @@ -0,0 +1,13 @@ +import unittest + +from tests.gen.issue483 import * + + +class TestIssue483(unittest.TestCase): + + def test_presense(self): + # Check attributes for their presence meta attribute + self.assertEqual(Issue483.unset_meta_attribute(MetaAttribute.Presence), "required") + self.assertEqual(Issue483.required_meta_attribute(MetaAttribute.Presence), "required") + self.assertEqual(Issue483.constant_meta_attribute(MetaAttribute.Presence), "constant") + self.assertEqual(Issue483.optional_meta_attribute(MetaAttribute.Presence), "optional") diff --git a/python/tests/test_issue560.py b/python/tests/test_issue560.py new file mode 100644 index 0000000000..46600f4c61 --- /dev/null +++ b/python/tests/test_issue560.py @@ -0,0 +1,20 @@ +import unittest + +from tests.gen.issue560 import * + + +class TestIssue560(unittest.TestCase): + + def setUp(self) -> None: + self._buffer = bytearray(4096) + self._issue560 = Issue560() + self._header = MessageHeader() + self._header.wrap(self._buffer, 0, Issue560.SCHEMA_VERSION) + self._header.set_block_length(Issue560.BLOCK_LENGTH) + self._header.set_schema_id(Issue560.SCHEMA_ID) + self._header.set_template_id(Issue560.TEMPLATE_ID) + self._header.set_version(Issue560.SCHEMA_VERSION) + + def test_const_enum(self): + self.assertEqual(self._issue560.get_discounted_model(), Model.C, "Incorrect const enum valueref") + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java index e489f22d99..a91a74a250 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java @@ -1,6 +1,5 @@ /* * Copyright 2013-2019 Real Logic Ltd. - * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +21,6 @@ import uk.co.real_logic.sbe.PrimitiveValue; import uk.co.real_logic.sbe.generation.CodeGenerator; import uk.co.real_logic.sbe.generation.Generators; -import uk.co.real_logic.sbe.generation.csharp.CSharpUtil; import uk.co.real_logic.sbe.ir.Encoding; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.ir.Signal; @@ -92,36 +90,48 @@ public void generate() throws IOException final Token msgToken = tokens.get(0); final String className = formatClassName(msgToken.name()); final String pyModuleName = camToSnake(className); - try (Writer out = outputManager.createOutput(pyModuleName)) - { - modules.add(pyModuleName); - final List messageBody = getMessageBody(tokens); - int offset = 0; - final List fields = new ArrayList<>(); - offset = collectFields(messageBody, offset, fields); + modules.add(pyModuleName); + final List messageBody = getMessageBody(tokens); + int offset = 0; - out.append(generateFileHeader(ir.applicableNamespace(), messageBody, true)); - out.append(generateClassDeclaration(className)); - out.append(generateMessageFlyweightCode(className, msgToken, BASE_INDENT, fields)); + final List fields = new ArrayList<>(); + offset = collectFields(messageBody, offset, fields); - out.append(generateFields(fields, BASE_INDENT, className)); + final List groups = new ArrayList<>(); + offset = collectGroups(messageBody, offset, groups); - final StringBuilder sb = new StringBuilder(); - final List groups = new ArrayList<>(); - offset = collectGroups(messageBody, offset, groups); - generateGroups(sb, className, groups, BASE_INDENT); - out.append(sb); + final List varData = new ArrayList<>(); + collectVarData(messageBody, offset, varData); - final List varData = new ArrayList<>(); - collectVarData(messageBody, offset, varData); - out.append(generateVarData(varData, BASE_INDENT, className)); + try (Writer out = outputManager.createOutput(pyModuleName)) + { + generateEncoder(out, className, fields, groups, varData, messageBody, msgToken); } } generateStructParsers(); generatePackageDefinition(modules); } + public void generateEncoder(final Writer out, final String className, + final List fields, final List groups, final List varData, + final List msgBody, final Token msgToken) throws IOException + { + out.append(generateFileHeader(ir.applicableNamespace(), msgBody, true)); + out.append(generateClassDeclaration(className)); + out.append(generateMessageFlyweightCode(className, msgToken, BASE_INDENT, fields)); + + out.append(generateFields(fields, BASE_INDENT, className)); + + final StringBuilder sb = new StringBuilder(); + + generateGroups(sb, className, groups, BASE_INDENT); + out.append(sb); + + out.append(generateVarData(varData, BASE_INDENT, className)); + } + + public void generatePackageDefinition(final List modules) throws IOException { try (Writer out = outputManager.createOutput("__init__")) @@ -216,7 +226,7 @@ private void generateGroupClassHeader( " memoryview" + "], acting_version: int):\n" + indent + " self._parent_message = parent_message\n" + indent + " self._buffer = buffer\n" + - indent + " self._dimensions.wrap(buffer, parent_message.limit)\n" + + indent + " self._dimensions.wrap(buffer, parent_message.limit, parent_message._acting_version)\n" + indent + " self._block_length = self._dimensions.get_block_length()\n" + indent + " self._count = self._dimensions.get_num_in_group()\n" + indent + " self._acting_version = acting_version\n" + @@ -237,7 +247,7 @@ private void generateGroupClassHeader( "max=%3$d')\n" + indent + " self._parent_message = parent_message\n" + indent + " self._buffer = buffer\n" + - indent + " self._dimensions.wrap(buffer, parent_message.limit)\n" + + indent + " self._dimensions.wrap(buffer, parent_message.limit, parent_message._acting_version)\n" + indent + " self._dimensions.set_block_length(%4$s(%5$d))\n" + indent + " self._dimensions.set_num_in_group(%6$s(count))\n" + indent + " self._index = -1\n" + @@ -294,7 +304,7 @@ private CharSequence generateGroupProperty(final String groupName, final Token t { final StringBuilder sb = new StringBuilder(); - final String className = CSharpUtil.formatClassName(groupName); + final String className = PyUtil.formatClassName(groupName); sb.append(String.format("\n" + indent + "%S_ID: int = %d\n", @@ -459,7 +469,6 @@ private CharSequence generateCompositePropertyElements(final List tokens, final Token token = tokens.get(i); final String propertyName = formatPropertyName(token.name()); - // FIXME: do I need to pass classname down here for disambiguation switch (token.signal()) { case ENCODING: @@ -576,14 +585,8 @@ private String generateChoiceIsEmpty(final PrimitiveType type, final ByteOrder b private String generateChoiceIsEmptyInner(final PrimitiveType type, final ByteOrder byteOrder) { - switch (type) - { - case UINT8: - return "0 == " + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + - ".unpack_from(self._buffer, self._offset)[0]"; - } - - throw new IllegalArgumentException("primitive type not supported: " + type); + return "0 == " + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + + ".unpack_from(self._buffer, self._offset)[0]"; } private String generateChoicePut(final PrimitiveType type, final String bitIdx, final ByteOrder byteOrder) @@ -1113,11 +1116,12 @@ private CharSequence generateFixedFlyweightCode(final int size, final List fields = new ArrayList<>(fieldTypes.keySet()); - builder.append(INDENT + "__slots__ = '_offset', '_buffer'"); + builder.append(INDENT + "__slots__ = '_offset', '_buffer', '_acting_version'"); if (fields.size() > 0) { builder.append(", '" + String.join("', '", fields) + "'"); @@ -1127,6 +1131,7 @@ private CharSequence generateFixedFlyweightCode(final int size, final List field : fieldTypes.entrySet()) { @@ -1135,16 +1140,18 @@ private CharSequence generateFixedFlyweightCode(final int size, final List fields) + private CharSequence generateMessageFlyweightCode(final String className, final Token token, + final String indent, final List fields) { final String blockLengthType = pythonTypeName(ir.headerStructure().blockLengthType()); final String templateIdType = pythonTypeName(ir.headerStructure().templateIdType()); @@ -1153,11 +1160,17 @@ private CharSequence generateMessageFlyweightCode(final String className, final final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); final StringBuilder builder = new StringBuilder(); final Map fieldTypes = new LinkedHashMap<>(); - for (final Token t : fields) + for (int i = 0, size = fields.size(); i < size; i++) { - if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET) + final Token signalToken = fields.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) { - fieldTypes.put("_" + camToSnake(t.name()), t.referencedName() != null ? t.referencedName() : t.name()); + final Token encodingToken = fields.get(i + 1); + final String propertyName = signalToken.name(); + if (encodingToken.signal() == Signal.BEGIN_SET || encodingToken.signal() == Signal.BEGIN_COMPOSITE) + { + fieldTypes.put("_" + camToSnake(propertyName), toUpperFirstChar(encodingToken.name())); + } } } builder.append(String.format( @@ -1231,14 +1244,12 @@ private CharSequence generateMessageFlyweightCode(final String className, final indent + "def limit(self) -> int:\n" + indent + " return self._limit\n"); builder.append("\n"); - builder.append( indent + "def set_limit(self, value):\n" + //TODO: make sure the capacity is checked either wrap in bytearray indent + " #self._buffer.CheckLimit(value);\n" + indent + " self._limit = value\n" + indent + " return self\n"); - return builder.toString(); } @@ -1414,8 +1425,8 @@ private String generateBitSetProperty(final String propertyName, final Token tok final String getter = String.format("\n" + indent + "def get_%2$s(self) -> '%1$s':\n" + "%3$s" + - indent + " return self._%5$s.wrap_decode(self._buffer, self._offset + %4$d, " + - "self._acting_block_length, self._acting_version)\n", + indent + " return self._%2$s.wrap_decode(self._buffer, self._offset + %4$d, %1$s.BLOCK_LENGTH, " + + "self._acting_version)\n", bitSetName, camToSnake(propertyName), generateTypeFieldNotPresentCondition(token.version(), indent), @@ -1424,7 +1435,7 @@ private String generateBitSetProperty(final String propertyName, final Token tok final String setter = String.format("\n" + indent + "def set_%3$s(self) -> '%1$s':\n" + - indent + " return self._%2$s.wrap_encode(self._buffer, self._offset + %4$d)\n", + indent + " return self._%3$s.wrap_encode(self._buffer, self._offset + %4$d)\n", bitSetName, camToSnake(bitSetName), camToSnake(propertyName), @@ -1441,7 +1452,7 @@ private Object generateCompositeProperty(final String propertyName, final Token sb.append(String.format("\n" + indent + "def set_%2$s(self) -> '%1$s':\n" + "%3$s" + - indent + " self._%4$s.wrap(self._buffer, self._offset + %5$d)\n" + + indent + " self._%4$s.wrap(self._buffer, self._offset + %5$d, self._acting_version)\n" + indent + " return self._%4$s\n", compositeName, camToSnake(propertyName), @@ -1452,7 +1463,7 @@ private Object generateCompositeProperty(final String propertyName, final Token sb.append(String.format("\n" + indent + "def get_%2$s(self) -> '%1$s':\n" + "%3$s" + - indent + " self._%4$s.wrap(self._buffer, self._offset + %5$d)\n" + + indent + " self._%4$s.wrap(self._buffer, self._offset + %5$d, self._acting_version)\n" + indent + " return self._%4$s\n", compositeName, camToSnake(propertyName), diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java index f2c304e69f..b8bd94e352 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java @@ -17,7 +17,6 @@ package uk.co.real_logic.sbe.generation.python; import uk.co.real_logic.sbe.PrimitiveType; -import uk.co.real_logic.sbe.ir.Token; import java.nio.ByteOrder; import java.util.EnumMap; @@ -177,75 +176,4 @@ public static String camToSnake(final String str) { return camToSnake(str, true); } - - /** - * Generate the Pydoc comment header for a type. - * - * @param indent level for the comment. - * @param typeToken for the type. - * @return a string representation of the Javadoc comment. - */ - public static String generateTypePydoc(final String indent, final Token typeToken) - { - final String description = typeToken.description(); - if (null == description || description.isEmpty()) - { - return ""; - } - - return - indent + "\"\"\"\n" + - indent + " " + description + '\n' + - indent + "\"\"\"\n"; - } - - /** - * Generate the Pydoc comment header for flyweight property. - * - * @param indent level for the comment. - * @param propertyToken for the property name. - * @param typeName for the property type. - * @return a string representation of the Javadoc comment. - */ - public static String generateFlyweightPropertyPydoc( - final String indent, final Token propertyToken, final String typeName) - { - final String description = propertyToken.description(); - if (null == description || description.isEmpty()) - { - return ""; - } - - return - indent + "\"\"\"\n" + - indent + description + '\n' + - indent + "@return " + typeName + " : " + description + "\n" + - indent + " \"\"\"\n"; - } - - /** - * Generate the Javadoc comment header for group encode property. - * - * @param indent level for the comment. - * @param propertyToken for the property name. - * @param typeName for the property type. - * @return a string representation of the Javadoc comment. - */ - public static String generateGroupEncodePropertyPydoc( - final String indent, final Token propertyToken, final String typeName) - { - final String description = propertyToken.description(); - if (null == description || description.isEmpty()) - { - return ""; - } - - return - indent + "/**\n" + - indent + " * " + description + "\n" + - indent + " *\n" + - indent + " * @param count of times the group will be encoded\n" + - indent + " * @return " + typeName + " : encoder for the group\n" + - indent + " */\n"; - } } From 92e93af7e1517f9dc7c5798ef7c82bb2abf091c2 Mon Sep 17 00:00:00 2001 From: Feras Date: Sun, 28 Apr 2019 23:31:40 -0400 Subject: [PATCH 0152/1594] [Java] Python fix tests after rebase --- build.gradle | 3 ++- python/tests/test_car_example.py | 23 ++++++++++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index dfcdc6699c..c6e5f85ab5 100644 --- a/build.gradle +++ b/build.gradle @@ -779,8 +779,9 @@ task generatePythonCarExample(type: JavaExec) { systemProperties( 'sbe.output.dir': 'python/tests', 'sbe.target.language': 'uk.co.real_logic.sbe.generation.python.Python', + 'sbe.xinclude.aware': 'true', 'sbe.target.namespace': 'gen.car_example') - args = ['sbe-tool/src/test/resources/example-schema.xml'] + args = ['sbe-samples/src/main/resources/example-schema.xml'] } task generatePythonIssue435Codecs(type: JavaExec) { diff --git a/python/tests/test_car_example.py b/python/tests/test_car_example.py index aac8aa2f33..046b1c44e4 100644 --- a/python/tests/test_car_example.py +++ b/python/tests/test_car_example.py @@ -22,10 +22,10 @@ def test_encoding(self): py_buf = bytearray(4096) self._encode(py_buf, self.MESSAGE_HEADER, self.CAR) # Encoded message should match - self.assertEqual(buffer, py_buf[:211]) + self.assertEqual(buffer, py_buf[:207]) # The empty part of the buffer should be all 0's self.assertEqual(bytes(len(py_buf) - len(buffer)), py_buf[len(buffer):]) - self.assertEqual(211, len(buffer)) + self.assertEqual(207, len(buffer)) def test_decoding(self): self.maxDiff = None @@ -51,8 +51,10 @@ def _encode(self, buf: bytes, header: MessageHeader, car: Car): car.set_code(Model.A) car.set_vehicle_code(self.VEHICLE_CODE) - for i in range(Car.SOME_NUMBERS_LENGTH): - car.put_some_numbers(i, i) + car.put_some_numbers(0,1) + car.put_some_numbers(1,2) + car.put_some_numbers(2,3) + car.put_some_numbers(3,4) car.set_extras() \ .clear() \ @@ -106,12 +108,11 @@ def _decode(self, buf: bytes, header: MessageHeader, car: Car): self.assertEqual(2013, car.get_model_year()) self.assertEqual(BooleanType.T, car.get_available()) self.assertEqual(Model.A, car.get_code()) - self.assertEqual((0, 1, 2, 3, 4), car.get_multi_some_numbers()) - self.assertEqual(0, car.get_some_numbers(0)) - self.assertEqual(1, car.get_some_numbers(1)) - self.assertEqual(2, car.get_some_numbers(2)) - self.assertEqual(3, car.get_some_numbers(3)) - self.assertEqual(4, car.get_some_numbers(4)) + self.assertEqual((1, 2, 3, 4), car.get_multi_some_numbers()) + self.assertEqual(1, car.get_some_numbers(0)) + self.assertEqual(2, car.get_some_numbers(1)) + self.assertEqual(3, car.get_some_numbers(2)) + self.assertEqual(4, car.get_some_numbers(3)) index_oob = False try: car.get_some_numbers(55) @@ -185,5 +186,5 @@ def _decode(self, buf: bytes, header: MessageHeader, car: Car): self.assertEqual("Honda", car.get_manufacturer().tobytes().decode(Car.MANUFACTURER_CHAR_ENCODING)) self.assertEqual("Civic VTi", car.get_model().tobytes().decode(Car.MODEL_CHAR_ENCODING)) self.assertEqual("abcdef", car.get_activation_code().tobytes().decode(Car.ACTIVATION_CODE_CHAR_ENCODING)) - self.assertEqual(203, car.size()) + self.assertEqual(199, car.size()) return out From 50243da816682172f1504c5d81222625b5302d20 Mon Sep 17 00:00:00 2001 From: Feras Date: Thu, 8 Aug 2019 16:44:34 -0400 Subject: [PATCH 0153/1594] [Java] Update python generator to split encoder and decoder --- python/tests/test_car_example.py | 266 +- python/tests/test_issue435.py | 60 +- python/tests/test_issue483.py | 11 +- python/tests/test_issue560.py | 23 +- .../sbe/generation/python/PyUtil.java | 109 +- .../sbe/generation/python/Python.java | 3 +- .../generation/python/PythonGenerator.java | 3028 +++++++++++++++++ .../generation/python/PyGeneratorTest.java | 25 +- 8 files changed, 3339 insertions(+), 186 deletions(-) create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PythonGenerator.java diff --git a/python/tests/test_car_example.py b/python/tests/test_car_example.py index 046b1c44e4..b900e3185c 100644 --- a/python/tests/test_car_example.py +++ b/python/tests/test_car_example.py @@ -1,26 +1,30 @@ import unittest from pathlib import Path -from tests.gen.car_example import MessageHeader, Car, BooleanType, Model, Engine, BoostType +from tests.gen.car_example import MessageHeaderEncoder, CarEncoder, BooleanType, Model, EngineEncoder, BoostType +from tests.gen.car_example import MessageHeaderDecoder, CarDecoder, EngineDecoder class TestCarExample(unittest.TestCase): REFERENCE_FILE_ENCODE = Path(__file__).resolve().parent / Path('gen') / 'car_example' / 'car_example_data.sbe' - VEHICLE_CODE = "abcdef".encode(Car.VEHICLE_CODE_CHAR_ENCODING) - MANUFACTURER_CODE = "123".encode(Engine.MANUFACTURER_CODE_CHAR_ENCODING) - MANUFACTURER = "Honda".encode(Car.MANUFACTURER_CHAR_ENCODING) - MODEL = "Civic VTi".encode(Car.MODEL_CHAR_ENCODING) - ACTIVATION_CODE = "abcdef".encode(Car.ACTIVATION_CODE_CHAR_ENCODING) + VEHICLE_CODE = "abcdef".encode(CarDecoder.vehicleCodeCharacterEncoding()) + MANUFACTURER_CODE = "123".encode(EngineDecoder.manufacturerCodeCharacterEncoding()) + MANUFACTURER = "Honda".encode(CarDecoder.manufacturerCharacterEncoding()) + MODEL = "Civic VTi".encode(CarDecoder.modelCharacterEncoding()) + ACTIVATION_CODE = "abcdef".encode(CarDecoder.activationCodeCharacterEncoding()) - CAR = Car() - MESSAGE_HEADER = MessageHeader() + CAR_ENCODER = CarEncoder() + MESSAGE_HEADER_ENCODER = MessageHeaderEncoder() + + CAR_DECODER = CarDecoder() + MESSAGE_HEADER_DECODER = MessageHeaderDecoder() def test_encoding(self): with open(self.REFERENCE_FILE_ENCODE, 'rb') as f: buffer = f.read() py_buf = bytearray(4096) - self._encode(py_buf, self.MESSAGE_HEADER, self.CAR) + self._encode(py_buf, self.MESSAGE_HEADER_ENCODER, self.CAR_ENCODER) # Encoded message should match self.assertEqual(buffer, py_buf[:207]) # The empty part of the buffer should be all 0's @@ -32,159 +36,157 @@ def test_decoding(self): with open(self.REFERENCE_FILE_ENCODE, 'rb') as f: buffer = f.read() py_buf = bytearray(4096) - self._encode(py_buf, self.MESSAGE_HEADER, self.CAR) - self._decode(py_buf, self.MESSAGE_HEADER, self.CAR) - self._decode(buffer, self.MESSAGE_HEADER, self.CAR) + self._encode(py_buf, self.MESSAGE_HEADER_ENCODER, self.CAR_ENCODER) + self._decode(py_buf, self.MESSAGE_HEADER_DECODER, self.CAR_DECODER) + self._decode(buffer, self.MESSAGE_HEADER_DECODER, self.CAR_DECODER) - def _encode(self, buf: bytes, header: MessageHeader, car: Car): + def _encode(self, buf: bytearray, header: MessageHeaderEncoder, car: CarEncoder): offset = 0 - header.wrap(buf, offset, Car.SCHEMA_VERSION) - header.set_block_length(Car.BLOCK_LENGTH) - header.set_schema_id(Car.SCHEMA_ID) - header.set_template_id(Car.SCHEMA_ID) - header.set_version(Car.SCHEMA_VERSION) - - car.wrap_encode(buf, offset + MessageHeader.SIZE) - car.set_serial_number(1234) - car.set_model_year(2013) - car.set_available(BooleanType.T) - car.set_code(Model.A) - car.set_vehicle_code(self.VEHICLE_CODE) - - car.put_some_numbers(0,1) - car.put_some_numbers(1,2) - car.put_some_numbers(2,3) - car.put_some_numbers(3,4) - - car.set_extras() \ + + car.wrapAndApplyHeader(buf, offset, header) + car.serialNumber(1234) + car.modelYear(2013) + car.available(BooleanType.T) + car.code(Model.A) + car.set_vehicleCode(self.VEHICLE_CODE) + + car.someNumbers(0,1) + car.someNumbers(1,2) + car.someNumbers(2,3) + car.someNumbers(3,4) + + car.extras() \ .clear() \ - .set_cruise_control(True) \ - .set_sports_pack(True) \ - .set_sun_roof(False) - - car.set_engine() \ - .set_capacity(2000) \ - .set_num_cylinders(4) \ - .set_manufacturer_code(self.MANUFACTURER_CODE) \ - .set_efficiency(35) \ - .set_booster_enabled(BooleanType.T) \ - .set_booster() \ - .set_boost_type(BoostType.NITROUS) \ - .set_horse_power(200) - - ff = car.set_fuel_figures_count(3) - ff.next().set_speed(30).set_mpg(35.9).set_usage_description("Urban Cycle".encode(Car.FuelFiguresGroup.USAGE_DESCRIPTION_CHAR_ENCODING)) - ff.next().set_speed(55).set_mpg(49.0).set_usage_description("Combined Cycle".encode(Car.FuelFiguresGroup.USAGE_DESCRIPTION_CHAR_ENCODING)) - ff.next().set_speed(75).set_mpg(40.0).set_usage_description("Highway Cycle".encode(Car.FuelFiguresGroup.USAGE_DESCRIPTION_CHAR_ENCODING)) - - figures = car.set_performance_figures_count(2) - figures.next().set_octane_rating(95).set_acceleration_count(3) \ - .next().set_mph(30).set_seconds(4.0) \ - .next().set_mph(60).set_seconds(7.5) \ - .next().set_mph(100).set_seconds(12.2) - - figures.next().set_octane_rating(99).set_acceleration_count(3) \ - .next().set_mph(30).set_seconds(3.8) \ - .next().set_mph(60).set_seconds(7.1) \ - .next().set_mph(100).set_seconds(11.8) - - car.set_manufacturer(self.MANUFACTURER).set_model(self.MODEL).set_activation_code(self.ACTIVATION_CODE) - - return MessageHeader.SIZE + car.size() - - def _decode(self, buf: bytes, header: MessageHeader, car: Car): + .cruiseControl(True) \ + .sportsPack(True) \ + .sunRoof(False) + + car.engine() \ + .capacity(2000) \ + .numCylinders(4) \ + .set_manufacturerCode(self.MANUFACTURER_CODE) \ + .efficiency(35) \ + .boosterEnabled(BooleanType.T) \ + .booster() \ + .boostType(BoostType.NITROUS) \ + .horsePower(200) + + ff = car.fuelFiguresCount(3) + ff.next().speed(30).mpg(35.9).usageDescription("Urban Cycle".encode(CarEncoder.FuelFiguresEncoder + .usageDescriptionCharacterEncoding())) + ff.next().speed(55).mpg(49.0).usageDescription("Combined Cycle".encode(CarEncoder.FuelFiguresEncoder + .usageDescriptionCharacterEncoding())) + ff.next().speed(75).mpg(40.0).usageDescription("Highway Cycle".encode(CarEncoder.FuelFiguresEncoder + .usageDescriptionCharacterEncoding())) + + figures = car.performanceFiguresCount(2) + figures.next().octaneRating(95).accelerationCount(3) \ + .next().mph(30).seconds(4.0) \ + .next().mph(60).seconds(7.5) \ + .next().mph(100).seconds(12.2) + + figures.next().octaneRating(99).accelerationCount(3) \ + .next().mph(30).seconds(3.8) \ + .next().mph(60).seconds(7.1) \ + .next().mph(100).seconds(11.8) + + car.manufacturer(self.MANUFACTURER).model(self.MODEL).activationCode(self.ACTIVATION_CODE) + + return header.encodedLength + car.encodedLength + + def _decode(self, buf: bytes, header: MessageHeaderDecoder, car: CarDecoder): offset = 0 out = "" - header.wrap(buf, offset, Car.SCHEMA_VERSION) - template_id = header.get_template_id() - if template_id != Car.TEMPLATE_ID: + header.wrap(buf, offset) + template_id = header.templateId() + if template_id != car.sbeTemplateId: raise Exception("Template ID missmatch") - acting_block_length = header.get_block_length() - acting_block_version = header.get_version() - offset += header.SIZE - - car.wrap_decode(buf, offset, acting_block_length, acting_block_version) - self.assertEqual(1234, car.get_serial_number()) - self.assertEqual(2013, car.get_model_year()) - self.assertEqual(BooleanType.T, car.get_available()) - self.assertEqual(Model.A, car.get_code()) - self.assertEqual((1, 2, 3, 4), car.get_multi_some_numbers()) - self.assertEqual(1, car.get_some_numbers(0)) - self.assertEqual(2, car.get_some_numbers(1)) - self.assertEqual(3, car.get_some_numbers(2)) - self.assertEqual(4, car.get_some_numbers(3)) + acting_block_length = header.blockLength() + acting_block_version = header.version() + offset += header.encodedLength + + car.wrap(buf, offset, acting_block_length, acting_block_version) + self.assertEqual(1234, car.serialNumber()) + self.assertEqual(2013, car.modelYear()) + self.assertEqual(BooleanType.T, car.available()) + self.assertEqual(Model.A, car.code()) + self.assertEqual((1, 2, 3, 4), car.getMultiSomeNumbers()) + self.assertEqual(1, car.someNumbers(0)) + self.assertEqual(2, car.someNumbers(1)) + self.assertEqual(3, car.someNumbers(2)) + self.assertEqual(4, car.someNumbers(3)) index_oob = False try: - car.get_some_numbers(55) + car.someNumbers(55) except IndexError as e: index_oob = True self.assertEqual(IndexError, type(e)) self.assertTrue(index_oob) - self.assertEqual("abcdef", str(car.get_multi_vehicle_code(), car.VEHICLE_CODE_CHAR_ENCODING)) + self.assertEqual("abcdef", str(car.getMultiVehicleCode(), car.vehicleCodeCharacterEncoding())) - extras = car.get_extras() - self.assertTrue(extras.has_cruise_control()) - self.assertTrue(extras.has_sports_pack()) - self.assertFalse(extras.has_sun_roof()) + extras = car.extras() + self.assertTrue(extras.cruiseControl()) + self.assertTrue(extras.sportsPack()) + self.assertFalse(extras.sunRoof()) - self.assertEqual("C", car.get_discounted_model().name) + self.assertEqual("C", car.discountedModel().name) - engine = car.get_engine() - self.assertEqual(2000, engine.get_capacity()) - self.assertEqual(4, engine.get_num_cylinders()) - self.assertEqual(9000, engine.get_max_rpm) - self.assertEqual("123", str(engine.get_multi_manufacturer_code(), Engine.MANUFACTURER_CODE_CHAR_ENCODING)) - self.assertEqual(35, engine.get_efficiency()) - self.assertEqual(BooleanType.T, engine.get_booster_enabled()) - self.assertEqual(BoostType.NITROUS, engine.get_booster().get_boost_type()) - self.assertEqual(200, engine.get_booster().get_horse_power()) + engine = car.engine() + self.assertEqual(2000, engine.capacity()) + self.assertEqual(4, engine.numCylinders()) + self.assertEqual(9000, engine.maxRpm) + self.assertEqual("123", str(engine.getMultiManufacturerCode(), EngineDecoder.manufacturerCodeCharacterEncoding())) + self.assertEqual(35, engine.efficiency()) + self.assertEqual(BooleanType.T, engine.boosterEnabled()) + self.assertEqual(BoostType.NITROUS, engine.booster().boostType()) + self.assertEqual(200, engine.booster().horsePower()) - self.assertEqual("Petrol", str(engine.get_fuel(0, len(buf)).tobytes().decode())) + self.assertEqual("Petrol", str(engine.getFuel(0, len(buf)).tobytes().decode())) - ff = car.get_fuel_figures() + ff = car.fuelFigures() ff.next() - self.assertEqual(30, ff.get_speed()) - self.assertAlmostEqual(35.9, ff.get_mpg(), places=5) - self.assertEqual("Urban Cycle", ff.get_usage_description().tobytes().decode(Car.FuelFiguresGroup.USAGE_DESCRIPTION_CHAR_ENCODING)) + self.assertEqual(30, ff.speed()) + self.assertAlmostEqual(35.9, ff.mpg(), places=5) + self.assertEqual("Urban Cycle", ff.usageDescription()) ff.next() - self.assertEqual(55, ff.get_speed()) - self.assertAlmostEqual(49.0, ff.get_mpg(), places=5) - self.assertEqual("Combined Cycle", ff.get_usage_description().tobytes().decode(Car.FuelFiguresGroup.USAGE_DESCRIPTION_CHAR_ENCODING)) + self.assertEqual(55, ff.speed()) + self.assertAlmostEqual(49.0, ff.mpg(), places=5) + self.assertEqual("Combined Cycle", ff.usageDescription()) ff.next() - self.assertEqual(75, ff.get_speed()) - self.assertAlmostEqual(40.0, ff.get_mpg(), places=5) - self.assertEqual("Highway Cycle", ff.get_usage_description().tobytes().decode(Car.FuelFiguresGroup.USAGE_DESCRIPTION_CHAR_ENCODING)) + self.assertEqual(75, ff.speed()) + self.assertAlmostEqual(40.0, ff.mpg(), places=5) + self.assertEqual("Highway Cycle", ff.usageDescription()) - pf = car.get_performance_figures() + pf = car.performanceFigures() pf.next() - self.assertEqual(95, pf.get_octane_rating()) - pfa = pf.get_acceleration() + self.assertEqual(95, pf.octaneRating()) + pfa = pf.acceleration() pfa.next() - self.assertEqual(30, pfa.get_mph()) - self.assertAlmostEqual(4.0, pfa.get_seconds(), places=5) + self.assertEqual(30, pfa.mph()) + self.assertAlmostEqual(4.0, pfa.seconds(), places=5) pfa.next() - self.assertEqual(60, pfa.get_mph()) - self.assertAlmostEqual(7.5, pfa.get_seconds(), places=5) + self.assertEqual(60, pfa.mph()) + self.assertAlmostEqual(7.5, pfa.seconds(), places=5) pfa.next() - self.assertEqual(100, pfa.get_mph()) - self.assertAlmostEqual(12.2, pfa.get_seconds(), places=5) + self.assertEqual(100, pfa.mph()) + self.assertAlmostEqual(12.2, pfa.seconds(), places=5) pf.next() - self.assertEqual(99, pf.get_octane_rating()) - pfa = pf.get_acceleration() + self.assertEqual(99, pf.octaneRating()) + pfa = pf.acceleration() pfa.next() - self.assertEqual(30, pfa.get_mph()) - self.assertAlmostEqual(3.8, pfa.get_seconds(), places=5) + self.assertEqual(30, pfa.mph()) + self.assertAlmostEqual(3.8, pfa.seconds(), places=5) pfa.next() - self.assertEqual(60, pfa.get_mph()) - self.assertAlmostEqual(7.1, pfa.get_seconds(), places=5) + self.assertEqual(60, pfa.mph()) + self.assertAlmostEqual(7.1, pfa.seconds(), places=5) pfa.next() - self.assertEqual(100, pfa.get_mph()) - self.assertAlmostEqual(11.8, pfa.get_seconds(), places=5) + self.assertEqual(100, pfa.mph()) + self.assertAlmostEqual(11.8, pfa.seconds(), places=5) - self.assertEqual("Honda", car.get_manufacturer().tobytes().decode(Car.MANUFACTURER_CHAR_ENCODING)) - self.assertEqual("Civic VTi", car.get_model().tobytes().decode(Car.MODEL_CHAR_ENCODING)) - self.assertEqual("abcdef", car.get_activation_code().tobytes().decode(Car.ACTIVATION_CODE_CHAR_ENCODING)) - self.assertEqual(199, car.size()) + self.assertEqual("Honda", car.manufacturer()) + self.assertEqual("Civic VTi", car.model()) + self.assertEqual("abcdef", car.activationCode()) + self.assertEqual(199, car.encodedLength) return out diff --git a/python/tests/test_issue435.py b/python/tests/test_issue435.py index f33030aed7..40a0237a12 100644 --- a/python/tests/test_issue435.py +++ b/python/tests/test_issue435.py @@ -1,42 +1,46 @@ import unittest -from tests.gen.issue435 import * +from tests.gen.issue435.message_header_encoder import * +from tests.gen.issue435.message_header_decoder import * +from tests.gen.issue435.issue435_encoder import * +from tests.gen.issue435.issue435_decoder import * class TestIssue435(unittest.TestCase): def setUp(self) -> None: self._buffer = bytearray(4096) - self._messageHeader = MessageHeader() - self._issue435 = Issue435() - self._messageHeader.wrap(self._buffer, 0, Issue435.SCHEMA_VERSION) - self._messageHeader.set_version(Issue435.SCHEMA_VERSION) - - self._messageHeader.set_block_length(Issue435.BLOCK_LENGTH) - self._messageHeader.set_schema_id(Issue435.SCHEMA_ID) - self._messageHeader.set_template_id(Issue435.TEMPLATE_ID) - self._messageHeader.set_version(Issue435.SCHEMA_VERSION) + self._messageHeader = MessageHeaderEncoder() + self._messageHeaderDecoder = MessageHeaderDecoder() + self._issue435 = Issue435Encoder() + self._issue435_decoder = Issue435Decoder() + self._messageHeader.wrap(self._buffer, 0) + self._messageHeader.version(self._issue435.sbeSchemaVersion) + self._messageHeader.blockLength(self._issue435.sbeBlockLength) + self._messageHeader.schemaId(self._issue435.sbeSchemaId) + self._messageHeader.templateId(self._issue435.sbeTemplateId) #< ref > element in non - standard - set_s = self._messageHeader.set_s() - set_s.set_one(True) + set_s = self._messageHeader.s() + set_s.one(True) def test_non_standard_header_size(self): - self.assertEqual(9, self._messageHeader.SIZE) + self.assertEqual(9, self._messageHeader.encodedLength) def test_issue435_ref_test(self): - self._issue435.wrap_encode(self._buffer, MessageHeader.SIZE) - ex = self._issue435.set_example() - ex.set_e(EnumRef.Two) - self.assertEqual(1, Issue435.BLOCK_LENGTH) - self._messageHeader.wrap(self._buffer, 0, Issue435.SCHEMA_VERSION) - self.assertEqual(Issue435.BLOCK_LENGTH, self._messageHeader.get_block_length(), "Incorrect BlockLength"); - self.assertEqual(Issue435.SCHEMA_ID, self._messageHeader.get_schema_id(), "Incorrect SchemaId"); - self.assertEqual(Issue435.TEMPLATE_ID, self._messageHeader.get_template_id(), "Incorrect TemplateId"); - self.assertEqual(Issue435.SCHEMA_VERSION, self._messageHeader.get_version(), "Incorrect SchemaVersion"); - self.assertTrue(self._messageHeader.get_s().has_one(), "Incorrect SetRef.One"); - - self._issue435.wrap_decode(self._buffer, MessageHeader.SIZE, self._messageHeader.get_block_length(), - self._messageHeader.get_version()) - - self.assertEqual(EnumRef.Two, self._issue435.get_example().get_e(), "Incorrect EnuRef"); + self._issue435.wrap(self._buffer, self._messageHeader.encodedLength) + ex = self._issue435.example() + ex.e(EnumRef.Two) + self.assertEqual(1, self._issue435.sbeBlockLength) + self._messageHeaderDecoder.wrap(self._buffer, 0) + self._messageHeader.wrap(self._buffer, 0) + self.assertEqual(self._issue435.sbeBlockLength, self._messageHeaderDecoder.blockLength(), "Incorrect BlockLength") + self.assertEqual(self._issue435.sbeSchemaId, self._messageHeaderDecoder.schemaId(), "Incorrect SchemaId") + self.assertEqual(self._issue435.sbeTemplateId, self._messageHeaderDecoder.templateId(), "Incorrect TemplateId") + self.assertEqual(self._issue435.sbeSchemaVersion, self._messageHeaderDecoder.version(), "Incorrect SchemaVersion") + self.assertTrue(self._messageHeaderDecoder.s().one(), "Incorrect SetRef.One") + + self._issue435_decoder.wrap(self._buffer, self._messageHeader.encodedLength, self._messageHeaderDecoder.blockLength(), + self._messageHeaderDecoder.version()) + + self.assertEqual(EnumRef.Two, self._issue435_decoder.example().e(), "Incorrect EnuRef"); diff --git a/python/tests/test_issue483.py b/python/tests/test_issue483.py index 1e20a57049..d18184784d 100644 --- a/python/tests/test_issue483.py +++ b/python/tests/test_issue483.py @@ -1,13 +1,14 @@ import unittest -from tests.gen.issue483 import * +from tests.gen.issue483.issue483_encoder import * +from tests.gen.issue483.issue483_decoder import * class TestIssue483(unittest.TestCase): def test_presense(self): # Check attributes for their presence meta attribute - self.assertEqual(Issue483.unset_meta_attribute(MetaAttribute.Presence), "required") - self.assertEqual(Issue483.required_meta_attribute(MetaAttribute.Presence), "required") - self.assertEqual(Issue483.constant_meta_attribute(MetaAttribute.Presence), "constant") - self.assertEqual(Issue483.optional_meta_attribute(MetaAttribute.Presence), "optional") + self.assertEqual(Issue483Encoder.unsetMetaAttribute(MetaAttribute.Presence), "required") + self.assertEqual(Issue483Encoder.requiredMetaAttribute(MetaAttribute.Presence), "required") + self.assertEqual(Issue483Encoder.constantMetaAttribute(MetaAttribute.Presence), "constant") + self.assertEqual(Issue483Encoder.optionalMetaAttribute(MetaAttribute.Presence), "optional") diff --git a/python/tests/test_issue560.py b/python/tests/test_issue560.py index 46600f4c61..5e0de72a26 100644 --- a/python/tests/test_issue560.py +++ b/python/tests/test_issue560.py @@ -1,20 +1,23 @@ import unittest -from tests.gen.issue560 import * +from tests.gen.issue560 import Model +from tests.gen.issue560.issue560_encoder import Issue560Encoder +from tests.gen.issue560.issue560_decoder import Issue560Decoder +from tests.gen.issue560.message_header_encoder import MessageHeaderEncoder class TestIssue560(unittest.TestCase): def setUp(self) -> None: self._buffer = bytearray(4096) - self._issue560 = Issue560() - self._header = MessageHeader() - self._header.wrap(self._buffer, 0, Issue560.SCHEMA_VERSION) - self._header.set_block_length(Issue560.BLOCK_LENGTH) - self._header.set_schema_id(Issue560.SCHEMA_ID) - self._header.set_template_id(Issue560.TEMPLATE_ID) - self._header.set_version(Issue560.SCHEMA_VERSION) + self._issue560 = Issue560Encoder() + self._issue560_decoder = Issue560Decoder() + self._header = MessageHeaderEncoder() + self._header.wrap(self._buffer, 0) + self._header.blockLength(self._issue560.BLOCK_LENGTH) + self._header.schemaId(self._issue560.SCHEMA_ID) + self._header.templateId(self._issue560.TEMPLATE_ID) + self._header.version(self._issue560.SCHEMA_VERSION) def test_const_enum(self): - self.assertEqual(self._issue560.get_discounted_model(), Model.C, "Incorrect const enum valueref") - + self.assertEqual(self._issue560_decoder.discountedModel(), Model.C, "Incorrect const enum valueref") \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java index b8bd94e352..64ce612830 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java @@ -17,6 +17,7 @@ package uk.co.real_logic.sbe.generation.python; import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.ir.Token; import java.nio.ByteOrder; import java.util.EnumMap; @@ -33,7 +34,7 @@ public class PyUtil public static final Map PRIMITIVE_TYPE_STRUCT_ENUM_MAP = new EnumMap<>(PrimitiveType.class); public static final Map PRIMITIVE_TYPE_SIZE_ENUM_MAP = new EnumMap<>(PrimitiveType.class); public static final Map BYTE_ORDER_STRING_MAP = new HashMap<>(); - public static final Pattern CAM_SNAKE_PATTERN = Pattern.compile("([a-z])([A-Z]+)"); + public static final Pattern CAM_SNAKE_PATTERN = Pattern.compile("([^_A-Z])([A-Z])"); // Ref: https://docs.python.org/3.7/library/struct.html#format-characters static @@ -75,6 +76,45 @@ public class PyUtil BYTE_ORDER_STRING_MAP.put(ByteOrder.BIG_ENDIAN, ">"); } + public enum Separators + { + BEGIN_GROUP('['), + END_GROUP(']'), + BEGIN_COMPOSITE('('), + END_COMPOSITE(')'), + BEGIN_SET('{'), + END_SET('}'), + BEGIN_ARRAY('['), + END_ARRAY(']'), + FIELD('|'), + KEY_VALUE('='), + ENTRY(','); + + public final char symbol; + + Separators(final char symbol) + { + this.symbol = symbol; + } + + /** + * Add separator to a generated StringBuilder + * + * @param builder the code generation builder to which information should be added + * @param indent the current generated code indentation + * @param builderName of the generated StringBuilder to which separator should be added + */ + public void appendToGeneratedBuilder(final StringBuilder builder, final String indent, final String builderName) + { + append(builder, indent, builderName + " += str('" + symbol + "')"); + } + + public String toString() + { + return String.valueOf(symbol); + } + } + /** * Map the name of a {@link PrimitiveType} to a Python C primitive type name. * @@ -138,7 +178,7 @@ public static String toLowerFirstChar(final String str) */ public static String formatPropertyName(final String str) { - return toUpperFirstChar(str); + return toLowerFirstChar(str); } /** @@ -152,6 +192,17 @@ public static String formatClassName(final String str) return toUpperFirstChar(str); } + /** + * Format a String as a module name. + * + * @param str to be formatted. + * @return the string formatted as a class name. + */ + public static String formatModuleName(final String str) + { + return camToSnake(str); + } + /** * Converts CamelCase to snake_case, which is the recommended python case * @@ -176,4 +227,58 @@ public static String camToSnake(final String str) { return camToSnake(str, true); } + + public static String generatePyDoc(final String indend, final Token token) + { + return ""; + } + + public static String generateLiteral(final PrimitiveType type, final String value) + { + String literal = ""; + + switch (type) + { + case CHAR: + literal = "\"" + value + "\""; + break; + case UINT8: + case INT8: + case INT16: + case UINT16: + case UINT32: + case INT64: + case INT32: + literal = value; + break; + case UINT64: + literal = Long.toUnsignedString(Long.parseLong(value)); + break; + case FLOAT: + case DOUBLE: + if (value.endsWith("NaN")) + { + literal = "float('nan')"; + } + else + { + literal = value; + } + break; + } + + return literal; + } + + /** + * Shortcut to append a line of generated code + * + * @param builder string builder to which to append the line + * @param indent current text indentation + * @param line line to be appended + */ + public static void append(final StringBuilder builder, final String indent, final String line) + { + builder.append(indent).append(line).append('\n'); + } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java index a6565ab37f..cd1e4b297b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java @@ -33,6 +33,7 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) public static CodeGenerator defaultPythonGenerator(final Ir ir, final String outputDir) { - return new PyGenerator(ir, new PyOutputManager(outputDir, ir.applicableNamespace())); + return new PythonGenerator(ir, false, false, + false, new PyOutputManager(outputDir, ir.applicableNamespace())); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PythonGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PythonGenerator.java new file mode 100644 index 0000000000..cf26d4560c --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PythonGenerator.java @@ -0,0 +1,3028 @@ +/* + * Copyright 2013-2019 Real Logic Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.python; + +import org.agrona.Verify; +import org.agrona.generation.OutputManager; +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.generation.CodeGenerator; +import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.ir.*; + +import java.io.IOException; +import java.io.Writer; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.Function; + +import static uk.co.real_logic.sbe.generation.python.PyUtil.*; +import static uk.co.real_logic.sbe.ir.GenerationUtil.*; + +public class PythonGenerator implements CodeGenerator +{ + enum CodecType + { + DECODER, + ENCODER, + NONE + } + + private static final String META_ATTRIBUTE_ENUM = "MetaAttribute"; + private static final String BASE_INDENT = ""; + private static final String INDENT = " "; + private static final String FLYWEIGHT = "Flyweight"; + private static final String COMPOSITE_DECODER_FLYWEIGHT = "CompositeDecoderFlyweight"; + private static final String COMPOSITE_ENCODER_FLYWEIGHT = "CompositeEncoderFlyweight"; + private static final String MESSAGE_DECODER_FLYWEIGHT = "MessageDecoderFlyweight"; + private static final String MESSAGE_ENCODER_FLYWEIGHT = "MessageEncoderFlyweight"; + + private final Ir ir; + private final OutputManager outputManager; + private final String fqMutableBuffer; + private final String mutableBuffer; + private final String fqReadOnlyBuffer; + private final String readOnlyBuffer; + private final boolean shouldGenerateGroupOrderAnnotation; + private final boolean shouldGenerateInterfaces; + private final boolean shouldDecodeUnknownEnumValues; + + public PythonGenerator( + final Ir ir, + final boolean shouldGenerateGroupOrderAnnotation, + final boolean shouldGenerateInterfaces, + final boolean shouldDecodeUnknownEnumValues, + final OutputManager outputManager) + { + Verify.notNull(ir, "ir"); + Verify.notNull(outputManager, "outputManager"); + + this.ir = ir; + this.outputManager = outputManager; + + this.fqMutableBuffer = "bytearray"; + this.mutableBuffer = "bytearray"; + + this.readOnlyBuffer = "bytes"; + this.fqReadOnlyBuffer = "bytes"; + + this.shouldGenerateGroupOrderAnnotation = shouldGenerateGroupOrderAnnotation; + this.shouldGenerateInterfaces = shouldGenerateInterfaces; + this.shouldDecodeUnknownEnumValues = shouldDecodeUnknownEnumValues; + } + + + private String encoderName(final String className) + { + return className + "Encoder"; + } + + private String decoderName(final String className) + { + return className + "Decoder"; + } + + private String implementsInterface(final String interfaceName) + { + if (shouldGenerateInterfaces) + { + throw new RuntimeException("Python codec doesn't support interfaces"); + } + return ""; + } + + public void generateMessageHeaderStub() throws IOException + { + generateComposite(ir.headerStructure().tokens()); + } + + public void generateTypeStubs() throws IOException + { + generateMetaAttributeEnum(); + + for (final List tokens : ir.types()) + { + switch (tokens.get(0).signal()) + { + case BEGIN_ENUM: + generateEnum(tokens); + break; + + case BEGIN_SET: + generateBitSet(tokens); + break; + + case BEGIN_COMPOSITE: + generateComposite(tokens); + break; + } + } + } + + public void generate() throws IOException + { + generateStructParsers(); + generateTypeStubs(); + generateMessageHeaderStub(); + final List modules = new ArrayList<>(ir.messages().size()); + for (final List tokens : ir.messages()) + { + final Token msgToken = tokens.get(0); + final List messageBody = getMessageBody(tokens); + + int i = 0; + final List fields = new ArrayList<>(); + i = collectFields(messageBody, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(messageBody, i, groups); + + final List varData = new ArrayList<>(); + collectVarData(messageBody, i, varData); + + generateDecoder(BASE_INDENT, fields, groups, varData, msgToken, messageBody); + generateEncoder(BASE_INDENT, fields, groups, varData, msgToken, messageBody); + + final String className = formatClassName(msgToken.name()); + final String pyModuleName = camToSnake(className); + modules.add(pyModuleName); + } + generatePackageDefinition(modules); + } + + public void generatePackageDefinition(final List modules) throws IOException + { + try (Writer out = outputManager.createOutput("__init__")) + { + out.append(generateMainHeader(ir.applicableNamespace(), new ArrayList<>(), CodecType.NONE)); + for (final String m : modules) + { + out.append("from .").append(m).append("_encoder import *\n"); + out.append("from .").append(m).append("_decoder import *\n"); + } + out.append("from .meta_attribute import *\n"); + } + } + + private void generateStructParsers() throws IOException + { + try (Writer out = outputManager.createOutput("_struct_defs")) + { + out.append(generateMainHeader(ir.applicableNamespace(), new ArrayList<>(), CodecType.NONE)); + out.append("from struct import Struct\n\n"); + final StringBuilder builder = new StringBuilder(); + for (final Map.Entry order : BYTE_ORDER_STRING_MAP.entrySet()) + { + for (final Map.Entry type : PRIMITIVE_TYPE_STRUCT_ENUM_MAP.entrySet()) + { + builder.append(String.format("%2$S_%1$S: Struct = Struct('%3$s%4$s')\n", + type.getKey().primitiveName(), + order.getKey().toString(), + pythonEndianCode(order.getKey()), + pythonTypeCode(type.getKey()))); + } + //edge case to handle char[] unpacking + builder.append(String.format("%2$S_%1$S: Struct = Struct('%3$s%4$s')\n", + "CHARS", + order.getKey().toString(), + pythonEndianCode(order.getKey()), + "s")); + } + + builder.append("\n"); + out.append(builder.toString()); + } + } + + private void generateEncoder( + final String indent, + final List fields, + final List groups, + final List varData, + final Token msgToken, + final List msgBody) throws IOException + { + final String className = formatClassName(encoderName(msgToken.name())); + final String moduleName = formatModuleName(className); + final String implementsString = implementsInterface(MESSAGE_ENCODER_FLYWEIGHT); + + try (Writer out = outputManager.createOutput(moduleName)) + { + out.append(generateMainHeader(ir.applicableNamespace(), msgBody, CodecType.ENCODER)); + + generateAnnotations(indent, className, groups, out, 0, this::encoderName); + out.append(generateDeclaration(className, implementsString, msgToken)); + out.append(generateEncoderFlyweightCode(className, msgToken)); + out.append(generateEncoderFields(className, fields, indent)); + + final StringBuilder sb = new StringBuilder(); + generateEncoderGroups(sb, className, className, groups, indent, false); + out.append(sb); + + out.append(generateEncoderVarData(className, varData, indent)); + + } + } + + private void generateDecoder( + final String indent, + final List fields, + final List groups, + final List varData, + final Token msgToken, + final List msgBody) throws IOException + { + final String className = formatClassName(decoderName(msgToken.name())); + final String moduleName = formatModuleName(className); + final String implementsString = implementsInterface(MESSAGE_DECODER_FLYWEIGHT); + + try (Writer out = outputManager.createOutput(moduleName)) + { + out.append(generateMainHeader(ir.applicableNamespace(), msgBody, CodecType.DECODER)); + + generateAnnotations(indent, className, groups, out, 0, this::decoderName); + out.append(generateDeclaration(className, implementsString, msgToken)); + out.append(generateDecoderFlyweightCode(className, msgToken)); + out.append(generateDecoderFields(fields, indent)); + + final StringBuilder sb = new StringBuilder(); + generateDecoderGroups(sb, className, className, groups, indent, false); + out.append(sb); + + out.append(generateDecoderVarData(varData, indent)); + + out.append(generateDecoderDisplay(msgToken.name(), fields, groups, varData, indent)); + + } + } + + private void generateDecoderGroups( + final StringBuilder sb, + final String outerClassName, + final String hierarchyName, + final List tokens, + final String indent, + final boolean isSubGroup) throws IOException + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + final int groupIndex = i; + final String groupName = decoderName(formatClassName(groupToken.name())); + + ++i; + final int groupHeaderTokenCount = tokens.get(i).componentTokenCount(); + i += groupHeaderTokenCount; + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + final String fullyQualifiedName = hierarchyName + '.' + groupName; + + generateAnnotations(indent + INDENT, groupName, tokens, sb, groupIndex + 1, this::decoderName); + generateGroupDecoderClassHeader(sb, groupName, outerClassName, fullyQualifiedName, tokens, groups, + groupIndex, indent + INDENT); + + sb.append(generateDecoderFields(fields, indent + INDENT)); + generateDecoderGroups(sb, outerClassName, fullyQualifiedName, groups, indent + INDENT, true); + sb.append(generateDecoderVarData(varData, indent + INDENT)); + + appendGroupInstanceDecoderDisplay(sb, fields, groups, varData, indent + INDENT); + + sb.append(generateGroupDecoderProperty(groupName, fullyQualifiedName, groupToken, indent, isSubGroup)); + + sb.append("\n"); + } + } + + private void generateEncoderGroups( + final StringBuilder sb, + final String outerClassName, + final String hierarchyName, + final List tokens, + final String indent, + final boolean isSubGroup) throws IOException + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + final int groupIndex = i; + final String groupName = groupToken.name(); + final String groupClassName = formatClassName(encoderName(groupName)); + + ++i; + final int groupHeaderTokenCount = tokens.get(i).componentTokenCount(); + i += groupHeaderTokenCount; + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + final String fullyQualifiedName = hierarchyName + '.' + groupClassName; + + generateAnnotations(indent + INDENT, groupClassName, tokens, sb, groupIndex + 1, this::encoderName); + generateGroupEncoderClassHeader(sb, groupName, outerClassName, fullyQualifiedName, tokens, groups, + groupIndex, indent + INDENT); + + sb.append(generateEncoderFields(fullyQualifiedName, fields, indent + INDENT)); + generateEncoderGroups(sb, outerClassName, fullyQualifiedName, groups, indent + INDENT, true); + sb.append(generateEncoderVarData(fullyQualifiedName, varData, indent + INDENT)); + + sb.append(generateGroupEncoderProperty(groupName, fullyQualifiedName, groupToken, indent, isSubGroup)); + + sb.append(indent).append("\n"); + } + } + + private void generateGroupDecoderClassHeader( + final StringBuilder sb, + final String groupName, + final String parentMessageClassName, + final String fullyQualifiedClassName, + final List tokens, + final List subGroupTokens, + final int index, + final String indent) + { + final Token groupToken = tokens.get(index); + final int dimensionHeaderLen = tokens.get(index + 1).encodedLength(); + + final Token blockLengthToken = Generators.findFirst("blockLength", tokens, index); + final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); + + final PrimitiveType blockLengthType = blockLengthToken.encoding().primitiveType(); + final String blockLengthOffset = "limit + " + blockLengthToken.offset(); + final String blockLengthGet = generateGet( + blockLengthType, blockLengthOffset, byteOrderString(blockLengthToken.encoding())); + + final PrimitiveType numInGroupType = numInGroupToken.encoding().primitiveType(); + final String numInGroupOffset = "limit + " + numInGroupToken.offset(); + final String numInGroupGet = generateGet( + numInGroupType, numInGroupOffset, byteOrderString(numInGroupToken.encoding())); + + generateGroupDecoderClassDeclaration( + sb, + groupToken, + groupName, + parentMessageClassName, + findSubGroupNames(subGroupTokens), + indent, + dimensionHeaderLen); + + sb.append(String.format( + "\n" + + indent + " def wrap(self, buffer: '%1$s', parentMessage: '%4$s'):\n" + + indent + " if buffer != self._buffer:\n" + + indent + " self._buffer = buffer\n" + + indent + " self._index: int = -1\n" + + indent + " self._parentMessage = parentMessage\n" + + indent + " limit: int = self._parentMessage.limit\n" + + indent + " self._parentMessage.set_limit(limit + self.HEADER_SIZE)\n" + + indent + " self._blockLength: int = %2$s\n" + + indent + " self._count: int = %3$s\n", + readOnlyBuffer, + blockLengthGet, + numInGroupGet, + parentMessageClassName)); + + final int blockLength = tokens.get(index).encodedLength(); + + sb.append(indent).append(" @property\n") + .append(indent).append(" def sbeHeaderSize(self) -> int:\n") + .append(indent).append(" return self.HEADER_SIZE\n"); + + sb.append(String.format("\n" + + indent + " @property\n" + + indent + " def sbeBlockLength(self) -> int:\n" + + indent + " return %d\n", + blockLength)); + + sb.append(String.format("\n" + + indent + " def actingBlockLength(self) -> int:\n" + + indent + " return self._blockLength\n" + + indent + " \n\n" + + indent + " def count(self) -> int:\n" + + indent + " return self._count\n" + + indent + " \n\n" + + indent + " def remove(self):\n" + + indent + " raise NotImplementedError()\n" + + indent + " \n\n" + + indent + " def hasNext(self) -> bool:\n" + + indent + " return (self._index + 1) < self._count\n" + + indent + " \n", + formatClassName(fullyQualifiedClassName))); + + sb.append(String.format("\n" + + indent + " def next(self) -> '%s':\n" + + indent + " if self._index + 1 >= self._count:\n" + + indent + " raise KeyError()\n" + + indent + " \n\n" + + indent + " self._offset: int = self._parentMessage.limit\n" + + indent + " self._parentMessage.set_limit(self._offset + self._blockLength)\n" + + indent + " self._index += 1\n\n" + + indent + " return self\n" + + indent + " \n", + formatClassName(fullyQualifiedClassName))); + } + + private void generateGroupEncoderClassHeader( + final StringBuilder sb, + final String groupName, + final String parentMessageClassName, + final String hierarchyName, + final List tokens, + final List subGroupTokens, + final int index, + final String ind) + { + final Token groupToken = tokens.get(index); + final int dimensionHeaderSize = tokens.get(index + 1).encodedLength(); + + generateGroupEncoderClassDeclaration( + sb, + groupToken, + groupName, + parentMessageClassName, + hierarchyName, + findSubGroupNames(subGroupTokens), + ind, + dimensionHeaderSize); + + final int blockLength = tokens.get(index).encodedLength(); + final Token blockLengthToken = Generators.findFirst("blockLength", tokens, index); + final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); + + final PrimitiveType blockLengthType = blockLengthToken.encoding().primitiveType(); + final String blockLengthOffset = "limit + " + blockLengthToken.offset(); + final String blockLengthValue = String.valueOf(blockLength); + final String blockLengthPut = generatePut( + blockLengthType, blockLengthOffset, blockLengthValue, byteOrderString(blockLengthToken.encoding())); + + final PrimitiveType numInGroupType = numInGroupToken.encoding().primitiveType(); + final String numInGroupOffset = "limit + " + numInGroupToken.offset(); + final String numInGroupValue = "count"; + final String numInGroupPut = generatePut( + numInGroupType, numInGroupOffset, numInGroupValue, byteOrderString(numInGroupToken.encoding())); + + sb.append(String.format( + ind + " def wrap(self, buffer: %2$s, parentMessage: '%1$s', count: int):\n" + + ind + " if count < %3$d or count > %4$d:\n" + + ind + " raise IndexError(\"count outside allowed range: count=\" + str(count))\n" + + ind + " \n\n" + + ind + " if buffer != self._buffer:\n" + + ind + " self._buffer = buffer\n" + + ind + " \n\n" + + ind + " self._index = -1\n" + + ind + " self._parentMessage = parentMessage\n" + + ind + " self._count = count\n" + + ind + " limit: int = self._parentMessage.limit\n" + + ind + " self._parentMessage.set_limit(limit + self.HEADER_SIZE)\n" + + ind + " %5$s\n" + + ind + " %6$s\n" + + ind + " \n\n", + parentMessageClassName, + mutableBuffer, + numInGroupToken.encoding().applicableMinValue().longValue(), + numInGroupToken.encoding().applicableMaxValue().longValue(), + blockLengthPut, + numInGroupPut)); + + sb.append(ind).append(" @property\n") + .append(ind).append(" def sbeHeaderSize(self) -> int:\n") + .append(ind).append(" return self.HEADER_SIZE\n"); + + sb.append(String.format("\n" + + ind + " @property\n" + + ind + " def sbeBlockLength(self) -> int:\n" + + ind + " return %d\n", + blockLength)); + + sb.append(String.format("\n" + + ind + " def next(self) -> '%s':\n" + + ind + " if self._index + 1 >= self._count:\n" + + ind + " raise IndexError('Index ' + str(self._index) + 'out of bounds ' + str(self._count))\n" + + ind + " \n\n" + + ind + " self._offset= self._parentMessage.limit\n" + + ind + " self._parentMessage.set_limit(self._offset + self.sbeBlockLength)\n" + + ind + " self._index += 1\n\n" + + ind + " return self\n" + + ind + " \n", + hierarchyName)); + } + + private static String primitiveTypeName(final Token token) + { + return pythonTypeName(token.encoding().primitiveType()); + } + + private void generateGroupDecoderClassDeclaration( + final StringBuilder sb, + final Token groupToken, + final String groupName, + final String parentMessageClassName, + final List subGroupNames, + final String indent, + final int dimensionHeaderSize) + { + final String className = formatClassName(groupName); + + sb.append(String.format("\n" + + "%1$s" + + indent + "class %2$s:\n" + + indent + " HEADER_SIZE: int = %3$d\n" + + indent + " _parentMessage: '%4$s'\n" + + indent + " _buffer: %5$s = None\n" + + indent + " _count: int\n" + + indent + " _index: int\n" + + indent + " _offset: int\n" + + indent + " _blockLength: int\n", + generatePyDoc(indent, groupToken), + className, + dimensionHeaderSize, + parentMessageClassName, + readOnlyBuffer)); + + } + + private void generateGroupEncoderClassDeclaration( + final StringBuilder sb, + final Token groupToken, + final String groupName, + final String parentMessageClassName, + final String fullyQualifiedName, + final List subGroupNames, + final String indent, + final int dimensionHeaderSize) + { + final String className = formatClassName(encoderName(groupName)); + + sb.append(String.format("\n" + + "%1$s" + + indent + "class %2$s:\n" + + indent + " HEADER_SIZE: int = %3$d\n", + generatePyDoc(indent, groupToken), + className, + dimensionHeaderSize)); + + + sb + .append("\n") + .append(indent).append(" ") + .append("def __init__(self):\n") + .append(String.format( + indent + " self._parentMessage: '%1$s' = None\n" + + indent + " self._buffer: '%2$s' = None\n" + + indent + " self._count: int = None\n" + + indent + " self._index: int = None\n" + + indent + " self._offset: int = None\n", + parentMessageClassName, + mutableBuffer)); + + for (final String subGroupName : subGroupNames) + { + final String type = formatClassName(encoderName(subGroupName)); + final String field = formatPropertyName(subGroupName); + sb.append(indent).append(" self._").append(field).append(": '").append(fullyQualifiedName) + .append(".").append(type).append("' = ").append("self").append('.').append(type).append("()\n"); + } + + sb.append("\n\n"); + } + + private static CharSequence generateGroupDecoderProperty( + final String groupName, final String fullyQualifiedName, final Token token, final String indent, + final boolean isSubGroup) + { + final StringBuilder sb = new StringBuilder(); + final String className = formatClassName(groupName); + final String propertyName = formatPropertyName(token.name()); + + sb.append(String.format("\n" + + indent + " _%s: %s = %s()\n", + propertyName, + className, + className)); + + sb.append(String.format("\n" + + indent + " def %sId(self) -> int:\n" + + indent + " return %d\n" + + indent + " \n", + formatPropertyName(groupName), + token.id())); + + sb.append(String.format("\n" + + indent + " def %sSinceVersion(self) -> int:\n" + + indent + " return %d\n" + + indent + " \n", + formatPropertyName(groupName), + token.version())); + + final String actingVersionGuard = token.version() == 0 ? + "" : + indent + " if parentMessage.actingVersion < " + token.version() + ":\n" + + indent + " " + propertyName + ".count = 0\n" + + indent + " " + propertyName + ".index = -1\n" + + indent + " return " + propertyName + "\n" + + indent + " \n\n"; + + sb.append(String.format("\n" + + indent + " def %2$s(self) -> %1$s:\n" + + "%3$s" + + indent + " self._%2$s.wrap(self._buffer, self._parentMessage)\n" + + indent + " return self._%2$s\n" + + indent + " \n", + className, + propertyName, + actingVersionGuard)); + + return sb; + } + + private CharSequence generateGroupEncoderProperty( + final String groupName, final String fullyQualifiedName, final Token token, final String indent, + final boolean isSubGroup) + { + final StringBuilder sb = new StringBuilder(); + final String className = formatClassName(encoderName(groupName)); + final String propertyName = formatPropertyName(groupName); + + if (!isSubGroup) + { + sb.append(String.format("\n" + + indent + " _%s: '%s' = %s()\n", + propertyName, + className, + className)); + } + + sb.append(String.format("\n" + + indent + " def %sId(self) -> int:\n" + + indent + " return %d\n" + + indent + " \n", + formatPropertyName(groupName), + token.id())); + + sb.append(String.format("\n" + + indent + " def %2$sCount(self, count: int) -> '%1$s':\n" + + indent + " self._%2$s.wrap(self._buffer, self._parentMessage, count)\n" + + indent + " return self._%2$s\n" + + indent + " \n", + className, + propertyName)); + + return sb; + } + + private CharSequence generateDecoderVarData(final List tokens, final String indent) + { + final StringBuilder sb = new StringBuilder(); + + for (int i = 0, size = tokens.size(); i < size; ) + { + final Token token = tokens.get(i); + if (token.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + token); + } + + generateFieldIdMethod(sb, token, indent); + generateFieldSinceVersionMethod(sb, token, indent); + + final String characterEncoding = tokens.get(i + 3).encoding().characterEncoding(); + generateCharacterEncodingMethod(sb, token.name(), characterEncoding, indent); + generateFieldMetaAttributeMethod(sb, token, indent); + + final String propertyName = Generators.toUpperFirstChar(token.name()); + final Token lengthToken = tokens.get(i + 2); + final int sizeOfLengthField = lengthToken.encodedLength(); + final Encoding lengthEncoding = lengthToken.encoding(); + final PrimitiveType lengthType = lengthEncoding.primitiveType(); + final String byteOrderStr = byteOrderString(lengthEncoding); + + sb.append(String.format("\n" + + indent + " @staticmethod\n" + + indent + " def %sHeaderLength() -> int:\n" + + indent + " return %d\n" + + indent + " \n", + Generators.toLowerFirstChar(propertyName), + sizeOfLengthField)); + + sb.append(String.format("\n" + + indent + " def %sLength(self) -> int:\n" + + "%s" + + indent + " limit: int = self._parentMessage.limit\n" + + indent + " return %s\n" + + indent + " \n", + Generators.toLowerFirstChar(propertyName), + generateArrayFieldNotPresentCondition(token.version(), indent), + generateGet(lengthType, "limit", byteOrderStr))); + + generateDataDecodeMethods( + sb, token, propertyName, sizeOfLengthField, lengthType, byteOrderStr, characterEncoding, indent); + + i += token.componentTokenCount(); + } + + return sb; + } + + private CharSequence generateEncoderVarData(final String className, final List tokens, final String indent) + { + final StringBuilder sb = new StringBuilder(); + + for (int i = 0, size = tokens.size(); i < size; ) + { + final Token token = tokens.get(i); + if (token.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + token); + } + + generateFieldIdMethod(sb, token, indent); + final Token varDataToken = Generators.findFirst("varData", tokens, i); + final String characterEncoding = varDataToken.encoding().characterEncoding(); + generateCharacterEncodingMethod(sb, token.name(), characterEncoding, indent); + generateFieldMetaAttributeMethod(sb, token, indent); + + final String propertyName = Generators.toUpperFirstChar(token.name()); + final Token lengthToken = Generators.findFirst("length", tokens, i); + final int sizeOfLengthField = lengthToken.encodedLength(); + final Encoding lengthEncoding = lengthToken.encoding(); + final int maxLengthValue = (int)lengthEncoding.applicableMaxValue().longValue(); + + sb.append(String.format("\n" + + indent + " def %sHeaderLength(self) -> int:\n" + + indent + " return %d\n" + + indent + " \n", + Generators.toLowerFirstChar(propertyName), + sizeOfLengthField)); + + generateDataEncodeMethods( + sb, + propertyName, + sizeOfLengthField, + maxLengthValue, + lengthEncoding.primitiveType(), + lengthEncoding, + characterEncoding, + className, + indent); + + i += token.componentTokenCount(); + } + + return sb; + } + + private void generateDataDecodeMethods( + final StringBuilder sb, + final Token token, + final String propertyName, + final int sizeOfLengthField, + final PrimitiveType lengthType, + final String byteOrderStr, + final String characterEncoding, + final String indent) + { + + generateVarDataWrapDecoder(sb, token, propertyName, sizeOfLengthField, lengthType, byteOrderStr, indent); + + if (null != characterEncoding) + { + sb.append(String.format("\n" + + indent + " def %1$s(self) -> str:\n" + + "%2$s" + + indent + " headerLength: int = %3$d\n" + + indent + " limit: int = self._parentMessage.limit\n" + + indent + " dataLength: int = %4$s\n" + + indent + " self._parentMessage.set_limit(limit + headerLength + dataLength)\n\n" + + indent + " if 0 == dataLength:\n" + + indent + " return \"\"\n" + + indent + " \n\n" + + indent + " return memoryview(self._buffer)[limit + headerLength:limit + " + + "headerLength + dataLength].tobytes()." + + "decode(\"%5$s\")\n" + + indent + "\n", + formatPropertyName(propertyName), + generateStringNotPresentCondition(token.version(), indent), + sizeOfLengthField, + generateGet(lengthType, "limit", byteOrderStr), + characterEncoding)); + } + } + + private void generateVarDataWrapDecoder( + final StringBuilder sb, + final Token token, + final String propertyName, + final int sizeOfLengthField, + final PrimitiveType lengthType, + final String byteOrderStr, + final String indent) + { + sb.append(String.format("\n" + + indent + " def wrap%s(self) -> memoryview:\n" + + "%s" + + indent + " headerLength: int = %d\n" + + indent + " limit: int = self._parentMessage.limit\n" + + indent + " dataLength: int = %s\n" + + indent + " self._parentMessage.set_limit(limit + headerLength + dataLength)\n" + + indent + " limit: int = self._parentMessage.limit\n" + + indent + " self._parentMessage.set_limit(limit + headerLength + dataLength)\n" + + indent + " return memoryview(self._buffer)[limit + headerLength:limit + headerLength + dataLength]" + + "\n" + + indent + " \n", + propertyName, + generateVarWrapFieldNotPresentCondition(token.version(), indent), + sizeOfLengthField, + generateGet(lengthType, "limit", byteOrderStr))); + } + + private void generateDataEncodeMethods( + final StringBuilder sb, + final String propertyName, + final int sizeOfLengthField, + final int maxLengthValue, + final PrimitiveType lengthType, + final Encoding encoding, + final String characterEncoding, + final String className, + final String indent) + { + generateDataTypedEncoder( + sb, + className, + propertyName, + sizeOfLengthField, + maxLengthValue, + readOnlyBuffer, + lengthType, + encoding, + indent); + + if (null != characterEncoding) + { + generateCharArrayEncodeMethods( + sb, + propertyName, + sizeOfLengthField, + maxLengthValue, + lengthType, + encoding, + characterEncoding, + className, + indent); + } + } + + private void generateCharArrayEncodeMethods( + final StringBuilder sb, + final String propertyName, + final int sizeOfLengthField, + final int maxLengthValue, + final PrimitiveType lengthType, + final Encoding encoding, + final String characterEncoding, + final String className, + final String indent) + { + sb.append(String.format("\n" + + indent + " def %1$s(self, data: Union[bytes, bytearray, memoryview]) -> '%7$s':\n" + + indent + " size_of_len_field: int = %2$d\n" + + indent + " limit:int = self._parentMessage.limit\n" + + indent + " self._parentMessage.set_limit(limit + size_of_len_field + len(data))\n" + + indent + " data_len: int = len(data)\n" + + indent + " %5$s\n" + + indent + " struct.pack_into('%6$s%%ds' %% (data_len,), self._buffer, limit + size_of_len_field, " + + "data)\n" + + indent + " return self\n\n", + formatPropertyName(propertyName), + sizeOfLengthField, + pythonTypeName(lengthType), + byteOrderString(encoding), + generatePut(lengthType, "limit", "data_len", byteOrderString(encoding)), + pythonEndianCode(encoding.byteOrder()), + className)); + } + + private void generateDataTypedEncoder( + final StringBuilder sb, + final String className, + final String propertyName, + final int sizeOfLengthField, + final int maxLengthValue, + final String exchangeType, + final PrimitiveType lengthType, + final Encoding encoding, + final String indent) + { + //TODO: FIX + sb.append(String.format("\n" + + indent + " def put%2$s(self, src: %3$s, srcOffset: int, length: int) -> '%1$s':\n" + + indent + " if length > %4$d:\n" + + indent + " raise OverflowError(\"length > maxValue for type: \" + length)\n" + + indent + " \n\n" + + indent + " headerLength: int = %5$d\n" + + indent + " limit: int = self._parentMessage.limit\n" + + indent + " self._parentMessage.set_limit(limit + headerLength + length)\n" + + indent + " %6$s\n" + + indent + " return self\n" + + indent + " \n", + className, + propertyName, + exchangeType, + maxLengthValue, + sizeOfLengthField, + generatePut(lengthType, "limit", "length", byteOrderString(encoding)))); + } + + private void generateBitSet(final List tokens) throws IOException + { + final Token token = tokens.get(0); + final List msgBody = getMessageBody(tokens); + final String bitSetName = formatClassName(token.applicableTypeName()); + final String decoderName = decoderName(bitSetName); + final String encoderName = encoderName(bitSetName); + final String encoderModuleName = formatModuleName(encoderName); + final String decoderModuleName = formatModuleName(decoderName); + + final List messageBody = getMessageBody(tokens); + final String implementsString = implementsInterface(FLYWEIGHT); + + try (Writer out = outputManager.createOutput(decoderModuleName)) + { + generateFixedFlyweightHeader(token, decoderName, implementsString, out, readOnlyBuffer, fqReadOnlyBuffer, + msgBody, CodecType.DECODER); + out.append(generateChoiceIsEmpty(token.encoding().primitiveType(), token.encoding().byteOrder())); + out.append(generateChoiceDecoders(messageBody)); + out.append(generateChoiceDisplay(messageBody)); + } + + try (Writer out = outputManager.createOutput(encoderModuleName)) + { + generateFixedFlyweightHeader(token, encoderName, implementsString, out, mutableBuffer, fqMutableBuffer, + msgBody, CodecType.ENCODER); + out.append(generateChoiceClear(encoderName, token)); + out.append(generateChoiceEncoders(encoderName, messageBody)); + } + } + + private void generateFixedFlyweightHeader( + final Token token, + final String typeName, + final String implementsString, + final Writer out, + final String buffer, + final String fqBuffer, + final List tokens, + final CodecType codecType) throws IOException + { + out.append(generateFileHeader(ir.applicableNamespace(), fqBuffer, tokens, codecType)); + out.append(generateDeclaration(typeName, implementsString, token)); + out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer)); + } + + private void generateCompositeFlyweightHeader( + final Token token, + final String typeName, + final Writer out, + final String buffer, + final String fqBuffer, + final String implementsString, + final List tokens, + final CodecType codecType) throws IOException + { + out.append(generateFileHeader(ir.applicableNamespace(), fqBuffer, tokens, codecType)); + out.append(generateDeclaration(typeName, implementsString, token)); + out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer)); + } + + private void generateEnum(final List tokens) throws IOException + { + final Token enumToken = tokens.get(0); + final String enumName = formatClassName(enumToken.applicableTypeName()); + final String moduleName = formatModuleName(enumName); + + + try (Writer out = outputManager.createOutput(moduleName)) + { + out.append(generateEnumFileHeader(ir.applicableNamespace())); + out.append(generateEnumDeclaration(enumName, enumToken)); + + out.append(generateEnumValues(getMessageBody(tokens))); + out.append(generateEnumBody(enumToken, enumName)); + + out.append(generateEnumLookupMethod(getMessageBody(tokens), enumName)); + } + } + + private void generateComposite(final List tokens) throws IOException + { + final Token token = tokens.get(0); + final List msgBody = getMessageBody(tokens); + final String compositeName = formatClassName(token.applicableTypeName()); + final String decoderName = decoderName(compositeName); + final String encoderName = encoderName(compositeName); + final String encoderModuleName = formatModuleName(encoderName); + final String decoderModuleName = formatModuleName(decoderName); + + try (Writer out = outputManager.createOutput(decoderModuleName)) + { + final String implementsString = implementsInterface(COMPOSITE_DECODER_FLYWEIGHT); + generateCompositeFlyweightHeader( + token, decoderName, out, readOnlyBuffer, fqReadOnlyBuffer, implementsString, msgBody, + CodecType.DECODER); + for (int i = 1, end = tokens.size() - 1; i < end; ) + { + final Token encodingToken = tokens.get(i); + final String propertyName = formatPropertyName(encodingToken.name()); + final String typeName = formatClassName(decoderName(encodingToken.applicableTypeName())); + + final StringBuilder sb = new StringBuilder(); + generateEncodingOffsetMethod(sb, propertyName, encodingToken.offset(), BASE_INDENT); + generateEncodingLengthMethod(sb, propertyName, encodingToken.encodedLength(), BASE_INDENT); + generateFieldSinceVersionMethod(sb, encodingToken, BASE_INDENT); + switch (encodingToken.signal()) + { + case ENCODING: + out.append(sb).append(generatePrimitiveDecoder( + true, encodingToken.name(), encodingToken, encodingToken, BASE_INDENT)); + break; + + case BEGIN_ENUM: + out.append(sb).append(generateEnumDecoder( + true, encodingToken, propertyName, encodingToken, BASE_INDENT)); + break; + + case BEGIN_SET: + out.append(sb).append(generateBitSetProperty( + true, CodecType.DECODER, propertyName, encodingToken, encodingToken, + BASE_INDENT, typeName)); + break; + + case BEGIN_COMPOSITE: + out.append(sb).append(generateCompositeProperty( + true, CodecType.DECODER, propertyName, encodingToken, encodingToken, + BASE_INDENT, typeName)); + break; + } + i += encodingToken.componentTokenCount(); + } + out.append(generateCompositeDecoderDisplay(tokens, BASE_INDENT)); + } + + try (Writer out = outputManager.createOutput(encoderModuleName)) + { + final String implementsString = implementsInterface(COMPOSITE_ENCODER_FLYWEIGHT); + generateCompositeFlyweightHeader(token, encoderName, out, mutableBuffer, fqMutableBuffer, implementsString, + msgBody, CodecType.ENCODER); + + for (int i = 1, end = tokens.size() - 1; i < end; ) + { + final Token encodingToken = tokens.get(i); + final String propertyName = formatPropertyName(encodingToken.name()); + final String typeName = formatClassName(encoderName(encodingToken.applicableTypeName())); + + final StringBuilder sb = new StringBuilder(); + generateEncodingOffsetMethod(sb, propertyName, encodingToken.offset(), BASE_INDENT); + generateEncodingLengthMethod(sb, propertyName, encodingToken.encodedLength(), BASE_INDENT); + + switch (encodingToken.signal()) + { + case ENCODING: + out.append(sb).append(generatePrimitiveEncoder( + encoderName, encodingToken.name(), encodingToken, BASE_INDENT)); + break; + + case BEGIN_ENUM: + out.append(sb).append(generateEnumEncoder( + encoderName, encodingToken, propertyName, encodingToken, BASE_INDENT)); + break; + + case BEGIN_SET: + out.append(sb).append(generateBitSetProperty( + true, CodecType.ENCODER, propertyName, encodingToken, encodingToken, + BASE_INDENT, typeName)); + break; + + case BEGIN_COMPOSITE: + out.append(sb).append(generateCompositeProperty( + true, CodecType.ENCODER, propertyName, encodingToken, encodingToken, + BASE_INDENT, typeName)); + break; + } + + i += encodingToken.componentTokenCount(); + } + + } + } + + private CharSequence generateChoiceClear(final String bitSetClassName, final Token token) + { + final StringBuilder sb = new StringBuilder(); + + final Encoding encoding = token.encoding(); + final String literalValue = generateLiteral(encoding.primitiveType(), "0"); + final String byteOrderStr = byteOrderString(encoding); + + sb.append(String.format("\n" + + " def clear(self) -> '%s':\n" + + " %s\n" + + " return self\n" + + " \n", + bitSetClassName, + generatePut(encoding.primitiveType(), "self._offset", literalValue, byteOrderStr))); + + return sb; + } + + private CharSequence generateChoiceDecoders(final List tokens) + { + return concatTokens( + tokens, + Signal.CHOICE, + (token) -> + { + final String choiceName = formatPropertyName(token.name()); + final Encoding encoding = token.encoding(); + final String choiceBitIndex = encoding.constValue().toString(); + final String byteOrderStr = byteOrderString(encoding); + final PrimitiveType primitiveType = encoding.primitiveType(); + final String argType = bitsetArgType(primitiveType); + + return String.format("\n" + + " def %1$s(self) -> bool:\n" + + " return %2$s\n" + + " \n\n" + + " @staticmethod\n" + + " def apply_%1$s(value: %3$s) -> bool:\n" + + " return %4$s\n" + + " \n", + choiceName, + generateChoiceGet(primitiveType, choiceBitIndex, byteOrderStr), + argType, + generateStaticChoiceGet(primitiveType, choiceBitIndex)); + }); + } + + private CharSequence generateChoiceEncoders(final String bitSetClassName, final List tokens) + { + return concatTokens( + tokens, + Signal.CHOICE, + (token) -> + { + final String choiceName = formatPropertyName(token.name()); + final Encoding encoding = token.encoding(); + final String choiceBitIndex = encoding.constValue().toString(); + final String byteOrderStr = byteOrderString(encoding); + final PrimitiveType primitiveType = encoding.primitiveType(); + final String argType = bitsetArgType(primitiveType); + + return String.format("\n" + + " def %2$s(self, value: bool) -> '%1$s':\n" + + "%3$s\n" + + " return self\n" + + " \n\n" + + " @staticmethod\n" + + " def apply_%2$s(bits: %4$s, value: bool) -> '%4$s':\n" + + "%5$s" + + " \n", + bitSetClassName, + choiceName, + generateChoicePut(encoding.primitiveType(), choiceBitIndex, byteOrderStr), + argType, + generateStaticChoicePut(encoding.primitiveType(), choiceBitIndex)); + }); + } + + private String bitsetArgType(final PrimitiveType primitiveType) + { + switch (primitiveType) + { + case UINT8: + case UINT16: + case UINT32: + case UINT64: + return "int"; + + default: + throw new IllegalStateException("Invalid type: " + primitiveType); + } + } + + private CharSequence generateEnumValues(final List tokens) + { + final StringBuilder sb = new StringBuilder(); + + for (final Token token : tokens) + { + final Encoding encoding = token.encoding(); + final CharSequence constVal = generateLiteral(PrimitiveType.INT32, encoding.constValue().toString()); + sb.append(INDENT).append(token.name()).append(" = ").append(constVal).append("\n"); + } + + final Token token = tokens.get(0); + final Encoding encoding = token.encoding(); + final CharSequence nullVal = generateLiteral(PrimitiveType.INT32, encoding.applicableNullValue().toString()); + + if (shouldDecodeUnknownEnumValues) + { + sb.append(INDENT).append("\"\"\"\n"); + sb.append(INDENT).append(" To be used to represent a not known value from a later version.\n"); + sb.append(INDENT).append("\"\"\"\n"); + sb.append(INDENT).append("SBE_UNKNOWN").append(" = ").append(nullVal).append("\n"); + } + + sb.append(INDENT).append("\"\"\"\n"); + sb.append(INDENT).append(" To be used to represent not present or null.\n"); + sb.append(INDENT).append("\"\"\"\n"); + sb.append(INDENT).append("NULL_VAL").append(" = ").append(nullVal).append("\n\n"); + + return sb; + } + + private CharSequence generateEnumBody(final Token token, final String enumName) + { + return ""; + } + + private CharSequence generateEnumLookupMethod(final List tokens, final String enumName) + { + final StringBuilder sb = new StringBuilder(); + + final PrimitiveType primitiveType = PrimitiveType.INT32; + sb.append(String.format( + INDENT + "@staticmethod\n" + + INDENT + "def get(value: %s) -> '%s':\n", + pythonTypeName(primitiveType), + enumName)); + + for (final Token token : tokens) + { + final CharSequence constVal = generateLiteral(PrimitiveType.INT32, + token.encoding().constValue().toString()); + sb.append(String.format( + INDENT + INDENT + "if value == %1$s: return " + enumName + ".%2$s\n", + constVal, + token.name())); + } + + final String handleUnknownLogic = shouldDecodeUnknownEnumValues ? + INDENT + INDENT + "return " + enumName + ".SBE_UNKNOWN\n" : + INDENT + INDENT + "raise KeyError(\"Unknown value: \" + str(value))\n"; + + sb.append(String.format( + INDENT + INDENT + "if %1$s == value:\n" + + INDENT + INDENT + INDENT + "return " + enumName + ".NULL_VAL\n" + + "%2$s", + generateLiteral(primitiveType, tokens.get(0).encoding().applicableNullValue().toString()), + handleUnknownLogic)); + + return sb; + } + + private CharSequence interfaceImportLine(final List tokens, final CodecType codecType, + final boolean includeHeader) + { + if (shouldGenerateInterfaces) + { + throw new RuntimeException("Interfaced not supported in python codec"); + } + final StringBuilder sb = new StringBuilder(); + final Set processed = new HashSet<>(); + sb.append("from typing import *\n"); + sb.append("import struct\n"); + sb.append("from ._struct_defs import *\n"); + sb.append("from .meta_attribute import MetaAttribute\n"); + if (includeHeader) + { + switch (codecType) + { + case ENCODER: + sb.append("from .message_header_encoder import MessageHeaderEncoder\n"); + break; + case DECODER: + sb.append("from .message_header_decoder import MessageHeaderDecoder\n"); + } + } + for (final Token t : tokens) + { + if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET || + t.signal() == Signal.BEGIN_ENUM) + { + String importName = formatClassName(t.applicableTypeName()); + if (processed.contains(importName)) + { + continue; + } + if (t.signal() == Signal.BEGIN_ENUM) + { + sb.append("from .").append(camToSnake(importName)) + .append(" import ").append(importName).append("\n"); + } + else + { + importName = codecType == CodecType.ENCODER ? encoderName(importName) : decoderName(importName); + sb.append("from .").append(camToSnake(importName)).append(" import ").append(importName) + .append("\n"); + } + processed.add(importName); + } + } + sb.append("\n\n"); + return sb; + } + + private CharSequence generateFileHeader(final String packageName, final String fqBuffer, final List tokens, + final CodecType codecType) + { + return String.format( + "\"\"\" Generated SBE (Simple Binary Encoding) message codec \"\"\"\n" + + "%s", + interfaceImportLine(tokens, codecType, false)); + } + + private CharSequence generateMainHeader(final String packageName, final List tokens, + final CodecType codecType) + { + if (fqMutableBuffer.equals(fqReadOnlyBuffer)) + { + return String.format( + "\"\"\" Generated SBE (Simple Binary Encoding) message codec \"\"\"\n" + + "%s", + interfaceImportLine(tokens, codecType, true)); + } + else + { + return String.format( + "\"\"\" Generated SBE (Simple Binary Encoding) message codec \"\"\"\n" + + "%s", + interfaceImportLine(tokens, codecType, true)); + } + } + + private static CharSequence generateEnumFileHeader(final String packageName) + { + return "\"\"\" Generated SBE (Simple Binary Encoding) message codec \"\"\"\n\n" + + "from enum import Enum\n\n\n"; + } + + private void generateAnnotations( + final String indent, + final String className, + final List tokens, + final Appendable out, + final int index, + final Function nameMapping) throws IOException + { + if (shouldGenerateGroupOrderAnnotation) + { + final List groupClassNames = new ArrayList<>(); + int level = 0; + int i = index; + + for (int size = tokens.size(); i < size; i++) + { + if (tokens.get(index).signal() == Signal.BEGIN_GROUP) + { + if (++level == 1) + { + final Token groupToken = tokens.get(index); + final String groupName = groupToken.name(); + groupClassNames.add(formatClassName(nameMapping.apply(groupName))); + } + } + else if (tokens.get(index).signal() == Signal.END_GROUP && --level < 0) + { + break; + } + } + + if (!groupClassNames.isEmpty()) + { + out.append(indent).append("@uk.co.real_logic.sbe.codec.java.GroupOrder({"); + i = 0; + for (final String name : groupClassNames) + { + out.append(className).append('.').append(name).append(".class"); + if (++i < groupClassNames.size()) + { + out.append(", "); + } + } + + out.append("})\n"); + } + } + } + + private static CharSequence generateDeclaration( + final String className, final String implementsString, final Token typeToken) + { + return String.format( + "class %s:\n", + className); + } + + private void generateMetaAttributeEnum() throws IOException + { + try (Writer out = outputManager.createOutput(formatModuleName(META_ATTRIBUTE_ENUM))) + { + out.append("\"\"\"Generated SBE (Simple Binary Encoding) message codec \"\"\"\n\n"); + out.append( + "from enum import IntEnum \n\n\n" + + "class MetaAttribute(IntEnum):\n" + + " Epoch = 1\n" + + " TimeUnit = 2\n" + + " SemanticType = 3\n" + + " Presence = 4\n"); + } + } + + private static CharSequence generateEnumDeclaration(final String name, final Token typeToken) + { + return + "class " + name + "(Enum):\n"; + } + + private CharSequence generatePrimitiveDecoder( + final boolean inComposite, + final String propertyName, + final Token propertyToken, + final Token encodingToken, + final String indent) + { + final StringBuilder sb = new StringBuilder(); + final String formattedPropertyName = formatPropertyName(propertyName); + + sb.append(generatePrimitiveFieldMetaData(formattedPropertyName, encodingToken, indent)); + + if (encodingToken.isConstantEncoding()) + { + sb.append(generateConstPropertyMethods(formattedPropertyName, encodingToken, indent)); + } + else + { + sb.append(generatePrimitivePropertyDecodeMethods( + inComposite, formattedPropertyName, propertyToken, encodingToken, indent)); + } + + return sb; + } + + private CharSequence generatePrimitiveEncoder( + final String containingClassName, final String propertyName, final Token token, final String indent) + { + final StringBuilder sb = new StringBuilder(); + final String formattedPropertyName = formatPropertyName(propertyName); + + sb.append(generatePrimitiveFieldMetaData(formattedPropertyName, token, indent)); + + if (!token.isConstantEncoding()) + { + sb.append(generatePrimitivePropertyEncodeMethods( + containingClassName, formattedPropertyName, token, indent)); + } + else + { + sb.append(generateConstPropertyMethods(formattedPropertyName, token, indent)); + } + + return sb; + } + + private CharSequence generatePrimitivePropertyDecodeMethods( + final boolean inComposite, + final String propertyName, + final Token propertyToken, + final Token encodingToken, + final String indent) + { + return encodingToken.matchOnLength( + () -> generatePrimitivePropertyDecode(inComposite, propertyName, propertyToken, encodingToken, indent), + () -> generatePrimitiveArrayPropertyDecode( + inComposite, propertyName, propertyToken, encodingToken, indent)); + } + + private CharSequence generatePrimitivePropertyEncodeMethods( + final String containingClassName, final String propertyName, final Token token, final String indent) + { + return token.matchOnLength( + () -> generatePrimitivePropertyEncode(containingClassName, propertyName, token, indent), + () -> generatePrimitiveArrayPropertyEncode(containingClassName, propertyName, token, indent)); + } + + private CharSequence generatePrimitiveFieldMetaData( + final String propertyName, final Token token, final String indent) + { + final StringBuilder sb = new StringBuilder(); + + final PrimitiveType primitiveType = token.encoding().primitiveType(); + final String pythonTypeName = pythonTypeName(primitiveType); + final String formattedPropertyName = formatPropertyName(propertyName); + + sb.append(String.format("\n" + + indent + " @staticmethod\n" + + indent + " def %2$sNullValue() -> '%1$s':\n" + + indent + " return %3$s\n" + + indent + " \n", + pythonTypeName, + formattedPropertyName, + generateLiteral(primitiveType, token.encoding().applicableNullValue().toString()))); + + sb.append(String.format("\n" + + indent + " @staticmethod\n" + + indent + " def %2$sMinValue() -> '%1$s':\n" + + indent + " return %3$s\n" + + indent + " \n", + pythonTypeName, + formattedPropertyName, + generateLiteral(primitiveType, token.encoding().applicableMinValue().toString()))); + + sb.append(String.format( + "\n" + + indent + " @staticmethod\n" + + indent + " def %2$sMaxValue() -> '%1$s':\n" + + indent + " return %3$s\n" + + indent + " \n", + pythonTypeName, + formattedPropertyName, + generateLiteral(primitiveType, token.encoding().applicableMaxValue().toString()))); + + + return sb; + } + + private CharSequence generatePrimitivePropertyDecode( + final boolean inComposite, + final String propertyName, + final Token propertyToken, + final Token encodingToken, + final String indent) + { + final Encoding encoding = encodingToken.encoding(); + final String javaTypeName = pythonTypeName(encoding.primitiveType()); + + final int offset = encodingToken.offset(); + final String byteOrderStr = byteOrderString(encoding); + + return String.format( + "\n" + + indent + " def %s(self) -> '%s':\n" + + "%s" + + indent + " return %s\n" + + indent + " \n\n", + formatPropertyName(propertyName), + javaTypeName, + generateFieldNotPresentCondition(inComposite, propertyToken.version(), encoding, indent), + generateGet(encoding.primitiveType(), "self._offset + " + offset, byteOrderStr)); + } + + private CharSequence generatePrimitivePropertyEncode( + final String containingClassName, final String propertyName, final Token token, final String indent) + { + final Encoding encoding = token.encoding(); + final String javaTypeName = pythonTypeName(encoding.primitiveType()); + final int offset = token.offset(); + final String byteOrderStr = byteOrderString(encoding); + + return String.format( + "\n" + + indent + " def %s(self, value: %s) -> '%s':\n" + + indent + " %s\n" + + indent + " return self\n" + + indent + " \n\n", + formatPropertyName(propertyName), + javaTypeName, + formatClassName(containingClassName), + generatePut(encoding.primitiveType(), "self._offset + " + offset, "value", byteOrderStr)); + } + + private CharSequence generateVarWrapFieldNotPresentCondition(final int sinceVersion, final String indent) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + " if parentMessage.actingVersion < %d:\n" + + indent + " self._wrapBuffer.wrap(buffer, offset, 0)\n" + + indent + " \n\n", + sinceVersion); + } + + private CharSequence generateFieldNotPresentCondition( + final boolean inComposite, final int sinceVersion, final Encoding encoding, final String indent) + { + if (inComposite || 0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + " if parentMessage.actingVersion < %d:\n" + + indent + " return %s\n" + + indent + " \n\n", + sinceVersion, + generateLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString())); + } + + private static CharSequence generateArrayFieldNotPresentCondition(final int sinceVersion, final String indent) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + " if parentMessage.actingVersion < %d:\n" + + indent + " return 0\n" + + indent + " \n\n", + sinceVersion); + } + + private static CharSequence generateStringNotPresentConditionForAppendable( + final int sinceVersion, final String indent) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + " if parentMessage.actingVersion < %d:\n" + + indent + " return\n" + + indent + " \n\n", + sinceVersion); + } + + private static CharSequence generateStringNotPresentCondition(final int sinceVersion, final String indent) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + " if parentMessage.actingVersion < %d:\n" + + indent + " return \"\"\n" + + indent + " \n\n", + sinceVersion); + } + + private static CharSequence generatePropertyNotPresentCondition( + final boolean inComposite, + final CodecType codecType, + final Token propertyToken, + final String enumName, + final String indent) + { + if (inComposite || codecType == CodecType.ENCODER || 0 == propertyToken.version()) + { + return ""; + } + + return String.format( + indent + " if parentMessage.actingVersion < %d:\n" + + indent + " return %s\n" + + indent + " \n\n", + propertyToken.version(), + enumName == null ? "null" : (enumName + ".NULL_VAL")); + } + + private CharSequence generatePrimitiveArrayPropertyDecode( + final boolean inComposite, + final String propertyName, + final Token propertyToken, + final Token encodingToken, + final String indent) + { + final Encoding encoding = encodingToken.encoding(); + final String typeName = pythonTypeName(encoding.primitiveType()); + final int offset = encodingToken.offset(); + final String byteOrderStr = byteOrderString(encoding); + final String typePrefix = toUpperFirstChar(encoding.primitiveType().primitiveName()); + final int fieldLength = encodingToken.arrayLength(); + final int typeSize = sizeOfPrimitive(encoding); + + final StringBuilder sb = new StringBuilder(); + + generateArrayLengthMethod(propertyName, indent, fieldLength, sb); + sb.append(String.format( + indent + " def %s(self, index: int) -> '%s':\n" + + indent + " if index < 0 or index >= %d:\n" + + indent + " raise IndexError(\"index out of range: index=\" + str(index))\n" + + "%s" + + indent + " pos: int = self._offset + %d + (index * %d)\n\n" + + indent + " return %s\n" + + indent + " \n\n", + propertyName, + typeName, + fieldLength, + generateFieldNotPresentCondition(inComposite, propertyToken.version(), encoding, indent), + offset, + typeSize, + generateGet(encoding.primitiveType(), "pos", byteOrderStr))); + + + final String structParserMulti = String.format("A_%1$S_%2$S_%3$S", Generators.toUpperFirstChar(propertyName), + typePrefix, byteOrderStr); + + sb.append(String.format("\n" + + INDENT + structParserMulti + " = Struct('%1$s%2$d%3$s') \n", + pythonEndianCode(encoding.byteOrder()), fieldLength, + pythonTypeCode(encoding.primitiveType()))); + + if (encoding.primitiveType() == PrimitiveType.CHAR) + { + generateCharacterEncodingMethod(sb, propertyName, encoding.characterEncoding(), indent); + //Properties for multi item assignment + sb.append(String.format("\n" + + INDENT + "def getMulti%2$s(self) -> bytes:\n" + + "%4$s" + + INDENT + " return self." + structParserMulti + ".unpack_from(self._buffer, self._offset + %5$d)[0]" + + "\n", + typeName, Generators.toUpperFirstChar(propertyName), fieldLength, + generateArrayFieldNotPresentCondition(propertyToken.version(), indent), + offset, typeSize)); + } + else + { + //Properties for multi item assignment + sb.append(String.format("\n" + + INDENT + "def getMulti%2$s(self) -> Tuple['%1$s']:\n" + + "%4$s" + + INDENT + " return self." + structParserMulti + ".unpack_from(self._buffer, self._offset + %5$d)\n", + typeName, Generators.toUpperFirstChar(propertyName), fieldLength, + generateArrayFieldNotPresentCondition(propertyToken.version(), indent), + offset, typeSize)); + } + + + return sb; + } + + private static void generateArrayLengthMethod( + final String propertyName, final String indent, final int fieldLength, final StringBuilder sb) + { + sb.append(String.format("\n" + + indent + " def %sLength(self) -> int:\n" + + indent + " return %d\n" + + indent + " \n\n", + formatPropertyName(propertyName), + fieldLength)); + } + + + private CharSequence generatePrimitiveArrayPropertyEncode( + final String containingClassName, final String propertyName, final Token token, final String indent) + { + final Encoding encoding = token.encoding(); + final PrimitiveType primitiveType = encoding.primitiveType(); + final String javaTypeName = pythonTypeName(primitiveType); + final String typeName = pythonTypeName(encoding.primitiveType()); + final String byteOrderStr = byteOrderString(encoding); + final int offset = token.offset(); + final int arrayLength = token.arrayLength(); + final int typeSize = sizeOfPrimitive(encoding); + final String typePrefix = toUpperFirstChar(encoding.primitiveType().primitiveName()); + + final StringBuilder sb = new StringBuilder(); + final String className = formatClassName(containingClassName); + final String structParserMulti = String.format("A_%1$S_%2$S_%3$S", Generators.toUpperFirstChar(propertyName), + typePrefix, byteOrderStr); + + sb.append(String.format("\n" + + INDENT + structParserMulti + " = Struct('%1$s%2$d%3$s') \n", + pythonEndianCode(encoding.byteOrder()), token.arrayLength(), + pythonTypeCode(encoding.primitiveType()))); + + generateArrayLengthMethod(propertyName, indent, arrayLength, sb); + + sb.append(String.format( + indent + " def %s(self, index: int, value: '%s') -> '%s':\n" + + indent + " if index < 0 or index >= %d:\n" + + indent + " raise IndexError(\"index out of range: index=\" + str(index))\n" + + indent + " \n" + + indent + " pos: int = self._offset + %d + (index * %d)\n" + + indent + " %s\n\n" + + indent + " return self\n" + + indent + " \n", + propertyName, + javaTypeName, + className, + arrayLength, + offset, + typeSize, + generatePut(primitiveType, "pos", "value", byteOrderStr))); + + sb.append(String.format("\n" + + INDENT + "def set_%1$s(self, value: %2$s) -> '%4$s':\n" + + INDENT + " self." + structParserMulti + ".pack_into(self._buffer, self._offset + %3$d, value)\n" + + INDENT + " return self\n", + propertyName, typeName, offset, containingClassName)); + + return sb; + } + + private void generateCharArrayEncodeMethods( + final String containingClassName, + final String propertyName, + final String indent, + final Encoding encoding, + final int offset, + final int fieldLength, + final StringBuilder sb) + { + generateCharacterEncodingMethod(sb, propertyName, encoding.characterEncoding(), indent); + + sb.append(String.format("\n" + + indent + " public %s put%s(final byte[] src, final int srcOffset)\n" + + indent + " {\n" + + indent + " FIX: final int length = %d;\n" + + indent + " if (srcOffset < 0 || srcOffset > (src.length - length))\n" + + indent + " {\n" + + indent + " throw new IndexOutOfBoundsException(" + + "\"Copy will go out of range: offset=\" + srcOffset);\n" + + indent + " }\n\n" + + indent + " buffer.putBytes(this.offset + %d, src, srcOffset, length);\n\n" + + indent + " return this;\n" + + indent + " }\n", + formatClassName(containingClassName), + Generators.toUpperFirstChar(propertyName), + fieldLength, + offset)); + + if (encoding.characterEncoding().contains("ASCII")) + { + sb.append(String.format("\n" + + indent + " public %1$s %2$s(final String src)\n" + + indent + " {\n" + + indent + " FIX: final int length = %3$d;\n" + + indent + " final int srcLength = null == src ? 0 : src.length();\n" + + indent + " if (srcLength > length)\n" + + indent + " {\n" + + indent + " throw new IndexOutOfBoundsException(" + + "\"String too large for copy: byte length=\" + srcLength);\n" + + indent + " }\n\n" + + indent + " buffer.putStringWithoutLengthAscii(this.offset + %4$d, src);\n\n" + + indent + " for (int start = srcLength; start < length; ++start)\n" + + indent + " {\n" + + indent + " buffer.putByte(this.offset + %4$d + start, (byte)0);\n" + + indent + " }\n\n" + + indent + " return this;\n" + + indent + " }\n", + formatClassName(containingClassName), + propertyName, + fieldLength, + offset)); + sb.append(String.format("\n" + + indent + " public %1$s %2$s(final CharSequence src)\n" + + indent + " {\n" + + indent + " final int length = %3$d;\n" + + indent + " final int srcLength = null == src ? 0 : src.length();\n" + + indent + " if (srcLength > length)\n" + + indent + " {\n" + + indent + " throw new IndexOutOfBoundsException(" + + "\"CharSequence too large for copy: byte length=\" + srcLength);\n" + + indent + " }\n\n" + + indent + " for (int i = 0; i < srcLength; ++i)\n" + + indent + " {\n" + + indent + " final char charValue = src.charAt(i);\n" + + indent + " final byte byteValue = charValue > 127 ? (byte)'?' : (byte)charValue;\n" + + indent + " buffer.putByte(this.offset + %4$d + i, byteValue);\n" + + indent + " }\n\n" + + indent + " for (int i = srcLength; i < length; ++i)\n" + + indent + " {\n" + + indent + " buffer.putByte(this.offset + %4$d + i, (byte)0);\n" + + indent + " }\n\n" + + indent + " return this;\n" + + indent + " }\n", + formatClassName(containingClassName), + propertyName, + fieldLength, + offset)); + } + else + { + sb.append(String.format("\n" + + indent + " public %s %s(final String src)\n" + + indent + " {\n" + + indent + " final int length = %d;\n" + + indent + " final byte[] bytes = null == src ? new byte[0] : src.getBytes(%s);\n" + + indent + " if (bytes.length > length)\n" + + indent + " {\n" + + indent + " throw new IndexOutOfBoundsException(" + + "\"String too large for copy: byte length=\" + bytes.length);\n" + + indent + " }\n\n" + + indent + " buffer.putBytes(this.offset + %d, bytes, 0, bytes.length);\n\n" + + indent + " for (int start = bytes.length; start < length; ++start)\n" + + indent + " {\n" + + indent + " buffer.putByte(this.offset + %d + start, (byte)0);\n" + + indent + " }\n\n" + + indent + " return this;\n" + + indent + " }\n", + formatClassName(containingClassName), + propertyName, + fieldLength, + encoding.characterEncoding(), + offset, + offset)); + } + } + + private static int sizeOfPrimitive(final Encoding encoding) + { + return encoding.primitiveType().size(); + } + + private static void generateCharacterEncodingMethod( + final StringBuilder sb, final String propertyName, final String characterEncoding, final String indent) + { + if (null != characterEncoding) + { + sb.append(String.format("\n" + + indent + " @staticmethod\n" + + indent + " def %sCharacterEncoding() -> str:\n" + + indent + " return \"%s\"\n" + + indent + " \n", + formatPropertyName(propertyName), + characterEncoding)); + } + } + + private CharSequence generateConstPropertyMethods( + final String propertyName, final Token token, final String indent) + { + final String formattedPropertyName = formatPropertyName(propertyName); + final Encoding encoding = token.encoding(); + if (encoding.primitiveType() != PrimitiveType.CHAR) + { + return String.format("\n" + + indent + " @property\n" + + indent + " def %s(self) -> '%s':\n" + + indent + " return %s\n" + + indent + " \n", + formattedPropertyName, + pythonTypeName(encoding.primitiveType()), + generateLiteral(encoding.primitiveType(), encoding.constValue().toString())); + } + + final StringBuilder sb = new StringBuilder(); + + final String javaTypeName = pythonTypeName(encoding.primitiveType()); + final byte[] constBytes = encoding.constValue().byteArrayValue(encoding.primitiveType()); + final CharSequence values = generateByteLiteralList( + encoding.constValue().byteArrayValue(encoding.primitiveType())); + + sb.append(String.format( + "\n" + + indent + " %s_VALUE: bytes = bytes([%s]) \n", + propertyName.toUpperCase(), + values)); + + generateArrayLengthMethod(formattedPropertyName, indent, constBytes.length, sb); + + sb.append(String.format( + indent + " def %s(self, index: int) -> int:\n" + + indent + " return self.%s_VALUE[index]\n" + + indent + " \n\n", + formattedPropertyName, + propertyName.toUpperCase())); + + sb.append(String.format( + indent + " def get%1$s(self, offset: int, length: int) -> memoryview:\n" + + indent + " last = min(length, %2$d)\n" + + indent + " offset = min(abs(offset), %3$d)\n" + + indent + " return memoryview(self.%4$S_VALUE)[offset:last]\n", + Generators.toUpperFirstChar(propertyName), + constBytes.length, + constBytes.length - 1, + propertyName)); + + + if (constBytes.length > 1) + { + sb.append(String.format("\n" + + indent + " @staticmethod\n" + + indent + " def get%sAll() -> str:\n" + + indent + " \n" + + indent + " return \"%s\"\n" + + indent + " \n\n", + toUpperFirstChar(formattedPropertyName), + encoding.constValue())); + } + else + { + sb.append(String.format("\n" + + indent + " @staticmethod\n" + + indent + " def %s() -> int:\n" + + indent + " \n" + + indent + " return %s\n" + + indent + " \n\n", + formattedPropertyName, + encoding.constValue())); + } + + return sb; + } + + private static CharSequence generateByteLiteralList(final byte[] bytes) + { + final StringBuilder values = new StringBuilder(); + for (final byte b : bytes) + { + values.append(b).append(", "); + } + + if (values.length() > 0) + { + values.setLength(values.length() - 2); + } + + return values; + } + + private CharSequence generateFixedFlyweightCode( + final String className, final int size, final String bufferImplementation) + { + final String schemaIdType = pythonTypeName(ir.headerStructure().schemaIdType()); + final String schemaIdAccessorType = shouldGenerateInterfaces ? "int" : schemaIdType; + final String schemaVersionType = pythonTypeName(ir.headerStructure().schemaVersionType()); + final String schemaVersionAccessorType = shouldGenerateInterfaces ? "int" : schemaVersionType; + + return String.format( + " SCHEMA_ID: %5$s = %6$s\n" + + " SCHEMA_VERSION: %7$s = %8$s\n" + + " ENCODED_LENGTH: int = %2$d\n" + + " _offset: int = 0\n" + + " _buffer: %3$s = None\n\n" + + " def wrap(self, buffer: %3$s, offset: int) -> '%1$s':\n" + + " if buffer != self._buffer:\n" + + " self._buffer = buffer\n" + + " \n" + + " self._offset = offset\n\n" + + " return self\n" + + " \n\n" + + " @property\n" + + " def buffer(self) -> '%3$s':\n" + + " \n" + + " return self._buffer\n" + + " \n\n" + + " @property\n" + + " def offset(self) -> int:\n" + + " return self._offset\n" + + " \n\n" + + " @property\n" + + " def encodedLength(self) ->int:\n" + + " return self.ENCODED_LENGTH\n" + + " \n\n" + + " @property\n" + + " def sbeSchemaId(self) -> '%9$s':\n" + + " return self.SCHEMA_ID\n" + + " \n\n" + + " def sbeSchemaVersion(self) -> '%10$s':\n" + + " return self.SCHEMA_VERSION\n" + + " \n", + className, + size, + bufferImplementation, + ir.byteOrder(), + schemaIdType, + generateLiteral(ir.headerStructure().schemaIdType(), Integer.toString(ir.id())), + schemaVersionType, + generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), + schemaIdAccessorType, + schemaVersionAccessorType); + + + } + + private CharSequence generateDecoderFlyweightCode(final String className, final Token token) + { + final String wrapMethod = String.format( + " def wrap(self, buffer: %2$s, offset: int, actingBlockLength: int, actingVersion: int) -> '%1$s':\n" + + " if buffer != self._buffer:\n" + + " self._buffer = buffer\n" + + " \n" + + " self._offset = offset\n" + + " self._actingBlockLength = actingBlockLength\n" + + " self._actingVersion = actingVersion\n" + + " self.set_limit(offset + actingBlockLength)\n\n" + + " return self\n" + + " \n\n", + className, + readOnlyBuffer); + + return generateFlyweightCode(CodecType.DECODER, className, token, wrapMethod, readOnlyBuffer); + } + + private CharSequence generateFlyweightCode( + final CodecType codecType, + final String className, + final Token token, + final String wrapMethod, + final String bufferImplementation) + { + final HeaderStructure headerStructure = ir.headerStructure(); + final String blockLengthType = pythonTypeName(headerStructure.blockLengthType()); + final String blockLengthAccessorType = shouldGenerateInterfaces ? "int" : blockLengthType; + final String templateIdType = pythonTypeName(headerStructure.templateIdType()); + final String templateIdAccessorType = shouldGenerateInterfaces ? "int" : templateIdType; + final String schemaIdType = pythonTypeName(headerStructure.schemaIdType()); + final String schemaIdAccessorType = shouldGenerateInterfaces ? "int" : schemaIdType; + final String schemaVersionType = pythonTypeName(headerStructure.schemaVersionType()); + final String schemaVersionAccessorType = shouldGenerateInterfaces ? "int" : schemaVersionType; + final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); + final String actingFields = codecType == CodecType.ENCODER ? + "" : + " self._actingBlockLength: int = None\n" + + " self._actingVersion: int = None\n"; + + return String.format( + " BLOCK_LENGTH: %1$s = %2$s\n" + + " TEMPLATE_ID: %3$s = %4$s\n" + + " SCHEMA_ID: %5$s = %6$s\n" + + " SCHEMA_VERSION: %7$s = %8$s\n" + + " def __init__(self):\n" + + " self._parentMessage: '%9$s' = self\n" + + " self._buffer: %11$s = None\n" + + " self._offset: int = None\n" + + " self._limit: int = None\n" + + "%13$s" + + "\n" + + " @property\n" + + " def sbeBlockLength(self) -> %15$s:\n" + + " return self.BLOCK_LENGTH\n" + + " \n\n" + + " @property\n" + + " def sbeTemplateId(self) -> %16$s:\n" + + " return self.TEMPLATE_ID\n" + + " \n\n" + + " @property\n" + + " def sbeSchemaId(self) -> %17$s:\n" + + " return self.SCHEMA_ID\n" + + " \n\n" + + " @property\n" + + " def sbeSchemaVersion(self) -> %18$s:\n" + + " return self.SCHEMA_VERSION\n" + + " \n\n" + + " @property\n" + + " def sbeSemanticType(self) -> str:\n" + + " return \"%10$s\"\n" + + " \n\n" + + " @property\n" + + " def buffer(self) -> %11$s:\n" + + " return self._buffer\n" + + " \n\n" + + " @property\n" + + " def offset(self) -> int:\n" + + " return self._offset\n" + + " \n\n" + + "%12$s" + + " @property\n" + + " def encodedLength(self) -> int:\n" + + " return self._limit - self._offset\n" + + " \n\n" + + " @property\n" + + " def limit(self) -> int:\n" + + " return self._limit\n" + + " \n\n" + + " def set_limit(self, limit: int):\n" + + " self._limit = limit\n" + + " \n", + blockLengthType, + generateLiteral(headerStructure.blockLengthType(), Integer.toString(token.encodedLength())), + templateIdType, + generateLiteral(headerStructure.templateIdType(), Integer.toString(token.id())), + schemaIdType, + generateLiteral(headerStructure.schemaIdType(), Integer.toString(ir.id())), + schemaVersionType, + generateLiteral(headerStructure.schemaVersionType(), Integer.toString(ir.version())), + className, + semanticType, + bufferImplementation, + wrapMethod, + actingFields, + ir.byteOrder(), + blockLengthAccessorType, + templateIdAccessorType, + schemaIdAccessorType, + schemaVersionAccessorType); + } + + private CharSequence generateEncoderFlyweightCode(final String className, final Token token) + { + final String wrapMethod = String.format( + " def wrap(self, buffer: %2$s , offset: int) -> '%1$s':\n" + + " if buffer != self._buffer:\n" + + " self._buffer = buffer\n" + + " \n" + + " self._offset = offset\n" + + " self.set_limit(offset + self.BLOCK_LENGTH)\n\n" + + " return self\n" + + " \n\n", + className, + mutableBuffer); + + final StringBuilder builder = new StringBuilder( + " def wrapAndApplyHeader(self, buffer: %2$s, offset: int, headerEncoder: '%3$s') -> '%1$s':\n" + + " headerEncoder.wrap(buffer, offset)"); + + for (final Token headerToken : ir.headerStructure().tokens()) + { + if (!headerToken.isConstantEncoding()) + { + switch (headerToken.name()) + { + case "blockLength": + builder.append(".blockLength(self.BLOCK_LENGTH)"); + break; + + case "templateId": + builder.append(".templateId(self.TEMPLATE_ID)"); + break; + + case "schemaId": + builder.append(".schemaId(self.SCHEMA_ID)"); + break; + + case "version": + builder.append(".version(self.SCHEMA_VERSION)"); + break; + } + } + } + + builder.append("\n\n return self.wrap(buffer, offset + %3$s.ENCODED_LENGTH)\n\n"); + + final String wrapAndApplyMethod = String.format( + builder.toString(), + className, + mutableBuffer, + formatClassName(ir.headerStructure().tokens().get(0).applicableTypeName() + "Encoder")); + + return generateFlyweightCode( + CodecType.ENCODER, className, token, wrapMethod + wrapAndApplyMethod, mutableBuffer); + } + + private CharSequence generateEncoderFields( + final String containingClassName, final List tokens, final String indent) + { + final StringBuilder sb = new StringBuilder(); + + Generators.forEachField( + tokens, + (fieldToken, typeToken) -> + { + final String propertyName = formatPropertyName(fieldToken.name()); + final String typeName = formatClassName(encoderName(typeToken.name())); + + generateFieldIdMethod(sb, fieldToken, indent); + generateFieldSinceVersionMethod(sb, fieldToken, indent); + generateEncodingOffsetMethod(sb, propertyName, fieldToken.offset(), indent); + generateEncodingLengthMethod(sb, propertyName, typeToken.encodedLength(), indent); + generateFieldMetaAttributeMethod(sb, fieldToken, indent); + + switch (typeToken.signal()) + { + case ENCODING: + sb.append(generatePrimitiveEncoder(containingClassName, propertyName, typeToken, indent)); + break; + + case BEGIN_ENUM: + sb.append(generateEnumEncoder( + containingClassName, fieldToken, propertyName, typeToken, indent)); + break; + + case BEGIN_SET: + sb.append(generateBitSetProperty( + false, CodecType.ENCODER, propertyName, fieldToken, typeToken, indent, typeName)); + break; + + case BEGIN_COMPOSITE: + sb.append(generateCompositeProperty( + false, CodecType.ENCODER, propertyName, fieldToken, typeToken, indent, typeName)); + break; + } + }); + + return sb; + } + + private CharSequence generateDecoderFields(final List tokens, final String indent) + { + final StringBuilder sb = new StringBuilder(); + + Generators.forEachField( + tokens, + (fieldToken, typeToken) -> + { + final String propertyName = formatPropertyName(fieldToken.name()); + final String typeName = decoderName(formatClassName(typeToken.name())); + + generateFieldIdMethod(sb, fieldToken, indent); + generateFieldSinceVersionMethod(sb, fieldToken, indent); + generateEncodingOffsetMethod(sb, propertyName, fieldToken.offset(), indent); + generateEncodingLengthMethod(sb, propertyName, typeToken.encodedLength(), indent); + generateFieldMetaAttributeMethod(sb, fieldToken, indent); + + switch (typeToken.signal()) + { + case ENCODING: + sb.append(generatePrimitiveDecoder(false, propertyName, fieldToken, typeToken, indent)); + break; + + case BEGIN_ENUM: + sb.append(generateEnumDecoder(false, fieldToken, propertyName, typeToken, indent)); + break; + + case BEGIN_SET: + sb.append(generateBitSetProperty( + false, CodecType.DECODER, propertyName, fieldToken, typeToken, indent, typeName)); + break; + + case BEGIN_COMPOSITE: + sb.append(generateCompositeProperty( + false, CodecType.DECODER, propertyName, fieldToken, typeToken, indent, typeName)); + break; + } + }); + + return sb; + } + + private static void generateFieldIdMethod(final StringBuilder sb, final Token token, final String indent) + { + sb.append(String.format( + "\n" + + indent + " @staticmethod\n" + + indent + " def %sId() -> int:\n" + + indent + " return %d\n" + + indent + " \n", + formatPropertyName(token.name()), + token.id())); + } + + private static void generateEncodingOffsetMethod( + final StringBuilder sb, final String name, final int offset, final String indent) + { + sb.append(String.format( + "\n" + + indent + " @staticmethod\n" + + indent + " def %sEncodingOffset() -> int:\n" + + indent + " return %d\n" + + indent + " \n", + formatPropertyName(name), + offset)); + } + + private static void generateEncodingLengthMethod( + final StringBuilder sb, final String name, final int length, final String indent) + { + sb.append(String.format( + "\n" + + indent + " @staticmethod\n" + + indent + " def %sEncodingLength() -> int:\n" + + indent + " return %d\n" + + indent + " \n", + formatPropertyName(name), + length)); + } + + private static void generateFieldSinceVersionMethod(final StringBuilder sb, final Token token, final String indent) + { + sb.append(String.format( + "\n" + + indent + " @staticmethod\n" + + indent + " def %sSinceVersion() -> int:\n" + + indent + " return %d\n" + + indent + " \n", + formatPropertyName(token.name()), + token.version())); + } + + private static void generateFieldMetaAttributeMethod(final StringBuilder sb, final Token token, final String indent) + { + final Encoding encoding = token.encoding(); + final String epoch = encoding.epoch() == null ? "" : encoding.epoch(); + final String timeUnit = encoding.timeUnit() == null ? "" : encoding.timeUnit(); + final String semanticType = encoding.semanticType() == null ? "" : encoding.semanticType(); + + sb.append(String.format( + "\n" + + indent + " @staticmethod\n" + + indent + " def %sMetaAttribute(metaAttribute: MetaAttribute) -> str:\n" + + indent + " if metaAttribute == MetaAttribute.Epoch: return \"%s\"\n" + + indent + " if metaAttribute == MetaAttribute.TimeUnit: return \"%s\"\n" + + indent + " if metaAttribute == MetaAttribute.SemanticType: return \"%s\"\n" + + indent + " if metaAttribute == MetaAttribute.Presence: return \"%s\"\n" + + indent + " return \"\"\n" + + indent + " \n", + formatPropertyName(token.name()), + epoch, + timeUnit, + semanticType, + encoding.presence().toString().toLowerCase())); + } + + private CharSequence generateEnumDecoder( + final boolean inComposite, + final Token fieldToken, + final String propertyName, + final Token typeToken, + final String indent) + { + final String enumName = formatClassName(typeToken.applicableTypeName()); + final Encoding encoding = typeToken.encoding(); + + if (fieldToken.isConstantEncoding()) + { + return String.format( + "\n" + + indent + " def %s(self) -> %s:\n" + + indent + " return %s\n" + + indent + " \n\n", + propertyName, + enumName, + fieldToken.encoding().constValue().toString()); + } + else + { + final String decoderProp; + if (encoding.primitiveType().equals(PrimitiveType.CHAR)) + { + decoderProp = "ord(" + generateGet(encoding.primitiveType(), "self._offset + " + typeToken.offset(), + byteOrderString(encoding)) + ")"; + } + else + { + decoderProp = generateGet(encoding.primitiveType(), "self._offset + " + typeToken.offset(), + byteOrderString(encoding)); + } + return String.format( + "\n" + + indent + " def %s(self) -> %s:\n" + + "%s" + + indent + " return %s.get(%s)\n" + + indent + " \n\n", + propertyName, + enumName, + generatePropertyNotPresentCondition(inComposite, CodecType.DECODER, fieldToken, enumName, indent), + enumName, + decoderProp); + } + } + + private CharSequence generateEnumEncoder( + final String containingClassName, + final Token fieldToken, + final String propertyName, + final Token typeToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return ""; + } + + final String enumName = formatClassName(typeToken.applicableTypeName()); + final Encoding encoding = typeToken.encoding(); + final int offset = typeToken.offset(); + + return String.format("\n" + + indent + " def %1$s(self, value: %2$s) -> '%3$s':\n" + + indent + " %4$s\n" + + indent + " return self\n" + + indent + " \n", + propertyName, + enumName, + formatClassName(containingClassName), + generatePut(encoding.primitiveType(), "self._offset + " + offset, "value.value", + byteOrderString(encoding))); + } + + private CharSequence generateBitSetProperty( + final boolean inComposite, + final CodecType codecType, + final String propertyName, + final Token propertyToken, + final Token bitsetToken, + final String indent, + final String bitSetName) + { + final StringBuilder sb = new StringBuilder(); + + sb.append(String.format("\n" + + indent + " _%s: %s = %s()\n", + propertyName, + bitSetName, + bitSetName)); + + sb.append(String.format("\n" + + indent + " def %2$s(self) -> '%1$s':\n" + + "%3$s" + + indent + " self._%4$s.wrap(self._buffer, self._offset + %5$d)\n" + + indent + " return self._%6$s\n" + + indent + " \n", + bitSetName, + propertyName, + generatePropertyNotPresentCondition(inComposite, codecType, propertyToken, null, indent), + propertyName, + bitsetToken.offset(), + propertyName)); + + return sb; + } + + private CharSequence generateCompositeProperty( + final boolean inComposite, + final CodecType codecType, + final String propertyName, + final Token propertyToken, + final Token compositeToken, + final String indent, + final String compositeName) + { + final StringBuilder sb = new StringBuilder(); + + sb.append(String.format("\n" + + indent + " _%2$s: %1$s = %3$s()\n", + compositeName, + propertyName, + compositeName)); + + sb.append(String.format("\n" + + indent + " def %2$s(self) -> '%1$s':\n" + + "%3$s" + + indent + " self._%4$s.wrap(self._buffer, self._offset + %5$d)\n" + + indent + " return self._%6$s\n" + + indent + " \n", + compositeName, + propertyName, + generatePropertyNotPresentCondition(inComposite, codecType, propertyToken, null, indent), + propertyName, + compositeToken.offset(), + propertyName)); + + return sb; + } + + private String generateGet(final PrimitiveType type, final String index, final String byteOrder) + { + switch (type) + { + case CHAR: + case INT8: + case UINT8: + case INT16: + case UINT16: + case INT32: + case UINT32: + case FLOAT: + case INT64: + case UINT64: + case DOUBLE: + return byteOrder.toUpperCase() + "_" + type.name().toUpperCase() + ".unpack_from(self._buffer, " + + index + ")[0]"; + } + + throw new IllegalArgumentException("primitive type not supported: " + type); + } + + private String generatePut( + final PrimitiveType type, final String index, final String value, final String byteOrder) + { + switch (type) + { + case CHAR: + return byteOrder.toUpperCase() + "_" + type.name().toUpperCase() + ".pack_into(self._buffer, " + index + + ", bytes([" + value + "]))"; + case INT8: + case UINT8: + case INT16: + case UINT16: + case INT32: + case UINT32: + case FLOAT: + case INT64: + case UINT64: + case DOUBLE: + return byteOrder.toUpperCase() + "_" + type.name().toUpperCase() + ".pack_into(self._buffer, " + index + + ", " + value + ")"; + + } + + throw new IllegalArgumentException("primitive type not supported: " + type); + } + + private String generateChoiceIsEmpty(final PrimitiveType type, final ByteOrder byteOrder) + { + return "\n" + + " @property\n" + + " def isEmpty(self) -> bool:\n" + + " return " + generateChoiceIsEmptyInner(type, byteOrder) + "\n" + + " \n"; + } + + private String generateChoiceIsEmptyInner(final PrimitiveType type, final ByteOrder byteOrder) + { + switch (type) + { + case UINT8: + case UINT16: + case UINT32: + case UINT64: + return "0 == " + byteOrder.toString() + "_" + type.primitiveName().toUpperCase() + + ".unpack_from(self._buffer, self._offset)[0]"; + } + + throw new IllegalArgumentException("primitive type not supported: " + type); + } + + private String generateChoiceGet(final PrimitiveType type, final String bitIndex, final String byteOrder) + { + switch (type) + { + case UINT8: + case UINT16: + case UINT32: + case UINT64: + return "0 != (" + byteOrder.toUpperCase() + "_" + type.primitiveName().toUpperCase() + + ".unpack_from(self._buffer, self._offset)[0] & (1 << " + bitIndex + "))"; + } + + throw new IllegalArgumentException("primitive type not supported: " + type); + } + + private String generateStaticChoiceGet(final PrimitiveType type, final String bitIndex) + { + switch (type) + { + case UINT8: + case UINT16: + case UINT32: + case UINT64: + return "0 != (value & (1 << " + bitIndex + "))"; + } + + throw new IllegalArgumentException("primitive type not supported: " + type); + } + + private String generateChoicePut(final PrimitiveType type, final String bitIdx, final String byteOrder) + { + final String byteOrderUpper = byteOrder.toUpperCase(); + switch (type) + { + case UINT8: + case UINT16: + case UINT32: + case UINT64: + return " bits = " + byteOrderUpper + "_" + type.primitiveName().toUpperCase() + + ".unpack_from(self._buffer, self._offset)[0]\n" + + " bits = (bits | (1 << " + bitIdx + ")) if value else (bits & ~(1 << " + bitIdx + "))\n" + + " " + byteOrderUpper + "_" + type.primitiveName().toUpperCase() + + ".pack_into(self._buffer, self._offset, bits)\n" + + " return self\n"; + + } + + throw new IllegalArgumentException("primitive type not supported: " + type); + } + + private String generateStaticChoicePut(final PrimitiveType type, final String bitIdx) + { + switch (type) + { + case UINT8: + case UINT16: + case UINT32: + case UINT64: + return INDENT + INDENT + "return (bits | (1 << " + bitIdx + ")) " + + "if value else (bits & ~(1 << " + bitIdx + "))\n"; + } + + throw new IllegalArgumentException("primitive type not supported: " + type); + } + + private CharSequence generateCompositeDecoderDisplay(final List tokens, final String baseIndent) + { + final String indent = baseIndent + INDENT; + final StringBuilder sb = new StringBuilder(); + + appendToString(sb, indent); + sb.append('\n'); + append(sb, indent, "def appendTo(self, builder: str) -> str:"); + Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + + int lengthBeforeLastGeneratedSeparator = -1; + + for (int i = 1, end = tokens.size() - 1; i < end; ) + { + final Token encodingToken = tokens.get(i); + final String propertyName = formatPropertyName(encodingToken.name()); + lengthBeforeLastGeneratedSeparator = writeTokenDisplay(propertyName, encodingToken, sb, indent + INDENT); + i += encodingToken.componentTokenCount(); + } + + if (-1 != lengthBeforeLastGeneratedSeparator) + { + sb.setLength(lengthBeforeLastGeneratedSeparator); + } + + Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + append(sb, indent, " return builder"); + return sb.toString(); + } + + private CharSequence generateChoiceDisplay(final List tokens) + { + final String indent = INDENT; + final StringBuilder sb = new StringBuilder(); + + appendToString(sb, indent); + sb.append('\n'); + append(sb, indent, "def appendTo(self, builder: str) -> str:"); + Separators.BEGIN_SET.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + append(sb, indent, " atLeastOne: bool = False"); + + tokens + .stream() + .filter((token) -> token.signal() == Signal.CHOICE) + .forEach((token) -> + { + final String choiceName = formatPropertyName(token.name()); + append(sb, indent, " if self." + choiceName + "():"); + append(sb, indent, " if atLeastOne:"); + Separators.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT + INDENT, "builder"); + append(sb, indent, " builder += str(\"" + choiceName + "\")"); + append(sb, indent, " atLeastOne = True"); + }); + + Separators.END_SET.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + sb.append('\n'); + append(sb, indent, " return builder"); + + return sb.toString(); + } + + private CharSequence generateDecoderDisplay( + final String name, + final List tokens, + final List groups, + final List varData, + final String baseIndent) + { + final String indent = baseIndent + INDENT; + final StringBuilder sb = new StringBuilder(); + + sb.append('\n'); + appendToString(sb, indent); + sb.append('\n'); + append(sb, indent, "def appendTo(self, builder: str) -> str:"); + append(sb, indent, " originalLimit: int = self.limit"); + append(sb, indent, " self.set_limit(self.offset + self._actingBlockLength)"); + append(sb, indent, " builder += str(\"[" + name + "](sbeTemplateId=\")"); + append(sb, indent, " builder += str(self.TEMPLATE_ID)"); + append(sb, indent, " builder += (\"|sbeSchemaId=\")"); + append(sb, indent, " builder += str(self.SCHEMA_ID)"); + append(sb, indent, " builder += (\"|sbeSchemaVersion=\")"); + append(sb, indent, " if self._parentMessage._actingVersion != self.SCHEMA_VERSION:"); + append(sb, indent, " builder += str(self._parentMessage._actingVersion)"); + append(sb, indent, " builder += str('/')"); + append(sb, indent, " builder += str(self.SCHEMA_VERSION)"); + append(sb, indent, " builder += (\"|sbeBlockLength=\")"); + append(sb, indent, " if self._actingBlockLength != self.BLOCK_LENGTH:"); + append(sb, indent, " builder += str(self._actingBlockLength)"); + append(sb, indent, " builder += str('/')"); + append(sb, indent, " builder += str(self.BLOCK_LENGTH)"); + append(sb, indent, " builder += (\"):\")"); + appendDecoderDisplay(sb, tokens, groups, varData, indent + INDENT); + sb.append('\n'); + append(sb, indent, " self.set_limit(originalLimit)"); + sb.append('\n'); + append(sb, indent, " return builder"); + sb.append('\n'); + return sb.toString(); + } + + private void appendGroupInstanceDecoderDisplay( + final StringBuilder sb, + final List fields, + final List groups, + final List varData, + final String baseIndent) + { + final String indent = baseIndent + INDENT; + + sb.append('\n'); + appendToString(sb, indent); + sb.append('\n'); + append(sb, indent, "def appendTo(self, builder: str) -> str:"); + Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + appendDecoderDisplay(sb, fields, groups, varData, indent + INDENT); + Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + append(sb, indent, " return builder"); + append(sb, "", "\n"); + } + + private void appendDecoderDisplay( + final StringBuilder sb, + final List fields, + final List groups, + final List varData, + final String indent) + { + int lengthBeforeLastGeneratedSeparator = -1; + + for (int i = 0, size = fields.size(); i < size; ) + { + final Token fieldToken = fields.get(i); + if (fieldToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = fields.get(i + 1); + + final String fieldName = formatPropertyName(fieldToken.name()); + append(sb, indent, "#" + fieldToken); + lengthBeforeLastGeneratedSeparator = writeTokenDisplay(fieldName, encodingToken, sb, indent); + + i += fieldToken.componentTokenCount(); + } + else + { + ++i; + } + } + + for (int i = 0, size = groups.size(); i < size; i++) + { + final Token groupToken = groups.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + append(sb, indent, "#" + groupToken); + + final String groupName = formatPropertyName(groupToken.name()); + + append( + sb, indent, "builder += str(\"" + groupName + Separators.KEY_VALUE + + Separators.BEGIN_GROUP + "\")"); + append(sb, indent, groupName + " = self." + groupName + "()"); + append(sb, indent, "if " + groupName + ".count() > 0:"); + append(sb, indent, " while " + groupName + ".hasNext():"); + append(sb, indent, " " + groupName + ".next().appendTo(builder)"); + Separators.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT, "builder"); + Separators.END_GROUP.appendToGeneratedBuilder(sb, indent, "builder"); + + lengthBeforeLastGeneratedSeparator = sb.length(); + Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + + i = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); + } + + for (int i = 0, size = varData.size(); i < size; ) + { + final Token varDataToken = varData.get(i); + if (varDataToken.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); + } + + append(sb, indent, "#" + varDataToken); + + final String characterEncoding = varData.get(i + 3).encoding().characterEncoding(); + final String varDataName = formatPropertyName(varDataToken.name()); + append(sb, indent, "builder += str(\"" + varDataName + Separators.KEY_VALUE + "\")"); + if (null == characterEncoding) + { + append(sb, indent, "builder += str(self." + varDataName + "Length() + \" bytes of raw data\")"); + append(sb, indent, + "self._parentMessage.set_limit(self._parentMessage.limit + " + varDataName + "HeaderLength() + " + + varDataName + "Length())"); + } + else + { + append(sb, indent, "builder += str('\\'' + self." + varDataName + "() + '\\'')"); + } + lengthBeforeLastGeneratedSeparator = sb.length(); + Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + i += varDataToken.componentTokenCount(); + } + + if (-1 != lengthBeforeLastGeneratedSeparator) + { + sb.setLength(lengthBeforeLastGeneratedSeparator); + } + } + + private int writeTokenDisplay( + final String fieldName, + final Token typeToken, + final StringBuilder sb, + final String indent) + { + append(sb, indent, "#" + typeToken); + + if (typeToken.encodedLength() <= 0 || typeToken.isConstantEncoding()) + { + return -1; + } + + append(sb, indent, "builder += str(\"" + fieldName + Separators.KEY_VALUE + "\")"); + + switch (typeToken.signal()) + { + case ENCODING: + if (typeToken.arrayLength() > 1) + { + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + append(sb, indent, "i: int = 0"); + append(sb, indent, + "while i < self." + fieldName + "Length() and self." + fieldName + "(i) > 0:"); + append(sb, indent, " builder += str(self." + fieldName + "(i))"); + append(sb, indent, " i += 1"); + } + else + { + Separators.BEGIN_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); + append(sb, indent, "if self." + fieldName + "Length() > 0:"); + append(sb, indent, " i: int = 0"); + append(sb, indent, " while i < self." + fieldName + "Length():"); + append(sb, indent, " builder += str(self." + fieldName + "(i))"); + append(sb, indent, " i += 1"); + Separators.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT, "builder"); + Separators.END_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); + } + } + else + { + // have to duplicate because of checkstyle :/ + append(sb, indent, "builder += str(self." + fieldName + "())"); + } + break; + + case BEGIN_ENUM: + case BEGIN_SET: + append(sb, indent, "builder += str(self." + fieldName + "())"); + break; + + case BEGIN_COMPOSITE: + append(sb, indent, "self._" + fieldName + ".appendTo(builder)"); + break; + } + + final int lengthBeforeFieldSeparator = sb.length(); + Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + + return lengthBeforeFieldSeparator; + } + + private void appendToString(final StringBuilder sb, final String indent) + { + sb.append('\n'); + append(sb, indent, "def __str__(self) -> str:"); + append(sb, indent, " return self.appendTo(\"\")"); + } + + private String byteOrderString(final Encoding encoding) + { + return encoding.byteOrder().toString(); + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java index 9a37431728..c6ede697ed 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java @@ -22,20 +22,29 @@ public void codeGenerationSchemaTest() throws Exception final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); final StringWriterOutputManager outputManager = new StringWriterOutputManager(); - final PyGenerator generator = new PyGenerator(ir, outputManager); + final PythonGenerator generator = new PythonGenerator(ir, + true, false, true, outputManager); generator.generate(); - assertEquals(13, outputManager.getSources().size()); - assertTrue(outputManager.getSources().containsKey("null.engine")); - assertTrue(outputManager.getSources().containsKey("null.optional_extras")); - assertTrue(outputManager.getSources().containsKey("null.booster")); - assertTrue(outputManager.getSources().containsKey("null.message_header")); + assertEquals(20, outputManager.getSources().size()); + assertTrue(outputManager.getSources().containsKey("null.engine_encoder")); + assertTrue(outputManager.getSources().containsKey("null.engine_decoder")); + assertTrue(outputManager.getSources().containsKey("null.optional_extras_encoder")); + assertTrue(outputManager.getSources().containsKey("null.optional_extras_decoder")); + assertTrue(outputManager.getSources().containsKey("null.booster_encoder")); + assertTrue(outputManager.getSources().containsKey("null.booster_decoder")); + assertTrue(outputManager.getSources().containsKey("null.message_header_encoder")); + assertTrue(outputManager.getSources().containsKey("null.message_header_decoder")); assertTrue(outputManager.getSources().containsKey("null.boolean_type")); assertTrue(outputManager.getSources().containsKey("null.model")); - assertTrue(outputManager.getSources().containsKey("null.var_string_encoding")); + assertTrue(outputManager.getSources().containsKey("null.var_string_encoding_encoder")); + assertTrue(outputManager.getSources().containsKey("null.var_string_encoding_decoder")); assertTrue(outputManager.getSources().containsKey("null.boost_type")); assertTrue(outputManager.getSources().containsKey("null._struct_defs")); - assertTrue(outputManager.getSources().containsKey("null.group_size_encoding")); + assertTrue(outputManager.getSources().containsKey("null.group_size_encoding_decoder")); + assertTrue(outputManager.getSources().containsKey("null.group_size_encoding_encoder")); assertTrue(outputManager.getSources().containsKey("null.meta_attribute")); + assertTrue(outputManager.getSources().containsKey("null.car_encoder")); + assertTrue(outputManager.getSources().containsKey("null.car_decoder")); assertTrue(outputManager.getSources().containsKey("null.__init__")); } } From eb65fddb7782b21cfd8e64b90cdf0c33eadc6547 Mon Sep 17 00:00:00 2001 From: Feras Date: Thu, 8 Aug 2019 17:22:32 -0400 Subject: [PATCH 0154/1594] [Java] Remove old python generator and port missing methods --- .../sbe/generation/python/PyGenerator.java | 1530 ----------------- .../generation/python/PythonGenerator.java | 11 + 2 files changed, 11 insertions(+), 1530 deletions(-) delete mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java deleted file mode 100644 index a91a74a250..0000000000 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyGenerator.java +++ /dev/null @@ -1,1530 +0,0 @@ -/* - * Copyright 2013-2019 Real Logic Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.generation.python; - -import org.agrona.Verify; -import org.agrona.generation.OutputManager; -import uk.co.real_logic.sbe.PrimitiveType; -import uk.co.real_logic.sbe.PrimitiveValue; -import uk.co.real_logic.sbe.generation.CodeGenerator; -import uk.co.real_logic.sbe.generation.Generators; -import uk.co.real_logic.sbe.ir.Encoding; -import uk.co.real_logic.sbe.ir.Ir; -import uk.co.real_logic.sbe.ir.Signal; -import uk.co.real_logic.sbe.ir.Token; - -import java.io.IOException; -import java.io.Writer; -import java.nio.ByteOrder; -import java.util.*; - -import static uk.co.real_logic.sbe.generation.python.PyUtil.*; -import static uk.co.real_logic.sbe.ir.GenerationUtil.*; - -public class PyGenerator implements CodeGenerator -{ - private static final String META_ATTRIBUTE_ENUM = "MetaAttribute"; - private static final String INDENT = " "; - private static final String BASE_INDENT = INDENT; - - private final Ir ir; - private final OutputManager outputManager; - - public PyGenerator(final Ir ir, final OutputManager outputManager) - { - Verify.notNull(ir, "ir"); - Verify.notNull(outputManager, "outputManager"); - - this.ir = ir; - this.outputManager = outputManager; - } - - public void generateMessageHeaderStub(final List modules) throws IOException - { - generateComposite(ir.headerStructure().tokens(), modules); - } - - public void generateTypeStubs(final List modules) throws IOException - { - generateMetaAttributeEnum(); - - for (final List tokens : ir.types()) - { - switch (tokens.get(0).signal()) - { - case BEGIN_ENUM: - generateEnum(tokens, modules); - break; - - case BEGIN_SET: - generateBitSet(tokens, modules); - break; - - case BEGIN_COMPOSITE: - generateComposite(tokens, modules); - break; - } - } - } - - public void generate() throws IOException - { - final List modules = new ArrayList<>(); - generateMessageHeaderStub(modules); - generateTypeStubs(modules); - for (final List tokens : ir.messages()) - { - final Token msgToken = tokens.get(0); - final String className = formatClassName(msgToken.name()); - final String pyModuleName = camToSnake(className); - - modules.add(pyModuleName); - final List messageBody = getMessageBody(tokens); - int offset = 0; - - final List fields = new ArrayList<>(); - offset = collectFields(messageBody, offset, fields); - - final List groups = new ArrayList<>(); - offset = collectGroups(messageBody, offset, groups); - - final List varData = new ArrayList<>(); - collectVarData(messageBody, offset, varData); - - try (Writer out = outputManager.createOutput(pyModuleName)) - { - generateEncoder(out, className, fields, groups, varData, messageBody, msgToken); - } - } - generateStructParsers(); - generatePackageDefinition(modules); - } - - public void generateEncoder(final Writer out, final String className, - final List fields, final List groups, final List varData, - final List msgBody, final Token msgToken) throws IOException - { - out.append(generateFileHeader(ir.applicableNamespace(), msgBody, true)); - out.append(generateClassDeclaration(className)); - out.append(generateMessageFlyweightCode(className, msgToken, BASE_INDENT, fields)); - - out.append(generateFields(fields, BASE_INDENT, className)); - - final StringBuilder sb = new StringBuilder(); - - generateGroups(sb, className, groups, BASE_INDENT); - out.append(sb); - - out.append(generateVarData(varData, BASE_INDENT, className)); - } - - - public void generatePackageDefinition(final List modules) throws IOException - { - try (Writer out = outputManager.createOutput("__init__")) - { - out.append(generateFileHeader(ir.applicableNamespace(), new ArrayList<>(), false)); - for (final String m : modules) - { - out.append("from ." + m + " import *\n"); - } - out.append("from .meta_attribute import *\n"); - } - } - - private void generateGroups( - final StringBuilder sb, - final String parentMessageClassName, - final List tokens, - final String indent) - { - for (int i = 0, size = tokens.size(); i < size; i++) - { - final Token groupToken = tokens.get(i); - if (groupToken.signal() != Signal.BEGIN_GROUP) - { - throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); - } - final String groupName = groupToken.name(); - - generateGroupClassHeader(sb, groupName, parentMessageClassName, tokens, i, indent); - i++; - i += tokens.get(i).componentTokenCount(); - - final List fields = new ArrayList<>(); - i = collectFields(tokens, i, fields); - sb.append(generateFields(fields, indent + INDENT, parentMessageClassName + "." + - formatClassName(groupName) + "Group")); - - final List groups = new ArrayList<>(); - i = collectGroups(tokens, i, groups); - generateGroups(sb, parentMessageClassName + "." + formatClassName(groupName) + - "Group", groups, indent + INDENT); - - final List varData = new ArrayList<>(); - i = collectVarData(tokens, i, varData); - sb.append(generateVarData(varData, indent + INDENT, parentMessageClassName + "." + - formatClassName(groupName) + "Group")); - - sb.append(generateGroupProperty(groupName, groupToken, indent, parentMessageClassName)); - - } - } - - private void generateGroupClassHeader( - final StringBuilder sb, - final String groupName, - final String parentMessageClassName, - final List tokens, - final int index, - final String indent) - { - final String dimensionsClassName = formatClassName(tokens.get(index + 1).name()); - final int dimensionHeaderLength = tokens.get(index + 1).encodedLength(); - final String topLevelParentMessageClassName = parentMessageClassName.split("\\.")[0]; - sb.append(String.format("\n" + - indent + "class %1$sGroup:\n" + - indent + INDENT + "__slots__ = '_dimensions', '_parent_message', '_buffer', '_block_length', " + - "'_acting_version', '_count', '_index', '_offset'\n\n" + - indent + INDENT + "def __init__(self):\n" + - indent + INDENT + INDENT + "self._dimensions: '%2$s' = %2$s()\n" + - indent + INDENT + INDENT + "self._parent_message: '%3$s'\n" + - indent + INDENT + INDENT + "self._buffer: Union[bytes, bytearray, memoryview]\n" + - indent + INDENT + INDENT + "self._block_length: int\n" + - indent + INDENT + INDENT + "self._acting_version: int\n" + - indent + INDENT + INDENT + "self._count: int\n" + - indent + INDENT + INDENT + "self._index: int\n" + - indent + INDENT + INDENT + "self._offset: int\n", - formatClassName(groupName), - dimensionsClassName, - topLevelParentMessageClassName)); - - final int blockLength = tokens.get(index).encodedLength(); - sb.append(String.format("\n" + - indent + INDENT + "SBE_BLOCK_LENGTH: int = %d\n" + - indent + INDENT + "SBE_HEADER_SIZE: int = %d\n", - blockLength, - dimensionHeaderLength)); - - final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); - - sb.append(String.format("\n" + - indent + " def wrap_decode(self, parent_message: '%1$s' , buffer: Union[bytes, bytearray," + - " memoryview" + "], acting_version: int):\n" + - indent + " self._parent_message = parent_message\n" + - indent + " self._buffer = buffer\n" + - indent + " self._dimensions.wrap(buffer, parent_message.limit, parent_message._acting_version)\n" + - indent + " self._block_length = self._dimensions.get_block_length()\n" + - indent + " self._count = self._dimensions.get_num_in_group()\n" + - indent + " self._acting_version = acting_version\n" + - indent + " self._index = -1\n" + - indent + " self._parent_message.set_limit(self._parent_message.limit + self.SBE_HEADER_SIZE)\n" + - indent + " return self\n", - topLevelParentMessageClassName, - formatClassName(groupName))); - - final String typeForBlockLength = pythonTypeName(tokens.get(index + 2).encoding().primitiveType()); - final String typeForNumInGroup = pythonTypeName(numInGroupToken.encoding().primitiveType()); - - sb.append(String.format("\n" + - indent + " def wrap_encode(self, parent_message: '%1$s', buffer: Union[bytes, bytearray, memoryview]," + - " count: int):\n" + - indent + " if count < %2$d or count > %3$d:\n" + - indent + " raise IndexError('Count Outside allowed range: count='+ str(count) +', min=%2$d, " + - "max=%3$d')\n" + - indent + " self._parent_message = parent_message\n" + - indent + " self._buffer = buffer\n" + - indent + " self._dimensions.wrap(buffer, parent_message.limit, parent_message._acting_version)\n" + - indent + " self._dimensions.set_block_length(%4$s(%5$d))\n" + - indent + " self._dimensions.set_num_in_group(%6$s(count))\n" + - indent + " self._index = -1\n" + - indent + " self._count = count\n" + - indent + " self._block_length = %5$d\n" + - indent + " self._acting_version = self._parent_message.SCHEMA_VERSION\n" + - indent + " self._parent_message.set_limit(parent_message.limit + self.SBE_HEADER_SIZE)\n" + - indent + " return self\n", - topLevelParentMessageClassName, - numInGroupToken.encoding().applicableMinValue().longValue(), - numInGroupToken.encoding().applicableMaxValue().longValue(), - typeForBlockLength, - blockLength, - typeForNumInGroup)); - - - sb.append("\n"); - generateGroupEnumerator(sb, groupName, indent + INDENT, parentMessageClassName); - } - - private void generateGroupEnumerator(final StringBuilder sb, final String groupName, final String indent, - final String parentClassName) - { - sb.append(indent + "@property\n" + - indent + "def acting_block_length(self) -> int:\n" + - indent + " return self._block_length\n\n" + - indent + "@property\n" + - indent + "def count(self) -> int:\n" + - indent + " return self._count\n\n" + - indent + "@property\n" + - indent + "def has_next(self) -> bool:\n" + - indent + " return (self._index + 1) < self._count\n"); - - sb.append(String.format("\n" + - indent + "def next(self) -> '%2$s.%1$sGroup':\n" + - indent + " if self._index + 1 >= self._count:\n" + - indent + " raise IndexError()\n" + - indent + " self._offset = self._parent_message.limit\n" + - indent + " self._parent_message.set_limit(self._offset + self._block_length)\n" + - indent + " self._index += 1\n" + - indent + " return self\n", - formatClassName(groupName), parentClassName)); - - sb.append(String.format("\n" + - indent + "def generator(self) -> Generator['%2$s.%1$sGroup', None, None]:\n" + - indent + " while self.has_next:\n" + - indent + " yield self.next()\n", - formatClassName(groupName), parentClassName - )); - } - - private CharSequence generateGroupProperty(final String groupName, final Token token, final String indent, - final String parentMessageClassName) - { - final StringBuilder sb = new StringBuilder(); - - final String className = PyUtil.formatClassName(groupName); - - sb.append(String.format("\n" + - indent + "%S_ID: int = %d\n", - camToSnake(groupName), - token.id())); - - sb.append(String.format("\n" + - indent + "_%1$s_group: '%2$sGroup' = %2$sGroup()\n", - camToSnake(groupName), - formatClassName(groupName), - token.id())); - - generateSinceActingDeprecated(sb, indent, toUpperFirstChar(groupName), token); - - sb.append(String.format("\n" + - indent + "def get_%2$s(self) -> '" + parentMessageClassName + ".%1$sGroup':\n" + - indent + " self._%3$s_group.wrap_decode(self._parent_message, self._buffer, " + - "self._parent_message.SCHEMA_VERSION)\n" + - indent + " return self._%3$s_group\n", - className, - camToSnake(groupName), - camToSnake(groupName))); - - sb.append(String.format("\n" + - indent + "def set_%2$s_count(self, count:int) -> '" + parentMessageClassName + ".%1$sGroup':\n" + - indent + " self._%3$s_group.wrap_encode(self._parent_message, self._buffer, count)\n" + - indent + " return self._%3$s_group\n", - className, - camToSnake(groupName), - camToSnake(groupName))); - - return sb; - } - - private CharSequence generateVarData(final List tokens, final String indent, final String parentClassName) - { - final StringBuilder sb = new StringBuilder(); - - for (int i = 0, size = tokens.size(); i < size; i++) - { - final Token token = tokens.get(i); - if (token.signal() == Signal.BEGIN_VAR_DATA) - { - generateFieldIdMethod(sb, token, indent); - - final Token varDataToken = Generators.findFirst("varData", tokens, i); - final String characterEncoding = varDataToken.encoding().characterEncoding(); - generateCharacterEncodingMethod(sb, token.name(), characterEncoding, indent); - generateFieldMetaAttributeMethod(sb, token, indent); - - final String propertyName = toUpperFirstChar(token.name()); - final Token lengthToken = Generators.findFirst("length", tokens, i); - final int sizeOfLengthField = lengthToken.encodedLength(); - final Encoding lengthEncoding = lengthToken.encoding(); - final String lengthCSharpType = pythonTypeName(lengthEncoding.primitiveType()); - final String lengthTypePrefix = toUpperFirstChar(lengthEncoding.primitiveType().primitiveName()); - final ByteOrder byteOrder = lengthEncoding.byteOrder(); - final String byteOrderStr = byteOrder.toString(); - - sb.append(String.format("\n" + - indent + "%1$S_HEADER_SIZE: int = %2$d\n", - camToSnake(propertyName), - sizeOfLengthField)); - - sb.append(String.format("\n" + - indent + "def get_%1$s(self) -> memoryview:\n" + - "%2$s" + - indent + " size_of_len_field: int = %3$d\n" + - indent + " limit:int = self._parent_message.limit\n" + - indent + " #self._buffer.CheckLimit(limit + size_of_len_field);\n" + - indent + " data_length: int = %4$S_%5$S.unpack_from(self._buffer, limit)[0]\n" + - indent + " self._parent_message.set_limit(limit + size_of_len_field + data_length)\n" + - indent + " return memoryview(self._buffer)[limit + size_of_len_field:limit + " + - "size_of_len_field+data_length]\n", - camToSnake(propertyName), - generateArrayFieldNotPresentCondition(token.version(), indent), - sizeOfLengthField, - lengthTypePrefix, - byteOrderStr)); - - sb.append(String.format("\n" + - indent + "def set_%1$s(self, data: Union[bytes, bytearray, memoryview]) -> '%7$s':\n" + - indent + " size_of_len_field: int = %2$d\n" + - indent + " limit:int = self._parent_message.limit\n" + - indent + " self._parent_message.set_limit(limit + size_of_len_field + len(data))\n" + - indent + " data_len = len(data)\n" + - indent + " %3$S_%5$S.pack_into(self._buffer, limit, %4$s(data_len))\n" + - indent + " struct.pack_into('%6$s%%ds' %% (data_len,), self._buffer, limit + size_of_len_field, " + - "data)\n" + - indent + " return self\n\n", - camToSnake(propertyName), - sizeOfLengthField, - lengthTypePrefix, - lengthCSharpType, - byteOrderStr, - pythonEndianCode(byteOrder), - parentClassName)); - } - } - - return sb; - } - - private void generateBitSet(final List tokens, final List modules) throws IOException - { - final Token bitSetToken = tokens.get(0); - final String bitSetName = formatClassName(bitSetToken.applicableTypeName()); - final List messageBody = getMessageBody(tokens); - try (Writer out = outputManager.createOutput(camToSnake(bitSetName))) - { - modules.add(camToSnake(bitSetName)); - out.append(generateFileHeader(ir.applicableNamespace(), messageBody, true)); - out.append(generateClassDeclaration(bitSetName)); - out.append(generateMessageFlyweightCode(bitSetName, bitSetToken, BASE_INDENT, new ArrayList<>())); - out.append(generateChoiceIsEmpty(bitSetToken.encoding().primitiveType(), - bitSetToken.encoding().byteOrder())); - out.append(generateChoiceDecoders(messageBody)); - out.append(generateChoiceDisplay(messageBody)); - out.append(generateChoiceClear(bitSetName, bitSetToken)); - out.append(generateChoiceEncoders(bitSetName, messageBody)); - - } - } - - private void generateEnum(final List tokens, final List modules) throws IOException - { - final Token enumToken = tokens.get(0); - final String enumName = formatClassName(enumToken.applicableTypeName()); - final List messageBody = getMessageBody(tokens); - try (Writer out = outputManager.createOutput(camToSnake(enumName))) - { - modules.add(camToSnake(enumName)); - out.append(generateFileHeader(ir.applicableNamespace(), messageBody, true)); - final String enumPrimitiveType = pythonTypeName(enumToken.encoding().primitiveType()); - out.append(generateEnumDeclaration(enumName, enumPrimitiveType)); - out.append(generateEnumValues(messageBody, enumToken)); - } - } - - private void generateComposite(final List tokens, final List modules) throws IOException - { - final String compositeName = formatClassName(tokens.get(0).applicableTypeName()); - - try (Writer out = outputManager.createOutput(camToSnake(compositeName))) - { - modules.add(camToSnake(compositeName)); - out.append(generateFileHeader(ir.applicableNamespace(), getMessageBody(tokens), true)); - out.append(generateClassDeclaration(compositeName)); - out.append(generateFixedFlyweightCode(tokens.get(0).encodedLength(), getMessageBody(tokens))); - out.append(generateCompositePropertyElements(getMessageBody(tokens), BASE_INDENT, compositeName)); - - } - } - - private CharSequence generateCompositePropertyElements(final List tokens, final String indent, - final String className) - { - final StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < tokens.size(); ) - { - final Token token = tokens.get(i); - final String propertyName = formatPropertyName(token.name()); - - switch (token.signal()) - { - case ENCODING: - sb.append(generatePrimitiveProperty(propertyName, token, indent, className)); - break; - - case BEGIN_ENUM: - sb.append(generateEnumProperty(propertyName, token, null, indent, className)); - break; - - case BEGIN_SET: - sb.append(generateBitSetProperty(propertyName, token, indent)); - break; - - case BEGIN_COMPOSITE: - sb.append(generateCompositeProperty(propertyName, token, indent)); - break; - } - - i += tokens.get(i).componentTokenCount(); - } - - return sb; - } - - private CharSequence generateChoiceEncoders(final String bitSetClassName, final List tokens) - { - return concatTokens( - tokens, - Signal.CHOICE, - (token) -> - { - final String choiceName = formatPropertyName(token.name()); - final Encoding encoding = token.encoding(); - final String choiceBitIndex = encoding.constValue().toString(); - final PrimitiveType primitiveType = encoding.primitiveType(); - - return String.format("\n" + - INDENT + "def set_%2$s(self, value: bool) -> '%1$s':\n" + - "%3$s\n\n" + - INDENT + "@staticmethod\n" + - INDENT + "def apply_%2$s(bits: '%4$s', value: bool) -> '%4$s':\n" + - "%5$s\n", - bitSetClassName, - camToSnake(choiceName), - generateChoicePut(primitiveType, choiceBitIndex, encoding.byteOrder()), - "int", - generateStaticChoicePut(primitiveType, choiceBitIndex)); - }); - } - - private CharSequence generateChoiceDisplay(final List tokens) - { - final String indent = INDENT; - final StringBuilder sb = new StringBuilder(); - - sb.append('\n'); - sb.append(indent + "def __repr__(self):\n"); - sb.append(indent + indent + "at_least_one = False\n"); - sb.append(indent + indent + "out = \"{\"\n"); - tokens - .stream() - .filter((token) -> token.signal() == Signal.CHOICE) - .forEach((token) -> - { - final String choiceName = formatPropertyName(token.name()); - sb.append(indent + indent + "if self.has_" + camToSnake(choiceName) + "():\n"); - sb.append(indent + indent + indent + "if at_least_one:\n"); - sb.append(indent + indent + indent + indent + "out += \",\"\n"); - sb.append(indent + indent + indent + "out += \"" + choiceName + "\"\n"); - sb.append(indent + indent + indent + "at_least_one = True\n"); - }); - sb.append(indent + indent + "out += \"}\"\n"); - sb.append('\n'); - sb.append(indent + indent + "return out\n"); - - return sb.toString(); - } - - private CharSequence generateChoiceDecoders(final List tokens) - { - return concatTokens( - tokens, - Signal.CHOICE, - (token) -> - { - final String choiceName = formatPropertyName(token.name()); - final Encoding encoding = token.encoding(); - final String choiceBitIndex = encoding.constValue().toString(); - final PrimitiveType primitiveType = encoding.primitiveType(); - - return String.format("\n" + - " def has_%1$s(self) -> bool:\n" + - " return %2$s\n\n" + - " @staticmethod\n" + - " def check_%1$s(value: '%3$s') -> bool:\n" + - " return %4$s\n" + - " \n", - camToSnake(choiceName), - generateChoiceGet(primitiveType, choiceBitIndex, encoding.byteOrder()), - "int", - generateStaticChoiceGet(primitiveType, choiceBitIndex)); - }); - } - - private String generateChoiceIsEmpty(final PrimitiveType type, final ByteOrder byteOrder) - { - return "\n" + - " @property\n" + - " def is_empty(self) -> bool:\n" + - " return " + generateChoiceIsEmptyInner(type, byteOrder) + "\n" + - " \n"; - } - - private String generateChoiceIsEmptyInner(final PrimitiveType type, final ByteOrder byteOrder) - { - return "0 == " + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + - ".unpack_from(self._buffer, self._offset)[0]"; - } - - private String generateChoicePut(final PrimitiveType type, final String bitIdx, final ByteOrder byteOrder) - { - switch (type) - { - case UINT8: - case UINT16: - case UINT32: - case UINT64: - return INDENT + INDENT + "bits = " + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + - ".unpack_from(self._buffer, self._offset)[0]\n" + - " bits = (bits | (1 << " + bitIdx + ")) if value else (bits & ~(1 << " + bitIdx + "))\n" + - INDENT + INDENT + type.primitiveName().toUpperCase() + "_" + byteOrder.toString() + - ".pack_into(self._buffer, self._offset, bits)\n" + - INDENT + INDENT + "return self\n"; - - } - - throw new IllegalArgumentException("primitive type not supported: " + type); - } - - private String generateStaticChoicePut(final PrimitiveType type, final String bitIdx) - { - switch (type) - { - case UINT8: - case UINT16: - case UINT32: - case UINT64: - return INDENT + INDENT + "return (bits | (1 << " + bitIdx + ")) " + - "if value else (bits & ~(1 << " + bitIdx + "))\n"; - } - - throw new IllegalArgumentException("primitive type not supported: " + type); - } - - private String generateStaticChoiceGet(final PrimitiveType type, final String bitIndex) - { - switch (type) - { - case UINT8: - case UINT16: - case UINT32: - case UINT64: - return "0 != (value & (1 << " + bitIndex + "))"; - } - - throw new IllegalArgumentException("primitive type not supported: " + type); - } - - private String generateChoiceGet(final PrimitiveType type, final String bitIndex, final ByteOrder byteOrder) - { - final String ending = byteOrder.toString().toUpperCase(); - switch (type) - { - case UINT8: - case UINT16: - case UINT32: - case UINT64: - return "0 != (" + type.primitiveName().toUpperCase() + "_" + ending + - ".unpack_from(self._buffer, self._offset)[0] & (1 << " + bitIndex + "))"; - } - - throw new IllegalArgumentException("primitive type not supported: " + type); - } - - private CharSequence generateChoiceClear(final String bitSetClassName, final Token token) - { - final StringBuilder sb = new StringBuilder(); - - final Encoding encoding = token.encoding(); - final String literalValue = generateLiteral(encoding.primitiveType(), "0"); - - sb.append(String.format("\n" + - " def clear(self) -> '%s':\n" + - " %2$S_%4$S.pack_into(self._buffer, self._offset, %3$s)\n" + - " return self\n" + - " \n", - bitSetClassName, - encoding.primitiveType().primitiveName(), - literalValue, - encoding.byteOrder())); - - return sb; - } - - private CharSequence generateEnumValues(final List tokens, final Token encodingToken) - { - final StringBuilder sb = new StringBuilder(); - final Encoding encoding = encodingToken.encoding(); - - for (final Token token : tokens) - { - sb.append(INDENT).append(token.name()).append(" = ") - .append(token.encoding().constValue()).append("\n"); - } - - final PrimitiveValue nullVal = encoding.applicableNullValue(); - - sb.append(INDENT).append("NULL_VALUE = ").append(nullVal).append("\n"); - - return sb; - } - - private CharSequence generateFileHeader(final String packageName, final List tokens, final boolean imports) - { - final StringBuilder sb = new StringBuilder("\"\"\"\n Generated SBE (Simple Binary Encoding) message codec\n"); - sb.append("Package: ").append(packageName); - sb.append("\"\"\"\n\n"); - if (imports) - { - sb.append(generateImports(tokens)); - } - sb.append("\n"); - return sb; - } - - private CharSequence generateImports(final List tokens) - { - final StringBuilder sb = new StringBuilder(); - final Set processed = new HashSet<>(); - sb.append("from typing import *\n"); - sb.append("import struct\n"); - sb.append("from ._struct_defs import *\n"); - sb.append("from .meta_attribute import MetaAttribute\n"); - for (final Token t : tokens) - { - if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET || - t.signal() == Signal.BEGIN_ENUM) - { - final String importName = t.referencedName() != null ? formatClassName(t.referencedName()) : - formatClassName(t.name()); - if (processed.contains(importName)) - { - continue; - } - sb.append("from .").append(camToSnake(importName)).append(" import ").append(importName).append("\n"); - processed.add(importName); - } - } - return sb; - } - - private void generateStructParsers() throws IOException - { - try (Writer out = outputManager.createOutput("_struct_defs")) - { - out.append(generateFileHeader(ir.applicableNamespace(), new ArrayList<>(), false)); - out.append("from struct import Struct\n\n"); - final StringBuilder builder = new StringBuilder(); - for (final Map.Entry order : BYTE_ORDER_STRING_MAP.entrySet()) - { - for (final Map.Entry type : PRIMITIVE_TYPE_STRUCT_ENUM_MAP.entrySet()) - { - builder.append(String.format("%1$S_%2$S: Struct = Struct('%3$s%4$s')\n", - type.getKey().primitiveName(), - order.getKey().toString(), - pythonEndianCode(order.getKey()), - pythonTypeCode(type.getKey()))); - } - //edge case to handle char[] unpacking - builder.append(String.format("%1$S_%2$S: Struct = Struct('%3$s%4$s')\n", - "CHARS", - order.getKey().toString(), - pythonEndianCode(order.getKey()), - "s")); - } - - builder.append("\n"); - out.append(builder.toString()); - } - } - - private CharSequence generateClassDeclaration(final String className) - { - return String.format("class %s:\n", className); - } - - private void generateMetaAttributeEnum() throws IOException - { - try (Writer out = outputManager.createOutput(camToSnake(META_ATTRIBUTE_ENUM))) - { - out.append(generateFileHeader(ir.applicableNamespace(), new ArrayList<>(), false)); - out.append( - "from enum import IntEnum \n\n" + - "class MetaAttribute(IntEnum):\n" + - " Epoch = 1\n" + - " TimeUnit = 2\n" + - " SemanticType = 3\n" + - " Presence = 4\n"); - } - } - - private CharSequence generateEnumDeclaration(final String name, final String primitiveType) - { - - return "from enum import IntEnum \n\n" + - "class " + name + "(IntEnum):\n"; - } - - private CharSequence generatePrimitiveProperty(final String propertyName, final Token token, final String indent, - final String parentClassName) - { - final StringBuilder sb = new StringBuilder(); - - sb.append(generatePrimitiveFieldMetaData(propertyName, token, indent)); - - if (token.isConstantEncoding()) - { - sb.append(generateConstPropertyMethods(propertyName, token, indent)); - } - else - { - sb.append(generatePrimitivePropertyMethods(propertyName, token, indent, parentClassName)); - } - - return sb; - } - - private CharSequence generatePrimitivePropertyMethods( - final String propertyName, - final Token token, - final String indent, - final String parentClassName) - { - final int arrayLength = token.arrayLength(); - - if (arrayLength == 1) - { - return generateSingleValueProperty(propertyName, token, indent, parentClassName); - } - else if (arrayLength > 1) - { - return generateArrayProperty(propertyName, token, indent, parentClassName); - } - - return ""; - } - - private CharSequence generatePrimitiveFieldMetaData( - final String propertyName, - final Token token, - final String indent) - { - final PrimitiveType primitiveType = token.encoding().primitiveType(); - final String typeName = pythonTypeName(primitiveType); - - return String.format( - "\n" + - indent + "%2$s_NULL_VALUE: '%1$s' = %3$s\n" + - indent + "%2$s_MIN_VALUE: '%1$s' = %4$s\n" + - indent + "%2$s_MAX_VALUE: '%1$s' = %5$s\n", - typeName, - camToSnake(propertyName).toUpperCase(), - generateLiteral(primitiveType, token.encoding().applicableNullValue().toString()), - generateLiteral(primitiveType, token.encoding().applicableMinValue().toString()), - generateLiteral(primitiveType, token.encoding().applicableMaxValue().toString())); - } - - private CharSequence generateSingleValueProperty( - final String propertyName, - final Token token, - final String indent, - final String parentClassName) - { - final String typeName = pythonTypeName(token.encoding().primitiveType()); - final String typePrefix = toUpperFirstChar(token.encoding().primitiveType().primitiveName()); - final int offset = token.offset(); - final ByteOrder byteOrder = token.encoding().byteOrder(); - final String byteOrderStr = byteOrder.toString(); - - final String getter = String.format("\n" + - indent + "def get_%2$s(self) -> '%1$s':\n" + - "%3$s" + - indent + " return %4$S_%6$S.unpack_from(self._buffer, self._offset + %5$d)[0]", - typeName, - camToSnake(propertyName), - generateFieldNotPresentCondition(token.version(), token.encoding(), indent), - typePrefix.toUpperCase(), - offset, - byteOrderStr); - - final String setter = String.format("\n" + - indent + "def set_%2$s(self, value:%1$s) -> '%3$s':\n" + - indent + " %4$S_%6$s.pack_into(self._buffer, self._offset + %5$d, value)\n" + - indent + " return self\n", - typeName, - camToSnake(propertyName), - formatClassName(parentClassName), - typePrefix.toUpperCase(), - offset, - byteOrderStr); - return getter + "\n" + setter + "\n"; - } - - private CharSequence generateFieldNotPresentCondition( - final int sinceVersion, - final Encoding encoding, - final String indent) - { - if (0 == sinceVersion) - { - return ""; - } - - final String literal; - if (sinceVersion > 0) - { - literal = generateLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString()); - } - else - { - literal = "(byte)0"; - } - - return String.format( - indent + "if self._acting_version < %1$d: return %2$s\n\n", - sinceVersion, - literal); - } - - private CharSequence generateArrayFieldNotPresentCondition( - final int sinceVersion, - final String indent) - { - if (0 == sinceVersion) - { - return ""; - } - - return String.format( - indent + "if self._acting_version < %d: return 0\n\n", - sinceVersion); - } - - private CharSequence generateTypeFieldNotPresentCondition( - final int sinceVersion, - final String indent) - { - if (0 == sinceVersion) - { - return ""; - } - - return String.format( - indent + "if self._acting_version < %d: return None\n\n", - sinceVersion); - } - - private CharSequence generateArrayProperty( - final String propertyName, - final Token token, - final String indent, - final String parentClassName) - { - final String typeName = pythonTypeName(token.encoding().primitiveType()); - final String typePrefix = toUpperFirstChar(token.encoding().primitiveType().primitiveName()); - final int offset = token.offset(); - final ByteOrder byteOrder = token.encoding().byteOrder(); - final String byteOrderStr = byteOrder.toString(); - final int fieldLength = token.arrayLength(); - final int typeSize = token.encoding().primitiveType().size(); - final String propName = toUpperFirstChar(propertyName); - - final StringBuilder sb = new StringBuilder(); - - sb.append(String.format("\n" + - indent + "%1$S_LENGTH = %2$d\n", - camToSnake(propName), fieldLength)); - - final String structParserMulti = String.format("A_%1$S_%2$S_%3$S", camToSnake(propName), typePrefix, - byteOrderStr); - - sb.append(String.format("\n" + - indent + structParserMulti + " = Struct('%1$s%2$d%3$s') \n", - pythonEndianCode(byteOrder), fieldLength, - pythonTypeCode(token.encoding().primitiveType()))); - - if (token.encoding().primitiveType() == PrimitiveType.CHAR) - { - generateCharacterEncodingMethod(sb, propertyName, token.encoding().characterEncoding(), indent); - //Properties for multi item assignment - sb.append(String.format("\n" + - indent + "def get_multi_%2$s(self) -> bytes:\n" + - "%4$s" + - indent + " return self." + structParserMulti + ".unpack_from(self._buffer, self._offset + %5$d)[0]" + - "\n", - typeName, camToSnake(propName), fieldLength, - generateFieldNotPresentCondition(token.version(), token.encoding(), indent), - offset, typeSize)); - } - else - { - //Properties for multi item assignment - sb.append(String.format("\n" + - indent + "def get_multi_%2$s(self) -> Tuple['%1$s']:\n" + - "%4$s" + - indent + " return self." + structParserMulti + ".unpack_from(self._buffer, self._offset + %5$d)\n", - typeName, camToSnake(propName), fieldLength, - generateFieldNotPresentCondition(token.version(), token.encoding(), indent), - offset, typeSize)); - } - - - sb.append(String.format("\n" + - indent + "def set_%1$s(self, value:%2$s) -> '%4$s':\n" + - indent + " self." + structParserMulti + ".pack_into(self._buffer, self._offset + %3$d, value)\n" + - indent + " return self\n", - camToSnake(propName), typeName, offset, parentClassName)); - - //Properties for single assigment - sb.append(String.format("\n" + - indent + "def get_%2$s(self, index: int) -> '%1$s':\n" + - indent + " if index < 0 or index >= %3$d:\n" + - indent + " raise IndexError(\"index out of range: index=\" + str(index))\n\n" + - "%4$s" + - indent + " return %5$S_%8$S.unpack_from(self._buffer, self._offset + %6$d + (index * %7$d))[0]\n", - typeName, camToSnake(propName), fieldLength, - generateFieldNotPresentCondition(token.version(), token.encoding(), indent), typePrefix, - offset, typeSize, byteOrder)); - - sb.append(String.format("\n" + - indent + "def put_%1$s(self, index:int, value:%2$s) -> '%8$s':\n" + - indent + " if index < 0 or index >= %3$d:\n" + - indent + " raise IndexError(\"index out of range: index=\" + str(index))\n\n" + - indent + " %4$S_%7$S.pack_into(self._buffer, self._offset + %5$d + (index * %6$d), value)\n" + - indent + " return self\n", - camToSnake(propName), typeName, fieldLength, typePrefix, offset, typeSize, byteOrder, parentClassName)); - - - return sb; - } - - private void generateCharacterEncodingMethod( - final StringBuilder sb, - final String propertyName, - final String encoding, - final String indent) - { - sb.append(String.format("\n" + - indent + "%S_CHAR_ENCODING = \"%s\"\n\n", - camToSnake(formatPropertyName(propertyName)), - encoding)); - } - - private CharSequence generateConstPropertyMethods( - final String propertyName, - final Token token, - final String indent) - { - if (token.encoding().primitiveType() != PrimitiveType.CHAR) - { - // ODE: we generate a property here because the constant could - // become a field in a newer version of the protocol - return String.format("\n" + - indent + "@property\n" + - indent + "def get_%2$s(self) -> '%1$s':\n" + - indent + " return %3$s\n", - pythonTypeName(token.encoding().primitiveType()), - camToSnake(propertyName), - generateLiteral(token.encoding().primitiveType(), token.encoding().constValue().toString())); - } - - final StringBuilder sb = new StringBuilder(); - - final String pyTypeName = pythonTypeName(token.encoding().primitiveType()); - final byte[] constantValue = token.encoding().constValue().byteArrayValue(token.encoding().primitiveType()); - final CharSequence values = generateByteLiteralList( - token.encoding().constValue().byteArrayValue(token.encoding().primitiveType())); - - sb.append(String.format( - "\n" + - indent + "_%1$S_VALUE: Union[bytes, bytearray, memoryview] = bytes([ %2$s ])\n", - camToSnake(propertyName), - values)); - - sb.append(String.format( - "\n" + - indent + "%1$S_LENGTH: int = %2$d\n", - camToSnake(propertyName).toUpperCase(), - constantValue.length)); - sb.append("\n"); - sb.append(String.format( - indent + "def %2$s(self, index: int) -> '%1$s':\n" + - indent + " return self._%3$s_VALUE[index]\n", - pyTypeName, - camToSnake(propertyName), - camToSnake(propertyName).toUpperCase())); - sb.append("\n"); - - sb.append(String.format( - indent + "def get_%1$s(self, offset: int, length: int) -> memoryview:\n" + - indent + " last = min(length, %2$d)\n" + - indent + " offset = min(abs(offset), %3$d)\n" + - indent + " return memoryview(self._%4$S_VALUE)[offset:last]\n", - camToSnake(propertyName), - constantValue.length, - constantValue.length - 1, - propertyName)); - - return sb; - } - - private CharSequence generateByteLiteralList(final byte[] bytes) - { - final StringBuilder values = new StringBuilder(); - for (final byte b : bytes) - { - values.append(b).append(", "); - } - - if (values.length() > 0) - { - values.setLength(values.length() - 2); - } - - return values; - } - - private CharSequence generateFixedFlyweightCode(final int size, final List tokens) - { - //reserve __slots__ to improve performance for instance fields - final StringBuilder builder = new StringBuilder(); - final Map fieldTypes = new LinkedHashMap<>(); - for (final Token t : tokens) - { - if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET) - { - fieldTypes.put("_" + camToSnake(t.name()), t.referencedName() != null ? - toUpperFirstChar(t.referencedName()) : toUpperFirstChar(t.name())); - } - } - final List fields = new ArrayList<>(fieldTypes.keySet()); - builder.append(INDENT + "__slots__ = '_offset', '_buffer', '_acting_version'"); - if (fields.size() > 0) - { - builder.append(", '" + String.join("', '", fields) + "'"); - } - builder.append("\n\n"); - builder.append(String.format( - " SIZE: int = %d \n\n" + - " def __init__(self):\n" + - " self._offset: int \n" + - " self._acting_version: int \n" + - " self._buffer: int \n", size)); - for (final Map.Entry field : fieldTypes.entrySet()) - { - builder.append(INDENT + INDENT + "self." + field.getKey() + ": '" + field.getValue() + "' = " + - field.getValue() + "()\n"); - } - builder.append("\n"); - - builder.append(INDENT + "def wrap(self, buffer: Union[bytes, bytearray, memoryview], offset: int, " + - "acting_version: int):\n" + - INDENT + INDENT + "self._offset = offset\n" + - INDENT + INDENT + "self._acting_version = acting_version\n" + - INDENT + INDENT + "self._buffer = buffer\n" + - INDENT + INDENT + "return self\n"); - return builder.toString(); - } - - - private CharSequence generateMessageFlyweightCode(final String className, final Token token, - final String indent, final List fields) - { - final String blockLengthType = pythonTypeName(ir.headerStructure().blockLengthType()); - final String templateIdType = pythonTypeName(ir.headerStructure().templateIdType()); - final String schemaIdType = pythonTypeName(ir.headerStructure().schemaIdType()); - final String schemaVersionType = pythonTypeName(ir.headerStructure().schemaVersionType()); - final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); - final StringBuilder builder = new StringBuilder(); - final Map fieldTypes = new LinkedHashMap<>(); - for (int i = 0, size = fields.size(); i < size; i++) - { - final Token signalToken = fields.get(i); - if (signalToken.signal() == Signal.BEGIN_FIELD) - { - final Token encodingToken = fields.get(i + 1); - final String propertyName = signalToken.name(); - if (encodingToken.signal() == Signal.BEGIN_SET || encodingToken.signal() == Signal.BEGIN_COMPOSITE) - { - fieldTypes.put("_" + camToSnake(propertyName), toUpperFirstChar(encodingToken.name())); - } - } - } - builder.append(String.format( - indent + "BLOCK_LENGTH: '%1$s' = %2$s\n" + - indent + "TEMPLATE_ID: '%3$s' = %4$s\n" + - indent + "SCHEMA_ID: '%5$s' = %6$s\n" + - indent + "SCHEMA_VERSION: '%7$s' = %8$s\n" + - indent + "SEMANTIC_TYPE: str = \"%9$s\"\n\n", - blockLengthType, - generateLiteral(ir.headerStructure().blockLengthType(), Integer.toString(token.encodedLength())), - templateIdType, - generateLiteral(ir.headerStructure().templateIdType(), Integer.toString(token.id())), - schemaIdType, - generateLiteral(ir.headerStructure().schemaIdType(), Integer.toString(ir.id())), - schemaVersionType, - generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), - semanticType)); - - builder.append(indent + "__slots__ = '_parent_message', '_buffer', '_offset', '_limit', " + - "'_acting_block_length', '_acting_version'"); - if (fieldTypes.size() > 0) - { - builder.append(", '" + String.join("', '", fieldTypes.keySet()) + "'"); - } - builder.append("\n\n"); - - builder.append(String.format( - indent + "def __init__(self):\n" + - indent + " self._parent_message: '%1$s' = self\n" + - indent + " self._buffer: Union[bytes, bytearray, memoryview]\n" + - indent + " self._offset: int\n" + - indent + " self._limit: int\n" + - indent + " self._acting_block_length: int\n" + - indent + " self._acting_version: int\n", className)); - for (final Map.Entry ft : fieldTypes.entrySet()) - { - builder.append(indent + INDENT + "self." + ft.getKey() + ": '" + ft.getValue() + "' = " + - ft.getValue() + "()\n"); - } - builder.append("\n"); - - builder.append( - indent + "@property\n" + - indent + "def offset(self) -> int:\n" + - indent + " return self._offset\n\n" + - indent + "def wrap_encode(self, buffer: Union[bytes, bytearray, memoryview], offset: int):\n" + - indent + " self._buffer = buffer\n" + - indent + " self._offset = offset\n" + - indent + " self._acting_block_length = self.BLOCK_LENGTH\n" + - indent + " self._acting_version = self.SCHEMA_VERSION\n" + - indent + " self.set_limit(offset + self._acting_block_length)\n" + - indent + " return self\n"); - builder.append("\n"); - - builder.append( - indent + "def wrap_decode(self,buffer: Union[bytes, bytearray, memoryview], offset: int, " + - "acting_block_length: int, acting_version:int):\n" + - indent + " self._buffer = buffer\n" + - indent + " self._offset = offset\n" + - indent + " self._acting_block_length = acting_block_length\n" + - indent + " self._acting_version = acting_version\n" + - indent + " self.set_limit(offset + self._acting_block_length)\n" + - indent + " return self\n"); - builder.append("\n"); - - builder.append( - indent + "def size(self) -> int:\n" + - indent + " return self._limit - self._offset\n" + - indent + "\n\n" + - indent + "@property\n" + - indent + "def limit(self) -> int:\n" + - indent + " return self._limit\n"); - builder.append("\n"); - builder.append( - indent + "def set_limit(self, value):\n" + - //TODO: make sure the capacity is checked either wrap in bytearray - indent + " #self._buffer.CheckLimit(value);\n" + - indent + " self._limit = value\n" + - indent + " return self\n"); - return builder.toString(); - } - - private CharSequence generateFields(final List tokens, final String indent, final String parentClassName) - { - final StringBuilder sb = new StringBuilder(); - - for (int i = 0, size = tokens.size(); i < size; i++) - { - final Token signalToken = tokens.get(i); - if (signalToken.signal() == Signal.BEGIN_FIELD) - { - final Token encodingToken = tokens.get(i + 1); - final String propertyName = signalToken.name(); - - generateFieldIdMethod(sb, signalToken, indent); - generateFieldMetaAttributeMethod(sb, signalToken, indent); - - switch (encodingToken.signal()) - { - case ENCODING: - sb.append(generatePrimitiveProperty(propertyName, encodingToken, indent, parentClassName)); - break; - - case BEGIN_ENUM: - sb.append(generateEnumProperty(propertyName, encodingToken, signalToken, indent, - parentClassName)); - break; - - case BEGIN_SET: - sb.append(generateBitSetProperty(propertyName, encodingToken, indent)); - break; - - case BEGIN_COMPOSITE: - sb.append(generateCompositeProperty(propertyName, encodingToken, indent)); - break; - } - } - } - - return sb; - } - - private void generateFieldIdMethod(final StringBuilder sb, final Token token, final String indent) - { - sb.append(String.format("\n" + - indent + "%S_ID: int = %d\n", - camToSnake(token.name()), - token.id())); - - generateSinceActingDeprecated(sb, indent, token.name(), token); - } - - private void generateFieldMetaAttributeMethod(final StringBuilder sb, final Token token, final String indent) - { - final Encoding encoding = token.encoding(); - final String epoch = encoding.epoch() == null ? "" : encoding.epoch(); - final String timeUnit = encoding.timeUnit() == null ? "" : encoding.timeUnit(); - final String semanticType = encoding.semanticType() == null ? "" : encoding.semanticType(); - final String presence = encoding.presence() == null ? "" : encoding.presence().toString().toLowerCase(); - - sb.append(String.format("\n" + - indent + "@staticmethod\n" + - indent + "def %s_meta_attribute(meta_attribute: 'MetaAttribute') -> str:\n" + - indent + " if meta_attribute == MetaAttribute.Epoch: return '%s'\n" + - indent + " if meta_attribute == MetaAttribute.TimeUnit: return '%s'\n" + - indent + " if meta_attribute == MetaAttribute.SemanticType: return '%s'\n" + - indent + " if meta_attribute == MetaAttribute.Presence: return '%s'\n" + - indent + " return ''\n", - camToSnake(token.name()), - epoch, - timeUnit, - semanticType, - presence)); - } - - private CharSequence generateEnumFieldNotPresentCondition( - final int sinceVersion, - final String enumName, - final String indent) - { - if (0 == sinceVersion) - { - return ""; - } - - return String.format( - indent + "if self._acting_version < %d: return %s.NULL_VALUE\n\n", - sinceVersion, - enumName); - } - - private CharSequence generateEnumProperty( - final String propertyName, - final Token token, - final Token signalToken, - final String indent, - final String parentClassName) - { - final String enumName = formatClassName(token.applicableTypeName()); - final String typePrefix = toUpperFirstChar(token.encoding().primitiveType().primitiveName()); - final String typeName = pythonTypeName(token.encoding().primitiveType()); - final String enumUnderlyingType = pythonTypeName(token.encoding().primitiveType()); - final int offset = token.offset(); - final ByteOrder byteOrder = token.encoding().byteOrder(); - final String byteOrderStr = byteOrder.toString(); - - if (signalToken != null && signalToken.isConstantEncoding()) - { - final String constValue = signalToken.encoding().constValue().toString(); - - return String.format("\n" + - indent + "@staticmethod\n" + - indent + "def get_%2$s() -> '%1$s':\n" + - indent + " return %3$s\n", - enumName, - camToSnake(propertyName), - constValue); - } - else - { - String enumStructType = typePrefix; - if (typePrefix.toUpperCase().equals("CHAR")) - { - enumStructType = "INT8"; - } - final String getter = String.format( - indent + "def get_%2$s(self) -> '%1$s':\n" + - "%3$s" + - indent + " return %4$s(%5$S_%7$S.unpack_from(self._buffer, self._offset + %6$d)[0])\n\n", - enumName, - camToSnake(propertyName), - generateEnumFieldNotPresentCondition(token.version(), enumName, indent), - enumName, - enumStructType, - offset, - byteOrderStr, - enumUnderlyingType); - - String cast = enumUnderlyingType + "(value)"; - if (enumUnderlyingType.equals("bytes") && enumStructType.equals("INT8")) - { - cast = "value"; - } - else if (enumUnderlyingType.equals("bytes")) - { - cast = "bytes([value])"; - } - final String setter = String.format("\n" + - indent + "def set_%2$s(self, value: '%4$s') -> '%9$s':\n" + - "%3$s" + - indent + " %5$S_%8$S.pack_into(self._buffer, self._offset + %7$d, %10$s)\n" + - indent + " return self\n\n", - enumName, - camToSnake(propertyName), - generateEnumFieldNotPresentCondition(token.version(), enumName, indent), - enumName, - enumStructType, - typeName, - offset, - byteOrderStr, - parentClassName, - cast); - return getter + setter; - } - } - - private String generateBitSetProperty(final String propertyName, final Token token, final String indent) - { - final String bitSetName = formatClassName(token.applicableTypeName()); - final int offset = token.offset(); - - final String getter = String.format("\n" + - indent + "def get_%2$s(self) -> '%1$s':\n" + - "%3$s" + - indent + " return self._%2$s.wrap_decode(self._buffer, self._offset + %4$d, %1$s.BLOCK_LENGTH, " + - "self._acting_version)\n", - bitSetName, - camToSnake(propertyName), - generateTypeFieldNotPresentCondition(token.version(), indent), - offset, - camToSnake(bitSetName)); - - final String setter = String.format("\n" + - indent + "def set_%3$s(self) -> '%1$s':\n" + - indent + " return self._%3$s.wrap_encode(self._buffer, self._offset + %4$d)\n", - bitSetName, - camToSnake(bitSetName), - camToSnake(propertyName), - offset); - return getter + setter; - } - - private Object generateCompositeProperty(final String propertyName, final Token token, final String indent) - { - final String compositeName = formatClassName(token.applicableTypeName()); - final int offset = token.offset(); - final StringBuilder sb = new StringBuilder(); - - sb.append(String.format("\n" + - indent + "def set_%2$s(self) -> '%1$s':\n" + - "%3$s" + - indent + " self._%4$s.wrap(self._buffer, self._offset + %5$d, self._acting_version)\n" + - indent + " return self._%4$s\n", - compositeName, - camToSnake(propertyName), - generateTypeFieldNotPresentCondition(token.version(), indent), - camToSnake(propertyName), - offset)); - - sb.append(String.format("\n" + - indent + "def get_%2$s(self) -> '%1$s':\n" + - "%3$s" + - indent + " self._%4$s.wrap(self._buffer, self._offset + %5$d, self._acting_version)\n" + - indent + " return self._%4$s\n", - compositeName, - camToSnake(propertyName), - generateTypeFieldNotPresentCondition(token.version(), indent), - camToSnake(propertyName), - offset)); - - return sb; - } - - private void generateSinceActingDeprecated( - final StringBuilder sb, - final String indent, - final String propertyName, - final Token token) - { - sb.append(String.format( - indent + "%1$S_SINCE_VERSION: int = %2$d\n" + - indent + "%1$S_DEPRECATED: int = %3$d\n\n" + - indent + "@property\n" + - indent + "def %1$s_in_acting_version(self) -> bool:\n" + - indent + " return self._acting_version >= self.%1$S_SINCE_VERSION\n", - camToSnake(propertyName), - token.version(), - token.deprecated())); - } - - private String generateLiteral(final PrimitiveType type, final String value) - { - String literal = ""; - - switch (type) - { - case CHAR: - literal = "\"" + value + "\""; - break; - case UINT8: - case INT8: - case INT16: - case UINT16: - case UINT32: - case INT64: - case INT32: - literal = value; - break; - case UINT64: - literal = Long.toUnsignedString(Long.parseLong(value)); - break; - case FLOAT: - case DOUBLE: - if (value.endsWith("NaN")) - { - literal = "float('nan')"; - } - else - { - literal = value; - } - break; - } - - return literal; - } -} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PythonGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PythonGenerator.java index cf26d4560c..ff828fa906 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PythonGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PythonGenerator.java @@ -28,6 +28,7 @@ import java.util.*; import java.util.function.Function; +import static java.util.stream.Collectors.joining; import static uk.co.real_logic.sbe.generation.python.PyUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.*; @@ -1228,6 +1229,16 @@ private CharSequence generateChoiceEncoders(final String bitSetClassName, final }); } + public static CharSequence concatTokens( + final List tokens, final Signal signal, final Function mapper) + { + return tokens + .stream() + .filter((token) -> token.signal() == signal) + .map(mapper) + .collect(joining()); + } + private String bitsetArgType(final PrimitiveType primitiveType) { switch (primitiveType) From bab7ec7565d53801c08cd3c25732956c71cd8613 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 13 Aug 2019 14:08:04 +0100 Subject: [PATCH 0155/1594] [Java] Upgrade to Agrona 1.0.7. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bb88adcff0..345273d2e5 100644 --- a/build.gradle +++ b/build.gradle @@ -137,7 +137,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.23' - compile 'org.agrona:agrona:1.0.6' + compile 'org.agrona:agrona:1.0.7' testCompile 'org.hamcrest:hamcrest:2.1' testCompile 'org.mockito:mockito-core:3.0.0' From b97aadabaa1696004265a07d281ed6c59815e1ee Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Wed, 14 Aug 2019 11:33:54 -0700 Subject: [PATCH 0156/1594] 1.13.1 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index b99622a410..b50dd27dd9 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.13.1-SNAPSHOT +1.13.1 From efcaee89f9426ace9ff89e47eef11bb0e6598efe Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Wed, 14 Aug 2019 11:36:39 -0700 Subject: [PATCH 0157/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index b50dd27dd9..22bcb7618b 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.13.1 +1.13.2-SNAPSHOT From a87209e38bf0eba317e428e9fea986d4e7479171 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 14 Aug 2019 20:25:03 +0100 Subject: [PATCH 0158/1594] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9b7745b5cb..a8a2522892 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.13.0 +    1.13.1 ``` @@ -65,7 +65,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.13.1-SNAPSHOT.jar my_sbe_input.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.13.2-SNAPSHOT.jar my_sbe_input.xml C++ Build using CMake From 38e2088fbf560381b759992b077ee23b7e0c603a Mon Sep 17 00:00:00 2001 From: billsegall Date: Fri, 16 Aug 2019 03:53:38 +0100 Subject: [PATCH 0159/1594] Revert the package name to sbe-tool for release 1.13.1 --- csharp/README.md | 3 +++ csharp/sbe-dll/sbe-dll.csproj | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/csharp/README.md b/csharp/README.md index ce103fb5da..686522e03d 100644 --- a/csharp/README.md +++ b/csharp/README.md @@ -20,6 +20,9 @@ The code, samples, tests and nuget package can be built/run using the [dotnet co ## Release Notes +### 1.13.1 +* Fix nuget package name (back to sbe-tool) + ### 1.13.0 * Many build system improvements diff --git a/csharp/sbe-dll/sbe-dll.csproj b/csharp/sbe-dll/sbe-dll.csproj index 2d6e6ae101..97571f1ae3 100644 --- a/csharp/sbe-dll/sbe-dll.csproj +++ b/csharp/sbe-dll/sbe-dll.csproj @@ -12,8 +12,8 @@ https://github.com/real-logic/simple-binary-encoding https://github.com/real-logic/simple-binary-encoding SBE;Marshaling;Low;Latency;Simple;Binary;Encoding - sbe-dll - 1.13.0 + sbe-tool + 1.13.1 Simple Binary Encoding for .NET This package contains all you need to define SBE messages and generate C# encoders and decoders. See https://github.com/real-logic/simple-binary-encoding for more detailed instructions git From ad98bfa1d600b108fbec8d92252c9166d865c0ea Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 16 Aug 2019 17:37:02 +0100 Subject: [PATCH 0160/1594] [Java] Cope with optional composites not being present when pretty printing decoders for debugging. Issue #708. --- .../sbe/generation/java/JavaGenerator.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 9594485fdf..08c26066e0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3207,9 +3207,7 @@ private void appendDecoderDisplay( if (fieldToken.signal() == Signal.BEGIN_FIELD) { final Token encodingToken = fields.get(i + 1); - final String fieldName = formatPropertyName(fieldToken.name()); - append(sb, indent, "//" + fieldToken); lengthBeforeLastGeneratedSeparator = writeTokenDisplay(fieldName, encodingToken, sb, indent); i += fieldToken.componentTokenCount(); @@ -3228,8 +3226,6 @@ private void appendDecoderDisplay( throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); } - append(sb, indent, "//" + groupToken); - final String groupName = formatPropertyName(groupToken.name()); final String groupDecoderName = decoderName(formatClassName(groupToken.name())); @@ -3261,8 +3257,6 @@ private void appendDecoderDisplay( throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); } - append(sb, indent, "//" + varDataToken); - final String characterEncoding = varData.get(i + 3).encoding().characterEncoding(); final String varDataName = formatPropertyName(varDataToken.name()); append(sb, indent, "builder.append(\"" + varDataName + Separators.KEY_VALUE + "\");"); @@ -3293,8 +3287,6 @@ private void appendDecoderDisplay( private int writeTokenDisplay( final String fieldName, final Token typeToken, final StringBuilder sb, final String indent) { - append(sb, indent, "//" + typeToken); - if (typeToken.encodedLength() <= 0 || typeToken.isConstantEncoding()) { return -1; @@ -3343,8 +3335,19 @@ private int writeTokenDisplay( break; case BEGIN_COMPOSITE: - append(sb, indent, fieldName + "().appendTo(builder);"); + { + final String typeName = formatClassName(decoderName(typeToken.applicableTypeName())); + append(sb, indent, "final " + typeName + " " + fieldName + " = " + fieldName + "();"); + append(sb, indent, "if (" + fieldName + " != null)"); + append(sb, indent, "{"); + append(sb, indent, " " + fieldName + ".appendTo(builder);"); + append(sb, indent, "}"); + append(sb, indent, "else"); + append(sb, indent, "{"); + append(sb, indent, " builder.append(\"null\");"); + append(sb, indent, "}"); break; + } } final int lengthBeforeFieldSeparator = sb.length(); From 4319db899c290365ed5ed21ffbeb85fe5647ce1f Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 16 Aug 2019 17:40:21 +0100 Subject: [PATCH 0161/1594] [Java] Regenerate IR codecs. --- .../sbe/ir/generated/FrameCodecDecoder.java | 14 +++----- .../ir/generated/MessageHeaderDecoder.java | 4 --- .../sbe/ir/generated/TokenCodecDecoder.java | 36 +++---------------- .../ir/generated/VarDataEncodingDecoder.java | 2 -- 4 files changed, 8 insertions(+), 48 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index ef85014c25..545ab66f15 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -59,7 +59,10 @@ public int offset() } public FrameCodecDecoder wrap( - final DirectBuffer buffer, final int offset, final int actingBlockLength, final int actingVersion) + final DirectBuffer buffer, + final int offset, + final int actingBlockLength, + final int actingVersion) { if (buffer != this.buffer) { @@ -579,30 +582,21 @@ public StringBuilder appendTo(final StringBuilder builder) } builder.append(BLOCK_LENGTH); builder.append("):"); - //Token{signal=BEGIN_FIELD, name='irId', referencedName='null', description='null', id=1, version=0, deprecated=0, encodedLength=4, offset=0, componentTokenCount=3, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=ENCODING, name='int32', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=4, offset=0, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=INT32, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("irId="); builder.append(irId()); builder.append('|'); - //Token{signal=BEGIN_FIELD, name='irVersion', referencedName='null', description='null', id=2, version=0, deprecated=0, encodedLength=4, offset=4, componentTokenCount=3, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=ENCODING, name='int32', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=4, offset=4, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=INT32, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("irVersion="); builder.append(irVersion()); builder.append('|'); - //Token{signal=BEGIN_FIELD, name='schemaVersion', referencedName='null', description='null', id=3, version=0, deprecated=0, encodedLength=4, offset=8, componentTokenCount=3, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=ENCODING, name='int32', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=4, offset=8, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=INT32, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("schemaVersion="); builder.append(schemaVersion()); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='packageName', referencedName='null', description='null', id=4, version=0, deprecated=0, encodedLength=0, offset=12, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("packageName="); builder.append('\'' + packageName() + '\''); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='namespaceName', referencedName='null', description='null', id=5, version=0, deprecated=0, encodedLength=0, offset=-1, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("namespaceName="); builder.append('\'' + namespaceName() + '\''); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='semanticVersion', referencedName='null', description='null', id=6, version=0, deprecated=0, encodedLength=0, offset=-1, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("semanticVersion="); builder.append('\'' + semanticVersion() + '\''); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java index 14cc32bb9a..e3e8501eda 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java @@ -205,19 +205,15 @@ public String toString() public StringBuilder appendTo(final StringBuilder builder) { builder.append('('); - //Token{signal=ENCODING, name='blockLength', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=2, offset=0, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=UINT16, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("blockLength="); builder.append(blockLength()); builder.append('|'); - //Token{signal=ENCODING, name='templateId', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=2, offset=2, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=UINT16, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("templateId="); builder.append(templateId()); builder.append('|'); - //Token{signal=ENCODING, name='schemaId', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=2, offset=4, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=UINT16, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("schemaId="); builder.append(schemaId()); builder.append('|'); - //Token{signal=ENCODING, name='version', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=2, offset=6, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=UINT16, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("version="); builder.append(version()); builder.append(')'); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 5196c8a366..7f88603f61 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -59,7 +59,10 @@ public int offset() } public TokenCodecDecoder wrap( - final DirectBuffer buffer, final int offset, final int actingBlockLength, final int actingVersion) + final DirectBuffer buffer, + final int offset, + final int actingBlockLength, + final int actingVersion) { if (buffer != this.buffer) { @@ -1697,97 +1700,66 @@ public StringBuilder appendTo(final StringBuilder builder) } builder.append(BLOCK_LENGTH); builder.append("):"); - //Token{signal=BEGIN_FIELD, name='tokenOffset', referencedName='null', description='null', id=1, version=0, deprecated=0, encodedLength=4, offset=0, componentTokenCount=3, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=ENCODING, name='int32', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=4, offset=0, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=INT32, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("tokenOffset="); builder.append(tokenOffset()); builder.append('|'); - //Token{signal=BEGIN_FIELD, name='tokenSize', referencedName='null', description='null', id=2, version=0, deprecated=0, encodedLength=4, offset=4, componentTokenCount=3, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=ENCODING, name='int32', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=4, offset=4, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=INT32, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("tokenSize="); builder.append(tokenSize()); builder.append('|'); - //Token{signal=BEGIN_FIELD, name='fieldId', referencedName='null', description='null', id=3, version=0, deprecated=0, encodedLength=4, offset=8, componentTokenCount=3, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=ENCODING, name='int32', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=4, offset=8, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=INT32, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("fieldId="); builder.append(fieldId()); builder.append('|'); - //Token{signal=BEGIN_FIELD, name='tokenVersion', referencedName='null', description='null', id=4, version=0, deprecated=0, encodedLength=4, offset=12, componentTokenCount=3, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=ENCODING, name='int32', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=4, offset=12, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=INT32, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("tokenVersion="); builder.append(tokenVersion()); builder.append('|'); - //Token{signal=BEGIN_FIELD, name='componentTokenCount', referencedName='null', description='null', id=5, version=0, deprecated=0, encodedLength=4, offset=16, componentTokenCount=3, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=ENCODING, name='int32', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=4, offset=16, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=INT32, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("componentTokenCount="); builder.append(componentTokenCount()); builder.append('|'); - //Token{signal=BEGIN_FIELD, name='signal', referencedName='null', description='null', id=6, version=0, deprecated=0, encodedLength=1, offset=20, componentTokenCount=21, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=BEGIN_ENUM, name='SignalCodec', referencedName='null', description='Token signal type in IR', id=-1, version=0, deprecated=0, encodedLength=1, offset=20, componentTokenCount=19, encoding=Encoding{presence=REQUIRED, primitiveType=UINT8, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("signal="); builder.append(signal()); builder.append('|'); - //Token{signal=BEGIN_FIELD, name='primitiveType', referencedName='null', description='null', id=7, version=0, deprecated=0, encodedLength=1, offset=21, componentTokenCount=16, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=BEGIN_ENUM, name='PrimitiveTypeCodec', referencedName='null', description='Primitive types in type system', id=-1, version=0, deprecated=0, encodedLength=1, offset=21, componentTokenCount=14, encoding=Encoding{presence=REQUIRED, primitiveType=UINT8, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("primitiveType="); builder.append(primitiveType()); builder.append('|'); - //Token{signal=BEGIN_FIELD, name='byteOrder', referencedName='null', description='null', id=8, version=0, deprecated=0, encodedLength=1, offset=22, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=BEGIN_ENUM, name='ByteOrderCodec', referencedName='null', description='Number encoding byte order', id=-1, version=0, deprecated=0, encodedLength=1, offset=22, componentTokenCount=4, encoding=Encoding{presence=REQUIRED, primitiveType=UINT8, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("byteOrder="); builder.append(byteOrder()); builder.append('|'); - //Token{signal=BEGIN_FIELD, name='presence', referencedName='null', description='null', id=9, version=0, deprecated=0, encodedLength=1, offset=23, componentTokenCount=7, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=BEGIN_ENUM, name='PresenceCodec', referencedName='null', description='Field presence declaration', id=-1, version=0, deprecated=0, encodedLength=1, offset=23, componentTokenCount=5, encoding=Encoding{presence=REQUIRED, primitiveType=UINT8, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("presence="); builder.append(presence()); builder.append('|'); - //Token{signal=BEGIN_FIELD, name='deprecated', referencedName='null', description='null', id=10, version=0, deprecated=0, encodedLength=4, offset=24, componentTokenCount=3, encoding=Encoding{presence=OPTIONAL, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} - //Token{signal=ENCODING, name='deprecatedVersionType', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=4, offset=24, componentTokenCount=1, encoding=Encoding{presence=OPTIONAL, primitiveType=INT32, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=0, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("deprecated="); builder.append(deprecated()); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='name', referencedName='null', description='null', id=11, version=0, deprecated=0, encodedLength=0, offset=28, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("name="); builder.append('\'' + name() + '\''); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='constValue', referencedName='null', description='null', id=12, version=0, deprecated=0, encodedLength=0, offset=-1, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("constValue="); builder.append('\'' + constValue() + '\''); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='minValue', referencedName='null', description='null', id=13, version=0, deprecated=0, encodedLength=0, offset=-1, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("minValue="); builder.append('\'' + minValue() + '\''); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='maxValue', referencedName='null', description='null', id=14, version=0, deprecated=0, encodedLength=0, offset=-1, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("maxValue="); builder.append('\'' + maxValue() + '\''); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='nullValue', referencedName='null', description='null', id=15, version=0, deprecated=0, encodedLength=0, offset=-1, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("nullValue="); builder.append('\'' + nullValue() + '\''); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='characterEncoding', referencedName='null', description='null', id=16, version=0, deprecated=0, encodedLength=0, offset=-1, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("characterEncoding="); builder.append('\'' + characterEncoding() + '\''); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='epoch', referencedName='null', description='null', id=17, version=0, deprecated=0, encodedLength=0, offset=-1, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("epoch="); builder.append('\'' + epoch() + '\''); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='timeUnit', referencedName='null', description='null', id=18, version=0, deprecated=0, encodedLength=0, offset=-1, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("timeUnit="); builder.append('\'' + timeUnit() + '\''); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='semanticType', referencedName='null', description='null', id=19, version=0, deprecated=0, encodedLength=0, offset=-1, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("semanticType="); builder.append('\'' + semanticType() + '\''); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='description', referencedName='null', description='null', id=20, version=0, deprecated=0, encodedLength=0, offset=-1, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("description="); builder.append('\'' + description() + '\''); builder.append('|'); - //Token{signal=BEGIN_VAR_DATA, name='referencedName', referencedName='null', description='null', id=21, version=0, deprecated=0, encodedLength=0, offset=-1, componentTokenCount=6, encoding=Encoding{presence=REQUIRED, primitiveType=null, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='unix', timeUnit=nanosecond, semanticType='null'}} builder.append("referencedName="); builder.append('\'' + referencedName() + '\''); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java index 64c33db3d3..9f79e9153b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java @@ -127,11 +127,9 @@ public String toString() public StringBuilder appendTo(final StringBuilder builder) { builder.append('('); - //Token{signal=ENCODING, name='length', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=2, offset=0, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=UINT16, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='null', epoch='null', timeUnit=null, semanticType='null'}} builder.append("length="); builder.append(length()); builder.append('|'); - //Token{signal=ENCODING, name='varData', referencedName='null', description='null', id=-1, version=0, deprecated=0, encodedLength=-1, offset=2, componentTokenCount=1, encoding=Encoding{presence=REQUIRED, primitiveType=UINT8, byteOrder=LITTLE_ENDIAN, minValue=null, maxValue=null, nullValue=null, constValue=null, characterEncoding='UTF-8', epoch='null', timeUnit=null, semanticType='null'}} builder.append(')'); return builder; From efa8fa34793ddbfd1bd75007d291945e1635bbf2 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 16 Aug 2019 17:43:05 +0100 Subject: [PATCH 0162/1594] [Java] Update README for release. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a8a2522892..b401e41c4d 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.13.1 +    1.13.2 ``` @@ -65,7 +65,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.13.2-SNAPSHOT.jar my_sbe_input.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.13.3-SNAPSHOT.jar my_sbe_input.xml C++ Build using CMake From 99de2cdfd264e6e0fdbe0d9649696412cd7c92fe Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 16 Aug 2019 10:00:43 -0700 Subject: [PATCH 0163/1594] 1.13.2 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 22bcb7618b..61ce01b301 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.13.2-SNAPSHOT +1.13.2 From 9e6f6b4df07425fdd36187dfcdde2bdad2e6f389 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 16 Aug 2019 10:03:06 -0700 Subject: [PATCH 0164/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 61ce01b301..0ab9a82382 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.13.2 +1.13.3-SNAPSHOT From 6265466b4410c81cf28ec416fcf9f90a230e470c Mon Sep 17 00:00:00 2001 From: Erik Rigtorp Date: Mon, 26 Aug 2019 06:41:37 -0500 Subject: [PATCH 0165/1594] Mark accessors for primitive types as noexcept --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 3f4d56fca8..0f63f0ee3c 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1279,7 +1279,7 @@ private CharSequence generateSingleValueProperty( final StringBuilder sb = new StringBuilder(); sb.append(String.format("\n" + - indent + " SBE_NODISCARD %1$s %2$s() const\n" + + indent + " SBE_NODISCARD %1$s %2$s() const SBE_NOEXCEPT\n" + indent + " {\n" + "%3$s" + "%4$s" + @@ -1293,7 +1293,7 @@ private CharSequence generateSingleValueProperty( primitiveType, "", Integer.toString(offset), token.encoding().byteOrder(), indent); sb.append(String.format("\n" + - indent + " %1$s &%2$s(const %3$s value)\n" + + indent + " %1$s &%2$s(const %3$s value) SBE_NOEXCEPT\n" + indent + " {\n" + "%4$s" + indent + " return *this;\n" + @@ -2101,7 +2101,7 @@ private CharSequence generateEnumProperty( else { sb.append(String.format("\n" + - indent + " SBE_NODISCARD %1$s::Value %2$s() const\n" + + indent + " SBE_NODISCARD %1$s::Value %2$s() const SBE_NOEXCEPT\n" + indent + " {\n" + "%3$s" + indent + " %5$s val;\n" + @@ -2116,7 +2116,7 @@ private CharSequence generateEnumProperty( offset)); sb.append(String.format("\n" + - indent + " %1$s &%2$s(const %3$s::Value value)\n" + + indent + " %1$s &%2$s(const %3$s::Value value) SBE_NOEXCEPT\n" + indent + " {\n" + indent + " %4$s val = %6$s(value);\n" + indent + " std::memcpy(m_buffer + m_offset + %5$d, &val, sizeof(%4$s));\n" + From 68697513750fa69228161cd15c6b855fd8862c08 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Mon, 26 Aug 2019 15:48:22 +0100 Subject: [PATCH 0166/1594] [Java] Upgrade to javadoc-links 4.0.0 and Gradle Build Scan 2.4.1. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 345273d2e5..917f16cce5 100644 --- a/build.gradle +++ b/build.gradle @@ -21,8 +21,8 @@ buildscript { plugins { id 'java' - id 'com.gradle.build-scan' version '2.3' - id "io.freefair.javadoc-links" version "3.8.4" apply false + id 'com.gradle.build-scan' version '2.4.1' + id 'io.freefair.javadoc-links' version '4.0.0' apply false id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } From 622ca29bace4a314f0976cc401a2ea1cfe99c7cd Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 28 Aug 2019 20:17:16 +0100 Subject: [PATCH 0167/1594] [Java] Upgrade to Gradle 5.6.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 917f16cce5..446a7cffab 100644 --- a/build.gradle +++ b/build.gradle @@ -771,6 +771,6 @@ task uploadToMavenCentral { } wrapper { - gradleVersion = '5.5.1' + gradleVersion = '5.6.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 430dfabc5c..dbe85eef28 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 8e25e6c19d..83f2acfdc3 100755 --- a/gradlew +++ b/gradlew @@ -125,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` From 353036f0cdc7d24df0e04fc581c1ff8c9a1d372a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 28 Aug 2019 22:22:22 +0100 Subject: [PATCH 0168/1594] [Java] Upgrade to javadoc-links 4.0.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 446a7cffab..ca743e4220 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.4.1' - id 'io.freefair.javadoc-links' version '4.0.0' apply false + id 'io.freefair.javadoc-links' version '4.0.1' apply false id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } From 3db1bfdb2b5289fb651705f4b721af19a7457e1c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 5 Sep 2019 04:40:06 +0100 Subject: [PATCH 0169/1594] [Java] Upgrade to Checkstyle 8.24. --- build.gradle | 4 ++-- config/checkstyle/checkstyle.xml | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index ca743e4220..6b5e8aa8ad 100644 --- a/build.gradle +++ b/build.gradle @@ -135,7 +135,7 @@ subprojects { jar.enabled = true dependencies { - checkstyle 'com.puppycrawl.tools:checkstyle:8.23' + checkstyle 'com.puppycrawl.tools:checkstyle:8.24' compile 'org.agrona:agrona:1.0.7' @@ -144,7 +144,7 @@ subprojects { testCompile 'junit:junit:4.12' } - checkstyle.toolVersion = '8.23' + checkstyle.toolVersion = '8.24' compileJava { sourceCompatibility = sbeJavaVersion diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 154e4b6217..63ad312c35 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -17,6 +17,11 @@ + + + + + @@ -59,11 +64,6 @@ - - - - - From ab76b3984837244631872cb64c80dda4e80ec9f3 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 9 Sep 2019 09:16:54 +0100 Subject: [PATCH 0170/1594] [Java] Upgrade to Gradle 5.6.2. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 6b5e8aa8ad..cf4b8585a1 100644 --- a/build.gradle +++ b/build.gradle @@ -771,6 +771,6 @@ task uploadToMavenCentral { } wrapper { - gradleVersion = '5.6.1' + gradleVersion = '5.6.2' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index dbe85eef28..ca9d62814a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From f8b59ef64e897d4458af754f86fc6d2860990660 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 9 Sep 2019 09:26:49 +0100 Subject: [PATCH 0171/1594] [Java] Upgrade to javadoc-links 4.0.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cf4b8585a1..0313f5943b 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.4.1' - id 'io.freefair.javadoc-links' version '4.0.1' apply false + id 'io.freefair.javadoc-links' version '4.0.2' apply false id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } From 0990c77e466cd3b9866a9149176cf5c256af68ad Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Mon, 9 Sep 2019 10:59:51 -0400 Subject: [PATCH 0172/1594] [C++]: for #714. Use better constant for type than -1 and preserve behavior. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 0f63f0ee3c..506b5d8ea3 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -226,7 +226,7 @@ private static void generateGroupClassHeader( indent + " m_bufferLength = bufferLength;\n" + indent + " m_blockLength = dimensions.blockLength();\n" + indent + " m_count = dimensions.numInGroup();\n" + - indent + " m_index = -1;\n" + + indent + " m_index = std::numeric_limits::max();\n" + indent + " m_actingVersion = actingVersion;\n" + indent + " m_positionPtr = pos;\n" + indent + " *m_positionPtr = *m_positionPtr + %1$d;\n" + @@ -260,7 +260,7 @@ private static void generateGroupClassHeader( indent + " %7$s dimensions(buffer, *pos, bufferLength, actingVersion);\n" + indent + " dimensions.blockLength((%1$s)%2$d);\n" + indent + " dimensions.numInGroup((%3$s)count);\n" + - indent + " m_index = -1;\n" + + indent + " m_index = std::numeric_limits::max();\n" + indent + " m_count = count;\n" + indent + " m_blockLength = %2$d;\n" + indent + " m_actingVersion = actingVersion;\n" + From 963f339d61a888b3de796328cd04bfc2c1281c6e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 11 Sep 2019 05:32:08 +0100 Subject: [PATCH 0173/1594] [Java] Add exports for modules enabled JVMs. --- build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.gradle b/build.gradle index 0313f5943b..3ea5716013 100644 --- a/build.gradle +++ b/build.gradle @@ -161,6 +161,11 @@ subprojects { } test { + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + jvmArgs('--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED') + jvmArgs('--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED') + } + testLogging { showStandardStreams = true exceptionFormat = 'full' From de7e35ec6686e23526893d762ebd2acabbd4532d Mon Sep 17 00:00:00 2001 From: Tomek Rozen Date: Thu, 12 Sep 2019 16:47:35 +0200 Subject: [PATCH 0174/1594] [C++] Non-printable CHAR printed as int --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 506b5d8ea3..595f46c380 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2532,7 +2532,12 @@ private CharSequence writeTokenDisplay( // have to duplicate because of checkstyle :/ if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { - sb.append(indent + "builder << '\"' << (char)" + fieldName + "() << '\"';\n"); + sb.append( + indent + "if (std::isprint(" + fieldName + "())) {\n" + + indent + " builder << '\"' << (char)" + fieldName + "() << '\"';\n" + + indent + "} else {\n" + + indent + " builder << (int)" + fieldName + "();\n" + + indent + "}\n"); } else { From 83407bad7e62c4b8ce9743d36552c6a0bbf4cfed Mon Sep 17 00:00:00 2001 From: Erik Rigtorp Date: Thu, 12 Sep 2019 20:48:21 -0700 Subject: [PATCH 0175/1594] Add descriptive name for each entry in the build matrix --- .travis.yml | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 174a881997..d5b075fc6c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,8 @@ matrix: - ./csharp/runtests.sh - ./csharp/pack.sh - - env: COMPILER=g++-5 + - name: "GCC 5" + env: COMPILER=g++-5 language: cpp compiler: gcc os: linux @@ -44,7 +45,8 @@ matrix: - ubuntu-toolchain-r-test script: ./cppbuild/cppbuild - - env: COMPILER=g++-6 + - name: "GCC 6" + env: COMPILER=g++-6 language: cpp compiler: gcc os: linux @@ -57,7 +59,8 @@ matrix: - ubuntu-toolchain-r-test script: ./cppbuild/cppbuild - - env: COMPILER=g++-7 + - name: "GCC 7" + env: COMPILER=g++-7 language: cpp compiler: gcc os: linux @@ -70,7 +73,8 @@ matrix: - ubuntu-toolchain-r-test script: ./cppbuild/cppbuild - - env: COMPILER=g++-8 + - name: "GCC 8" + env: COMPILER=g++-8 language: cpp compiler: gcc os: linux @@ -83,7 +87,8 @@ matrix: - ubuntu-toolchain-r-test script: ./cppbuild/cppbuild - - env: COMPILER=g++-9 + - name: "GCC 9" + env: COMPILER=g++-9 language: cpp compiler: gcc os: linux @@ -96,7 +101,8 @@ matrix: - ubuntu-toolchain-r-test script: ./cppbuild/cppbuild - - env: COMPILER=clang++-5.0 + - name: "Clang 5" + env: COMPILER=clang++-5.0 language: cpp compiler: clang os: linux @@ -109,7 +115,8 @@ matrix: - llvm-toolchain-xenial-5.0 script: ./cppbuild/cppbuild - - env: COMPILER=clang++-6.0 + - name: "Clang 6" + env: COMPILER=clang++-6.0 language: cpp compiler: clang os: linux @@ -122,7 +129,8 @@ matrix: - llvm-toolchain-xenial-6.0 script: ./cppbuild/cppbuild - - env: COMPILER=clang++-7 + - name: "Clang 7" + env: COMPILER=clang++-7 language: cpp compiler: clang os: linux @@ -135,7 +143,8 @@ matrix: - llvm-toolchain-xenial-7 script: ./cppbuild/cppbuild - - env: COMPILER=clang++-8 + - name: "Clang 8" + env: COMPILER=clang++-8 language: cpp compiler: clang os: linux @@ -148,7 +157,8 @@ matrix: - llvm-toolchain-xenial-8 script: ./cppbuild/cppbuild - - env: COMPILER=clang++ + - name: "macOS" + env: COMPILER=clang++ language: c++ compiler: clang os: osx From a3afc6db7779b3ecec745c1610d55102d53be488 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 13 Sep 2019 08:25:02 +0100 Subject: [PATCH 0176/1594] [Java] Upgrade to javadoc-links 4.1.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3ea5716013..ed42ca3021 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.4.1' - id 'io.freefair.javadoc-links' version '4.0.2' apply false + id 'io.freefair.javadoc-links' version '4.1.0' apply false id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } From b8f46e86bd697e07ca83fa3f01156bf5cce8bea9 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 14 Sep 2019 08:41:54 +0100 Subject: [PATCH 0177/1594] [C++] Style tidy up after merge of PR #716. --- .../sbe/generation/cpp/CppGenerator.java | 66 ++++++++----------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 595f46c380..cf4b9a146e 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2283,9 +2283,7 @@ private CharSequence generateDisplay( final List varData, final String indent) { - final StringBuilder sb = new StringBuilder(); - - sb.append(String.format("\n" + + return String.format("\n" + indent + "template\n" + indent + "friend std::basic_ostream& operator<<(\n" + indent + " std::basic_ostream& builder, %1$s _writer)\n" + @@ -2302,9 +2300,7 @@ private CharSequence generateDisplay( indent + " return builder;\n" + indent + "}\n", formatClassName(name), - appendDisplay(fields, groups, varData, indent + INDENT))); - - return sb.toString(); + appendDisplay(fields, groups, varData, indent + INDENT)); } private CharSequence generateGroupDisplay( @@ -2314,8 +2310,7 @@ private CharSequence generateGroupDisplay( final List varData, final String indent) { - final StringBuilder sb = new StringBuilder(); - sb.append(String.format("\n" + + return String.format("\n" + indent + "template\n" + indent + "friend std::basic_ostream& operator<<(\n" + indent + " std::basic_ostream& builder, %1$s writer)\n" + @@ -2326,9 +2321,7 @@ private CharSequence generateGroupDisplay( indent + " return builder;\n" + indent + "}\n", formatClassName(name), - appendDisplay(fields, groups, varData, indent + INDENT))); - - return sb.toString(); + appendDisplay(fields, groups, varData, indent + INDENT)); } private CharSequence generateCompositeDisplay( @@ -2336,9 +2329,7 @@ private CharSequence generateCompositeDisplay( final List tokens, final String indent) { - final StringBuilder sb = new StringBuilder(); - final boolean[] atLeastOne = {false}; - sb.append(String.format("\n" + + return String.format("\n" + indent + "template\n" + indent + "friend std::basic_ostream& operator<<(\n" + indent + " std::basic_ostream& builder, %1$s writer)\n" + @@ -2349,9 +2340,7 @@ private CharSequence generateCompositeDisplay( indent + " return builder;\n" + indent + "}\n\n", formatClassName(name), - appendDisplay(tokens, new ArrayList<>(), new ArrayList<>(), indent + INDENT))); - - return sb.toString(); + appendDisplay(tokens, new ArrayList<>(), new ArrayList<>(), indent + INDENT)); } private CharSequence appendDisplay( @@ -2362,6 +2351,7 @@ private CharSequence appendDisplay( { final StringBuilder sb = new StringBuilder(); final boolean[] atLeastOne = {false}; + for (int i = 0, size = fields.size(); i < size;) { final Token fieldToken = fields.get(i); @@ -2394,8 +2384,6 @@ private CharSequence appendDisplay( throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); } - sb.append(indent + "//" + groupToken + "\n"); - if (atLeastOne[0]) { sb.append( @@ -2410,7 +2398,9 @@ private CharSequence appendDisplay( indent + " writer.%2$s().forEach([&](%1$s& %2$s)\n" + indent + " {\n" + indent + " if (atLeastOne)\n" + + indent + " {\n" + indent + " builder << \", \";\n" + + indent + " }\n" + indent + " atLeastOne = true;\n" + indent + " builder << %2$s;\n" + indent + " });\n" + @@ -2420,7 +2410,6 @@ private CharSequence appendDisplay( formatPropertyName(groupToken.name()), groupToken.name())); - i = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); } @@ -2432,8 +2421,6 @@ private CharSequence appendDisplay( throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); } - sb.append(indent + "//" + varDataToken + "\n"); - if (atLeastOne[0]) { sb.append( @@ -2444,15 +2431,12 @@ private CharSequence appendDisplay( final String characterEncoding = varData.get(i + 3).encoding().characterEncoding(); final String getAsStringFunction = "get" + toUpperFirstChar(varDataToken.name()) + "AsString().c_str()"; sb.append(indent + "builder << R\"(\"" + varDataToken.name() + "\": )\";\n"); + if (null == characterEncoding) { sb.append( indent + "builder << '\"' <<\n" + indent + INDENT + "writer." + getAsStringFunction + " << '\"';\n\n"); - /*sb.append(indent + "builder << " + varDataName + "Length() << \" bytes of raw data\";\n"); - append(sb, indent, - "parentMessage.limit(parentMessage.limit() + " + varDataName + "HeaderLength() + " + - varDataName + "Length());");*/ } else { @@ -2463,7 +2447,7 @@ private CharSequence appendDisplay( i += varDataToken.componentTokenCount(); } - return sb.toString(); + return sb; } private CharSequence writeTokenDisplay( @@ -2475,8 +2459,6 @@ private CharSequence writeTokenDisplay( final StringBuilder sb = new StringBuilder(); final String fieldName = "writer." + formatPropertyName(fieldTokenName); - sb.append(indent + "//" + typeToken + "\n"); - if (typeToken.encodedLength() <= 0 || typeToken.isConstantEncoding()) { return sb.toString(); @@ -2520,7 +2502,9 @@ private CharSequence writeTokenDisplay( indent + " for (size_t i = 0; i < " + fieldName + "Length(); i++)\n" + indent + " {\n" + indent + " if (i)\n" + + indent + " {\n" + indent + " builder << ',';\n" + + indent + " }\n" + indent + " builder << +" + fieldName + "(i);\n" + indent + " }\n" + indent + "}\n" + @@ -2533,9 +2517,12 @@ private CharSequence writeTokenDisplay( if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { sb.append( - indent + "if (std::isprint(" + fieldName + "())) {\n" + + indent + "if (std::isprint(" + fieldName + "()))\n" + + indent + "{\n" + indent + " builder << '\"' << (char)" + fieldName + "() << '\"';\n" + - indent + "} else {\n" + + indent + "}\n" + + indent + "else\n" + + indent + "{\n" + indent + " builder << (int)" + fieldName + "();\n" + indent + "}\n"); } @@ -2549,15 +2536,17 @@ private CharSequence writeTokenDisplay( case BEGIN_ENUM: sb.append(indent + "builder << '\"' << " + fieldName + "() << '\"';\n"); break; + case BEGIN_SET: sb.append(indent + "builder << " + fieldName + "();\n"); break; + case BEGIN_COMPOSITE: sb.append(indent + "builder << " + fieldName + "();\n"); break; } - return sb.toString(); + return sb; } private CharSequence generateChoicesDisplay(final String name, final List tokens) @@ -2584,8 +2573,8 @@ private CharSequence generateChoicesDisplay(final String name, final List for (int i = 0, size = choiceTokens.size(); i < size; i++) { final Token token = choiceTokens.get(i); - sb.append(indent + " //" + token + "\n"); final String choiceName = "writer." + formatPropertyName(token.name()); + sb.append( indent + " if (" + choiceName + "())\n" + indent + " {\n"); @@ -2612,7 +2601,7 @@ private CharSequence generateChoicesDisplay(final String name, final List indent + " return builder;\n" + indent + "}\n"); - return sb.toString(); + return sb; } private CharSequence generateEnumDisplay(final List tokens, final Token encodingToken) @@ -2625,15 +2614,13 @@ private CharSequence generateEnumDisplay(final List tokens, final Token e " {\n" + " switch (value)\n" + " {\n", - enumName - )); + enumName)); for (final Token token : tokens) { sb.append(String.format( " case %1$s: return \"%1$s\";\n", - token.name()) - ); + token.name())); } sb.append(String.format( @@ -2648,8 +2635,7 @@ private CharSequence generateEnumDisplay(final List tokens, final Token e " {\n" + " return os << %1$s::c_str(m);\n" + " }\n", - enumName - )); + enumName)); return sb; } From ab29f889413935ef09814e0803fc50e12fb36568 Mon Sep 17 00:00:00 2001 From: Roman Ivanov Date: Sun, 11 Aug 2019 15:27:39 -0700 Subject: [PATCH 0178/1594] bump checkstyle to 8.24; checkstyle config: move LineLenght to Checker --- build.gradle | 4 ++-- config/checkstyle/checkstyle.xml | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index bb88adcff0..5753f2faf8 100644 --- a/build.gradle +++ b/build.gradle @@ -135,7 +135,7 @@ subprojects { jar.enabled = true dependencies { - checkstyle 'com.puppycrawl.tools:checkstyle:8.23' + checkstyle 'com.puppycrawl.tools:checkstyle:8.24' compile 'org.agrona:agrona:1.0.6' @@ -144,7 +144,7 @@ subprojects { testCompile 'junit:junit:4.12' } - checkstyle.toolVersion = '8.23' + checkstyle.toolVersion = '8.24' compileJava { sourceCompatibility = sbeJavaVersion diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 154e4b6217..63ad312c35 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -17,6 +17,11 @@ + + + + + @@ -59,11 +64,6 @@ - - - - - From eea5d968b7e8d9f9a33438ce84ff6cf3f0bacb25 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 16 Sep 2019 05:33:59 +0100 Subject: [PATCH 0179/1594] [Java] Javadoc typos. --- .../java/uk/co/real_logic/sbe/generation/c/COutputManager.java | 2 +- .../real_logic/sbe/generation/cpp/NamespaceOutputManager.java | 2 +- .../sbe/generation/csharp/CSharpNamespaceOutputManager.java | 2 +- .../real_logic/sbe/generation/golang/GolangOutputManager.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java index e298d5cc50..ebf85f08c9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java @@ -57,7 +57,7 @@ public COutputManager(final String baseDirName, final String namespaceName) * Create a new output which will be a C11 source file in the given package. *

    * The {@link java.io.Writer} should be closed once the caller has finished with it. The Writer is - * buffer for efficient IO operations. + * buffered for efficient IO operations. * * @param name the name of the C struct. * @return a {@link java.io.Writer} to which the source code should be written. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java index 1665e47da0..7bfa5670f7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java @@ -57,7 +57,7 @@ public NamespaceOutputManager(final String baseDirName, final String namespaceNa * Create a new output which will be a C++98 source file in the given package. *

    * The {@link java.io.Writer} should be closed once the caller has finished with it. The Writer is - * buffer for efficient IO operations. + * buffered for efficient IO operations. * * @param name the name of the C++ class. * @return a {@link java.io.Writer} to which the source code should be written. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java index 6a7b8baef6..9da1b7e813 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java @@ -64,7 +64,7 @@ public CSharpNamespaceOutputManager(final String baseDirName, final String packa * Create a new output which will be a C# source file in the given package. *

    * The {@link java.io.Writer} should be closed once the caller has finished with it. The Writer is - * buffer for efficient IO operations. + * buffered for efficient IO operations. * * @param name the name of the C# class. * @return a {@link java.io.Writer} to which the source code should be written. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java index e543a37771..db6e58c50c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java @@ -57,7 +57,7 @@ public GolangOutputManager(final String baseDirName, final String namespaceName) * Create a new output which will be a golang source file in the given package. *

    * The {@link java.io.Writer} should be closed once the caller has finished with it. The Writer is - * buffer for efficient IO operations. + * buffered for efficient IO operations. * * @param name the name of the golang class. * @return a {@link java.io.Writer} to which the source code should be written. From 9af9f3fd210f96685650c0225bb391dccb428e71 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Mon, 16 Sep 2019 08:24:00 +0100 Subject: [PATCH 0180/1594] Revert "[Java] Python generator implementation #665" --- README.md | 12 - build.gradle | 78 - python/tests/__init__.py | 0 python/tests/test_car_example.py | 192 -- python/tests/test_issue435.py | 46 - python/tests/test_issue483.py | 14 - python/tests/test_issue560.py | 23 - .../generation/python/PyOutputManager.java | 74 - .../sbe/generation/python/PyUtil.java | 284 -- .../sbe/generation/python/Python.java | 39 - .../generation/python/PythonGenerator.java | 3039 ----------------- .../generation/python/PyGeneratorTest.java | 50 - 12 files changed, 3851 deletions(-) delete mode 100644 python/tests/__init__.py delete mode 100644 python/tests/test_car_example.py delete mode 100644 python/tests/test_issue435.py delete mode 100644 python/tests/test_issue483.py delete mode 100644 python/tests/test_issue560.py delete mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyOutputManager.java delete mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java delete mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java delete mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PythonGenerator.java delete mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java diff --git a/README.md b/README.md index dc799071ff..b401e41c4d 100644 --- a/README.md +++ b/README.md @@ -118,18 +118,6 @@ Users of CSharp generated code should see the [user documentation](https://githu Developers wishing to enhance the CSharp generator should see the [developer documentation](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/README.md) -Python Build ------------- -Python support is experimental and tested against Python >= 3.6. Other python versions and implementations -should also work, given that they have support for the `struct` package and the `buffer protocol`, but they aren't -officially supported. - -Use the following the build the java stub generator and execute the python tests: -```bash -$ ./gradlew -$ ./gradlew runPythonTests -``` - License (See LICENSE file for full license) ------------------------------------------- Copyright 2013-2019 Real Logic Limited diff --git a/build.gradle b/build.gradle index f5cc3b968e..ed42ca3021 100644 --- a/build.gradle +++ b/build.gradle @@ -775,84 +775,6 @@ task uploadToMavenCentral { 'sbe-all:uploadShadow' } -/** - * Python tests and benchmarks - */ -task generatePythonCarExample(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath - systemProperties( - 'sbe.output.dir': 'python/tests', - 'sbe.target.language': 'uk.co.real_logic.sbe.generation.python.Python', - 'sbe.xinclude.aware': 'true', - 'sbe.target.namespace': 'gen.car_example') - args = ['sbe-samples/src/main/resources/example-schema.xml'] -} - -task generatePythonIssue435Codecs(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath - systemProperties( - 'sbe.output.dir': 'python/tests', - 'sbe.target.language': 'uk.co.real_logic.sbe.generation.python.Python', - 'sbe.target.namespace': 'gen.issue435') - args = ['sbe-tool/src/test/resources/issue435.xml'] -} - -task generatePythonIssue483Codecs(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath - systemProperties( - 'sbe.output.dir': 'python/tests', - 'sbe.target.language': 'uk.co.real_logic.sbe.generation.python.Python', - 'sbe.target.namespace': 'gen.issue483') - args = ['sbe-tool/src/test/resources/issue483.xml'] -} - -task generatePythonIssue560Codecs(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath - systemProperties( - 'sbe.output.dir': 'python/tests', - 'sbe.target.language': 'uk.co.real_logic.sbe.generation.python.Python', - 'sbe.target.namespace': 'gen.issue560') - args = ['sbe-tool/src/test/resources/issue560.xml'] -} - -task generatePythonFixBinaryCodecs(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath - systemProperties( - 'sbe.output.dir': 'python/tests', - 'sbe.target.language': 'uk.co.real_logic.sbe.generation.python.Python', - 'sbe.target.namespace': 'gen.fix_binary') - args = [ - 'sbe-tool/src/test/resources/FixBinary.xml', - ] -} - -task generatePythonExampleDataFile(type: JavaExec) { - mkdir "python/tests/gen/car_example" - main = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub' - classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath - systemProperties('sbe.encoding.filename': 'python/tests/gen/car_example/car_example_data.sbe') - args = [] -} - -task generatePythonCodecs { - description = 'Generate python test codecs' - delete 'python/tests/gen' - dependsOn 'generatePythonCarExample', 'generatePythonExampleDataFile', 'generatePythonIssue435Codecs', - 'generatePythonIssue483Codecs', 'generatePythonIssue560Codecs', 'generatePythonFixBinaryCodecs' -} - -task runPythonTests(type: Exec) { - workingDir = './python/' - executable = 'python' - args = ['-m','unittest','discover'] - dependsOn 'generatePythonCodecs' -} - wrapper { gradleVersion = '5.6.2' distributionType = 'ALL' diff --git a/python/tests/__init__.py b/python/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/python/tests/test_car_example.py b/python/tests/test_car_example.py deleted file mode 100644 index b900e3185c..0000000000 --- a/python/tests/test_car_example.py +++ /dev/null @@ -1,192 +0,0 @@ -import unittest -from pathlib import Path - -from tests.gen.car_example import MessageHeaderEncoder, CarEncoder, BooleanType, Model, EngineEncoder, BoostType -from tests.gen.car_example import MessageHeaderDecoder, CarDecoder, EngineDecoder - - -class TestCarExample(unittest.TestCase): - REFERENCE_FILE_ENCODE = Path(__file__).resolve().parent / Path('gen') / 'car_example' / 'car_example_data.sbe' - - VEHICLE_CODE = "abcdef".encode(CarDecoder.vehicleCodeCharacterEncoding()) - MANUFACTURER_CODE = "123".encode(EngineDecoder.manufacturerCodeCharacterEncoding()) - MANUFACTURER = "Honda".encode(CarDecoder.manufacturerCharacterEncoding()) - MODEL = "Civic VTi".encode(CarDecoder.modelCharacterEncoding()) - ACTIVATION_CODE = "abcdef".encode(CarDecoder.activationCodeCharacterEncoding()) - - CAR_ENCODER = CarEncoder() - MESSAGE_HEADER_ENCODER = MessageHeaderEncoder() - - CAR_DECODER = CarDecoder() - MESSAGE_HEADER_DECODER = MessageHeaderDecoder() - - def test_encoding(self): - with open(self.REFERENCE_FILE_ENCODE, 'rb') as f: - buffer = f.read() - py_buf = bytearray(4096) - self._encode(py_buf, self.MESSAGE_HEADER_ENCODER, self.CAR_ENCODER) - # Encoded message should match - self.assertEqual(buffer, py_buf[:207]) - # The empty part of the buffer should be all 0's - self.assertEqual(bytes(len(py_buf) - len(buffer)), py_buf[len(buffer):]) - self.assertEqual(207, len(buffer)) - - def test_decoding(self): - self.maxDiff = None - with open(self.REFERENCE_FILE_ENCODE, 'rb') as f: - buffer = f.read() - py_buf = bytearray(4096) - self._encode(py_buf, self.MESSAGE_HEADER_ENCODER, self.CAR_ENCODER) - self._decode(py_buf, self.MESSAGE_HEADER_DECODER, self.CAR_DECODER) - self._decode(buffer, self.MESSAGE_HEADER_DECODER, self.CAR_DECODER) - - def _encode(self, buf: bytearray, header: MessageHeaderEncoder, car: CarEncoder): - offset = 0 - - car.wrapAndApplyHeader(buf, offset, header) - car.serialNumber(1234) - car.modelYear(2013) - car.available(BooleanType.T) - car.code(Model.A) - car.set_vehicleCode(self.VEHICLE_CODE) - - car.someNumbers(0,1) - car.someNumbers(1,2) - car.someNumbers(2,3) - car.someNumbers(3,4) - - car.extras() \ - .clear() \ - .cruiseControl(True) \ - .sportsPack(True) \ - .sunRoof(False) - - car.engine() \ - .capacity(2000) \ - .numCylinders(4) \ - .set_manufacturerCode(self.MANUFACTURER_CODE) \ - .efficiency(35) \ - .boosterEnabled(BooleanType.T) \ - .booster() \ - .boostType(BoostType.NITROUS) \ - .horsePower(200) - - ff = car.fuelFiguresCount(3) - ff.next().speed(30).mpg(35.9).usageDescription("Urban Cycle".encode(CarEncoder.FuelFiguresEncoder - .usageDescriptionCharacterEncoding())) - ff.next().speed(55).mpg(49.0).usageDescription("Combined Cycle".encode(CarEncoder.FuelFiguresEncoder - .usageDescriptionCharacterEncoding())) - ff.next().speed(75).mpg(40.0).usageDescription("Highway Cycle".encode(CarEncoder.FuelFiguresEncoder - .usageDescriptionCharacterEncoding())) - - figures = car.performanceFiguresCount(2) - figures.next().octaneRating(95).accelerationCount(3) \ - .next().mph(30).seconds(4.0) \ - .next().mph(60).seconds(7.5) \ - .next().mph(100).seconds(12.2) - - figures.next().octaneRating(99).accelerationCount(3) \ - .next().mph(30).seconds(3.8) \ - .next().mph(60).seconds(7.1) \ - .next().mph(100).seconds(11.8) - - car.manufacturer(self.MANUFACTURER).model(self.MODEL).activationCode(self.ACTIVATION_CODE) - - return header.encodedLength + car.encodedLength - - def _decode(self, buf: bytes, header: MessageHeaderDecoder, car: CarDecoder): - offset = 0 - out = "" - header.wrap(buf, offset) - template_id = header.templateId() - if template_id != car.sbeTemplateId: - raise Exception("Template ID missmatch") - acting_block_length = header.blockLength() - acting_block_version = header.version() - offset += header.encodedLength - - car.wrap(buf, offset, acting_block_length, acting_block_version) - self.assertEqual(1234, car.serialNumber()) - self.assertEqual(2013, car.modelYear()) - self.assertEqual(BooleanType.T, car.available()) - self.assertEqual(Model.A, car.code()) - self.assertEqual((1, 2, 3, 4), car.getMultiSomeNumbers()) - self.assertEqual(1, car.someNumbers(0)) - self.assertEqual(2, car.someNumbers(1)) - self.assertEqual(3, car.someNumbers(2)) - self.assertEqual(4, car.someNumbers(3)) - index_oob = False - try: - car.someNumbers(55) - except IndexError as e: - index_oob = True - self.assertEqual(IndexError, type(e)) - self.assertTrue(index_oob) - - self.assertEqual("abcdef", str(car.getMultiVehicleCode(), car.vehicleCodeCharacterEncoding())) - - extras = car.extras() - self.assertTrue(extras.cruiseControl()) - self.assertTrue(extras.sportsPack()) - self.assertFalse(extras.sunRoof()) - - self.assertEqual("C", car.discountedModel().name) - - engine = car.engine() - self.assertEqual(2000, engine.capacity()) - self.assertEqual(4, engine.numCylinders()) - self.assertEqual(9000, engine.maxRpm) - self.assertEqual("123", str(engine.getMultiManufacturerCode(), EngineDecoder.manufacturerCodeCharacterEncoding())) - self.assertEqual(35, engine.efficiency()) - self.assertEqual(BooleanType.T, engine.boosterEnabled()) - self.assertEqual(BoostType.NITROUS, engine.booster().boostType()) - self.assertEqual(200, engine.booster().horsePower()) - - self.assertEqual("Petrol", str(engine.getFuel(0, len(buf)).tobytes().decode())) - - ff = car.fuelFigures() - ff.next() - self.assertEqual(30, ff.speed()) - self.assertAlmostEqual(35.9, ff.mpg(), places=5) - self.assertEqual("Urban Cycle", ff.usageDescription()) - ff.next() - self.assertEqual(55, ff.speed()) - self.assertAlmostEqual(49.0, ff.mpg(), places=5) - self.assertEqual("Combined Cycle", ff.usageDescription()) - ff.next() - self.assertEqual(75, ff.speed()) - self.assertAlmostEqual(40.0, ff.mpg(), places=5) - self.assertEqual("Highway Cycle", ff.usageDescription()) - - pf = car.performanceFigures() - pf.next() - self.assertEqual(95, pf.octaneRating()) - pfa = pf.acceleration() - pfa.next() - self.assertEqual(30, pfa.mph()) - self.assertAlmostEqual(4.0, pfa.seconds(), places=5) - pfa.next() - self.assertEqual(60, pfa.mph()) - self.assertAlmostEqual(7.5, pfa.seconds(), places=5) - pfa.next() - self.assertEqual(100, pfa.mph()) - self.assertAlmostEqual(12.2, pfa.seconds(), places=5) - - pf.next() - self.assertEqual(99, pf.octaneRating()) - pfa = pf.acceleration() - pfa.next() - self.assertEqual(30, pfa.mph()) - self.assertAlmostEqual(3.8, pfa.seconds(), places=5) - pfa.next() - self.assertEqual(60, pfa.mph()) - self.assertAlmostEqual(7.1, pfa.seconds(), places=5) - pfa.next() - self.assertEqual(100, pfa.mph()) - self.assertAlmostEqual(11.8, pfa.seconds(), places=5) - - self.assertEqual("Honda", car.manufacturer()) - self.assertEqual("Civic VTi", car.model()) - self.assertEqual("abcdef", car.activationCode()) - self.assertEqual(199, car.encodedLength) - return out diff --git a/python/tests/test_issue435.py b/python/tests/test_issue435.py deleted file mode 100644 index 40a0237a12..0000000000 --- a/python/tests/test_issue435.py +++ /dev/null @@ -1,46 +0,0 @@ -import unittest - -from tests.gen.issue435.message_header_encoder import * -from tests.gen.issue435.message_header_decoder import * -from tests.gen.issue435.issue435_encoder import * -from tests.gen.issue435.issue435_decoder import * - - -class TestIssue435(unittest.TestCase): - - def setUp(self) -> None: - self._buffer = bytearray(4096) - self._messageHeader = MessageHeaderEncoder() - self._messageHeaderDecoder = MessageHeaderDecoder() - self._issue435 = Issue435Encoder() - self._issue435_decoder = Issue435Decoder() - self._messageHeader.wrap(self._buffer, 0) - self._messageHeader.version(self._issue435.sbeSchemaVersion) - self._messageHeader.blockLength(self._issue435.sbeBlockLength) - self._messageHeader.schemaId(self._issue435.sbeSchemaId) - self._messageHeader.templateId(self._issue435.sbeTemplateId) - - #< ref > element in non - standard - set_s = self._messageHeader.s() - set_s.one(True) - - def test_non_standard_header_size(self): - self.assertEqual(9, self._messageHeader.encodedLength) - - def test_issue435_ref_test(self): - self._issue435.wrap(self._buffer, self._messageHeader.encodedLength) - ex = self._issue435.example() - ex.e(EnumRef.Two) - self.assertEqual(1, self._issue435.sbeBlockLength) - self._messageHeaderDecoder.wrap(self._buffer, 0) - self._messageHeader.wrap(self._buffer, 0) - self.assertEqual(self._issue435.sbeBlockLength, self._messageHeaderDecoder.blockLength(), "Incorrect BlockLength") - self.assertEqual(self._issue435.sbeSchemaId, self._messageHeaderDecoder.schemaId(), "Incorrect SchemaId") - self.assertEqual(self._issue435.sbeTemplateId, self._messageHeaderDecoder.templateId(), "Incorrect TemplateId") - self.assertEqual(self._issue435.sbeSchemaVersion, self._messageHeaderDecoder.version(), "Incorrect SchemaVersion") - self.assertTrue(self._messageHeaderDecoder.s().one(), "Incorrect SetRef.One") - - self._issue435_decoder.wrap(self._buffer, self._messageHeader.encodedLength, self._messageHeaderDecoder.blockLength(), - self._messageHeaderDecoder.version()) - - self.assertEqual(EnumRef.Two, self._issue435_decoder.example().e(), "Incorrect EnuRef"); diff --git a/python/tests/test_issue483.py b/python/tests/test_issue483.py deleted file mode 100644 index d18184784d..0000000000 --- a/python/tests/test_issue483.py +++ /dev/null @@ -1,14 +0,0 @@ -import unittest - -from tests.gen.issue483.issue483_encoder import * -from tests.gen.issue483.issue483_decoder import * - - -class TestIssue483(unittest.TestCase): - - def test_presense(self): - # Check attributes for their presence meta attribute - self.assertEqual(Issue483Encoder.unsetMetaAttribute(MetaAttribute.Presence), "required") - self.assertEqual(Issue483Encoder.requiredMetaAttribute(MetaAttribute.Presence), "required") - self.assertEqual(Issue483Encoder.constantMetaAttribute(MetaAttribute.Presence), "constant") - self.assertEqual(Issue483Encoder.optionalMetaAttribute(MetaAttribute.Presence), "optional") diff --git a/python/tests/test_issue560.py b/python/tests/test_issue560.py deleted file mode 100644 index 5e0de72a26..0000000000 --- a/python/tests/test_issue560.py +++ /dev/null @@ -1,23 +0,0 @@ -import unittest - -from tests.gen.issue560 import Model -from tests.gen.issue560.issue560_encoder import Issue560Encoder -from tests.gen.issue560.issue560_decoder import Issue560Decoder -from tests.gen.issue560.message_header_encoder import MessageHeaderEncoder - - -class TestIssue560(unittest.TestCase): - - def setUp(self) -> None: - self._buffer = bytearray(4096) - self._issue560 = Issue560Encoder() - self._issue560_decoder = Issue560Decoder() - self._header = MessageHeaderEncoder() - self._header.wrap(self._buffer, 0) - self._header.blockLength(self._issue560.BLOCK_LENGTH) - self._header.schemaId(self._issue560.SCHEMA_ID) - self._header.templateId(self._issue560.TEMPLATE_ID) - self._header.version(self._issue560.SCHEMA_VERSION) - - def test_const_enum(self): - self.assertEqual(self._issue560_decoder.discountedModel(), Model.C, "Incorrect const enum valueref") \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyOutputManager.java deleted file mode 100644 index bfdf3e00b5..0000000000 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyOutputManager.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2013-2019 Real Logic Ltd. - * Copyright (C) 2017 MarketFactory, Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.generation.python; - -import org.agrona.Verify; -import org.agrona.generation.OutputManager; - -import java.io.File; -import java.io.IOException; -import java.io.Writer; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; - -import static java.io.File.separatorChar; - -/** - * The character encoding for the {@link Writer} is UTF-8. - */ -public class PyOutputManager implements OutputManager -{ - private final File outputDir; - - /** - * Create a new {@link OutputManager} for generating C# source - * files into a given package. - * - * @param baseDirName for the generated source code. - * @param packageName for the generated source code relative to the baseDirName. - */ - public PyOutputManager(final String baseDirName, final String packageName) - { - Verify.notNull(baseDirName, "baseDirName"); - Verify.notNull(packageName, "packageName"); - final String dirName = baseDirName.endsWith("" + separatorChar) ? baseDirName : baseDirName + separatorChar; - final String packageDirName = dirName + packageName.replace('.', File.separatorChar); - - outputDir = new File(packageDirName); - if (!outputDir.exists() && !outputDir.mkdirs()) - { - throw new IllegalStateException("Unable to create directory: " + packageDirName); - } - - } - - /** - * Create a new output which will be a C# source file in the given package. - *

    - * The {@link Writer} should be closed once the caller has finished with it. The Writer is - * buffer for efficient IO operations. - * - * @param name the name of the C# class. - * @return a {@link Writer} to which the source code should be written. - * @throws IOException if an issue occurs when creating the file. - */ - public Writer createOutput(final String name) throws IOException - { - final File targetFile = new File(outputDir, name + ".py"); - return Files.newBufferedWriter(targetFile.toPath(), StandardCharsets.UTF_8); - } -} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java deleted file mode 100644 index 64ce612830..0000000000 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PyUtil.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright 2013-2019 Real Logic Ltd. - * Copyright (C) 2017 MarketFactory, Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.generation.python; - -import uk.co.real_logic.sbe.PrimitiveType; -import uk.co.real_logic.sbe.ir.Token; - -import java.nio.ByteOrder; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Pattern; - -/** - * Utilities for mapping between IR and Python - */ -public class PyUtil -{ - public static final Map PRIMITIVE_TYPE_STRING_ENUM_MAP = new EnumMap<>(PrimitiveType.class); - public static final Map PRIMITIVE_TYPE_STRUCT_ENUM_MAP = new EnumMap<>(PrimitiveType.class); - public static final Map PRIMITIVE_TYPE_SIZE_ENUM_MAP = new EnumMap<>(PrimitiveType.class); - public static final Map BYTE_ORDER_STRING_MAP = new HashMap<>(); - public static final Pattern CAM_SNAKE_PATTERN = Pattern.compile("([^_A-Z])([A-Z])"); - - // Ref: https://docs.python.org/3.7/library/struct.html#format-characters - static - { - PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.CHAR, "bytes"); - PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.CHAR, "s"); - PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.CHAR, 1); - PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.INT8, "int"); - PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.INT8, "b"); - PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.INT8, 1); - PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.INT16, "int"); - PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.INT16, "h"); - PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.INT16, 2); - PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.INT32, "int"); - PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.INT32, "i"); - PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.INT32, 4); - PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.INT64, "int"); - PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.INT64, "q"); - PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.INT64, 8); - PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.UINT8, "int"); - PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.UINT8, "B"); - PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.UINT8, 1); - PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.UINT16, "int"); - PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.UINT16, "H"); - PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.UINT16, 2); - PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.UINT32, "int"); - PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.UINT32, "I"); - PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.UINT32, 4); - PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.UINT64, "int"); - PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.UINT64, "Q"); - PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.UINT64, 8); - PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.FLOAT, "float"); - PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.FLOAT, "f"); - PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.FLOAT, 4); - PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.DOUBLE, "float"); - PRIMITIVE_TYPE_STRUCT_ENUM_MAP.put(PrimitiveType.DOUBLE, "d"); - PRIMITIVE_TYPE_SIZE_ENUM_MAP.put(PrimitiveType.DOUBLE, 8); - BYTE_ORDER_STRING_MAP.put(ByteOrder.LITTLE_ENDIAN, "<"); - BYTE_ORDER_STRING_MAP.put(ByteOrder.BIG_ENDIAN, ">"); - } - - public enum Separators - { - BEGIN_GROUP('['), - END_GROUP(']'), - BEGIN_COMPOSITE('('), - END_COMPOSITE(')'), - BEGIN_SET('{'), - END_SET('}'), - BEGIN_ARRAY('['), - END_ARRAY(']'), - FIELD('|'), - KEY_VALUE('='), - ENTRY(','); - - public final char symbol; - - Separators(final char symbol) - { - this.symbol = symbol; - } - - /** - * Add separator to a generated StringBuilder - * - * @param builder the code generation builder to which information should be added - * @param indent the current generated code indentation - * @param builderName of the generated StringBuilder to which separator should be added - */ - public void appendToGeneratedBuilder(final StringBuilder builder, final String indent, final String builderName) - { - append(builder, indent, builderName + " += str('" + symbol + "')"); - } - - public String toString() - { - return String.valueOf(symbol); - } - } - - /** - * Map the name of a {@link PrimitiveType} to a Python C primitive type name. - * - * @param primitiveType to map. - * @return the name of the Python struct primitive that most closely maps. - */ - public static String pythonTypeName(final PrimitiveType primitiveType) - { - return PRIMITIVE_TYPE_STRING_ENUM_MAP.get(primitiveType); - } - - /** - * https://docs.python.org/3/library/struct.html - * - * @param primitiveType SBE primitive type - * @return A string representation for python c struct unpacking - */ - public static String pythonTypeCode(final PrimitiveType primitiveType) - { - return PRIMITIVE_TYPE_STRUCT_ENUM_MAP.get(primitiveType); - } - - /** - * https://docs.python.org/3/library/struct.html - * - * @param byteOrder byte order for convertion from Java enum to python string - * @return python struct unpacking code for endianess - */ - public static String pythonEndianCode(final ByteOrder byteOrder) - { - return BYTE_ORDER_STRING_MAP.get(byteOrder); - } - - /** - * Uppercase the first character of a given String. - * - * @param str to have the first character upper cased. - * @return a new String with the first character in uppercase. - */ - public static String toUpperFirstChar(final String str) - { - return Character.toUpperCase(str.charAt(0)) + str.substring(1); - } - - /** - * Lowercase the first character of a given String. - * - * @param str to have the first character upper cased. - * @return a new String with the first character in uppercase. - */ - public static String toLowerFirstChar(final String str) - { - return Character.toLowerCase(str.charAt(0)) + str.substring(1); - } - - /** - * Format a String as a property name. - * - * @param str to be formatted. - * @return the string formatted as a property name. - */ - public static String formatPropertyName(final String str) - { - return toLowerFirstChar(str); - } - - /** - * Format a String as a class name. - * - * @param str to be formatted. - * @return the string formatted as a class name. - */ - public static String formatClassName(final String str) - { - return toUpperFirstChar(str); - } - - /** - * Format a String as a module name. - * - * @param str to be formatted. - * @return the string formatted as a class name. - */ - public static String formatModuleName(final String str) - { - return camToSnake(str); - } - - /** - * Converts CamelCase to snake_case, which is the recommended python case - * - * @param str string to transform - * @param toUpperFirst whether to make the first char upper case first - * @return transformed string - */ - public static String camToSnake(final String str, final boolean toUpperFirst) - { - if (toUpperFirst) - { - return CAM_SNAKE_PATTERN.matcher(toUpperFirstChar(str)).replaceAll("$1_$2").toLowerCase(); - } - return CAM_SNAKE_PATTERN.matcher(str).replaceAll("$1_$2").toLowerCase(); - } - - /** - * @param str string to transform - * @return transformed strings with toUpper applied - */ - public static String camToSnake(final String str) - { - return camToSnake(str, true); - } - - public static String generatePyDoc(final String indend, final Token token) - { - return ""; - } - - public static String generateLiteral(final PrimitiveType type, final String value) - { - String literal = ""; - - switch (type) - { - case CHAR: - literal = "\"" + value + "\""; - break; - case UINT8: - case INT8: - case INT16: - case UINT16: - case UINT32: - case INT64: - case INT32: - literal = value; - break; - case UINT64: - literal = Long.toUnsignedString(Long.parseLong(value)); - break; - case FLOAT: - case DOUBLE: - if (value.endsWith("NaN")) - { - literal = "float('nan')"; - } - else - { - literal = value; - } - break; - } - - return literal; - } - - /** - * Shortcut to append a line of generated code - * - * @param builder string builder to which to append the line - * @param indent current text indentation - * @param line line to be appended - */ - public static void append(final StringBuilder builder, final String indent, final String line) - { - builder.append(indent).append(line).append('\n'); - } -} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java deleted file mode 100644 index cd1e4b297b..0000000000 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/Python.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2013-2019 Real Logic Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.generation.python; - -import uk.co.real_logic.sbe.generation.CodeGenerator; -import uk.co.real_logic.sbe.generation.TargetCodeGenerator; -import uk.co.real_logic.sbe.ir.Ir; - -/** - * This class is present largely to enable the dynamic-loading style pattern - * of specifying a TargetCodeGenerator Java class name rather than the language - * name. - */ -public class Python implements TargetCodeGenerator -{ - public CodeGenerator newInstance(final Ir ir, final String outputDir) - { - return defaultPythonGenerator(ir, outputDir); - } - - public static CodeGenerator defaultPythonGenerator(final Ir ir, final String outputDir) - { - return new PythonGenerator(ir, false, false, - false, new PyOutputManager(outputDir, ir.applicableNamespace())); - } -} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PythonGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PythonGenerator.java deleted file mode 100644 index ff828fa906..0000000000 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/python/PythonGenerator.java +++ /dev/null @@ -1,3039 +0,0 @@ -/* - * Copyright 2013-2019 Real Logic Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.generation.python; - -import org.agrona.Verify; -import org.agrona.generation.OutputManager; -import uk.co.real_logic.sbe.PrimitiveType; -import uk.co.real_logic.sbe.generation.CodeGenerator; -import uk.co.real_logic.sbe.generation.Generators; -import uk.co.real_logic.sbe.ir.*; - -import java.io.IOException; -import java.io.Writer; -import java.nio.ByteOrder; -import java.util.*; -import java.util.function.Function; - -import static java.util.stream.Collectors.joining; -import static uk.co.real_logic.sbe.generation.python.PyUtil.*; -import static uk.co.real_logic.sbe.ir.GenerationUtil.*; - -public class PythonGenerator implements CodeGenerator -{ - enum CodecType - { - DECODER, - ENCODER, - NONE - } - - private static final String META_ATTRIBUTE_ENUM = "MetaAttribute"; - private static final String BASE_INDENT = ""; - private static final String INDENT = " "; - private static final String FLYWEIGHT = "Flyweight"; - private static final String COMPOSITE_DECODER_FLYWEIGHT = "CompositeDecoderFlyweight"; - private static final String COMPOSITE_ENCODER_FLYWEIGHT = "CompositeEncoderFlyweight"; - private static final String MESSAGE_DECODER_FLYWEIGHT = "MessageDecoderFlyweight"; - private static final String MESSAGE_ENCODER_FLYWEIGHT = "MessageEncoderFlyweight"; - - private final Ir ir; - private final OutputManager outputManager; - private final String fqMutableBuffer; - private final String mutableBuffer; - private final String fqReadOnlyBuffer; - private final String readOnlyBuffer; - private final boolean shouldGenerateGroupOrderAnnotation; - private final boolean shouldGenerateInterfaces; - private final boolean shouldDecodeUnknownEnumValues; - - public PythonGenerator( - final Ir ir, - final boolean shouldGenerateGroupOrderAnnotation, - final boolean shouldGenerateInterfaces, - final boolean shouldDecodeUnknownEnumValues, - final OutputManager outputManager) - { - Verify.notNull(ir, "ir"); - Verify.notNull(outputManager, "outputManager"); - - this.ir = ir; - this.outputManager = outputManager; - - this.fqMutableBuffer = "bytearray"; - this.mutableBuffer = "bytearray"; - - this.readOnlyBuffer = "bytes"; - this.fqReadOnlyBuffer = "bytes"; - - this.shouldGenerateGroupOrderAnnotation = shouldGenerateGroupOrderAnnotation; - this.shouldGenerateInterfaces = shouldGenerateInterfaces; - this.shouldDecodeUnknownEnumValues = shouldDecodeUnknownEnumValues; - } - - - private String encoderName(final String className) - { - return className + "Encoder"; - } - - private String decoderName(final String className) - { - return className + "Decoder"; - } - - private String implementsInterface(final String interfaceName) - { - if (shouldGenerateInterfaces) - { - throw new RuntimeException("Python codec doesn't support interfaces"); - } - return ""; - } - - public void generateMessageHeaderStub() throws IOException - { - generateComposite(ir.headerStructure().tokens()); - } - - public void generateTypeStubs() throws IOException - { - generateMetaAttributeEnum(); - - for (final List tokens : ir.types()) - { - switch (tokens.get(0).signal()) - { - case BEGIN_ENUM: - generateEnum(tokens); - break; - - case BEGIN_SET: - generateBitSet(tokens); - break; - - case BEGIN_COMPOSITE: - generateComposite(tokens); - break; - } - } - } - - public void generate() throws IOException - { - generateStructParsers(); - generateTypeStubs(); - generateMessageHeaderStub(); - final List modules = new ArrayList<>(ir.messages().size()); - for (final List tokens : ir.messages()) - { - final Token msgToken = tokens.get(0); - final List messageBody = getMessageBody(tokens); - - int i = 0; - final List fields = new ArrayList<>(); - i = collectFields(messageBody, i, fields); - - final List groups = new ArrayList<>(); - i = collectGroups(messageBody, i, groups); - - final List varData = new ArrayList<>(); - collectVarData(messageBody, i, varData); - - generateDecoder(BASE_INDENT, fields, groups, varData, msgToken, messageBody); - generateEncoder(BASE_INDENT, fields, groups, varData, msgToken, messageBody); - - final String className = formatClassName(msgToken.name()); - final String pyModuleName = camToSnake(className); - modules.add(pyModuleName); - } - generatePackageDefinition(modules); - } - - public void generatePackageDefinition(final List modules) throws IOException - { - try (Writer out = outputManager.createOutput("__init__")) - { - out.append(generateMainHeader(ir.applicableNamespace(), new ArrayList<>(), CodecType.NONE)); - for (final String m : modules) - { - out.append("from .").append(m).append("_encoder import *\n"); - out.append("from .").append(m).append("_decoder import *\n"); - } - out.append("from .meta_attribute import *\n"); - } - } - - private void generateStructParsers() throws IOException - { - try (Writer out = outputManager.createOutput("_struct_defs")) - { - out.append(generateMainHeader(ir.applicableNamespace(), new ArrayList<>(), CodecType.NONE)); - out.append("from struct import Struct\n\n"); - final StringBuilder builder = new StringBuilder(); - for (final Map.Entry order : BYTE_ORDER_STRING_MAP.entrySet()) - { - for (final Map.Entry type : PRIMITIVE_TYPE_STRUCT_ENUM_MAP.entrySet()) - { - builder.append(String.format("%2$S_%1$S: Struct = Struct('%3$s%4$s')\n", - type.getKey().primitiveName(), - order.getKey().toString(), - pythonEndianCode(order.getKey()), - pythonTypeCode(type.getKey()))); - } - //edge case to handle char[] unpacking - builder.append(String.format("%2$S_%1$S: Struct = Struct('%3$s%4$s')\n", - "CHARS", - order.getKey().toString(), - pythonEndianCode(order.getKey()), - "s")); - } - - builder.append("\n"); - out.append(builder.toString()); - } - } - - private void generateEncoder( - final String indent, - final List fields, - final List groups, - final List varData, - final Token msgToken, - final List msgBody) throws IOException - { - final String className = formatClassName(encoderName(msgToken.name())); - final String moduleName = formatModuleName(className); - final String implementsString = implementsInterface(MESSAGE_ENCODER_FLYWEIGHT); - - try (Writer out = outputManager.createOutput(moduleName)) - { - out.append(generateMainHeader(ir.applicableNamespace(), msgBody, CodecType.ENCODER)); - - generateAnnotations(indent, className, groups, out, 0, this::encoderName); - out.append(generateDeclaration(className, implementsString, msgToken)); - out.append(generateEncoderFlyweightCode(className, msgToken)); - out.append(generateEncoderFields(className, fields, indent)); - - final StringBuilder sb = new StringBuilder(); - generateEncoderGroups(sb, className, className, groups, indent, false); - out.append(sb); - - out.append(generateEncoderVarData(className, varData, indent)); - - } - } - - private void generateDecoder( - final String indent, - final List fields, - final List groups, - final List varData, - final Token msgToken, - final List msgBody) throws IOException - { - final String className = formatClassName(decoderName(msgToken.name())); - final String moduleName = formatModuleName(className); - final String implementsString = implementsInterface(MESSAGE_DECODER_FLYWEIGHT); - - try (Writer out = outputManager.createOutput(moduleName)) - { - out.append(generateMainHeader(ir.applicableNamespace(), msgBody, CodecType.DECODER)); - - generateAnnotations(indent, className, groups, out, 0, this::decoderName); - out.append(generateDeclaration(className, implementsString, msgToken)); - out.append(generateDecoderFlyweightCode(className, msgToken)); - out.append(generateDecoderFields(fields, indent)); - - final StringBuilder sb = new StringBuilder(); - generateDecoderGroups(sb, className, className, groups, indent, false); - out.append(sb); - - out.append(generateDecoderVarData(varData, indent)); - - out.append(generateDecoderDisplay(msgToken.name(), fields, groups, varData, indent)); - - } - } - - private void generateDecoderGroups( - final StringBuilder sb, - final String outerClassName, - final String hierarchyName, - final List tokens, - final String indent, - final boolean isSubGroup) throws IOException - { - for (int i = 0, size = tokens.size(); i < size; i++) - { - final Token groupToken = tokens.get(i); - if (groupToken.signal() != Signal.BEGIN_GROUP) - { - throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); - } - - final int groupIndex = i; - final String groupName = decoderName(formatClassName(groupToken.name())); - - ++i; - final int groupHeaderTokenCount = tokens.get(i).componentTokenCount(); - i += groupHeaderTokenCount; - - final List fields = new ArrayList<>(); - i = collectFields(tokens, i, fields); - - final List groups = new ArrayList<>(); - i = collectGroups(tokens, i, groups); - - final List varData = new ArrayList<>(); - i = collectVarData(tokens, i, varData); - final String fullyQualifiedName = hierarchyName + '.' + groupName; - - generateAnnotations(indent + INDENT, groupName, tokens, sb, groupIndex + 1, this::decoderName); - generateGroupDecoderClassHeader(sb, groupName, outerClassName, fullyQualifiedName, tokens, groups, - groupIndex, indent + INDENT); - - sb.append(generateDecoderFields(fields, indent + INDENT)); - generateDecoderGroups(sb, outerClassName, fullyQualifiedName, groups, indent + INDENT, true); - sb.append(generateDecoderVarData(varData, indent + INDENT)); - - appendGroupInstanceDecoderDisplay(sb, fields, groups, varData, indent + INDENT); - - sb.append(generateGroupDecoderProperty(groupName, fullyQualifiedName, groupToken, indent, isSubGroup)); - - sb.append("\n"); - } - } - - private void generateEncoderGroups( - final StringBuilder sb, - final String outerClassName, - final String hierarchyName, - final List tokens, - final String indent, - final boolean isSubGroup) throws IOException - { - for (int i = 0, size = tokens.size(); i < size; i++) - { - final Token groupToken = tokens.get(i); - if (groupToken.signal() != Signal.BEGIN_GROUP) - { - throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); - } - - final int groupIndex = i; - final String groupName = groupToken.name(); - final String groupClassName = formatClassName(encoderName(groupName)); - - ++i; - final int groupHeaderTokenCount = tokens.get(i).componentTokenCount(); - i += groupHeaderTokenCount; - - final List fields = new ArrayList<>(); - i = collectFields(tokens, i, fields); - - final List groups = new ArrayList<>(); - i = collectGroups(tokens, i, groups); - - final List varData = new ArrayList<>(); - i = collectVarData(tokens, i, varData); - final String fullyQualifiedName = hierarchyName + '.' + groupClassName; - - generateAnnotations(indent + INDENT, groupClassName, tokens, sb, groupIndex + 1, this::encoderName); - generateGroupEncoderClassHeader(sb, groupName, outerClassName, fullyQualifiedName, tokens, groups, - groupIndex, indent + INDENT); - - sb.append(generateEncoderFields(fullyQualifiedName, fields, indent + INDENT)); - generateEncoderGroups(sb, outerClassName, fullyQualifiedName, groups, indent + INDENT, true); - sb.append(generateEncoderVarData(fullyQualifiedName, varData, indent + INDENT)); - - sb.append(generateGroupEncoderProperty(groupName, fullyQualifiedName, groupToken, indent, isSubGroup)); - - sb.append(indent).append("\n"); - } - } - - private void generateGroupDecoderClassHeader( - final StringBuilder sb, - final String groupName, - final String parentMessageClassName, - final String fullyQualifiedClassName, - final List tokens, - final List subGroupTokens, - final int index, - final String indent) - { - final Token groupToken = tokens.get(index); - final int dimensionHeaderLen = tokens.get(index + 1).encodedLength(); - - final Token blockLengthToken = Generators.findFirst("blockLength", tokens, index); - final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); - - final PrimitiveType blockLengthType = blockLengthToken.encoding().primitiveType(); - final String blockLengthOffset = "limit + " + blockLengthToken.offset(); - final String blockLengthGet = generateGet( - blockLengthType, blockLengthOffset, byteOrderString(blockLengthToken.encoding())); - - final PrimitiveType numInGroupType = numInGroupToken.encoding().primitiveType(); - final String numInGroupOffset = "limit + " + numInGroupToken.offset(); - final String numInGroupGet = generateGet( - numInGroupType, numInGroupOffset, byteOrderString(numInGroupToken.encoding())); - - generateGroupDecoderClassDeclaration( - sb, - groupToken, - groupName, - parentMessageClassName, - findSubGroupNames(subGroupTokens), - indent, - dimensionHeaderLen); - - sb.append(String.format( - "\n" + - indent + " def wrap(self, buffer: '%1$s', parentMessage: '%4$s'):\n" + - indent + " if buffer != self._buffer:\n" + - indent + " self._buffer = buffer\n" + - indent + " self._index: int = -1\n" + - indent + " self._parentMessage = parentMessage\n" + - indent + " limit: int = self._parentMessage.limit\n" + - indent + " self._parentMessage.set_limit(limit + self.HEADER_SIZE)\n" + - indent + " self._blockLength: int = %2$s\n" + - indent + " self._count: int = %3$s\n", - readOnlyBuffer, - blockLengthGet, - numInGroupGet, - parentMessageClassName)); - - final int blockLength = tokens.get(index).encodedLength(); - - sb.append(indent).append(" @property\n") - .append(indent).append(" def sbeHeaderSize(self) -> int:\n") - .append(indent).append(" return self.HEADER_SIZE\n"); - - sb.append(String.format("\n" + - indent + " @property\n" + - indent + " def sbeBlockLength(self) -> int:\n" + - indent + " return %d\n", - blockLength)); - - sb.append(String.format("\n" + - indent + " def actingBlockLength(self) -> int:\n" + - indent + " return self._blockLength\n" + - indent + " \n\n" + - indent + " def count(self) -> int:\n" + - indent + " return self._count\n" + - indent + " \n\n" + - indent + " def remove(self):\n" + - indent + " raise NotImplementedError()\n" + - indent + " \n\n" + - indent + " def hasNext(self) -> bool:\n" + - indent + " return (self._index + 1) < self._count\n" + - indent + " \n", - formatClassName(fullyQualifiedClassName))); - - sb.append(String.format("\n" + - indent + " def next(self) -> '%s':\n" + - indent + " if self._index + 1 >= self._count:\n" + - indent + " raise KeyError()\n" + - indent + " \n\n" + - indent + " self._offset: int = self._parentMessage.limit\n" + - indent + " self._parentMessage.set_limit(self._offset + self._blockLength)\n" + - indent + " self._index += 1\n\n" + - indent + " return self\n" + - indent + " \n", - formatClassName(fullyQualifiedClassName))); - } - - private void generateGroupEncoderClassHeader( - final StringBuilder sb, - final String groupName, - final String parentMessageClassName, - final String hierarchyName, - final List tokens, - final List subGroupTokens, - final int index, - final String ind) - { - final Token groupToken = tokens.get(index); - final int dimensionHeaderSize = tokens.get(index + 1).encodedLength(); - - generateGroupEncoderClassDeclaration( - sb, - groupToken, - groupName, - parentMessageClassName, - hierarchyName, - findSubGroupNames(subGroupTokens), - ind, - dimensionHeaderSize); - - final int blockLength = tokens.get(index).encodedLength(); - final Token blockLengthToken = Generators.findFirst("blockLength", tokens, index); - final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); - - final PrimitiveType blockLengthType = blockLengthToken.encoding().primitiveType(); - final String blockLengthOffset = "limit + " + blockLengthToken.offset(); - final String blockLengthValue = String.valueOf(blockLength); - final String blockLengthPut = generatePut( - blockLengthType, blockLengthOffset, blockLengthValue, byteOrderString(blockLengthToken.encoding())); - - final PrimitiveType numInGroupType = numInGroupToken.encoding().primitiveType(); - final String numInGroupOffset = "limit + " + numInGroupToken.offset(); - final String numInGroupValue = "count"; - final String numInGroupPut = generatePut( - numInGroupType, numInGroupOffset, numInGroupValue, byteOrderString(numInGroupToken.encoding())); - - sb.append(String.format( - ind + " def wrap(self, buffer: %2$s, parentMessage: '%1$s', count: int):\n" + - ind + " if count < %3$d or count > %4$d:\n" + - ind + " raise IndexError(\"count outside allowed range: count=\" + str(count))\n" + - ind + " \n\n" + - ind + " if buffer != self._buffer:\n" + - ind + " self._buffer = buffer\n" + - ind + " \n\n" + - ind + " self._index = -1\n" + - ind + " self._parentMessage = parentMessage\n" + - ind + " self._count = count\n" + - ind + " limit: int = self._parentMessage.limit\n" + - ind + " self._parentMessage.set_limit(limit + self.HEADER_SIZE)\n" + - ind + " %5$s\n" + - ind + " %6$s\n" + - ind + " \n\n", - parentMessageClassName, - mutableBuffer, - numInGroupToken.encoding().applicableMinValue().longValue(), - numInGroupToken.encoding().applicableMaxValue().longValue(), - blockLengthPut, - numInGroupPut)); - - sb.append(ind).append(" @property\n") - .append(ind).append(" def sbeHeaderSize(self) -> int:\n") - .append(ind).append(" return self.HEADER_SIZE\n"); - - sb.append(String.format("\n" + - ind + " @property\n" + - ind + " def sbeBlockLength(self) -> int:\n" + - ind + " return %d\n", - blockLength)); - - sb.append(String.format("\n" + - ind + " def next(self) -> '%s':\n" + - ind + " if self._index + 1 >= self._count:\n" + - ind + " raise IndexError('Index ' + str(self._index) + 'out of bounds ' + str(self._count))\n" + - ind + " \n\n" + - ind + " self._offset= self._parentMessage.limit\n" + - ind + " self._parentMessage.set_limit(self._offset + self.sbeBlockLength)\n" + - ind + " self._index += 1\n\n" + - ind + " return self\n" + - ind + " \n", - hierarchyName)); - } - - private static String primitiveTypeName(final Token token) - { - return pythonTypeName(token.encoding().primitiveType()); - } - - private void generateGroupDecoderClassDeclaration( - final StringBuilder sb, - final Token groupToken, - final String groupName, - final String parentMessageClassName, - final List subGroupNames, - final String indent, - final int dimensionHeaderSize) - { - final String className = formatClassName(groupName); - - sb.append(String.format("\n" + - "%1$s" + - indent + "class %2$s:\n" + - indent + " HEADER_SIZE: int = %3$d\n" + - indent + " _parentMessage: '%4$s'\n" + - indent + " _buffer: %5$s = None\n" + - indent + " _count: int\n" + - indent + " _index: int\n" + - indent + " _offset: int\n" + - indent + " _blockLength: int\n", - generatePyDoc(indent, groupToken), - className, - dimensionHeaderSize, - parentMessageClassName, - readOnlyBuffer)); - - } - - private void generateGroupEncoderClassDeclaration( - final StringBuilder sb, - final Token groupToken, - final String groupName, - final String parentMessageClassName, - final String fullyQualifiedName, - final List subGroupNames, - final String indent, - final int dimensionHeaderSize) - { - final String className = formatClassName(encoderName(groupName)); - - sb.append(String.format("\n" + - "%1$s" + - indent + "class %2$s:\n" + - indent + " HEADER_SIZE: int = %3$d\n", - generatePyDoc(indent, groupToken), - className, - dimensionHeaderSize)); - - - sb - .append("\n") - .append(indent).append(" ") - .append("def __init__(self):\n") - .append(String.format( - indent + " self._parentMessage: '%1$s' = None\n" + - indent + " self._buffer: '%2$s' = None\n" + - indent + " self._count: int = None\n" + - indent + " self._index: int = None\n" + - indent + " self._offset: int = None\n", - parentMessageClassName, - mutableBuffer)); - - for (final String subGroupName : subGroupNames) - { - final String type = formatClassName(encoderName(subGroupName)); - final String field = formatPropertyName(subGroupName); - sb.append(indent).append(" self._").append(field).append(": '").append(fullyQualifiedName) - .append(".").append(type).append("' = ").append("self").append('.').append(type).append("()\n"); - } - - sb.append("\n\n"); - } - - private static CharSequence generateGroupDecoderProperty( - final String groupName, final String fullyQualifiedName, final Token token, final String indent, - final boolean isSubGroup) - { - final StringBuilder sb = new StringBuilder(); - final String className = formatClassName(groupName); - final String propertyName = formatPropertyName(token.name()); - - sb.append(String.format("\n" + - indent + " _%s: %s = %s()\n", - propertyName, - className, - className)); - - sb.append(String.format("\n" + - indent + " def %sId(self) -> int:\n" + - indent + " return %d\n" + - indent + " \n", - formatPropertyName(groupName), - token.id())); - - sb.append(String.format("\n" + - indent + " def %sSinceVersion(self) -> int:\n" + - indent + " return %d\n" + - indent + " \n", - formatPropertyName(groupName), - token.version())); - - final String actingVersionGuard = token.version() == 0 ? - "" : - indent + " if parentMessage.actingVersion < " + token.version() + ":\n" + - indent + " " + propertyName + ".count = 0\n" + - indent + " " + propertyName + ".index = -1\n" + - indent + " return " + propertyName + "\n" + - indent + " \n\n"; - - sb.append(String.format("\n" + - indent + " def %2$s(self) -> %1$s:\n" + - "%3$s" + - indent + " self._%2$s.wrap(self._buffer, self._parentMessage)\n" + - indent + " return self._%2$s\n" + - indent + " \n", - className, - propertyName, - actingVersionGuard)); - - return sb; - } - - private CharSequence generateGroupEncoderProperty( - final String groupName, final String fullyQualifiedName, final Token token, final String indent, - final boolean isSubGroup) - { - final StringBuilder sb = new StringBuilder(); - final String className = formatClassName(encoderName(groupName)); - final String propertyName = formatPropertyName(groupName); - - if (!isSubGroup) - { - sb.append(String.format("\n" + - indent + " _%s: '%s' = %s()\n", - propertyName, - className, - className)); - } - - sb.append(String.format("\n" + - indent + " def %sId(self) -> int:\n" + - indent + " return %d\n" + - indent + " \n", - formatPropertyName(groupName), - token.id())); - - sb.append(String.format("\n" + - indent + " def %2$sCount(self, count: int) -> '%1$s':\n" + - indent + " self._%2$s.wrap(self._buffer, self._parentMessage, count)\n" + - indent + " return self._%2$s\n" + - indent + " \n", - className, - propertyName)); - - return sb; - } - - private CharSequence generateDecoderVarData(final List tokens, final String indent) - { - final StringBuilder sb = new StringBuilder(); - - for (int i = 0, size = tokens.size(); i < size; ) - { - final Token token = tokens.get(i); - if (token.signal() != Signal.BEGIN_VAR_DATA) - { - throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + token); - } - - generateFieldIdMethod(sb, token, indent); - generateFieldSinceVersionMethod(sb, token, indent); - - final String characterEncoding = tokens.get(i + 3).encoding().characterEncoding(); - generateCharacterEncodingMethod(sb, token.name(), characterEncoding, indent); - generateFieldMetaAttributeMethod(sb, token, indent); - - final String propertyName = Generators.toUpperFirstChar(token.name()); - final Token lengthToken = tokens.get(i + 2); - final int sizeOfLengthField = lengthToken.encodedLength(); - final Encoding lengthEncoding = lengthToken.encoding(); - final PrimitiveType lengthType = lengthEncoding.primitiveType(); - final String byteOrderStr = byteOrderString(lengthEncoding); - - sb.append(String.format("\n" + - indent + " @staticmethod\n" + - indent + " def %sHeaderLength() -> int:\n" + - indent + " return %d\n" + - indent + " \n", - Generators.toLowerFirstChar(propertyName), - sizeOfLengthField)); - - sb.append(String.format("\n" + - indent + " def %sLength(self) -> int:\n" + - "%s" + - indent + " limit: int = self._parentMessage.limit\n" + - indent + " return %s\n" + - indent + " \n", - Generators.toLowerFirstChar(propertyName), - generateArrayFieldNotPresentCondition(token.version(), indent), - generateGet(lengthType, "limit", byteOrderStr))); - - generateDataDecodeMethods( - sb, token, propertyName, sizeOfLengthField, lengthType, byteOrderStr, characterEncoding, indent); - - i += token.componentTokenCount(); - } - - return sb; - } - - private CharSequence generateEncoderVarData(final String className, final List tokens, final String indent) - { - final StringBuilder sb = new StringBuilder(); - - for (int i = 0, size = tokens.size(); i < size; ) - { - final Token token = tokens.get(i); - if (token.signal() != Signal.BEGIN_VAR_DATA) - { - throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + token); - } - - generateFieldIdMethod(sb, token, indent); - final Token varDataToken = Generators.findFirst("varData", tokens, i); - final String characterEncoding = varDataToken.encoding().characterEncoding(); - generateCharacterEncodingMethod(sb, token.name(), characterEncoding, indent); - generateFieldMetaAttributeMethod(sb, token, indent); - - final String propertyName = Generators.toUpperFirstChar(token.name()); - final Token lengthToken = Generators.findFirst("length", tokens, i); - final int sizeOfLengthField = lengthToken.encodedLength(); - final Encoding lengthEncoding = lengthToken.encoding(); - final int maxLengthValue = (int)lengthEncoding.applicableMaxValue().longValue(); - - sb.append(String.format("\n" + - indent + " def %sHeaderLength(self) -> int:\n" + - indent + " return %d\n" + - indent + " \n", - Generators.toLowerFirstChar(propertyName), - sizeOfLengthField)); - - generateDataEncodeMethods( - sb, - propertyName, - sizeOfLengthField, - maxLengthValue, - lengthEncoding.primitiveType(), - lengthEncoding, - characterEncoding, - className, - indent); - - i += token.componentTokenCount(); - } - - return sb; - } - - private void generateDataDecodeMethods( - final StringBuilder sb, - final Token token, - final String propertyName, - final int sizeOfLengthField, - final PrimitiveType lengthType, - final String byteOrderStr, - final String characterEncoding, - final String indent) - { - - generateVarDataWrapDecoder(sb, token, propertyName, sizeOfLengthField, lengthType, byteOrderStr, indent); - - if (null != characterEncoding) - { - sb.append(String.format("\n" + - indent + " def %1$s(self) -> str:\n" + - "%2$s" + - indent + " headerLength: int = %3$d\n" + - indent + " limit: int = self._parentMessage.limit\n" + - indent + " dataLength: int = %4$s\n" + - indent + " self._parentMessage.set_limit(limit + headerLength + dataLength)\n\n" + - indent + " if 0 == dataLength:\n" + - indent + " return \"\"\n" + - indent + " \n\n" + - indent + " return memoryview(self._buffer)[limit + headerLength:limit + " + - "headerLength + dataLength].tobytes()." + - "decode(\"%5$s\")\n" + - indent + "\n", - formatPropertyName(propertyName), - generateStringNotPresentCondition(token.version(), indent), - sizeOfLengthField, - generateGet(lengthType, "limit", byteOrderStr), - characterEncoding)); - } - } - - private void generateVarDataWrapDecoder( - final StringBuilder sb, - final Token token, - final String propertyName, - final int sizeOfLengthField, - final PrimitiveType lengthType, - final String byteOrderStr, - final String indent) - { - sb.append(String.format("\n" + - indent + " def wrap%s(self) -> memoryview:\n" + - "%s" + - indent + " headerLength: int = %d\n" + - indent + " limit: int = self._parentMessage.limit\n" + - indent + " dataLength: int = %s\n" + - indent + " self._parentMessage.set_limit(limit + headerLength + dataLength)\n" + - indent + " limit: int = self._parentMessage.limit\n" + - indent + " self._parentMessage.set_limit(limit + headerLength + dataLength)\n" + - indent + " return memoryview(self._buffer)[limit + headerLength:limit + headerLength + dataLength]" + - "\n" + - indent + " \n", - propertyName, - generateVarWrapFieldNotPresentCondition(token.version(), indent), - sizeOfLengthField, - generateGet(lengthType, "limit", byteOrderStr))); - } - - private void generateDataEncodeMethods( - final StringBuilder sb, - final String propertyName, - final int sizeOfLengthField, - final int maxLengthValue, - final PrimitiveType lengthType, - final Encoding encoding, - final String characterEncoding, - final String className, - final String indent) - { - generateDataTypedEncoder( - sb, - className, - propertyName, - sizeOfLengthField, - maxLengthValue, - readOnlyBuffer, - lengthType, - encoding, - indent); - - if (null != characterEncoding) - { - generateCharArrayEncodeMethods( - sb, - propertyName, - sizeOfLengthField, - maxLengthValue, - lengthType, - encoding, - characterEncoding, - className, - indent); - } - } - - private void generateCharArrayEncodeMethods( - final StringBuilder sb, - final String propertyName, - final int sizeOfLengthField, - final int maxLengthValue, - final PrimitiveType lengthType, - final Encoding encoding, - final String characterEncoding, - final String className, - final String indent) - { - sb.append(String.format("\n" + - indent + " def %1$s(self, data: Union[bytes, bytearray, memoryview]) -> '%7$s':\n" + - indent + " size_of_len_field: int = %2$d\n" + - indent + " limit:int = self._parentMessage.limit\n" + - indent + " self._parentMessage.set_limit(limit + size_of_len_field + len(data))\n" + - indent + " data_len: int = len(data)\n" + - indent + " %5$s\n" + - indent + " struct.pack_into('%6$s%%ds' %% (data_len,), self._buffer, limit + size_of_len_field, " + - "data)\n" + - indent + " return self\n\n", - formatPropertyName(propertyName), - sizeOfLengthField, - pythonTypeName(lengthType), - byteOrderString(encoding), - generatePut(lengthType, "limit", "data_len", byteOrderString(encoding)), - pythonEndianCode(encoding.byteOrder()), - className)); - } - - private void generateDataTypedEncoder( - final StringBuilder sb, - final String className, - final String propertyName, - final int sizeOfLengthField, - final int maxLengthValue, - final String exchangeType, - final PrimitiveType lengthType, - final Encoding encoding, - final String indent) - { - //TODO: FIX - sb.append(String.format("\n" + - indent + " def put%2$s(self, src: %3$s, srcOffset: int, length: int) -> '%1$s':\n" + - indent + " if length > %4$d:\n" + - indent + " raise OverflowError(\"length > maxValue for type: \" + length)\n" + - indent + " \n\n" + - indent + " headerLength: int = %5$d\n" + - indent + " limit: int = self._parentMessage.limit\n" + - indent + " self._parentMessage.set_limit(limit + headerLength + length)\n" + - indent + " %6$s\n" + - indent + " return self\n" + - indent + " \n", - className, - propertyName, - exchangeType, - maxLengthValue, - sizeOfLengthField, - generatePut(lengthType, "limit", "length", byteOrderString(encoding)))); - } - - private void generateBitSet(final List tokens) throws IOException - { - final Token token = tokens.get(0); - final List msgBody = getMessageBody(tokens); - final String bitSetName = formatClassName(token.applicableTypeName()); - final String decoderName = decoderName(bitSetName); - final String encoderName = encoderName(bitSetName); - final String encoderModuleName = formatModuleName(encoderName); - final String decoderModuleName = formatModuleName(decoderName); - - final List messageBody = getMessageBody(tokens); - final String implementsString = implementsInterface(FLYWEIGHT); - - try (Writer out = outputManager.createOutput(decoderModuleName)) - { - generateFixedFlyweightHeader(token, decoderName, implementsString, out, readOnlyBuffer, fqReadOnlyBuffer, - msgBody, CodecType.DECODER); - out.append(generateChoiceIsEmpty(token.encoding().primitiveType(), token.encoding().byteOrder())); - out.append(generateChoiceDecoders(messageBody)); - out.append(generateChoiceDisplay(messageBody)); - } - - try (Writer out = outputManager.createOutput(encoderModuleName)) - { - generateFixedFlyweightHeader(token, encoderName, implementsString, out, mutableBuffer, fqMutableBuffer, - msgBody, CodecType.ENCODER); - out.append(generateChoiceClear(encoderName, token)); - out.append(generateChoiceEncoders(encoderName, messageBody)); - } - } - - private void generateFixedFlyweightHeader( - final Token token, - final String typeName, - final String implementsString, - final Writer out, - final String buffer, - final String fqBuffer, - final List tokens, - final CodecType codecType) throws IOException - { - out.append(generateFileHeader(ir.applicableNamespace(), fqBuffer, tokens, codecType)); - out.append(generateDeclaration(typeName, implementsString, token)); - out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer)); - } - - private void generateCompositeFlyweightHeader( - final Token token, - final String typeName, - final Writer out, - final String buffer, - final String fqBuffer, - final String implementsString, - final List tokens, - final CodecType codecType) throws IOException - { - out.append(generateFileHeader(ir.applicableNamespace(), fqBuffer, tokens, codecType)); - out.append(generateDeclaration(typeName, implementsString, token)); - out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer)); - } - - private void generateEnum(final List tokens) throws IOException - { - final Token enumToken = tokens.get(0); - final String enumName = formatClassName(enumToken.applicableTypeName()); - final String moduleName = formatModuleName(enumName); - - - try (Writer out = outputManager.createOutput(moduleName)) - { - out.append(generateEnumFileHeader(ir.applicableNamespace())); - out.append(generateEnumDeclaration(enumName, enumToken)); - - out.append(generateEnumValues(getMessageBody(tokens))); - out.append(generateEnumBody(enumToken, enumName)); - - out.append(generateEnumLookupMethod(getMessageBody(tokens), enumName)); - } - } - - private void generateComposite(final List tokens) throws IOException - { - final Token token = tokens.get(0); - final List msgBody = getMessageBody(tokens); - final String compositeName = formatClassName(token.applicableTypeName()); - final String decoderName = decoderName(compositeName); - final String encoderName = encoderName(compositeName); - final String encoderModuleName = formatModuleName(encoderName); - final String decoderModuleName = formatModuleName(decoderName); - - try (Writer out = outputManager.createOutput(decoderModuleName)) - { - final String implementsString = implementsInterface(COMPOSITE_DECODER_FLYWEIGHT); - generateCompositeFlyweightHeader( - token, decoderName, out, readOnlyBuffer, fqReadOnlyBuffer, implementsString, msgBody, - CodecType.DECODER); - for (int i = 1, end = tokens.size() - 1; i < end; ) - { - final Token encodingToken = tokens.get(i); - final String propertyName = formatPropertyName(encodingToken.name()); - final String typeName = formatClassName(decoderName(encodingToken.applicableTypeName())); - - final StringBuilder sb = new StringBuilder(); - generateEncodingOffsetMethod(sb, propertyName, encodingToken.offset(), BASE_INDENT); - generateEncodingLengthMethod(sb, propertyName, encodingToken.encodedLength(), BASE_INDENT); - generateFieldSinceVersionMethod(sb, encodingToken, BASE_INDENT); - switch (encodingToken.signal()) - { - case ENCODING: - out.append(sb).append(generatePrimitiveDecoder( - true, encodingToken.name(), encodingToken, encodingToken, BASE_INDENT)); - break; - - case BEGIN_ENUM: - out.append(sb).append(generateEnumDecoder( - true, encodingToken, propertyName, encodingToken, BASE_INDENT)); - break; - - case BEGIN_SET: - out.append(sb).append(generateBitSetProperty( - true, CodecType.DECODER, propertyName, encodingToken, encodingToken, - BASE_INDENT, typeName)); - break; - - case BEGIN_COMPOSITE: - out.append(sb).append(generateCompositeProperty( - true, CodecType.DECODER, propertyName, encodingToken, encodingToken, - BASE_INDENT, typeName)); - break; - } - i += encodingToken.componentTokenCount(); - } - out.append(generateCompositeDecoderDisplay(tokens, BASE_INDENT)); - } - - try (Writer out = outputManager.createOutput(encoderModuleName)) - { - final String implementsString = implementsInterface(COMPOSITE_ENCODER_FLYWEIGHT); - generateCompositeFlyweightHeader(token, encoderName, out, mutableBuffer, fqMutableBuffer, implementsString, - msgBody, CodecType.ENCODER); - - for (int i = 1, end = tokens.size() - 1; i < end; ) - { - final Token encodingToken = tokens.get(i); - final String propertyName = formatPropertyName(encodingToken.name()); - final String typeName = formatClassName(encoderName(encodingToken.applicableTypeName())); - - final StringBuilder sb = new StringBuilder(); - generateEncodingOffsetMethod(sb, propertyName, encodingToken.offset(), BASE_INDENT); - generateEncodingLengthMethod(sb, propertyName, encodingToken.encodedLength(), BASE_INDENT); - - switch (encodingToken.signal()) - { - case ENCODING: - out.append(sb).append(generatePrimitiveEncoder( - encoderName, encodingToken.name(), encodingToken, BASE_INDENT)); - break; - - case BEGIN_ENUM: - out.append(sb).append(generateEnumEncoder( - encoderName, encodingToken, propertyName, encodingToken, BASE_INDENT)); - break; - - case BEGIN_SET: - out.append(sb).append(generateBitSetProperty( - true, CodecType.ENCODER, propertyName, encodingToken, encodingToken, - BASE_INDENT, typeName)); - break; - - case BEGIN_COMPOSITE: - out.append(sb).append(generateCompositeProperty( - true, CodecType.ENCODER, propertyName, encodingToken, encodingToken, - BASE_INDENT, typeName)); - break; - } - - i += encodingToken.componentTokenCount(); - } - - } - } - - private CharSequence generateChoiceClear(final String bitSetClassName, final Token token) - { - final StringBuilder sb = new StringBuilder(); - - final Encoding encoding = token.encoding(); - final String literalValue = generateLiteral(encoding.primitiveType(), "0"); - final String byteOrderStr = byteOrderString(encoding); - - sb.append(String.format("\n" + - " def clear(self) -> '%s':\n" + - " %s\n" + - " return self\n" + - " \n", - bitSetClassName, - generatePut(encoding.primitiveType(), "self._offset", literalValue, byteOrderStr))); - - return sb; - } - - private CharSequence generateChoiceDecoders(final List tokens) - { - return concatTokens( - tokens, - Signal.CHOICE, - (token) -> - { - final String choiceName = formatPropertyName(token.name()); - final Encoding encoding = token.encoding(); - final String choiceBitIndex = encoding.constValue().toString(); - final String byteOrderStr = byteOrderString(encoding); - final PrimitiveType primitiveType = encoding.primitiveType(); - final String argType = bitsetArgType(primitiveType); - - return String.format("\n" + - " def %1$s(self) -> bool:\n" + - " return %2$s\n" + - " \n\n" + - " @staticmethod\n" + - " def apply_%1$s(value: %3$s) -> bool:\n" + - " return %4$s\n" + - " \n", - choiceName, - generateChoiceGet(primitiveType, choiceBitIndex, byteOrderStr), - argType, - generateStaticChoiceGet(primitiveType, choiceBitIndex)); - }); - } - - private CharSequence generateChoiceEncoders(final String bitSetClassName, final List tokens) - { - return concatTokens( - tokens, - Signal.CHOICE, - (token) -> - { - final String choiceName = formatPropertyName(token.name()); - final Encoding encoding = token.encoding(); - final String choiceBitIndex = encoding.constValue().toString(); - final String byteOrderStr = byteOrderString(encoding); - final PrimitiveType primitiveType = encoding.primitiveType(); - final String argType = bitsetArgType(primitiveType); - - return String.format("\n" + - " def %2$s(self, value: bool) -> '%1$s':\n" + - "%3$s\n" + - " return self\n" + - " \n\n" + - " @staticmethod\n" + - " def apply_%2$s(bits: %4$s, value: bool) -> '%4$s':\n" + - "%5$s" + - " \n", - bitSetClassName, - choiceName, - generateChoicePut(encoding.primitiveType(), choiceBitIndex, byteOrderStr), - argType, - generateStaticChoicePut(encoding.primitiveType(), choiceBitIndex)); - }); - } - - public static CharSequence concatTokens( - final List tokens, final Signal signal, final Function mapper) - { - return tokens - .stream() - .filter((token) -> token.signal() == signal) - .map(mapper) - .collect(joining()); - } - - private String bitsetArgType(final PrimitiveType primitiveType) - { - switch (primitiveType) - { - case UINT8: - case UINT16: - case UINT32: - case UINT64: - return "int"; - - default: - throw new IllegalStateException("Invalid type: " + primitiveType); - } - } - - private CharSequence generateEnumValues(final List tokens) - { - final StringBuilder sb = new StringBuilder(); - - for (final Token token : tokens) - { - final Encoding encoding = token.encoding(); - final CharSequence constVal = generateLiteral(PrimitiveType.INT32, encoding.constValue().toString()); - sb.append(INDENT).append(token.name()).append(" = ").append(constVal).append("\n"); - } - - final Token token = tokens.get(0); - final Encoding encoding = token.encoding(); - final CharSequence nullVal = generateLiteral(PrimitiveType.INT32, encoding.applicableNullValue().toString()); - - if (shouldDecodeUnknownEnumValues) - { - sb.append(INDENT).append("\"\"\"\n"); - sb.append(INDENT).append(" To be used to represent a not known value from a later version.\n"); - sb.append(INDENT).append("\"\"\"\n"); - sb.append(INDENT).append("SBE_UNKNOWN").append(" = ").append(nullVal).append("\n"); - } - - sb.append(INDENT).append("\"\"\"\n"); - sb.append(INDENT).append(" To be used to represent not present or null.\n"); - sb.append(INDENT).append("\"\"\"\n"); - sb.append(INDENT).append("NULL_VAL").append(" = ").append(nullVal).append("\n\n"); - - return sb; - } - - private CharSequence generateEnumBody(final Token token, final String enumName) - { - return ""; - } - - private CharSequence generateEnumLookupMethod(final List tokens, final String enumName) - { - final StringBuilder sb = new StringBuilder(); - - final PrimitiveType primitiveType = PrimitiveType.INT32; - sb.append(String.format( - INDENT + "@staticmethod\n" + - INDENT + "def get(value: %s) -> '%s':\n", - pythonTypeName(primitiveType), - enumName)); - - for (final Token token : tokens) - { - final CharSequence constVal = generateLiteral(PrimitiveType.INT32, - token.encoding().constValue().toString()); - sb.append(String.format( - INDENT + INDENT + "if value == %1$s: return " + enumName + ".%2$s\n", - constVal, - token.name())); - } - - final String handleUnknownLogic = shouldDecodeUnknownEnumValues ? - INDENT + INDENT + "return " + enumName + ".SBE_UNKNOWN\n" : - INDENT + INDENT + "raise KeyError(\"Unknown value: \" + str(value))\n"; - - sb.append(String.format( - INDENT + INDENT + "if %1$s == value:\n" + - INDENT + INDENT + INDENT + "return " + enumName + ".NULL_VAL\n" + - "%2$s", - generateLiteral(primitiveType, tokens.get(0).encoding().applicableNullValue().toString()), - handleUnknownLogic)); - - return sb; - } - - private CharSequence interfaceImportLine(final List tokens, final CodecType codecType, - final boolean includeHeader) - { - if (shouldGenerateInterfaces) - { - throw new RuntimeException("Interfaced not supported in python codec"); - } - final StringBuilder sb = new StringBuilder(); - final Set processed = new HashSet<>(); - sb.append("from typing import *\n"); - sb.append("import struct\n"); - sb.append("from ._struct_defs import *\n"); - sb.append("from .meta_attribute import MetaAttribute\n"); - if (includeHeader) - { - switch (codecType) - { - case ENCODER: - sb.append("from .message_header_encoder import MessageHeaderEncoder\n"); - break; - case DECODER: - sb.append("from .message_header_decoder import MessageHeaderDecoder\n"); - } - } - for (final Token t : tokens) - { - if (t.signal() == Signal.BEGIN_COMPOSITE || t.signal() == Signal.BEGIN_SET || - t.signal() == Signal.BEGIN_ENUM) - { - String importName = formatClassName(t.applicableTypeName()); - if (processed.contains(importName)) - { - continue; - } - if (t.signal() == Signal.BEGIN_ENUM) - { - sb.append("from .").append(camToSnake(importName)) - .append(" import ").append(importName).append("\n"); - } - else - { - importName = codecType == CodecType.ENCODER ? encoderName(importName) : decoderName(importName); - sb.append("from .").append(camToSnake(importName)).append(" import ").append(importName) - .append("\n"); - } - processed.add(importName); - } - } - sb.append("\n\n"); - return sb; - } - - private CharSequence generateFileHeader(final String packageName, final String fqBuffer, final List tokens, - final CodecType codecType) - { - return String.format( - "\"\"\" Generated SBE (Simple Binary Encoding) message codec \"\"\"\n" + - "%s", - interfaceImportLine(tokens, codecType, false)); - } - - private CharSequence generateMainHeader(final String packageName, final List tokens, - final CodecType codecType) - { - if (fqMutableBuffer.equals(fqReadOnlyBuffer)) - { - return String.format( - "\"\"\" Generated SBE (Simple Binary Encoding) message codec \"\"\"\n" + - "%s", - interfaceImportLine(tokens, codecType, true)); - } - else - { - return String.format( - "\"\"\" Generated SBE (Simple Binary Encoding) message codec \"\"\"\n" + - "%s", - interfaceImportLine(tokens, codecType, true)); - } - } - - private static CharSequence generateEnumFileHeader(final String packageName) - { - return "\"\"\" Generated SBE (Simple Binary Encoding) message codec \"\"\"\n\n" + - "from enum import Enum\n\n\n"; - } - - private void generateAnnotations( - final String indent, - final String className, - final List tokens, - final Appendable out, - final int index, - final Function nameMapping) throws IOException - { - if (shouldGenerateGroupOrderAnnotation) - { - final List groupClassNames = new ArrayList<>(); - int level = 0; - int i = index; - - for (int size = tokens.size(); i < size; i++) - { - if (tokens.get(index).signal() == Signal.BEGIN_GROUP) - { - if (++level == 1) - { - final Token groupToken = tokens.get(index); - final String groupName = groupToken.name(); - groupClassNames.add(formatClassName(nameMapping.apply(groupName))); - } - } - else if (tokens.get(index).signal() == Signal.END_GROUP && --level < 0) - { - break; - } - } - - if (!groupClassNames.isEmpty()) - { - out.append(indent).append("@uk.co.real_logic.sbe.codec.java.GroupOrder({"); - i = 0; - for (final String name : groupClassNames) - { - out.append(className).append('.').append(name).append(".class"); - if (++i < groupClassNames.size()) - { - out.append(", "); - } - } - - out.append("})\n"); - } - } - } - - private static CharSequence generateDeclaration( - final String className, final String implementsString, final Token typeToken) - { - return String.format( - "class %s:\n", - className); - } - - private void generateMetaAttributeEnum() throws IOException - { - try (Writer out = outputManager.createOutput(formatModuleName(META_ATTRIBUTE_ENUM))) - { - out.append("\"\"\"Generated SBE (Simple Binary Encoding) message codec \"\"\"\n\n"); - out.append( - "from enum import IntEnum \n\n\n" + - "class MetaAttribute(IntEnum):\n" + - " Epoch = 1\n" + - " TimeUnit = 2\n" + - " SemanticType = 3\n" + - " Presence = 4\n"); - } - } - - private static CharSequence generateEnumDeclaration(final String name, final Token typeToken) - { - return - "class " + name + "(Enum):\n"; - } - - private CharSequence generatePrimitiveDecoder( - final boolean inComposite, - final String propertyName, - final Token propertyToken, - final Token encodingToken, - final String indent) - { - final StringBuilder sb = new StringBuilder(); - final String formattedPropertyName = formatPropertyName(propertyName); - - sb.append(generatePrimitiveFieldMetaData(formattedPropertyName, encodingToken, indent)); - - if (encodingToken.isConstantEncoding()) - { - sb.append(generateConstPropertyMethods(formattedPropertyName, encodingToken, indent)); - } - else - { - sb.append(generatePrimitivePropertyDecodeMethods( - inComposite, formattedPropertyName, propertyToken, encodingToken, indent)); - } - - return sb; - } - - private CharSequence generatePrimitiveEncoder( - final String containingClassName, final String propertyName, final Token token, final String indent) - { - final StringBuilder sb = new StringBuilder(); - final String formattedPropertyName = formatPropertyName(propertyName); - - sb.append(generatePrimitiveFieldMetaData(formattedPropertyName, token, indent)); - - if (!token.isConstantEncoding()) - { - sb.append(generatePrimitivePropertyEncodeMethods( - containingClassName, formattedPropertyName, token, indent)); - } - else - { - sb.append(generateConstPropertyMethods(formattedPropertyName, token, indent)); - } - - return sb; - } - - private CharSequence generatePrimitivePropertyDecodeMethods( - final boolean inComposite, - final String propertyName, - final Token propertyToken, - final Token encodingToken, - final String indent) - { - return encodingToken.matchOnLength( - () -> generatePrimitivePropertyDecode(inComposite, propertyName, propertyToken, encodingToken, indent), - () -> generatePrimitiveArrayPropertyDecode( - inComposite, propertyName, propertyToken, encodingToken, indent)); - } - - private CharSequence generatePrimitivePropertyEncodeMethods( - final String containingClassName, final String propertyName, final Token token, final String indent) - { - return token.matchOnLength( - () -> generatePrimitivePropertyEncode(containingClassName, propertyName, token, indent), - () -> generatePrimitiveArrayPropertyEncode(containingClassName, propertyName, token, indent)); - } - - private CharSequence generatePrimitiveFieldMetaData( - final String propertyName, final Token token, final String indent) - { - final StringBuilder sb = new StringBuilder(); - - final PrimitiveType primitiveType = token.encoding().primitiveType(); - final String pythonTypeName = pythonTypeName(primitiveType); - final String formattedPropertyName = formatPropertyName(propertyName); - - sb.append(String.format("\n" + - indent + " @staticmethod\n" + - indent + " def %2$sNullValue() -> '%1$s':\n" + - indent + " return %3$s\n" + - indent + " \n", - pythonTypeName, - formattedPropertyName, - generateLiteral(primitiveType, token.encoding().applicableNullValue().toString()))); - - sb.append(String.format("\n" + - indent + " @staticmethod\n" + - indent + " def %2$sMinValue() -> '%1$s':\n" + - indent + " return %3$s\n" + - indent + " \n", - pythonTypeName, - formattedPropertyName, - generateLiteral(primitiveType, token.encoding().applicableMinValue().toString()))); - - sb.append(String.format( - "\n" + - indent + " @staticmethod\n" + - indent + " def %2$sMaxValue() -> '%1$s':\n" + - indent + " return %3$s\n" + - indent + " \n", - pythonTypeName, - formattedPropertyName, - generateLiteral(primitiveType, token.encoding().applicableMaxValue().toString()))); - - - return sb; - } - - private CharSequence generatePrimitivePropertyDecode( - final boolean inComposite, - final String propertyName, - final Token propertyToken, - final Token encodingToken, - final String indent) - { - final Encoding encoding = encodingToken.encoding(); - final String javaTypeName = pythonTypeName(encoding.primitiveType()); - - final int offset = encodingToken.offset(); - final String byteOrderStr = byteOrderString(encoding); - - return String.format( - "\n" + - indent + " def %s(self) -> '%s':\n" + - "%s" + - indent + " return %s\n" + - indent + " \n\n", - formatPropertyName(propertyName), - javaTypeName, - generateFieldNotPresentCondition(inComposite, propertyToken.version(), encoding, indent), - generateGet(encoding.primitiveType(), "self._offset + " + offset, byteOrderStr)); - } - - private CharSequence generatePrimitivePropertyEncode( - final String containingClassName, final String propertyName, final Token token, final String indent) - { - final Encoding encoding = token.encoding(); - final String javaTypeName = pythonTypeName(encoding.primitiveType()); - final int offset = token.offset(); - final String byteOrderStr = byteOrderString(encoding); - - return String.format( - "\n" + - indent + " def %s(self, value: %s) -> '%s':\n" + - indent + " %s\n" + - indent + " return self\n" + - indent + " \n\n", - formatPropertyName(propertyName), - javaTypeName, - formatClassName(containingClassName), - generatePut(encoding.primitiveType(), "self._offset + " + offset, "value", byteOrderStr)); - } - - private CharSequence generateVarWrapFieldNotPresentCondition(final int sinceVersion, final String indent) - { - if (0 == sinceVersion) - { - return ""; - } - - return String.format( - indent + " if parentMessage.actingVersion < %d:\n" + - indent + " self._wrapBuffer.wrap(buffer, offset, 0)\n" + - indent + " \n\n", - sinceVersion); - } - - private CharSequence generateFieldNotPresentCondition( - final boolean inComposite, final int sinceVersion, final Encoding encoding, final String indent) - { - if (inComposite || 0 == sinceVersion) - { - return ""; - } - - return String.format( - indent + " if parentMessage.actingVersion < %d:\n" + - indent + " return %s\n" + - indent + " \n\n", - sinceVersion, - generateLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString())); - } - - private static CharSequence generateArrayFieldNotPresentCondition(final int sinceVersion, final String indent) - { - if (0 == sinceVersion) - { - return ""; - } - - return String.format( - indent + " if parentMessage.actingVersion < %d:\n" + - indent + " return 0\n" + - indent + " \n\n", - sinceVersion); - } - - private static CharSequence generateStringNotPresentConditionForAppendable( - final int sinceVersion, final String indent) - { - if (0 == sinceVersion) - { - return ""; - } - - return String.format( - indent + " if parentMessage.actingVersion < %d:\n" + - indent + " return\n" + - indent + " \n\n", - sinceVersion); - } - - private static CharSequence generateStringNotPresentCondition(final int sinceVersion, final String indent) - { - if (0 == sinceVersion) - { - return ""; - } - - return String.format( - indent + " if parentMessage.actingVersion < %d:\n" + - indent + " return \"\"\n" + - indent + " \n\n", - sinceVersion); - } - - private static CharSequence generatePropertyNotPresentCondition( - final boolean inComposite, - final CodecType codecType, - final Token propertyToken, - final String enumName, - final String indent) - { - if (inComposite || codecType == CodecType.ENCODER || 0 == propertyToken.version()) - { - return ""; - } - - return String.format( - indent + " if parentMessage.actingVersion < %d:\n" + - indent + " return %s\n" + - indent + " \n\n", - propertyToken.version(), - enumName == null ? "null" : (enumName + ".NULL_VAL")); - } - - private CharSequence generatePrimitiveArrayPropertyDecode( - final boolean inComposite, - final String propertyName, - final Token propertyToken, - final Token encodingToken, - final String indent) - { - final Encoding encoding = encodingToken.encoding(); - final String typeName = pythonTypeName(encoding.primitiveType()); - final int offset = encodingToken.offset(); - final String byteOrderStr = byteOrderString(encoding); - final String typePrefix = toUpperFirstChar(encoding.primitiveType().primitiveName()); - final int fieldLength = encodingToken.arrayLength(); - final int typeSize = sizeOfPrimitive(encoding); - - final StringBuilder sb = new StringBuilder(); - - generateArrayLengthMethod(propertyName, indent, fieldLength, sb); - sb.append(String.format( - indent + " def %s(self, index: int) -> '%s':\n" + - indent + " if index < 0 or index >= %d:\n" + - indent + " raise IndexError(\"index out of range: index=\" + str(index))\n" + - "%s" + - indent + " pos: int = self._offset + %d + (index * %d)\n\n" + - indent + " return %s\n" + - indent + " \n\n", - propertyName, - typeName, - fieldLength, - generateFieldNotPresentCondition(inComposite, propertyToken.version(), encoding, indent), - offset, - typeSize, - generateGet(encoding.primitiveType(), "pos", byteOrderStr))); - - - final String structParserMulti = String.format("A_%1$S_%2$S_%3$S", Generators.toUpperFirstChar(propertyName), - typePrefix, byteOrderStr); - - sb.append(String.format("\n" + - INDENT + structParserMulti + " = Struct('%1$s%2$d%3$s') \n", - pythonEndianCode(encoding.byteOrder()), fieldLength, - pythonTypeCode(encoding.primitiveType()))); - - if (encoding.primitiveType() == PrimitiveType.CHAR) - { - generateCharacterEncodingMethod(sb, propertyName, encoding.characterEncoding(), indent); - //Properties for multi item assignment - sb.append(String.format("\n" + - INDENT + "def getMulti%2$s(self) -> bytes:\n" + - "%4$s" + - INDENT + " return self." + structParserMulti + ".unpack_from(self._buffer, self._offset + %5$d)[0]" + - "\n", - typeName, Generators.toUpperFirstChar(propertyName), fieldLength, - generateArrayFieldNotPresentCondition(propertyToken.version(), indent), - offset, typeSize)); - } - else - { - //Properties for multi item assignment - sb.append(String.format("\n" + - INDENT + "def getMulti%2$s(self) -> Tuple['%1$s']:\n" + - "%4$s" + - INDENT + " return self." + structParserMulti + ".unpack_from(self._buffer, self._offset + %5$d)\n", - typeName, Generators.toUpperFirstChar(propertyName), fieldLength, - generateArrayFieldNotPresentCondition(propertyToken.version(), indent), - offset, typeSize)); - } - - - return sb; - } - - private static void generateArrayLengthMethod( - final String propertyName, final String indent, final int fieldLength, final StringBuilder sb) - { - sb.append(String.format("\n" + - indent + " def %sLength(self) -> int:\n" + - indent + " return %d\n" + - indent + " \n\n", - formatPropertyName(propertyName), - fieldLength)); - } - - - private CharSequence generatePrimitiveArrayPropertyEncode( - final String containingClassName, final String propertyName, final Token token, final String indent) - { - final Encoding encoding = token.encoding(); - final PrimitiveType primitiveType = encoding.primitiveType(); - final String javaTypeName = pythonTypeName(primitiveType); - final String typeName = pythonTypeName(encoding.primitiveType()); - final String byteOrderStr = byteOrderString(encoding); - final int offset = token.offset(); - final int arrayLength = token.arrayLength(); - final int typeSize = sizeOfPrimitive(encoding); - final String typePrefix = toUpperFirstChar(encoding.primitiveType().primitiveName()); - - final StringBuilder sb = new StringBuilder(); - final String className = formatClassName(containingClassName); - final String structParserMulti = String.format("A_%1$S_%2$S_%3$S", Generators.toUpperFirstChar(propertyName), - typePrefix, byteOrderStr); - - sb.append(String.format("\n" + - INDENT + structParserMulti + " = Struct('%1$s%2$d%3$s') \n", - pythonEndianCode(encoding.byteOrder()), token.arrayLength(), - pythonTypeCode(encoding.primitiveType()))); - - generateArrayLengthMethod(propertyName, indent, arrayLength, sb); - - sb.append(String.format( - indent + " def %s(self, index: int, value: '%s') -> '%s':\n" + - indent + " if index < 0 or index >= %d:\n" + - indent + " raise IndexError(\"index out of range: index=\" + str(index))\n" + - indent + " \n" + - indent + " pos: int = self._offset + %d + (index * %d)\n" + - indent + " %s\n\n" + - indent + " return self\n" + - indent + " \n", - propertyName, - javaTypeName, - className, - arrayLength, - offset, - typeSize, - generatePut(primitiveType, "pos", "value", byteOrderStr))); - - sb.append(String.format("\n" + - INDENT + "def set_%1$s(self, value: %2$s) -> '%4$s':\n" + - INDENT + " self." + structParserMulti + ".pack_into(self._buffer, self._offset + %3$d, value)\n" + - INDENT + " return self\n", - propertyName, typeName, offset, containingClassName)); - - return sb; - } - - private void generateCharArrayEncodeMethods( - final String containingClassName, - final String propertyName, - final String indent, - final Encoding encoding, - final int offset, - final int fieldLength, - final StringBuilder sb) - { - generateCharacterEncodingMethod(sb, propertyName, encoding.characterEncoding(), indent); - - sb.append(String.format("\n" + - indent + " public %s put%s(final byte[] src, final int srcOffset)\n" + - indent + " {\n" + - indent + " FIX: final int length = %d;\n" + - indent + " if (srcOffset < 0 || srcOffset > (src.length - length))\n" + - indent + " {\n" + - indent + " throw new IndexOutOfBoundsException(" + - "\"Copy will go out of range: offset=\" + srcOffset);\n" + - indent + " }\n\n" + - indent + " buffer.putBytes(this.offset + %d, src, srcOffset, length);\n\n" + - indent + " return this;\n" + - indent + " }\n", - formatClassName(containingClassName), - Generators.toUpperFirstChar(propertyName), - fieldLength, - offset)); - - if (encoding.characterEncoding().contains("ASCII")) - { - sb.append(String.format("\n" + - indent + " public %1$s %2$s(final String src)\n" + - indent + " {\n" + - indent + " FIX: final int length = %3$d;\n" + - indent + " final int srcLength = null == src ? 0 : src.length();\n" + - indent + " if (srcLength > length)\n" + - indent + " {\n" + - indent + " throw new IndexOutOfBoundsException(" + - "\"String too large for copy: byte length=\" + srcLength);\n" + - indent + " }\n\n" + - indent + " buffer.putStringWithoutLengthAscii(this.offset + %4$d, src);\n\n" + - indent + " for (int start = srcLength; start < length; ++start)\n" + - indent + " {\n" + - indent + " buffer.putByte(this.offset + %4$d + start, (byte)0);\n" + - indent + " }\n\n" + - indent + " return this;\n" + - indent + " }\n", - formatClassName(containingClassName), - propertyName, - fieldLength, - offset)); - sb.append(String.format("\n" + - indent + " public %1$s %2$s(final CharSequence src)\n" + - indent + " {\n" + - indent + " final int length = %3$d;\n" + - indent + " final int srcLength = null == src ? 0 : src.length();\n" + - indent + " if (srcLength > length)\n" + - indent + " {\n" + - indent + " throw new IndexOutOfBoundsException(" + - "\"CharSequence too large for copy: byte length=\" + srcLength);\n" + - indent + " }\n\n" + - indent + " for (int i = 0; i < srcLength; ++i)\n" + - indent + " {\n" + - indent + " final char charValue = src.charAt(i);\n" + - indent + " final byte byteValue = charValue > 127 ? (byte)'?' : (byte)charValue;\n" + - indent + " buffer.putByte(this.offset + %4$d + i, byteValue);\n" + - indent + " }\n\n" + - indent + " for (int i = srcLength; i < length; ++i)\n" + - indent + " {\n" + - indent + " buffer.putByte(this.offset + %4$d + i, (byte)0);\n" + - indent + " }\n\n" + - indent + " return this;\n" + - indent + " }\n", - formatClassName(containingClassName), - propertyName, - fieldLength, - offset)); - } - else - { - sb.append(String.format("\n" + - indent + " public %s %s(final String src)\n" + - indent + " {\n" + - indent + " final int length = %d;\n" + - indent + " final byte[] bytes = null == src ? new byte[0] : src.getBytes(%s);\n" + - indent + " if (bytes.length > length)\n" + - indent + " {\n" + - indent + " throw new IndexOutOfBoundsException(" + - "\"String too large for copy: byte length=\" + bytes.length);\n" + - indent + " }\n\n" + - indent + " buffer.putBytes(this.offset + %d, bytes, 0, bytes.length);\n\n" + - indent + " for (int start = bytes.length; start < length; ++start)\n" + - indent + " {\n" + - indent + " buffer.putByte(this.offset + %d + start, (byte)0);\n" + - indent + " }\n\n" + - indent + " return this;\n" + - indent + " }\n", - formatClassName(containingClassName), - propertyName, - fieldLength, - encoding.characterEncoding(), - offset, - offset)); - } - } - - private static int sizeOfPrimitive(final Encoding encoding) - { - return encoding.primitiveType().size(); - } - - private static void generateCharacterEncodingMethod( - final StringBuilder sb, final String propertyName, final String characterEncoding, final String indent) - { - if (null != characterEncoding) - { - sb.append(String.format("\n" + - indent + " @staticmethod\n" + - indent + " def %sCharacterEncoding() -> str:\n" + - indent + " return \"%s\"\n" + - indent + " \n", - formatPropertyName(propertyName), - characterEncoding)); - } - } - - private CharSequence generateConstPropertyMethods( - final String propertyName, final Token token, final String indent) - { - final String formattedPropertyName = formatPropertyName(propertyName); - final Encoding encoding = token.encoding(); - if (encoding.primitiveType() != PrimitiveType.CHAR) - { - return String.format("\n" + - indent + " @property\n" + - indent + " def %s(self) -> '%s':\n" + - indent + " return %s\n" + - indent + " \n", - formattedPropertyName, - pythonTypeName(encoding.primitiveType()), - generateLiteral(encoding.primitiveType(), encoding.constValue().toString())); - } - - final StringBuilder sb = new StringBuilder(); - - final String javaTypeName = pythonTypeName(encoding.primitiveType()); - final byte[] constBytes = encoding.constValue().byteArrayValue(encoding.primitiveType()); - final CharSequence values = generateByteLiteralList( - encoding.constValue().byteArrayValue(encoding.primitiveType())); - - sb.append(String.format( - "\n" + - indent + " %s_VALUE: bytes = bytes([%s]) \n", - propertyName.toUpperCase(), - values)); - - generateArrayLengthMethod(formattedPropertyName, indent, constBytes.length, sb); - - sb.append(String.format( - indent + " def %s(self, index: int) -> int:\n" + - indent + " return self.%s_VALUE[index]\n" + - indent + " \n\n", - formattedPropertyName, - propertyName.toUpperCase())); - - sb.append(String.format( - indent + " def get%1$s(self, offset: int, length: int) -> memoryview:\n" + - indent + " last = min(length, %2$d)\n" + - indent + " offset = min(abs(offset), %3$d)\n" + - indent + " return memoryview(self.%4$S_VALUE)[offset:last]\n", - Generators.toUpperFirstChar(propertyName), - constBytes.length, - constBytes.length - 1, - propertyName)); - - - if (constBytes.length > 1) - { - sb.append(String.format("\n" + - indent + " @staticmethod\n" + - indent + " def get%sAll() -> str:\n" + - indent + " \n" + - indent + " return \"%s\"\n" + - indent + " \n\n", - toUpperFirstChar(formattedPropertyName), - encoding.constValue())); - } - else - { - sb.append(String.format("\n" + - indent + " @staticmethod\n" + - indent + " def %s() -> int:\n" + - indent + " \n" + - indent + " return %s\n" + - indent + " \n\n", - formattedPropertyName, - encoding.constValue())); - } - - return sb; - } - - private static CharSequence generateByteLiteralList(final byte[] bytes) - { - final StringBuilder values = new StringBuilder(); - for (final byte b : bytes) - { - values.append(b).append(", "); - } - - if (values.length() > 0) - { - values.setLength(values.length() - 2); - } - - return values; - } - - private CharSequence generateFixedFlyweightCode( - final String className, final int size, final String bufferImplementation) - { - final String schemaIdType = pythonTypeName(ir.headerStructure().schemaIdType()); - final String schemaIdAccessorType = shouldGenerateInterfaces ? "int" : schemaIdType; - final String schemaVersionType = pythonTypeName(ir.headerStructure().schemaVersionType()); - final String schemaVersionAccessorType = shouldGenerateInterfaces ? "int" : schemaVersionType; - - return String.format( - " SCHEMA_ID: %5$s = %6$s\n" + - " SCHEMA_VERSION: %7$s = %8$s\n" + - " ENCODED_LENGTH: int = %2$d\n" + - " _offset: int = 0\n" + - " _buffer: %3$s = None\n\n" + - " def wrap(self, buffer: %3$s, offset: int) -> '%1$s':\n" + - " if buffer != self._buffer:\n" + - " self._buffer = buffer\n" + - " \n" + - " self._offset = offset\n\n" + - " return self\n" + - " \n\n" + - " @property\n" + - " def buffer(self) -> '%3$s':\n" + - " \n" + - " return self._buffer\n" + - " \n\n" + - " @property\n" + - " def offset(self) -> int:\n" + - " return self._offset\n" + - " \n\n" + - " @property\n" + - " def encodedLength(self) ->int:\n" + - " return self.ENCODED_LENGTH\n" + - " \n\n" + - " @property\n" + - " def sbeSchemaId(self) -> '%9$s':\n" + - " return self.SCHEMA_ID\n" + - " \n\n" + - " def sbeSchemaVersion(self) -> '%10$s':\n" + - " return self.SCHEMA_VERSION\n" + - " \n", - className, - size, - bufferImplementation, - ir.byteOrder(), - schemaIdType, - generateLiteral(ir.headerStructure().schemaIdType(), Integer.toString(ir.id())), - schemaVersionType, - generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), - schemaIdAccessorType, - schemaVersionAccessorType); - - - } - - private CharSequence generateDecoderFlyweightCode(final String className, final Token token) - { - final String wrapMethod = String.format( - " def wrap(self, buffer: %2$s, offset: int, actingBlockLength: int, actingVersion: int) -> '%1$s':\n" + - " if buffer != self._buffer:\n" + - " self._buffer = buffer\n" + - " \n" + - " self._offset = offset\n" + - " self._actingBlockLength = actingBlockLength\n" + - " self._actingVersion = actingVersion\n" + - " self.set_limit(offset + actingBlockLength)\n\n" + - " return self\n" + - " \n\n", - className, - readOnlyBuffer); - - return generateFlyweightCode(CodecType.DECODER, className, token, wrapMethod, readOnlyBuffer); - } - - private CharSequence generateFlyweightCode( - final CodecType codecType, - final String className, - final Token token, - final String wrapMethod, - final String bufferImplementation) - { - final HeaderStructure headerStructure = ir.headerStructure(); - final String blockLengthType = pythonTypeName(headerStructure.blockLengthType()); - final String blockLengthAccessorType = shouldGenerateInterfaces ? "int" : blockLengthType; - final String templateIdType = pythonTypeName(headerStructure.templateIdType()); - final String templateIdAccessorType = shouldGenerateInterfaces ? "int" : templateIdType; - final String schemaIdType = pythonTypeName(headerStructure.schemaIdType()); - final String schemaIdAccessorType = shouldGenerateInterfaces ? "int" : schemaIdType; - final String schemaVersionType = pythonTypeName(headerStructure.schemaVersionType()); - final String schemaVersionAccessorType = shouldGenerateInterfaces ? "int" : schemaVersionType; - final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); - final String actingFields = codecType == CodecType.ENCODER ? - "" : - " self._actingBlockLength: int = None\n" + - " self._actingVersion: int = None\n"; - - return String.format( - " BLOCK_LENGTH: %1$s = %2$s\n" + - " TEMPLATE_ID: %3$s = %4$s\n" + - " SCHEMA_ID: %5$s = %6$s\n" + - " SCHEMA_VERSION: %7$s = %8$s\n" + - " def __init__(self):\n" + - " self._parentMessage: '%9$s' = self\n" + - " self._buffer: %11$s = None\n" + - " self._offset: int = None\n" + - " self._limit: int = None\n" + - "%13$s" + - "\n" + - " @property\n" + - " def sbeBlockLength(self) -> %15$s:\n" + - " return self.BLOCK_LENGTH\n" + - " \n\n" + - " @property\n" + - " def sbeTemplateId(self) -> %16$s:\n" + - " return self.TEMPLATE_ID\n" + - " \n\n" + - " @property\n" + - " def sbeSchemaId(self) -> %17$s:\n" + - " return self.SCHEMA_ID\n" + - " \n\n" + - " @property\n" + - " def sbeSchemaVersion(self) -> %18$s:\n" + - " return self.SCHEMA_VERSION\n" + - " \n\n" + - " @property\n" + - " def sbeSemanticType(self) -> str:\n" + - " return \"%10$s\"\n" + - " \n\n" + - " @property\n" + - " def buffer(self) -> %11$s:\n" + - " return self._buffer\n" + - " \n\n" + - " @property\n" + - " def offset(self) -> int:\n" + - " return self._offset\n" + - " \n\n" + - "%12$s" + - " @property\n" + - " def encodedLength(self) -> int:\n" + - " return self._limit - self._offset\n" + - " \n\n" + - " @property\n" + - " def limit(self) -> int:\n" + - " return self._limit\n" + - " \n\n" + - " def set_limit(self, limit: int):\n" + - " self._limit = limit\n" + - " \n", - blockLengthType, - generateLiteral(headerStructure.blockLengthType(), Integer.toString(token.encodedLength())), - templateIdType, - generateLiteral(headerStructure.templateIdType(), Integer.toString(token.id())), - schemaIdType, - generateLiteral(headerStructure.schemaIdType(), Integer.toString(ir.id())), - schemaVersionType, - generateLiteral(headerStructure.schemaVersionType(), Integer.toString(ir.version())), - className, - semanticType, - bufferImplementation, - wrapMethod, - actingFields, - ir.byteOrder(), - blockLengthAccessorType, - templateIdAccessorType, - schemaIdAccessorType, - schemaVersionAccessorType); - } - - private CharSequence generateEncoderFlyweightCode(final String className, final Token token) - { - final String wrapMethod = String.format( - " def wrap(self, buffer: %2$s , offset: int) -> '%1$s':\n" + - " if buffer != self._buffer:\n" + - " self._buffer = buffer\n" + - " \n" + - " self._offset = offset\n" + - " self.set_limit(offset + self.BLOCK_LENGTH)\n\n" + - " return self\n" + - " \n\n", - className, - mutableBuffer); - - final StringBuilder builder = new StringBuilder( - " def wrapAndApplyHeader(self, buffer: %2$s, offset: int, headerEncoder: '%3$s') -> '%1$s':\n" + - " headerEncoder.wrap(buffer, offset)"); - - for (final Token headerToken : ir.headerStructure().tokens()) - { - if (!headerToken.isConstantEncoding()) - { - switch (headerToken.name()) - { - case "blockLength": - builder.append(".blockLength(self.BLOCK_LENGTH)"); - break; - - case "templateId": - builder.append(".templateId(self.TEMPLATE_ID)"); - break; - - case "schemaId": - builder.append(".schemaId(self.SCHEMA_ID)"); - break; - - case "version": - builder.append(".version(self.SCHEMA_VERSION)"); - break; - } - } - } - - builder.append("\n\n return self.wrap(buffer, offset + %3$s.ENCODED_LENGTH)\n\n"); - - final String wrapAndApplyMethod = String.format( - builder.toString(), - className, - mutableBuffer, - formatClassName(ir.headerStructure().tokens().get(0).applicableTypeName() + "Encoder")); - - return generateFlyweightCode( - CodecType.ENCODER, className, token, wrapMethod + wrapAndApplyMethod, mutableBuffer); - } - - private CharSequence generateEncoderFields( - final String containingClassName, final List tokens, final String indent) - { - final StringBuilder sb = new StringBuilder(); - - Generators.forEachField( - tokens, - (fieldToken, typeToken) -> - { - final String propertyName = formatPropertyName(fieldToken.name()); - final String typeName = formatClassName(encoderName(typeToken.name())); - - generateFieldIdMethod(sb, fieldToken, indent); - generateFieldSinceVersionMethod(sb, fieldToken, indent); - generateEncodingOffsetMethod(sb, propertyName, fieldToken.offset(), indent); - generateEncodingLengthMethod(sb, propertyName, typeToken.encodedLength(), indent); - generateFieldMetaAttributeMethod(sb, fieldToken, indent); - - switch (typeToken.signal()) - { - case ENCODING: - sb.append(generatePrimitiveEncoder(containingClassName, propertyName, typeToken, indent)); - break; - - case BEGIN_ENUM: - sb.append(generateEnumEncoder( - containingClassName, fieldToken, propertyName, typeToken, indent)); - break; - - case BEGIN_SET: - sb.append(generateBitSetProperty( - false, CodecType.ENCODER, propertyName, fieldToken, typeToken, indent, typeName)); - break; - - case BEGIN_COMPOSITE: - sb.append(generateCompositeProperty( - false, CodecType.ENCODER, propertyName, fieldToken, typeToken, indent, typeName)); - break; - } - }); - - return sb; - } - - private CharSequence generateDecoderFields(final List tokens, final String indent) - { - final StringBuilder sb = new StringBuilder(); - - Generators.forEachField( - tokens, - (fieldToken, typeToken) -> - { - final String propertyName = formatPropertyName(fieldToken.name()); - final String typeName = decoderName(formatClassName(typeToken.name())); - - generateFieldIdMethod(sb, fieldToken, indent); - generateFieldSinceVersionMethod(sb, fieldToken, indent); - generateEncodingOffsetMethod(sb, propertyName, fieldToken.offset(), indent); - generateEncodingLengthMethod(sb, propertyName, typeToken.encodedLength(), indent); - generateFieldMetaAttributeMethod(sb, fieldToken, indent); - - switch (typeToken.signal()) - { - case ENCODING: - sb.append(generatePrimitiveDecoder(false, propertyName, fieldToken, typeToken, indent)); - break; - - case BEGIN_ENUM: - sb.append(generateEnumDecoder(false, fieldToken, propertyName, typeToken, indent)); - break; - - case BEGIN_SET: - sb.append(generateBitSetProperty( - false, CodecType.DECODER, propertyName, fieldToken, typeToken, indent, typeName)); - break; - - case BEGIN_COMPOSITE: - sb.append(generateCompositeProperty( - false, CodecType.DECODER, propertyName, fieldToken, typeToken, indent, typeName)); - break; - } - }); - - return sb; - } - - private static void generateFieldIdMethod(final StringBuilder sb, final Token token, final String indent) - { - sb.append(String.format( - "\n" + - indent + " @staticmethod\n" + - indent + " def %sId() -> int:\n" + - indent + " return %d\n" + - indent + " \n", - formatPropertyName(token.name()), - token.id())); - } - - private static void generateEncodingOffsetMethod( - final StringBuilder sb, final String name, final int offset, final String indent) - { - sb.append(String.format( - "\n" + - indent + " @staticmethod\n" + - indent + " def %sEncodingOffset() -> int:\n" + - indent + " return %d\n" + - indent + " \n", - formatPropertyName(name), - offset)); - } - - private static void generateEncodingLengthMethod( - final StringBuilder sb, final String name, final int length, final String indent) - { - sb.append(String.format( - "\n" + - indent + " @staticmethod\n" + - indent + " def %sEncodingLength() -> int:\n" + - indent + " return %d\n" + - indent + " \n", - formatPropertyName(name), - length)); - } - - private static void generateFieldSinceVersionMethod(final StringBuilder sb, final Token token, final String indent) - { - sb.append(String.format( - "\n" + - indent + " @staticmethod\n" + - indent + " def %sSinceVersion() -> int:\n" + - indent + " return %d\n" + - indent + " \n", - formatPropertyName(token.name()), - token.version())); - } - - private static void generateFieldMetaAttributeMethod(final StringBuilder sb, final Token token, final String indent) - { - final Encoding encoding = token.encoding(); - final String epoch = encoding.epoch() == null ? "" : encoding.epoch(); - final String timeUnit = encoding.timeUnit() == null ? "" : encoding.timeUnit(); - final String semanticType = encoding.semanticType() == null ? "" : encoding.semanticType(); - - sb.append(String.format( - "\n" + - indent + " @staticmethod\n" + - indent + " def %sMetaAttribute(metaAttribute: MetaAttribute) -> str:\n" + - indent + " if metaAttribute == MetaAttribute.Epoch: return \"%s\"\n" + - indent + " if metaAttribute == MetaAttribute.TimeUnit: return \"%s\"\n" + - indent + " if metaAttribute == MetaAttribute.SemanticType: return \"%s\"\n" + - indent + " if metaAttribute == MetaAttribute.Presence: return \"%s\"\n" + - indent + " return \"\"\n" + - indent + " \n", - formatPropertyName(token.name()), - epoch, - timeUnit, - semanticType, - encoding.presence().toString().toLowerCase())); - } - - private CharSequence generateEnumDecoder( - final boolean inComposite, - final Token fieldToken, - final String propertyName, - final Token typeToken, - final String indent) - { - final String enumName = formatClassName(typeToken.applicableTypeName()); - final Encoding encoding = typeToken.encoding(); - - if (fieldToken.isConstantEncoding()) - { - return String.format( - "\n" + - indent + " def %s(self) -> %s:\n" + - indent + " return %s\n" + - indent + " \n\n", - propertyName, - enumName, - fieldToken.encoding().constValue().toString()); - } - else - { - final String decoderProp; - if (encoding.primitiveType().equals(PrimitiveType.CHAR)) - { - decoderProp = "ord(" + generateGet(encoding.primitiveType(), "self._offset + " + typeToken.offset(), - byteOrderString(encoding)) + ")"; - } - else - { - decoderProp = generateGet(encoding.primitiveType(), "self._offset + " + typeToken.offset(), - byteOrderString(encoding)); - } - return String.format( - "\n" + - indent + " def %s(self) -> %s:\n" + - "%s" + - indent + " return %s.get(%s)\n" + - indent + " \n\n", - propertyName, - enumName, - generatePropertyNotPresentCondition(inComposite, CodecType.DECODER, fieldToken, enumName, indent), - enumName, - decoderProp); - } - } - - private CharSequence generateEnumEncoder( - final String containingClassName, - final Token fieldToken, - final String propertyName, - final Token typeToken, - final String indent) - { - if (fieldToken.isConstantEncoding()) - { - return ""; - } - - final String enumName = formatClassName(typeToken.applicableTypeName()); - final Encoding encoding = typeToken.encoding(); - final int offset = typeToken.offset(); - - return String.format("\n" + - indent + " def %1$s(self, value: %2$s) -> '%3$s':\n" + - indent + " %4$s\n" + - indent + " return self\n" + - indent + " \n", - propertyName, - enumName, - formatClassName(containingClassName), - generatePut(encoding.primitiveType(), "self._offset + " + offset, "value.value", - byteOrderString(encoding))); - } - - private CharSequence generateBitSetProperty( - final boolean inComposite, - final CodecType codecType, - final String propertyName, - final Token propertyToken, - final Token bitsetToken, - final String indent, - final String bitSetName) - { - final StringBuilder sb = new StringBuilder(); - - sb.append(String.format("\n" + - indent + " _%s: %s = %s()\n", - propertyName, - bitSetName, - bitSetName)); - - sb.append(String.format("\n" + - indent + " def %2$s(self) -> '%1$s':\n" + - "%3$s" + - indent + " self._%4$s.wrap(self._buffer, self._offset + %5$d)\n" + - indent + " return self._%6$s\n" + - indent + " \n", - bitSetName, - propertyName, - generatePropertyNotPresentCondition(inComposite, codecType, propertyToken, null, indent), - propertyName, - bitsetToken.offset(), - propertyName)); - - return sb; - } - - private CharSequence generateCompositeProperty( - final boolean inComposite, - final CodecType codecType, - final String propertyName, - final Token propertyToken, - final Token compositeToken, - final String indent, - final String compositeName) - { - final StringBuilder sb = new StringBuilder(); - - sb.append(String.format("\n" + - indent + " _%2$s: %1$s = %3$s()\n", - compositeName, - propertyName, - compositeName)); - - sb.append(String.format("\n" + - indent + " def %2$s(self) -> '%1$s':\n" + - "%3$s" + - indent + " self._%4$s.wrap(self._buffer, self._offset + %5$d)\n" + - indent + " return self._%6$s\n" + - indent + " \n", - compositeName, - propertyName, - generatePropertyNotPresentCondition(inComposite, codecType, propertyToken, null, indent), - propertyName, - compositeToken.offset(), - propertyName)); - - return sb; - } - - private String generateGet(final PrimitiveType type, final String index, final String byteOrder) - { - switch (type) - { - case CHAR: - case INT8: - case UINT8: - case INT16: - case UINT16: - case INT32: - case UINT32: - case FLOAT: - case INT64: - case UINT64: - case DOUBLE: - return byteOrder.toUpperCase() + "_" + type.name().toUpperCase() + ".unpack_from(self._buffer, " + - index + ")[0]"; - } - - throw new IllegalArgumentException("primitive type not supported: " + type); - } - - private String generatePut( - final PrimitiveType type, final String index, final String value, final String byteOrder) - { - switch (type) - { - case CHAR: - return byteOrder.toUpperCase() + "_" + type.name().toUpperCase() + ".pack_into(self._buffer, " + index + - ", bytes([" + value + "]))"; - case INT8: - case UINT8: - case INT16: - case UINT16: - case INT32: - case UINT32: - case FLOAT: - case INT64: - case UINT64: - case DOUBLE: - return byteOrder.toUpperCase() + "_" + type.name().toUpperCase() + ".pack_into(self._buffer, " + index + - ", " + value + ")"; - - } - - throw new IllegalArgumentException("primitive type not supported: " + type); - } - - private String generateChoiceIsEmpty(final PrimitiveType type, final ByteOrder byteOrder) - { - return "\n" + - " @property\n" + - " def isEmpty(self) -> bool:\n" + - " return " + generateChoiceIsEmptyInner(type, byteOrder) + "\n" + - " \n"; - } - - private String generateChoiceIsEmptyInner(final PrimitiveType type, final ByteOrder byteOrder) - { - switch (type) - { - case UINT8: - case UINT16: - case UINT32: - case UINT64: - return "0 == " + byteOrder.toString() + "_" + type.primitiveName().toUpperCase() + - ".unpack_from(self._buffer, self._offset)[0]"; - } - - throw new IllegalArgumentException("primitive type not supported: " + type); - } - - private String generateChoiceGet(final PrimitiveType type, final String bitIndex, final String byteOrder) - { - switch (type) - { - case UINT8: - case UINT16: - case UINT32: - case UINT64: - return "0 != (" + byteOrder.toUpperCase() + "_" + type.primitiveName().toUpperCase() + - ".unpack_from(self._buffer, self._offset)[0] & (1 << " + bitIndex + "))"; - } - - throw new IllegalArgumentException("primitive type not supported: " + type); - } - - private String generateStaticChoiceGet(final PrimitiveType type, final String bitIndex) - { - switch (type) - { - case UINT8: - case UINT16: - case UINT32: - case UINT64: - return "0 != (value & (1 << " + bitIndex + "))"; - } - - throw new IllegalArgumentException("primitive type not supported: " + type); - } - - private String generateChoicePut(final PrimitiveType type, final String bitIdx, final String byteOrder) - { - final String byteOrderUpper = byteOrder.toUpperCase(); - switch (type) - { - case UINT8: - case UINT16: - case UINT32: - case UINT64: - return " bits = " + byteOrderUpper + "_" + type.primitiveName().toUpperCase() + - ".unpack_from(self._buffer, self._offset)[0]\n" + - " bits = (bits | (1 << " + bitIdx + ")) if value else (bits & ~(1 << " + bitIdx + "))\n" + - " " + byteOrderUpper + "_" + type.primitiveName().toUpperCase() + - ".pack_into(self._buffer, self._offset, bits)\n" + - " return self\n"; - - } - - throw new IllegalArgumentException("primitive type not supported: " + type); - } - - private String generateStaticChoicePut(final PrimitiveType type, final String bitIdx) - { - switch (type) - { - case UINT8: - case UINT16: - case UINT32: - case UINT64: - return INDENT + INDENT + "return (bits | (1 << " + bitIdx + ")) " + - "if value else (bits & ~(1 << " + bitIdx + "))\n"; - } - - throw new IllegalArgumentException("primitive type not supported: " + type); - } - - private CharSequence generateCompositeDecoderDisplay(final List tokens, final String baseIndent) - { - final String indent = baseIndent + INDENT; - final StringBuilder sb = new StringBuilder(); - - appendToString(sb, indent); - sb.append('\n'); - append(sb, indent, "def appendTo(self, builder: str) -> str:"); - Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); - - int lengthBeforeLastGeneratedSeparator = -1; - - for (int i = 1, end = tokens.size() - 1; i < end; ) - { - final Token encodingToken = tokens.get(i); - final String propertyName = formatPropertyName(encodingToken.name()); - lengthBeforeLastGeneratedSeparator = writeTokenDisplay(propertyName, encodingToken, sb, indent + INDENT); - i += encodingToken.componentTokenCount(); - } - - if (-1 != lengthBeforeLastGeneratedSeparator) - { - sb.setLength(lengthBeforeLastGeneratedSeparator); - } - - Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); - append(sb, indent, " return builder"); - return sb.toString(); - } - - private CharSequence generateChoiceDisplay(final List tokens) - { - final String indent = INDENT; - final StringBuilder sb = new StringBuilder(); - - appendToString(sb, indent); - sb.append('\n'); - append(sb, indent, "def appendTo(self, builder: str) -> str:"); - Separators.BEGIN_SET.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); - append(sb, indent, " atLeastOne: bool = False"); - - tokens - .stream() - .filter((token) -> token.signal() == Signal.CHOICE) - .forEach((token) -> - { - final String choiceName = formatPropertyName(token.name()); - append(sb, indent, " if self." + choiceName + "():"); - append(sb, indent, " if atLeastOne:"); - Separators.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT + INDENT, "builder"); - append(sb, indent, " builder += str(\"" + choiceName + "\")"); - append(sb, indent, " atLeastOne = True"); - }); - - Separators.END_SET.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); - sb.append('\n'); - append(sb, indent, " return builder"); - - return sb.toString(); - } - - private CharSequence generateDecoderDisplay( - final String name, - final List tokens, - final List groups, - final List varData, - final String baseIndent) - { - final String indent = baseIndent + INDENT; - final StringBuilder sb = new StringBuilder(); - - sb.append('\n'); - appendToString(sb, indent); - sb.append('\n'); - append(sb, indent, "def appendTo(self, builder: str) -> str:"); - append(sb, indent, " originalLimit: int = self.limit"); - append(sb, indent, " self.set_limit(self.offset + self._actingBlockLength)"); - append(sb, indent, " builder += str(\"[" + name + "](sbeTemplateId=\")"); - append(sb, indent, " builder += str(self.TEMPLATE_ID)"); - append(sb, indent, " builder += (\"|sbeSchemaId=\")"); - append(sb, indent, " builder += str(self.SCHEMA_ID)"); - append(sb, indent, " builder += (\"|sbeSchemaVersion=\")"); - append(sb, indent, " if self._parentMessage._actingVersion != self.SCHEMA_VERSION:"); - append(sb, indent, " builder += str(self._parentMessage._actingVersion)"); - append(sb, indent, " builder += str('/')"); - append(sb, indent, " builder += str(self.SCHEMA_VERSION)"); - append(sb, indent, " builder += (\"|sbeBlockLength=\")"); - append(sb, indent, " if self._actingBlockLength != self.BLOCK_LENGTH:"); - append(sb, indent, " builder += str(self._actingBlockLength)"); - append(sb, indent, " builder += str('/')"); - append(sb, indent, " builder += str(self.BLOCK_LENGTH)"); - append(sb, indent, " builder += (\"):\")"); - appendDecoderDisplay(sb, tokens, groups, varData, indent + INDENT); - sb.append('\n'); - append(sb, indent, " self.set_limit(originalLimit)"); - sb.append('\n'); - append(sb, indent, " return builder"); - sb.append('\n'); - return sb.toString(); - } - - private void appendGroupInstanceDecoderDisplay( - final StringBuilder sb, - final List fields, - final List groups, - final List varData, - final String baseIndent) - { - final String indent = baseIndent + INDENT; - - sb.append('\n'); - appendToString(sb, indent); - sb.append('\n'); - append(sb, indent, "def appendTo(self, builder: str) -> str:"); - Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); - appendDecoderDisplay(sb, fields, groups, varData, indent + INDENT); - Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); - append(sb, indent, " return builder"); - append(sb, "", "\n"); - } - - private void appendDecoderDisplay( - final StringBuilder sb, - final List fields, - final List groups, - final List varData, - final String indent) - { - int lengthBeforeLastGeneratedSeparator = -1; - - for (int i = 0, size = fields.size(); i < size; ) - { - final Token fieldToken = fields.get(i); - if (fieldToken.signal() == Signal.BEGIN_FIELD) - { - final Token encodingToken = fields.get(i + 1); - - final String fieldName = formatPropertyName(fieldToken.name()); - append(sb, indent, "#" + fieldToken); - lengthBeforeLastGeneratedSeparator = writeTokenDisplay(fieldName, encodingToken, sb, indent); - - i += fieldToken.componentTokenCount(); - } - else - { - ++i; - } - } - - for (int i = 0, size = groups.size(); i < size; i++) - { - final Token groupToken = groups.get(i); - if (groupToken.signal() != Signal.BEGIN_GROUP) - { - throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); - } - - append(sb, indent, "#" + groupToken); - - final String groupName = formatPropertyName(groupToken.name()); - - append( - sb, indent, "builder += str(\"" + groupName + Separators.KEY_VALUE + - Separators.BEGIN_GROUP + "\")"); - append(sb, indent, groupName + " = self." + groupName + "()"); - append(sb, indent, "if " + groupName + ".count() > 0:"); - append(sb, indent, " while " + groupName + ".hasNext():"); - append(sb, indent, " " + groupName + ".next().appendTo(builder)"); - Separators.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT, "builder"); - Separators.END_GROUP.appendToGeneratedBuilder(sb, indent, "builder"); - - lengthBeforeLastGeneratedSeparator = sb.length(); - Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); - - i = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); - } - - for (int i = 0, size = varData.size(); i < size; ) - { - final Token varDataToken = varData.get(i); - if (varDataToken.signal() != Signal.BEGIN_VAR_DATA) - { - throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); - } - - append(sb, indent, "#" + varDataToken); - - final String characterEncoding = varData.get(i + 3).encoding().characterEncoding(); - final String varDataName = formatPropertyName(varDataToken.name()); - append(sb, indent, "builder += str(\"" + varDataName + Separators.KEY_VALUE + "\")"); - if (null == characterEncoding) - { - append(sb, indent, "builder += str(self." + varDataName + "Length() + \" bytes of raw data\")"); - append(sb, indent, - "self._parentMessage.set_limit(self._parentMessage.limit + " + varDataName + "HeaderLength() + " + - varDataName + "Length())"); - } - else - { - append(sb, indent, "builder += str('\\'' + self." + varDataName + "() + '\\'')"); - } - lengthBeforeLastGeneratedSeparator = sb.length(); - Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); - i += varDataToken.componentTokenCount(); - } - - if (-1 != lengthBeforeLastGeneratedSeparator) - { - sb.setLength(lengthBeforeLastGeneratedSeparator); - } - } - - private int writeTokenDisplay( - final String fieldName, - final Token typeToken, - final StringBuilder sb, - final String indent) - { - append(sb, indent, "#" + typeToken); - - if (typeToken.encodedLength() <= 0 || typeToken.isConstantEncoding()) - { - return -1; - } - - append(sb, indent, "builder += str(\"" + fieldName + Separators.KEY_VALUE + "\")"); - - switch (typeToken.signal()) - { - case ENCODING: - if (typeToken.arrayLength() > 1) - { - if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) - { - append(sb, indent, "i: int = 0"); - append(sb, indent, - "while i < self." + fieldName + "Length() and self." + fieldName + "(i) > 0:"); - append(sb, indent, " builder += str(self." + fieldName + "(i))"); - append(sb, indent, " i += 1"); - } - else - { - Separators.BEGIN_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); - append(sb, indent, "if self." + fieldName + "Length() > 0:"); - append(sb, indent, " i: int = 0"); - append(sb, indent, " while i < self." + fieldName + "Length():"); - append(sb, indent, " builder += str(self." + fieldName + "(i))"); - append(sb, indent, " i += 1"); - Separators.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT, "builder"); - Separators.END_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); - } - } - else - { - // have to duplicate because of checkstyle :/ - append(sb, indent, "builder += str(self." + fieldName + "())"); - } - break; - - case BEGIN_ENUM: - case BEGIN_SET: - append(sb, indent, "builder += str(self." + fieldName + "())"); - break; - - case BEGIN_COMPOSITE: - append(sb, indent, "self._" + fieldName + ".appendTo(builder)"); - break; - } - - final int lengthBeforeFieldSeparator = sb.length(); - Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); - - return lengthBeforeFieldSeparator; - } - - private void appendToString(final StringBuilder sb, final String indent) - { - sb.append('\n'); - append(sb, indent, "def __str__(self) -> str:"); - append(sb, indent, " return self.appendTo(\"\")"); - } - - private String byteOrderString(final Encoding encoding) - { - return encoding.byteOrder().toString(); - } -} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java deleted file mode 100644 index c6ede697ed..0000000000 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/python/PyGeneratorTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package uk.co.real_logic.sbe.generation.python; - -import org.agrona.generation.StringWriterOutputManager; -import org.junit.Test; -import uk.co.real_logic.sbe.TestUtil; -import uk.co.real_logic.sbe.ir.Ir; -import uk.co.real_logic.sbe.xml.IrGenerator; -import uk.co.real_logic.sbe.xml.MessageSchema; -import uk.co.real_logic.sbe.xml.ParserOptions; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; - -public class PyGeneratorTest -{ - @Test() - public void codeGenerationSchemaTest() throws Exception - { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(TestUtil.getLocalResource("example-schema.xml"), options); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final StringWriterOutputManager outputManager = new StringWriterOutputManager(); - final PythonGenerator generator = new PythonGenerator(ir, - true, false, true, outputManager); - generator.generate(); - assertEquals(20, outputManager.getSources().size()); - assertTrue(outputManager.getSources().containsKey("null.engine_encoder")); - assertTrue(outputManager.getSources().containsKey("null.engine_decoder")); - assertTrue(outputManager.getSources().containsKey("null.optional_extras_encoder")); - assertTrue(outputManager.getSources().containsKey("null.optional_extras_decoder")); - assertTrue(outputManager.getSources().containsKey("null.booster_encoder")); - assertTrue(outputManager.getSources().containsKey("null.booster_decoder")); - assertTrue(outputManager.getSources().containsKey("null.message_header_encoder")); - assertTrue(outputManager.getSources().containsKey("null.message_header_decoder")); - assertTrue(outputManager.getSources().containsKey("null.boolean_type")); - assertTrue(outputManager.getSources().containsKey("null.model")); - assertTrue(outputManager.getSources().containsKey("null.var_string_encoding_encoder")); - assertTrue(outputManager.getSources().containsKey("null.var_string_encoding_decoder")); - assertTrue(outputManager.getSources().containsKey("null.boost_type")); - assertTrue(outputManager.getSources().containsKey("null._struct_defs")); - assertTrue(outputManager.getSources().containsKey("null.group_size_encoding_decoder")); - assertTrue(outputManager.getSources().containsKey("null.group_size_encoding_encoder")); - assertTrue(outputManager.getSources().containsKey("null.meta_attribute")); - assertTrue(outputManager.getSources().containsKey("null.car_encoder")); - assertTrue(outputManager.getSources().containsKey("null.car_decoder")); - assertTrue(outputManager.getSources().containsKey("null.__init__")); - } -} From 8b6b0fb465da4f69c807087c531bee476a885d2d Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 17 Sep 2019 14:32:52 -0700 Subject: [PATCH 0181/1594] [C++]: move print of JSON to after decode so that Car values are using decoding values. --- sbe-samples/src/main/cpp/GeneratedStubExample.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index b7abaf1d97..3e6a06349c 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -309,10 +309,10 @@ int main(int argc, const char* argv[]) std::size_t encodeMsgLength = encodeCar(car, buffer, hdr.encodedLength(), sizeof(buffer)); cout << "Encoded Lengths are " << encodeHdrLength << " + " << encodeMsgLength << endl; - cout << "Encoded json: '" << car << "'" << endl; std::size_t decodeHdrLength = decodeHdr(hdr, buffer, 0, sizeof(buffer)); std::size_t decodeMsgLength = decodeCar(car, buffer, hdr.encodedLength(), hdr.blockLength(), hdr.version(), sizeof(buffer)); + cout << "Encoded json: '" << car << "'" << endl; cout << "Decoded Lengths are " << decodeHdrLength << " + " << decodeMsgLength << endl; From afcbc40d478a58c541afa754c5b4eeac800746d9 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 17 Sep 2019 14:37:21 -0700 Subject: [PATCH 0182/1594] [C++]: move print of JSON to after decode and check and reset decoder before printing. --- sbe-samples/src/main/cpp/GeneratedStubExample.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index 3e6a06349c..2bc3ba528a 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -312,7 +312,6 @@ int main(int argc, const char* argv[]) std::size_t decodeHdrLength = decodeHdr(hdr, buffer, 0, sizeof(buffer)); std::size_t decodeMsgLength = decodeCar(car, buffer, hdr.encodedLength(), hdr.blockLength(), hdr.version(), sizeof(buffer)); - cout << "Encoded json: '" << car << "'" << endl; cout << "Decoded Lengths are " << decodeHdrLength << " + " << decodeMsgLength << endl; @@ -328,5 +327,8 @@ int main(int argc, const char* argv[]) return EXIT_FAILURE; } + car.wrapForDecode(buffer, hdr.encodedLength(), hdr.blockLength(), hdr.version(), sizeof(buffer)); + cout << "Encoded json: '" << car << "'" << endl; + return EXIT_SUCCESS; } From f8e3255acdd9b9893e27f0fdc9a888d457e6f883 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 17 Sep 2019 15:13:15 -0700 Subject: [PATCH 0183/1594] [C++]: make sure to set engine efficiency and boosterEnable fields. And decode them. --- sbe-samples/src/main/cpp/GeneratedStubExample.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index 2bc3ba528a..ae9686bf0e 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -85,6 +85,8 @@ std::size_t encodeCar(Car &car, char *buffer, std::uint64_t offset, std::uint64_ .capacity(2000) .numCylinders((short)4) .putManufacturerCode(MANUFACTURER_CODE) + .efficiency((std::int8_t)35) + .boosterEnabled(BooleanType::T) .booster().boostType(BoostType::NITROUS).horsePower(200); Car::FuelFigures& fuelFigures = car.fuelFiguresCount(3); @@ -250,6 +252,8 @@ std::size_t decodeCar( char tmp[1024]; std::uint64_t bytesCopied = engine.getFuel(tmp, sizeof(tmp)); + std::cout << "\ncar.engine.effifiency=" << (int)engine.efficiency(); + std::cout << "\ncar.engine.boosterEnabled=" << format(engine.boosterEnabled()); std::cout << "\ncar.engine.fuelLength=" << bytesCopied; std::cout << "\ncar.engine.fuel=" << std::string(tmp, bytesCopied); std::cout << "\ncar.engine.booster.boostType=" << format(engine.booster().boostType()); From 40ea81d0c7c497591cae857ebf057b04f36b4337 Mon Sep 17 00:00:00 2001 From: rnveach Date: Sun, 22 Sep 2019 17:39:19 -0400 Subject: [PATCH 0184/1594] remove deprecated allowMissingJavadoc from JavadocMethod --- config/checkstyle/checkstyle.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 63ad312c35..7e98799f1e 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -172,8 +172,7 @@ - - \ No newline at end of file + From 26b2ecd8e37fd3d4748f7f7f472a2e682454cf5a Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Mon, 23 Sep 2019 12:13:37 +0100 Subject: [PATCH 0185/1594] [Java] Update checkstyle config. --- config/checkstyle/checkstyle.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 7e98799f1e..203098f8b1 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -174,5 +174,9 @@ + + + + From 888329e4cd0012eac8cfbf1fbe65733d1e20aaf9 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Mon, 23 Sep 2019 12:23:06 +0100 Subject: [PATCH 0186/1594] [Java] Update checkstyle config. --- config/checkstyle/checkstyle.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 203098f8b1..7e98799f1e 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -174,9 +174,5 @@ - - - - From da83679564c1876b8fb0de4373a1f46672900d44 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 25 Sep 2019 13:39:17 +0100 Subject: [PATCH 0187/1594] [Java] Upgrade to javadoc-links 4.1.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ed42ca3021..f574474fd8 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'com.gradle.build-scan' version '2.4.1' - id 'io.freefair.javadoc-links' version '4.1.0' apply false + id 'io.freefair.javadoc-links' version '4.1.1' apply false id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } From 8db4cfaad8fd51af926c14c726d9683f0a056b81 Mon Sep 17 00:00:00 2001 From: Tomek Rozen Date: Wed, 25 Sep 2019 16:40:29 +0200 Subject: [PATCH 0188/1594] [C++] Read/write set raw value --- .../sbe/generation/cpp/CppGenerator.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index cf4b9a146e..deac6cc5b9 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -669,6 +669,24 @@ private void generateChoiceSet(final List tokens) throws IOException " }\n", cppTypeName(tokens.get(0).encoding().primitiveType()))); + out.append(String.format("\n" + + " SBE_NODISCARD %1$s rawValue() const\n" + + " {\n" + + " %1$s val;\n" + + " std::memcpy(&val, m_buffer + m_offset, sizeof(%1$s));\n" + + " return val;\n" + + " }\n", + cppTypeName(tokens.get(0).encoding().primitiveType()))); + + out.append(String.format("\n" + + " %1$s &rawValue(%2$s value)\n" + + " {\n" + + " std::memcpy(m_buffer + m_offset, &value, sizeof(%2$s));\n" + + " return *this;\n" + + " }\n", + bitSetName, + cppTypeName(tokens.get(0).encoding().primitiveType()))); + out.append(generateChoices(bitSetName, tokens.subList(1, tokens.size() - 1))); out.append(generateChoicesDisplay(bitSetName, tokens.subList(1, tokens.size() - 1))); out.append("};\n"); From e753d7a98032e1f4e9da934a0d56613bcb2dcfc4 Mon Sep 17 00:00:00 2001 From: Tomek Rozen Date: Fri, 27 Sep 2019 11:31:59 +0200 Subject: [PATCH 0189/1594] [C++] Remove conversion warnings Warnings reported by GCC (-Wconversion, -Wsign-conversion) and clang-tidy. --- .../sbe/generation/cpp/CppGenerator.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index deac6cc5b9..f178e6c119 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -772,7 +772,7 @@ private CharSequence generateChoices(final String bitsetClassName, final List(1) << %3$s)) != 0;\n" + + " return (bits & (1u << %3$su)) != 0;\n" + " }\n", choiceName, typeName, @@ -782,7 +782,7 @@ private CharSequence generateChoices(final String bitsetClassName, final List(1) << %3$s)) : (bits & ~(static_cast<%2$s>(1) << %3$s));\n" + + " static_cast<%2$s>(bits | (1u << %3$su)) : static_cast<%2$s>(bits & ~(1u << %3$su));\n" + " }\n", choiceName, typeName, @@ -794,7 +794,7 @@ private CharSequence generateChoices(final String bitsetClassName, final List(1) << %5$s)) != 0;\n" + + " return (%3$s(val) & (1u << %5$su)) != 0;\n" + " }\n", choiceName, generateChoiceNotPresentCondition(token.version(), BASE_INDENT), @@ -808,8 +808,8 @@ private CharSequence generateChoices(final String bitsetClassName, final List(1) << %5$s)) " + - ": (%4$s(bits) & ~(static_cast<%3$s>(1) << %5$s)));\n" + + " static_cast<%3$s>(%4$s(bits) | (1u << %5$su)) " + + ": static_cast<%3$s>(%4$s(bits) & ~(1u << %5$su)));\n" + " std::memcpy(m_buffer + m_offset, &bits, sizeof(%3$s));\n" + " return *this;\n" + " }\n", @@ -1594,7 +1594,7 @@ private CharSequence generateConstPropertyMethods( sb.append(String.format("\n" + indent + " SBE_NODISCARD const char *%1$s() const\n" + indent + " {\n" + - indent + " static std::uint8_t %1$sValues[] = {%2$s};\n\n" + + indent + " static const std::uint8_t %1$sValues[] = {%2$s};\n\n" + indent + " return (const char *)%1$sValues;\n" + indent + " }\n", @@ -1602,11 +1602,11 @@ private CharSequence generateConstPropertyMethods( values)); sb.append(String.format("\n" + - indent + " %1$s %2$s(const std::uint64_t index) const\n" + + indent + " SBE_NODISCARD %1$s %2$s(const std::uint64_t index) const\n" + indent + " {\n" + - indent + " static std::uint8_t %2$sValues[] = {%3$s};\n\n" + + indent + " static const std::uint8_t %2$sValues[] = {%3$s};\n\n" + - indent + " return %2$sValues[index];\n" + + indent + " return (char)%2$sValues[index];\n" + indent + " }\n", cppTypeName, propertyName, From edda8bb3ad9993c31205aae3e65417b2d9d0f80f Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 27 Sep 2019 12:07:21 +0100 Subject: [PATCH 0190/1594] [Java] Tidy up. --- .../sbe/generation/cpp/CppGenerator.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index f178e6c119..af41f10d19 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1594,7 +1594,7 @@ private CharSequence generateConstPropertyMethods( sb.append(String.format("\n" + indent + " SBE_NODISCARD const char *%1$s() const\n" + indent + " {\n" + - indent + " static const std::uint8_t %1$sValues[] = {%2$s};\n\n" + + indent + " static const std::uint8_t %1$sValues[] = { %2$s };\n\n" + indent + " return (const char *)%1$sValues;\n" + indent + " }\n", @@ -1604,7 +1604,7 @@ private CharSequence generateConstPropertyMethods( sb.append(String.format("\n" + indent + " SBE_NODISCARD %1$s %2$s(const std::uint64_t index) const\n" + indent + " {\n" + - indent + " static const std::uint8_t %2$sValues[] = {%3$s};\n\n" + + indent + " static const std::uint8_t %2$sValues[] = { %3$s };\n\n" + indent + " return (char)%2$sValues[index];\n" + indent + " }\n", @@ -1615,7 +1615,7 @@ private CharSequence generateConstPropertyMethods( sb.append(String.format("\n" + indent + " std::uint64_t get%1$s(char *dst, const std::uint64_t length) const\n" + indent + " {\n" + - indent + " static std::uint8_t %2$sValues[] = {%3$s};\n" + + indent + " static std::uint8_t %2$sValues[] = { %3$s };\n" + indent + " std::uint64_t bytesToCopy = " + "length < sizeof(%2$sValues) ? length : sizeof(%2$sValues);\n\n" + @@ -2465,6 +2465,7 @@ private CharSequence appendDisplay( i += varDataToken.componentTokenCount(); } + return sb; } @@ -2474,14 +2475,13 @@ private CharSequence writeTokenDisplay( final boolean[] atLeastOne, final String indent) { - final StringBuilder sb = new StringBuilder(); - final String fieldName = "writer." + formatPropertyName(fieldTokenName); - if (typeToken.encodedLength() <= 0 || typeToken.isConstantEncoding()) { - return sb.toString(); + return ""; } + final StringBuilder sb = new StringBuilder(); + if (atLeastOne[0]) { sb.append( @@ -2493,6 +2493,7 @@ private CharSequence writeTokenDisplay( } sb.append(indent + "builder << R\"(\"" + fieldTokenName + "\": )\";\n"); + final String fieldName = "writer." + formatPropertyName(fieldTokenName); switch (typeToken.signal()) { @@ -2596,6 +2597,7 @@ private CharSequence generateChoicesDisplay(final String name, final List sb.append( indent + " if (" + choiceName + "())\n" + indent + " {\n"); + if (i > 0) { sb.append( @@ -2606,10 +2608,12 @@ private CharSequence generateChoicesDisplay(final String name, final List } sb.append( indent + " builder << R\"(\"" + formatPropertyName(token.name()) + "\")\";\n"); + if (i < (size - 1)) { sb.append(indent + " atLeastOne = true;\n"); } + sb.append( indent + " }\n"); } From 64eb62fbedf429d45e31a6c940ee9b627620b1e5 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 30 Sep 2019 20:03:29 +0100 Subject: [PATCH 0191/1594] [Java] Remove build scan. --- build.gradle | 9 --------- gradle/build-scans.gradle | 33 --------------------------------- 2 files changed, 42 deletions(-) delete mode 100644 gradle/build-scans.gradle diff --git a/build.gradle b/build.gradle index f574474fd8..3ea2651bc8 100644 --- a/build.gradle +++ b/build.gradle @@ -21,21 +21,12 @@ buildscript { plugins { id 'java' - id 'com.gradle.build-scan' version '2.4.1' id 'io.freefair.javadoc-links' version '4.1.1' apply false id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } defaultTasks 'clean', 'build', 'shadowJar', 'install' -def env = System.getenv() -if (env.CI || env.TRAVIS) { - buildScan { - termsOfServiceUrl = 'https://gradle.com/terms-of-service' - apply from: 'gradle/build-scans.gradle' - } -} - def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() def sbeJavaVersion = JavaVersion.VERSION_1_8 diff --git a/gradle/build-scans.gradle b/gradle/build-scans.gradle deleted file mode 100644 index d30daf921d..0000000000 --- a/gradle/build-scans.gradle +++ /dev/null @@ -1,33 +0,0 @@ -def acceptFile = new File(gradle.gradleUserHomeDir, "build-scans/sbe/gradle-scans-license-agree.txt") -def env = System.getenv() -boolean isCI = env.CI || env.TRAVIS -boolean hasAccepted = isCI || env.SBE_GRADLE_SCANS_ACCEPT=='yes' || acceptFile.exists() && acceptFile.text.trim() == 'yes' -boolean hasRefused = env.SBE_GRADLE_SCANS_ACCEPT=='no' || acceptFile.exists() && acceptFile.text.trim() == 'no' - -buildScan { - if (hasAccepted) { - termsOfServiceAgree = 'yes' - } else if (!hasRefused) { - gradle.buildFinished { - println """ -This build uses Gradle Build Scans to gather statistics, share information about -failures, environmental issues, dependencies resolved during the build and more. -Build scans will be published after each build, if you accept the terms of -service, and in particular the privacy policy. - -Please read - - https://gradle.com/terms-of-service - https://gradle.com/legal/privacy - -and then: - - - set the `SBE_GRADLE_SCANS_ACCEPT` to `yes`/`no` if you agree with/refuse the TOS - - or create the ${acceptFile} file with `yes`/`no` in it if you agree with/refuse - -And we'll not bother you again. Note that build scans are only made public if -you share the URL at the end of the build. -""" - } - } -} From f86a7cb467545acaed1069a10ce0ff8d9938e82f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 30 Sep 2019 21:03:07 +0100 Subject: [PATCH 0192/1594] [Java] Remove scan from travis. --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index d5b075fc6c..d8327de355 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,13 +9,13 @@ matrix: language: java jdk: openjdk8 os: linux - script: ./gradlew --scan + script: ./gradlew - name: "OpenJDK 11" language: java jdk: openjdk11 os: linux - script: ./gradlew --scan + script: ./gradlew - name: "C#" language: csharp @@ -157,7 +157,7 @@ matrix: - llvm-toolchain-xenial-8 script: ./cppbuild/cppbuild - - name: "macOS" + - name: "Clang macOS" env: COMPILER=clang++ language: c++ compiler: clang From 6aa964a941cf6fd7d28c2818d65d89df0b6ec205 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 1 Oct 2019 21:46:48 +0100 Subject: [PATCH 0193/1594] [Java] Upgrade to Mockito 3.1.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3ea2651bc8..791df14072 100644 --- a/build.gradle +++ b/build.gradle @@ -131,7 +131,7 @@ subprojects { compile 'org.agrona:agrona:1.0.7' testCompile 'org.hamcrest:hamcrest:2.1' - testCompile 'org.mockito:mockito-core:3.0.0' + testCompile 'org.mockito:mockito-core:3.1.0' testCompile 'junit:junit:4.12' } From 0ef9693b72e7b44cdadb1f9c7ffe71097e6dd81e Mon Sep 17 00:00:00 2001 From: Erik Rigtorp Date: Thu, 3 Oct 2019 18:29:11 -0700 Subject: [PATCH 0194/1594] [C++] Make sure all members are initilized Compiler dead store elimination optimization pass should remove any unncessary stores when the codecs are used correctly. With incorrect use it will give predictable behavior. --- .../sbe/generation/cpp/CppGenerator.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 506b5d8ea3..b65d701f65 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -197,14 +197,14 @@ private static void generateGroupClassHeader( indent + "class %1$s\n" + indent + "{\n" + indent + "private:\n" + - indent + " char *m_buffer;\n" + - indent + " std::uint64_t m_bufferLength;\n" + - indent + " std::uint64_t *m_positionPtr;\n" + - indent + " std::uint64_t m_blockLength;\n" + - indent + " std::uint64_t m_count;\n" + - indent + " std::uint64_t m_index;\n" + - indent + " std::uint64_t m_offset;\n" + - indent + " std::uint64_t m_actingVersion;\n\n" + + indent + " char *m_buffer = nullptr;\n" + + indent + " std::uint64_t m_bufferLength = 0;\n" + + indent + " std::uint64_t *m_positionPtr = nullptr;\n" + + indent + " std::uint64_t m_blockLength = 0;\n" + + indent + " std::uint64_t m_count = 0;\n" + + indent + " std::uint64_t m_index = 0;\n" + + indent + " std::uint64_t m_offset = 0;\n" + + indent + " std::uint64_t m_actingVersion = 0;\n\n" + indent + " SBE_NODISCARD std::uint64_t *sbePositionPtr() SBE_NOEXCEPT\n" + indent + " {\n" + @@ -1619,9 +1619,9 @@ private CharSequence generateFixedFlyweightCode(final String className, final in return String.format( "private:\n" + " char *m_buffer = nullptr;\n" + - " std::uint64_t m_bufferLength;\n" + + " std::uint64_t m_bufferLength = 0;\n" + " std::uint64_t m_offset = 0;\n" + - " std::uint64_t m_actingVersion;\n\n" + + " std::uint64_t m_actingVersion = 0;\n\n" + "public:\n" + " enum MetaAttribute\n" + @@ -1772,8 +1772,8 @@ private CharSequence generateMessageFlyweightCode(final String className, final " char *m_buffer = nullptr;\n" + " std::uint64_t m_bufferLength = 0;\n" + " std::uint64_t m_offset = 0;\n" + - " std::uint64_t m_position;\n" + - " std::uint64_t m_actingVersion;\n\n" + + " std::uint64_t m_position = 0;\n" + + " std::uint64_t m_actingVersion = 0;\n\n" + " inline std::uint64_t *sbePositionPtr() SBE_NOEXCEPT\n" + " {\n" + From b32cbfaa0cd80ef16236afb6a17e7c6c2d137eeb Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 4 Oct 2019 08:24:08 +0100 Subject: [PATCH 0195/1594] [Java] Upgrade to javadoc-links 4.1.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 791df14072..8c5b3ac7cc 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ buildscript { plugins { id 'java' - id 'io.freefair.javadoc-links' version '4.1.1' apply false + id 'io.freefair.javadoc-links' version '4.1.2' apply false id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } From 8d319ee7eedd7c146acc512abacae3bf7cc7e7c3 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 4 Oct 2019 17:52:32 +0100 Subject: [PATCH 0196/1594] [Java] Upgrade to Agrona 1.0.8. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8c5b3ac7cc..abc723c9ff 100644 --- a/build.gradle +++ b/build.gradle @@ -128,7 +128,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.24' - compile 'org.agrona:agrona:1.0.7' + compile 'org.agrona:agrona:1.0.8' testCompile 'org.hamcrest:hamcrest:2.1' testCompile 'org.mockito:mockito-core:3.1.0' From f863b64cc6c3c721900ff9850e390a9fe3ef2b3e Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 8 Oct 2019 14:46:45 +0100 Subject: [PATCH 0197/1594] [Java] Update README for release. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b401e41c4d..3a2e3c30bc 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.13.2 +    1.13.3 ``` @@ -65,7 +65,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.13.3-SNAPSHOT.jar my_sbe_input.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.13.4-SNAPSHOT.jar my-sbe-input.xml C++ Build using CMake From 3a394420ddc5f7216e487dc28b3bc6c0996ff8bb Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 8 Oct 2019 16:17:48 -0700 Subject: [PATCH 0198/1594] 1.13.3 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 0ab9a82382..01b7568230 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.13.3-SNAPSHOT +1.13.3 From 4ff9c9de19e32d2ca3cc0aadf7ccca8c971bc9f6 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 8 Oct 2019 16:18:52 -0700 Subject: [PATCH 0199/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 01b7568230..955dfe681e 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.13.3 +1.13.4-SNAPSHOT \ No newline at end of file From 40751e9730add58bd3742dff583df79321f4a30c Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 11 Oct 2019 10:47:21 +0100 Subject: [PATCH 0200/1594] Drop GCC 5 from Travis build. --- .travis.yml | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/.travis.yml b/.travis.yml index d8327de355..c5cd55ac8a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,21 +31,7 @@ matrix: - ./csharp/runtests.sh - ./csharp/pack.sh - - name: "GCC 5" - env: COMPILER=g++-5 - language: cpp - compiler: gcc - os: linux - addons: - apt: - packages: - - g++-5 - - libsparsehash-dev - sources: - - ubuntu-toolchain-r-test - script: ./cppbuild/cppbuild - - - name: "GCC 6" + - name: "GCC 6" env: COMPILER=g++-6 language: cpp compiler: gcc @@ -59,7 +45,7 @@ matrix: - ubuntu-toolchain-r-test script: ./cppbuild/cppbuild - - name: "GCC 7" + - name: "GCC 7" env: COMPILER=g++-7 language: cpp compiler: gcc @@ -73,7 +59,7 @@ matrix: - ubuntu-toolchain-r-test script: ./cppbuild/cppbuild - - name: "GCC 8" + - name: "GCC 8" env: COMPILER=g++-8 language: cpp compiler: gcc @@ -87,7 +73,7 @@ matrix: - ubuntu-toolchain-r-test script: ./cppbuild/cppbuild - - name: "GCC 9" + - name: "GCC 9" env: COMPILER=g++-9 language: cpp compiler: gcc @@ -101,7 +87,7 @@ matrix: - ubuntu-toolchain-r-test script: ./cppbuild/cppbuild - - name: "Clang 5" + - name: "Clang 5" env: COMPILER=clang++-5.0 language: cpp compiler: clang @@ -115,7 +101,7 @@ matrix: - llvm-toolchain-xenial-5.0 script: ./cppbuild/cppbuild - - name: "Clang 6" + - name: "Clang 6" env: COMPILER=clang++-6.0 language: cpp compiler: clang @@ -129,7 +115,7 @@ matrix: - llvm-toolchain-xenial-6.0 script: ./cppbuild/cppbuild - - name: "Clang 7" + - name: "Clang 7" env: COMPILER=clang++-7 language: cpp compiler: clang @@ -143,7 +129,7 @@ matrix: - llvm-toolchain-xenial-7 script: ./cppbuild/cppbuild - - name: "Clang 8" + - name: "Clang 8" env: COMPILER=clang++-8 language: cpp compiler: clang From 6f9a79141c069193650b915e78f318d0410af095 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sun, 13 Oct 2019 16:13:04 +0100 Subject: [PATCH 0201/1594] [Java] Escape JSON strings in JsonTokenListener. --- .../sbe/json/JsonTokenListener.java | 33 +++++++++++++++---- .../co/real_logic/sbe/EncodedCarTestBase.java | 3 +- .../sbe/generation/java/ToStringTest.java | 4 +-- .../real_logic/sbe/json/JsonPrinterTest.java | 4 +-- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index 0252cdfa2d..75aa4c2148 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -184,7 +184,9 @@ public void onVarData( final byte[] tempBuffer = new byte[length]; buffer.getBytes(bufferIndex, tempBuffer, 0, length); - output.append(new String(tempBuffer, 0, length, typeToken.encoding().characterEncoding())); + final String str = new String(tempBuffer, 0, length, typeToken.encoding().characterEncoding()); + + escape(str); doubleQuote(); next(); @@ -223,13 +225,12 @@ private void appendEncodingAsString( if (encoding.primitiveType() == CHAR) { doubleQuote(); + output.append(constOrNotPresentValue.toString()); + doubleQuote(); } - - output.append(constOrNotPresentValue.toString()); - - if (encoding.primitiveType() == CHAR) + else { - doubleQuote(); + output.append(constOrNotPresentValue.toString()); } return; @@ -244,7 +245,7 @@ private void appendEncodingAsString( for (int i = 0; i < size; i++) { - output.append((char)buffer.getByte(index + (i * elementSize))); + escape((char)buffer.getByte(index + (i * elementSize))); } doubleQuote(); @@ -348,4 +349,22 @@ private static long readEncodingAsLong( return Types.getLong(buffer, bufferIndex, typeToken.encoding()); } + + private void escape(final String str) + { + for (int i = 0, length = str.length(); i < length; i++) + { + escape(str.charAt(i)); + } + } + + private void escape(final char c) + { + if ('"' == c || '\\' == c || '\b' == c || '\f' == c || '\n' == c || '\r' == c || '\t' == c) + { + output.append('\\'); + } + + output.append(c); + } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java index 317452b7ff..1cc0904e47 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java @@ -37,7 +37,7 @@ public static void setupExampleData() { try { - vehicleCode = "abcdef".getBytes(CarEncoder.vehicleCodeCharacterEncoding()); + vehicleCode = "ab\"def".getBytes(CarEncoder.vehicleCodeCharacterEncoding()); manufacturerCode = "123".getBytes(EngineEncoder.manufacturerCodeCharacterEncoding()); manufacturer = "Honda".getBytes(CarEncoder.manufacturerCharacterEncoding()); model = "Civic VTi".getBytes(CarEncoder.modelCharacterEncoding()); @@ -108,6 +108,7 @@ protected static void encodeTestMessage(final ByteBuffer buffer) CAR.manufacturer(new String(manufacturer)); CAR.putModel(model, srcOffset, model.length); + CAR.activationCode("315\\8"); bufferOffset += CAR.encodedLength(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java index 1b63202d41..b978a23fc1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java @@ -39,7 +39,7 @@ public void exampleMessagePrinted() "(sbeTemplateId=1|sbeSchemaId=1|sbeSchemaVersion=0|sbeBlockLength=45):" + "serialNumber=1234|modelYear=2013|available=T|code=A|" + "someNumbers=[0,1,2,3,4]|" + - "vehicleCode=abcdef|" + + "vehicleCode=ab\"def|" + "extras={sportsPack,cruiseControl}|" + "engine=(capacity=2000|numCylinders=4|manufacturerCode=123|)|" + "fuelFigures=[" + @@ -49,7 +49,7 @@ public void exampleMessagePrinted() "performanceFigures=[" + "(octaneRating=95|acceleration=[(mph=30|seconds=4.0),(mph=60|seconds=7.5),(mph=100|seconds=12.2)])," + "(octaneRating=99|acceleration=[(mph=30|seconds=3.8),(mph=60|seconds=7.1),(mph=100|seconds=11.8)])]|" + - "manufacturer='Honda'|model='Civic VTi'|activationCode=''", + "manufacturer='Honda'|model='Civic VTi'|activationCode='315\\8'", result); } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java index 0d76fde8a6..78c7f25c89 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java @@ -60,7 +60,7 @@ public void exampleMessagePrintedAsJson() throws Exception " \"available\": \"T\",\n" + " \"code\": \"A\",\n" + " \"someNumbers\": [0, 1, 2, 3, 4],\n" + - " \"vehicleCode\": \"abcdef\",\n" + + " \"vehicleCode\": \"ab\\\"def\",\n" + " \"extras\": { \"sunRoof\": false, \"sportsPack\": true, \"cruiseControl\": true },\n" + " \"engine\": \n" + " {\n" + @@ -118,7 +118,7 @@ public void exampleMessagePrintedAsJson() throws Exception " }],\n" + " \"manufacturer\": \"Honda\",\n" + " \"model\": \"Civic VTi\",\n" + - " \"activationCode\": \"\"\n" + + " \"activationCode\": \"315\\\\8\"\n" + "}", result); } From 83e514ac76ce83430aeda4374563053f8cd1ba13 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sun, 13 Oct 2019 16:58:40 +0100 Subject: [PATCH 0202/1594] [C++] Codec output formatting. --- .../sbe/generation/cpp/CppGenerator.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index e701000872..edae1f3fa0 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1769,8 +1769,11 @@ private static CharSequence generateConstructorsAndOperators(final String classN " {\n" + " }\n\n" + - " %1$s(char *buffer, const std::uint64_t bufferLength, const std::uint64_t actingBlockLength," + - " const std::uint64_t actingVersion) :\n" + + " %1$s(\n" + + " char *buffer,\n" + + " const std::uint64_t bufferLength,\n" + + " const std::uint64_t actingBlockLength,\n" + + " const std::uint64_t actingVersion) :\n" + " %1$s(buffer, 0, bufferLength, actingBlockLength, actingVersion)\n" + " {\n" + " }\n\n", @@ -1872,8 +1875,11 @@ private CharSequence generateMessageFlyweightCode(final String className, final " }\n\n" + " %10$s &wrapForDecode(\n" + - " char *buffer, const std::uint64_t offset, const std::uint64_t actingBlockLength,\n" + - " const std::uint64_t actingVersion, const std::uint64_t bufferLength)\n" + + " char *buffer,\n" + + " const std::uint64_t offset,\n" + + " const std::uint64_t actingBlockLength,\n" + + " const std::uint64_t actingVersion,\n" + + " const std::uint64_t bufferLength)\n" + " {\n" + " return *this = %10$s(buffer, offset, bufferLength, actingBlockLength, actingVersion);\n" + " }\n\n" + From 3a6e1348cacc5e1fb57e70eba16da483e5b19a10 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sun, 13 Oct 2019 20:12:59 +0100 Subject: [PATCH 0203/1594] [C++] Escape var data character strings when pretty printing codecs as JSON. Issue #718. --- .../sbe/generation/cpp/CppGenerator.java | 72 +++++++++++++++---- 1 file changed, 57 insertions(+), 15 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index edae1f3fa0..57cdfe3c48 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -302,6 +302,11 @@ private static void generateGroupClassHeader( indent + " *m_positionPtr = sbeCheckPosition(position);\n" + indent + " }\n\n" + + indent + " SBE_NODISCARD std::string sbeEscapeJson(const std::string &s) const SBE_NOEXCEPT\n" + + indent + " {\n" + + indent + " return ::sbeEscapeJsonString(s);\n" + + indent + " }\n\n" + + indent + " SBE_NODISCARD inline std::uint64_t count() const SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return m_count;\n" + @@ -1010,7 +1015,9 @@ private static CharSequence generateFileHeader( "#include \n" + "#include \n" + "#include \n\n" + - "#include \n\n" + + "#include \n" + + "#include \n" + + "#include \n\n" + "#if defined(WIN32) || defined(_WIN32)\n" + "# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)\n" + @@ -1053,10 +1060,12 @@ private static CharSequence generateFileHeader( "#define SBE_NULLVALUE_UINT8 (std::numeric_limits::max)()\n" + "#define SBE_NULLVALUE_UINT16 (std::numeric_limits::max)()\n" + "#define SBE_NULLVALUE_UINT32 (std::numeric_limits::max)()\n" + - "#define SBE_NULLVALUE_UINT64 (std::numeric_limits::max)()\n", + "#define SBE_NULLVALUE_UINT64 (std::numeric_limits::max)()\n\n", String.join("_", namespaces).toUpperCase(), className.toUpperCase())); + sb.append(generateEscapeFunction()); + if (typesToInclude != null && typesToInclude.size() != 0) { sb.append("\n"); @@ -1073,12 +1082,35 @@ private static CharSequence generateFileHeader( return sb; } + private static CharSequence generateEscapeFunction() + { + return + "#ifndef _SBE_JSON_ESCAPE_FUNC_H_\n" + + "#define _SBE_JSON_ESCAPE_FUNC_H_\n" + + "static inline std::string sbeEscapeJsonString(const std::string &s)\n" + + "{\n" + + " std::ostringstream oss;\n\n" + + " for (auto c = s.cbegin(); c != s.cend(); c++)\n" + + " {\n" + + " if (*c == '\"' || *c == '\\\\' || ('\\x00' <= *c && *c <= '\\x1f'))\n" + + " {\n" + + " oss << \"\\\\u\"" + " << std::hex << std::setw(4) << std::setfill('0') << (int)*c;\n" + + " }\n" + + " else\n" + + " {\n" + + " oss << *c;\n" + + " }\n" + + " }\n\n" + + " return oss.str();\n" + + "}\n" + + "#endif\n\n"; + } + private static CharSequence generateClassDeclaration(final String className) { - return String.format( - "class %s\n" + - "{\n", - className); + return + "class " + className + "\n" + + "{\n"; } private static CharSequence generateEnumDeclaration(final String name) @@ -1903,6 +1935,11 @@ private CharSequence generateMessageFlyweightCode(final String className, final " m_position = sbeCheckPosition(position);\n" + " }\n\n" + + " SBE_NODISCARD std::string sbeEscapeJson(const std::string &s) const SBE_NOEXCEPT\n" + + " {\n" + + " return ::sbeEscapeJsonString(s);\n" + + " }\n\n" + + " SBE_NODISCARD std::uint64_t encodedLength() const SBE_NOEXCEPT\n" + " {\n" + " return sbePosition() - m_offset;\n" + @@ -2320,7 +2357,7 @@ private CharSequence generateDisplay( indent + " builder << writer.sbeTemplateId();\n" + indent + " builder << \", \";\n\n" + "%2$s" + - indent + " builder << '}';\n" + + indent + " builder << '}';\n\n" + indent + " return builder;\n" + indent + "}\n", formatClassName(name), @@ -2341,7 +2378,7 @@ private CharSequence generateGroupDisplay( indent + "{\n" + indent + " builder << '{';\n" + "%2$s" + - indent + " builder << '}';\n" + + indent + " builder << '}';\n\n" + indent + " return builder;\n" + indent + "}\n", formatClassName(name), @@ -2360,7 +2397,7 @@ private CharSequence generateCompositeDisplay( indent + "{\n" + indent + " builder << '{';\n" + "%2$s" + - indent + " builder << '}';\n" + + indent + " builder << '}';\n\n" + indent + " return builder;\n" + indent + "}\n\n", formatClassName(name), @@ -2453,20 +2490,25 @@ private CharSequence appendDisplay( atLeastOne[0] = true; final String characterEncoding = varData.get(i + 3).encoding().characterEncoding(); - final String getAsStringFunction = "get" + toUpperFirstChar(varDataToken.name()) + "AsString().c_str()"; sb.append(indent + "builder << R\"(\"" + varDataToken.name() + "\": )\";\n"); if (null == characterEncoding) { + final String getAsStringFunction = + "writer.get" + toUpperFirstChar(varDataToken.name()) + "AsString().c_str()"; + sb.append( indent + "builder << '\"' <<\n" + - indent + INDENT + "writer." + getAsStringFunction + " << '\"';\n\n"); + indent + INDENT + getAsStringFunction + " << '\"';\n\n"); } else { + final String getAsStringFunction = + "writer.sbeEscapeJson(writer.get" + toUpperFirstChar(varDataToken.name()) + "AsString()).c_str()"; + sb.append( indent + "builder << '\"' <<\n" + - indent + INDENT + "writer." + getAsStringFunction + " << '\"';\n\n"); + indent + INDENT + getAsStringFunction + " << '\"';\n\n"); } i += varDataToken.componentTokenCount(); @@ -2510,8 +2552,8 @@ private CharSequence writeTokenDisplay( { sb.append( indent + "builder << '\"';\n" + - indent + "for (size_t i = 0;\n" + - indent + " i < " + fieldName + "Length() && " + fieldName + "(i) > 0;\n" + + indent + "for (size_t i = 0, length = " + fieldName + "Length();\n" + + indent + " i < length && " + fieldName + "(i) > 0;\n" + indent + " i++)\n" + indent + "{\n" + indent + " builder << (char)" + fieldName + "(i);\n" + @@ -2524,7 +2566,7 @@ private CharSequence writeTokenDisplay( indent + "builder << '[';\n" + indent + "if (" + fieldName + "Length() > 0)\n" + indent + "{\n" + - indent + " for (size_t i = 0; i < " + fieldName + "Length(); i++)\n" + + indent + " for (size_t i = 0, length = " + fieldName + "Length(); i < length; i++)\n" + indent + " {\n" + indent + " if (i)\n" + indent + " {\n" + From c24ac395e541f453c462e3c6d671c850806cf424 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Mon, 14 Oct 2019 10:03:35 +0100 Subject: [PATCH 0204/1594] [C++] Provide a getAsJsonEscapedString for var data and use it pretty printing plus give a summary of raw binary data rather than trying to print. Issue #718. --- .../sbe/generation/cpp/CppGenerator.java | 81 +++++++++---------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 57cdfe3c48..d07a0b1a11 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -302,11 +302,6 @@ private static void generateGroupClassHeader( indent + " *m_positionPtr = sbeCheckPosition(position);\n" + indent + " }\n\n" + - indent + " SBE_NODISCARD std::string sbeEscapeJson(const std::string &s) const SBE_NOEXCEPT\n" + - indent + " {\n" + - indent + " return ::sbeEscapeJsonString(s);\n" + - indent + " }\n\n" + - indent + " SBE_NODISCARD inline std::uint64_t count() const SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return m_count;\n" + @@ -526,6 +521,29 @@ private CharSequence generateVarData(final String className, final List t lengthByteOrderStr, lengthCppType)); + sb.append(String.format("\n" + + indent + " std::string get%1$sAsJsonEscapedString()\n" + + indent + " {\n" + + "%2$s" + + indent + " std::ostringstream oss;\n" + + indent + " std::string s = get%1$sAsString();\n\n" + + indent + " for (auto c = s.cbegin(); c != s.cend(); c++)\n" + + indent + " {\n" + + indent + " if (*c == '\"' || *c == '\\\\' || ('\\x00' <= *c && *c <= '\\x1f'))\n" + + indent + " {\n" + + indent + " oss << \"\\\\u\"" + " << std::hex << std::setw(4)\n" + + indent + " << std::setfill('0') << (int)(*c);\n" + + indent + " }\n" + + indent + " else\n" + + indent + " {\n" + + indent + " oss << *c;\n" + + indent + " }\n" + + indent + " }\n\n" + + indent + " return oss.str();\n" + + indent + " }\n", + propertyName, + generateStringNotPresentCondition(token.version(), indent))); + sb.append(String.format("\n" + indent + " #if __cplusplus >= 201703L\n" + indent + " std::string_view get%1$sAsStringView()\n" + @@ -1064,8 +1082,6 @@ private static CharSequence generateFileHeader( String.join("_", namespaces).toUpperCase(), className.toUpperCase())); - sb.append(generateEscapeFunction()); - if (typesToInclude != null && typesToInclude.size() != 0) { sb.append("\n"); @@ -1082,35 +1098,11 @@ private static CharSequence generateFileHeader( return sb; } - private static CharSequence generateEscapeFunction() - { - return - "#ifndef _SBE_JSON_ESCAPE_FUNC_H_\n" + - "#define _SBE_JSON_ESCAPE_FUNC_H_\n" + - "static inline std::string sbeEscapeJsonString(const std::string &s)\n" + - "{\n" + - " std::ostringstream oss;\n\n" + - " for (auto c = s.cbegin(); c != s.cend(); c++)\n" + - " {\n" + - " if (*c == '\"' || *c == '\\\\' || ('\\x00' <= *c && *c <= '\\x1f'))\n" + - " {\n" + - " oss << \"\\\\u\"" + " << std::hex << std::setw(4) << std::setfill('0') << (int)*c;\n" + - " }\n" + - " else\n" + - " {\n" + - " oss << *c;\n" + - " }\n" + - " }\n\n" + - " return oss.str();\n" + - "}\n" + - "#endif\n\n"; - } - private static CharSequence generateClassDeclaration(final String className) { return - "class " + className + "\n" + - "{\n"; + "class " + className + "\n" + + "{\n"; } private static CharSequence generateEnumDeclaration(final String name) @@ -1724,8 +1716,11 @@ private CharSequence generateFixedFlyweightCode(final String className, final in " {\n" + " }\n\n" + - " %1$s &wrap(char *buffer, const std::uint64_t offset, const std::uint64_t actingVersion," + - " const std::uint64_t bufferLength)\n" + + " %1$s &wrap(\n" + + " char *buffer,\n" + + " const std::uint64_t offset,\n" + + " const std::uint64_t actingVersion,\n" + + " const std::uint64_t bufferLength)\n" + " {\n" + " return *this = %1$s(buffer, offset, bufferLength, actingVersion);\n" + " }\n\n" + @@ -1935,11 +1930,6 @@ private CharSequence generateMessageFlyweightCode(final String className, final " m_position = sbeCheckPosition(position);\n" + " }\n\n" + - " SBE_NODISCARD std::string sbeEscapeJson(const std::string &s) const SBE_NOEXCEPT\n" + - " {\n" + - " return ::sbeEscapeJsonString(s);\n" + - " }\n\n" + - " SBE_NODISCARD std::uint64_t encodedLength() const SBE_NOEXCEPT\n" + " {\n" + " return sbePosition() - m_offset;\n" + @@ -2494,17 +2484,20 @@ private CharSequence appendDisplay( if (null == characterEncoding) { - final String getAsStringFunction = - "writer.get" + toUpperFirstChar(varDataToken.name()) + "AsString().c_str()"; + final String propertyName = toLowerFirstChar(varDataToken.name()); + final String getLengthFunction = "writer." + propertyName + "Length()"; sb.append( indent + "builder << '\"' <<\n" + - indent + INDENT + getAsStringFunction + " << '\"';\n\n"); + indent + INDENT + getLengthFunction + " << \" bytes of raw data\\\"\";\n"); + + sb.append( + indent + "writer." + propertyName + "();\n\n"); } else { final String getAsStringFunction = - "writer.sbeEscapeJson(writer.get" + toUpperFirstChar(varDataToken.name()) + "AsString()).c_str()"; + "writer.get" + toUpperFirstChar(varDataToken.name()) + "AsJsonEscapedString().c_str()"; sb.append( indent + "builder << '\"' <<\n" + From fef655d256bd0f182fb9a810cb8e1a42e41b6d1f Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Mon, 14 Oct 2019 10:30:54 +0100 Subject: [PATCH 0205/1594] [Java] Upgrade to Checkstyle 8.25. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index abc723c9ff..47604b29ac 100644 --- a/build.gradle +++ b/build.gradle @@ -126,7 +126,7 @@ subprojects { jar.enabled = true dependencies { - checkstyle 'com.puppycrawl.tools:checkstyle:8.24' + checkstyle 'com.puppycrawl.tools:checkstyle:8.25' compile 'org.agrona:agrona:1.0.8' @@ -135,7 +135,7 @@ subprojects { testCompile 'junit:junit:4.12' } - checkstyle.toolVersion = '8.24' + checkstyle.toolVersion = '8.25' compileJava { sourceCompatibility = sbeJavaVersion From 812a833c1298e4709000f0af3315ad59cf4025ee Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 15 Oct 2019 08:48:48 +0100 Subject: [PATCH 0206/1594] [C++] Use Json shortcuts so US_ASCII can be encoded and UTF-8 in shortest format. --- .../sbe/generation/cpp/CppGenerator.java | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index d07a0b1a11..1f96bfe460 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -529,14 +529,25 @@ private CharSequence generateVarData(final String className, final List t indent + " std::string s = get%1$sAsString();\n\n" + indent + " for (auto c = s.cbegin(); c != s.cend(); c++)\n" + indent + " {\n" + - indent + " if (*c == '\"' || *c == '\\\\' || ('\\x00' <= *c && *c <= '\\x1f'))\n" + + indent + " switch (*c)\n" + indent + " {\n" + - indent + " oss << \"\\\\u\"" + " << std::hex << std::setw(4)\n" + - indent + " << std::setfill('0') << (int)(*c);\n" + - indent + " }\n" + - indent + " else\n" + - indent + " {\n" + - indent + " oss << *c;\n" + + indent + " case '\"': oss << \"\\\\\\\"\"; break;\n" + + indent + " case '\\\\': oss << \"\\\\\\\\\"; break;\n" + + indent + " case '\\b': oss << \"\\\\b\"; break;\n" + + indent + " case '\\f': oss << \"\\\\f\"; break;\n" + + indent + " case '\\n': oss << \"\\\\n\"; break;\n" + + indent + " case '\\r': oss << \"\\\\r\"; break;\n" + + indent + " case '\\t': oss << \"\\\\t\"; break;\n\n" + + indent + " default:\n" + + indent + " if ('\\x00' <= *c && *c <= '\\x1f')\n" + + indent + " {\n" + + indent + " oss << \"\\\\u\"" + " << std::hex << std::setw(4)\n" + + indent + " << std::setfill('0') << (int)(*c);\n" + + indent + " }\n" + + indent + " else\n" + + indent + " {\n" + + indent + " oss << *c;\n" + + indent + " }\n" + indent + " }\n" + indent + " }\n\n" + indent + " return oss.str();\n" + From 97b38c8a094dd8dd5f00347dd55bb94d8f7e85e2 Mon Sep 17 00:00:00 2001 From: Tomek Rozen Date: Tue, 15 Oct 2019 10:05:12 +0200 Subject: [PATCH 0207/1594] [C++] Cast memcpy argument to size_t --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index d07a0b1a11..077ff22017 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -472,7 +472,7 @@ private CharSequence generateVarData(final String className, final List t indent + " std::uint64_t bytesToCopy = length < dataLength ? length : dataLength;\n" + indent + " std::uint64_t pos = sbePosition();\n" + indent + " sbePosition(pos + dataLength);\n" + - indent + " std::memcpy(dst, m_buffer + pos, bytesToCopy);\n" + + indent + " std::memcpy(dst, m_buffer + pos, static_cast(bytesToCopy));\n" + indent + " return bytesToCopy;\n" + indent + " }\n", propertyName, @@ -1441,7 +1441,8 @@ private CharSequence generateArrayProperty( indent + " }\n\n" + "%3$s" + - indent + " std::memcpy(dst, m_buffer + m_offset + %4$d, sizeof(%5$s) * length);\n" + + indent + " std::memcpy(dst, m_buffer + m_offset + %4$d, " + + "sizeof(%5$s) * static_cast(length));\n" + indent + " return length;\n" + indent + " }\n", toUpperFirstChar(propertyName), @@ -1643,7 +1644,7 @@ private CharSequence generateConstPropertyMethods( indent + " std::uint64_t bytesToCopy = " + "length < sizeof(%2$sValues) ? length : sizeof(%2$sValues);\n\n" + - indent + " std::memcpy(dst, %2$sValues, bytesToCopy);\n" + + indent + " std::memcpy(dst, %2$sValues, static_cast(bytesToCopy));\n" + indent + " return bytesToCopy;\n" + indent + " }\n", toUpperFirstChar(propertyName), From 49ca0138dd81278ae4a54aa47370839c8c732102 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 16 Oct 2019 09:00:59 +0100 Subject: [PATCH 0208/1594] [C++] Reduce copying of data in CppGenerator. --- .../sbe/generation/cpp/CppGenerator.java | 64 ++++++++----------- 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index f2fbc4b0ef..1ad2a5f411 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -132,13 +132,13 @@ public void generate() throws IOException collectVarData(messageBody, i, varData); final StringBuilder sb = new StringBuilder(); - out.append(generateFields(className, fields, BASE_INDENT, false)); + generateFields(sb, className, fields, BASE_INDENT, false); generateGroups(sb, groups, BASE_INDENT); + generateVarData(sb, className, varData, BASE_INDENT); + generateDisplay(sb, msgToken.name(), fields, groups, varData, BASE_INDENT + INDENT); + sb.append("};\n"); + sb.append(CppUtil.closingBraces(ir.namespaces().length)).append("#endif\n"); out.append(sb); - out.append(generateVarData(className, varData, BASE_INDENT)); - out.append(generateDisplay(msgToken.name(), fields, groups, varData, BASE_INDENT + INDENT)); - out.append("};\n"); - out.append(CppUtil.closingBraces(ir.namespaces().length)).append("#endif\n"); } } } @@ -165,7 +165,7 @@ private void generateGroups(final StringBuilder sb, final List tokens, fi final List fields = new ArrayList<>(); i = collectFields(tokens, i, fields); - sb.append(generateFields(formatClassName(groupName), fields, indent + INDENT, false)); + generateFields(sb, formatClassName(groupName), fields, indent + INDENT, false); final List groups = new ArrayList<>(); i = collectGroups(tokens, i, groups); @@ -173,12 +173,12 @@ private void generateGroups(final StringBuilder sb, final List tokens, fi final List varData = new ArrayList<>(); i = collectVarData(tokens, i, varData); - sb.append(generateVarData(formatClassName(groupName), varData, indent + INDENT)); + generateVarData(sb, formatClassName(groupName), varData, indent + INDENT); sb.append(generateGroupDisplay(groupName, fields, groups, varData, indent + INDENT + INDENT)); sb.append(indent).append(" };\n"); - sb.append(generateGroupProperty(groupName, groupToken, cppTypeForNumInGroup, indent)); + generateGroupProperty(sb, groupName, groupToken, cppTypeForNumInGroup, indent); } } @@ -350,11 +350,13 @@ private static void generateGroupClassHeader( .append(indent).append("#endif\n"); } - private static CharSequence generateGroupProperty( - final String groupName, final Token token, final String cppTypeForNumInGroup, final String indent) + private static void generateGroupProperty( + final StringBuilder sb, + final String groupName, + final Token token, + final String cppTypeForNumInGroup, + final String indent) { - final StringBuilder sb = new StringBuilder(); - final String className = formatClassName(groupName); final String propertyName = formatPropertyName(groupName); @@ -413,14 +415,11 @@ private static CharSequence generateGroupProperty( indent + " }\n", propertyName, token.version())); - - return sb; } - private CharSequence generateVarData(final String className, final List tokens, final String indent) + private void generateVarData( + final StringBuilder sb, final String className, final List tokens, final String indent) { - final StringBuilder sb = new StringBuilder(); - for (int i = 0, size = tokens.size(); i < size;) { final Token token = tokens.get(i); @@ -604,8 +603,6 @@ private CharSequence generateVarData(final String className, final List t i += token.componentTokenCount(); } - - return sb; } private void generateVarDataDescriptors( @@ -1979,11 +1976,13 @@ private CharSequence generateMessageFlyweightCode(final String className, final generateConstructorsAndOperators(className)); } - private CharSequence generateFields( - final String containingClassName, final List tokens, final String indent, final boolean inComposite) + private void generateFields( + final StringBuilder sb, + final String containingClassName, + final List tokens, + final String indent, + final boolean inComposite) { - final StringBuilder sb = new StringBuilder(); - for (int i = 0, size = tokens.size(); i < size; i++) { final Token signalToken = tokens.get(i); @@ -2016,8 +2015,6 @@ private CharSequence generateFields( } } } - - return sb; } private void generateFieldCommonMethods( @@ -2339,14 +2336,15 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu return literal; } - private CharSequence generateDisplay( + private void generateDisplay( + final StringBuilder sb, final String name, final List fields, final List groups, final List varData, final String indent) { - return String.format("\n" + + sb.append(String.format("\n" + indent + "template\n" + indent + "friend std::basic_ostream& operator<<(\n" + indent + " std::basic_ostream& builder, %1$s _writer)\n" + @@ -2363,7 +2361,7 @@ private CharSequence generateDisplay( indent + " return builder;\n" + indent + "}\n", formatClassName(name), - appendDisplay(fields, groups, varData, indent + INDENT)); + appendDisplay(fields, groups, varData, indent + INDENT))); } private CharSequence generateGroupDisplay( @@ -2387,10 +2385,7 @@ private CharSequence generateGroupDisplay( appendDisplay(fields, groups, varData, indent + INDENT)); } - private CharSequence generateCompositeDisplay( - final String name, - final List tokens, - final String indent) + private CharSequence generateCompositeDisplay(final String name, final List tokens, final String indent) { return String.format("\n" + indent + "template\n" + @@ -2407,10 +2402,7 @@ private CharSequence generateCompositeDisplay( } private CharSequence appendDisplay( - final List fields, - final List groups, - final List varData, - final String indent) + final List fields, final List groups, final List varData, final String indent) { final StringBuilder sb = new StringBuilder(); final boolean[] atLeastOne = {false}; From c043457f4de39ee6fb1baaa29c7f2101cae24349 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 16 Oct 2019 09:36:53 +0100 Subject: [PATCH 0209/1594] [C++] Reduce copying of data in CppGenerator. --- .../sbe/generation/cpp/CppGenerator.java | 413 +++++++++--------- 1 file changed, 200 insertions(+), 213 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 1ad2a5f411..307b135082 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -29,6 +29,7 @@ import java.io.Writer; import java.nio.ByteOrder; import java.util.ArrayList; +import java.util.Formatter; import java.util.List; import static uk.co.real_logic.sbe.generation.cpp.CppUtil.*; @@ -193,7 +194,7 @@ private static void generateGroupClassHeader( final String cppTypeForBlockLength = cppTypeName(blockLengthToken.encoding().primitiveType()); final String cppTypeForNumInGroup = cppTypeName(numInGroupToken.encoding().primitiveType()); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + "class %1$s\n" + indent + "{\n" + indent + "private:\n" + @@ -212,9 +213,9 @@ private static void generateGroupClassHeader( indent + " }\n\n" + indent + "public:\n", - formatClassName(groupName))); + formatClassName(groupName)); - sb.append(String.format( + new Formatter(sb).format( indent + " inline void wrapForDecode(\n" + indent + " char *buffer,\n" + indent + " std::uint64_t *pos,\n" + @@ -231,12 +232,12 @@ private static void generateGroupClassHeader( indent + " m_positionPtr = pos;\n" + indent + " *m_positionPtr = *m_positionPtr + %1$d;\n" + indent + " }\n", - dimensionHeaderLength, dimensionsClassName)); + dimensionHeaderLength, dimensionsClassName); final long minCount = numInGroupToken.encoding().applicableMinValue().longValue(); final String minCheck = minCount > 0 ? "count < " + minCount + " || " : ""; - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " inline void wrapForEncode(\n" + indent + " char *buffer,\n" + indent + " const %3$s count,\n" + @@ -270,9 +271,9 @@ private static void generateGroupClassHeader( cppTypeForBlockLength, blockLength, cppTypeForNumInGroup, dimensionHeaderLength, minCheck, numInGroupToken.encoding().applicableMaxValue().longValue(), - dimensionsClassName)); + dimensionsClassName); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t sbeHeaderSize() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %1$d;\n" + @@ -325,7 +326,7 @@ private static void generateGroupClassHeader( indent + " return *this;\n" + indent + " }\n", - dimensionHeaderLength, blockLength, formatClassName(groupName))); + dimensionHeaderLength, blockLength, formatClassName(groupName)); sb.append(indent).append("#if __cplusplus < 201103L\n") .append(indent).append(" template inline void forEach(Func& func)\n") @@ -360,32 +361,32 @@ private static void generateGroupProperty( final String className = formatClassName(groupName); final String propertyName = formatPropertyName(groupName); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + "private:\n" + indent + " %1$s m_%2$s;\n\n" + "public:\n", className, - propertyName)); + propertyName); - sb.append(String.format( + new Formatter(sb).format( indent + " SBE_NODISCARD static SBE_CONSTEXPR std::uint16_t %1$sId() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n", groupName, - token.id())); + token.id()); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD inline %1$s &%2$s()\n" + indent + " {\n" + indent + " m_%2$s.wrapForDecode(m_buffer, sbePositionPtr(), m_actingVersion, m_bufferLength);\n" + indent + " return m_%2$s;\n" + indent + " }\n", className, - propertyName)); + propertyName); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " %1$s &%2$sCount(const %3$s count)\n" + indent + " {\n" + indent + " m_%2$s.wrapForEncode(" + @@ -394,9 +395,9 @@ private static void generateGroupProperty( indent + " }\n", className, propertyName, - cppTypeForNumInGroup)); + cppTypeForNumInGroup); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + @@ -414,7 +415,7 @@ private static void generateGroupProperty( indent + "#endif\n" + indent + " }\n", propertyName, - token.version())); + token.version()); } private void generateVarData( @@ -442,7 +443,7 @@ private void generateVarData( generateVarDataDescriptors( sb, token, propertyName, characterEncoding, lengthToken, lengthOfLengthField, lengthCppType, indent); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD const char *%1$s()\n" + indent + " {\n" + "%2$s" + @@ -456,9 +457,9 @@ private void generateVarData( generateTypeFieldNotPresentCondition(token.version(), indent), lengthOfLengthField, lengthCppType, - lengthByteOrderStr)); + lengthByteOrderStr); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " std::uint64_t get%1$s(char *dst, const std::uint64_t length)\n" + indent + " {\n" + "%2$s" + @@ -478,9 +479,9 @@ private void generateVarData( generateArrayFieldNotPresentCondition(token.version(), indent), lengthOfLengthField, lengthByteOrderStr, - lengthCppType)); + lengthCppType); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " %5$s &put%1$s(const char *src, const %3$s length)\n" + indent + " {\n" + indent + " std::uint64_t lengthOfLengthField = %2$d;\n" + @@ -497,9 +498,9 @@ private void generateVarData( lengthOfLengthField, lengthCppType, lengthByteOrderStr, - className)); + className); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " std::string get%1$sAsString()\n" + indent + " {\n" + "%2$s" + @@ -518,9 +519,9 @@ private void generateVarData( generateStringNotPresentCondition(token.version(), indent), lengthOfLengthField, lengthByteOrderStr, - lengthCppType)); + lengthCppType); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " std::string get%1$sAsJsonEscapedString()\n" + indent + " {\n" + "%2$s" + @@ -552,9 +553,9 @@ private void generateVarData( indent + " return oss.str();\n" + indent + " }\n", propertyName, - generateStringNotPresentCondition(token.version(), indent))); + generateStringNotPresentCondition(token.version(), indent)); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " #if __cplusplus >= 201703L\n" + indent + " std::string_view get%1$sAsStringView()\n" + indent + " {\n" + @@ -575,9 +576,9 @@ private void generateVarData( generateStringViewNotPresentCondition(token.version(), indent), lengthOfLengthField, lengthByteOrderStr, - lengthCppType)); + lengthCppType); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " %1$s &put%2$s(const std::string& str)\n" + indent + " {\n" + indent + " if (str.length() > %6$d)\n" + @@ -599,7 +600,7 @@ private void generateVarData( lengthOfLengthField, lengthCppType, lengthByteOrderStr, - lengthToken.encoding().applicableMaxValue().longValue())); + lengthToken.encoding().applicableMaxValue().longValue()); i += token.componentTokenCount(); } @@ -615,15 +616,15 @@ private void generateVarDataDescriptors( final String lengthCppType, final String indent) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " static const char *%1$sCharacterEncoding() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return \"%2$s\";\n" + indent + " }\n", toLowerFirstChar(propertyName), - characterEncoding)); + characterEncoding); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + @@ -647,17 +648,17 @@ private void generateVarDataDescriptors( indent + " }\n", toLowerFirstChar(propertyName), token.version(), - token.id())); + token.id()); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t %sHeaderLength() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %d;\n" + indent + " }\n", toLowerFirstChar(propertyName), - sizeOfLengthField)); + sizeOfLengthField); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " %4$s %1$sLength() const\n" + indent + " {\n" + "%2$s" + @@ -668,7 +669,7 @@ private void generateVarDataDescriptors( toLowerFirstChar(propertyName), generateArrayFieldNotPresentCondition(token.version(), BASE_INDENT), formatByteOrderEncoding(lengthToken.encoding().byteOrder(), lengthToken.encoding().primitiveType()), - lengthCppType)); + lengthCppType); } private void generateChoiceSet(final List tokens) throws IOException @@ -681,7 +682,7 @@ private void generateChoiceSet(final List tokens) throws IOException out.append(generateClassDeclaration(bitSetName)); out.append(generateFixedFlyweightCode(bitSetName, tokens.get(0).encodedLength())); - out.append(String.format("\n" + + new Formatter(out).format("\n" + " %1$s &clear()\n" + " {\n" + " %2$s zero = 0;\n" + @@ -689,34 +690,34 @@ private void generateChoiceSet(final List tokens) throws IOException " return *this;\n" + " }\n", bitSetName, - cppTypeName(tokens.get(0).encoding().primitiveType()))); + cppTypeName(tokens.get(0).encoding().primitiveType())); - out.append(String.format("\n" + + new Formatter(out).format("\n" + " SBE_NODISCARD bool isEmpty() const\n" + " {\n" + " %1$s val;\n" + " std::memcpy(&val, m_buffer + m_offset, sizeof(%1$s));\n" + " return 0 == val;\n" + " }\n", - cppTypeName(tokens.get(0).encoding().primitiveType()))); + cppTypeName(tokens.get(0).encoding().primitiveType())); - out.append(String.format("\n" + + new Formatter(out).format("\n" + " SBE_NODISCARD %1$s rawValue() const\n" + " {\n" + " %1$s val;\n" + " std::memcpy(&val, m_buffer + m_offset, sizeof(%1$s));\n" + " return val;\n" + " }\n", - cppTypeName(tokens.get(0).encoding().primitiveType()))); + cppTypeName(tokens.get(0).encoding().primitiveType())); - out.append(String.format("\n" + + new Formatter(out).format("\n" + " %1$s &rawValue(%2$s value)\n" + " {\n" + " std::memcpy(m_buffer + m_offset, &value, sizeof(%2$s));\n" + " return *this;\n" + " }\n", bitSetName, - cppTypeName(tokens.get(0).encoding().primitiveType()))); + cppTypeName(tokens.get(0).encoding().primitiveType())); out.append(generateChoices(bitSetName, tokens.subList(1, tokens.size() - 1))); out.append(generateChoicesDisplay(bitSetName, tokens.subList(1, tokens.size() - 1))); @@ -800,16 +801,16 @@ private CharSequence generateChoices(final String bitsetClassName, final List tokens, f final String enumName = formatClassName(encodingToken.applicableTypeName()); final StringBuilder sb = new StringBuilder(); - sb.append(String.format( + new Formatter(sb).format( " static %1$s::Value get(const %2$s value)\n" + " {\n" + " switch (value)\n" + " {\n", enumName, - cppTypeName(tokens.get(0).encoding().primitiveType()))); + cppTypeName(tokens.get(0).encoding().primitiveType())); for (final Token token : tokens) { - sb.append(String.format( + new Formatter(sb).format( " case %1$s: return %2$s;\n", token.encoding().constValue().toString(), - token.name())); + token.name()); } - sb.append(String.format( + new Formatter(sb).format( " case %1$s: return NULL_VALUE;\n" + " }\n\n" + " throw std::runtime_error(\"unknown value for enum %2$s [E103]\");\n" + " }\n", encodingToken.encoding().applicableNullValue().toString(), - enumName)); + enumName); return sb; } @@ -1134,19 +1135,19 @@ private CharSequence generateCompositePropertyElements( switch (fieldToken.signal()) { case ENCODING: - sb.append(generatePrimitiveProperty(containingClassName, propertyName, fieldToken, indent)); + generatePrimitiveProperty(sb, containingClassName, propertyName, fieldToken, indent); break; case BEGIN_ENUM: - sb.append(generateEnumProperty(containingClassName, fieldToken, propertyName, fieldToken, indent)); + generateEnumProperty(sb, containingClassName, fieldToken, propertyName, fieldToken, indent); break; case BEGIN_SET: - sb.append(generateBitsetProperty(propertyName, fieldToken, indent)); + generateBitsetProperty(sb, propertyName, fieldToken, indent); break; case BEGIN_COMPOSITE: - sb.append(generateCompositeProperty(propertyName, fieldToken, indent)); + generateCompositeProperty(sb, propertyName, fieldToken, indent); break; } @@ -1156,88 +1157,85 @@ private CharSequence generateCompositePropertyElements( return sb; } - private CharSequence generatePrimitiveProperty( - final String containingClassName, final String propertyName, final Token token, final String indent) + private void generatePrimitiveProperty( + final StringBuilder sb, + final String containingClassName, + final String propertyName, + final Token token, + final String indent) { - final StringBuilder sb = new StringBuilder(); - - sb.append(generatePrimitiveFieldMetaData(propertyName, token, indent)); + generatePrimitiveFieldMetaData(sb, propertyName, token, indent); if (token.isConstantEncoding()) { - sb.append(generateConstPropertyMethods(propertyName, token, indent)); + generateConstPropertyMethods(sb, propertyName, token, indent); } else { - sb.append(generatePrimitivePropertyMethods(containingClassName, propertyName, token, indent)); + generatePrimitivePropertyMethods(sb, containingClassName, propertyName, token, indent); } - - return sb; } - private CharSequence generatePrimitivePropertyMethods( - final String containingClassName, final String propertyName, final Token token, final String indent) + private void generatePrimitivePropertyMethods( + final StringBuilder sb, + final String containingClassName, + final String propertyName, + final Token token, + final String indent) { final int arrayLength = token.arrayLength(); - if (arrayLength == 1) { - return generateSingleValueProperty(containingClassName, propertyName, token, indent); + generateSingleValueProperty(sb, containingClassName, propertyName, token, indent); } else if (arrayLength > 1) { - return generateArrayProperty(containingClassName, propertyName, token, indent); + generateArrayProperty(sb, containingClassName, propertyName, token, indent); } - - return ""; } - private CharSequence generatePrimitiveFieldMetaData( - final String propertyName, final Token token, final String indent) + private void generatePrimitiveFieldMetaData( + final StringBuilder sb, final String propertyName, final Token token, final String indent) { - final StringBuilder sb = new StringBuilder(); - final Encoding encoding = token.encoding(); final PrimitiveType primitiveType = encoding.primitiveType(); final String cppTypeName = cppTypeName(primitiveType); final CharSequence nullValueString = generateNullValueLiteral(primitiveType, encoding); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR %1$s %2$sNullValue() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %3$s;\n" + indent + " }\n", cppTypeName, propertyName, - nullValueString)); + nullValueString); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR %1$s %2$sMinValue() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %3$s;\n" + indent + " }\n", cppTypeName, propertyName, - generateLiteral(primitiveType, token.encoding().applicableMinValue().toString()))); + generateLiteral(primitiveType, token.encoding().applicableMinValue().toString())); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR %1$s %2$sMaxValue() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %3$s;\n" + indent + " }\n", cppTypeName, propertyName, - generateLiteral(primitiveType, token.encoding().applicableMaxValue().toString()))); + generateLiteral(primitiveType, token.encoding().applicableMaxValue().toString())); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR std::size_t %1$sEncodingLength() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n", propertyName, - token.encoding().primitiveType().size() * token.arrayLength())); - - return sb; + token.encoding().primitiveType().size() * token.arrayLength()); } private CharSequence generateLoadValue( @@ -1253,9 +1251,9 @@ private CharSequence generateLoadValue( if (primitiveType == PrimitiveType.FLOAT || primitiveType == PrimitiveType.DOUBLE) { final String stackUnion = - (primitiveType == PrimitiveType.FLOAT) ? "union sbe_float_as_uint_u" : "union sbe_double_as_uint_u"; + primitiveType == PrimitiveType.FLOAT ? "union sbe_float_as_uint_u" : "union sbe_double_as_uint_u"; - sb.append(String.format( + new Formatter(sb).format( indent + " %1$s val;\n" + indent + " std::memcpy(&val, m_buffer + m_offset + %2$s, sizeof(%3$s));\n" + indent + " val.uint_value = %4$s(val.uint_value);\n" + @@ -1263,17 +1261,17 @@ private CharSequence generateLoadValue( stackUnion, offsetStr, cppTypeName, - byteOrderStr)); + byteOrderStr); } else { - sb.append(String.format( + new Formatter(sb).format( indent + " %1$s val;\n" + indent + " std::memcpy(&val, m_buffer + m_offset + %2$s, sizeof(%1$s));\n" + indent + " return %3$s(val);\n", cppTypeName, offsetStr, - byteOrderStr)); + byteOrderStr); } return sb; @@ -1295,7 +1293,7 @@ private CharSequence generateStoreValue( final String stackUnion = primitiveType == PrimitiveType.FLOAT ? "union sbe_float_as_uint_u" : "union sbe_double_as_uint_u"; - sb.append(String.format( + new Formatter(sb).format( indent + " %1$s val%2$s;\n" + indent + " val%2$s.fp_value = value%2$s;\n" + indent + " val%2$s.uint_value = %3$s(val%2$s.uint_value);\n" + @@ -1304,31 +1302,34 @@ private CharSequence generateStoreValue( valueSuffix, byteOrderStr, offsetStr, - cppTypeName)); + cppTypeName); } else { - sb.append(String.format( + new Formatter(sb).format( indent + " %1$s val%2$s = %3$s(value%2$s);\n" + indent + " std::memcpy(m_buffer + m_offset + %4$s, &val%2$s, sizeof(%1$s));\n", cppTypeName, valueSuffix, byteOrderStr, - offsetStr)); + offsetStr); } return sb; } - private CharSequence generateSingleValueProperty( - final String containingClassName, final String propertyName, final Token token, final String indent) + private void generateSingleValueProperty( + final StringBuilder sb, + final String containingClassName, + final String propertyName, + final Token token, + final String indent) { final PrimitiveType primitiveType = token.encoding().primitiveType(); final String cppTypeName = cppTypeName(primitiveType); final int offset = token.offset(); - final StringBuilder sb = new StringBuilder(); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD %1$s %2$s() const SBE_NOEXCEPT\n" + indent + " {\n" + "%3$s" + @@ -1337,12 +1338,12 @@ private CharSequence generateSingleValueProperty( cppTypeName, propertyName, generateFieldNotPresentCondition(token.version(), token.encoding(), indent), - generateLoadValue(primitiveType, Integer.toString(offset), token.encoding().byteOrder(), indent))); + generateLoadValue(primitiveType, Integer.toString(offset), token.encoding().byteOrder(), indent)); final CharSequence storeValue = generateStoreValue( primitiveType, "", Integer.toString(offset), token.encoding().byteOrder(), indent); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " %1$s &%2$s(const %3$s value) SBE_NOEXCEPT\n" + indent + " {\n" + "%4$s" + @@ -1351,30 +1352,30 @@ private CharSequence generateSingleValueProperty( formatClassName(containingClassName), propertyName, cppTypeName, - storeValue)); - - return sb; + storeValue); } - private CharSequence generateArrayProperty( - final String containingClassName, final String propertyName, final Token token, final String indent) + private void generateArrayProperty( + final StringBuilder sb, + final String containingClassName, + final String propertyName, + final Token token, + final String indent) { final PrimitiveType primitiveType = token.encoding().primitiveType(); final String cppTypeName = cppTypeName(primitiveType); final int offset = token.offset(); - final StringBuilder sb = new StringBuilder(); - final int arrayLength = token.arrayLength(); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t %1$sLength() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n", propertyName, - arrayLength)); + arrayLength); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD const char *%1$s() const SBE_NOEXCEPT\n" + indent + " {\n" + "%2$s" + @@ -1382,9 +1383,9 @@ private CharSequence generateArrayProperty( indent + " }\n", propertyName, generateTypeFieldNotPresentCondition(token.version(), indent), - offset)); + offset); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD char *%1$s() SBE_NOEXCEPT\n" + indent + " {\n" + "%2$s" + @@ -1392,7 +1393,7 @@ private CharSequence generateArrayProperty( indent + " }\n", propertyName, generateTypeFieldNotPresentCondition(token.version(), indent), - offset)); + offset); final CharSequence loadValue = generateLoadValue( primitiveType, @@ -1400,7 +1401,7 @@ private CharSequence generateArrayProperty( token.encoding().byteOrder(), indent); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD %1$s %2$s(const std::uint64_t index) const\n" + indent + " {\n" + indent + " if (index >= %3$d)\n" + @@ -1414,7 +1415,7 @@ private CharSequence generateArrayProperty( propertyName, arrayLength, generateFieldNotPresentCondition(token.version(), token.encoding(), indent), - loadValue)); + loadValue); final CharSequence storeValue = generateStoreValue( primitiveType, @@ -1423,7 +1424,7 @@ private CharSequence generateArrayProperty( token.encoding().byteOrder(), indent); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " %1$s &%2$s(const std::uint64_t index, const %3$s value)\n" + indent + " {\n" + indent + " if (index >= %4$d)\n" + @@ -1438,9 +1439,9 @@ private CharSequence generateArrayProperty( propertyName, cppTypeName, arrayLength, - storeValue)); + storeValue); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " std::uint64_t get%1$s(char *const dst, const std::uint64_t length) const\n" + indent + " {\n" + indent + " if (length > %2$d)\n" + @@ -1457,9 +1458,9 @@ private CharSequence generateArrayProperty( arrayLength, generateArrayFieldNotPresentCondition(token.version(), indent), offset, - cppTypeName)); + cppTypeName); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " %1$s &put%2$s(const char *const src) SBE_NOEXCEPT\n" + indent + " {\n" + indent + " std::memcpy(m_buffer + m_offset + %3$d, src, sizeof(%4$s) * %5$d);\n" + @@ -1469,7 +1470,7 @@ private CharSequence generateArrayProperty( toUpperFirstChar(propertyName), offset, cppTypeName, - arrayLength)); + arrayLength); if (arrayLength > 1 && arrayLength <= 4) { @@ -1508,7 +1509,7 @@ private CharSequence generateArrayProperty( if (token.encoding().primitiveType() == PrimitiveType.CHAR) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " std::string get%1$sAsString() const\n" + indent + " {\n" + indent + " const char *buffer = m_buffer + m_offset + %2$d;\n" + @@ -1521,9 +1522,9 @@ private CharSequence generateArrayProperty( indent + " }\n", toUpperFirstChar(propertyName), offset, - arrayLength)); + arrayLength); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " #if __cplusplus >= 201703L\n" + indent + " std::string_view get%1$sAsStringView() const SBE_NOEXCEPT\n" + indent + " {\n" + @@ -1538,9 +1539,9 @@ private CharSequence generateArrayProperty( indent + " #endif\n", toUpperFirstChar(propertyName), offset, - arrayLength)); + arrayLength); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " #if __cplusplus >= 201703L\n" + indent + " %1$s &put%2$s(const std::string_view str)\n" + indent + " {\n" + @@ -1579,20 +1580,18 @@ private CharSequence generateArrayProperty( containingClassName, toUpperFirstChar(propertyName), offset, - arrayLength)); + arrayLength); } - - return sb; } - private CharSequence generateConstPropertyMethods( - final String propertyName, final Token token, final String indent) + private void generateConstPropertyMethods( + final StringBuilder sb, final String propertyName, final Token token, final String indent) { final String cppTypeName = cppTypeName(token.encoding().primitiveType()); if (token.encoding().primitiveType() != PrimitiveType.CHAR) { - return String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD static SBE_CONSTEXPR %1$s %2$s() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %3$s;\n" + @@ -1600,9 +1599,9 @@ private CharSequence generateConstPropertyMethods( cppTypeName, propertyName, generateLiteral(token.encoding().primitiveType(), token.encoding().constValue().toString())); - } - final StringBuilder sb = new StringBuilder(); + return; + } final byte[] constantValue = token.encoding().constValue().byteArrayValue(token.encoding().primitiveType()); final StringBuilder values = new StringBuilder(); @@ -1616,15 +1615,15 @@ private CharSequence generateConstPropertyMethods( values.setLength(values.length() - 2); } - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t %1$sLength() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n", propertyName, - constantValue.length)); + constantValue.length); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD const char *%1$s() const\n" + indent + " {\n" + indent + " static const std::uint8_t %1$sValues[] = { %2$s };\n\n" + @@ -1632,7 +1631,7 @@ private CharSequence generateConstPropertyMethods( indent + " return (const char *)%1$sValues;\n" + indent + " }\n", propertyName, - values)); + values); sb.append(String.format("\n" + indent + " SBE_NODISCARD %1$s %2$s(const std::uint64_t index) const\n" + @@ -1645,7 +1644,7 @@ private CharSequence generateConstPropertyMethods( propertyName, values)); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " std::uint64_t get%1$s(char *dst, const std::uint64_t length) const\n" + indent + " {\n" + indent + " static std::uint8_t %2$sValues[] = { %3$s };\n" + @@ -1657,9 +1656,7 @@ private CharSequence generateConstPropertyMethods( indent + " }\n", toUpperFirstChar(propertyName), propertyName, - values)); - - return sb; + values); } private CharSequence generateFixedFlyweightCode(final String className, final int size) @@ -1997,20 +1994,19 @@ private void generateFields( switch (encodingToken.signal()) { case ENCODING: - sb.append(generatePrimitiveProperty(containingClassName, propertyName, encodingToken, indent)); + generatePrimitiveProperty(sb, containingClassName, propertyName, encodingToken, indent); break; case BEGIN_ENUM: - sb.append(generateEnumProperty( - containingClassName, signalToken, propertyName, encodingToken, indent)); + generateEnumProperty(sb, containingClassName, signalToken, propertyName, encodingToken, indent); break; case BEGIN_SET: - sb.append(generateBitsetProperty(propertyName, encodingToken, indent)); + generateBitsetProperty(sb, propertyName, encodingToken, indent); break; case BEGIN_COMPOSITE: - sb.append(generateCompositeProperty(propertyName, encodingToken, indent)); + generateCompositeProperty(sb, propertyName, encodingToken, indent); break; } } @@ -2027,16 +2023,16 @@ private void generateFieldCommonMethods( { if (!inComposite) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR std::uint16_t %1$sId() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n", propertyName, - fieldToken.id())); + fieldToken.id()); } - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + @@ -2054,15 +2050,15 @@ private void generateFieldCommonMethods( indent + "#endif\n" + indent + " }\n", propertyName, - fieldToken.version())); + fieldToken.version()); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::size_t %1$sEncodingOffset() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n", propertyName, - encodingToken.offset())); + encodingToken.offset()); } private static void generateFieldMetaAttributeMethod( @@ -2073,7 +2069,7 @@ private static void generateFieldMetaAttributeMethod( final String timeUnit = encoding.timeUnit() == null ? "" : encoding.timeUnit(); final String semanticType = encoding.semanticType() == null ? "" : encoding.semanticType(); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD static const char * %sMetaAttribute(const MetaAttribute metaAttribute)" + " SBE_NOEXCEPT\n" + indent + " {\n" + @@ -2091,7 +2087,7 @@ private static void generateFieldMetaAttributeMethod( epoch, timeUnit, semanticType, - encoding.presence().toString().toLowerCase())); + encoding.presence().toString().toLowerCase()); } private static CharSequence generateEnumFieldNotPresentCondition( @@ -2113,7 +2109,8 @@ private static CharSequence generateEnumFieldNotPresentCondition( enumName); } - private CharSequence generateEnumProperty( + private void generateEnumProperty( + final StringBuilder sb, final String containingClassName, final Token fieldToken, final String propertyName, @@ -2124,30 +2121,28 @@ private CharSequence generateEnumProperty( final String typeName = cppTypeName(token.encoding().primitiveType()); final int offset = token.offset(); - final StringBuilder sb = new StringBuilder(); - - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::size_t %1$sEncodingLength() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n", propertyName, - fieldToken.encodedLength())); + fieldToken.encodedLength()); if (fieldToken.isConstantEncoding()) { final String constValue = fieldToken.encoding().constValue().toString(); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD static SBE_CONSTEXPR %1$s::Value %2$sConstValue() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %1$s::Value::%3$s;\n" + indent + " }\n", enumName, propertyName, - constValue.substring(constValue.indexOf(".") + 1))); + constValue.substring(constValue.indexOf(".") + 1)); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD %1$s::Value %2$s() const SBE_NOEXCEPT\n" + indent + " {\n" + "%3$s" + @@ -2156,11 +2151,11 @@ private CharSequence generateEnumProperty( enumName, propertyName, generateEnumFieldNotPresentCondition(token.version(), enumName, indent), - constValue.substring(constValue.indexOf(".") + 1))); + constValue.substring(constValue.indexOf(".") + 1)); } else { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD %1$s::Value %2$s() const SBE_NOEXCEPT\n" + indent + " {\n" + "%3$s" + @@ -2173,9 +2168,9 @@ private CharSequence generateEnumProperty( generateEnumFieldNotPresentCondition(token.version(), enumName, indent), formatByteOrderEncoding(token.encoding().byteOrder(), token.encoding().primitiveType()), typeName, - offset)); + offset); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " %1$s &%2$s(const %3$s::Value value) SBE_NOEXCEPT\n" + indent + " {\n" + indent + " %4$s val = %6$s(value);\n" + @@ -2187,28 +2182,25 @@ private CharSequence generateEnumProperty( enumName, typeName, offset, - formatByteOrderEncoding(token.encoding().byteOrder(), token.encoding().primitiveType()))); + formatByteOrderEncoding(token.encoding().byteOrder(), token.encoding().primitiveType())); } - - return sb; } - private static Object generateBitsetProperty(final String propertyName, final Token token, final String indent) + private static void generateBitsetProperty( + final StringBuilder sb, final String propertyName, final Token token, final String indent) { - final StringBuilder sb = new StringBuilder(); - final String bitsetName = formatClassName(token.applicableTypeName()); final int offset = token.offset(); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + "private:\n" + indent + " %1$s m_%2$s;\n\n" + indent + "public:\n", bitsetName, - propertyName)); + propertyName); - sb.append(String.format( + new Formatter(sb).format( indent + " SBE_NODISCARD %1$s &%2$s()\n" + indent + " {\n" + indent + " m_%2$s.wrap(m_buffer, m_offset + %3$d, m_actingVersion, m_bufferLength);\n" + @@ -2216,35 +2208,32 @@ private static Object generateBitsetProperty(final String propertyName, final To indent + " }\n", bitsetName, propertyName, - offset)); + offset); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR std::size_t %1$sEncodingLength() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return %2$d;\n" + indent + " }\n", propertyName, - token.encoding().primitiveType().size())); - - return sb; + token.encoding().primitiveType().size()); } - private static Object generateCompositeProperty(final String propertyName, final Token token, final String indent) + private static void generateCompositeProperty( + final StringBuilder sb, final String propertyName, final Token token, final String indent) { final String compositeName = formatClassName(token.applicableTypeName()); final int offset = token.offset(); - final StringBuilder sb = new StringBuilder(); - - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + "private:\n" + indent + " %1$s m_%2$s;\n\n" + "public:\n", compositeName, - propertyName)); + propertyName); - sb.append(String.format( + new Formatter(sb).format( indent + " SBE_NODISCARD %1$s &%2$s()\n" + indent + " {\n" + indent + " m_%2$s.wrap(m_buffer, m_offset + %3$d, m_actingVersion, m_bufferLength);\n" + @@ -2252,9 +2241,7 @@ private static Object generateCompositeProperty(final String propertyName, final indent + " }\n", compositeName, propertyName, - offset)); - - return sb; + offset); } private CharSequence generateNullValueLiteral(final PrimitiveType primitiveType, final Encoding encoding) @@ -2344,7 +2331,7 @@ private void generateDisplay( final List varData, final String indent) { - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + "template\n" + indent + "friend std::basic_ostream& operator<<(\n" + indent + " std::basic_ostream& builder, %1$s _writer)\n" + @@ -2361,7 +2348,7 @@ private void generateDisplay( indent + " return builder;\n" + indent + "}\n", formatClassName(name), - appendDisplay(fields, groups, varData, indent + INDENT))); + appendDisplay(fields, groups, varData, indent + INDENT)); } private CharSequence generateGroupDisplay( @@ -2446,7 +2433,7 @@ private CharSequence appendDisplay( } atLeastOne[0] = true; - sb.append(String.format( + new Formatter(sb).format( indent + "{\n" + indent + " bool atLeastOne = false;\n" + indent + " builder << R\"(\"%3$s\": [)\";\n" + @@ -2463,7 +2450,7 @@ private CharSequence appendDisplay( indent + "}\n\n", formatClassName(groupToken.name()), formatPropertyName(groupToken.name()), - groupToken.name())); + groupToken.name()); i = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); } @@ -2621,13 +2608,13 @@ private CharSequence generateChoicesDisplay(final String name, final List collect(Signal.CHOICE, tokens, 0, choiceTokens); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + indent + "template\n" + indent + "friend std::basic_ostream& operator<<(" + indent + " std::basic_ostream& builder, %1$s writer)\n" + indent + "{\n" + indent + " builder << '[';\n", - name)); + name); if (choiceTokens.size() > 1) { @@ -2676,21 +2663,21 @@ private CharSequence generateEnumDisplay(final List tokens, final Token e final String enumName = formatClassName(encodingToken.applicableTypeName()); final StringBuilder sb = new StringBuilder(); - sb.append(String.format("\n" + + new Formatter(sb).format("\n" + " static const char* c_str(const %1$s::Value value)\n" + " {\n" + " switch (value)\n" + " {\n", - enumName)); + enumName); for (final Token token : tokens) { - sb.append(String.format( + new Formatter(sb).format( " case %1$s: return \"%1$s\";\n", - token.name())); + token.name()); } - sb.append(String.format( + new Formatter(sb).format( " case NULL_VALUE: return \"NULL_VALUE\";\n" + " }\n\n" + " throw std::runtime_error(\"unknown value for enum %1$s [E103]:\");\n" + @@ -2702,7 +2689,7 @@ private CharSequence generateEnumDisplay(final List tokens, final Token e " {\n" + " return os << %1$s::c_str(m);\n" + " }\n", - enumName)); + enumName); return sb; } From 0463eed600322ca05d4510d1d7cdfe2276d82414 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 16 Oct 2019 10:33:30 +0100 Subject: [PATCH 0210/1594] [C++] Complete and tidy up string handling for fixed length array fields plus reduce copying of string while generating codecs. --- .../sbe/generation/cpp/CppGenerator.java | 117 ++++++++++-------- 1 file changed, 65 insertions(+), 52 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 307b135082..c69c779464 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -521,39 +521,7 @@ private void generateVarData( lengthByteOrderStr, lengthCppType); - new Formatter(sb).format("\n" + - indent + " std::string get%1$sAsJsonEscapedString()\n" + - indent + " {\n" + - "%2$s" + - indent + " std::ostringstream oss;\n" + - indent + " std::string s = get%1$sAsString();\n\n" + - indent + " for (auto c = s.cbegin(); c != s.cend(); c++)\n" + - indent + " {\n" + - indent + " switch (*c)\n" + - indent + " {\n" + - indent + " case '\"': oss << \"\\\\\\\"\"; break;\n" + - indent + " case '\\\\': oss << \"\\\\\\\\\"; break;\n" + - indent + " case '\\b': oss << \"\\\\b\"; break;\n" + - indent + " case '\\f': oss << \"\\\\f\"; break;\n" + - indent + " case '\\n': oss << \"\\\\n\"; break;\n" + - indent + " case '\\r': oss << \"\\\\r\"; break;\n" + - indent + " case '\\t': oss << \"\\\\t\"; break;\n\n" + - indent + " default:\n" + - indent + " if ('\\x00' <= *c && *c <= '\\x1f')\n" + - indent + " {\n" + - indent + " oss << \"\\\\u\"" + " << std::hex << std::setw(4)\n" + - indent + " << std::setfill('0') << (int)(*c);\n" + - indent + " }\n" + - indent + " else\n" + - indent + " {\n" + - indent + " oss << *c;\n" + - indent + " }\n" + - indent + " }\n" + - indent + " }\n\n" + - indent + " return oss.str();\n" + - indent + " }\n", - propertyName, - generateStringNotPresentCondition(token.version(), indent)); + generateJsonEscapedStringGetter(sb, token, indent, propertyName); new Formatter(sb).format("\n" + indent + " #if __cplusplus >= 201703L\n" + @@ -1524,6 +1492,8 @@ private void generateArrayProperty( offset, arrayLength); + generateJsonEscapedStringGetter(sb, token, indent, propertyName); + new Formatter(sb).format("\n" + indent + " #if __cplusplus >= 201703L\n" + indent + " std::string_view get%1$sAsStringView() const SBE_NOEXCEPT\n" + @@ -1584,6 +1554,44 @@ private void generateArrayProperty( } } + private void generateJsonEscapedStringGetter( + final StringBuilder sb, final Token token, final String indent, final String propertyName) + { + new Formatter(sb).format("\n" + + indent + " std::string get%1$sAsJsonEscapedString()\n" + + indent + " {\n" + + "%2$s" + + indent + " std::ostringstream oss;\n" + + indent + " std::string s = get%1$sAsString();\n\n" + + indent + " for (auto c = s.cbegin(); c != s.cend(); c++)\n" + + indent + " {\n" + + indent + " switch (*c)\n" + + indent + " {\n" + + indent + " case '\"': oss << \"\\\\\\\"\"; break;\n" + + indent + " case '\\\\': oss << \"\\\\\\\\\"; break;\n" + + indent + " case '\\b': oss << \"\\\\b\"; break;\n" + + indent + " case '\\f': oss << \"\\\\f\"; break;\n" + + indent + " case '\\n': oss << \"\\\\n\"; break;\n" + + indent + " case '\\r': oss << \"\\\\r\"; break;\n" + + indent + " case '\\t': oss << \"\\\\t\"; break;\n\n" + + indent + " default:\n" + + indent + " if ('\\x00' <= *c && *c <= '\\x1f')\n" + + indent + " {\n" + + indent + " oss << \"\\\\u\"" + " << std::hex << std::setw(4)\n" + + indent + " << std::setfill('0') << (int)(*c);\n" + + indent + " }\n" + + indent + " else\n" + + indent + " {\n" + + indent + " oss << *c;\n" + + indent + " }\n" + + indent + " }\n" + + indent + " }\n\n" + + indent + " return oss.str();\n" + + indent + " }\n", + toUpperFirstChar(propertyName), + generateStringNotPresentCondition(token.version(), indent)); + } + private void generateConstPropertyMethods( final StringBuilder sb, final String propertyName, final Token token, final String indent) { @@ -1657,6 +1665,18 @@ private void generateConstPropertyMethods( toUpperFirstChar(propertyName), propertyName, values); + + new Formatter(sb).format("\n" + + indent + " std::string get%1$sAsString() const\n" + + indent + " {\n" + + indent + " static const std::uint8_t %1$sValues[] = { %2$s };\n\n" + + indent + " return std::string((const char *)%1$sValues, %3$s);\n" + + indent + " }\n", + toUpperFirstChar(propertyName), + values, + constantValue.length); + + generateJsonEscapedStringGetter(sb, token, indent, propertyName); } private CharSequence generateFixedFlyweightCode(final String className, final int size) @@ -2392,7 +2412,7 @@ private CharSequence appendDisplay( final List fields, final List groups, final List varData, final String indent) { final StringBuilder sb = new StringBuilder(); - final boolean[] atLeastOne = {false}; + final boolean[] atLeastOne = { false }; for (int i = 0, size = fields.size(); i < size;) { @@ -2402,8 +2422,7 @@ private CharSequence appendDisplay( { final Token encodingToken = fields.get(i + 1); - sb.append( - writeTokenDisplay(fieldToken.name(), encodingToken, atLeastOne, indent) + "\n"); + writeTokenDisplay(sb, fieldToken.name(), encodingToken, atLeastOne, indent); i += fieldToken.componentTokenCount(); } @@ -2411,8 +2430,7 @@ private CharSequence appendDisplay( { final Token encodingToken = fields.get(i); - sb.append( - writeTokenDisplay(fieldToken.name(), encodingToken, atLeastOne, indent) + "\n"); + writeTokenDisplay(sb, fieldToken.name(), encodingToken, atLeastOne, indent); i += fieldToken.componentTokenCount(); } @@ -2501,7 +2519,8 @@ private CharSequence appendDisplay( return sb; } - private CharSequence writeTokenDisplay( + private void writeTokenDisplay( + final StringBuilder sb, final String fieldTokenName, final Token typeToken, final boolean[] atLeastOne, @@ -2509,11 +2528,9 @@ private CharSequence writeTokenDisplay( { if (typeToken.encodedLength() <= 0 || typeToken.isConstantEncoding()) { - return ""; + return; } - final StringBuilder sb = new StringBuilder(); - if (atLeastOne[0]) { sb.append( @@ -2534,15 +2551,12 @@ private CharSequence writeTokenDisplay( { if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { + final String getAsStringFunction = + "writer.get" + toUpperFirstChar(fieldTokenName) + "AsJsonEscapedString().c_str()"; + sb.append( - indent + "builder << '\"';\n" + - indent + "for (size_t i = 0, length = " + fieldName + "Length();\n" + - indent + " i < length && " + fieldName + "(i) > 0;\n" + - indent + " i++)\n" + - indent + "{\n" + - indent + " builder << (char)" + fieldName + "(i);\n" + - indent + "}\n" + - indent + "builder << '\"';\n"); + indent + "builder << '\"' <<\n" + + indent + INDENT + getAsStringFunction + " << '\"';\n"); } else { @@ -2564,7 +2578,6 @@ private CharSequence writeTokenDisplay( } else { - // have to duplicate because of checkstyle :/ if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { sb.append( @@ -2597,7 +2610,7 @@ private CharSequence writeTokenDisplay( break; } - return sb; + sb.append('\n'); } private CharSequence generateChoicesDisplay(final String name, final List tokens) From df24e0812848fa5a041a92c403c6baa61350d4e5 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 18 Oct 2019 15:09:48 +0100 Subject: [PATCH 0211/1594] [Java] Increase version. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 955dfe681e..79f267ba07 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.13.4-SNAPSHOT \ No newline at end of file +1.14.0-SNAPSHOT \ No newline at end of file From 4837db6095f6a3007dfcedec1f29486462996c36 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 18 Oct 2019 15:11:59 +0100 Subject: [PATCH 0212/1594] [Java] Upgrade to Gradle 5.6.3. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 47604b29ac..076749f6f8 100644 --- a/build.gradle +++ b/build.gradle @@ -767,6 +767,6 @@ task uploadToMavenCentral { } wrapper { - gradleVersion = '5.6.2' + gradleVersion = '5.6.3' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ca9d62814a..3a54a3332e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 94bdcf9a61814f2a5108d59cce2b47bb896e214c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 23 Oct 2019 09:28:20 +0100 Subject: [PATCH 0213/1594] [Java] Upgrade to javadoc-links 4.1.3. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 076749f6f8..f439139af0 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ buildscript { plugins { id 'java' - id 'io.freefair.javadoc-links' version '4.1.2' apply false + id 'io.freefair.javadoc-links' version '4.1.3' apply false id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } From 50e902a820177955c96c0588ba22f520ba486005 Mon Sep 17 00:00:00 2001 From: Arik Sher Date: Thu, 24 Oct 2019 15:08:13 +0300 Subject: [PATCH 0214/1594] varDataDisplay - use method getVarFieldName(Appendable) - no memory allocation. unlike calling method 'varFieldName' where it has new Byte and new String. --- .../sbe/generation/java/JavaGenerator.java | 3 ++- .../co/real_logic/sbe/generation/java/JavaUtil.java | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 08c26066e0..1c13429262 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3269,7 +3269,8 @@ private void appendDecoderDisplay( } else { - append(sb, indent, "builder.append('\\'' + " + varDataName + "() + '\\'');"); + //append(sb, indent, "builder.append('\\'' + " + varDataName + "() + '\\'');"); + append(sb, indent, formatGetterName(varDataToken.name()) + "(builder);"); } lengthBeforeLastGeneratedSeparator = sb.length(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index cb8877de1f..fc71991b66 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -158,6 +158,18 @@ public static String formatPropertyName(final String value) return formattedValue; } + /** + * Format a Getter name for generated code. + *

    + * + * @param value to be formatted. + * @return the string formatted as a getter name. + */ + public static String formatGetterName(final String value) + { + return "get" + Generators.toUpperFirstChar(value); + } + /** * Format a class name for the generated code. * From ac2840e981115f07e4a0e878c9a144b6a1371fbf Mon Sep 17 00:00:00 2001 From: Arik Sher Date: Thu, 24 Oct 2019 16:39:19 +0300 Subject: [PATCH 0215/1594] support method getVarFieldName for UTF similar to Ascii. --- .../sbe/generation/java/JavaGenerator.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 1c13429262..ab142f18ac 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -904,6 +904,28 @@ private void generateDataDecodeMethods( generateGet(lengthType, "limit", byteOrderStr), byteOrderStr); } + if (characterEncoding.contains("UTF8")) + { + new Formatter(sb).format("\n" + + indent + " public int get%1$s(final Appendable appendable)\n" + + indent + " {\n" + + "%2$s" + + indent + " final int headerLength = %3$d;\n" + + indent + " final int limit = parentMessage.limit();\n" + + indent + " final int dataLength = (int)%4$s;\n" + + indent + " final int dataOffset = limit + headerLength;\n\n" + + indent + " parentMessage.limit(dataOffset + dataLength);\n" + + indent + " appendable.append(buffer.getStringWithoutLengthUtf8(dataOffset, dataLength));\n\n" + + //TODO: wait for signature below, similar to getStringWithoutLengthAscii(offset,length,appendable) + indent + " //buffer.getStringWithoutLengthUtf8(dataOffset, dataLength, appendable);\n\n" + + indent + " return dataLength;\n" + + indent + " }\n", + Generators.toUpperFirstChar(propertyName), + generateStringNotPresentConditionForAppendable(token.version(), indent), + sizeOfLengthField, + generateGet(lengthType, "limit", byteOrderStr), + byteOrderStr); + } } } From de9384e2cc12faa8cecb2e325508193a8b1c786c Mon Sep 17 00:00:00 2001 From: Arik Sher Date: Thu, 24 Oct 2019 16:43:36 +0300 Subject: [PATCH 0216/1594] UTF only --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index ab142f18ac..6d7289bbe9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -904,7 +904,7 @@ private void generateDataDecodeMethods( generateGet(lengthType, "limit", byteOrderStr), byteOrderStr); } - if (characterEncoding.contains("UTF8")) + if (characterEncoding.contains("UTF")) { new Formatter(sb).format("\n" + indent + " public int get%1$s(final Appendable appendable)\n" + From 391527ac04df032671167b12d923b29dad30c5c0 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 24 Oct 2019 14:56:55 +0100 Subject: [PATCH 0217/1594] [Java] Reduce allocation when displaying var data in Java codecs. --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 08c26066e0..ce62ec4d72 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3262,14 +3262,14 @@ private void appendDecoderDisplay( append(sb, indent, "builder.append(\"" + varDataName + Separators.KEY_VALUE + "\");"); if (null == characterEncoding) { - append(sb, indent, "builder.append(" + varDataName + "Length() + \" bytes of raw data\");"); + append(sb, indent, "builder.append(" + varDataName + "Length()).append(\" bytes of raw data\");"); append(sb, indent, "parentMessage.limit(parentMessage.limit() + " + varDataName + "HeaderLength() + " + varDataName + "Length());"); } else { - append(sb, indent, "builder.append('\\'' + " + varDataName + "() + '\\'');"); + append(sb, indent, "builder.append('\\'').append(" + varDataName + "()).append('\\'');"); } lengthBeforeLastGeneratedSeparator = sb.length(); From 45e61a33dcf0c31d3db4540b7e027a67971c7a7f Mon Sep 17 00:00:00 2001 From: Arik Sher Date: Thu, 24 Oct 2019 17:28:19 +0300 Subject: [PATCH 0218/1594] avoid allocation for ASCII only --- .../real_logic/sbe/generation/java/JavaGenerator.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index ac3e5bf34f..0e2bb5f6f3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3291,8 +3291,14 @@ private void appendDecoderDisplay( } else { - //append(sb, indent, "builder.append('\\'' + " + varDataName + "() + '\\'');"); - append(sb, indent, formatGetterName(varDataToken.name()) + "(builder);"); + if (characterEncoding.contains("ASCII")) + { + append(sb, indent, "builder.append('\\'');"); + append(sb, indent, formatGetterName(varDataToken.name()) + "(builder);"); + append(sb, indent, "builder.append('\\'');"); + } else { + append(sb, indent, "builder.append('\\'').append(" + varDataName + "()).append('\\'');"); + } } lengthBeforeLastGeneratedSeparator = sb.length(); From 3fd1452fe47fb0ea5f1c152e5b39aed9fb7ae043 Mon Sep 17 00:00:00 2001 From: Arik Sher Date: Thu, 24 Oct 2019 17:39:32 +0300 Subject: [PATCH 0219/1594] remove UTF code. --- .../sbe/generation/java/JavaGenerator.java | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 0e2bb5f6f3..4b484c238a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -904,28 +904,6 @@ private void generateDataDecodeMethods( generateGet(lengthType, "limit", byteOrderStr), byteOrderStr); } - if (characterEncoding.contains("UTF")) - { - new Formatter(sb).format("\n" + - indent + " public int get%1$s(final Appendable appendable)\n" + - indent + " {\n" + - "%2$s" + - indent + " final int headerLength = %3$d;\n" + - indent + " final int limit = parentMessage.limit();\n" + - indent + " final int dataLength = (int)%4$s;\n" + - indent + " final int dataOffset = limit + headerLength;\n\n" + - indent + " parentMessage.limit(dataOffset + dataLength);\n" + - indent + " appendable.append(buffer.getStringWithoutLengthUtf8(dataOffset, dataLength));\n\n" + - //TODO: wait for signature below, similar to getStringWithoutLengthAscii(offset,length,appendable) - indent + " //buffer.getStringWithoutLengthUtf8(dataOffset, dataLength, appendable);\n\n" + - indent + " return dataLength;\n" + - indent + " }\n", - Generators.toUpperFirstChar(propertyName), - generateStringNotPresentConditionForAppendable(token.version(), indent), - sizeOfLengthField, - generateGet(lengthType, "limit", byteOrderStr), - byteOrderStr); - } } } From e6c1b32f25d5c973a2f2921fa499bc2b43a5239f Mon Sep 17 00:00:00 2001 From: Arik Sher Date: Thu, 24 Oct 2019 17:57:06 +0300 Subject: [PATCH 0220/1594] fix checkStyle --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 4b484c238a..98cc8b233d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3274,7 +3274,9 @@ private void appendDecoderDisplay( append(sb, indent, "builder.append('\\'');"); append(sb, indent, formatGetterName(varDataToken.name()) + "(builder);"); append(sb, indent, "builder.append('\\'');"); - } else { + } + else + { append(sb, indent, "builder.append('\\'').append(" + varDataName + "()).append('\\'');"); } } From cf7f30e6d5ce89cc4639b8c6d814b8bf50b60db0 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 24 Oct 2019 16:07:04 +0100 Subject: [PATCH 0221/1594] [Java] Tidy up. --- .../sbe/generation/java/JavaUtil.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index fc71991b66..e277875c2b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -160,25 +160,24 @@ public static String formatPropertyName(final String value) /** * Format a Getter name for generated code. - *

    * - * @param value to be formatted. - * @return the string formatted as a getter name. + * @param propertyName to be formatted. + * @return the property name formatted as a getter name. */ - public static String formatGetterName(final String value) + public static String formatGetterName(final String propertyName) { - return "get" + Generators.toUpperFirstChar(value); + return "get" + Generators.toUpperFirstChar(propertyName); } /** * Format a class name for the generated code. * - * @param value to be formatted. - * @return the string formatted as a class name. + * @param className to be formatted. + * @return the formatted class name. */ - public static String formatClassName(final String value) + public static String formatClassName(final String className) { - return Generators.toUpperFirstChar(value); + return Generators.toUpperFirstChar(className); } /** From 76a8c3a1870521013bd69a91490a4083cff8e1d3 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 25 Oct 2019 06:08:17 +0100 Subject: [PATCH 0222/1594] [Java] Check both upper and lower case versions of ascii for generating display. --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 98cc8b233d..54eea623ea 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3269,7 +3269,7 @@ private void appendDecoderDisplay( } else { - if (characterEncoding.contains("ASCII")) + if (characterEncoding.contains("ASCII") || characterEncoding.contains("ascii")) { append(sb, indent, "builder.append('\\'');"); append(sb, indent, formatGetterName(varDataToken.name()) + "(builder);"); From 4634849a0cec5af4e1d376486676febd11d71df8 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 25 Oct 2019 10:53:17 -0700 Subject: [PATCH 0223/1594] [Java]: update agrona dep. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f439139af0..314e1dabca 100644 --- a/build.gradle +++ b/build.gradle @@ -128,7 +128,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.25' - compile 'org.agrona:agrona:1.0.8' + compile 'org.agrona:agrona:1.0.9' testCompile 'org.hamcrest:hamcrest:2.1' testCompile 'org.mockito:mockito-core:3.1.0' From a8130a6012b34c8afd759df69d1d4472a4e8a25b Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 26 Oct 2019 15:17:33 -0700 Subject: [PATCH 0224/1594] 1.14.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 79f267ba07..cd99d386a8 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.14.0-SNAPSHOT \ No newline at end of file +1.14.0 \ No newline at end of file From a1aafb7b5a947d242a12baec2479275610c07ce1 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 26 Oct 2019 15:19:07 -0700 Subject: [PATCH 0225/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index cd99d386a8..1baa6e874f 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.14.0 \ No newline at end of file +1.14.1-SNAPSHOT \ No newline at end of file From 0a51bb71bc9f1aa804de269e01d6ad5ad2e2b087 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sun, 27 Oct 2019 17:11:30 +0000 Subject: [PATCH 0226/1594] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3a2e3c30bc..04e8191f05 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.13.3 +    1.14.0 ``` @@ -65,7 +65,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.13.4-SNAPSHOT.jar my-sbe-input.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.14.1-SNAPSHOT.jar my-sbe-input.xml C++ Build using CMake From 3edff3aa56bc7b3fd8c00786c71ec0da9f8539e2 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 29 Oct 2019 09:34:10 +0000 Subject: [PATCH 0227/1594] [Java] Generate null value lookup as part of switch for enums. Issue #732. --- .../co/real_logic/sbe/generation/java/JavaGenerator.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 54eea623ea..c3a78d1ad9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1477,16 +1477,14 @@ private CharSequence generateEnumLookupMethod(final List tokens, final St sb.append(" case ").append(constStr).append(": return ").append(name).append(";\n"); } + final String nullValue = tokens.get(0).encoding().applicableNullValue().toString(); + sb.append(" case ").append(nullValue).append(": return NULL_VAL").append(";\n"); + final String handleUnknownLogic = shouldDecodeUnknownEnumValues ? INDENT + INDENT + "return SBE_UNKNOWN;\n" : INDENT + INDENT + "throw new IllegalArgumentException(\"Unknown value: \" + value);\n"; - final String nullValue = tokens.get(0).encoding().applicableNullValue().toString(); sb.append(" }\n\n") - .append(" if (").append(generateLiteral(primitiveType, nullValue)).append(" == value)\n") - .append(" {\n") - .append(" return NULL_VAL;\n") - .append(" }\n\n") .append(handleUnknownLogic) .append(" }\n"); From edb717b01104cab701b27fc933d78b07355fd5f6 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 29 Oct 2019 09:37:52 +0000 Subject: [PATCH 0228/1594] [Java] Regenerate IR codecs. --- .../sbe/ir/generated/ByteOrderCodec.java | 6 +---- .../sbe/ir/generated/FrameCodecDecoder.java | 6 ++--- .../sbe/ir/generated/PresenceCodec.java | 6 +---- .../sbe/ir/generated/PrimitiveTypeCodec.java | 6 +---- .../sbe/ir/generated/SignalCodec.java | 6 +---- .../sbe/ir/generated/TokenCodecDecoder.java | 22 +++++++++---------- 6 files changed, 18 insertions(+), 34 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java index 15b85e6551..8eabf31b28 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java @@ -33,11 +33,7 @@ public static ByteOrderCodec get(final short value) { case 0: return SBE_LITTLE_ENDIAN; case 1: return SBE_BIG_ENDIAN; - } - - if ((short)255 == value) - { - return NULL_VAL; + case 255: return NULL_VAL; } throw new IllegalArgumentException("Unknown value: " + value); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 545ab66f15..2167c289c8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -592,13 +592,13 @@ public StringBuilder appendTo(final StringBuilder builder) builder.append(schemaVersion()); builder.append('|'); builder.append("packageName="); - builder.append('\'' + packageName() + '\''); + builder.append('\'').append(packageName()).append('\''); builder.append('|'); builder.append("namespaceName="); - builder.append('\'' + namespaceName() + '\''); + builder.append('\'').append(namespaceName()).append('\''); builder.append('|'); builder.append("semanticVersion="); - builder.append('\'' + semanticVersion() + '\''); + builder.append('\'').append(semanticVersion()).append('\''); limit(originalLimit); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java index 66d8f68a13..634cfa0baf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java @@ -36,11 +36,7 @@ public static PresenceCodec get(final short value) case 0: return SBE_REQUIRED; case 1: return SBE_OPTIONAL; case 2: return SBE_CONSTANT; - } - - if ((short)255 == value) - { - return NULL_VAL; + case 255: return NULL_VAL; } throw new IllegalArgumentException("Unknown value: " + value); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java index 04f4affb2e..39279c4235 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java @@ -63,11 +63,7 @@ public static PrimitiveTypeCodec get(final short value) case 9: return UINT64; case 10: return FLOAT; case 11: return DOUBLE; - } - - if ((short)255 == value) - { - return NULL_VAL; + case 255: return NULL_VAL; } throw new IllegalArgumentException("Unknown value: " + value); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java index 62ecbafd3c..48441dd02c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java @@ -78,11 +78,7 @@ public static SignalCodec get(final short value) case 15: return BEGIN_VAR_DATA; case 16: return END_VAR_DATA; case 17: return ENCODING; - } - - if ((short)255 == value) - { - return NULL_VAL; + case 255: return NULL_VAL; } throw new IllegalArgumentException("Unknown value: " + value); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 7f88603f61..020942c8a7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -1731,37 +1731,37 @@ public StringBuilder appendTo(final StringBuilder builder) builder.append(deprecated()); builder.append('|'); builder.append("name="); - builder.append('\'' + name() + '\''); + builder.append('\'').append(name()).append('\''); builder.append('|'); builder.append("constValue="); - builder.append('\'' + constValue() + '\''); + builder.append('\'').append(constValue()).append('\''); builder.append('|'); builder.append("minValue="); - builder.append('\'' + minValue() + '\''); + builder.append('\'').append(minValue()).append('\''); builder.append('|'); builder.append("maxValue="); - builder.append('\'' + maxValue() + '\''); + builder.append('\'').append(maxValue()).append('\''); builder.append('|'); builder.append("nullValue="); - builder.append('\'' + nullValue() + '\''); + builder.append('\'').append(nullValue()).append('\''); builder.append('|'); builder.append("characterEncoding="); - builder.append('\'' + characterEncoding() + '\''); + builder.append('\'').append(characterEncoding()).append('\''); builder.append('|'); builder.append("epoch="); - builder.append('\'' + epoch() + '\''); + builder.append('\'').append(epoch()).append('\''); builder.append('|'); builder.append("timeUnit="); - builder.append('\'' + timeUnit() + '\''); + builder.append('\'').append(timeUnit()).append('\''); builder.append('|'); builder.append("semanticType="); - builder.append('\'' + semanticType() + '\''); + builder.append('\'').append(semanticType()).append('\''); builder.append('|'); builder.append("description="); - builder.append('\'' + description() + '\''); + builder.append('\'').append(description()).append('\''); builder.append('|'); builder.append("referencedName="); - builder.append('\'' + referencedName() + '\''); + builder.append('\'').append(referencedName()).append('\''); limit(originalLimit); From ade3ba219960ac519e148df7a967179fa74c1b68 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Thu, 31 Oct 2019 11:06:16 -0700 Subject: [PATCH 0229/1594] [Java]: update agrona dep. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 314e1dabca..832a2e67ea 100644 --- a/build.gradle +++ b/build.gradle @@ -128,7 +128,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.25' - compile 'org.agrona:agrona:1.0.9' + compile 'org.agrona:agrona:1.0.10' testCompile 'org.hamcrest:hamcrest:2.1' testCompile 'org.mockito:mockito-core:3.1.0' From d325cbcb4fde8e0dad3faea4135602758b71c636 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 1 Nov 2019 16:08:47 +0000 Subject: [PATCH 0230/1594] [Java] Upgrade to JMH 1.22. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 314e1dabca..bdc8adbd8b 100644 --- a/build.gradle +++ b/build.gradle @@ -449,8 +449,8 @@ project(':sbe-benchmarks') { apply plugin: 'com.github.johnrengelman.shadow' dependencies { - compile 'org.openjdk.jmh:jmh-core:1.21' - annotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.21' + compile 'org.openjdk.jmh:jmh-core:1.22' + annotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.22' compile project(':sbe-tool') compile files('build/classes/java/generated') } From 8f585e9f55516aab0e883e84f277491d974cd27e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 3 Nov 2019 08:34:50 +0000 Subject: [PATCH 0231/1594] [Java] Compile for Java 8 release with later compilers. --- build.gradle | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index a31b5d2db6..ea80314774 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,7 @@ defaultTasks 'clean', 'build', 'shadowJar', 'install' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() def sbeJavaVersion = JavaVersion.VERSION_1_8 +def sbeJavaReleaseVersion = '8' group = sbeGroup version = sbeVersion @@ -138,15 +139,25 @@ subprojects { checkstyle.toolVersion = '8.25' compileJava { - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + options.compilerArgs.addAll(['--release', sbeJavaReleaseVersion]) + } + else { + sourceCompatibility = sbeJavaVersion + targetCompatibility = sbeJavaVersion + } options.encoding = 'UTF-8' options.deprecation = true } compileTestJava { - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + options.compilerArgs.addAll(['--release', sbeJavaReleaseVersion]) + } + else { + sourceCompatibility = sbeJavaVersion + targetCompatibility = sbeJavaVersion + } options.encoding = 'UTF-8' options.deprecation = true } @@ -206,8 +217,13 @@ project(':sbe-tool') { compileGeneratedJava { dependsOn 'generateCodecs' - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + options.compilerArgs.addAll(['--release', sbeJavaReleaseVersion]) + } + else { + sourceCompatibility = sbeJavaVersion + targetCompatibility = sbeJavaVersion + } options.encoding = 'UTF-8' options.deprecation = true classpath += sourceSets.main.runtimeClasspath @@ -365,8 +381,13 @@ project(':sbe-samples') { compileGeneratedJava { dependsOn 'generateCodecs' - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + options.compilerArgs.addAll(['--release', sbeJavaReleaseVersion]) + } + else { + sourceCompatibility = sbeJavaVersion + targetCompatibility = sbeJavaVersion + } options.encoding = 'UTF-8' options.deprecation = true classpath += project(':sbe-all').sourceSets.main.runtimeClasspath @@ -461,8 +482,13 @@ project(':sbe-benchmarks') { compileGeneratedJava { dependsOn 'generateCodecs' - sourceCompatibility = '1.8' - targetCompatibility = '1.8' + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + options.compilerArgs.addAll(['--release', sbeJavaReleaseVersion]) + } + else { + sourceCompatibility = sbeJavaVersion + targetCompatibility = sbeJavaVersion + } options.encoding = 'UTF-8' options.deprecation = true classpath += project(':sbe-all').sourceSets.main.runtimeClasspath From e78eedf53958df98dd791c9467792141590a4ee8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 3 Nov 2019 08:44:15 +0000 Subject: [PATCH 0232/1594] [Java] Revert. --- build.gradle | 46 ++++++++++------------------------------------ 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/build.gradle b/build.gradle index ea80314774..cb4d8d9787 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,6 @@ defaultTasks 'clean', 'build', 'shadowJar', 'install' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() def sbeJavaVersion = JavaVersion.VERSION_1_8 -def sbeJavaReleaseVersion = '8' group = sbeGroup version = sbeVersion @@ -139,25 +138,15 @@ subprojects { checkstyle.toolVersion = '8.25' compileJava { - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { - options.compilerArgs.addAll(['--release', sbeJavaReleaseVersion]) - } - else { - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion - } + sourceCompatibility = sbeJavaVersion + targetCompatibility = sbeJavaVersion options.encoding = 'UTF-8' options.deprecation = true } compileTestJava { - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { - options.compilerArgs.addAll(['--release', sbeJavaReleaseVersion]) - } - else { - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion - } + sourceCompatibility = sbeJavaVersion + targetCompatibility = sbeJavaVersion options.encoding = 'UTF-8' options.deprecation = true } @@ -217,13 +206,8 @@ project(':sbe-tool') { compileGeneratedJava { dependsOn 'generateCodecs' - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { - options.compilerArgs.addAll(['--release', sbeJavaReleaseVersion]) - } - else { - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion - } + sourceCompatibility = sbeJavaVersion + targetCompatibility = sbeJavaVersion options.encoding = 'UTF-8' options.deprecation = true classpath += sourceSets.main.runtimeClasspath @@ -381,13 +365,8 @@ project(':sbe-samples') { compileGeneratedJava { dependsOn 'generateCodecs' - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { - options.compilerArgs.addAll(['--release', sbeJavaReleaseVersion]) - } - else { - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion - } + sourceCompatibility = sbeJavaVersion + targetCompatibility = sbeJavaVersion options.encoding = 'UTF-8' options.deprecation = true classpath += project(':sbe-all').sourceSets.main.runtimeClasspath @@ -482,13 +461,8 @@ project(':sbe-benchmarks') { compileGeneratedJava { dependsOn 'generateCodecs' - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { - options.compilerArgs.addAll(['--release', sbeJavaReleaseVersion]) - } - else { - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion - } + sourceCompatibility = sbeJavaVersion + targetCompatibility = sbeJavaVersion options.encoding = 'UTF-8' options.deprecation = true classpath += project(':sbe-all').sourceSets.main.runtimeClasspath From 04306d0ebd53eddbcf3df46cf3657ff4d2c1dbe9 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 5 Nov 2019 16:03:58 -0800 Subject: [PATCH 0233/1594] [Java]: update agrona dep. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cb4d8d9787..3147a07553 100644 --- a/build.gradle +++ b/build.gradle @@ -128,7 +128,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.25' - compile 'org.agrona:agrona:1.0.10' + compile 'org.agrona:agrona:1.0.11' testCompile 'org.hamcrest:hamcrest:2.1' testCompile 'org.mockito:mockito-core:3.1.0' From a94830af716699aa286b8c385bf169da03e1ff30 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 6 Nov 2019 16:32:57 +0000 Subject: [PATCH 0234/1594] [Java] Version refs update. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 04e8191f05..f79bc00d51 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.14.0 +    1.14.1 ``` @@ -65,7 +65,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.14.1-SNAPSHOT.jar my-sbe-input.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.14.2-SNAPSHOT.jar my-sbe-input.xml C++ Build using CMake From ba90d8a828a15b5b7d7cf926e492d0bedff7878f Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Wed, 6 Nov 2019 08:58:41 -0800 Subject: [PATCH 0235/1594] 1.14.1 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 1baa6e874f..30f101cbef 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.14.1-SNAPSHOT \ No newline at end of file +1.14.1 \ No newline at end of file From a517a1dcedba1a59e796ef391f6468abb3df50bc Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Wed, 6 Nov 2019 09:00:22 -0800 Subject: [PATCH 0236/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 30f101cbef..79dff6fe96 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.14.1 \ No newline at end of file +1.14.2-SNAPSHOT \ No newline at end of file From f246447df1d51ca4572db6e78c3c35660fe69394 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 10 Nov 2019 16:39:21 +0000 Subject: [PATCH 0237/1594] [Java] Allow build with Java greater than 8. --- .gitignore | 7 ++++++- build.gradle | 32 +++++++++++++++++++++----------- gradle.properties | 1 - 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 8c5c1918f9..b27d8153a7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ # editors *~ *.swp -.idea .project .classpath .factorypath @@ -10,6 +9,12 @@ *.sublime-project *.sublime-workspace +# intellij +.idea +*.iml +*.ipr +*.iws + # Build tools build-local.properties deps diff --git a/build.gradle b/build.gradle index 3147a07553..29d67d290e 100644 --- a/build.gradle +++ b/build.gradle @@ -21,6 +21,7 @@ buildscript { plugins { id 'java' + id 'idea' id 'io.freefair.javadoc-links' version '4.1.3' apply false id 'com.github.johnrengelman.shadow' version '5.1.0' apply false } @@ -29,7 +30,6 @@ defaultTasks 'clean', 'build', 'shadowJar', 'install' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() -def sbeJavaVersion = JavaVersion.VERSION_1_8 group = sbeGroup version = sbeVersion @@ -138,15 +138,19 @@ subprojects { checkstyle.toolVersion = '8.25' compileJava { - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) + options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) + } options.encoding = 'UTF-8' options.deprecation = true } compileTestJava { - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) + options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) + } options.encoding = 'UTF-8' options.deprecation = true } @@ -206,8 +210,10 @@ project(':sbe-tool') { compileGeneratedJava { dependsOn 'generateCodecs' - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) + options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) + } options.encoding = 'UTF-8' options.deprecation = true classpath += sourceSets.main.runtimeClasspath @@ -365,8 +371,10 @@ project(':sbe-samples') { compileGeneratedJava { dependsOn 'generateCodecs' - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) + options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) + } options.encoding = 'UTF-8' options.deprecation = true classpath += project(':sbe-all').sourceSets.main.runtimeClasspath @@ -461,8 +469,10 @@ project(':sbe-benchmarks') { compileGeneratedJava { dependsOn 'generateCodecs' - sourceCompatibility = sbeJavaVersion - targetCompatibility = sbeJavaVersion + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) + options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) + } options.encoding = 'UTF-8' options.deprecation = true classpath += project(':sbe-all').sourceSets.main.runtimeClasspath diff --git a/gradle.properties b/gradle.properties index e163055e76..f0ce1dd4da 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1 @@ org.gradle.daemon = true -org.gradle.caching = true From eed614392d5f28bf164d70c583f0e484dd86378b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 10 Nov 2019 17:40:04 +0000 Subject: [PATCH 0238/1594] [Java] Upgrade to Shadow 5.2.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 29d67d290e..6a9248c00d 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ plugins { id 'java' id 'idea' id 'io.freefair.javadoc-links' version '4.1.3' apply false - id 'com.github.johnrengelman.shadow' version '5.1.0' apply false + id 'com.github.johnrengelman.shadow' version '5.2.0' apply false } defaultTasks 'clean', 'build', 'shadowJar', 'install' From 8fb352eae2a3420fbd8d306068af7bd380c64ef5 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 10 Nov 2019 17:55:20 +0000 Subject: [PATCH 0239/1594] [Java] Upgrade to Versions 0.27.0, Checkstyle 8.26, and Hamcrest 2.2. --- build.gradle | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 6a9248c00d..03cc06f3ec 100644 --- a/build.gradle +++ b/build.gradle @@ -24,6 +24,7 @@ plugins { id 'idea' id 'io.freefair.javadoc-links' version '4.1.3' apply false id 'com.github.johnrengelman.shadow' version '5.2.0' apply false + id "com.github.ben-manes.versions" version "0.27.0" } defaultTasks 'clean', 'build', 'shadowJar', 'install' @@ -126,16 +127,16 @@ subprojects { jar.enabled = true dependencies { - checkstyle 'com.puppycrawl.tools:checkstyle:8.25' + checkstyle 'com.puppycrawl.tools:checkstyle:8.26' compile 'org.agrona:agrona:1.0.11' - testCompile 'org.hamcrest:hamcrest:2.1' + testCompile 'org.hamcrest:hamcrest:2.2' testCompile 'org.mockito:mockito-core:3.1.0' testCompile 'junit:junit:4.12' } - checkstyle.toolVersion = '8.25' + checkstyle.toolVersion = '8.26' compileJava { if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { From 23039c441dfa1c1e5e6d8f36dd1f0077ea5f87a5 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 11 Nov 2019 09:40:28 +0000 Subject: [PATCH 0240/1594] [Java] Move disable of bounds checks in benchmarks options to jvmArgs. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 03cc06f3ec..06609885ad 100644 --- a/build.gradle +++ b/build.gradle @@ -764,8 +764,8 @@ task generateIrCodecs { task runJavaBenchmarks(type: Exec) { commandLine 'java', - '-Dagrona.disable.bounds.checks=true', '-jar', 'sbe-benchmarks/build/libs/sbe-benchmarks.jar', + '-jvmArgs', '-Dagrona.disable.bounds.checks=true -XX:+UseParallelOldGC', '-w', '1s', '-r', '1s','-wi', '3', '-i', '5', '-tu', 'ns', '-f', '5' } From 3c8fe60ae3662c3a7a2c3b013bddda61b35c599d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 12 Nov 2019 13:44:52 +0000 Subject: [PATCH 0241/1594] [Java] Upgrade to javadoc-links 4.1.4 and set javadoc encoding to UTF-8. --- build.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 06609885ad..00105fcf90 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'idea' - id 'io.freefair.javadoc-links' version '4.1.3' apply false + id 'io.freefair.javadoc-links' version '4.1.4' apply false id 'com.github.johnrengelman.shadow' version '5.2.0' apply false id "com.github.ben-manes.versions" version "0.27.0" } @@ -171,6 +171,9 @@ subprojects { javadoc { title = '

    Simple Binary Encoding

    ' options.bottom = 'Copyright © 2014-2019 Real Logic Ltd. All Rights Reserved.' + options.encoding = 'UTF-8' + options.docEncoding = 'UTF-8' + options.charSet = 'UTF-8' if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_10.ordinal()) { options.addBooleanOption 'html5', true } From e1c470cddb5b1a34dca4f1b16648fabf2e8fb8ea Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 12 Nov 2019 18:59:58 +0000 Subject: [PATCH 0242/1594] [C++] Fix sinceVersion checks added to fields and enums so that the field rather than encoding token version is used. --- .../sbe/generation/cpp/CppGenerator.java | 75 ++++++++++--------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index c69c779464..774f63bff1 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1103,7 +1103,7 @@ private CharSequence generateCompositePropertyElements( switch (fieldToken.signal()) { case ENCODING: - generatePrimitiveProperty(sb, containingClassName, propertyName, fieldToken, indent); + generatePrimitiveProperty(sb, containingClassName, propertyName, fieldToken, fieldToken, indent); break; case BEGIN_ENUM: @@ -1129,18 +1129,20 @@ private void generatePrimitiveProperty( final StringBuilder sb, final String containingClassName, final String propertyName, - final Token token, + final Token propertyToken, + final Token encodingToken, final String indent) { - generatePrimitiveFieldMetaData(sb, propertyName, token, indent); + generatePrimitiveFieldMetaData(sb, propertyName, encodingToken, indent); - if (token.isConstantEncoding()) + if (encodingToken.isConstantEncoding()) { - generateConstPropertyMethods(sb, propertyName, token, indent); + generateConstPropertyMethods(sb, propertyName, encodingToken, indent); } else { - generatePrimitivePropertyMethods(sb, containingClassName, propertyName, token, indent); + generatePrimitivePropertyMethods( + sb, containingClassName, propertyName, propertyToken, encodingToken, indent); } } @@ -1148,17 +1150,18 @@ private void generatePrimitivePropertyMethods( final StringBuilder sb, final String containingClassName, final String propertyName, - final Token token, + final Token propertyToken, + final Token encodingToken, final String indent) { - final int arrayLength = token.arrayLength(); + final int arrayLength = encodingToken.arrayLength(); if (arrayLength == 1) { - generateSingleValueProperty(sb, containingClassName, propertyName, token, indent); + generateSingleValueProperty(sb, containingClassName, propertyName, propertyToken, encodingToken, indent); } else if (arrayLength > 1) { - generateArrayProperty(sb, containingClassName, propertyName, token, indent); + generateArrayProperty(sb, containingClassName, propertyName, propertyToken, encodingToken, indent); } } @@ -1290,12 +1293,13 @@ private void generateSingleValueProperty( final StringBuilder sb, final String containingClassName, final String propertyName, - final Token token, + final Token propertyToken, + final Token encodingToken, final String indent) { - final PrimitiveType primitiveType = token.encoding().primitiveType(); + final PrimitiveType primitiveType = encodingToken.encoding().primitiveType(); final String cppTypeName = cppTypeName(primitiveType); - final int offset = token.offset(); + final int offset = encodingToken.offset(); new Formatter(sb).format("\n" + indent + " SBE_NODISCARD %1$s %2$s() const SBE_NOEXCEPT\n" + @@ -1305,11 +1309,11 @@ private void generateSingleValueProperty( indent + " }\n", cppTypeName, propertyName, - generateFieldNotPresentCondition(token.version(), token.encoding(), indent), - generateLoadValue(primitiveType, Integer.toString(offset), token.encoding().byteOrder(), indent)); + generateFieldNotPresentCondition(propertyToken.version(), encodingToken.encoding(), indent), + generateLoadValue(primitiveType, Integer.toString(offset), encodingToken.encoding().byteOrder(), indent)); final CharSequence storeValue = generateStoreValue( - primitiveType, "", Integer.toString(offset), token.encoding().byteOrder(), indent); + primitiveType, "", Integer.toString(offset), encodingToken.encoding().byteOrder(), indent); new Formatter(sb).format("\n" + indent + " %1$s &%2$s(const %3$s value) SBE_NOEXCEPT\n" + @@ -1327,14 +1331,15 @@ private void generateArrayProperty( final StringBuilder sb, final String containingClassName, final String propertyName, - final Token token, + final Token propertyToken, + final Token encodingToken, final String indent) { - final PrimitiveType primitiveType = token.encoding().primitiveType(); + final PrimitiveType primitiveType = encodingToken.encoding().primitiveType(); final String cppTypeName = cppTypeName(primitiveType); - final int offset = token.offset(); + final int offset = encodingToken.offset(); - final int arrayLength = token.arrayLength(); + final int arrayLength = encodingToken.arrayLength(); new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t %1$sLength() SBE_NOEXCEPT\n" + indent + " {\n" + @@ -1350,7 +1355,7 @@ private void generateArrayProperty( indent + " return m_buffer + m_offset + %3$d;\n" + indent + " }\n", propertyName, - generateTypeFieldNotPresentCondition(token.version(), indent), + generateTypeFieldNotPresentCondition(propertyToken.version(), indent), offset); new Formatter(sb).format("\n" + @@ -1360,13 +1365,13 @@ private void generateArrayProperty( indent + " return m_buffer + m_offset + %3$d;\n" + indent + " }\n", propertyName, - generateTypeFieldNotPresentCondition(token.version(), indent), + generateTypeFieldNotPresentCondition(propertyToken.version(), indent), offset); final CharSequence loadValue = generateLoadValue( primitiveType, String.format("%d + (index * %d)", offset, primitiveType.size()), - token.encoding().byteOrder(), + encodingToken.encoding().byteOrder(), indent); new Formatter(sb).format("\n" + @@ -1382,14 +1387,14 @@ private void generateArrayProperty( cppTypeName, propertyName, arrayLength, - generateFieldNotPresentCondition(token.version(), token.encoding(), indent), + generateFieldNotPresentCondition(propertyToken.version(), encodingToken.encoding(), indent), loadValue); final CharSequence storeValue = generateStoreValue( primitiveType, "", String.format("%d + (index * %d)", offset, primitiveType.size()), - token.encoding().byteOrder(), + encodingToken.encoding().byteOrder(), indent); new Formatter(sb).format("\n" + @@ -1424,7 +1429,7 @@ private void generateArrayProperty( indent + " }\n", toUpperFirstChar(propertyName), arrayLength, - generateArrayFieldNotPresentCondition(token.version(), indent), + generateArrayFieldNotPresentCondition(propertyToken.version(), indent), offset, cppTypeName); @@ -1466,7 +1471,7 @@ private void generateArrayProperty( primitiveType, Integer.toString(i), Integer.toString(offset + (i * primitiveType.size())), - token.encoding().byteOrder(), + encodingToken.encoding().byteOrder(), indent)); } @@ -1475,7 +1480,7 @@ private void generateArrayProperty( sb.append(indent).append(" }\n"); } - if (token.encoding().primitiveType() == PrimitiveType.CHAR) + if (encodingToken.encoding().primitiveType() == PrimitiveType.CHAR) { new Formatter(sb).format("\n" + indent + " std::string get%1$sAsString() const\n" + @@ -1492,7 +1497,7 @@ private void generateArrayProperty( offset, arrayLength); - generateJsonEscapedStringGetter(sb, token, indent, propertyName); + generateJsonEscapedStringGetter(sb, encodingToken, indent, propertyName); new Formatter(sb).format("\n" + indent + " #if __cplusplus >= 201703L\n" + @@ -2014,7 +2019,8 @@ private void generateFields( switch (encodingToken.signal()) { case ENCODING: - generatePrimitiveProperty(sb, containingClassName, propertyName, encodingToken, indent); + generatePrimitiveProperty( + sb, containingClassName, propertyName, signalToken, encodingToken, indent); break; case BEGIN_ENUM: @@ -2170,7 +2176,7 @@ private void generateEnumProperty( indent + " }\n", enumName, propertyName, - generateEnumFieldNotPresentCondition(token.version(), enumName, indent), + generateEnumFieldNotPresentCondition(fieldToken.version(), enumName, indent), constValue.substring(constValue.indexOf(".") + 1)); } else @@ -2185,7 +2191,7 @@ private void generateEnumProperty( indent + " }\n", enumName, propertyName, - generateEnumFieldNotPresentCondition(token.version(), enumName, indent), + generateEnumFieldNotPresentCondition(fieldToken.version(), enumName, indent), formatByteOrderEncoding(token.encoding().byteOrder(), token.encoding().primitiveType()), typeName, offset); @@ -2243,7 +2249,6 @@ private static void generateCompositeProperty( final StringBuilder sb, final String propertyName, final Token token, final String indent) { final String compositeName = formatClassName(token.applicableTypeName()); - final int offset = token.offset(); new Formatter(sb).format("\n" + "private:\n" + @@ -2261,7 +2266,7 @@ private static void generateCompositeProperty( indent + " }\n", compositeName, propertyName, - offset); + token.offset()); } private CharSequence generateNullValueLiteral(final PrimitiveType primitiveType, final Encoding encoding) @@ -2623,7 +2628,7 @@ private CharSequence generateChoicesDisplay(final String name, final List new Formatter(sb).format("\n" + indent + "template\n" + - indent + "friend std::basic_ostream& operator<<(" + + indent + "friend std::basic_ostream& operator<<(\n" + indent + " std::basic_ostream& builder, %1$s writer)\n" + indent + "{\n" + indent + " builder << '[';\n", From 3cb1e3c5ac681252212973eaaca72781abd9eb76 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 12 Nov 2019 20:13:47 +0000 Subject: [PATCH 0243/1594] [Java] sinceVersion should be the min of field and type sinceVersion in IR. --- .../uk/co/real_logic/sbe/xml/IrGenerator.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index 7091536df6..437c3043fc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -117,7 +117,7 @@ private void addMessageSignal(final Message msg, final Signal signal) tokenList.add(token); } - private void addFieldSignal(final Field field, final Signal signal) + private void addFieldSignal(final Field field, final Signal signal, final int typeSinceVersion) { final Encoding.Builder encodingBuilder = new Encoding.Builder() .epoch(field.epoch()) @@ -142,7 +142,7 @@ private void addFieldSignal(final Field field, final Signal signal) .description(field.description()) .id(field.id()) .offset(field.computedOffset()) - .version(field.sinceVersion()) + .version(Math.max(field.sinceVersion(), typeSinceVersion)) .deprecated(field.deprecated()) .encoding(encodingBuilder.build()) .build(); @@ -158,20 +158,22 @@ private void addAllFields(final List fieldList) if (null == type) { - addFieldSignal(field, Signal.BEGIN_GROUP); + addFieldSignal(field, Signal.BEGIN_GROUP, 0); add(field.dimensionType(), 0, field); addAllFields(field.groupFields()); - addFieldSignal(field, Signal.END_GROUP); + addFieldSignal(field, Signal.END_GROUP, 0); } else if (type instanceof CompositeType && field.isVariableLength()) { - addFieldSignal(field, Signal.BEGIN_VAR_DATA); + addFieldSignal(field, Signal.BEGIN_VAR_DATA, 0); add((CompositeType)type, field.computedOffset(), field); - addFieldSignal(field, Signal.END_VAR_DATA); + addFieldSignal(field, Signal.END_VAR_DATA, 0); } else { - addFieldSignal(field, Signal.BEGIN_FIELD); + final int typeSinceVersion = type.sinceVersion(); + + addFieldSignal(field, Signal.BEGIN_FIELD, typeSinceVersion); if (type instanceof EncodedDataType) { @@ -194,7 +196,7 @@ else if (type instanceof SetType) throw new IllegalStateException("Unknown type: " + type); } - addFieldSignal(field, Signal.END_FIELD); + addFieldSignal(field, Signal.END_FIELD, typeSinceVersion); } } } From facd36c417f561dcb4fe249208bec66b2ff8d0d3 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 13 Nov 2019 14:25:16 +0000 Subject: [PATCH 0244/1594] [Java] Handle the JSON encoding of NaN, Infinity, and -Infinity. --- .../sbe/json/JsonTokenListener.java | 2 +- .../java/uk/co/real_logic/sbe/otf/Types.java | 95 +++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index 75aa4c2148..edc0aef61f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -259,7 +259,7 @@ private void appendEncodingAsString( for (int i = 0; i < size; i++) { - Types.appendAsString(output, buffer, index + (i * elementSize), encoding); + Types.appendAsJsonString(output, buffer, index + (i * elementSize), encoding); output.append(", "); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java index 41e994a97d..0961df215c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java @@ -171,4 +171,99 @@ public static void appendAsString( break; } } + + /** + * Append an encoding as a Json String to a {@link StringBuilder}. + * + * @param sb to append the encoding to. + * @param buffer containing the encoded value. + * @param index at which the encoded value exists. + * @param encoding representing the encoded value. + */ + public static void appendAsJsonString( + final StringBuilder sb, final DirectBuffer buffer, final int index, final Encoding encoding) + { + switch (encoding.primitiveType()) + { + case CHAR: + sb.append('\'').append((char)buffer.getByte(index)).append('\''); + break; + + case INT8: + sb.append(buffer.getByte(index)); + break; + + case INT16: + sb.append(buffer.getShort(index, encoding.byteOrder())); + break; + + case INT32: + sb.append(buffer.getInt(index, encoding.byteOrder())); + break; + + case INT64: + sb.append(buffer.getLong(index, encoding.byteOrder())); + break; + + case UINT8: + sb.append((short)(buffer.getByte(index) & 0xFF)); + break; + + case UINT16: + sb.append(buffer.getShort(index, encoding.byteOrder()) & 0xFFFF); + break; + + case UINT32: + sb.append(buffer.getInt(index, encoding.byteOrder()) & 0xFFFF_FFFFL); + break; + + case UINT64: + sb.append(buffer.getLong(index, encoding.byteOrder())); + break; + + case FLOAT: + { + final float value = buffer.getFloat(index, encoding.byteOrder()); + if (Float.isNaN(value)) + { + sb.append("0/0"); + } + else if (value == Float.POSITIVE_INFINITY) + { + sb.append("1/0"); + } + else if (value == Float.NEGATIVE_INFINITY) + { + sb.append("-1/0"); + } + else + { + sb.append(value); + } + break; + } + + case DOUBLE: + { + final double value = buffer.getDouble(index, encoding.byteOrder()); + if (Double.isNaN(value)) + { + sb.append("0/0"); + } + else if (value == Double.POSITIVE_INFINITY) + { + sb.append("1/0"); + } + else if (value == Double.NEGATIVE_INFINITY) + { + sb.append("-1/0"); + } + else + { + sb.append(value); + } + break; + } + } + } } From 29c5992232d975053871e4ff1f67075f2b7e62b0 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 13 Nov 2019 15:49:29 +0000 Subject: [PATCH 0245/1594] [Java] Logic tidy up. --- .../sbe/generation/cpp/CppGenerator.java | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 774f63bff1..e93c92a65b 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2422,23 +2422,10 @@ private CharSequence appendDisplay( for (int i = 0, size = fields.size(); i < size;) { final Token fieldToken = fields.get(i); + final Token encodingToken = fields.get(fieldToken.signal() == Signal.BEGIN_FIELD ? i + 1 : i); - if (fieldToken.signal() == Signal.BEGIN_FIELD) - { - final Token encodingToken = fields.get(i + 1); - - writeTokenDisplay(sb, fieldToken.name(), encodingToken, atLeastOne, indent); - - i += fieldToken.componentTokenCount(); - } - else - { - final Token encodingToken = fields.get(i); - - writeTokenDisplay(sb, fieldToken.name(), encodingToken, atLeastOne, indent); - - i += fieldToken.componentTokenCount(); - } + writeTokenDisplay(sb, fieldToken.name(), encodingToken, atLeastOne, indent); + i += fieldToken.componentTokenCount(); } for (int i = 0, size = groups.size(); i < size; i++) @@ -2607,9 +2594,6 @@ private void writeTokenDisplay( break; case BEGIN_SET: - sb.append(indent + "builder << " + fieldName + "();\n"); - break; - case BEGIN_COMPOSITE: sb.append(indent + "builder << " + fieldName + "();\n"); break; From a0b4769bca58f8777b19d4842937a4c203dc7112 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 13 Nov 2019 15:54:13 +0000 Subject: [PATCH 0246/1594] [Java] Bump minor version. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 79dff6fe96..147bacfdda 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.14.2-SNAPSHOT \ No newline at end of file +1.15.0-SNAPSHOT \ No newline at end of file From d4b23269e5b48232f648d44f589a44ba63e67bf1 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Mon, 18 Nov 2019 10:51:05 -0800 Subject: [PATCH 0247/1594] [Java]: update Agrona dep. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 00105fcf90..2f58c95337 100644 --- a/build.gradle +++ b/build.gradle @@ -129,7 +129,7 @@ subprojects { dependencies { checkstyle 'com.puppycrawl.tools:checkstyle:8.26' - compile 'org.agrona:agrona:1.0.11' + compile 'org.agrona:agrona:1.1.0' testCompile 'org.hamcrest:hamcrest:2.2' testCompile 'org.mockito:mockito-core:3.1.0' From 777e543dbabce8c5368d7b7a6a06b87d91a0092a Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 20 Nov 2019 19:40:27 +0000 Subject: [PATCH 0248/1594] [C++] Add skip method for var data fields without reading. --- .../sbe/generation/cpp/CppGenerator.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index e93c92a65b..0d42ebd77c 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -443,6 +443,24 @@ private void generateVarData( generateVarDataDescriptors( sb, token, propertyName, characterEncoding, lengthToken, lengthOfLengthField, lengthCppType, indent); + new Formatter(sb).format("\n" + + indent + " std::uint64_t skip%1$s()\n" + + indent + " {\n" + + "%2$s" + + indent + " std::uint64_t lengthOfLengthField = %3$d;\n" + + indent + " std::uint64_t lengthPosition = sbePosition();\n" + + indent + " %5$s lengthFieldValue;\n" + + indent + " std::memcpy(&lengthFieldValue, m_buffer + lengthPosition, sizeof(%5$s));\n" + + indent + " std::uint64_t dataLength = %4$s(lengthFieldValue);\n" + + indent + " sbePosition(lengthPosition + lengthOfLengthField + dataLength);\n" + + indent + " return dataLength;\n" + + indent + " }\n", + propertyName, + generateArrayFieldNotPresentCondition(token.version(), indent), + lengthOfLengthField, + lengthByteOrderStr, + lengthCppType); + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD const char *%1$s()\n" + indent + " {\n" + From 905d541aff65b667829e5638c9f91cc06b5f11f2 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 20 Nov 2019 19:40:45 +0000 Subject: [PATCH 0249/1594] [Java] Add skip method for var data fields without reading. --- .../sbe/generation/java/JavaGenerator.java | 17 +++ .../sbe/ir/generated/FrameCodecDecoder.java | 36 +++++ .../sbe/ir/generated/TokenCodecDecoder.java | 132 ++++++++++++++++++ 3 files changed, 185 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index c3a78d1ad9..8f3ac6c796 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -829,6 +829,23 @@ private void generateDataDecodeMethods( final String characterEncoding, final String indent) { + new Formatter(sb).format("\n" + + indent + " public int skip%1$s()\n" + + indent + " {\n" + + "%2$s" + + indent + " final int headerLength = %3$d;\n" + + indent + " final int limit = parentMessage.limit();\n" + + indent + " final int dataLength = (int)%4$s;\n" + + indent + " final int dataOffset = limit + headerLength;\n\n" + + indent + " parentMessage.limit(dataOffset + dataLength);\n\n" + + indent + " return dataLength;\n" + + indent + " }\n", + Generators.toUpperFirstChar(propertyName), + generateStringNotPresentConditionForAppendable(token.version(), indent), + sizeOfLengthField, + generateGet(lengthType, "limit", byteOrderStr), + byteOrderStr); + generateVarDataTypedDecoder( sb, token, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 2167c289c8..4082de62c6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -292,6 +292,18 @@ public int packageNameLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipPackageName() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getPackageName(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; @@ -392,6 +404,18 @@ public int namespaceNameLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipNamespaceName() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getNamespaceName(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; @@ -492,6 +516,18 @@ public int semanticVersionLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipSemanticVersion() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getSemanticVersion(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 020942c8a7..97be0c0658 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -610,6 +610,18 @@ public int nameLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipName() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getName(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; @@ -710,6 +722,18 @@ public int constValueLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipConstValue() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getConstValue(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; @@ -810,6 +834,18 @@ public int minValueLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipMinValue() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getMinValue(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; @@ -910,6 +946,18 @@ public int maxValueLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipMaxValue() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getMaxValue(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; @@ -1010,6 +1058,18 @@ public int nullValueLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipNullValue() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getNullValue(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; @@ -1110,6 +1170,18 @@ public int characterEncodingLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipCharacterEncoding() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getCharacterEncoding(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; @@ -1210,6 +1282,18 @@ public int epochLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipEpoch() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getEpoch(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; @@ -1310,6 +1394,18 @@ public int timeUnitLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipTimeUnit() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getTimeUnit(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; @@ -1410,6 +1506,18 @@ public int semanticTypeLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipSemanticType() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getSemanticType(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; @@ -1510,6 +1618,18 @@ public int descriptionLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipDescription() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getDescription(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; @@ -1610,6 +1730,18 @@ public int referencedNameLength() return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } + public int skipReferencedName() + { + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataOffset = limit + headerLength; + + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + public int getReferencedName(final MutableDirectBuffer dst, final int dstOffset, final int length) { final int headerLength = 2; From 558a79f11ebc9bc33d7edb6597d7d104892190ec Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Thu, 21 Nov 2019 18:19:08 +0000 Subject: [PATCH 0250/1594] [Java] README. --- README.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f79bc00d51..b64f01abf5 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,6 @@ The Java and C++ SBE implementations are designed with work very efficiently wit high-throughput communications. The Java SBE implementation has a dependency on [Agrona](https://github.com/real-logic/agrona) for its buffer implementations. - Binaries -------- Binaries and dependency information for Maven, Ivy, Gradle, and others can be found at @@ -53,7 +52,6 @@ Run the Java examples $ ./gradlew runJavaExamples - Distribution ------------ Jars for the executable, source, and javadoc for the various modules can be found in the following directories: @@ -65,8 +63,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.14.2-SNAPSHOT.jar my-sbe-input.xml - + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.15.0.jar my-sbe-input.xml C++ Build using CMake --------------------- @@ -86,8 +83,8 @@ If you are comfortable with using CMake, then a full clean, build, and test look $ cmake --build . --clean-first $ ctest -__Note__: A C generator is included with the C++ build. And is built with the C++ build. Currently, the C generator is a work -in progress. +__Note__: A C generator is included with the C++ build. And is built with the C++ build. Currently, the C generator is + a work in progress. Golang Build ------------ @@ -110,14 +107,12 @@ documentation](https://github.com/real-logic/simple-binary-encoding/wiki/Golang- Developers wishing to enhance the golang generator should see the [developer documentation](https://github.com/real-logic/simple-binary-encoding/blob/master/gocode/README.md) - C# Build -------- Users of CSharp generated code should see the [user documentation](https://github.com/real-logic/simple-binary-encoding/wiki/Csharp-User-Guide). Developers wishing to enhance the CSharp generator should see the [developer documentation](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/README.md) - License (See LICENSE file for full license) ------------------------------------------- Copyright 2013-2019 Real Logic Limited From ad08cad7d12a6542de2045f075546d515da77751 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Thu, 21 Nov 2019 18:19:45 +0000 Subject: [PATCH 0251/1594] [Java] README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b64f01abf5..8ac9d45e8d 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.14.1 +    1.15.0 ``` From ac7feba549ea070355f60b3bc7e7008b64235c9a Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Thu, 21 Nov 2019 10:28:32 -0800 Subject: [PATCH 0252/1594] 1.15.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 147bacfdda..d19d089012 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.15.0-SNAPSHOT \ No newline at end of file +1.15.0 \ No newline at end of file From 71c6153f299e453280208f4872c840f906bc9b47 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Thu, 21 Nov 2019 10:31:17 -0800 Subject: [PATCH 0253/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index d19d089012..65659b4c80 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.15.0 \ No newline at end of file +1.15.1-SNAPSHOT \ No newline at end of file From b9738cbb4c5d28f420ebded85eb3d8cbe99c8aa2 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Tue, 26 Nov 2019 10:42:53 +1300 Subject: [PATCH 0254/1594] [C/C++] Upgrade gtest to 1.10. Replace uses of INSTANTIATE_TEST_CASE_P with INSTANTIATE_TEST_SUITE_P. --- CMakeLists.txt | 11 ++++++----- sbe-tool/src/test/c/BoundsCheckTest.cpp | 8 ++++---- sbe-tool/src/test/cpp/BoundsCheckTest.cpp | 8 ++++---- sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp | 4 ++-- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 960ba6d2cd..89d6661e97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,11 +65,11 @@ if(SBE_TESTS) ExternalProject_Add( gtest - URL ${CMAKE_CURRENT_SOURCE_DIR}/cppbuild/googletest-release-1.8.0.zip - URL_MD5 adfafc8512ab65fd3cf7955ef0100ff5 + URL ${CMAKE_CURRENT_SOURCE_DIR}/cppbuild/googletest-release-1.10.0.zip + URL_MD5 82358affdd7ab94854c8ee73a180fc53 PREFIX "${SBE_THIRDPARTY_BINARY_DIR}/gtest" CMAKE_ARGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER};-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} - BUILD_BYPRODUCTS "${SBE_THIRDPARTY_BINARY_DIR}/gtest/src/gtest-build/googlemock/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX};${SBE_THIRDPARTY_BINARY_DIR}/gtest/src/gtest-build/googlemock/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock_main${CMAKE_STATIC_LIBRARY_SUFFIX}" + BUILD_BYPRODUCTS "${SBE_THIRDPARTY_BINARY_DIR}/gtest/src/gtest-build/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX};${SBE_THIRDPARTY_BINARY_DIR}/gtest/src/gtest-build/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock_main${CMAKE_STATIC_LIBRARY_SUFFIX}" INSTALL_COMMAND "" LOG_CONFIGURE ON LOG_BUILD ON @@ -81,8 +81,9 @@ if(SBE_TESTS) set(GTEST_BINARY_DIR ${binary_dir}) set(GTEST_LIBS - ${GTEST_BINARY_DIR}/googlemock/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX} - ${GTEST_BINARY_DIR}/googlemock/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock_main${CMAKE_STATIC_LIBRARY_SUFFIX} + ${GTEST_BINARY_DIR}/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX} + ${GTEST_BINARY_DIR}/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gtest${CMAKE_STATIC_LIBRARY_SUFFIX} + ${GTEST_BINARY_DIR}/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gtest_main${CMAKE_STATIC_LIBRARY_SUFFIX} ) endif() diff --git a/sbe-tool/src/test/c/BoundsCheckTest.cpp b/sbe-tool/src/test/c/BoundsCheckTest.cpp index 2a2794f2ab..43afa0b4bf 100644 --- a/sbe-tool/src/test/c/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/c/BoundsCheckTest.cpp @@ -532,10 +532,10 @@ TEST_P(HeaderBoundsCheckTest, shouldExceptionWhenBufferTooShortForDecodeOfHeader }, std::runtime_error); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( HeaderLengthTest, HeaderBoundsCheckTest, - ::testing::Range(0, static_cast(encodedHdrSz), 1), ); + ::testing::Range(0, static_cast(encodedHdrSz), 1)); class MessageBoundsCheckTest : public BoundsCheckTest, public ::testing::WithParamInterface { @@ -576,7 +576,7 @@ TEST_P(MessageBoundsCheckTest, shouldExceptionWhenBufferTooShortForDecodeOfMessa }, std::runtime_error); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MessageLengthTest, MessageBoundsCheckTest, - ::testing::Range(0, static_cast(encodedCarSz), 1), ); + ::testing::Range(0, static_cast(encodedCarSz), 1)); diff --git a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp index f72223f86a..ca3f76951f 100644 --- a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp @@ -312,10 +312,10 @@ TEST_P(HeaderBoundsCheckTest, shouldExceptionWhenBufferTooShortForDecodeOfHeader }, std::runtime_error); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( HeaderLengthTest, HeaderBoundsCheckTest, - ::testing::Range(0, static_cast(encodedHdrSz), 1), ); + ::testing::Range(0, static_cast(encodedHdrSz), 1)); class MessageBoundsCheckTest : public BoundsCheckTest, public ::testing::WithParamInterface { @@ -356,7 +356,7 @@ TEST_P(MessageBoundsCheckTest, shouldExceptionWhenBufferTooShortForDecodeOfMessa }, std::runtime_error); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MessageLengthTest, MessageBoundsCheckTest, - ::testing::Range(0, static_cast(encodedCarSz), 1), ); + ::testing::Range(0, static_cast(encodedCarSz), 1)); diff --git a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp index 6487ce8ea3..a04a771fe7 100644 --- a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp +++ b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp @@ -1197,7 +1197,7 @@ TEST_P(Rc3OtfFullIrLengthTest, shouldExceptionIfLengthTooShort) }, std::runtime_error); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( LengthUpToHdrAndCar, Rc3OtfFullIrLengthTest, - ::testing::Range(0, static_cast(encodedCarAndHdrLength - MessageHeader::encodedLength()), 1), ); + ::testing::Range(0, static_cast(encodedCarAndHdrLength - MessageHeader::encodedLength()), 1)); From 1d1c6c66f90b2a2bad6fe246be4fd5d20cdca2ff Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Tue, 26 Nov 2019 10:46:59 +1300 Subject: [PATCH 0255/1594] [C/C++] Include the gtest 1.10 binary and remove the 1.8 one. --- cppbuild/googletest-release-1.10.0.zip | Bin 0 -> 1146687 bytes cppbuild/googletest-release-1.8.0.zip | Bin 1586287 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 cppbuild/googletest-release-1.10.0.zip delete mode 100644 cppbuild/googletest-release-1.8.0.zip diff --git a/cppbuild/googletest-release-1.10.0.zip b/cppbuild/googletest-release-1.10.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..87570a3086970824be1a80ef6bb237cb1eab5793 GIT binary patch literal 1146687 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 FH0I#}06 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 z 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

    vUu1tZHe3*fLE`rB3Wyvr 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

    ZzGY7+$z+tbNeyp-VPDX~J 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 z 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�&Tk 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 z z2{a<9=31mFEMT5wAPe0G81Z_�$-FJ0~7)3%1S^zJ11y)J1ko@i3l5gfP!)l+AxH93Z|FYv>j$rM zIxvjR;!??pQbZ<+yHpK$@X1mFKamo0aA55p+N^l6(QQ*L-W`FrN@(z69YdnTEIPzH zvK4f$x*N6GVs9+5F%dglx;kk|{Vwj37{4%d5|Jn~P>*W{lG5WNqb*$+9E|MR8J9)# z-_1Qq9T#hHF>0oRHY{(BdQ65L|*FR-;iXPMM+)-iUTPPs^#(RmGsrA z%H?uCCy(};i$mWRr_bJA%jfUpbo66Ogh%Th!oXH`B{7&Y27n}M;3oTAI+LgL{K2r5|A)Wx#J;MDYtvpywXq!jw#t8la$ zk|$iZ3RBvO{F+Ajg{}5QmQV|uVyYPdMM~T|!4fV?NPX=y>x!o6YGF)|-wm$@rx(vB zoF0QbwSY^@G|GZImo#gHbCZostE6;d${w^~sMUXQ(zpQvZE`9=*wN32WCx>{$BzLy zssVCT1oESyBP{tlw-7~g38xF(%XI>|)EwvJ=6?o1Mf&__@Y0r%vGBfCE-8iJ%))x7 zFg7_X_f7=Gh6C%j4Fs^~-5>)-D4bEjmyk@UW{hx{j7@}`$tmgr0E)!Pw@=&yxCp}Y z_Eg3QZ=Z~B)j+5_`leE+UN?&r66DGvHV4^w2}l`OC6Dz${#??z(Nj%DJ7Fm4IwnXh zlp<7FEI_7diizL+IrfZcZy1TR%@y>Grf828$kBAn&YN@2E8Fo-jqT7q zi)dj^8hN4|h!r*d*b@!Ey>jd%fafoE3Wlp2jFOQNP^7)RQ{i}S0114dTQv1OM%u?| zGf!@Ryu%0esj%tHIg!+f@&?oYVg9EfRy<*&ocwM@)MUaF@H6~^H5<1o^mhJ&z1VK6S{b_^n&%0fQGSsj2d_%LM(OLHs<^ zVnAEXsI(bsYdoo{$)S4@eVA6=Lr*q_C*MN<^gHM`Tr|I72pg`MfBGf!_D%AZcZr+? z4o=X0V>Ph-rzK1j+7^J3Lt;x{(st{DUd4DE3{%43#p{P0;{z$u@P;l5w7cgEnxJQN z_>M8k8vQKn9TV^Dh-n%Nu^fpc6=qHXmSfywk2bPuD zrI*}nLn}z8P_cB3MMBxq(V(lr77tA?_CVrXL>zvaDe1`$mmrZ0KN7)#+-D|U8Q3J+ z?R7*S!Z_8}K=3^ea!W~ucRTVm0i+#BR5ogX=n_yd+P2@2#(Zv#uz{y=%%Tu4iY|sq z^4x2Qk2-9X&EU}Ip{Hg_tzvJ_!)u)f>faVeDWaj(TT-K6PzcgBRvXV))-%$|FBMfH z-3qeqf?NzI{j+|Ttc<=`ipiiYcbjB|>*|)0^{nkWTE1_~*SBJ(2W<|IeN z!iW;KEErVL8wesz9!&L#(uf@8ieXg{!@ap8k<7EaV4aR zxhq46`m(8gfp}}@ooZ5Ms4ouX`(FfuR_u%0D<-JpzdAV68s!!-FgD6m9E?|ao8)I? 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.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

    aOx9|_^ho-PaF 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 literal 0 HcmV?d00001 diff --git a/cppbuild/googletest-release-1.8.0.zip b/cppbuild/googletest-release-1.8.0.zip deleted file mode 100644 index ee1136a802250567197b03b5469eaf5c6cca2ff4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1586287 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%0AwlVeewVB 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
    Tw&lGI4KPGDnT znHJ~0A#-11u=k<@F%;P&sH5I4CAQIwg~`ruz7)oD$Xmdzw>Uz~=r2oloqYuoS~98C zsywd->SRcQ2Aex&q2SXuXwQvt;ZU}Oq6n^W_E{GtjsW9Dt6~y$7lpVeTXwXFR&i6i z53E;1mn=He28n0>7;*}!*A~eCK2b11Y(T0gNw?#sM{jVdz@VWL56_o*V($w2as1z& zPBIQ6iU+zC9A0%C${C%yFZz94_2UO__g@I_UXZWS7of*{!^i6QNWu+Xl4(Beh!Kqu z|MPh2R&$yrAmFN1QCS-N44`mX(pk0iC--(Ta%%!!6E49vgm=EcJA(evo_i#_kQvPL z@9ST38(->m9{=H;rKaWu z`|IsP@~?GG05Nol1OeeG<%qc85FLH?gD}2n-b8#uU zr42N_?WkOuwu0sho0VEKfwCR;8g6=qrD?=iKeRh~qR5q3WKEFUCM>eh6LsI8jK{Q4 zDOE0>x*0D&>`3&4KHf%+l8bnzMGD(1AI)$O$)A#mJUj6aDp&0Tn(B4XZi zVdlsnauUTVXEP#GFkM+Wvln)R(D8L6d7B}g`BDAPFTas?tiDjin~G3pMu<)mctwbP ze2k5BJ%m)pAUlA-9ve!Ur_jtdzap&qW<6-_t09gphDrQDpRehq%uj#`&JxNo-$CRx zIcxBe^c}*_+#V0fEw(FOFr6E6Gr}*VdNPo> z;-LQJ%sgTdE+4+3zhRjp6^ZqX+Bv}Xet-zf8M+rukT7qcTM4#WooZM80~+6jeXVYu z=E3)CBNpxU$U6evSE^(9{Jt9ZFe8$o=Dv)2g$K4Z^dfsaHzvnEVSrzsi0k25<{u+O z1NL6Sn#ADoG)Jbvnsw-h=|C)>iC{FoO3uw4P%K86J$G~Srw70Y#zPER3mu~N8T#~H zuU<#xdN%Ftjd{#FMi6Ze-ru*nL9kBjsiB8hMIvN1SoU|%9@4cP3HIi|Y8^)fX1(-U zv?Xl=ouv0{>2mC#<)K(StDV?)7e+Q#0d?E!B49ZL&i>LN6&X|I>pw_E8L(e40000A z@Thbnd7u~=S_lFFz=Ht*`~YZxg@c2It(mKtiz}V8nXQ?Tiy0jgJtsXQ!~Z+5b1<=C zFm*6-VQ^Da$Bq3&Qo@*5B2#2AAM< zINHSQhyJ3zC>5?Y`fFOli#M7d_xAcsiYut2CS8J^@Xco{0FIKW8#A9$5qRlSu~7~p z;U>*HD2q>r4GJ&OVPfwS>hpq+HUd(7R5JBY^`(yH=wu{hy&s24D&(lBvSi50y6)Wh z4(E)Zk}#`G@}KNsAKLF^c^}PGSONas0}n^6wv0A<2ca-fpdHU)kr8R~apQLCd*vUA zBEs_;t^BfBm|^gK#o~t3Fm|dyHMPcY0Z86Im`HEYFDTnc1btL324Z@4KKs(?9mLP} z!9zEi7;|&(wia_79nKEP++WL56stXWpBf8x!)vB9=X<>}5zi*V6L#JnUj?UetB|a< zF+Z5B_Bn~JSyWq^E(5*1;R8wq1`qnF-8-lur%EJ$NX2+oJr|oE&4Sl1Y3=VEGsc}U zs;3O?=3Zz{2~H%l8|?tdIMKj1ql=-1BM}_(4i6LO??)}gyt-;?mh@|34R3;~N^J(~ zs_LF%wL0w>jOrkZOk{05Chink-u;OiKjfIQvjx_tHqro)|2+hi8FA(cGyp)JD*(Xr ze;xvH2WL??J3A{gm;ZkPYW=KIa3zwDJ-(t<(>9POi~5VZ1#BBvT2Q2vwvol+s#LbOriA}Z%;Py?^wpvtmRZ~@pc?$cNvld1|b_rd2T~$ttW_(Jg%tf2Cl**)@*v^UE z!-1Suol8a!4JKiV#xanp`UmGQ>(q~>-j1pB+I#!4f3|(O zL%Cb`R$8l$e2#OMoIsb=b@Zm()Jn?+=X-*jmf8ld$I_^shu3BYRRre-y+q1_p=176 zY*BA5D(=t}L*EhSf9yS9l~SE{hUx@{J{>+vHjs_Twf5 z586duk10&%eo+QWnvHi%-#d0X1Yfyt;W`KQkL4Ea_S_xVZ=M2DRKD?=>^5qB(mJhJ z@(>|X4`vLl<`(`;q+0EoTH5%UN%pKdQMj)~`De9-Yn%@_A zid2Lb-%YKpv{U7Il!37dFIz8>&1p96Xp>zt*=WL@D3xf~`fae=^gxPa9bNmKw$%4} z(VUbI#hBG`&&Knn?k3I~m1w1yl9+9yA_{h;Gg&$ox$1_O2Uia&2hA89JF(;rR24W! zBbEFQrb*4V2f?%n+X07rglQyZwQ9-z1MfcG_{kPWX0;@QMlmXI3DRPB`xr6m6jyzY zv@7~kYGDC(A5tD7m!6};cC#JB|9rP9eLEkvTG5@EEz{FlRm!CGRIgRSiM??tb9cE^ zY0SsQ@@B2se~RfU^m>6cbd#k^6j2?~f@~>A>Nk(chPmra{F@2nR6Sg8`VWM(j8Ek;})7!(%Vp|3Msrf8kMxGNKKO0axcWt zotfCSa5ci&xwT&^bHR>-x~X)hdM70O9>2q@28cQmWB#KM=2+;stcZzIDBhZ#Qyyb+ z)(%D(F!lW4*k_x2Jip!h_Z56aN61cEe|ru~_R=L?{=83a1IV-qiqSzoU z?=wB1oZVSVJo{C+{OL^&f7WgAZK z1ykxUOd5$3)jJgsM`C@s^pk06TXmgTT&&CPb|OB%uKqh`z%+1gY?l(aCE|%_;Ltx0GRuxEfgxt+McM+$l zgAMem2+@X?e6w(VSJhJVkF($jC#8qqOJ%ap2!e1U-*GH zjR>h#LkxXW$$UCJQN#RmWw>sATea9m)vn0@L9We;?y&V>BW4O{Gw~PKFrYE~W$S2s zi@DrBO2;ln4$u%%Z~MhAn{kYAV<%zIO$`LXBA-h=)LJ%XPnS%t;;v^fM-0(C zwhg!hZzb@?)`%-;i8-Izr7v+Rj;ijP9O^J{~3_v^%Jp6m3qi6$3LdH&Yv=F%dF-BA(ZY{_IJ;rS_%v$X*qm2O+sA zEA32fhq zId~X(G3Npb3JCs{3$EJyU(i3?L_g&phDe7A>LJJKc!aDiXs2$m_KA;+8ARf% zy{|-gp@P{o{&bAx94~g(9Dc9xsc5XTTX4^;AH<1aVA!vnQC9$vUl#}OM~l}P^u}1UgdT}Os!(c6Qz~rA#)B9FzaiT(_ zPQtr`Z&kt4nb zE=&?JOGTXRlk|1rlP z-O9yR(^vV3Zj}Dtqu%Ihmjr5e_LrDCi~(~YUCsOW`G^PXF}12n_4Xk~5BZXo0U%zW061IHrCb_7x{UF9kS`DDb?WR3A+| zqVD~nejNeZo7^1yhiJwK@~@y*S>NEyOdbfXQP6uK=cV&drC=h<$hF-KR}hWlL*fGY^eCJE-->!g9duLohr++Zn*UE$5lJa~=k}HcKh+uMYdzloj=O z7Uox=a}Z3}AMyWW>kvY6AvZapo}N9KpR@=sZtSS?oiH{gJc@SMhA6t!A$|p4g>3L2 zlx35k@3ZNb*Azr??WBpBs(@j^JEtGbHzQSv?2gSJNf zoVS7`#@cU~Q`48qrp%IiEIBC8Krk$7GSN)-jN><`!34>S!$5}hvKV+!m5+}6^V_qF zFQNwQr6ooz|7}e~E%En=TO~c~)Zx<4>2Wk@Pw+zrODu6GS+yj@$d40ZRN{#XZgFml zjy5WDmQ}7GRi_nIE4-{u$o^1xhRWbmuqnKS0!b`#WeiSK|ATv9nNX=!LF9?t+^W4Z zs6>p&)HDucCapMRPpI7rRb|rr@^CpXFkZ-?%y}t^@u|m+!f-Z9zMDM&xBdI02dD$-Jfg`~h(^no-Oq~Wxl@6qo z=1xw!qDvj^%P;X2i=jAFPT?4u|JJc&{pO+Y{-zr&W7YJ|ni;e)>|pky+HXHc;SzcR zDgBkaUc7s;IqQC{i}$iZTe$<2IB{t5J=f6G@O!!Wo(d@F_3`_>{?ssz%AXsTxh!Yc z3kY!8`lP=U9ZR9HVlI}**5Z!NLZscQ$@E%NZaI4J>o|t|*%ojJ+8Dr8B~$I$C7Myk z$Yu@9EtlYumr?a%(adNA>`j3NRjjQEGyXD!5idEum&$1vj1*EvrrxlO;-E*Cy)G2Y zR)WevXU?un0(o#!UzuT*9W?o^yuhvbjLE3fe`3E9>SM+;X^g!?TPXNV|D`3SgW&CK z+qP!E#ClrA@pe95_EikvYZx+4auyyn5vsav+{Zy;3@6mB$9eQOwjJ23n$@mjN_2)n zJy3$rct@h(f-y@zx<5R+oV2(me$K;6zkK@LDXpqZ;%foK4b&&iR|t3QGBK_?uzdO& zUb`Da)Vp)FtXrc$E9(Bl9AX>O!0G4dz1u+2=jmcJ?75lLOv;BlSoE5?bIJHx)cb3+ z%kaDOmTpeD7ANJptCgQ3R!)V_wbQqJqfK*z!JOYuSWmkfbf7E3>0wMvy1l8@{E%LUjz*AW~ct|V0M)|P_Mj_+>7erbII{|#! zF$+E0uzSW`9s1y=CuS}cvV`Lo+bS6$Jo6&%gdrqL^pz?({|3JKB<~ZM`U#JSw$<8l zf}P*w#r?D~e*ffePmKG6Aeirl_3K1JTF_S*34X1|B2*^11doJovIL2FF2NmS-&#?> z6w!N>4s%TsAzu6bpdu8JU7QtnMYcGJ0QPqlWK85%-e18@;i$&`NTlG{{8N4lg~9)Yx1+^&^4p|=p4nNj25d%8BhGDxaXooXsl&ZzI&}v8WC5ByK zWx)pNH>_Mv^vR(Y8P+Oa`deAz+)dO-LVdl#AD=kwD3_A?T#St`qTu?>!&Ca%qS==N zc{qx6dyrtO+k!?CTy2RfD|nb&Fh@lrXAm@FfQcY(dJunP-`)7jIlqY;d( z0F`tW@`8~>>OojH1|E%-br&R*bNA$)*P^`+AI_V_3RFZCzcfDcF28LhY{yq3-oR#x ziFx8CiMTm$t90dpK*Q<&X5$OB7wAoWeBzU+EG2#ZvdHlqeW9qmoinSXA#>pgPnrQ&%}qg|v@4oex=7aQBOilW(Q zai?=dE9x*P&o+7lrI7IPiUnEio3}ZT7Vb<6P`g=0OMx2=aMsskAXOai<1)BIGN>F^ zCC|X#`Gx0T6TI~;AD`w_9*9;`DqPW2tdDyBfRJv!?~PATuZj}m68}K;tF*%zn>S-G zjf-VJ{l7(WG7ZgpMDvS(rng=y?dVFi&uG# zc_ijY7f05s9Wm4&3AcRs^Iq%SiH;~?G(GDQ9w}D8n{U)UpaYQGrmzo5mYg8a$w@2x zjdZ15Tsnq>WoePjy(@Bwm}<2SE2##%7_E|+=_o9r&sk^_icq2?Fc|IcPFU%a`<4|J?TOWK$KdE z2RKT5HW@!tk64zD<7Vl4dg&4z=a2bpQ!*#ZOwP=($wvf??A0YM4bwsGpKJuRN;~GS zHjRgJ0$w)s7#Z*Yel-|L|7~JGmwGx#_(IqwTKsJgC_3~_;u2ll*adYfE0@ET?I(Dr zBmj=4Rygol%7ph4o5&(qPV2u^s#r)S#LxsLI<&^nj{GE(aO;lPp3a$w{Ea0|w|&OE zVd&Rro0@-sCM+dQ>EC7AipyJZ(~JHk^49M?;i6IYzBKA+R=uX+`uCWBQkMiXJ}xHF_Af5F-sM@Vz4CKE3PK%D6(B>l);QXS2$eVUbkf&) zWn(ndy87-H_9I<=(PqxE6a?6KKeDzTKLi3izaQK`9zMEn!@ZX}NRA|4Z{L>$e|(%_ zjR-dHA{3BuCp6fl%jA#d4*JenB+A8u$G*Mh;|^ZN3iJ`LN1@AJnX8A<5es5b-+z`U z;Q9#i7r-3erVIfMaHtcBilWXS_>%wSht%D=ULP%P>A#E4PGTY@yBsxa16!44T+lZ5 ze8}YqnL@du(5#N8h=;o{cM~cUGH{8RJZTVDKJOa-yOxrRH?&k6B=_rW=~ZRpKZogG z^T^|Q!zb-Oqv=|tlW$#QAy$t1Ndz`9%e)X>&Dwqm z>xMF`w8An~mG}dj1}Ko*E5vmqq*zoM3pF7V((3d1zYR1dIJD83I`p5SID1pk)F|CI zn?~coqFDb;+Rq?r{I!qD=A1YUSu?MylULBuNCmNbV5PpXuUY!2-ffMu6o)w{QBOUvyj?uVPWV+9u>WmaPhOjh#hUV`)rW-GfaS;;3 zDS?wLHO@)9FOs&}_S}D+JFunbq^qgrV|y;ru+w}3BV}_>hKX5a|I{m{U@S;M@IGSy=umAhE1#>T8$o~X;LL6PYrg{wF)}=O}k{w%L<$rG_7Phqa zGVl-bCzM72#bW()R#znLxlWf?w?2zKgs19R91{356!F#j@3w#=XHs4x7&O#72-8Zm zv~+*r06MC0(v)Ul3Wy!;R?!soHi?F)8fp~0Y#S*pJbi}-#5CX36WtL0==1WwrdUfz zb(-zs8iF#^hyG-6^<5aYUN#4o71oe*MrBivGj{l> z|3_$stL|L60_&$-8%E>2^LP@tkQ!8@$a&?;lVxi8Y?Qwq8l@*x!BVoCg- zl0$E|Kg$tPnHf_njnV>9!v^0^Ipe4)v(b}~$9;ccFq^n=e}9B|nn!mPT3FG7RO`(* z%tc-HrcSdDEW4ryPIsMzn{FQxH$8cjxD>{)u@SwTJZ5;`wWORei#dIX0s-K>aP$K-YQ7K z{xsN+@e7D;vMN{q38p+Dg#uGcHZc?OXz2k}c{JoUdI;|UJ z!`Rs@)p<&fauIA(9HsI|B*3-=?+ynFB4!#~;fOb>!&Ia-nv_b&(Uy?lM4kpo;!90% zZh+)+r*2Mo&|;J1xtO>m*PH0N@*DOA@>KL#$#W{xG|)=YQg@dcYv~MHRyj7WrIi^y z4x1PToFik_XVW=yVH~5RM;R^&*A0HO>5kXvL>vzsJ=hcg3KT!v! zfdFmhxt=;m6RM@mC#kRwZPm6Fkx>IjOB$2DyRhBEr_>A&Dp(7c?75JEMfG&-~?Mi zZv&?JYP_TFkBLlanyU+zNZ_9pJ)%d6Y>=N{78_4j_V zMSdGeq8iYsANZax#Z9JJ-tNtWy}_K@anT_i5AuZ9pfL&-IoA9P*t4U}3+uL=RaM7P zLmQ^#*4)38U%G~>4IJsrLSB_nOW3$wi5rZWM{5GDIHtC{uytl-oy2rS?XPs1^^RQi zRQw{Ka~^E9f_4={mTPGEl*I<#5ZW|>Q(`)6HHuDDIiynNrFsr2j>sm8pUnUrVP8C^AcU^CObLTLX=T*GbZ=>sIMfF@#aA2{nk*& z`|x6l_>JG5CQ=qe48BWW)kw?S2bw8Jvni|Dn(~DT&EwP%z#~zpLFLFlXZDC^A_*85 zog{Z~Qb=Cjpo8jeBG^SB> zci(CTJksyw!t3pOFWb{>D$eMXHaGH0$u0GX;wH(F)b{msivCN;b_n$26EIRr8+Tb4 zhpO=*H$fwgX4HX&$qEuE`;TU9S0#KxJyo;OMHJ49?d?6AX0y%)N@_|-E0UkTue7dP zx*TJh8k_4D`nwIzs8sXT!yL0dHKPxq)SzBkiT`ngK{%T0+6C}mzMqM*uLD}KgX(qj z&lLkg+%9waDJ!#Ivi2aXU+sb3VSvnP7kPMELm3j+u;sJW^FwKa0?B(HbmV3`_n@J7 zyNw{tQBnAJ32gP!jA9bfA{vK1azrMb0qHHW)f3OoLJsgL-p$zUy6RYWTH7qYy?Uz! z&T35aTH$H??b+<_c+~*+l-~q@OOtUD1tOv$N8rj(sk>-|ncN~dJubhxSD?BLI&o^+ zz&i>;K$r0Pp5hBfo>wB8pINzd0~b9V0#0+ij7EVTpP@kc9AraYfFuz=1K1J~2$qhz z&0b*Z?qv4mI~uoDYEzDSAaA$)l|x6IJM?w_S-l(`E=+kL(!!~AbR868*uck~guVoi z{-_R#Pw&e=yb#iKYr%#^`P;u^pR(v+Y{U34KTSQIq4*7zu612>pfaBa$KtsoGoziO z@@D7!`%Kh+h#d>a_0Fqlt6?5Fr=AG zAG517bkgdCHYIXK6^aC$uYx=QlOmRarU6V$WK!@Dk#OYFiZjLAQoZtM?{(K&WU@*n z_U}v{D;p9+5Y$b*$w_M&!5`W{-&sOiS2?BVz>i%$j?TQi@H;KEX5bdWHDjwY5~D!uYc~G zq@`-ezIfnO5^L*XGi;_7zw4@pS+Z;hFqS&oQ)TLBzxCZY98s9K&MTqeGNpHYI;Ty? zdsv3HlKvFfWhN-{#Pr-wThPWJ*V_M(V%m$gh@B0H&>;Z;X*w)i65_=HeyY8UCzXJJ zaaYSsB+=dKSSiWM&=*nC-E9>9b9#X!{0zr|Rf=>@0~F693RqR!54l#}6C}bHW4_9V zwwM@UrR;4MSV!+rf-)c+p}3%S>zeIJl751mvYD+VFd<^q>T7Ai_V3e8Aq97P0@M(@vc_0jp;uCnVb&A;_eqB2ZOvx9%*um!$1VR>+WXM%fviotQ8b#lJ( z-*i45r7x)`VYZayW*c!EDIV{+1oKweeC{$I*A?FzLUW-K3V?Qft4Q;V*KyhsOfmJ+ z+4uZamrGLoVa6-L>cXxcniQrPg-(omZWX&mdw^h)Y?N>;pOD$2&0i4fLFx5t0^xtXAtKid13a}h-P)dMW12QGF=g7N2aKsogF-?UO~b7p zDM1GQDDOsy1TGZJOfd`ej*4^YlzLs)T+5~~>w&WL-bq19w?5#VY>J3XxrViv`#NXU z%)pzJH^L|ckbMzso;;Ux%1@s?3m|YDz||@)?mXVeS)RN$2LBQWLqXv+zUFMLK&VGp zj){cUDb(<*Hi45$5CzG7K%4ZNxf*H;0C~Stn1`Pu_;;b8R9Lz#V~87TmFekyKslc2 z4o8k)!R*U&Rj_A@k*+-OCEYJVk>R3%X@&3ow_Vev)1!A?gq?a0L(9aG;z1Q7moN#} zm zOpt%Rej^X(UHOcw((I+;Fs6Qtynpr9VY-gN#nU!vKLM=TL{*2*OlS^Y2`x+eT@q)( z>cRF1&w{$Pa3uy6Y1g+@k+_YM^Zb`^$J#SP{b;j+k5)gNVWseEu|4w*dLr0PsqI|| z_WJhsic1JgxTeC&&368{P6K4_@0@O#$8`9EBp=2K8@4OjfAbi`?zs|}#AsQ~lbEuc z7YfCi)g*zw1MyWfGM#Y|(R2A(c%^TA-C_V^DPcxEjPzpdLdo7>d%mBV2uACVxd(%> zvWmBdDMPDW_c5L`dSf`&T!jMOk-q%6BvZo2NDwr_MfdECTOLQc@D+@_anQ))tO;C; zB7uH}e~TBN_Dy!_#S2Dwp|EMMd#R=E9)st$43xf!q2l&9XpsZyB=_QpV7b? zf}$N7^^GS4n7@^}(f-{$@wjd^DgQ&+Idq8rQ)?s5uxk%?jj#_^vfpN!R=;M1SHsNu&5R21A*JaYqN z`xTg0g3o02q7c&g-v6E*@Dd9!a(?>G0-AvP-W0?C zM#nAtFBVD@K`$o^a7cP6aRUf z2sf7(b0th+b8DXQ#K#3(t{jU(Td`e-(kKc0~v&CfxJu1_y1%k;8W_ zy$tLn+wBa@N$F{^T6D>g8c$+Rz&(0A*iB;+cwEt0EBs_(s`|%UX6GhI2?6b0&3q z@^6>M2SOx`e>tfrr3S@R&=MTixT&@VqMMo(iqpeibyW>Qs=1wkl}|DnAyhh%EQXf9^-|8V%e-dMCO*mkuKmD4 zlGH(|*@%#1if4H~q@`Fz4_yYCQrvqbU93b7%xes?hsOSe84_~3ysl1KuL^xV@2KoY zj(0p-a{wW_fNA!dU-H*hF7?{gOMhzV_F10C?=G__`O^$9P^^cK2=jpD z{-&D_1Kd8d$#z^HBd+U^hEa!pG6!twN_Vx$yR>D8<9e0`uFFu*a_nmP^<1+jFd^?< z0G_1Be(SVRTjyc%p0bbh=rYHC+%T}#J<25> zfNY@9%`6h^4}fxI7{l?)%nK+M0I~0JKIfCi>Rqs>YhC~Dxt#1%)SCRMkNq<`@2(`P z2<4IfP5>83?%Ewc+!wP!QtpE@E%3F$rj^GC?4=F-#2xt}$%ITMZI=+VD1!qBz4%;` zw&0g9G$o>o+D8_Sm*2Gf8o|}kL8pZpwIA>5keHEZh5e!vevVv_)|PC@Q7f9%1+jnY8~8)5?axKPkQ`gDedAiV)x&xYKp zadjj?75%wmAL$U#G$}ETa)TY@c4$R3h4~Z&uTV*A#(Kx5W7Ae050Vu+F;y_6xr-1e z=yA{?iq$sfe&#_?|JeC%RkZUN*KkARl?=wEitbv1@2t719_+s7H>~h8a)siFjFjN9 zsfvM%zG=e!z=*%)P&^E?OPBPDKSdjicXB0*xgEShUctRsu&MEeUCHS|gP_JiAUr*B zYC|JXypXt=@>-;(FW zUty5@c|H&XY~HK4U7;LtzVqrr^>`JoA0fx54%Q`%GqOAXIn|#X%~8N4@)a|B8zSK} z6FNd>EKksZ0C$g~%NEfb45eywo?>nyO}oT(%UEjUx$!B@kurXHDz2gj3wr&-Raz;2 zUHV5rw3Ub@FLygSY*njEvhYuW;q#MjPbb~EvM4j`lqV4or+XF^AcHTCH5Pj^*bOx1q(^OMTrY*T_fMg)x|k0YSLYHA*QR4tHd% zH;pBKvY-*}8QM`<)I7)a=SdEH8A_L1I(jHux_Y!Sceyk27d=)8iE-LLH}U~|ux{QS zjx|4u`3g*iHw~YsZYx{>q4!I@J%G;64}#ym)z`atj$* z+!Q!G*}0RQpx_Sfcg#&u-lGZ4AupgqT=!KIL=JFk7zkbUi2#CqR1dI{a+W1elVDN{ zO~oUh8@ezk9YWi>hb14X1EqmJMXgteK!IgE91Fv^`-%dMkyvM`&H#&C>#fS-hmqU0 zJ|KFci^883`d9D$dedBm>nfnn7`3A}eifd-?6rHcz&XR`FTQ}WutS|EH1bd6n(w({ z=hkj$a9{3JiNzMd>DP(m68~JQ1m6bZwVxgF5^n>d0Yz^r}GOu<{Y6o)~%dQ$knuHX+Lt}8AotzBHU>L=t28$QH)=^%io zX_^lRX$zh1dAHANRu>gwKu8TiKfKW`d&l|vNKwthb)0~^~6Cndgy&o8}(%cd$g7f!zU%R z@wzoZllNPQ?c1n*so*t1v9d*3XBs+kKluL_*tJb`fNsYJ0PxoY0Fe04fn7%v2bX`; zwzY?Vla-0Fg3CYJ`yapkfAHOFZJQ))k;I?fzCvpvSJ5V{4b!xpC`M>AY;3ar^?$ZY z?9h14%S7e&71GX5vDNE_zVC;L>C4*HX$-H|eco*(!06)I%Ia!wAEv6ND-VlDeVKX{ zgO}c#8MzwRm`4?c81|V>(>m4NI?1m4s5L&Ex~zXq@Uz*KQ z_Ih)n{0gQY2gBJk^+DxTG*g?YnvD)q8}p~tlvcLZS|8j|)1*GKz|GBvrN3W`rZU&& z(^YdGo{!0=?0N4ZM}P5S`Q8R^OW#dBd10?z{|3>P#^f2sQrb|hSLn%FU_Xs*uC-*P zxo)n{v`%AlpP-Uw85*b7!p)FO@xJwEXX#vH7xvrHEG*Kjw!$GB;n83dJ#05`spOyw z!`+jY&0I~B^6+o5_*x)AjqUI5D(@!uYA(p{P{=$x=CF$mRCiaYj;iHl!t;(ZW$?|q z*gcF*>;z%X(7~6sdK-?cU(qm@F?g708#rZ-Re#eFSEdKlGCpM&QC|FebEYq|u=;K~ zD6ICz;k5`v`8}2Q6DIvj20r}i7(Bgt+g&?gY5<+ zuuP+Kii*Q?SLK!(+urL^U`tck!xSf?HvMBr4yIlf+qqrcwUgcrd+%=Tjvzh{-pnZG z-1HQOLP!qvl$G3rg|P*RBw5(*bS`hZ`_ssgovf*8hMjiDn1$_w$aT;}1a69*bg%X% zC}R@FU0|`3T{t9$G&XF2tWK-WD|uMJ4gqgc2W?Kzum^s~v`Xkt?Q3r%iC+FovTJX_ zQOR$DZWaaZ^xg!yW(vdn_9aFi83^JbtJh0Nz=w>&~tMm(3-8&4s?Z~1~qVZlk zK(3i&r6&Ap9QfRv#Uy<=P$u}|LKdKB<(-*EX{i7U{SMOD6$*n_dFV0Mj?ym!CXp++Mtp{mMSh z==4V0mlNy&IZ5rqTAfein62PTS*wbyt|i)uIm=MQEL@w2-q4>qoGr))%>g7Ak<_)S zR2c@1QZVd1owl+K<7Mjd5J0M+I925|@lhRj(jaMvYkFGfh)KmK+TUclu;0DOY#Of% z9fMk)fLA2rpR+3(mXVDNcp00=nTY!XsOvea2Vwyr;$get9$x$Y3J!TsA*;B-!kFXM8_v+oSCW=+NT`p!m>kZ-%z}sdzDV3~uDr z-jHk&1Dfy1*$m?!(TftFk1H%ztk<7!O&vm>D5@5r?WFr4q19QAXyQ_o-^SM8wAB|9 zIA1+PFF7|a-sl5{dj|DxPNZ)c!Q8*Ac#(r=B&{+iK~`|@YAwF-PKUwo>tFXnz^9A9 z)3DjtiQa#(?$d?5@@JdYOdRsDx2k>a(fBe?KuvVm-zIkfaEuQ9Q6H>|c3~QP(bvTi z-cC?VpQtlq{+b+o$BcDJO@C$v>G7O@=%u!me{cCJyO|yX56p=b? zF+Kflgtp@>%L*dWa29{PCHmbx_1|4l&_Ne6i2LQgdXf{7wb&N+_KZ?8qT8MG{TZvV z$dtqrRLqp*YI{Ib^SomfQdFhbFURFvW*7P83BAb=bO6X?oT&6*vw@Cb6bODdoB{PVSUA_qEaF)lsO6P-d{_fq{1 zB+#e5B^fjXn6K^bM2BG>1hPGF3}=@0GtqG9=X&$Za%E zc`v6wsM6W(IX|-56_R6I2S9R}kO(FI#Lbf5K2T z64+ZeF)X3aF`MZ*_aRe>uQYwJ5;&GjL3~8?3{^qm|IdxEj+n6w@Jz^eOa(_+k5IQE z0&m27SzltnF*JBmHA#$OaAe8M1lK$S%bA9|kdx$7X2)KBmVd`jClfn_4x@w&OyAuh z)7o1gW)~;3qq=?_iiW6^n-**A)I#~=_;k+}Hu6%c7AjOfKphg5zVz`*rO0I_+n4y?eUO&Ix3l5jpoS zlhydi;r*eplU0Pa*-Z%|uJv~P)6BI46bTeWxC4yF{8jQ?EXMM+t#5a{K>xUT0{T8` zqD8AuE^PlpH3gv6cOgI=uD9#Aa9l@7(Mq$!)*g>LH{Locssn~3A4H72o@{(pRp2yD zC*J*(uVJemYba2Dyot)fl5QbFm3do6Bi#{ycE-2ZjL^D+SN z*|=>Z{y>c=NQZi`W_yeXobU%Q;!<<{GJw3`o5lA)DrZYH zHPyHWbCI#!vwETl0=SrtHFZ3s6?Joj%ivC3RTP1ZH4AM8Ig6fTzyC3#5pb)Fa=Bcf zr2THe_B0hzwq3D7&Z)&Zk=>m6u+}(O-gwpE>KLg2c|^(OqGPi>WB@?}p`y6vk18a` zeqWV&6kG|{i%Fcj$6b&&H5F%v$J6It7HNlBp%+l-m4~)gi1$WE`Y`QNXs1@#NvKpa zPUbRgGJF1{>iW%*0cyN)VlpbKS+YE*t{L=EB@9YJ!}^^BNc%E?6Lsd((}-If#;~YG zd~jne!EfBpTUgg?J<<3586SXKP_G0pE~u)LC!uapxec5f!AWh}-|zmws+Lry435Jx zxD@U_>uEQ*5(d-VFt=M@W8FV}bt3l{r^Ex{w$V$Af#Ka)D%Gi;jna*s+svOe{w%qVX_|UEG;|Lz5E19mo9Tj7MZ( z-X8I5nf5PhLx_b{`nDJ;t9zV#VbzwKA3sBoPoj=Q)3nuBR00Vp}@lZEh?K0Ajuc*|ytS;l{s zxg?RTSJn{rB+!v)_r1aLd~CP^ewOWZ5#>GAW|biTxy@4qv%MFdG=%0rBve_dS(r1e z>wVN)D%Qg-L`~iLDVV)APa3%;Y{Bxw6Mv>E(6H;OMXr7Z5q%(V2o*f|MBIQjSNQpo zw87oAU&yR;nM!h*3ohOwOR8zl)?#s=w~+@NiPop2M_j?UWyv%MWz(;+72)o=MW1P= zdPOsIkSwOy@(kGvJn+8Pn(w!k5)WS;Eo&j5K#YKlGCT{7yP9R5e@Mo(=B~jxG?2(S zhZ+)k3XS~LlETjS&nqhafGNOHo+Y0R_L*o&<_WTZ9sx6pX%tCdQ1K=dW|(G5x;_-|&9_ekO z_^Uy`KgFbnNzPj7(C9tte^OZM;&)1pG>v^}LHYRmDRt>VW5N=R30UCVt zc60utA^{!`dv9dw7|O`OCuzdb+~w}^bM8PARt*JdBjuTWLtUxnS$+l+U^~1q+c^@ z-Gm{MoCeM~tfda=H=cjmOqreq@$S@8f8bl!a6^EM0M=R`zYRr*Y?H5VLgGdqU zN{MJ?gN(N#Jo#E}5%jHip6PTY_oT!9YHZtNa~h5$(oDU`-QWGxx4KG~q`mI+Zzuiy zUah|o@4K3E3V36XzVmBbpQ3=)Qz3LdQ}-h z4%I%}$QfYklVGCmq3gTUTK2qP5cRFtI)X;AQ{f>kbm1K`e&%_c9s6cT9tliJWoEk zg#ToXql~7ZS8yh%lOIgmIcoprvwG-d{Uce!FcZet)?&ShbDY)Oc#de!Bl#fN>OdPngYViAp-?1n@CJJk8NL0Yu%iXvBh%4ZXlFi&6d=9Als-V5Vs`NX5#~ z?3@6G4?yBd3An~-@wXsBzYu>C3?Kt-oeBP4EcO5j#@TPPl{L@1${@#Z9P2h0++)A$ z!9X*HkC3`F5Td{jK!YROxn#rFBAW~%SMAf@rqJrprKRB%Wq4U5?@(>wj0P{qUDIU@ z5pwvE?tq37wND<50n$O<(kedkFy{rJ#$=7-ssgaBgai&iC~}WVc7I=4VMbsCo@@lr zfgB8|aaJ~uBRKGD7hWXj8T_e3w?;CgS>1h{W*p1V0wbY8TBw|lE03*bEEI>0;pXmz z6$(^g3JcFfC(8Cfbp;9)DUU&fq719Dku8ssXSsjG9An115AXSF!h(t|!!}-kBR+Q( zV$-|hIMv7oR*rt1p`MgQ!P=`#IF8jrvMdhz3#7ep@>bSC|8lq#)N@H1PHpvXnl=g! zHufn6(}{n`U;{@$tiM(1YnlygNH??Jv)(hlsGW)EsBHk1ist_#7!Cj^RiTHZMP+9i zVUy`HP@5WzRB&XZP_XMnH@ybTh+EtAz04J*Xle18G6O}f^Xb}hV~mBd)hJ}GPaF?k zEf{J!UD)ax<uc0TGS*7*I+i>w zY!unaqiOS{c)HNkZV(&xIVT*sNXdbQbY&VoYB6PX@NB)9V^7(*G&YNGV$GFK4L`a6 zS(E6_-a=oJJl&sV^L#Ed1*RWw95WL~@zh8N zpbwhNyF>|FbP%?lajL8~Ur^MGGu2>H;_E4IX55Hy4yr}Rxx8F#A{EhB$G%9PPTx7& zMl9OHWUEwxJ+KCDk%abjFv*@uJ-@^0uS**>T9u>`jhmjZL9MKXM>D+DTVo}edmu{5 z#KuH-QS6yUxj0&7-06UI9ey$u5HO3pULzRocX5(frRY1Wr>NJK&%&fqg?iGPeu z-=nLk+`h*BFuW;SfjEY8?icbhUq>*b`7ZfbJC#Ud&Z!~yY z_Bz^+@+2fexRIOa&%S`EaOwr^qXit6&}OV5|H8qIdqAiRy0L$$Pa03`j{)cu!rFXA z3IJmBFnb+uu0RvaV&xq_cJAC>CYXs(?TiG9L2=B)S{(YcehhjiZ0mkt9h?<#>9Z!E zz*bdHYQ*7xSnLg5m;8!QxoUti3#9(jVWTUrUDSe#b>9G70O|cWaXU@6nQzA}Q zv!Q{Hvw-F1*qA2eNYYr0;Vhyfez&8V`mST%0&ds=%z`+?tULVnry+r8_fe;BTNws> zPOEu;{-WA?X#`Dt+UN+^Z93zxNbp|{fy2Y}kH58b%)vT#@UNHkU9mcY03SLrn-K3l zo@m#uK1JN0=>mNH$EQwTq!|%s;nQlCk&8hY_S2BcHSY+I(0CMXs8KdrE>C9L?qu?L zn&xzogq@X$lZ@GUmQX`a(IUH9=^Og!a{DeBrp*X(rrxP2rjGX@v<>5@?}lh!Xmi=a zOf9XzQZ3j51g04d%A+$h{a}V~bUU((r4XP!i?*A%55g2Z@(mcN3jQ~98WmnD;BCc! zno{pP#2mGVxC$8}ut!)LMT9{na7KCE3Ya zo!YjlD{g0wLqVxSX9r&B;_2?FVT-ltylAi_`H_8KzMu_i=pF1eDZypUVU5taKh_i=*G)x&_in(ZLO%`8z zDc^mQQ}ZDEoaW}z%u+7|C2i2&k9%DMC&nj0i`hDuseE`WCImqV?-^cX3W$}Qn?xQ- zYyg*4N6ZC(ig%8Ry+S8saIqDX+@emei!Hs{s<;rMV{Jpv_G2a#r8f!Gph=|Jwe{;@ z`0f)pX>78OmyUfUICsE${32q;dkcdqC~&tFJ>tAa>Y_eOmFT7-+*uEaoKRpb_EggL zR5+!ggyJf_)|)!HH%FdOcPkbr54IRY zQHokS@hyB8TI7VA#81r)WbxYR_$=dYc0lS;;>=nC z?Sv%zYpN96=)ZC=namEIIQ%A=B&L0s#CtA*($PHBq7*SG^-uFDz|g7vqD9YR=L5Zt zp^#G8)?*l2aEqe;n`#WW-A#3X+Xq)1)Zp21(q9;<4usKOjFaefBEfF-uXwOGr4m4A zH~0)KA+z35R3!+9_=+ixRY-Z-3NG0{zrGt@X)fKBU<+EiCMT^&Yl`8YC8(w@47FYG z=}`w8&iK3;y#W&k@NsFM9JtplA{*@))eJywZsbVNWzFzkFX4lH-`{#yV^c0_10V5d_CpEYyPw!3tRn&E z#e^uW*ax{whjz1ongG_}LG1MQUDKQ3m%K#+M z)>pF#7h_!~Tg7LWD)Yd@YlVn*aW;(c+U@<%iNK4j(l=Wq_Sn9p<~@fy?8?cVFO3^z z{rVIQ6BLZ6HN-Q`3!V5OaDF9xE&hM{$t7q5kpvxy@C2#R4F}ElQa_7E1Cb=jb4nK+ zm&B%k9-wN?Wde2^VJu5Q8_dBSXTYf*iss2TbiY~yJvLzV;KPs;+f{U>RXa;o+`3}w zsJmbUxqU|ja`V**lMG=J*M$<>X^YhwZ+zVEX^wKBD!3|6WsqWoh7l4tI2L|L?bb-C z3NzzM`cjc$ZJzmLBA<8z8=`krTcsL%wi}7Bho~1$%D2e8L;+B z&?+E2|BYMpIL4+&ys@q^x=6VrGc$=ul{h2cL!io-tOZkt+u5_vCWr#U%{b{Clsa5l z7ADF!Gjrkr@OtP-1F9^~#?sJhYPv8$jHf1-!2u;sW9E1kcT>Tm$L*n?^1zARg+y79 zpc7Ir+UNWvy?@PEoSWB73!Ck?N&7s(-#~>(9Es(Bys&t-GYa$&%g^QoelisM6 z;|u%qEUh|j%D~~c)ahDLK(8q~VU>%Wp;x0&fEF96K#dxzV z`!FqjgNkhTM{kYD4~cr;9Xs|+O0nL9u?Dmd{fpPw)9Qmi5oCSC6|Z z-M#$UKQ$y?;b>7^XH91peKxig;${c{ZgOn5+5;rQhLu*|mdAZOL0IXlX_iImQK{2{ zhG12F{GG^wjbFWu0Rp|TtMw|W$IMFYwhIq}<_=y$ME#AR7v5zdgE1HZ@x z!UzR+_m0e%q?^OFnv3iz|1DUUda9AHqb!!t^u#Z~e{%u=|KINRPxJOa58Z#r39!-s zkIn7B5B)D?oTZoG@H`#>fS=)iZVO|h7cw_7a8@!mF>(Iiwy+r(z!TaP-)#FRpl5!V{pPa4tm&?u zxw*b>a~u$@E7;5ujU?P^nm*HGX_pi$CKatg`d(RhcU4K<>6gpB!EJU))JdQUD4<53 zFG9Ihdq5>0-@IQQDJUyAo4@pb;J80`lSrzTwUlzm{MZe|Vjiojm#Lq(?G#l(Wj{uf zkBBfc;<01soflLxax-UjaP4C)Ikjv!CLfi3=pGsvi2iFW9dY`=`_!h!xVaPpxt=VA+?is-eNmq8*ju{m8;pvvf#^ zrdM{%Jqe*qkyT;^=cKN=S3Ohta*BS;4!o=90QXGg*3NIfz6V^ zpH5KoK&qO1d=NZ`EO0NZwKGV23C89)v%3?&z@(v5UAUuBREfo|AS&#%EiU!cK5k5N z%LiVNTw2Xu4nFkPtQ%UQDubQ7Ib<~tz_>tk)O5d32YC5(HXWTXj?nT2VUh7W!wjFJ z3edF#LXk~;4f9|-6%&WJCAZ9&gD!oG=vH*FoxJLjoRJa=2g)cqvk;jUls*ExF?a%qo@<@M(H{Cj33*gKml-o(LD#2YU1XV@Rylb3p0C2=m` z2(5!E#=qJCeCpjgb&;zf#~)>xfY9qOOG0tK75(h7LO>&F?eSUQBS5}mwSJ{kjKVtK zr+o{A>kp6Dklj@h-lQC&y!d8Do68ScU%MAUyj}OF100CavWwhA8!235KP?@jO8LodZAKjGyVl0ztqJW=8tKR_ZFT1FxO*$T-F zIs@6_m91V+-t0pmQFG7CqmzF)1%yZ8u#Z|sfCpd$Ke-Ppz((h$H1K|7iNXjI`=J^$ z3i%@qs6<>{+H&%Qz`)J%U9~z1f57;?L!JPap@JN@2K0sEu5TtGAb<#sz)X6jK$oWY z_~MS`tdM>0KMeWd=W@#K0S>6)YHZAeEz@FWByONMnccslV$#>+J6;wGKexr znt{}zsaDxG`H{5Gse#V}EF|4^1-;hC_i+`OE$gQr2%>a#H+OUACw6zym1d%%UCu+{ zDMqe!2o8^yn43`$@OhrWj@LFs6kXQ`5tqg)j<|U_j-vp$e7OimVadlYWj$PMuiwV} z`(FLP9^8AphnCSFBnNfSkmnJUfs)>!0ty@b*~a|dy}g}J0rz3%(yRpfCw`}7eNzE~ zLj11Y`n?&Mk8?P5G|gLM_g_79X;!9cSp8XFnjly1e}lF7weD5re6#~Q(B>fBtF#8m z0T`pl<$GX!``|a#R3FI~Y{t`3vv#8^0#x+(3EZDN3Kl3XUBw9nqSNmKl>yO{4a9`L5*_&56ULgeF0*q-U;gUEI++7f54JwVzS%2g=0h+w+u-|DW7+hYqlwGfq zc;eNMoru!Yg9B{W&fo}Ywj~rp=a&%85i{~@2+ujGAatwwCirXyXuw800i>kMBwDN? z;4Geaxmo*WWx&9kDfK2hb<(h5$@m`&`b_=GZDaQ2IAZf#Cl+;y=g< z8kJy$rI0nLibb1E^t(j62jMUU`CU;dXvARScJsy6m|#hwuifu(9o{2?@^wFGyThB7h{Pt-X{^B*OYREUoy?nlB> zhB&MjL#{LMDs(;9xsdYTGIuU30M{tN52;O90z2=$x7(-q2_^CgcVuK0GMj!)`JhhE zJ9o`L1`w5OWQvg4pFl`ntr>|2NrS7$i`SNz4gf|n6o6r2ua(CFXRp28=o-+Vfa+&b zFScFwucl=5BeF!`OeeO$d|r{UZ)$V;dsh3ZD-~>I@9Ftv!mMpRn|9t3$ky!w%Oihh z#9ZYL>YwP8gt^Z;r0HBpol`h_EDlab;%>uQl_E-o64}Tt1R}JXrqb{t11^Co?+yAH ztg9Phi;I!4?-IQMBf*dzSWAOo8~qi9cPYaXZQFg|Fc**<|D)a!!NWHTz5PeA#%J{X z`(Cq%9V>pz&m7V`zGKf#P(Tv*H&|zE4wm+m))3V?yvQ3WlAaQf^xS<gg2D{_OofzMfSj?`98%s)yl0SXkovtYe7|%Y8s>+beJVFZ@e|mJeZjv`|VAQkbNM84=A$@FD9WrL_xp=82a8l zJdZbGv_kh|m$P0xP}ffb6PLK*W7(`lf*K+i3-yh8hLwTF9|NbUJ-?;!&7ZEMLSz7? zm>cS^1FsgG1>A;iJi3vL;%gUE`YB^)4C7&)D+{XVc4V)oU4{pjlwv=NuLNuV4nk8v zj9h|Og$)iI`RO{Xhpdp~8m~kwKEShi z!i~3R=OYVgL>xN`aUkkBVOUh=@*qyX9TB3UCmZ#{Ul20Z{r@Il$yhHiaDy}F}>-I4!C!pB$yh=Xm{?hCt8Bb>};QPAb#{($0QPuXa)g1&e_96 zoI^+643f1%f1h%gW_^6IRTKv$#uZ_`A^BTp4=#KG;s6%yaHw*Zw?!eZd4~Sywa#XW;%btI9j1o?;0@$N^@_YUQ z3vIH461>SDWe1QeaPKBa16X1a`_-dl8Z&*V2fA%}eW+a~6w7t)u%rb|{vB|JJiIT~ zR{u_V{qIwGfvAA$bBlPWKg|UlDvl77q%ih2O}qnYPklG!n&=ZI4_9S72YI1EZ<0Z% zSbaG`%&p%c9LWzJ%R6&+0x9AfFS0R8i;((IqNM{$P7ej zRGL0=6XK@Sxb0=>$^8rfH#zG56zUDvh2kWi!Kje+kLJp^#q(8Tt^fXkkaoI@Ag}0< z6-|!>!kCpAkwaFb!7AZZ4>GBkli7Go8yo z3D*-TsEd;GR`QA!#2EARM%3iH5N(M`_ax`&WEkcEd_!^Vh|{B#ru}52kT%bKP2RXR zILGcawvjFxLN&Rp*o@hB-9o@hWq z;010SFz>YqB3vMw!t#gLcm9V_gVw}8leA@<F(ZXQJR(ad`lAu`Ka7B*? zHHW`|1l@J}#85JT6bC6bP0uI=3gzNQN(_s2(wD(O@6AWY;a$k7qxZWI#ue<0PGc1# z3Yr$R;=q#CK8X3yL}$9xKsPr9dUOoXkPOr}6H6H_uft~?YCI~GS5^5&vR%SX^K791 zSi<;|PEcL~0vvjefdHCZzY&o{srjQ`kv~`rzY4GV$obG{2+W;|yPAp*t6)G4b|+-G z$l)!RBH`tQ{I#N_w1;=QG$bBE!FV;4Bjh2Okk|TD;vY4lI|j)nSVH{H^xO^g)U?3~0TvflfCXkh-a|d_cG4 z_LlXYq~((tjI6Ow;(QT*t~yTEm>$9Y56Shd(v=H*i+x6oERA@1q{jnMfprP7EZ>g86@u5%L~ijE$?0PqJ#3RsNfD;3z8~l z?+M9%iS;Nx#T9lePZ>dE>qKG0fK4K|A0YF7mjt|Z8f4?7zm>ht=C{ulke5?~MNKI% zLx_ruE3RCZ9apa@N8~a~02luVorK;{aQ@yb$0m^l9Q zw&nq}MR<}Yu6{YTD1Az)32`hA>=a}0<8;@sK(*f(=@~xTMkpf5G6(}sPS7f+8xHR1 z=pinzBtT|Uu20e#4Py6?d{KksNrSKk62(NdUiKBHEoB^&>I@|d>d?gr6-RHTaUCpc z>K4vx6}Wc&Bq=evNUioG+3eOgOZ_`cU2wQx7I>RJ7bxVe;%$^%WaveN26Nws=3ta_1w=fzkfO6>37iD($@_`b zn;&)<2#_0^%h?TS0t^@R=><|zMn60OHpSwl@4Mw%>SqdPYOgpaw`v^9RgnIER+UaA z5Hy)EaaV)w%Ji&!e+>}f!Z&zHyD*U#Su6V(M|NIy$zi4q&{5$G5Tu-zh+xd97#O3oypK#eJlHfiXvIj zayQu2L`~z?CWVWAeye3!2ZPf3Ub;;QtvBV{IM*jFj0rZQG2*cRKdEQ#4#_~ydTYKA ziUtWGaa%Ncee7DPCdM||juP>o5wO~19FwVO&J>Eu+ZEM7BwwlP19tTbC4b*xo`Wr= zcyN8-yp!x4XjXQ9HLK^7@}q&_2;N#1MXLqWT%qrW4v!rGOK#ORM6F zE6$G)L5>}|b0(!5moB8*g6;x>p`27f#$X3Fs~AU6T`7h{;FUVD287rL_lmn>G*|rD zQ_xG;Erl{6bhL&h`x3EMWtNBx>2kK!)qldee82`5>+@=K)jSia)O+hn|CSkOGn!~= z8|^V$7HAUnOe|%PO9Bl+p$|5rIHuVWq+PtV&AOYfWzQ2&?6Tp1GbcThls4d&hHwgzl~+2xPzlcjp%JGnYS%&@4?YGO8C+@FE!+s13Ur~8uP+%!~Uou>_ZL_Av)U?HX|3)-m6z^|u`Uh~!SR1c=sX#c#> zc2r4EQ*0ZZjqUtP@vKlE8SS6DfoP(5;UhJZzP;uu7<~mRUxNY_d4O zdU<9C$k3_j%>V#>4k)6ir`xBl8SdC&@wgA8`R%U5N_Ihq>}^R2G16KtTKEQr)MqHl zRnay=E{JilcDDFgY~|EDg{S_4SThbi0&5E6#AM8<)6XHT*{6*vHSE8Hp9i!2_r=}B ztO>(zv(zJ$ED3EC>-AD@{g|OccKSnD8luL|}cXR}wmTYG=jtVAT(xt5Mn{%xa%!fN~x>c7SN8VbQO-#X;0;RYMVpN;+lQ z-_9Y_uKUa}bCS!+N1^Qb>>#8+uw(}^F@USFLWE7ZjUAM{7%D~JYQI_8sfmh8USs1y z@viV)b)j%a3-8^9_RdaKs*%z+L2jFr|BteBXwQWSkZ6n>+qP}nwr$(CZR<^PW7{@w zY}@91%bDdY`ZshxT~+5OgAG$@>4$VfS3lSDf>~WUp46%VGfw&p+yj-qBg2h?4?+Dj zFX+E{uLsweG4Knf)Q&jUkwe99t3oE^%Mo5ZdF$bpL>-{P~PpyCsy|em9kyN4BeG=-9W9*pHtl^ zlpnrp({%e=(xKV+-JQW3l~`KD|7W1E^WMSX5gsRNmtrtVu4u^ag_H1(INLTt_Myhs zJe2FbL9`g>HzVeVV@1$5_VKvlpOdv1Iru&u_r%EC0HxqSZ<+;|AG->!tHeFqLa8QM z7&aL+j^gn$k$OVBwokts#{b77ccwpChxZCK1$olZVm*zAQHR`9E;0e+JxyQ^WPUbc z@QZ3IOL5y|qUxK%Y-9N5jNfaaVwlWq98IGINwkAt!pJOK?~ztjKLHthuQ=ZIaj}aa z=h|N+`v%n}Ec&s7=Zz=kMK|LHmYk>xj8t4K(O^K^R)5_Sgu?zSc$3=j805Fu z8|iZa^!gAxFqo6u$o~Btx)5q5&w~wIx%)?Tga$R`08tz^hYgQ^v2uMLoRbXkF(wzx zLug}afn8lyJg~6-sX(!R?t3AzAMf4`^K@hUcy+lij&g1CimFwHQFvYLju+P zm1~1~+DKH{0kY2vW_orv*0gu>fAZH*a6|qigebnwe3!p>-YoB$4*(=P7e0_|-QlZX zLQhmB(N4+c1^2?&($-}Ta<2PibW7C4^^Wi_nR3cDUvA?EO5L_DvsyndOOar!r1$q8T5RQ zbhw(4$CV$gM!CbXMxO!SmWX?(3+G)@MVSqrNU5bhqF6;m%9};*JUtGEWxLDArf_re z#*h+Dol%rF?Gt!~eE}{STJI4$0B_B6JJI@Oe_^TIH!0^5kZ-?6!*zsA?#gxI$37GH ze)mnh(oiJUCIB3t9_T9JhjL(*8kWR|o#MbJ{0VSN22Y6a`VLOYI#T{46lKE=afehV zPxxxOeZwf*jpMrw+?uTBu8Yq+pE_f?D=zp_WkV|wd2OdS94-JeuqJ~+X~EpvuWfTS z$00%V1!uKbB16z`L4_h)eH@gA+{~P82J6&zd6R$PZkHR@Kz>?nWlt!CECx(qXm!Up zr3Nyt;J>ezLYM@fJQRfDM$V6k7IEck0zU^H&eUrUY$TPLF!ngu>rqzWs%5svd+-CH zUXQtjaK)h({70}iNQ&OUON+YSaNkx7(q z0RfMP|1>jw-hE))HcG5|r#2QII5Skaf{@rIxb|YoYQzGgGite8GQX!#D2d3E&HMCt{n=t6$M)Q^lh6lDWk9KKNJT?>Tz4`dWMhKxV9Y_Ay z1?{8osGkymg~U(4*KB5l8uxrzp4(Gi^TNMD^rP~&pvi*?nrUl%sOxh@UFBLzU|uUr zS5y}_tRn2oZN-LWzQz$@?L`4OBG79Dt-buj0W~?#SX}vbW%FQ>_7-jG?_Ga40lR`$ zxAQ|93k`skC`OyP_ZPZ4jp7TwltxDa7ekJ+%O_F?MwwSgVY%l--0&crM%~ zDtDSiNcUD2da%oJ-+ggC{Wy%YUA4aK;N^>9D?`@4^M{Y-Q_lvw-Z`<$z5q*Uzc zuHRbebXez+^W6i2kl+YrLm7lD?q#L#$N6*qCV~g8?czekHhiff2$7{4hLoQ>#`-9% z5`?^aLXouwPdr9}?9+^|{uJA{TE&zh*e#~ID1YfXTDZB-BcCXRO`tZyE0EcZ2>KaTyajMWFT{;Bm)%-Yq)7d}E46y7<;h10&+K`pYTjDvG0jvb#{kQvsZOajJ1xC3f#v6a zemAu~Ih0E| z`+havL@ym4S{hb8WJBnwpYdEqx0V!HSf$lfPW-poQd0SaMqucp)G%wyDK*PTr&DOx zUlK$g35Il9O2um-R1x6&moBf+S9e+0)LeT4{+v7ygoDlb?5{L0jn=8U#nt&AsL>{Q^_T6oW5SjRHJBTJ+_lKLuz<6X`(Me&U%#Za?-b_f#vV8y>QcZ=xWtP{bb1koS!9t%biVN7-(8>B|U-XJ8wRk>Fc2t zp84{hLf1uK8jr{wpS!KQZu%a3<7AF;$`$m^t-5Z=r;tuHifWTP%lu}ScCJWe%a^Ns z1lZga*J_-5rD)J8EqOnQ^tMxX9zI#;`lsxCau*@kktu}K)m}O$^-^hb14X{(IYOlqHJFP|*+ZEt zT^L5$;46!r`|90k$9MKfCLq38{@(3N)Bh9m1E1I?J7_+Lz^A|*|1AT4u0_FwwHbO8 zYjH0{gJC!Sw&(a16{)08L8fB`gU#Tgkk{CVs>T*3TE!kiu>`jSdKOKu7^f2<=Lt}n zPYhqVY%+!8OFT_%^`VZ`*!!1uKIZ%v&Trn*4t?m=I|mjhN)YItWfR5=!6kOMQKN z^D}hsZp94U{qmGWxOe}p5HB}(=U+7Pe!*LU>KO=G#v#PNV5|$!(qJD;T#YcUK73cx z%X=CDhC;-kwOL#zDefzB5%LisSh$%^Kb{B&WYGQrAR!yLKg|{#W9K3@1ptJPbLDa7 zDz7zF%SE>7U2@5YIgmr6{5~EfBRYm!CY-;imHyL*05H6dhL_sSH~&(38lbb3$p1`- z@+Rv=$*Ahdi*Ug2Z8#8BWN4`EB!Tn?qwYRj$Lj|mAbHZoWQM{VzDdTgn{SQBLaQ6d z`!HPW6A}xQ^lC;DBjt$77|YYn7MePKaID7qk8wW4QmUl6kMd z19za@OyV+`3%B^HZhG9F1g^Vi28h{-o+8Qtj?KUJMiC2MxeFl1?(P<^@H#$8Rv$?9 z6ZX|OUALb{Sr)_=QE(fLdS4woo=QCrZpEf>_099l7vSTi*4Nal9`Ke!hE+JXHI`TM z*heHp!>Y0s(&ou8lWMpBBI=<)wvk4WdTDjvI@TXy?Pl}%mmCXthJKCH<8uE>v5WdD z`by^O*^2oYnmGo`4IZ!WCdRT!;A5inZ!V(d3yzZBxBuk{KvON=^x$Zb?da!;;(28T zmpnq0V(=KGJ(=n(U9rMvNkegznq5SqQ|MV=9$r9R>25{CM}#A*vqW-3D?B+!U3JG= z%(q@*mCz#A?@(WjP*ESzL^Xo%*kB-BW`+7Ga<6z zb&!H;A9PD%6fc9L>0EU-`3y|%X($rsJ7^?HvDR(~Z}b^oBJM}}i7F`Pr{F>@TDE*$ zA{K#Ws*s+zgv5SF2^bx5}=n?N`H+pXH{#F*Cz&~&Lwu#eODp|30`uD3} zb5_y8{RXraX=~E8qu(+Z1|ySA3uZ+F>s9haxuF)lwbwY#H_Te9g6kF|6}XjtcO_3(+98 zCTq!D2tpi=%Aptw!#`I^of)_nvhv%UV#z)a->5Qx#k5tFQ}Z#n3kuhB5#>KFs*mJ8 zclImR zcdEfW@1qw*tTQa|bd>INfauXhT-@6?>5Tq@+an*-gl#UpWJrO>aCKyWDZ*&Ftf>jyDo{jRJQSB}-1=dSeqDE(9o35|g$`52< z`xW`j>^GZVt6jmWNiw%uS!X_}JB}ms=jR4tZUtb0ELA zt*VyvC-;mE#~O?rmyu*sk|q9=hnmP7%8Qo>Zhu$_r_|;Kk^4K@YDv^9)?RHF6%M6# z4O|o3aDy7V)hdQN0VeUIBFAm^A;c!KG|FzN|0VD0oM{juienM^fvHfPVaj}a11*-H zoSlxHPPbkX{F!WCa!m>N<9Fof8~Aunp=2&KX1e=_P31cV4@t!_JEQyRi?~|7l!2Wr zPwyT0>ZH-)4Nzl(#l?=_&U z@cm?2enML|8^4?(2B#c|No}F_7{<+56qlGn*qU&u856UqE`Eka0H>iz);lYM#^-#_ z7$ozQSn51hhM~W=D)P*1%O0Q-dm&MrWwV0KUGm~9*4#$#Ja4A5Wfb!^@-hjP#slUR z-o1%%8Qe06Hl;5%u{-oWyt^=u?cGTYmvoiF?y)%H(f(i)|#s^ZWL0ImA22vMf1ezG5Vfmxhf0;{n5aNfpKU{ z?3TkWyj1qxv!!MS;!>cmH-KYNw>(3`oMqcIBFikH8Z zQ<@K@n94#qC?Ola%9CYP`N?)))}9>{k!b!~9qV}lu*GtY2e8j%Y|Pf(8+%| zvWqj`XNd!0f&1R#=@KjNm_7v`A#bNP0Y~7gt@n$LojDgHHx?Tb%4LMY;U@Cc3Y$&h z9@N!CM3tS!P<*EzJ3gBx*e1opIZo1KiHm1l_f0|naaJYe-AtP>YA_W00oEpTbe zUC!fzBrv65x((dY+9FABqgy?WzWy2U(YLUQW;c%`Gi`00YtYsOwGHHHX6#MrDZ5Yj zF+)B74&dbEG;VL7%v5Vn01-FBllsp?e~i&Y<>(dIeM0JatY=d@w7}Bxk+W|>*G7ti zqot0_$5$Ess^{IJrr?*upl;ho<-SP&85=Vtb1=ZkqR{&mJnkg+S=#vzQ{(gdoG>M* z%G)rGi!#W2zvK|MOrEhG3XC8hk>}j%Ia1nPljRLz@z6wtYmKDz9`$DJZ;_1xHnpF| zp2OJK&VNFmVOWr2c`+7V}K}2%}x~ z^!SYD^mHNx>7VR-I&AmN$(~{7stQK>7a(F#RWNq`?DOAX>|_N*laf~~37kk~pB6Ig z&n3%sx16Q_KFaPipLBV%CK;fRi_p3^^))=KApUiAJlc=qYXxyA3=&5WVn8-Cmt z-~DcEYA*zcE*GNZE=*fcIdB9}<-k4mPDT)$wQhzV8S~#AA47VpQZW<@6i3IB%}(cb zpF`p4qBftH$+Z7@mq#VrKYK&AmrXnB^udvr+?{kt5PJB@X zDUMyJ;84>TFQAxQK0i2W0Dd_J*d6Y z#5gjJ75+0^7bsRz@|Y)|-4qkDX3ehfaP=LNdhpZo`mFo=>Dn5f5XCQ;FdW-9-Dx)R36yq932@1snuDThKY zR>R&7@!r0?spu1j?ZoQ=3%_m{5S5POWL_cDAMQC;prCbJ>ZvfrQI0fb%|;A1Vj0*4 z&yLqRlFK^S&+ftT>#`jCt^=*kby4HO>0eH#Gh$0a1GniC+2qi;i2kCaZ z(813JcD{eAmQFto!Nfr8&fW z(3AQ>&KaU_tNIsfr*=hA&`-VctMJBM!1>Gl^<351`7FYfXVu0J_?__#;@^U!BZjG+ zm9G2ESL)l*uW-hyBUI0^gFJ~Iu+G5c*U)pD%EK1KiP|^Sg39$1HT5l*%f*3PjD1Oa zADu+EMQkvBmA6b-877XDOK{?Jcxq2ae4TVhj#S~a23#C-+@5LDzLo3^7R?<4k=7s= zIHvS-Qvjoz8=Yiguv1M(r7>cK4Jr&SCQ3r!E`Z?}X(5>ee%gbrW)ig*rrX78)JJ9(~u$mAK*~KVP@(#eg zWcfq=GjM+f#&4p)Aup_H6sTe1IyL?L<;t~a`Y z8D1v3Q0#i7b&mEk5RvUZy&0RvZk635TbFy<#a`*H|Dq0Y>6QtQF|`gV#i(w)Mv6p9 z=C=kXQYozOf;@OFOm2UB5LcZjU?=NBL=5d(KGSxcb|K|@r*#BV_ z^D0-9F~rZXGDtz3uEg|`anO%8VTK~MV2~La1*>jQ%6|M@|B_2OW#^ESdmX}_mFpc2 zPLu6=u%0N=+Jx(7!T_h!Myd^r`3zk16#fM?b&aBx6lW?IUgQ0e*Qr{Am@=5A(2Jw^>K9jx$TNIqc_<|nC zjjX~oi>>}PV=NCWPpxu8$8#zW%XUI!!O};;?W_(z2$BfqTZj&LVR96vRLSq zXc{fKfwfu5$5FZW zCu1^*0x8D&wZlmYzx^7B5DHsBYXL2#F4C*7|U~Iuva&(aP#K}7(pRt8<#i=;)`iT3fc>Z>K;Yk=|-_d+K zZ{-aN?^GE&ck*|=VRO0|!uoUchj4CVa4$=!{17YSy2Uf3k(Oh{kifWKFY@$oQS>GT z;03~NCu>Bc)U`P$YnA4fMORw zPVtGM+M*4%nyKXF=o^`v zXt%)_ zYa!&c<93#s_d&n@2}|@PLAo|z6Wh3@>g|utTjCPYB$TXd3$(gm!OV`kC^UCRW8e_r zQ#|7xlr9pFMb&-=#3&*wFX=%saGmHJH^fyg%&s8wFe+l01khHP%n_&R84{$8E?NLj zw?1vTWiM@F{d^PkI+=q9ssV~KH}%27zIrUXtH%+J(V!JXQDyhIrYILuR*AhkGVZiG zX;-INBd=5>T|l#;hB=oQ)w$MJ{x~%4?vkTbTdVK-9pF!wd+U!VSKFI*{L(*a<{V7?@?qkcnEw|GA2wZzpk4tAtD0&urH4p^p(F0KSm=Z z2W?&huBNMFZ8Mo(+1kXvu#$j0$ET7Z z>&IpjsKYs5^bNM!dCAib=Qn%L<4E4q@_Fpjr^xqrsK3JPR@b5GsRCx(lUsKYbRwq+ z_FKg@ctQ^h+;ocMw^u0EEyI(csED!4D2yMFr!C`8hE=YNu4Vqmu2+Roum z?#NaQ9mG;mT-T(Iu?}-`^3yxDer~+YnKRQL+r{eWUOqZc2AVB{v`L|qu*6nJ6+DB# z!GsmKr8F}Wv|7xF5P+2yQIqtBK&QJc-*gh)W7-%S@eI!HB@?GE z+!#@jImwgxP)qJtemFntq80Y^$Lvqc^{9G>cph0jgfm-ScSy$%mhG?vkKKv0|EhT< zb6$@YDNinV_ve+q)HLjC^my_gdu{A_9_B1CESYvacTvN(U$@0;%_2X{`^`VF@3_eY zWVlSXUqp@_=*VZvV%YUl8{czuyeJ3b(z1ZZ#lIcG>O72pdcXDLIV1Qw@KAOoa97#y zOW27dIRd(pNFr0Cb>h>8-E;M(=a33sce@M@BN^h(3k3jv4{zBS4^*KaD+!0l@G>3u zi10CJ0X=GT(}0jnM0hHzAhsY++GK*O?~E3@kU!>ERHk|&YThVC2cSy{ozS2Py~rDw zzE|V$<;Y_jH++7-=K*nNvsvTZZxBo?_+AN!3W~vsNMeS&iVPA0=@OzXXaVOxOAf@h zFWGk`o{U84k1ZpOxCB*C^;QZA2`DJM*YOX{(m3)*`&Uw*GGj#$w6Cc#k_B-S3RtG$ zBJY0>O6O>Ms($@dZ1*1YuMtbyFhVMgnIs;bp{P=vg!kE{7Pe`Le!H}sF%J_t!E#`A zvSiB~&HtR^Np<1n9G#(tWc(wZNyRa0NgB$T(jARe8KAfF3a*nvYU+}o z0)d=DOJdQbnbF)qsFv65kdb)CD?pHG@9jWP}=8-H`r7jq0 zC45J5Wv)&57@O56j&l76d0LLM+W5KIVy&dKe<2c@!j zY;5rH5oX`O%*QwO&bC4D0Ejaay8tnxZI-%&9$oUwy33fv2nL;0(C?@^vE#4`ipc?} z!+3@809EpeYB$ELw{0V3S-6cxg?tSItKtm<8MLwAJQpBj*}&p1#e2Vr7v}_b&ZhN` z!+OU0p2k9*6+r%c(8>Ctt82^KXyIW%w*P6-JuB2k&N{S$njn7^Fcv>K^@ zE!?zFc01{nNh29oh4<-$f_uaG7!t&3`Mn+5oQ>n4iL<{l$`YG0hWM@+|mXuYjYw8*IJ{glvHBH^ZZM;KXXn#vBSjs+*7^E!;Y z7PG-N+%7=y@aN(x!BL<5#E&d245T83RhAUbSv0Hw&QYa-utUXcGnLc*>=2^EQSO9{g(EBbFIHOjX_Dy{gdU+(t`NE(~p z8pY0E`Kcv16!U%vF2ln`6Xdh7Xil*!?yh9Ef38O=&v!P7^+kW1zvA!0qNpl$|NTNN<+DQnMe<-a@Pf<6VyU;MvsS9l>dZ8t`L$f*_rgmTb>< z4CppC?Mqh?XV6w5vqEBw88(&|!+TbZi=|~FWk)G&MXnf}lmQBISSz)Y+o z&H2WXCZa}&8!duy#PC^%sU3W6*x=a^g+}|r%M%Y|{+`8$Li3YB|Eidc@awIq43A+Q-z0tjE9) z1?jBaYc+hv#T;LN!WT+G@6tlvObNmmUw&nN{2yIBW`naHL5#_(YqO9j zpISJj{DHXWc|{`ts0ad$Y53S5fp%X*hXmiU*gf$LigcQHj)&sK*H{+2*-lPM6vi+F zrV@TStPkj{6Szv#SC0E6<3`fHuZc%9%uhgUp0xC!dV_{qGXW1H7>=ebxfl0XNvwj7 zTt8VN@u)xp|6Zbm9A@__KYFX(*0K zDYrA3-PF)UZqj+@Suc-G732$OD1F2Zs7o?bXF3`>Ew`9)Pnc)HWDM5P23#8se4*}~ zpg*KPBP)orqLD;V2(CsVNC_ffY$Aius7(7PVAY49rW1*1GG?L8vW^&lI=jwE{=-mg*bi40x6E{@t-lrC|9gBKhbd z6V&^CY{cB|}x>zwGy-jey!$PqX1?jLg z5d|u`IBmtVnr1vE0ZW~EE&`nmwwne{9*>*F6%}P*qAugNi0vrPhiWMwuw{Us$$_a9zG>BVt|O;O0r3K*OMGBjQ8^@}LsT&cY{&2?sf2ZV5_h?pZx z{SV=X8KZ)>h}_@7E_-UlFt_~dW2q{@0Hw9W5?NBA!%Q9edCJK5+6!Xkk<`n7e_*bA zvRw#s1aT{(@bI?KSs-3C8BMjmt?1Lb;)^a#`~j&0IOXo*6Si?(;_bQil;!fJ>k3(7 zEWy$pMgxs^&|jyXj`>)y5XgPQIdg}NL5?~GQyBHSL!T5z%>Mng5)h#=pv^7>0KGqYqX$O4DyX569V)Z@Uk8T&8kx>?I z3^kOgRfQE>v@E|Nj4o#QHKU9ia`_L(2Io~1GGR!0ZG507K0`O9sl#b=;(|?0;9-x!Y*lz6km4& z#lP;)rFS3iMz;m=rIuebMSUeSwJI8DCQsibVRWAgFY2^UOaaYg$Mi~;aaazym04yM z-P9gL*IQ|}_86hk)Bbsq7(vA}#hw#sChApyxWJ^W4jW(>8$fZbM#1!VoS~0F(_JQJ zfRw}H5P|K}C0E)C9-D;W|4>W{lrrY0R-fC1hoJA;vd11hvIMkQdpJZ-?J8345sW<% z@RvV9R0Y2lA@XA``&7>kaKZ{6lE1%3qWzdP?H!@x#TzNF$cCl8vB{A4}3W$ z%<04apT~s{>TqYea}lf@csuV;bvRoWKSyf_5ezKd4Gyw= zZ}7!ar{3PAS4uod^AcY}kOCV(><_2;r}6=-x8lvgPh%t%TSb4wQyKV^#4r7>@Urwp zT5Bw?y&yLuAh7+lMOr6#ZzYT&2j&mL-zqDrKi*aSF?LP9Hv161Mz1>^MLRk4VI(OX zI_5sPmYSY0i8Llt=5i}1z+JDj)&@U~M==Rlifrxqp(@9EX6_Ioou|pHhGG-x?3n>R zD@i+L5^4kRqA_8mIfi1$^GKCR4mNSYdx>aLhb@Hn+?@N0Eym5^ku8x|>*U#WD)_^i zILr^Q`DJU0fa&D}4z8sO_Mj>Y2KYhN8Bup9idOAv5wK^3);iXYApT+4(`}&GZw#=d z@QV2KCI;zoX+j<=nO=X*VQ02$X^XFqDgz2UWI11i)ee@Ea zL&oKR=y%?X54ggVbntBvnvsS2l@-pI>Bd)4o|P6^-v8RaWt5S_GMYiD^*&K{Eypc% zQP&ztPDM61OGj&V?zvPv-Wvg&5}BtBTyV9LYT@k?LSr&jl&{w#Xm)Qz>K(A8k{`XU$*bzre==9abu@>Q}4gM`>1?sb$@Y2FS#9|!Dce?{Ix&R z1eda^b^#*+Jp_!$;c}??S1O!sj8#>}qrLJ!$Z$G{c{p>dcRO4(e0~?^M2m|F9om4X z<1`mhm1DjBV(I4;=L#Z>$cM)?jHoP9TR4Y(DX~~_9*0R7(g(DvDTm5O>(g)k_lv*b zN{wm%oUR9$4=AX*h>V(qa0fOYPhF$T5%gFR8eOBP5s^>RLY+vtBsi*#ig?blfk?p( zJm)KsqX-x{8UyFr9zDvyjlFUbHKGzn^6jg-p*0|`GKM5JL`7v5nDYKZ=Syc~6-^T) z$8bp8vQ*6-F``*9zVD6MkSYlf&-Pm?J}^Z7oVPHNB2W02(g~}2G(5PO)HT2-tc5+> z5qrBuP5;=9gst42R(Ip-DKJD=HDWIa8z^Aa#{3wI{0ix*qo;#WeBF?I1u3gkA$b%U zW>_*?q|$AS2)Wm;B^|0Vrr@NKet@ugA575TMJ0?_i;^TA^s^W2 z&GVpmtN~Wi=q$4DTbH~k{$A;b;?c3+r$=-jQ5%2VgFFlu!rYG+M6LHCGl4L;2)DoPwM-5A_TkbNEpIQA6CMRxGVQJOW)aFpo z%T*J%D z(kav#&@KTn7`BAGqU2ouc@{l#-Szf+{y_N-X7HA1^Z7oXAnooDU3Ku?f7piCFq+OF zVZj8O0S26#vfO93kCIwOQgU5H;-~0O*fNpRGxnIjS8*q%U<@Gi>8*<8N ze251w?iTJ%XylTip9HZT-(flLJ5`!zR6z@CL`aNChQ+OP4n;Ioh7TG7o;(LKRoJ;H z#7=ioO z>lNmeZIGpPr!b)1AVnD^*Xo?N`*|#%%q1UO2Gxoib!1!_j5_Fe{c?ujB-}X00Sj*W z9`PBr=~UV;Qe#{e!l41S~t=SB5Zp&f#iM zz6*F=T6)5dDEb%#Q9kW}%plCxAls{V7L520L!>!M|D6Cjq^@b2q=Fax_!G;?N{u+_v=b-M1#DX5G!g#``Cn)f8t zvp(>7YulV1I$zfiA`SaIQb56Z8Yw<){IAKZ^Z^WCT3wyPvDf0s+`I^6vZ{wDaiB4~ zy%8BEiu89FyLkCFxehb{u72<^9_$bEZkVSLd@fXl&Y<0WC%KzdPjFa>v4!vb@Ib=t zKWt%B%G#Q+%nPv7D5ia@Roz8;P%EA!_*Ub1_k*-Uop^icZ<=I=OVlX0gtj~|#x!n{ zD$agWT?fxZNT|6ySVv98Btp)uo})HZeiS+mgHTv1!%rNp^RDN{!qV`nRD%{KYWVJTG0FLjJ~a5 zqO@cLTVRHcgoZrSxD{c_q#6`fWPwu>#f(Z$ZAwUH3Y~#>NM^z2UXcb31va;1V?3U5 z4h_OgjS#h>dGC*R3k&e%sN6U6O%jNvWR{brOtqR4LW;`#5x`s`%TBTs;g%-$PRe$3c13l84P zuhoE37s=aBb?RXXa`-4>Cqqgn>Ftsyht^nT+9YO9W#cEZoULE;3$#tY8MizCzZ-)k z4vP#{4ZrDM*H1^SzrK47y`&}QH7SHC5f^&_D^t{bopz2-&oFbLZ2_iz~KSH`|Xla(SaUQi9|;+H08MS7ymU#NrpEI;)0# zir&;fDHGHX&o$N67CirhkXnAexQ-PWR zqnzA|&H2Ppg$Ojj$^CA>J>i^8>yA)Dt$-AuS2fy+TB^KUQBG?jop#n@F~gJY3mub% z7@39ZGPk}60%VG}qfoBQ4UZ8)3){iM@L$(Q<(x*@6o|mJM2NncfA#DxP-=)46#(z- z?^tKPMf8wS;^=jO2r~}%{d0s|mzT=8K`+AzyqHO{c^D>?m#>G_O5CwS_AJUNwiV9O zxw(oJUqL`XElr{KLFhn+F31^iaO!3A2GB zwdMAH3Mp0{W_9%|#HNmkf|(oNM>bJOFS7AaB1RWZNuTRzHW_(QD+p!>n>jEYL%dSj zWD07gY6T9=Ne$9qQVEQZR*Q)bFHZ#GkdHh%uFiQ4*t|C!AXJt|N|-o}#`By{b6 zi-D81m`w(6HGLVMlAqWCJ>KRo-kWlDEy?HD7(70951YI&OgxR2 zNhw!&8s3y^W~d&;+NW0@4*PS0tWo9smuV@ofOJ$Lv;e%4XeSQiKbMu3@w+{?@FW;z{vvVSS(FezXz1)-@;>wlv%9U2*6>H6`G? z8*z1-Ub->L%v)E5c&$rpkq{2)j6CY!nho7&UzRfxFXV9_cpB<^WB#foFRhNx zg=?tK(q_H=j+}q$xMS2yqz^2lite#oA}WPaHzsTycAr4GCE3_|l~p1)!5oTE`6bNw z#5iCTF#LKK0<%=so_r@ zZZLE~_8r>w5S|H&_dFe3Z%6uu?5A3Cb$l{&d6D6W(!z&Z=61&7&Ugg> zL$nl@dR&Q}PzmZ`a-M;CwenWVWXgCdmQQRUOj@iVy?&nL$lf1am?O*3L+9XZQ+Ggs zouT0W=w)9EAgDn4wWa5B#x*jO0d7nk$kku=oy9azbg0EMif|@B3t0~aAota&s~5lmC)O?QkhWj*b25Fpi4SEMi5Q z1(w;xV9=sSK~p>*L(c}H^DA4TcjjoL{wKFAH&bXSZvsGpHYD=PcJ==hDg0rA-{46M zx9cD?qWpfPU51QY5vra%rGIwZdS!;JP^*`OQ0Y+EaG?+?OnIWI!y~l7=@rkh!iBoP zKv504e)p@#YrjA#!Mq?_L_zEz>UeE*F=+6!B@z5B-2L&+P!di8m)<(;+wQ}-sGOs3 z!IoDcEU1KX!~o||1Etm^O*QU$qVKv~p2v6d8&v?gD+qx&*`Y9i^soJ4xt*$Nwon+y zZsEr>-)r1_4R}}iko(ZkU#=rR50U!#j3OiTAC8}j{g8ujKiA;Q|0Hp_nJ0C_fHW@k zw&SZGK+@ww?EH8jz~2iYq*2OiAbw!8j%`VviP1}|V98+j^2?wP3Uuko3 zYj1B-hi(9OgGtAYxoRlCpy;lVof-nA%}&@PIK-z-OKXM{`6`E1G{2#+195Jt2OIpp9%i072V``^dst!i^2X5K3mdgm zslM7mBdtH;7j>mheR_&;VH2d@1Q()J7kB!<67oogaFlsU|1#~=$27}G=_$+#$bxVM z-6-_(O7i!bj}$krYFPM$u5mi2sR|4Vx$$HXRpWgE!6|zy_z# zf_#Xyawz+oB!0dCH(!~aq0RibunXI=7zl{cniKsRdvy$W#jh*8eqA)KnDk7gy3TSd z1d%b1sfFmu)7b^ca7`6=C;g-U+OX!Hf5*e{R!CvS-$3ZqQ?A>`*muI7S^Ltts>z>fwvxXABbUtDe6v8Pf)u1r3 z(hqdA3v`RI>Vy#=2EisocC)hvU^|*0nn$C$S>xMO^y52H%8-1Tqrw~}ZQk6f9v|qQ zD|EWs{{I0wK*hgY4i!t`XT+5d!`lNMw$6P1-kD%Lau`kM=rP-~BZB~lrB4lsuTpe? z6rLIeA88MCnMPD_wh{xxUa(q7W=_^B@@7@?FB#+j_Gb{IH<$#!!&H$A{5wk_l0Ekkd(Yc)z0f8fE2Ii^KBDPTPPvqFeE8# z^kf{|MlDi!vBIT*o1KmJ&W7%TV$3n{ta=N?zIoxZ4u+2Wz_0#OsIFo^^*^R9e*R!B zqWA>_$P7W7%K>{Z@JZO_zgz7qQ&qu|!z5$_Xo-)d8&Wn=-9XjQn>uj}i@h3F!)R>L z3{eE82BUi0ilJu~3GXgjZNt`w2l4M?35n3BAPzdxiCWDRKz#4|Cn<{!o`)F2Yrg-W zmhZC&Z@p#s#uDO>h<;18=Q#?MjG=;yuz+6(wbHzk73(Y=${2UuO3Nek&ZQ=S&%y7- z8GV-N3^{R1!P5j7?6HQfJkjH*0C4-jS52{!pneR7K}3RY`$CnIfYg&m;`9oxGMXRY zkfpA~Bnj0pM8LxSwey~@5>=-o^p&WxaJfcx79WvLy2W>AKcpk68p?O?d^e{{Hz7%E zvm85^9x2bjzI#ndQke!%xdnkNR?}$m%NYj|elR5oSvWW4yYg-?LG?3IDrRV7_5@k< zW6P%Jl?+ZAl58u5Ny~SFOPdQv^5;It#vcg>^#Jq;bPQOIAb^eSoZRr%6Y<_yao|5= zSszI96g-_0aWFXY%T?ixDqI?QN{`bt^lp}&p!S~PexP|@m&MI(d>xU@i$WPZ2u6zo zELe3-iUsLGSTlYtJ>wDMZ;ypfvF30l0<4^6J!+2~$|2&AnY>Vo$?WcY(9@$c8Qg8w_cTO9^_Fn+ne<5gB#(Jb_rMen|f3D>TI>ZQvwO))T9IF z{D8EZd0N+~I#)bd3Lf#y`oX`Dz-0;czt{5JJW`_KX{^I4$>F@&>V>-=$r!MN@!d2i zL>-g{qFdkJ_V*`g`(O_s2$%C&P}Cz}6!OWQj13Xs@u5$KUw?Ao_5IdGTDawPfhf>= zi(1mLHa!dcTf-RJ`x3HvmYzIH9~(G9`@sL2JmE**Wn(8=;XhxTobVU+&%beiRElWS z;FsXdCn^5;&OAemNr8g%lB6gXJ?>Wn%4-) zcTiDc2et!(8QFwpC)&>jT0?yQ+TCha_0FT$B8*v%5Nc3iN zp5h*Hr|N)^$gB(IL|~x$$|!%Ar?W;zIvdL;CXxy6ck5*zm?jeb$po^#&QX1${QODh zXjPLm`Mkaw{e1T3<+GPRz^`-kJz#Pf0+K|~VtS--c6aZlpWQ#KnST6H9PahIyvvcK z$D;Lm)9s{V?)AaPo!Q}be`;yhS!B4Zx78w=&6l^HR!(xP1<6M-<34-9HlxqJ1bz!N zKB9up?wh2{Tdp$pP2R91mt=d3iE~UNbtyKQ#xZP=@$ucU(i?~qNQTI_UA=aY(xAB# zs9ia!2YJ^gt4}e)46f>|2gQ~~6!Ke0>}%WVeSD(E=fN6IGip=H8hcZsCC$pBC*h(` z%}b)u4EC*hA0$}MHPA6Pr_BZ!mKq}1uB||bk~#zKv}F*>lMAM-lk2ix!82)_XSO@V z1ilF^=ia87x9|F!D@lvkSK30Q!IJH3!ff2Gev&oq<2Ujj*~i|ARhIp#dMjh5>5c4w zvE<6j941?WS=Vq(wRPl;V4x-4Hjf;c#Cskcv`JuH0sY8MQip~bF2s<85AUZZJ(A-f zPg8w03)wLD#I`RmZ2bEh@1B9sjO*ux7Q%^br$N0|4ZJcS$q3FFI5a94B8tJoc=iCQ z6bw#$h}vYX#Cm%TjgLWD9mI(o09ySJc*y6hJKTGQcr%h1Ja

    (%G7(S7uP$PL&p*Aj6MWBDN}r}MP0c4--ocsPycK5`v+3iJ!n$T@K21I(QPYg zk>R8Q0|`PffOMYva5X`hXO4_)EwF#=%^nm+++Bc)aW4SE`27PP4@bwll~W^`9XdGy zxz7~qpJPh!OJ+W%9L**noz(-!>;oq?WG^Bk6pF$fp5b%^^~_gcBeTjyGJHQ*6$TcK-Na6KCcofU?Ci8 z6eV_NF7EB~Z0y&er)81!KamvJK80mb#-1+vJ&q`pH!W~Q!zspsQKB#)f(>1-uC*{5 zC%deQbrNRPA`U3z>Y8K_CEaD(d=~C%a)|W~pZsXN|I+hmYx4Pflde^pDALbUD<$x; zr&a--O7#`C+xeWulB&L$x=YztL2?2TE9yRXCC-u*H-PHL`~K~3wJKS{X0K_QeOI3$ z3sGYZ)PB0~RzFahb__p5DlsOnNTf`auY?iq}!w%2pH4T?}0)o-mC0ojRD zEe4-P#SLcHb6DwMyhrs7);#&~*p2@_&3WZ%p( z#rtJ>QFfB7Q{Y|jI=1pRPC&4n?~84h@Drq<$=iK@Pbpdb3V8s=b+xK5@|Bpj8LJ(* zB0Jk-bc02rRr> z9#UqoKT1(u47w=E-WJ_ia}}iQd4A*l5(lfNgdazw`eNH54AW;K=?{lU_Q42mSe;E| z3$67RgtE%5=?XZ<>VUPrmOuC6hUMppjG`DZq)QJMRw+K3(Zl(z9)1@*7da|gFA;tQEY;XiZd2CYZOMwd<8S+`O=Ce$qlOoyPT-wzxL7o zq7Nkju8pWYSQ?4T)RdQ=USTmei~!(5x1AoUS_?Zm!hCEvu?Ch*kPf^`Yq4H>1$;_I zhRM|b^kcDCcjUevj%NUWR<0f#iGSoUP@A{#{`frHdvr@tJzY~iTTw|MnC4?91ffw= z1}4rgESp6?8ScQtmybp;vP^K92FytWKq(}~v902%4Utw`;;nN7>C1kJn=wHf!S&JM z6I7y?*$GjJJ9}>2hp6LlvCRIIB5J^sJ(7ri{YZA{$pIG*s*26z--lRc)J;GtrAsRL z=^#qHeB=qw(NFhI={i=zLkP^Y&=Z5u#&& zs(@Jz@{XZBmM$EuvHTM$7E!HBmRl4eig~|e+uv!^$EKl1)kxk#DjO(g+{Shn8H zBpc^h`&|j_oFE=;*w7-}`j)1?UlCD^ZhhtBd%L8ATv)_gnraJE^zrOcTL}-o$TXR~ z=z20#R)%|LBZMw~7PT0o68cJ0X@+qqnAuI~*ZaPtr{QzbHh? zdtQf4N4_IRN%7PMjYZLI6e|B&)O-d?v^ssA!(h@h1I1$E5Sv_ODXCLB6d6BcVs~(~ zjMOAn!^VRgk!WL)%;pa^TbG&!Q9^zpz)kR#^=qGz;%f4jx*x4Yp^(VT%JZP35@(k8 zT@;Qv_uB%RVEA?tj-%HvV%d;MH)P>Qcou?0_961rfVPa8ewg>65q}ArFITw(3;#`4 z^e6d>^EtZ099uoV7CW+ZW;1nY-M!1C(njelG3U^^^T&K}qns7`O|w>lW+iVovII&; zKNme@Rln~hce814VyL#-rhFU?N+dNN+O{1`RtQ&Oq?yEQ7L0!nEQ2og6}<$rv7G6j zNVd9VoenI`lU0F^cKEqP<# zTX|=3d#Hy>oQINUbeKPx;%g4RL?Z*DomTGh z`CNkM9!F0n^DRjPYfcb%Yk4Pdtf)~$rGOR9^`KxlSQzO8SwSBtK4)Xc>3dsVRsDPb6`b3nQ|EwH#0REx8@ay_vshu zj&%qf?2pB2)2{^!yT0#EJGv#hM;lqGo@=Q4~* z`ne2?BnbCi$be`>Uro|~ckyq;F{FhyUP!!T93~jT{d>xi>?`TF|B8<^fV{5xA7&JD zhWIdoz!PcF&0Vp@88BBnPE(l$wJ9- zdC$JEi-xg$YE)%S{HHeJx>*|nl>c{60aECw!`m6 za{;2g{Gi^dgf-_&0YSVh%$;1PCxADdq|5E{TS?#NuEpSG97`FN@vHP_g&K`Z?`BGq zV&s5Rnm7^{h`&Uo3bd)5%mt%|rVO^8CqVNUm`AjUx={n=NF>uNQQc9Htvuut8(s>D zO2_A%KU$MI`rd7ZS?O3~0HmsmrnM$R@BKb}0X(!d?jmz^xnaYb3rmflqLmDkAZSjE z*HtiFhTT;Prs9rGF4s}MrIl|WC2H0V4=RW$a4@i;4WJ!7FVi&GF}*tl9x_?fCW#9n zXa)N|R_3zdZ-BuWcc(cLr6Z+EG>?^pOjNY+5k6=7k~BPlLq%a*6}t5h(b6K+4v5Sb z?R;x>J0#K2Rgw`TTb-2BC`yrXJ`jh*v{6iq<-`F2+OI_Mo?&_t1NAkn-PL9M5LHTr zvcf@e3fA0hxX6dE*Z7~ldlc^ytVyKjwuzT(>pT0N&XuXc=14cC5X-CKqN zwGYCZ=_NgjSdYtQ6M_%j%QX7g{RvNE_CO0D^WWDF6l1R(} zx?&7&bY_L65tE26GtNUz1@Ed42*L53A2>k$^{JS{i*19`)49xm2zGfF!a9c~5I=!c zdS~eYJd)e#x3>`%XY(&3XoEL5nM3kzEnvozZ~$NSE$@aB5Q%MobK#3Qs3_Zy#2$#- z@NsxCcbOvj}3$Kqqg8sA)=wJ`3Q~b;thGWyjQhjKzz zRL{qBD+#Fg^_nKqmW50@^xbGPfBQb;1ajhcogN=k-^a(Y&GGT8{AP3XC)?Dt zGjaMQJb{_rn*QG6-XPo{l{1*Ws6zBjSdb#=t&ya;mXZ{%o|67bh_QwP)zoCN+9k{m zb_Zf7g3xTVc$k<4N~A~6V?~x-)O6DppR-{=evsgV&(rqPi2LJ+_!h2{563eNknQx| zL`OL~`msD3A7nw}fp;B8Qiin0ouw&*U-29%P2-A#8uUUv2-0NG36kB>jNc=G^Mg7n z!KRH?VH`jt(G^>^OY}(Ej0YWdpgNW+O`I1n_kn5(5;Ev-c*!Y{Ao`h8)Mo;t;RF@$qKrPsI1(pIM}f;A z0vRkjpYD^yT36fzYc_ffT8ZZjPojtXG8_jOaxNfXpV{9?zs(x0ab`hPkMT0A#!nX|L(w`oRa7xM^- zI_j!#lDs$i@7=G;Xl_mZ+lOwrnCtN;D%~^S>1^FW_h~@D_LfS83ggQvhpo=o(Lt$_ zF84E*{nr!fVp4gM(|!IE?sI=Q2b>j|CX{_*kN-`g9F={OCC6D=vY&OX4ForIGRYIO31lu)#EKuVB>^gk{Ol zYRy@>Qp~83v&7c2x3`rdu_B~FNs<T@XP7;_Zv36EYQ58E)bNsaj2)Zs-P= zWm>9tCT%XNwhkUxuHxD;? z31n1!^Jt=S!K2Sf#$qS*Ep5n~>AI|D`mXyae?Pn7UmR3D2L7!5gADyy^3S@V|$B21A3itf!xrlbGi~16H#> z-Omz`pguJr{2%H7pWbWI^pB%_k#9&5JW34=Bypx{Z_3YIQFdHUiWRpNp#^#Z&}?a zv-~95bn6VbpxIs3^AcAA&(9%*Wt8fzrqwe4Rsfs5mI3w@e* zI5AS<2?^WuowxO0w0&OBoV`JVr#qqX(`ldeFaHY)e;X{JSi-m#wqFj|+cPvIJB&y?0 zf#80swE{w0w~|4Cve4TkxzuM>J&RRw-xPKGW>f=hdtb#1m zxf`w?3aggmDHJq(*_3piTVFcLY_%7Wzvkq`+-d=CXk3Iq;L{_6OWCtK02jHuBqCw? zm(*G@==(7}l#CPl?^lmxY2rSDz_Jj3Hk82)X;(1PEZQsk`rAg;LHpii;v?jx!9GseD+Y7O{pBAGM$sp5fUE@>a$;m+d0@WU zGT+zK4E%K2f{Z9nwtOK}irDp6GDh~`?i#{#g}ealj8P`f9MYxnev^TcLs zho#dkKeaYb8rSAYd~Kd*hYIo>vTC_{JgKk8lbD1XiHuf{2Z?R%yn)CR6z9<(FXm#RO0!~xB-%T<1rev^K3YJLAdd&!$tVaRntd*ly~lrZZj%#D44 zA(wnnhWmn5V>yAF~=G33{|%vqq>u>>=h z(A6h6V_b8%?4Z#xs`LTXzO;`Jt>z5Lxzw5CP$I2{Q352}m2uAamuzDBUpKWK)Wk{v zYDT6KnBv)+TxoH7Qd-^1n5$J%ye|PsGn_~Av_~d~q9zU|Iqt2}y#w*g=63wlhJvyV zYEF8ii|R5Vh95r&A9K&WuhWzC@hV>u)gj*~_Y1U7^Yoo*|k)a`!gwiosWHhagdFL zT=Yr}*@*NOHB_95W$SU0AlozF=|jaV3j3!eA?_0MVOMo^LNe<$pYtwnN!yl^enc$* zViSh6U!-Qt7cYZ>!EiDeNFehk+3EXjKUYkY6bVt^Vq|3#4!^zY$KIN0jMHm$#``ry ziIs2i1{j9Z7${GXYh|Ex%O(9`&@6QV6TjR(D@|A2v{VVQOWGCVt%b@cuM*pY=J3Wb zFxuRcgTFx6^>xwH@3>e+ue&?9Y$juOxPWks?V?`n5Oayz3wfGN=bKH&#$UdWUw%RU=%y+GhY9g$c_}08_w!|*W8TzelMW6JN{%C<>D!TznMdScSzF*1_ z36_ag^m)O=MJ!>sDFO#e-2&_8v zxK&-hgOc&jTmAFiGWSSOY(?0Sg)jZ3CDA4hfl<2}VT#vf!?2?1{{+AOf4`1MP##(% zI^fg9&Tx9fHCpa=^G$@s)B+VE@VaCDi%JsbG>{M0c4E`T-7ye%ah_4Y%^GMz1rpBz);y%2KrqMKM|y`9{)hZmLicSQIw!L~T7@m+G_{3gdoU ziGPI=3-}ueJ9DWtqVPlT2?xDt7;cXSdlE#0vqx7;Mxg|0>kww)`$}A|cA(HbE!0n{ z5@9OyWifvzGH9OChA-s4lX!!Q>8zlW+PT|gPTD?>Z2~OM*nDBO1zNWI_wM~07f&lC z&XqIx+9+snQ9G~@Vj9i7n8g(!>s0AI%15>f72wFpXi4kBxoW$yW4Q*45@Lsl;hoz( zJ;mwVomC4!FN6h-MxTR&Nk=YF{QT+L^U;gl+oGZI@PV0Fq*>9vVTh+zBMkOTecWFN z;9(`+iA8EvcYV-TRgR&nuQrv!7lW)mQ8#w^pyRG?iRyU7)X6YMxwuih0UTr z^>^#u$hiL=PPJ_P$#sy~S8Q!kAyuF-<%ab&>`#xynfPIP7-wOIh}tWXjIY#8BF6+L zo;&ZBDsn_h48ug=tnm<$F<+hRZEVENaqhebTvvaUbmxTX>IY9~=S0BW;pH6i|_dwAd z^^T?*-Pnx=u99q|t+Em}%m?F?-$KDPydr}Z1!ezw(`5brJ?AcL?f2lN*I9)=8mu6j z^PwBKHu>JV)bQWphJCxj^!1YS=n0ADzZ%yKhe6Xk0t7;Pq_(WK{Iw8F7ZhS61u(xV zBm*Mh3XDj>ZRbVBtLA){;d0S{7%t|gO-PH*vX|I?SnXCFiQS;eiA*yi*3DIJ%slAA z#yFWnjA+q>7&3eA%G1(GE7^b+*cKf!6d#;qNFuSFngrR#+Fr(db@qJ*{n3FfGcv^` z5!Z5Hmj;3~F3YPe4~ovasEZ$SrhU-(4Vw&a4%MyTGl`{vDHN3mUNxrDC%nFjM;n06 zD7Z#k&3uq(S-6fC&@{>DLkE?MnioTp>s?wNZuLB>7Y-vl*RJ^FYfwJ*hk(?7fun<5w zV7!R$o#t)rDhw=~lc0+k=wikVjUUNRJgSc>NbQ}aytV_doM>($Lp!?v;a46EzB14a zBX%0Wq%!KM>*Z^G_+anh1OM<#xRf1eNm!zTk3|}lX4CRonIj{E5(nukoQQ-GaZSKUov#nW%<@Kc2bqlqAZD;$nQzA*PH@)luA zUBLlTQY6(6%>$HPXbIKC)!3Fe?P*jN;k&>ju`f{Vqr>&&i8jz_lz$|ie`wI0#yno+ z&B>#)7)6y&vVpDQ`Qu({!_S4~bpUzMJCQYH7>I(dBz5QRF;@yZ4&%~7$KpEg)v^^v zjrU_4WHN}qp^&mISJZ0-6oe-X{0YQp@qxFDaez!Ztptj!W>W@NJqtVftA;E~2A};@ zkaX6Sb6-K1F3P~%W;k+txS3^lIuLPmZ)8Ry&7-n_@1MgAg5UY`10l(_?jP!qx3LxB-7 ztS@Sku;$BJDyl;aN%-UGSgK9m6dEm|_U~e$0;43HGX<-ptz~R79bc9N0UyFwg7?^f zV#Dj#uJuG^wu3>d0sr+eTXpGt2Tvd8L9+P4tBSTq-Ki+*@M6#}S054{4QwmKwza(QD^RW?;f!kB^_dc>U_l z`Ps|!^yRDbr>yBC%N(`B+j&!76jn^!qTyOX_eI?*01*!S?CLK z;dpKI+|1p8t&)`yWyf4dTtzb&#j6c>!WQU>GwDhJ-NGwQ`tEmP&-3>J?_*o6E)i0_ z(hvIGs}+!K1nP8(ZIp3YWE}$x3hF|a+o^X^>6P1TR|;P3U;4xCHomCTm55pQR(N^$qVpkUp>|)IroC1bobAL=shujDj$2PvIuC%FrcS z;?>2qKodtbJei)PQnetVtwd0jPvE5zEIN5lD&&6l)g%y6tJ)Q9=MhO!bT)5-fUxV< zx71Gtcpf+Z*_YDX?=6IT!RJFuYM0?@;jN}0a42~PY^_h!UhJgj_*hB$!#wvX9y&c| zWfk|h!!_a8}LUDa3R+*68HcNSfqDI*P-6=tac0JTtexH^46moT;-&_sKACfJ{{ z@`Og`g$%Ecrz@jFJN}PKs0=_F>=s|5YUP_=Ug2*8~52J-8 z-=hwm+y;Cxu7pjs!6w7|p4g=|ujS@1#>P^Lyb1_Irm68Pey#`zi05aJ43;T5qi$vr z6bv`8h7XIUI5&}5B9T>fXGKLEoO|*K4jxlcBisU zECQE5f23tmwRRv~OHz%B-%U0(!zh;GKGo78Gy2zzM7L{6pmkTTb95vsTTIiJsCK?G zE-b!hr}s0{kz^+m9hBoGw!?K3B2km-z?YduY)B0gQ+*eBC%V5BPrgtYs$Q@l`EDT|`$~5T*>dtmp;=!h;6!?E?$a47qxGT;$cN?&Z^W z(|pQ}#Q8$}e4-{8bHS)hBSeN__ag(g)QK5(*rlHfX>uE5c=ITB{Elbe<@XB4=0|-gYOYWe|G=(XuEsdRv@#oLR#r9tXeK zHx=bbQ>ZS>g`9s2Y>)~D@)R~ym4)GjPe>wRC5O2J+%G=PL}xA)$?Zb-Wj`cjNk!=- z=m|2IE+3*dupD8nrhYJlX}n^zyD8gcpd-{5@Z@TAnb-kfPZNq`i(bnWgl%_R9-zW7 z4ebYUG*8`#<l4KmEhg=NZ6hX*?&urs1%D!<@?W1+h!PvYe>vjqyT={R_B-%*isQOFFmNX}Wg- zfsj*i3%ip|r_mF$lDFzbg1wT`)Z`4 zXEl$tB1vXChQkwp2f{`g4HTl7AE*Tx1WHOcsa4z{gAMq)3k zXAtl<$N`fF$DMEG%Yi z5I=Y1b7ruW!`!2LT2ioAC>hO8TiamSUUvOtPfp&a86=25Z`T|97-d&5xM>pFT@b!3 zR)mmT`o>LX*aUrK|8sX*@PbM>v{J}OB#jfUn((gJrAPng#mV}JgxNc479OYR*Xf$6 zo+Wc0!QMB&yg1>U=Rc))c)%wZ@ObF0?dDJ1^2iWg$IMT;sNtMxpZ?{)Pq~c9*qNlg zqf^$41}XmSE^j(5VI`T)8F!Q2&16iO82Yb^gsT$@TtVH?aW~&g2nY53cF(ByR>+Pc zPK9cNhj;cO&cY7m#bDK8_~mGgJRQ4wQD;`e27 z!zkZqSbgkaR70=c1fck=v7GI)$(jxJRiU_nyoSqsZrK|gTma2UVx|fMco9oA$M$2& ztK{{LG(#@(+mstN_7JmB{(_-RH#;YoXYx{eH%k{~Q%LUC2wlSj&38~!2yD^)>4WJ# zUYE1B-LBPuCYrML_+a{bK-jXhkF;h{muh7oI=hLSu&df3`Ma)-;efz4(&)hO(^o&8 zzy9fb_T95LF`Tn%3oJV^0)l@nn4U_c7P5&cqTwVH(x; zo03)3+*t03JOp)5rP#D6oC4G5FPj7@sdCw}!24PH^nIs%dq2+(wbO~@>i9w^`pKO(vDXK`Ms(>^keXarK4(DP6rw@z4N12{uDoKs=}216j*hbN zgiAqbLT}#VWFTb|Q@!EpQmO&y{gc=rivx%ByL-%N} z-ErLTeT>p_(jtnZ19G(Y`H`9wkM>$m&^kZo(45GHG`GS~LGpP>?nxGJKsFG&O8u2{ zwt!(nsQDA0Um6X16kvmQh%3I-Og=mO<1q1p@z+@X@iBUe!@%|D8shy4L=6pK*7F~* zUdsn1aryQ`iDK!BfbF=_x9JhU3y;!M{u`a!FAm})9QC&%0yya%a|=cby@@VVsiO(6 zSsg3Y91<8uL;_!yi$wqui|`KGb;%5!F|HIZKCVzUB<5v!S;$*G*G8Tw7G9kF+28q; zLuNk6+i2Q!VUOZD3uRmBEMo15+c@rxIeqvrJrXO}IxpcAB`QARpIvib`(?!i<5pA4 zOh`#zoyBB`MQC2A6o=7?>(%RaVOVoX(vE7{6OTGBwuLIlev6IVA2ap(%+$?v&7ba)%6^L6C&@`F=l8)5T$Pp7s zEl$!gpa4qCm*pgpSW=NCP#i!O-I9zM{5Vqx8%_Rj;RslO(2Q+J8lAY&^ES5MX#AfV z$jdG$27P?YGjC6ij}!0u4-3=<@?mQ7;mAvWV+mm-QdyT#uAGz=bMl24Sc_=RD%x?> z%&L^B!E_ZT-uFDawg^Fbp{Cx7W0ip-8|*!OGlrP&vpd4x)dEnjcI&#?&>&SicZWag zU$9wU!w`Z1unn)6zmS|^F^f;TYvB;Ypo#eq;zh$Bls_`3f8h+nC#~US_+Xs*DjNV2 zoCFfPv&iAe*NWuh-``dYtWYcfj(Fh9_?@pcnkHqD4`eh{`P;dth5YM1V4zTCl73tf z^m7O06z-w;4z+4xI@^#ku<~`)^3}|+iogvVA``PY?x&&S5pfs}-J)r)`G~Y;><%kK+UQ+gQyK#&f%HYC3>y_koCu!YXzJo~EEH~G zmLhMzl%O~s%QG&tN35Ua9ER|4jWd;2Z1NCaP0!t@U>~_9FiV<-(>5beOP>i7lEidR z;eTyw#CWX3>VIU;W23M+S@#rf=gssh?@VuE$4dg+iI@+f3w-ukjR0t1cE}(wYy}vU zOHByV^RFQ>tc6L@s681i=^>4UY9NGJKeX%?HH&8QW8R)!wDoG+6@QQlHCm`9(zx=A zmU$KU6rQ{3h^J_!q-cuQX&mzbWd(pj97aD$`<;#)G@RNtNSL)s0s<=`f(8dosdX|F zh4=ow@xJuodWz%@6d}`I^<>_^7s(zc|Epgr0bZ)e>=104WNrs^gxnq6qb$|0Ju;6C zf4L=oc4A&w38#!(cY-7*#d-NwjC~wkrL4BAlh{aMw{ji~M@3wT$?AvYKto6B9p6MB zBnXZOl*=RR%;~0bG@jnTztJm1_ zfp9PFoAV|^R#$=PFh9v{*22hqq5_Fi8InDsRW=KML)vWt$dnGy&xff)Z#t>(`mbDf z)_DdNofJj1tqU)$d%S%dSq%{9naWpf{#UR(A*zr)XuI3-o3v)At)#xIBOjPy}BNd4hmJTQq(gC|U` zK>qsLzPf(L`KqBl$eMnk*~f;jmh`x2c6~pp=Xw1ub2@LD2AFE15^Od*fe#6E00YZI z$?;0>;lLcFC&iC~*kll%CVamu^8j94)*8}tDP@Qrvi2nSO{m%k!wpB_pK+b?a*=Y7 zlM6=>1z3?dMvU|)y71UWlLVTYis*MfN;?k@XW~JweCtcjWIx7%k)KFbs5 zMiHWxt^E-3WTvuf_3O}J!X!|)Ue$tF?{o$ACwbsnPZ0_0n*19=g^*Y1xQ)Q=YKkDX z^0W^|tBIe2I~+{HoLV+fp|>*wuX(d&t|B@hfS$MaxgPGB34iSdPF zv@@}B9@N4J=mkr%S{j7c^WV4fT3MHt;Kau9!^F_)uBxui%F4?8^2@2rg?;t?DZgs; zIFy9F;s`2s?}aEh-N>Tl=)T&BF!o-dBthYlaGzeP)QZ_)atsj82U#rzRsBF+dwkJ@ z6DTp!;`V^xR3)UKs+oQ!jiKPC0?JX`4nRwa}Z4waFV&Oan z3Aq@49^tu^bA|u_aN-?hd~3%uQIs9`nOJ)gpD7{gaEo`RK_A_ab2~1WueTL&`z;N7(?kmDiN$V>lwQ}OeX+q}=fT-oA5d+?|WmChbs0iab3GM`BlbTh1iUF^t zT*^@!;}^s*I-zLTb1e>pu1SW2@Q>7rd(#hpfAZa2V~Ro?f#YH|z)V z;R)Ed{ESM^kT0tb^(UQprYFssPJB$6DK{V5=?8v%Rp-w&Q~%f~{9%N~A|jgpYytH5 z6@|Ix!cjOOF9PJ=73$Tp)eX)@#&*XSgTz5@&RM5~l5%$2xxT$b$mlHKF`5nE z8J(lA9dVP@jVV}=dY>`v5VR6{&=uncX?C}ipXn4Jv8hB1r4kGjp*9p}(oMk({XSy_ zpm&-jtSyk+iL@URuwcd~%`sLIMphm8E}V0NN>i!>F@J`W5Y3D5=lA+ECRzvn##Qqn zgq5V}rM6Yw6k(XyzbzMmHaavHFx0vR+pr^3DRxGFqNfW~l(b|xh2y07qo#*Llc7t^N{o=`+! z6}00$BE{C_%Rn9i3*!Gl_*&6C{ON&gScdbr1n5+#**LI4uufBGvxV)#)fA@{() z=oM=2PrD*am%1j(fJNMCN4M50>kC}=${3SZ;b)fvz)(MSq@H|uYFVrX!zdKyrwkNk zud961L4?%oM}evC#PSIgOoyaBr^y+OP0lnydHI8HM1)w-fsGS#BE}^R2Q${*90$!A z5SdV@prW!iX$Ztett8`eTl{YXd@lxOqaB1HTxyh1Y&KyNih<9>TSEqdYBWnpT2^wPYoN5I-VI*FWfidt_yRkWJMV_mrL<@096tyhK#}ecQH0ea zlasKeZmg?E6>q^rAzjZ4fIi&(fyWEC&(0TPtUUn*F&gikgi;>K#%nDXInr{@idsqt zjKZ*B+u2^L9|#BmXfU`BfG2%e0M}j>rUSIH1ZI1=@3xzR*FyK1UvizW;^c=!XC@T? zmM=a#i9I&jbfRB= zHese46rRcKydDEb5<{5Wdd8-Pa>4t~!QzA@3iasK^Hpct{4s5#oVM<9*}d&YzrB?k zKW443DePTv)K>c_Id%~N!u*bc_~hCm>!$g@1wQ%q2d1{!gq-KMv;OTlt#&Nzs~wwRIWGy9=pI4~Ju-VR95{sCKiX8M@x4?RO08%`eF zy-F1}b~i8+MT^T9);M9@u$`V_U=&$437ReFw9Hl|)Ykz`MKySgb1`s7gEiHLz=kM7 z&Vr8N-t882k+Gmt&*!TlDxDj5Wh5@o&wB070CLN!52!QdR7BQLia5W2f6K?r(OI))k{jU?dt13b$=BV@5NO& zIJWrtzFX(o%iX%dy$6##z%pyhVU(RikS4&gM%%V++qP|6f7^EVv~AlnZQHhOo6~mR ziFliLmv>#;tfL^p5!eU8@_k-M7gK8(6fFa91TKU zxnV`>dNBt5`;PCc`@=k1h?fXLiHOyW^F~k+QM@5S{Ciuw7;%cL=)S9BsOIeodys(= zP5a}oHyYc}fyYtU6R;$}|LOGPL-uqKK;gQ8Mg5k|dvV;&j+h=^fI9Q@ir5~=<;L)0 z9GgC(P?>+_ipc&_7(nr1ymC_{=;h9&GSecf8oXxhTP|wLJY0W*MncbXN)60ZAv-?b z^T$at#QLO%1_gIh?-l>DC;X^KjJ_( zVi{e-YpbT+k~mG+@MVXMp)w#t<>TKN`3Zq80}<@9=wy3DdC}p=5(xR z-ngWa7O`<)9;3C$NH3YW&h)>$xjMJl_b#WWXGV}1swZ8+>jKOB?Q|YYZtJJ5R^(uG zC%R>gbJ*?kgINt0jgS!(WyL>hQjiqXnuR#Myq@H!bbi>MO>uLe@_rH@YUB{tp=Af0-YVqN7aC?(Rf=Nrlb+Y1MO6_f{Z zEMd`=HO^xsYqG4jc;lc4DyYKET-`RQV3j}fk8=mRY3_Jz`!V(iZnFFg^b&mD^2X1c zV|>1J^NES{L@+XFf50inZbNVAJp;lK?QpV-Z?V`c$@q5VHU({!ZmhqEUTkEu;p|3q zVa||a3!;F#wO9>vw4)XZiY>aZrzcmFRi#yL3+%-HQ32!KIWra@OXM&w7B{IJ911aF zc|~F!ptPTkTPcjlI=lIOsYU7r3xr3eH)`jy;Y7_a5L)M}yZf2)1Vn#e>lMbPJ1=!T zZf$Q2x4Gn!dfTmRa>S}G=B5TpG$QX>9s|vfd|NKRL1V85FXu+N|FEEJa!k-L#{Mhy z9#p)u3*UyE^VKW`4)%B){+ow8Ifl%!9Otj1ObhoErsOK}MKa*#%f|52({5+m#iksl z)a+wVdH1v>*RPZc-$wES?zY$(8w6kG`Up#3A(V7bb#2g6YNIW5NnMy4@{}`# zd~0cXFGrm%wL)<{dZ-nw=E^BNGGJYbut!;MM==f8YPBR<&3N3^COg#X(jZB%&bj9DSDf)9D)YhZ;{0wvp zwjbMtrYJ7?=vlS)BY3+O(V+JZig1Tr{D(CAN3-Z$MGT{zT*gUEvLD^!`}TH!$yJZS zf4N(eS+$K`r@rm`d7G}Bb~(FN?WEIA*7a3~^R9XJytvl4r`NxMv4k2}i{!6;kBp}m zg%HQ3rC54l0`gkQ)#Tev_g^AZi(hl`DoRf9B!yYpX2C|QSe%_3fm&-u2|jB31fM1v zp)%oel1T^PA}Q+_Ii}k9)IjY{&>7zYw;k5Fto54M!YAJ+4`jU{{+_n0L2I#zGP4B_ z)&u2Oxglm>2BqqC^=-ybHdl*X&rM+~(cwc!UfjByO(3q>qAnt$Ti0E6Ly!gV!pKc)UmgH$Lg+QLd&@hABg!q92cM8c1^MHBX z=_HZt7c7jxoR)chA!vw^b&2gCpB_7&v^JKwRBAXXt2|j!%lF_X{mug^czz&eNeC3e z_uJ;=e34;yK!Hbj+(ZEq^IyhvZT$m8aU&1eN7q9Kq>E+pf=1oEUs7y0V#>*3n5Wlw+~P!oduYKr%x=RVU=9*jHVk@wxC zO8^6`xxlNl(E|JSeWVmqh1c;@Awz_j1w)14lwT896>dYm9(`9ucmDPk2nhj{D&bA^ zHM%rJw{rru49ZwVHY8x=7yVVigH|LXOtgj-cY@*#}=Ncx+%c(=TC8o_SR^q%)c-GZ$;q=p%m;zexgY{_@CDDdPu=~yKiJws@w|6 zmu9Z7-NsotQY#iU8^djUuujvQAI})@^ zTxRDEx3%Y#Kl_^T-R>*;rnKcZZuB!o_f=Hk8|H5G4j%y(-ruBv@#C`rk4v+~_dhpx z@RsKJyxVjP3>V};^|TmfcgXW?6$bxgN2lH5`X&>`loCEP?q*aRa+y^y{mInqrGmFr z8-^!xVmo=@v^6FbSwqtQTrwc2LWM=Kqd$gp+70Gy_jvDfSFI%xh4R$bHEt*RNaO(!{ z4h|qx#E_4a5H0qWbJ>O8SwGy9$SjfL*&wsv1*sjOO8G4%vxR}OV1)GLDHb7uyKAhf zL5utPUtLtrtqrA@DcF<6UQ@C-AyZeryo#Td@faRZ3F>UAFa`!OT10W1V>6DYf&1x; z_M42(iaNVqjzTV`*E^ihjv%i9_&`)gsh=aa3`(>Pmh{nwwekI=nb4nuWxjoc4p0O$ z@sh`AyGYE5Vs2yLVr0RM_T+s>A`DMsf&t#jv>ky_W;)~~aL&JZgiTig+D%nF08b!G^wjts1e`KRwW5~KL z>B$aYx#G>lW$MQ~kAorm#}qZ%w>;8y3|c6I2>h_%<|Pi5c!6CE?Pl29dnaJy(vN#4 zb1FDlJpStgbWSYb&#rVSJ>DlD_oJC+w7;g$O_hXvb@;^9{Yz4E67R+{CYvik^H-&l#y==CHuK2~DhWrAi&NyS(=%Y6hKr!mHLz$9(cM zR%v@fZw2Zo9F3wIm2iV0Ae>RAWLR$^K4S?PYsOYDbxORIrl^adS_xMV5brI40%JPl z?W-oAdN~ezICJaYL-!ubFDhn=VI&%_P72M>=#L}U;fN~ILp44p90Hm&TyWD*hH!!* zi|1T6QhuJ>MLcRM(@LE{o%mo%1`9Q?DRc{zrCsLmgBma|6Eml15`ytJs6Gr2eOVk# zN&ei&AI0e;!el=8O=7Y=NMK_bBV!>#O8UO3ffkWNjHL(E1b&BHg39(4+H;gj#F2e+ z?i!9JYzC{ZV2kJSUS9WKs4zb^`g#o&LW7JM-~?;d$R`{BuyS-D5ko3Yn=BJM#mJPp zc@ez0$kLHAvwD$TX%qS1{h&Z~pdBFm#o_z&ceytBMe?ha(D2sHK+$ObdCC2yugh6( z*mmk#aQ|AAiwf0&W~=3D{f_CgAzN?#62$=t*MddDLVbA0yJ^`{$?p686H=BY(MEQV zyXA3jgsKcEjW8Y(CDi*^wGPM+>)fM)OwPQ(ug~q0;$VIg2g|~6Czhc8*pe{Nu)A=L z5S}`C@xXH@={(%GIfdmFm$(pT9!sk%J?ZLe&4Jdn*)Ml<#l5IM-4tQqq`-j`FWpWKAAB1ni#GV)!VR#ntEkL0FaLuzTvk5o&-{S!Z7+b!p?*5mbU z-;zJJaV)XF7)9RRk@Q?bbF$Sy_lkPJGD2-^K!g{5;4J{2-=j#}Sd5rYZ|^3-TC#U7 zJv9NJb{=;RdkOj9-~`{oAs#~da0Su7P;gI!^n2cG_T+CE`R3 zmGe|3_NY&TY5J#}+AZr=N3^dcP>INJV7Bv2X^umEj%GaTC>`2NcZYxDUE> zjIo8RJ@TAZnD^5sseLMp{k@XH@Unb1>&tBYn*fX#Pv4lHp)dDXg_+;nmlgQt(2!Wc z>0+f1P)cuoMY0qt^m#u+_JNd(l8ZO33TAEeQDj85l+Rl#nsCFuNbJfb?DS>+WM?rs zZTPWFBui_iOxD5WgN=S&M$;ok%ArjiTt7hnT?KJ`=gx_=KtMTeKtR0za}`K9IE%U2 z*;xTx{(lKn`&lL9N+un9d`79It|L(u_7!)o+D0$R(#CxGI(u-29FWS!QsJahgVRoBL$EBZ%rQPu%5D$?`>Z{kTCV3WH6ijX_fV4a zbATbAJNC%p%Pd`!91Tks=tu68IG(YsQPa0E2{W0HRAs5xEQ84sqa%UBPm8@$3P+?} z0{&c_3g~AC>`OEV+a(_<5QJDQ@wSd>go~LQHj6Kq-EYaak4}Hk&31N10~$tg#xbAD zY#&N({aCgf8ipy>JIqxXE*(cnrd?Wni9zKagBnoYJo_OX77zMXml%)U&5IS~E8Qm7 zyXSfzq*>;Jrz)%}55y0$hAmmJ#1^Pc6WL`igCjR8hBqb-#wu)+&t=T|7_Zd~(dn)D zrF+s~trg(%Cj;oSG$8yF&c_l2{r6pi4$!@NwQV`|kTzrruS?zw0d2gcRJ zd4^0%(eM&uHrnYi%H})~eF30;m2a#qXxM1y?7CD}1?MHUg+mOkP=7 zy~|}1yUMmIVT9i~6a)rc%G4%OqPbI-t)Jss3f$kK8X$arE221||FWhSuiiQ(mrq&W zZQ@B%T&w{vG2WbTrgx^4RgTn|)K@#9sK$wb%<9Yj!<^q})u1V=o$83pkT6@PlG27u zkw@XhQLCa|MQoP1k$okO;>^sthNTtC#;yDII}dz6q@7B4rgKWt_eKOxJy_V081rA; zCC6;bNkw#wLcz}Dg7O5jqfRJduaRfJ+ttg*IHTuSN!3ccr0-DpstMAKJ~%D1K2@45 z!H2`SKF#F=sUeQfpQ<+6e-bg-V>7`aUq&;#?V2(X!CW%I6$9GxZkA}KsO~#?= zKN{{3Sp>mB>dqUc2x$vbcIZwgkfl4Ttk82n?Y&Vem+c6LTNf;+<67;-cEOD)w; zmfWMaIZ|0B+tJxkr$;3Zyje4b>gl7bb6;uMhn;!Bl$VSAr5)$a@^xNqRYw&@!img|wi`@}HplYBL!^g(iD+-pK?t0&E3{V-60Lz;>FrEVu| zp%43+_uhIZT!xR&VAAIT1RaUcflzW0m%Z|!<*YdG6^U28GU?A?DaL0TVm2RvHp^AO z<%r|gQoS@BhBhXUrbY3uR5k(~`N7Q?!{k;>iMi;lJha-_)|={@Gw5>(Z6)YWO3Ppq z5hp{tWT#vuCbc~t-nCMEfKhFh3*EBN@0Zlo?d{U*o>L&TV71(spTy}~mS|P?1=tpHGDKvTjbkA@8>z^i^@GW(+p`zKtJ&x zSUcWzfJu#lQGI#~df4sjsab?uVHz69>x?_-JRBW(-;+XBkCauA(e)#w6q6jpqL@?^oA>J%uHPtDya?NOQuvlp;Q4FwQNs2Ll?Wk;>milV$ ztF|vTVFV#yDRa_Kr*^43O7ixmsL!?p6}ySGkUoVCv`PbeQ=>XpLVkPRZB^eXmra6A z{Q?p_#V}l5N7C*uB3r0RZlu`;Og2UmY9C*tK~SLv0ZJ;BT*BIbYl)IHM&TYLOmBFO zAkY78uc_t2P>kixf+p1-`Kq_ijw(;;P}@~~x?*onC;vL?tzhgZZMdk92+PvIo3(L;1h>PgAU>*&Sbw0Zy;%- zY`^%4LyYN1?5=jKNq8a;S2g^7NZ^nrd)g59qWL1HZ@igv&So0UiJ`64re9oH03x;} z3p{;(QJgS$rSCAz#*-_2{=8j|_BX!5VHb0q{kBs|(deV}hTx#A0 zpE1%xSuIbzXjVbPSqhDdN^P!O0MlN>;;mti|9cadZc!6>sJ#OlVjtBD_K77bPQ|_? z(DrT4zOwhuG_YyH{G5o&yc!zm=?FQ^TY+yg7{ilTZic@f%18i1L=RrA1<56KMiyH~ zoBF_uv^c103utUoBtKu|H_oGfVi!G?f-g%|lr^oJWzOe9)W-Boqe)_`ET^owh0W9+ z^AG=e&NLUyTM8fSPpl$(`bOU12V=SIWzt}$fzKLb5|1;CuXAK%j-lYFS5J>TE-yIoZ(8J>Ur zOw`z@N*()W*hZ8rkLI|=#atMZ^7Zm6g@Q4Gw-ebhlI=XKO0y~N@IL?y#`-4>qu+xa z32i>A9KS>pxqnaEg?Sick{@ef2fj0@S2LT8Yv4znt>A>&OD#~Vrp4l}+?b)KSq~2p zj@J##xB0ayz-|z4L3CM((6tbCqCKXsDEIs<(%Y8pH@S!QUI^7CsulQOtR4+Q`?n?Cua0(tq@%c z9H{e<-vmtE0N9dENsaj*V8-Pe(6M=(hhe$!Ssd<3fr6G;3X~!qTz>_ae`ObdfTAby zVXiXXwV>&5R7T56rx5>EVODBfx9w}2BolZGUyB|GJ9%ZO?871d(d@;JOA7e(cw{zy zf2nzOqTKyt_qzWa@~EBg``g#r&{Fp!iY*uT^Sd@>71KL2*|LB6cdfVTPFmN+A{MF~ z!VAOTZCr;d>; zm~VG@D+W^4;oH<}oD-lu=^)|>38vKeBjt%iO?8_B{pw8Hj6X3n(ahFGcn5fr!Tq!5 zVOS{1yYPt{^ zVCfS^yOe^K^1%X8}&{Bu=&?b%?6jpo^s2~J;Kw&b_$Ys+2Zh@dX(uHHLJ=m6W zliT7I6@R{#RU_Fl9Vd^&`-t zp7ya2sfLcY#2M@wyQuXTHw7YfJ$7{*N%I?ECgVZbioLhKd)Y@yl(5JY@R<-pPrh9g z<0N(^F&4_-7o0pGCEz50V|g(-4O1|JAWoW8w8+!)I`na^Y{LW%uf*ANSFuejBeJi5 zQ|&OLF{!1FWOJJe<-a?72U=8!2^BhNU2A^Xo+K5j6motPxsFC{g zC1y182cS|EqNt=eGcq68(!aHo)Q0m1<84bv(@d^E7&!7jGm!=X(RI>Hb(u%hCyjSJ zSR>&nh#=HPgxb8*w&R_Gj`L9sZI3kr7NIfA%~iTzlB@xY;A;NlKRLJ_{9iS6pGdps zv|>=)c?!8P1Nty^Ueu1==PHWA+Q8pnV(Uk{6>L-P*Lp-F%XH=2Md|(t+KkhndcA&RY)>DsGhM$Pk3Vkh?R|Cuxph7~RPyGJg{--d15{eGsEQy0RGpP(F3K+aNiCINo_^rD+aK&&4jH@65g6;t3J~7`?;e|ukeE46i zMX;bW*EKQd=i^93A**nL9^bGtzM>Q>D)wq?=uNslbTnA9(m z6I6kv(q>vAM$bL!_-Qpyy6uRyi+_f_W!Hejt`}-vAjz#(>3%@8rZtaRqfIL>62g~Q zW`_pfj23w82P6Mdqbof@fmk-PgAjMRb|H2DrmY1!!Ocu?l3b=Nj&g#Re#ep!!`E*( zcc$Vo1;9b_wsD!Bw4n*0hm~x=UH)rr<#!dqEFBLh5J3xzElp6G}`_z{BU-Zm=g#*EEvh7YUODd^~H=Ii)2AmQWl7Wa3Q4?$LuM~ zAPr(lt92e6HjuKSNt#Og3O;0xaRP*tLuFuOHf=V^g?)={J3C5-@yeA0CC1?ptM_Efcpo6$h%lSj~r7rSl?gA$O+9+ejDU+|_Y5Sb{P zC0|qtj^SuJZx_M$y}x)lp-+!K$SAe?&>?FR=WnA%6B-!ydcWW-hcQH)eY)%N2~Ct8Te@|MAcf{Oo625fz4G^PdGOeLJ`S^KZ#6) z#}q!0ca3MJ*>5;0Rr!xdkCNz^&5^;&cO$sxN?A4~9E2OxT zt(WOjX84uSRbr<|%)iN>_+>+h+$!f z1dR`YG9@uiA}N=?uSi+_H9raKP*cMs)x8?E#x3q)A5A4`ClBkoLpEiQ!UevKC{a%k z>DqiskCU-@1I?dFp%2u#P>by=Wn4usV3t^_D%|ItUdNOm$w35hoC|ETfM%bY5Yf-U zARu~bLsF__z&{_NTdMB@^rKp!kG9@9yCqyoA-@eH*mxPjSHIiSdS*34Rl=1aQ$&ee zMOw-fq|rsHmw14qw9?QDFn5W!o7dfyuBDYO=J5ZR&om^BaZP7W51GD)%a~kU;?hR# zS9jB(sh8Wae3ogJ{2}0DM~{xi4d7All9JdZ0qW4eUzoLLrJ=(KyqP@Wx#FTR1D4%@QE`feXhHx*Xi7qR!0yCPItusXgPrN0 zjmY0fxpUFi!4rvklM1Rm3}(hmvYqlM*9=zCiknGJBmKN|?*$);vi&MiMTNphJnqU^ zvr#&I;-o4t(#8<$zm>y}iiG5rEQ@D~JzgZ@9aK z(5qiJ&2KRVh{XP;x_&DbcT z_xEm`EAdCrZ{Y57ADjO!tQQUfXp$)r4qBWHbM9A@iTe4w!m0v8_cgljQPnbVD39dI zG`$Wj0=s15SGUE%BeG~lvQ(l(Pl9Nb&;D1$yK6f!N^tAFQa2(Z?ss%t(x9kT1^eVU zqM$!#YHXGWk$spJ0=z`+vW;!#OHoX%u5%5b2gLTAxgH@fqcJC$=A{4gchUi~23J6~x2 z7V}3*QfSl($;?IABc?MM?5h&_fgQgiuf-k5k`$&!1flLblI=@XyU2o$@Az=2b;cIP zz^^#F!B4mJQOUP1rCJ&j7pGtDs1lo)m}d6_{^~ZSAO=g4E z6O*W>iS0WT4Fw{XXZE-Ir!y+F{yo;LTI34zzfDr3L#ytW%q*6JIC8CJ$a^rL{S0(| zMF?Hfvhwi@!a!N@WODQr^uzddcSmXLOs$9U)s^*lTfv!yK>;oP5qnYNwnr-qGI!3O zGhQh1gm6wYb+<5b7!nv*-i>^;5ie&TiAGAd->F%R$p$7s_a+q+1`mbu@sGGBY{!FE z%xD@0>jKuM5icFCm@||;B&I*9Vv81TUD2K|Nxeq4C8>-`i7^jXNo!oiy%HrSEahG; zh&Op37sVc73!z;xTuA*)nrJiZ9IUJX*WJ89s|>@7wSDItwG!>Ln)?*okDSsM% z&PjChms`*?c6Fs#*tXVGdC-zD0Z3aWvO&1ym7Fcka?U|5qnq)r;&wRkyN?Q0#u~Wf zcKu9IV2;K=7BW{Aj2VHcX`v*M!@S(e;sozRi&>a)pQ#KPgAn;l+Rl1n${C^P`cAxo zZbGvYN7n9ofgWdnh>=K{>dW4Ij@64GQB3Ep<&LvWi}lO}%8@ zrf@OB>tMgO_Yo>AHL^u32jVBqhCNF-Ewprp8ZMvNZFF|mx|%nGF`~btOtj{~_B6VT zqT3lj9&m>4iolOE?y_aHh(#{t8?Pb|cVSxQw%{wP2A#&P1HS`=GDH$60ISR*TO6K7 z1nw$9=w`}u3Bk@?{Ng|ODVDcYhadIbe#Yx^%3bU8ns6@M3;5+A-Q9VP%r>!5eQmel zn;H^9>(3-@fgWGK&1c3%F5$+8BjzM9A%@ImHr+4qBkhj8wXbxURIJDji|~5f>vO{& zdVJE{YGvsDIj26L=O3Q^^@mQeOkw*foY4cpqj-&o0d+~T^Ish2Y+2TXY*^!8TQ-h| zSQJOE14oX`$Seflr0$!$3rs!P^*z6(dMkbGT&SvyaAsPgjp?i|`;jyTRVif6E?nkx zIZW>E6}4UCfs<&(xiM?YEb%(Y3aY!EehgWocFW7GVQL0|B&ALF(w|U}DtdFvJ}NK@ zVWo}}?A>=qGDkRNEcPyjm9s;WX?smww1sJPZp>b9C61s673{9jpf4f+LvE#EY7rS( za37GjbW`RfNw|CgFBb2!%HGGGsG%hW&*u<4R6w)D04vl|RlP}Rpn}L-(YRT!s(uOf zFHi{{1Z`bXC$kWY5Y@foEGH7tMW$eJ>StplKkW3`#&OKAkYWf2z|hFjw6Ke9OQF?$ z6m-xeZa&lNN>cau-STwn7lCIiN;kO-Z)fAu))cIn(t3RnOqUHU+9Bi@d_?UjC0zlE z7XuFVujY3%I3Y1)a~ok|R;5w3Mfpy7^)WqwG`lWlNIYe+f?}&Pd}mE)$WSo(=prf_ z3~zsmTViZdV&fTeNGfp=+U3{G)j_Jt{c7RGr8@P5MbE4F7{l+cyL@y-x2f>kSp7%+ zX1{~{>A6B${gL||iLzNmS+l}g_CGdD4&wt`Lv<)CXe8lxRRYxpJ@zkFWIvq1avwc% zSaP@S@Rp%yOLh4U#?;-|G|s|V+avS`NR7wQNBluC{<;D-g*JBl5kr2eaJyY1)#99{ZjO%Qg8dXxq(vY_Lbt-L33i$OQ(i=nUGov(!bJl+H zAq^~ChTZ$|K~NvKG~Z>ch)G4YS5R>7_oc(agHLYf7mbyWSEr9}KrIg*&_kyHBOEdy z(@ASP=Q;snZ5MtyQOej3pGBBE^VP^N_||!bLQeGQzH)MreKa(ZcQ*O?<=w(4ZNl%d zOH0XdPaCt@Rf$s5gdrMuD2$3Y^;U5rOTn(Kh{m>c zuGP;~rAnzm$YlBo5g!7_Vr=q`IL<##fWhY9x{l;5S)@NR;VnxtQ$d-3wI(>KDaC3~oxsn_Y_zjtlgV21`z5|*H3`=|`?O`Mr zNPIx^X6>3IaoWOp@0Pd#5LUN)ORU%NH&9}p2WnhjCuCuj1Wqzc<f527ykOkI_os1^OoU(4^ zODglf>e8$`l5T!H;}(ilN^=$A3i-mJLnv$rWt9k_ytddvj$*0R+-O+^*9XPA z?oY{RD~Be}{i}EErd9Fx@^DSQ<=@O`tDv%75Fg1a3pMby7TPIuJ#AVY>M$6x)bKgZ zDHN<|S(5FLH>vjmcpx#~wgzc$f7v+()@i0~Ecl(X;?JGa|As2^C{>7`GOZHe=p@ma zu^pPOnAzE5@y4oqzSHi%%yHBT4m+7h)c!cNK|}h7THoY(I1G$~3TPzk{ZMwto!V`-yu}maJ-@&ONH#Q$+5R=VYwhH1_2HWme$X1-4QuKBXTg1z>eOY#@-p6fne~|_w zT{T<(Ih+r{Emdry>vrR)dC+10R>}rkTN?|b)0>4ZK)lb97#xyrB5$Q=(`bbJ<9sNT z)(IUbgkc=WG8M_CC5hpDvCOoNgK6c#p(}+XJ5U}dsa(Ap$tx4=j_N=s(IOx$I(d9?v?gmAQP0 z%}BKD$(%DHxW9ITN>hP%%r@yH1&6qxNMIg&8Dt%BF?C3C8ypQQXW+@gNb*scduq$O zZpAtnFvZRI?>jXY8_shBhYm;3s69OJULLdtXGNX~#UZ;vlb+>@*uZFhz1G_s6Lzi} z`W-=l0v#sk=z;})Vp=bFGxeNLqL`dv{sipYNyXi~i6s}jxUBS#jSze^Lmq}R$YhWi zHt!2z=Z;0%N_4Gp=z5MY##P+S=Q|IWczmOW^NQMh2r-XbV<3dww3AxmKrtN1djr+! zva3+wU^7Yjrp)l3-wGZovcEo#bv+a$2FN23*TGaRZcz4wzgo^Ev}9B+_A;?4!S(RG4r7JS)$Upv;rb7#t};|(WPh+jm$j}DAz(KJ+)}VNyvRrh#08$y6zg?Er{wv5-1~qNIe6A~w5w#uCRrT`JyUipj&)UUCnPLh zIuml*RbqJ_Pr$grXq+l2 zYFND+>Ll!Ait8GSmbm8YHv4!=rPt!5ikb-fR6mhI7K8)W=~6z|R$xf{hOLXlc@5+! zp%eT;g?Yrc5mlVo^r^{X;1vNddKr%EN!4y`7?z@&(1hJB?MQIFH2g<`UV)M*28J`U zs@EJSqB)8$-L+R7v!b06*;%6y8^2)%Z7u5Pyu89+a0(}(s-E%kskpZnN25heyZ!9&WaRjRGm z%2r(#HH-F%Db@F0r%qCQE~-sk#5`sEDI4LfB^uEfandx>$?L|7zvK9P$Dn%X?OzX( zV5fWQe`JiRF^&sa%fB`F#$t5`kz(+Lq{8DKu&7B*u-*b}taPUx2);GES)=`={;h3{HFs#%K>&i!i?`#oQ81Eq2W*Sr9EnWnoMq!^QIK{F?F$-SA{ zC03L*pkUXcK`gs`qrcQGa9A|mu?xYZiB?imY~f>)8+O=MWw^i_Wd{?#%aMM3k(3^% z_(qSdd3z>-LEsu{P?ZVB1dY+nOUJ$kT%f{VN!;qt!Z=5X19eD*sRC0wM1D$6`c>fC(Yus(h!;TW~LdzyqsHcJjo> zneW6_hmVX}0~#{1jhWGvM1vdf;0$OfF0EbxS0xzxcR0nxJZ!)_V%-bA%_AP3g9l5s z{q$O&5f?VPuj=iXa$gvZU}eH(Ch5K>3%oJIv;?EjnlJPFAyWe7oBZhbQgP>R=8jGV zgx$n}Vq)(*|0Y*|0{nMX15rl|dmkXGFw|C_2u~L4hzT)Xs@~>{y_u(6LD?{MM&ILE z)dc=^z>44((G=d_*UAXlTH>+q;ne8&?nfaAV5%xT4!}RxuYZLL&(X+hCyGwGQ7D^- z##Q0*G~UCy#lS@496jkscyE9+?z+rKdKd;HLma+XZN0R)=LpNkAU08)F-ph~2h4Yh ziWbr*72+(@9q?K%;%>dWD>b?l@C{eou#lD|z%<4OWrW|Y70n9y>lvnAGi8t9LxYW% zQ&%=xRpQ)S&6w$5?_JR4h(MBHVAX3OhN^Z)^kw(^;G3@HCL|yYT~G&SzB1O`aGf~D z=QMak19bSz*AI;--J3!iKbLm@QsDK2V&9@+jCz;p`kiEcFq!!BLWy8Il+d7#cWq`} z@6ESSu!J5-jZa!=ZqdO}t%^q!X~4dM?#)JpFJ16EjW1DQTpw1OGj?~})*s$Sx*O29^{i|nnYXg?x)S&dJntRP+Q?OofVkLgNNoEZk-NB)J^ zC7%j})$7d>`=J2(f(r5-j<+kQT1SXv^K}Cm*Whosb(UaO<|G+V-*o7==5GfN_+s^7 z32tCQ8mf2KQpJqJ7nc;kU?-9(tRHcW{<|oCR{L!CG!w2Gwaq&PD~c;eCsDDj(E5f;VcGdxbg9xU{8bZ4p-zN(HLvy>Gu@_I<@p*IQ>;dQ9kcGX-`ih01Ay*80N5$M>#7kd7qlfDjG^k- z3)wNc+eKY1+nRqv1htc{_o4R?Qw*E|sdcU1Mi9ek-Pnk##z$PNa3BGJjcLqtS((n% zV!2G;i9P=6R(<>ZA>{fK7*oYvnQxg9-fs`hnxN;J7V1M@=kRq)oqvd{=1BoGcj)Zd zzdjCrkmr(4=@HWK?OW>1*24_p(~~Bt#404?I*C%6?B;{~i+Z-^13yLjm0adm@oRf! zI-nlI%dVN-aG*0E9siZ|S-;R13DRrHtWXf*bT)(~WHXodAUMxZh7i;}^B_UNKoihe zc^JYX7@0Idx;q30e3Gt1fSkV7;hBHiyl<0PAqj#~AN(y4)698Xu!j=eG&HLQY;WKl zBgVhxLf%Bv2({Vm%&_{d#~fUsFz5iKlowzp8y!=Os;li*E3VXwjT$~A;4z?p(XwOk zxo0u>9qw;YK8%u{-XY@Mj6gFQZ?fmC`KdzCWX{9WWS?i@#{U-Z-^g$49&`a65fIRj z9uSc9|Bn1R1DxFcf#0@X!Y(!dGiA4b!1zA|{J#L;Ydt%cO^KxMI74Rl3XP()qJyi= z)ExO4_bajH`rPQ$qnaFg6tb|RA)>H;pdv4y^EgZJ+I zn@qZoq9(68inR(RpWT&{kCm{IH=2x*Y;(KDblO|Z((Tvb%3i|SY;zxf_m&F3PI%Ne zK*JsG+euY`s~HR?h8+}}+K8aS)G&%_#>B=zm0deK?`jo%ceh(8j@QqjxvA!UR!|5g0(vX`*;C39E)VfxVoXXAPWQdbUFa2QKIrMMp z`V~Bf`R6BZr{ze2{HNQw&9~NO*V1k*?1;MNH+uD^dSSg6Gc%j}4j#C_yRMJUX%TJJ<`Cc zn7jab#x8YU*B;o_QK1P^3bWieNj>Y!HRqh7u#>nbNfTAJ0GlL=A||JJe-E-cToaj| zhW@qV1^S%oEa!M}T~k9;i>;Kh9h3@>m>6gwzgq! z*iJ_o9!Y0gX0+-Qs2_BUxh8b_vaNW)R_rvbewD5}jCe4eK0y8WtLEZ4b^7J2j_CTT z{L@(&wkG{;U`9$!`ahK2Ly#~`)FtS$ZQHhO`z_nHZQHhO+qP}nuKs2wx}#_LXGCsu ze-$tvhQ=wj+U>xMY;U;_17||fW6VUFG?KLz0-$bu=pDC>_8B3S9B21>&oEEM z*5U^B{TGFCEz`4G&sz%V$DpOW#Tm9C{ZE{AQN-fFvre_sCLAOeZ>+@=Rggu6#XdPD zGXslFv`WeLQ{$S)49|8usx-W0qR$PGdG3YM3Q&_T&--Cu=y$ZLz>xr#r?Qkh>Th;* z_`Mnn{SMO<3jG^T){N=KMuvwj+D;vBl879Xov_PtdQP35C}ay*7ZmKSY_mloWZmrC z1M!cGuP+7NThoMbBCV8Rs7L4DXcA{-noUJqhEtQxS&3Hq&>Nq3XWzEnjrb{k2A^Xt zW>7=4Vv*75ZrZ0IN9x(kKiyVWkwZ~2^t(m==2Lo`rB#LCPLqiJvSc8GLHU*M@NcG% zWj6V4e!Psh>Ac&eIsWr){%tcTq0TshSt-91An=28^Y7?&SL_(UEqjS=x6M_^AZq@qcPNJ!+e^X@XG|E9SbGDmH)=ZbE%Yy(Z1LD+`$|QF>o;qL| zhnsp4dTJVxy(eZDj_-dp(-X~VyQrsPaNS7+PyAlyX0w8u11Mi*+sW{DqKC26l0P1wuk+h1?kE+Nk}mCJAr z@}ux@lH5lOvEfSJQ=7kfnp;Wlk6n@L+?`ud1~6d(VFQOZ3Fmf5kJ~J73MhP}4K{@s z+x^FSE1$g65lE-PPh;?K;nIK1Z3?#S$43j{dz{VSmpooNXyBXV^=jncl%}VDjnH=cOE-cEGF;kkcSJwC$NsykiaRL6266m^uAdqS z%2@1(IlKGI>5*?u_`aR2vdR-d5L5pKP+w&^2W1&o`=+<*uur;E1iryiA0W5!?FU3) zN3V$kWEQnT46eDoHm<+rL%sScbcXEfc4YHDC$BzB5!pGa`(0LZ~7i`+i=?sJ>60T&$szXURyNwE`?nI*2xeu#c`ewT&7dYF{+8H_}y zt9Z2%ib)8F_yEeF?dU+{ZFq+6KCehoDABX^SO;mWpp5bz@w46+P3=-YQp~hJHjSd$ zP;z_Zbr~-)B-GHaAc=Q?C9+UA+5!dVvz`7lpSd*P=Y{)#8!PmSXNK@3*e`|_Yxc1) zd!@W_!|i=^bbB5QZ*~Ud8q)ws_fj56+Vh&TVww(m>IBv*s+}W$WEel51zYlTCy$rN z9Uc*rZEpU9+c)DT*hOa4KQ8h$YQHI1&*RiT7#kjoTF7X7A!vXv0BPg@5e1`YU@wMpcnFCQ#e7L-#-7rO>zkOS#{KBc2l zem>u6sMvz)+L20b86hdk1*&& z@v)ytZ?N!wBSf>u0{wN~?QG;&q2yoWTVcY0Hu?VUwjoKl!Rn(>{4 zySl$PbFl-^I{z+3IJZ4$`&znmhQ5ae35A1^nD)<71;jt00CF6lCx6oE>L#%3wx+Hv zh}i#5lL2P=YXy(dkM{TzO)7FWwbtmgu_xrtO<>K7>C7h2ca%D9rc`Xg?mW6~q{nI8 zuE!ZcQkhs`I(J}LibUbulQ$Ab0;oRrV3gMr=6+2PJZvD>_G;P`wDEmX3Fgy#)o62=b81f;#RW5Zw74)n=ivLp<*; zaW3AofJ4T4W|ny0Uyp{8fWTF*KY^ETU5!xhHICvTkEhe_%#hZgfOuPa3_ z;{%`j-w%HVy52Uj5fLDzeU+bf(6)P8_=d4#nAFwy_e!@PKBHE&iA9Zj5Aa*45wFkh zx!qD(96i6+??jIgmeq6-oEXkdoCLbeWGIQ1i6~xLFU=1ex8mSLCb$X@yLe~tlM~k8 zc{XUhD`;*w_r-Nwm?N5P2Z-Syk?V2~WZT#kSJ&e)nc&pjg-M%pvOtv1nI@}bWxdO8 zt%wXrvB6!TcK*PClqp{KM*1;@GPT?t#S}r6@a#7>2QlMyEMcicC;_B1_9{wQYq?Gd$F$^($ckKr%f3#`i(m+@ra0;&&m_6 z3!y^LY{7%3I$830eC%0cpvWJo45$D@@KdGmq@p0Q&Wl`#L_CXo3saVL{jYjUR31=IKDNs}>2TmF3e#NVk2Txiq zxsEkw?-`}lRA$eySkGIFfkDJ;lTt(OAYAgK>U=60SGkCYcibY+RFgS{^|a-k#+kBp z*;SsnU#rdc8w*KAUryFF5YRxzfCd>}#YUaYQcu6cqnfi&aQoC@Np}vmMzv>(`~Rd^ z#@O7>jnhfMUpPtr56*=n7p9gCp)7;FJgMD-kBQN?5-2jom!GYgdU`e?u9)C zjLi}=Y$R|g%=PGSYs0nLDJV1?H#A+GE%w**$S!S)C932X_axLWYsJ+j-TpL_UM9Ip z!z1I*Xu?JQpQpJ}2kc?<%W^wi$y{s6Oe3K#O~Bjh?p`_Xd&7|!`EI>v1VdsBoAAPT zl4&4-G*gM=8fqy$N=z}U2(Q&nRM5Zl6eZ94K#OR#o~&mkeP6gZFCZl%jGa-+OT_T1H|L` zc=$JxXPbsNNWwn;Sb;q%a$x}VIMwM5Y>2=yu&pyJXpdeAu*G@43sk~@%GDSN(L-Ky z?m0ZapLc294BB9^_}#I;kC7wsv?XzPzQ1qxi=XrqeJ(6U1=fyWdz?Q0PCuPRz#QT4 z^z>{4n0N6Cm@wD0J#8LOoHSw8kl5`9P~bY8rUY=}qO_rq`e)(6#R@1U zW$57vu?6qj$ZaT^=+a(l2!X&5lQG8YyNjie0Ygs;KwAu|^IiFme$AW>Q^v@4roQ2P zM+4Gt!l2BhQhi&)gn+9gShw^T7w`-L*7}f;V^xR@bKsRiYfhCTACZiX)@m9Zw71R# ziEtsci^RCVUg-j8h^iV%r>$!m8t@G@9TN<*4(A^snxK}Q%6Kq)&pOdIp~m7 zB#vf5306R5v|ARzrd@h>HY4#ojyoC^;D78w5q^230|&y=z5VBgdJ^HTtc9dlC!M0g zAM)J84%__*0%ZhkaUYR)br#5F*3S0llTZ#LgW>Wz$V9wOlEL&pRhSqc6(9IG9iSu^ zs49l`?uga{Rl<$ksQG?HwU+t^b}v>Zf-|&O(;Ex?E-4<&knRk60>rphN(9WMq@yWW zWC+0fEyqU8azeH`xH4xxAIyHfd(rmElTyOpXAd7aGaKt}3Qd{{>qUrOlZ!_R`cHex z!JV(@7DiTu;g?ESdV?|ECquiAIi+KRB}d(WCh*-)cBrL#hSBdp`*1MK=U(|4_q47k zCyzJ)QM2h(Tu7!+$Rufqspe7xIj756YG8b-sG>z|A2pCA5x6XrQzJC6#w@3J6D<5| zto4IcABn*}1*)On?jC?C*>-_H7w>&$n5CcN94xy5voUMF7?UArLHSK@Re2tBxZP}D zyB2PIg<-tp3SJtP3u5`h`RC2V$?iN}fF$7OVhR_zVO{UU!IqMLxk|@*6u}!^aEdjY z9GS?SoE!~NK8Y%qCBh6-g1pKiiXc=ZfGOmswi0D-{5^rBM3LrEZ}+_a?#+4}*!s zy#>HLyIe^{pSE6pwLOOvnGN2p0`RNCm1D6E6oTq&7T|?pKq7^IfD97hNXz3D` zN#DaQBe%9ZY}5f#h7@2p0ft1HQAcw%ph=b{S~CIhCN1-uAv?D0ipBLRb&*B!n-3x47@!O zGLa)(kS4#$u0JDIk9BNP--mHbMTqqDxF2JNFKW5GW;Nzn{gAA6p;ee6{6tO6=JFmU z&E_>lq?~dB`52&H=IIFOoWiD_G#}@Xm#kuN^puYysVLb7`JdngO}rO=rV=~Is9mMKtqVy zClAH|=^*cDm7Zvk^8!#~vc_>$0oYbT0{bD9xCf=Wf4(!iBQOF_HXbtApaz5L991k5 z2m=MR3ojD%2zlnvt&t3AR(GGq8OJiTz({D27AoiC%46#p3ngG{gt+W|II#D>{aV#XR+8SDvsT@AzS&yoOtR3oo`P!#h!Mc6hr+C6jN06! zece!v9FbLU#>#Su#xg1$%h-V3^8RhZyEUC~$CdzdeUZBjWbC{#G0<4XSv|hw0s;if~i@Qj(g0 z>FzMid;P=DcVrejBx}eQ&uFjD;TYyy_R8D?6{W@W7ffVj+bfu#3I*^-Rrr(%V~GyM zH#Eys))5Yi{dA-mOHKK_5X?zP3lX4Scbq6FC8OnVy1I&SrZ|nNUAYZctc%`KxfHv9 z5!@^W^=p5OIe~H>1Fu$_DtxFnMKb~?Gk!%{Nd<>~Xzh~#PlXY)U0GxDTugk4l1py& z9FZKeI3`hL0ng=sziXR}xIkZy$uNqt&E#1q0zlOo2)X~fXfH#y*;CJ@6#OP@o0%+2pTwi=RmKz(<<e+qF9|DO@><_aN=QTxCZ_lTS6mec?s;6z1)#%O9Q7GbQVnW?=C1pG| ze;e6}lGjH=P06`ni9Y-YW>JhR6p@N=Z`?G&eC`a>NtscB*KXlicw1wmG|ChJbU0K% zM(EMEDBS*pLV^Tu0Bq+)wzTa(TjrJk4#AL|MGCrBj5U-9))NiZ*N2(kt3?oe@Yt2_ zH+@=!k7zBGs`NRO48;j3)(UL&IdE=DXT)$zb?1}W)&<#K(FZ8)0AX$g0 z%wKFcSn#u|m=Ouevj(=+=ut$~v%-*(W;;KZ!K~!=AMSEu;JhZ#EAE6%gnKj)v#sos zIu;`aiI?pO7C_osA{%98(S?&?Ygsx4D0lUj8=j<(Um;iJJZLmpjP!?S{J$!FFLt>MoVbRM#FCQXf)3Frr7Jkm6Flzmw`r|N9 z{5Gak|2PUH4kRy}u$q@W4{ofsLIj9gJAo@F%~83T6>`>cMjRC1kx7Yk(HNA{Y@l8Q zUiS2DxcIKsSprCfcBNxf)4z)|Nq7WHJRjvUD=^;d!Zb=piV!q=4doh0w_4|#)LU^w zK^N=B)Lw2zBYfGtu74|_9_EMi9A{=Q@rB!9D+a|Ly*oe`2K_-pnWQ(g)!zme zl+VItetztT`~^N&Nu0b0t-S{j2sb8XcYhzzY;uKeRNb69`F;kCwrnR9(CN5qz1_O; zB%@YZcn*q+Ty^A%$BVg}a->l7C2(I@gjbFmc0JGCFSP!aBL5=M-y$(XdzGOe-AL~C zT{R%@-Y1jbIId1ofupDj(Fyhw8&z))$akU}^c^V#Vi}w>uwv6Cn1*L@eQ*XvvYQAj z!b{V!X(>*GseOnm3mI?3K8f3f^$kBiS%BfULpujal$79i=Dch?q9=Aur&aZ7a(fpc z8TQkSD7XCr9ci%Su{qmhUsEyz zZ%zdpl|B-xGfFGWbybHD2{85Va143`B1!nvU(v>=NQvsH&B0BoCI^u?&PX;(SmZ9B z9`&f=e3&22=nj~YwBtenN5y72gy&zADY%jjDo00@Fqj&Sx1*7$IYt8FW=z9@C>{q1 zPR_O)Gm&j`kC<1Xa?v3-LOGA%jXvJ+g&Q|e7@PSHMMxYmQ!1*Sf@R8snF&JmYFvhn zxzDe2=M$(w=gks;%sRHqPL;`!uv}+Cd#0cFV_~ZwaU3S%%#nOi*=R}x$PcBv>hI_$ zGc-VMsSgji?GP`Of29|wWw%k?^lpm7P5#K`eH(mRqTP-p(DS!$4Ufc zyCl%`#vc3*^QdLhWFj0M>gJf-mz3fbZtiefw-k>BxnUHPb?N=HkRPwdj&c>ukQ>77 zD8miJdcYvEW6jtuDW_vgw0WAOCBbo*aID^mBq^WE-BbLU@glA8c+^8jp6L4EW9!wX zCK}l}(fmMA#&YW;C_F8#wdAihbB8O64Xa0xojQ3R^6Dn~0i+Zql3<_!L;#nggE>en zwK{RrQHx5?gP|+rf9p@RATemlwvHcDUt0g<`@>dDArzuSNSd4GA}q#N?BR#Oy%i~} z@TJ9icwI*mUJHTNF5pz}44v>X0+ai$E9T3G_@ZU4t}U>6Wn{pRvSyNs_PCN@wrRfg z#KkAl`c#%)1r|wOCOQ|AkQ){@uMv^KxY=?PUsbo4yx3V{(VRuIAQY;_j9Nu;XPnA6 z)kKJLC0LtQNWcfxns_~IL!F+obqB@cAaSVD?p5t9S^2seWk>Y{E5Ow|iYKQ~9WVY4 zB6+o!+zwx))^I!1J2v4NA#|Zz>6R>X2*)7O1t;IsGj>xhB&z&S=knxSm>&WylhpE$ zyQe=INx4b1ra$|X__Bx9L%T`TX!l&OwWq+DxiGfZf)qRQad1EtoKqmhjR~5z-X2@1 zT?m?QYVXicYDQJv=Fb*LQAF;fiJiI7)(b}z5rK}6NLs9D%2+i#vGvEKygx{xKx`Mq zRvfiDh@6cQBp7X$$zhoHx>cMx!un>?FdD2q;9K@5S+h50)(~_|$cM%aA1;HA35|Un zl}RRx?K-{+@z-MzAu>Za=_^}ksyTTDw~b8}CMPNp&l=V%FhvFZRms|L;perVA8>4l zpfpEc(#a<((W=)iMuMZT^ z4w3%S5qI}Ar)t?Mr{XJD(;NR)r${)xUWPG=u9BQKo=*!&CR)8YpST?uuy`##iEEPK zWas@F=BJRpaV;9o_;RY9!-uzZz7GCqzPx;9_?YX>c?Pwy`b=*NfeUa~>8+Q&ZBA#6 zhnu-Fv_$nv$$3rW_qfM*11p<3PB&C5TAYr0dlzKj}zYr`af2(ZX-$ADRIzYKUHDSB_7LFZKDh);+X>O5Hnf-D?`P+aVfG zcp}(vFiD&WtjnqY`(iA$`ToGp#hjotD~vfCGHMS}yLxDc9e+xoT_38SVfS4B@2B}f zXW;qEO*i2p?dNAGbj+`8D(Vc0+69&;*P8T_-&4nNC1?1cTSNMg4&=P-8N4@H-hWPa zZt*r`&e=D5ce4`Wp0aG>WM-5ryQ*Tk+b&ryyjPniGIS2 zphMCZ6pCMmg<{p{sxz@gr;qbPDtP!^iUx4G@0s>R5(_qGl>3}?C7 zWpQ0Uu8f+2Oji}Y4+=j;iD#^AxfkTJU|9^YHtxoDN0NsnWi?-DU39HJgU z8SIzf*;2#&sL>}Fd@(_^QYjR^8~d)@K5CvhR(+LDjbNTi9`+`!$5o8q+28d4JDULT z|DtsN>2&|+(ESgy3GDR$2ci4lkN$tsUAH}f3_l?NfTPX-+&E*W7dAIBa8@=qF>(IC zjk6hEtN$nBkO$vqs9Ng;kXcB3;;2PBA+^wGSf!fkf|j(MN-gR?tS}r2f&qXs664tS z^T`?nC=r?XwEpjgi-aLAH`mu~ZvH8^qRlh8SkkkG=!Fn_w>(Kw1?4j1jMqyH{(VI> zRlX>~1JZ7fw2kX!kl{J>`MQfnxzAn7g$wunjcsCzv-ywT{Te)MHi?9GgdsY=2uF<-X?#a45YS0h) zL`wd-S(X8|$wN~rOb_0|z&A5RGv%mUg^->^rDoMxH@PMi%beLVA59asNM$5kvL>-n zL3!9%Wu9R!(U~J-O!G$j=qT;k&aC?g@)Thrya$*y3!ZFZzVLBqEUE8Bo=;c%yE$I=LGr`!kC|6_`iL@zB6o;W>E5~b}te9s9w`8A3gguGMU;Def@>A7beze7Z8r< zWw}h4m;V4K>~CRs=@ty~p$4hiC7QL6NHSzra4s5FZ)ykbu={dzFOAq8#AX8x?0j0{ zWDaq_ui`R)N7l&137k<50s=aHO_BQq{SS3Qf*-|HT&i!c52csU%+x9*e<9Q-Ks#wR zChnz&TJzUW4j9C^=XOO1O4eFK*UO6w>p*j%UZCOwtO^GUU7UmQcAra>c^{f!r+;EY zS9 z3k6O^o+Krwg=CDtZH?UEPm~6pg7lSwO7yX}LVxh*Jnz29cb=Yh_vqyzKNLGfGDiw9 zUvy~>3Bh>&bAD^>lC0ry+QwB1K#w6@>(l2k6eNQ~vZnWY@JU%x&1Rw%3* zEqmc4_z|ew5UpEmk)f>2@9tItUh6#VK4Lr;#Xcy3pd`6nT4#3-e{O&SypML`mVjtLrJH$VRmX>djs)?VLsu^JEDtyIu~_6?f_+@K+t6T;nQJUzH2@a zL6N%;&>dcF2!irH9Ssm|hE{#QfEk{S@J*Fk)G|hgI`!>~WnoN9O`9 zwny^59W-X)bbE&jxYwQwnWszX&FDX%4}VMmycN&0(MTD7I9B^{q4a6X)w9fjB^hFES@Xe5Dfc}9Zw!cg-Xvzq2b6|_XgobE zz`=#c!NK#KIp>sD3$T9$DEYR4iTHXh3rhUo&8yl7`aF+{A=U>Gm&PiOX#F^jd%YBVOdN(wH)ou8%6mov!`hc5J z@0wS_NYkwzvi;dRNBrOrhQeW1*mvvV1ivONf3=*knM@~2*^Mf#P%tsxhx~|B0xto+q<6%UILpnMkjyYM z;&5Ae1{%jp1<Dph2Wc~V_+z{ted}*Re)^oCqe$Ju|DzDuUVJxROc2gYaD4a0Aaug zK*5?N*I$!&;hYtiCZH%VXd^IoPQQcD+fzT<9s=hCNo1r4B6A?Pcf6K2s4TW)@zvV| zX!5qg>Y$lm01cC+;&z$9lb~_tM3j*k6sS6J1dmrWC8ZQTKZj@zZ(dtQc*a2mp&H{fdX?T#E-1hiNbaf7kKLJGIc9g4cUw1h|O=E zU6dmhM`6u`k|D@Pns>urs)7hlC1X*Mh%uk)cZKx`0mKv%a3!UrZH2xmlw3gp-KQ{B zHnt53Uxx@sCxkje(I| z+`0yvUl*r@T66$V7Yc$Byl%5NWVM!GhU=L+2ispo>|B};s$PT_S{t{}ao&69wny<3 zO4t?e;8^gnns!V6p|C;Z;?WSi5>EKdVC&zaa z20il$)UzfZ7GGN!8|7PJPD&Rr|5&pO%U!k!4Oi5JMKEU~0Zu#oZPZ+qI3}4M#l$rf zBD9;n$Z#eLKoV8K8~Q6)S2w~I7b9Wc1!eAUI&sU-8lpUF^G>UPpd|Khu=Z$=m-ZCb5Y;+7$r>t> zo)Uoc+FyAH40rsvLx8u`EjL%gJ?!VwMmb4bh@xAxd zxcKe(nU)xzqj>K+)1%&Y!dzt3hwKct0&csp5BVsgDHlv%me}QeMb52>LCA z`7RfW*dUr1XbLRN@DZUe7YSC`!s5$pfGE=QXOxmSBT|*Lk60EQj`xfvUhfGBro}N%vQFCTmfmqaHcZeabLK=xt z19tg%GuC3~oA~2*IE6U0i(AsgoFYm|@9q)|#A<>|r}lC=+G)UVG89788B-6}wEki& zocBokX^8eR484N&O(JFV1yD^n%Uq?cSunw8W6uAkrDM23P+HgEy!a7SHR-xm`qV5N zjVi+mlmG{qQqhdhX7WNniNMGu#e8o+-;St+(R6nelq@~2 z(Xnm<-a8+`a;o!u%%%zA7bDWKbG;+MEHmc#{1(IY0wES3YiD-hZNyHU34isubWV1x1GO`$R}NI)fyg z1PtNtzeVPO3rZqZHg;Nsq03N--9%-wvlW|IabPS>MZsX0z+h}4`v^w_QiUkQnW{qC z`QUaCaH8uv`1MQV%Qj{E2PD+aIi@Lg_0;d+CHSkMutD_5B>(kxZ!lCPum^G-rl9`k zcM8y59*@|KZId-T-!)IcOVxope3}_HlN~eojb8j@rjnBBG<=eBAygnMBMTVRB%#w^ zyG8EgV`JtTTSS0Oll#=%dHd?=l|NuAj%yqB086A;MaBkn18oEn9RS9D5YeBp#6U+9 zpgt{7bRb8qgh&ZP!$FN_3fWTi#$dEFEPs`^XTs+v=x95Y7vuwk=A#uvl6dt@!E-U8 z9Q6iJy{Kq2E@xi_tx_~OZT^%yKL)B-Bfu{Fw@*pmA!WfBu?=RNqjx|M&6GZtKMfjF zYLOqE#YJ&c@Q6JBFW;Dru-bG5dUjKLsGk%XwByK?;ywot14?$WW@y43HXjc-T^jxt z3tNB}tzOQDqHaJyOnyxQ6faZ#m5S4S1PQF2*+S`#8H@(cEQ}^G>)3?7H>TexYHub< zo&Rh2=uQ6S{f8Qh|J;3cw$SVNI`)Ig&KxwF$hoiaJ2W~3RIDBYmZSj9lgU6{z#d>& z6ImXgDSxSIm$QDsu@E-zKx;a|=#tI*2kVrY$ro%)@8vpZ7_f<3RgX?E8CQ&`gax9H$i=$BP~NBAS0EMvXW|e zzY#j2+BKC+J#C#XP7Je|cA(EM#zh%?U_kHSN=!hs2Kg|(*@T7R)_PnyY?RLCQj&4- zq39ifTF7V!f4~h3c1(6%b)VR&U=tcn`jxT2{aVZ4&rKbZuOQO4*5{|P=2;iJ$>N@n zl*)S8eo&=H!K;9j3^_%-QPOql0n0pzto`c1JH)!}Z8B6lLvFxr5{>J&8enVY$^7E4 z5R0KoPg1*vCHh_uve527xb(66->#EFbLd;Ok!h-26}7Hr9I^t6iM#QP*~o>nD%}qmWDNpBJR6(y`8fQ|S!}9c;F!{#5oGou zxBBIw{8lC1z^X&OOJfy?3~73KYZ;JcGc2hth`heV$ZpqN6e*i^*JrxhhpdXo!A2Y`f4o@DQH_}#my*X)j zq-sr>t@9(V`ej1|#0R@n771v71phvPSRfeLv+TK=qn*=Tr9{5TvuU5~XbOMWP|?8H zl{=E8)tWnlgXRu#St%QfRz>X^(f2(1wtBuRsA&$|HH)WQ>bA>a4FzFJ_#($HVuD^w z(`Wn0;?3pAaM(Gnq_$oomi#Xyz%n%AjM9J1hoqj61|0ecmc(~e%Zw7uK57+3#>5=KR z;0#_vdwXrV#>B^r^r5>IX3}v6W8K9hU@DLGEB(?48=XQx)*(+`s;lZnF}@R8h3*4M zKsxZzZT~+WC_cX@Wq%n+j8@{(mxl2>HVv9uBmy}5Q6J~uFIB{ zx3L1sr1OZT4<8AkDF+h{L~;WYd;j@}n)S(KLG=fHy_SYZWc)$4qNU?hLSjOu7E36V z1GKPOWpafDqavu9A~OzL96m>patu1rI&l3WC`@Im5VFsQ7Bf__epv2j zK4&lTJ9+*OhKq|io0g^_(iEhrP%`nlSiy8%aNGggIGedB`wFa_}y z)rI$Q#np#lG(m-xHotk}YnDd+JyK7kuel1gzkU7SJqdM{f>1bK5Y*5w8@yY*sil!h z0#LYtK_YU|2r+EvOt6?{fOfRmEl_uABuC3Xv!HEVTxMLRrN!BIuheBos*sM zkn;nM6B+9)Z^^RzpuoU?8M(!3U6y8=%*d|RJ;2vAxc_-*D#C!#LYeJzn2U;`u|g)K z^$*7Z?u?~b8QGo{^LwNt&`Lh{1W|dWr-(~BhEaI z^%N3o^Ty}hIA0Rz%`|W|@@5(V371$cSvN_AWL7MN)L|l7CpfbENl2j_u%Cjv4P1#X zvP&a_q6Dq_d)B=vRa4y}1DH;=E*81}e#{lu}{8<;HTF!c(#mJ~VukJ*Y9ynI9`> zK)N!ikpLT+MukqB$wr?Bb$@HWlBql00e}2MgaQ3EcPQ3+NE7+Ge0emCypZ1jjR8t! zuUS>DGXdz)fGI|t^ARsgoL^b#6Q`bcOk;@#3*)ZU;H*uoDE3tX}f&jn{6*5s2~D5Czgy zF6-Xeb#Va%vJ1Q9`T^S{IGY$oj%)~DtfMX2Api>lcv=v0tTgh1KTChM#Hc3!1U*;5wMGhEh1=sbU83;o|vA!TfgM zdJX+(C1CyDtb>T9@{L* z1tI&2;O>#DpFsuq_jB(rK*xdW1H3TPw%!rh1=OrwP6+JB35A}Z(Z9brf53ZT@ra-T zR>k$Nq)n%^Xv%P)ZCB113WNL(Y8cf~wAbahS3q&E7kHoHXnx3;smhT3L9*i2$5+he{X+()0H&rf z7;eveCuBB_D*j-PdZ|x!EOdf5K#vn#M))q__ypoTEJuEOwyPr5)1>wK3tk>vonw*! z;F#smCmLH%|9xj*(Mu76S`4K-k7v<8NK&~~!V`~$Tq7^P`!aI<=*=8Z7i5az9U}}Q zlqui9E2GHf$?jMg1U;=96{8yW`^dLk(UmGiPOW*0B zkbD_(xw415`j~_?Hb|;GN#+`h%jI-`fX_^0IdqvWUnb~TniK&vGuhosbqahtLoO?r zB2+b>(cmjrp6R|cLEvV1{^j7DIFl+HY2h6AP9h`96qZO87M66Znp6yG^s%{}jD(3* z%B8MCUskMJ{SBJhEBA8-M$=#b2;gf(84dT(F)NJpKp00TbWAJeaRW)d1vYYzM@Ebc z#pc<{#ZnLHH(%Ps8aWHv!`b`ke!W?c_5y7c9A&XQ?h2+eR;X8>NoP)&ME%t zm*1HGy1_3u*{zr;(fz7hNmmM)GpZ4}=GM!GtZA@jNu_E2ZKdM2PNvfhnE^K+VxH^V zU=)`Nd?pQ7rb(+;_T07ZX>GR3vXVzL^TQq^^1nK~Q}j~cSE=IO^$JZ8d5>IpYNG@v zFanJRHH`EZ>Drfvtu9KFL$UY=JXE=x20+YzYAg;dgkt55pr#OG6VrGu4*q4Hgl2$X zsAV3xraLTXtRg3ms8&Zd90j9fI41{|o=k{OorQ(#LmYExd}aF&JbfqYUY~pT zp9#(t(-Bk#3q>5 z9qy?7$<7~KCzq$>)(6mfM-PnxvYgc!e+!`$!+re--E|E8n+^2FtEyy}Bb0|wyzQTQ z$AJKx8YZti^j^E{+tsO!`s z2ktAjC5xtatnH9_pgETL`dZyuJKEa*4MZKDbwA%}x?P57wx$jge6H+5t#`kN*rq0j;`c)pWHDo8>VjOubyXMd^EaEvckl>W>`$_!xJ?isSkx zVMl40IW{jx#e{&}kge;U%K;jHyG8nJtj!CdWH5%DYVvlOX3WNn~lb zY1eOpra|F0jZ5VvBSufqIgM#xNZwLNS&@YxPYS((?vW{FMjjesG_YN47-ie$&HAAcT}lTapSSsI-l1U*^OWNX>yF?sy8wROZDgsuZrXKCf$i zr2i8hSNMs@L+OxPHyL(gOh(+gM?$|}UPk-wqJ zk2==F;iEfUYN7b8EH6LapcZ;)>M1)m|7A$+sjHvwd!{FMim$q$qFbB^@8=^MdNe67 zcccf4$Ih$G%*oJSy9N^!%1YDeP9X_z(M$9zWF^fn_;(O1$RO1}`!G9bxgS4w@-ug^lgG=H1x2KQ&d{<&=VrW-QI%mQAZKB!f$$EO)=0zM`8YJE!7e+?098&Sqp@pbyU zWUb?NX}74WOtNGD13`uxb^;>gG+9;@3py{LU_i`svXlb=cWc&Zz{3fADFlLM;WAUy zkpSN*Nx(M}sdb7igu_9jS3zX^6!~&+-g_+%odO(&03KHVB{4#R^ z1XF6%5kwANVCfU%bmSZxj9c!t)nQeqZM;jQiAI-_Xxa}g4TB=GgfufiLU(%TUj!hk zahtNyQo2+?5{+2k+(D$f6sy6CGHOK+{9gy`xXFsGJ)i94Z;oe=r_D8H_lI7mhIh%2 zqw-gu)7L3A54Qeo-Z3y!wGO=~NZYmJbxg!bd_&Pl?LIg&S0sutL zR8WV}n6?^RD3xidtx`Oks?fA!kMvqY{y!==Xtk>mNB2VJ?%Hg5GIEm}8b-A#HJw^# z%8%)ZV7gT7tBZlxnvTKBkI`Fw3Ru;7aT?SxJT&Hok^{&cYxqA-riV^G+%bP~dR_a1 zo|{r#>vd|*z(aCvyT5SRCL=zdzHk>A^M%_uwH#|8X=r(Tn&#_;c<(E~P4*b#W%tRg zi!<0~ilj~ONfo2XjW7SUkOZ$rTQ>}{UD)0OXsrn<;H{uq9Vak8=>&a4+NbE`{FDS5qi`)+uN})OlS7(l z)(+M1Q!peF#p4IS9xV7KZBqa3V|3j*IHU^-&Rb2zvZEqF-|1QQ(|c=ujH4?sgw)^- zdycsoFD);rwYOJf| z)yVS8)LT|yTMTQv8;RG>o7;q^C$cey$IJrufez%kvZWKb`bmq%+j%N{12%&oKB>`O zs2fkAWiy98Xj<)4GD!BAuJLfU8@NSy+IXE7>_fX?v(i{B44>8T+Zr4tY_b#k*fKj{&5 zkaG8nHC`E`ZUV+RLB1U^iw($mn2&(ig8KJ}3>E1!@o22KxFl9f`C69iq-uwyUKFC_ z8R$1b_VsxZ(O&0dd4WXhb*Sug&Z`q?F!qHI5fuht)#{L8Z3dt49vN1O$7CQ(pxsFX zKVN;8JZB!9zkUCQd0C@Q`0XBoEkD~)C|_a>XM#nWoo;k|=woncFG|0Alm0b;()|ib z3nBoiop;ozMN0C79ON5_q8*8uWJQ+KQQ7YYOfjM9uhDqt2MB<6aP}$z9w%Qk>AG!e ze679OLpiVrzvR(x)0ih|jprip!%rNa$F9+*t5U(EF^lXyUP+(t3k-zGme-ZL>3u@a zPRVB{I7|K3o?%Pn2jy0HsBczB9LU7gRzyE(gV?zQ*I3NxH z;B*=gfb)Nx`Vh9Wvl9C6{@?M8)lchvbE#}Uc zB2!I7r_ zj%5Y&&Yqfe&@SlZFK^zuUOH(q`C)(U-5$Rp{tUWv;g>vkw`!s)OKjU@vszs`XZO%7 znzqo)ebi>4J>%7$g153xWjU=zB^^CK3vHvGmX^%*s~&M-JFDm2R?%doh36Kj^pumb zyv2%2f06NY`Dp*+NAOEbvQlB?+jW-&PDirA9eQZBECow_eQRlR^7t#R>>8VEO+jB0 z=K@R&Z=cQ0PRkk@hr_Wz#a?qQLm#>}iV_mX;wToXmt&>dIwJg;%q?B!-brEvF z{ucmEK(fCLZIfRW*of)2c!wcRcP$pDS=PJNoYs&gkON1`+~OLq$rQ`BtgCd8J%9P=KPS&0U;g;=`_pX5)5w!-vzxBU**Q&++UNJ`1=b0z z%y?WQ+JmcnJ6{z|{*r)b*0(k|9uI1PMPH)Pfn9O)! z=Q^%qqYTLA?!b+5gi!}$#Sqflx6{idp9)@GrU%gHw6L|(u9VnDDXlI)sCQROel9Jn zmBw>Axo+xALOR1f0*c0YXCUh`!XgcLY@O$RQAWH-c!idRw=6t@FW(j0Rh`d!4j!{) zkXG&AG0LE!H^g&j2gd1(nm8PBZQ6~zZHa+^a+tCGWmj%_OAiSJD=%yDT-VQblp4M+ zZmoE0iQ5y81j*BPAwm5w{d?dxB$z}k3)k-X4x!U^n-;a&t*6AwLF3yiF#TrSp`nZU zeDHV${+GVTYIdLUpDnE@ov!f3VRzVzoH>J(qc zkL9et7u7hutm%$@Pw(V(h;~ik?n+{$)2&{(Yi_2Q)ti_jeqeLtzNX*K&uP`a z`Pl6uQlraTR_HpfL~P-e`T&(mw>{?{7jt@95JxAzBZvP|+ssqFHuUKz%{QBZZ>-5B z)&Q~&#(kQR^fcSnjjn-xlHTW&2$6(`^FSBpO`Ff&KCRkfyCBghSeB3G2XPA#Ylt5y zm+0IVZ^~Z_J5q87b*`OPyJk6%$2{;aX%*!?K7JpV9j`40;Ws}X(|x?%J*v^EnOqKZ zn4W#dG(vCiAoT`_huY8UU(}V&G352380&a`Raa+SaR36ulx0midqnitbS`Lb=p)*l z$+A4#(Dagd!8AhR%bwo(vs{A{V)jo}sGQMh<2f}gi|TZ!n`Mr(MC3+-FtJa69_cW* zxHeg?UnMH7LD=*{kDPcK*JM|13*MLc#Hf=$Ga-*;SK<;?o72#Z1Gx4Z2!Z<$Cpp6MPGGT(%m($LRdN_#4FQ_jTqDaIh(URCwOCw!7 zA&zzm(p^cy__~nWi#pNf#!6?8NE_G|ZSe|iypbj%`39tXfkP`V4djp0v?{JA(l-c8 z$j2TM<>~7U5#XfNQBLF{bvIF(>f;yq{pCVFY6ig@%64SV*t7l_KW*)NH*&zMI<09@ zx1w{1Cev^;esDvG&j+24gJXDnX%3Fu-GOU)6t74BDjd7+I^!AXBIyYZ*)ZRGxLi6? zJn{FUVGb{|PP1qShoo%ms#WOtZuobD@X>sFKEBcj4p&8JFell4f~ZdHh`iGy2` zM3THH-nTed@{DiIJ-^ZLA3Q>SWET#d|0L@pJ}5pU&(3$EKCm)4!Y1MJ>~2WLnj;U4 z3E)j>3Qr(ol6YLzt-lH?(e2yoTBcm!oy47cnF1toh@^|XFpJr;E~#~z$3*1>T#}P? zK+98aHZ^gygf*{Sg$G1K$xB*9T?MGQIOVlnhP0>JG|f?#h*z%B^`R9MYDt97X@bvL zO_x!XyzqM&Y$UE|bGf^6A;=~swSp0ucx&=dbe{Mmg(g`*$m_yjUE~0BWZ~%gU%l}#CWrlX_vT1n2d{~>1E*N_D?Q}A%-bfiF3bc2gU29vG~(?U z(*J}}k`B#k0G*oRJsq1i7p72GVRI@#-8@8C1&i(A%iu%f#?*MRot0`jq^;%#yOPtB zZBe989A9Fo=_zwsVjN95Wo{y;J`|-|Cq*y#YiCm#l;dKY=EZbhwU{cQV;Se%`>01!YGFjz?{g%{6|Et&e(|G zkJ9WVT{lmNNoK=zP8$5IC1yqZqXjW_I%1YY%#rDe?Xi&Jgc<|86SGI|vw`6$>NBSemD++1IQqd-mTh__;aGyY^V{KaKMagBh5JO@2G^B zA>{FdG=wupZIG_HL+JENrcD#&F}hWKU2K_f#V)|o0Mk~nWt+CB^SA)1k9xb#S$=R0 zkudc5ZMNR~@g>2JcV9dr^HnaR}M9;G6A}?3=(x1f?Fv~@v(ixXtkbPSb@yoc~ zOvf12k3>7~SbJ!V>hl%R;JU~`pWEUVTgIomD8dQ)0Ytwvq7aMpN(^DmZiP|GCPC_(mWEd)+%CRnS=8QbHrt{Rc}w?%Xv0l} zEmyGYcp*vUarY&Q^L=}lXmd1->m@V4V{Nf{jiup|jXk)hSmI?#f!j_*;#{*(SZufT zmgM%x2S&1xHYmyoDKK=i;%;MC3?F_b-7_(S!llMS!aFa@D&v%gQLzO5~ds?RV z#pUBSmjf0Tz-Z0bhWmX{*S$gp{XR;+ubB;cWh{{2(W$*Dikk3dIdejMv;>*GlZl4P zU(=3S%UO8nh*p)Q5%1j8+xEa4$BXIC;Mmix8bhPo9&4kwea75^8@R8NhaiRpK4)Vk-8z;xwYyOFgKKOc+o-E6g;Wsd+J_0Y&x7@SwKXqp=!3Wt{%sU{L7x#$e zZOV1IV*7vbp4VBLqK#Q&37M@Na;yf|02|_tEsXEvU}^lLe;Gx3KOhbcjuUNaKF^0qM-;^3)T|IGljmRpjIjw~~YzMfRY`!>DWsmH#_ z=PS136nklxeaFROK|B~|=Fx9|OXRqseNr83h^zhXxR=SmW!JwQzsZ$ zB!Ul9h@JJcdPF6AtQq_W>FKGd9_$&?xC(b{)!=m?4VAtt@VC=bZ%n3kVg>; z^)}hU62(+UR}8Q3s;bUhRm+{xn#&?dJUU?JGPMeHTy0 z@(Y4RXa#RK@2cB0gX-<=*=8eeykD<|I>+yK=4*?1F#UI4_{4_YS0Q!Xy%iY zx0}C|&4!s@R|Vb3q(E$UtKwWZ%7+ILYaLjPa2zAyWd4*usADy%36&PH>TgOi*PW@pw(d6KcZ1lchDxz z+q58c8co!DI=;gsc~Vy14yEG(J^Qc0*G|j zvX|B(+F+X#L)w&8u2rGdnk}2V@Ky=07-?c=mZamKW1`+D%@oSRKm-v4NNSa?8B&#b z7DRz!3iG5+#~4ri^a9_*ZZl^CY+min1t4m^_6CU{=L-raBi9-8JcBc2+6z(D7LxH5 zTf#T_dR@%rL(_cBkS+2r@0U6TI2?*5POP&qq5Ieng0&ubWu=KnAo?qzN zMmrCQ>%dU*_aHf+3cDrp{?HgfS|txB1wzqCY*Y_J5YeJn$cBd0=WV0>0z zy(z1=H<|fh-EU|&2K+M9S=qA9O#Tv^`WCy@YQlCnjsY0K;@AC8_&ReD|2kq3R%LbL zhr)5vc700!n_!PW*bOZr3**iMq5qyxzup$AvL>$}R-5f1=4QfbmmC^cUA4=-V;6`| zW%&*VVnF)-ttN3ULP%)ZSLPcl8?bi7!QDBdJz5jnqpN3#6MroPo|F(_%Vrdah`3ly zea)}m(pjGKM*#z%&)Y3qJ(EU>PYgbRJ)_&=Y+e$(X=lqYXjG+DZ@q|Y+;2EkXwISv(U&(v|DQ>j`qDp- z{KPCSVN870f}z;aE!^6zXleY!crp_0EW=~3ls3aJY6oNdMoTk@zYONpwDa?GW@y#b zzzs7TpIYTbH+#zL!?;Zm%6aE_LEch-Aott5E%w&o!KP7siD^yX7Wlx6I?Qey&{y26 z1_9kf7QOu)`A>hxf&22|UIVY;L#o&U903ovbDmTl;3SvgfZgM(zE_ls6O)k8gE|QlxwUT@z>qPWBr^YESq%>x|}BA<=i`6layZMeVB8iPa;OChqN9#2wz{+cM|) zT{uQnXvP}mhtm{;1g%;ElfO*+9SQcFW|BAb=0cpVL4Z7akhW|f!5SN-IiIG@-;5L7 z=4M;d{ji4PmM^hjB}po~T5{OgZUax#w4g;R!WD2aEf6KoAP_feTv3osl_Toq!Sut6 zKvM|fIQUC$$BFy0c*OKr*Wyr=5)QyR&E*bZlGRbujl1SP>7Q3y7M!YIR+2W*fL;INPQVINFJJ2(!Ps)4zurGK~tA>Vt#$; z;9k6X>I`PoiY%H=fEJAjGKF4yU948nRE;0<7gOPZIItp`@nGo&DKHc4#W=;agCWz< zUCL1)>seM9^W!CmpGlE4G6_d zl0J)e7E(Rzuej`-mCC~Le98~^<+8gxK@H$OR1MBeL{gVzpAnEslyc3H86upr6SE0i zOY)+mma#V<|1|a~Kg9|uUa-)hcZHDG(?z_Y?zo9o3cm?!WG;zl6h!M|(SzU=etR#M zhD6S>|AkMXI;iXr5*63msVtgfcUYcI_uVCOQ`)MzN&@GYcYqz*($GHbG-iRLN+kkW zlz!1U(@jxxATH@OTUBJrg^ZtraKYXk4{W1D4>RLloat)B3iU??|sF za)zx_NJ0Y)M2TqmyeB@{koRjGy06U}z(J34YtigTDT50oJUt0VR_oFHzFfe5+wwO5 z8HRqmY{r)+;?A_@bN2x!+F85?wcG@Zu`y1wcI)fD8w-D8LmHisoXFI?#dsA2!pwzF ztgwSK3x*6hZy)n^VGw(1D&QB0GLe)+CE=oio5amJh*|B8OF^^36p>-b!RQ4{{W#X< zWeII~7Ox&&FP1MgTNX&hh>6u*@^(k@H6f>?A|4%X#b85sN4^mzoMsT3%4x#0T&npg()2mx1%aerI@<$8gWtLNvl6uDPiJZXlJq?$3YsZ((!t8wBe~~EX7XQ)H zTXS6rk{}wFA?vjM|H$7-@cyo1)q}YNuT;`KIU;Srpu?&p#saAiR~;JǠc-%eSQ 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%0D?6 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

    Ig$0)u{*|j)N&> z4D!yHEfZ4HRYHt@M^YY9dtx-RYgB7Y&0;=DUSbZDq5kU2>Zz!P!Q!x~&pIpiz3GzvoEm;IczM-^(h8w*@2Kp>wEf zP8w~;O�Q+iUE6vB4Sr;a!giQ zMCE~srHpaPNjiGHzQ6*re8iQ=94d5poZbMc{`{u|Q4_F?c!WB6slz{zKRa2`GU*-# zqH$D9P{|=eM~p@=99~f~^;2L8t^>-wFj?RGHsKzB>x=UJq+O^y$varE6!s|NU1MX5 z80}xOfD^Z}W6yncEF}jlBv-XX zHl()M&-KcA>XE`KiVTo)@*7i|(rSZPho_>baD9VhRw&{os;2>qj)+g0>dTuQNhgUR zi1O|_K?dpV%NU6s!chM;ilJ+Y+Vz~Z=KKTVL_E$+cB2V0V1`%aIMY*6K)x=uYF3Qx z3zR3PPhUifOj7&4fDoc^g;jWP^1wr=umR;EYrZ#9nN{q#46X!-9B$AN1xLrA7Q(>1 zQE*Xra^&)%!>D@rTW~KeLf@}Hb7MOMcr4mKCl4BOplJDK`1|-+OEc=purzDX(7P_L zRaw{FBcm;|=8#L(nJ`R6O16rdR+gHs;Lfa=!h( z)^68P@=%XG%?|_hfPvq_#rAF@JxULjQl`!G`Hn5OIlI-#>i&ZSb~G7UvcqeHSY-!W zu-L%6Abtp-gg?XLf;LDhazAfvT;89Plr6$6qO1y-i`hW`g^FbveU)UeUCdpo#I@+m z8hSu{wB8Yw{hr}JN--cTh@EuBLRcmE!rn=WSUxF~3{X%o7Z36mKJ_h4(JUHik9fr% z?c+ZeF@*S6|7%~)&D*atyDka;1^>>BPpezs+lgObMHx^q7$6`ZD4<8B8%fKggo$1_ zAfQ50ARuudXdnv*2Mb#>S2Gt^I%hLmGb0x>IwpEfdPau-dtm2aV#8o%Z({3aYQ|vk zKfC`~>FgYw&FG9wT&*1JUFa>$Wg=~jN-uI;cSk?m%0>G6}AF5P;-KZ{PN@?&s{rKB}MnKxo2$hwJC0=y`mLrqV7Ou@KjBK+lg&Af3`8@O}kb^&4U#AZK&Fe6(KBspld}*%3O2mQp z{fhexL!|=~@uTfBknQ5=!t#QDr1L4M56@8ez$Gk;*-{V&E_wc7<;&bfu( z!*pgGptHGgN*@+=Dwn%wD)40RcriDI4@a`M_vjfSjiu!i?-+Ow{BsgtZlJ3HBKTj2 zsD%$-lU`CGHGR(Jc%>V6!#P)4+ii!tgS4@oz%!Dlsq;L!@b2&p*Bh2oqY~xR_cpsJ z-={&kCjv*I!+)fdl*V^%?uwG#QX9lbkC5Rm-siH}Cui%Sch7B$b-t}0XYV!-u;9kA zem!q?mZkPGbb)wPBu?JId<6!+a3WW6l`S_03Ka`p>%!T3WTNBc!7blWZ(ice*6VeX zSC&L_UQHakj@|~R9WqZWw&?vkq@LXtZ@7F>My-b0ZpNlL$k|T5iw##p*^oNCIs3u~ z+;{}eFHUVR{=XAV$%_db>T6m%Ia@V)jn zR&1Vo+DNdl{DY2H1%qPi&kv68TgR(Serqtd%XbVv6Ug|n$TxV7yF^mm(+q*Q;1k^< z&*&8?vu8Y(j$hjBTWt8akjnt!9>tj1wMp$9Lp1pyGI|ujS#aAVXZP+}GqQ$xB; zj;P5%{Zy*nKC=nkQ%ZbAabuaosWA(RmKM^bfnSR*>AqOoLcQ9=?CjFGT}OzS4iaug zmZu1)O<7(AS7#_f8N{xgAi9$63sz~MxJcTw!m2k4_%@!QYIA7dFgL&Em?3-606XNR zUwW9(a{#)FTK`7+0aJ-j5MmZM_sPHBUo`%4?0~nXQH{fz7oX;`yiM3zh%E8SDOBug8y{yua&EDX= z8~;PL8g1fLdojkg*zT7`NM_&cBKy}oi44F!9E3zy^+RbSsHO6*5hmp0i&W;att36a zsbcI?uIwE@0dGb|DmhByOSD? {5r+^kP;`!)M?DBl#?`||I#(9|aDq7ap67xmer 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%0AL1y05G$&GqW~v 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

    &%{1#rcq?Axs&ee2QX& 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 Qzy4MAOj~F76ioAhR&vQ?Y*~=B+nH6E#4*>T_3 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 From 15a5883ad241373fd8e9f81b1fad9db099589e5a Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Wed, 27 Nov 2019 14:06:27 +0000 Subject: [PATCH 0256/1594] [Java] Upgrade to javadoc-links 4.1.5. --- build.gradle | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index 2f58c95337..00b9af7a68 100644 --- a/build.gradle +++ b/build.gradle @@ -22,13 +22,20 @@ buildscript { plugins { id 'java' id 'idea' - id 'io.freefair.javadoc-links' version '4.1.4' apply false + id 'io.freefair.javadoc-links' version '4.1.5' apply false id 'com.github.johnrengelman.shadow' version '5.2.0' apply false id "com.github.ben-manes.versions" version "0.27.0" } defaultTasks 'clean', 'build', 'shadowJar', 'install' +def checkstyleVersion = '8.26' +def hamcrestVersion = '2.2' +def mockitoVersion = '3.1.0' +def junitVersion = '4.12' +def jmhVersion = '1.22' +def agronaVersion = '1.1.0' + def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() @@ -127,16 +134,16 @@ subprojects { jar.enabled = true dependencies { - checkstyle 'com.puppycrawl.tools:checkstyle:8.26' + checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" - compile 'org.agrona:agrona:1.1.0' + compile "org.agrona:agrona:${agronaVersion}" - testCompile 'org.hamcrest:hamcrest:2.2' - testCompile 'org.mockito:mockito-core:3.1.0' - testCompile 'junit:junit:4.12' + testCompile "org.hamcrest:hamcrest:${hamcrestVersion}" + testCompile "org.mockito:mockito-core:${mockitoVersion}" + testCompile "junit:junit:${junitVersion}" } - checkstyle.toolVersion = '8.26' + checkstyle.toolVersion = "${checkstyleVersion}" compileJava { if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { @@ -461,8 +468,8 @@ project(':sbe-benchmarks') { apply plugin: 'com.github.johnrengelman.shadow' dependencies { - compile 'org.openjdk.jmh:jmh-core:1.22' - annotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.22' + compile "org.openjdk.jmh:jmh-core:${jmhVersion}" + annotationProcessor "org.openjdk.jmh:jmh-generator-annprocess:${jmhVersion}" compile project(':sbe-tool') compile files('build/classes/java/generated') } From 2db6e74ed0a4071cd07302210048475924eb0a63 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 29 Nov 2019 13:28:42 +0000 Subject: [PATCH 0257/1594] [Java] Use skip method to advance reading past var data. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 0d42ebd77c..182c0bc702 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2503,15 +2503,14 @@ private CharSequence appendDisplay( if (null == characterEncoding) { - final String propertyName = toLowerFirstChar(varDataToken.name()); - final String getLengthFunction = "writer." + propertyName + "Length()"; + final String getLengthFunction = "writer." + toLowerFirstChar(varDataToken.name()) + "Length()"; sb.append( indent + "builder << '\"' <<\n" + indent + INDENT + getLengthFunction + " << \" bytes of raw data\\\"\";\n"); sb.append( - indent + "writer." + propertyName + "();\n\n"); + indent + "writer.skip" + toUpperFirstChar(varDataToken.name()) + "();\n\n"); } else { From 18298016fad51aaedd38765bce175ecb16377174 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 29 Nov 2019 14:20:27 +0000 Subject: [PATCH 0258/1594] [Java] Use skip methods to provide length for raw data summary in pretty printers. --- .../real_logic/sbe/generation/cpp/CppGenerator.java | 7 ++----- .../real_logic/sbe/generation/java/JavaGenerator.java | 8 +++----- .../sbe/ir/generated/FrameCodecDecoder.java | 3 --- .../sbe/ir/generated/TokenCodecDecoder.java | 11 ----------- 4 files changed, 5 insertions(+), 24 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 182c0bc702..5da9d8f8e5 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2503,14 +2503,11 @@ private CharSequence appendDisplay( if (null == characterEncoding) { - final String getLengthFunction = "writer." + toLowerFirstChar(varDataToken.name()) + "Length()"; + final String skipFunction = "writer.skip" + toUpperFirstChar(varDataToken.name()) + "()"; sb.append( indent + "builder << '\"' <<\n" + - indent + INDENT + getLengthFunction + " << \" bytes of raw data\\\"\";\n"); - - sb.append( - indent + "writer.skip" + toUpperFirstChar(varDataToken.name()) + "();\n\n"); + indent + INDENT + skipFunction + " << \" bytes of raw data\\\"\";\n"); } else { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 8f3ac6c796..cbd5a6a31d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -836,7 +836,7 @@ private void generateDataDecodeMethods( indent + " final int headerLength = %3$d;\n" + indent + " final int limit = parentMessage.limit();\n" + indent + " final int dataLength = (int)%4$s;\n" + - indent + " final int dataOffset = limit + headerLength;\n\n" + + indent + " final int dataOffset = limit + headerLength;\n" + indent + " parentMessage.limit(dataOffset + dataLength);\n\n" + indent + " return dataLength;\n" + indent + " }\n", @@ -3277,10 +3277,8 @@ private void appendDecoderDisplay( append(sb, indent, "builder.append(\"" + varDataName + Separators.KEY_VALUE + "\");"); if (null == characterEncoding) { - append(sb, indent, "builder.append(" + varDataName + "Length()).append(\" bytes of raw data\");"); - append(sb, indent, - "parentMessage.limit(parentMessage.limit() + " + varDataName + "HeaderLength() + " + - varDataName + "Length());"); + final String name = Generators.toUpperFirstChar(varDataToken.name()); + append(sb, indent, "builder.append(skip" + name + "()).append(\" bytes of raw data\");"); } else { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 4082de62c6..fc30fb7bb4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -298,7 +298,6 @@ public int skipPackageName() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; @@ -410,7 +409,6 @@ public int skipNamespaceName() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; @@ -522,7 +520,6 @@ public int skipSemanticVersion() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 97be0c0658..cb9b247b50 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -616,7 +616,6 @@ public int skipName() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; @@ -728,7 +727,6 @@ public int skipConstValue() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; @@ -840,7 +838,6 @@ public int skipMinValue() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; @@ -952,7 +949,6 @@ public int skipMaxValue() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; @@ -1064,7 +1060,6 @@ public int skipNullValue() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; @@ -1176,7 +1171,6 @@ public int skipCharacterEncoding() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; @@ -1288,7 +1282,6 @@ public int skipEpoch() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; @@ -1400,7 +1393,6 @@ public int skipTimeUnit() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; @@ -1512,7 +1504,6 @@ public int skipSemanticType() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; @@ -1624,7 +1615,6 @@ public int skipDescription() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; @@ -1736,7 +1726,6 @@ public int skipReferencedName() final int limit = parentMessage.limit(); final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; - parentMessage.limit(dataOffset + dataLength); return dataLength; From 7aed4e68323e264cceedaddc2cbf492e6ab8108c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 29 Nov 2019 23:36:59 +0000 Subject: [PATCH 0259/1594] [Java] Upgrade to Mockito 3.2.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 00b9af7a68..7bc4f68488 100644 --- a/build.gradle +++ b/build.gradle @@ -31,7 +31,7 @@ defaultTasks 'clean', 'build', 'shadowJar', 'install' def checkstyleVersion = '8.26' def hamcrestVersion = '2.2' -def mockitoVersion = '3.1.0' +def mockitoVersion = '3.2.0' def junitVersion = '4.12' def jmhVersion = '1.22' def agronaVersion = '1.1.0' From 08fadca08cb4604cf28fe3dd6039bf4a959897ee Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 2 Dec 2019 02:39:31 +0000 Subject: [PATCH 0260/1594] [Java] Upgrade to Checkstyle 8.27. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7bc4f68488..9efa81140a 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ plugins { defaultTasks 'clean', 'build', 'shadowJar', 'install' -def checkstyleVersion = '8.26' +def checkstyleVersion = '8.27' def hamcrestVersion = '2.2' def mockitoVersion = '3.2.0' def junitVersion = '4.12' From f12de25301c01e2ee6f7463c3e91a7690c3bb69f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 4 Dec 2019 22:37:20 +0000 Subject: [PATCH 0261/1594] [Java] Declare that shadowJar should run after jar to avoid name conflict. --- build.gradle | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index 9efa81140a..840fecc3f8 100644 --- a/build.gradle +++ b/build.gradle @@ -203,18 +203,6 @@ project(':sbe-tool') { testCompile files('build/classes/java/generated') } - jar { - manifest.attributes( - 'Main-Class': 'uk.co.real_logic.sbe.SbeTool', - 'Specification-Title': 'Simple Binary Encoding', - 'Specification-Version': '1.0', - 'Implementation-Title': 'SBE', - 'Implementation-Version': "${sbeVersion}", - 'Implementation-Vendor': 'Real Logic Limited', - 'Automatic-Module-Name': 'uk.co.real_logic.sbe.tool' - ) - } - sourceSets { generated.java.srcDir 'build/generated-src' } @@ -262,6 +250,18 @@ project(':sbe-tool') { } } + jar { + manifest.attributes( + 'Main-Class': 'uk.co.real_logic.sbe.SbeTool', + 'Specification-Title': 'Simple Binary Encoding', + 'Specification-Version': '1.0', + 'Implementation-Title': 'SBE', + 'Implementation-Version': "${sbeVersion}", + 'Implementation-Vendor': 'Real Logic Limited', + 'Automatic-Module-Name': 'uk.co.real_logic.sbe.tool' + ) + } + task copyCppFiles(type: Copy) { from 'src/main/cpp/sbe' from 'src/main/cpp/otf' @@ -309,6 +309,7 @@ project(':sbe-all') { } shadowJar { + mustRunAfter jar archiveClassifier = '' manifest.attributes( 'Main-Class': 'uk.co.real_logic.sbe.SbeTool', @@ -507,6 +508,7 @@ project(':sbe-benchmarks') { } shadowJar { + mustRunAfter jar archiveFileName = 'sbe-benchmarks.jar' archiveClassifier = 'benchmarks' manifest.attributes('Main-Class': 'org.openjdk.jmh.Main') From 86ec8bc0f20afaadbe5d2807b92e09f2551c5c00 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 4 Dec 2019 22:40:32 +0000 Subject: [PATCH 0262/1594] [Java] Depend on build only for SBE jar. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 89d6661e97..b155db5453 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,7 +119,7 @@ file(GLOB_RECURSE SBE_SOURCES ) add_custom_command(OUTPUT ${SBE_JAR} - COMMAND ./gradlew -x test -x check -x javadoc + COMMAND ./gradlew build -x test -x check -x javadoc DEPENDS ${SBE_SOURCES} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating SBE jar" From 3642aa995c3e9690ff0f10f1f21ffb0f1b5b1fd1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 4 Dec 2019 23:10:50 +0000 Subject: [PATCH 0263/1594] [Java] Depend on assemble only for SBE jar. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b155db5453..280d233d51 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,7 +119,7 @@ file(GLOB_RECURSE SBE_SOURCES ) add_custom_command(OUTPUT ${SBE_JAR} - COMMAND ./gradlew build -x test -x check -x javadoc + COMMAND ./gradlew assemble -x check -x javadoc DEPENDS ${SBE_SOURCES} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating SBE jar" From a3fe73a5e64f49acbefbd8397a8bea1c356810e1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 4 Dec 2019 23:12:33 +0000 Subject: [PATCH 0264/1594] [Java] Depend on assemble only for SBE jar. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 280d233d51..4b544810c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,7 +119,7 @@ file(GLOB_RECURSE SBE_SOURCES ) add_custom_command(OUTPUT ${SBE_JAR} - COMMAND ./gradlew assemble -x check -x javadoc + COMMAND ./gradlew assemble -x javadoc DEPENDS ${SBE_SOURCES} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating SBE jar" From fd20a132dbfb8aac7ce094b24462fa83d9531eb5 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 5 Dec 2019 23:37:59 +0000 Subject: [PATCH 0265/1594] [Java] Upgrade to javadoc-links 4.1.6. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 840fecc3f8..b8036830d9 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java' id 'idea' - id 'io.freefair.javadoc-links' version '4.1.5' apply false + id 'io.freefair.javadoc-links' version '4.1.6' apply false id 'com.github.johnrengelman.shadow' version '5.2.0' apply false id "com.github.ben-manes.versions" version "0.27.0" } From 35705cac9f284c89af20c0f3d97c756d4c896356 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 12 Dec 2019 06:13:12 +0000 Subject: [PATCH 0266/1594] [Java] Upgrade to Gradle 6.0.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 55616 -> 58702 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 29 ++++++++++------------- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/build.gradle b/build.gradle index b8036830d9..619c5df071 100644 --- a/build.gradle +++ b/build.gradle @@ -790,6 +790,6 @@ task uploadToMavenCentral { } wrapper { - gradleVersion = '5.6.3' + gradleVersion = '6.0.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b3885f6930543d57b744ea8c220a1a..cc4fdc293d0e50b0ad9b65c16e7ddd1db2f6025b 100644 GIT binary patch delta 16535 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 Date: Sun, 15 Dec 2019 05:23:20 +0000 Subject: [PATCH 0267/1594] [Java] Efficiency improvements to display decoder. --- sbe-samples/src/main/resources/example-extension-schema.xml | 2 +- sbe-samples/src/main/resources/example-schema.xml | 2 +- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 3 ++- .../java/uk/co/real_logic/sbe/generation/java/JavaUtil.java | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sbe-samples/src/main/resources/example-extension-schema.xml b/sbe-samples/src/main/resources/example-extension-schema.xml index 3255bb6fd4..df1d6bf53c 100644 --- a/sbe-samples/src/main/resources/example-extension-schema.xml +++ b/sbe-samples/src/main/resources/example-extension-schema.xml @@ -65,7 +65,7 @@ - + diff --git a/sbe-samples/src/main/resources/example-schema.xml b/sbe-samples/src/main/resources/example-schema.xml index c251dbe55c..b4a39e7ac1 100644 --- a/sbe-samples/src/main/resources/example-schema.xml +++ b/sbe-samples/src/main/resources/example-schema.xml @@ -61,7 +61,7 @@ - + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index cbd5a6a31d..cd54c209a3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3203,6 +3203,7 @@ private void appendGroupInstanceDecoderDisplay( Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); appendDecoderDisplay(sb, fields, groups, varData, indent + INDENT); Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + sb.append('\n'); append(sb, indent, " return builder;"); append(sb, indent, "}"); } @@ -3383,7 +3384,7 @@ private void appendToString(final StringBuilder sb, final String indent) sb.append('\n'); append(sb, indent, "public String toString()"); append(sb, indent, "{"); - append(sb, indent, " return appendTo(new StringBuilder(100)).toString();"); + append(sb, indent, " return appendTo(new StringBuilder()).toString();"); append(sb, indent, "}"); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index e277875c2b..7bbf264331 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -58,7 +58,7 @@ public enum Separators } /** - * Add separator to a generated StringBuilder + * Add separator to a generated append to a {@link StringBuilder}. * * @param builder the code generation builder to which information should be added * @param indent the current generated code indentation @@ -66,7 +66,7 @@ public enum Separators */ public void appendToGeneratedBuilder(final StringBuilder builder, final String indent, final String builderName) { - append(builder, indent, builderName + ".append('" + symbol + "');"); + builder.append(indent).append(builderName).append(".append('").append(symbol).append("');").append('\n'); } public String toString() From 81787d952484ba306abdf55700dc41a65095d066 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 16 Dec 2019 14:11:30 +0000 Subject: [PATCH 0268/1594] [Java] Upgrade to Mockito 3.2.4. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 619c5df071..0d9a097ca2 100644 --- a/build.gradle +++ b/build.gradle @@ -31,7 +31,7 @@ defaultTasks 'clean', 'build', 'shadowJar', 'install' def checkstyleVersion = '8.27' def hamcrestVersion = '2.2' -def mockitoVersion = '3.2.0' +def mockitoVersion = '3.2.4' def junitVersion = '4.12' def jmhVersion = '1.22' def agronaVersion = '1.1.0' From d0241d9638cb4d74bfb5b72cd823ba198974dba3 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 18 Dec 2019 11:00:29 +0000 Subject: [PATCH 0269/1594] [Java] Track the initial offset on codecs so toString() can be safely called at any point which allows for debugging. --- .../sbe/generation/java/JavaGenerator.java | 55 ++++++++++++------- .../sbe/ir/generated/FrameCodecDecoder.java | 15 ++++- .../sbe/ir/generated/FrameCodecEncoder.java | 12 +++- .../ir/generated/MessageHeaderDecoder.java | 2 +- .../ir/generated/MessageHeaderEncoder.java | 2 +- .../sbe/ir/generated/TokenCodecDecoder.java | 15 ++++- .../sbe/ir/generated/TokenCodecEncoder.java | 12 +++- .../ir/generated/VarDataEncodingDecoder.java | 2 +- .../ir/generated/VarDataEncodingEncoder.java | 2 +- 9 files changed, 81 insertions(+), 36 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index cd54c209a3..fbbf8e16fc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1940,7 +1940,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( indent + " throw new IndexOutOfBoundsException(\"index out of range: index=\" + index);\n" + indent + " }\n\n" + "%s" + - indent + " final int pos = this.offset + %d + (index * %d);\n\n" + + indent + " final int pos = offset + %d + (index * %d);\n\n" + indent + " return %s;\n" + indent + " }\n\n", javaTypeName, @@ -1965,7 +1965,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( "\"Copy will go out of range: offset=\" + dstOffset);\n" + indent + " }\n\n" + "%s" + - indent + " buffer.getBytes(this.offset + %d, dst, dstOffset, length);\n\n" + + indent + " buffer.getBytes(offset + %d, dst, dstOffset, length);\n\n" + indent + " return length;\n" + indent + " }\n", Generators.toUpperFirstChar(propertyName), @@ -1978,7 +1978,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( indent + " {\n" + "%s" + indent + " final byte[] dst = new byte[%d];\n" + - indent + " buffer.getBytes(this.offset + %d, dst, 0, %d);\n\n" + + indent + " buffer.getBytes(offset + %d, dst, 0, %d);\n\n" + indent + " int end = 0;\n" + indent + " for (; end < %d && dst[end] != 0; ++end);\n\n" + indent + " return new String(dst, 0, end, %s);\n" + @@ -1999,7 +1999,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( "%2$s" + indent + " for (int i = 0; i < %3$d; ++i)\n" + indent + " {\n" + - indent + " final int c = buffer.getByte(this.offset + %4$d + i) & 0xFF;\n" + + indent + " final int c = buffer.getByte(offset + %4$d + i) & 0xFF;\n" + indent + " if (c == 0)\n" + indent + " {\n" + indent + " return i;\n" + @@ -2064,7 +2064,7 @@ private CharSequence generatePrimitiveArrayPropertyEncode( indent + " {\n" + indent + " throw new IndexOutOfBoundsException(\"index out of range: index=\" + index);\n" + indent + " }\n\n" + - indent + " final int pos = this.offset + %d + (index * %d);\n" + + indent + " final int pos = offset + %d + (index * %d);\n" + indent + " %s;\n\n" + indent + " return this;\n" + indent + " }\n", @@ -2094,7 +2094,7 @@ private CharSequence generatePrimitiveArrayPropertyEncode( for (int i = 0; i < arrayLength; i++) { - final String indexStr = "this.offset + " + (offset + (typeSize * i)); + final String indexStr = "offset + " + (offset + (typeSize * i)); sb.append(indent).append(" ") .append(generatePut(primitiveType, indexStr, "value" + i, byteOrderStr)) @@ -2135,7 +2135,7 @@ private void generateCharArrayEncodeMethods( indent + " throw new IndexOutOfBoundsException(" + "\"Copy will go out of range: offset=\" + srcOffset);\n" + indent + " }\n\n" + - indent + " buffer.putBytes(this.offset + %d, src, srcOffset, length);\n\n" + + indent + " buffer.putBytes(offset + %d, src, srcOffset, length);\n\n" + indent + " return this;\n" + indent + " }\n", formatClassName(containingClassName), @@ -2155,10 +2155,10 @@ private void generateCharArrayEncodeMethods( indent + " throw new IndexOutOfBoundsException(" + "\"String too large for copy: byte length=\" + srcLength);\n" + indent + " }\n\n" + - indent + " buffer.putStringWithoutLengthAscii(this.offset + %4$d, src);\n\n" + + indent + " buffer.putStringWithoutLengthAscii(offset + %4$d, src);\n\n" + indent + " for (int start = srcLength; start < length; ++start)\n" + indent + " {\n" + - indent + " buffer.putByte(this.offset + %4$d + start, (byte)0);\n" + + indent + " buffer.putByte(offset + %4$d + start, (byte)0);\n" + indent + " }\n\n" + indent + " return this;\n" + indent + " }\n", @@ -2181,11 +2181,11 @@ private void generateCharArrayEncodeMethods( indent + " {\n" + indent + " final char charValue = src.charAt(i);\n" + indent + " final byte byteValue = charValue > 127 ? (byte)'?' : (byte)charValue;\n" + - indent + " buffer.putByte(this.offset + %4$d + i, byteValue);\n" + + indent + " buffer.putByte(offset + %4$d + i, byteValue);\n" + indent + " }\n\n" + indent + " for (int i = srcLength; i < length; ++i)\n" + indent + " {\n" + - indent + " buffer.putByte(this.offset + %4$d + i, (byte)0);\n" + + indent + " buffer.putByte(offset + %4$d + i, (byte)0);\n" + indent + " }\n\n" + indent + " return this;\n" + indent + " }\n", @@ -2206,10 +2206,10 @@ private void generateCharArrayEncodeMethods( indent + " throw new IndexOutOfBoundsException(" + "\"String too large for copy: byte length=\" + bytes.length);\n" + indent + " }\n\n" + - indent + " buffer.putBytes(this.offset + %d, bytes, 0, bytes.length);\n\n" + + indent + " buffer.putBytes(offset + %d, bytes, 0, bytes.length);\n\n" + indent + " for (int start = bytes.length; start < length; ++start)\n" + indent + " {\n" + - indent + " buffer.putByte(this.offset + %d + start, (byte)0);\n" + + indent + " buffer.putByte(offset + %d + start, (byte)0);\n" + indent + " }\n\n" + indent + " return this;\n" + indent + " }\n", @@ -2400,6 +2400,7 @@ private CharSequence generateDecoderFlyweightCode(final String className, final " {\n" + " this.buffer = buffer;\n" + " }\n" + + " this.initialOffset = offset;\n" + " this.offset = offset;\n" + " this.actingBlockLength = actingBlockLength;\n" + " this.actingVersion = actingVersion;\n" + @@ -2440,6 +2441,7 @@ private CharSequence generateFlyweightCode( " public static final java.nio.ByteOrder BYTE_ORDER = java.nio.ByteOrder.%14$s;\n\n" + " private final %9$s parentMessage = this;\n" + " private %11$s buffer;\n" + + " protected int initialOffset;\n" + " protected int offset;\n" + " protected int limit;\n" + "%13$s" + @@ -2468,6 +2470,10 @@ private CharSequence generateFlyweightCode( " {\n" + " return buffer;\n" + " }\n\n" + + " public int initialOffset()\n" + + " {\n" + + " return initialOffset;\n" + + " }\n\n" + " public int offset()\n" + " {\n" + " return offset;\n" + @@ -2514,6 +2520,7 @@ private CharSequence generateEncoderFlyweightCode(final String className, final " {\n" + " this.buffer = buffer;\n" + " }\n" + + " this.initialOffset = offset;\n" + " this.offset = offset;\n" + " limit(offset + BLOCK_LENGTH);\n\n" + " return this;\n" + @@ -3043,13 +3050,12 @@ private String generateStaticChoicePut(final PrimitiveType type, final String bi private void generateEncoderDisplay(final StringBuilder sb, final String decoderName) { final String indent = INDENT; - sb.append('\n'); appendToString(sb, indent); sb.append('\n'); append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, indent, "{"); append(sb, indent, INDENT + decoderName + " writer = new " + decoderName + "();"); - append(sb, indent, " writer.wrap(buffer, offset, BLOCK_LENGTH, SCHEMA_VERSION);"); + append(sb, indent, " writer.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION);"); sb.append('\n'); append(sb, indent, " return writer.appendTo(builder);"); append(sb, indent, "}"); @@ -3152,13 +3158,12 @@ private void generateDecoderDisplay( { final String indent = INDENT; - sb.append('\n'); - appendToString(sb, indent); + appendMessageToString(sb, indent, name + "Decoder"); sb.append('\n'); append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, indent, "{"); append(sb, indent, " final int originalLimit = limit();"); - append(sb, indent, " limit(offset + actingBlockLength);"); + append(sb, indent, " limit(initialOffset + actingBlockLength);"); append(sb, indent, " builder.append(\"[" + name + "](sbeTemplateId=\");"); append(sb, indent, " builder.append(TEMPLATE_ID);"); append(sb, indent, " builder.append(\"|sbeSchemaId=\");"); @@ -3195,8 +3200,6 @@ private void appendGroupInstanceDecoderDisplay( { final String indent = baseIndent + INDENT; - sb.append('\n'); - appendToString(sb, indent); sb.append('\n'); append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, indent, "{"); @@ -3387,4 +3390,16 @@ private void appendToString(final StringBuilder sb, final String indent) append(sb, indent, " return appendTo(new StringBuilder()).toString();"); append(sb, indent, "}"); } + + private void appendMessageToString(final StringBuilder sb, final String indent, final String decoderName) + { + sb.append('\n'); + append(sb, indent, "public String toString()"); + append(sb, indent, "{"); + append(sb, indent, " " + decoderName + " decoder = new " + decoderName + "();"); + append(sb, indent, " decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION);"); + sb.append('\n'); + append(sb, indent, " return decoder.appendTo(new StringBuilder()).toString();"); + append(sb, indent, "}"); + } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index fc30fb7bb4..17172e39fa 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -18,6 +18,7 @@ public class FrameCodecDecoder private final FrameCodecDecoder parentMessage = this; private DirectBuffer buffer; + protected int initialOffset; protected int offset; protected int limit; protected int actingBlockLength; @@ -53,6 +54,11 @@ public DirectBuffer buffer() return buffer; } + public int initialOffset() + { + return initialOffset; + } + public int offset() { return offset; @@ -68,6 +74,7 @@ public FrameCodecDecoder wrap( { this.buffer = buffer; } + this.initialOffset = offset; this.offset = offset; this.actingBlockLength = actingBlockLength; this.actingVersion = actingVersion; @@ -586,16 +593,18 @@ public String semanticVersion() return value; } - public String toString() { - return appendTo(new StringBuilder(100)).toString(); + FrameCodecDecoder decoder = new FrameCodecDecoder(); + decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION); + + return decoder.appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) { final int originalLimit = limit(); - limit(offset + actingBlockLength); + limit(initialOffset + actingBlockLength); builder.append("[FrameCodec](sbeTemplateId="); builder.append(TEMPLATE_ID); builder.append("|sbeSchemaId="); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index 9a3ed53b7f..837bb0ce81 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -18,6 +18,7 @@ public class FrameCodecEncoder private final FrameCodecEncoder parentMessage = this; private MutableDirectBuffer buffer; + protected int initialOffset; protected int offset; protected int limit; @@ -51,6 +52,11 @@ public MutableDirectBuffer buffer() return buffer; } + public int initialOffset() + { + return initialOffset; + } + public int offset() { return offset; @@ -62,6 +68,7 @@ public FrameCodecEncoder wrap(final MutableDirectBuffer buffer, final int offset { this.buffer = buffer; } + this.initialOffset = offset; this.offset = offset; limit(offset + BLOCK_LENGTH); @@ -522,16 +529,15 @@ public FrameCodecEncoder semanticVersion(final String value) return this; } - public String toString() { - return appendTo(new StringBuilder(100)).toString(); + return appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) { FrameCodecDecoder writer = new FrameCodecDecoder(); - writer.wrap(buffer, offset, BLOCK_LENGTH, SCHEMA_VERSION); + writer.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION); return writer.appendTo(builder); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java index e3e8501eda..7e43a9b990 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java @@ -199,7 +199,7 @@ public int version() public String toString() { - return appendTo(new StringBuilder(100)).toString(); + return appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java index 8026ff8562..ffacea8c31 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java @@ -183,7 +183,7 @@ public MessageHeaderEncoder version(final int value) public String toString() { - return appendTo(new StringBuilder(100)).toString(); + return appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index cb9b247b50..c47860a4ab 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -18,6 +18,7 @@ public class TokenCodecDecoder private final TokenCodecDecoder parentMessage = this; private DirectBuffer buffer; + protected int initialOffset; protected int offset; protected int limit; protected int actingBlockLength; @@ -53,6 +54,11 @@ public DirectBuffer buffer() return buffer; } + public int initialOffset() + { + return initialOffset; + } + public int offset() { return offset; @@ -68,6 +74,7 @@ public TokenCodecDecoder wrap( { this.buffer = buffer; } + this.initialOffset = offset; this.offset = offset; this.actingBlockLength = actingBlockLength; this.actingVersion = actingVersion; @@ -1792,16 +1799,18 @@ public String referencedName() return value; } - public String toString() { - return appendTo(new StringBuilder(100)).toString(); + TokenCodecDecoder decoder = new TokenCodecDecoder(); + decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION); + + return decoder.appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) { final int originalLimit = limit(); - limit(offset + actingBlockLength); + limit(initialOffset + actingBlockLength); builder.append("[TokenCodec](sbeTemplateId="); builder.append(TEMPLATE_ID); builder.append("|sbeSchemaId="); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index 569db5d0fe..dbbc2a74ad 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -18,6 +18,7 @@ public class TokenCodecEncoder private final TokenCodecEncoder parentMessage = this; private MutableDirectBuffer buffer; + protected int initialOffset; protected int offset; protected int limit; @@ -51,6 +52,11 @@ public MutableDirectBuffer buffer() return buffer; } + public int initialOffset() + { + return initialOffset; + } + public int offset() { return offset; @@ -62,6 +68,7 @@ public TokenCodecEncoder wrap(final MutableDirectBuffer buffer, final int offset { this.buffer = buffer; } + this.initialOffset = offset; this.offset = offset; limit(offset + BLOCK_LENGTH); @@ -1539,16 +1546,15 @@ public TokenCodecEncoder referencedName(final String value) return this; } - public String toString() { - return appendTo(new StringBuilder(100)).toString(); + return appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) { TokenCodecDecoder writer = new TokenCodecDecoder(); - writer.wrap(buffer, offset, BLOCK_LENGTH, SCHEMA_VERSION); + writer.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION); return writer.appendTo(builder); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java index 9f79e9153b..fdda13dee1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java @@ -121,7 +121,7 @@ public static short varDataMaxValue() public String toString() { - return appendTo(new StringBuilder(100)).toString(); + return appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java index 3c8a5d279a..f15f1828f7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java @@ -112,7 +112,7 @@ public static short varDataMaxValue() public String toString() { - return appendTo(new StringBuilder(100)).toString(); + return appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) From 20c0369b9593e0a0c89394feada3cab19a36c38e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 20 Dec 2019 08:21:29 +0000 Subject: [PATCH 0270/1594] CMake formatting. --- CMakeLists.txt | 72 ++++++++++++------------- sbe-samples/src/main/cpp/CMakeLists.txt | 3 +- sbe-tool/src/main/cpp/CMakeLists.txt | 20 ++++--- sbe-tool/src/test/c/CMakeLists.txt | 4 +- sbe-tool/src/test/cpp/CMakeLists.txt | 6 +-- 5 files changed, 51 insertions(+), 54 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b544810c4..4382ee30d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,9 +25,9 @@ project("sbe" VERSION "${SBE_VERSION_NUMERIC}") include(ExternalProject) include(CheckLibraryExists) -if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) - set(STANDALONE_BUILD TRUE) -endif() +if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) + set(STANDALONE_BUILD TRUE) +endif () option(SBE_TESTS "Enable tests" ${STANDALONE_BUILD}) option(SBE_BUILD_SAMPLES "Enable building the sample projects" ${STANDALONE_BUILD}) @@ -35,32 +35,32 @@ option(SBE_BUILD_BENCHMARKS "Enable building the benchmarks" ${STANDALONE_BUILD} unset(STANDALONE_BUILD) -if(SBE_TESTS) +if (SBE_TESTS) enable_testing() -endif() +endif () # default built type is Release -if(NOT CMAKE_BUILD_TYPE) +if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build" FORCE) -endif(NOT CMAKE_BUILD_TYPE) +endif (NOT CMAKE_BUILD_TYPE) -if(NOT DEFINED CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 11) -endif() +if (NOT DEFINED CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 11) +endif () -if(NOT DEFINED CMAKE_CXX_EXTENSIONS) - set(CMAKE_CXX_EXTENSIONS OFF) -endif() +if (NOT DEFINED CMAKE_CXX_EXTENSIONS) + set(CMAKE_CXX_EXTENSIONS OFF) +endif () -if(NOT DEFINED CMAKE_C_STANDARD) - set(CMAKE_C_STANDARD 11) -endif() +if (NOT DEFINED CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 11) +endif () -if(NOT DEFINED CMAKE_C_EXTENSIONS) - set(CMAKE_C_EXTENSIONS OFF) -endif() +if (NOT DEFINED CMAKE_C_EXTENSIONS) + set(CMAKE_C_EXTENSIONS OFF) +endif () -if(SBE_TESTS) +if (SBE_TESTS) set(SBE_THIRDPARTY_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/thirdparty") ExternalProject_Add( @@ -85,26 +85,26 @@ if(SBE_TESTS) ${GTEST_BINARY_DIR}/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gtest${CMAKE_STATIC_LIBRARY_SUFFIX} ${GTEST_BINARY_DIR}/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gtest_main${CMAKE_STATIC_LIBRARY_SUFFIX} ) -endif() +endif () find_package(Threads) -if(UNIX) +if (UNIX) add_compile_options(-Wall -Wpedantic -Wextra -Wno-unused-parameter) -endif() +endif () -if(APPLE) +if (APPLE) # -Wall doesn't enable everything we want to see add_compile_options(-Wsign-compare) add_definitions(-DDarwin) -elseif(MSVC) +elseif (MSVC) add_definitions(-DWIN32) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd /Od /Zi") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") -else() +else () add_definitions(-D_GNU_SOURCE) -endif() +endif () set(LIBPREFIX "${CMAKE_STATIC_LIBRARY_PREFIX}") set(LIBSUFFIX "${CMAKE_STATIC_LIBRARY_SUFFIX}") @@ -126,7 +126,7 @@ add_custom_command(OUTPUT ${SBE_JAR} ) add_custom_target(sbe-jar - DEPENDS ${SBE_JAR} + DEPENDS ${SBE_JAR} ) set(CODEC_TARGET_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") @@ -138,15 +138,15 @@ set(CODEC_EXAMPLES_SCHEMA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/sbe-samples/src/main/ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sbe-tool/src/main/cpp) -if(SBE_TESTS) +if (SBE_TESTS) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sbe-tool/src/test/c) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sbe-tool/src/test/cpp) -endif() +endif () -if(SBE_BUILD_SAMPLES) - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sbe-samples/src/main/cpp) -endif() +if (SBE_BUILD_SAMPLES) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sbe-samples/src/main/cpp) +endif () -if(SBE_BUILD_BENCHMARKS) - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sbe-benchmarks/src/main/cpp) -endif() +if (SBE_BUILD_BENCHMARKS) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sbe-benchmarks/src/main/cpp) +endif () diff --git a/sbe-samples/src/main/cpp/CMakeLists.txt b/sbe-samples/src/main/cpp/CMakeLists.txt index 8ea4e437d7..619221db22 100644 --- a/sbe-samples/src/main/cpp/CMakeLists.txt +++ b/sbe-samples/src/main/cpp/CMakeLists.txt @@ -17,8 +17,7 @@ find_package(Java REQUIRED) set(GENERATED_CODECS - ${CXX_CODEC_TARGET_DIR}/baseline -) + ${CXX_CODEC_TARGET_DIR}/baseline) set(EXAMPLES_SCHEMA ${CODEC_EXAMPLES_SCHEMA_DIR}/example-schema.xml) diff --git a/sbe-tool/src/main/cpp/CMakeLists.txt b/sbe-tool/src/main/cpp/CMakeLists.txt index 6370fc6307..9863f39ac5 100644 --- a/sbe-tool/src/main/cpp/CMakeLists.txt +++ b/sbe-tool/src/main/cpp/CMakeLists.txt @@ -22,21 +22,20 @@ set(CODECS uk_co_real_logic_sbe_ir_generated/PrimitiveTypeCodec.h uk_co_real_logic_sbe_ir_generated/SignalCodec.h uk_co_real_logic_sbe_ir_generated/TokenCodec.h - uk_co_real_logic_sbe_ir_generated/VarDataEncoding.h -) + uk_co_real_logic_sbe_ir_generated/VarDataEncoding.h) find_package(Java REQUIRED) add_custom_command(OUTPUT ${CODECS} COMMAND ${Java_JAVA_EXECUTABLE} - "-Dsbe.output.dir=${CMAKE_CURRENT_SOURCE_DIR}" - "-Dsbe.target.language=CPP" - "-jar" "${SBE_JAR}" - "../resources/sbe-ir.xml" - DEPENDS ${SBE_JAR} sbe-jar "../resources/sbe-ir.xml" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMENT "Generate IR codecs" + "-Dsbe.output.dir=${CMAKE_CURRENT_SOURCE_DIR}" + "-Dsbe.target.language=CPP" + "-jar" "${SBE_JAR}" + "../resources/sbe-ir.xml" + DEPENDS ${SBE_JAR} sbe-jar "../resources/sbe-ir.xml" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Generate IR codecs" ) add_custom_target( @@ -49,8 +48,7 @@ set(HEADERS otf/Token.h otf/Encoding.h otf/OtfMessageDecoder.h - otf/OtfHeaderDecoder.h -) + otf/OtfHeaderDecoder.h) add_library(sbe INTERFACE) target_include_directories(sbe INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index b803232528..07681772e4 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -26,9 +26,9 @@ function(sbe_test name) target_link_libraries("C${name}" ${GTEST_LIBS} ${CMAKE_THREAD_LIBS_INIT}) add_test(NAME C${name} COMMAND C${name} WORKING_DIRECTORY ${C_CODEC_TARGET_DIR}) add_dependencies(C${name} gtest) - if(${ARGC} GREATER 1) + if (${ARGC} GREATER 1) add_dependencies(C${name} ${ARGV1}) - endif() + endif () endfunction() find_package(Java REQUIRED) diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index 04acddf5a1..533f172f2e 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -26,9 +26,9 @@ function(sbe_test name) target_link_libraries("${name}" sbe ${GTEST_LIBS} ${CMAKE_THREAD_LIBS_INIT}) add_test(NAME ${name} COMMAND ${name} WORKING_DIRECTORY ${CXX_CODEC_TARGET_DIR}) add_dependencies(${name} gtest) - if(${ARGC} GREATER 1) + if (${ARGC} GREATER 1) add_dependencies(${name} ${ARGV1}) - endif() + endif () endfunction() find_package(Java REQUIRED) @@ -46,7 +46,7 @@ set(GENERATED_CODECS add_custom_command( OUTPUT ${GENERATED_CODECS} DEPENDS ${CODE_GENERATION_SCHEMA} ${CODE_GENERATION_SCHEMA_CPP} ${COMPOSITE_OFFSETS_SCHEMA} ${MESSAGE_BLOCK_LENGTH_TEST} - sbe-jar ${SBE_JAR} + sbe-jar ${SBE_JAR} COMMAND ${Java_JAVA_EXECUTABLE} -Dsbe.output.dir=${CXX_CODEC_TARGET_DIR} From b9141b6a608fc319cfe1187b98a39e344471a701 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 24 Dec 2019 11:28:13 -0800 Subject: [PATCH 0271/1594] [Java]: remove benchmarks upload. --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0d9a097ca2..7de4684fc7 100644 --- a/build.gradle +++ b/build.gradle @@ -784,7 +784,6 @@ task runJavaBenchmarks(type: Exec) { task uploadToMavenCentral { dependsOn 'sbe-tool:uploadArchives', 'sbe-samples:uploadArchives', - 'sbe-benchmarks:uploadArchives', 'sbe-all:uploadArchives', 'sbe-all:uploadShadow' } From 677035ca1bb8f8a9c919d51aeff6b5ec431b3bdd Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 24 Dec 2019 19:47:04 +0000 Subject: [PATCH 0272/1594] [Java] Remove the upload of archives for benchmarks. --- build.gradle | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/build.gradle b/build.gradle index 7de4684fc7..fc0c4b90a0 100644 --- a/build.gradle +++ b/build.gradle @@ -513,44 +513,6 @@ project(':sbe-benchmarks') { archiveClassifier = 'benchmarks' manifest.attributes('Main-Class': 'org.openjdk.jmh.Main') } - - uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } - - snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } - - pom.project(projectPom) - } - } - } - - task sourcesJar(type: Jar) { - archiveClassifier = 'sources' - from sourceSets.main.allSource - } - - task javadocJar(type: Jar, dependsOn: javadoc) { - archiveClassifier = 'javadoc' - from javadoc.destinationDir - } - - artifacts { - archives sourcesJar - archives javadocJar - } - - signing { - required { isReleaseVersion && gradle.taskGraph.hasTask("uploadArchives") } - sign configurations.shadow - } } /* From 5ab16a22a9925d8e76f810ac2d453b5d6fdb008f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 30 Dec 2019 15:41:46 +0000 Subject: [PATCH 0273/1594] [Java] Upgrade to Checkstyle 8.28. --- build.gradle | 2 +- config/checkstyle/checkstyle.xml | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index fc0c4b90a0..5d709323cf 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ plugins { defaultTasks 'clean', 'build', 'shadowJar', 'install' -def checkstyleVersion = '8.27' +def checkstyleVersion = '8.28' def hamcrestVersion = '2.2' def mockitoVersion = '3.2.4' def junitVersion = '4.12' diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 7e98799f1e..661cc5f88e 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -171,8 +171,6 @@ - - - + From 2fbb6827551468da5beb8a47b0df80d3c64605f8 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 31 Dec 2019 13:17:46 +0200 Subject: [PATCH 0274/1594] [Java] Add initial build with Java 8 and 11 --- .github/workflows/ci.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..57b6f2cac3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,31 @@ +name: Java CI +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + java: [ 8, 11 ] + name: Java ${{ matrix.java }} + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Cache Gradle dependencies + uses: actions/cache@v1 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v1 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper + - name: Setup java + uses: actions/setup-java@v1 + with: + java-version: ${{ matrix.java }} + - name: Build with Gradle + run: ./gradlew From b6afc0843688db2617bd3ef3ecc9a18e7c7dd002 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 31 Dec 2019 13:24:08 +0200 Subject: [PATCH 0275/1594] [Java] Add build status from Github Actions --- .github/workflows/ci.yml | 8 ++++---- README.md | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57b6f2cac3..68d55ef54a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,13 +1,13 @@ -name: Java CI +name: Continuos Integration on: [push, pull_request] jobs: - build: + java-build: + name: Java ${{ matrix.java }} runs-on: ubuntu-latest strategy: matrix: - java: [ 8, 11 ] - name: Java ${{ matrix.java }} + java: [ 8, 11 ] steps: - name: Checkout code uses: actions/checkout@v2 diff --git a/README.md b/README.md index 8ac9d45e8d..4d4f9fa4fc 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ Simple Binary Encoding (SBE) [![Javadocs](https://www.javadoc.io/badge/uk.co.real-logic/sbe-tool.svg)](https://www.javadoc.io/doc/uk.co.real-logic/sbe-tool) [![Build Status](https://travis-ci.org/real-logic/simple-binary-encoding.svg?branch=master)](https://travis-ci.org/real-logic/simple-binary-encoding) +[![Actions Status](https://github.com/real-logic/simple-binary-encoding/workflows/Continuos%20Integration/badge.svg)](https://github.com/real-logic/simple-binary-encoding/actions) [![GitHub](https://img.shields.io/github/license/real-logic/simple-binary-encoding.svg)](https://github.com/real-logic/simple-binary-encoding/blob/master/LICENSE) [![Code Quality: Java](https://img.shields.io/lgtm/grade/java/g/real-logic/simple-binary-encoding.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/real-logic/simple-binary-encoding/context:java) [![Total Alerts](https://img.shields.io/lgtm/alerts/g/real-logic/simple-binary-encoding.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/real-logic/simple-binary-encoding/alerts) From 547f5a5ed362a89983f58968c79fe23443bd5a2f Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 31 Dec 2019 13:25:38 +0200 Subject: [PATCH 0276/1594] [Java] Fix nesting --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68d55ef54a..a474fc0532 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ 8, 11 ] + java: [ 8, 11 ] steps: - name: Checkout code uses: actions/checkout@v2 From da6c1f17a18aaae67b0ddeac679bd633a611d8ce Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 31 Dec 2019 13:27:24 +0200 Subject: [PATCH 0277/1594] [Java] Fix typo --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a474fc0532..fc35de7fd6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Continuos Integration +name: Continuous Integration on: [push, pull_request] jobs: From 53acb2a8588e276e5cd3cf7a3edde73b8f0aaef1 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 31 Dec 2019 13:39:08 +0200 Subject: [PATCH 0278/1594] [Java] Add C# build --- .github/workflows/ci.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc35de7fd6..b41cf6478e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,3 +29,33 @@ jobs: java-version: ${{ matrix.java }} - name: Build with Gradle run: ./gradlew + + csharp-build: + name: C# ${{ matrix.dotnet }} + runs-on: ubuntu-latest + strategy: + matrix: + dotnet: [ '2.2.103', '3.0.100', '3.1.100' ] + env: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Cache NuGet dependencies + uses: actions/cache@v1 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('csharp/**/packages.lock.json') }} + restore-keys: | + ${{ runner.os }}-nuget- + - name: Setup dotnet + uses: actions/setup-dotnet@v1 + with: + dotnet-version: ${{ matrix.dotnet }} + - name: Build + run: ./csharp/build.sh + - name: Run tests + run: ./csharp/runtests.sh + - name: Pack + run: ./csharp/pack.sh From fe029f4ca5f06640af89423bad5c28f0cadc1a8d Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 31 Dec 2019 13:41:41 +0200 Subject: [PATCH 0279/1594] [Java] Fix nuget cache pattern --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b41cf6478e..57cf33d3a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,7 @@ jobs: uses: actions/cache@v1 with: path: ~/.nuget/packages - key: ${{ runner.os }}-nuget-${{ hashFiles('csharp/**/packages.lock.json') }} + key: ${{ runner.os }}-nuget-${{ hashFiles('**/csharp/**/packages.lock.json') }} restore-keys: | ${{ runner.os }}-nuget- - name: Setup dotnet From 46a3108b16a6fa5468aba80b89a57a339d8140e7 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 31 Dec 2019 13:43:21 +0200 Subject: [PATCH 0280/1594] [Java] Remove nuget caching --- .github/workflows/ci.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57cf33d3a4..259588e907 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,20 +35,13 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - dotnet: [ '2.2.103', '3.0.100', '3.1.100' ] + dotnet: [ '2.2.103', '3.1.100' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code uses: actions/checkout@v2 - - name: Cache NuGet dependencies - uses: actions/cache@v1 - with: - path: ~/.nuget/packages - key: ${{ runner.os }}-nuget-${{ hashFiles('**/csharp/**/packages.lock.json') }} - restore-keys: | - ${{ runner.os }}-nuget- - name: Setup dotnet uses: actions/setup-dotnet@v1 with: From 0c09d5f1cc814e175db3031d5aa677aea62fa39c Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 31 Dec 2019 13:46:01 +0200 Subject: [PATCH 0281/1594] [Java] Remove dotnet 3.3 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 259588e907..4e0fd193d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - dotnet: [ '2.2.103', '3.1.100' ] + dotnet: [ '2.2.103' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 From cd8706b80890f5a31771c81dbb5aca91eb008b1f Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 31 Dec 2019 13:49:47 +0200 Subject: [PATCH 0282/1594] [Java] Add Gradle caching for .Net build --- .github/workflows/ci.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e0fd193d7..62d67370f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,6 +42,18 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v2 + - name: Cache Gradle dependencies + uses: actions/cache@v1 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v1 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper - name: Setup dotnet uses: actions/setup-dotnet@v1 with: From 92c82f98a31ed68f4e4a45d585342ed374931b1e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 31 Dec 2019 13:54:00 +0200 Subject: [PATCH 0283/1594] [Java] Cache .Net deps --- .github/workflows/ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 62d67370f1..547fbbaf0c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,6 +54,13 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper + - name: Cache NuGet dependencies + uses: actions/cache@v1 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('csharp/**/*.sln') }} + restore-keys: | + ${{ runner.os }}-nuget- - name: Setup dotnet uses: actions/setup-dotnet@v1 with: From 505781b1070671e2d8c036ef96907e3c7726e29d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 2 Jan 2020 16:35:33 +0000 Subject: [PATCH 0284/1594] Update copyright. --- CMakeLists.txt | 2 +- CONTRIBUTING.md | 2 +- README.md | 2 +- build.gradle | 6 +++--- sbe-benchmarks/src/main/cpp/CMakeLists.txt | 2 +- sbe-benchmarks/src/main/cpp/CarBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/CodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/MarketDataBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/benchlet-main.cpp | 2 +- sbe-benchmarks/src/main/cpp/benchlet.h | 2 +- .../src/main/java/uk/co/real_logic/sbe/CarBenchmark.java | 2 +- .../main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java | 2 +- sbe-samples/src/main/cpp/CMakeLists.txt | 2 +- sbe-samples/src/main/cpp/GeneratedStubExample.cpp | 2 +- sbe-samples/src/main/cpp/OtfExample.cpp | 2 +- .../uk/co/real_logic/sbe/examples/ExampleTokenListener.java | 2 +- .../real_logic/sbe/examples/ExampleUsingGeneratedStub.java | 2 +- .../sbe/examples/ExampleUsingGeneratedStubExtension.java | 2 +- .../main/java/uk/co/real_logic/sbe/examples/OtfExample.java | 2 +- sbe-tool/src/main/cpp/CMakeLists.txt | 2 +- sbe-tool/src/main/cpp/otf/Encoding.h | 2 +- sbe-tool/src/main/cpp/otf/IrDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/Token.h | 2 +- .../src/main/java/uk/co/real_logic/sbe/PrimitiveType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java | 2 +- .../java/uk/co/real_logic/sbe/codec/java/GroupOrder.java | 2 +- .../uk/co/real_logic/sbe/codec/java/MethodSelector.java | 2 +- .../java/uk/co/real_logic/sbe/generation/CodeGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/Generators.java | 2 +- .../java/uk/co/real_logic/sbe/generation/NamedToken.java | 2 +- .../co/real_logic/sbe/generation/TargetCodeGenerator.java | 2 +- .../sbe/generation/TargetCodeGeneratorLoader.java | 2 +- .../java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 2 +- .../uk/co/real_logic/sbe/generation/c/COutputManager.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/c/CUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java | 2 +- .../sbe/generation/cpp/NamespaceOutputManager.java | 2 +- .../real_logic/sbe/generation/csharp/CSharpGenerator.java | 2 +- .../sbe/generation/csharp/CSharpNamespaceOutputManager.java | 2 +- .../uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/JavaUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/Rust.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/RustCodecType.java | 2 +- .../sbe/generation/rust/RustFlatFileOutputManager.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/RustUtil.java | 2 +- .../sbe/generation/rust/SplitCompositeTokens.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/Encoding.java | 2 +- .../main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java | 2 +- .../main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java | 2 +- .../java/uk/co/real_logic/sbe/ir/MessageComponents.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java | 2 +- .../main/java/uk/co/real_logic/sbe/json/JsonPrinter.java | 2 +- .../java/uk/co/real_logic/sbe/json/JsonTokenListener.java | 2 +- .../uk/co/real_logic/sbe/otf/AbstractTokenListener.java | 2 +- .../java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java | 2 +- .../java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java | 2 +- .../main/java/uk/co/real_logic/sbe/otf/TokenListener.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java | 2 +- .../main/java/uk/co/real_logic/sbe/util/ValidationUtil.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/CompositeType.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/EnumType.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/Message.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/MessageSchema.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/ParserOptions.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/Presence.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/SetType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java | 2 +- sbe-tool/src/test/c/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/c/CMakeLists.txt | 2 +- sbe-tool/src/test/c/CodeGenTest.cpp | 2 +- sbe-tool/src/test/c/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/cpp/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/cpp/CMakeLists.txt | 2 +- sbe-tool/src/test/cpp/CodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeElementsTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp | 2 +- sbe-tool/src/test/cpp/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp | 2 +- sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp | 2 +- .../test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java | 2 +- .../java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/TestTargetLanguage.java | 2 +- sbe-tool/src/test/java/uk/co/real_logic/sbe/TestUtil.java | 2 +- .../java/uk/co/real_logic/sbe/codec/java/TypesTest.java | 2 +- .../generation/java/CompositeElementsGenerationTest.java | 2 +- .../sbe/generation/java/ConstantCharArrayTest.java | 2 +- .../sbe/generation/java/GenerateFixBinaryTest.java | 2 +- .../real_logic/sbe/generation/java/JavaGeneratorTest.java | 2 +- .../sbe/generation/java/PackageOutputManagerTest.java | 2 +- .../co/real_logic/sbe/generation/java/ReflectionUtil.java | 2 +- .../real_logic/sbe/generation/java/SchemaExtensionTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/ToStringTest.java | 2 +- .../uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java | 2 +- .../uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java | 2 +- .../java/uk/co/real_logic/sbe/json/JsonPrinterTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java | 2 +- .../uk/co/real_logic/sbe/xml/CompositeElementsTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java | 2 +- .../real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java | 2 +- 131 files changed, 133 insertions(+), 133 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4382ee30d4..5397c98be9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2019 Real Logic Ltd. +# Copyright 2013-2020 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 31c8c7695a..4b67622291 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ If you are adding a new file it should have the following header: ``` /* - * Copyright 2013-2019 Real Logic Limited. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 4d4f9fa4fc..7eecc522e9 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ Developers wishing to enhance the CSharp generator should see the [developer doc License (See LICENSE file for full license) ------------------------------------------- -Copyright 2013-2019 Real Logic Limited +Copyright 2013-2020 Real Logic Limited Copyright 2017 MarketFactory Inc Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/build.gradle b/build.gradle index 5d709323cf..5de697205d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -176,8 +176,8 @@ subprojects { } javadoc { - title = '

    Simple Binary Encoding

    ' - options.bottom = 'Copyright © 2014-2019 Real Logic Ltd. All Rights Reserved.' + title = '

    Simple Binary Encoding (SBE)

    ' + options.bottom = 'Copyright © 2013-2020 Real Logic Limited. All Rights Reserved.' options.encoding = 'UTF-8' options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' diff --git a/sbe-benchmarks/src/main/cpp/CMakeLists.txt b/sbe-benchmarks/src/main/cpp/CMakeLists.txt index efd9407019..2165c6c3d7 100644 --- a/sbe-benchmarks/src/main/cpp/CMakeLists.txt +++ b/sbe-benchmarks/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2019 Real Logic Ltd. +# Copyright 2013-2020 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/CarBench.cpp b/sbe-benchmarks/src/main/cpp/CarBench.cpp index 7fe2943261..9c789203c4 100644 --- a/sbe-benchmarks/src/main/cpp/CarBench.cpp +++ b/sbe-benchmarks/src/main/cpp/CarBench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/CodecBench.h b/sbe-benchmarks/src/main/cpp/CodecBench.h index f7eee1ce47..bb6a9bc9dc 100644 --- a/sbe-benchmarks/src/main/cpp/CodecBench.h +++ b/sbe-benchmarks/src/main/cpp/CodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp index 13887ade4b..56df14ee27 100644 --- a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp +++ b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h index c2f2cf4f9a..227c5c5f4d 100644 --- a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h index 6bff1943c0..043622b25a 100644 --- a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp index a8bb92cfb5..333f3b3f1f 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp +++ b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/benchlet.h b/sbe-benchmarks/src/main/cpp/benchlet.h index 32ad219c59..bdd489224d 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet.h +++ b/sbe-benchmarks/src/main/cpp/benchlet.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java index 855659cf5a..87effdb2b3 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java index 064fd8308b..2a95866ce9 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/CMakeLists.txt b/sbe-samples/src/main/cpp/CMakeLists.txt index 619221db22..73a313af81 100644 --- a/sbe-samples/src/main/cpp/CMakeLists.txt +++ b/sbe-samples/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2019 Real Logic Ltd. +# Copyright 2013-2020 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index ae9686bf0e..1dd42acaa7 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/OtfExample.cpp b/sbe-samples/src/main/cpp/OtfExample.cpp index cc1a6b90a4..dde1226745 100644 --- a/sbe-samples/src/main/cpp/OtfExample.cpp +++ b/sbe-samples/src/main/cpp/OtfExample.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java index cfdbe23862..bd911189a2 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java index 787b950066..db6e7b8da2 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java index 43c51632b8..022b426e3c 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java index 6440554997..e7b0059a9a 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/CMakeLists.txt b/sbe-tool/src/main/cpp/CMakeLists.txt index 9863f39ac5..b0a0a91611 100644 --- a/sbe-tool/src/main/cpp/CMakeLists.txt +++ b/sbe-tool/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2019 Real Logic Ltd. +# Copyright 2013-2020 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/Encoding.h b/sbe-tool/src/main/cpp/otf/Encoding.h index 1dea6949b4..af007b2668 100644 --- a/sbe-tool/src/main/cpp/otf/Encoding.h +++ b/sbe-tool/src/main/cpp/otf/Encoding.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index e91a475ebe..866ad4b48c 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h index 64fc7636d1..300760ed84 100644 --- a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h index ad9668a3ef..e6e6f69966 100644 --- a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/Token.h b/sbe-tool/src/main/cpp/otf/Token.h index 760ea45ca8..45d7702ddc 100644 --- a/sbe-tool/src/main/cpp/otf/Token.h +++ b/sbe-tool/src/main/cpp/otf/Token.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java index cea3f50fa8..7d2f84509c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index b9f4ee7e9c..493163f134 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index d2c9ef79f6..dbf6fafee1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java index 73ba37d545..a0086feb5e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java index 5a008d8abd..22ae107bc0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java index e2386ee6f3..23bb089e3b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java index 5b5bd69c21..dc219002d5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/NamedToken.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/NamedToken.java index 488973e952..7858940615 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/NamedToken.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/NamedToken.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java index 43052e9aa0..7575ca3b79 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 19a6f0d658..e23b246923 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 50bd245236..0229500baf 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java index ebf85f08c9..11354f8df3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java index 5d3ff4c62a..b150f7ae2e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 5da9d8f8e5..308e3fdc16 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index 8158cd46b6..5a41e8157a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java index 7bfa5670f7..ec50d0a246 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 949da1894a..56b1b6c6bb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java index 9da1b7e813..19a0215dc7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index 33e37d2551..bd8d20d469 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index fbbf8e16fc..87ea9525ba 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 7bbf264331..a532740fd0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/Rust.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/Rust.java index 0959f6ec0c..297fafb0f3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/Rust.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/Rust.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java index bd57d24a6e..7c1a33d8f0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManager.java index a35dedc1b6..9de59d0f9b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index d882c85fc6..a047995390 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index 62f8b19762..0d7d3f15ed 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SplitCompositeTokens.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SplitCompositeTokens.java index 9d65ed96cd..f895d53633 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SplitCompositeTokens.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SplitCompositeTokens.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java index 1add1f0b24..96cbc1700b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java index 92cdf7fa2b..735266ec58 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java index c43b5d3ca3..9549b82e19 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java index e1cd5358d1..2d77eb36fb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index 51f4d8ff1d..db6b07d1bc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java index 92e8b67e30..e713e16047 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java index 10c13028ca..d8be88b3ec 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java index b376a62506..83e51764e9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java index 80827c50fc..99656faa94 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index b913d1814a..30ce063b4f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java index fa26223540..745fa2783c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index edc0aef61f..f86506b75b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java index 16c82c71ec..9ffaec5aab 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java index 59671f61fb..f9847c9153 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java index 8faab2d090..db4a2affd5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java index 1401214b4d..9e68c255ef 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java index 0961df215c..8e9b4db9a0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/util/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/util/ValidationUtil.java index fa08859339..b7f2ffe561 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/util/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/util/ValidationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index 9e09db8ced..6efa092a56 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index e63ff5d36a..1476896056 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index d2588082b9..d97ab07f4f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java index f707ed2eaf..ca83e1edbf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java index f8e190f6d5..089f5b573d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index 437c3043fc..58742e1108 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -1,4 +1,4 @@ -/* Copyright 2013-2019 Real Logic Ltd. +/* Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java index 7f374c07ea..2fe4fedf4c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index e13fb37539..cb2a38c365 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java index 0bcfefa768..6165ad63a9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java @@ -1,6 +1,6 @@ /* -*- mode: java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java index 5668831df3..9993875732 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index 43972fafce..834c249318 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java index 7bd0aa8da0..4553db0c8d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 0afe2b1cc7..427f3edf73 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/test/c/BoundsCheckTest.cpp b/sbe-tool/src/test/c/BoundsCheckTest.cpp index 43afa0b4bf..64b2141e25 100644 --- a/sbe-tool/src/test/c/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/c/BoundsCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index 07681772e4..aff6c9aa7d 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2019 Real Logic Ltd. +# Copyright 2013-2020 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index e21f738567..688c83178c 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/GroupWithDataTest.cpp b/sbe-tool/src/test/c/GroupWithDataTest.cpp index 86ca19852f..b7c3b91e99 100644 --- a/sbe-tool/src/test/c/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/c/GroupWithDataTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp index ca3f76951f..fca2b0740f 100644 --- a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index 533f172f2e..267f2109bb 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2019 Real Logic Ltd. +# Copyright 2013-2020 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index d5cda13f4c..f59eaca599 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp index 0cd94abe36..09ccbec8a7 100644 --- a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp index 93c7615eb1..59be7c1305 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp index fed1b77956..00768328d0 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp index 09aff16b65..9578a9aa65 100644 --- a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp index c26d5417df..7196b6065b 100644 --- a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp +++ b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp index a04a771fe7..40cb970e6f 100644 --- a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp +++ b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java index 1cc0904e47..cb66266d80 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java index aacf5ab3e1..e550264c39 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java index 116dbdbda2..5364804ad5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestUtil.java index f721dcda45..1bb3aa8f2d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java index a0c245ec6f..3ea450e98b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java index ea2a9921ee..1c56233bc5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java index 2317aafbac..70c2c244ab 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java index ad3b8f9e6a..6a3d1483c8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 1b01d099eb..0704772c71 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java index 207ebb76d2..0f8cd58d69 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java index 8b4738f814..65428b740e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index b2fca44468..d3323b445d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java index b978a23fc1..3b38fbd92a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index 04b32f9e8f..e11dd627be 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java index 0ccf66ee70..458a9c11f8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java index 76a0960a1d..71df1f681c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java index 0395b7002e..f77cd26a8a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index 149de3dc70..ab6d082d8d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java index 4ef371a1d3..ea12a6ce62 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java index d26b71bd34..ab26295889 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java index 78c7f25c89..24cd8dd71f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java index eb03e6ca7f..5a69840954 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java index 2aa8d89293..70c5345550 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java index 3ecd6af946..f2e5b9661f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java index 7267ce24ab..4108f0a811 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java index e0a6f90724..6450805eab 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index 8315020c78..05199a7636 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index bd584c0999..a0c580b548 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index 1dfc9d1b6e..7ddce93cfc 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * Copyright 2017 MarketFactory Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java index 0e38562d5c..9075ccce30 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java index a37a024458..ef726a7432 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java index cb4bc180a5..9c28c3afb4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index 54176e1a90..c85b8edf26 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 Real Logic Ltd. + * Copyright 2013-2020 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 60745094dea2cfd461605e62f12ec31093faaf66 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Fri, 3 Jan 2020 12:47:08 +1300 Subject: [PATCH 0285/1594] [C++] add test to show that display string can be printed at any point during the decode of a message. --- sbe-tool/src/test/cpp/CodeGenTest.cpp | 119 +++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index f59eaca599..0291625db1 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -41,6 +41,7 @@ static const char *FUEL_FIGURES_3_USAGE_DESCRIPTION = "Highway Cycle"; static const char *MANUFACTURER = "Honda"; static const char *MODEL = "Civic VTi"; static const char *ACTIVATION_CODE = "deadbeef"; +static const char *COLOR = "racing green"; static const std::uint64_t VEHICLE_CODE_LENGTH = sizeof(VEHICLE_CODE); static const std::uint64_t MANUFACTURER_CODE_LENGTH = sizeof(MANUFACTURER_CODE); @@ -50,12 +51,13 @@ static const std::uint64_t FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH = 13; static const std::uint64_t MANUFACTURER_LENGTH = 5; static const std::uint64_t MODEL_LENGTH = 9; static const std::uint64_t ACTIVATION_CODE_LENGTH = 8; +static const std::uint64_t COLOR_LENGTH = 12; static const std::uint8_t PERFORMANCE_FIGURES_COUNT = 2; static const std::uint8_t FUEL_FIGURES_COUNT = 3; static const std::uint8_t ACCELERATION_COUNT = 3; static const std::uint64_t expectedHeaderSize = 8; -static const std::uint64_t expectedCarSize = 191; +static const std::uint64_t expectedCarSize = 207; static const std::uint16_t fuel1Speed = 30; static const float fuel1Mpg = 35.9f; @@ -156,7 +158,8 @@ class CodeGenTest : public testing::Test car.putManufacturer(MANUFACTURER, static_cast(strlen(MANUFACTURER))) .putModel(MODEL, static_cast(strlen(MODEL))) - .putActivationCode(ACTIVATION_CODE, static_cast(strlen(ACTIVATION_CODE))); + .putActivationCode(ACTIVATION_CODE, static_cast(strlen(ACTIVATION_CODE))) + .putColor(COLOR, static_cast(strlen(COLOR))); return car.encodedLength(); } @@ -173,6 +176,15 @@ class CodeGenTest : public testing::Test return encodeCar(m_car); } + void expectDisplayString(const char *expectedDisplayString, Car& carDecoder) + { + std::stringstream displayStream; + + displayStream << carDecoder; + EXPECT_STREQ(expectedDisplayString, displayStream.str().c_str()); + displayStream.clear(); + } + MessageHeader m_hdr; MessageHeader m_hdrDecoder; Car m_car; @@ -408,6 +420,10 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) offset += sizeof(std::uint16_t); EXPECT_EQ(std::string(bp + offset, ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); offset += ACTIVATION_CODE_LENGTH; + EXPECT_EQ(*(std::uint32_t *)(bp + offset), COLOR_LENGTH); + offset += sizeof(std::uint32_t); + EXPECT_EQ(std::string(bp + offset, COLOR_LENGTH), COLOR); + offset += COLOR_LENGTH; EXPECT_EQ(sz, offset); } @@ -424,7 +440,8 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeHeaderPlusCarCorrectly) EXPECT_EQ(carSz, expectedCarSize); EXPECT_EQ(*((std::uint16_t *)bp), Car::sbeBlockLength()); - const size_t activationCodePosition = hdrSz + carSz - ACTIVATION_CODE_LENGTH; + const size_t activationCodePosition = + (hdrSz + carSz) - (ACTIVATION_CODE_LENGTH + sizeof(std::uint32_t) + COLOR_LENGTH); const size_t activationCodeLengthPosition = activationCodePosition - sizeof(std::uint16_t); EXPECT_EQ(*(std::uint16_t *)(bp + activationCodeLengthPosition), ACTIVATION_CODE_LENGTH); EXPECT_EQ(std::string(bp + activationCodePosition, ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); @@ -557,6 +574,9 @@ TEST_F(CodeGenTest, shouldbeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) EXPECT_EQ(m_carDecoder.activationCodeLength(), ACTIVATION_CODE_LENGTH); EXPECT_EQ(std::string(m_carDecoder.activationCode(), ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); + EXPECT_EQ(m_carDecoder.colorLength(), COLOR_LENGTH); + EXPECT_EQ(std::string(m_carDecoder.color(), COLOR_LENGTH), COLOR); + EXPECT_EQ(m_carDecoder.encodedLength(), expectedCarSize); } @@ -659,6 +679,9 @@ TEST_F(CodeGenTest, shouldbeAbleUseOnStackCodecsAndGroupForEach) EXPECT_EQ(carDecoder.getManufacturer(tmp, sizeof(tmp)), ACTIVATION_CODE_LENGTH); EXPECT_EQ(std::string(tmp, ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); + EXPECT_EQ(carDecoder.getColor(tmp, sizeof(tmp)), COLOR_LENGTH); + EXPECT_EQ(std::string(tmp, COLOR_LENGTH), COLOR); + EXPECT_EQ(carDecoder.encodedLength(), expectedCarSize); } @@ -675,6 +698,8 @@ static const std::size_t offsetModelLength = 170; static const std::size_t offsetModelData = offsetModelLength + sizeof(std::uint16_t); static const std::size_t offsetActivationCodeLength = 181; static const std::size_t offsetActivationCodeData = offsetActivationCodeLength + sizeof(std::uint16_t); +static const std::size_t offsetColorLength = 191; +static const std::size_t offsetColorData = offsetColorLength + sizeof(std::uint32_t); TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) { @@ -685,6 +710,7 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) std::string manufacturer(MANUFACTURER, MANUFACTURER_LENGTH); std::string model(MODEL, MODEL_LENGTH); std::string activationCode(ACTIVATION_CODE, ACTIVATION_CODE_LENGTH); + std::string color(COLOR, COLOR_LENGTH); char buffer[BUFFER_LEN]; std::uint64_t baseOffset = MessageHeader::encodedLength(); @@ -708,7 +734,8 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) car.putManufacturer(manufacturer) .putModel(model) - .putActivationCode(activationCode); + .putActivationCode(activationCode) + .putColor(color); EXPECT_EQ(car.encodedLength(), expectedCarSize); @@ -731,6 +758,9 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetActivationCodeLength), ACTIVATION_CODE_LENGTH); EXPECT_EQ(std::string(buffer + baseOffset + offsetActivationCodeData, ACTIVATION_CODE_LENGTH), activationCode); + + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetColorLength), COLOR_LENGTH); + EXPECT_EQ(std::string(buffer + baseOffset + offsetColorData, COLOR_LENGTH), color); } TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) @@ -751,6 +781,7 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) std::string manufacturer(MANUFACTURER, MANUFACTURER_LENGTH); std::string model(MODEL, MODEL_LENGTH); std::string activationCode(ACTIVATION_CODE, ACTIVATION_CODE_LENGTH); + std::string color(COLOR, COLOR_LENGTH); EXPECT_EQ(carDecoder.getVehicleCodeAsString(), vehicleCode); @@ -779,6 +810,86 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) EXPECT_EQ(carDecoder.getManufacturerAsString(), manufacturer); EXPECT_EQ(carDecoder.getModelAsString(), model); EXPECT_EQ(carDecoder.getActivationCodeAsString(), activationCode); + EXPECT_EQ(carDecoder.getColorAsString(), color); EXPECT_EQ(carDecoder.encodedLength(), expectedCarSize); } + +TEST_F(CodeGenTest, shouldPrintFullDecodedFlyweightRegardlessOfReadPosition) +{ + const char *expectedDisplayString = + "{\"Name\": \"Car\", \"sbeTemplateId\": 1, \"serialNumber\": 1234, \"modelYear\": 2013, \"available\": \"T\", " + "\"code\": \"A\", \"someNumbers\": [0,1,2,3,4], \"vehicleCode\": \"abcdef\", " + "\"extras\": [\"sportsPack\",\"cruiseControl\"], \"discountedModel\": \"C\", " + "\"engine\": {\"capacity\": 2000, \"numCylinders\": 4, \"manufacturerCode\": \"123\", " + "\"booster\": {\"BoostType\": \"NITROUS\", \"horsePower\": 200}}, " + "\"fuelFigures\": [{\"speed\": 30, \"mpg\": 35.9, \"usageDescription\": \"Urban Cycle\"}, " + "{\"speed\": 55, \"mpg\": 49, \"usageDescription\": \"Combined Cycle\"}, " + "{\"speed\": 75, \"mpg\": 40, \"usageDescription\": \"Highway Cycle\"}], " + "\"performanceFigures\": [{\"octaneRating\": 95, \"acceleration\": [" + "{\"mph\": 30, \"seconds\": 4}, {\"mph\": 60, \"seconds\": 7.5}, {\"mph\": 100, \"seconds\": 12.2}]}, " + "{\"octaneRating\": 99, \"acceleration\": [{\"mph\": 30, \"seconds\": 3.8}, {\"mph\": 60, \"seconds\": 7.1}, " + "{\"mph\": 100, \"seconds\": 11.8}]}], \"manufacturer\": \"Honda\", \"model\": \"Civic VTi\", " + "\"activationCode\": \"deadbeef\", \"color\": \"racing green\"}"; + + char buffer[2048]; + memset(buffer, 0, 2048); + Car carEncoder(buffer, sizeof(buffer)); + + std::uint64_t carSz = encodeCar(carEncoder); + + EXPECT_EQ(carSz, expectedCarSize); + + Car carDecoder(buffer, carSz, Car::sbeBlockLength(), Car::sbeSchemaVersion()); + + std::string vehicleCode(VEHICLE_CODE, Car::vehicleCodeLength()); + std::string usageDesc1(FUEL_FIGURES_1_USAGE_DESCRIPTION, FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH); + std::string usageDesc2(FUEL_FIGURES_2_USAGE_DESCRIPTION, FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH); + std::string usageDesc3(FUEL_FIGURES_3_USAGE_DESCRIPTION, FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH); + std::string manufacturer(MANUFACTURER, MANUFACTURER_LENGTH); + std::string model(MODEL, MODEL_LENGTH); + std::string activationCode(ACTIVATION_CODE, ACTIVATION_CODE_LENGTH); + std::string color(COLOR, COLOR_LENGTH); + + expectDisplayString(expectedDisplayString, carDecoder); + + EXPECT_EQ(carDecoder.getVehicleCodeAsString(), vehicleCode); + + Car::FuelFigures &fuelFigures = carDecoder.fuelFigures(); + + fuelFigures.next(); + EXPECT_EQ(fuelFigures.getUsageDescriptionAsString(), usageDesc1); + + fuelFigures.next(); + EXPECT_EQ(fuelFigures.getUsageDescriptionAsString(), usageDesc2); + + fuelFigures.next(); + EXPECT_EQ(fuelFigures.getUsageDescriptionAsString(), usageDesc3); + + expectDisplayString(expectedDisplayString, carDecoder); + + Car::PerformanceFigures &perfFigures = carDecoder.performanceFigures(); + + perfFigures.next(); + Car::PerformanceFigures::Acceleration &acceleration = perfFigures.acceleration(); + + acceleration.next().next().next(); + + expectDisplayString(expectedDisplayString, carDecoder); + + perfFigures.next(); + acceleration = perfFigures.acceleration(); + acceleration.next().next().next(); + + EXPECT_EQ(carDecoder.getManufacturerAsString(), manufacturer); + EXPECT_EQ(carDecoder.getModelAsString(), model); + + expectDisplayString(expectedDisplayString, carDecoder); + + EXPECT_EQ(carDecoder.getActivationCodeAsString(), activationCode); + EXPECT_EQ(carDecoder.getColorAsString(), color); + + expectDisplayString(expectedDisplayString, carDecoder); + + EXPECT_EQ(carDecoder.encodedLength(), expectedCarSize); +} \ No newline at end of file From 231a5db32d2686842d6e4955e85db5c5f43c1bdb Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 09:51:43 +0200 Subject: [PATCH 0286/1594] [Java] Add GCC to the build --- .github/workflows/ci.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 547fbbaf0c..17723b8d94 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,3 +71,29 @@ jobs: run: ./csharp/runtests.sh - name: Pack run: ./csharp/pack.sh + + gcc-build: + name: GCC ${{ matrix.gcc }} + runs-on: ubuntu-latest + strategy: + matrix: + gcc: [ 6, 7, 8, 9 ] + env: + COMPILER: g++-${{ matrix.gcc }} + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Cache Gradle dependencies + uses: actions/cache@v1 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v1 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper + - name: Build + run: ./cppbuild/cppbuild From 91902a2bb961523fc4b4e1a5781a36cba2d88b0c Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 09:56:10 +0200 Subject: [PATCH 0287/1594] [Java] Try different ENV variable to select GCC compiler version --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 17723b8d94..0ef2b6a7de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,9 +77,9 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - gcc: [ 6, 7, 8, 9 ] + gcc: [ 6, 7 ] env: - COMPILER: g++-${{ matrix.gcc }} + CC: g++-${{ matrix.gcc }} steps: - name: Checkout code uses: actions/checkout@v2 From f6c7ac99b74443718d2def8f76d409b16bc81854 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 10:00:38 +0200 Subject: [PATCH 0288/1594] [Java] Use CXX variable to enforce the version of the C++ compiler --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ef2b6a7de..db017f84a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,7 +79,7 @@ jobs: matrix: gcc: [ 6, 7 ] env: - CC: g++-${{ matrix.gcc }} + CXX: g++-${{ matrix.gcc }} steps: - name: Checkout code uses: actions/checkout@v2 From 435846db1e6dca1f39e814d52fe62e462268b2af Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 10:02:42 +0200 Subject: [PATCH 0289/1594] [Java] Use `CMAKE_CXX_COMPILER` ENV variable --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index db017f84a2..e60cdbba34 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,13 +73,13 @@ jobs: run: ./csharp/pack.sh gcc-build: - name: GCC ${{ matrix.gcc }} + name: C++ GCC ${{ matrix.gcc }} runs-on: ubuntu-latest strategy: matrix: - gcc: [ 6, 7 ] + gcc: [ 6, 7, 8, 9 ] env: - CXX: g++-${{ matrix.gcc }} + CMAKE_CXX_COMPILER: g++-${{ matrix.gcc }} steps: - name: Checkout code uses: actions/checkout@v2 From da9fade669d6899aace9c33da1c2c0d4076f66af Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 10:07:55 +0200 Subject: [PATCH 0290/1594] [Java] Use `COMPILER` ENV variable --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e60cdbba34..c3ba91071d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,7 +79,7 @@ jobs: matrix: gcc: [ 6, 7, 8, 9 ] env: - CMAKE_CXX_COMPILER: g++-${{ matrix.gcc }} + COMPILER: g++-${{ matrix.gcc }} steps: - name: Checkout code uses: actions/checkout@v2 From 42240b36e74c3b69fc9b32160a66e26d11081d9d Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 10:15:22 +0200 Subject: [PATCH 0291/1594] [Java] Use `CC` and `CXX` ENV variables --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3ba91071d..a358243284 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,7 +79,8 @@ jobs: matrix: gcc: [ 6, 7, 8, 9 ] env: - COMPILER: g++-${{ matrix.gcc }} + CC: gcc-${{ matrix.gcc }} + CXX: g++-${{ matrix.gcc }} steps: - name: Checkout code uses: actions/checkout@v2 From 22d9a89f143b8037a4039b9924bd498f96391abd Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 10:20:40 +0200 Subject: [PATCH 0292/1594] [Java] Try installing compiler manually --- .github/workflows/ci.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a358243284..5ff2416e2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,14 +73,14 @@ jobs: run: ./csharp/pack.sh gcc-build: - name: C++ GCC ${{ matrix.gcc }} + name: C++ GCC ${{ matrix.version }} runs-on: ubuntu-latest strategy: matrix: - gcc: [ 6, 7, 8, 9 ] + version: [ 6, 7, 8, 9 ] env: - CC: gcc-${{ matrix.gcc }} - CXX: g++-${{ matrix.gcc }} + CC: gcc-${{ matrix.version }} + CXX: g++-${{ matrix.version }} steps: - name: Checkout code uses: actions/checkout@v2 @@ -96,5 +96,8 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper + - name: Install compiler + run: | + sudo apt-get install -y g++-${{ matrix.version }} - name: Build run: ./cppbuild/cppbuild From 933b02f805da4e08f4024547acc2a0a859cc8082 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 10:46:54 +0200 Subject: [PATCH 0293/1594] [Java] Add Clang build --- .github/workflows/ci.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ff2416e2c..028ea448f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,3 +101,33 @@ jobs: sudo apt-get install -y g++-${{ matrix.version }} - name: Build run: ./cppbuild/cppbuild + + clang-build: + name: C++ Clang ${{ matrix.version }} + runs-on: ubuntu-latest + strategy: + matrix: + version: [ 6, 7, 8, 9 ] + env: + CC: clang-${{ matrix.version }} + CXX: clang++-${{ matrix.version }} + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Cache Gradle dependencies + uses: actions/cache@v1 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v1 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper + - name: Install compiler + run: | + sudo apt-get install -y clang-${{ matrix.version }} + - name: Build + run: ./cppbuild/cppbuild From 51a277eb50fbfed8cf9f38f7bdf908e357a21541 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 10:49:25 +0200 Subject: [PATCH 0294/1594] [Java] Add missing repos for Clang --- .github/workflows/ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 028ea448f5..b95eba9139 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -128,6 +128,13 @@ jobs: key: ${{ runner.os }}-gradle-wrapper - name: Install compiler run: | + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main" + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe" + + if [ "${{ matrix.version }}" = "9" ]; then + sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main" + fi + sudo apt-get install -y clang-${{ matrix.version }} - name: Build run: ./cppbuild/cppbuild From d80646f3aab9262110768fc98e4884f1832f703f Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 10:51:27 +0200 Subject: [PATCH 0295/1594] [Java] Add `sudo apt-get update` --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b95eba9139..8cda40c382 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -135,6 +135,8 @@ jobs: sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main" fi + sudo apt-get update + sudo apt-get install -y clang-${{ matrix.version }} - name: Build run: ./cppbuild/cppbuild From de32fe909ca013c67d513c1667f5221be065bb4e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 10:53:44 +0200 Subject: [PATCH 0296/1594] [Java] Fix Clang 6.0 version --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8cda40c382..5a97d4450b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,7 +107,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - version: [ 6, 7, 8, 9 ] + version: [ 6.0, 7, 8, 9 ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} From 9fcff87c64f378bc276a497caeba685d222308d8 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 10:58:20 +0200 Subject: [PATCH 0297/1594] [Java] Use LLVM repos --- .github/workflows/ci.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a97d4450b..828fb173ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,7 +107,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - version: [ 6.0, 7, 8, 9 ] + version: [ '6.0', '7', '8', '9' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} @@ -128,12 +128,7 @@ jobs: key: ${{ runner.os }}-gradle-wrapper - name: Install compiler run: | - sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main" - sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe" - - if [ "${{ matrix.version }}" = "9" ]; then - sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main" - fi + sudo add-apt-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-${{ matrix.version }} main" sudo apt-get update From fdfecbee2f2d9ebbdcbfe22888bcabc742abe6a9 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 11:00:20 +0200 Subject: [PATCH 0298/1594] [Java] Use bionic repos for Clang installation --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 828fb173ca..33dea51797 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -128,7 +128,7 @@ jobs: key: ${{ runner.os }}-gradle-wrapper - name: Install compiler run: | - sudo add-apt-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-${{ matrix.version }} main" + sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-${{ matrix.version }} main" sudo apt-get update From 61f04653f304156e42c51449f70109f832464ea3 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 11:02:43 +0200 Subject: [PATCH 0299/1594] [Java] Install `libsparsehash-dev` package --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33dea51797..927dd88dcc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,7 +98,7 @@ jobs: key: ${{ runner.os }}-gradle-wrapper - name: Install compiler run: | - sudo apt-get install -y g++-${{ matrix.version }} + sudo apt-get install -y g++-${{ matrix.version }} libsparsehash-dev - name: Build run: ./cppbuild/cppbuild @@ -132,6 +132,6 @@ jobs: sudo apt-get update - sudo apt-get install -y clang-${{ matrix.version }} + sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev - name: Build run: ./cppbuild/cppbuild From 298590211d1f83f0619daa9744ac78f0b58ecd77 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 11:12:46 +0200 Subject: [PATCH 0300/1594] [Java] Add macOS build --- .github/workflows/ci.yml | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 927dd88dcc..6774b10a8c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ 8, 11 ] + java: [ '8', '11' ] steps: - name: Checkout code uses: actions/checkout@v2 @@ -72,12 +72,12 @@ jobs: - name: Pack run: ./csharp/pack.sh - gcc-build: + cpp-gcc-build: name: C++ GCC ${{ matrix.version }} runs-on: ubuntu-latest strategy: matrix: - version: [ 6, 7, 8, 9 ] + version: [ '6', '7', '8', '9' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} @@ -102,7 +102,7 @@ jobs: - name: Build run: ./cppbuild/cppbuild - clang-build: + cpp-clang-build: name: C++ Clang ${{ matrix.version }} runs-on: ubuntu-latest strategy: @@ -135,3 +135,33 @@ jobs: sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev - name: Build run: ./cppbuild/cppbuild + + cpp-clang-macos-build: + name: C++ Clang ${{ matrix.version }} (macOS) + runs-on: macOS-latest + strategy: + matrix: + version: [ '11.1' ] + env: + CC: clang + CXX: clang++ + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Cache Gradle dependencies + uses: actions/cache@v1 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v1 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper + - name: Install compiler + run: | + sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app + - name: Build + run: ./cppbuild/cppbuild From 5b402407d54eec282b29390191d02357b542557d Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 11:16:46 +0200 Subject: [PATCH 0301/1594] [Java] Use latest Xcode installed --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6774b10a8c..5eb641e734 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -141,7 +141,7 @@ jobs: runs-on: macOS-latest strategy: matrix: - version: [ '11.1' ] + version: [ '11.2.1' ] env: CC: clang CXX: clang++ From 8b5bab0ad5de78fd4dc520985429acf4a5f08a82 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 11:31:09 +0200 Subject: [PATCH 0302/1594] [Java] Remove Gradle caching from macOS build since it overflows allowed limits See https://github.com/real-logic/simple-binary-encoding/runs/372121366, e.g.: ``` Post job cleanup. /usr/bin/tar -cz -f /Users/runner/runners/2.163.1/work/_temp/7ec94d5c-8369-467d-ae86-dc123a967837/cache.tgz -C /Users/runner/.gradle/wrapper . [warning]Cache size of ~2187 MB (2293228503 B) is over the 400MB limit, not saving cache. ``` --- .github/workflows/ci.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5eb641e734..4916ef3e29 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -146,20 +146,6 @@ jobs: CC: clang CXX: clang++ steps: - - name: Checkout code - uses: actions/checkout@v2 - - name: Cache Gradle dependencies - uses: actions/cache@v1 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v1 - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper - name: Install compiler run: | sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app From 4c38ea2614501d39554ddbf412d7a3f1d1dbf54c Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 11:33:20 +0200 Subject: [PATCH 0303/1594] [Java] Rename and restore macOS build --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4916ef3e29..db080e660b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -137,7 +137,7 @@ jobs: run: ./cppbuild/cppbuild cpp-clang-macos-build: - name: C++ Clang ${{ matrix.version }} (macOS) + name: C++ Xcode ${{ matrix.version }} (macOS) runs-on: macOS-latest strategy: matrix: @@ -146,6 +146,8 @@ jobs: CC: clang CXX: clang++ steps: + - name: Checkout code + uses: actions/checkout@v2 - name: Install compiler run: | sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app From 49a4e47a2a5080da13860bbd00617ee7f0dfb7ec Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 11:38:58 +0200 Subject: [PATCH 0304/1594] [Java] Remove Travis build --- .travis.yml | 161 ---------------------------------------------------- README.md | 3 +- 2 files changed, 1 insertion(+), 163 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c5cd55ac8a..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,161 +0,0 @@ -dist: xenial - -sudo: false - -matrix: - include: - - - name: "OpenJDK 8" - language: java - jdk: openjdk8 - os: linux - script: ./gradlew - - - name: "OpenJDK 11" - language: java - jdk: openjdk11 - os: linux - script: ./gradlew - - - name: "C#" - language: csharp - jdk: openjdk8 - dotnet: 2.2 - os: linux - mono: latest - global: - - DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true - - DOTNET_CLI_TELEMETRY_OPTOUT=1 - script: - - ./csharp/build.sh - - ./csharp/runtests.sh - - ./csharp/pack.sh - - - name: "GCC 6" - env: COMPILER=g++-6 - language: cpp - compiler: gcc - os: linux - addons: - apt: - packages: - - g++-6 - - libsparsehash-dev - sources: - - ubuntu-toolchain-r-test - script: ./cppbuild/cppbuild - - - name: "GCC 7" - env: COMPILER=g++-7 - language: cpp - compiler: gcc - os: linux - addons: - apt: - packages: - - g++-7 - - libsparsehash-dev - sources: - - ubuntu-toolchain-r-test - script: ./cppbuild/cppbuild - - - name: "GCC 8" - env: COMPILER=g++-8 - language: cpp - compiler: gcc - os: linux - addons: - apt: - packages: - - g++-8 - - libsparsehash-dev - sources: - - ubuntu-toolchain-r-test - script: ./cppbuild/cppbuild - - - name: "GCC 9" - env: COMPILER=g++-9 - language: cpp - compiler: gcc - os: linux - addons: - apt: - packages: - - g++-9 - - libsparsehash-dev - sources: - - ubuntu-toolchain-r-test - script: ./cppbuild/cppbuild - - - name: "Clang 5" - env: COMPILER=clang++-5.0 - language: cpp - compiler: clang - os: linux - addons: - apt: - packages: - - clang-5.0 - - libsparsehash-dev - sources: - - llvm-toolchain-xenial-5.0 - script: ./cppbuild/cppbuild - - - name: "Clang 6" - env: COMPILER=clang++-6.0 - language: cpp - compiler: clang - os: linux - addons: - apt: - packages: - - clang-6.0 - - libsparsehash-dev - sources: - - llvm-toolchain-xenial-6.0 - script: ./cppbuild/cppbuild - - - name: "Clang 7" - env: COMPILER=clang++-7 - language: cpp - compiler: clang - os: linux - addons: - apt: - packages: - - clang-7 - - libsparsehash-dev - sources: - - llvm-toolchain-xenial-7 - script: ./cppbuild/cppbuild - - - name: "Clang 8" - env: COMPILER=clang++-8 - language: cpp - compiler: clang - os: linux - addons: - apt: - packages: - - clang-8 - - libsparsehash-dev - sources: - - llvm-toolchain-xenial-8 - script: ./cppbuild/cppbuild - - - name: "Clang macOS" - env: COMPILER=clang++ - language: c++ - compiler: clang - os: osx - script: ./cppbuild/cppbuild - - -before_cache: - - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ - -cache: - directories: - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ diff --git a/README.md b/README.md index 7eecc522e9..bbd8b01461 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,7 @@ Simple Binary Encoding (SBE) ============================ [![Javadocs](https://www.javadoc.io/badge/uk.co.real-logic/sbe-tool.svg)](https://www.javadoc.io/doc/uk.co.real-logic/sbe-tool) -[![Build Status](https://travis-ci.org/real-logic/simple-binary-encoding.svg?branch=master)](https://travis-ci.org/real-logic/simple-binary-encoding) -[![Actions Status](https://github.com/real-logic/simple-binary-encoding/workflows/Continuos%20Integration/badge.svg)](https://github.com/real-logic/simple-binary-encoding/actions) +[![Actions Status](https://github.com/real-logic/simple-binary-encoding/workflows/Continuous%20Integration/badge.svg)](https://github.com/real-logic/simple-binary-encoding/actions) [![GitHub](https://img.shields.io/github/license/real-logic/simple-binary-encoding.svg)](https://github.com/real-logic/simple-binary-encoding/blob/master/LICENSE) [![Code Quality: Java](https://img.shields.io/lgtm/grade/java/g/real-logic/simple-binary-encoding.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/real-logic/simple-binary-encoding/context:java) [![Total Alerts](https://img.shields.io/lgtm/alerts/g/real-logic/simple-binary-encoding.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/real-logic/simple-binary-encoding/alerts) From 2a1c02711becb3471c2cf76a8294b1e766c234e8 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 11:45:27 +0200 Subject: [PATCH 0305/1594] [Java] Show the build badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bbd8b01461..66d6c2a69c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Simple Binary Encoding (SBE) ============================ [![Javadocs](https://www.javadoc.io/badge/uk.co.real-logic/sbe-tool.svg)](https://www.javadoc.io/doc/uk.co.real-logic/sbe-tool) -[![Actions Status](https://github.com/real-logic/simple-binary-encoding/workflows/Continuous%20Integration/badge.svg)](https://github.com/real-logic/simple-binary-encoding/actions) +![](https://github.com/real-logic/simple-binary-encoding/workflows/Continuous%20Integration/badge.svg) [![GitHub](https://img.shields.io/github/license/real-logic/simple-binary-encoding.svg)](https://github.com/real-logic/simple-binary-encoding/blob/master/LICENSE) [![Code Quality: Java](https://img.shields.io/lgtm/grade/java/g/real-logic/simple-binary-encoding.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/real-logic/simple-binary-encoding/context:java) [![Total Alerts](https://img.shields.io/lgtm/alerts/g/real-logic/simple-binary-encoding.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/real-logic/simple-binary-encoding/alerts) From cc90b486c0e3af85db45915c05c092e31579ccbe Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 3 Jan 2020 09:58:13 +0000 Subject: [PATCH 0306/1594] [Java] Upgrade to JUnit 4.13 and improve tests. --- build.gradle | 2 +- .../sbe/TargetCodeGeneratorTest.java | 7 +- .../real_logic/sbe/codec/java/TypesTest.java | 11 +- .../java/CompositeElementsGenerationTest.java | 2 +- .../java/ConstantCharArrayTest.java | 2 +- .../generation/java/JavaGeneratorTest.java | 1 + .../generation/java/SchemaExtensionTest.java | 1 + .../generation/rust/RustGeneratorTest.java | 2 +- .../sbe/ir/BasicXmlIrGenerationTest.java | 127 +++++++++--------- .../sbe/ir/CompositeElementsIrTest.java | 2 +- .../sbe/ir/CompositeOffsetsTest.java | 2 +- .../co/real_logic/sbe/ir/EncodedIrTest.java | 2 +- .../sbe/ir/GroupWithDataIrTest.java | 27 ++-- .../co/real_logic/sbe/ir/ValueRefsTest.java | 2 +- .../sbe/xml/BasicSchemaFileTest.java | 3 +- .../sbe/xml/CompositeElementsTest.java | 2 +- .../real_logic/sbe/xml/CompositeTypeTest.java | 2 +- .../sbe/xml/CyclicReferencesTest.java | 22 +-- .../xml/EmbeddedLengthAndCountFileTest.java | 6 +- .../sbe/xml/EncodedDataTypeTest.java | 2 +- .../co/real_logic/sbe/xml/EnumTypeTest.java | 2 +- .../real_logic/sbe/xml/ErrorHandlerTest.java | 126 +++++++++++------ .../real_logic/sbe/xml/GroupWithDataTest.java | 2 +- .../co/real_logic/sbe/xml/OffsetFileTest.java | 111 ++++++++------- .../uk/co/real_logic/sbe/xml/SetTypeTest.java | 2 +- 25 files changed, 253 insertions(+), 217 deletions(-) diff --git a/build.gradle b/build.gradle index 5de697205d..40acfaa73a 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ defaultTasks 'clean', 'build', 'shadowJar', 'install' def checkstyleVersion = '8.28' def hamcrestVersion = '2.2' def mockitoVersion = '3.2.4' -def junitVersion = '4.12' +def junitVersion = '4.13' def jmhVersion = '1.22' def agronaVersion = '1.1.0' diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java index e550264c39..8d85650d37 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java @@ -18,8 +18,7 @@ import org.junit.Test; import uk.co.real_logic.sbe.ir.Ir; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -40,7 +39,7 @@ public void shouldLoadAndInstantiateNonStandardTargetLanguage() throws Exception SbeTool.generate(ir, outputDir, "uk.co.real_logic.sbe.TestTargetLanguage"); verify(TestTargetLanguage.SINGLETON).generate(); - assertThat(ir, is(TestTargetLanguage.ir)); - assertThat(outputDir, is(TestTargetLanguage.outputDir)); + assertEquals(TestTargetLanguage.ir, ir); + assertEquals(TestTargetLanguage.outputDir, outputDir); } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java index 3ea450e98b..36195415a6 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java @@ -21,10 +21,7 @@ import java.nio.ByteOrder; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; public class TypesTest { @@ -67,7 +64,7 @@ public void shouldSetBitInByte() bits = (byte)(bits | (1 << i)); buffer.putByte(bufferIndex, bits); total += (1 << i); - assertThat(buffer.getByte(bufferIndex), is((byte)total)); + assertEquals((byte)total, buffer.getByte(bufferIndex)); } } @@ -105,7 +102,7 @@ public void shouldSetBitInShort() bits = (short)(bits | (1 << i)); buffer.putShort(bufferIndex, bits, BYTE_ORDER); total += (1 << i); - assertThat(buffer.getShort(bufferIndex, BYTE_ORDER), is((short)total)); + assertEquals((short)total, buffer.getShort(bufferIndex, BYTE_ORDER)); } } @@ -143,7 +140,7 @@ public void shouldSetBitInInt() bits = bits | (1 << i); buffer.putInt(bufferIndex, bits, BYTE_ORDER); total += (1 << i); - assertThat(buffer.getInt(bufferIndex, BYTE_ORDER), is((int)total)); + assertEquals((int)total, buffer.getInt(bufferIndex, BYTE_ORDER)); } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java index 1c56233bc5..bbc27a431b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java @@ -43,10 +43,10 @@ import java.nio.file.Path; import java.nio.file.Paths; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.*; public class CompositeElementsGenerationTest diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java index 70c2c244ab..87d03cbfa6 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java @@ -25,8 +25,8 @@ import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.StringContains.containsString; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class ConstantCharArrayTest diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 0704772c71..31b82a0380 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -33,6 +33,7 @@ import java.nio.ByteOrder; import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.hasToString; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index d3323b445d..26235aa33f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -30,6 +30,7 @@ import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.junit.Assert.*; import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.get; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java index 420d2868e9..568f2eafec 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java @@ -14,8 +14,8 @@ import java.util.Optional; import java.util.concurrent.TimeUnit; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static uk.co.real_logic.sbe.generation.rust.RustTest.minimalDummyIr; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index e11dd627be..0bb84c74ff 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -24,9 +24,8 @@ import java.nio.ByteOrder; import java.util.List; -import static java.lang.Integer.valueOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.TestUtil.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -42,57 +41,57 @@ public void shouldGenerateCorrectIrForMessageHeader() final Ir ir = irg.generate(schema); final List tokens = ir.headerStructure().tokens(); - assertThat(valueOf(tokens.size()), is(valueOf(6))); + assertThat(tokens.size(), is(6)); /* assert all elements of node 0 */ assertThat(tokens.get(0).signal(), is(Signal.BEGIN_COMPOSITE)); assertThat(tokens.get(0).name(), is("messageHeader")); - assertThat(valueOf(tokens.get(0).id()), is(valueOf(Token.INVALID_ID))); - assertThat(valueOf(tokens.get(0).encodedLength()), is(valueOf(8))); - assertThat(valueOf(tokens.get(0).offset()), is(valueOf(0))); + assertThat(tokens.get(0).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(0).encodedLength(), is(8)); + assertThat(tokens.get(0).offset(), is(0)); /* assert all elements of node 1 */ assertThat(tokens.get(1).signal(), is(Signal.ENCODING)); assertThat(tokens.get(1).name(), is("blockLength")); assertThat(tokens.get(1).encoding().primitiveType(), is(PrimitiveType.UINT16)); - assertThat(valueOf(tokens.get(1).id()), is(valueOf(Token.INVALID_ID))); - assertThat(valueOf(tokens.get(1).encodedLength()), is(valueOf(2))); - assertThat(valueOf(tokens.get(1).offset()), is(valueOf(0))); + assertThat(tokens.get(1).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(1).encodedLength(), is(2)); + assertThat(tokens.get(1).offset(), is(0)); assertThat(tokens.get(1).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); /* assert all elements of node 2 */ assertThat(tokens.get(2).signal(), is(Signal.ENCODING)); assertThat(tokens.get(2).name(), is("templateId")); assertThat(tokens.get(2).encoding().primitiveType(), is(PrimitiveType.UINT16)); - assertThat(valueOf(tokens.get(2).id()), is(valueOf(Token.INVALID_ID))); - assertThat(valueOf(tokens.get(2).encodedLength()), is(valueOf(2))); - assertThat(valueOf(tokens.get(2).offset()), is(valueOf(2))); + assertThat(tokens.get(2).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(2).encodedLength(), is(2)); + assertThat(tokens.get(2).offset(), is(2)); assertThat(tokens.get(2).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); /* assert all elements of node 3 */ assertThat(tokens.get(3).signal(), is(Signal.ENCODING)); assertThat(tokens.get(3).name(), is("schemaId")); assertThat(tokens.get(3).encoding().primitiveType(), is(PrimitiveType.UINT16)); - assertThat(valueOf(tokens.get(3).id()), is(valueOf(Token.INVALID_ID))); - assertThat(valueOf(tokens.get(3).encodedLength()), is(valueOf(2))); - assertThat(valueOf(tokens.get(3).offset()), is(valueOf(4))); + assertThat(tokens.get(3).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(3).encodedLength(), is(2)); + assertThat(tokens.get(3).offset(), is(4)); assertThat(tokens.get(3).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); /* assert all elements of node 4 */ assertThat(tokens.get(4).signal(), is(Signal.ENCODING)); assertThat(tokens.get(4).name(), is("version")); assertThat(tokens.get(4).encoding().primitiveType(), is(PrimitiveType.UINT16)); - assertThat(valueOf(tokens.get(4).id()), is(valueOf(Token.INVALID_ID))); - assertThat(valueOf(tokens.get(4).encodedLength()), is(valueOf(2))); - assertThat(valueOf(tokens.get(4).offset()), is(valueOf(6))); + assertThat(tokens.get(4).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(4).encodedLength(), is(2)); + assertThat(tokens.get(4).offset(), is(6)); assertThat(tokens.get(4).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); /* assert all elements of node 6 */ assertThat(tokens.get(5).signal(), is(Signal.END_COMPOSITE)); assertThat(tokens.get(5).name(), is("messageHeader")); - assertThat(valueOf(tokens.get(5).id()), is(valueOf(Token.INVALID_ID))); - assertThat(valueOf(tokens.get(5).encodedLength()), is(valueOf(8))); - assertThat(valueOf(tokens.get(5).offset()), is(valueOf(0))); + assertThat(tokens.get(5).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(5).encodedLength(), is(8)); + assertThat(tokens.get(5).offset(), is(0)); } @Test @@ -105,44 +104,44 @@ public void shouldGenerateCorrectIrForBasicMessage() final List tokens = ir.getMessage(50001); - assertThat(valueOf(tokens.size()), is(valueOf(5))); + assertThat(tokens.size(), is(5)); /* assert all elements of node 0 */ assertThat(tokens.get(0).signal(), is(Signal.BEGIN_MESSAGE)); assertThat(tokens.get(0).name(), is("TestMessage50001")); - assertThat(valueOf(tokens.get(0).id()), is(valueOf(50001))); - assertThat(valueOf(tokens.get(0).encodedLength()), is(valueOf(16))); - assertThat(valueOf(tokens.get(0).offset()), is(valueOf(0))); + assertThat(tokens.get(0).id(), is(50001)); + assertThat(tokens.get(0).encodedLength(), is(16)); + assertThat(tokens.get(0).offset(), is(0)); /* assert all elements of node 1 */ assertThat(tokens.get(1).signal(), is(Signal.BEGIN_FIELD)); assertThat(tokens.get(1).name(), is("Tag40001")); - assertThat(valueOf(tokens.get(1).id()), is(valueOf(40001))); - assertThat(valueOf(tokens.get(1).encodedLength()), is(valueOf(4))); - assertThat(valueOf(tokens.get(1).offset()), is(valueOf(0))); + assertThat(tokens.get(1).id(), is(40001)); + assertThat(tokens.get(1).encodedLength(), is(4)); + assertThat(tokens.get(1).offset(), is(0)); /* assert all elements of node 2 */ assertThat(tokens.get(2).signal(), is(Signal.ENCODING)); assertThat(tokens.get(2).name(), is("uint32")); assertThat(tokens.get(2).encoding().primitiveType(), is(PrimitiveType.UINT32)); - assertThat(valueOf(tokens.get(2).id()), is(valueOf(Token.INVALID_ID))); - assertThat(valueOf(tokens.get(2).encodedLength()), is(valueOf(4))); - assertThat(valueOf(tokens.get(2).offset()), is(valueOf(0))); + assertThat(tokens.get(2).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(2).encodedLength(), is(4)); + assertThat(tokens.get(2).offset(), is(0)); assertThat(tokens.get(2).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); /* assert all elements of node 3 */ assertThat(tokens.get(3).signal(), is(Signal.END_FIELD)); assertThat(tokens.get(3).name(), is("Tag40001")); - assertThat(valueOf(tokens.get(3).id()), is(valueOf(40001))); - assertThat(valueOf(tokens.get(3).encodedLength()), is(valueOf(4))); - assertThat(valueOf(tokens.get(3).offset()), is(valueOf(0))); + assertThat(tokens.get(3).id(), is(40001)); + assertThat(tokens.get(3).encodedLength(), is(4)); + assertThat(tokens.get(3).offset(), is(0)); /* assert all elements of node 4 */ assertThat(tokens.get(4).signal(), is(Signal.END_MESSAGE)); assertThat(tokens.get(4).name(), is("TestMessage50001")); - assertThat(valueOf(tokens.get(4).id()), is(valueOf(50001))); - assertThat(valueOf(tokens.get(4).encodedLength()), is(valueOf(16))); - assertThat(valueOf(tokens.get(4).offset()), is(valueOf(0))); + assertThat(tokens.get(4).id(), is(50001)); + assertThat(tokens.get(4).encodedLength(), is(16)); + assertThat(tokens.get(4).offset(), is(0)); } @Test @@ -156,57 +155,57 @@ public void shouldGenerateCorrectIrForMessageWithVariableLengthField() final List tokens = ir.getMessage(1); - assertThat(valueOf(tokens.size()), is(valueOf(8))); + assertThat(tokens.size(), is(8)); assertThat(tokens.get(0).signal(), is(Signal.BEGIN_MESSAGE)); assertThat(tokens.get(0).name(), is("TestMessage1")); - assertThat(valueOf(tokens.get(0).id()), is(valueOf(1))); - assertThat(valueOf(tokens.get(0).encodedLength()), is(valueOf(0))); - assertThat(valueOf(tokens.get(0).offset()), is(valueOf(0))); + assertThat(tokens.get(0).id(), is(1)); + assertThat(tokens.get(0).encodedLength(), is(0)); + assertThat(tokens.get(0).offset(), is(0)); assertThat(tokens.get(1).signal(), is(Signal.BEGIN_VAR_DATA)); assertThat(tokens.get(1).name(), is("encryptedNewPassword")); - assertThat(valueOf(tokens.get(1).id()), is(valueOf(1404))); - assertThat(valueOf(tokens.get(1).encodedLength()), is(valueOf(0))); - assertThat(valueOf(tokens.get(1).offset()), is(valueOf(0))); + assertThat(tokens.get(1).id(), is(1404)); + assertThat(tokens.get(1).encodedLength(), is(0)); + assertThat(tokens.get(1).offset(), is(0)); assertThat(tokens.get(2).signal(), is(Signal.BEGIN_COMPOSITE)); assertThat(tokens.get(2).name(), is("varDataEncoding")); - assertThat(valueOf(tokens.get(2).encodedLength()), is(valueOf(-1))); - assertThat(valueOf(tokens.get(2).offset()), is(valueOf(0))); + assertThat(tokens.get(2).encodedLength(), is(-1)); + assertThat(tokens.get(2).offset(), is(0)); assertThat(tokens.get(3).signal(), is(Signal.ENCODING)); assertThat(tokens.get(3).name(), is("length")); assertThat(tokens.get(3).encoding().primitiveType(), is(PrimitiveType.UINT8)); - assertThat(valueOf(tokens.get(3).id()), is(valueOf(Token.INVALID_ID))); - assertThat(valueOf(tokens.get(3).encodedLength()), is(valueOf(1))); - assertThat(valueOf(tokens.get(3).offset()), is(valueOf(0))); + assertThat(tokens.get(3).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(3).encodedLength(), is(1)); + assertThat(tokens.get(3).offset(), is(0)); assertThat(tokens.get(3).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); assertThat(tokens.get(4).signal(), is(Signal.ENCODING)); assertThat(tokens.get(4).name(), is("varData")); assertThat(tokens.get(4).encoding().primitiveType(), is(PrimitiveType.CHAR)); - assertThat(valueOf(tokens.get(4).id()), is(valueOf(Token.INVALID_ID))); - assertThat(valueOf(tokens.get(4).encodedLength()), is(valueOf(-1))); - assertThat(valueOf(tokens.get(4).offset()), is(valueOf(1))); + assertThat(tokens.get(4).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(4).encodedLength(), is(-1)); + assertThat(tokens.get(4).offset(), is(1)); assertThat(tokens.get(4).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); assertThat(tokens.get(5).signal(), is(Signal.END_COMPOSITE)); assertThat(tokens.get(5).name(), is("varDataEncoding")); - assertThat(valueOf(tokens.get(5).encodedLength()), is(valueOf(-1))); - assertThat(valueOf(tokens.get(5).offset()), is(valueOf(0))); + assertThat(tokens.get(5).encodedLength(), is(-1)); + assertThat(tokens.get(5).offset(), is(0)); assertThat(tokens.get(6).signal(), is(Signal.END_VAR_DATA)); assertThat(tokens.get(6).name(), is("encryptedNewPassword")); - assertThat(valueOf(tokens.get(6).id()), is(valueOf(1404))); - assertThat(valueOf(tokens.get(6).encodedLength()), is(valueOf(0))); - assertThat(valueOf(tokens.get(6).offset()), is(valueOf(0))); + assertThat(tokens.get(6).id(), is(1404)); + assertThat(tokens.get(6).encodedLength(), is(0)); + assertThat(tokens.get(6).offset(), is(0)); assertThat(tokens.get(7).signal(), is(Signal.END_MESSAGE)); assertThat(tokens.get(7).name(), is("TestMessage1")); - assertThat(valueOf(tokens.get(7).id()), is(valueOf(1))); - assertThat(valueOf(tokens.get(7).encodedLength()), is(valueOf(0))); - assertThat(valueOf(tokens.get(7).offset()), is(valueOf(0))); + assertThat(tokens.get(7).id(), is(1)); + assertThat(tokens.get(7).encodedLength(), is(0)); + assertThat(tokens.get(7).offset(), is(0)); } @Test @@ -229,7 +228,7 @@ public void shouldGenerateCorrectIrForMessageWithRepeatingGroupWithEmbeddedDimen /* assert on the group token */ assertThat(tokens.get(groupIdx).signal(), is(Signal.BEGIN_GROUP)); assertThat(tokens.get(groupIdx).name(), is("Entries")); - assertThat(valueOf(tokens.get(groupIdx).id()), is(valueOf(2))); + assertThat(tokens.get(groupIdx).id(), is(2)); /* assert on the comp token for dimensions */ assertThat(tokens.get(dimensionsCompIdx).signal(), is(Signal.BEGIN_COMPOSITE)); @@ -262,7 +261,7 @@ public void shouldGenerateCorrectIrForMessageWithRepeatingGroupWithEmbeddedDimen assertThat(tokens.get(groupIdx).signal(), is(Signal.BEGIN_GROUP)); assertThat(tokens.get(groupIdx).name(), is("ListOrdGrp")); - assertThat(valueOf(tokens.get(groupIdx).id()), is(valueOf(73))); + assertThat(tokens.get(groupIdx).id(), is(73)); assertThat(tokens.get(dimensionsCompIdx).signal(), is(Signal.BEGIN_COMPOSITE)); assertThat(tokens.get(dimensionsCompIdx).name(), is("groupSizeEncoding")); @@ -290,7 +289,7 @@ public void shouldGenerateCorrectIrForMessageWithVariableLengthFieldWithEmbedded /* assert the varDataEncoding field node is formed correctly */ assertThat(tokens.get(lengthFieldIdx).signal(), is(Signal.BEGIN_VAR_DATA)); assertThat(tokens.get(lengthFieldIdx).name(), is("EncryptedPassword")); - assertThat(valueOf(tokens.get(lengthFieldIdx).id()), is(valueOf(1402))); + assertThat(tokens.get(lengthFieldIdx).id(), is(1402)); /* assert the length node has correct values */ assertThat(tokens.get(lengthEncIdx).signal(), is(Signal.ENCODING)); @@ -300,4 +299,4 @@ public void shouldGenerateCorrectIrForMessageWithVariableLengthFieldWithEmbedded assertThat(tokens.get(dataEncIdx).signal(), is(Signal.ENCODING)); assertThat(tokens.get(dataEncIdx).encoding().primitiveType(), is(PrimitiveType.CHAR)); } -} \ No newline at end of file +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java index 458a9c11f8..df53e4a54e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java @@ -23,8 +23,8 @@ import java.util.List; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.TestUtil.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java index 71df1f681c..1a7b4ac01f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java @@ -22,8 +22,8 @@ import java.util.List; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.TestUtil.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index ab6d082d8d..967da41f1a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -24,8 +24,8 @@ import java.nio.ByteBuffer; import java.util.List; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class EncodedIrTest diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java index ea12a6ce62..b424ddf07f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java @@ -23,9 +23,8 @@ import java.util.List; -import static java.lang.Integer.valueOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.TestUtil.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -52,7 +51,7 @@ public void shouldGenerateCorrectIrForSingleVarDataInRepeatingGroup() /* assert on the group token */ assertThat(groupToken.signal(), is(Signal.BEGIN_GROUP)); assertThat(groupToken.name(), is("Entries")); - assertThat(valueOf(groupToken.id()), is(valueOf(2))); + assertThat(groupToken.id(), is(2)); /* assert on the comp token for dimensions */ assertThat(dimensionsCompToken.signal(), is(Signal.BEGIN_COMPOSITE)); @@ -64,7 +63,7 @@ public void shouldGenerateCorrectIrForSingleVarDataInRepeatingGroup() assertThat(varDataFieldToken.signal(), is(Signal.BEGIN_VAR_DATA)); assertThat(varDataFieldToken.name(), is("varDataField")); - assertThat(valueOf(varDataFieldToken.id()), is(valueOf(5))); + assertThat(varDataFieldToken.id(), is(5)); assertThat(lengthEncToken.signal(), is(Signal.ENCODING)); assertThat(lengthEncToken.encoding().primitiveType(), is(PrimitiveType.UINT8)); @@ -91,15 +90,15 @@ public void shouldGenerateCorrectIrForMultipleVarDataInRepeatingGroup() /* assert on the group token */ assertThat(groupToken.signal(), is(Signal.BEGIN_GROUP)); assertThat(groupToken.name(), is("Entries")); - assertThat(valueOf(groupToken.id()), is(valueOf(2))); + assertThat(groupToken.id(), is(2)); assertThat(varDataField1Token.signal(), is(Signal.BEGIN_VAR_DATA)); assertThat(varDataField1Token.name(), is("varDataField1")); - assertThat(valueOf(varDataField1Token.id()), is(valueOf(5))); + assertThat(varDataField1Token.id(), is(5)); assertThat(varDataField2Token.signal(), is(Signal.BEGIN_VAR_DATA)); assertThat(varDataField2Token.name(), is("varDataField2")); - assertThat(valueOf(varDataField2Token.id()), is(valueOf(6))); + assertThat(varDataField2Token.id(), is(6)); } @Test @@ -120,19 +119,19 @@ public void shouldGenerateCorrectIrForVarDataInNestedRepeatingGroup() assertThat(groupToken.signal(), is(Signal.BEGIN_GROUP)); assertThat(groupToken.name(), is("Entries")); - assertThat(valueOf(groupToken.id()), is(valueOf(2))); + assertThat(groupToken.id(), is(2)); assertThat(nestedGroupToken.signal(), is(Signal.BEGIN_GROUP)); assertThat(nestedGroupToken.name(), is("NestedEntries")); - assertThat(valueOf(nestedGroupToken.id()), is(valueOf(4))); + assertThat(nestedGroupToken.id(), is(4)); assertThat(varDataFieldNestedToken.signal(), is(Signal.BEGIN_VAR_DATA)); assertThat(varDataFieldNestedToken.name(), is("varDataFieldNested")); - assertThat(valueOf(varDataFieldNestedToken.id()), is(valueOf(6))); + assertThat(varDataFieldNestedToken.id(), is(6)); assertThat(varDataFieldToken.signal(), is(Signal.BEGIN_VAR_DATA)); assertThat(varDataFieldToken.name(), is("varDataField")); - assertThat(valueOf(varDataFieldToken.id()), is(valueOf(7))); + assertThat(varDataFieldToken.id(), is(7)); } @Test @@ -153,14 +152,14 @@ public void shouldGenerateCorrectIrForOnlyMultipleVarDataInRepeatingGroup() /* assert on the group token */ assertThat(groupToken.signal(), is(Signal.BEGIN_GROUP)); assertThat(groupToken.name(), is("Entries")); - assertThat(valueOf(groupToken.id()), is(valueOf(2))); + assertThat(groupToken.id(), is(2)); assertThat(varDataField1Token.signal(), is(Signal.BEGIN_VAR_DATA)); assertThat(varDataField1Token.name(), is("varDataField1")); - assertThat(valueOf(varDataField1Token.id()), is(valueOf(5))); + assertThat(varDataField1Token.id(), is(5)); assertThat(varDataField2Token.signal(), is(Signal.BEGIN_VAR_DATA)); assertThat(varDataField2Token.name(), is("varDataField2")); - assertThat(valueOf(varDataField2Token.id()), is(valueOf(6))); + assertThat(varDataField2Token.id(), is(6)); } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java index ab26295889..30a49b402e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java @@ -20,8 +20,8 @@ import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.TestUtil.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java index 5a69840954..2f1db7adfd 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java @@ -20,8 +20,8 @@ import org.junit.Test; import uk.co.real_logic.sbe.TestUtil; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class BasicSchemaFileTest @@ -60,6 +60,7 @@ public void shouldHandleBasicAllTypes() { final MessageSchema schema = parse(TestUtil.getLocalResource("basic-types-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(1).fields(); + assertThat(fields.get(0).name(), is("header")); assertThat(fields.get(1).name(), is("EDTField")); assertThat(fields.get(2).name(), is("ENUMField")); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java index 70c5345550..26d9216318 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java @@ -20,8 +20,8 @@ import java.util.List; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class CompositeElementsTest diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java index f2e5b9661f..3785ade621 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java @@ -33,8 +33,8 @@ import java.util.HashMap; import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; public class CompositeTypeTest { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java index 4108f0a811..ce54e372f2 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java @@ -15,27 +15,31 @@ */ package uk.co.real_logic.sbe.xml; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import uk.co.real_logic.sbe.TestUtil; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class CyclicReferencesTest { - @Rule - public final ExpectedException exceptionRule = ExpectedException.none(); - @Test public void shouldTestForCyclicRefs() throws Exception { - exceptionRule.expect(IllegalStateException.class); - exceptionRule.expectMessage("ref types cannot create circular dependencies"); + try + { + final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + parse(TestUtil.getLocalResource("cyclic-refs-schema.xml"), options); + } + catch (final IllegalStateException ex) + { + assertEquals(ex.getMessage(), "ref types cannot create circular dependencies"); + return; + } - parse(TestUtil.getLocalResource("cyclic-refs-schema.xml"), options); + fail("Expected IllegalStateException"); } } \ No newline at end of file diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java index 6450805eab..377a041900 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java @@ -21,9 +21,8 @@ import java.util.List; -import static java.lang.Integer.valueOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class EmbeddedLengthAndCountFileTest @@ -37,7 +36,7 @@ public void shouldHandleEmbeddedCountForGroup() final List fields = schema.getMessage(1).fields(); assertThat(fields.get(1).name(), is("ListOrdGrp")); - assertThat(valueOf(fields.get(1).id()), is(valueOf(73))); + assertThat(fields.get(1).id(), is(73)); Assert.assertNotNull(fields.get(1).dimensionType()); final List groupFields = fields.get(1).groupFields(); @@ -49,6 +48,5 @@ public void shouldHandleEmbeddedLengthForData() throws Exception { parse(TestUtil.getLocalResource("embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); - /* should parse correctly */ } } \ No newline at end of file diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index 05199a7636..ef42e69f4b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -34,8 +34,8 @@ import java.util.HashMap; import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.PrimitiveValue.parse; public class EncodedDataTypeTest diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index a0c580b548..741c2e4cc3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -35,9 +35,9 @@ import java.util.List; import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class EnumTypeTest diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index 7ddce93cfc..ec419f674f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -18,9 +18,7 @@ import uk.co.real_logic.sbe.TestUtil; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; @@ -37,16 +35,14 @@ import java.util.HashMap; import java.util.Map; -import static java.lang.Integer.valueOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class ErrorHandlerTest { - @Rule - public final ExpectedException exceptionRule = ExpectedException.none(); - @Test public void shouldNotExitOnTypeErrorsAndWarnings() throws Exception @@ -93,92 +89,134 @@ public void shouldNotExitOnTypeErrorsAndWarnings() parseTestXmlAddToMap(map, "/types/enum", testXmlString, handler); parseTestXmlAddToMap(map, "/types/set", testXmlString, handler); - assertThat(valueOf(handler.errorCount()), is(valueOf(3))); - assertThat(valueOf(handler.warningCount()), is(valueOf(33))); + assertThat(handler.errorCount(), is(3)); + assertThat(handler.warningCount(), is(33)); } @Test public void shouldExitAfterTypes() throws Exception { - exceptionRule.expect(IllegalStateException.class); - exceptionRule.expectMessage("had 2 errors"); - - final ParserOptions options = ParserOptions.builder().suppressOutput(true).build(); + try + { + final ParserOptions options = ParserOptions.builder().suppressOutput(true).build(); + parse(TestUtil.getLocalResource("error-handler-types-schema.xml"), options); + } + catch (final IllegalStateException ex) + { + assertEquals("had 2 errors", ex.getMessage()); + return; + } - parse(TestUtil.getLocalResource("error-handler-types-schema.xml"), options); + fail("expected IllegalStateException"); } @Test public void shouldExitAfterTypesWhenDupTypesDefined() throws Exception { - exceptionRule.expect(IllegalStateException.class); - exceptionRule.expectMessage("had 1 warnings"); - - final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + try + { + final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + parse(TestUtil.getLocalResource("error-handler-types-dup-schema.xml"), options); + } + catch (final IllegalStateException ex) + { + assertEquals("had 1 warnings", ex.getMessage()); + return; + } - parse(TestUtil.getLocalResource("error-handler-types-dup-schema.xml"), options); + fail("expected IllegalStateException"); } @Test public void shouldExitAfterMessageWhenDupMessageIdsDefined() throws Exception { - exceptionRule.expect(IllegalStateException.class); - exceptionRule.expectMessage("had 1 errors"); - - final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + try + { + final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + parse(TestUtil.getLocalResource("error-handler-dup-message-schema.xml"), options); + } + catch (final IllegalStateException ex) + { + assertEquals("had 1 errors", ex.getMessage()); + return; + } - parse(TestUtil.getLocalResource("error-handler-dup-message-schema.xml"), options); + fail("expected IllegalStateException"); } @Test public void shouldExitAfterMessage() throws Exception { - exceptionRule.expect(IllegalStateException.class); - exceptionRule.expectMessage("had 13 errors"); - - final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + try + { + final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + parse(TestUtil.getLocalResource("error-handler-message-schema.xml"), options); + } + catch (final IllegalStateException ex) + { + assertEquals("had 13 errors", ex.getMessage()); + return; + } - parse(TestUtil.getLocalResource("error-handler-message-schema.xml"), options); + fail("expected IllegalStateException"); } @Test public void shouldExitAfterMessageWhenGroupDimensionsNotComposite() throws Exception { - exceptionRule.expect(IllegalStateException.class); - exceptionRule.expectMessage("had 1 errors"); - - final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + try + { + final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + parse(TestUtil.getLocalResource("error-handler-group-dimensions-schema.xml"), options); + } + catch (final IllegalStateException ex) + { + assertEquals("had 1 errors", ex.getMessage()); + return; + } - parse(TestUtil.getLocalResource("error-handler-group-dimensions-schema.xml"), options); + fail("expected IllegalStateException"); } @Test public void shouldExitAfterTypesWhenCompositeOffsetsIncorrect() throws Exception { - exceptionRule.expect(IllegalStateException.class); - exceptionRule.expectMessage("had 2 errors"); - - final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + try + { + final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + parse(TestUtil.getLocalResource("error-handler-invalid-composite-offsets-schema.xml"), options); + } + catch (final IllegalStateException ex) + { + assertEquals("had 2 errors", ex.getMessage()); + return; + } - parse(TestUtil.getLocalResource("error-handler-invalid-composite-offsets-schema.xml"), options); + fail("expected IllegalStateException"); } @Test public void shouldExitInvalidFieldNames() throws Exception { - exceptionRule.expect(IllegalStateException.class); - exceptionRule.expectMessage("had 16 warnings"); - - final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + try + { + final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + parse(TestUtil.getLocalResource("error-handler-invalid-name.xml"), options); + } + catch (final IllegalStateException ex) + { + assertEquals("had 16 warnings", ex.getMessage()); + return; + } - parse(TestUtil.getLocalResource("error-handler-invalid-name.xml"), options); + fail("expected IllegalStateException"); } private static void parseTestXmlAddToMap( diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java index 9075ccce30..ead4bac1b3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java @@ -20,8 +20,8 @@ import java.util.List; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java index ef726a7432..07d9f22b9b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java @@ -21,9 +21,8 @@ import java.util.List; -import static java.lang.Integer.valueOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; /* @@ -39,16 +38,16 @@ public void shouldHandleAllTypeOffsets() "basic-types-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(1).fields(); - assertThat(valueOf(fields.get(0).computedOffset()), is(valueOf(0))); - assertThat(valueOf(fields.get(0).type().encodedLength()), is(valueOf(8))); - assertThat(valueOf(fields.get(1).computedOffset()), is(valueOf(8))); - assertThat(valueOf(fields.get(1).type().encodedLength()), is(valueOf(20))); - assertThat(valueOf(fields.get(2).computedOffset()), is(valueOf(28))); - assertThat(valueOf(fields.get(2).type().encodedLength()), is(valueOf(1))); - assertThat(valueOf(fields.get(3).computedOffset()), is(valueOf(29))); - assertThat(valueOf(fields.get(3).type().encodedLength()), is(valueOf(4))); - assertThat(valueOf(fields.get(4).computedOffset()), is(valueOf(33))); - assertThat(valueOf(fields.get(4).type().encodedLength()), is(valueOf(8))); + assertThat(fields.get(0).computedOffset(), is(0)); + assertThat(fields.get(0).type().encodedLength(), is(8)); + assertThat(fields.get(1).computedOffset(), is(8)); + assertThat(fields.get(1).type().encodedLength(), is(20)); + assertThat(fields.get(2).computedOffset(), is(28)); + assertThat(fields.get(2).type().encodedLength(), is(1)); + assertThat(fields.get(3).computedOffset(), is(29)); + assertThat(fields.get(3).type().encodedLength(), is(4)); + assertThat(fields.get(4).computedOffset(), is(33)); + assertThat(fields.get(4).type().encodedLength(), is(8)); } @Test @@ -59,16 +58,16 @@ public void shouldHandleAllTypeOffsetsSetByXML() "basic-types-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(2).fields(); - assertThat(valueOf(fields.get(0).computedOffset()), is(valueOf(0))); - assertThat(valueOf(fields.get(0).type().encodedLength()), is(valueOf(8))); - assertThat(valueOf(fields.get(1).computedOffset()), is(valueOf(8))); - assertThat(valueOf(fields.get(1).type().encodedLength()), is(valueOf(20))); - assertThat(valueOf(fields.get(2).computedOffset()), is(valueOf(32))); - assertThat(valueOf(fields.get(2).type().encodedLength()), is(valueOf(1))); - assertThat(valueOf(fields.get(3).computedOffset()), is(valueOf(128))); - assertThat(valueOf(fields.get(3).type().encodedLength()), is(valueOf(4))); - assertThat(valueOf(fields.get(4).computedOffset()), is(valueOf(136))); - assertThat(valueOf(fields.get(4).type().encodedLength()), is(valueOf(8))); + assertThat(fields.get(0).computedOffset(), is(0)); + assertThat(fields.get(0).type().encodedLength(), is(8)); + assertThat(fields.get(1).computedOffset(), is(8)); + assertThat(fields.get(1).type().encodedLength(), is(20)); + assertThat(fields.get(2).computedOffset(), is(32)); + assertThat(fields.get(2).type().encodedLength(), is(1)); + assertThat(fields.get(3).computedOffset(), is(128)); + assertThat(fields.get(3).type().encodedLength(), is(4)); + assertThat(fields.get(4).computedOffset(), is(136)); + assertThat(fields.get(4).type().encodedLength(), is(8)); } @Test @@ -79,20 +78,20 @@ public void shouldCalculateGroupOffsetWithNoPaddingFromBlockLength() "block-length-schema.xml"), ParserOptions.DEFAULT); final Message msg = schema.getMessage(1); - assertThat(valueOf(msg.blockLength()), is(valueOf(8))); + assertThat(msg.blockLength(), is(8)); final List fields = msg.fields(); - assertThat(valueOf(fields.get(0).computedOffset()), is(valueOf(0))); - assertThat(valueOf(fields.get(0).type().encodedLength()), is(valueOf(8))); - assertThat(valueOf(fields.get(1).computedOffset()), is(valueOf(8))); + assertThat(fields.get(0).computedOffset(), is(0)); + assertThat(fields.get(0).type().encodedLength(), is(8)); + assertThat(fields.get(1).computedOffset(), is(8)); Assert.assertNull(fields.get(1).type()); final List groupFields = fields.get(1).groupFields(); - assertThat(valueOf(groupFields.size()), is(valueOf(2))); - assertThat(valueOf(groupFields.get(0).computedOffset()), is(valueOf(0))); - assertThat(valueOf(groupFields.get(0).type().encodedLength()), is(valueOf(4))); - assertThat(valueOf(groupFields.get(1).computedOffset()), is(valueOf(4))); - assertThat(valueOf(groupFields.get(1).type().encodedLength()), is(valueOf(8))); + assertThat(groupFields.size(), is(2)); + assertThat(groupFields.get(0).computedOffset(), is(0)); + assertThat(groupFields.get(0).type().encodedLength(), is(4)); + assertThat(groupFields.get(1).computedOffset(), is(4)); + assertThat(groupFields.get(1).type().encodedLength(), is(8)); } @Test @@ -103,19 +102,19 @@ public void shouldCalculateGroupOffsetWithPaddingFromBlockLength() "block-length-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(2).fields(); - assertThat(valueOf(fields.get(0).computedOffset()), is(valueOf(0))); - assertThat(valueOf(fields.get(0).type().encodedLength()), is(valueOf(8))); - assertThat(valueOf(fields.get(1).computedOffset()), is(valueOf(64))); + assertThat(fields.get(0).computedOffset(), is(0)); + assertThat(fields.get(0).type().encodedLength(), is(8)); + assertThat(fields.get(1).computedOffset(), is(64)); Assert.assertNull(fields.get(1).type()); - assertThat(valueOf(fields.get(1).computedBlockLength()), is(valueOf(12))); + assertThat(fields.get(1).computedBlockLength(), is(12)); final List groupFields = fields.get(1).groupFields(); - assertThat(valueOf(groupFields.size()), is(valueOf(2))); - assertThat(valueOf(groupFields.get(0).computedOffset()), is(valueOf(0))); - assertThat(valueOf(groupFields.get(0).type().encodedLength()), is(valueOf(4))); - assertThat(valueOf(groupFields.get(1).computedOffset()), is(valueOf(4))); - assertThat(valueOf(groupFields.get(1).type().encodedLength()), is(valueOf(8))); + assertThat(groupFields.size(), is(2)); + assertThat(groupFields.get(0).computedOffset(), is(0)); + assertThat(groupFields.get(0).type().encodedLength(), is(4)); + assertThat(groupFields.get(1).computedOffset(), is(4)); + assertThat(groupFields.get(1).type().encodedLength(), is(8)); } @Test @@ -126,19 +125,19 @@ public void shouldCalculateGroupOffsetWithPaddingFromBlockLengthAndGroupBlockLen "block-length-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(3).fields(); - assertThat(valueOf(fields.get(0).computedOffset()), is(valueOf(0))); - assertThat(valueOf(fields.get(0).type().encodedLength()), is(valueOf(8))); - assertThat(valueOf(fields.get(1).computedOffset()), is(valueOf(64))); + assertThat(fields.get(0).computedOffset(), is(0)); + assertThat(fields.get(0).type().encodedLength(), is(8)); + assertThat(fields.get(1).computedOffset(), is(64)); Assert.assertNull(fields.get(1).type()); - assertThat(valueOf(fields.get(1).computedBlockLength()), is(valueOf(16))); + assertThat(fields.get(1).computedBlockLength(), is(16)); final List groupFields = fields.get(1).groupFields(); - assertThat(valueOf(groupFields.size()), is(valueOf(2))); - assertThat(valueOf(groupFields.get(0).computedOffset()), is(valueOf(0))); - assertThat(valueOf(groupFields.get(0).type().encodedLength()), is(valueOf(4))); - assertThat(valueOf(groupFields.get(1).computedOffset()), is(valueOf(4))); - assertThat(valueOf(groupFields.get(1).type().encodedLength()), is(valueOf(8))); + assertThat(groupFields.size(), is(2)); + assertThat(groupFields.get(0).computedOffset(), is(0)); + assertThat(groupFields.get(0).type().encodedLength(), is(4)); + assertThat(groupFields.get(1).computedOffset(), is(4)); + assertThat(groupFields.get(1).type().encodedLength(), is(8)); } @Test @@ -149,10 +148,10 @@ public void shouldCalculateDataOffsetWithPaddingFromBlockLength() "block-length-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(4).fields(); - assertThat(valueOf(fields.get(0).computedOffset()), is(valueOf(0))); - assertThat(valueOf(fields.get(0).type().encodedLength()), is(valueOf(8))); - assertThat(valueOf(fields.get(1).computedOffset()), is(valueOf(64))); - assertThat(valueOf(fields.get(1).type().encodedLength()), is(valueOf(-1))); + assertThat(fields.get(0).computedOffset(), is(0)); + assertThat(fields.get(0).type().encodedLength(), is(8)); + assertThat(fields.get(1).computedOffset(), is(64)); + assertThat(fields.get(1).type().encodedLength(), is(-1)); } @Test @@ -163,7 +162,7 @@ public void shouldCalculateCompositeSizeWithOffsetsSpecified() "composite-offsets-schema.xml"), ParserOptions.DEFAULT); final CompositeType header = schema.messageHeader(); - assertThat(valueOf(header.encodedLength()), is(valueOf(12))); + assertThat(header.encodedLength(), is(12)); } @Test @@ -174,6 +173,6 @@ public void shouldCalculateDimensionSizeWithOffsetsSpecified() "composite-offsets-schema.xml"), ParserOptions.DEFAULT); final CompositeType dimensions = schema.getMessage(1).fields().get(0).dimensionType(); - assertThat(valueOf(dimensions.encodedLength()), is(valueOf(8))); + assertThat(dimensions.encodedLength(), is(8)); } -} \ No newline at end of file +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index c85b8edf26..875fa02d28 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -35,9 +35,9 @@ import java.util.List; import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class SetTypeTest From cd5cc4db3c445f304246e724b8619cbb4a86bcd8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 3 Jan 2020 11:26:40 +0000 Subject: [PATCH 0307/1594] [Java] README. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 66d6c2a69c..681a4234d7 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,11 @@ Simple Binary Encoding (SBE) ============================ [![Javadocs](https://www.javadoc.io/badge/uk.co.real-logic/sbe-tool.svg)](https://www.javadoc.io/doc/uk.co.real-logic/sbe-tool) -![](https://github.com/real-logic/simple-binary-encoding/workflows/Continuous%20Integration/badge.svg) [![GitHub](https://img.shields.io/github/license/real-logic/simple-binary-encoding.svg)](https://github.com/real-logic/simple-binary-encoding/blob/master/LICENSE) -[![Code Quality: Java](https://img.shields.io/lgtm/grade/java/g/real-logic/simple-binary-encoding.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/real-logic/simple-binary-encoding/context:java) + +![](https://github.com/real-logic/simple-binary-encoding/workflows/Continuous%20Integration/badge.svg) [![Total Alerts](https://img.shields.io/lgtm/alerts/g/real-logic/simple-binary-encoding.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/real-logic/simple-binary-encoding/alerts) +[![Code Quality: Java](https://img.shields.io/lgtm/grade/java/g/real-logic/simple-binary-encoding.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/real-logic/simple-binary-encoding/context:java) [SBE](https://github.com/FIXTradingCommunity/fix-simple-binary-encoding) is an OSI layer 6 presentation for encoding and decoding binary application messages for low-latency financial applications. This repository contains From e7b97185da67527545a87ca6c3a9f3501acc7d9d Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 14:18:12 +0200 Subject: [PATCH 0308/1594] [Java] Do not use Gradle daemon --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index db080e660b..497ab1f9cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: with: java-version: ${{ matrix.java }} - name: Build with Gradle - run: ./gradlew + run: ./gradlew --no-daemon csharp-build: name: C# ${{ matrix.dotnet }} From f93f40c55313f90f2f73098795867ec10603405b Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 14:25:43 +0200 Subject: [PATCH 0309/1594] [Java] Disable Gradle daemon globally --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 497ab1f9cd..142f0514d1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,9 @@ name: Continuous Integration on: [push, pull_request] +env: + GRADLE_OPTS: "-Dorg.gradle.daemon=false" + jobs: java-build: name: Java ${{ matrix.java }} @@ -28,7 +31,7 @@ jobs: with: java-version: ${{ matrix.java }} - name: Build with Gradle - run: ./gradlew --no-daemon + run: ./gradlew csharp-build: name: C# ${{ matrix.dotnet }} From e1ab41bb810b4a169790f0449b8fcca60cff829e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2020 15:55:55 +0200 Subject: [PATCH 0310/1594] [Java] Trigger a build if a push to master occurs or when a PR for master branch is created --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 142f0514d1..3f8321b7c8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,11 @@ name: Continuous Integration -on: [push, pull_request] +on: + push: + branches: + - master + pull_request: + branches: + - master env: GRADLE_OPTS: "-Dorg.gradle.daemon=false" From 3f66c70e910341ef1a8719a83b3fd140d73dcd60 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 3 Jan 2020 15:47:25 +0000 Subject: [PATCH 0311/1594] [Java] Actions link in README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 681a4234d7..714ee3b55f 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Simple Binary Encoding (SBE) [![Javadocs](https://www.javadoc.io/badge/uk.co.real-logic/sbe-tool.svg)](https://www.javadoc.io/doc/uk.co.real-logic/sbe-tool) [![GitHub](https://img.shields.io/github/license/real-logic/simple-binary-encoding.svg)](https://github.com/real-logic/simple-binary-encoding/blob/master/LICENSE) -![](https://github.com/real-logic/simple-binary-encoding/workflows/Continuous%20Integration/badge.svg) +[![Actions Status](https://github.com/real-logic/simple-binary-encoding/workflows/Continuous%20Integration/badge.svg)](https://github.com/real-logic/simple-binary-encoding/actions) [![Total Alerts](https://img.shields.io/lgtm/alerts/g/real-logic/simple-binary-encoding.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/real-logic/simple-binary-encoding/alerts) [![Code Quality: Java](https://img.shields.io/lgtm/grade/java/g/real-logic/simple-binary-encoding.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/real-logic/simple-binary-encoding/context:java) From 72f6481bcca52452458c1492e4e3143d70ea9d95 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 5 Jan 2020 15:12:54 +0000 Subject: [PATCH 0312/1594] [Java] Add Mike and Dmitry to developers list. --- build.gradle | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/build.gradle b/build.gradle index 40acfaa73a..ecc3dc3ca7 100644 --- a/build.gradle +++ b/build.gradle @@ -104,6 +104,18 @@ def projectPom = { email = 'bill.segall@gmail.com' url = 'https://github.com/BillSegall' } + developer { + id = 'mikeb01' + name = 'Mike Barker' + email = 'mikeb01@gmail.com' + url = 'https://github.com/mikeb01' + } + developer { + id = 'vyazelenko' + name = 'Dmitry Vyazelenko' + email = 'vyazelenko@yahoo.com' + url = 'https://github.com/vyazelenko' + } } } From bc01c84995c1a756c20a9f6a4a4316e14c6c5d34 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 5 Jan 2020 23:05:14 +0200 Subject: [PATCH 0313/1594] [Java] Migrate all tests to JUnit 5 --- build.gradle | 12 +++-- .../co/real_logic/sbe/EncodedCarTestBase.java | 4 +- .../sbe/TargetCodeGeneratorTest.java | 10 ++-- .../real_logic/sbe/codec/java/TypesTest.java | 10 ++-- .../csharp/Issue567GroupSizeTest.java | 32 +++++------- .../java/CompositeElementsGenerationTest.java | 2 +- .../java/ConstantCharArrayTest.java | 2 +- .../java/GenerateFixBinaryTest.java | 6 +-- .../generation/java/JavaGeneratorTest.java | 32 ++++++------ .../java/PackageOutputManagerTest.java | 4 +- .../generation/java/SchemaExtensionTest.java | 8 +-- .../sbe/generation/java/ToStringTest.java | 4 +- .../rust/RustFlatFileOutputManagerTest.java | 21 ++++---- .../generation/rust/RustGeneratorTest.java | 50 ++++++++----------- .../sbe/generation/rust/RustTest.java | 22 ++++---- .../sbe/generation/rust/RustUtilTest.java | 28 ++++++----- .../sbe/ir/BasicXmlIrGenerationTest.java | 2 +- .../sbe/ir/CompositeElementsIrTest.java | 2 +- .../sbe/ir/CompositeOffsetsTest.java | 2 +- .../real_logic/sbe/ir/CompositeRefsTest.java | 4 +- .../co/real_logic/sbe/ir/EncodedIrTest.java | 2 +- .../sbe/ir/GroupWithDataIrTest.java | 2 +- .../co/real_logic/sbe/ir/ValueRefsTest.java | 2 +- .../real_logic/sbe/json/JsonPrinterTest.java | 4 +- .../sbe/xml/BasicSchemaFileTest.java | 2 +- .../sbe/xml/CompositeElementsTest.java | 2 +- .../real_logic/sbe/xml/CompositeTypeTest.java | 8 +-- .../sbe/xml/CyclicReferencesTest.java | 6 +-- .../xml/EmbeddedLengthAndCountFileTest.java | 8 +-- .../sbe/xml/EncodedDataTypeTest.java | 36 ++++++------- .../co/real_logic/sbe/xml/EnumTypeTest.java | 20 +++++--- .../real_logic/sbe/xml/ErrorHandlerTest.java | 6 +-- .../real_logic/sbe/xml/GroupWithDataTest.java | 4 +- .../co/real_logic/sbe/xml/OffsetFileTest.java | 10 ++-- .../sbe/xml/RelativeXIncludeTest.java | 13 +++-- .../uk/co/real_logic/sbe/xml/SetTypeTest.java | 25 ++++++---- 36 files changed, 209 insertions(+), 198 deletions(-) diff --git a/build.gradle b/build.gradle index ecc3dc3ca7..46520fc6c7 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ defaultTasks 'clean', 'build', 'shadowJar', 'install' def checkstyleVersion = '8.28' def hamcrestVersion = '2.2' def mockitoVersion = '3.2.4' -def junitVersion = '4.13' +def junitVersion = '5.5.2' def jmhVersion = '1.22' def agronaVersion = '1.1.0' @@ -150,9 +150,11 @@ subprojects { compile "org.agrona:agrona:${agronaVersion}" - testCompile "org.hamcrest:hamcrest:${hamcrestVersion}" - testCompile "org.mockito:mockito-core:${mockitoVersion}" - testCompile "junit:junit:${junitVersion}" + testImplementation "org.hamcrest:hamcrest:${hamcrestVersion}" + testImplementation "org.mockito:mockito-junit-jupiter:${mockitoVersion}" + testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}" + testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" } checkstyle.toolVersion = "${checkstyleVersion}" @@ -181,6 +183,8 @@ subprojects { jvmArgs('--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED') } + useJUnitPlatform() + testLogging { showStandardStreams = true exceptionFormat = 'full' diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java index cb66266d80..c125a1d90d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java @@ -17,7 +17,7 @@ import baseline.*; import org.agrona.concurrent.UnsafeBuffer; -import org.junit.BeforeClass; +import org.junit.jupiter.api.BeforeAll; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; @@ -32,7 +32,7 @@ public class EncodedCarTestBase private static byte[] manufacturer; private static byte[] model; - @BeforeClass + @BeforeAll public static void setupExampleData() { try diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java index 8d85650d37..93e1b60dac 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java @@ -15,19 +15,21 @@ */ package uk.co.real_logic.sbe; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.ir.Ir; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; public class TargetCodeGeneratorTest { - @Test(expected = IllegalArgumentException.class) + @Test public void shouldThrowOnNoTargetLanguage() throws Exception { - SbeTool.generate(mock(Ir.class), ".", "none"); + assertThrows(IllegalArgumentException.class, () -> + SbeTool.generate(mock(Ir.class), ".", "none")); } @Test diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java index 36195415a6..13747e94f4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java @@ -15,13 +15,13 @@ */ package uk.co.real_logic.sbe.codec.java; -import org.junit.Test; import org.agrona.MutableDirectBuffer; import org.agrona.concurrent.UnsafeBuffer; +import org.junit.jupiter.api.Test; import java.nio.ByteOrder; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; public class TypesTest { @@ -47,7 +47,7 @@ public void shouldTestBitInByte() } else { - assertFalse("bit set i = " + i, result); + assertFalse(result, "bit set i = " + i); } } } @@ -85,7 +85,7 @@ public void shouldTestBitInShort() } else { - assertFalse("bit set i = " + i, result); + assertFalse(result, "bit set i = " + i); } } } @@ -123,7 +123,7 @@ public void shouldTestBitInInt() } else { - assertFalse("bit set i = " + i, result); + assertFalse(result, "bit set i = " + i); } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index e494e98a44..acdc2fef32 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -1,12 +1,9 @@ package uk.co.real_logic.sbe.generation.csharp; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; - import org.agrona.generation.StringWriterOutputManager; -import org.junit.*; - +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.TestUtil; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; @@ -15,6 +12,11 @@ import java.io.PrintStream; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + public class Issue567GroupSizeTest { public static final String ERR_MSG = @@ -23,34 +25,26 @@ public class Issue567GroupSizeTest private PrintStream err; private PrintStream mockErr = mock(PrintStream.class); - @Before + @BeforeEach public void before() { err = System.err; System.setErr(mockErr); } - @After + @AfterEach public void after() { System.setErr(err); verify(mockErr).println(ERR_MSG); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupSize() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(TestUtil.getLocalResource("issue567-invalid.xml"), options); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - - final StringWriterOutputManager outputManager = new StringWriterOutputManager(); - outputManager.setPackageName(ir.applicableNamespace()); - final CSharpGenerator generator = new CSharpGenerator(ir, outputManager); - - // Act + Assert (exception thrown) - generator.generate(); + assertThrows(IllegalArgumentException.class, + () -> parse(TestUtil.getLocalResource("issue567-invalid.xml"), options)); } @Test diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java index bbc27a431b..3972b445e0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java @@ -19,7 +19,7 @@ import composite.elements.MessageHeaderEncoder; import composite.elements.MsgDecoder; import composite.elements.MsgEncoder; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.mockito.InOrder; import org.agrona.BitUtil; import org.agrona.DirectBuffer; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java index 87d03cbfa6..7839f64e1f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java @@ -18,7 +18,7 @@ import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; import org.agrona.generation.StringWriterOutputManager; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.TestUtil; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java index 6a3d1483c8..66acaf41c6 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.generation.java; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; import org.agrona.generation.CompilerUtil; @@ -32,8 +32,8 @@ import java.nio.ByteBuffer; import java.util.Map; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class GenerateFixBinaryTest diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 31b82a0380..b3ff43fc72 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -15,13 +15,13 @@ */ package uk.co.real_logic.sbe.generation.java; -import org.junit.Before; -import org.junit.Test; import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; import org.agrona.concurrent.UnsafeBuffer; import org.agrona.generation.CompilerUtil; import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.TestUtil; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; @@ -34,11 +34,9 @@ import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.hasToString; import static org.hamcrest.Matchers.startsWith; -import static org.junit.Assert.*; +import static org.hamcrest.Matchers.*; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import static uk.co.real_logic.sbe.generation.CodeGenerator.MESSAGE_HEADER_DECODER_TYPE; import static uk.co.real_logic.sbe.generation.java.JavaGenerator.MESSAGE_HEADER_ENCODER_TYPE; @@ -58,7 +56,7 @@ public class JavaGeneratorTest private Ir ir; - @Before + @BeforeEach public void setUp() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); @@ -480,28 +478,32 @@ private static Object wrap( return decoder; } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldValidateMissingMutableBufferClass() { - new JavaGenerator(ir, "dasdsads", BUFFER_NAME, false, false, false, outputManager); + assertThrows(IllegalArgumentException.class, () -> + new JavaGenerator(ir, "dasdsads", BUFFER_NAME, false, false, false, outputManager)); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldValidateNotImplementedMutableBufferClass() { - new JavaGenerator(ir, "java.nio.ByteBuffer", BUFFER_NAME, false, false, false, outputManager); + assertThrows(IllegalArgumentException.class, () -> + new JavaGenerator(ir, "java.nio.ByteBuffer", BUFFER_NAME, false, false, false, outputManager)); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldValidateMissingReadOnlyBufferClass() { - new JavaGenerator(ir, BUFFER_NAME, "dasdsads", false, false, false, outputManager); + assertThrows(IllegalArgumentException.class, () -> + new JavaGenerator(ir, BUFFER_NAME, "dasdsads", false, false, false, outputManager)); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldValidateNotImplementedReadOnlyBufferClass() { - new JavaGenerator(ir, BUFFER_NAME, "java.nio.ByteBuffer", false, false, false, outputManager); + assertThrows(IllegalArgumentException.class, () -> + new JavaGenerator(ir, BUFFER_NAME, "java.nio.ByteBuffer", false, false, false, outputManager)); } private Class compileCarEncoder() throws Exception diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java index 0f8cd58d69..a995d1fd7c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.generation.java; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.agrona.generation.PackageOutputManager; import java.io.File; @@ -24,7 +24,7 @@ import java.nio.file.Files; import java.nio.file.Path; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; public class PackageOutputManagerTest { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index 26235aa33f..3c59f2b6a0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -20,8 +20,8 @@ import org.agrona.concurrent.UnsafeBuffer; import org.agrona.generation.CompilerUtil; import org.agrona.generation.StringWriterOutputManager; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.TestUtil; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; @@ -32,7 +32,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.get; import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.set; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -48,7 +48,7 @@ public class SchemaExtensionTest private Ir ir; - @Before + @BeforeEach public void setup() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java index 3b38fbd92a..2e0cb1b93a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java @@ -16,12 +16,12 @@ package uk.co.real_logic.sbe.generation.java; import org.agrona.concurrent.UnsafeBuffer; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.EncodedCarTestBase; import java.nio.ByteBuffer; -import static junit.framework.TestCase.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; public class ToStringTest extends EncodedCarTestBase { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManagerTest.java index 859bed0e48..68d3149d6d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManagerTest.java @@ -1,8 +1,7 @@ package uk.co.real_logic.sbe.generation.rust; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import java.io.File; import java.io.Writer; @@ -11,12 +10,12 @@ import java.nio.file.Files; import java.nio.file.Path; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; public class RustFlatFileOutputManagerTest { - @Rule - public final TemporaryFolder folderRule = new TemporaryFolder(); + @TempDir + File tempDir; static final String PACKAGE_NAME = "uk.co.real_logic.test"; static final String EXAMPLE_CLASS_NAME = "ExampleClassName"; @@ -24,7 +23,6 @@ public class RustFlatFileOutputManagerTest @Test public void shouldCreateFileUponConstruction() throws Exception { - final File tempDir = folderRule.getRoot(); final String tempDirName = tempDir.getAbsolutePath(); final RustFlatFileOutputManager om = new RustFlatFileOutputManager(tempDirName, PACKAGE_NAME); @@ -48,16 +46,17 @@ public void shouldCreateFileUponConstruction() throws Exception assertTrue(postOutputContents.contains(arbitraryInput)); } - @Test(expected = NullPointerException.class) + @Test public void nullDirectoryParamThrowsNPE() { - new RustFlatFileOutputManager(null, PACKAGE_NAME); + assertThrows(NullPointerException.class, () -> new RustFlatFileOutputManager(null, PACKAGE_NAME)); } - @Test(expected = NullPointerException.class) + @Test public void nullPackageParamThrowsNpe() { - new RustFlatFileOutputManager(folderRule.getRoot().getAbsolutePath(), null); + assertThrows(NullPointerException.class, + () -> new RustFlatFileOutputManager(tempDir.getAbsolutePath(), null)); } private static String getExpectedFullFileName(final String tempDirName) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java index 568f2eafec..6b565654eb 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java @@ -1,8 +1,9 @@ package uk.co.real_logic.sbe.generation.rust; -import junit.framework.AssertionFailedError; -import org.junit.*; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import uk.co.real_logic.sbe.TestUtil; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; @@ -16,7 +17,8 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static uk.co.real_logic.sbe.generation.rust.RustTest.minimalDummyIr; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -27,10 +29,10 @@ public class RustGeneratorTest private static final String NESTED_GROUP_SCHEMA = "nested-group-schema"; private SingleStringOutputManager outputManager; - @Rule - public final TemporaryFolder folderRule = new TemporaryFolder(); + @TempDir + File tempDir; - @Before + @BeforeEach public void setUp() { outputManager = new SingleStringOutputManager(); @@ -57,16 +59,16 @@ private static Ir generateIrForResource(final String localResourceName) return irg.generate(schema); } - @Test(expected = NullPointerException.class) + @Test public void nullOutputManagerTossesNpe() { - new RustGenerator(minimalDummyIr(), null); + assertThrows(NullPointerException.class, () -> new RustGenerator(minimalDummyIr(), null)); } - @Test(expected = NullPointerException.class) + @Test public void nullIrTossesNpe() { - new RustGenerator(null, outputManager); + assertThrows(NullPointerException.class, () -> new RustGenerator(null, outputManager)); } @Test @@ -90,25 +92,17 @@ public void generateBasicEnum() throws IOException } private static String fullGenerateForResource( - final SingleStringOutputManager outputManager, final String localResourceName) + final SingleStringOutputManager outputManager, final String localResourceName) throws IOException { outputManager.clear(); final RustGenerator rustGenerator = new RustGenerator(generateIrForResource(localResourceName), outputManager); - try - { - rustGenerator.generate(); - } - catch (final IOException e) - { - throw new AssertionFailedError("Unexpected IOException during generation. " + e.getMessage()); - } - + rustGenerator.generate(); return outputManager.toString(); } @Test - public void fullGenerateBasicTypes() + public void fullGenerateBasicTypes() throws IOException { final String generatedRust = fullGenerateForResource(outputManager, BASIC_TYPES_SCHEMA); assertContainsSharedImports(generatedRust); @@ -251,11 +245,11 @@ private static boolean cargoExists() private void assertRustBuildable(final String generatedRust, final Optional name) throws IOException, InterruptedException { - Assume.assumeTrue(cargoExists()); - final File folder = writeCargoFolderWrapper(name.orElse("test"), generatedRust, folderRule.newFolder()); + Assumptions.assumeTrue(cargoExists()); + final File folder = writeCargoFolderWrapper(name.orElse("test"), generatedRust, tempDir); final CargoCheckResult result = cargoCheckInDirectory(folder); - assertTrue(String.format("Generated Rust (%s) should be buildable with cargo", name) + result.error, - result.isSuccess); + assertTrue(result.isSuccess, + () -> String.format("Generated Rust (%s) should be buildable with cargo", name) + result.error); } private void assertSchemaInterpretableAsRust(final String localResourceSchema) @@ -296,7 +290,7 @@ public void checkValidRustFromAllExampleSchema() throws IOException, Interrupted } @Test - public void messageWithOffsets() + public void messageWithOffsets() throws IOException { final String rust = fullGenerateForResource(outputManager, "composite-offsets-schema"); final String expectedHeader = @@ -312,7 +306,7 @@ public void messageWithOffsets() } @Test - public void messageBlockLengthExceedingSumOfFieldLengths() + public void messageBlockLengthExceedingSumOfFieldLengths() throws IOException { final String rust = fullGenerateForResource(outputManager, "message-block-length-test"); final String expectedEncoderSegment = "let v = self.scratch.writable_overlay::(9+2)?;"; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustTest.java index 30a7425dd5..827ac4c09f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustTest.java @@ -1,8 +1,7 @@ package uk.co.real_logic.sbe.generation.rust; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.generation.CodeGenerator; import uk.co.real_logic.sbe.ir.*; @@ -12,29 +11,30 @@ import java.nio.ByteOrder; import java.util.Arrays; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; public class RustTest { - @Rule - public final TemporaryFolder temporaryFolder = new TemporaryFolder(); + @TempDir + File temporaryFolder; - @Test(expected = NullPointerException.class) + @Test public void nullIRParamShouldTossNPE() { - new Rust().newInstance(null, temporaryFolder.toString()); + assertThrows(NullPointerException.class, () -> new Rust().newInstance(null, temporaryFolder.toString())); } - @Test(expected = NullPointerException.class) + @Test public void nullOutputDirParamShouldTossNPE() { - new Rust().newInstance(minimalDummyIr(), null); + assertThrows(NullPointerException.class, () -> new Rust().newInstance(minimalDummyIr(), null)); } @Test public void happyPathRustGeneratorThatThrowsNoExceptions() throws IOException { - final File newFolder = temporaryFolder.newFolder(); + final File newFolder = temporaryFolder; final CodeGenerator codeGenerator = new Rust().newInstance(minimalDummyIr(), newFolder.toString()); assertNotNull(codeGenerator); codeGenerator.generate(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java index 20ff6e34e4..8d671cddb3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java @@ -1,30 +1,34 @@ package uk.co.real_logic.sbe.generation.rust; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.PrimitiveType; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static uk.co.real_logic.sbe.generation.rust.RustUtil.formatMethodName; import static uk.co.real_logic.sbe.generation.rust.RustUtil.generateRustLiteral; public class RustUtilTest { - @Test(expected = NullPointerException.class) + @Test public void nullParamToEightBitCharacterThrowsNPE() { - RustUtil.eightBitCharacter(null); + assertThrows(NullPointerException.class, () -> + RustUtil.eightBitCharacter(null)); } - @Test(expected = IllegalArgumentException.class) + @Test public void emptyParamToEightBitCharacterThrowsIAE() { - RustUtil.eightBitCharacter(""); + assertThrows(IllegalArgumentException.class, () -> + RustUtil.eightBitCharacter("")); } - @Test(expected = IllegalArgumentException.class) + @Test public void tooManyCharactersParamToEightBitCharacterThrowsIAE() { - RustUtil.eightBitCharacter("ABC"); + assertThrows(IllegalArgumentException.class, () -> + RustUtil.eightBitCharacter("ABC")); } @Test @@ -53,16 +57,16 @@ public void generateRustLiteralsHappyPaths() assertEquals("65u64", generateRustLiteral(PrimitiveType.UINT64, "65")); } - @Test(expected = NullPointerException.class) + @Test public void generateRustLiteralNullPrimitiveTypeParam() { - generateRustLiteral(null, "65"); + assertThrows(NullPointerException.class, () -> generateRustLiteral(null, "65")); } - @Test(expected = NullPointerException.class) + @Test public void generateRustLiteralNullValueParam() { - generateRustLiteral(PrimitiveType.INT8, null); + assertThrows(NullPointerException.class, () -> generateRustLiteral(PrimitiveType.INT8, null)); } @Test diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index 0bb84c74ff..0b08890d8b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.ir; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java index df53e4a54e..93cce2f679 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.ir; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java index 1a7b4ac01f..4d2e27f13e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.ir; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java index f77cd26a8a..05fc1e3a92 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java @@ -15,12 +15,12 @@ */ package uk.co.real_logic.sbe.ir; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.TestUtil.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index 967da41f1a..584e581906 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.ir; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.TestUtil; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java index b424ddf07f..4ed971b141 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.ir; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java index 30a49b402e..21bfd8f15b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.ir; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java index 24cd8dd71f..115de2b821 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.json; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.EncodedCarTestBase; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.ir.IrDecoder; @@ -32,7 +32,7 @@ import java.nio.file.Path; import java.nio.file.Paths; -import static junit.framework.TestCase.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; public class JsonPrinterTest extends EncodedCarTestBase { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java index 2f1db7adfd..c47fc48087 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java @@ -17,7 +17,7 @@ import java.util.List; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.TestUtil; import static org.hamcrest.MatcherAssert.assertThat; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java index 26d9216318..ed4e858d05 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.xml; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.TestUtil; import java.util.List; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java index 3785ade621..aa062d5d86 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.xml; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; @@ -35,6 +35,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; +import static org.junit.jupiter.api.Assertions.*; public class CompositeTypeTest { @@ -158,7 +159,7 @@ public void shouldHandleCompositeHasNullableType() assertThat(mantissa.nullValue(), is(PrimitiveValue.parse(nullValStr, PrimitiveType.INT64))); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldThrowExceptionWhenCompositeTypeHasTypeNameDuplicates() throws Exception { @@ -171,7 +172,8 @@ public void shouldThrowExceptionWhenCompositeTypeHasTypeNameDuplicates() "" + ""; - parseTestXmlWithMap("/types/composite", testXmlString); + assertThrows(IllegalArgumentException.class, + () -> parseTestXmlWithMap("/types/composite", testXmlString)); } private static Map parseTestXmlWithMap(final String xPathExpr, final String xml) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java index ce54e372f2..6d7cd3b43d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java @@ -15,11 +15,11 @@ */ package uk.co.real_logic.sbe.xml; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.TestUtil; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class CyclicReferencesTest diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java index 377a041900..39722bb043 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java @@ -15,14 +15,14 @@ */ package uk.co.real_logic.sbe.xml; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.TestUtil; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class EmbeddedLengthAndCountFileTest @@ -37,10 +37,10 @@ public void shouldHandleEmbeddedCountForGroup() assertThat(fields.get(1).name(), is("ListOrdGrp")); assertThat(fields.get(1).id(), is(73)); - Assert.assertNotNull(fields.get(1).dimensionType()); + assertNotNull(fields.get(1).dimensionType()); final List groupFields = fields.get(1).groupFields(); - Assert.assertNotNull(groupFields); + assertNotNull(groupFields); } @Test diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index ef42e69f4b..9c9be157a7 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -15,8 +15,7 @@ */ package uk.co.real_logic.sbe.xml; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; @@ -36,6 +35,8 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static uk.co.real_logic.sbe.PrimitiveValue.parse; public class EncodedDataTypeTest @@ -125,7 +126,7 @@ public void shouldUseAppropriatePresence() assertThat(map.get("testTypeConstant").presence(), is(Presence.CONSTANT)); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldThrowExceptionWhenUnknownPresenceSpecified() throws Exception { @@ -134,10 +135,10 @@ public void shouldThrowExceptionWhenUnknownPresenceSpecified() " " + ""; - parseTestXmlWithMap("/types/type", testXmlString); + assertThrows(IllegalArgumentException.class, () -> parseTestXmlWithMap("/types/type", testXmlString)); } - @Test(expected = IllegalStateException.class) + @Test public void shouldThrowExceptionWhenNoPrimitiveTypeSpecified() throws Exception { @@ -146,10 +147,10 @@ public void shouldThrowExceptionWhenNoPrimitiveTypeSpecified() " " + ""; - parseTestXmlWithMap("/types/type", testXmlString); + assertThrows(IllegalStateException.class, () -> parseTestXmlWithMap("/types/type", testXmlString)); } - @Test(expected = IllegalStateException.class) + @Test public void shouldThrowExceptionWhenNoNameSpecified() throws Exception { @@ -158,7 +159,7 @@ public void shouldThrowExceptionWhenNoNameSpecified() " " + ""; - parseTestXmlWithMap("/types/type", testXmlString); + assertThrows(IllegalStateException.class, () -> parseTestXmlWithMap("/types/type", testXmlString)); } @Test @@ -195,7 +196,7 @@ public void shouldUseAppropriatePrimitiveType() assertThat(((EncodedDataType)map.get("testTypeDouble")).primitiveType(), is(PrimitiveType.DOUBLE)); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldThrowExceptionWhenUnknownPrimitiveTypeSpecified() throws Exception { @@ -204,7 +205,8 @@ public void shouldThrowExceptionWhenUnknownPrimitiveTypeSpecified() " " + ""; - parseTestXmlWithMap("/types/type", testXmlString); + assertThrows(IllegalArgumentException.class, + () -> parseTestXmlWithMap("/types/type", testXmlString)); } @Test @@ -267,7 +269,7 @@ public void shouldReturnNullOnNoDescriptionSet() final Map map = parseTestXmlWithMap("/types/type", testXmlString); final String description = map.get("testTypeNoDescription").description(); - Assert.assertNull(description); + assertNull(description); } @Test @@ -296,10 +298,10 @@ public void shouldReturnNullWhenSemanticTypeNotSpecified() final Map map = parseTestXmlWithMap("/types/type", testXmlString); - Assert.assertNull(map.get("testType").semanticType()); + assertNull(map.get("testType").semanticType()); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldThrowExceptionWhenConstantPresenceButNoDataSpecified() throws Exception { @@ -308,7 +310,7 @@ public void shouldThrowExceptionWhenConstantPresenceButNoDataSpecified() " " + ""; - parseTestXmlWithMap("/types/type", testXmlString); + assertThrows(IllegalArgumentException.class, () -> parseTestXmlWithMap("/types/type", testXmlString)); } @Test @@ -356,7 +358,7 @@ public void shouldReturnDefaultMinValueWhenSpecified() final Map map = parseTestXmlWithMap("/types/type", testXmlString); - Assert.assertNull(((EncodedDataType)map.get("testTypeDefaultCharMinValue")).minValue()); + assertNull(((EncodedDataType)map.get("testTypeDefaultCharMinValue")).minValue()); } @Test @@ -370,7 +372,7 @@ public void shouldReturnDefaultMaxValueWhenSpecified() final Map map = parseTestXmlWithMap("/types/type", testXmlString); - Assert.assertNull(((EncodedDataType)map.get("testTypeDefaultCharMaxValue")).maxValue()); + assertNull(((EncodedDataType)map.get("testTypeDefaultCharMaxValue")).maxValue()); } @Test @@ -384,7 +386,7 @@ public void shouldReturnDefaultNullValueWhenSpecified() final Map map = parseTestXmlWithMap("/types/type", testXmlString); - Assert.assertNull(((EncodedDataType)map.get("testTypeDefaultCharNullValue")).nullValue()); + assertNull(((EncodedDataType)map.get("testTypeDefaultCharNullValue")).nullValue()); } @Test diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index 741c2e4cc3..3cf93c95a4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.xml; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; @@ -37,7 +37,8 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class EnumTypeTest @@ -180,7 +181,7 @@ public void shouldHandleCharEnumEncodingType() assertThat(e.getValidValue("Eee").primitiveValue(), is(PrimitiveValue.parse("E", PrimitiveType.CHAR))); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() throws Exception { @@ -192,10 +193,11 @@ public void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() "" + ""; - parseTestXmlWithMap("/types/enum", testXmlString); + assertThrows(IllegalArgumentException.class, () -> + parseTestXmlWithMap("/types/enum", testXmlString)); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldThrowExceptionWhenDuplicateValueSpecified() throws Exception { @@ -208,10 +210,11 @@ public void shouldThrowExceptionWhenDuplicateValueSpecified() "" + ""; - parseTestXmlWithMap("/types/enum", testXmlString); + assertThrows(IllegalArgumentException.class, () -> + parseTestXmlWithMap("/types/enum", testXmlString)); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldThrowExceptionWhenDuplicateNameSpecified() throws Exception { @@ -224,7 +227,8 @@ public void shouldThrowExceptionWhenDuplicateNameSpecified() "" + ""; - parseTestXmlWithMap("/types/enum", testXmlString); + assertThrows(IllegalArgumentException.class, () -> + parseTestXmlWithMap("/types/enum", testXmlString)); } @Test diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index ec419f674f..d2f8fdaed5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -18,7 +18,7 @@ import uk.co.real_logic.sbe.TestUtil; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; @@ -37,8 +37,8 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class ErrorHandlerTest diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java index ead4bac1b3..16f34fa433 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java @@ -15,14 +15,14 @@ */ package uk.co.real_logic.sbe.xml; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.TestUtil; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class GroupWithDataTest diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java index 07d9f22b9b..f80b847706 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java @@ -15,14 +15,14 @@ */ package uk.co.real_logic.sbe.xml; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.TestUtil; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; +import static org.junit.jupiter.api.Assertions.assertNull; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; /* @@ -84,7 +84,7 @@ public void shouldCalculateGroupOffsetWithNoPaddingFromBlockLength() assertThat(fields.get(0).computedOffset(), is(0)); assertThat(fields.get(0).type().encodedLength(), is(8)); assertThat(fields.get(1).computedOffset(), is(8)); - Assert.assertNull(fields.get(1).type()); + assertNull(fields.get(1).type()); final List groupFields = fields.get(1).groupFields(); assertThat(groupFields.size(), is(2)); @@ -105,7 +105,7 @@ public void shouldCalculateGroupOffsetWithPaddingFromBlockLength() assertThat(fields.get(0).computedOffset(), is(0)); assertThat(fields.get(0).type().encodedLength(), is(8)); assertThat(fields.get(1).computedOffset(), is(64)); - Assert.assertNull(fields.get(1).type()); + assertNull(fields.get(1).type()); assertThat(fields.get(1).computedBlockLength(), is(12)); final List groupFields = fields.get(1).groupFields(); @@ -128,7 +128,7 @@ public void shouldCalculateGroupOffsetWithPaddingFromBlockLengthAndGroupBlockLen assertThat(fields.get(0).computedOffset(), is(0)); assertThat(fields.get(0).type().encodedLength(), is(8)); assertThat(fields.get(1).computedOffset(), is(64)); - Assert.assertNull(fields.get(1).type()); + assertNull(fields.get(1).type()); assertThat(fields.get(1).computedBlockLength(), is(16)); final List groupFields = fields.get(1).groupFields(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java index 9c28c3afb4..5591a0b1d3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java @@ -15,14 +15,13 @@ */ package uk.co.real_logic.sbe.xml; +import org.junit.jupiter.api.Test; +import org.xml.sax.InputSource; + import java.io.File; import java.net.URL; -import org.junit.Assert; -import org.junit.Test; - -import org.xml.sax.InputSource; - +import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class RelativeXIncludeTest @@ -32,13 +31,13 @@ public void shouldParseFileInSubDir() throws Exception { final URL testResource = getClass().getClassLoader().getResource("sub/basic-schema.xml"); - Assert.assertNotNull(testResource); + assertNotNull(testResource); final InputSource is = new InputSource(testResource.openStream()); final File file = new File(testResource.getFile()); is.setSystemId(file.toPath().toAbsolutePath().getParent().toUri().toString()); final MessageSchema messageSchema = parse(is, ParserOptions.DEFAULT); - Assert.assertNotNull(messageSchema.getType("Symbol")); + assertNotNull(messageSchema.getType("Symbol")); } } \ No newline at end of file diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index 875fa02d28..af979473bd 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.xml; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; @@ -37,7 +37,8 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class SetTypeTest @@ -115,7 +116,7 @@ public void shouldHandleSetTypeList() assertThat(foundBit3, is(1)); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() throws Exception { @@ -127,10 +128,11 @@ public void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() "" + ""; - parseTestXmlWithMap("/types/set", testXmlString); + assertThrows(IllegalArgumentException.class, () -> + parseTestXmlWithMap("/types/set", testXmlString)); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldThrowExceptionWhenDuplicateValueSpecified() throws Exception { @@ -142,10 +144,11 @@ public void shouldThrowExceptionWhenDuplicateValueSpecified() "" + ""; - parseTestXmlWithMap("/types/set", testXmlString); + assertThrows(IllegalArgumentException.class, () -> + parseTestXmlWithMap("/types/set", testXmlString)); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldThrowExceptionWhenDuplicateNameSpecified() throws Exception { @@ -157,10 +160,11 @@ public void shouldThrowExceptionWhenDuplicateNameSpecified() "" + ""; - parseTestXmlWithMap("/types/set", testXmlString); + assertThrows(IllegalArgumentException.class, () -> + parseTestXmlWithMap("/types/set", testXmlString)); } - @Test(expected = IllegalArgumentException.class) + @Test public void shouldThrowExceptionWhenValueOutOfBoundsSpecified() throws Exception { @@ -172,7 +176,8 @@ public void shouldThrowExceptionWhenValueOutOfBoundsSpecified() "" + ""; - parseTestXmlWithMap("/types/set", testXmlString); + assertThrows(IllegalArgumentException.class, () -> + parseTestXmlWithMap("/types/set", testXmlString)); } @Test From fa07ef4a5ab78c42606a0c0a2a11cef8b38dd5e9 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 5 Jan 2020 23:29:40 +0200 Subject: [PATCH 0314/1594] [Java] Create separate folder per invocation --- .../real_logic/sbe/generation/rust/RustGeneratorTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java index 6b565654eb..9d3974d238 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java @@ -12,6 +12,7 @@ import java.io.*; import java.nio.file.Files; +import java.nio.file.Path; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -30,7 +31,7 @@ public class RustGeneratorTest private SingleStringOutputManager outputManager; @TempDir - File tempDir; + Path tempDir; @BeforeEach public void setUp() @@ -246,7 +247,8 @@ private void assertRustBuildable(final String generatedRust, final Optional String.format("Generated Rust (%s) should be buildable with cargo", name) + result.error); From 615c0c65636fbff77ffbc9417257b78ee9e5e8fc Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 6 Jan 2020 17:10:37 +0200 Subject: [PATCH 0315/1594] [Java] Enable aggregated test report --- build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build.gradle b/build.gradle index 46520fc6c7..322494fe67 100644 --- a/build.gradle +++ b/build.gradle @@ -189,6 +189,8 @@ subprojects { showStandardStreams = true exceptionFormat = 'full' } + + reports.html.enabled = false // Disable individual test reports } javadoc { @@ -766,6 +768,12 @@ task uploadToMavenCentral { 'sbe-all:uploadShadow' } +task testReport(type: TestReport) { + destinationDir = file("$buildDir/reports/allTests") + // Include the results from the `test` task in all subprojects + reportOn subprojects*.test +} + wrapper { gradleVersion = '6.0.1' distributionType = 'ALL' From edc146835a3ba5aea1380768b4d0609fb526ed7b Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 6 Jan 2020 17:13:28 +0200 Subject: [PATCH 0316/1594] [Java] Run CI actions on pull request when 'opened', 'reopened' or 'synchronize' --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f8321b7c8..8d921aefc4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,7 @@ on: branches: - master pull_request: + types: [opened, synchronize, reopened] branches: - master From ce5e58ad3c86b344a4bb9d8e7bb9d928482df70c Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 7 Jan 2020 11:41:16 +0200 Subject: [PATCH 0317/1594] [Java] Remove unnecessary Checkstyle dependency --- build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.gradle b/build.gradle index 322494fe67..34604e6b45 100644 --- a/build.gradle +++ b/build.gradle @@ -146,8 +146,6 @@ subprojects { jar.enabled = true dependencies { - checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" - compile "org.agrona:agrona:${agronaVersion}" testImplementation "org.hamcrest:hamcrest:${hamcrestVersion}" From bb85203608e600b21cc1c3939ecccadd4004b8bd Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 7 Jan 2020 11:49:30 +0200 Subject: [PATCH 0318/1594] [Java] Remove `compile` and `testCompile` dependencies --- build.gradle | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index 34604e6b45..303ba2c170 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ buildscript { } plugins { - id 'java' + id 'java-library' id 'idea' id 'io.freefair.javadoc-links' version '4.1.6' apply false id 'com.github.johnrengelman.shadow' version '5.2.0' apply false @@ -133,7 +133,7 @@ configurations { jar.enabled = false subprojects { - apply plugin: 'java' + apply plugin: 'java-library' apply plugin: 'maven' apply plugin: 'signing' apply plugin: 'checkstyle' @@ -146,7 +146,7 @@ subprojects { jar.enabled = true dependencies { - compile "org.agrona:agrona:${agronaVersion}" + api "org.agrona:agrona:${agronaVersion}" testImplementation "org.hamcrest:hamcrest:${hamcrestVersion}" testImplementation "org.mockito:mockito-junit-jupiter:${mockitoVersion}" @@ -216,7 +216,7 @@ def validationXsdPath = project(':sbe-tool').projectDir.toString() + '/src/main/ project(':sbe-tool') { dependencies { - testCompile files('build/classes/java/generated') + testImplementation files('build/classes/java/generated') } sourceSets { @@ -307,7 +307,7 @@ project(':sbe-all') { apply plugin: 'com.github.johnrengelman.shadow' dependencies { - compile project(':sbe-tool') + implementation project(':sbe-tool') } task sourcesJar(type: Jar) { @@ -389,8 +389,8 @@ project(':sbe-all') { project(':sbe-samples') { dependencies { - compile project(':sbe-tool') - compile files('build/classes/java/generated') + api project(':sbe-tool') + api files('build/classes/java/generated') } sourceSets { @@ -485,10 +485,10 @@ project(':sbe-benchmarks') { apply plugin: 'com.github.johnrengelman.shadow' dependencies { - compile "org.openjdk.jmh:jmh-core:${jmhVersion}" + implementation "org.openjdk.jmh:jmh-core:${jmhVersion}" annotationProcessor "org.openjdk.jmh:jmh-generator-annprocess:${jmhVersion}" - compile project(':sbe-tool') - compile files('build/classes/java/generated') + implementation project(':sbe-tool') + implementation files('build/classes/java/generated') } sourceSets { From fbca1c7a670caa629e021d1b157a19420448b4f9 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 7 Jan 2020 12:04:03 +0200 Subject: [PATCH 0319/1594] [Java] Prevent suite cancellation upon a single job failure --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d921aefc4..7881228121 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,7 @@ jobs: name: Java ${{ matrix.java }} runs-on: ubuntu-latest strategy: + fail-fast: false matrix: java: [ '8', '11' ] steps: @@ -44,6 +45,7 @@ jobs: name: C# ${{ matrix.dotnet }} runs-on: ubuntu-latest strategy: + fail-fast: false matrix: dotnet: [ '2.2.103' ] env: @@ -86,6 +88,7 @@ jobs: name: C++ GCC ${{ matrix.version }} runs-on: ubuntu-latest strategy: + fail-fast: false matrix: version: [ '6', '7', '8', '9' ] env: @@ -116,6 +119,7 @@ jobs: name: C++ Clang ${{ matrix.version }} runs-on: ubuntu-latest strategy: + fail-fast: false matrix: version: [ '6.0', '7', '8', '9' ] env: @@ -150,6 +154,7 @@ jobs: name: C++ Xcode ${{ matrix.version }} (macOS) runs-on: macOS-latest strategy: + fail-fast: false matrix: version: [ '11.2.1' ] env: From ab9099bb90947e176c3a0b695189df80073fdac9 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Jan 2020 16:05:22 +0000 Subject: [PATCH 0320/1594] [Java] Upgrade to JUnit 5.6.0-RC1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 303ba2c170..7fc50d0ed6 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ defaultTasks 'clean', 'build', 'shadowJar', 'install' def checkstyleVersion = '8.28' def hamcrestVersion = '2.2' def mockitoVersion = '3.2.4' -def junitVersion = '5.5.2' +def junitVersion = '5.6.0-RC1' def jmhVersion = '1.22' def agronaVersion = '1.1.0' From 9d893a306eccbdaeb97f4128401b1e07cd2f9563 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Jan 2020 18:56:06 +0000 Subject: [PATCH 0321/1594] [Java] Generate only required cases in switches for meta attributes and don't default timeunit and epoch for var data. --- .../sbe/generation/java/JavaGenerator.java | 24 ++++--- .../sbe/ir/generated/FrameCodecDecoder.java | 18 ------ .../sbe/ir/generated/FrameCodecEncoder.java | 18 ------ .../sbe/ir/generated/TokenCodecDecoder.java | 63 ------------------- .../sbe/ir/generated/TokenCodecEncoder.java | 63 ------------------- .../uk/co/real_logic/sbe/xml/Message.java | 6 +- .../real_logic/sbe/xml/XmlSchemaParser.java | 12 ++-- 7 files changed, 26 insertions(+), 178 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 87ea9525ba..92aec62212 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -15,9 +15,7 @@ */ package uk.co.real_logic.sbe.generation.java; -import org.agrona.DirectBuffer; -import org.agrona.MutableDirectBuffer; -import org.agrona.Verify; +import org.agrona.*; import org.agrona.generation.OutputManager; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.generation.CodeGenerator; @@ -2704,10 +2702,22 @@ private static void generateFieldMetaAttributeMethod(final StringBuilder sb, fin .append(propertyName).append("MetaAttribute(final MetaAttribute metaAttribute)\n") .append(indent).append(" {\n") .append(indent).append(" switch (metaAttribute)\n") - .append(indent).append(" {\n") - .append(indent).append(" case EPOCH: return \"").append(epoch).append("\";\n") - .append(indent).append(" case TIME_UNIT: return \"").append(timeUnit).append("\";\n") - .append(indent).append(" case SEMANTIC_TYPE: return \"").append(semanticType).append("\";\n") + .append(indent).append(" {\n"); + + if (!Strings.isEmpty(epoch)) + { + sb.append(indent).append(" case EPOCH: return \"").append(epoch).append("\";\n"); + } + if (!Strings.isEmpty(timeUnit)) + { + sb.append(indent).append(" case TIME_UNIT: return \"").append(timeUnit).append("\";\n"); + } + if (!Strings.isEmpty(semanticType)) + { + sb.append(indent).append(" case SEMANTIC_TYPE: return \"").append(semanticType).append("\";\n"); + } + + sb .append(indent).append(" case PRESENCE: return \"").append(presence).append("\";\n") .append(indent).append(" }\n\n") .append(indent).append(" return \"\";\n") diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 17172e39fa..36c9af639e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -122,9 +122,6 @@ public static String irIdMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -176,9 +173,6 @@ public static String irVersionMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -230,9 +224,6 @@ public static String schemaVersionMetaAttribute(final MetaAttribute metaAttribut { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -279,9 +270,6 @@ public static String packageNameMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -390,9 +378,6 @@ public static String namespaceNameMetaAttribute(final MetaAttribute metaAttribut { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -501,9 +486,6 @@ public static String semanticVersionMetaAttribute(final MetaAttribute metaAttrib { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index 837bb0ce81..0f90fbcf46 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -127,9 +127,6 @@ public static String irIdMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -182,9 +179,6 @@ public static String irVersionMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -237,9 +231,6 @@ public static String schemaVersionMetaAttribute(final MetaAttribute metaAttribut { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -282,9 +273,6 @@ public static String packageNameMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -369,9 +357,6 @@ public static String namespaceNameMetaAttribute(final MetaAttribute metaAttribut { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -456,9 +441,6 @@ public static String semanticVersionMetaAttribute(final MetaAttribute metaAttrib { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index c47860a4ab..4dc388ed3f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -122,9 +122,6 @@ public static String tokenOffsetMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -176,9 +173,6 @@ public static String tokenSizeMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -230,9 +224,6 @@ public static String fieldIdMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -284,9 +275,6 @@ public static String tokenVersionMetaAttribute(final MetaAttribute metaAttribute { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -338,9 +326,6 @@ public static String componentTokenCountMetaAttribute(final MetaAttribute metaAt { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -392,9 +377,6 @@ public static String signalMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -431,9 +413,6 @@ public static String primitiveTypeMetaAttribute(final MetaAttribute metaAttribut { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -470,9 +449,6 @@ public static String byteOrderMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -509,9 +485,6 @@ public static String presenceMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -548,9 +521,6 @@ public static String deprecatedMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "optional"; } @@ -597,9 +567,6 @@ public static String nameMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -708,9 +675,6 @@ public static String constValueMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -819,9 +783,6 @@ public static String minValueMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -930,9 +891,6 @@ public static String maxValueMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -1041,9 +999,6 @@ public static String nullValueMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -1152,9 +1107,6 @@ public static String characterEncodingMetaAttribute(final MetaAttribute metaAttr { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -1263,9 +1215,6 @@ public static String epochMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -1374,9 +1323,6 @@ public static String timeUnitMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -1485,9 +1431,6 @@ public static String semanticTypeMetaAttribute(final MetaAttribute metaAttribute { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -1596,9 +1539,6 @@ public static String descriptionMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -1707,9 +1647,6 @@ public static String referencedNameMetaAttribute(final MetaAttribute metaAttribu { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index dbbc2a74ad..f13ceccd67 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -127,9 +127,6 @@ public static String tokenOffsetMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -182,9 +179,6 @@ public static String tokenSizeMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -237,9 +231,6 @@ public static String fieldIdMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -292,9 +283,6 @@ public static String tokenVersionMetaAttribute(final MetaAttribute metaAttribute { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -347,9 +335,6 @@ public static String componentTokenCountMetaAttribute(final MetaAttribute metaAt { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -402,9 +387,6 @@ public static String signalMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -441,9 +423,6 @@ public static String primitiveTypeMetaAttribute(final MetaAttribute metaAttribut { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -480,9 +459,6 @@ public static String byteOrderMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -519,9 +495,6 @@ public static String presenceMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -558,9 +531,6 @@ public static String deprecatedMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return ""; - case TIME_UNIT: return ""; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "optional"; } @@ -603,9 +573,6 @@ public static String nameMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -690,9 +657,6 @@ public static String constValueMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -777,9 +741,6 @@ public static String minValueMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -864,9 +825,6 @@ public static String maxValueMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -951,9 +909,6 @@ public static String nullValueMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -1038,9 +993,6 @@ public static String characterEncodingMetaAttribute(final MetaAttribute metaAttr { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -1125,9 +1077,6 @@ public static String epochMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -1212,9 +1161,6 @@ public static String timeUnitMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -1299,9 +1245,6 @@ public static String semanticTypeMetaAttribute(final MetaAttribute metaAttribute { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -1386,9 +1329,6 @@ public static String descriptionMetaAttribute(final MetaAttribute metaAttribute) { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } @@ -1473,9 +1413,6 @@ public static String referencedNameMetaAttribute(final MetaAttribute metaAttribu { switch (metaAttribute) { - case EPOCH: return "unix"; - case TIME_UNIT: return "nanosecond"; - case SEMANTIC_TYPE: return ""; case PRESENCE: return "required"; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java index 2fe4fedf4c..541893d2e5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java @@ -160,7 +160,7 @@ public List fields() */ public int blockLength() { - return blockLength > computedBlockLength ? blockLength : computedBlockLength; + return Math.max(blockLength, computedBlockLength); } private List parseMembers(final Node node) throws XPathExpressionException @@ -339,8 +339,8 @@ else if (!(fieldType instanceof CompositeType)) .presence(Presence.get(getAttributeValue(node, "presence", "required"))) .sinceVersion(Integer.parseInt(getAttributeValue(node, "sinceVersion", "0"))) .deprecated(Integer.parseInt(getAttributeValue(node, "deprecated", "0"))) - .epoch(getAttributeValue(node, "epoch", "unix")) - .timeUnit(getAttributeValue(node, "timeUnit", "nanosecond")) + .epoch(getAttributeValueOrNull(node, "epoch")) + .timeUnit(getAttributeValueOrNull(node, "timeUnit")) .type(fieldType) .variableLength(true) .build(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 427f3edf73..e2c4e859ed 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -69,7 +69,7 @@ public class XmlSchemaParser "//*[local-name() = 'message']"; /** - * Validate the document against a given schema. Error will be written to {@link java.lang.System#err} + * Validate the document against a given schema. Error will be written to {@link java.lang.System#err}. * * @param xsdFilename schema to validate against. * @param is source from which schema is read. Ideally it will have the systemId property set to resolve @@ -170,7 +170,7 @@ public static MessageSchema parse(final InputStream in, final ParserOptions opti } /** - * Scan XML for all types (encodedDataType, compositeType, enumType, and setType) and save in map + * Scan XML for all types (encodedDataType, compositeType, enumType, and setType) and save in map. * * @param document for the XML parsing * @param xPath for XPath expression reuse @@ -209,7 +209,7 @@ public static Map findTypes(final Document document, final XPath x } /** - * Scan XML for all message definitions and save in map + * Scan XML for all message definitions and save in map. * * @param document for the XML parsing * @param xPath for XPath expression reuse @@ -311,7 +311,7 @@ public static String getAttributeValue(final Node elementNode, final String attr } /** - * Helper function that hides the null return from {@link org.w3c.dom.NamedNodeMap#getNamedItem(String)} + * Helper function that hides the null return from {@link org.w3c.dom.NamedNodeMap#getNamedItem(String)}. * * @param elementNode that could be null * @param attrName that is to be looked up @@ -334,7 +334,7 @@ public static String getAttributeValueOrNull(final Node elementNode, final Strin } /** - * Helper function to convert a schema byteOrderName into a {@link ByteOrder} + * Helper function to convert a schema byteOrderName into a {@link ByteOrder}. * * @param byteOrderName specified as a FIX SBE string * @return ByteOrder representation @@ -435,7 +435,7 @@ interface NodeFunction void execute(Node node) throws XPathExpressionException; } - private static void forEach(final NodeList nodeList, final NodeFunction func) + static void forEach(final NodeList nodeList, final NodeFunction func) throws XPathExpressionException { for (int i = 0, size = nodeList.getLength(); i < size; i++) From 3249ead687e6b872496b951f53c0ce45c73b3c57 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Jan 2020 19:17:25 +0000 Subject: [PATCH 0322/1594] [Java] Replace generation of switch on metadata attributes with ifs to avoid synthetic class generation. --- .../sbe/generation/java/JavaGenerator.java | 27 ++++-- .../sbe/ir/generated/FrameCodecDecoder.java | 24 +++--- .../sbe/ir/generated/FrameCodecEncoder.java | 24 +++--- .../sbe/ir/generated/TokenCodecDecoder.java | 84 +++++++++---------- .../sbe/ir/generated/TokenCodecEncoder.java | 84 +++++++++---------- 5 files changed, 127 insertions(+), 116 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 92aec62212..09ff46e3e5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2701,25 +2701,36 @@ private static void generateFieldMetaAttributeMethod(final StringBuilder sb, fin .append(indent).append(" public static String ") .append(propertyName).append("MetaAttribute(final MetaAttribute metaAttribute)\n") .append(indent).append(" {\n") - .append(indent).append(" switch (metaAttribute)\n") - .append(indent).append(" {\n"); + .append(indent).append(" if (MetaAttribute.PRESENCE == metaAttribute)\n") + .append(indent).append(" {\n") + .append(indent).append(" return \"").append(presence).append("\";\n") + .append(indent).append(" }\n"); if (!Strings.isEmpty(epoch)) { - sb.append(indent).append(" case EPOCH: return \"").append(epoch).append("\";\n"); + sb.append(indent).append(" if (MetaAttribute.EPOCH == metaAttribute)\n") + .append(indent).append(" {\n") + .append(indent).append(" return \"").append(epoch).append("\";\n") + .append(indent).append(" }\n"); } + if (!Strings.isEmpty(timeUnit)) { - sb.append(indent).append(" case TIME_UNIT: return \"").append(timeUnit).append("\";\n"); + sb.append(indent).append(" if (MetaAttribute.TIME_UNIT == metaAttribute)\n") + .append(indent).append(" {\n") + .append(indent).append(" return \"").append(timeUnit).append("\";\n") + .append(indent).append(" }\n"); } + if (!Strings.isEmpty(semanticType)) { - sb.append(indent).append(" case SEMANTIC_TYPE: return \"").append(semanticType).append("\";\n"); + sb.append(indent).append(" if (MetaAttribute.SEMANTIC_TYPE == metaAttribute)\n") + .append(indent).append(" {\n") + .append(indent).append(" return \"").append(semanticType).append("\";\n") + .append(indent).append(" }\n"); } - sb - .append(indent).append(" case PRESENCE: return \"").append(presence).append("\";\n") - .append(indent).append(" }\n\n") + sb.append("\n") .append(indent).append(" return \"\";\n") .append(indent).append(" }\n"); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 36c9af639e..b48571280b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -120,9 +120,9 @@ public static int irIdEncodingLength() public static String irIdMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -171,9 +171,9 @@ public static int irVersionEncodingLength() public static String irVersionMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -222,9 +222,9 @@ public static int schemaVersionEncodingLength() public static String schemaVersionMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -268,9 +268,9 @@ public static String packageNameCharacterEncoding() public static String packageNameMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -376,9 +376,9 @@ public static String namespaceNameCharacterEncoding() public static String namespaceNameMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -484,9 +484,9 @@ public static String semanticVersionCharacterEncoding() public static String semanticVersionMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index 0f90fbcf46..63b149a6c7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -125,9 +125,9 @@ public static int irIdEncodingLength() public static String irIdMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -177,9 +177,9 @@ public static int irVersionEncodingLength() public static String irVersionMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -229,9 +229,9 @@ public static int schemaVersionEncodingLength() public static String schemaVersionMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -271,9 +271,9 @@ public static String packageNameCharacterEncoding() public static String packageNameMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -355,9 +355,9 @@ public static String namespaceNameCharacterEncoding() public static String namespaceNameMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -439,9 +439,9 @@ public static String semanticVersionCharacterEncoding() public static String semanticVersionMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 4dc388ed3f..2d7f0b3c05 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -120,9 +120,9 @@ public static int tokenOffsetEncodingLength() public static String tokenOffsetMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -171,9 +171,9 @@ public static int tokenSizeEncodingLength() public static String tokenSizeMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -222,9 +222,9 @@ public static int fieldIdEncodingLength() public static String fieldIdMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -273,9 +273,9 @@ public static int tokenVersionEncodingLength() public static String tokenVersionMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -324,9 +324,9 @@ public static int componentTokenCountEncodingLength() public static String componentTokenCountMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -375,9 +375,9 @@ public static int signalEncodingLength() public static String signalMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -411,9 +411,9 @@ public static int primitiveTypeEncodingLength() public static String primitiveTypeMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -447,9 +447,9 @@ public static int byteOrderEncodingLength() public static String byteOrderMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -483,9 +483,9 @@ public static int presenceEncodingLength() public static String presenceMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -519,9 +519,9 @@ public static int deprecatedEncodingLength() public static String deprecatedMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "optional"; + return "optional"; } return ""; @@ -565,9 +565,9 @@ public static String nameCharacterEncoding() public static String nameMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -673,9 +673,9 @@ public static String constValueCharacterEncoding() public static String constValueMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -781,9 +781,9 @@ public static String minValueCharacterEncoding() public static String minValueMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -889,9 +889,9 @@ public static String maxValueCharacterEncoding() public static String maxValueMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -997,9 +997,9 @@ public static String nullValueCharacterEncoding() public static String nullValueMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -1105,9 +1105,9 @@ public static String characterEncodingCharacterEncoding() public static String characterEncodingMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -1213,9 +1213,9 @@ public static String epochCharacterEncoding() public static String epochMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -1321,9 +1321,9 @@ public static String timeUnitCharacterEncoding() public static String timeUnitMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -1429,9 +1429,9 @@ public static String semanticTypeCharacterEncoding() public static String semanticTypeMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -1537,9 +1537,9 @@ public static String descriptionCharacterEncoding() public static String descriptionMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -1645,9 +1645,9 @@ public static String referencedNameCharacterEncoding() public static String referencedNameMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index f13ceccd67..d19dd15aae 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -125,9 +125,9 @@ public static int tokenOffsetEncodingLength() public static String tokenOffsetMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -177,9 +177,9 @@ public static int tokenSizeEncodingLength() public static String tokenSizeMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -229,9 +229,9 @@ public static int fieldIdEncodingLength() public static String fieldIdMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -281,9 +281,9 @@ public static int tokenVersionEncodingLength() public static String tokenVersionMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -333,9 +333,9 @@ public static int componentTokenCountEncodingLength() public static String componentTokenCountMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -385,9 +385,9 @@ public static int signalEncodingLength() public static String signalMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -421,9 +421,9 @@ public static int primitiveTypeEncodingLength() public static String primitiveTypeMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -457,9 +457,9 @@ public static int byteOrderEncodingLength() public static String byteOrderMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -493,9 +493,9 @@ public static int presenceEncodingLength() public static String presenceMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -529,9 +529,9 @@ public static int deprecatedEncodingLength() public static String deprecatedMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "optional"; + return "optional"; } return ""; @@ -571,9 +571,9 @@ public static String nameCharacterEncoding() public static String nameMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -655,9 +655,9 @@ public static String constValueCharacterEncoding() public static String constValueMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -739,9 +739,9 @@ public static String minValueCharacterEncoding() public static String minValueMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -823,9 +823,9 @@ public static String maxValueCharacterEncoding() public static String maxValueMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -907,9 +907,9 @@ public static String nullValueCharacterEncoding() public static String nullValueMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -991,9 +991,9 @@ public static String characterEncodingCharacterEncoding() public static String characterEncodingMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -1075,9 +1075,9 @@ public static String epochCharacterEncoding() public static String epochMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -1159,9 +1159,9 @@ public static String timeUnitCharacterEncoding() public static String timeUnitMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -1243,9 +1243,9 @@ public static String semanticTypeCharacterEncoding() public static String semanticTypeMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -1327,9 +1327,9 @@ public static String descriptionCharacterEncoding() public static String descriptionMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; @@ -1411,9 +1411,9 @@ public static String referencedNameCharacterEncoding() public static String referencedNameMetaAttribute(final MetaAttribute metaAttribute) { - switch (metaAttribute) + if (MetaAttribute.PRESENCE == metaAttribute) { - case PRESENCE: return "required"; + return "required"; } return ""; From 045de02e776d3dcae196c1644fd118cb7c55118e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Jan 2020 15:00:20 +0000 Subject: [PATCH 0323/1594] [Java] Expose correct level of dependency for POM generation. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7fc50d0ed6..542deb8f16 100644 --- a/build.gradle +++ b/build.gradle @@ -307,7 +307,7 @@ project(':sbe-all') { apply plugin: 'com.github.johnrengelman.shadow' dependencies { - implementation project(':sbe-tool') + api project(':sbe-tool') } task sourcesJar(type: Jar) { From 82afd2efe05766b3cb17e2f828dc5dd4cd388afe Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 9 Jan 2020 09:12:09 +0000 Subject: [PATCH 0324/1594] [Java] Increase version number. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 65659b4c80..88e00f364d 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.15.1-SNAPSHOT \ No newline at end of file +1.16.0-SNAPSHOT \ No newline at end of file From ea8fcec98ed9eb23e61a2bd11712af920b7106a1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 10 Jan 2020 09:29:58 +0000 Subject: [PATCH 0325/1594] [Java] Upgrade to Agrona 1.2.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 542deb8f16..1a63c8ba10 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.2.4' def junitVersion = '5.6.0-RC1' def jmhVersion = '1.22' -def agronaVersion = '1.1.0' +def agronaVersion = '1.2.0' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 3caabe64981e623c700e6a752a94b6f349c40993 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 10 Jan 2020 16:32:04 +0000 Subject: [PATCH 0326/1594] [Java] Update README. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 714ee3b55f..6bac51a988 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.15.0 +    1.16.0 ``` @@ -64,7 +64,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.15.0.jar my-sbe-input.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.16.0.jar my-sbe-messages.xml C++ Build using CMake --------------------- From 019c7f15d4cc59d59a60c60e24fba1ca6299f51c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 10 Jan 2020 16:56:04 +0000 Subject: [PATCH 0327/1594] [Java] Depending on implementation rather than api for all jar. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1a63c8ba10..67ff0a31cb 100644 --- a/build.gradle +++ b/build.gradle @@ -307,7 +307,7 @@ project(':sbe-all') { apply plugin: 'com.github.johnrengelman.shadow' dependencies { - api project(':sbe-tool') + implementation project(':sbe-tool') } task sourcesJar(type: Jar) { From 706e690cfd3006b87b0f140068f6489ddf520677 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 10 Jan 2020 17:01:04 +0000 Subject: [PATCH 0328/1594] [Java] Don't depend on Agrona api in all sub modules. --- build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 67ff0a31cb..b1b68eeb38 100644 --- a/build.gradle +++ b/build.gradle @@ -146,8 +146,6 @@ subprojects { jar.enabled = true dependencies { - api "org.agrona:agrona:${agronaVersion}" - testImplementation "org.hamcrest:hamcrest:${hamcrestVersion}" testImplementation "org.mockito:mockito-junit-jupiter:${mockitoVersion}" testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}" @@ -216,6 +214,7 @@ def validationXsdPath = project(':sbe-tool').projectDir.toString() + '/src/main/ project(':sbe-tool') { dependencies { + api "org.agrona:agrona:${agronaVersion}" testImplementation files('build/classes/java/generated') } From 6fa746596ceec3c9d5ef468d3c073b19f4d313cf Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 10 Jan 2020 17:36:36 +0000 Subject: [PATCH 0329/1594] [Java] Tests only apply to sbe-tool module. --- build.gradle | 66 ++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/build.gradle b/build.gradle index b1b68eeb38..444cb66949 100644 --- a/build.gradle +++ b/build.gradle @@ -145,14 +145,6 @@ subprojects { jar.enabled = true - dependencies { - testImplementation "org.hamcrest:hamcrest:${hamcrestVersion}" - testImplementation "org.mockito:mockito-junit-jupiter:${mockitoVersion}" - testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}" - testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" - } - checkstyle.toolVersion = "${checkstyleVersion}" compileJava { @@ -164,31 +156,6 @@ subprojects { options.deprecation = true } - compileTestJava { - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { - options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) - options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) - } - options.encoding = 'UTF-8' - options.deprecation = true - } - - test { - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { - jvmArgs('--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED') - jvmArgs('--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED') - } - - useJUnitPlatform() - - testLogging { - showStandardStreams = true - exceptionFormat = 'full' - } - - reports.html.enabled = false // Disable individual test reports - } - javadoc { title = '

    Simple Binary Encoding (SBE)

    ' options.bottom = 'Copyright © 2013-2020 Real Logic Limited. All Rights Reserved.' @@ -216,6 +183,11 @@ project(':sbe-tool') { dependencies { api "org.agrona:agrona:${agronaVersion}" testImplementation files('build/classes/java/generated') + testImplementation "org.hamcrest:hamcrest:${hamcrestVersion}" + testImplementation "org.mockito:mockito-junit-jupiter:${mockitoVersion}" + testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}" + testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" } sourceSets { @@ -233,7 +205,31 @@ project(':sbe-tool') { classpath += sourceSets.main.runtimeClasspath } - compileTestJava.dependsOn 'compileGeneratedJava' + compileTestJava { + dependsOn 'compileGeneratedJava' + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) + options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) + } + options.encoding = 'UTF-8' + options.deprecation = true + } + + test { + if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + jvmArgs('--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED') + jvmArgs('--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED') + } + + useJUnitPlatform() + + testLogging { + showStandardStreams = true + exceptionFormat = 'full' + } + + reports.html.enabled = false // Disable individual test reports + } task generateCodecs(dependsOn: 'compileJava', type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' @@ -306,7 +302,7 @@ project(':sbe-all') { apply plugin: 'com.github.johnrengelman.shadow' dependencies { - implementation project(':sbe-tool') + compile project(':sbe-tool') } task sourcesJar(type: Jar) { From 53846980a9056c072e660e743244b7ff86d7352b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 10 Jan 2020 18:21:31 +0000 Subject: [PATCH 0330/1594] [Java] Revert to implementation dependency. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 444cb66949..476d714f0b 100644 --- a/build.gradle +++ b/build.gradle @@ -302,7 +302,7 @@ project(':sbe-all') { apply plugin: 'com.github.johnrengelman.shadow' dependencies { - compile project(':sbe-tool') + implementation project(':sbe-tool') } task sourcesJar(type: Jar) { From 35d1a50a92d1c9c4d98fd8307727adc16ac7f881 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 10 Jan 2020 19:38:25 +0000 Subject: [PATCH 0331/1594] [Java] Fix warnings. --- build.gradle | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 476d714f0b..b0386c17f5 100644 --- a/build.gradle +++ b/build.gradle @@ -280,7 +280,7 @@ project(':sbe-tool') { } task sourcesJar(type: Jar) { - archiveClassifier = 'sources' + archiveClassifier.set 'sources' from sourceSets.main.allSource dependsOn 'copyCppFiles' @@ -288,7 +288,7 @@ project(':sbe-tool') { } task javadocJar(type: Jar, dependsOn: javadoc) { - archiveClassifier = 'javadoc' + archiveClassifier.set 'javadoc' from javadoc.destinationDir } @@ -306,7 +306,7 @@ project(':sbe-all') { } task sourcesJar(type: Jar) { - archiveClassifier = 'sources' + archiveClassifier.set 'sources' from project(':sbe-tool').sourceSets.main.allSource } @@ -315,13 +315,13 @@ project(':sbe-all') { } task javadocJar(type: Jar, dependsOn: javadoc) { - archiveClassifier = 'javadoc' + archiveClassifier.set 'javadoc' from javadoc.destinationDir } shadowJar { mustRunAfter jar - archiveClassifier = '' + archiveClassifier.set '' manifest.attributes( 'Main-Class': 'uk.co.real_logic.sbe.SbeTool', 'Specification-Title': 'Simple Binary Encoding', @@ -461,12 +461,12 @@ project(':sbe-samples') { } task sourcesJar(type: Jar) { - archiveClassifier = 'sources' + archiveClassifier.set 'sources' from sourceSets.main.allSource } task javadocJar(type: Jar, dependsOn: javadoc) { - archiveClassifier = 'javadoc' + archiveClassifier.set'javadoc' from javadoc.destinationDir } @@ -521,7 +521,7 @@ project(':sbe-benchmarks') { shadowJar { mustRunAfter jar archiveFileName = 'sbe-benchmarks.jar' - archiveClassifier = 'benchmarks' + archiveClassifier.set 'benchmarks' manifest.attributes('Main-Class': 'org.openjdk.jmh.Main') } } From 9bbf7c847e05273ac93727b0adee5106ce263f6e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 10 Jan 2020 22:09:05 +0000 Subject: [PATCH 0332/1594] [Java] Use custom configuration to build shadow jar with correct POM. --- build.gradle | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index b0386c17f5..c376792a7d 100644 --- a/build.gradle +++ b/build.gradle @@ -301,8 +301,19 @@ project(':sbe-tool') { project(':sbe-all') { apply plugin: 'com.github.johnrengelman.shadow' + configurations { + customApi + } + dependencies { - implementation project(':sbe-tool') + customApi project(':sbe-tool') + } + + sourceSets { + main { + compileClasspath += configurations.customApi + runtimeClasspath += compileClasspath + } } task sourcesJar(type: Jar) { @@ -311,6 +322,7 @@ project(':sbe-all') { } javadoc { + classpath += configurations.customApi source += project(':sbe-tool').sourceSets.main.allJava } @@ -320,7 +332,7 @@ project(':sbe-all') { } shadowJar { - mustRunAfter jar + configurations = [project.configurations.customApi] archiveClassifier.set '' manifest.attributes( 'Main-Class': 'uk.co.real_logic.sbe.SbeTool', @@ -333,6 +345,8 @@ project(':sbe-all') { ) } + jar.finalizedBy shadowJar + uploadArchives { repositories { mavenDeployer { @@ -519,11 +533,12 @@ project(':sbe-benchmarks') { } shadowJar { - mustRunAfter jar archiveFileName = 'sbe-benchmarks.jar' archiveClassifier.set 'benchmarks' manifest.attributes('Main-Class': 'org.openjdk.jmh.Main') } + + jar.finalizedBy shadowJar } /* From 7e9d81d59772e33c1ee1053a8a9b340841deda35 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 10 Jan 2020 22:30:08 +0000 Subject: [PATCH 0333/1594] [Java] Use custom configuration to build shadow jar with correct POM. --- build.gradle | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index c376792a7d..4a2bf247e3 100644 --- a/build.gradle +++ b/build.gradle @@ -302,16 +302,17 @@ project(':sbe-all') { apply plugin: 'com.github.johnrengelman.shadow' configurations { - customApi + customCompile } dependencies { - customApi project(':sbe-tool') + customCompile project(':sbe-tool') + customCompile "org.agrona:agrona:${agronaVersion}" } sourceSets { main { - compileClasspath += configurations.customApi + compileClasspath += configurations.customCompile runtimeClasspath += compileClasspath } } @@ -322,7 +323,7 @@ project(':sbe-all') { } javadoc { - classpath += configurations.customApi + classpath += configurations.customCompile source += project(':sbe-tool').sourceSets.main.allJava } @@ -332,7 +333,7 @@ project(':sbe-all') { } shadowJar { - configurations = [project.configurations.customApi] + configurations = [project.configurations.customCompile] archiveClassifier.set '' manifest.attributes( 'Main-Class': 'uk.co.real_logic.sbe.SbeTool', From 63954104763f0a6f8955229bf998bdbbb2b46d69 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 10 Jan 2020 14:42:33 -0800 Subject: [PATCH 0334/1594] 1.16.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 88e00f364d..71bd5d9ee6 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.16.0-SNAPSHOT \ No newline at end of file +1.16.0 \ No newline at end of file From 9e203348b5aac51db5fde594c5b097321137c596 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 10 Jan 2020 14:44:16 -0800 Subject: [PATCH 0335/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 71bd5d9ee6..847fc873ee 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.16.0 \ No newline at end of file +1.16.1-SNAPSHOT \ No newline at end of file From c6c1fc10a131f67aa23ddc6db9eb35ed72a6a90c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 11 Jan 2020 07:41:06 +0000 Subject: [PATCH 0336/1594] [Java] Remove unnecessary dependency. --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4a2bf247e3..90303fe55f 100644 --- a/build.gradle +++ b/build.gradle @@ -307,7 +307,6 @@ project(':sbe-all') { dependencies { customCompile project(':sbe-tool') - customCompile "org.agrona:agrona:${agronaVersion}" } sourceSets { From 3237f5c1ecc0ca3486ea74a97509aac286148532 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 11 Jan 2020 10:29:11 +0000 Subject: [PATCH 0337/1594] [Java] Filter unneeded dependencies from POMs. --- build.gradle | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index 90303fe55f..f1fb4a4ce8 100644 --- a/build.gradle +++ b/build.gradle @@ -174,6 +174,14 @@ subprojects { install { repositories.mavenInstaller.pom.project(projectPom) + + repositories.mavenInstaller.pom.whenConfigured { + p -> p.dependencies = p.dependencies.findAll { + dep -> !(dep.artifactId.contains("hamcrest") || + dep.artifactId.contains("mockito") || + dep.artifactId.contains("junit")) + } + } } } @@ -301,19 +309,8 @@ project(':sbe-tool') { project(':sbe-all') { apply plugin: 'com.github.johnrengelman.shadow' - configurations { - customCompile - } - dependencies { - customCompile project(':sbe-tool') - } - - sourceSets { - main { - compileClasspath += configurations.customCompile - runtimeClasspath += compileClasspath - } + implementation project(':sbe-tool') } task sourcesJar(type: Jar) { @@ -322,7 +319,6 @@ project(':sbe-all') { } javadoc { - classpath += configurations.customCompile source += project(':sbe-tool').sourceSets.main.allJava } @@ -332,7 +328,6 @@ project(':sbe-all') { } shadowJar { - configurations = [project.configurations.customCompile] archiveClassifier.set '' manifest.attributes( 'Main-Class': 'uk.co.real_logic.sbe.SbeTool', @@ -390,6 +385,12 @@ project(':sbe-all') { archives javadocJar } + install { + repositories.mavenInstaller.pom.whenConfigured { + p -> p.dependencies = [] + } + } + signing { required { isReleaseVersion && gradle.taskGraph.hasTask("uploadArchives") } sign configurations.shadow From 3fb67a2504446c5e3d9bc3e37bb8316bf4963681 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 13 Jan 2020 09:56:19 +0000 Subject: [PATCH 0338/1594] [Java] Filter dependencies in POMs. --- build.gradle | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index f1fb4a4ce8..38cffe8c7e 100644 --- a/build.gradle +++ b/build.gradle @@ -144,7 +144,6 @@ subprojects { version = sbeVersion jar.enabled = true - checkstyle.toolVersion = "${checkstyleVersion}" compileJava { @@ -174,7 +173,6 @@ subprojects { install { repositories.mavenInstaller.pom.project(projectPom) - repositories.mavenInstaller.pom.whenConfigured { p -> p.dependencies = p.dependencies.findAll { dep -> !(dep.artifactId.contains("hamcrest") || @@ -183,6 +181,20 @@ subprojects { } } } + + uploadArchives { + repositories { + mavenDeployer { + pom.whenConfigured { + p -> p.dependencies = p.dependencies.findAll { + dep ->!(dep.artifactId.contains("hamcrest") || + dep.artifactId.contains("mockito") || + dep.artifactId.contains("junit")) + } + } + } + } + } } def validationXsdPath = project(':sbe-tool').projectDir.toString() + '/src/main/resources/fpl/sbe.xsd' @@ -345,7 +357,13 @@ project(':sbe-all') { uploadArchives { repositories { mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + pom.whenConfigured { + p -> p.dependencies = [] + } + + beforeDeployment { + MavenDeployment deployment -> signing.signPom(deployment) + } repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { authentication(userName: ossrhUsername, password: ossrhPassword) @@ -363,7 +381,13 @@ project(':sbe-all') { uploadShadow { repositories { mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + pom.whenConfigured { + p -> p.dependencies = [] + } + + beforeDeployment { + MavenDeployment deployment -> signing.signPom(deployment) + } repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { authentication(userName: ossrhUsername, password: ossrhPassword) From c55ee4db53e3ff9d00317da8125de77923e0087e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 15 Jan 2020 18:29:14 +0000 Subject: [PATCH 0339/1594] [Java] Use consistent methods for naming encoders and decoders. --- .../sbe/generation/java/JavaGenerator.java | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 09ff46e3e5..106f5f02d8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -115,12 +115,12 @@ private static String validateBufferImplementation( private String encoderName(final String className) { - return className + "Encoder"; + return formatClassName(className) + "Encoder"; } private String decoderName(final String className) { - return className + "Decoder"; + return formatClassName(className) + "Decoder"; } private String implementsInterface(final String interfaceName) @@ -209,7 +209,7 @@ private void generateEncoder( generateEncoderGroups(sb, className, groups, BASE_INDENT, false); generateEncoderVarData(sb, className, varData, BASE_INDENT); - generateEncoderDisplay(sb, formatClassName(decoderName(msgToken.name()))); + generateEncoderDisplay(sb, decoderName(msgToken.name())); out.append(sb); out.append("}\n"); @@ -305,7 +305,7 @@ private void generateEncoderGroups( final int groupIndex = i; final String groupName = groupToken.name(); - final String groupClassName = formatClassName(encoderName(groupName)); + final String groupClassName = encoderName(groupName); ++i; final int groupHeaderTokenCount = tokens.get(i).componentTokenCount(); @@ -503,7 +503,7 @@ private void generateGroupEncoderClassHeader( .append(ind).append(" }\n"); sb.append("\n") - .append(ind).append(" public ").append(formatClassName(encoderName(groupName))).append(" next()\n") + .append(ind).append(" public ").append(encoderName(groupName)).append(" next()\n") .append(ind).append(" {\n") .append(ind).append(" if (index + 1 >= count)\n") .append(ind).append(" {\n") @@ -584,7 +584,7 @@ private void generateGroupEncoderClassDeclaration( final String indent, final int dimensionHeaderSize) { - final String className = formatClassName(encoderName(groupName)); + final String className = encoderName(groupName); generateTypeJavadoc(sb, indent, groupToken); new Formatter(sb).format("\n" + @@ -603,7 +603,7 @@ private void generateGroupEncoderClassDeclaration( for (final String subGroupName : subGroupNames) { - final String type = formatClassName(encoderName(subGroupName)); + final String type = encoderName(subGroupName); final String field = formatPropertyName(subGroupName); sb.append(indent).append(" private final ").append(type).append(" ").append(field).append(";\n"); } @@ -617,7 +617,7 @@ private void generateGroupEncoderClassDeclaration( for (final String subGroupName : subGroupNames) { - final String type = formatClassName(encoderName(subGroupName)); + final String type = encoderName(subGroupName); final String field = formatPropertyName(subGroupName); sb .append(indent).append(" ") @@ -1157,7 +1157,7 @@ private void generateDataTypedEncoder( private void generateBitSet(final List tokens) throws IOException { final Token token = tokens.get(0); - final String bitSetName = formatClassName(token.applicableTypeName()); + final String bitSetName = token.applicableTypeName(); final String decoderName = decoderName(bitSetName); final String encoderName = encoderName(bitSetName); final List messageBody = getMessageBody(tokens); @@ -1229,7 +1229,7 @@ private void generateEnum(final List tokens) throws IOException private void generateComposite(final List tokens) throws IOException { final Token token = tokens.get(0); - final String compositeName = formatClassName(token.applicableTypeName()); + final String compositeName = token.applicableTypeName(); final String decoderName = decoderName(compositeName); final String encoderName = encoderName(compositeName); @@ -1243,7 +1243,7 @@ private void generateComposite(final List tokens) throws IOException { final Token encodingToken = tokens.get(i); final String propertyName = formatPropertyName(encodingToken.name()); - final String typeName = formatClassName(decoderName(encodingToken.applicableTypeName())); + final String typeName = decoderName(encodingToken.applicableTypeName()); final StringBuilder sb = new StringBuilder(); generateEncodingOffsetMethod(sb, propertyName, encodingToken.offset(), BASE_INDENT); @@ -1290,7 +1290,7 @@ private void generateComposite(final List tokens) throws IOException { final Token encodingToken = tokens.get(i); final String propertyName = formatPropertyName(encodingToken.name()); - final String typeName = formatClassName(encoderName(encodingToken.applicableTypeName())); + final String typeName = encoderName(encodingToken.applicableTypeName()); final StringBuilder sb = new StringBuilder(); generateEncodingOffsetMethod(sb, propertyName, encodingToken.offset(), BASE_INDENT); @@ -2576,7 +2576,7 @@ private void generateEncoderFields( (fieldToken, typeToken) -> { final String propertyName = formatPropertyName(fieldToken.name()); - final String typeName = formatClassName(encoderName(typeToken.name())); + final String typeName = encoderName(typeToken.name()); generateFieldIdMethod(sb, fieldToken, indent); generateFieldSinceVersionMethod(sb, fieldToken, indent); @@ -2615,7 +2615,7 @@ private void generateDecoderFields(final StringBuilder sb, final List tok (fieldToken, typeToken) -> { final String propertyName = formatPropertyName(fieldToken.name()); - final String typeName = decoderName(formatClassName(typeToken.name())); + final String typeName = decoderName(typeToken.name()); generateFieldIdMethod(sb, fieldToken, indent); generateFieldSinceVersionMethod(sb, fieldToken, indent); @@ -3178,8 +3178,9 @@ private void generateDecoderDisplay( final List varData) { final String indent = INDENT; + final String decoderName = decoderName(name); - appendMessageToString(sb, indent, name + "Decoder"); + appendMessageToString(sb, indent, decoderName); sb.append('\n'); append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, indent, "{"); @@ -3267,7 +3268,7 @@ private void appendDecoderDisplay( } final String groupName = formatPropertyName(groupToken.name()); - final String groupDecoderName = decoderName(formatClassName(groupToken.name())); + final String groupDecoderName = decoderName(groupToken.name()); append( sb, indent, "builder.append(\"" + groupName + Separators.KEY_VALUE + Separators.BEGIN_GROUP + "\");"); From 68527738490fe37e6eb4612c34ca8ae6dea3390d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 20 Jan 2020 10:00:14 +0000 Subject: [PATCH 0340/1594] [Java] Support resetting group count to current index to allow for streaming operations where the group count is difficult to determine upfront but can be limited and reset down to current index value when group is complete. --- .../sbe/generation/java/JavaGenerator.java | 79 +++++++++++-------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 106f5f02d8..c245578586 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -342,6 +342,7 @@ private void generateGroupDecoderClassHeader( final String indent) { final Token groupToken = tokens.get(index); + final String className = formatClassName(groupName); final int dimensionHeaderLen = tokens.get(index + 1).encodedLength(); final Token blockLengthToken = Generators.findFirst("blockLength", tokens, index); @@ -372,14 +373,27 @@ private void generateGroupDecoderClassHeader( .append(indent).append(" if (buffer != this.buffer)\n") .append(indent).append(" {\n") .append(indent).append(" this.buffer = buffer;\n") - .append(indent).append(" }\n") - .append(indent).append(" index = -1;\n") + .append(indent).append(" }\n\n") + .append(indent).append(" index = 0;\n") .append(indent).append(" final int limit = parentMessage.limit();\n") .append(indent).append(" parentMessage.limit(limit + HEADER_SIZE);\n") .append(indent).append(" blockLength = (int)").append(blockLengthGet).append(";\n") .append(indent).append(" count = (int)").append(numInGroupGet).append(";\n") .append(indent).append(" }\n"); + sb.append("\n") + .append(indent).append(" public ").append(className).append(" next()\n") + .append(indent).append(" {\n") + .append(indent).append(" if (index >= count)\n") + .append(indent).append(" {\n") + .append(indent).append(" throw new java.util.NoSuchElementException();\n") + .append(indent).append(" }\n\n") + .append(indent).append(" offset = parentMessage.limit();\n") + .append(indent).append(" parentMessage.limit(offset + blockLength);\n") + .append(indent).append(" ++index;\n\n") + .append(indent).append(" return this;\n") + .append(indent).append(" }\n"); + sb.append("\n") .append(indent).append(" public static int sbeHeaderSize()\n") .append(indent).append(" {\n") @@ -392,7 +406,6 @@ private void generateGroupDecoderClassHeader( .append(indent).append(" return ").append(tokens.get(index).encodedLength()).append(";\n") .append(indent).append(" }\n"); - final String className = formatClassName(groupName); sb.append("\n") .append(indent).append(" public int actingBlockLength()\n") .append(indent).append(" {\n") @@ -412,20 +425,7 @@ private void generateGroupDecoderClassHeader( .append(indent).append(" }\n\n") .append(indent).append(" public boolean hasNext()\n") .append(indent).append(" {\n") - .append(indent).append(" return (index + 1) < count;\n") - .append(indent).append(" }\n"); - - sb.append("\n") - .append(indent).append(" public ").append(className).append(" next()\n") - .append(indent).append(" {\n") - .append(indent).append(" if (index + 1 >= count)\n") - .append(indent).append(" {\n") - .append(indent).append(" throw new java.util.NoSuchElementException();\n") - .append(indent).append(" }\n\n") - .append(indent).append(" offset = parentMessage.limit();\n") - .append(indent).append(" parentMessage.limit(offset + blockLength);\n") - .append(indent).append(" ++index;\n\n") - .append(indent).append(" return this;\n") + .append(indent).append(" return index < count;\n") .append(indent).append(" }\n"); } @@ -477,13 +477,14 @@ private void generateGroupEncoderClassHeader( ind + " {\n" + ind + " this.buffer = buffer;\n" + ind + " }\n\n" + - ind + " index = -1;\n" + + ind + " index = 0;\n" + ind + " this.count = count;\n" + ind + " final int limit = parentMessage.limit();\n" + + ind + " initialLimit = limit;\n" + ind + " parentMessage.limit(limit + HEADER_SIZE);\n" + ind + " %5$s;\n" + ind + " %6$s;\n" + - ind + " }\n\n", + ind + " }\n", parentMessageClassName, mutableBuffer, numInGroupToken.encoding().applicableMinValue().longValue(), @@ -491,21 +492,10 @@ private void generateGroupEncoderClassHeader( blockLengthPut, numInGroupPut); - sb.append(ind).append(" public static int sbeHeaderSize()\n") - .append(ind).append(" {\n") - .append(ind).append(" return HEADER_SIZE;\n") - .append(ind).append(" }\n"); - - sb.append("\n") - .append(ind).append(" public static int sbeBlockLength()\n") - .append(ind).append(" {\n") - .append(ind).append(" return ").append(blockLength).append(";\n") - .append(ind).append(" }\n"); - sb.append("\n") .append(ind).append(" public ").append(encoderName(groupName)).append(" next()\n") .append(ind).append(" {\n") - .append(ind).append(" if (index + 1 >= count)\n") + .append(ind).append(" if (index >= count)\n") .append(ind).append(" {\n") .append(ind).append(" throw new java.util.NoSuchElementException();\n") .append(ind).append(" }\n\n") @@ -514,6 +504,30 @@ private void generateGroupEncoderClassHeader( .append(ind).append(" ++index;\n\n") .append(ind).append(" return this;\n") .append(ind).append(" }\n"); + + final String countOffset = "initialLimit + " + numInGroupToken.offset(); + final String resetCountPut = generatePut( + numInGroupType, countOffset, numInGroupValue, byteOrderString(numInGroupToken.encoding())); + + sb.append("\n") + .append(ind).append(" public int resetCountToIndex()\n") + .append(ind).append(" {\n") + .append(ind).append(" count = index;\n") + .append(ind).append(" ").append(resetCountPut).append(";\n\n") + .append(ind).append(" return count;\n") + .append(ind).append(" }\n"); + + sb.append("\n") + .append(ind).append(" public static int sbeHeaderSize()\n") + .append(ind).append(" {\n") + .append(ind).append(" return HEADER_SIZE;\n") + .append(ind).append(" }\n"); + + sb.append("\n") + .append(ind).append(" public static int sbeBlockLength()\n") + .append(ind).append(" {\n") + .append(ind).append(" return ").append(blockLength).append(";\n") + .append(ind).append(" }\n"); } private static String primitiveTypeName(final Token token) @@ -595,7 +609,8 @@ private void generateGroupEncoderClassDeclaration( indent + " private %4$s buffer;\n" + indent + " private int count;\n" + indent + " private int index;\n" + - indent + " private int offset;\n", + indent + " private int offset;\n" + + indent + " private int initialLimit;\n", className, dimensionHeaderSize, parentMessageClassName, From 9e67177fcee73f20c9289694df030990d1518169 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 20 Jan 2020 10:34:34 +0000 Subject: [PATCH 0341/1594] [Java] Generate minimal set of cases in switch for attribute metadata in C++ codec. --- .../sbe/generation/cpp/CppGenerator.java | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 308e3fdc16..2689fc3891 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -15,6 +15,7 @@ */ package uk.co.real_logic.sbe.generation.cpp; +import org.agrona.Strings; import org.agrona.Verify; import org.agrona.generation.OutputManager; import uk.co.real_logic.sbe.PrimitiveType; @@ -2113,25 +2114,38 @@ private static void generateFieldMetaAttributeMethod( final String timeUnit = encoding.timeUnit() == null ? "" : encoding.timeUnit(); final String semanticType = encoding.semanticType() == null ? "" : encoding.semanticType(); - new Formatter(sb).format("\n" + - indent + " SBE_NODISCARD static const char * %sMetaAttribute(const MetaAttribute metaAttribute)" + - " SBE_NOEXCEPT\n" + - indent + " {\n" + - indent + " switch (metaAttribute)\n" + - indent + " {\n" + - indent + " case MetaAttribute::EPOCH: return \"%s\";\n" + - indent + " case MetaAttribute::TIME_UNIT: return \"%s\";\n" + - indent + " case MetaAttribute::SEMANTIC_TYPE: return \"%s\";\n" + - indent + " case MetaAttribute::PRESENCE: return \"%s\";\n" + - indent + " }\n\n" + + sb.append("\n") + .append(indent).append(" SBE_NODISCARD static const char * ") + .append(token.name()).append("MetaAttribute(const MetaAttribute metaAttribute) SBE_NOEXCEPT\n") + .append(indent).append(" {\n") + .append(indent).append(" switch (metaAttribute)\n") + .append(indent).append(" {\n"); - indent + " return \"\";\n" + - indent + " }\n", - token.name(), - epoch, - timeUnit, - semanticType, - encoding.presence().toString().toLowerCase()); + if (!Strings.isEmpty(epoch)) + { + sb.append(indent) + .append(" case MetaAttribute::EPOCH: return \"").append(epoch).append("\";\n"); + } + + if (!Strings.isEmpty(timeUnit)) + { + sb.append(indent) + .append(" case MetaAttribute::TIME_UNIT: return \"").append(timeUnit).append("\";\n"); + } + + if (!Strings.isEmpty(semanticType)) + { + sb.append(indent) + .append(" case MetaAttribute::SEMANTIC_TYPE: return \"").append(semanticType) + .append("\";\n"); + } + + sb + .append(indent).append(" case MetaAttribute::PRESENCE: return \"") + .append(encoding.presence().toString().toLowerCase()).append("\";\n") + .append(indent).append(" default: return \"\";\n") + .append(indent).append(" }\n") + .append(indent).append(" }\n"); } private static CharSequence generateEnumFieldNotPresentCondition( From 30c6a437faa12ee04b5a83bfb721dfa71434ff21 Mon Sep 17 00:00:00 2001 From: Ofir Green Date: Mon, 20 Jan 2020 13:26:49 +0200 Subject: [PATCH 0342/1594] [C#] Support resetting group count to current index to allow for streaming operations. --- .../generation/csharp/CSharpGenerator.java | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 56b1b6c6bb..1789e0e874 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -201,7 +201,7 @@ private void generateGroupClassHeader( indent + INDENT + INDENT + "_blockLength = _dimensions.BlockLength;\n" + indent + INDENT + INDENT + "_count = (int) _dimensions.NumInGroup;\n" + // cast safety checked above indent + INDENT + INDENT + "_actingVersion = actingVersion;\n" + - indent + INDENT + INDENT + "_index = -1;\n" + + indent + INDENT + INDENT + "_index = 0;\n" + indent + INDENT + INDENT + "_parentMessage.Limit = parentMessage.Limit + SbeHeaderSize;\n" + indent + INDENT + "}\n", parentMessageClassName)); @@ -224,11 +224,11 @@ private void generateGroupClassHeader( indent + INDENT + INDENT + "_parentMessage = parentMessage;\n" + indent + INDENT + INDENT + "_buffer = buffer;\n" + indent + INDENT + INDENT + "_dimensions.Wrap(buffer, parentMessage.Limit, _actingVersion);\n" + - indent + INDENT + INDENT + "_dimensions.BlockLength = (%4$s)%5$d;\n" + - indent + INDENT + INDENT + "_dimensions.NumInGroup = (%6$s)count;\n" + - indent + INDENT + INDENT + "_index = -1;\n" + + indent + INDENT + INDENT + "_dimensions.BlockLength = SbeBlockLength;\n" + + indent + INDENT + INDENT + "_dimensions.NumInGroup = (%5$s) count;\n" + + indent + INDENT + INDENT + "_index = 0;\n" + indent + INDENT + INDENT + "_count = count;\n" + - indent + INDENT + INDENT + "_blockLength = %5$d;\n" + + indent + INDENT + INDENT + "_blockLength = SbeBlockLength;\n" + indent + INDENT + INDENT + "_actingVersion = SchemaVersion;\n" + indent + INDENT + INDENT + "parentMessage.Limit = parentMessage.Limit + SbeHeaderSize;\n" + indent + INDENT + "}\n", @@ -236,7 +236,6 @@ private void generateGroupClassHeader( numInGroupToken.encoding().applicableMinValue().longValue(), numInGroupToken.encoding().applicableMaxValue().longValue(), typeForBlockLength, - blockLength, typeForNumInGroup)); sb.append(String.format("\n" + @@ -245,20 +244,33 @@ private void generateGroupClassHeader( blockLength, dimensionHeaderLength)); - generateGroupEnumerator(sb, groupName, indent); + generateGroupEnumerator(sb, groupName, typeForNumInGroup, indent); } - private void generateGroupEnumerator(final StringBuilder sb, final String groupName, final String indent) + private void generateGroupEnumerator( + final StringBuilder sb, + final String groupName, + final String typeForNumInGroup, + final String indent) { sb.append( indent + INDENT + "public int ActingBlockLength { get { return _blockLength; } }\n\n" + indent + INDENT + "public int Count { get { return _count; } }\n\n" + - indent + INDENT + "public bool HasNext { get { return (_index + 1) < _count; } }\n"); + indent + INDENT + "public bool HasNext { get { return _index < _count; } }\n"); + + sb.append(String.format("\n" + + indent + INDENT + "public int ResetCountToIndex()\n" + + indent + INDENT + "{\n" + + indent + INDENT + INDENT + "_count = _index;\n" + + indent + INDENT + INDENT + "_dimensions.NumInGroup = (%s) _count;\n\n" + + indent + INDENT + INDENT + "return _count;\n" + + indent + INDENT + "}\n", + typeForNumInGroup)); sb.append(String.format("\n" + indent + INDENT + "public %sGroup Next()\n" + indent + INDENT + "{\n" + - indent + INDENT + INDENT + "if (_index + 1 >= _count)\n" + + indent + INDENT + INDENT + "if (_index >= _count)\n" + indent + INDENT + INDENT + "{\n" + indent + INDENT + INDENT + INDENT + "ThrowHelper.ThrowInvalidOperationException();\n" + indent + INDENT + INDENT + "}\n\n" + From e100fcb95a298c879a50f03f46f50fadc15bc4ee Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 20 Jan 2020 14:42:06 +0000 Subject: [PATCH 0343/1594] [C++] Support resetting group count to current index to allow for streaming operations where the group count is difficult to determine upfront but can be limited and reset down to current index value when group is complete. --- .../src/main/cpp/GeneratedStubExample.cpp | 11 +++-- .../sbe/generation/cpp/CppGenerator.java | 42 ++++++++++++++----- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index 1dd42acaa7..b8f1fa2720 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -126,7 +126,6 @@ std::size_t encodeCar(Car &car, char *buffer, std::uint64_t offset, std::uint64_ return car.encodedLength(); } - const char *format(BooleanType::Value value) { if (value == BooleanType::T) @@ -176,8 +175,12 @@ const char *format(bool value) } std::size_t decodeCar( - Car &car, char *buffer, std::uint64_t offset, std::uint64_t actingBlockLength, - std::uint64_t actingVersion, std::uint64_t bufferLength) + Car &car, + char *buffer, + std::uint64_t offset, + std::uint64_t actingBlockLength, + std::uint64_t actingVersion, + std::uint64_t bufferLength) { car.wrapForDecode(buffer, offset, actingBlockLength, actingVersion, bufferLength); @@ -252,7 +255,7 @@ std::size_t decodeCar( char tmp[1024]; std::uint64_t bytesCopied = engine.getFuel(tmp, sizeof(tmp)); - std::cout << "\ncar.engine.effifiency=" << (int)engine.efficiency(); + std::cout << "\ncar.engine.efficiency=" << (int)engine.efficiency(); std::cout << "\ncar.engine.boosterEnabled=" << format(engine.boosterEnabled()); std::cout << "\ncar.engine.fuelLength=" << bytesCopied; std::cout << "\ncar.engine.fuel=" << std::string(tmp, bytesCopied); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 2689fc3891..7bcebd5e1e 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -192,8 +192,8 @@ private static void generateGroupClassHeader( final int blockLength = tokens.get(index).encodedLength(); final Token blockLengthToken = Generators.findFirst("blockLength", tokens, index); final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); - final String cppTypeForBlockLength = cppTypeName(blockLengthToken.encoding().primitiveType()); - final String cppTypeForNumInGroup = cppTypeName(numInGroupToken.encoding().primitiveType()); + final String cppTypeBlockLength = cppTypeName(blockLengthToken.encoding().primitiveType()); + final String cppTypeNumInGroup = cppTypeName(numInGroupToken.encoding().primitiveType()); new Formatter(sb).format("\n" + indent + "class %1$s\n" + @@ -201,6 +201,7 @@ private static void generateGroupClassHeader( indent + "private:\n" + indent + " char *m_buffer = nullptr;\n" + indent + " std::uint64_t m_bufferLength = 0;\n" + + indent + " std::uint64_t m_initialPosition = 0;\n" + indent + " std::uint64_t *m_positionPtr = nullptr;\n" + indent + " std::uint64_t m_blockLength = 0;\n" + indent + " std::uint64_t m_count = 0;\n" + @@ -228,8 +229,9 @@ private static void generateGroupClassHeader( indent + " m_bufferLength = bufferLength;\n" + indent + " m_blockLength = dimensions.blockLength();\n" + indent + " m_count = dimensions.numInGroup();\n" + - indent + " m_index = std::numeric_limits::max();\n" + + indent + " m_index = 0;\n" + indent + " m_actingVersion = actingVersion;\n" + + indent + " m_initialPosition = *pos;\n" + indent + " m_positionPtr = pos;\n" + indent + " *m_positionPtr = *m_positionPtr + %1$d;\n" + indent + " }\n", @@ -262,14 +264,18 @@ private static void generateGroupClassHeader( indent + " %7$s dimensions(buffer, *pos, bufferLength, actingVersion);\n" + indent + " dimensions.blockLength((%1$s)%2$d);\n" + indent + " dimensions.numInGroup((%3$s)count);\n" + - indent + " m_index = std::numeric_limits::max();\n" + + indent + " m_index = 0;\n" + indent + " m_count = count;\n" + indent + " m_blockLength = %2$d;\n" + indent + " m_actingVersion = actingVersion;\n" + + indent + " m_initialPosition = *pos;\n" + indent + " m_positionPtr = pos;\n" + indent + " *m_positionPtr = *m_positionPtr + %4$d;\n" + indent + " }\n", - cppTypeForBlockLength, blockLength, cppTypeForNumInGroup, dimensionHeaderLength, + cppTypeBlockLength, + blockLength, + cppTypeNumInGroup, + dimensionHeaderLength, minCheck, numInGroupToken.encoding().applicableMaxValue().longValue(), dimensionsClassName); @@ -311,25 +317,41 @@ private static void generateGroupClassHeader( indent + " SBE_NODISCARD inline bool hasNext() const SBE_NOEXCEPT\n" + indent + " {\n" + - indent + " return m_index + 1 < m_count;\n" + + indent + " return m_index < m_count;\n" + indent + " }\n\n" + indent + " inline %3$s &next()\n" + indent + " {\n" + + indent + " if (m_index >= m_count)\n" + + indent + " {\n" + + indent + " throw std::runtime_error(\"index >= count [E108]\");\n" + + indent + " }\n" + indent + " m_offset = *m_positionPtr;\n" + indent + " if (SBE_BOUNDS_CHECK_EXPECT(((m_offset + m_blockLength) > m_bufferLength), false))\n" + indent + " {\n" + - indent + " throw std::runtime_error(\"" + - "buffer too short to support next group index [E108]\");\n" + + indent + " throw std::runtime_error(\"buffer too short for next group index [E108]\");\n" + indent + " }\n" + indent + " *m_positionPtr = m_offset + m_blockLength;\n" + indent + " ++m_index;\n\n" + indent + " return *this;\n" + indent + " }\n", - dimensionHeaderLength, blockLength, formatClassName(groupName)); + dimensionHeaderLength, + blockLength, + formatClassName(groupName)); + + sb.append("\n") + .append(indent).append(" inline std::uint64_t resetCountToIndex() SBE_NOEXCEPT\n") + .append(indent).append(" {\n") + .append(indent).append(" m_count = m_index;\n") + .append(indent).append(" ").append(dimensionsClassName) + .append(" dimensions(m_buffer, m_initialPosition, m_bufferLength, m_actingVersion);\n") + .append(indent).append(" dimensions.numInGroup((").append(cppTypeNumInGroup).append(")m_count);\n") + .append(indent).append(" return m_count;\n") + .append(indent).append(" }\n"); - sb.append(indent).append("#if __cplusplus < 201103L\n") + sb.append("\n") + .append(indent).append("#if __cplusplus < 201103L\n") .append(indent).append(" template inline void forEach(Func& func)\n") .append(indent).append(" {\n") .append(indent).append(" while (hasNext())\n") From 6aa64c3c4528dcf7dbc1eecda734b02311a8513f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 21 Jan 2020 08:28:40 +0000 Subject: [PATCH 0344/1594] [Java] Upgrade to JUnit 5.6.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 38cffe8c7e..01af7a3799 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ defaultTasks 'clean', 'build', 'shadowJar', 'install' def checkstyleVersion = '8.28' def hamcrestVersion = '2.2' def mockitoVersion = '3.2.4' -def junitVersion = '5.6.0-RC1' +def junitVersion = '5.6.0' def jmhVersion = '1.22' def agronaVersion = '1.2.0' From bed9e707999f5a12858c5376679e693ebd0d0315 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 21 Jan 2020 08:41:45 -0800 Subject: [PATCH 0345/1594] 1.16.1 released. --- build.gradle | 2 +- version.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 01af7a3799..79d87d90c4 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.2.4' def junitVersion = '5.6.0' def jmhVersion = '1.22' -def agronaVersion = '1.2.0' +def agronaVersion = '1.3.0' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() diff --git a/version.txt b/version.txt index 847fc873ee..bbb75a1b66 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.16.1-SNAPSHOT \ No newline at end of file +1.16.1 \ No newline at end of file From 7c09baf59173a2ec89a55a209c0a5739d1877f1d Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 21 Jan 2020 08:43:28 -0800 Subject: [PATCH 0346/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index bbb75a1b66..90d091dfae 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.16.1 \ No newline at end of file +1.16.2-SNAPSHOT \ No newline at end of file From d130ed2cf500850ee7ffa06f5c702f27074cc157 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 21 Jan 2020 18:57:58 +0000 Subject: [PATCH 0347/1594] Update version refs. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6bac51a988..ecbde4eba6 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.16.0 +    1.16.1 ``` @@ -64,7 +64,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.16.0.jar my-sbe-messages.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.16.1.jar my-sbe-messages.xml C++ Build using CMake --------------------- From d953eba3bc0e411e72b28867bfaeae401d4053ee Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 22 Jan 2020 12:10:24 +0000 Subject: [PATCH 0348/1594] [Java] Upgrade to JMH 1.23. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 79d87d90c4..f585e892a7 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,7 @@ def checkstyleVersion = '8.28' def hamcrestVersion = '2.2' def mockitoVersion = '3.2.4' def junitVersion = '5.6.0' -def jmhVersion = '1.22' +def jmhVersion = '1.23' def agronaVersion = '1.3.0' def sbeGroup = 'uk.co.real-logic' From 0e550fd862ffa2f67aa1c9e6676079afa58f7c07 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 24 Jan 2020 13:40:45 +0000 Subject: [PATCH 0349/1594] [C++] sbePosition() method should be SBE_NOEXCEPT. --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 7bcebd5e1e..04f0ab9301 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -291,7 +291,7 @@ private static void generateGroupClassHeader( indent + " return %2$d;\n" + indent + " }\n\n" + - indent + " SBE_NODISCARD std::uint64_t sbePosition() const\n" + + indent + " SBE_NODISCARD std::uint64_t sbePosition() const SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return *m_positionPtr;\n" + indent + " }\n\n" + From 32290c1cae6093cd2c22e3a44510a30631197250 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 27 Jan 2020 18:13:27 +0000 Subject: [PATCH 0350/1594] [Java] Upgrade to Gradle 6.1.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 58695 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index f585e892a7..1edbda4d53 100644 --- a/build.gradle +++ b/build.gradle @@ -808,6 +808,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.0.1' + gradleVersion = '6.1.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index cc4fdc293d0e50b0ad9b65c16e7ddd1db2f6025b..f3d88b1c2faf2fc91d853cd5d4242b5547257070 100644 GIT binary patch delta 12333 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1ba7206f88..4e1cc9db6b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From bf01599ec739180070f9e50f908a758ae46dede6 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 10 Feb 2020 22:42:40 +0100 Subject: [PATCH 0351/1594] [Java] Migrate to `maven-publish` plugin and cleanup artifacts being published The following changes were done to the generated artifacts: - `sbe-tool`: * exclude Golang sources from all the jars * include C++ oft headers - `sbe-all`: * exclude Golang sources from all the jars * include C++ oft headers - `sbe-samples`: * include generated sources into the jars * include proper MANIFEST metadata Other changes include: - Cleanup build to use helper functions - Configure HTTP timeouts and retries via Gradle system properties --- build.gradle | 375 +++++++++++++++++++--------------------------- gradle.properties | 7 +- 2 files changed, 158 insertions(+), 224 deletions(-) diff --git a/build.gradle b/build.gradle index 1edbda4d53..ec16941a06 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ plugins { id "com.github.ben-manes.versions" version "0.27.0" } -defaultTasks 'clean', 'build', 'shadowJar', 'install' +defaultTasks 'clean', 'build' def checkstyleVersion = '8.28' def hamcrestVersion = '2.2' @@ -39,11 +39,13 @@ def agronaVersion = '1.3.0' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() -group = sbeGroup -version = sbeVersion -ext.isReleaseVersion = !version.endsWith("SNAPSHOT") - ext { + group = sbeGroup + version = sbeVersion + isReleaseVersion = !version.endsWith('-SNAPSHOT') + releasesRepoUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' + snapshotsRepoUrl = 'https://oss.sonatype.org/content/repositories/snapshots/' + if (!project.hasProperty('ossrhUsername')) { ossrhUsername = '' } @@ -126,16 +128,10 @@ allprojects { } } -configurations { - shadow -} - jar.enabled = false subprojects { apply plugin: 'java-library' - apply plugin: 'maven' - apply plugin: 'signing' apply plugin: 'checkstyle' apply plugin: 'eclipse' apply plugin: 'io.freefair.javadoc-links' @@ -143,11 +139,21 @@ subprojects { group = sbeGroup version = sbeVersion - jar.enabled = true checkstyle.toolVersion = "${checkstyleVersion}" - compileJava { - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { + tasks.withType(Sign) { + onlyIf { + isReleaseVersion && gradle.taskGraph.hasTask(tasks.publish) + } + } + + tasks.withType(Jar) { + enabled = true + includeEmptyDirs = false + } + + tasks.withType(JavaCompile) { + if (JavaVersion.current().isJava9Compatible()) { options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) } @@ -161,45 +167,34 @@ subprojects { options.encoding = 'UTF-8' options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_10.ordinal()) { + if (JavaVersion.current().isJava10Compatible()) { options.addBooleanOption 'html5', true } } - signing { - required { isReleaseVersion && gradle.taskGraph.hasTask("uploadArchives") } - sign configurations.archives - } - - install { - repositories.mavenInstaller.pom.project(projectPom) - repositories.mavenInstaller.pom.whenConfigured { - p -> p.dependencies = p.dependencies.findAll { - dep -> !(dep.artifactId.contains("hamcrest") || - dep.artifactId.contains("mockito") || - dep.artifactId.contains("junit")) - } + test { + if (JavaVersion.current().isJava9Compatible()) { + jvmArgs('--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED') + jvmArgs('--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED') } - } - uploadArchives { - repositories { - mavenDeployer { - pom.whenConfigured { - p -> p.dependencies = p.dependencies.findAll { - dep ->!(dep.artifactId.contains("hamcrest") || - dep.artifactId.contains("mockito") || - dep.artifactId.contains("junit")) - } - } - } + useJUnitPlatform() + + testLogging { + showStandardStreams = true + exceptionFormat = 'full' } + + reports.html.enabled = false // Disable individual test reports } } def validationXsdPath = project(':sbe-tool').projectDir.toString() + '/src/main/resources/fpl/sbe.xsd' project(':sbe-tool') { + apply plugin: 'maven-publish' + apply plugin: 'signing' + dependencies { api "org.agrona:agrona:${agronaVersion}" testImplementation files('build/classes/java/generated') @@ -210,52 +205,21 @@ project(':sbe-tool') { testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" } + def generatedDir = 'build/generated-src' sourceSets { - generated.java.srcDir 'build/generated-src' + generated.java.srcDir generatedDir } compileGeneratedJava { - dependsOn 'generateCodecs' - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { - options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) - options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) - } - options.encoding = 'UTF-8' - options.deprecation = true + dependsOn 'generateTestCodecs' classpath += sourceSets.main.runtimeClasspath } - compileTestJava { - dependsOn 'compileGeneratedJava' - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { - options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) - options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) - } - options.encoding = 'UTF-8' - options.deprecation = true - } - - test { - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { - jvmArgs('--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED') - jvmArgs('--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED') - } - - useJUnitPlatform() - - testLogging { - showStandardStreams = true - exceptionFormat = 'full' - } - - reports.html.enabled = false // Disable individual test reports - } - - task generateCodecs(dependsOn: 'compileJava', type: JavaExec) { + task generateTestCodecs(dependsOn: 'compileJava', type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' classpath = sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'build/generated-src', + 'sbe.output.dir': generatedDir, 'sbe.target.language': 'Java', 'sbe.validation.stop.on.error': 'true', 'sbe.validation.xsd': validationXsdPath) @@ -263,27 +227,10 @@ project(':sbe-tool') { 'src/test/resources/composite-elements-schema.xml'] } - uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } - - snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } - - pom.project(projectPom) - } - } - } - jar { + exclude 'golang/templates' + manifest.attributes( - 'Main-Class': 'uk.co.real_logic.sbe.SbeTool', 'Specification-Title': 'Simple Binary Encoding', 'Specification-Version': '1.0', 'Implementation-Title': 'SBE', @@ -293,52 +240,54 @@ project(':sbe-tool') { ) } - task copyCppFiles(type: Copy) { - from 'src/main/cpp/sbe' - from 'src/main/cpp/otf' - into 'build/generated/cpp/cpp' - } - task sourcesJar(type: Jar) { archiveClassifier.set 'sources' from sourceSets.main.allSource + from ('src/main/cpp/otf') { + into 'cpp' - dependsOn 'copyCppFiles' - from 'build/generated/cpp' + } + exclude 'golang/templates' } - task javadocJar(type: Jar, dependsOn: javadoc) { - archiveClassifier.set 'javadoc' - from javadoc.destinationDir + java { + withSourcesJar() + withJavadocJar() } - artifacts { - archives sourcesJar - archives javadocJar + publishing { + publications { + sbe(MavenPublication) { + from components.java + pom(projectPom) + } + } + + repositories { + maven { + url = !isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl + credentials { + username = ossrhUsername + password = ossrhPassword + } + } + } + } + + signing { + sign publishing.publications.sbe } } project(':sbe-all') { + apply plugin: 'maven-publish' + apply plugin: 'signing' apply plugin: 'com.github.johnrengelman.shadow' dependencies { implementation project(':sbe-tool') } - task sourcesJar(type: Jar) { - archiveClassifier.set 'sources' - from project(':sbe-tool').sourceSets.main.allSource - } - - javadoc { - source += project(':sbe-tool').sourceSets.main.allJava - } - - task javadocJar(type: Jar, dependsOn: javadoc) { - archiveClassifier.set 'javadoc' - from javadoc.destinationDir - } - shadowJar { archiveClassifier.set '' manifest.attributes( @@ -354,103 +303,77 @@ project(':sbe-all') { jar.finalizedBy shadowJar - uploadArchives { - repositories { - mavenDeployer { - pom.whenConfigured { - p -> p.dependencies = [] - } - - beforeDeployment { - MavenDeployment deployment -> signing.signPom(deployment) - } + task sourcesJar(type: Jar) { + archiveClassifier.set 'sources' + from project(':sbe-tool').sourceSets.main.allSource + from (project(':sbe-tool').file('src/main/cpp/otf')) { + into 'cpp' + } + exclude 'golang/templates' + } - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } + javadoc { + source += project(':sbe-tool').sourceSets.main.allJava + } - snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } + task javadocJar(type: Jar, dependsOn: javadoc) { + archiveClassifier.set 'javadoc' + from javadoc.destinationDir + } - pom.project(projectPom) + publishing { + publications { + sbeAll(MavenPublication) { + artifact shadowJar + artifact sourcesJar + artifact javadocJar + pom(projectPom) } } - } - - uploadShadow { repositories { - mavenDeployer { - pom.whenConfigured { - p -> p.dependencies = [] - } - - beforeDeployment { - MavenDeployment deployment -> signing.signPom(deployment) - } - - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: ossrhUsername, password: ossrhPassword) + maven { + url = !isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl + credentials { + username = ossrhUsername + password = ossrhPassword } - - snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } - - pom.project(projectPom) } } - - mustRunAfter 'uploadArchives' - } - - artifacts { - archives sourcesJar - archives javadocJar } - install { - repositories.mavenInstaller.pom.whenConfigured { - p -> p.dependencies = [] - } - } - signing { - required { isReleaseVersion && gradle.taskGraph.hasTask("uploadArchives") } - sign configurations.shadow + sign publishing.publications.sbeAll } } project(':sbe-samples') { + apply plugin: 'maven-publish' + apply plugin: 'signing' + dependencies { api project(':sbe-tool') - api files('build/classes/java/generated') + implementation files('build/classes/java/generated') } + def generatedDir = 'build/generated-src' sourceSets { - generated.java.srcDir 'build/generated-src' + generated.java.srcDir generatedDir + } + + compileJava { + dependsOn 'compileGeneratedJava' } compileGeneratedJava { dependsOn 'generateCodecs' - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { - options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) - options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) - } - options.encoding = 'UTF-8' - options.deprecation = true classpath += project(':sbe-all').sourceSets.main.runtimeClasspath } - compileJava { - dependsOn 'compileGeneratedJava' - } - task generateCodecs(type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'build/generated-src', + 'sbe.output.dir': generatedDir, 'sbe.target.language': 'Java', 'sbe.java.generate.interfaces': 'true', 'sbe.validation.stop.on.error': 'true', @@ -481,37 +404,56 @@ project(':sbe-samples') { dependsOn 'runExampleUsingGeneratedStub', 'runExampleUsingGeneratedStubExtension', 'runOtfExample' } - uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } - - snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } + jar { + from sourceSets.generated.output - pom.project(projectPom) - } - } + manifest.attributes( + 'Main-Class': 'uk.co.real_logic.sbe.SbeTool', + 'Specification-Title': 'Simple Binary Encoding', + 'Specification-Version': '1.0', + 'Implementation-Title': 'SBE', + 'Implementation-Version': "${sbeVersion}", + 'Implementation-Vendor': 'Real Logic Limited', + 'Automatic-Module-Name': 'uk.co.real_logic.sbe.samples' + ) } task sourcesJar(type: Jar) { archiveClassifier.set 'sources' from sourceSets.main.allSource + from sourceSets.generated.allSource } - task javadocJar(type: Jar, dependsOn: javadoc) { - archiveClassifier.set'javadoc' - from javadoc.destinationDir + javadoc { + source += sourceSets.generated.allJava } - artifacts { - archives sourcesJar - archives javadocJar + java { + withSourcesJar() + withJavadocJar() + } + + publishing { + publications { + sbeSamples(MavenPublication) { + from components.java + pom(projectPom) + } + } + + repositories { + maven { + url = !isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl + credentials { + username = ossrhUsername + password = ossrhPassword + } + } + } + } + + signing { + sign publishing.publications.sbeSamples } } @@ -531,12 +473,6 @@ project(':sbe-benchmarks') { compileGeneratedJava { dependsOn 'generateCodecs' - if (JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()) { - options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) - options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) - } - options.encoding = 'UTF-8' - options.deprecation = true classpath += project(':sbe-all').sourceSets.main.runtimeClasspath } @@ -794,16 +730,9 @@ task runJavaBenchmarks(type: Exec) { '-w', '1s', '-r', '1s','-wi', '3', '-i', '5', '-tu', 'ns', '-f', '5' } -task uploadToMavenCentral { - dependsOn 'sbe-tool:uploadArchives', - 'sbe-samples:uploadArchives', - 'sbe-all:uploadArchives', - 'sbe-all:uploadShadow' -} - task testReport(type: TestReport) { destinationDir = file("$buildDir/reports/allTests") - // Include the results from the `test` task in all subprojects + // Include the results from the `test` task in all sub-projects reportOn subprojects*.test } diff --git a/gradle.properties b/gradle.properties index f0ce1dd4da..372647326d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,6 @@ -org.gradle.daemon = true +org.gradle.daemon=true + +# HTTP timeouts for Gradle +systemProp.org.gradle.internal.http.connectionTimeout=300000 +systemProp.org.gradle.internal.http.socketTimeout=300000 +systemProp.org.gradle.internal.repository.max.retries=1 \ No newline at end of file From 90ec7b746fcd0923123d2e26f0a4ec4e6c73ea23 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 10 Feb 2020 23:34:28 +0100 Subject: [PATCH 0352/1594] [Java] Remove useless assigment of version/group in the ext block --- build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.gradle b/build.gradle index ec16941a06..c0377d099c 100644 --- a/build.gradle +++ b/build.gradle @@ -40,8 +40,6 @@ def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() ext { - group = sbeGroup - version = sbeVersion isReleaseVersion = !version.endsWith('-SNAPSHOT') releasesRepoUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' snapshotsRepoUrl = 'https://oss.sonatype.org/content/repositories/snapshots/' From 027fe21e865cc135fbda5239cec7d2f47f955610 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 11 Feb 2020 00:57:41 +0100 Subject: [PATCH 0353/1594] [Java] Fix Go code generation, i.e. use `sbe-tool` when generating codes for all languages except of Java --- build.gradle | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index c0377d099c..5978d7199b 100644 --- a/build.gradle +++ b/build.gradle @@ -567,7 +567,7 @@ task generateRustCodecs { */ task generateGolangCodecTestComposite(type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src', 'sbe.target.language': 'golang') @@ -576,7 +576,7 @@ task generateGolangCodecTestComposite(type: JavaExec) { task generateGolangCodecTestBasic(type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src/basic', 'sbe.target.language': 'golang') @@ -585,7 +585,7 @@ task generateGolangCodecTestBasic(type: JavaExec) { task generateGolangCodecTestGroup(type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src/group', 'sbe.target.language': 'golang') @@ -594,7 +594,7 @@ task generateGolangCodecTestGroup(type: JavaExec) { task generateGolangCodecTestVarData(type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src/vardata', 'sbe.target.language': 'golang') @@ -603,7 +603,7 @@ task generateGolangCodecTestVarData(type: JavaExec) { task generateGolangCodecsWithXIncludes(type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src', 'sbe.target.language': 'golang', @@ -615,7 +615,7 @@ task generateGolangCodecsWithXIncludes(type: JavaExec) { task generateGolangCodecsWithXSD(type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src', 'sbe.target.language': 'golang', @@ -653,7 +653,7 @@ task generateGolangCodecs { */ task generateCSharpCodecsWithXIncludes(type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'csharp/sbe-generated', 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharp', @@ -665,7 +665,7 @@ task generateCSharpCodecsWithXIncludes(type: JavaExec) { task generateCSharpCodecsTests(type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'csharp/sbe-generated', 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharp', @@ -698,7 +698,7 @@ task generateJavaIrCodecs(type: JavaExec) { task generateCppIrCodecs(type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/cpp', 'sbe.target.language': 'cpp', @@ -708,7 +708,7 @@ task generateCppIrCodecs(type: JavaExec) { task generateGolangIrCodecs(type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/golang', 'sbe.target.language': 'golang', From fbd09553e3587701347eafca5a01a5d81ab3b661 Mon Sep 17 00:00:00 2001 From: billsegall Date: Tue, 11 Feb 2020 14:42:27 +1000 Subject: [PATCH 0354/1594] Fix a bug in populating optional values when they are arrays --- gocode/Makefile | 2 +- .../resources/example-extension-2-schema.xml | 94 ------------------- .../generation/golang/GolangGenerator.java | 21 ++++- 3 files changed, 18 insertions(+), 99 deletions(-) delete mode 100644 gocode/resources/example-extension-2-schema.xml diff --git a/gocode/Makefile b/gocode/Makefile index c07f7931ba..7a471aee87 100644 --- a/gocode/Makefile +++ b/gocode/Makefile @@ -59,7 +59,7 @@ src/baseline/SbeMarshalling.go: $(DEP) # they geenrate into the same directory but golang doesn't allow that test: $(DEP) (export GOPATH=$(GOPATH) && \ - (for t in baseline extension extension2; do \ + (for t in baseline extension; do \ export GOPATH=$(GOPATH) && \ cd $(GOPATH)/src/$$t && \ go build && \ diff --git a/gocode/resources/example-extension-2-schema.xml b/gocode/resources/example-extension-2-schema.xml deleted file mode 100644 index 330e84c1d5..0000000000 --- a/gocode/resources/example-extension-2-schema.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - T - S - N - K - - - - - - - 9000 - - Petrol - - - - - - 0 - 1 - - - A - B - C - - - 0 - 1 - 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index a16fdbb741..b9b57db312 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -494,10 +494,23 @@ private void generateOptionalInitPrimitive( final Encoding encoding = token.encoding(); // Optional items get initialized to their NullValue - sb.append(String.format( - "\t%1$s = %2$s\n", - varName, - generateNullValueLiteral(encoding.primitiveType(), encoding))); + if (token.arrayLength() > 1) + { + sb.append(String.format( + "\tfor idx := 0; idx < %1$d; idx++ {\n" + + "\t\t%2$s[idx] = %3$s\n" + + "\t}\n", + token.arrayLength(), + varName, + generateNullValueLiteral(encoding.primitiveType(), encoding))); + } + else + { + sb.append(String.format( + "\t%1$s = %2$s\n", + varName, + generateNullValueLiteral(encoding.primitiveType(), encoding))); + } } private void generateConstantInitPrimitive( From 3ef72c9c1a344bc908df9ead86e03f42148b4da8 Mon Sep 17 00:00:00 2001 From: billsegall Date: Tue, 11 Feb 2020 14:52:51 +1000 Subject: [PATCH 0355/1594] Freshen the examples and tests to reflect changes to the example schemas. Drop the gocode specific second extension example as it's a maintenance nightmare. --- build.gradle | 1 - gocode/src/baseline/Car_test.go | 8 +- gocode/src/example-schema/CarExample.go | 239 +----------------------- 3 files changed, 12 insertions(+), 236 deletions(-) diff --git a/build.gradle b/build.gradle index 5978d7199b..7b2c495eb0 100644 --- a/build.gradle +++ b/build.gradle @@ -632,7 +632,6 @@ task generateGolangCodecsWithXSD(type: JavaExec) { 'sbe-tool/src/test/resources/since-deprecated-test-schema.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', 'gocode/resources/example-composite.xml', - 'gocode/resources/example-extension-2-schema.xml', 'gocode/resources/group-with-data-extension-schema.xml', 'gocode/resources/simple.xml'] } diff --git a/gocode/src/baseline/Car_test.go b/gocode/src/baseline/Car_test.go index 2af880336e..f0e601dd21 100644 --- a/gocode/src/baseline/Car_test.go +++ b/gocode/src/baseline/Car_test.go @@ -45,7 +45,7 @@ func TestEncodeDecodeCar(t *testing.T) { pf = append(pf, CarPerformanceFigures{95, acc1}) pf = append(pf, CarPerformanceFigures{99, acc2}) - in := Car{1234, 2013, BooleanType.T, Model.A, [5]uint32{0, 1, 2, 3, 4}, vehicleCode, optionalExtras, Model.A, engine, fuel, pf, manufacturer, model, activationCode} + in := Car{1234, 2013, BooleanType.T, Model.A, [4]uint32{0, 1, 2, 3}, vehicleCode, optionalExtras, Model.A, engine, fuel, pf, manufacturer, model, activationCode} var buf = new(bytes.Buffer) if err := in.Encode(m, buf, true); err != nil { @@ -112,10 +112,8 @@ func TestEncodeDecodeCar(t *testing.T) { } func TestDecodeJavaBuffer(t *testing.T) { - - // The byte array is from the java example for interop test made by - // running with -Dsbe.encoding.filename and then decoded using od -tu1 - data := []byte{49, 0, 1, 0, 1, 0, 0, 0, 210, 4, 0, 0, 0, 0, 0, 0, 221, 7, 1, 65, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 97, 98, 99, 100, 101, 102, 6, 208, 7, 4, 49, 50, 51, 35, 1, 78, 200, 6, 0, 3, 0, 30, 0, 154, 153, 15, 66, 11, 0, 0, 0, 85, 114, 98, 97, 110, 32, 67, 121, 99, 108, 101, 55, 0, 0, 0, 68, 66, 14, 0, 0, 0, 67, 111, 109, 98, 105, 110, 101, 100, 32, 67, 121, 99, 108, 101, 75, 0, 0, 0, 32, 66, 13, 0, 0, 0, 72, 105, 103, 104, 119, 97, 121, 32, 67, 121, 99, 108, 101, 1, 0, 2, 0, 95, 6, 0, 3, 0, 30, 0, 0, 0, 128, 64, 60, 0, 0, 0, 240, 64, 100, 0, 51, 51, 67, 65, 99, 6, 0, 3, 0, 30, 0, 51, 51, 115, 64, 60, 0, 51, 51, 227, 64, 100, 0, 205, 204, 60, 65, 5, 0, 0, 0, 72, 111, 110, 100, 97, 9, 0, 0, 0, 67, 105, 118, 105, 99, 32, 86, 84, 105, 6, 0, 0, 0, 97, 98, 99, 100, 101, 102} + // See ~gocode/src/example-schema/CarExample.go for how this is generated + data := []byte{45, 0, 1, 0, 1, 0, 0, 0, 210, 4, 0, 0, 0, 0, 0, 0, 221, 7, 1, 65, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 97, 98, 99, 100, 101, 102, 6, 208, 7, 4, 49, 50, 51, 35, 1, 78, 200, 6, 0, 3, 0, 30, 0, 154, 153, 15, 66, 11, 0, 0, 0, 85, 114, 98, 97, 110, 32, 67, 121, 99, 108, 101, 55, 0, 0, 0, 68, 66, 14, 0, 0, 0, 67, 111, 109, 98, 105, 110, 101, 100, 32, 67, 121, 99, 108, 101, 75, 0, 0, 0, 32, 66, 13, 0, 0, 0, 72, 105, 103, 104, 119, 97, 121, 32, 67, 121, 99, 108, 101, 1, 0, 2, 0, 95, 6, 0, 3, 0, 30, 0, 0, 0, 128, 64, 60, 0, 0, 0, 240, 64, 100, 0, 51, 51, 67, 65, 99, 6, 0, 3, 0, 30, 0, 51, 51, 115, 64, 60, 0, 51, 51, 227, 64, 100, 0, 205, 204, 60, 65, 5, 0, 0, 0, 72, 111, 110, 100, 97, 9, 0, 0, 0, 67, 105, 118, 105, 99, 32, 86, 84, 105, 6, 0, 0, 0, 97, 98, 99, 100, 101, 102} buf := bytes.NewBuffer(data) m := NewSbeGoMarshaller() diff --git a/gocode/src/example-schema/CarExample.go b/gocode/src/example-schema/CarExample.go index ab5709040c..dee6e32588 100644 --- a/gocode/src/example-schema/CarExample.go +++ b/gocode/src/example-schema/CarExample.go @@ -5,11 +5,9 @@ package main import ( "baseline" // Car "bytes" - "extension" // Car extended with cupholder - "extension2" // extension extended with CO2 + "extension" // Car extended with cupholder "fmt" "io" - "math" "net" "os" "reflect" @@ -39,12 +37,6 @@ func main() { fmt.Println("Example Extension->Car") ExampleExtensionToCar() - fmt.Println("Example Car->Extension2") - ExampleCarToExtension2() - - fmt.Println("Example Extension2->Car") - ExampleExtension2ToCar() - fmt.Println("Example decode using bytes.buffer") ExampleDecodeBuffer() @@ -140,7 +132,7 @@ func ExampleDecodeBuffer() bool { // fmt.Println("\tbuffer is length:", buf.Len()) var c baseline.Car if err := c.Decode(m, buf, hdr.Version, hdr.BlockLength, true); err != nil { - fmt.Println("Failed to decode car", err) + fmt.Println("FIXME: Failed to decode car", err) os.Exit(1) } return true @@ -433,180 +425,6 @@ func ExampleExtensionToCar() bool { return true } -func ExampleExtension2ToCar() bool { - in := makeExtension2() - min := extension2.NewSbeGoMarshaller() - mout := baseline.NewSbeGoMarshaller() - - var buf = new(bytes.Buffer) - if err := in.Encode(min, buf, true); err != nil { - fmt.Println("Encoding Error", err) - os.Exit(1) - } - - var out baseline.Car = *new(baseline.Car) - if err := out.Decode(mout, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil { - fmt.Println("Decoding Error", err) - os.Exit(1) - } - - if in.SerialNumber != out.SerialNumber { - fmt.Println("in.SerialNumber != out.SerialNumber:\n", in.SerialNumber, out.SerialNumber) - os.Exit(1) - } - if in.ModelYear != out.ModelYear { - fmt.Println("in.ModelYear != out.ModelYear:\n", in.ModelYear, out.ModelYear) - os.Exit(1) - } - - // Note casts so we can compare - if in.Available != extension2.BooleanTypeEnum(out.Available) { - fmt.Println("in.Available != out.Available:\n", in.Available, out.Available) - os.Exit(1) - } - if in.Code != extension2.ModelEnum(out.Code) { - fmt.Println("in.Code != out.Code:\n", in.Code, out.Code) - os.Exit(1) - } - if in.SomeNumbers != out.SomeNumbers { - fmt.Println("in.SomeNumbers != out.SomeNumbers:\n", in.SomeNumbers, out.SomeNumbers) - os.Exit(1) - } - if in.VehicleCode != out.VehicleCode { - fmt.Println("in.VehicleCode != out.VehicleCode:\n", in.VehicleCode, out.VehicleCode) - os.Exit(1) - } - if in.Extras != extension2.OptionalExtras(out.Extras) { - fmt.Println("in.Extras != out.Extras:\n", in.Extras, out.Extras) - os.Exit(1) - } - - // DiscountedModel is constant - if extension2.Model.C != extension2.ModelEnum(out.DiscountedModel) { - fmt.Println("in.DiscountedModel != out.DiscountedModel:\n", in.DiscountedModel, out.DiscountedModel) - os.Exit(1) - } - - // Engine has two constant values which in this case should match - if in.Engine.MaxRpm != out.Engine.MaxRpm { - fmt.Println("in.Engine.MaxRpm != out.Engine/MaxRpm:\n", in.Engine.MaxRpm, out.Engine.MaxRpm) - os.Exit(1) - } - - if !reflect.DeepEqual(in.ActivationCode, out.ActivationCode) { - fmt.Println("in.ActivationCode != out.ActivationCode:\n", in.ActivationCode, out.ActivationCode) - os.Exit(1) - - } - - // Extension2 added Co2 to FuelFigures before the UsageDescription - // check UsageDescription still look right - if !reflect.DeepEqual(out.FuelFigures[0].UsageDescription, []uint8("Urban Cycle")) { - fmt.Println("out.FuelFigures[0].UsageDescription != 'Urban Cycle':\n", out.FuelFigures[0].UsageDescription) - os.Exit(1) - } - - return true -} - -func ExampleCarToExtension2() bool { - in := makeCar() - min := baseline.NewSbeGoMarshaller() - mout := extension2.NewSbeGoMarshaller() - - var buf = new(bytes.Buffer) - if err := in.Encode(min, buf, true); err != nil { - fmt.Println("Encoding Error", err) - os.Exit(1) - } - - var out extension2.Car = *new(extension2.Car) - if err := out.Decode(mout, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil { - fmt.Println("Decoding Error", err) - os.Exit(1) - } - - if in.SerialNumber != out.SerialNumber { - fmt.Println("in.SerialNumber != out.SerialNumber:\n", in.SerialNumber, out.SerialNumber) - os.Exit(1) - } - if in.ModelYear != out.ModelYear { - fmt.Println("in.ModelYear != out.ModelYear:\n", in.ModelYear, out.ModelYear) - os.Exit(1) - } - - // Note casts so we can compare - if in.Available != baseline.BooleanTypeEnum(out.Available) { - fmt.Println("in.Available != out.Available:\n", in.Available, out.Available) - os.Exit(1) - } - if in.Code != baseline.ModelEnum(out.Code) { - fmt.Println("in.Code != out.Code:\n", in.Code, out.Code) - os.Exit(1) - } - if in.SomeNumbers != out.SomeNumbers { - fmt.Println("in.SomeNumbers != out.SomeNumbers:\n", in.SomeNumbers, out.SomeNumbers) - os.Exit(1) - } - if in.VehicleCode != out.VehicleCode { - fmt.Println("in.VehicleCode != out.VehicleCode:\n", in.VehicleCode, out.VehicleCode) - os.Exit(1) - } - if in.Extras != baseline.OptionalExtras(out.Extras) { - fmt.Println("in.Extras != out.Extras:\n", in.Extras, out.Extras) - os.Exit(1) - } - - // DiscountedModel is constant - if baseline.Model.C != baseline.ModelEnum(out.DiscountedModel) { - fmt.Println("in.DiscountedModel != out.DiscountedModel:\n", in.DiscountedModel, out.DiscountedModel) - os.Exit(1) - } - - // Engine has two constant values which should come back filled in - if in.Engine.MaxRpm == out.Engine.MaxRpm { - fmt.Println("in.Engine.MaxRpm == out.Engine/MaxRpm (and they should be different):\n", in.Engine.MaxRpm, out.Engine.MaxRpm) - os.Exit(1) - } - - // Engine has constant elements so We should have used our the - // EngineInit() function to fill those in when we created the - // object, and then they will correctly compare - baseline.EngineInit(&in.Engine) - if in.Engine.MaxRpm != out.Engine.MaxRpm { - fmt.Println("in.Engine.MaxRpm != out.Engine.MaxRpm:\n", in.Engine.MaxRpm, out.Engine.MaxRpm) - os.Exit(1) - } - - if !reflect.DeepEqual(in.ActivationCode, out.ActivationCode) { - fmt.Println("in.ActivationCode != out.ActivationCode:\n", in.ActivationCode, out.ActivationCode) - os.Exit(1) - } - - // Extension - // Cupholder is not in example-schema and was introduced in - // extension-schema so it should be NullValue - if out.CupHolderCount != out.CupHolderCountNullValue() { - fmt.Println("out.cupholderCount not successfully nulled:\n", out.CupHolderCount) - os.Exit(1) - } - - // Extension2 - // We added Co2 to FuelFigures before the UsageDescription so - // check Co2 and UsageDescription look right - if !math.IsNaN(float64(out.FuelFigures[0].Co2)) { - fmt.Println("out.FuelFigures[0].Co2 is legit and should be NaN:\n", out.FuelFigures[0].Co2) - os.Exit(1) - } - if !reflect.DeepEqual(out.FuelFigures[0].UsageDescription, []uint8("Urban Cycle")) { - fmt.Println("out.FuelFigures[0].UsageDescription != 'Urban Cycle':\n", out.FuelFigures[0].UsageDescription) - os.Exit(1) - } - - // fmt.Printf("%+v", out) - return true -} - // Helper to make a Car object as per the Java example func makeCar() baseline.Car { return baseline.Car{ @@ -614,7 +432,7 @@ func makeCar() baseline.Car { 2013, baseline.BooleanType.T, baseline.Model.A, - [5]uint32{0, 1, 2, 3, 4}, + [4]uint32{0, 1, 2, 3}, vehicleCode, [8]bool{false, true, true, false, false, false, false, false}, baseline.Model.A, @@ -653,7 +471,7 @@ func makeExtension() extension.Car { 2013, extension.BooleanType.T, extension.Model.A, - [5]uint32{0, 1, 2, 3, 4}, + [4]uint32{0, 1, 2, 3}, vehicleCode, [8]bool{false, true, true, false, false, false, false, false}, extension.Model.A, @@ -665,7 +483,8 @@ func makeExtension() extension.Car { 35, extension.BooleanType.T, extension.EngineBooster{extension.BoostType.NITROUS, 200}}, - 119, // sinceVersion = 1 + [2]int64{119, 120}, // uuid sinceVersion = 1 + 121, // cupHoldercount, sinceVersion = 1 []extension.CarFuelFigures{ extension.CarFuelFigures{30, 35.9, urban}, extension.CarFuelFigures{55, 49.0, combined}, @@ -686,46 +505,6 @@ func makeExtension() extension.Car { activationCode} } -// Helper to make an Extension2 (car with cupholder and c02 info) object -func makeExtension2() extension2.Car { - return extension2.Car{ - 1234, - 2013, - extension2.BooleanType.T, - extension2.Model.A, - [5]uint32{0, 1, 2, 3, 4}, - vehicleCode, - [8]bool{false, true, true, false, false, false, false, false}, - extension2.Model.A, - extension2.Engine{2000, - 4, - 9000, - manufacturerCode, - [6]byte{'P', 'e', 't', 'r', 'o', 'l'}, - 35, - extension2.BooleanType.T, - extension2.EngineBooster{extension2.BoostType.NITROUS, 200}}, - 119, // sinceVersion = 1 - []extension2.CarFuelFigures{ - extension2.CarFuelFigures{30, 35.9, 0.1, urban}, - extension2.CarFuelFigures{55, 49.0, 0.2, combined}, - extension2.CarFuelFigures{75, 40.0, 0.3, highway}}, - []extension2.CarPerformanceFigures{ - extension2.CarPerformanceFigures{95, - []extension2.CarPerformanceFiguresAcceleration{ - extension2.CarPerformanceFiguresAcceleration{30, 4.0}, - extension2.CarPerformanceFiguresAcceleration{60, 7.5}, - extension2.CarPerformanceFiguresAcceleration{100, 12.2}}}, - extension2.CarPerformanceFigures{99, - []extension2.CarPerformanceFiguresAcceleration{ - extension2.CarPerformanceFiguresAcceleration{30, 3.8}, - extension2.CarPerformanceFiguresAcceleration{60, 7.1}, - extension2.CarPerformanceFiguresAcceleration{100, 11.8}}}}, - manufacturer, - model, - activationCode} -} - // MaxInt returns the larger of two ints. func MaxInt(a, b int) int { if a > b { @@ -742,6 +521,6 @@ func MinInt(a, b int) int { return b } -// The byte array is from the java example for interop test made by -// running with -Dsbe.encoding.filename and then decoded using od -tu1 -var data []byte = []byte{49, 0, 1, 0, 1, 0, 0, 0, 210, 4, 0, 0, 0, 0, 0, 0, 221, 7, 1, 65, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 97, 98, 99, 100, 101, 102, 6, 208, 7, 4, 49, 50, 51, 35, 1, 78, 200, 6, 0, 3, 0, 30, 0, 154, 153, 15, 66, 11, 0, 0, 0, 85, 114, 98, 97, 110, 32, 67, 121, 99, 108, 101, 55, 0, 0, 0, 68, 66, 14, 0, 0, 0, 67, 111, 109, 98, 105, 110, 101, 100, 32, 67, 121, 99, 108, 101, 75, 0, 0, 0, 32, 66, 13, 0, 0, 0, 72, 105, 103, 104, 119, 97, 121, 32, 67, 121, 99, 108, 101, 1, 0, 2, 0, 95, 6, 0, 3, 0, 30, 0, 0, 0, 128, 64, 60, 0, 0, 0, 240, 64, 100, 0, 51, 51, 67, 65, 99, 6, 0, 3, 0, 30, 0, 51, 51, 115, 64, 60, 0, 51, 51, 227, 64, 100, 0, 205, 204, 60, 65, 5, 0, 0, 0, 72, 111, 110, 100, 97, 9, 0, 0, 0, 67, 105, 118, 105, 99, 32, 86, 84, 105, 6, 0, 0, 0, 97, 98, 99, 100, 101, 102} +// The byte array can be made at ~rust/car_example/car_example_data.sbe by running gradlew generateCarExampleDataFile +// This can then be decoded using od -tu1 +var data []byte = []byte{45, 0, 1, 0, 1, 0, 0, 0, 210, 4, 0, 0, 0, 0, 0, 0, 221, 7, 1, 65, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 97, 98, 99, 100, 101, 102, 6, 208, 7, 4, 49, 50, 51, 35, 1, 78, 200, 6, 0, 3, 0, 30, 0, 154, 153, 15, 66, 11, 0, 0, 0, 85, 114, 98, 97, 110, 32, 67, 121, 99, 108, 101, 55, 0, 0, 0, 68, 66, 14, 0, 0, 0, 67, 111, 109, 98, 105, 110, 101, 100, 32, 67, 121, 99, 108, 101, 75, 0, 0, 0, 32, 66, 13, 0, 0, 0, 72, 105, 103, 104, 119, 97, 121, 32, 67, 121, 99, 108, 101, 1, 0, 2, 0, 95, 6, 0, 3, 0, 30, 0, 0, 0, 128, 64, 60, 0, 0, 0, 240, 64, 100, 0, 51, 51, 67, 65, 99, 6, 0, 3, 0, 30, 0, 51, 51, 115, 64, 60, 0, 51, 51, 227, 64, 100, 0, 205, 204, 60, 65, 5, 0, 0, 0, 72, 111, 110, 100, 97, 9, 0, 0, 0, 67, 105, 118, 105, 99, 32, 86, 84, 105, 6, 0, 0, 0, 97, 98, 99, 100, 101, 102} From b8cbec84ec09dd0b3669b1e61624bfb18cc6b577 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 11 Feb 2020 10:51:52 +0100 Subject: [PATCH 0356/1594] [Java] Remove `reopened` pull request event from triggering the build --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7881228121..b65d072851 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: branches: - master pull_request: - types: [opened, synchronize, reopened] + types: [opened, synchronize] branches: - master From 5b88c8097aec29ffc2663f3ebebda2b5e1b66e29 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 13 Feb 2020 17:05:37 +0100 Subject: [PATCH 0357/1594] [Java] Add dependency between tests and generated code --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index 7b2c495eb0..5bea0cbde6 100644 --- a/build.gradle +++ b/build.gradle @@ -206,6 +206,10 @@ project(':sbe-tool') { def generatedDir = 'build/generated-src' sourceSets { generated.java.srcDir generatedDir + test { + compileClasspath += generated.output + runtimeClasspath += generated.output + } } compileGeneratedJava { From d4de4bf35523b018aebad254d7cf33c912d7c1e3 Mon Sep 17 00:00:00 2001 From: Sergey Zubarev Date: Mon, 17 Feb 2020 23:52:16 +0300 Subject: [PATCH 0358/1594] Fix decoder benchmark. (#753) --- sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h index 227c5c5f4d..c1c9f6d9e9 100644 --- a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h @@ -77,16 +77,16 @@ class SbeCarCodecBench : public CodecBench car.putModel(MODEL, MODELLEN); return car.encodedLength(); - }; + } virtual std::uint64_t decode(const char *buffer, const std::uint64_t bufferLength) { car.wrapForDecode((char *)buffer, 0, Car::sbeBlockLength(), Car::sbeSchemaVersion(), bufferLength); - int64_t tmpInt; - const char *tmpChar; - double tmpDouble; - bool tmpBool; + volatile int64_t tmpInt; + volatile const char *tmpChar; + volatile double tmpDouble; + volatile bool tmpBool; tmpInt = car.serialNumber(); tmpInt = car.modelYear(); @@ -139,7 +139,7 @@ class SbeCarCodecBench : public CodecBench (void)tmpBool; return car.encodedLength(); - }; + } private: Car car; From 1af4e286f9f2e2353c2d9ff700200c9b14438d18 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 20 Feb 2020 19:58:39 +0000 Subject: [PATCH 0359/1594] [Java] Support optional group for version extension. Issue #754. --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index c245578586..92e782b73c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -682,7 +682,7 @@ private static void generateGroupDecoderProperty( indent + " if (parentMessage.actingVersion < " + token.version() + ")\n" + indent + " {\n" + indent + " " + propertyName + ".count = 0;\n" + - indent + " " + propertyName + ".index = -1;\n" + + indent + " " + propertyName + ".index = 0;\n" + indent + " return " + propertyName + ";\n" + indent + " }\n\n"; From f575244d13dc65d4185756e1b2597f269ce6b14b Mon Sep 17 00:00:00 2001 From: vdaniloff Date: Fri, 21 Feb 2020 20:29:49 +0300 Subject: [PATCH 0360/1594] Eliminated garbage produced in appendTo for set-based fields to allow full GC-free logging of decoders (#755) (cherry picked from commit c011057411efae1bef62a49f39612f042b186c54) --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 92e782b73c..2a038dff9d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3393,10 +3393,13 @@ private int writeTokenDisplay( break; case BEGIN_ENUM: - case BEGIN_SET: append(sb, indent, "builder.append(" + fieldName + "());"); break; + case BEGIN_SET: + append(sb, indent, fieldName + "().appendTo(builder);"); + break; + case BEGIN_COMPOSITE: { final String typeName = formatClassName(decoderName(typeToken.applicableTypeName())); From 4425f9770633dbec8a9609c67855a51595e8eae7 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 22 Feb 2020 10:02:50 +0000 Subject: [PATCH 0361/1594] [Java] Upgrade to Mockito 3.3.0 and Versions 0.28.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 5bea0cbde6..b82f00ccd8 100644 --- a/build.gradle +++ b/build.gradle @@ -24,14 +24,14 @@ plugins { id 'idea' id 'io.freefair.javadoc-links' version '4.1.6' apply false id 'com.github.johnrengelman.shadow' version '5.2.0' apply false - id "com.github.ben-manes.versions" version "0.27.0" + id "com.github.ben-manes.versions" version "0.28.0" } defaultTasks 'clean', 'build' def checkstyleVersion = '8.28' def hamcrestVersion = '2.2' -def mockitoVersion = '3.2.4' +def mockitoVersion = '3.3.0' def junitVersion = '5.6.0' def jmhVersion = '1.23' def agronaVersion = '1.3.0' From 543f901b60bc4fc9b18997258fa70adc8ba8e5c4 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Wed, 16 Oct 2019 18:32:06 +0900 Subject: [PATCH 0362/1594] [C++] Add nodiscard attributes. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 04f0ab9301..a6e0abe85d 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -668,7 +668,7 @@ private void generateVarDataDescriptors( sizeOfLengthField); new Formatter(sb).format("\n" + - indent + " %4$s %1$sLength() const\n" + + indent + " SBE_NODISCARD %4$s %1$sLength() const\n" + indent + " {\n" + "%2$s" + indent + " %4$s length;\n" + @@ -1524,7 +1524,7 @@ private void generateArrayProperty( if (encodingToken.encoding().primitiveType() == PrimitiveType.CHAR) { new Formatter(sb).format("\n" + - indent + " std::string get%1$sAsString() const\n" + + indent + " SBE_NODISCARD std::string get%1$sAsString() const\n" + indent + " {\n" + indent + " const char *buffer = m_buffer + m_offset + %2$d;\n" + indent + " size_t length = 0;\n\n" + @@ -1542,7 +1542,7 @@ private void generateArrayProperty( new Formatter(sb).format("\n" + indent + " #if __cplusplus >= 201703L\n" + - indent + " std::string_view get%1$sAsStringView() const SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD std::string_view get%1$sAsStringView() const SBE_NOEXCEPT\n" + indent + " {\n" + indent + " const char *buffer = m_buffer + m_offset + %2$d;\n" + indent + " size_t length = 0;\n\n" + From 2dec9fbe4022afd54fb5ab5ab7cff79d02b4c141 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Mon, 28 Oct 2019 19:07:28 +0900 Subject: [PATCH 0363/1594] [C++] Use range-based for loop. --- .../co/real_logic/sbe/generation/cpp/CppGenerator.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index a6e0abe85d..257aa20593 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1609,9 +1609,9 @@ private void generateJsonEscapedStringGetter( "%2$s" + indent + " std::ostringstream oss;\n" + indent + " std::string s = get%1$sAsString();\n\n" + - indent + " for (auto c = s.cbegin(); c != s.cend(); c++)\n" + + indent + " for (const auto c : s)\n" + indent + " {\n" + - indent + " switch (*c)\n" + + indent + " switch (c)\n" + indent + " {\n" + indent + " case '\"': oss << \"\\\\\\\"\"; break;\n" + indent + " case '\\\\': oss << \"\\\\\\\\\"; break;\n" + @@ -1621,14 +1621,14 @@ private void generateJsonEscapedStringGetter( indent + " case '\\r': oss << \"\\\\r\"; break;\n" + indent + " case '\\t': oss << \"\\\\t\"; break;\n\n" + indent + " default:\n" + - indent + " if ('\\x00' <= *c && *c <= '\\x1f')\n" + + indent + " if ('\\x00' <= c && c <= '\\x1f')\n" + indent + " {\n" + indent + " oss << \"\\\\u\"" + " << std::hex << std::setw(4)\n" + - indent + " << std::setfill('0') << (int)(*c);\n" + + indent + " << std::setfill('0') << (int)(c);\n" + indent + " }\n" + indent + " else\n" + indent + " {\n" + - indent + " oss << *c;\n" + + indent + " oss << c;\n" + indent + " }\n" + indent + " }\n" + indent + " }\n\n" + From 1584e93e044ac52018ab958b0f01e5fc728bb92b Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Fri, 18 Oct 2019 02:14:28 +0900 Subject: [PATCH 0364/1594] [C++] Stop clang-tidy from falsely analyzing sbeCheckPosition should be static. --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 257aa20593..6541d41163 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -296,6 +296,7 @@ private static void generateGroupClassHeader( indent + " return *m_positionPtr;\n" + indent + " }\n\n" + + indent + " // NOLINTNEXTLINE(readability-convert-member-functions-to-static)\n" + indent + " std::uint64_t sbeCheckPosition(const std::uint64_t position)\n" + indent + " {\n" + indent + " if (SBE_BOUNDS_CHECK_EXPECT((position > m_bufferLength), false))\n" + @@ -1988,6 +1989,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final " return m_position;\n" + " }\n\n" + + " // NOLINTNEXTLINE(readability-convert-member-functions-to-static)\n" + " std::uint64_t sbeCheckPosition(const std::uint64_t position)\n" + " {\n" + " if (SBE_BOUNDS_CHECK_EXPECT((position > m_bufferLength), false))\n" + From 177e21df1fce779e2a9c521e8ce059c9bd9559ed Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 25 Feb 2020 12:27:20 +0000 Subject: [PATCH 0365/1594] [Java] Short circuit toString and appendTo when buffer is null to be a no op. --- .../sbe/generation/java/JavaGenerator.java | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 2a038dff9d..f35825d81e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3090,7 +3090,12 @@ private void generateEncoderDisplay(final StringBuilder sb, final String decoder sb.append('\n'); append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, indent, "{"); - append(sb, indent, INDENT + decoderName + " writer = new " + decoderName + "();"); + append(sb, indent, " if (null == buffer)"); + append(sb, indent, " {"); + append(sb, indent, " return builder;"); + append(sb, indent, " }"); + sb.append('\n'); + append(sb, indent, " final " + decoderName + " writer = new " + decoderName + "();"); append(sb, indent, " writer.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION);"); sb.append('\n'); append(sb, indent, " return writer.appendTo(builder);"); @@ -3105,7 +3110,12 @@ private CharSequence generateCompositeEncoderDisplay(final String decoderName) sb.append('\n'); append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, indent, "{"); - append(sb, indent, INDENT + decoderName + " writer = new " + decoderName + "();"); + append(sb, indent, " if (null == buffer)"); + append(sb, indent, " {"); + append(sb, indent, " return builder;"); + append(sb, indent, " }"); + sb.append('\n'); + append(sb, indent, " final " + decoderName + " writer = new " + decoderName + "();"); append(sb, indent, " writer.wrap(buffer, offset);"); sb.append('\n'); append(sb, indent, " return writer.appendTo(builder);"); @@ -3123,6 +3133,11 @@ private CharSequence generateCompositeDecoderDisplay(final List tokens) sb.append('\n'); append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, indent, "{"); + append(sb, indent, " if (null == buffer)"); + append(sb, indent, " {"); + append(sb, indent, " return builder;"); + append(sb, indent, " }"); + sb.append('\n'); Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); int lengthBeforeLastGeneratedSeparator = -1; @@ -3199,6 +3214,11 @@ private void generateDecoderDisplay( sb.append('\n'); append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, indent, "{"); + append(sb, indent, " if (null == buffer)"); + append(sb, indent, " {"); + append(sb, indent, " return builder;"); + append(sb, indent, " }"); + sb.append('\n'); append(sb, indent, " final int originalLimit = limit();"); append(sb, indent, " limit(initialOffset + actingBlockLength);"); append(sb, indent, " builder.append(\"[" + name + "](sbeTemplateId=\");"); @@ -3240,6 +3260,11 @@ private void appendGroupInstanceDecoderDisplay( sb.append('\n'); append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, indent, "{"); + append(sb, indent, " if (null == buffer)"); + append(sb, indent, " {"); + append(sb, indent, " return builder;"); + append(sb, indent, " }"); + sb.append('\n'); Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); appendDecoderDisplay(sb, fields, groups, varData, indent + INDENT); Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); @@ -3427,6 +3452,11 @@ private void appendToString(final StringBuilder sb, final String indent) sb.append('\n'); append(sb, indent, "public String toString()"); append(sb, indent, "{"); + append(sb, indent, " if (null == buffer)"); + append(sb, indent, " {"); + append(sb, indent, " return \"\";"); + append(sb, indent, " }"); + sb.append('\n'); append(sb, indent, " return appendTo(new StringBuilder()).toString();"); append(sb, indent, "}"); } @@ -3436,7 +3466,12 @@ private void appendMessageToString(final StringBuilder sb, final String indent, sb.append('\n'); append(sb, indent, "public String toString()"); append(sb, indent, "{"); - append(sb, indent, " " + decoderName + " decoder = new " + decoderName + "();"); + append(sb, indent, " if (null == buffer)"); + append(sb, indent, " {"); + append(sb, indent, " return \"\";"); + append(sb, indent, " }"); + sb.append('\n'); + append(sb, indent, " final " + decoderName + " decoder = new " + decoderName + "();"); append(sb, indent, " decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION);"); sb.append('\n'); append(sb, indent, " return decoder.appendTo(new StringBuilder()).toString();"); From dac05e6709f3d4736e3278b1c570a2fb67f1f849 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 25 Feb 2020 12:42:20 +0000 Subject: [PATCH 0366/1594] [Java] Upgrade to Gradle 6.2.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew.bat | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b82f00ccd8..bc0c371728 100644 --- a/build.gradle +++ b/build.gradle @@ -738,6 +738,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.1.1' + gradleVersion = '6.2.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4e1cc9db6b..6254d2d4ae 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew.bat b/gradlew.bat index 9618d8d960..62bd9b9cce 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" From fa95ef199926ebe3c20254292c8421096f20a0c1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 25 Feb 2020 13:27:49 +0000 Subject: [PATCH 0367/1594] [Java] Formatting. --- build.gradle | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index bc0c371728..a6d7ae51d1 100644 --- a/build.gradle +++ b/build.gradle @@ -243,7 +243,7 @@ project(':sbe-tool') { } task sourcesJar(type: Jar) { - archiveClassifier.set 'sources' + archiveClassifier.set('sources') from sourceSets.main.allSource from ('src/main/cpp/otf') { into 'cpp' @@ -291,7 +291,7 @@ project(':sbe-all') { } shadowJar { - archiveClassifier.set '' + archiveClassifier.set('') manifest.attributes( 'Main-Class': 'uk.co.real_logic.sbe.SbeTool', 'Specification-Title': 'Simple Binary Encoding', @@ -306,7 +306,7 @@ project(':sbe-all') { jar.finalizedBy shadowJar task sourcesJar(type: Jar) { - archiveClassifier.set 'sources' + archiveClassifier.set('sources') from project(':sbe-tool').sourceSets.main.allSource from (project(':sbe-tool').file('src/main/cpp/otf')) { into 'cpp' @@ -319,7 +319,7 @@ project(':sbe-all') { } task javadocJar(type: Jar, dependsOn: javadoc) { - archiveClassifier.set 'javadoc' + archiveClassifier.set('javadoc') from javadoc.destinationDir } @@ -421,7 +421,7 @@ project(':sbe-samples') { } task sourcesJar(type: Jar) { - archiveClassifier.set 'sources' + archiveClassifier.set('sources') from sourceSets.main.allSource from sourceSets.generated.allSource } @@ -497,7 +497,7 @@ project(':sbe-benchmarks') { shadowJar { archiveFileName = 'sbe-benchmarks.jar' - archiveClassifier.set 'benchmarks' + archiveClassifier.set('benchmarks') manifest.attributes('Main-Class': 'org.openjdk.jmh.Main') } From 10e9bf2b9144b3396263ebeacc3d2b713105fa16 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Wed, 26 Feb 2020 16:08:45 +0900 Subject: [PATCH 0368/1594] [C++] Put std::string to var length string using overload. --- .../sbe/generation/cpp/CppGenerator.java | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 6541d41163..159b727701 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -591,25 +591,15 @@ private void generateVarData( new Formatter(sb).format("\n" + indent + " %1$s &put%2$s(const std::string& str)\n" + indent + " {\n" + - indent + " if (str.length() > %6$d)\n" + + indent + " if (str.length() > %4$d)\n" + indent + " {\n" + indent + " throw std::runtime_error(\"std::string too long for length type [E109]\");\n" + indent + " }\n" + - indent + " std::uint64_t lengthOfLengthField = %3$d;\n" + - indent + " std::uint64_t lengthPosition = sbePosition();\n" + - indent + " %4$s lengthFieldValue = %5$s(static_cast<%4$s>(str.length()));\n" + - indent + " sbePosition(lengthPosition + lengthOfLengthField);\n" + - indent + " std::memcpy(m_buffer + lengthPosition, &lengthFieldValue, sizeof(%4$s));\n" + - indent + " std::uint64_t pos = sbePosition();\n" + - indent + " sbePosition(pos + str.length());\n" + - indent + " std::memcpy(m_buffer + pos, str.c_str(), str.length());\n" + - indent + " return *this;\n" + + indent + " return put%2$s(str.data(), static_cast<%3$s>(str.length()));" + indent + " }\n", className, propertyName, - lengthOfLengthField, lengthCppType, - lengthByteOrderStr, lengthToken.encoding().applicableMaxValue().longValue()); i += token.componentTokenCount(); From 2f698d211c64512aca1ccf7263532ec673787752 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Wed, 26 Feb 2020 16:11:16 +0900 Subject: [PATCH 0369/1594] [C++] Add method to put var length string from std::string_view. --- .../sbe/generation/cpp/CppGenerator.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 159b727701..be4b5bc994 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -602,6 +602,22 @@ private void generateVarData( lengthCppType, lengthToken.encoding().applicableMaxValue().longValue()); + new Formatter(sb).format("\n" + + indent + " #if __cplusplus >= 201703L\n" + + indent + " %1$s &put%2$s(const std::string_view str)\n" + + indent + " {\n" + + indent + " if (str.length() > %4$d)\n" + + indent + " {\n" + + indent + " throw std::runtime_error(\"std::string too long for length type [E109]\");\n" + + indent + " }\n" + + indent + " return put%2$s(str.data(), static_cast<%3$s>(str.length()));" + + indent + " }\n" + + indent + " #endif\n", + className, + propertyName, + lengthCppType, + lengthToken.encoding().applicableMaxValue().longValue()); + i += token.componentTokenCount(); } } From b54a9af34b2434e216c7a29ce5bd27808a8cfe24 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Wed, 26 Feb 2020 16:37:22 +0900 Subject: [PATCH 0370/1594] [C++] Check the length passed to put method for var length strings. Passing nullptr as src to std::memcpy is undefined behavior even if the length is zero is undefined behavior. --- .../co/real_logic/sbe/generation/cpp/CppGenerator.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index be4b5bc994..ec1b200d3d 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -531,9 +531,12 @@ private void generateVarData( indent + " %3$s lengthFieldValue = %4$s(length);\n" + indent + " sbePosition(lengthPosition + lengthOfLengthField);\n" + indent + " std::memcpy(m_buffer + lengthPosition, &lengthFieldValue, sizeof(%3$s));\n" + - indent + " std::uint64_t pos = sbePosition();\n" + - indent + " sbePosition(pos + length);\n" + - indent + " std::memcpy(m_buffer + pos, src, length);\n" + + indent + " if (length != %3$s(0))" + + indent + " {" + + indent + " std::uint64_t pos = sbePosition();\n" + + indent + " sbePosition(pos + length);\n" + + indent + " std::memcpy(m_buffer + pos, src, length);\n" + + indent + " }" + indent + " return *this;\n" + indent + " }\n", propertyName, From 744c47510041a79b281e6633bd8b752ab708a408 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Thu, 27 Feb 2020 01:39:01 +0900 Subject: [PATCH 0371/1594] [C++] Formatting --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index ec1b200d3d..2d8da61aa0 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -531,12 +531,12 @@ private void generateVarData( indent + " %3$s lengthFieldValue = %4$s(length);\n" + indent + " sbePosition(lengthPosition + lengthOfLengthField);\n" + indent + " std::memcpy(m_buffer + lengthPosition, &lengthFieldValue, sizeof(%3$s));\n" + - indent + " if (length != %3$s(0))" + - indent + " {" + + indent + " if (length != %3$s(0))\n" + + indent + " {\n" + indent + " std::uint64_t pos = sbePosition();\n" + indent + " sbePosition(pos + length);\n" + indent + " std::memcpy(m_buffer + pos, src, length);\n" + - indent + " }" + + indent + " }\n" + indent + " return *this;\n" + indent + " }\n", propertyName, From 349f203c1a3e519c9eaa1e9229808a755ac51979 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Wed, 26 Feb 2020 08:50:18 -0800 Subject: [PATCH 0372/1594] update Agrona dependency. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a6d7ae51d1..c08a9fc3b5 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.3.0' def junitVersion = '5.6.0' def jmhVersion = '1.23' -def agronaVersion = '1.3.0' +def agronaVersion = '1.4.0' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From b8f8453859191ba00a6735a7ead5644808c473cb Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 27 Feb 2020 11:11:09 +0000 Subject: [PATCH 0373/1594] [Java] Update version for upcoming release. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ecbde4eba6..b1ea210ebd 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.16.1 +    1.16.2 ``` @@ -64,7 +64,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-1.16.1.jar my-sbe-messages.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-${SBE_VERSION}.jar my-sbe-messages.xml C++ Build using CMake --------------------- From b12d9948591bec66a89444121d83f1bfc2c46c0e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 27 Feb 2020 11:12:58 +0000 Subject: [PATCH 0374/1594] [Java] Update version for upcoming release. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b1ea210ebd..e4f7591933 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-${SBE_VERSION}.jar my-sbe-messages.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-${SBE_LIB_VERSION}.jar my-sbe-messages.xml C++ Build using CMake --------------------- From 5a5d1932d809827d40ee92f5874075d73135f0c1 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Thu, 27 Feb 2020 10:40:02 -0800 Subject: [PATCH 0375/1594] 1.16.2 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 90d091dfae..f21c0ae0be 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.16.2-SNAPSHOT \ No newline at end of file +1.16.2 \ No newline at end of file From 3a3e6245510bc257b99dbbf5518633a5fed9bf15 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Thu, 27 Feb 2020 10:41:55 -0800 Subject: [PATCH 0376/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index f21c0ae0be..994e1f8ad8 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.16.2 \ No newline at end of file +1.16.3-SNAPSHOT \ No newline at end of file From b396208ba7669f0afaf20638c9ee0f3a0026244a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 27 Feb 2020 19:51:50 +0000 Subject: [PATCH 0377/1594] [Java] Make codec toString() methods version aware. --- .../sbe/generation/java/JavaGenerator.java | 14 +++++++------- .../sbe/ir/generated/FrameCodecDecoder.java | 14 ++++++++++++-- .../sbe/ir/generated/FrameCodecEncoder.java | 16 +++++++++++++--- .../sbe/ir/generated/MessageHeaderDecoder.java | 10 ++++++++++ .../sbe/ir/generated/MessageHeaderEncoder.java | 16 +++++++++++++--- .../sbe/ir/generated/TokenCodecDecoder.java | 14 ++++++++++++-- .../sbe/ir/generated/TokenCodecEncoder.java | 16 +++++++++++++--- .../sbe/ir/generated/VarDataEncodingDecoder.java | 10 ++++++++++ .../sbe/ir/generated/VarDataEncodingEncoder.java | 16 +++++++++++++--- 9 files changed, 103 insertions(+), 23 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index f35825d81e..bbc4f015ad 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3095,10 +3095,10 @@ private void generateEncoderDisplay(final StringBuilder sb, final String decoder append(sb, indent, " return builder;"); append(sb, indent, " }"); sb.append('\n'); - append(sb, indent, " final " + decoderName + " writer = new " + decoderName + "();"); - append(sb, indent, " writer.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION);"); + append(sb, indent, " final " + decoderName + " decoder = new " + decoderName + "();"); + append(sb, indent, " decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION);"); sb.append('\n'); - append(sb, indent, " return writer.appendTo(builder);"); + append(sb, indent, " return decoder.appendTo(builder);"); append(sb, indent, "}"); } @@ -3115,10 +3115,10 @@ private CharSequence generateCompositeEncoderDisplay(final String decoderName) append(sb, indent, " return builder;"); append(sb, indent, " }"); sb.append('\n'); - append(sb, indent, " final " + decoderName + " writer = new " + decoderName + "();"); - append(sb, indent, " writer.wrap(buffer, offset);"); + append(sb, indent, " final " + decoderName + " decoder = new " + decoderName + "();"); + append(sb, indent, " decoder.wrap(buffer, offset);"); sb.append('\n'); - append(sb, indent, " return writer.appendTo(builder);"); + append(sb, indent, " return decoder.appendTo(builder);"); append(sb, indent, "}"); return sb; @@ -3472,7 +3472,7 @@ private void appendMessageToString(final StringBuilder sb, final String indent, append(sb, indent, " }"); sb.append('\n'); append(sb, indent, " final " + decoderName + " decoder = new " + decoderName + "();"); - append(sb, indent, " decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION);"); + append(sb, indent, " decoder.wrap(buffer, initialOffset, actingBlockLength, actingVersion);"); sb.append('\n'); append(sb, indent, " return decoder.appendTo(new StringBuilder()).toString();"); append(sb, indent, "}"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index b48571280b..8428eefad0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -577,14 +577,24 @@ public String semanticVersion() public String toString() { - FrameCodecDecoder decoder = new FrameCodecDecoder(); - decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION); + if (null == buffer) + { + return ""; + } + + final FrameCodecDecoder decoder = new FrameCodecDecoder(); + decoder.wrap(buffer, initialOffset, actingBlockLength, actingVersion); return decoder.appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) { + if (null == buffer) + { + return builder; + } + final int originalLimit = limit(); limit(initialOffset + actingBlockLength); builder.append("[FrameCodec](sbeTemplateId="); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index 63b149a6c7..e12b0380ad 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -513,14 +513,24 @@ public FrameCodecEncoder semanticVersion(final String value) public String toString() { + if (null == buffer) + { + return ""; + } + return appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) { - FrameCodecDecoder writer = new FrameCodecDecoder(); - writer.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION); + if (null == buffer) + { + return builder; + } + + final FrameCodecDecoder decoder = new FrameCodecDecoder(); + decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION); - return writer.appendTo(builder); + return decoder.appendTo(builder); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java index 7e43a9b990..8056af47c6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java @@ -199,11 +199,21 @@ public int version() public String toString() { + if (null == buffer) + { + return ""; + } + return appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) { + if (null == buffer) + { + return builder; + } + builder.append('('); builder.append("blockLength="); builder.append(blockLength()); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java index ffacea8c31..4bee4884ea 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java @@ -183,14 +183,24 @@ public MessageHeaderEncoder version(final int value) public String toString() { + if (null == buffer) + { + return ""; + } + return appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) { - MessageHeaderDecoder writer = new MessageHeaderDecoder(); - writer.wrap(buffer, offset); + if (null == buffer) + { + return builder; + } + + final MessageHeaderDecoder decoder = new MessageHeaderDecoder(); + decoder.wrap(buffer, offset); - return writer.appendTo(builder); + return decoder.appendTo(builder); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 2d7f0b3c05..ad223fbab1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -1738,14 +1738,24 @@ public String referencedName() public String toString() { - TokenCodecDecoder decoder = new TokenCodecDecoder(); - decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION); + if (null == buffer) + { + return ""; + } + + final TokenCodecDecoder decoder = new TokenCodecDecoder(); + decoder.wrap(buffer, initialOffset, actingBlockLength, actingVersion); return decoder.appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) { + if (null == buffer) + { + return builder; + } + final int originalLimit = limit(); limit(initialOffset + actingBlockLength); builder.append("[TokenCodec](sbeTemplateId="); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index d19dd15aae..c7a676ab0e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -1485,14 +1485,24 @@ public TokenCodecEncoder referencedName(final String value) public String toString() { + if (null == buffer) + { + return ""; + } + return appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) { - TokenCodecDecoder writer = new TokenCodecDecoder(); - writer.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION); + if (null == buffer) + { + return builder; + } + + final TokenCodecDecoder decoder = new TokenCodecDecoder(); + decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION); - return writer.appendTo(builder); + return decoder.appendTo(builder); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java index fdda13dee1..1215de103b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java @@ -121,11 +121,21 @@ public static short varDataMaxValue() public String toString() { + if (null == buffer) + { + return ""; + } + return appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) { + if (null == buffer) + { + return builder; + } + builder.append('('); builder.append("length="); builder.append(length()); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java index f15f1828f7..e7a6015993 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java @@ -112,14 +112,24 @@ public static short varDataMaxValue() public String toString() { + if (null == buffer) + { + return ""; + } + return appendTo(new StringBuilder()).toString(); } public StringBuilder appendTo(final StringBuilder builder) { - VarDataEncodingDecoder writer = new VarDataEncodingDecoder(); - writer.wrap(buffer, offset); + if (null == buffer) + { + return builder; + } + + final VarDataEncodingDecoder decoder = new VarDataEncodingDecoder(); + decoder.wrap(buffer, offset); - return writer.appendTo(builder); + return decoder.appendTo(builder); } } From 2f6a58b8b9541b8c2bb8d90475c5840d711488ec Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 28 Feb 2020 11:07:16 +0000 Subject: [PATCH 0378/1594] [Java] Fix warnings. --- .../java/uk/co/real_logic/sbe/xml/EnumType.java | 2 +- .../uk/co/real_logic/sbe/xml/XmlSchemaParser.java | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index d97ab07f4f..8c2d442bf4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -87,7 +87,7 @@ public EnumType(final Node node, final String givenName, final String referenced default: // might not have ran into this type yet, so look for it final Node encodingTypeNode = (Node)xPath.compile( - String.format("%s[@name=\'%s\']", XmlSchemaParser.TYPE_XPATH_EXPR, encodingTypeStr)) + String.format("%s[@name='%s']", XmlSchemaParser.TYPE_XPATH_EXPR, encodingTypeStr)) .evaluate(node.getOwnerDocument(), XPathConstants.NODE); if (null == encodingTypeNode) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index e2c4e859ed..6d5f9e87f1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -341,17 +341,12 @@ public static String getAttributeValueOrNull(final Node elementNode, final Strin */ public static ByteOrder getByteOrder(final String byteOrderName) { - switch (byteOrderName) + if ("bigEndian".equals(byteOrderName)) { - case "littleEndian": - return ByteOrder.LITTLE_ENDIAN; - - case "bigEndian": - return ByteOrder.BIG_ENDIAN; - - default: - return ByteOrder.LITTLE_ENDIAN; + return ByteOrder.BIG_ENDIAN; } + + return ByteOrder.LITTLE_ENDIAN; } /** From 145eec6745b6f4c4e1e9dbf40d129748a8853e49 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 28 Feb 2020 16:01:55 +0000 Subject: [PATCH 0379/1594] [Java] Increase version for release. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e4f7591933..a7fa196245 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.16.2 +    1.16.3 ``` From 5f0e1808d7815766b77525b1ce76e54bcf21ae22 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 28 Feb 2020 08:09:27 -0800 Subject: [PATCH 0380/1594] 1.16.3 released --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 994e1f8ad8..b8ae5a5b4d 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.16.3-SNAPSHOT \ No newline at end of file +1.16.3 \ No newline at end of file From 4a30ef91bd53506754bdba377a8e02ee4fd8ec94 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 28 Feb 2020 08:10:40 -0800 Subject: [PATCH 0381/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index b8ae5a5b4d..9cee920373 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.16.3 \ No newline at end of file +1.16.4-SNAPSHOT \ No newline at end of file From 6ec0439cc3ac4b10f7a4ed9011bc7e34486b911a Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 3 Mar 2020 23:37:25 +0000 Subject: [PATCH 0382/1594] [Java] Workaround for the https://issues.sonatype.org/browse/NEXUS-21802 bug --- gradle.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 372647326d..0dfc37be2d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,5 @@ org.gradle.daemon=true # HTTP timeouts for Gradle systemProp.org.gradle.internal.http.connectionTimeout=300000 systemProp.org.gradle.internal.http.socketTimeout=300000 -systemProp.org.gradle.internal.repository.max.retries=1 \ No newline at end of file +systemProp.org.gradle.internal.repository.max.retries=1 +systemProp.org.gradle.internal.publish.checksums.insecure=true \ No newline at end of file From 0bf900cea05657778a9c663995977a5c5b60fd69 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 9 Mar 2020 14:04:59 +0000 Subject: [PATCH 0383/1594] [Java] Upgrade to Gradle 6.2.2. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index c08a9fc3b5..756e746e67 100644 --- a/build.gradle +++ b/build.gradle @@ -738,6 +738,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.2.1' + gradleVersion = '6.2.2' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6254d2d4ae..84a906615c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 23e8c16caf03d2b073bc850f37b1fb68cecbe54a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 9 Mar 2020 16:43:07 +0000 Subject: [PATCH 0384/1594] [C#] Use sinceVersion from field in C# codecs. Issue #763. --- .../generation/csharp/CSharpGenerator.java | 132 +++++++++--------- 1 file changed, 68 insertions(+), 64 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 1789e0e874..4185ebeb60 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -510,19 +510,19 @@ private CharSequence generateCompositePropertyElements(final List tokens, switch (token.signal()) { case ENCODING: - sb.append(generatePrimitiveProperty(propertyName, token, indent)); + sb.append(generatePrimitiveProperty(propertyName, token, token, indent)); break; case BEGIN_ENUM: - sb.append(generateEnumProperty(propertyName, token, null, indent)); + sb.append(generateEnumProperty(propertyName, token, token, indent)); break; case BEGIN_SET: - sb.append(generateBitSetProperty(propertyName, token, indent)); + sb.append(generateBitSetProperty(propertyName, token, token, indent)); break; case BEGIN_COMPOSITE: - sb.append(generateCompositeProperty(propertyName, token, indent)); + sb.append(generateCompositeProperty(propertyName, token, token, indent)); break; } @@ -643,19 +643,20 @@ private CharSequence generateEnumDeclaration( return result; } - private CharSequence generatePrimitiveProperty(final String propertyName, final Token token, final String indent) + private CharSequence generatePrimitiveProperty( + final String propertyName, final Token fieldToken, final Token typeToken, final String indent) { final StringBuilder sb = new StringBuilder(); - sb.append(generatePrimitiveFieldMetaData(propertyName, token, indent + INDENT)); + sb.append(generatePrimitiveFieldMetaData(propertyName, typeToken, indent + INDENT)); - if (token.isConstantEncoding()) + if (typeToken.isConstantEncoding()) { - sb.append(generateConstPropertyMethods(propertyName, token, indent)); + sb.append(generateConstPropertyMethods(propertyName, typeToken, indent)); } else { - sb.append(generatePrimitivePropertyMethods(propertyName, token, indent)); + sb.append(generatePrimitivePropertyMethods(propertyName, fieldToken, typeToken, indent)); } return sb; @@ -663,18 +664,19 @@ private CharSequence generatePrimitiveProperty(final String propertyName, final private CharSequence generatePrimitivePropertyMethods( final String propertyName, - final Token token, + final Token fieldToken, + final Token typeToken, final String indent) { - final int arrayLength = token.arrayLength(); + final int arrayLength = typeToken.arrayLength(); if (arrayLength == 1) { - return generateSingleValueProperty(propertyName, token, indent + INDENT); + return generateSingleValueProperty(propertyName, fieldToken, typeToken, indent + INDENT); } else if (arrayLength > 1) { - return generateArrayProperty(propertyName, token, indent + INDENT); + return generateArrayProperty(propertyName, fieldToken, typeToken, indent + INDENT); } return ""; @@ -702,14 +704,15 @@ private CharSequence generatePrimitiveFieldMetaData( private CharSequence generateSingleValueProperty( final String propertyName, - final Token token, + final Token fieldToken, + final Token typeToken, final String indent) { - final String typeName = cSharpTypeName(token.encoding().primitiveType()); - final String typePrefix = toUpperFirstChar(token.encoding().primitiveType().primitiveName()); - final int offset = token.offset(); - final ByteOrder byteOrder = token.encoding().byteOrder(); - final String byteOrderStr = generateByteOrder(byteOrder, token.encoding().primitiveType().size()); + final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); + final String typePrefix = toUpperFirstChar(typeToken.encoding().primitiveType().primitiveName()); + final int offset = typeToken.offset(); + final ByteOrder byteOrder = typeToken.encoding().byteOrder(); + final String byteOrderStr = generateByteOrder(byteOrder, typeToken.encoding().primitiveType().size()); return String.format("\n" + indent + "public %1$s %2$s\n" + @@ -726,7 +729,7 @@ private CharSequence generateSingleValueProperty( indent + "}\n\n", typeName, toUpperFirstChar(propertyName), - generateFieldNotPresentCondition(token.version(), token.encoding(), indent), + generateFieldNotPresentCondition(fieldToken.version(), typeToken.encoding(), indent), typePrefix, offset, byteOrderStr); @@ -758,9 +761,7 @@ private CharSequence generateFieldNotPresentCondition( literal); } - private CharSequence generateArrayFieldNotPresentCondition( - final int sinceVersion, - final String indent) + private CharSequence generateArrayFieldNotPresentCondition(final int sinceVersion, final String indent) { if (0 == sinceVersion) { @@ -804,16 +805,17 @@ private CharSequence generateTypeFieldNotPresentCondition( private CharSequence generateArrayProperty( final String propertyName, - final Token token, + final Token fieldToken, + final Token typeToken, final String indent) { - final String typeName = cSharpTypeName(token.encoding().primitiveType()); - final String typePrefix = toUpperFirstChar(token.encoding().primitiveType().primitiveName()); - final int offset = token.offset(); - final ByteOrder byteOrder = token.encoding().byteOrder(); - final String byteOrderStr = generateByteOrder(byteOrder, token.encoding().primitiveType().size()); - final int fieldLength = token.arrayLength(); - final int typeSize = token.encoding().primitiveType().size(); + final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); + final String typePrefix = toUpperFirstChar(typeToken.encoding().primitiveType().primitiveName()); + final int offset = typeToken.offset(); + final ByteOrder byteOrder = typeToken.encoding().byteOrder(); + final String byteOrderStr = generateByteOrder(byteOrder, typeToken.encoding().primitiveType().size()); + final int fieldLength = typeToken.arrayLength(); + final int typeSize = typeToken.encoding().primitiveType().size(); final String propName = toUpperFirstChar(propertyName); final StringBuilder sb = new StringBuilder(); @@ -833,7 +835,7 @@ private CharSequence generateArrayProperty( indent + INDENT + "return _buffer.%5$sGet%8$s(_offset + %6$d + (index * %7$d));\n" + indent + "}\n", typeName, propName, fieldLength, - generateFieldNotPresentCondition(token.version(), token.encoding(), indent), + generateFieldNotPresentCondition(fieldToken.version(), typeToken.encoding(), indent), typePrefix, offset, typeSize, byteOrderStr)); sb.append(String.format("\n" + @@ -847,9 +849,9 @@ private CharSequence generateArrayProperty( indent + "}\n", propName, typeName, fieldLength, typePrefix, offset, typeSize, byteOrderStr)); - if (token.encoding().primitiveType() == PrimitiveType.CHAR) + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { - generateCharacterEncodingMethod(sb, propertyName, token.encoding().characterEncoding(), indent); + generateCharacterEncodingMethod(sb, propertyName, typeToken.encoding().characterEncoding(), indent); sb.append(String.format("\n" + indent + "public int Get%1$s(byte[] dst, int dstOffset)\n" + @@ -858,7 +860,7 @@ private CharSequence generateArrayProperty( "%3$s" + indent + INDENT + "return Get%1$s(new Span(dst, dstOffset, length));\n" + indent + "}\n", - propName, fieldLength, generateArrayFieldNotPresentCondition(token.version(), indent), offset)); + propName, fieldLength, generateArrayFieldNotPresentCondition(fieldToken.version(), indent), offset)); sb.append(String.format("\n" + indent + "public int Get%1$s(Span dst)\n" + @@ -872,7 +874,7 @@ private CharSequence generateArrayProperty( indent + INDENT + "_buffer.GetBytes(_offset + %4$d, dst);\n" + indent + INDENT + "return length;\n" + indent + "}\n", - propName, fieldLength, generateArrayFieldNotPresentCondition(token.version(), indent), offset)); + propName, fieldLength, generateArrayFieldNotPresentCondition(fieldToken.version(), indent), offset)); sb.append(String.format("\n" + indent + "public void Set%1$s(byte[] src, int srcOffset)\n" + @@ -1091,19 +1093,19 @@ private CharSequence generateFields(final List tokens, final String inden switch (encodingToken.signal()) { case ENCODING: - sb.append(generatePrimitiveProperty(propertyName, encodingToken, indent)); + sb.append(generatePrimitiveProperty(propertyName, signalToken, encodingToken, indent)); break; case BEGIN_ENUM: - sb.append(generateEnumProperty(propertyName, encodingToken, signalToken, indent)); + sb.append(generateEnumProperty(propertyName, signalToken, encodingToken, indent)); break; case BEGIN_SET: - sb.append(generateBitSetProperty(propertyName, encodingToken, indent)); + sb.append(generateBitSetProperty(propertyName, signalToken, encodingToken, indent)); break; case BEGIN_COMPOSITE: - sb.append(generateCompositeProperty(propertyName, encodingToken, indent)); + sb.append(generateCompositeProperty(propertyName, signalToken, encodingToken, indent)); break; } } @@ -1167,20 +1169,20 @@ private CharSequence generateEnumFieldNotPresentCondition( private CharSequence generateEnumProperty( final String propertyName, - final Token token, - final Token signalToken, + final Token fieldToken, + final Token typeToken, final String indent) { - final String enumName = formatClassName(token.applicableTypeName()); - final String typePrefix = toUpperFirstChar(token.encoding().primitiveType().primitiveName()); - final String enumUnderlyingType = cSharpTypeName(token.encoding().primitiveType()); - final int offset = token.offset(); - final ByteOrder byteOrder = token.encoding().byteOrder(); - final String byteOrderStr = generateByteOrder(byteOrder, token.encoding().primitiveType().size()); - - if (signalToken != null && signalToken.isConstantEncoding()) + final String enumName = formatClassName(typeToken.applicableTypeName()); + final String typePrefix = toUpperFirstChar(typeToken.encoding().primitiveType().primitiveName()); + final String enumUnderlyingType = cSharpTypeName(typeToken.encoding().primitiveType()); + final int offset = typeToken.offset(); + final ByteOrder byteOrder = typeToken.encoding().byteOrder(); + final String byteOrderStr = generateByteOrder(byteOrder, typeToken.encoding().primitiveType().size()); + + if (fieldToken != null && fieldToken.isConstantEncoding()) { - final String constValue = signalToken.encoding().constValue().toString(); + final String constValue = fieldToken.encoding().constValue().toString(); return String.format("\n" + indent + INDENT + "public %1$s %2$s\n" + @@ -1211,7 +1213,7 @@ private CharSequence generateEnumProperty( indent + INDENT + "}\n\n", enumName, toUpperFirstChar(propertyName), - generateEnumFieldNotPresentCondition(token.version(), enumName, indent), + generateEnumFieldNotPresentCondition(fieldToken.version(), enumName, indent), enumName, typePrefix, offset, @@ -1220,14 +1222,15 @@ private CharSequence generateEnumProperty( } } - private String generateBitSetProperty(final String propertyName, final Token token, final String indent) + private String generateBitSetProperty( + final String propertyName, final Token fieldToken, final Token typeToken, final String indent) { - final String bitSetName = formatClassName(token.applicableTypeName()); - final int offset = token.offset(); - final String typePrefix = toUpperFirstChar(token.encoding().primitiveType().primitiveName()); - final ByteOrder byteOrder = token.encoding().byteOrder(); - final String byteOrderStr = generateByteOrder(byteOrder, token.encoding().primitiveType().size()); - final String typeName = cSharpTypeName(token.encoding().primitiveType()); + final String bitSetName = formatClassName(typeToken.applicableTypeName()); + final int offset = typeToken.offset(); + final String typePrefix = toUpperFirstChar(typeToken.encoding().primitiveType().primitiveName()); + final ByteOrder byteOrder = typeToken.encoding().byteOrder(); + final String byteOrderStr = generateByteOrder(byteOrder, typeToken.encoding().primitiveType().size()); + final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); return String.format("\n" + indent + INDENT + "public %1$s %2$s\n" + @@ -1244,7 +1247,7 @@ private String generateBitSetProperty(final String propertyName, final Token tok indent + INDENT + "}\n", bitSetName, toUpperFirstChar(propertyName), - generateBitSetNotPresentCondition(token.version(), indent, bitSetName), + generateBitSetNotPresentCondition(fieldToken.version(), indent, bitSetName), bitSetName, typePrefix, offset, @@ -1252,10 +1255,11 @@ private String generateBitSetProperty(final String propertyName, final Token tok typeName); } - private Object generateCompositeProperty(final String propertyName, final Token token, final String indent) + private Object generateCompositeProperty( + final String propertyName, final Token fieldToken, final Token typeToken, final String indent) { - final String compositeName = CSharpUtil.formatClassName(token.applicableTypeName()); - final int offset = token.offset(); + final String compositeName = CSharpUtil.formatClassName(typeToken.applicableTypeName()); + final int offset = typeToken.offset(); final StringBuilder sb = new StringBuilder(); sb.append(String.format("\n" + @@ -1276,7 +1280,7 @@ private Object generateCompositeProperty(final String propertyName, final Token indent + INDENT + "}\n", compositeName, toUpperFirstChar(propertyName), - generateTypeFieldNotPresentCondition(token.version(), indent), + generateTypeFieldNotPresentCondition(fieldToken.version(), indent), toLowerFirstChar(propertyName), offset)); From 46753167d9e98228b18c7fdc367580bee10f468b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 9 Mar 2020 17:06:39 +0000 Subject: [PATCH 0385/1594] [Rust] Rust has been removed from project due to lack of community support. --- .gitignore | 7 - build.gradle | 70 +- gocode/src/example-schema/CarExample.go | 3 +- rust/car_example/Cargo.toml | 7 - rust/car_example/README.md | 6 - rust/car_example/src/main.rs | 277 --- .../real_logic/sbe/generation/rust/Rust.java | 38 - .../sbe/generation/rust/RustCodecType.java | 202 -- .../rust/RustFlatFileOutputManager.java | 74 - .../sbe/generation/rust/RustGenerator.java | 2009 ----------------- .../sbe/generation/rust/RustUtil.java | 230 -- .../generation/rust/SplitCompositeTokens.java | 68 - .../rust/RustFlatFileOutputManagerTest.java | 67 - .../generation/rust/RustGeneratorTest.java | 406 ---- .../sbe/generation/rust/RustTest.java | 71 - .../sbe/generation/rust/RustUtilTest.java | 87 - .../rust/SingleStringOutputManager.java | 32 - 17 files changed, 9 insertions(+), 3645 deletions(-) delete mode 100644 rust/car_example/Cargo.toml delete mode 100644 rust/car_example/README.md delete mode 100644 rust/car_example/src/main.rs delete mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/Rust.java delete mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java delete mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManager.java delete mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java delete mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java delete mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SplitCompositeTokens.java delete mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManagerTest.java delete mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java delete mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustTest.java delete mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java delete mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/SingleStringOutputManager.java diff --git a/.gitignore b/.gitignore index b27d8153a7..ba860d57dc 100644 --- a/.gitignore +++ b/.gitignore @@ -106,13 +106,6 @@ csharp/sbe-generated/uk_co_real_logic_sbe_benchmarks_fix csharp/sbe-tests/*.sbe csharp/nuget/ -# rust -rust/car_example/.vscode -rust/car_example/car_example_data.sbe -rust/car_example/Cargo.lock -rust/car_example/src/car_example_generated_codec.rs -rust/car_example/target - # Mac .DS_Store /sbe-tool/src/main/golang/uk_co_real_logic_sbe_ir_generated/ diff --git a/build.gradle b/build.gradle index 756e746e67..46b6068079 100644 --- a/build.gradle +++ b/build.gradle @@ -410,13 +410,13 @@ project(':sbe-samples') { from sourceSets.generated.output manifest.attributes( - 'Main-Class': 'uk.co.real_logic.sbe.SbeTool', - 'Specification-Title': 'Simple Binary Encoding', - 'Specification-Version': '1.0', - 'Implementation-Title': 'SBE', - 'Implementation-Version': "${sbeVersion}", - 'Implementation-Vendor': 'Real Logic Limited', - 'Automatic-Module-Name': 'uk.co.real_logic.sbe.samples' + 'Main-Class': 'uk.co.real_logic.sbe.SbeTool', + 'Specification-Title': 'Simple Binary Encoding', + 'Specification-Version': '1.0', + 'Implementation-Title': 'SBE', + 'Implementation-Version': "${sbeVersion}", + 'Implementation-Vendor': 'Real Logic Limited', + 'Automatic-Module-Name': 'uk.co.real_logic.sbe.samples' ) } @@ -504,62 +504,6 @@ project(':sbe-benchmarks') { jar.finalizedBy shadowJar } -/* - * Rust codec targets used for testing and demonstration - */ -task generateRustCarExample(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath - systemProperties( - 'sbe.output.dir': 'rust/car_example/src', - 'sbe.xinclude.aware': 'true', - 'sbe.target.language': 'uk.co.real_logic.sbe.generation.rust.Rust', - 'sbe.target.namespace': 'car_example_generated_codec') - args = ['sbe-samples/src/main/resources/example-schema.xml'] -} - -task generateCarExampleDataFile(type: JavaExec) { - main = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub' - classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath - systemProperties('sbe.encoding.filename': 'rust/car_example/car_example_data.sbe') - args = [] - standardOutput = new ByteArrayOutputStream() -} - -task runRustCarExample(type: Exec) { - workingDir = './rust/car_example' - executable = 'cargo' - args = ['run'] - standardOutput = new ByteArrayOutputStream() - errorOutput = new ByteArrayOutputStream() - dependsOn 'generateRustCarExample', 'generateCarExampleDataFile' -} - -def cargo_exists() { - try { - def result = project.exec { - executable = 'cargo' - args = [ '-V' ] - standardOutput = new ByteArrayOutputStream() - } - return result.exitValue == 0 - } - catch (Exception ignore) { - return false - } -} - -if (cargo_exists() && !project.hasProperty('sbe.skipRust')) { - test.dependsOn('runRustCarExample') -} else { - println 'Skipping Rust integration test due to absent cargo command or sbe.skipRust property' -} - -task generateRustCodecs { - description = 'Generate rust test codecs' - dependsOn 'generateRustCarExample', 'generateCarExampleDataFile' -} - /* * Golang codec targets used for testing, benchmarking etc. We have * multiple targets as: diff --git a/gocode/src/example-schema/CarExample.go b/gocode/src/example-schema/CarExample.go index dee6e32588..dd74181df9 100644 --- a/gocode/src/example-schema/CarExample.go +++ b/gocode/src/example-schema/CarExample.go @@ -47,7 +47,6 @@ func main() { ExampleDecodeSocket() return - } func ExampleEncodeDecode() bool { @@ -135,6 +134,7 @@ func ExampleDecodeBuffer() bool { fmt.Println("FIXME: Failed to decode car", err) os.Exit(1) } + return true } @@ -174,6 +174,7 @@ func ExampleDecodePipe() bool { os.Exit(1) } r.Close() + return true } diff --git a/rust/car_example/Cargo.toml b/rust/car_example/Cargo.toml deleted file mode 100644 index 6a401aa889..0000000000 --- a/rust/car_example/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "sbe_rust_car_example" -version = "0.1.0" -authors = [] - -[dependencies] -[dev-dependencies] \ No newline at end of file diff --git a/rust/car_example/README.md b/rust/car_example/README.md deleted file mode 100644 index f0d28ca9a9..0000000000 --- a/rust/car_example/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Rust Car Example project - -Depends on SBE-tool generated bindings, which can be created by running, from the simple-binary-encoding project root, -`./gradlew generateRustCodecs`. - -Assumes the presence of Rust and Cargo. diff --git a/rust/car_example/src/main.rs b/rust/car_example/src/main.rs deleted file mode 100644 index fcc980edb4..0000000000 --- a/rust/car_example/src/main.rs +++ /dev/null @@ -1,277 +0,0 @@ -/// Note that the included codec file and the data file further below -/// are generated through SBE's gradle tooling. `./gradlew generateRustCodecs` -mod car_example_generated_codec; -use car_example_generated_codec::*; - -use std::fs::File; -use std::io::prelude::*; -use std::io::{Error as IoError, ErrorKind as IoErrorKind, Write}; - -pub fn main() { - ::std::process::exit(match run_car_example() { - Ok(_) => 0, - Err(e) => { - writeln!(::std::io::stderr(), "error: {:?}", e).unwrap(); - 1 - } - }); -} - -fn read_sbe_file_generated_from_java_example() -> ::std::io::Result> { - // Generated by the generateCarExampleDataFile gradle task. - let mut f = File::open("car_example_data.sbe")?; - let mut buffer = Vec::new(); - f.read_to_end(&mut buffer)?; - Ok(buffer) -} - -fn run_car_example() -> ::std::io::Result<()> { - let reference_example_bytes = read_sbe_file_generated_from_java_example()?; - decode_car_and_assert_expected_content(&reference_example_bytes)?; - let bytes_encoded_from_rust = encode_car_from_scratch()?; - assert_eq!(reference_example_bytes, bytes_encoded_from_rust); - decode_car_and_assert_expected_content(&bytes_encoded_from_rust)?; - Ok(()) -} - -impl std::convert::From for IoError { - fn from(codec_err: CodecErr) -> Self { - IoError::new(IoErrorKind::Other, match codec_err { - CodecErr::NotEnoughBytes => "not enough bytes", - CodecErr::SliceIsLongerThanAllowedBySchema => "slice is longer than allowed by schema", - }) - } -} - -fn decode_car_and_assert_expected_content(buffer: &[u8]) -> CodecResult<()> { - let (h, dec_fields) = start_decoding_car(&buffer).header()?; - assert_eq!(45u16, {h.block_length}); - assert_eq!(h.block_length as usize, ::std::mem::size_of::()); - assert_eq!(1u16, {h.template_id}); - assert_eq!(1u16, {h.schema_id}); - assert_eq!(0u16, {h.version}); - println!("Header read"); - - assert_eq!(Model::C, CarFields::discounted_model()); - assert_eq!(9000u16, Engine::max_rpm()); - assert_eq!("Petrol", Engine::fuel()); - - let mut found_fuel_figures = Vec::::with_capacity(EXPECTED_FUEL_FIGURES.len()); - - let (fields, dec_fuel_figures_header) = dec_fields.car_fields()?; - assert_eq!(1234, {fields.serial_number}); - assert_eq!(2013, {fields.model_year}); - assert_eq!(BooleanType::T, {fields.available}); - assert_eq!([97_i8, 98, 99, 100, 101, 102], {fields.vehicle_code}); // abcdef - assert_eq!([1, 2, 3, 4], {fields.some_numbers}); - assert_eq!(6, fields.extras.0); - assert!(fields.extras.get_cruise_control()); - assert!(fields.extras.get_sports_pack()); - assert!(!fields.extras.get_sun_roof()); - assert_eq!(2000, {fields.engine.capacity}); - assert_eq!(4, fields.engine.num_cylinders); - assert_eq!(BoostType::NITROUS, fields.engine.booster.boost_type); - assert_eq!(200, fields.engine.booster.horse_power); - println!("Static-length fields all match the expected values"); - - let dec_perf_figures_header = match dec_fuel_figures_header.fuel_figures_individually()? { - Either::Left(mut dec_ff_members) => { - println!("Got some fuel figure members"); - loop { - let (ff_fields, dec_usage_description) = dec_ff_members.next_fuel_figures_member()?; - let (usage_description, next_step) = dec_usage_description.usage_description()?; - let usage_str = std::str::from_utf8(usage_description).unwrap(); - println!("Fuel Figure: Speed: {0}, MPG: {1}, Usage: {2}", - {ff_fields.speed}, - {ff_fields.mpg}, - usage_str); - found_fuel_figures.push(FuelFigure { - speed: {ff_fields.speed}, - mpg: {ff_fields.mpg}, - usage_description: usage_str, - }); - match next_step { - Either::Left(more_members) => dec_ff_members = more_members, - Either::Right(done_with_group) => { - break done_with_group; - } - } - } - } - Either::Right(next_decoder) => next_decoder, - }; - assert!(EXPECTED_FUEL_FIGURES - .iter() - .zip(found_fuel_figures.iter()) - .all(|(exp, found)| exp == found), - "fuel figures should match expected values"); - - let dec_manufacturer = match dec_perf_figures_header.performance_figures_individually()? { - Either::Left(mut dec_pf_members) => { - println!("Got some performance figure members"); - loop { - let (pf_fields, dec_acceleration_header) = dec_pf_members - .next_performance_figures_member()?; - println!("Performance Figure Fixed Fields: Octane Rating: {0}", - pf_fields.octane_rating); - let (accel_slice, next_step) = dec_acceleration_header.acceleration_as_slice()?; - for accel_fields in accel_slice { - println!("Acceleration: MPH: {0}, Seconds: {1}", - {accel_fields.mph}, - {accel_fields.seconds}); - } - match next_step { - Either::Left(more_members) => dec_pf_members = more_members, - Either::Right(done_with_group) => { - break done_with_group; - } - } - } - } - Either::Right(next_decoder) => next_decoder, - }; - let (manufacturer, dec_model) = dec_manufacturer.manufacturer()?; - let manufacturer = std::str::from_utf8(manufacturer).unwrap(); - println!("Manufacturer: {}", manufacturer); - assert_eq!("Honda", manufacturer); - - let (model, dec_activation_code) = dec_model.model()?; - let model = std::str::from_utf8(model).unwrap(); - println!("Model: {}", model); - assert_eq!("Civic VTi", model); - - let (activation_code, dec_done) = dec_activation_code.activation_code()?; - let activation_code = std::str::from_utf8(activation_code).unwrap(); - println!("Activation Code: {}", activation_code); - assert_eq!("abcdef", activation_code); - - let position = dec_done.unwrap(); - println!("Finished decoding. Made it to position {0} out of {1}", - position, - buffer.len()); - Ok(()) -} - -fn encode_car_from_scratch() -> CodecResult> { - let mut buffer = vec![0u8; 256]; - let used_pos = { - let enc_header = start_encoding_car(&mut buffer); - let enc_fields = enc_header - .header_copy(&CarMessageHeader::default().message_header)?; - println!("encoded header"); - let (fields, enc_fuel_figures_header) = enc_fields.car_fields()?; - fields.serial_number = 1234; - fields.model_year = 2013; - fields.available = BooleanType::T; - fields.code = Model::A; - fields.vehicle_code = [97_i8, 98, 99, 100, 101, 102]; // abcdef - fields.some_numbers = [1, 2, 3, 4]; - fields.extras = OptionalExtras::new(); - fields.extras.set_cruise_control(true) - .set_sports_pack(true) - .set_sun_roof(false); - fields.engine = Engine { - capacity: 2000, - num_cylinders: 4, - manufacturer_code: [49, 50, 51], // 123 - efficiency: 35, - booster_enabled: BooleanType::T, - booster: Booster { - boost_type: BoostType::NITROUS, - horse_power: 200, - }, - }; - println!("encoded top level fields"); - let mut enc_fuel_figures = enc_fuel_figures_header.fuel_figures_individually()?; - let mut fuel_figure_scratch = CarFuelFiguresMember { speed: 0, mpg: 0.0 }; - for ff in EXPECTED_FUEL_FIGURES { - fuel_figure_scratch.speed = ff.speed; - fuel_figure_scratch.mpg = ff.mpg; - //fuel_figure_scratch.usage_description = ff.mpg; - let enc_usage = enc_fuel_figures - .next_fuel_figures_member(&fuel_figure_scratch)?; - enc_fuel_figures = enc_usage - .usage_description(ff.usage_description.as_bytes())?; - } - let enc_perf_figures_header = enc_fuel_figures.done_with_fuel_figures()?; - println!("encoded fuel figures"); - let mut perf_figure_member_scratch = CarPerformanceFiguresMember { octane_rating: 0 }; - let mut enc_perf_figures = enc_perf_figures_header.performance_figures_individually()?; - for pf in EXPECTED_PERF_FIXTURES { - perf_figure_member_scratch.octane_rating = pf.octane_rating; - let enc_accel = enc_perf_figures - .next_performance_figures_member(&perf_figure_member_scratch)?; - enc_perf_figures = enc_accel.acceleration_from_slice(&pf.acceleration)?; - } - let enc_manufacturer = enc_perf_figures.done_with_performance_figures()?; - println!("encoded perf figures"); - let enc_model = enc_manufacturer.manufacturer("Honda".as_bytes())?; - let enc_activation_code = enc_model.model("Civic VTi".as_bytes())?; - let done = enc_activation_code.activation_code("abcdef".as_bytes())?; - let pos = done.unwrap(); - pos - }; - println!("encoded up to position {}", used_pos); - buffer.truncate(used_pos); - - Ok(buffer) -} - -#[derive(Debug, PartialEq)] -struct FuelFigure<'d> { - speed: u16, - mpg: f32, - usage_description: &'d str, -} - -const EXPECTED_FUEL_FIGURES: &'static [FuelFigure] = &[FuelFigure { - speed: 30, - mpg: 35.9, - usage_description: "Urban Cycle", - }, - FuelFigure { - speed: 55, - mpg: 49.0, - usage_description: "Combined Cycle", - }, - FuelFigure { - speed: 75, - mpg: 40.0, - usage_description: "Highway Cycle", - }]; - -struct PerfFigure { - octane_rating: u8, - acceleration: [CarPerformanceFiguresAccelerationMember; 3], -} - -const EXPECTED_PERF_FIXTURES: &'static [PerfFigure] = &[PerfFigure { - octane_rating: 95, - acceleration: [CarPerformanceFiguresAccelerationMember { - mph: 30, - seconds: 4.0, - }, - CarPerformanceFiguresAccelerationMember { - mph: 60, - seconds: 7.5, - }, - CarPerformanceFiguresAccelerationMember { - mph: 100, - seconds: 12.2, - }], - }, - PerfFigure { - octane_rating: 99, - acceleration: [CarPerformanceFiguresAccelerationMember { - mph: 30, - seconds: 3.8, - }, - CarPerformanceFiguresAccelerationMember { - mph: 60, - seconds: 7.1, - }, - CarPerformanceFiguresAccelerationMember { - mph: 100, - seconds: 11.8, - }], - }]; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/Rust.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/Rust.java deleted file mode 100644 index 297fafb0f3..0000000000 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/Rust.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2013-2020 Real Logic Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.generation.rust; - -import uk.co.real_logic.sbe.generation.CodeGenerator; -import uk.co.real_logic.sbe.generation.TargetCodeGenerator; -import uk.co.real_logic.sbe.ir.Ir; - -/** - * This class is present largely to enable the dynamic-loading style pattern - * of specifying a TargetCodeGenerator Java class name rather than the language - * name. - */ -public class Rust implements TargetCodeGenerator -{ - public CodeGenerator newInstance(final Ir ir, final String outputDir) - { - return defaultRustGenerator(ir, outputDir); - } - - public static CodeGenerator defaultRustGenerator(final Ir ir, final String outputDir) - { - return new RustGenerator(ir, new RustFlatFileOutputManager(outputDir, ir.applicableNamespace())); - } -} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java deleted file mode 100644 index 7c1a33d8f0..0000000000 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustCodecType.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2013-2020 Real Logic Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.generation.rust; - -import org.agrona.generation.OutputManager; - -import java.io.IOException; -import java.io.Writer; - -import static java.lang.String.format; -import static uk.co.real_logic.sbe.generation.rust.RustGenerator.DATA_LIFETIME; -import static uk.co.real_logic.sbe.generation.rust.RustUtil.INDENT; -import static uk.co.real_logic.sbe.generation.rust.RustUtil.indent; - -enum RustCodecType -{ - Decoder - { - String scratchProperty() - { - return RustGenerator.SCRATCH_DECODER_PROPERTY; - } - - String scratchType() - { - return RustGenerator.SCRATCH_DECODER_TYPE; - } - - void appendDirectCodeMethods( - final Appendable appendable, - final String methodName, - final String representationType, - final String nextCoderType, - final int numBytes, - final int trailingBytes) throws IOException - { - indent(appendable, 1, "pub fn %s(mut self) -> CodecResult<(&%s %s, %s)> {\n", - methodName, DATA_LIFETIME, representationType, RustGenerator.withLifetime(nextCoderType)); - indent(appendable, 2, "let v = self.%s.read_type::<%s>(%s)?;\n", - RustCodecType.Decoder.scratchProperty(), representationType, numBytes); - if (trailingBytes > 0) - { - indent(appendable, 2, "self.%s.skip_bytes(%s)?;\n", - RustCodecType.Decoder.scratchProperty(), trailingBytes); - } - indent(appendable, 2, "Ok((v, %s::wrap(self.%s)))\n", - nextCoderType, RustCodecType.Decoder.scratchProperty()); - indent(appendable).append("}\n"); - } - - String gerund() - { - return "decoding"; - } - }, - - Encoder - { - String scratchProperty() - { - return RustGenerator.SCRATCH_ENCODER_PROPERTY; - } - - String scratchType() - { - return RustGenerator.SCRATCH_ENCODER_TYPE; - } - - void appendDirectCodeMethods( - final Appendable appendable, - final String methodName, - final String representationType, - final String nextCoderType, - final int numBytes, - final int trailingBytes) throws IOException - { - indent(appendable, 1, "\n/// Create a mutable struct reference overlaid atop the data buffer\n"); - indent(appendable, 1, "/// such that changes to the struct directly edit the buffer. \n"); - indent(appendable, 1, "/// Note that the initial content of the struct's fields may be garbage.\n"); - indent(appendable, 1, "pub fn %s(mut self) -> CodecResult<(&%s mut %s, %s)> {\n", - methodName, DATA_LIFETIME, representationType, RustGenerator.withLifetime(nextCoderType)); - if (trailingBytes > 0) - { - indent(appendable, 2, "// add trailing bytes to extend the end position of the scratch buffer\n"); - } - indent(appendable, 2, "let v = self.%s.writable_overlay::<%s>(%s+%s)?;\n", - RustCodecType.Encoder.scratchProperty(), representationType, numBytes, trailingBytes); - indent(appendable, 2, "Ok((v, %s::wrap(self.%s)))\n", - nextCoderType, RustCodecType.Encoder.scratchProperty()); - indent(appendable).append("}\n\n"); - - indent(appendable, 1, "/// Copy the bytes of a value into the data buffer\n"); - indent(appendable).append(String.format("pub fn %s_copy(mut self, t: &%s) -> CodecResult<%s> {\n", - methodName, representationType, RustGenerator.withLifetime(nextCoderType))); - indent(appendable, 2) - .append(format("self.%s.write_type::<%s>(t, %s)?;\n", - RustCodecType.Encoder.scratchProperty(), representationType, numBytes)); - if (trailingBytes > 0) - { - indent(appendable, 2, "// fixed message length > sum of field lengths\n"); - indent(appendable, 2, "self.%s.skip_bytes(%s)?;\n", - RustCodecType.Decoder.scratchProperty(), trailingBytes); - } - indent(appendable, 2).append(format("Ok(%s::wrap(self.%s))\n", - nextCoderType, RustCodecType.Encoder.scratchProperty())); - indent(appendable).append("}\n"); - } - - String gerund() - { - return "encoding"; - } - }; - - void appendScratchWrappingStruct(final Appendable appendable, final String structName) - throws IOException - { - appendable.append(String.format("pub struct %s <%s> {\n", structName, DATA_LIFETIME)) - .append(INDENT).append(String.format("%s: %s <%s>,%n", scratchProperty(), scratchType(), DATA_LIFETIME)) - .append("}\n"); - } - - abstract String scratchProperty(); - - abstract String scratchType(); - - abstract void appendDirectCodeMethods( - Appendable appendable, - String methodName, - String representationType, - String nextCoderType, - int numBytes, - int trailingBytes) throws IOException; - - abstract String gerund(); - - String generateDoneCoderType( - final OutputManager outputManager, - final String messageTypeName) - throws IOException - { - final String doneTypeName = messageTypeName + name() + "Done"; - try (Writer writer = outputManager.createOutput(doneTypeName)) - { - appendScratchWrappingStruct(writer, doneTypeName); - RustGenerator.appendImplWithLifetimeHeader(writer, doneTypeName); - indent(writer, 1, "/// Returns the number of bytes %s\n", this == Encoder ? "encoded" : "decoded"); - indent(writer, 1, "pub fn unwrap(self) -> usize {\n"); - indent(writer, 2, "self.%s.pos\n", scratchProperty()); - indent(writer, 1, "}\n"); - - appendWrapMethod(writer, doneTypeName); - writer.append("}\n"); - } - - return doneTypeName; - } - - void appendWrapMethod(final Appendable appendable, final String structName) - throws IOException - { - appendable.append("\n").append(INDENT).append(String.format( - "pub fn wrap(%s: %s) -> %s {%n", scratchProperty(), RustGenerator.withLifetime(scratchType()), - RustGenerator.withLifetime(structName))); - indent(appendable, 2, "%s { %s: %s }\n", - structName, scratchProperty(), scratchProperty()); - indent(appendable).append("}\n"); - } - - String generateMessageHeaderCoder( - final String messageTypeName, - final OutputManager outputManager, - final String topType, - final int headerSize) throws IOException - { - final String messageHeaderRepresentation = "MessageHeader"; - final String headerCoderType = messageTypeName + messageHeaderRepresentation + name(); - try (Writer writer = outputManager.createOutput(headerCoderType)) - { - appendScratchWrappingStruct(writer, headerCoderType); - RustGenerator.appendImplWithLifetimeHeader(writer, headerCoderType); - appendWrapMethod(writer, headerCoderType); - appendDirectCodeMethods(writer, "header", messageHeaderRepresentation, topType, headerSize, 0); - writer.append("}\n"); - } - - return headerCoderType; - } -} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManager.java deleted file mode 100644 index 9de59d0f9b..0000000000 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManager.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2013-2020 Real Logic Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.generation.rust; - -import org.agrona.Verify; -import org.agrona.generation.OutputManager; - -import java.io.File; -import java.io.IOException; -import java.io.Writer; -import java.nio.file.Files; - -import static java.io.File.separatorChar; -import static java.nio.charset.StandardCharsets.UTF_8; -import static java.nio.file.StandardOpenOption.APPEND; -import static java.nio.file.StandardOpenOption.WRITE; - -public class RustFlatFileOutputManager implements OutputManager -{ - private final File outputFile; - - RustFlatFileOutputManager(final String baseDirName, final String packageName) - { - Verify.notNull(baseDirName, "baseDirName"); - Verify.notNull(packageName, "packageName"); - - final String outputDirName = baseDirName.endsWith("" + separatorChar) ? - baseDirName : baseDirName + separatorChar; - final File outputDir = new File(outputDirName); - final boolean outputDirAvailable = outputDir.exists() || outputDir.mkdirs(); - if (!outputDirAvailable) - { - throw new IllegalStateException("Unable to create directory: " + outputDirName); - } - this.outputFile = new File(outputDirName + packageName.replace('.', '_') + ".rs"); - - try (Writer writer = Files.newBufferedWriter(outputFile.toPath(), UTF_8)) - { - writer.append("/// Generated code for SBE package ") - .append(packageName) - .append("\n\n"); - } - catch (final IOException ex) - { - throw new IllegalStateException("Unable to write header for : " + outputDirName, ex); - } - } - - public Writer createOutput(final String name) throws IOException - { - // Note the deliberate lack of a "CREATE" or "CREATE_NEW" option in order to - // prevent writing to a file that has not been properly initialized - final Writer writer = Files.newBufferedWriter(outputFile.toPath(), UTF_8, WRITE, APPEND); - - writer.append("\n/// ") - .append(name) - .append("\n"); - - return writer; - } -} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java deleted file mode 100644 index a047995390..0000000000 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ /dev/null @@ -1,2009 +0,0 @@ -/* - * Copyright 2013-2020 Real Logic Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.generation.rust; - -import org.agrona.Verify; -import org.agrona.generation.OutputManager; -import uk.co.real_logic.sbe.PrimitiveType; -import uk.co.real_logic.sbe.generation.CodeGenerator; -import uk.co.real_logic.sbe.generation.NamedToken; -import uk.co.real_logic.sbe.ir.*; - -import java.io.IOException; -import java.io.Writer; -import java.util.*; -import java.util.stream.IntStream; - -import static java.lang.String.format; -import static uk.co.real_logic.sbe.generation.rust.RustUtil.*; -import static uk.co.real_logic.sbe.ir.GenerationUtil.*; -import static uk.co.real_logic.sbe.ir.Signal.*; - -public class RustGenerator implements CodeGenerator -{ - private final Ir ir; - private final OutputManager outputManager; - static final String SCRATCH_ENCODER_TYPE = "ScratchEncoderData"; - static final String SCRATCH_ENCODER_PROPERTY = "scratch"; - static final String SCRATCH_DECODER_PROPERTY = SCRATCH_ENCODER_PROPERTY; - static final String SCRATCH_DECODER_TYPE = "ScratchDecoderData"; - static final String DATA_LIFETIME = "'d"; - - public RustGenerator(final Ir ir, final OutputManager outputManager) - { - Verify.notNull(ir, "ir"); - Verify.notNull(outputManager, "outputManager"); - - this.ir = ir; - this.outputManager = outputManager; - } - - public void generate() throws IOException - { - final int headerSize = totalByteSize(ir.headerStructure()); - - generateSharedImports(outputManager); - generateResultEnums(outputManager); - generateDecoderScratchStruct(outputManager); - generateEncoderScratchStruct(outputManager); - generateEitherEnum(outputManager); - generateEnums(ir, outputManager); - generateComposites(ir, outputManager); - generateBitSets(ir, outputManager); - generateMessageHeaderDecoder(outputManager, headerSize); - - for (final List tokens : ir.messages()) - { - final MessageComponents components = MessageComponents.collectMessageComponents(tokens); - final String messageTypeName = formatTypeName(components.messageToken.name()); - - final RustStruct fieldStruct = generateMessageFieldStruct(messageTypeName, components, outputManager); - generateMessageHeaderDefault(ir, outputManager, components.messageToken); - - // Avoid the work of recomputing the group tree twice per message - final List groupTree = buildGroupTrees(messageTypeName, components.groups); - generateGroupFieldRepresentations(outputManager, groupTree); - - generateMessageDecoder(outputManager, components, groupTree, fieldStruct, headerSize); - generateMessageEncoder(outputManager, components, groupTree, fieldStruct, headerSize); - } - } - - private static int totalByteSize(final HeaderStructure headerStructure) - { - return headerStructure - .tokens() - .stream() - .filter((t) -> t.signal() == ENCODING || t.signal() == BEGIN_ENUM || t.signal() == BEGIN_SET) - .mapToInt(Token::encodedLength) - .sum(); - } - - private void generateGroupFieldRepresentations( - final OutputManager outputManager, final List groupTree) throws IOException - { - try (Writer writer = outputManager.createOutput("Group fixed-field member representations")) - { - generateGroupFieldRepresentations(writer, groupTree); - } - } - - private void generateGroupFieldRepresentations( - final Appendable appendable, final List groupTree) throws IOException - { - for (final GroupTreeNode node : groupTree) - { - final RustStruct struct = RustStruct.fromTokens(node.contextualName + "Member", - node.simpleNamedFields, - EnumSet.of(RustStruct.Modifier.PACKED, RustStruct.Modifier.DEFAULT)); - struct.appendDefinitionTo(appendable); - - generateConstantAccessorImpl(appendable, node.contextualName + "Member", node.rawFields); - - generateGroupFieldRepresentations(appendable, node.groups); - } - } - - private static RustStruct generateMessageFieldStruct( - final String messageTypeName, - final MessageComponents components, - final OutputManager outputManager) throws IOException - { - final List namedFieldTokens = NamedToken.gatherNamedNonConstantFieldTokens(components.fields); - - final String representationStruct = messageTypeName + "Fields"; - final RustStruct struct = RustStruct.fromTokens(representationStruct, namedFieldTokens, - EnumSet.of(RustStruct.Modifier.PACKED, RustStruct.Modifier.DEFAULT)); - - try (Writer writer = outputManager.createOutput( - messageTypeName + " Fixed-size Fields (" + struct.sizeBytes() + " bytes)")) - { - struct.appendDefinitionTo(writer); - writer.append("\n"); - generateConstantAccessorImpl(writer, representationStruct, components.fields); - } - - return struct; - } - - private static void generateBitSets(final Ir ir, final OutputManager outputManager) throws IOException - { - for (final List tokens : ir.types()) - { - if (!tokens.isEmpty() && tokens.get(0).signal() == BEGIN_SET) - { - generateSingleBitSet(tokens, outputManager); - } - } - } - - private static void generateSingleBitSet(final List tokens, final OutputManager outputManager) - throws IOException - { - final Token beginToken = tokens.get(0); - final String setType = formatTypeName(beginToken.applicableTypeName()); - try (Writer writer = outputManager.createOutput(setType + " bit set")) - { - writer.append("#[derive(Default)]\n"); - writer.append("#[repr(C,packed)]\n"); - final String rustPrimitiveType = rustTypeName(beginToken.encoding().primitiveType()); - writer.append(format("pub struct %s(pub %s);\n", setType, rustPrimitiveType)); - writer.append(format("impl %s {\n", setType)); - indent(writer, 1, "pub fn new() -> Self {\n"); - indent(writer, 2, "%s(0)\n", setType); - indent(writer, 1, "}\n"); - - indent(writer, 1, "pub fn clear(&mut self) -> &mut Self {\n"); - indent(writer, 2, "self.0 = 0;\n"); - indent(writer, 2, "self\n"); - indent(writer, 1, "}\n"); - - for (final Token token : tokens) - { - if (Signal.CHOICE != token.signal()) - { - continue; - } - - final String choiceName = formatMethodName(token.name()); - final Encoding encoding = token.encoding(); - final String choiceBitIndex = encoding.constValue().toString(); - - indent(writer, 1, "pub fn get_%s(&self) -> bool {\n", choiceName); - indent(writer, 2, "0 != self.0 & (1 << %s)\n", choiceBitIndex); - indent(writer, 1, "}\n"); - - indent(writer, 1, "pub fn set_%s(&mut self, value: bool) -> &mut Self {\n", choiceName); - indent(writer, 2, "self.0 = if value {\n"); - indent(writer, 3, "self.0 | (1 << %s)\n", choiceBitIndex); - indent(writer, 2, "} else {\n"); - indent(writer, 3, "self.0 & !(1 << %s)\n", choiceBitIndex); - indent(writer, 2, "};\n"); - indent(writer, 2, "self\n"); - indent(writer, 1, "}\n"); - } - - writer.append("}\n"); - } - - try (Writer writer = outputManager.createOutput(setType + " bit set debug")) - { - indent(writer, 0, "impl core::fmt::Debug for %s {\n", setType); - indent(writer, 1, "fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {\n"); - indent(writer, 2, "write!(fmt, \"%s[", setType); - - final StringBuilder builder = new StringBuilder(); - final StringBuilder arguments = new StringBuilder(); - for (final Token token : tokens) - { - if (Signal.CHOICE != token.signal()) - { - continue; - } - - final String choiceName = formatMethodName(token.name()); - final String choiceBitIndex = token.encoding().constValue().toString(); - - builder.append(choiceName).append("(").append(choiceBitIndex).append(")={},"); - arguments.append("self.get_").append(choiceName).append("(),"); - } - - writer.append(builder.toString()).append("]\",\n"); - indent(writer, 3, arguments.toString() + ")\n"); - indent(writer, 1, "}\n"); - writer.append("}\n"); - } - } - - private static void generateMessageEncoder( - final OutputManager outputManager, - final MessageComponents components, - final List groupTree, - final RustStruct fieldStruct, - final int headerSize) - throws IOException - { - final Token msgToken = components.messageToken; - final String messageTypeName = formatTypeName(msgToken.name()); - final int msgLen = msgToken.encodedLength(); - final RustCodecType codecType = RustCodecType.Encoder; - String topType = codecType.generateDoneCoderType(outputManager, messageTypeName); - topType = generateTopVarDataCoders(messageTypeName, components.varData, outputManager, topType, codecType); - topType = generateGroupsCoders(groupTree, outputManager, topType, codecType); - topType = generateFixedFieldCoder(messageTypeName, msgLen, outputManager, topType, fieldStruct, codecType); - topType = codecType.generateMessageHeaderCoder(messageTypeName, outputManager, topType, headerSize); - generateEntryPoint(messageTypeName, outputManager, topType, codecType); - } - - private static void generateMessageDecoder( - final OutputManager outputManager, - final MessageComponents components, - final List groupTree, - final RustStruct fieldStruct, - final int headerSize) - throws IOException - { - final Token msgToken = components.messageToken; - final String messageTypeName = formatTypeName(msgToken.name()); - final int msgLen = msgToken.encodedLength(); - final RustCodecType codecType = RustCodecType.Decoder; - String topType = codecType.generateDoneCoderType(outputManager, messageTypeName); - topType = generateTopVarDataCoders(messageTypeName, components.varData, outputManager, topType, codecType); - topType = generateGroupsCoders(groupTree, outputManager, topType, codecType); - topType = generateFixedFieldCoder(messageTypeName, msgLen, outputManager, topType, fieldStruct, codecType); - topType = codecType.generateMessageHeaderCoder(messageTypeName, outputManager, topType, headerSize); - generateEntryPoint(messageTypeName, outputManager, topType, codecType); - } - - private static void generateEntryPoint( - final String messageTypeName, - final OutputManager outputManager, - final String topType, - final RustCodecType codecType) throws IOException - { - try (Writer writer = outputManager.createOutput(messageTypeName + format(" %s entry point", codecType.name()))) - { - final String gerund = codecType.gerund(); - writer.append(format("pub fn start_%s_%s<%s>(data: &%s%s [u8]) -> %s {\n", gerund, - formatMethodName(messageTypeName), DATA_LIFETIME, DATA_LIFETIME, - codecType == RustCodecType.Encoder ? " mut" : "", - withLifetime(topType))); - indent(writer, 1, "%s::wrap(%s { data: data, pos: 0 })\n", - topType, codecType.scratchType()); - writer.append("}\n"); - } - } - - static void generateMessageHeaderDecoder( - final OutputManager outputManager, - final int headerSize) throws IOException - { - final String messageTypeName = "MessageHeader"; - final RustCodecType codecType = RustCodecType.Decoder; - try (Writer writer = outputManager.createOutput(messageTypeName + format(" %s entry point", codecType.name()))) - { - final String gerund = codecType.gerund(); - writer.append(format("pub fn start_%s_%s<%s>(data: &%s%s [u8]) -> CodecResult<(&%s %s, %s)> {\n", gerund, - formatMethodName(messageTypeName), DATA_LIFETIME, DATA_LIFETIME, - codecType == RustCodecType.Encoder ? " mut" : "", - DATA_LIFETIME, messageTypeName, - withLifetime(codecType.scratchType()))); - indent(writer, 1, format("let mut scratch = %s { data: data, pos: 0 };\n", codecType.scratchType())); - indent(writer, 1, format("let v = scratch.read_type::<%s>(%s)?;\n", messageTypeName, headerSize)); - indent(writer, 1, "Ok((v, scratch))\n"); - writer.append("}\n"); - } - } - - static String withLifetime(final String typeName) - { - return format("%s<%s>", typeName, DATA_LIFETIME); - } - - private static String generateFixedFieldCoder( - final String messageTypeName, - final int messageEncodedLength, - final OutputManager outputManager, - final String topType, - final RustStruct fieldStruct, - final RustCodecType codecType) throws IOException - { - try (Writer writer = outputManager.createOutput(messageTypeName + " Fixed fields " + codecType.name())) - { - final String decoderName = fieldStruct.name + codecType.name(); - codecType.appendScratchWrappingStruct(writer, decoderName); - appendImplWithLifetimeHeader(writer, decoderName); - codecType.appendWrapMethod(writer, decoderName); - codecType.appendDirectCodeMethods(writer, formatMethodName(messageTypeName) + "_fields", - fieldStruct.name, topType, fieldStruct.sizeBytes(), - messageEncodedLength - fieldStruct.sizeBytes()); - writer.append("}\n"); - - return decoderName; - } - } - - private static String generateGroupsCoders( - final List groupTreeNodes, - final OutputManager outputManager, - final String initialNextCoderType, - final RustCodecType codecType) throws IOException - { - String nextCoderType = initialNextCoderType; - for (int i = groupTreeNodes.size() - 1; i >= 0; i--) - { - if (codecType == RustCodecType.Decoder) - { - nextCoderType = generateGroupNodeDecoders(outputManager, nextCoderType, groupTreeNodes.get(i), false); - } - else if (codecType == RustCodecType.Encoder) - { - nextCoderType = generateGroupNodeEncoders(outputManager, nextCoderType, groupTreeNodes.get(i), false); - } - else - { - throw new IllegalArgumentException(format("Unknown CodecType %s", codecType)); - } - } - - return nextCoderType; - } - - private static String generateGroupNodeEncoders( - final OutputManager outputManager, - final String afterGroupCoderType, - final GroupTreeNode node, - final boolean atEndOfParent) throws IOException - { - final boolean hasParent = node.parent.isPresent(); - if (!hasParent && atEndOfParent) - { - throw new IllegalArgumentException("Group cannot both lack a parent and be at the end of a parent group"); - } - - boolean atEndOfCurrentLevel = true; - // TODO - either make this CodecType a param or collapse it - final RustCodecType codecType = RustCodecType.Encoder; - final String memberCoderType = node.contextualName + "Member" + codecType.name(); - String nextCoderType = memberCoderType; - - if (!node.varData.isEmpty()) - { - for (final VarDataSummary varDataSummary : reversedList(node.varData)) - { - nextCoderType = varDataSummary.generateVarDataEncoder( - node.contextualName, memberCoderType, node.depth() + 1, - atEndOfCurrentLevel, outputManager, nextCoderType); - atEndOfCurrentLevel = false; - } - } - - for (final GroupTreeNode childNode : reversedList(node.groups)) - { - nextCoderType = generateGroupNodeEncoders(outputManager, nextCoderType, childNode, atEndOfCurrentLevel); - atEndOfCurrentLevel = false; - } - - return writeGroupEncoderTopTypes( - outputManager, - afterGroupCoderType, - node, - atEndOfParent, - atEndOfCurrentLevel, - memberCoderType, - nextCoderType); - } - - private static String generateGroupNodeDecoders( - final OutputManager outputManager, - final String initialNextDecoderType, - final GroupTreeNode node, - final boolean atEndOfParent) throws IOException - { - final boolean hasParent = node.parent.isPresent(); - if (!hasParent && atEndOfParent) - { - throw new IllegalArgumentException("Group cannot both lack a parent and be at the end of a parent group"); - } - - boolean atEndOfCurrentLevel = true; - final String memberDecoderType = node.contextualName + "MemberDecoder"; - final String headerDecoderType = node.contextualName + "HeaderDecoder"; - final String groupLevelNextDecoderType = - format("Either<%s, %s>", withLifetime(memberDecoderType), initialNextDecoderType.startsWith("Either") ? - initialNextDecoderType : withLifetime(initialNextDecoderType)); - String nextDecoderType = groupLevelNextDecoderType; - - if (!node.varData.isEmpty()) - { - for (final VarDataSummary varDataSummary : reversedList(node.varData)) - { - nextDecoderType = varDataSummary.generateVarDataDecoder( - node.contextualName, memberDecoderType, node.depth() + 1, - atEndOfCurrentLevel, outputManager, nextDecoderType); - atEndOfCurrentLevel = false; - } - } - - for (final GroupTreeNode childNode : reversedList(node.groups)) - { - nextDecoderType = generateGroupNodeDecoders(outputManager, nextDecoderType, childNode, atEndOfCurrentLevel); - atEndOfCurrentLevel = false; - } - - writeGroupDecoderTopTypes(outputManager, initialNextDecoderType, node, atEndOfParent, - atEndOfCurrentLevel, memberDecoderType, headerDecoderType, groupLevelNextDecoderType, nextDecoderType); - - return headerDecoderType; - } - - private static String writeGroupEncoderTopTypes( - final OutputManager outputManager, - final String afterGroupCoderType, - final GroupTreeNode node, - final boolean atEndOfParent, - final boolean atEndOfCurrentLevel, - final String memberCoderType, - final String nextCoderType) throws IOException - { - final String headerCoderType = node.contextualName + "HeaderEncoder"; - try (Writer out = outputManager.createOutput(node.contextualName + " Encoder for fields and header")) - { - appendStructHeader(out, withLifetime(memberCoderType)); - final String rustCountType = rustTypeName(node.dimensionsNumInGroupType()); - final String contentProperty; - final String contentBearingType; - if (node.parent.isPresent()) - { - contentProperty = "parent"; - contentBearingType = withLifetime(node.parent.get().contextualName + "MemberEncoder"); - } - else - { - contentProperty = SCRATCH_ENCODER_PROPERTY; - contentBearingType = withLifetime(SCRATCH_ENCODER_TYPE); - } - indent(out, 1, "%s: %s,\n", contentProperty, contentBearingType); - indent(out).append("count_write_pos: usize,\n"); - indent(out, 1, "count: %s,\n", rustCountType); - out.append("}\n\n"); - - appendImplWithLifetimeHeader(out, memberCoderType); - - indent(out).append("#[inline]\n"); - indent(out, 1, "fn new(%s: %s, count_write_pos: usize) -> Self {\n", contentProperty, contentBearingType); - indent(out, 2).append(memberCoderType).append(" {\n"); - indent(out, 3, "%s: %s,\n", contentProperty, contentProperty); - indent(out, 3).append("count_write_pos: count_write_pos,\n"); - indent(out, 3).append("count: 0,\n"); - indent(out, 2).append("}\n").append(INDENT).append("}\n\n"); - - indent(out).append("#[inline]\n"); - final String fieldsType = node.contextualName + "Member"; - indent(out, 1, "pub fn next_%s_member(mut self, fields: &%s)", - formatMethodName(node.originalName), fieldsType); - out.append(format(" -> CodecResult<%s> {\n", withLifetime(nextCoderType))); - final String scratchChain = toScratchChain(node); - indent(out, 2, "%s.write_type::<%s>(fields, %s)?; // block length\n", - scratchChain, fieldsType, node.blockLength); - indent(out, 2).append("self.count += 1;\n"); - indent(out, 2, "Ok(%s)\n", atEndOfCurrentLevel ? "self" : format("%s::wrap(self)", nextCoderType)); - indent(out).append("}\n"); - - indent(out).append("#[inline]\n"); - indent(out, 1, "pub fn done_with_%s(mut self) -> CodecResult<%s> {\n", - formatMethodName(node.originalName), withLifetime(afterGroupCoderType)); - indent(out, 2, "%s.write_at_position::<%s>(self.count_write_pos, &self.count, %s)?;\n", - scratchChain, rustCountType, node.dimensionsNumInGroupType().size()); - indent(out, 2, "Ok(%s)\n", atEndOfParent ? "self.parent" : - format("%s::wrap(self.%s)", afterGroupCoderType, contentProperty)); - indent(out).append("}\n").append("}\n"); - - appendStructHeader(out, withLifetime(headerCoderType)); - indent(out, 1, "%s: %s,\n", contentProperty, contentBearingType); - out.append("}\n"); - - // Header impl - appendImplWithLifetimeHeader(out, headerCoderType); - indent(out).append("#[inline]\n"); - indent(out, 1, "fn wrap(%s: %s) -> Self {\n", contentProperty, contentBearingType); - indent(out, 2, "%s { %s: %s }\n", headerCoderType, contentProperty, contentProperty) - .append(INDENT).append("}\n"); - - indent(out).append("#[inline]\n"); - indent(out, 1, "pub fn %s_individually(mut self) -> CodecResult<%s> {\n", - formatMethodName(node.originalName), withLifetime(memberCoderType)); - indent(out, 2, "%s.write_type::<%s>(&%s, %s)?; // block length\n", - scratchChain, rustTypeName(node.dimensionsBlockLengthType()), - generateRustLiteral(node.dimensionsBlockLengthType(), Integer.toString(node.blockLength)), - node.dimensionsBlockLengthType().size()); - indent(out, 2, "let count_pos = %s.pos;\n", scratchChain); - indent(out, 2, "%s.write_type::<%s>(&0, %s)?; // preliminary group member count\n", - scratchChain, rustCountType, node.dimensionsNumInGroupType().size()); - indent(out, 2, "Ok(%s::new(self.%s, count_pos))\n", memberCoderType, contentProperty); - indent(out, 1).append("}\n"); - - if (node.hasFixedSizeMembers()) - { - appendFixedSizeMemberGroupEncoderMethods( - afterGroupCoderType, node, atEndOfParent, out, - rustCountType, contentProperty, fieldsType, scratchChain); - } - - out.append("}\n"); - } - - return headerCoderType; - } - - private static void appendFixedSizeMemberGroupEncoderMethods( - final String afterGroupCoderType, - final GroupTreeNode node, - final boolean atEndOfParent, - final Writer out, - final String rustCountType, - final String contentProperty, - final String fieldsType, - final String scratchChain) throws IOException - { - final String s = atEndOfParent ? - "self.parent" : format("%s::wrap(self.%s)", afterGroupCoderType, contentProperty); - - indent(out).append("#[inline]\n"); - indent(out, 1, "pub fn %s_as_slice(mut self, count: %s) -> CodecResult<(&%s mut [%s], %s)> {\n", - formatMethodName(node.originalName), rustCountType, DATA_LIFETIME, fieldsType, - withLifetime(afterGroupCoderType)); - indent(out, 2, "%s.write_type::<%s>(&%s, %s)?; // block length\n", - scratchChain, rustTypeName(node.dimensionsBlockLengthType()), - generateRustLiteral(node.dimensionsBlockLengthType(), Integer.toString(node.blockLength)), - node.dimensionsBlockLengthType().size()); - indent(out, 2, "%s.write_type::<%s>(&count, %s)?; // group count\n", - scratchChain, rustCountType, node.dimensionsNumInGroupType().size()); - indent(out, 2, "let c = count as usize;\n"); - indent(out, 2, "let group_slice = %s.writable_slice::<%s>(c, %s)?;\n", - scratchChain, fieldsType, node.blockLength); - - indent(out, 2, "Ok((group_slice, %s))\n", s); - indent(out, 1).append("}\n"); - - indent(out).append("#[inline]\n"); - indent(out, 1, "pub fn %s_from_slice(mut self, s: &[%s]) -> CodecResult<%s> {\n", - formatMethodName(node.originalName), fieldsType, - withLifetime(afterGroupCoderType)); - indent(out, 2, "%s.write_type::<%s>(&%s, %s)?; // block length\n", - scratchChain, rustTypeName(node.dimensionsBlockLengthType()), - generateRustLiteral(node.dimensionsBlockLengthType(), Integer.toString(node.blockLength)), - node.dimensionsBlockLengthType().size()); - indent(out, 2, "let count = s.len();\n"); - indent(out, 2, "if count > %s {\n", node.dimensionsNumInGroupType().maxValue()); - indent(out, 3).append("return Err(CodecErr::SliceIsLongerThanAllowedBySchema)\n"); - indent(out, 2).append("}\n"); - indent(out, 2, "%s.write_type::<%s>(&(count as %s), %s)?; // group count\n", - scratchChain, rustCountType, rustCountType, node.dimensionsNumInGroupType().size()); - indent(out, 2, "%s.write_slice_without_count::<%s>(s, %s)?;\n", - scratchChain, fieldsType, node.blockLength); - indent(out, 2, "Ok(%s)\n", s); - indent(out, 1).append("}\n"); - } - - private static void writeGroupDecoderTopTypes( - final OutputManager outputManager, - final String initialNextDecoderType, - final GroupTreeNode node, - final boolean atEndOfParent, - final boolean atEndOfCurrentLevel, - final String memberDecoderType, - final String headerDecoderType, - final String groupLevelNextDecoderType, - final String nextDecoderType) throws IOException - { - try (Writer out = outputManager.createOutput(node.contextualName + " Decoder for fields and header")) - { - appendStructHeader(out, withLifetime(memberDecoderType)); - final String rustCountType = rustTypeName(node.dimensionsNumInGroupType()); - final String contentProperty; - final String contentBearingType; - if (node.parent.isPresent()) - { - contentProperty = "parent"; - contentBearingType = withLifetime(node.parent.get().contextualName + "MemberDecoder"); - } - else - { - contentProperty = SCRATCH_DECODER_PROPERTY; - contentBearingType = withLifetime(SCRATCH_DECODER_TYPE); - } - indent(out, 1, "%s: %s,\n", contentProperty, contentBearingType); - indent(out, 1, "max_index: %s,\n", rustCountType); - indent(out, 1, "index: %s,\n", rustCountType); - out.append("}\n\n"); - - appendImplWithLifetimeHeader(out, memberDecoderType); - - indent(out, 1, "fn new(%s: %s, count: %s) -> Self {\n", - contentProperty, contentBearingType, rustCountType); - indent(out, 2, "assert!(count > 0%s);\n", rustCountType); // TODO - elide assert - indent(out, 2).append(memberDecoderType).append(" {\n"); - indent(out, 3, "%s: %s,\n", contentProperty, contentProperty); - indent(out, 3).append("max_index: count - 1,\n"); - indent(out, 3).append("index: 0,\n"); - indent(out, 2).append("}\n").append(INDENT).append("}\n\n"); - - indent(out, 1, "pub fn next_%s_member(mut self)", formatMethodName(node.originalName)); - out.append(format(" -> CodecResult<(&%s %s, %s)> {\n", DATA_LIFETIME, node.contextualName + "Member", - nextDecoderType.startsWith("Either") ? nextDecoderType : withLifetime(nextDecoderType))); - // TODO - account for version mismatch by making use of previously read in-message blockLength - indent(out, 2, "let v = %s.read_type::<%s>(%s)?;\n", - toScratchChain(node), node.contextualName + "Member", node.blockLength); - indent(out, 2).append("self.index += 1;\n"); - - indent(out, 2, "Ok((v, %s))\n", atEndOfCurrentLevel ? "self.after_member()" : - format("%s::wrap(self)", nextDecoderType)); - indent(out).append("}\n"); - - indent(out).append("#[inline]\n"); - indent(out, 1, "fn after_member(self) -> %s {\n", groupLevelNextDecoderType); - indent(out, 2).append("if self.index <= self.max_index {\n"); - indent(out, 3).append("Either::Left(self)\n"); - indent(out, 2).append("} else {\n").append(INDENT).append(INDENT).append(INDENT) - .append(format("Either::Right(%s)\n", atEndOfParent ? "self.parent.after_member()" : - format("%s::wrap(self.%s)", initialNextDecoderType, contentProperty))); - indent(out, 2).append("}\n").append(INDENT).append("}\n").append("}\n"); - - appendStructHeader(out, withLifetime(headerDecoderType)); - indent(out, 1, "%s: %s,\n", contentProperty, contentBearingType).append("}\n"); - - appendImplWithLifetimeHeader(out, headerDecoderType); - indent(out, 1, "fn wrap(%s: %s) -> Self {\n", contentProperty, contentBearingType); - indent(out, 2, "%s { %s: %s }\n", headerDecoderType, contentProperty, contentProperty) - .append(INDENT).append("}\n"); - - indent(out, 1, "pub fn %s_individually(mut self) -> CodecResult<%s> {\n", - formatMethodName(node.originalName), groupLevelNextDecoderType); - indent(out, 2, "let dim = %s.read_type::<%s>(%s)?;\n", - toScratchChain(node), - formatTypeName(node.dimensionsTypeName()), - node.dimensionsTypeSize()); - indent(out, 2).append("if dim.num_in_group > 0 {\n"); - indent(out, 3, "Ok(Either::Left(%s::new(self.%s, dim.num_in_group)))\n", - memberDecoderType, contentProperty).append(INDENT).append(INDENT).append("} else {\n"); - - if (atEndOfParent) - { - indent(out, 3).append("Ok(Either::Right(self.parent.after_member()))\n"); - } - else - { - indent(out, 3, "Ok(Either::Right(%s::wrap(self.%s)))\n", - initialNextDecoderType, contentProperty); - } - indent(out, 2).append("}\n"); - indent(out, 1, "}\n"); - - if (node.hasFixedSizeMembers()) - { - appendFixedSizeMemberGroupDecoderMethods( - initialNextDecoderType, node, atEndOfParent, out, contentProperty); - } - - out.append("}\n"); - } - } - - private static void appendFixedSizeMemberGroupDecoderMethods( - final String initialNextDecoderType, - final GroupTreeNode node, - final boolean atEndOfParent, - final Writer out, - final String contentProperty) throws IOException - { - indent(out, 1, "pub fn %s_as_slice(mut self) -> CodecResult<(&%s [%s], %s)> {\n", - formatMethodName(node.originalName), DATA_LIFETIME, node.contextualName + "Member", - initialNextDecoderType.startsWith("Either") ? - initialNextDecoderType : withLifetime(initialNextDecoderType)); - indent(out, 2, "let dim = %s.read_type::<%s>(%s)?;\n", - toScratchChain(node), - formatTypeName(node.dimensionsTypeName()), - node.dimensionsTypeSize()); - indent(out, 2, "let s = %s.read_slice::<%s>(dim.num_in_group as usize, %s)?;\n", - toScratchChain(node), node.contextualName + "Member", node.blockLength); - indent(out, 2, "Ok((s,%s))\n", atEndOfParent ? "self.parent.after_member()" : - format("%s::wrap(self.%s)", initialNextDecoderType, contentProperty)); - indent(out, 1, "}\n"); - } - - private static String toScratchChain(final GroupTreeNode node) - { - final StringBuilder builder = new StringBuilder("self"); - Optional currentParent = node.parent; - while (currentParent.isPresent()) - { - builder.append(".parent"); - currentParent = currentParent.get().parent; - } - builder.append(".scratch"); - - return builder.toString(); - } - - private static String toScratchChain(final int depth) - { - final StringBuilder builder = new StringBuilder("self"); - for (int i = 0; i < depth; i++) - { - builder.append(".parent"); - } - builder.append(format(".%s", SCRATCH_DECODER_PROPERTY)); - - return builder.toString(); - } - - private static Iterable reversedList(final List list) - { - return - () -> - { - if (list.isEmpty()) - { - return list.stream().iterator(); - } - - final int maxIndex = list.size() - 1; - - return IntStream.rangeClosed(0, maxIndex).mapToObj((i) -> list.get(maxIndex - i)).iterator(); - }; - } - - private static List buildGroupTrees(final String parentTypeName, final List groupsTokens) - { - return buildGroupTrees(parentTypeName, groupsTokens, Optional.empty()); - } - - private static List buildGroupTrees( - final String parentTypeName, - final List groupsTokens, - final Optional parent) - { - final int size = groupsTokens.size(); - final List groups = new ArrayList<>(); - for (int i = 0; i < size; i++) - { - final Token groupToken = groupsTokens.get(i); - if (groupToken.signal() != Signal.BEGIN_GROUP) - { - throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); - } - - final String originalName = groupToken.name(); - final String contextualName = parentTypeName + formatTypeName(originalName); - ++i; - - final Token dimensionsToken = groupsTokens.get(i); - final int groupHeaderTokenCount = dimensionsToken.componentTokenCount(); - final List dimensionsTokens = groupsTokens.subList(i, i + groupHeaderTokenCount); - final GroupDimensions dimensions = GroupDimensions.ofTokens(dimensionsTokens); - final int blockLength = groupToken.encodedLength(); - i += groupHeaderTokenCount; - - final List fields = new ArrayList<>(); - i = collectFields(groupsTokens, i, fields); - - final List childGroups = new ArrayList<>(); - i = collectGroups(groupsTokens, i, childGroups); - - final List varData = new ArrayList<>(); - i = collectVarData(groupsTokens, i, varData); - final List varDataSummaries = VarDataSummary.gatherVarDataSummaries(varData); - - final GroupTreeNode node = new GroupTreeNode( - parent, - originalName, - contextualName, - dimensions, - blockLength, - fields, - varDataSummaries); - - groups.add(node); - buildGroupTrees(contextualName, childGroups, Optional.of(node)); - } - - return groups; - } - - private static PrimitiveType findPrimitiveByTokenName(final List tokens, final String targetName) - { - return findPrimitiveTokenByTokenName(tokens, targetName).encoding().primitiveType(); - } - - private static Token findPrimitiveTokenByTokenName(final List tokens, final String targetName) - { - for (final Token token : tokens) - { - if (targetName.equalsIgnoreCase(token.name()) && - token.encoding() != null && - token.encoding().primitiveType() != null) - { - return token; - } - } - - throw new IllegalStateException(format("%s not specified for group", targetName)); - } - - private static final class GroupDimensions - { - final String typeName; - final int typeSize; - final PrimitiveType numInGroupType; - final PrimitiveType blockLengthType; - - private GroupDimensions(final String typeName, final int typeSize, - final PrimitiveType numInGroupType, final PrimitiveType blockLengthType) - { - this.typeName = typeName; - this.typeSize = typeSize; - this.numInGroupType = numInGroupType; - this.blockLengthType = blockLengthType; - } - - public static GroupDimensions ofTokens(final List dimensionsTokens) - { - final PrimitiveType numInGroupType = findPrimitiveByTokenName(dimensionsTokens, "numInGroup"); - final PrimitiveType blockLengthType = findPrimitiveByTokenName(dimensionsTokens, "blockLength"); - return new GroupDimensions(dimensionsTokens.get(0).name(), dimensionsTokens.get(0).encodedLength(), - numInGroupType, blockLengthType); - } - } - - static class GroupTreeNode - { - final Optional parent; - final String originalName; - final String contextualName; - final GroupDimensions dimensions; - final int blockLength; - final List rawFields; - final List simpleNamedFields; - final List groups = new ArrayList<>(); - final List varData; - - GroupTreeNode( - final Optional parent, - final String originalName, - final String contextualName, - final GroupDimensions dimensions, - final int blockLength, - final List fields, - final List varData) - { - this.parent = parent; - this.originalName = originalName; - this.contextualName = contextualName; - this.dimensions = dimensions; - this.blockLength = blockLength; - this.rawFields = fields; - this.simpleNamedFields = NamedToken.gatherNamedNonConstantFieldTokens(fields); - this.varData = varData; - - parent.ifPresent((p) -> p.addChild(this)); - } - - void addChild(final GroupTreeNode child) - { - groups.add(child); - } - - int depth() - { - Optional currentParent = this.parent; - int d = 0; - while (currentParent.isPresent()) - { - d += 1; - currentParent = currentParent.get().parent; - } - - return d; - } - - boolean hasFixedSizeMembers() - { - return groups.isEmpty() && varData.isEmpty(); - } - - public PrimitiveType dimensionsNumInGroupType() - { - return dimensions.numInGroupType; - } - - public PrimitiveType dimensionsBlockLengthType() - { - return dimensions.blockLengthType; - } - - public String dimensionsTypeName() - { - return dimensions.typeName; - } - - public int dimensionsTypeSize() - { - return dimensions.typeSize; - } - } - - static class VarDataSummary - { - final String name; - final PrimitiveType lengthType; - final PrimitiveType dataType; - - VarDataSummary(final String name, final PrimitiveType lengthType, final PrimitiveType dataType) - { - this.name = name; - this.lengthType = lengthType; - this.dataType = dataType; - } - - String generateVarDataEncoder( - final String parentContextualName, - final String contentType, - final int groupDepth, - final boolean atEndOfGroup, - final OutputManager outputManager, - final String nextCoderType) throws IOException - { - if (groupDepth <= 0 && atEndOfGroup) - { - throw new IllegalStateException("Cannot be both outside of any group and at the end of a group"); - } - - final RustCodecType codecType = RustCodecType.Encoder; - final String decoderType = parentContextualName + formatTypeName(name) + codecType.name(); - try (Writer writer = outputManager.createOutput(name + " variable-length data")) - { - appendStructHeader(writer, withLifetime(decoderType)); - final String contentPropertyName = groupDepth > 0 ? "parent" : codecType.scratchProperty(); - indent(writer, 1, "%s: %s,\n", contentPropertyName, withLifetime(contentType)); - writer.append("}\n"); - - appendImplWithLifetimeHeader(writer, decoderType); - indent(writer, 1, "fn wrap(%s: %s) -> Self {\n", - contentPropertyName, withLifetime(contentType)); - indent(writer, 2, "%s { %s: %s }\n", - decoderType, contentPropertyName, contentPropertyName).append(INDENT).append("}\n"); - - indent(writer, 1, "pub fn %s(mut self, s: &%s [%s]) -> CodecResult<%s> {\n", - formatMethodName(name), DATA_LIFETIME, rustTypeName(this.dataType), - atEndOfGroup ? nextCoderType : withLifetime(nextCoderType)); - - indent(writer, 2).append("let l = s.len();\n"); - indent(writer, 2, "if l > %s {\n", this.lengthType.maxValue()); - indent(writer, 3).append("return Err(CodecErr::SliceIsLongerThanAllowedBySchema)\n"); - indent(writer, 2).append("}\n"); - indent(writer, 2).append("// Write data length\n"); - indent(writer, 2, "%s.write_type::<%s>(&(l as %s), %s)?; // group length\n", - toScratchChain(groupDepth), rustTypeName(this.lengthType), rustTypeName(this.lengthType), - this.lengthType.size()); - indent(writer, 2).append(format("%s.write_slice_without_count::<%s>(s, %s)?;\n", - toScratchChain(groupDepth), rustTypeName(this.dataType), this.dataType.size())); - indent(writer, 2, "Ok(%s)\n", atEndOfGroup ? "self.parent" : - format("%s::wrap(self.%s)", nextCoderType, contentPropertyName)); - - indent(writer).append("}\n}\n"); - } - - return decoderType; - } - - String generateVarDataDecoder( - final String parentContextualName, - final String contentType, - final int groupDepth, - final boolean atEndOfGroup, - final OutputManager outputManager, - final String nextDecoderType) throws IOException - { - if (groupDepth <= 0 && atEndOfGroup) - { - throw new IllegalStateException("Cannot be both outside of any group and at the end of a group"); - } - - final String name = this.name; - final String decoderType = parentContextualName + formatTypeName(name) + "Decoder"; - try (Writer writer = outputManager.createOutput(name + " variable-length data")) - { - appendStructHeader(writer, withLifetime(decoderType)); - final String contentPropertyName = groupDepth > 0 ? "parent" : SCRATCH_DECODER_PROPERTY; - indent(writer, 1, "%s: %s,\n", contentPropertyName, withLifetime(contentType)); - writer.append("}\n"); - - appendImplWithLifetimeHeader(writer, decoderType); - indent(writer, 1, "fn wrap(%s: %s) -> Self {\n", contentPropertyName, withLifetime(contentType)); - indent(writer, 2, "%s { %s: %s }\n", - decoderType, contentPropertyName, contentPropertyName).append(INDENT).append("}\n"); - - indent(writer, 1, "pub fn %s(mut self) -> CodecResult<(&%s [%s], %s)> {\n", - formatMethodName(name), DATA_LIFETIME, rustTypeName(this.dataType), - atEndOfGroup ? nextDecoderType : withLifetime(nextDecoderType)); - indent(writer, 2, "let count = *%s.read_type::<%s>(%s)?;\n", - toScratchChain(groupDepth), rustTypeName(this.lengthType), this.lengthType.size()); - - final String goToNext; - if (atEndOfGroup) - { - goToNext = "self.parent.after_member()"; - } - else - { - goToNext = format("%s::wrap(self.%s)", nextDecoderType, contentPropertyName); - } - - indent(writer, 2, - "Ok((%s.read_slice::<%s>(count as usize, %s)?, %s))\n", toScratchChain(groupDepth), - rustTypeName(this.dataType), this.dataType.size(), goToNext); - indent(writer).append("}\n"); - - writer.append("}\n"); - } - - return decoderType; - } - - static List gatherVarDataSummaries(final List tokens) - { - final List summaries = new ArrayList<>(); - for (int i = 0; i < tokens.size(); i++) - { - final Token beginToken = tokens.get(i); - if (beginToken.signal() != Signal.BEGIN_VAR_DATA) - { - throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + beginToken); - } - - ++i; - final Token dimensionsToken = tokens.get(i); - final int headerTokenCount = dimensionsToken.componentTokenCount(); - final List currentEncodingTokens = tokens.subList(i, i + headerTokenCount); - final PrimitiveType lengthType = findPrimitiveByTokenName(currentEncodingTokens, "length"); - final PrimitiveType dataType = findPrimitiveByTokenName(currentEncodingTokens, "varData"); - summaries.add(new VarDataSummary(beginToken.name(), lengthType, dataType)); - i += headerTokenCount; - } - - return summaries; - } - } - - static String generateTopVarDataCoders( - final String messageTypeName, - final List tokens, - final OutputManager outputManager, - final String initialNextType, - final RustCodecType codecType) - throws IOException - { - final List summaries = VarDataSummary.gatherVarDataSummaries(tokens); - - String nextCoderType = initialNextType; - for (final VarDataSummary summary : reversedList(summaries)) - { - if (codecType == RustCodecType.Decoder) - { - nextCoderType = summary.generateVarDataDecoder( - messageTypeName, SCRATCH_DECODER_TYPE, 0, false, outputManager, nextCoderType); - } - else if (codecType == RustCodecType.Encoder) - { - nextCoderType = summary.generateVarDataEncoder( - messageTypeName, SCRATCH_ENCODER_TYPE, 0, false, outputManager, nextCoderType); - } - else - { - throw new IllegalArgumentException(format("Unknown RustCodecType %s", codecType)); - } - } - - return nextCoderType; - } - - static void appendImplWithLifetimeHeader(final Appendable appendable, final String typeName) - throws IOException - { - appendable.append(format("impl<%s> %s<%s> {\n", DATA_LIFETIME, typeName, DATA_LIFETIME)); - } - - private static void generateEnums(final Ir ir, final OutputManager outputManager) - throws IOException - { - final Set enumTypeNames = new HashSet<>(); - for (final List tokens : ir.types()) - { - if (tokens.isEmpty()) - { - continue; - } - - final Token beginToken = tokens.get(0); - if (beginToken.signal() != BEGIN_ENUM) - { - continue; - } - - final String typeName = beginToken.applicableTypeName(); - if (enumTypeNames.contains(typeName)) - { - continue; - } - - generateEnum(tokens, outputManager); - enumTypeNames.add(typeName); - } - } - - static void generateSharedImports(final OutputManager outputManager) throws IOException - { - try (Writer writer = outputManager.createOutput("Imports core rather than std to broaden usable environments.")) - { - writer.append("extern crate core;\n"); - } - } - - static void generateResultEnums(final OutputManager outputManager) throws IOException - { - try (Writer writer = outputManager.createOutput("Result types for error handling")) - { - writer.append("\n/// Errors that may occur during the course of encoding or decoding.\n"); - writer.append("#[derive(Debug)]\n"); - writer.append("pub enum CodecErr {\n"); - indent(writer, 1, "/// Too few bytes in the byte-slice to read or write the data structure relevant\n"); - indent(writer, 1, "/// to the current state of the codec\n"); - indent(writer, 1, "NotEnoughBytes,\n\n"); - indent(writer, 1, "/// Groups and vardata are constrained by the numeric type chosen to represent their\n"); - indent(writer, 1, "/// length as well as optional maxima imposed by the schema\n"); - indent(writer, 1, "SliceIsLongerThanAllowedBySchema,\n"); - writer.append("}\n\n"); - writer.append("pub type CodecResult = core::result::Result;\n"); - } - } - - static void generateEncoderScratchStruct(final OutputManager outputManager) throws IOException - { - try (Writer writer = outputManager.createOutput("Scratch Encoder Data Wrapper - codec internal use only")) - { - writer.append("#[derive(Debug)]\n"); - writer.append(format("pub struct %s<%s> {\n", SCRATCH_ENCODER_TYPE, DATA_LIFETIME)); - indent(writer, 1, "data: &%s mut [u8],\n", DATA_LIFETIME); - indent(writer).append("pos: usize,\n"); - writer.append("}\n"); - - writer.append(format("%nimpl<%s> %s<%s> {\n", DATA_LIFETIME, SCRATCH_ENCODER_TYPE, DATA_LIFETIME)); - - indent(writer, 1, "/// Copy the bytes of a value into the data buffer\n"); - indent(writer, 1, "/// Advances the `pos` index to after the newly-written bytes.\n"); - indent(writer).append("#[inline]\n"); - indent(writer).append("fn write_type(&mut self, t: & T, num_bytes: usize) -> " + - "CodecResult<()> {\n"); - indent(writer, 2).append("let end = self.pos + num_bytes;\n"); - indent(writer, 2).append("if end <= self.data.len() {\n"); - indent(writer, 3).append("let source_bytes: &[u8] = unsafe {\n"); - indent(writer, 4).append("core::slice::from_raw_parts(t as *const T as *const u8, num_bytes)\n"); - indent(writer, 3).append("};\n"); - indent(writer, 3).append("(&mut self.data[self.pos..end]).copy_from_slice(source_bytes);\n"); - indent(writer, 3).append("self.pos = end;\n"); - indent(writer, 3).append("Ok(())\n"); - indent(writer, 2).append("} else {\n"); - indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n"); - indent(writer, 2).append("}\n"); - indent(writer).append("}\n\n"); - - indent(writer, 1, "/// Advances the `pos` index by a set number of bytes.\n"); - indent(writer).append("#[inline]\n"); - indent(writer).append("fn skip_bytes(&mut self, num_bytes: usize) -> CodecResult<()> {\n"); - indent(writer, 2).append("let end = self.pos + num_bytes;\n"); - indent(writer, 2).append("if end <= self.data.len() {\n"); - indent(writer, 3).append("self.pos = end;\n"); - indent(writer, 3).append("Ok(())\n"); - indent(writer, 2).append("} else {\n"); - indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n"); - indent(writer, 2).append("}\n"); - indent(writer).append("}\n\n"); - - indent(writer, 1, "/// Create a struct reference overlaid atop the data buffer\n"); - indent(writer, 1, "/// such that changes to the struct directly edit the buffer. \n"); - indent(writer, 1, "/// Note that the initial content of the struct's fields may be garbage.\n"); - indent(writer, 1, "/// Advances the `pos` index to after the newly-written bytes.\n"); - indent(writer).append("#[inline]\n"); - indent(writer, 1, "fn writable_overlay(&mut self, num_bytes: usize) " + - "-> CodecResult<&%s mut T> {\n", DATA_LIFETIME); - indent(writer, 2).append("let end = self.pos + num_bytes;\n"); - indent(writer, 2).append("if end <= self.data.len() {\n"); - indent(writer, 3, "let v: &%s mut T = unsafe {\n", DATA_LIFETIME); - indent(writer, 4).append("let s = self.data.as_ptr().offset(self.pos as isize) as *mut T;\n"); - indent(writer, 4).append("&mut *s\n"); - indent(writer, 3).append("};\n"); - indent(writer, 3).append("self.pos = end;\n"); - indent(writer, 3).append("Ok(v)\n"); - indent(writer, 2).append("} else {\n"); - indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n"); - indent(writer, 2).append("}\n"); - indent(writer).append("}\n\n"); - - indent(writer, 1, "/// Copy the bytes of a value into the data buffer at a specific position\n"); - indent(writer, 1, "/// Does **not** alter the `pos` index.\n"); - indent(writer).append("#[inline]\n"); - indent(writer).append("fn write_at_position(&mut self, position: usize, t: & T, num_bytes: usize) -> " + - "CodecResult<()> {\n"); - indent(writer, 2).append("let end = position + num_bytes;\n"); - indent(writer, 2).append("if end <= self.data.len() {\n"); - indent(writer, 3).append("let source_bytes: &[u8] = unsafe {\n"); - indent(writer, 4).append("core::slice::from_raw_parts(t as *const T as *const u8, num_bytes)\n"); - indent(writer, 3).append("};\n"); - indent(writer, 3).append("(&mut self.data[position..end]).copy_from_slice(source_bytes);\n"); - indent(writer, 3).append("Ok(())\n"); - indent(writer, 2).append("} else {\n"); - indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n"); - indent(writer, 2).append("}\n"); - indent(writer).append("}\n"); - - generateEncoderScratchSliceMethods(writer); - - writer.append("}\n"); - } - } - - static void generateEncoderScratchSliceMethods(final Appendable writer) throws IOException - { - indent(writer, 1, "/// Create a mutable slice overlaid atop the data buffer directly\n"); - indent(writer, 1, "/// such that changes to the slice contents directly edit the buffer\n"); - indent(writer, 1, "/// Note that the initial content of the slice's members' fields may be garbage.\n"); - indent(writer, 1, "/// Advances the `pos` index to after the region representing the slice.\n"); - indent(writer).append("#[inline]\n"); - indent(writer, 1, "fn writable_slice(&mut self, count: usize, bytes_per_item: usize) " + - "-> CodecResult<&%s mut [T]> {\n", DATA_LIFETIME); - indent(writer, 2).append("let end = self.pos + (count * bytes_per_item);\n"); - indent(writer, 2).append("if end <= self.data.len() {\n"); - indent(writer, 3, "let v: &%s mut [T] = unsafe {\n", DATA_LIFETIME); - indent(writer, 4).append("core::slice::from_raw_parts_mut(" + - "self.data[self.pos..end].as_mut_ptr() as *mut T, count)\n"); - indent(writer, 3).append("};\n"); - indent(writer, 3).append("self.pos = end;\n"); - indent(writer, 3).append("Ok(v)\n"); - indent(writer, 2).append("} else {\n"); - indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n"); - indent(writer, 2).append("}\n"); - indent(writer).append("}\n\n"); - - indent(writer, 1, "/// Copy the raw bytes of a slice's contents into the data buffer\n"); - indent(writer, 1, "/// Does **not** encode the length of the slice explicitly into the buffer.\n"); - indent(writer, 1, "/// Advances the `pos` index to after the newly-written slice bytes.\n"); - indent(writer).append("#[inline]\n"); - indent(writer).append("fn write_slice_without_count(&mut self, t: &[T], bytes_per_item: usize) -> " + - "CodecResult<()> {\n"); - indent(writer, 2).append("let content_bytes_size = bytes_per_item * t.len();\n"); - indent(writer, 2).append("let end = self.pos + content_bytes_size;\n"); - indent(writer, 2).append("if end <= self.data.len() {\n"); - indent(writer, 3).append("let source_bytes: &[u8] = unsafe {\n"); - indent(writer, 4).append("core::slice::from_raw_parts(t.as_ptr() as *const u8, content_bytes_size)\n"); - indent(writer, 3).append("};\n"); - indent(writer, 3).append("(&mut self.data[self.pos..end]).copy_from_slice(source_bytes);\n"); - indent(writer, 3).append("self.pos = end;\n"); - indent(writer, 3).append("Ok(())\n"); - indent(writer, 2).append("} else {\n"); - indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n"); - indent(writer, 2).append("}\n"); - indent(writer).append("}\n"); - } - - private static void generateDecoderScratchStruct(final OutputManager outputManager) throws IOException - { - try (Writer writer = outputManager.createOutput("Scratch Decoder Data Wrapper - codec internal use only")) - { - writer.append("#[derive(Debug)]\n"); - writer.append(format("pub struct %s<%s> {\n", SCRATCH_DECODER_TYPE, DATA_LIFETIME)); - indent(writer, 1, "data: &%s [u8],\n", DATA_LIFETIME); - indent(writer).append("pos: usize,\n"); - writer.append("}\n"); - - writer.append(format("%nimpl<%s> %s<%s> {\n", DATA_LIFETIME, SCRATCH_DECODER_TYPE, DATA_LIFETIME)); - - indent(writer, 1, "/// Create a struct reference overlaid atop the data buffer\n"); - indent(writer, 1, "/// such that the struct's contents directly reflect the buffer. \n"); - indent(writer, 1, "/// Advances the `pos` index by the size of the struct in bytes.\n"); - indent(writer).append("#[inline]\n"); - indent(writer, 1, "fn read_type(&mut self, num_bytes: usize) -> CodecResult<&%s T> {\n", DATA_LIFETIME); - indent(writer, 2).append("let end = self.pos + num_bytes;\n"); - indent(writer, 2).append("if end <= self.data.len() {\n"); - indent(writer, 3).append("let s = self.data[self.pos..end].as_ptr() as *mut T;\n"); - indent(writer, 3, "let v: &%s T = unsafe { &*s };\n", DATA_LIFETIME); - indent(writer, 3).append("self.pos = end;\n"); - indent(writer, 3).append("Ok(v)\n"); - indent(writer, 2).append("} else {\n"); - indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n"); - indent(writer, 2).append("}\n"); - indent(writer).append("}\n\n"); - - indent(writer, 1, "/// Advances the `pos` index by a set number of bytes.\n"); - indent(writer).append("#[inline]\n"); - indent(writer).append("fn skip_bytes(&mut self, num_bytes: usize) -> CodecResult<()> {\n"); - indent(writer, 2).append("let end = self.pos + num_bytes;\n"); - indent(writer, 2).append("if end <= self.data.len() {\n"); - indent(writer, 3).append("self.pos = end;\n"); - indent(writer, 3).append("Ok(())\n"); - indent(writer, 2).append("} else {\n"); - indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n"); - indent(writer, 2).append("}\n"); - indent(writer).append("}\n\n"); - - indent(writer, 1, "/// Create a slice reference overlaid atop the data buffer\n"); - indent(writer, 1, "/// such that the slice's members' contents directly reflect the buffer.\n"); - indent(writer, 1, "/// Advances the `pos` index by the size of the slice contents in bytes.\n"); - indent(writer).append("#[inline]\n"); - indent(writer, 1, "fn read_slice(&mut self, count: usize, bytes_per_item: usize) " + - "-> CodecResult<&%s [T]> {\n", DATA_LIFETIME); - indent(writer, 2).append("let num_bytes = bytes_per_item * count;\n"); - indent(writer, 2).append("let end = self.pos + num_bytes;\n"); - indent(writer, 2).append("if end <= self.data.len() {\n"); - indent(writer, 3, "let v: &%s [T] = unsafe {\n", DATA_LIFETIME); - indent(writer, 4).append("core::slice::from_raw_parts(self.data[self.pos..end].as_ptr() as *const T, " + - "count)\n"); - indent(writer, 3).append("};\n"); - indent(writer, 3).append("self.pos = end;\n"); - indent(writer, 3).append("Ok(v)\n"); - indent(writer, 2).append("} else {\n"); - indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n"); - indent(writer, 2).append("}\n"); - indent(writer).append("}\n"); - - writer.append("}\n"); - } - } - - private static void generateEitherEnum(final OutputManager outputManager) throws IOException - { - try (Writer writer = outputManager.createOutput("Convenience Either enum")) - { - writer.append("#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]\n"); - writer.append("pub enum Either {\n"); - indent(writer).append("Left(L),\n"); - indent(writer).append("Right(R)\n"); - writer.append("}\n"); - } - } - - private static void generateEnum(final List enumTokens, final OutputManager outputManager) - throws IOException - { - final String originalEnumName = enumTokens.get(0).applicableTypeName(); - final String enumRustName = formatTypeName(originalEnumName); - try (Writer writer = outputManager.createOutput("Enum " + enumRustName)) - { - final List messageBody = getMessageBody(enumTokens); - if (messageBody.isEmpty()) - { - throw new IllegalArgumentException("No valid values provided for enum " + originalEnumName); - } - - writer.append("#[derive(Clone,Copy,Debug,PartialEq,Eq,PartialOrd,Ord,Hash)]").append("\n"); - final String rustReprTypeName = rustTypeName(messageBody.get(0).encoding().primitiveType()); - writer.append(format("#[repr(%s)]", - rustReprTypeName)).append("\n"); - writer.append("pub enum ").append(enumRustName).append(" {\n"); - - for (final Token token : messageBody) - { - final Encoding encoding = token.encoding(); - final String literal = generateRustLiteral(encoding.primitiveType(), encoding.constValue().toString()); - indent(writer, 1).append(token.name()) - .append(" = ") - .append(literal) - .append(",\n"); - } - - // null value - final Token token = messageBody.get(0); - final Encoding encoding = token.encoding(); - final CharSequence nullVal = generateRustLiteral( - encoding.primitiveType(), encoding.applicableNullValue().toString()); - indent(writer, 1).append("NullVal") - .append(" = ") - .append(nullVal) - .append(",\n"); - - writer.append("}\n"); - - // Default implementation to support Default in other structs - indent(writer, 0, "impl Default for %s {\n", enumRustName); - indent(writer, 1, "fn default() -> Self { %s::%s }\n", enumRustName, "NullVal"); - indent(writer, 0, "}\n"); - } - } - - private static void generateComposites(final Ir ir, final OutputManager outputManager) throws IOException - { - for (final List tokens : ir.types()) - { - if (!tokens.isEmpty() && tokens.get(0).signal() == Signal.BEGIN_COMPOSITE) - { - generateSingleComposite(tokens, outputManager); - } - } - } - - private static void generateSingleComposite(final List tokens, final OutputManager outputManager) - throws IOException - { - final Token beginToken = tokens.get(0); - final String originalTypeName = beginToken.applicableTypeName(); - final String formattedTypeName = formatTypeName(originalTypeName); - final SplitCompositeTokens splitTokens = SplitCompositeTokens.splitInnerTokens(tokens); - - try (Writer writer = outputManager.createOutput(formattedTypeName)) - { - final RustStruct struct = RustStruct.fromTokens(formattedTypeName, - splitTokens.nonConstantEncodingTokens(), - EnumSet.of(RustStruct.Modifier.PACKED, RustStruct.Modifier.DEFAULT)); - struct.appendDefinitionTo(writer); - - generateConstantAccessorImpl(writer, formattedTypeName, getMessageBody(tokens)); - } - } - - private interface RustTypeDescriptor - { - String DEFAULT_VALUE = "Default::default()"; - - String name(); - - String literalValue(String valueRep); - - int sizeBytes(); - - default String defaultValue() - { - return DEFAULT_VALUE; - } - } - - private static final class RustArrayType implements RustTypeDescriptor - { - private final RustTypeDescriptor componentType; - private final int length; - - private RustArrayType(final RustTypeDescriptor component, final int length) - { - this.componentType = component; - this.length = length; - } - - public String name() - { - return getRustStaticArrayString(componentType.name(), length); - } - - public String literalValue(final String valueRep) - { - return getRustStaticArrayString(valueRep + componentType.name(), length); - } - - public int sizeBytes() - { - return componentType.sizeBytes() * length; - } - - public String defaultValue() - { - final String defaultValue = RustTypeDescriptor.super.defaultValue(); - if (length <= 32) - { - return defaultValue; - } - else - { - final StringBuilder result = new StringBuilder(); - result.append('['); - for (int i = 0; i < length; i++) - { - result.append(defaultValue); - result.append(", "); - if (i % 4 == 0) // ~80 char lines - { - result.append('\n'); - } - } - result.append(']'); - - return result.toString(); - } - } - } - - private static final class RustPrimitiveType implements RustTypeDescriptor - { - private final String name; - private final int sizeBytes; - - private RustPrimitiveType(final String name, final int sizeBytes) - { - this.name = name; - this.sizeBytes = sizeBytes; - } - - public String name() - { - return name; - } - - public String literalValue(final String valueRep) - { - return valueRep + name; - } - - public int sizeBytes() - { - return sizeBytes; - } - } - - private static final class AnyRustType implements RustTypeDescriptor - { - private final String name; - private final int sizeBytes; - - private AnyRustType(final String name, final int sizeBytes) - { - this.name = name; - this.sizeBytes = sizeBytes; - } - - public String name() - { - return name; - } - - public String literalValue(final String valueRep) - { - final String msg = String.format("Cannot produce a literal value %s of type %s!", valueRep, name); - throw new UnsupportedOperationException(msg); - } - - public int sizeBytes() - { - return sizeBytes; - } - } - - private static final class RustTypes - { - static final RustTypeDescriptor U_8 = new RustPrimitiveType("u8", 1); - - static RustTypeDescriptor ofPrimitiveToken(final Token token) - { - final PrimitiveType primitiveType = token.encoding().primitiveType(); - final String rustPrimitiveType = RustUtil.rustTypeName(primitiveType); - final RustPrimitiveType type = new RustPrimitiveType(rustPrimitiveType, primitiveType.size()); - if (token.arrayLength() > 1) - { - return new RustArrayType(type, token.arrayLength()); - } - - return type; - } - - static RustTypeDescriptor ofGeneratedToken(final Token token) - { - return new AnyRustType(formatTypeName(token.applicableTypeName()), token.encodedLength()); - } - - static RustTypeDescriptor arrayOf(final RustTypeDescriptor type, final int len) - { - return new RustArrayType(type, len); - } - } - - private static final class RustStruct - { - enum Modifier - { - PACKED, DEFAULT - } - - final String name; - final List fields; - final EnumSet modifiers; - - private RustStruct(final String name, final List fields, final EnumSet modifiers) - { - this.name = name; - this.fields = fields; - this.modifiers = modifiers; - } - - public int sizeBytes() - { - return fields.stream().mapToInt((v) -> v.type.sizeBytes()).sum(); - } - - static RustStruct fromHeader(final HeaderStructure header) - { - final List tokens = header.tokens(); - final String originalTypeName = tokens.get(0).applicableTypeName(); - final String formattedTypeName = formatTypeName(originalTypeName); - final SplitCompositeTokens splitTokens = SplitCompositeTokens.splitInnerTokens(tokens); - - return RustStruct.fromTokens( - formattedTypeName, - splitTokens.nonConstantEncodingTokens(), - EnumSet.of(Modifier.PACKED, Modifier.DEFAULT)); - } - - static RustStruct fromTokens( - final String name, final List tokens, final EnumSet modifiers) - { - return new RustStruct(name, collectStructFields(tokens), modifiers); - } - - // No way to create struct with default values. - // Rust RFC: https://github.com/Centril/rfcs/pull/19 - // Used when struct contains a field which doesn't have a Default impl - void appendDefaultConstructorTo(final Appendable appendable) throws IOException - { - indent(appendable, 0, "impl Default for %s {\n", name); - indent(appendable, 1, "fn default() -> Self {\n"); - - appendInstanceTo(appendable, 2, Collections.emptyMap()); - - indent(appendable, 1, "}\n"); - - appendable.append("}\n"); - } - - void appendDefinitionTo(final Appendable appendable) throws IOException - { - final boolean needsDefault = modifiers.contains(Modifier.DEFAULT); - final boolean canDeriveDefault = fields.stream() - .allMatch((v) -> v.type.defaultValue() == RustTypeDescriptor.DEFAULT_VALUE); - - final Set modifiers = this.modifiers.clone(); - if (needsDefault && !canDeriveDefault) - { - modifiers.remove(Modifier.DEFAULT); - } - - appendStructHeader(appendable, name, modifiers); - for (final RustStructField field: fields) - { - indent(appendable); - if (field.modifiers.contains(RustStructField.Modifier.PUBLIC)) - { - appendable.append("pub "); - } - appendable.append(field.name).append(":").append(field.type.name()).append(",\n"); - } - appendable.append("}\n"); - - if (needsDefault && !canDeriveDefault) - { - appendDefaultConstructorTo(appendable); - } - } - - void appendInstanceTo(final Appendable appendable, final int indent, final Map values) - throws IOException - { - indent(appendable, indent, "%s {\n", name); - for (final RustStructField field: fields) - { - final String value; - if (values.containsKey(field.name)) - { - value = field.type.literalValue(values.get(field.name)); - } - else - { - value = field.type.defaultValue(); - } - - indent(appendable, indent + 1, "%s: %s,\n", formatMethodName(field.name), value); - } - indent(appendable, indent, "}\n"); - } - } - - private static final class RustStructField - { - enum Modifier - { - PUBLIC - } - - final String name; - final RustTypeDescriptor type; - final EnumSet modifiers; - - private RustStructField(final String name, final RustTypeDescriptor type, final EnumSet modifiers) - { - this.name = name; - this.type = type; - this.modifiers = modifiers; - } - - private RustStructField(final String name, final RustTypeDescriptor type) - { - this(name, type, EnumSet.noneOf(Modifier.class)); - } - } - - private static List collectStructFields(final List namedTokens) - { - final List fields = new ArrayList<>(); - int totalSize = 0; - for (final NamedToken namedToken : namedTokens) - { - final Token typeToken = namedToken.typeToken(); - if (typeToken.isConstantEncoding()) - { - continue; - } - - final String propertyName = formatMethodName(namedToken.name()); - - // need padding when field offsets imply gaps - final int offset = typeToken.offset(); - if (offset != totalSize) - { - int rem = offset - totalSize; - int idx = 1; - while (rem > 0) - { - // split padding arrays to 32 as larger arrays do not have an `impl Default` - final int padding = Math.min(rem, 32); - final RustTypeDescriptor type = RustTypes.arrayOf(RustTypes.U_8, padding); - fields.add(new RustStructField(propertyName + "_padding_" + idx, type)); - - idx += 1; - rem -= padding; - } - } - totalSize = offset + typeToken.encodedLength(); - - final RustTypeDescriptor type; - switch (typeToken.signal()) - { - case ENCODING: - type = RustTypes.ofPrimitiveToken(typeToken); - fields.add(new RustStructField(propertyName, type, EnumSet.of(RustStructField.Modifier.PUBLIC))); - break; - - case BEGIN_ENUM: - case BEGIN_SET: - case BEGIN_COMPOSITE: - type = RustTypes.ofGeneratedToken(typeToken); - fields.add(new RustStructField(propertyName, type, EnumSet.of(RustStructField.Modifier.PUBLIC))); - break; - - default: - throw new IllegalStateException(format("Unsupported struct property from %s", typeToken)); - } - } - return fields; - } - - private void generateMessageHeaderDefault( - final Ir ir, - final OutputManager outputManager, - final Token messageToken) - throws IOException - { - final HeaderStructure header = ir.headerStructure(); - final RustStruct rustHeader = RustStruct.fromHeader(header); - - final String messageTypeName = formatTypeName(messageToken.name()); - final String wrapperName = messageTypeName + "MessageHeader"; - - try (Writer writer = outputManager.createOutput(messageTypeName + " specific Message Header ")) - { - appendStructHeader(writer, wrapperName, EnumSet.of(RustStruct.Modifier.PACKED)); - indent(writer, 1, "pub message_header: MessageHeader\n"); - writer.append("}\n"); - - final String blockLength = Integer.toString(messageToken.encodedLength()); - final String templateId = Integer.toString(messageToken.id()); - final String schemaId = Integer.toString(ir.id()); - final String version = Integer.toString(ir.version()); - - indent(writer, 0, "impl %s {\n", wrapperName); - indent(writer, 1, "pub const BLOCK_LENGTH : u16 = " + blockLength + ";\n"); - indent(writer, 1, "pub const TEMPLATE_ID : u16 = " + templateId + ";\n"); - indent(writer, 1, "pub const SCHEMA_ID : u16 = " + schemaId + ";\n"); - indent(writer, 1, "pub const VERSION : u16 = " + version + ";\n"); - indent(writer, 0, "}\n"); - - indent(writer, 0, "impl Default for %s {\n", wrapperName); - indent(writer, 1, "fn default() -> %s {\n", wrapperName); - indent(writer, 2, "%s {\n", wrapperName); - - indent(writer, 3, "message_header: "); - rustHeader.appendInstanceTo(writer, 3, - new HashMap() - { - { - put("block_length", blockLength); - put("template_id", templateId); - put("schema_id", schemaId); - put("version", version); - } - }); - - indent(writer, 2, "}\n"); - indent(writer, 1, "}\n"); - - writer.append("}\n"); - } - } - - private static void appendStructHeader(final Appendable appendable, final String structName) throws IOException - { - appendStructHeader(appendable, structName, EnumSet.noneOf(RustStruct.Modifier.class)); - } - - private static void appendStructHeader( - final Appendable appendable, final String structName, final Set modifiers) - throws IOException - { - if (!modifiers.isEmpty()) - { - if (modifiers.contains(RustStruct.Modifier.PACKED)) - { - appendable.append("#[repr(C,packed)]\n"); - } - if (modifiers.contains(RustStruct.Modifier.DEFAULT)) - { - appendable.append("#[derive(Default)]\n"); - } - } - - appendable.append(format("pub struct %s {\n", structName)); - } - - private static String getRustStaticArrayString(final String rustPrimitiveType, final int length) - { - return format("[%s;%s]", rustPrimitiveType, length); - } - - private static String getRustTypeForPrimitivePossiblyArray( - final Token encodingToken, final String rustPrimitiveType) - { - final String rustType; - if (encodingToken.arrayLength() > 1) - { - rustType = getRustStaticArrayString(rustPrimitiveType, encodingToken.arrayLength()); - } - else - { - rustType = rustPrimitiveType; - } - - return rustType; - } - - private static void generateConstantAccessorImpl( - final Appendable writer, final String formattedTypeName, final List unfilteredFields) throws IOException - { - writer.append(format("%nimpl %s {\n", formattedTypeName)); - - for (int i = 0; i < unfilteredFields.size(); ) - { - final Token fieldToken = unfilteredFields.get(i); - final String name = fieldToken.name(); - final int componentTokenCount = fieldToken.componentTokenCount(); - final Token signalToken; - if (fieldToken.signal() == BEGIN_FIELD) - { - if (i > unfilteredFields.size() - 1) - { - throw new ArrayIndexOutOfBoundsException("BEGIN_FIELD token should be followed by content tokens"); - } - signalToken = unfilteredFields.get(i + 1); - } - else - { - signalToken = fieldToken; - } - - // Either the field must be marked directly as constant - // or it must wrap something that is fully constant - if (!(fieldToken.isConstantEncoding() || signalToken.isConstantEncoding())) - { - i += componentTokenCount; - continue; - } - - final String constantRustTypeName; - final String constantRustExpression; - switch (signalToken.signal()) - { - case ENCODING: - final String rawValue = signalToken.encoding().constValue().toString(); - if (signalToken.encoding().primitiveType() == PrimitiveType.CHAR) - { - // Special case string handling - constantRustTypeName = "&'static str"; - // TODO - proper string escaping - constantRustExpression = "\"" + rawValue + "\""; - } - else - { - final String constantRustPrimitiveType = RustUtil.rustTypeName( - signalToken.encoding().primitiveType()); - constantRustTypeName = getRustTypeForPrimitivePossiblyArray( - signalToken, constantRustPrimitiveType); - constantRustExpression = generateRustLiteral( - signalToken.encoding().primitiveType(), rawValue); - } - break; - - case BEGIN_ENUM: - final String enumType = formatTypeName(signalToken.applicableTypeName()); - final String rawConstValueName = fieldToken.encoding().constValue().toString(); - final int indexOfDot = rawConstValueName.indexOf('.'); - final String constValueName = -1 == indexOfDot ? - rawConstValueName : rawConstValueName.substring(indexOfDot + 1); - boolean foundMatchingValueName = false; - for (int j = i; j < unfilteredFields.size(); j++) - { - final Token searchAhead = unfilteredFields.get(j); - if (searchAhead.signal() == VALID_VALUE && searchAhead.name().equals(constValueName)) - { - foundMatchingValueName = true; - break; - } - } - if (!foundMatchingValueName) - { - throw new IllegalStateException(format("Found a constant enum field that requested value %s, " + - "which is not an available enum option.", rawConstValueName)); - } - constantRustTypeName = enumType; - constantRustExpression = enumType + "::" + constValueName; - break; - - case BEGIN_SET: - case BEGIN_COMPOSITE: - default: - throw new IllegalStateException("Unsupported constant presence property " + fieldToken); - } - - appendConstAccessor(writer, name, constantRustTypeName, constantRustExpression); - i += componentTokenCount; - } - - writer.append("}\n"); - } - - private static void appendConstAccessor( - final Appendable writer, - final String name, - final String rustTypeName, - final String rustExpression) throws IOException - { - writer.append("\n").append(INDENT).append("#[inline]\n").append(INDENT); - writer.append(format("pub fn %s() -> %s {\n", formatMethodName(name), rustTypeName)); - indent(writer, 2).append(rustExpression).append("\n"); - indent(writer).append("}\n"); - } -} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java deleted file mode 100644 index 0d7d3f15ed..0000000000 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright 2013-2020 Real Logic Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.generation.rust; - -import org.agrona.Verify; -import uk.co.real_logic.sbe.PrimitiveType; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.*; - -import static java.lang.String.format; -import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; -import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; - -public class RustUtil -{ - static final String INDENT = " "; - private static final Map TYPE_NAME_BY_PRIMITIVE_TYPE_MAP = - new EnumMap<>(PrimitiveType.class); - - static - { - TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.CHAR, "i8"); - TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.INT8, "i8"); - TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.INT16, "i16"); - TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.INT32, "i32"); - TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.INT64, "i64"); - TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.UINT8, "u8"); - TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.UINT16, "u16"); - TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.UINT32, "u32"); - TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.UINT64, "u64"); - TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.FLOAT, "f32"); - TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.DOUBLE, "f64"); - } - - /** - * Map the name of a {@link uk.co.real_logic.sbe.PrimitiveType} to a Rust primitive type name. - * - * @param primitiveType to map. - * @return the name of the Rust primitive that most closely maps. - */ - static String rustTypeName(final PrimitiveType primitiveType) - { - return TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.get(primitiveType); - } - - static String generateRustLiteral(final PrimitiveType type, final String value) - { - Verify.notNull(type, "type"); - Verify.notNull(value, "value"); - final String typeName = rustTypeName(type); - if (typeName == null) - { - throw new IllegalArgumentException("Unknown Rust type name found for primitive " + type.primitiveName()); - } - - switch (type) - { - case CHAR: - case UINT8: - case INT8: - case INT16: - case UINT16: - case INT32: - case INT64: - case UINT32: - case UINT64: - return value + typeName; - - case FLOAT: - case DOUBLE: - return value.endsWith("NaN") ? typeName + "::NAN" : value + typeName; - - default: - throw new IllegalArgumentException("Unsupported literal generation for type: " + type.primitiveName()); - } - } - - static byte eightBitCharacter(final String asciiCharacter) - { - Verify.notNull(asciiCharacter, "asciiCharacter"); - final byte[] bytes = asciiCharacter.getBytes(StandardCharsets.US_ASCII); - if (bytes.length != 1) - { - throw new IllegalArgumentException( - format("String value %s did not fit into a single 8-bit " + "character", asciiCharacter)); - } - - return bytes[0]; - } - - static String formatTypeName(final String value) - { - return toUpperFirstChar(value); - } - - static String formatMethodName(final String value) - { - if (value.isEmpty()) - { - return value; - } - return sanitizeMethodOrProperty(toLowerUnderscoreFromCamel(value)); - } - - // Adapted from Guava, Apache License Version 2.0 - private static String toLowerUnderscoreFromCamel(final String value) - { - if (value.isEmpty()) - { - return value; - } - final String s = toLowerFirstChar(value); - - // include some extra space for separators - final StringBuilder out = new StringBuilder(s.length() + 4); - int i = 0; - int j = -1; - while ((j = indexInUpperAlphaRange(s, ++j)) != -1) - { - final String word = s.substring(i, j).toLowerCase(); - out.append(word); - if (!word.endsWith("_")) - { - out.append("_"); - } - i = j; - } - - return (i == 0) ? s.toLowerCase() : out.append(s.substring(i).toLowerCase()).toString(); - } - - // Adapted from Guava, Apache License Version 2.0 - private static int indexInUpperAlphaRange(final CharSequence sequence, final int start) - { - final int length = sequence.length(); - if (start < 0 || start > length) - { - throw new IndexOutOfBoundsException(); - } - - for (int i = start; i < length; i++) - { - final char c = sequence.charAt(i); - if ('A' <= c && c <= 'Z') - { - return i; - } - } - - return -1; - } - - private static String sanitizeMethodOrProperty(final String name) - { - if (shadowsKeyword(name)) - { - return name + "_"; - } - else - { - return name; - } - } - - private static boolean shadowsKeyword(final String name) - { - return ReservedKeyword.anyMatch(name); - } - - static Appendable indent(final Appendable appendable) throws IOException - { - return indent(appendable, 1); - } - - static Appendable indent(final Appendable appendable, final int level) throws IOException - { - Appendable out = appendable; - for (int i = 0; i < level; i++) - { - out = out.append(INDENT); - } - - return out; - } - - static Appendable indent(final Appendable appendable, final int level, final String f, final Object... args) - throws IOException - { - return indent(appendable, level).append(format(f, args)); - } - - private enum ReservedKeyword - { - Abstract, Alignof, As, Become, Box, Break, Const, Continue, Crate, Do, - Else, Enum, Extern, False, Final, Fn, For, If, Impl, In, Let, Loop, - Macro, Match, Mod, Move, Mut, Offsetof, Override, Priv, Proc, Pub, - Pure, Ref, Return, Self, Sizeof, Static, Struct, Super, Trait, True, - Type, Typeof, Unsafe, Unsized, Use, Virtual, Where, While, Yield; - - private static final Set LOWER_CASE_NAMES = new HashSet<>(); - - static - { - Arrays.stream(ReservedKeyword.values()) - .map(java.lang.Enum::name) - .map(String::toLowerCase) - .forEach(LOWER_CASE_NAMES::add); - } - - private static boolean anyMatch(final String v) - { - return LOWER_CASE_NAMES.contains(v.toLowerCase()); - } - } -} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SplitCompositeTokens.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SplitCompositeTokens.java deleted file mode 100644 index f895d53633..0000000000 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SplitCompositeTokens.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2013-2020 Real Logic Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.generation.rust; - -import uk.co.real_logic.sbe.generation.NamedToken; -import uk.co.real_logic.sbe.ir.Token; - -import java.util.ArrayList; -import java.util.List; - -final class SplitCompositeTokens -{ - private final List constantEncodingTokens; - private final List nonConstantEncodingTokens; - - private SplitCompositeTokens( - final List constantEncodingTokens, final List nonConstantEncodingTokens) - { - this.constantEncodingTokens = constantEncodingTokens; - this.nonConstantEncodingTokens = nonConstantEncodingTokens; - } - - public List constantEncodingTokens() - { - return constantEncodingTokens; - } - - public List nonConstantEncodingTokens() - { - return nonConstantEncodingTokens; - } - - public static SplitCompositeTokens splitInnerTokens(final List tokens) - { - final List constantTokens = new ArrayList<>(); - final List namedNonConstantTokens = new ArrayList<>(); - - for (int i = 1, end = tokens.size() - 1; i < end; ) - { - final Token encodingToken = tokens.get(i); - if (encodingToken.isConstantEncoding()) - { - constantTokens.add(encodingToken); - } - else - { - namedNonConstantTokens.add(new NamedToken(encodingToken.name(), encodingToken)); - } - - i += encodingToken.componentTokenCount(); - } - - return new SplitCompositeTokens(constantTokens, namedNonConstantTokens); - } -} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManagerTest.java deleted file mode 100644 index 68d3149d6d..0000000000 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustFlatFileOutputManagerTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package uk.co.real_logic.sbe.generation.rust; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - -import java.io.File; -import java.io.Writer; -import java.nio.charset.StandardCharsets; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; - -import static org.junit.jupiter.api.Assertions.*; - -public class RustFlatFileOutputManagerTest -{ - @TempDir - File tempDir; - - static final String PACKAGE_NAME = "uk.co.real_logic.test"; - static final String EXAMPLE_CLASS_NAME = "ExampleClassName"; - - @Test - public void shouldCreateFileUponConstruction() throws Exception - { - final String tempDirName = tempDir.getAbsolutePath(); - final RustFlatFileOutputManager om = new RustFlatFileOutputManager(tempDirName, PACKAGE_NAME); - - final String expectedFullyQualifiedFilename = getExpectedFullFileName(tempDirName); - final Path path = FileSystems.getDefault().getPath(expectedFullyQualifiedFilename); - assertTrue(Files.exists(path)); - - final String initialContents = new String(Files.readAllBytes(path), StandardCharsets.UTF_8); - assertTrue(initialContents.contains("Generated code")); - - final String arbitraryInput = "\narbitrary\n"; - assertFalse(initialContents.contains(arbitraryInput)); - - try (Writer out = om.createOutput(EXAMPLE_CLASS_NAME)) - { - out.write(arbitraryInput); - } - - final String postOutputContents = new String(Files.readAllBytes(path), StandardCharsets.UTF_8); - assertTrue(postOutputContents.contains("Generated code")); - assertTrue(postOutputContents.contains(arbitraryInput)); - } - - @Test - public void nullDirectoryParamThrowsNPE() - { - assertThrows(NullPointerException.class, () -> new RustFlatFileOutputManager(null, PACKAGE_NAME)); - } - - @Test - public void nullPackageParamThrowsNpe() - { - assertThrows(NullPointerException.class, - () -> new RustFlatFileOutputManager(tempDir.getAbsolutePath(), null)); - } - - private static String getExpectedFullFileName(final String tempDirName) - { - return (tempDirName.endsWith("" + File.separatorChar) ? tempDirName : tempDirName + File.separatorChar) + - PACKAGE_NAME.replace('.', '_') + ".rs"; - } -} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java deleted file mode 100644 index 9d3974d238..0000000000 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorTest.java +++ /dev/null @@ -1,406 +0,0 @@ -package uk.co.real_logic.sbe.generation.rust; - -import org.junit.jupiter.api.Assumptions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; -import uk.co.real_logic.sbe.TestUtil; -import uk.co.real_logic.sbe.ir.Ir; -import uk.co.real_logic.sbe.xml.IrGenerator; -import uk.co.real_logic.sbe.xml.MessageSchema; -import uk.co.real_logic.sbe.xml.ParserOptions; - -import java.io.*; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Optional; -import java.util.concurrent.TimeUnit; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static uk.co.real_logic.sbe.generation.rust.RustTest.minimalDummyIr; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; - -public class RustGeneratorTest -{ - private static final String BROAD_USE_CASES_SCHEMA = "code-generation-schema"; - private static final String BASIC_TYPES_SCHEMA = "basic-types-schema"; - private static final String NESTED_GROUP_SCHEMA = "nested-group-schema"; - private SingleStringOutputManager outputManager; - - @TempDir - Path tempDir; - - @BeforeEach - public void setUp() - { - outputManager = new SingleStringOutputManager(); - } - - private static Ir generateIrForResource(final String localResourceName) - { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final String xmlLocalResourceName = localResourceName.endsWith(".xml") ? - localResourceName : localResourceName + ".xml"; - final MessageSchema schema; - - try - { - schema = parse(TestUtil.getLocalResource(xmlLocalResourceName), options); - } - catch (final Exception e) - { - throw new IllegalStateException(e); - } - - final IrGenerator irg = new IrGenerator(); - - return irg.generate(schema); - } - - @Test - public void nullOutputManagerTossesNpe() - { - assertThrows(NullPointerException.class, () -> new RustGenerator(minimalDummyIr(), null)); - } - - @Test - public void nullIrTossesNpe() - { - assertThrows(NullPointerException.class, () -> new RustGenerator(null, outputManager)); - } - - @Test - public void generateSharedImports() throws IOException - { - RustGenerator.generateSharedImports(outputManager); - assertContainsSharedImports(outputManager.toString()); - } - - private static void assertContainsSharedImports(final String generatedRust) - { - assertTrue(generatedRust.contains("Imports core rather than std")); - assertTrue(generatedRust.contains("extern crate core;")); - } - - @Test - public void generateBasicEnum() throws IOException - { - RustGenerator.generateSharedImports(outputManager); - assertContainsSharedImports(outputManager.toString()); - } - - private static String fullGenerateForResource( - final SingleStringOutputManager outputManager, final String localResourceName) throws IOException - { - outputManager.clear(); - - final RustGenerator rustGenerator = new RustGenerator(generateIrForResource(localResourceName), outputManager); - rustGenerator.generate(); - return outputManager.toString(); - } - - @Test - public void fullGenerateBasicTypes() throws IOException - { - final String generatedRust = fullGenerateForResource(outputManager, BASIC_TYPES_SCHEMA); - assertContainsSharedImports(generatedRust); - assertContainsNumericEnum(generatedRust); - } - - private void assertContainsNumericEnum(final String generatedRust) - { - final String expectedDeclaration = - "#[derive(Clone,Copy,Debug,PartialEq,Eq,PartialOrd,Ord,Hash)]\n" + - "#[repr(u8)]\n" + - "pub enum ENUM {\n" + - " Value1 = 1u8,\n" + - " Value10 = 10u8,\n" + - " NullVal = 255u8,\n" + - "}\n"; - assertTrue(generatedRust.contains(expectedDeclaration)); - } - - @Test - public void fullGenerateBroadUseCase() throws IOException, InterruptedException - { - final String generatedRust = fullGenerateForResource(outputManager, "example-schema"); - assertContainsSharedImports(generatedRust); - assertContains(generatedRust, - "pub fn car_fields(mut self) -> CodecResult<(&'d CarFields, CarFuelFiguresHeaderDecoder<'d>)> {\n" + - " let v = self.scratch.read_type::(49)?;\n" + - " Ok((v, CarFuelFiguresHeaderDecoder::wrap(self.scratch)))\n" + - " }"); - - final String expectedBooleanTypeDeclaration = - "#[derive(Clone,Copy,Debug,PartialEq,Eq,PartialOrd,Ord,Hash)]\n" + - "#[repr(u8)]\n" + - "pub enum BooleanType {\n" + - " F = 0u8,\n" + - " T = 1u8,\n" + - " NullVal = 255u8,\n" + - "}\n"; - assertTrue(generatedRust.contains(expectedBooleanTypeDeclaration)); - - final String expectedCharTypeDeclaration = - "#[derive(Clone,Copy,Debug,PartialEq,Eq,PartialOrd,Ord,Hash)]\n" + - "#[repr(i8)]\n" + - "pub enum Model {\n" + - " A = 65i8,\n" + - " B = 66i8,\n" + - " C = 67i8,\n" + - " NullVal = 0i8,\n" + - "}\n"; - assertTrue(generatedRust.contains(expectedCharTypeDeclaration)); - assertRustBuildable(generatedRust, Optional.of("example-schema")); - } - - private File writeCargoFolderWrapper(final String name, final String generatedRust, final File folder) - throws IOException - { - final File src = new File(folder, "src"); - assertTrue(src.mkdirs()); - - final File cargo = new File(folder, "Cargo.toml"); - try (Writer cargoWriter = Files.newBufferedWriter(cargo.toPath())) - { - cargoWriter.append("[package]\n") - .append(String.format("name = \"%s\"\n", name)) - .append("version = \"0.1.0\"\n") - .append("authors = []\n\n") - .append("[dependencies]\n") - .append("[dev-dependencies]\n"); - } - - final File lib = new File(src, "lib.rs"); - try (Writer libWriter = Files.newBufferedWriter(lib.toPath())) - { - libWriter.append(generatedRust); - } - - return folder; - } - - private static final class CargoCheckResult - { - final boolean isSuccess; - final String error; - - private CargoCheckResult(final boolean isSuccess, final String error) - { - this.isSuccess = isSuccess; - this.error = error; - } - } - - private static CargoCheckResult cargoCheckInDirectory(final File folder) throws IOException, InterruptedException - { - final ProcessBuilder builder = new ProcessBuilder("cargo", "check"); - builder.directory(folder); - final Process process = builder.start(); - process.waitFor(30, TimeUnit.SECONDS); - final boolean success = process.exitValue() == 0; - - final StringBuilder errorString = new StringBuilder(); - if (!success) - { - // Include output as a debugging aid when things go wrong - try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) - { - while (true) - { - final String line = errorReader.readLine(); - if (line == null) - { - break; - } - else - { - errorString.append(line); - errorString.append('\n'); - } - } - } - } - - return new CargoCheckResult(success, errorString.toString()); - } - - private static boolean cargoExists() - { - try - { - final ProcessBuilder builder = new ProcessBuilder("cargo", "-V"); - final Process process = builder.start(); - process.waitFor(5, TimeUnit.SECONDS); - return process.exitValue() == 0; - } - catch (final IOException | InterruptedException | IllegalThreadStateException ignore) - { - return false; - } - } - - private void assertRustBuildable(final String generatedRust, final Optional name) - throws IOException, InterruptedException - { - Assumptions.assumeTrue(cargoExists()); - final File parentDir = Files.createTempDirectory(tempDir, "rust-build").toFile(); - final File folder = writeCargoFolderWrapper(name.orElse("test"), generatedRust, parentDir); - final CargoCheckResult result = cargoCheckInDirectory(folder); - assertTrue(result.isSuccess, - () -> String.format("Generated Rust (%s) should be buildable with cargo", name) + result.error); - } - - private void assertSchemaInterpretableAsRust(final String localResourceSchema) - throws IOException, InterruptedException - { - final String rust = fullGenerateForResource(outputManager, localResourceSchema); - assertRustBuildable(rust, Optional.of(localResourceSchema)); - } - - @Test - public void checkValidRustFromAllExampleSchema() throws IOException, InterruptedException - { - final String[] schema = - { - "basic-group-schema", - BASIC_TYPES_SCHEMA, - "basic-variable-length-schema", - "block-length-schema", - BROAD_USE_CASES_SCHEMA, - "composite-elements-schema", - "composite-elements-schema-rc4", - "composite-offsets-schema", - "encoding-types-schema", - "example-schema", - "FixBinary", - "group-with-data-schema", - "group-with-constant-fields", - "issue435", - "message-block-length-test", - NESTED_GROUP_SCHEMA, - "new-order-single-schema", - }; - - for (final String s : schema) - { - assertSchemaInterpretableAsRust(s); - } - } - - @Test - public void messageWithOffsets() throws IOException - { - final String rust = fullGenerateForResource(outputManager, "composite-offsets-schema"); - final String expectedHeader = - "pub struct MessageHeader {\n" + - " pub block_length:u16,\n" + - " template_id_padding_1:[u8;2],\n" + - " pub template_id:u16,\n" + - " schema_id_padding_1:[u8;2],\n" + - " pub schema_id:u16,\n" + - " pub version:u16,\n" + - "}"; - assertContains(rust, expectedHeader); - } - - @Test - public void messageBlockLengthExceedingSumOfFieldLengths() throws IOException - { - final String rust = fullGenerateForResource(outputManager, "message-block-length-test"); - final String expectedEncoderSegment = "let v = self.scratch.writable_overlay::(9+2)?;"; - assertContains(rust, expectedEncoderSegment); - final String expectedDecoderSegment = "let v = self.scratch.read_type::(9)?;\n" + - " self.scratch.skip_bytes(2)?;"; - assertContains(rust, expectedDecoderSegment); - } - - @Test - public void constantEnumFields() throws IOException, InterruptedException - { - final String rust = fullGenerateForResource(outputManager, "constant-enum-fields"); - assertContainsSharedImports(rust); - final String expectedCharTypeDeclaration = - "#[derive(Clone,Copy,Debug,PartialEq,Eq,PartialOrd,Ord,Hash)]\n" + - "#[repr(i8)]\n" + - "pub enum Model {\n" + - " A = 65i8,\n" + - " B = 66i8,\n" + - " C = 67i8,\n" + - " NullVal = 0i8,\n" + - "}\n"; - assertContains(rust, expectedCharTypeDeclaration); - assertContains(rust, "pub struct ConstantEnumsFields {\n}"); - assertContains(rust, "impl ConstantEnumsFields {"); - assertContains(rust, " pub fn c() -> Model {\n" + - " Model::C\n }"); - assertContains(rust, "impl ConstantEnumsFMember {"); - assertContains(rust, " pub fn k() -> Model {\n" + - " Model::C\n }"); - assertContains(rust, - "pub fn constant_enums_fields(mut self) -> " + - "CodecResult<(&'d ConstantEnumsFields, ConstantEnumsFHeaderDecoder<'d>)> {\n" + - " let v = self.scratch.read_type::(0)?;\n" + - " Ok((v, ConstantEnumsFHeaderDecoder::wrap(self.scratch)))\n" + - " }"); - assertRustBuildable(rust, Optional.of("constant-enum-fields")); - } - - @Test - public void constantFieldsCase() throws IOException, InterruptedException - { - final String rust = fullGenerateForResource(outputManager, "group-with-constant-fields"); - assertContainsSharedImports(rust); - final String expectedCharTypeDeclaration = - "#[derive(Clone,Copy,Debug,PartialEq,Eq,PartialOrd,Ord,Hash)]\n" + - "#[repr(i8)]\n" + - "pub enum Model {\n" + - " A = 65i8,\n" + - " B = 66i8,\n" + - " C = 67i8,\n" + - " NullVal = 0i8,\n" + - "}\n"; - assertContains(rust, expectedCharTypeDeclaration); - final String expectedComposite = - "pub struct CompositeWithConst {\n" + - " pub w:u8,\n" + - "}"; - assertContains(rust, expectedComposite); - assertContains(rust, "impl CompositeWithConst {"); - assertContains(rust, " pub fn x() -> u8 {\n" + - " 250u8\n }"); - assertContains(rust, " pub fn y() -> u16 {\n" + - " 9000u16\n }"); - assertContains(rust, "pub struct ConstantsGaloreFields {\n" + - " pub a:u8,\n" + - " pub e:CompositeWithConst,\n}"); - assertContains(rust, "impl ConstantsGaloreFields {"); - assertContains(rust, " pub fn b() -> u16 {\n" + - " 9000u16\n }"); - assertContains(rust, " pub fn c() -> Model {\n" + - " Model::C\n }"); - assertContains(rust, " pub fn d() -> u16 {\n" + - " 9000u16\n }"); - assertContains(rust, "pub struct ConstantsGaloreFMember {\n" + - " pub g:u8,\n" + - " pub h:CompositeWithConst,\n}"); - assertContains(rust, "impl ConstantsGaloreFMember {"); - assertContains(rust, " pub fn i() -> u16 {\n" + - " 9000u16\n }"); - assertContains(rust, " pub fn j() -> u16 {\n" + - " 9000u16\n }"); - assertContains(rust, " pub fn k() -> Model {\n" + - " Model::C\n }"); - assertContains(rust, " pub fn l() -> &'static str {\n" + - " \"Huzzah\"\n }"); - assertRustBuildable(rust, Optional.of("group-with-constant-fields")); - } - - private static void assertContains(final String haystack, final String needle) - { - assertThat(haystack, containsString(needle)); - } -} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustTest.java deleted file mode 100644 index 827ac4c09f..0000000000 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package uk.co.real_logic.sbe.generation.rust; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; -import uk.co.real_logic.sbe.PrimitiveType; -import uk.co.real_logic.sbe.generation.CodeGenerator; -import uk.co.real_logic.sbe.ir.*; - -import java.io.File; -import java.io.IOException; -import java.nio.ByteOrder; -import java.util.Arrays; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; - -public class RustTest -{ - @TempDir - File temporaryFolder; - - @Test - public void nullIRParamShouldTossNPE() - { - assertThrows(NullPointerException.class, () -> new Rust().newInstance(null, temporaryFolder.toString())); - } - - @Test - public void nullOutputDirParamShouldTossNPE() - { - assertThrows(NullPointerException.class, () -> new Rust().newInstance(minimalDummyIr(), null)); - } - - @Test - public void happyPathRustGeneratorThatThrowsNoExceptions() throws IOException - { - final File newFolder = temporaryFolder; - final CodeGenerator codeGenerator = new Rust().newInstance(minimalDummyIr(), newFolder.toString()); - assertNotNull(codeGenerator); - codeGenerator.generate(); - newFolder.setWritable(true, false); - } - - static Ir minimalDummyIr() - { - return new Ir("a", "b", 0, 1, null, "2", ByteOrder.BIG_ENDIAN, - Arrays.asList( - dummyToken(Signal.ENCODING, HeaderStructure.BLOCK_LENGTH), - dummyToken(Signal.ENCODING, HeaderStructure.SCHEMA_ID), - dummyToken(Signal.ENCODING, HeaderStructure.SCHEMA_VERSION), - dummyToken(Signal.ENCODING, HeaderStructure.TEMPLATE_ID) - ) - ); - } - - private static Token dummyToken(final Signal signal, final String name) - { - return new Token( - signal, - name, - name, - name, - 0, - 0, - 0, - 0, - 0, - 1, - new Encoding.Builder().primitiveType(PrimitiveType.INT32).build()); - } -} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java deleted file mode 100644 index 8d671cddb3..0000000000 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package uk.co.real_logic.sbe.generation.rust; - -import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.PrimitiveType; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static uk.co.real_logic.sbe.generation.rust.RustUtil.formatMethodName; -import static uk.co.real_logic.sbe.generation.rust.RustUtil.generateRustLiteral; - -public class RustUtilTest -{ - @Test - public void nullParamToEightBitCharacterThrowsNPE() - { - assertThrows(NullPointerException.class, () -> - RustUtil.eightBitCharacter(null)); - } - - @Test - public void emptyParamToEightBitCharacterThrowsIAE() - { - assertThrows(IllegalArgumentException.class, () -> - RustUtil.eightBitCharacter("")); - } - - @Test - public void tooManyCharactersParamToEightBitCharacterThrowsIAE() - { - assertThrows(IllegalArgumentException.class, () -> - RustUtil.eightBitCharacter("ABC")); - } - - @Test - public void happyPathEightBitCharacter() - { - final byte aByte = RustUtil.eightBitCharacter("a"); - assertEquals('a', (char)aByte); - assertEquals("97", Byte.toString(aByte)); - } - - @Test - public void generateRustLiteralsHappyPaths() - { - assertEquals("65i8", generateRustLiteral(PrimitiveType.CHAR, "65")); - assertEquals("64.1f64", generateRustLiteral(PrimitiveType.DOUBLE, "64.1")); - assertEquals("f64::NAN", generateRustLiteral(PrimitiveType.DOUBLE, "NaN")); - assertEquals("64.1f32", generateRustLiteral(PrimitiveType.FLOAT, "64.1")); - assertEquals("f32::NAN", generateRustLiteral(PrimitiveType.FLOAT, "NaN")); - assertEquals("65i8", generateRustLiteral(PrimitiveType.INT8, "65")); - assertEquals("65i16", generateRustLiteral(PrimitiveType.INT16, "65")); - assertEquals("65i32", generateRustLiteral(PrimitiveType.INT32, "65")); - assertEquals("65i64", generateRustLiteral(PrimitiveType.INT64, "65")); - assertEquals("65u8", generateRustLiteral(PrimitiveType.UINT8, "65")); - assertEquals("65u16", generateRustLiteral(PrimitiveType.UINT16, "65")); - assertEquals("65u32", generateRustLiteral(PrimitiveType.UINT32, "65")); - assertEquals("65u64", generateRustLiteral(PrimitiveType.UINT64, "65")); - } - - @Test - public void generateRustLiteralNullPrimitiveTypeParam() - { - assertThrows(NullPointerException.class, () -> generateRustLiteral(null, "65")); - } - - @Test - public void generateRustLiteralNullValueParam() - { - assertThrows(NullPointerException.class, () -> generateRustLiteral(PrimitiveType.INT8, null)); - } - - @Test - public void methodNameCasing() - { - assertEquals("", formatMethodName("")); - assertEquals("a", formatMethodName("a")); - assertEquals("a", formatMethodName("A")); - assertEquals("car", formatMethodName("Car")); - assertEquals("car", formatMethodName("car")); - assertEquals("decode_car", formatMethodName("DecodeCar")); - assertEquals("decode_car", formatMethodName("decodeCar")); - assertEquals("decode_car", formatMethodName("decode_car")); - assertEquals("decode_car", formatMethodName("Decode_car")); - assertEquals("decode_car", formatMethodName("decode_Car")); - assertEquals("decode_car", formatMethodName("Decode_Car")); - } -} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/SingleStringOutputManager.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/SingleStringOutputManager.java deleted file mode 100644 index afb8415424..0000000000 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/SingleStringOutputManager.java +++ /dev/null @@ -1,32 +0,0 @@ -package uk.co.real_logic.sbe.generation.rust; - -import org.agrona.generation.OutputManager; - -import java.io.StringWriter; -import java.io.Writer; -import java.util.*; -import java.util.stream.Collectors; - -public class SingleStringOutputManager implements OutputManager -{ - private final List> sections = new ArrayList<>(); - - public Writer createOutput(final String name) - { - final StringWriter stringWriter = new StringWriter(); - sections.add(new AbstractMap.SimpleEntry<>(name, stringWriter)); - return stringWriter; - } - - public String toString() - { - return sections.stream() - .map((e) -> String.format("\n/// %s%n%s", e.getKey(), e.getValue().toString())) - .collect(Collectors.joining()); - } - - public void clear() - { - sections.clear(); - } -} From ac6f012adb63c98fdc84156e28349444f623832d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 9 Mar 2020 17:12:23 +0000 Subject: [PATCH 0386/1594] [Java] Increase minor version. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 9cee920373..76c5ba15cf 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.16.4-SNAPSHOT \ No newline at end of file +1.17.0-SNAPSHOT \ No newline at end of file From 1df6b7c04c83432bed94212bc5b74a5b3f126874 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 9 Mar 2020 17:54:27 +0000 Subject: [PATCH 0387/1594] [Cpp] Fix warnings and spellings. --- .../src/main/cpp/SbeCarCodecBench.h | 8 ++--- .../src/main/cpp/SbeMarketDataCodecBench.h | 24 +++++++------- sbe-tool/src/test/cpp/CodeGenTest.cpp | 8 ++--- .../src/test/cpp/CompositeElementsTest.cpp | 2 +- .../test/cpp/CompositeOffsetsCodeGenTest.cpp | 1 - .../src/test/cpp/CompositeOffsetsIrTest.cpp | 9 +++--- sbe-tool/src/test/cpp/GroupWithDataTest.cpp | 8 ++--- .../src/test/cpp/MessageBlockLengthTest.cpp | 9 +++--- sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp | 32 +++++++++---------- 9 files changed, 49 insertions(+), 52 deletions(-) diff --git a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h index c1c9f6d9e9..12c077bccc 100644 --- a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h @@ -133,10 +133,10 @@ class SbeCarCodecBench : public CodecBench tmpChar = car.manufacturer(); tmpChar = car.model(); - (void)tmpInt; - (void)tmpChar; - (void)tmpDouble; - (void)tmpBool; + static_cast(tmpInt); + static_cast(tmpChar); + static_cast(tmpDouble); + static_cast(tmpBool); return car.encodedLength(); } diff --git a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h index 043622b25a..1af630f8c5 100644 --- a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h @@ -74,23 +74,23 @@ class SbeMarketDataCodecBench : public CodecBench marketData_.wrapForDecode((char *)buffer, messageHeader_.encodedLength(), actingBlockLength, actingVersion, bufferLength); - marketData_.transactTime(); - marketData_.eventTimeDelta(); - marketData_.matchEventIndicator(); + static_cast(marketData_.transactTime()); + static_cast(marketData_.eventTimeDelta()); + static_cast(marketData_.matchEventIndicator()); MarketDataIncrementalRefreshTrades::MdIncGrp &mdIncGrp = marketData_.mdIncGrp(); while (mdIncGrp.hasNext()) { mdIncGrp.next(); - mdIncGrp.tradeId(); - mdIncGrp.securityId(); - mdIncGrp.mdEntryPx().mantissa(); - mdIncGrp.mdEntrySize().mantissa(); - mdIncGrp.numberOfOrders(); - mdIncGrp.mdUpdateAction(); - mdIncGrp.rptSeq(); - mdIncGrp.aggressorSide(); - mdIncGrp.mdEntryType(); + static_cast(mdIncGrp.tradeId()); + static_cast(mdIncGrp.securityId()); + static_cast(mdIncGrp.mdEntryPx().mantissa()); + static_cast(mdIncGrp.mdEntrySize().mantissa()); + static_cast(mdIncGrp.numberOfOrders()); + static_cast(mdIncGrp.mdUpdateAction()); + static_cast(mdIncGrp.rptSeq()); + static_cast(mdIncGrp.aggressorSide()); + static_cast(mdIncGrp.mdEntryType()); } return MessageHeader::encodedLength() + marketData_.encodedLength(); diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index 0291625db1..ad8485ce30 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -447,7 +447,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeHeaderPlusCarCorrectly) EXPECT_EQ(std::string(bp + activationCodePosition, ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); } -TEST_F(CodeGenTest, shouldbeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) +TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) { char buffer[BUFFER_LEN]; @@ -591,7 +591,7 @@ struct CallbacksForEach void operator()(Car::FuelFigures& fuelFigures) { countOfFuelFigures++; - fuelFigures.usageDescription(); + static_cast(fuelFigures.usageDescription()); } void operator()(Car::PerformanceFigures& performanceFigures) @@ -608,7 +608,7 @@ struct CallbacksForEach } }; -TEST_F(CodeGenTest, shouldbeAbleUseOnStackCodecsAndGroupForEach) +TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) { char buffer[BUFFER_LEN]; MessageHeader hdr(buffer, sizeof(buffer), 0); @@ -892,4 +892,4 @@ TEST_F(CodeGenTest, shouldPrintFullDecodedFlyweightRegardlessOfReadPosition) expectDisplayString(expectedDisplayString, carDecoder); EXPECT_EQ(carDecoder.encodedLength(), expectedCarSize); -} \ No newline at end of file +} diff --git a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp index 09ccbec8a7..db466d678b 100644 --- a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp @@ -267,7 +267,7 @@ TEST_F(CompositeElementsTest, shouldEncodeAndDecodeMsgCorrectly) EXPECT_EQ(msg.encodedLength(), sz - MessageHeader::encodedLength()); } -TEST_F(CompositeElementsTest, shouldHandleAllEventsCorrectltInOrder) +TEST_F(CompositeElementsTest, shouldHandleAllEventsCorrectlyInOrder) { std::uint64_t sz = encodeHdrAndMsg(); diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp index 59be7c1305..cf193c3a11 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp @@ -155,4 +155,3 @@ TEST_F(CompositeOffsetsCodeGenTest, shouldBeAbleToDecodeHeaderAndMsgCorrectly) EXPECT_EQ(m_msgDecoder.encodedLength(), 40u); } - diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp index 00768328d0..3aabea3243 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp @@ -102,9 +102,7 @@ class CompositeOffsetsIrTest : public testing::Test, public OtfMessageDecoder::B } - void onGroupHeader( - Token& token, - std::uint64_t numInGroup) + void onGroupHeader(Token& token, std::uint64_t numInGroup) { switch (m_eventNumber++) { @@ -138,14 +136,15 @@ TEST_F(CompositeOffsetsIrTest, shouldHandleDecodingOfMessageHeaderCorrectly) EXPECT_EQ(headerDecoder.getSchemaVersion(m_buffer), TestMessage1::sbeSchemaVersion()); } -TEST_F(CompositeOffsetsIrTest, shouldHandleAllEventsCorrectltInOrder) +TEST_F(CompositeOffsetsIrTest, shouldHandleAllEventsCorrectlyInOrder) { ASSERT_EQ(encodeHdrAndMsg(), 52u); ASSERT_GE(m_irDecoder.decode(SCHEMA_FILENAME), 0); std::shared_ptr> headerTokens = m_irDecoder.header(); - std::shared_ptr> messageTokens = m_irDecoder.message(TestMessage1::sbeTemplateId(), TestMessage1::sbeSchemaVersion()); + std::shared_ptr> messageTokens = m_irDecoder.message( + TestMessage1::sbeTemplateId(), TestMessage1::sbeSchemaVersion()); ASSERT_TRUE(headerTokens != nullptr); ASSERT_TRUE(messageTokens!= nullptr); diff --git a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp index 9578a9aa65..ab2c5502fc 100644 --- a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp @@ -248,7 +248,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage1Correctly) EXPECT_EQ(sz, offset); } -TEST_F(GroupWithDataTest, shouldbeAbleToEncodeAndDecodeTestMessage1Correctly) +TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage1Correctly) { char buffer[2048]; std::uint64_t sz = encodeTestMessage1(buffer, 0, sizeof(buffer)); @@ -329,7 +329,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage2Correctly) EXPECT_EQ(sz, offset); } -TEST_F(GroupWithDataTest, shouldbeAbleToEncodeAndDecodeTestMessage2Correctly) +TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage2Correctly) { char buffer[2048]; std::uint64_t sz = encodeTestMessage2(buffer, 0, sizeof(buffer)); @@ -458,7 +458,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage3Correctly) EXPECT_EQ(sz, offset); } -TEST_F(GroupWithDataTest, shouldbeAbleToEncodeAndDecodeTestMessage3Correctly) +TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage3Correctly) { char buffer[2048]; std::uint64_t sz = encodeTestMessage3(buffer, 0, sizeof(buffer)); @@ -576,7 +576,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage4Correctly) EXPECT_EQ(sz, offset); } -TEST_F(GroupWithDataTest, shouldbeAbleToEncodeAndDecodeTestMessage4Correctly) +TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage4Correctly) { char buffer[2048]; std::uint64_t sz = encodeTestMessage4(buffer, 0, sizeof(buffer)); diff --git a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp index 7196b6065b..9c5c576a22 100644 --- a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp +++ b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp @@ -151,7 +151,7 @@ class MessageBlockLengthIrTest : public testing::Test, public OtfMessageDecoder: } }; -TEST_F(MessageBlockLengthIrTest, shouldHandleAllEventsCorrectltInOrder) +TEST_F(MessageBlockLengthIrTest, shouldHandleAllEventsCorrectlyInOrder) { std::uint64_t sz = encodeHdrAndMsg(); const char *bufferPtr = m_buffer; @@ -171,7 +171,8 @@ TEST_F(MessageBlockLengthIrTest, shouldHandleAllEventsCorrectltInOrder) ASSERT_GE(m_irDecoder.decode("message-block-length-test.sbeir"), 0); std::shared_ptr> headerTokens = m_irDecoder.header(); - std::shared_ptr> messageTokens = m_irDecoder.message(MsgName::sbeTemplateId(), MsgName::sbeSchemaVersion()); + std::shared_ptr> messageTokens = m_irDecoder.message( + MsgName::sbeTemplateId(), MsgName::sbeSchemaVersion()); ASSERT_TRUE(headerTokens != nullptr); ASSERT_TRUE(messageTokens!= nullptr); @@ -184,8 +185,8 @@ TEST_F(MessageBlockLengthIrTest, shouldHandleAllEventsCorrectltInOrder) std::uint64_t actingVersion = headerDecoder.getSchemaVersion(m_buffer); std::uint64_t blockLength = headerDecoder.getBlockLength(m_buffer); - const std::size_t result = - OtfMessageDecoder::decode(messageBuffer, length, actingVersion, blockLength, messageTokens, *this); + const std::size_t result = OtfMessageDecoder::decode( + messageBuffer, length, actingVersion, blockLength, messageTokens, *this); EXPECT_EQ(result, static_cast(54 - MessageHeader::encodedLength())); EXPECT_EQ(m_eventNumber, 7); diff --git a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp index 40cb970e6f..1ab88cf654 100644 --- a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp +++ b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp @@ -380,7 +380,8 @@ class Rc3OtfFullIrTest : public testing::Test { EXPECT_EQ(encoding.primitiveType(), PrimitiveType::CHAR); EXPECT_EQ(typeToken.encodedLength(), MANUFACTURER_CODE_LENGTH); - EXPECT_EQ(std::string(buffer, MANUFACTURER_CODE_LENGTH), std::string(MANUFACTURER_CODE, MANUFACTURER_CODE_LENGTH)); + EXPECT_EQ(std::string(buffer, MANUFACTURER_CODE_LENGTH), + std::string(MANUFACTURER_CODE, MANUFACTURER_CODE_LENGTH)); break; } @@ -794,9 +795,7 @@ class Rc3OtfFullIrTest : public testing::Test m_eventNumber++; } - void onGroupHeader( - Token& token, - std::uint64_t numInGroup) + void onGroupHeader(Token& token, std::uint64_t numInGroup) { std::cout << m_eventNumber << ": Group Header " << token.name() << " num " << numInGroup << "\n"; @@ -838,12 +837,10 @@ class Rc3OtfFullIrTest : public testing::Test } - void onBeginGroup( - Token& token, - std::uint64_t groupIndex, - std::uint64_t numInGroup) + void onBeginGroup(Token& token, std::uint64_t groupIndex, std::uint64_t numInGroup) { - std::cout << m_eventNumber << ": Begin Group " << token.name() << " " << groupIndex + 1 << "/" << numInGroup << "\n"; + std::cout << m_eventNumber << ": Begin Group " << token.name() + << " " << groupIndex + 1 << "/" << numInGroup << "\n"; switch (EventNumber(m_eventNumber)) { @@ -942,12 +939,10 @@ class Rc3OtfFullIrTest : public testing::Test m_eventNumber++; } - void onEndGroup( - Token& token, - std::uint64_t groupIndex, - std::uint64_t numInGroup) + void onEndGroup(Token& token, std::uint64_t groupIndex, std::uint64_t numInGroup) { - std::cout << m_eventNumber << ": End Group " << token.name() << " " << groupIndex + 1 << "/" << numInGroup << "\n"; + std::cout << m_eventNumber << ": End Group " << token.name() + << " " << groupIndex + 1 << "/" << numInGroup << "\n"; switch (EventNumber(m_eventNumber)) { @@ -1150,7 +1145,8 @@ TEST_F(Rc3OtfFullIrTest, shouldHandleAllEventsCorrectlyAndInOrder) ASSERT_GE(m_irDecoder.decode(SCHEMA_FILENAME), 0); std::shared_ptr> headerTokens = m_irDecoder.header(); - std::shared_ptr> messageTokens = m_irDecoder.message(Car::sbeTemplateId(), Car::sbeSchemaVersion()); + std::shared_ptr> messageTokens = m_irDecoder.message( + Car::sbeTemplateId(), Car::sbeSchemaVersion()); ASSERT_TRUE(headerTokens != nullptr); ASSERT_TRUE(messageTokens!= nullptr); @@ -1163,7 +1159,8 @@ TEST_F(Rc3OtfFullIrTest, shouldHandleAllEventsCorrectlyAndInOrder) std::uint64_t actingVersion = headerDecoder.getSchemaVersion(m_buffer); std::uint64_t blockLength = headerDecoder.getBlockLength(m_buffer); - const std::size_t result = OtfMessageDecoder::decode(messageBuffer, length, actingVersion, blockLength, messageTokens, *this); + const std::size_t result = OtfMessageDecoder::decode( + messageBuffer, length, actingVersion, blockLength, messageTokens, *this); EXPECT_EQ(result, static_cast(encodedCarAndHdrLength - MessageHeader::encodedLength())); } @@ -1174,7 +1171,8 @@ TEST_P(Rc3OtfFullIrLengthTest, shouldExceptionIfLengthTooShort) ASSERT_GE(m_irDecoder.decode(SCHEMA_FILENAME), 0); std::shared_ptr> headerTokens = m_irDecoder.header(); - std::shared_ptr> messageTokens = m_irDecoder.message(Car::sbeTemplateId(), Car::sbeSchemaVersion()); + std::shared_ptr> messageTokens = m_irDecoder.message( + Car::sbeTemplateId(), Car::sbeSchemaVersion()); ASSERT_TRUE(headerTokens != nullptr); ASSERT_TRUE(messageTokens!= nullptr); From e99de1e5fa1b9eeae822e7adf6e15064b7104f37 Mon Sep 17 00:00:00 2001 From: Egor Seredin Date: Tue, 3 Mar 2020 11:47:29 +0900 Subject: [PATCH 0388/1594] [C++] add function to request block and header length --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 2d8da61aa0..6009a93dd1 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1934,6 +1934,11 @@ private CharSequence generateMessageFlyweightCode(final String className, final " return %2$s;\n" + " }\n\n" + + " SBE_NODISCARD static SBE_CONSTEXPR %1$s sbeBlockAndHeaderLength() SBE_NOEXCEPT\n" + + " {\n" + + " return MessageHeader::encodedLength() + sbeBlockLength();\n" + + " }\n\n" + + " SBE_NODISCARD static SBE_CONSTEXPR %3$s sbeTemplateId() SBE_NOEXCEPT\n" + " {\n" + " return %4$s;\n" + From c69434e97c1deb85eb272ca502b89d37a22dbf51 Mon Sep 17 00:00:00 2001 From: Egor Seredin Date: Wed, 4 Mar 2020 06:03:50 +0000 Subject: [PATCH 0389/1594] [C++] include headers being used --- .../co/real_logic/sbe/generation/cpp/CppGenerator.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 6009a93dd1..3eec6ae6d1 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1049,6 +1049,7 @@ private static CharSequence generateFileHeader( "#endif\n\n" + "#if __cplusplus >= 201703L\n" + + "# include \n" + "# define SBE_NODISCARD [[nodiscard]]\n" + "#else\n" + "# define SBE_NODISCARD\n" + @@ -1056,14 +1057,17 @@ private static CharSequence generateFileHeader( "#if !defined(__STDC_LIMIT_MACROS)\n" + "# define __STDC_LIMIT_MACROS 1\n" + - "#endif\n" + + "#endif\n\n" + + "#include \n" + "#include \n" + + "#include \n" + "#include \n" + - "#include \n\n" + "#include \n" + + "#include \n" + "#include \n" + - "#include \n\n" + + "#include \n" + + "\n" + "#if defined(WIN32) || defined(_WIN32)\n" + "# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)\n" + From 4c899bc9bc1d4b6bfd622f2644a40d7e20c7b48c Mon Sep 17 00:00:00 2001 From: Egor Seredin Date: Wed, 4 Mar 2020 06:04:16 +0000 Subject: [PATCH 0390/1594] [C++] remove already included headers --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 3eec6ae6d1..3d75a9a2c8 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1034,12 +1034,6 @@ private static CharSequence generateFileHeader( "# define SBE_DOUBLE_NAN NAN\n" + "#endif\n\n" + - "#if __cplusplus >= 201103L\n" + - "# include \n" + - "# include \n" + - "# include \n" + - "#endif\n\n" + - "#if __cplusplus >= 201103L\n" + "# define SBE_CONSTEXPR constexpr\n" + "# define SBE_NOEXCEPT noexcept\n" + From 4d75b0b94a643e433c42b9c6d4385a2d1e1e7860 Mon Sep 17 00:00:00 2001 From: Egor Seredin Date: Wed, 4 Mar 2020 06:07:15 +0000 Subject: [PATCH 0391/1594] [C++] add macro for C++14 constexpr --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 3d75a9a2c8..1917078cbf 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1042,6 +1042,12 @@ private static CharSequence generateFileHeader( "# define SBE_NOEXCEPT\n" + "#endif\n\n" + + "#if __cplusplus >= 201402L\n" + + "# define SBE_CONSTEXPR_14 constexpr\n" + + "#else\n" + + "# define SBE_CONSTEXPR_14\n" + + "#endif\n\n" + + "#if __cplusplus >= 201703L\n" + "# include \n" + "# define SBE_NODISCARD [[nodiscard]]\n" + From 7709a7eca48fa8c24f595242cfc9c436224a9a1f Mon Sep 17 00:00:00 2001 From: Egor Seredin Date: Wed, 4 Mar 2020 05:51:03 +0000 Subject: [PATCH 0392/1594] [C++] add computeLength() to compute message length including variable items --- .../sbe/generation/cpp/CppGenerator.java | 262 ++++++++++++++++++ 1 file changed, 262 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 1917078cbf..2357d6777c 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -138,6 +138,7 @@ public void generate() throws IOException generateGroups(sb, groups, BASE_INDENT); generateVarData(sb, className, varData, BASE_INDENT); generateDisplay(sb, msgToken.name(), fields, groups, varData, BASE_INDENT + INDENT); + sb.append(generateMessageLength(fields, groups, varData, BASE_INDENT + INDENT)); sb.append("};\n"); sb.append(CppUtil.closingBraces(ir.namespaces().length)).append("#endif\n"); out.append(sb); @@ -178,6 +179,7 @@ private void generateGroups(final StringBuilder sb, final List tokens, fi generateVarData(sb, formatClassName(groupName), varData, indent + INDENT); sb.append(generateGroupDisplay(groupName, fields, groups, varData, indent + INDENT + INDENT)); + sb.append(generateMessageLength(fields, groups, varData, indent + INDENT + INDENT)); sb.append(indent).append(" };\n"); generateGroupProperty(sb, groupName, groupToken, cppTypeForNumInGroup, indent); @@ -1067,6 +1069,7 @@ private static CharSequence generateFileHeader( "#include \n" + "#include \n" + "#include \n" + + "#include \n" + "\n" + "#if defined(WIN32) || defined(_WIN32)\n" + @@ -2765,4 +2768,263 @@ private CharSequence generateEnumDisplay(final List tokens, final Token e return sb; } + + private Object[] generateMessageLengthArgs( + final List fields, + final List groups, + final List varData, + final String indent, + final boolean withName) + { + final StringBuilder sb = new StringBuilder(); + int count = 0; + + for (int i = 0, size = groups.size(); i < size; i++) + { + final Token groupToken = groups.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + final int endSignal = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); + + if (count > 0) + { + sb.append(",\n" + indent); + } + + final List thisGroup = groups.subList(i, endSignal + 1); + + if (isMessageConstLength(thisGroup)) + { + sb.append("std::size_t"); + if (withName) + { + sb.append(" " + groupToken.name() + "Length = 0"); + } + } + else + { + sb.append("const std::vector>&"); + + if (withName) + { + sb.append(" " + groupToken.name() + "ItemLengths = {}"); + } + } + + count += 1; + + i = endSignal; + } + + for (int i = 0, size = varData.size(); i < size;) + { + final Token varDataToken = varData.get(i); + if (varDataToken.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); + } + + if (count > 0) + { + sb.append(",\n" + indent); + } + + sb.append("std::size_t"); + if (withName) + { + sb.append(" " + varDataToken.name() + "Length = 0"); + } + + count += 1; + + i += varDataToken.componentTokenCount(); + } + + CharSequence result = sb; + if (count > 1) + { + result = "\n" + indent + result; + } + + return new Object[]{result, count}; + } + + private Object[] generateMessageLengthArgs( + final List tokens, + final String indent, + final boolean withName) + { + int i = 0; + + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + ++i; + final int groupHeaderTokenCount = tokens.get(i).componentTokenCount(); + i += groupHeaderTokenCount; + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + + return generateMessageLengthArgs(fields, groups, varData, indent, withName); + } + + private boolean isMessageConstLength(final List tokens) + { + final Integer count = (Integer)generateMessageLengthArgs(tokens, "", false)[1]; + + return (count == 0); + } + + private CharSequence generateMessageLengthCallPre17Helper(final List tokens) + { + final StringBuilder sb = new StringBuilder(); + + final Integer count = (Integer)generateMessageLengthArgs(tokens, "", false)[1]; + + for (int i = 0; i < count; i++) + { + if (i > 0) + { + sb.append(", "); + } + new Formatter(sb).format("std::get<%1$d>(e)", i); + } + + return sb; + } + + private CharSequence generateMessageLength( + final List fields, + final List groups, + final List varData, + final String indent) + { + final StringBuilder sbEncode = new StringBuilder(); + + for (int i = 0, size = groups.size(); i < size; i++) + { + final Token groupToken = groups.get(i); + + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + final int endSignal = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); + final List thisGroup = groups.subList(i, endSignal + 1); + + final Token numInGroupToken = Generators.findFirst("numInGroup", groups, i); + final long minCount = numInGroupToken.encoding().applicableMinValue().longValue(); + final long maxCount = numInGroupToken.encoding().applicableMaxValue().longValue(); + + final String countName = groupToken.name() + + (isMessageConstLength(thisGroup) ? "Length" : "ItemLengths.size()"); + + final String minCheck = minCount > 0 ? countName + " < " + minCount + " || " : ""; + final String maxCheck = countName + " > " + maxCount; + + new Formatter(sbEncode).format("\n" + + indent + " length += %1$s::sbeHeaderSize();\n", + formatClassName(groupToken.name())); + + if (isMessageConstLength(thisGroup)) + { + new Formatter(sbEncode).format( + indent + " if (%3$s%4$s)\n" + + indent + " {\n" + + indent + " throw std::runtime_error(\"%5$s outside of allowed range [E110]\");\n" + + indent + " }\n" + + indent + " length += %1$sLength * %2$s::sbeBlockLength();\n", + groupToken.name(), + formatClassName(groupToken.name()), + minCheck, + maxCheck, + countName); + } + else + { + new Formatter(sbEncode).format( + indent + " if (%3$s%4$s)\n" + + indent + " {\n" + + indent + " throw std::runtime_error(\"%5$s outside of allowed range [E110]\");\n" + + indent + " }\n" + + indent + " for (const auto& e: %1$sItemLengths)\n" + + indent + " {\n" + + indent + " #if __cpluplus >= 201703L\n" + + indent + " length += std::apply(%2$s::computeLength, e);\n" + + indent + " #else\n" + + indent + " length += %2$s::computeLength(%6$s);\n" + + indent + " #endif\n" + + indent + " }\n", + groupToken.name(), + formatClassName(groupToken.name()), + minCheck, + maxCheck, + countName, + generateMessageLengthCallPre17Helper(thisGroup)); + } + + i = endSignal; + } + + for (int i = 0, size = varData.size(); i < size;) + { + final Token varDataToken = varData.get(i); + + if (varDataToken.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); + } + + final Token lengthToken = Generators.findFirst("length", varData, i); + + new Formatter(sbEncode).format("\n" + + indent + " length += %1$sHeaderLength();\n" + + indent + " if (%1$sLength > %2$d)\n" + + indent + " {\n" + + indent + " throw std::runtime_error(\"%1$sLength too long for length type [E109]\");\n" + + indent + " }\n" + + indent + " length += %1$sLength;\n", + varDataToken.name(), + lengthToken.encoding().applicableMaxValue().longValue()); + + i += varDataToken.componentTokenCount(); + } + + final StringBuilder sb = new StringBuilder(); + + new Formatter(sb).format("\n" + + indent + "SBE_NODISCARD static SBE_CONSTEXPR_14 size_t computeLength(%1$s)\n" + + indent + "{\n" + + "#if defined(__GNUG__) && !defined(__clang__)\n" + + "#pragma GCC diagnostic push\n" + + "#pragma GCC diagnostic ignored \"-Wtype-limits\"\n" + + "#endif\n" + + indent + " size_t length = sbeBlockLength();\n\n" + + "%2$s" + + indent + " return length;\n" + + "#if defined(__GNUG__) && !defined(__clang__)\n" + + "#pragma GCC diagnostic pop\n" + + "#endif\n" + + indent + "}\n", + generateMessageLengthArgs(fields, groups, varData, indent + INDENT, true)[0], + sbEncode.toString()); + + return sb; + } } From a7e800a7ceb77ef88ff3f281dc4b66eb0de07aa8 Mon Sep 17 00:00:00 2001 From: Egor Seredin Date: Thu, 5 Mar 2020 13:16:44 +0900 Subject: [PATCH 0393/1594] [C++] add isConstLength() to check if message contains variable-length items --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 2357d6777c..aefc8c073a 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -3009,6 +3009,11 @@ private CharSequence generateMessageLength( final StringBuilder sb = new StringBuilder(); new Formatter(sb).format("\n" + + indent + "SBE_NODISCARD static SBE_CONSTEXPR bool isConstLength() SBE_NOEXCEPT\n" + + indent + "{\n" + + indent + " return " + ((groups.isEmpty() && varData.isEmpty()) ? "true" : "false") + ";\n" + + indent + "}\n\n" + + indent + "SBE_NODISCARD static SBE_CONSTEXPR_14 size_t computeLength(%1$s)\n" + indent + "{\n" + "#if defined(__GNUG__) && !defined(__clang__)\n" + From 5fef4797f37899fecf4446e5d915650de118f4b8 Mon Sep 17 00:00:00 2001 From: Egor Seredin Date: Thu, 5 Mar 2020 15:08:06 +0900 Subject: [PATCH 0394/1594] [C++] add skip() to walkthrough whole message --- .../sbe/generation/cpp/CppGenerator.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index aefc8c073a..1802b8430d 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2915,6 +2915,7 @@ private CharSequence generateMessageLength( final String indent) { final StringBuilder sbEncode = new StringBuilder(); + final StringBuilder sbSkip = new StringBuilder(); for (int i = 0, size = groups.size(); i < size; i++) { @@ -2979,6 +2980,15 @@ private CharSequence generateMessageLength( generateMessageLengthCallPre17Helper(thisGroup)); } + new Formatter(sbSkip).format( + indent + " %2$s().forEach([](%1$s e)" + + indent + " {\n" + + indent + " e.skip();\n" + + indent + " });\n", + formatClassName(groupToken.name()), + formatPropertyName(groupToken.name()), + groupToken.name()); + i = endSignal; } @@ -2991,6 +3001,7 @@ private CharSequence generateMessageLength( throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); } + final String propertyName = toUpperFirstChar(varDataToken.name()); final Token lengthToken = Generators.findFirst("length", varData, i); new Formatter(sbEncode).format("\n" + @@ -3003,12 +3014,21 @@ private CharSequence generateMessageLength( varDataToken.name(), lengthToken.encoding().applicableMaxValue().longValue()); + new Formatter(sbSkip).format( + indent + " skip%1$s();\n", + propertyName); + i += varDataToken.componentTokenCount(); } final StringBuilder sb = new StringBuilder(); new Formatter(sb).format("\n" + + indent + "void skip()\n" + + indent + "{\n" + + "%3$s" + + indent + "}\n\n" + + indent + "SBE_NODISCARD static SBE_CONSTEXPR bool isConstLength() SBE_NOEXCEPT\n" + indent + "{\n" + indent + " return " + ((groups.isEmpty() && varData.isEmpty()) ? "true" : "false") + ";\n" + @@ -3028,7 +3048,8 @@ private CharSequence generateMessageLength( "#endif\n" + indent + "}\n", generateMessageLengthArgs(fields, groups, varData, indent + INDENT, true)[0], - sbEncode.toString()); + sbEncode.toString(), + sbSkip.toString()); return sb; } From 96599e5428fc8ade3583dbbc7d521eabc0b846a5 Mon Sep 17 00:00:00 2001 From: Egor Seredin Date: Thu, 5 Mar 2020 16:49:27 +0900 Subject: [PATCH 0395/1594] [C++] add decodeLength() to determine real message length --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 1802b8430d..cd001272a4 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2030,6 +2030,14 @@ private CharSequence generateMessageFlyweightCode(final String className, final " return sbePosition() - m_offset;\n" + " }\n\n" + + " SBE_NODISCARD std::uint64_t decodeLength() const\n" + + " {\n" + + " %10$s skipper(m_buffer, m_offset,\n" + + " m_bufferLength, sbeBlockLength(), m_actingVersion);\n" + + " skipper.skip();\n" + + " return skipper.encodedLength();\n" + + " }\n\n" + + " SBE_NODISCARD const char * buffer() const SBE_NOEXCEPT\n" + " {\n" + " return m_buffer;\n" + From 0d83eefe195349e74b973ae264e04e42225a0aad Mon Sep 17 00:00:00 2001 From: Egor Seredin Date: Wed, 4 Mar 2020 22:05:06 +0900 Subject: [PATCH 0396/1594] [C++] test message length functions --- .../src/main/cpp/GeneratedStubExample.cpp | 3 ++- sbe-tool/src/test/cpp/CodeGenTest.cpp | 22 +++++++++++++++++++ .../src/test/cpp/CompositeElementsTest.cpp | 2 ++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index b8f1fa2720..e77aa1fdeb 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -314,8 +314,9 @@ int main(int argc, const char* argv[]) std::size_t encodeHdrLength = encodeHdr(hdr, car, buffer, 0, sizeof(buffer)); std::size_t encodeMsgLength = encodeCar(car, buffer, hdr.encodedLength(), sizeof(buffer)); + std::size_t predictedLength = Car::computeLength({11, 14, 13}, {3, 3}, 5, 9, 8); - cout << "Encoded Lengths are " << encodeHdrLength << " + " << encodeMsgLength << endl; + cout << "Encoded Lengths are " << encodeHdrLength << " + " << encodeMsgLength << " (" << predictedLength << ")" << endl; std::size_t decodeHdrLength = decodeHdr(hdr, buffer, 0, sizeof(buffer)); std::size_t decodeMsgLength = decodeCar(car, buffer, hdr.encodedLength(), hdr.blockLength(), hdr.version(), sizeof(buffer)); diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index ad8485ce30..0f6a654e8c 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -426,6 +426,25 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) offset += COLOR_LENGTH; EXPECT_EQ(sz, offset); + + std::uint64_t predictedCarSz = Car::computeLength( + { + FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH, + FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH, + FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH + }, + { + ACCELERATION_COUNT, + ACCELERATION_COUNT + }, + MANUFACTURER_LENGTH, + MODEL_LENGTH, + ACTIVATION_CODE_LENGTH, + COLOR_LENGTH + ); + EXPECT_EQ(sz, predictedCarSz); + EXPECT_EQ(Car::isConstLength(), false); + EXPECT_EQ(Car::PerformanceFigures::Acceleration::isConstLength(), true); } TEST_F(CodeGenTest, shouldBeAbleToEncodeHeaderPlusCarCorrectly) @@ -467,6 +486,8 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) m_carDecoder.wrapForDecode(buffer, m_hdrDecoder.encodedLength(), Car::sbeBlockLength(), Car::sbeSchemaVersion(), hdrSz + carSz); + EXPECT_EQ(m_carDecoder.decodeLength(), expectedCarSize); + EXPECT_EQ(m_carDecoder.serialNumber(), SERIAL_NUMBER); EXPECT_EQ(m_carDecoder.modelYear(), MODEL_YEAR); EXPECT_EQ(m_carDecoder.available(), AVAILABLE); @@ -578,6 +599,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) EXPECT_EQ(std::string(m_carDecoder.color(), COLOR_LENGTH), COLOR); EXPECT_EQ(m_carDecoder.encodedLength(), expectedCarSize); + EXPECT_EQ(m_carDecoder.decodeLength(), expectedCarSize); } struct CallbacksForEach diff --git a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp index db466d678b..e423b453de 100644 --- a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp @@ -210,6 +210,8 @@ TEST_F(CompositeElementsTest, shouldEncodeMsgCorrectly) std::uint64_t offset = 0; ASSERT_EQ(sz, 8u + 22u); + ASSERT_EQ(Msg::isConstLength(), true); + EXPECT_EQ(sz, Msg::sbeBlockAndHeaderLength()); EXPECT_EQ(*((std::uint16_t *)(bufferPtr + offset)), Msg::sbeBlockLength()); offset += sizeof(std::uint16_t); From f023e0ae8d2d23e250fca2ed5917bc6a19a30802 Mon Sep 17 00:00:00 2001 From: Bill Segall Date: Tue, 10 Mar 2020 18:10:05 +1000 Subject: [PATCH 0397/1594] Restore the now fixed SinceDeprecated tests (#764) --- csharp/sbe-tests/SinceDeprecatedTests.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/csharp/sbe-tests/SinceDeprecatedTests.cs b/csharp/sbe-tests/SinceDeprecatedTests.cs index 747fe4a059..ad5f23edbf 100644 --- a/csharp/sbe-tests/SinceDeprecatedTests.cs +++ b/csharp/sbe-tests/SinceDeprecatedTests.cs @@ -64,15 +64,13 @@ public void SinceDeprecatedTest() sinceDeprecated.WrapForDecode(directBuffer, SinceDeprecated.MessageHeader.Size, SinceDeprecated.SinceDeprecated.BlockLength, 2); Assert.AreEqual(sinceDeprecated.V1, 1UL, "Incorrect V1 schemaversion:2"); Assert.AreEqual(sinceDeprecated.V2, 2UL, "Incorrect V2 schemaversion:2"); - // FIXME: broken - // Assert.AreEqual(sinceDeprecated.V3, SinceDeprecated.SinceDeprecated.V3NullValue, "Incorrect V3 schemaversion:2"); + Assert.AreEqual(sinceDeprecated.V3, SinceDeprecated.SinceDeprecated.V3NullValue, "Incorrect V3 schemaversion:2"); // SchemaVersion is 1 sinceDeprecated.WrapForDecode(directBuffer, SinceDeprecated.MessageHeader.Size, SinceDeprecated.SinceDeprecated.BlockLength, 1); Assert.AreEqual(sinceDeprecated.V1, 1UL, "Incorrect V1 schemaversion:1"); - // FIXME: broken - // Assert.AreEqual(sinceDeprecated.V2, SinceDeprecated.SinceDeprecated.V2NullValue, "Incorrect V2 schemaversion:1"); - // Assert.AreEqual(sinceDeprecated.V3, SinceDeprecated.SinceDeprecated.V3NullValue, "Incorrect V3 schemaversion:1"); + Assert.AreEqual(sinceDeprecated.V2, SinceDeprecated.SinceDeprecated.V2NullValue, "Incorrect V2 schemaversion:1"); + Assert.AreEqual(sinceDeprecated.V3, SinceDeprecated.SinceDeprecated.V3NullValue, "Incorrect V3 schemaversion:1"); } } } From 48fefaa4be1e5d91299685f71d72052ecd7ed2fd Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 11 Mar 2020 15:17:42 +0100 Subject: [PATCH 0398/1594] [Java] Use gradle-wrapper.properties file to compute hash when caching wrapper --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b65d072851..503b2d0348 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: uses: actions/cache@v1 with: path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Setup java uses: actions/setup-java@v1 with: @@ -65,7 +65,7 @@ jobs: uses: actions/cache@v1 with: path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Cache NuGet dependencies uses: actions/cache@v1 with: @@ -108,7 +108,7 @@ jobs: uses: actions/cache@v1 with: path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | sudo apt-get install -y g++-${{ matrix.version }} libsparsehash-dev @@ -139,7 +139,7 @@ jobs: uses: actions/cache@v1 with: path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-${{ matrix.version }} main" From 22400745cc18a543f04d83cb65f64078b515d586 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 14 Mar 2020 10:43:58 +0000 Subject: [PATCH 0399/1594] [Java] Upgrade to Mockito 3.3.3. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 46b6068079..738c28822a 100644 --- a/build.gradle +++ b/build.gradle @@ -31,7 +31,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.28' def hamcrestVersion = '2.2' -def mockitoVersion = '3.3.0' +def mockitoVersion = '3.3.3' def junitVersion = '5.6.0' def jmhVersion = '1.23' def agronaVersion = '1.4.0' From 33273a8fbeb61a12ea241f8dabcd8bb7673fbc47 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 19 Mar 2020 12:10:00 +0000 Subject: [PATCH 0400/1594] [Java] Tidy up and reduce warnings after merge of PR #761. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index cd001272a4..ce8af4af20 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2470,7 +2470,7 @@ private CharSequence generateGroupDisplay( { return String.format("\n" + indent + "template\n" + - indent + "friend std::basic_ostream& operator<<(\n" + + indent + "friend std::basic_ostream& operator << (\n" + indent + " std::basic_ostream& builder, %1$s writer)\n" + indent + "{\n" + indent + " builder << '{';\n" + @@ -2693,7 +2693,7 @@ private CharSequence generateChoicesDisplay(final String name, final List new Formatter(sb).format("\n" + indent + "template\n" + - indent + "friend std::basic_ostream& operator<<(\n" + + indent + "friend std::basic_ostream& operator << (\n" + indent + " std::basic_ostream& builder, %1$s writer)\n" + indent + "{\n" + indent + " builder << '[';\n", @@ -2767,7 +2767,7 @@ private CharSequence generateEnumDisplay(final List tokens, final Token e " }\n\n" + " template\n" + - " friend std::basic_ostream& operator<<(\n" + + " friend std::basic_ostream& operator << (\n" + " std::basic_ostream& os, %1$s::Value m)\n" + " {\n" + " return os << %1$s::c_str(m);\n" + @@ -2989,7 +2989,7 @@ private CharSequence generateMessageLength( } new Formatter(sbSkip).format( - indent + " %2$s().forEach([](%1$s e)" + + indent + " %2$s().forEach([](%1$s e)\n" + indent + " {\n" + indent + " e.skip();\n" + indent + " });\n", From d587c6847d12f95285def73c18233915bab78278 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 19 Mar 2020 12:10:44 +0000 Subject: [PATCH 0401/1594] [Java] Tidy up and reduce warnings after merge of PR #761. --- .../sbe/generation/cpp/CppGenerator.java | 192 ++++++++---------- 1 file changed, 83 insertions(+), 109 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index ce8af4af20..ac20820693 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -134,11 +134,11 @@ public void generate() throws IOException collectVarData(messageBody, i, varData); final StringBuilder sb = new StringBuilder(); - generateFields(sb, className, fields, BASE_INDENT, false); + generateFields(sb, className, fields, BASE_INDENT); generateGroups(sb, groups, BASE_INDENT); generateVarData(sb, className, varData, BASE_INDENT); - generateDisplay(sb, msgToken.name(), fields, groups, varData, BASE_INDENT + INDENT); - sb.append(generateMessageLength(fields, groups, varData, BASE_INDENT + INDENT)); + generateDisplay(sb, msgToken.name(), fields, groups, varData); + sb.append(generateMessageLength(groups, varData, BASE_INDENT)); sb.append("};\n"); sb.append(CppUtil.closingBraces(ir.namespaces().length)).append("#endif\n"); out.append(sb); @@ -168,7 +168,7 @@ private void generateGroups(final StringBuilder sb, final List tokens, fi final List fields = new ArrayList<>(); i = collectFields(tokens, i, fields); - generateFields(sb, formatClassName(groupName), fields, indent + INDENT, false); + generateFields(sb, formatClassName(groupName), fields, indent + INDENT); final List groups = new ArrayList<>(); i = collectGroups(tokens, i, groups); @@ -179,7 +179,7 @@ private void generateGroups(final StringBuilder sb, final List tokens, fi generateVarData(sb, formatClassName(groupName), varData, indent + INDENT); sb.append(generateGroupDisplay(groupName, fields, groups, varData, indent + INDENT + INDENT)); - sb.append(generateMessageLength(fields, groups, varData, indent + INDENT + INDENT)); + sb.append(generateMessageLength(groups, varData, indent + INDENT + INDENT)); sb.append(indent).append(" };\n"); generateGroupProperty(sb, groupName, groupToken, cppTypeForNumInGroup, indent); @@ -783,16 +783,14 @@ private void generateComposite(final List tokens) throws IOException compositeName, tokens.subList(1, tokens.size() - 1), BASE_INDENT)); out.append(generateCompositeDisplay( - tokens.get(0).applicableTypeName(), - tokens.subList(1, tokens.size() - 1), - BASE_INDENT + INDENT)); + tokens.get(0).applicableTypeName(), tokens.subList(1, tokens.size() - 1))); out.append("};\n\n"); out.append(CppUtil.closingBraces(ir.namespaces().length)).append("\n#endif\n"); } } - private static CharSequence generateChoiceNotPresentCondition(final int sinceVersion, final String indent) + private static CharSequence generateChoiceNotPresentCondition(final int sinceVersion) { if (0 == sinceVersion) { @@ -800,10 +798,10 @@ private static CharSequence generateChoiceNotPresentCondition(final int sinceVer } return String.format( - indent + " if (m_actingVersion < %1$d)\n" + - indent + " {\n" + - indent + " return false;\n" + - indent + " }\n\n", + " if (m_actingVersion < %1$d)\n" + + " {\n" + + " return false;\n" + + " }\n\n", sinceVersion); } @@ -850,7 +848,7 @@ private CharSequence generateChoices(final String bitsetClassName, final List tokens, - final String indent, - final boolean inComposite) + final String indent) { for (int i = 0, size = tokens.size(); i < size; i++) { @@ -2086,7 +2083,7 @@ private void generateFields( final String propertyName = formatPropertyName(signalToken.name()); generateFieldMetaAttributeMethod(sb, signalToken, indent); - generateFieldCommonMethods(indent, sb, signalToken, encodingToken, propertyName, inComposite); + generateFieldCommonMethods(indent, sb, signalToken, encodingToken, propertyName); switch (encodingToken.signal()) { @@ -2116,19 +2113,15 @@ private void generateFieldCommonMethods( final StringBuilder sb, final Token fieldToken, final Token encodingToken, - final String propertyName, - final boolean inComposite) + final String propertyName) { - if (!inComposite) - { - new Formatter(sb).format("\n" + - indent + " static SBE_CONSTEXPR std::uint16_t %1$sId() SBE_NOEXCEPT\n" + - indent + " {\n" + - indent + " return %2$d;\n" + - indent + " }\n", - propertyName, - fieldToken.id()); - } + new Formatter(sb).format("\n" + + indent + " static SBE_CONSTEXPR std::uint16_t %1$sId() SBE_NOEXCEPT\n" + + indent + " {\n" + + indent + " return %2$d;\n" + + indent + " }\n", + propertyName, + fieldToken.id()); new Formatter(sb).format("\n" + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + @@ -2438,27 +2431,26 @@ private void generateDisplay( final String name, final List fields, final List groups, - final List varData, - final String indent) + final List varData) { new Formatter(sb).format("\n" + - indent + "template\n" + - indent + "friend std::basic_ostream& operator<<(\n" + - indent + " std::basic_ostream& builder, %1$s _writer)\n" + - indent + "{\n" + - indent + " %1$s writer(_writer.m_buffer, _writer.m_offset,\n" + - indent + " _writer.m_bufferLength, _writer.sbeBlockLength(), _writer.m_actingVersion);\n" + - indent + " builder << '{';\n" + - indent + " builder << R\"(\"Name\": \"%1$s\", )\";\n" + - indent + " builder << R\"(\"sbeTemplateId\": )\";\n" + - indent + " builder << writer.sbeTemplateId();\n" + - indent + " builder << \", \";\n\n" + + "template\n" + + "friend std::basic_ostream& operator << (\n" + + " std::basic_ostream& builder, %1$s _writer)\n" + + "{\n" + + " %1$s writer(_writer.m_buffer, _writer.m_offset,\n" + + " _writer.m_bufferLength, _writer.sbeBlockLength(), _writer.m_actingVersion);\n" + + " builder << '{';\n" + + " builder << R\"(\"Name\": \"%1$s\", )\";\n" + + " builder << R\"(\"sbeTemplateId\": )\";\n" + + " builder << writer.sbeTemplateId();\n" + + " builder << \", \";\n\n" + "%2$s" + - indent + " builder << '}';\n\n" + - indent + " return builder;\n" + - indent + "}\n", + " builder << '}';\n\n" + + " return builder;\n" + + "}\n", formatClassName(name), - appendDisplay(fields, groups, varData, indent + INDENT)); + appendDisplay(fields, groups, varData, INDENT)); } private CharSequence generateGroupDisplay( @@ -2482,20 +2474,20 @@ private CharSequence generateGroupDisplay( appendDisplay(fields, groups, varData, indent + INDENT)); } - private CharSequence generateCompositeDisplay(final String name, final List tokens, final String indent) + private CharSequence generateCompositeDisplay(final String name, final List tokens) { return String.format("\n" + - indent + "template\n" + - indent + "friend std::basic_ostream& operator<<(\n" + - indent + " std::basic_ostream& builder, %1$s writer)\n" + - indent + "{\n" + - indent + " builder << '{';\n" + + "template\n" + + "friend std::basic_ostream& operator << (\n" + + " std::basic_ostream& builder, %1$s writer)\n" + + "{\n" + + " builder << '{';\n" + "%2$s" + - indent + " builder << '}';\n\n" + - indent + " return builder;\n" + - indent + "}\n\n", + " builder << '}';\n\n" + + " return builder;\n" + + "}\n\n", formatClassName(name), - appendDisplay(tokens, new ArrayList<>(), new ArrayList<>(), indent + INDENT)); + appendDisplay(tokens, new ArrayList<>(), new ArrayList<>(), INDENT)); } private CharSequence appendDisplay( @@ -2523,8 +2515,7 @@ private CharSequence appendDisplay( if (atLeastOne[0]) { - sb.append( - indent + "builder << \", \";\n"); + sb.append(indent).append("builder << \", \";\n"); } atLeastOne[0] = true; @@ -2560,30 +2551,27 @@ private CharSequence appendDisplay( if (atLeastOne[0]) { - sb.append( - indent + "builder << \", \";\n"); + sb.append(indent).append("builder << \", \";\n"); } atLeastOne[0] = true; final String characterEncoding = varData.get(i + 3).encoding().characterEncoding(); - sb.append(indent + "builder << R\"(\"" + varDataToken.name() + "\": )\";\n"); + sb.append(indent).append("builder << R\"(\"").append(varDataToken.name()).append("\": )\";\n"); if (null == characterEncoding) { final String skipFunction = "writer.skip" + toUpperFirstChar(varDataToken.name()) + "()"; - sb.append( - indent + "builder << '\"' <<\n" + - indent + INDENT + skipFunction + " << \" bytes of raw data\\\"\";\n"); + sb.append(indent).append("builder << '\"' <<\n").append(indent).append(INDENT).append(skipFunction) + .append(" << \" bytes of raw data\\\"\";\n"); } else { final String getAsStringFunction = "writer.get" + toUpperFirstChar(varDataToken.name()) + "AsJsonEscapedString().c_str()"; - sb.append( - indent + "builder << '\"' <<\n" + - indent + INDENT + getAsStringFunction + " << '\"';\n\n"); + sb.append(indent).append("builder << '\"' <<\n").append(indent).append(INDENT) + .append(getAsStringFunction).append(" << '\"';\n\n"); } i += varDataToken.componentTokenCount(); @@ -2606,15 +2594,14 @@ private void writeTokenDisplay( if (atLeastOne[0]) { - sb.append( - indent + "builder << \", \";\n"); + sb.append(indent).append("builder << \", \";\n"); } else { atLeastOne[0] = true; } - sb.append(indent + "builder << R\"(\"" + fieldTokenName + "\": )\";\n"); + sb.append(indent).append("builder << R\"(\"").append(fieldTokenName).append("\": )\";\n"); final String fieldName = "writer." + formatPropertyName(fieldTokenName); switch (typeToken.signal()) @@ -2627,9 +2614,8 @@ private void writeTokenDisplay( final String getAsStringFunction = "writer.get" + toUpperFirstChar(fieldTokenName) + "AsJsonEscapedString().c_str()"; - sb.append( - indent + "builder << '\"' <<\n" + - indent + INDENT + getAsStringFunction + " << '\"';\n"); + sb.append(indent).append("builder << '\"' <<\n").append(indent).append(INDENT) + .append(getAsStringFunction).append(" << '\"';\n"); } else { @@ -2665,18 +2651,18 @@ private void writeTokenDisplay( } else { - sb.append(indent + "builder << +" + fieldName + "();\n"); + sb.append(indent).append("builder << +").append(fieldName).append("();\n"); } } break; case BEGIN_ENUM: - sb.append(indent + "builder << '\"' << " + fieldName + "() << '\"';\n"); + sb.append(indent).append("builder << '\"' << ").append(fieldName).append("() << '\"';\n"); break; case BEGIN_SET: case BEGIN_COMPOSITE: - sb.append(indent + "builder << " + fieldName + "();\n"); + sb.append(indent).append("builder << ").append(fieldName).append("();\n"); break; } @@ -2709,9 +2695,8 @@ private CharSequence generateChoicesDisplay(final String name, final List final Token token = choiceTokens.get(i); final String choiceName = "writer." + formatPropertyName(token.name()); - sb.append( - indent + " if (" + choiceName + "())\n" + - indent + " {\n"); + sb.append(indent + " if (").append(choiceName).append("())\n") + .append(indent).append(" {\n"); if (i > 0) { @@ -2721,16 +2706,14 @@ private CharSequence generateChoicesDisplay(final String name, final List indent + " builder << \",\";\n" + indent + " }\n"); } - sb.append( - indent + " builder << R\"(\"" + formatPropertyName(token.name()) + "\")\";\n"); + sb.append(indent + " builder << R\"(\"").append(formatPropertyName(token.name())).append("\")\";\n"); if (i < (size - 1)) { sb.append(indent + " atLeastOne = true;\n"); } - sb.append( - indent + " }\n"); + sb.append(indent + " }\n"); } sb.append( @@ -2778,7 +2761,6 @@ private CharSequence generateEnumDisplay(final List tokens, final Token e } private Object[] generateMessageLengthArgs( - final List fields, final List groups, final List varData, final String indent, @@ -2799,7 +2781,7 @@ private Object[] generateMessageLengthArgs( if (count > 0) { - sb.append(",\n" + indent); + sb.append(",\n").append(indent); } final List thisGroup = groups.subList(i, endSignal + 1); @@ -2809,7 +2791,7 @@ private Object[] generateMessageLengthArgs( sb.append("std::size_t"); if (withName) { - sb.append(" " + groupToken.name() + "Length = 0"); + sb.append(" ").append(groupToken.name()).append("Length = 0"); } } else @@ -2820,7 +2802,7 @@ private Object[] generateMessageLengthArgs( if (withName) { - sb.append(" " + groupToken.name() + "ItemLengths = {}"); + sb.append(" ").append(groupToken.name()).append("ItemLengths = {}"); } } @@ -2839,13 +2821,13 @@ private Object[] generateMessageLengthArgs( if (count > 0) { - sb.append(",\n" + indent); + sb.append(",\n").append(indent); } sb.append("std::size_t"); if (withName) { - sb.append(" " + varDataToken.name() + "Length = 0"); + sb.append(" ").append(varDataToken.name()).append("Length = 0"); } count += 1; @@ -2859,13 +2841,10 @@ private Object[] generateMessageLengthArgs( result = "\n" + indent + result; } - return new Object[]{result, count}; + return new Object[]{ result, count }; } - private Object[] generateMessageLengthArgs( - final List tokens, - final String indent, - final boolean withName) + private Object[] generateMessageLengthArgs(final List tokens, final String indent, final boolean withName) { int i = 0; @@ -2886,23 +2865,22 @@ private Object[] generateMessageLengthArgs( i = collectGroups(tokens, i, groups); final List varData = new ArrayList<>(); - i = collectVarData(tokens, i, varData); + collectVarData(tokens, i, varData); - return generateMessageLengthArgs(fields, groups, varData, indent, withName); + return generateMessageLengthArgs(groups, varData, indent, withName); } private boolean isMessageConstLength(final List tokens) { - final Integer count = (Integer)generateMessageLengthArgs(tokens, "", false)[1]; + final Integer count = (Integer)generateMessageLengthArgs(tokens, BASE_INDENT, false)[1]; - return (count == 0); + return count == 0; } private CharSequence generateMessageLengthCallPre17Helper(final List tokens) { final StringBuilder sb = new StringBuilder(); - - final Integer count = (Integer)generateMessageLengthArgs(tokens, "", false)[1]; + final Integer count = (Integer)generateMessageLengthArgs(tokens, BASE_INDENT, false)[1]; for (int i = 0; i < count; i++) { @@ -2916,11 +2894,7 @@ private CharSequence generateMessageLengthCallPre17Helper(final List toke return sb; } - private CharSequence generateMessageLength( - final List fields, - final List groups, - final List varData, - final String indent) + private CharSequence generateMessageLength(final List groups, final List varData, final String indent) { final StringBuilder sbEncode = new StringBuilder(); final StringBuilder sbSkip = new StringBuilder(); @@ -3055,9 +3029,9 @@ private CharSequence generateMessageLength( "#pragma GCC diagnostic pop\n" + "#endif\n" + indent + "}\n", - generateMessageLengthArgs(fields, groups, varData, indent + INDENT, true)[0], - sbEncode.toString(), - sbSkip.toString()); + generateMessageLengthArgs(groups, varData, indent + INDENT, true)[0], + sbEncode, + sbSkip); return sb; } From df5a19124506008f09eeb52ae68fd7c24807a5d5 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Mar 2020 10:05:52 +0100 Subject: [PATCH 0402/1594] [Java] Upgrade to JUnit 5.6.1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 738c28822a..59c78769db 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.28' def hamcrestVersion = '2.2' def mockitoVersion = '3.3.3' -def junitVersion = '5.6.0' +def junitVersion = '5.6.1' def jmhVersion = '1.23' def agronaVersion = '1.4.0' From 816485517611a3a1b3f14066afd99580e7602a16 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 25 Mar 2020 12:53:39 +0000 Subject: [PATCH 0403/1594] [Java] Reduce redundant casts in generated code. Issue #766. --- .../sbe/generation/java/JavaGenerator.java | 41 +++--- .../sbe/ir/generated/FrameCodecDecoder.java | 36 ++--- .../sbe/ir/generated/TokenCodecDecoder.java | 132 +++++++++--------- 3 files changed, 108 insertions(+), 101 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index bbc4f015ad..721c166a1b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -377,8 +377,8 @@ private void generateGroupDecoderClassHeader( .append(indent).append(" index = 0;\n") .append(indent).append(" final int limit = parentMessage.limit();\n") .append(indent).append(" parentMessage.limit(limit + HEADER_SIZE);\n") - .append(indent).append(" blockLength = (int)").append(blockLengthGet).append(";\n") - .append(indent).append(" count = (int)").append(numInGroupGet).append(";\n") + .append(indent).append(" blockLength = ").append(blockLengthGet).append(";\n") + .append(indent).append(" count = ").append(numInGroupGet).append(";\n") .append(indent).append(" }\n"); sb.append("\n") @@ -774,7 +774,7 @@ private void generateDecoderVarData( .append(indent).append(" {\n") .append(generateArrayFieldNotPresentCondition(token.version(), indent)) .append(indent).append(" final int limit = parentMessage.limit();\n") - .append(indent).append(" return (int)") + .append(indent).append(" return ").append(PrimitiveType.UINT32 == lengthType ? "(int)" : "") .append(generateGet(lengthType, "limit", byteOrderStr)).append(";\n") .append(indent).append(" }\n"); @@ -848,7 +848,7 @@ private void generateDataDecodeMethods( "%2$s" + indent + " final int headerLength = %3$d;\n" + indent + " final int limit = parentMessage.limit();\n" + - indent + " final int dataLength = (int)%4$s;\n" + + indent + " final int dataLength = %4$s%5$s;\n" + indent + " final int dataOffset = limit + headerLength;\n" + indent + " parentMessage.limit(dataOffset + dataLength);\n\n" + indent + " return dataLength;\n" + @@ -856,8 +856,8 @@ private void generateDataDecodeMethods( Generators.toUpperFirstChar(propertyName), generateStringNotPresentConditionForAppendable(token.version(), indent), sizeOfLengthField, - generateGet(lengthType, "limit", byteOrderStr), - byteOrderStr); + PrimitiveType.UINT32 == lengthType ? "(int)" : "", + generateGet(lengthType, "limit", byteOrderStr)); generateVarDataTypedDecoder( sb, @@ -889,7 +889,7 @@ private void generateDataDecodeMethods( "%2$s" + indent + " final int headerLength = %3$d;\n" + indent + " final int limit = parentMessage.limit();\n" + - indent + " final int dataLength = (int)%4$s;\n" + + indent + " final int dataLength = %4$s%5$s;\n" + indent + " parentMessage.limit(limit + headerLength + dataLength);\n\n" + indent + " if (0 == dataLength)\n" + indent + " {\n" + @@ -900,7 +900,7 @@ private void generateDataDecodeMethods( indent + " final String value;\n" + indent + " try\n" + indent + " {\n" + - indent + " value = new String(tmp, \"%5$s\");\n" + + indent + " value = new String(tmp, \"%6$s\");\n" + indent + " }\n" + indent + " catch (final java.io.UnsupportedEncodingException ex)\n" + indent + " {\n" + @@ -911,6 +911,7 @@ private void generateDataDecodeMethods( formatPropertyName(propertyName), generateStringNotPresentCondition(token.version(), indent), sizeOfLengthField, + PrimitiveType.UINT32 == lengthType ? "(int)" : "", generateGet(lengthType, "limit", byteOrderStr), characterEncoding); @@ -922,7 +923,7 @@ private void generateDataDecodeMethods( "%2$s" + indent + " final int headerLength = %3$d;\n" + indent + " final int limit = parentMessage.limit();\n" + - indent + " final int dataLength = (int)%4$s;\n" + + indent + " final int dataLength = %4$s%5$s;\n" + indent + " final int dataOffset = limit + headerLength;\n\n" + indent + " parentMessage.limit(dataOffset + dataLength);\n" + indent + " buffer.getStringWithoutLengthAscii(dataOffset, dataLength, appendable);\n\n" + @@ -931,8 +932,8 @@ private void generateDataDecodeMethods( Generators.toUpperFirstChar(propertyName), generateStringNotPresentConditionForAppendable(token.version(), indent), sizeOfLengthField, - generateGet(lengthType, "limit", byteOrderStr), - byteOrderStr); + PrimitiveType.UINT32 == lengthType ? "(int)" : "", + generateGet(lengthType, "limit", byteOrderStr)); } } } @@ -952,7 +953,7 @@ private void generateVarDataWrapDecoder( "%s" + indent + " final int headerLength = %d;\n" + indent + " final int limit = parentMessage.limit();\n" + - indent + " final int dataLength = (int)%s;\n" + + indent + " final int dataLength = %s%s;\n" + indent + " parentMessage.limit(limit + headerLength + dataLength);\n" + indent + " wrapBuffer.wrap(buffer, limit + headerLength, dataLength);\n" + indent + " }\n", @@ -960,6 +961,7 @@ private void generateVarDataWrapDecoder( readOnlyBuffer, generateVarWrapFieldNotPresentCondition(token.version(), indent), sizeOfLengthField, + PrimitiveType.UINT32 == lengthType ? "(int)" : "", generateGet(lengthType, "limit", byteOrderStr)); } @@ -1022,6 +1024,8 @@ private void generateCharArrayEncodeMethods( final String className, final String indent) { + final PrimitiveType lengthPutType = PrimitiveType.UINT32 == lengthType ? PrimitiveType.INT32 : lengthType; + if (characterEncoding.contains("ASCII")) { new Formatter(sb).format("\n" + @@ -1043,7 +1047,7 @@ private void generateCharArrayEncodeMethods( formatPropertyName(propertyName), maxLengthValue, sizeOfLengthField, - generatePut(lengthType, "limit", "length", byteOrderStr)); + generatePut(lengthPutType, "limit", "length", byteOrderStr)); new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final CharSequence value)\n" + @@ -1069,7 +1073,7 @@ private void generateCharArrayEncodeMethods( formatPropertyName(propertyName), maxLengthValue, sizeOfLengthField, - generatePut(lengthType, "limit", "length", byteOrderStr)); + generatePut(lengthPutType, "limit", "length", byteOrderStr)); } else { @@ -1103,7 +1107,7 @@ private void generateCharArrayEncodeMethods( characterEncoding, maxLengthValue, sizeOfLengthField, - generatePut(lengthType, "limit", "length", byteOrderStr)); + generatePut(lengthPutType, "limit", "length", byteOrderStr)); } } @@ -1123,7 +1127,7 @@ private void generateVarDataTypedDecoder( "%s" + indent + " final int headerLength = %d;\n" + indent + " final int limit = parentMessage.limit();\n" + - indent + " final int dataLength = (int)%s;\n" + + indent + " final int dataLength = %s%s;\n" + indent + " final int bytesCopied = Math.min(length, dataLength);\n" + indent + " parentMessage.limit(limit + headerLength + dataLength);\n" + indent + " buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied);\n\n" + @@ -1133,6 +1137,7 @@ private void generateVarDataTypedDecoder( exchangeType, generateArrayFieldNotPresentCondition(token.version(), indent), sizeOfLengthField, + PrimitiveType.UINT32 == lengthType ? "(int)" : "", generateGet(lengthType, "limit", byteOrderStr)); } @@ -1147,6 +1152,8 @@ private void generateDataTypedEncoder( final String byteOrderStr, final String indent) { + final PrimitiveType lengthPutType = PrimitiveType.UINT32 == lengthType ? PrimitiveType.INT32 : lengthType; + new Formatter(sb).format("\n" + indent + " public %1$s put%2$s(final %3$s src, final int srcOffset, final int length)\n" + indent + " {\n" + @@ -1166,7 +1173,7 @@ private void generateDataTypedEncoder( exchangeType, maxLengthValue, sizeOfLengthField, - generatePut(lengthType, "limit", "length", byteOrderStr)); + generatePut(lengthPutType, "limit", "length", byteOrderStr)); } private void generateBitSet(final List tokens) throws IOException diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 8428eefad0..52b28a6c40 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -284,14 +284,14 @@ public static int packageNameHeaderLength() public int packageNameLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipPackageName() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -302,7 +302,7 @@ public int getPackageName(final MutableDirectBuffer dst, final int dstOffset, fi { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -314,7 +314,7 @@ public int getPackageName(final byte[] dst, final int dstOffset, final int lengt { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -326,7 +326,7 @@ public void wrapPackageName(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -335,7 +335,7 @@ public String packageName() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -392,14 +392,14 @@ public static int namespaceNameHeaderLength() public int namespaceNameLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipNamespaceName() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -410,7 +410,7 @@ public int getNamespaceName(final MutableDirectBuffer dst, final int dstOffset, { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -422,7 +422,7 @@ public int getNamespaceName(final byte[] dst, final int dstOffset, final int len { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -434,7 +434,7 @@ public void wrapNamespaceName(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -443,7 +443,7 @@ public String namespaceName() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -500,14 +500,14 @@ public static int semanticVersionHeaderLength() public int semanticVersionLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipSemanticVersion() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -518,7 +518,7 @@ public int getSemanticVersion(final MutableDirectBuffer dst, final int dstOffset { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -530,7 +530,7 @@ public int getSemanticVersion(final byte[] dst, final int dstOffset, final int l { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -542,7 +542,7 @@ public void wrapSemanticVersion(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -551,7 +551,7 @@ public String semanticVersion() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index ad223fbab1..0920a8a6e2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -581,14 +581,14 @@ public static int nameHeaderLength() public int nameLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipName() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -599,7 +599,7 @@ public int getName(final MutableDirectBuffer dst, final int dstOffset, final int { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -611,7 +611,7 @@ public int getName(final byte[] dst, final int dstOffset, final int length) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -623,7 +623,7 @@ public void wrapName(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -632,7 +632,7 @@ public String name() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -689,14 +689,14 @@ public static int constValueHeaderLength() public int constValueLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipConstValue() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -707,7 +707,7 @@ public int getConstValue(final MutableDirectBuffer dst, final int dstOffset, fin { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -719,7 +719,7 @@ public int getConstValue(final byte[] dst, final int dstOffset, final int length { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -731,7 +731,7 @@ public void wrapConstValue(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -740,7 +740,7 @@ public String constValue() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -797,14 +797,14 @@ public static int minValueHeaderLength() public int minValueLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipMinValue() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -815,7 +815,7 @@ public int getMinValue(final MutableDirectBuffer dst, final int dstOffset, final { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -827,7 +827,7 @@ public int getMinValue(final byte[] dst, final int dstOffset, final int length) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -839,7 +839,7 @@ public void wrapMinValue(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -848,7 +848,7 @@ public String minValue() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -905,14 +905,14 @@ public static int maxValueHeaderLength() public int maxValueLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipMaxValue() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -923,7 +923,7 @@ public int getMaxValue(final MutableDirectBuffer dst, final int dstOffset, final { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -935,7 +935,7 @@ public int getMaxValue(final byte[] dst, final int dstOffset, final int length) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -947,7 +947,7 @@ public void wrapMaxValue(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -956,7 +956,7 @@ public String maxValue() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -1013,14 +1013,14 @@ public static int nullValueHeaderLength() public int nullValueLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipNullValue() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1031,7 +1031,7 @@ public int getNullValue(final MutableDirectBuffer dst, final int dstOffset, fina { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1043,7 +1043,7 @@ public int getNullValue(final byte[] dst, final int dstOffset, final int length) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1055,7 +1055,7 @@ public void wrapNullValue(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -1064,7 +1064,7 @@ public String nullValue() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -1121,14 +1121,14 @@ public static int characterEncodingHeaderLength() public int characterEncodingLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipCharacterEncoding() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1139,7 +1139,7 @@ public int getCharacterEncoding(final MutableDirectBuffer dst, final int dstOffs { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1151,7 +1151,7 @@ public int getCharacterEncoding(final byte[] dst, final int dstOffset, final int { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1163,7 +1163,7 @@ public void wrapCharacterEncoding(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -1172,7 +1172,7 @@ public String characterEncoding() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -1229,14 +1229,14 @@ public static int epochHeaderLength() public int epochLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipEpoch() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1247,7 +1247,7 @@ public int getEpoch(final MutableDirectBuffer dst, final int dstOffset, final in { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1259,7 +1259,7 @@ public int getEpoch(final byte[] dst, final int dstOffset, final int length) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1271,7 +1271,7 @@ public void wrapEpoch(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -1280,7 +1280,7 @@ public String epoch() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -1337,14 +1337,14 @@ public static int timeUnitHeaderLength() public int timeUnitLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipTimeUnit() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1355,7 +1355,7 @@ public int getTimeUnit(final MutableDirectBuffer dst, final int dstOffset, final { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1367,7 +1367,7 @@ public int getTimeUnit(final byte[] dst, final int dstOffset, final int length) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1379,7 +1379,7 @@ public void wrapTimeUnit(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -1388,7 +1388,7 @@ public String timeUnit() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -1445,14 +1445,14 @@ public static int semanticTypeHeaderLength() public int semanticTypeLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipSemanticType() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1463,7 +1463,7 @@ public int getSemanticType(final MutableDirectBuffer dst, final int dstOffset, f { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1475,7 +1475,7 @@ public int getSemanticType(final byte[] dst, final int dstOffset, final int leng { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1487,7 +1487,7 @@ public void wrapSemanticType(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -1496,7 +1496,7 @@ public String semanticType() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -1553,14 +1553,14 @@ public static int descriptionHeaderLength() public int descriptionLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipDescription() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1571,7 +1571,7 @@ public int getDescription(final MutableDirectBuffer dst, final int dstOffset, fi { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1583,7 +1583,7 @@ public int getDescription(final byte[] dst, final int dstOffset, final int lengt { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1595,7 +1595,7 @@ public void wrapDescription(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -1604,7 +1604,7 @@ public String description() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -1661,14 +1661,14 @@ public static int referencedNameHeaderLength() public int referencedNameLength() { final int limit = parentMessage.limit(); - return (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipReferencedName() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1679,7 +1679,7 @@ public int getReferencedName(final MutableDirectBuffer dst, final int dstOffset, { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1691,7 +1691,7 @@ public int getReferencedName(final byte[] dst, final int dstOffset, final int le { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1703,7 +1703,7 @@ public void wrapReferencedName(final DirectBuffer wrapBuffer) { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -1712,7 +1712,7 @@ public String referencedName() { final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (int)(buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) From f491d596185fba680225358d4fa21a38846d2213 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 25 Mar 2020 15:59:24 +0000 Subject: [PATCH 0404/1594] [Java] Allow for block length and numInGroup to be of type UINT32 Issue #766. --- .../co/real_logic/sbe/generation/java/JavaGenerator.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 721c166a1b..523704e9f7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -367,6 +367,9 @@ private void generateGroupDecoderClassHeader( indent, dimensionHeaderLen); + final String blockLenCast = PrimitiveType.UINT32 == blockLengthType ? "(int)" : ""; + final String numInGroupCast = PrimitiveType.UINT32 == numInGroupType ? "(int)" : ""; + sb.append("\n") .append(indent).append(" public void wrap(final ").append(readOnlyBuffer).append(" buffer)\n") .append(indent).append(" {\n") @@ -377,8 +380,8 @@ private void generateGroupDecoderClassHeader( .append(indent).append(" index = 0;\n") .append(indent).append(" final int limit = parentMessage.limit();\n") .append(indent).append(" parentMessage.limit(limit + HEADER_SIZE);\n") - .append(indent).append(" blockLength = ").append(blockLengthGet).append(";\n") - .append(indent).append(" count = ").append(numInGroupGet).append(";\n") + .append(indent).append(" blockLength = ").append(blockLenCast).append(blockLengthGet).append(";\n") + .append(indent).append(" count = ").append(numInGroupCast).append(numInGroupGet).append(";\n") .append(indent).append(" }\n"); sb.append("\n") From a2ebaf9d9fff7774f671a82a27d3b6f270c9867d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 25 Mar 2020 16:34:31 +0000 Subject: [PATCH 0405/1594] [Java] Remove more redundant casts. Issue #766. --- .../real_logic/sbe/generation/java/JavaGenerator.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 523704e9f7..10e6f29d4f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -459,15 +459,17 @@ private void generateGroupEncoderClassHeader( final PrimitiveType blockLengthType = blockLengthToken.encoding().primitiveType(); final String blockLengthOffset = "limit + " + blockLengthToken.offset(); - final String blockLengthValue = "(" + primitiveTypeName(blockLengthToken) + ")" + blockLength; + final String blockLengthValue = Integer.toString(blockLength); final String blockLengthPut = generatePut( blockLengthType, blockLengthOffset, blockLengthValue, byteOrderString(blockLengthToken.encoding())); final PrimitiveType numInGroupType = numInGroupToken.encoding().primitiveType(); + final PrimitiveType newInGroupTypeCast = PrimitiveType.UINT32 == numInGroupType ? + PrimitiveType.INT32 : numInGroupType; final String numInGroupOffset = "limit + " + numInGroupToken.offset(); - final String numInGroupValue = "(" + primitiveTypeName(numInGroupToken) + ")count"; + final String numInGroupValue = "count"; final String numInGroupPut = generatePut( - numInGroupType, numInGroupOffset, numInGroupValue, byteOrderString(numInGroupToken.encoding())); + newInGroupTypeCast, numInGroupOffset, numInGroupValue, byteOrderString(numInGroupToken.encoding())); new Formatter(sb).format("\n" + ind + " public void wrap(final %2$s buffer, final int count)\n" + @@ -510,7 +512,7 @@ private void generateGroupEncoderClassHeader( final String countOffset = "initialLimit + " + numInGroupToken.offset(); final String resetCountPut = generatePut( - numInGroupType, countOffset, numInGroupValue, byteOrderString(numInGroupToken.encoding())); + newInGroupTypeCast, countOffset, numInGroupValue, byteOrderString(numInGroupToken.encoding())); sb.append("\n") .append(ind).append(" public int resetCountToIndex()\n") From 1b080e540b193d64e1cd1e98345800194a757716 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 25 Mar 2020 21:18:21 +0000 Subject: [PATCH 0406/1594] [Java] Remove unnecessary null check on field to silence warning. --- .../uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 4185ebeb60..c4268cf912 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1180,7 +1180,7 @@ private CharSequence generateEnumProperty( final ByteOrder byteOrder = typeToken.encoding().byteOrder(); final String byteOrderStr = generateByteOrder(byteOrder, typeToken.encoding().primitiveType().size()); - if (fieldToken != null && fieldToken.isConstantEncoding()) + if (fieldToken.isConstantEncoding()) { final String constValue = fieldToken.encoding().constValue().toString(); From 73206cb8104a17a63e1d2464d3ae3ec635ee220d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 26 Mar 2020 13:40:41 +0000 Subject: [PATCH 0407/1594] [Java] Upgrade to Gradle 6.3. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 58695 -> 58694 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 59c78769db..b79fbb0240 100644 --- a/build.gradle +++ b/build.gradle @@ -682,6 +682,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.2.2' + gradleVersion = '6.3' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f3d88b1c2faf2fc91d853cd5d4242b5547257070..490fda8577df6c95960ba7077c43220e5bb2c0d9 100644 GIT binary patch delta 6577 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 MViXjGx&OBR0?kH%b^rhX delta 6547 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 Date: Fri, 27 Mar 2020 16:09:33 +0000 Subject: [PATCH 0408/1594] [Java] Warnings cleanup. --- .../generation/golang/GolangGenerator.java | 23 +++---------------- .../sbe/TargetCodeGeneratorTest.java | 2 +- .../csharp/Issue567GroupSizeTest.java | 4 ++-- .../real_logic/sbe/xml/CompositeTypeTest.java | 1 - .../sbe/xml/EncodedDataTypeTest.java | 5 ---- .../co/real_logic/sbe/xml/EnumTypeTest.java | 3 --- .../uk/co/real_logic/sbe/xml/SetTypeTest.java | 4 ---- 7 files changed, 6 insertions(+), 36 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index b9b57db312..fc2b621d72 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -81,9 +81,6 @@ public void generateTypeStubs() throws IOException generateComposite(tokens, ""); break; - case BEGIN_MESSAGE: - break; - default: break; } @@ -2112,24 +2109,10 @@ private void generateFields( generateSinceActingDeprecated(sb, containingTypeName, propertyName, signalToken); generateFieldMetaAttributeMethod(sb, containingTypeName, propertyName, signalToken); - switch (encodingToken.signal()) + if (encodingToken.signal() == Signal.ENCODING) { - case ENCODING: - generateMinMaxNull(sb, containingTypeName, propertyName, encodingToken); - generateCharacterEncoding(sb, containingTypeName, propertyName, encodingToken); - break; - - case BEGIN_ENUM: - break; - - case BEGIN_SET: - break; - - case BEGIN_COMPOSITE: - break; - - default: - break; + generateMinMaxNull(sb, containingTypeName, propertyName, encodingToken); + generateCharacterEncoding(sb, containingTypeName, propertyName, encodingToken); } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java index 93e1b60dac..0a39a3bbde 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java @@ -26,7 +26,7 @@ public class TargetCodeGeneratorTest { @Test - public void shouldThrowOnNoTargetLanguage() throws Exception + public void shouldThrowOnNoTargetLanguage() { assertThrows(IllegalArgumentException.class, () -> SbeTool.generate(mock(Ir.class), ".", "none")); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index acdc2fef32..5216440f7a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -22,8 +22,8 @@ public class Issue567GroupSizeTest public static final String ERR_MSG = "WARNING: at \"numInGroup\" should be UINT8 or UINT16"; + private final PrintStream mockErr = mock(PrintStream.class); private PrintStream err; - private PrintStream mockErr = mock(PrintStream.class); @BeforeEach public void before() @@ -40,7 +40,7 @@ public void after() } @Test - public void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupSize() throws Exception + public void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupSize() { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); assertThrows(IllegalArgumentException.class, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java index aa062d5d86..9f02621a2f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java @@ -161,7 +161,6 @@ public void shouldHandleCompositeHasNullableType() @Test public void shouldThrowExceptionWhenCompositeTypeHasTypeNameDuplicates() - throws Exception { final String testXmlString = "" + diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index 9c9be157a7..dfbf4e59b7 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -128,7 +128,6 @@ public void shouldUseAppropriatePresence() @Test public void shouldThrowExceptionWhenUnknownPresenceSpecified() - throws Exception { final String testXmlString = "" + @@ -140,7 +139,6 @@ public void shouldThrowExceptionWhenUnknownPresenceSpecified() @Test public void shouldThrowExceptionWhenNoPrimitiveTypeSpecified() - throws Exception { final String testXmlString = "" + @@ -152,7 +150,6 @@ public void shouldThrowExceptionWhenNoPrimitiveTypeSpecified() @Test public void shouldThrowExceptionWhenNoNameSpecified() - throws Exception { final String testXmlString = "" + @@ -198,7 +195,6 @@ public void shouldUseAppropriatePrimitiveType() @Test public void shouldThrowExceptionWhenUnknownPrimitiveTypeSpecified() - throws Exception { final String testXmlString = "" + @@ -303,7 +299,6 @@ public void shouldReturnNullWhenSemanticTypeNotSpecified() @Test public void shouldThrowExceptionWhenConstantPresenceButNoDataSpecified() - throws Exception { final String testXmlString = "" + diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index 3cf93c95a4..5c59aea13a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -183,7 +183,6 @@ public void shouldHandleCharEnumEncodingType() @Test public void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() - throws Exception { final String testXmlString = "" + @@ -199,7 +198,6 @@ public void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() @Test public void shouldThrowExceptionWhenDuplicateValueSpecified() - throws Exception { final String testXmlString = "" + @@ -216,7 +214,6 @@ public void shouldThrowExceptionWhenDuplicateValueSpecified() @Test public void shouldThrowExceptionWhenDuplicateNameSpecified() - throws Exception { final String testXmlString = "" + diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index af979473bd..0813b38f5a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -118,7 +118,6 @@ public void shouldHandleSetTypeList() @Test public void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() - throws Exception { final String testXmlString = "" + @@ -134,7 +133,6 @@ public void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() @Test public void shouldThrowExceptionWhenDuplicateValueSpecified() - throws Exception { final String testXmlString = "" + @@ -150,7 +148,6 @@ public void shouldThrowExceptionWhenDuplicateValueSpecified() @Test public void shouldThrowExceptionWhenDuplicateNameSpecified() - throws Exception { final String testXmlString = "" + @@ -166,7 +163,6 @@ public void shouldThrowExceptionWhenDuplicateNameSpecified() @Test public void shouldThrowExceptionWhenValueOutOfBoundsSpecified() - throws Exception { final String testXmlString = "" + From 59ca69dda26b02f6d0a4074f6ec1449c6ffb6818 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 27 Mar 2020 16:00:16 -0700 Subject: [PATCH 0409/1594] [Java]: update agrona dep to 1.4.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b79fbb0240..ca18a38952 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.3.3' def junitVersion = '5.6.1' def jmhVersion = '1.23' -def agronaVersion = '1.4.0' +def agronaVersion = '1.4.1' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From cf6a00121d5cf8d1e9d8f89f175848f1dd756dc1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 28 Mar 2020 09:45:26 +0000 Subject: [PATCH 0410/1594] [Java] Upgrade to Agrona 1.4.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b79fbb0240..ca18a38952 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.3.3' def junitVersion = '5.6.1' def jmhVersion = '1.23' -def agronaVersion = '1.4.0' +def agronaVersion = '1.4.1' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 2e0c5884704ad16dc85a2a61e61c85f5b0d6d126 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 28 Mar 2020 15:49:14 +0000 Subject: [PATCH 0411/1594] [Java] Prepare for 1.17.0 release. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a7fa196245..8fd6f5fe93 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.16.3 +    1.17.0 ``` From 2f6e2296a4b2278a5d41cb6183c4bd4ca1176864 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 28 Mar 2020 11:43:19 -0700 Subject: [PATCH 0412/1594] 1.17.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 76c5ba15cf..73d74673c7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.17.0-SNAPSHOT \ No newline at end of file +1.17.0 \ No newline at end of file From 6098bb88f3cbbc8aa48d565cb9668b384a8e7f2d Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 28 Mar 2020 11:44:43 -0700 Subject: [PATCH 0413/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 73d74673c7..f799225b81 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.17.0 \ No newline at end of file +1.17.1-SNAPSHOT \ No newline at end of file From 4bc8ade69825cd5ba6347f09cdf618a116b42d45 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 30 Mar 2020 13:19:12 +0100 Subject: [PATCH 0414/1594] [C] Improve formatting of C generator output. --- .../sbe/generation/c/CGenerator.java | 218 +++++++++++------- 1 file changed, 137 insertions(+), 81 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 0229500baf..2ece260095 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -243,7 +243,8 @@ private static void generateGroupHeaderFunctions( final String cTypeForNumInGroup = cTypeName(numInGroupToken.encoding().primitiveType()); sb.append(String.format("\n" + - "SBE_ONE_DEF uint64_t *%1$s_sbe_position_ptr(struct %1$s *const codec)\n" + + "SBE_ONE_DEF uint64_t *%1$s_sbe_position_ptr(\n" + + " struct %1$s *const codec)\n" + "{\n" + " return codec->position_ptr;\n" + "}\n\n" + @@ -261,13 +262,13 @@ private static void generateGroupHeaderFunctions( " if (!%2$s_wrap(&dimensions, codec->buffer, *pos, acting_version, buffer_length))\n" + " {\n" + " return NULL;\n" + - " }\n" + + " }\n\n" + " codec->block_length = %2$s_blockLength(&dimensions);\n" + " codec->count = %2$s_numInGroup(&dimensions);\n" + " codec->index = -1;\n" + " codec->acting_version = acting_version;\n" + " codec->position_ptr = pos;\n" + - " *codec->position_ptr = *codec->position_ptr + %3$d;\n" + + " *codec->position_ptr = *codec->position_ptr + %3$d;\n\n" + " return codec;\n" + "}\n", groupName, dimensionsStructName, dimensionHeaderLength)); @@ -302,7 +303,7 @@ private static void generateGroupHeaderFunctions( " if (!%5$s_wrap(&dimensions, codec->buffer, *pos, acting_version, buffer_length))\n" + " {\n" + " return NULL;\n" + - " }\n" + + " }\n\n" + " %5$s_set_blockLength(&dimensions, (%2$s)%3$d);\n" + " %5$s_set_numInGroup(&dimensions, (%4$s)count);\n" + " codec->index = -1;\n" + @@ -310,7 +311,7 @@ private static void generateGroupHeaderFunctions( " codec->block_length = %3$d;\n" + " codec->acting_version = acting_version;\n" + " codec->position_ptr = pos;\n" + - " *codec->position_ptr = *codec->position_ptr + %6$d;\n" + + " *codec->position_ptr = *codec->position_ptr + %6$d;\n\n" + " return codec;\n" + "}\n", groupName, cTypeForBlockLength, blockLength, cTypeForNumInGroup, @@ -329,7 +330,8 @@ private static void generateGroupHeaderFunctions( " return %2$d;\n" + "}\n\n" + - "SBE_ONE_DEF uint64_t %3$s_sbe_position(const struct %3$s *const codec)\n" + + "SBE_ONE_DEF uint64_t %3$s_sbe_position(\n" + + " const struct %3$s *const codec)\n" + "{\n" + "#if defined(__GNUG__) && !defined(__clang__)\n" + "#pragma GCC diagnostic push\n" + @@ -341,23 +343,27 @@ private static void generateGroupHeaderFunctions( "#endif\n" + "}\n\n" + - "SBE_ONE_DEF bool %3$s_set_sbe_position(struct %3$s *const codec, const uint64_t position)\n" + + "SBE_ONE_DEF bool %3$s_set_sbe_position(\n" + + " struct %3$s *const codec,\n" + + " const uint64_t position)\n" + "{\n" + " if (SBE_BOUNDS_CHECK_EXPECT((position > codec->buffer_length), false))\n" + " {\n" + " errno = E100;\n" + " return false;\n" + " }\n" + - " *codec->position_ptr = position;\n" + + " *codec->position_ptr = position;\n\n" + " return true;\n" + "}\n\n" + - "SBE_ONE_DEF uint64_t %3$s_count(const struct %3$s *const codec)\n" + + "SBE_ONE_DEF uint64_t %3$s_count(\n" + + " const struct %3$s *const codec)\n" + "{\n" + " return codec->count;\n" + "}\n\n" + - "SBE_ONE_DEF bool %3$s_has_next(const struct %3$s *const codec)\n" + + "SBE_ONE_DEF bool %3$s_has_next(\n" + + " const struct %3$s *const codec)\n" + "{\n" + "#if defined(__GNUG__) && !defined(__clang__)\n" + "#pragma GCC diagnostic push\n" + @@ -369,7 +375,8 @@ private static void generateGroupHeaderFunctions( "#endif\n" + "}\n\n" + - "SBE_ONE_DEF struct %3$s *%3$s_next(struct %3$s *const codec)\n" + + "SBE_ONE_DEF struct %3$s *%3$s_next(\n" + + " struct %3$s *const codec)\n" + "{\n" + " codec->offset = *codec->position_ptr;\n" + "#if defined(__GNUG__) && !defined(__clang__)\n" + @@ -403,7 +410,7 @@ private static void generateGroupHeaderFunctions( " return NULL;\n" + " }\n" + " func(codec, context);\n" + - " }\n" + + " }\n\n" + " return codec;\n" + "}\n", dimensionHeaderLength, blockLength, groupName)); @@ -425,7 +432,8 @@ private static CharSequence generateGroupPropertyFunctions( sb.append(String.format("\n" + "SBE_ONE_DEF struct %2$s *%1$s_get_%3$s(\n" + - " struct %1$s *const codec, struct %2$s *const property)\n" + + " struct %1$s *const codec,\n" + + " struct %2$s *const property)\n" + "{\n" + " return %2$s_wrap_for_decode(\n" + " property,\n" + @@ -440,7 +448,9 @@ private static CharSequence generateGroupPropertyFunctions( sb.append(String.format("\n" + "SBE_ONE_DEF struct %2$s *%2$s_set_count(\n" + - " struct %1$s *const codec, struct %2$s *const property, const %3$s count)\n" + + " struct %1$s *const codec,\n" + + " struct %2$s *const property,\n" + + " const %3$s count)\n" + "{\n" + " return %2$s_wrap_for_encode(\n" + " property,\n" + @@ -460,7 +470,8 @@ private static CharSequence generateGroupPropertyFunctions( " return %3$d;\n" + "}\n\n" + - "SBE_ONE_DEF bool %2$s_in_acting_version(const struct %1$s *const codec)\n" + + "SBE_ONE_DEF bool %2$s_in_acting_version(\n" + + " const struct %1$s *const codec)\n" + "{\n" + "#if defined(__clang__)\n" + "#pragma clang diagnostic push\n" + @@ -507,17 +518,18 @@ private CharSequence generateVarData( lengthOfLengthField, lengthCType, structName); sb.append(String.format("\n" + - "SBE_ONE_DEF const char *%6$s_%1$s(struct %6$s *const codec)\n" + + "SBE_ONE_DEF const char *%6$s_%1$s(\n" + + " struct %6$s *const codec)\n" + "{\n" + "%2$s" + " %4$s length_field_value;\n" + " memcpy(&length_field_value, codec->buffer + %6$s_sbe_position(codec), sizeof(%4$s));\n" + - " const char *field_ptr = (codec->buffer + %6$s_sbe_position(codec) + %3$d);\n" + + " const char *field_ptr = (codec->buffer + %6$s_sbe_position(codec) + %3$d);\n\n" + " if (!%6$s_set_sbe_position(\n" + " codec, %6$s_sbe_position(codec) + %3$d + %5$s(length_field_value)))\n" + " {\n" + " return NULL;\n" + - " }\n" + + " }\n\n" + " return field_ptr;\n" + "}\n", propertyName, @@ -539,17 +551,17 @@ private CharSequence generateVarData( " if (!%6$s_set_sbe_position(codec, length_position + length_of_length_field))\n" + " {\n" + " return 0;\n" + - " }\n" + + " }\n\n" + " %5$s length_field_value;\n" + " memcpy(&length_field_value, codec->buffer + length_position, sizeof(%5$s));\n" + " uint64_t data_length = %4$s(length_field_value);\n" + " uint64_t bytes_to_copy = length < data_length ? length : data_length;\n" + - " uint64_t pos = %6$s_sbe_position(codec);\n" + + " uint64_t pos = %6$s_sbe_position(codec);\n\n" + " if (!%6$s_set_sbe_position(codec, pos + data_length))\n" + " {\n" + " return 0;\n" + - " }\n" + - " memcpy(dst, codec->buffer + pos, bytes_to_copy);\n" + + " }\n\n" + + " memcpy(dst, codec->buffer + pos, bytes_to_copy);\n\n" + " return bytes_to_copy;\n" + "}\n", propertyName, @@ -560,7 +572,8 @@ private CharSequence generateVarData( structName)); sb.append(String.format("\n" + - "SBE_ONE_DEF struct %6$s_string_view %5$s_get_%1$s_as_string_view(struct %5$s *const codec)\n" + + "SBE_ONE_DEF struct %6$s_string_view %5$s_get_%1$s_as_string_view(\n" + + " struct %5$s *const codec)\n" + "{\n" + "%2$s" + " %4$s length_field_value = %5$s_%1$s_length(codec);\n" + @@ -570,8 +583,8 @@ private CharSequence generateVarData( " {\n" + " struct %6$s_string_view ret = {NULL, 0};\n" + " return ret;\n" + - " }\n" + - " struct %6$s_string_view ret = {field_ptr, length_field_value};\n" + + " }\n\n" + + " struct %6$s_string_view ret = {field_ptr, length_field_value};\n\n" + " return ret;\n" + "}\n", propertyName, @@ -593,14 +606,14 @@ private CharSequence generateVarData( " if (!%5$s_set_sbe_position(codec, length_position + length_of_length_field))\n" + " {\n" + " return NULL;\n" + - " }\n" + + " }\n\n" + " memcpy(codec->buffer + length_position, &length_field_value, sizeof(%3$s));\n" + - " uint64_t pos = %5$s_sbe_position(codec);\n" + + " uint64_t pos = %5$s_sbe_position(codec);\n\n" + " if (!%5$s_set_sbe_position(codec, pos + length))\n" + " {\n" + " return NULL;\n" + - " }\n" + - " memcpy(codec->buffer + pos, src, length);\n" + + " }\n\n" + + " memcpy(codec->buffer + pos, src, length);\n\n" + " return codec;\n" + "}\n", propertyName, @@ -641,7 +654,8 @@ private void generateVarDataDescriptors( " return %2$d;\n" + "}\n\n" + - "SBE_ONE_DEF bool %1$s_in_acting_version(const struct %4$s *const codec)\n" + + "SBE_ONE_DEF bool %1$s_in_acting_version(\n" + + " const struct %4$s *const codec)\n" + "{\n" + "#if defined(__clang__)\n" + "#pragma clang diagnostic push\n" + @@ -671,11 +685,12 @@ private void generateVarDataDescriptors( sizeOfLengthField)); sb.append(String.format("\n" + - "SBE_ONE_DEF %4$s %1$s_length(const struct %5$s *const codec)\n" + + "SBE_ONE_DEF %4$s %1$s_length(\n" + + " const struct %5$s *const codec)\n" + "{\n" + "%2$s" + " %4$s length;\n" + - " memcpy(&length, codec->buffer + %5$s_sbe_position(codec), sizeof(%4$s));\n" + + " memcpy(&length, codec->buffer + %5$s_sbe_position(codec), sizeof(%4$s));\n\n" + " return %3$s(length);\n" + "}\n", fullyQualifiedPropertyName, @@ -697,20 +712,22 @@ private void generateChoiceSet(final CharSequence[] scope, final List tok out.append(generateFixedFlyweightCodeFunctions(bitSetName, bitsetToken.encodedLength())); out.append(String.format("\n" + - "SBE_ONE_DEF struct %1$s *%1$s_clear(struct %1$s *const codec)\n" + + "SBE_ONE_DEF struct %1$s *%1$s_clear(\n" + + " struct %1$s *const codec)\n" + "{\n" + " %2$s zero = 0;\n" + - " memcpy(codec->buffer + codec->offset, &zero, sizeof(%2$s));\n" + + " memcpy(codec->buffer + codec->offset, &zero, sizeof(%2$s));\n\n" + " return codec;\n" + "}\n", bitSetName, cTypeName(bitsetToken.encoding().primitiveType()))); out.append(String.format("\n" + - "SBE_ONE_DEF bool %1$s_is_empty(const struct %1$s *const codec)\n" + + "SBE_ONE_DEF bool %1$s_is_empty(\n" + + " const struct %1$s *const codec)\n" + "{\n" + " %2$s val;\n" + - " memcpy(&val, codec->buffer + codec->offset, sizeof(%2$s));\n" + + " memcpy(&val, codec->buffer + codec->offset, sizeof(%2$s));\n\n" + " return 0 == val;\n" + "}\n", bitSetName, @@ -817,7 +834,8 @@ private CharSequence generateChoices(final String bitsetStructName, final Listbuffer + codec->offset, sizeof(%5$s));\n" + + " memcpy(&val, codec->buffer + codec->offset, sizeof(%5$s));\n\n" + " return (%4$s(val) & ((%5$s)1 << %6$s)) != 0;\n" + "}\n", bitsetStructName, @@ -853,14 +874,15 @@ private CharSequence generateChoices(final String bitsetStructName, final Listbuffer + codec->offset, sizeof(%3$s));\n" + - " bits = %4$s(value ?" + - " (%4$s(bits) | ((%3$s)1 << %5$s)) " + - ": (%4$s(bits) & ~((%3$s)1 << %5$s)));\n" + - " memcpy(codec->buffer + codec->offset, &bits, sizeof(%3$s));\n" + + " bits = %4$s(value ? " + + "(%4$s(bits) | ((%3$s)1 << %5$s)) : (%4$s(bits) & ~((%3$s)1 << %5$s)));\n" + + " memcpy(codec->buffer + codec->offset, &bits, sizeof(%3$s));\n\n" + " return codec;\n" + "}\n", bitsetStructName, @@ -913,7 +935,9 @@ private static CharSequence generateEnumLookupFunction( final StringBuilder sb = new StringBuilder(); sb.append(String.format( - "SBE_ONE_DEF bool %1$s_get(const %2$s value, enum %1$s *const out)\n" + + "SBE_ONE_DEF bool %1$s_get(\n" + + " const %2$s value,\n" + + " enum %1$s *const out)\n" + "{\n" + " switch (value)\n" + " {\n", @@ -1443,7 +1467,8 @@ private CharSequence generateSingleValueProperty( token.encoding().byteOrder()); sb.append(String.format("\n" + - "SBE_ONE_DEF %1$s %5$s_%2$s(const struct %5$s *const codec)\n" + + "SBE_ONE_DEF %1$s %5$s_%2$s(\n" + + " const struct %5$s *const codec)\n" + "{\n" + "%3$s" + "%4$s\n" + @@ -1458,7 +1483,9 @@ private CharSequence generateSingleValueProperty( outermostStruct, primitiveType, Integer.toString(offset), token.encoding().byteOrder()); sb.append(String.format("\n" + - "SBE_ONE_DEF struct %1$s *%1$s_set_%2$s(struct %1$s *const codec, const %3$s value)\n" + + "SBE_ONE_DEF struct %1$s *%1$s_set_%2$s(\n" + + " struct %1$s *const codec,\n" + + " const %3$s value)\n" + "{\n" + "%4$s\n" + " return codec;\n" + @@ -1490,7 +1517,8 @@ private CharSequence generateArrayProperty( token.arrayLength())); sb.append(String.format("\n" + - "SBE_ONE_DEF const char *%1$s_%2$s_buffer(const struct %1$s *const codec)\n" + + "SBE_ONE_DEF const char *%1$s_%2$s_buffer(\n" + + " const struct %1$s *const codec)\n" + "{\n" + "%3$s" + " return codec->buffer + codec->offset + %4$d;\n" + @@ -1603,7 +1631,7 @@ private CharSequence generateArrayProperty( " }\n\n" + "%4$s" + - " memcpy(dst, codec->buffer + codec->offset + %5$d, sizeof(%6$s) * length);\n" + + " memcpy(dst, codec->buffer + codec->offset + %5$d, sizeof(%6$s) * length);\n\n" + " return dst;\n" + "}\n", containingStructName, @@ -1618,7 +1646,7 @@ private CharSequence generateArrayProperty( " struct %1$s *const codec,\n" + " const char *src)\n" + "{\n" + - " memcpy(codec->buffer + codec->offset + %3$d, src, sizeof(%4$s) * %5$d);\n" + + " memcpy(codec->buffer + codec->offset + %3$d, src, sizeof(%4$s) * %5$d);\n\n" + " return codec;\n" + "}\n", containingStructName, @@ -1703,7 +1731,7 @@ private CharSequence generateConstPropertyFunctions( " static uint8_t %2$s_values[] = {%3$s};\n" + " uint64_t bytes_to_copy = length < sizeof(%2$s_values) ? length : sizeof(%2$s_values);\n\n" + - " memcpy(dst, %2$s_values, bytes_to_copy);\n" + + " memcpy(dst, %2$s_values, bytes_to_copy);\n\n" + " return bytes_to_copy;\n" + "}\n", toUpperFirstChar(propertyName), @@ -1748,7 +1776,7 @@ private CharSequence generateFixedFlyweightCodeFunctions(final String structName " codec->buffer = buffer;\n" + " codec->buffer_length = buffer_length;\n" + " codec->offset = offset;\n" + - " codec->acting_version = acting_version;\n" + + " codec->acting_version = acting_version;\n\n" + " return codec;\n" + "}\n\n" + @@ -1767,22 +1795,26 @@ private CharSequence generateFixedFlyweightCodeFunctions(final String structName " return %2$s;\n" + "}\n\n" + - "SBE_ONE_DEF uint64_t %1$s_offset(const struct %1$s *const codec)\n" + + "SBE_ONE_DEF uint64_t %1$s_offset(\n" + + " const struct %1$s *const codec)\n" + "{\n" + " return codec->offset;\n" + "}\n\n" + - "SBE_ONE_DEF const char *%1$s_buffer(const struct %1$s *const codec)\n" + + "SBE_ONE_DEF const char *%1$s_buffer(\n" + + " const struct %1$s *const codec)\n" + "{\n" + " return codec->buffer;\n" + "}\n\n" + - "SBE_ONE_DEF char *%1$s_mut_buffer(struct %1$s *const codec)\n" + + "SBE_ONE_DEF char *%1$s_mut_buffer(\n" + + " struct %1$s *const codec)\n" + "{\n" + " return codec->buffer;\n" + "}\n\n" + - "SBE_ONE_DEF uint64_t %1$s_buffer_length(const struct %1$s *const codec)\n" + + "SBE_ONE_DEF uint64_t %1$s_buffer_length(\n" + + " const struct %1$s *const codec)\n" + "{\n" + " return codec->buffer_length;\n" + "}\n\n" + @@ -1829,23 +1861,27 @@ private CharSequence generateMessageFlyweightFunctions( final String messageHeaderStruct = formatScopedName(scope, "messageHeader"); return String.format("\n" + - "SBE_ONE_DEF uint64_t %10$s_sbe_position(const struct %10$s *const codec)\n" + + "SBE_ONE_DEF uint64_t %10$s_sbe_position(\n" + + " const struct %10$s *const codec)\n" + "{\n" + " return codec->position;\n" + "}\n\n" + - "SBE_ONE_DEF bool %10$s_set_sbe_position(struct %10$s *const codec, const uint64_t position)\n" + + "SBE_ONE_DEF bool %10$s_set_sbe_position(\n" + + " struct %10$s *const codec,\n" + + " const uint64_t position)\n" + "{\n" + " if (SBE_BOUNDS_CHECK_EXPECT((position > codec->buffer_length), false))\n" + " {\n" + " errno = E100;\n" + " return false;\n" + " }\n" + - " codec->position = position;\n" + + " codec->position = position;\n\n" + " return true;\n" + "}\n\n" + - "SBE_ONE_DEF uint64_t *%10$s_sbe_position_ptr(struct %10$s *const codec)\n" + + "SBE_ONE_DEF uint64_t *%10$s_sbe_position_ptr(\n" + + " struct %10$s *const codec)\n" + "{\n" + " return &codec->position;\n" + "}\n\n" + @@ -1865,17 +1901,19 @@ private CharSequence generateMessageFlyweightFunctions( " if (!%10$s_set_sbe_position(codec, offset + acting_block_length))\n" + " {\n" + " return NULL;\n" + - " }\n" + + " }\n\n" + " return codec;\n" + "}\n\n" + - "SBE_ONE_DEF struct %10$s *%10$s_copy(struct %10$s *const codec, const struct %10$s *const other)\n" + + "SBE_ONE_DEF struct %10$s *%10$s_copy(\n" + + " struct %10$s *const codec,\n" + + " const struct %10$s *const other)\n" + "{\n" + " codec->buffer = other->buffer;\n" + " codec->offset = other->offset;\n" + " codec->buffer_length = other->buffer_length;\n" + " codec->acting_version = other->acting_version;\n" + - " codec->position = other->position;\n" + + " codec->position = other->position;\n\n" + " return codec;\n" + "}\n\n" + @@ -1904,7 +1942,8 @@ private CharSequence generateMessageFlyweightFunctions( " return \"%9$s\";\n" + "}\n\n" + - "SBE_ONE_DEF uint64_t %10$s_offset(const struct %10$s *const codec)\n" + + "SBE_ONE_DEF uint64_t %10$s_offset(\n" + + " const struct %10$s *const codec)\n" + "{\n" + " return codec->offset;\n" + "}\n\n" + @@ -1916,7 +1955,8 @@ private CharSequence generateMessageFlyweightFunctions( " const uint64_t buffer_length,\n" + " struct %11$s *const hdr)\n" + "{\n" + - " %11$s_wrap(hdr, buffer + offset, 0, buffer_length, %11$s_sbe_schema_version());\n\n" + + " %11$s_wrap(\n" + + " hdr, buffer + offset, 0, buffer_length, %11$s_sbe_schema_version());\n\n" + " %11$s_set_blockLength(hdr, %10$s_sbe_block_length());\n" + " %11$s_set_templateId(hdr, %10$s_sbe_template_id());\n" + @@ -1929,7 +1969,7 @@ private CharSequence generateMessageFlyweightFunctions( " 0,\n" + " buffer_length - %11$s_encoded_length(),\n" + " %10$s_sbe_block_length(),\n" + - " %10$s_sbe_schema_version());\n" + + " %10$s_sbe_schema_version());\n\n" + " return codec;\n" + "}\n\n" + @@ -1965,27 +2005,32 @@ private CharSequence generateMessageFlyweightFunctions( " acting_version);\n" + "}\n\n" + - "SBE_ONE_DEF uint64_t %10$s_encoded_length(const struct %10$s *const codec)\n" + + "SBE_ONE_DEF uint64_t %10$s_encoded_length(\n" + + " const struct %10$s *const codec)\n" + "{\n" + " return %10$s_sbe_position(codec) - codec->offset;\n" + "}\n\n" + - "SBE_ONE_DEF const char *%10$s_buffer(const struct %10$s *const codec)\n" + + "SBE_ONE_DEF const char *%10$s_buffer(\n" + + " const struct %10$s *const codec)\n" + "{\n" + " return codec->buffer;\n" + "}\n\n" + - "SBE_ONE_DEF char *%10$s_mut_buffer(struct %10$s *const codec)\n" + + "SBE_ONE_DEF char *%10$s_mut_buffer(\n" + + " struct %10$s *const codec)\n" + "{\n" + " return codec->buffer;\n" + "}\n\n" + - "SBE_ONE_DEF uint64_t %10$s_buffer_length(const struct %10$s *const codec)\n" + + "SBE_ONE_DEF uint64_t %10$s_buffer_length(\n" + + " const struct %10$s *const codec)\n" + "{\n" + " return codec->buffer_length;\n" + "}\n\n" + - "SBE_ONE_DEF uint64_t %10$s_acting_version(const struct %10$s *const codec)\n" + + "SBE_ONE_DEF uint64_t %10$s_acting_version(\n" + + " const struct %10$s *const codec)\n" + "{\n" + " return codec->acting_version;\n" + "}\n", @@ -2065,7 +2110,8 @@ private void generateFieldCommonFunctions( " return %2$d;\n" + "}\n\n" + - "SBE_ONE_DEF bool %3$s_%1$s_in_acting_version(const struct %3$s *const codec)\n" + + "SBE_ONE_DEF bool %3$s_%1$s_in_acting_version(\n" + + " const struct %3$s *const codec)\n" + "{\n" + "#if defined(__clang__)\n" + "#pragma clang diagnostic push\n" + @@ -2099,7 +2145,8 @@ private static void generateFieldMetaAttributeFunction( final String semanticType = encoding.semanticType() == null ? "" : encoding.semanticType(); sb.append(String.format("\n" + - "SBE_ONE_DEF const char *%6$s_%s_meta_attribute(const enum %7$s_meta_attribute attribute)\n" + + "SBE_ONE_DEF const char *%6$s_%s_meta_attribute(\n" + + " const enum %7$s_meta_attribute attribute)\n" + "{\n" + " switch (attribute)\n" + " {\n" + @@ -2172,7 +2219,8 @@ private void generateEnumProperty( containingStructName)); sb.append(String.format("\n" + - "SBE_ONE_DEF enum %1$s %5$s_%2$s(const struct %5$s *const codec)\n" + + "SBE_ONE_DEF enum %1$s %5$s_%2$s(\n" + + " const struct %5$s *const codec)\n" + "{\n" + "%3$s" + " return %1$s_%4$s;\n" + @@ -2186,11 +2234,13 @@ private void generateEnumProperty( else { sb.append(String.format("\n" + - "SBE_ONE_DEF bool %7$s_%2$s(const struct %7$s *const codec, enum %1$s *const out)\n" + + "SBE_ONE_DEF bool %7$s_%2$s(\n" + + " const struct %7$s *const codec,\n" + + " enum %1$s *const out)\n" + "{\n" + "%3$s" + " %5$s val;\n" + - " memcpy(&val, codec->buffer + codec->offset + %6$d, sizeof(%5$s));\n" + + " memcpy(&val, codec->buffer + codec->offset + %6$d, sizeof(%5$s));\n\n" + " return %1$s_get(%4$s(val), out);\n" + "}\n", enumName, @@ -2202,10 +2252,12 @@ private void generateEnumProperty( containingStructName)); sb.append(String.format("\n" + - "SBE_ONE_DEF struct %1$s *%1$s_set_%2$s(struct %1$s *const codec, const enum %3$s value)\n" + + "SBE_ONE_DEF struct %1$s *%1$s_set_%2$s(\n" + + " struct %1$s *const codec,\n" + + " const enum %3$s value)\n" + "{\n" + " %4$s val = %6$s(value);\n" + - " memcpy(codec->buffer + codec->offset + %5$d, &val, sizeof(%4$s));\n" + + " memcpy(codec->buffer + codec->offset + %5$d, &val, sizeof(%4$s));\n\n" + " return codec;\n" + "}\n", containingStructName, @@ -2228,7 +2280,9 @@ private static void generateBitsetPropertyFunctions( final int offset = token.offset(); sb.append(String.format("\n" + - "SBE_ONE_DEF struct %1$s *%4$s_%2$s(struct %4$s *const codec, struct %1$s *const bitset)\n" + + "SBE_ONE_DEF struct %1$s *%4$s_%2$s(\n" + + " struct %4$s *const codec,\n" + + " struct %1$s *const bitset)\n" + "{\n" + " return %1$s_wrap(\n" + " bitset,\n" + @@ -2263,7 +2317,9 @@ private static void generateCompositePropertyFunction( final int offset = token.offset(); sb.append(String.format("\n" + - "SBE_ONE_DEF struct %1$s *%4$s_%2$s(struct %4$s *const codec, struct %1$s *const composite)\n" + + "SBE_ONE_DEF struct %1$s *%4$s_%2$s(\n" + + " struct %4$s *const codec,\n" + + " struct %1$s *const composite)\n" + "{\n" + " return %1$s_wrap(\n" + " composite,\n" + From 26a057779a7126f9c02d482ba2f22e26495a3577 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 2 Apr 2020 21:59:50 +0200 Subject: [PATCH 0415/1594] [Java] Fix `isReleaseVersion` --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ca18a38952..1b6dc159fc 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,7 @@ def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() ext { - isReleaseVersion = !version.endsWith('-SNAPSHOT') + isReleaseVersion = !sbeVersion.endsWith('-SNAPSHOT') releasesRepoUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' snapshotsRepoUrl = 'https://oss.sonatype.org/content/repositories/snapshots/' From 8e1349b7dbc65094562f2067f88a799d838c49a9 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 2 Apr 2020 22:06:01 +0200 Subject: [PATCH 0416/1594] [Java] Use `strict` dependency on Agrona, i.e. allow only the exact version of Agrona and nothing else --- build.gradle | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1b6dc159fc..1c8b65f6dc 100644 --- a/build.gradle +++ b/build.gradle @@ -194,7 +194,11 @@ project(':sbe-tool') { apply plugin: 'signing' dependencies { - api "org.agrona:agrona:${agronaVersion}" + api("org.agrona:agrona") { + version { + strictly(agronaVersion) + } + } testImplementation files('build/classes/java/generated') testImplementation "org.hamcrest:hamcrest:${hamcrestVersion}" testImplementation "org.mockito:mockito-junit-jupiter:${mockitoVersion}" From c4587632e54b7e6116f8b3fcc810cfcf98f635d5 Mon Sep 17 00:00:00 2001 From: Egor Seredin Date: Tue, 7 Apr 2020 13:30:26 +0900 Subject: [PATCH 0417/1594] [C++] add link to correct message header type --- .../real_logic/sbe/generation/cpp/CppGenerator.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index ac20820693..858335be61 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1901,6 +1901,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final final String schemaIdType = cppTypeName(ir.headerStructure().schemaIdType()); final String schemaVersionType = cppTypeName(ir.headerStructure().schemaVersionType()); final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); + final String headerType = ir.headerStructure().tokens().get(0).name(); return String.format( "private:\n" + @@ -1933,6 +1934,8 @@ private CharSequence generateMessageFlyweightCode(final String className, final " std::uint64_t uint_value;\n" + " };\n\n" + + " using messageHeader = %12$s;\n\n" + + "%11$s" + " SBE_NODISCARD static SBE_CONSTEXPR %1$s sbeBlockLength() SBE_NOEXCEPT\n" + " {\n" + @@ -1941,7 +1944,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final " SBE_NODISCARD static SBE_CONSTEXPR %1$s sbeBlockAndHeaderLength() SBE_NOEXCEPT\n" + " {\n" + - " return MessageHeader::encodedLength() + sbeBlockLength();\n" + + " return messageHeader::encodedLength() + sbeBlockLength();\n" + " }\n\n" + " SBE_NODISCARD static SBE_CONSTEXPR %3$s sbeTemplateId() SBE_NOEXCEPT\n" + @@ -1977,7 +1980,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final " %10$s &wrapAndApplyHeader(" + "char *buffer, const std::uint64_t offset, const std::uint64_t bufferLength)\n" + " {\n" + - " MessageHeader hdr(buffer, offset, bufferLength, sbeSchemaVersion());\n\n" + + " messageHeader hdr(buffer, offset, bufferLength, sbeSchemaVersion());\n\n" + " hdr\n" + " .blockLength(sbeBlockLength())\n" + @@ -1987,7 +1990,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final " return *this = %10$s(\n" + " buffer,\n" + - " offset + MessageHeader::encodedLength(),\n" + + " offset + messageHeader::encodedLength(),\n" + " bufferLength,\n" + " sbeBlockLength(),\n" + " sbeSchemaVersion());\n" + @@ -2065,7 +2068,8 @@ private CharSequence generateMessageFlyweightCode(final String className, final generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), semanticType, className, - generateConstructorsAndOperators(className)); + generateConstructorsAndOperators(className), + formatClassName(headerType)); } private void generateFields( From 36e982a6d740a9355b4acb9eb1bc3d0a73919a01 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 11 Apr 2020 12:34:56 +0100 Subject: [PATCH 0418/1594] [Java] Upgrade to JUnit 5.6.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1c8b65f6dc..c3407607fa 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.28' def hamcrestVersion = '2.2' def mockitoVersion = '3.3.3' -def junitVersion = '5.6.1' +def junitVersion = '5.6.2' def jmhVersion = '1.23' def agronaVersion = '1.4.1' From 2118769344ab13ed9f13624249d90744787e8039 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 18 Apr 2020 13:22:35 +0100 Subject: [PATCH 0419/1594] [Java] Upgrade to javadoc-links 5.0.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c3407607fa..b808199613 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java-library' id 'idea' - id 'io.freefair.javadoc-links' version '4.1.6' apply false + id 'io.freefair.javadoc-links' version '5.0.0' apply false id 'com.github.johnrengelman.shadow' version '5.2.0' apply false id "com.github.ben-manes.versions" version "0.28.0" } From 1958f9eac9a51532d08d32b6bb9b7f8904fbfed2 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 30 Apr 2020 07:51:16 +0100 Subject: [PATCH 0420/1594] [Java] Upgrade to javadoc-links 5.0.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b808199613..1a6d507fbd 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java-library' id 'idea' - id 'io.freefair.javadoc-links' version '5.0.0' apply false + id 'io.freefair.javadoc-links' version '5.0.1' apply false id 'com.github.johnrengelman.shadow' version '5.2.0' apply false id "com.github.ben-manes.versions" version "0.28.0" } From 6cd1a118def50d24c5d9521b219b7dc96f7d1edb Mon Sep 17 00:00:00 2001 From: szehetner <32911487+szehetner@users.noreply.github.com> Date: Mon, 4 May 2020 13:48:27 +0200 Subject: [PATCH 0421/1594] [C#] Add Offsets and WrapForEncodeAndApplyHeader (#777) * add field offset * added WrapForEncodeAndApplyHeader method * undo whitespaces * fixed long line checkstyle violation --- .../sbe/generation/csharp/CSharpGenerator.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index c4268cf912..85c6c71280 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1035,6 +1035,17 @@ private CharSequence generateMessageFlyweightCode(final String className, final indent + INDENT + INDENT + "_actingVersion = SchemaVersion;\n" + indent + INDENT + INDENT + "Limit = offset + _actingBlockLength;\n" + indent + INDENT + "}\n\n" + + indent + INDENT + "public void WrapForEncodeAndApplyHeader(DirectBuffer buffer, int offset, " + + " MessageHeader headerEncoder)\n" + + indent + INDENT + "{\n" + + indent + INDENT + INDENT + "headerEncoder.Wrap(buffer, offset, SchemaVersion);\n" + + indent + INDENT + INDENT + "headerEncoder.BlockLength = BlockLength;\n" + + indent + INDENT + INDENT + "headerEncoder.TemplateId = TemplateId;\n" + + indent + INDENT + INDENT + "headerEncoder.SchemaId = SchemaId;\n" + + indent + INDENT + INDENT + "headerEncoder.Version = SchemaVersion;\n" + + indent + INDENT + INDENT + "\n" + + indent + INDENT + INDENT + "WrapForEncode(buffer, offset + MessageHeader.Size);\n" + + indent + INDENT + "}\n\n" + indent + INDENT + "public void WrapForDecode(DirectBuffer buffer, int offset, " + "int actingBlockLength, int actingVersion)\n" + indent + INDENT + "{\n" + @@ -1122,6 +1133,11 @@ private void generateFieldIdMethod(final StringBuilder sb, final Token token, fi token.id())); generateSinceActingDeprecated(sb, indent, CSharpUtil.formatPropertyName(token.name()), token); + + sb.append(String.format("\n" + + indent + "public const int %sOffset = %d;\n", + CSharpUtil.formatPropertyName(token.name()), + token.offset())); } private void generateFieldMetaAttributeMethod(final StringBuilder sb, final Token token, final String indent) From f9170b0af1f97e8113acb5aecd06e8bcb4573d37 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 4 May 2020 12:54:59 +0100 Subject: [PATCH 0422/1594] [Java] Improve method name. --- .../real_logic/sbe/generation/csharp/CSharpGenerator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 85c6c71280..a61f057cca 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -352,7 +352,7 @@ private CharSequence generateVarData(final List tokens, final String inde final Token token = tokens.get(i); if (token.signal() == Signal.BEGIN_VAR_DATA) { - generateFieldIdMethod(sb, token, indent); + generateCommonFieldMethods(sb, token, indent); final Token varDataToken = Generators.findFirst("varData", tokens, i); final String characterEncoding = varDataToken.encoding().characterEncoding(); generateCharacterEncodingMethod(sb, token.name(), characterEncoding, indent); @@ -1098,7 +1098,7 @@ private CharSequence generateFields(final List tokens, final String inden final Token encodingToken = tokens.get(i + 1); final String propertyName = signalToken.name(); - generateFieldIdMethod(sb, signalToken, indent + INDENT); + generateCommonFieldMethods(sb, signalToken, indent + INDENT); generateFieldMetaAttributeMethod(sb, signalToken, indent + INDENT); switch (encodingToken.signal()) @@ -1125,7 +1125,7 @@ private CharSequence generateFields(final List tokens, final String inden return sb; } - private void generateFieldIdMethod(final StringBuilder sb, final Token token, final String indent) + private void generateCommonFieldMethods(final StringBuilder sb, final Token token, final String indent) { sb.append(String.format("\n" + indent + "public const int %sId = %d;\n", From 3a4cc5d0363bd5af3453f1ffa27bf1f79dc1c2e6 Mon Sep 17 00:00:00 2001 From: szehetner <32911487+szehetner@users.noreply.github.com> Date: Mon, 4 May 2020 17:07:41 +0200 Subject: [PATCH 0423/1594] generate source docs from descriptions (#778) --- .../generation/csharp/CSharpGenerator.java | 106 ++++++++++++------ 1 file changed, 73 insertions(+), 33 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index a61f057cca..f6d5a64bad 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -94,6 +94,7 @@ public void generate() throws IOException try (Writer out = outputManager.createOutput(className)) { out.append(generateFileHeader(ir.applicableNamespace())); + out.append(generateDocumentation(BASE_INDENT, msgToken)); out.append(generateClassDeclaration(className)); out.append(generateMessageFlyweightCode(className, msgToken, BASE_INDENT)); @@ -168,16 +169,18 @@ private void generateGroupClassHeader( final int dimensionHeaderLength = tokens.get(index + 1).encodedLength(); sb.append(String.format("\n" + - indent + "public sealed partial class %1$sGroup\n" + + "%1$s" + + indent + "public sealed partial class %2$sGroup\n" + indent + "{\n" + - indent + INDENT + "private readonly %2$s _dimensions = new %2$s();\n" + - indent + INDENT + "private %3$s _parentMessage;\n" + + indent + INDENT + "private readonly %3$s _dimensions = new %3$s();\n" + + indent + INDENT + "private %4$s _parentMessage;\n" + indent + INDENT + "private DirectBuffer _buffer;\n" + indent + INDENT + "private int _blockLength;\n" + indent + INDENT + "private int _actingVersion;\n" + indent + INDENT + "private int _count;\n" + indent + INDENT + "private int _index;\n" + indent + INDENT + "private int _offset;\n", + generateDocumentation(indent, tokens.get(index)), formatClassName(groupName), dimensionsClassName, parentMessageClassName)); @@ -318,14 +321,16 @@ private CharSequence generateGroupProperty(final String groupName, final Token t generateSinceActingDeprecated(sb, indent, toUpperFirstChar(groupName), token); sb.append(String.format("\n" + - indent + "public %1$sGroup %2$s\n" + + "%1$s" + + indent + "public %2$sGroup %3$s\n" + indent + "{\n" + indent + INDENT + "get\n" + indent + INDENT + "{\n" + - indent + INDENT + INDENT + "_%3$s.WrapForDecode(_parentMessage, _buffer, _actingVersion);\n" + - indent + INDENT + INDENT + "return _%3$s;\n" + + indent + INDENT + INDENT + "_%4$s.WrapForDecode(_parentMessage, _buffer, _actingVersion);\n" + + indent + INDENT + INDENT + "return _%4$s;\n" + indent + INDENT + "}\n" + indent + "}\n", + generateDocumentation(indent, token), className, toUpperFirstChar(groupName), toLowerFirstChar(groupName))); @@ -453,6 +458,7 @@ private void generateBitSet(final List tokens) throws IOException try (Writer out = outputManager.createOutput(enumName)) { out.append(generateFileHeader(ir.applicableNamespace())); + out.append(generateDocumentation(INDENT, enumToken)); final String enumPrimitiveType = cSharpTypeName(enumToken.encoding().primitiveType()); out.append(generateEnumDeclaration(enumName, enumPrimitiveType, true)); @@ -471,6 +477,7 @@ private void generateEnum(final List tokens) throws IOException try (Writer out = outputManager.createOutput(enumName)) { out.append(generateFileHeader(ir.applicableNamespace())); + out.append(generateDocumentation(INDENT, enumToken)); final String enumPrimitiveType = cSharpTypeName(enumToken.encoding().primitiveType()); out.append(generateEnumDeclaration(enumName, enumPrimitiveType, false)); @@ -488,6 +495,7 @@ private void generateComposite(final List tokens) throws IOException try (Writer out = outputManager.createOutput(compositeName)) { out.append(generateFileHeader(ir.applicableNamespace())); + out.append(generateDocumentation(INDENT, tokens.get(0))); out.append(generateClassDeclaration(compositeName)); out.append(generateFixedFlyweightCode(tokens.get(0).encodedLength())); out.append(generateCompositePropertyElements(tokens.subList(1, tokens.size() - 1), BASE_INDENT)); @@ -557,7 +565,8 @@ private CharSequence generateEnumValues(final List tokens, final Token en for (final Token token : tokens) { - sb.append(INDENT).append(INDENT).append(token.name()).append(" = ") + sb.append(generateDocumentation(INDENT + INDENT, token)) + .append(INDENT).append(INDENT).append(token.name()).append(" = ") .append(token.encoding().constValue()).append(",\n"); } @@ -607,6 +616,21 @@ private CharSequence generateClassDeclaration(final String className) className); } + public static String generateDocumentation(final String indent, final Token token) + { + final String description = token.description(); + if (null == description || description.isEmpty()) + { + return ""; + } + + return String.format( + indent + "/// \n" + + indent + "/// %s\n" + + indent + "/// \n", + description); + } + private void generateMetaAttributeEnum() throws IOException { try (Writer out = outputManager.createOutput(META_ATTRIBUTE_ENUM)) @@ -715,18 +739,20 @@ private CharSequence generateSingleValueProperty( final String byteOrderStr = generateByteOrder(byteOrder, typeToken.encoding().primitiveType().size()); return String.format("\n" + - indent + "public %1$s %2$s\n" + + "%1$s" + + indent + "public %2$s %3$s\n" + indent + "{\n" + indent + INDENT + "get\n" + indent + INDENT + "{\n" + - "%3$s" + - indent + INDENT + INDENT + "return _buffer.%4$sGet%6$s(_offset + %5$d);\n" + + "%4$s" + + indent + INDENT + INDENT + "return _buffer.%5$sGet%7$s(_offset + %6$d);\n" + indent + INDENT + "}\n" + indent + INDENT + "set\n" + indent + INDENT + "{\n" + - indent + INDENT + INDENT + "_buffer.%4$sPut%6$s(_offset + %5$d, value);\n" + + indent + INDENT + INDENT + "_buffer.%5$sPut%7$s(_offset + %6$d, value);\n" + indent + INDENT + "}\n" + indent + "}\n\n", + generateDocumentation(indent, fieldToken), typeName, toUpperFirstChar(propertyName), generateFieldNotPresentCondition(fieldToken.version(), typeToken.encoding(), indent), @@ -825,28 +851,32 @@ private CharSequence generateArrayProperty( propName, fieldLength)); sb.append(String.format("\n" + - indent + "public %1$s Get%2$s(int index)\n" + + "%1$s" + + indent + "public %2$s Get%3$s(int index)\n" + indent + "{\n" + - indent + INDENT + "if ((uint) index >= %3$d)\n" + + indent + INDENT + "if ((uint) index >= %4$d)\n" + indent + INDENT + "{\n" + indent + INDENT + INDENT + "ThrowHelper.ThrowIndexOutOfRangeException(index);\n" + indent + INDENT + "}\n\n" + - "%4$s" + - indent + INDENT + "return _buffer.%5$sGet%8$s(_offset + %6$d + (index * %7$d));\n" + + "%5$s" + + indent + INDENT + "return _buffer.%6$sGet%9$s(_offset + %7$d + (index * %8$d));\n" + indent + "}\n", + generateDocumentation(indent, fieldToken), typeName, propName, fieldLength, generateFieldNotPresentCondition(fieldToken.version(), typeToken.encoding(), indent), typePrefix, offset, typeSize, byteOrderStr)); sb.append(String.format("\n" + - indent + "public void Set%1$s(int index, %2$s value)\n" + + "%1$s" + + indent + "public void Set%2$s(int index, %3$s value)\n" + indent + "{\n" + - indent + INDENT + "if ((uint) index >= %3$d)\n" + + indent + INDENT + "if ((uint) index >= %4$d)\n" + indent + INDENT + "{\n" + indent + INDENT + INDENT + "ThrowHelper.ThrowIndexOutOfRangeException(index);\n" + indent + INDENT + "}\n\n" + - indent + INDENT + "_buffer.%4$sPut%7$s(_offset + %5$d + (index * %6$d), value);\n" + + indent + INDENT + "_buffer.%5$sPut%8$s(_offset + %6$d + (index * %7$d), value);\n" + indent + "}\n", + generateDocumentation(indent, fieldToken), propName, typeName, fieldLength, typePrefix, offset, typeSize, byteOrderStr)); if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) @@ -921,7 +951,9 @@ private CharSequence generateConstPropertyMethods( // ODE: we generate a property here because the constant could // become a field in a newer version of the protocol return String.format("\n" + - indent + INDENT + "public %1$s %2$s { get { return %3$s; } }\n", + "%1s" + + indent + INDENT + "public %2$s %3$s { get { return %4$s; } }\n", + generateDocumentation(indent + INDENT, token), cSharpTypeName(token.encoding().primitiveType()), toUpperFirstChar(propertyName), generateLiteral(token.encoding().primitiveType(), token.encoding().constValue().toString())); @@ -1201,13 +1233,15 @@ private CharSequence generateEnumProperty( final String constValue = fieldToken.encoding().constValue().toString(); return String.format("\n" + - indent + INDENT + "public %1$s %2$s\n" + + "%1$s" + + indent + INDENT + "public %2$s %3$s\n" + indent + INDENT + "{\n" + indent + INDENT + INDENT + "get\n" + indent + INDENT + INDENT + "{\n" + - indent + INDENT + INDENT + INDENT + "return %3$s;\n" + + indent + INDENT + INDENT + INDENT + "return %4$s;\n" + indent + INDENT + INDENT + "}\n" + indent + INDENT + "}\n\n", + generateDocumentation(indent + INDENT, fieldToken), enumName, toUpperFirstChar(propertyName), constValue); @@ -1215,18 +1249,20 @@ private CharSequence generateEnumProperty( else { return String.format("\n" + - indent + INDENT + "public %1$s %2$s\n" + + "%1$s" + + indent + INDENT + "public %2$s %3$s\n" + indent + INDENT + "{\n" + indent + INDENT + INDENT + "get\n" + indent + INDENT + INDENT + "{\n" + - "%3$s" + - indent + INDENT + INDENT + INDENT + "return (%4$s)_buffer.%5$sGet%7$s(_offset + %6$d);\n" + + "%4$s" + + indent + INDENT + INDENT + INDENT + "return (%5$s)_buffer.%6$sGet%8$s(_offset + %7$d);\n" + indent + INDENT + INDENT + "}\n" + indent + INDENT + INDENT + "set\n" + indent + INDENT + INDENT + "{\n" + - indent + INDENT + INDENT + INDENT + "_buffer.%5$sPut%7$s(_offset + %6$d, (%8$s)value);\n" + + indent + INDENT + INDENT + INDENT + "_buffer.%6$sPut%8$s(_offset + %7$d, (%9$s)value);\n" + indent + INDENT + INDENT + "}\n" + indent + INDENT + "}\n\n", + generateDocumentation(indent + INDENT, fieldToken), enumName, toUpperFirstChar(propertyName), generateEnumFieldNotPresentCondition(fieldToken.version(), enumName, indent), @@ -1249,18 +1285,20 @@ private String generateBitSetProperty( final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); return String.format("\n" + - indent + INDENT + "public %1$s %2$s\n" + + "%1$s" + + indent + INDENT + "public %2$s %3$s\n" + indent + INDENT + "{\n" + indent + INDENT + INDENT + "get\n" + indent + INDENT + INDENT + "{\n" + - "%3$s" + - indent + INDENT + INDENT + INDENT + "return (%4$s)_buffer.%5$sGet%7$s(_offset + %6$d);\n" + + "%4$s" + + indent + INDENT + INDENT + INDENT + "return (%5$s)_buffer.%6$sGet%8$s(_offset + %7$d);\n" + indent + INDENT + INDENT + "}\n" + indent + INDENT + INDENT + "set\n" + indent + INDENT + INDENT + "{\n" + - indent + INDENT + INDENT + INDENT + "_buffer.%5$sPut%7$s(_offset + %6$d, (%8$s)value);\n" + + indent + INDENT + INDENT + INDENT + "_buffer.%6$sPut%8$s(_offset + %7$d, (%9$s)value);\n" + indent + INDENT + INDENT + "}\n" + indent + INDENT + "}\n", + generateDocumentation(indent + INDENT, fieldToken), bitSetName, toUpperFirstChar(propertyName), generateBitSetNotPresentCondition(fieldToken.version(), indent, bitSetName), @@ -1285,15 +1323,17 @@ private Object generateCompositeProperty( compositeName)); sb.append(String.format("\n" + - indent + INDENT + "public %1$s %2$s\n" + + "%1$s" + + indent + INDENT + "public %2$s %3$s\n" + indent + INDENT + "{\n" + indent + INDENT + INDENT + "get\n" + indent + INDENT + INDENT + "{\n" + - "%3$s" + - indent + INDENT + INDENT + INDENT + "_%4$s.Wrap(_buffer, _offset + %5$d, _actingVersion);\n" + - indent + INDENT + INDENT + INDENT + "return _%4$s;\n" + + "%4$s" + + indent + INDENT + INDENT + INDENT + "_%5$s.Wrap(_buffer, _offset + %6$d, _actingVersion);\n" + + indent + INDENT + INDENT + INDENT + "return _%5$s;\n" + indent + INDENT + INDENT + "}\n" + indent + INDENT + "}\n", + generateDocumentation(indent + INDENT, fieldToken), compositeName, toUpperFirstChar(propertyName), generateTypeFieldNotPresentCondition(fieldToken.version(), indent), From 6678b143ef62730bc7a5e2292edfce81261ccf3d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 5 May 2020 08:39:22 +0100 Subject: [PATCH 0424/1594] [Java] Not all fields should have offset. --- .../generation/csharp/CSharpGenerator.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index f6d5a64bad..dfd8cab722 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -35,6 +35,7 @@ import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; +@SuppressWarnings("MethodLength") public class CSharpGenerator implements CodeGenerator { private static final String META_ATTRIBUTE_ENUM = "MetaAttribute"; @@ -357,7 +358,10 @@ private CharSequence generateVarData(final List tokens, final String inde final Token token = tokens.get(i); if (token.signal() == Signal.BEGIN_VAR_DATA) { - generateCommonFieldMethods(sb, token, indent); + generateFieldIdMethod(sb, token, indent); + generateSinceActingDeprecated(sb, indent, CSharpUtil.formatPropertyName(token.name()), token); + generateOffsetMethod(sb, token, indent); + final Token varDataToken = Generators.findFirst("varData", tokens, i); final String characterEncoding = varDataToken.encoding().characterEncoding(); generateCharacterEncodingMethod(sb, token.name(), characterEncoding, indent); @@ -376,6 +380,7 @@ private CharSequence generateVarData(final List tokens, final String inde indent + "public const int %sHeaderSize = %d;\n", propertyName, sizeOfLengthField)); + sb.append(String.format(indent + "\n" + indent + "public int %1$sLength()\n" + indent + "{\n" + @@ -386,10 +391,12 @@ private CharSequence generateVarData(final List tokens, final String inde sizeOfLengthField, lengthTypePrefix, byteOrderStr)); + sb.append(String.format("\n" + indent + "public int Get%1$s(byte[] dst, int dstOffset, int length) =>\n" + indent + INDENT + "Get%1$s(new Span(dst, dstOffset, length));\n", propertyName)); + sb.append(String.format("\n" + indent + "public int Get%1$s(Span dst)\n" + indent + "{\n" + @@ -408,6 +415,7 @@ private CharSequence generateVarData(final List tokens, final String inde sizeOfLengthField, lengthTypePrefix, byteOrderStr)); + sb.append(String.format(indent + "\n" + indent + "// Allocates and returns a new byte array\n" + indent + "public byte[] Get%1$sBytes()\n" + @@ -418,7 +426,6 @@ private CharSequence generateVarData(final List tokens, final String inde indent + INDENT + "int dataLength = (int)_buffer.%3$sGet%4$s(limit);\n" + indent + INDENT + "byte[] data = new byte[dataLength];\n" + indent + INDENT + "_parentMessage.Limit = limit + sizeOfLengthField + dataLength;\n" + - indent + INDENT + "_buffer.GetBytes(limit + sizeOfLengthField, data);\n\n" + indent + INDENT + "return data;\n" + indent + "}\n", @@ -426,10 +433,12 @@ private CharSequence generateVarData(final List tokens, final String inde sizeOfLengthField, lengthTypePrefix, byteOrderStr)); + sb.append(String.format("\n" + indent + "public int Set%1$s(byte[] src, int srcOffset, int length) =>\n" + indent + INDENT + "Set%1$s(new ReadOnlySpan(src, srcOffset, length));\n", propertyName)); + sb.append(String.format("\n" + indent + "public int Set%1$s(ReadOnlySpan src)\n" + indent + "{\n" + @@ -447,6 +456,7 @@ private CharSequence generateVarData(final List tokens, final String inde byteOrderStr)); } } + return sb; } @@ -1130,7 +1140,10 @@ private CharSequence generateFields(final List tokens, final String inden final Token encodingToken = tokens.get(i + 1); final String propertyName = signalToken.name(); - generateCommonFieldMethods(sb, signalToken, indent + INDENT); + generateFieldIdMethod(sb, signalToken, indent + INDENT); + generateSinceActingDeprecated( + sb, indent, CSharpUtil.formatPropertyName(signalToken.name()), signalToken); + generateOffsetMethod(sb, signalToken, indent + INDENT); generateFieldMetaAttributeMethod(sb, signalToken, indent + INDENT); switch (encodingToken.signal()) @@ -1157,15 +1170,16 @@ private CharSequence generateFields(final List tokens, final String inden return sb; } - private void generateCommonFieldMethods(final StringBuilder sb, final Token token, final String indent) + private void generateFieldIdMethod(final StringBuilder sb, final Token token, final String indent) { sb.append(String.format("\n" + indent + "public const int %sId = %d;\n", CSharpUtil.formatPropertyName(token.name()), token.id())); + } - generateSinceActingDeprecated(sb, indent, CSharpUtil.formatPropertyName(token.name()), token); - + private void generateOffsetMethod(final StringBuilder sb, final Token token, final String indent) + { sb.append(String.format("\n" + indent + "public const int %sOffset = %d;\n", CSharpUtil.formatPropertyName(token.name()), From 247e2f34311c616523e1ad83c2f4e4bbb3e6c429 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 8 May 2020 18:29:48 +0100 Subject: [PATCH 0425/1594] [Java] Fix handling of C codec reading an enum for older acting version. Issue #773. --- .../sbe/generation/c/CGenerator.java | 63 +++++++++++-------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 2ece260095..9425d79b56 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -978,10 +978,10 @@ private CharSequence generateFieldNotPresentCondition(final int sinceVersion, fi } return String.format( - "if (codec->acting_version < %1$d)\n" + - "{\n" + - " return %2$s;\n" + - "}\n\n", + " if (codec->acting_version < %1$d)\n" + + " {\n" + + " return %2$s;\n" + + " }\n\n", sinceVersion, generateLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString())); } @@ -994,10 +994,10 @@ private static CharSequence generateArrayFieldNotPresentCondition(final int sinc } return String.format( - "if (codec->acting_version < %1$d)\n" + - "{\n" + - " return 0;\n" + - "}\n\n", + " if (codec->acting_version < %1$d)\n" + + " {\n" + + " return 0;\n" + + " }\n\n", sinceVersion); } @@ -1009,10 +1009,10 @@ private static CharSequence generateStringViewNotPresentCondition(final int sinc } return String.format( - "if (codec->acting_version < %1$d)\n" + - "{\n" + - " return {NULL, 0};\n" + - "}\n\n", + " if (codec->acting_version < %1$d)\n" + + " {\n" + + " return { NULL, 0 };\n" + + " }\n\n", sinceVersion); } @@ -1024,10 +1024,10 @@ private static CharSequence generateTypeFieldNotPresentCondition(final int since } return String.format( - "if (codec->acting_version < %1$d)\n" + - "{\n" + - " return NULL;\n" + - "}\n\n", + " if (codec->acting_version < %1$d)\n" + + " {\n" + + " return NULL;\n" + + " }\n\n", sinceVersion); } @@ -1351,8 +1351,7 @@ private CharSequence generateLoadValue( if (primitiveType == PrimitiveType.FLOAT || primitiveType == PrimitiveType.DOUBLE) { - final String stackUnion = - (primitiveType == PrimitiveType.FLOAT) ? "float" : "double"; + final String stackUnion = primitiveType == PrimitiveType.FLOAT ? "float" : "double"; sb.append(String.format( " union %1$s_%2$s_as_uint val;\n" + @@ -1418,8 +1417,7 @@ private CharSequence generateStoreValue( if (primitiveType == PrimitiveType.FLOAT || primitiveType == PrimitiveType.DOUBLE) { - final String stackUnion = - (primitiveType == PrimitiveType.FLOAT) ? "float" : "double"; + final String stackUnion = primitiveType == PrimitiveType.FLOAT ? "float" : "double"; sb.append(String.format( " union %1$s_%2$s_as_uint val;\n" + @@ -2167,6 +2165,21 @@ private static void generateFieldMetaAttributeFunction( outermostStruct)); } + private static CharSequence generateEnumFieldNotPresentCondition(final int sinceVersion) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + " if (codec->acting_version < %1$d)\n" + + " {\n" + + " return false;\n" + + " }\n\n", + sinceVersion); + } + private static CharSequence generateEnumFieldNotPresentCondition(final int sinceVersion, final String enumName) { if (0 == sinceVersion) @@ -2175,10 +2188,10 @@ private static CharSequence generateEnumFieldNotPresentCondition(final int since } return String.format( - "if (codec->acting_version < %1$d)\n" + - "{\n" + - " return %2$s_NULL_VALUE;\n" + - "}\n\n", + " if (codec->acting_version < %1$d)\n" + + " {\n" + + " return %2$s_NULL_VALUE;\n" + + " }\n\n", sinceVersion, enumName); } @@ -2245,7 +2258,7 @@ private void generateEnumProperty( "}\n", enumName, propertyName, - generateEnumFieldNotPresentCondition(token.version(), enumName), + generateEnumFieldNotPresentCondition(token.version()), formatByteOrderEncoding(token.encoding().byteOrder(), token.encoding().primitiveType()), typeName, offset, From 2f699f6049e639f987e45708cff379ca70ee69ec Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 9 May 2020 16:22:52 +0100 Subject: [PATCH 0426/1594] [Java] Add SchemaId and SchemaVersion to fix flyweight codecs for C#. --- .../sbe/generation/csharp/CSharpGenerator.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index dfd8cab722..660c0c0e20 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1029,17 +1029,28 @@ private CharSequence generateByteLiteralList(final byte[] bytes) private CharSequence generateFixedFlyweightCode(final int size) { + final String schemaIdType = cSharpTypeName(ir.headerStructure().schemaIdType()); + final String schemaVersionType = cSharpTypeName(ir.headerStructure().schemaVersionType()); + return String.format( + INDENT + INDENT + "public const %1$s SchemaId = %2$s;\n" + + INDENT + INDENT + "public const %3$s SchemaVersion = %4$s;\n" + + INDENT + INDENT + "public const int Size = %5$d;\n\n", + INDENT + INDENT + "private DirectBuffer _buffer;\n" + INDENT + INDENT + "private int _offset;\n" + INDENT + INDENT + "private int _actingVersion;\n\n" + + INDENT + INDENT + "public void Wrap(DirectBuffer buffer, int offset, int actingVersion)\n" + INDENT + INDENT + "{\n" + INDENT + INDENT + INDENT + "_offset = offset;\n" + INDENT + INDENT + INDENT + "_actingVersion = actingVersion;\n" + INDENT + INDENT + INDENT + "_buffer = buffer;\n" + INDENT + INDENT + "}\n\n" + - INDENT + INDENT + "public const int Size = %d;\n", + schemaIdType, + generateLiteral(ir.headerStructure().schemaIdType(), Integer.toString(ir.id())), + schemaVersionType, + generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), size); } From 47226c4f668d83c163f45fa1821224e1ed250647 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 9 May 2020 16:56:31 +0100 Subject: [PATCH 0427/1594] [Java] Prefix with Sbe so we have SbeSchemaId and SbeSchemaVersion in generated codec for CSharp. --- .../sbe/generation/csharp/CSharpGenerator.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 660c0c0e20..db16531c08 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1029,13 +1029,10 @@ private CharSequence generateByteLiteralList(final byte[] bytes) private CharSequence generateFixedFlyweightCode(final int size) { - final String schemaIdType = cSharpTypeName(ir.headerStructure().schemaIdType()); - final String schemaVersionType = cSharpTypeName(ir.headerStructure().schemaVersionType()); - return String.format( - INDENT + INDENT + "public const %1$s SchemaId = %2$s;\n" + - INDENT + INDENT + "public const %3$s SchemaVersion = %4$s;\n" + - INDENT + INDENT + "public const int Size = %5$d;\n\n", + INDENT + INDENT + "public const %1$s SbeSchemaId = %2$s;\n" + + INDENT + INDENT + "public const %3$s SbeSchemaVersion = %4$s;\n" + + INDENT + INDENT + "public const int Size = %5$d;\n\n" + INDENT + INDENT + "private DirectBuffer _buffer;\n" + INDENT + INDENT + "private int _offset;\n" + @@ -1046,10 +1043,10 @@ private CharSequence generateFixedFlyweightCode(final int size) INDENT + INDENT + INDENT + "_offset = offset;\n" + INDENT + INDENT + INDENT + "_actingVersion = actingVersion;\n" + INDENT + INDENT + INDENT + "_buffer = buffer;\n" + - INDENT + INDENT + "}\n\n" + - schemaIdType, + INDENT + INDENT + "}\n\n", + cSharpTypeName(ir.headerStructure().schemaIdType()), generateLiteral(ir.headerStructure().schemaIdType(), Integer.toString(ir.id())), - schemaVersionType, + cSharpTypeName(ir.headerStructure().schemaVersionType()), generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), size); } From e6b1d3980f721536c8c0117256f2cafa0f23a55c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 11 May 2020 11:38:24 +0100 Subject: [PATCH 0428/1594] [Java] Upgrade to Gradle 6.4. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 58694 -> 58910 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 ++ gradlew.bat | 1 + 5 files changed, 5 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 1a6d507fbd..b9cd6b4c73 100644 --- a/build.gradle +++ b/build.gradle @@ -686,6 +686,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.3' + gradleVersion = '6.4' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 490fda8577df6c95960ba7077c43220e5bb2c0d9..62d4c053550b91381bbd28b1afc82d634bf73a8a 100644 GIT binary patch delta 6447 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 F{|nTN-B$nr diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6623300beb..fd0c5a38e9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 2fe81a7d95..fbd7c51583 100755 --- a/gradlew +++ b/gradlew @@ -82,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -129,6 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index 62bd9b9cce..5093609d51 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -84,6 +84,7 @@ set CMD_LINE_ARGS=%* set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% From de2e1b06be9cce19ad8f257a4525c4718d965b4e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 16 May 2020 13:29:42 +0100 Subject: [PATCH 0429/1594] [Java] Upgrade to Gradle 6.4.1 and javadoc-links 5.1.0. --- build.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index b9cd6b4c73..7b5bcf8057 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java-library' id 'idea' - id 'io.freefair.javadoc-links' version '5.0.1' apply false + id 'io.freefair.javadoc-links' version '5.1.0' apply false id 'com.github.johnrengelman.shadow' version '5.2.0' apply false id "com.github.ben-manes.versions" version "0.28.0" } @@ -686,6 +686,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.4' + gradleVersion = '6.4.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fd0c5a38e9..21e622da69 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 4c541acbf399f0b72ca23055dc5befae98dfd252 Mon Sep 17 00:00:00 2001 From: "Dr. James Gate" Date: Sat, 16 May 2020 15:17:47 +0100 Subject: [PATCH 0430/1594] Indexed fields as spans (#780) * Added a rough outline of my C# value type encoder/decoder. * Revert "Added a rough outline of my C# value type encoder/decoder." This reverts commit b34653fc1d32dc411ad8d4a870d596d99922cd84. * Expose an array property as a span * Get the Length property right * Get the type right * Add field-as-span method * Set the type correctly --- .../generation/csharp/CSharpGenerator.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index db16531c08..8de581714c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -889,6 +889,27 @@ private CharSequence generateArrayProperty( generateDocumentation(indent, fieldToken), propName, typeName, fieldLength, typePrefix, offset, typeSize, byteOrderStr)); + // Expose the array as a ReadOnlySpan + sb.append(String.format("\n" + + "%1$s" + + indent + "public ReadOnlySpan<%2$s> %3$s\n" + + indent + "{\n" + + indent + INDENT + "get => _buffer.AsReadOnlySpan<%2$s>(_offset + %4$s, %3$sLength);\n" + + indent + INDENT + "set => value.CopyTo(_buffer.AsSpan<%2$s>(_offset + %4$s, %3$sLength));\n" + + indent + "}\n", + generateDocumentation(indent, fieldToken), + typeName, propName, offset)); + + // Expose the array as a Span + sb.append(String.format("\n" + + "%1$s" + + indent + "public Span<%2$s> %3$sAsSpan()\n" + + indent + "{\n" + + indent + INDENT + "return _buffer.AsSpan<%2$s>(_offset + %4$s, %3$sLength);\n" + + indent + "}\n", + generateDocumentation(indent, fieldToken), + typeName, propName, offset)); + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { generateCharacterEncodingMethod(sb, propertyName, typeToken.encoding().characterEncoding(), indent); From 8e208923c72c699977b404b5c04b639f2857ff03 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 16 May 2020 15:23:10 +0100 Subject: [PATCH 0431/1594] [Java] Remove comments after merge of PR #780. --- .../uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 8de581714c..3851e848c8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -889,7 +889,6 @@ private CharSequence generateArrayProperty( generateDocumentation(indent, fieldToken), propName, typeName, fieldLength, typePrefix, offset, typeSize, byteOrderStr)); - // Expose the array as a ReadOnlySpan sb.append(String.format("\n" + "%1$s" + indent + "public ReadOnlySpan<%2$s> %3$s\n" + @@ -900,7 +899,6 @@ private CharSequence generateArrayProperty( generateDocumentation(indent, fieldToken), typeName, propName, offset)); - // Expose the array as a Span sb.append(String.format("\n" + "%1$s" + indent + "public Span<%2$s> %3$sAsSpan()\n" + From 6b33c119e73e921137cdd7c8f333dad7d915d632 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 20 May 2020 19:57:09 +0100 Subject: [PATCH 0432/1594] [Java] Increase minor version to reflect additional features. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index f799225b81..dacb57abf2 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.17.1-SNAPSHOT \ No newline at end of file +1.18.0-SNAPSHOT \ No newline at end of file From b25ad6ab357ac6ac5c1012e7c7859a040a19d016 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 21 May 2020 14:02:46 +0100 Subject: [PATCH 0433/1594] [Java] Warnings clean up. --- .../src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/SetType.java | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index 493163f134..664a606acf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -192,7 +192,7 @@ public static PrimitiveValue parse(final String value, final PrimitiveType primi { throw new IllegalArgumentException("Constant char value malformed: " + value); } - return new PrimitiveValue((long)value.getBytes(US_ASCII)[0], 1); + return new PrimitiveValue(value.getBytes(US_ASCII)[0], 1); case INT8: return new PrimitiveValue(Byte.parseByte(value), 1); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index 834c249318..d0167f5f3f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -78,11 +78,12 @@ public SetType(final Node node, final String givenName, final String referencedN default: // might not have ran into this type yet, so look for it - final Node encodingTypeNode = (Node)xPath.compile( - String.format("%s[@name=\'%s\']", XmlSchemaParser.TYPE_XPATH_EXPR, encodingTypeStr)) + final String expression = TYPE_XPATH_EXPR + "[@name='" + encodingTypeStr + "']"; + final Node encodingTypeNode = (Node)xPath + .compile(expression) .evaluate(node.getOwnerDocument(), XPathConstants.NODE); - if (encodingTypeNode == null) + if (null == encodingTypeNode) { encodingType = null; } From 1eeee4a05572625a5006923e6b447e819e94213b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 21 May 2020 15:58:05 +0100 Subject: [PATCH 0434/1594] [Java] Upgrade to Agrona 1.5.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7b5bcf8057..1019feba3e 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.3.3' def junitVersion = '5.6.2' def jmhVersion = '1.23' -def agronaVersion = '1.4.1' +def agronaVersion = '1.5.0' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From f541cc8c5cfb59ea90e4633f42d359182e985a8d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 22 May 2020 13:47:44 +0100 Subject: [PATCH 0435/1594] [Java] Only import buffers to generated codecs when required to reduce warnings. --- .../sbe/generation/java/JavaGenerator.java | 115 +++++++++--------- .../sbe/ir/generated/ByteOrderCodec.java | 2 +- .../sbe/ir/generated/FrameCodecDecoder.java | 2 +- .../sbe/ir/generated/FrameCodecEncoder.java | 2 +- .../ir/generated/MessageHeaderDecoder.java | 2 +- .../ir/generated/MessageHeaderEncoder.java | 2 +- .../sbe/ir/generated/PresenceCodec.java | 2 +- .../sbe/ir/generated/PrimitiveTypeCodec.java | 2 +- .../sbe/ir/generated/SignalCodec.java | 2 +- .../sbe/ir/generated/TokenCodecDecoder.java | 2 +- .../sbe/ir/generated/TokenCodecEncoder.java | 2 +- .../ir/generated/VarDataEncodingDecoder.java | 2 +- .../ir/generated/VarDataEncodingEncoder.java | 2 +- 13 files changed, 70 insertions(+), 69 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 10e6f29d4f..53c1238296 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -108,8 +108,7 @@ private static String validateBufferImplementation( } catch (final ClassNotFoundException ex) { - throw new IllegalArgumentException( - "Unable to validate " + fullyQualifiedBufferImplementation + " because it can't be found", ex); + throw new IllegalArgumentException("Unable to find " + fullyQualifiedBufferImplementation, ex); } } @@ -198,7 +197,7 @@ private void generateEncoder( try (Writer out = outputManager.createOutput(className)) { - out.append(generateMainHeader(ir.applicableNamespace())); + out.append(generateMainHeader(ir.applicableNamespace(), ENCODER, !varData.isEmpty())); generateAnnotations(BASE_INDENT, className, groups, out, 0, this::encoderName); out.append(generateDeclaration(className, implementsString, msgToken)); @@ -225,7 +224,7 @@ private void generateDecoder( try (Writer out = outputManager.createOutput(className)) { - out.append(generateMainHeader(ir.applicableNamespace())); + out.append(generateMainHeader(ir.applicableNamespace(), DECODER, !varData.isEmpty())); generateAnnotations(BASE_INDENT, className, groups, out, 0, this::decoderName); out.append(generateDeclaration(className, implementsString, msgToken)); @@ -1546,29 +1545,33 @@ private String interfaceImportLine() private CharSequence generateFileHeader(final String packageName, final String fqBuffer) { return - "/* Generated SBE (Simple Binary Encoding) message codec */\n" + + "/* Generated SBE (Simple Binary Encoding) message codec. */\n" + "package " + packageName + ";\n\n" + "import " + fqBuffer + ";\n" + interfaceImportLine(); } - private CharSequence generateMainHeader(final String packageName) + private CharSequence generateMainHeader( + final String packageName, final CodecType codecType, final boolean hasVarData) { if (fqMutableBuffer.equals(fqReadOnlyBuffer)) { return - "/* Generated SBE (Simple Binary Encoding) message codec */\n" + + "/* Generated SBE (Simple Binary Encoding) message codec. */\n" + "package " + packageName + ";\n\n" + "import " + fqMutableBuffer + ";\n" + interfaceImportLine(); } else { + final boolean hasMutableBuffer = ENCODER == codecType || hasVarData; + final boolean hasReadOnlyBuffer = DECODER == codecType || hasVarData; + return - "/* Generated SBE (Simple Binary Encoding) message codec */\n" + + "/* Generated SBE (Simple Binary Encoding) message codec. */\n" + "package " + packageName + ";\n\n" + - "import " + fqMutableBuffer + ";\n" + - "import " + fqReadOnlyBuffer + ";\n" + + (hasMutableBuffer ? "import " + fqMutableBuffer + ";\n" : "") + + (hasReadOnlyBuffer ? "import " + fqReadOnlyBuffer + ";\n" : "") + interfaceImportLine(); } } @@ -1576,7 +1579,7 @@ private CharSequence generateMainHeader(final String packageName) private static CharSequence generateEnumFileHeader(final String packageName) { return - "/* Generated SBE (Simple Binary Encoding) message codec */\n" + + "/* Generated SBE (Simple Binary Encoding) message codec. */\n" + "package " + packageName + ";\n\n"; } @@ -3138,19 +3141,18 @@ private CharSequence generateCompositeEncoderDisplay(final String decoderName) private CharSequence generateCompositeDecoderDisplay(final List tokens) { - final String indent = INDENT; final StringBuilder sb = new StringBuilder(); - appendToString(sb, indent); + appendToString(sb, INDENT); sb.append('\n'); - append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); - append(sb, indent, "{"); - append(sb, indent, " if (null == buffer)"); - append(sb, indent, " {"); - append(sb, indent, " return builder;"); - append(sb, indent, " }"); + append(sb, INDENT, "public StringBuilder appendTo(final StringBuilder builder)"); + append(sb, INDENT, "{"); + append(sb, INDENT, " if (null == buffer)"); + append(sb, INDENT, " {"); + append(sb, INDENT, " return builder;"); + append(sb, INDENT, " }"); sb.append('\n'); - Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, INDENT + INDENT, "builder"); int lengthBeforeLastGeneratedSeparator = -1; @@ -3158,7 +3160,7 @@ private CharSequence generateCompositeDecoderDisplay(final List tokens) { final Token encodingToken = tokens.get(i); final String propertyName = formatPropertyName(encodingToken.name()); - lengthBeforeLastGeneratedSeparator = writeTokenDisplay(propertyName, encodingToken, sb, indent + INDENT); + lengthBeforeLastGeneratedSeparator = writeTokenDisplay(propertyName, encodingToken, sb, INDENT + INDENT); i += encodingToken.componentTokenCount(); } @@ -3167,10 +3169,10 @@ private CharSequence generateCompositeDecoderDisplay(final List tokens) sb.setLength(lengthBeforeLastGeneratedSeparator); } - Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, INDENT + INDENT, "builder"); sb.append('\n'); - append(sb, indent, " return builder;"); - append(sb, indent, "}"); + append(sb, INDENT, " return builder;"); + append(sb, INDENT, "}"); return sb; } @@ -3219,45 +3221,44 @@ private void generateDecoderDisplay( final List groups, final List varData) { - final String indent = INDENT; final String decoderName = decoderName(name); - appendMessageToString(sb, indent, decoderName); + appendMessageToString(sb, INDENT, decoderName); sb.append('\n'); - append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); - append(sb, indent, "{"); - append(sb, indent, " if (null == buffer)"); - append(sb, indent, " {"); - append(sb, indent, " return builder;"); - append(sb, indent, " }"); + append(sb, INDENT, "public StringBuilder appendTo(final StringBuilder builder)"); + append(sb, INDENT, "{"); + append(sb, INDENT, " if (null == buffer)"); + append(sb, INDENT, " {"); + append(sb, INDENT, " return builder;"); + append(sb, INDENT, " }"); sb.append('\n'); - append(sb, indent, " final int originalLimit = limit();"); - append(sb, indent, " limit(initialOffset + actingBlockLength);"); - append(sb, indent, " builder.append(\"[" + name + "](sbeTemplateId=\");"); - append(sb, indent, " builder.append(TEMPLATE_ID);"); - append(sb, indent, " builder.append(\"|sbeSchemaId=\");"); - append(sb, indent, " builder.append(SCHEMA_ID);"); - append(sb, indent, " builder.append(\"|sbeSchemaVersion=\");"); - append(sb, indent, " if (parentMessage.actingVersion != SCHEMA_VERSION)"); - append(sb, indent, " {"); - append(sb, indent, " builder.append(parentMessage.actingVersion);"); - append(sb, indent, " builder.append('/');"); - append(sb, indent, " }"); - append(sb, indent, " builder.append(SCHEMA_VERSION);"); - append(sb, indent, " builder.append(\"|sbeBlockLength=\");"); - append(sb, indent, " if (actingBlockLength != BLOCK_LENGTH)"); - append(sb, indent, " {"); - append(sb, indent, " builder.append(actingBlockLength);"); - append(sb, indent, " builder.append('/');"); - append(sb, indent, " }"); - append(sb, indent, " builder.append(BLOCK_LENGTH);"); - append(sb, indent, " builder.append(\"):\");"); - appendDecoderDisplay(sb, tokens, groups, varData, indent + INDENT); + append(sb, INDENT, " final int originalLimit = limit();"); + append(sb, INDENT, " limit(initialOffset + actingBlockLength);"); + append(sb, INDENT, " builder.append(\"[" + name + "](sbeTemplateId=\");"); + append(sb, INDENT, " builder.append(TEMPLATE_ID);"); + append(sb, INDENT, " builder.append(\"|sbeSchemaId=\");"); + append(sb, INDENT, " builder.append(SCHEMA_ID);"); + append(sb, INDENT, " builder.append(\"|sbeSchemaVersion=\");"); + append(sb, INDENT, " if (parentMessage.actingVersion != SCHEMA_VERSION)"); + append(sb, INDENT, " {"); + append(sb, INDENT, " builder.append(parentMessage.actingVersion);"); + append(sb, INDENT, " builder.append('/');"); + append(sb, INDENT, " }"); + append(sb, INDENT, " builder.append(SCHEMA_VERSION);"); + append(sb, INDENT, " builder.append(\"|sbeBlockLength=\");"); + append(sb, INDENT, " if (actingBlockLength != BLOCK_LENGTH)"); + append(sb, INDENT, " {"); + append(sb, INDENT, " builder.append(actingBlockLength);"); + append(sb, INDENT, " builder.append('/');"); + append(sb, INDENT, " }"); + append(sb, INDENT, " builder.append(BLOCK_LENGTH);"); + append(sb, INDENT, " builder.append(\"):\");"); + appendDecoderDisplay(sb, tokens, groups, varData, INDENT + INDENT); sb.append('\n'); - append(sb, indent, " limit(originalLimit);"); + append(sb, INDENT, " limit(originalLimit);"); sb.append('\n'); - append(sb, indent, " return builder;"); - append(sb, indent, "}"); + append(sb, INDENT, " return builder;"); + append(sb, INDENT, "}"); } private void appendGroupInstanceDecoderDisplay( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java index 8eabf31b28..65404dd8ad 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java @@ -1,4 +1,4 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ +/* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 52b28a6c40..7c998b888f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -1,4 +1,4 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ +/* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; import org.agrona.MutableDirectBuffer; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index e12b0380ad..914a4aa4ce 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -1,4 +1,4 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ +/* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; import org.agrona.MutableDirectBuffer; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java index 8056af47c6..a1d6fb2936 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java @@ -1,4 +1,4 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ +/* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; import org.agrona.DirectBuffer; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java index 4bee4884ea..1d0bd0a892 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java @@ -1,4 +1,4 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ +/* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; import org.agrona.MutableDirectBuffer; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java index 634cfa0baf..55ecb2a6e9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java @@ -1,4 +1,4 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ +/* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java index 39279c4235..93906b5e82 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java @@ -1,4 +1,4 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ +/* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java index 48441dd02c..9573abf7bd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java @@ -1,4 +1,4 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ +/* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 0920a8a6e2..a18ebca7c6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -1,4 +1,4 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ +/* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; import org.agrona.MutableDirectBuffer; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index c7a676ab0e..33a46e05f9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -1,4 +1,4 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ +/* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; import org.agrona.MutableDirectBuffer; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java index 1215de103b..e820dc0b27 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java @@ -1,4 +1,4 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ +/* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; import org.agrona.DirectBuffer; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java index e7a6015993..a6299907cb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java @@ -1,4 +1,4 @@ -/* Generated SBE (Simple Binary Encoding) message codec */ +/* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; import org.agrona.MutableDirectBuffer; From e6942dfaf6ff2079a1d1c753df524761fb505be8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 22 May 2020 13:55:34 +0100 Subject: [PATCH 0436/1594] [Java] Stronger typing of interface names. --- .../sbe/generation/java/JavaGenerator.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 53c1238296..2a083010b2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -17,6 +17,7 @@ import org.agrona.*; import org.agrona.generation.OutputManager; +import org.agrona.sbe.*; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.generation.CodeGenerator; import uk.co.real_logic.sbe.generation.Generators; @@ -48,11 +49,6 @@ enum CodecType private static final String PACKAGE_INFO = "package-info"; private static final String BASE_INDENT = ""; private static final String INDENT = " "; - private static final String FLYWEIGHT = "Flyweight"; - private static final String COMPOSITE_DECODER_FLYWEIGHT = "CompositeDecoderFlyweight"; - private static final String COMPOSITE_ENCODER_FLYWEIGHT = "CompositeEncoderFlyweight"; - private static final String MESSAGE_DECODER_FLYWEIGHT = "MessageDecoderFlyweight"; - private static final String MESSAGE_ENCODER_FLYWEIGHT = "MessageEncoderFlyweight"; private final Ir ir; private final OutputManager outputManager; @@ -193,7 +189,7 @@ private void generateEncoder( throws IOException { final String className = formatClassName(encoderName(msgToken.name())); - final String implementsString = implementsInterface(MESSAGE_ENCODER_FLYWEIGHT); + final String implementsString = implementsInterface(MessageEncoderFlyweight.class.getSimpleName()); try (Writer out = outputManager.createOutput(className)) { @@ -220,7 +216,7 @@ private void generateDecoder( throws IOException { final String className = formatClassName(decoderName(msgToken.name())); - final String implementsString = implementsInterface(MESSAGE_DECODER_FLYWEIGHT); + final String implementsString = implementsInterface(MessageDecoderFlyweight.class.getSimpleName()); try (Writer out = outputManager.createOutput(className)) { @@ -1187,7 +1183,7 @@ private void generateBitSet(final List tokens) throws IOException final String decoderName = decoderName(bitSetName); final String encoderName = encoderName(bitSetName); final List messageBody = getMessageBody(tokens); - final String implementsString = implementsInterface(FLYWEIGHT); + final String implementsString = implementsInterface(Flyweight.class.getSimpleName()); try (Writer out = outputManager.createOutput(decoderName)) { @@ -1261,7 +1257,7 @@ private void generateComposite(final List tokens) throws IOException try (Writer out = outputManager.createOutput(decoderName)) { - final String implementsString = implementsInterface(COMPOSITE_DECODER_FLYWEIGHT); + final String implementsString = implementsInterface(CompositeDecoderFlyweight.class.getSimpleName()); generateCompositeFlyweightHeader( token, decoderName, out, readOnlyBuffer, fqReadOnlyBuffer, implementsString); @@ -1309,7 +1305,7 @@ private void generateComposite(final List tokens) throws IOException try (Writer out = outputManager.createOutput(encoderName)) { - final String implementsString = implementsInterface(COMPOSITE_ENCODER_FLYWEIGHT); + final String implementsString = implementsInterface(CompositeEncoderFlyweight.class.getSimpleName()); generateCompositeFlyweightHeader(token, encoderName, out, mutableBuffer, fqMutableBuffer, implementsString); for (int i = 1, end = tokens.size() - 1; i < end;) From 6ef0c48365dfa182ae08b91f9b3a32d5b21d48cf Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 22 May 2020 14:36:33 +0100 Subject: [PATCH 0437/1594] [Java] Tidy up common methods and add javadoc. --- .../sbe/codec/java/MethodSelector.java | 3 + .../real_logic/sbe/generation/Generators.java | 3 + .../real_logic/sbe/generation/NamedToken.java | 59 ------------------- .../generation/TargetCodeGeneratorLoader.java | 16 +++++ .../sbe/generation/c/CGenerator.java | 5 ++ .../co/real_logic/sbe/generation/c/CUtil.java | 24 +------- .../sbe/generation/cpp/CppGenerator.java | 5 ++ .../sbe/generation/cpp/CppUtil.java | 25 +------- .../sbe/generation/csharp/CSharp.java | 3 + .../generation/csharp/CSharpGenerator.java | 5 ++ .../sbe/generation/csharp/CSharpUtil.java | 24 +------- .../generation/golang/GolangGenerator.java | 4 ++ .../sbe/generation/golang/GolangUtil.java | 24 +------- .../sbe/generation/java/JavaGenerator.java | 3 + .../sbe/generation/java/JavaUtil.java | 2 +- .../real_logic/sbe/ir/MessageComponents.java | 58 ------------------ .../java/uk/co/real_logic/sbe/ir/Signal.java | 34 +++++------ .../sbe/json/JsonTokenListener.java | 3 + 18 files changed, 77 insertions(+), 223 deletions(-) delete mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/NamedToken.java delete mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java index 22ae107bc0..f2112e2a52 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java @@ -27,6 +27,9 @@ import java.util.Map; import java.util.Set; +/** + * Selects sorted methods of a class that are annotated with {@link GroupOrder}. + */ public class MethodSelector { private final Set ignoredMethods; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java index dc219002d5..8b9d02c964 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java @@ -21,6 +21,9 @@ import java.util.List; import java.util.function.BiConsumer; +/** + * Common operations available to all {@link CodeGenerator}s. + */ public class Generators { /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/NamedToken.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/NamedToken.java deleted file mode 100644 index 7858940615..0000000000 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/NamedToken.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2013-2020 Real Logic Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.generation; - -import uk.co.real_logic.sbe.ir.Token; - -import java.util.ArrayList; -import java.util.List; - -import static uk.co.real_logic.sbe.generation.Generators.forEachField; - -public class NamedToken -{ - private final String name; - private final Token typeToken; - - public NamedToken(final String name, final Token typeToken) - { - this.name = name; - this.typeToken = typeToken; - } - - public String name() - { - return name; - } - - public Token typeToken() - { - return typeToken; - } - - public static List gatherNamedNonConstantFieldTokens(final List fields) - { - final List namedTokens = new ArrayList<>(); - forEachField(fields, (f, t) -> - { - if (!f.isConstantEncoding()) - { - namedTokens.add(new NamedToken(f.name(), t)); - } - }); - - return namedTokens; - } -} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index e23b246923..ae0b51d873 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -27,8 +27,15 @@ import static uk.co.real_logic.sbe.SbeTool.*; +/** + * Loader for {@link CodeGenerator}s which target a language. This provide convenient short names rather than the + * fully qualified class name of the generator. + */ public enum TargetCodeGeneratorLoader implements TargetCodeGenerator { + /** + * Generates codecs for the Java 8 programming language. + */ JAVA() { public CodeGenerator newInstance(final Ir ir, final String outputDir) @@ -44,6 +51,9 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) } }, + /** + * Generates codecs for the C11 programming language. + */ C() { public CodeGenerator newInstance(final Ir ir, final String outputDir) @@ -52,6 +62,9 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) } }, + /** + * Generates codecs for the C++11 programming language with some conditional includes for C++14 and C++17. + */ CPP() { public CodeGenerator newInstance(final Ir ir, final String outputDir) @@ -60,6 +73,9 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) } }, + /** + * Generates codecs for the Go programming language. + */ GOLANG() { public CodeGenerator newInstance(final Ir ir, final String outputDir) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 9425d79b56..795a3bd5a0 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -31,9 +31,14 @@ import java.util.ArrayList; import java.util.List; +import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; +import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; import static uk.co.real_logic.sbe.generation.c.CUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.*; +/** + * Codec generator for the C11 programming language. + */ @SuppressWarnings("MethodLength") public class CGenerator implements CodeGenerator { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java index b150f7ae2e..6f21674564 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java @@ -23,6 +23,8 @@ import java.util.EnumMap; import java.util.Map; +import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; + /** * Utilities for mapping between IR and the C language. */ @@ -56,28 +58,6 @@ public static String cTypeName(final PrimitiveType primitiveType) return PRIMITIVE_TYPE_STRING_ENUM_MAP.get(primitiveType); } - /** - * Uppercase the first character of a given String. - * - * @param str to have the first character upper cased. - * @return a new String with the first character in uppercase. - */ - public static String toUpperFirstChar(final String str) - { - return Character.toUpperCase(str.charAt(0)) + str.substring(1); - } - - /** - * Lowercase the first character of a given String. - * - * @param str to have the first character upper cased. - * @return a new String with the first character in uppercase. - */ - public static String toLowerFirstChar(final String str) - { - return Character.toLowerCase(str.charAt(0)) + str.substring(1); - } - /** * Format a String as a property name. * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 858335be61..d64673b240 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -33,9 +33,14 @@ import java.util.Formatter; import java.util.List; +import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; +import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; import static uk.co.real_logic.sbe.generation.cpp.CppUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.*; +/** + * Codec generator for the C++11 programming language with conditional complication for C++14 and C++17 features. + */ @SuppressWarnings("MethodLength") public class CppGenerator implements CodeGenerator { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index 5a41e8157a..2abd4f163b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -23,6 +23,9 @@ import java.util.EnumMap; import java.util.Map; +import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; +import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; + /** * Utilities for mapping between IR and the C++ language. */ @@ -56,28 +59,6 @@ public static String cppTypeName(final PrimitiveType primitiveType) return PRIMITIVE_TYPE_STRING_ENUM_MAP.get(primitiveType); } - /** - * Uppercase the first character of a given String. - * - * @param str to have the first character upper cased. - * @return a new String with the first character in uppercase. - */ - public static String toUpperFirstChar(final String str) - { - return Character.toUpperCase(str.charAt(0)) + str.substring(1); - } - - /** - * Lowercase the first character of a given String. - * - * @param str to have the first character upper cased. - * @return a new String with the first character in uppercase. - */ - public static String toLowerFirstChar(final String str) - { - return Character.toLowerCase(str.charAt(0)) + str.substring(1); - } - /** * Format a String as a property name. * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java index a8feda1e8f..22234384de 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java @@ -19,6 +19,9 @@ import uk.co.real_logic.sbe.generation.TargetCodeGenerator; import uk.co.real_logic.sbe.ir.Ir; +/** + * {@link CodeGenerator} factory for the CSharp target programming language. + */ public class CSharp implements TargetCodeGenerator { public CodeGenerator newInstance(final Ir ir, final String outputDir) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 3851e848c8..e3671c14c0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -30,11 +30,16 @@ import java.util.ArrayList; import java.util.List; +import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; +import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; import static uk.co.real_logic.sbe.generation.csharp.CSharpUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; +/** + * Codec generator for the CSharp programming language. + */ @SuppressWarnings("MethodLength") public class CSharpGenerator implements CodeGenerator { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index bd8d20d469..d86109f7e8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -21,6 +21,8 @@ import java.util.EnumMap; import java.util.Map; +import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; + /** * Utilities for mapping between IR and the C# language. */ @@ -57,28 +59,6 @@ public static String cSharpTypeName(final PrimitiveType primitiveType) return PRIMITIVE_TYPE_STRING_ENUM_MAP.get(primitiveType); } - /** - * Uppercase the first character of a given String. - * - * @param str to have the first character upper cased. - * @return a new String with the first character in uppercase. - */ - public static String toUpperFirstChar(final String str) - { - return Character.toUpperCase(str.charAt(0)) + str.substring(1); - } - - /** - * Lowercase the first character of a given String. - * - * @param str to have the first character upper cased. - * @return a new String with the first character in uppercase. - */ - public static String toLowerFirstChar(final String str) - { - return Character.toLowerCase(str.charAt(0)) + str.substring(1); - } - /** * Format a String as a property name. * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index fc2b621d72..e2f2468b0e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -33,11 +33,15 @@ import java.util.TreeSet; import static uk.co.real_logic.sbe.PrimitiveType.CHAR; +import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; import static uk.co.real_logic.sbe.generation.golang.GolangUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; +/** + * Codec generator for the Go Lang programming language. + */ @SuppressWarnings("MethodLength") public class GolangGenerator implements CodeGenerator { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java index 45dc74d6c5..1a3d3b551f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java @@ -22,6 +22,8 @@ import java.util.EnumMap; import java.util.Map; +import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; + /** * Utilities for mapping between IR and the Golang language. */ @@ -84,28 +86,6 @@ public static String golangMarshalType(final PrimitiveType primitiveType) return MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP.get(primitiveType); } - /** - * Uppercase the first character of a given String. - * - * @param str to have the first character upper cased. - * @return a new String with the first character in uppercase. - */ - public static String toUpperFirstChar(final String str) - { - return Character.toUpperCase(str.charAt(0)) + str.substring(1); - } - - /** - * Lowercase the first character of a given String. - * - * @param str to have the first character upper cased. - * @return a new String with the first character in uppercase. - */ - public static String toLowerFirstChar(final String str) - { - return Character.toLowerCase(str.charAt(0)) + str.substring(1); - } - /** * Format a String as a property name. * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 2a083010b2..cc7424ea07 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -36,6 +36,9 @@ import static uk.co.real_logic.sbe.generation.java.JavaUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.*; +/** + * Generate codecs for the Java 8 programming language. + */ @SuppressWarnings("MethodLength") public class JavaGenerator implements CodeGenerator { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index a532740fd0..35df2dd99f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -32,7 +32,7 @@ import static java.lang.reflect.Modifier.STATIC; /** - * Utilities for mapping between IR and the Java language. + * Utilities for mapping between {@link uk.co.real_logic.sbe.ir.Ir} and the Java language. */ public class JavaUtil { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java deleted file mode 100644 index 83e51764e9..0000000000 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/MessageComponents.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2013-2020 Real Logic Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.ir; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Collect the message components (fields, groups, data) to help with generating codecs. - */ -public class MessageComponents -{ - public final Token messageToken; - public final List fields; - public final List groups; - public final List varData; - - public MessageComponents( - final Token messageToken, final List fields, final List groups, final List varData) - { - this.messageToken = messageToken; - this.fields = Collections.unmodifiableList(fields); - this.groups = Collections.unmodifiableList(groups); - this.varData = Collections.unmodifiableList(varData); - } - - public static MessageComponents collectMessageComponents(final List tokens) - { - final Token msgToken = tokens.get(0); - final List messageBody = GenerationUtil.getMessageBody(tokens); - - int i = 0; - final List fields = new ArrayList<>(); - i = GenerationUtil.collectFields(messageBody, i, fields); - - final List groups = new ArrayList<>(); - i = GenerationUtil.collectGroups(messageBody, i, groups); - - final List varData = new ArrayList<>(); - GenerationUtil.collectVarData(messageBody, i, varData); - - return new MessageComponents(msgToken, fields, groups, varData); - } -} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java index 99656faa94..03a8cd9f9f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java @@ -22,87 +22,87 @@ public enum Signal { /** - * Denotes the beginning of a message + * Denotes the beginning of a message. */ BEGIN_MESSAGE, /** - * Denotes the end of a message + * Denotes the end of a message. */ END_MESSAGE, /** - * Denotes the beginning of a composite + * Denotes the beginning of a composite. */ BEGIN_COMPOSITE, /** - * Denotes the end of a composite + * Denotes the end of a composite. */ END_COMPOSITE, /** - * Denotes the beginning of a field + * Denotes the beginning of a field. */ BEGIN_FIELD, /** - * Denotes the end of a field + * Denotes the end of a field. */ END_FIELD, /** - * Denotes the beginning of a repeating group + * Denotes the beginning of a repeating group. */ BEGIN_GROUP, /** - * Denotes the end of a repeating group + * Denotes the end of a repeating group. */ END_GROUP, /** - * Denotes the beginning of an enumeration + * Denotes the beginning of an enumeration. */ BEGIN_ENUM, /** - * Denotes a value of an enumeration + * Denotes a value of an enumeration. */ VALID_VALUE, /** - * Denotes the end of an enumeration + * Denotes the end of an enumeration. */ END_ENUM, /** - * Denotes the beginning of a bitset + * Denotes the beginning of a bitset. */ BEGIN_SET, /** - * Denotes a bit value (choice) of a bitset + * Denotes a bit value (choice) of a bitset. */ CHOICE, /** - * Denotes the end of a bitset + * Denotes the end of a bitset. */ END_SET, /** - * Denotes the beginning of a variable data block + * Denotes the beginning of a variable data block. */ BEGIN_VAR_DATA, /** - * Denotes the end of a variable data block + * Denotes the end of a variable data block. */ END_VAR_DATA, /** - * Denotes the {@link uk.co.real_logic.sbe.ir.Token} is an encoding + * Denotes the {@link uk.co.real_logic.sbe.ir.Token} is an encoding. */ ENCODING } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index f86506b75b..2435d347dd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -27,6 +27,9 @@ import static uk.co.real_logic.sbe.PrimitiveType.CHAR; +/** + * Listener for tokens when dynamically decoding a message which converts them to Json for output. + */ public class JsonTokenListener implements TokenListener { private final StringBuilder output; From 803b8b2274d98cc5717c4ce70b5a3cde16b85286 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 23 May 2020 18:16:08 +0100 Subject: [PATCH 0438/1594] [Java] README update. --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8fd6f5fe93..e7aa82a683 100644 --- a/README.md +++ b/README.md @@ -12,17 +12,15 @@ Simple Binary Encoding (SBE) encoding and decoding binary application messages for low-latency financial applications. This repository contains the reference implementations in Java, C++, Golang, and C#. -Further details on the background and usage of SBE can be found on the -[Wiki](https://github.com/real-logic/simple-binary-encoding/wiki). +For more details on the design and usage of SBE can be found on the [Wiki](https://github.com/real-logic/simple-binary-encoding/wiki). An XSD for SBE specs can be found [here](https://github.com/real-logic/simple-binary-encoding/blob/master/sbe-tool/src/main/resources/fpl/sbe.xsd). Please address questions about the specification to the [SBE FIX community](https://github.com/FIXTradingCommunity/fix-simple-binary-encoding). For the latest version information and changes see the [Change Log](https://github.com/real-logic/simple-binary-encoding/wiki/Change-Log) with **downloads** at [Maven Central](http://search.maven.org/#search%7Cga%7C1%7Csbe). -The Java and C++ SBE implementations are designed with work very efficiently with the -[Aeron](https://github.com/real-logic/aeron) messaging system for low-latency and -high-throughput communications. The Java SBE implementation has a dependency on +The Java and C++ SBE implementations work very efficiently with the [Aeron](https://github.com/real-logic/aeron) +messaging system for low-latency and high-throughput communications. The Java SBE implementation has a dependency on [Agrona](https://github.com/real-logic/agrona) for its buffer implementations. Binaries @@ -36,7 +34,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.17.0 +    1.18.0 ``` From 250fd8fa02df2b2a08b6016386c36075f7d89463 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 23 May 2020 18:17:04 +0100 Subject: [PATCH 0439/1594] [Java] README update. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e7aa82a683..a23d5badd8 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Simple Binary Encoding (SBE) encoding and decoding binary application messages for low-latency financial applications. This repository contains the reference implementations in Java, C++, Golang, and C#. -For more details on the design and usage of SBE can be found on the [Wiki](https://github.com/real-logic/simple-binary-encoding/wiki). +More details on the design and usage of SBE can be found on the [Wiki](https://github.com/real-logic/simple-binary-encoding/wiki). An XSD for SBE specs can be found [here](https://github.com/real-logic/simple-binary-encoding/blob/master/sbe-tool/src/main/resources/fpl/sbe.xsd). Please address questions about the specification to the [SBE FIX community](https://github.com/FIXTradingCommunity/fix-simple-binary-encoding). From 8ea5070dd9ad0671e99a8a17153087983e8e18a2 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 23 May 2020 10:52:25 -0700 Subject: [PATCH 0440/1594] 1.18.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index dacb57abf2..744068368f 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.18.0-SNAPSHOT \ No newline at end of file +1.18.0 \ No newline at end of file From 63a2e7ea25efa8f07054ba4b09bfffb81725314f Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 23 May 2020 10:53:52 -0700 Subject: [PATCH 0441/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 744068368f..7a4570dd0a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.18.0 \ No newline at end of file +1.18.1-SNAPSHOT \ No newline at end of file From 244a587f0e67f633e0bb522d05b76b70e6354ffe Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 23 May 2020 19:27:04 +0100 Subject: [PATCH 0442/1594] [Java] Check for var data when requiring imports needs to consider nested var data in groups. --- .../sbe/generation/java/JavaGenerator.java | 21 +++++++++++++------ .../co/real_logic/sbe/ir/GenerationUtil.java | 13 ++++++++++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index cc7424ea07..0279dd2484 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -171,6 +171,7 @@ public void generate() throws IOException { final Token msgToken = tokens.get(0); final List messageBody = getMessageBody(tokens); + final boolean hasVarData = -1 != findSignal(messageBody, Signal.BEGIN_VAR_DATA); int i = 0; final List fields = new ArrayList<>(); @@ -182,13 +183,17 @@ public void generate() throws IOException final List varData = new ArrayList<>(); collectVarData(messageBody, i, varData); - generateDecoder(fields, groups, varData, msgToken); - generateEncoder(fields, groups, varData, msgToken); + generateDecoder(msgToken, fields, groups, varData, hasVarData); + generateEncoder(msgToken, fields, groups, varData, hasVarData); } } private void generateEncoder( - final List fields, final List groups, final List varData, final Token msgToken) + final Token msgToken, + final List fields, + final List groups, + final List varData, + final boolean hasVarData) throws IOException { final String className = formatClassName(encoderName(msgToken.name())); @@ -196,7 +201,7 @@ private void generateEncoder( try (Writer out = outputManager.createOutput(className)) { - out.append(generateMainHeader(ir.applicableNamespace(), ENCODER, !varData.isEmpty())); + out.append(generateMainHeader(ir.applicableNamespace(), ENCODER, hasVarData)); generateAnnotations(BASE_INDENT, className, groups, out, 0, this::encoderName); out.append(generateDeclaration(className, implementsString, msgToken)); @@ -215,7 +220,11 @@ private void generateEncoder( } private void generateDecoder( - final List fields, final List groups, final List varData, final Token msgToken) + final Token msgToken, + final List fields, + final List groups, + final List varData, + final boolean hasVarData) throws IOException { final String className = formatClassName(decoderName(msgToken.name())); @@ -223,7 +232,7 @@ private void generateDecoder( try (Writer out = outputManager.createOutput(className)) { - out.append(generateMainHeader(ir.applicableNamespace(), DECODER, !varData.isEmpty())); + out.append(generateMainHeader(ir.applicableNamespace(), DECODER, hasVarData)); generateAnnotations(BASE_INDENT, className, groups, out, 0, this::decoderName); out.append(generateDeclaration(className, implementsString, msgToken)); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java index 735266ec58..7d5fbe3d06 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java @@ -107,4 +107,17 @@ public static List findSubGroupNames(final List tokens) return groupNames; } + + public static int findSignal(final List tokens, final Signal signal) + { + for (int i = 0, endIndex = tokens.size() - 1; i < endIndex; i++) + { + if (signal == tokens.get(i).signal()) + { + return i; + } + } + + return -1; + } } From f01b1c485198fc913621b3a2ce86654890cee718 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 23 May 2020 19:27:54 +0100 Subject: [PATCH 0443/1594] [Java] Update README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a23d5badd8..a4186e8081 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.18.0 +    1.18.1 ``` From 4257c6df04a0033dda601caaea98ee871bc6efa5 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 23 May 2020 12:43:46 -0700 Subject: [PATCH 0444/1594] 1.18.1 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 7a4570dd0a..5ce8b39599 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.18.1-SNAPSHOT \ No newline at end of file +1.18.1 \ No newline at end of file From ee1cdfcc524d88027fdc103cb0150c0fbb8e47f2 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 23 May 2020 12:45:36 -0700 Subject: [PATCH 0445/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 5ce8b39599..5b2c5d3f7c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.18.1 \ No newline at end of file +1.18.2-SNAPSHOT \ No newline at end of file From 3ad2f9d131b1bfcbad94999ada670b3a44f28c3d Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Mon, 25 May 2020 02:47:09 +0800 Subject: [PATCH 0446/1594] Move include Windows.h into Cpp --- sbe-benchmarks/src/main/cpp/benchlet-main.cpp | 21 ++++++++++++++++++- sbe-benchmarks/src/main/cpp/benchlet.h | 17 +-------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp index 333f3b3f1f..9dc05bda18 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp +++ b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp @@ -19,4 +19,23 @@ int main(int argc, char **argv) { BenchmarkRunner::run(); return 0; -} \ No newline at end of file +} + +#ifdef _WIN32 +#include +uint64_t BenchmarkRunner::currentTimestamp(void) +{ + static LARGE_INTEGER freq; + static int first = 1; + LARGE_INTEGER counter; + + ::QueryPerformanceCounter(&counter); + if (1 == first) + { + ::QueryPerformanceFrequency(&freq); + first = 0; + } + return (1000000000 * counter.QuadPart)/freq.QuadPart; +} + +#endif \ No newline at end of file diff --git a/sbe-benchmarks/src/main/cpp/benchlet.h b/sbe-benchmarks/src/main/cpp/benchlet.h index bdd489224d..fa4b5926b9 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet.h +++ b/sbe-benchmarks/src/main/cpp/benchlet.h @@ -28,7 +28,6 @@ #elif defined(__linux__) # include #elif defined(WIN32) || defined(_WIN32) -# include #else # error "Must define Darwin or __linux__ or WIN32" #endif /* platform includes */ @@ -213,21 +212,7 @@ class BenchmarkRunner return end_timestamp - start_timestamp; }; #elif defined(WIN32) || defined(_WIN32) - static uint64_t currentTimestamp(void) - { - static LARGE_INTEGER freq; - static int first = 1; - LARGE_INTEGER counter; - - ::QueryPerformanceCounter(&counter); - if (1 == first) - { - ::QueryPerformanceFrequency(&freq); - first = 0; - } - return (1000000000 * counter.QuadPart)/freq.QuadPart; - } - + static uint64_t currentTimestamp(void); static uint64_t elapsedNanoseconds(uint64_t start_timestamp, uint64_t end_timestamp) { return end_timestamp - start_timestamp; From 7dafac5553f8137280ad35525ce0bb6234bfa772 Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Sun, 24 May 2020 20:20:18 +0800 Subject: [PATCH 0447/1594] Generate integer literal properly --- .../sbe/generation/c/CGenerator.java | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 795a3bd5a0..e3ae89b7ae 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -2403,24 +2403,39 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu break; case UINT32: + { + final long intValue = Long.parseLong(value); + literal = "UINT32_C(0x" + Integer.toHexString((int)intValue) + ")"; + break; + } + case INT32: - literal = value; + { + final long intValue = Long.parseLong(value); + literal = "INT32_C(" + Integer.toString((int)intValue) + ")"; break; + } case FLOAT: literal = value.endsWith("NaN") ? "SBE_FLOAT_NAN" : value + "f"; break; case INT64: - literal = value + "L"; - if (value.equals("-9223372036854775808")) + { + final long longValue = Long.parseLong(value); + if (longValue == -9223372036854775808L) { literal = "INT64_MIN"; } + else + { + literal = "INT64_C(" + String.valueOf(longValue) + ")"; + } break; + } case UINT64: - literal = "0x" + Long.toHexString(Long.parseLong(value)) + "L"; + literal = "UINT64_C(0x" + Long.toHexString(Long.parseLong(value)) + ")"; break; case DOUBLE: From 21b166caea6405c8d0db4f94a19cbb326fa76294 Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Mon, 25 May 2020 18:52:45 +0800 Subject: [PATCH 0448/1594] Show ident with 4. (#782) --- .../java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 795a3bd5a0..b72d545e43 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -2271,8 +2271,8 @@ private void generateEnumProperty( sb.append(String.format("\n" + "SBE_ONE_DEF struct %1$s *%1$s_set_%2$s(\n" + - " struct %1$s *const codec,\n" + - " const enum %3$s value)\n" + + " struct %1$s *const codec,\n" + + " const enum %3$s value)\n" + "{\n" + " %4$s val = %6$s(value);\n" + " memcpy(codec->buffer + codec->offset + %5$d, &val, sizeof(%4$s));\n\n" + From c60d8cf44eebd01d573da651ec29207254817149 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 26 May 2020 10:52:29 +0200 Subject: [PATCH 0449/1594] [Go] Restore `golang/templates` in the build, because they are required to generate marshaling code --- build.gradle | 5 ----- 1 file changed, 5 deletions(-) diff --git a/build.gradle b/build.gradle index 1019feba3e..5d3977f4b0 100644 --- a/build.gradle +++ b/build.gradle @@ -234,8 +234,6 @@ project(':sbe-tool') { } jar { - exclude 'golang/templates' - manifest.attributes( 'Specification-Title': 'Simple Binary Encoding', 'Specification-Version': '1.0', @@ -251,9 +249,7 @@ project(':sbe-tool') { from sourceSets.main.allSource from ('src/main/cpp/otf') { into 'cpp' - } - exclude 'golang/templates' } java { @@ -315,7 +311,6 @@ project(':sbe-all') { from (project(':sbe-tool').file('src/main/cpp/otf')) { into 'cpp' } - exclude 'golang/templates' } javadoc { From 82596e02b4b330467b1a8ba13a0160e766436a3c Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 May 2020 00:14:24 +0200 Subject: [PATCH 0450/1594] [C++] Add Windows build to the CI matrix --- .github/workflows/ci.yml | 14 ++++++++++++++ cppbuild/{cppbuild-vs2015.cmd => cppbuild.cmd} | 9 +++++++-- cppbuild/vs-helper.cmd | 2 ++ 3 files changed, 23 insertions(+), 2 deletions(-) rename cppbuild/{cppbuild-vs2015.cmd => cppbuild.cmd} (54%) create mode 100644 cppbuild/vs-helper.cmd diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 503b2d0348..aeef260a2d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -168,3 +168,17 @@ jobs: sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app - name: Build run: ./cppbuild/cppbuild + + cpp-msvc-build: + name: C++ MSVC (Windows) + runs-on: windows-latest + strategy: + fail-fast: false + env: + CC: cl + CXX: cl + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Build + run: cppbuild/cppbuild.cmd diff --git a/cppbuild/cppbuild-vs2015.cmd b/cppbuild/cppbuild.cmd similarity index 54% rename from cppbuild/cppbuild-vs2015.cmd rename to cppbuild/cppbuild.cmd index 0d0777757f..05fafd988d 100644 --- a/cppbuild/cppbuild-vs2015.cmd +++ b/cppbuild/cppbuild.cmd @@ -1,14 +1,19 @@ @if "%DEBUG%" == "" @echo off -setlocal +setlocal EnableDelayedExpansion set SOURCE_DIR=%CD% set BUILD_DIR=%CD%\cppbuild\Release +call cppbuild/vs-helper.cmd +if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% + if EXIST %BUILD_DIR% rd /S /Q %BUILD_DIR% md %BUILD_DIR% pushd %BUILD_DIR% -cmake -G "Visual Studio 14 Win64" %SOURCE_DIR% cmake --build . --clean-first --config Release +if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% + ctest -C Release +if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% diff --git a/cppbuild/vs-helper.cmd b/cppbuild/vs-helper.cmd new file mode 100644 index 0000000000..d35a611046 --- /dev/null +++ b/cppbuild/vs-helper.cmd @@ -0,0 +1,2 @@ +rem Invoke script to set all of the Visual Studio ENV variables +@for /f "usebackq delims=#" %%a in (`"%programfiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -latest -property installationPath`) do "%%a\Common7\Tools\VsDevCmd.bat" \ No newline at end of file From 2eb4660aed5d464ea433271cc41e1b3972abdd38 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 May 2020 00:51:57 +0200 Subject: [PATCH 0451/1594] [C++] Pass SOURCE_DIR --- cppbuild/cppbuild.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppbuild/cppbuild.cmd b/cppbuild/cppbuild.cmd index 05fafd988d..0cb48eda04 100644 --- a/cppbuild/cppbuild.cmd +++ b/cppbuild/cppbuild.cmd @@ -12,7 +12,7 @@ if EXIST %BUILD_DIR% rd /S /Q %BUILD_DIR% md %BUILD_DIR% pushd %BUILD_DIR% -cmake --build . --clean-first --config Release +cmake --build . --clean-first --config Release %SOURCE_DIR% if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% ctest -C Release From ef74a9dab6389a59b86ce61f09e93d2a315e2f80 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 May 2020 00:53:48 +0200 Subject: [PATCH 0452/1594] Revert "[C++] Pass SOURCE_DIR" This reverts commit 2eb4660a --- cppbuild/cppbuild.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppbuild/cppbuild.cmd b/cppbuild/cppbuild.cmd index 0cb48eda04..05fafd988d 100644 --- a/cppbuild/cppbuild.cmd +++ b/cppbuild/cppbuild.cmd @@ -12,7 +12,7 @@ if EXIST %BUILD_DIR% rd /S /Q %BUILD_DIR% md %BUILD_DIR% pushd %BUILD_DIR% -cmake --build . --clean-first --config Release %SOURCE_DIR% +cmake --build . --clean-first --config Release if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% ctest -C Release From 3e25bb97cc7f3af590c12a5956fdbb8d8a67576c Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 May 2020 00:58:56 +0200 Subject: [PATCH 0453/1594] [C++] Remove `--clean-first` --- cppbuild/cppbuild.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppbuild/cppbuild.cmd b/cppbuild/cppbuild.cmd index 05fafd988d..8d635238d9 100644 --- a/cppbuild/cppbuild.cmd +++ b/cppbuild/cppbuild.cmd @@ -12,7 +12,7 @@ if EXIST %BUILD_DIR% rd /S /Q %BUILD_DIR% md %BUILD_DIR% pushd %BUILD_DIR% -cmake --build . --clean-first --config Release +cmake --build . --config Release if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% ctest -C Release From 35b1613ee16958230e0588ccc84240f7fa8edcc4 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 May 2020 01:02:17 +0200 Subject: [PATCH 0454/1594] Revert "[C++] Remove `--clean-first`" This reverts commit 3e25bb97 --- cppbuild/cppbuild.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppbuild/cppbuild.cmd b/cppbuild/cppbuild.cmd index 8d635238d9..05fafd988d 100644 --- a/cppbuild/cppbuild.cmd +++ b/cppbuild/cppbuild.cmd @@ -12,7 +12,7 @@ if EXIST %BUILD_DIR% rd /S /Q %BUILD_DIR% md %BUILD_DIR% pushd %BUILD_DIR% -cmake --build . --config Release +cmake --build . --clean-first --config Release if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% ctest -C Release From 3a7f7014139be12823c4e291444c22f141d56cd6 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 May 2020 01:03:37 +0200 Subject: [PATCH 0455/1594] [C++] Remove Windows build for now --- .github/workflows/ci.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aeef260a2d..503b2d0348 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -168,17 +168,3 @@ jobs: sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app - name: Build run: ./cppbuild/cppbuild - - cpp-msvc-build: - name: C++ MSVC (Windows) - runs-on: windows-latest - strategy: - fail-fast: false - env: - CC: cl - CXX: cl - steps: - - name: Checkout code - uses: actions/checkout@v2 - - name: Build - run: cppbuild/cppbuild.cmd From f19b1361a262e515c21c339614984a4cc7411da8 Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Mon, 25 May 2020 02:37:33 +0800 Subject: [PATCH 0456/1594] Fixes a cpp warning. --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index d64673b240..7f2385b67e 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1947,7 +1947,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final " return %2$s;\n" + " }\n\n" + - " SBE_NODISCARD static SBE_CONSTEXPR %1$s sbeBlockAndHeaderLength() SBE_NOEXCEPT\n" + + " SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t sbeBlockAndHeaderLength() SBE_NOEXCEPT\n" + " {\n" + " return messageHeader::encodedLength() + sbeBlockLength();\n" + " }\n\n" + From ddba719eb5c205e01ad4aab6532f7844b365ed1f Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Wed, 27 May 2020 07:46:48 +0800 Subject: [PATCH 0457/1594] More C String literal improve --- .../uk/co/real_logic/sbe/generation/c/CGenerator.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 91045b2279..173d35830e 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -2412,7 +2412,14 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu case INT32: { final long intValue = Long.parseLong(value); - literal = "INT32_C(" + Integer.toString((int)intValue) + ")"; + if (intValue == Integer.MIN_VALUE) + { + literal = "INT32_MIN"; + } + else + { + literal = "INT32_C(" + Long.toString(intValue) + ")"; + } break; } @@ -2423,7 +2430,7 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu case INT64: { final long longValue = Long.parseLong(value); - if (longValue == -9223372036854775808L) + if (longValue == Long.MIN_VALUE) { literal = "INT64_MIN"; } From e99c02499d588ff935fc78356f13190cdce0434f Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Wed, 27 May 2020 07:50:15 +0800 Subject: [PATCH 0458/1594] Cpp literal improve. --- .../sbe/generation/cpp/CppGenerator.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index d64673b240..bc78783cbd 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2407,8 +2407,21 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu break; case UINT32: + { + final long intValue = Long.parseLong(value); + literal = "UINT32_C(0x" + Integer.toHexString((int)intValue) + ")"; + break; + } case INT32: - literal = value; + final long intValue = Long.parseLong(value); + if (intValue == Integer.MIN_VALUE) + { + literal = "INT32_MIN"; + } + else + { + literal = "INT32_C(" + Long.toString(intValue) + ")"; + } break; case FLOAT: @@ -2416,15 +2429,19 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu break; case INT64: - literal = value + "L"; - if (value.equals("-9223372036854775808")) + final long longValue = Long.parseLong(value); + if (longValue == Long.MIN_VALUE) { literal = "INT64_MIN"; } + else + { + literal = "INT64_C(" + String.valueOf(longValue) + ")"; + } break; case UINT64: - literal = "0x" + Long.toHexString(Long.parseLong(value)) + "L"; + literal = "UINT64_C(0x" + Long.toHexString(Long.parseLong(value)) + ")"; break; case DOUBLE: From bdaba5f760ff81ff8f00de3d0daa582c572520b5 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 May 2020 13:37:13 +0200 Subject: [PATCH 0459/1594] [C++] Enable C++ Windows build --- .github/workflows/ci.yml | 14 ++++++++++++++ CMakeLists.txt | 38 ++++++++++++++++++++++++++++++++++++-- cppbuild/cppbuild.cmd | 25 ++++++++++++++++++++++++- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 503b2d0348..aeef260a2d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -168,3 +168,17 @@ jobs: sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app - name: Build run: ./cppbuild/cppbuild + + cpp-msvc-build: + name: C++ MSVC (Windows) + runs-on: windows-latest + strategy: + fail-fast: false + env: + CC: cl + CXX: cl + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Build + run: cppbuild/cppbuild.cmd diff --git a/CMakeLists.txt b/CMakeLists.txt index 5397c98be9..406d03f96d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,8 @@ endif () option(SBE_TESTS "Enable tests" ${STANDALONE_BUILD}) option(SBE_BUILD_SAMPLES "Enable building the sample projects" ${STANDALONE_BUILD}) option(SBE_BUILD_BENCHMARKS "Enable building the benchmarks" ${STANDALONE_BUILD}) +option(C_WARNINGS_AS_ERRORS "Enable warnings as errors for C" OFF) +option(CXX_WARNINGS_AS_ERRORS "Enable warnings as errors for C++" OFF) unset(STANDALONE_BUILD) @@ -80,6 +82,12 @@ if (SBE_TESTS) ExternalProject_Get_Property(gtest binary_dir) set(GTEST_BINARY_DIR ${binary_dir}) + if (MSVC AND CMAKE_BUILD_TYPE STREQUAL "Debug") + set(GTEST_POSTFIX "d") + else () + set(GTEST_POSTFIX "") + endif () + set(GTEST_LIBS ${GTEST_BINARY_DIR}/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX} ${GTEST_BINARY_DIR}/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gtest${CMAKE_STATIC_LIBRARY_SUFFIX} @@ -91,17 +99,42 @@ find_package(Threads) if (UNIX) add_compile_options(-Wall -Wpedantic -Wextra -Wno-unused-parameter) + + if (C_WARNINGS_AS_ERRORS) + add_compile_options($<$:-Werror>) + endif (C_WARNINGS_AS_ERRORS) + + if (CXX_WARNINGS_AS_ERRORS) + add_compile_options($<$:-Werror>) + endif (CXX_WARNINGS_AS_ERRORS) endif () if (APPLE) # -Wall doesn't enable everything we want to see add_compile_options(-Wsign-compare) add_definitions(-DDarwin) + add_compile_options(-Wno-deprecated-register) elseif (MSVC) add_definitions(-DWIN32) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + add_definitions(-D_CRT_NONSTDC_NO_WARNINGS) + add_definitions(-DNOMINMAX) + + if (${MSVC_VERSION} GREATER_EQUAL 1915) + # Acknowledge that we understand MSVC resolved a byte alignment issue in this compiler + add_definitions(-D_ENABLE_EXTENDED_ALIGNED_STORAGE) + endif () + + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd /Od /Zi /MP") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT /MP") + + if (C_WARNINGS_AS_ERRORS) + add_compile_options($<$:/WX>) + endif (C_WARNINGS_AS_ERRORS) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd /Od /Zi") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") + if (CXX_WARNINGS_AS_ERRORS) + add_compile_options($<$:/WX>) + endif (CXX_WARNINGS_AS_ERRORS) else () add_definitions(-D_GNU_SOURCE) endif () @@ -111,6 +144,7 @@ set(LIBSUFFIX "${CMAKE_STATIC_LIBRARY_SUFFIX}") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/binaries") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") set(SBE_JAR "${CMAKE_CURRENT_SOURCE_DIR}/sbe-all/build/libs/sbe-all-${SBE_VERSION_TXT}.jar") diff --git a/cppbuild/cppbuild.cmd b/cppbuild/cppbuild.cmd index 05fafd988d..8a6740851d 100644 --- a/cppbuild/cppbuild.cmd +++ b/cppbuild/cppbuild.cmd @@ -4,6 +4,26 @@ setlocal EnableDelayedExpansion set SOURCE_DIR=%CD% set BUILD_DIR=%CD%\cppbuild\Release +for %%o in (%*) do ( + + set PROCESSED=0 + + if "%%o"=="--help" ( + echo cppbuild.cmd [--c-warnings-as-errors] [--cxx-warnings-as-errors] + exit /b + ) + + if "%%o"=="--c-warnings-as-errors" ( + set EXTRA_CMAKE_ARGS=!EXTRA_CMAKE_ARGS! -DC_WARNINGS_AS_ERRORS=ON + set PROCESSED=1 + ) + + if "%%o"=="--cxx-warnings-as-errors" ( + set EXTRA_CMAKE_ARGS=!EXTRA_CMAKE_ARGS! -DCXX_WARNINGS_AS_ERRORS=ON + set PROCESSED=1 + ) +) + call cppbuild/vs-helper.cmd if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% @@ -12,8 +32,11 @@ if EXIST %BUILD_DIR% rd /S /Q %BUILD_DIR% md %BUILD_DIR% pushd %BUILD_DIR% +cmake %EXTRA_CMAKE_ARGS% %SOURCE_DIR% +if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% + cmake --build . --clean-first --config Release if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% -ctest -C Release +ctest -C Release --output-on-failure if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% From 32b963f3da508b0b4b4486c81e1a1220ae0d126b Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 May 2020 13:52:10 +0200 Subject: [PATCH 0460/1594] [C++] Add `#include ` to fix Windows build --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index bd336bf8fd..7c01406678 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1073,6 +1073,7 @@ private static CharSequence generateFileHeader( "#include \n" + "#include \n" + "#include \n" + + "#include \n" + "\n" + "#if defined(WIN32) || defined(_WIN32)\n" + From 690e8333e6b24504dfa65d26116ad0fe3da704a1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 27 May 2020 14:22:30 +0100 Subject: [PATCH 0461/1594] [C++] Warnings cleanup. --- sbe-tool/src/test/cpp/CodeGenTest.cpp | 41 ++++++++++++++------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index 0f6a654e8c..cb3db54435 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ #include +#include #include "gtest/gtest.h" #include "code_generation_test/MessageHeader.h" @@ -43,15 +44,15 @@ static const char *MODEL = "Civic VTi"; static const char *ACTIVATION_CODE = "deadbeef"; static const char *COLOR = "racing green"; -static const std::uint64_t VEHICLE_CODE_LENGTH = sizeof(VEHICLE_CODE); -static const std::uint64_t MANUFACTURER_CODE_LENGTH = sizeof(MANUFACTURER_CODE); -static const std::uint64_t FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH = 11; -static const std::uint64_t FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH = 14; -static const std::uint64_t FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH = 13; -static const std::uint64_t MANUFACTURER_LENGTH = 5; -static const std::uint64_t MODEL_LENGTH = 9; -static const std::uint64_t ACTIVATION_CODE_LENGTH = 8; -static const std::uint64_t COLOR_LENGTH = 12; +static const std::size_t VEHICLE_CODE_LENGTH = sizeof(VEHICLE_CODE); +static const std::size_t MANUFACTURER_CODE_LENGTH = sizeof(MANUFACTURER_CODE); +static const std::size_t FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH = strlen(FUEL_FIGURES_1_USAGE_DESCRIPTION); +static const std::size_t FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH = strlen(FUEL_FIGURES_2_USAGE_DESCRIPTION); +static const std::size_t FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH = strlen(FUEL_FIGURES_3_USAGE_DESCRIPTION); +static const std::size_t MANUFACTURER_LENGTH = strlen(MANUFACTURER); +static const std::size_t MODEL_LENGTH = strlen(MODEL); +static const std::size_t ACTIVATION_CODE_LENGTH = strlen(ACTIVATION_CODE); +static const std::size_t COLOR_LENGTH = strlen(COLOR); static const std::uint8_t PERFORMANCE_FIGURES_COUNT = 2; static const std::uint8_t FUEL_FIGURES_COUNT = 3; static const std::uint8_t ACCELERATION_COUNT = 3; @@ -657,13 +658,14 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) EXPECT_EQ(fuelFigures.count(), FUEL_FIGURES_COUNT); #if __cplusplus >= 201103L - fuelFigures.forEach([&](Car::FuelFigures &figures) - { - cbs.countOfFuelFigures++; + fuelFigures.forEach( + [&](Car::FuelFigures &figures) + { + cbs.countOfFuelFigures++; - char tmp[256]; - figures.getUsageDescription(tmp, sizeof(tmp)); - }); + char tmp[256]; + figures.getUsageDescription(tmp, sizeof(tmp)); + }); #else fuelFigures.forEach(cbs); #endif @@ -677,10 +679,11 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) Car::PerformanceFigures::Acceleration acceleration = figures.acceleration(); cbs.countOfPerformanceFigures++; - acceleration.forEach([&](Car::PerformanceFigures::Acceleration&) - { - cbs.countOfAccelerations++; - }); + acceleration.forEach( + [&](Car::PerformanceFigures::Acceleration&) + { + cbs.countOfAccelerations++; + }); }); #else performanceFigures.forEach(cbs); From 5e68fd039c2264c376d05adcc97c82839080ac75 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 27 May 2020 14:32:48 +0100 Subject: [PATCH 0462/1594] [C++] Warnings cleanup. --- sbe-samples/src/main/cpp/OtfExample.cpp | 7 ++++--- sbe-tool/src/main/cpp/otf/IrDecoder.h | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sbe-samples/src/main/cpp/OtfExample.cpp b/sbe-samples/src/main/cpp/OtfExample.cpp index dde1226745..fb0e967fd0 100644 --- a/sbe-samples/src/main/cpp/OtfExample.cpp +++ b/sbe-samples/src/main/cpp/OtfExample.cpp @@ -449,10 +449,11 @@ int main(int argc, char **argv) std::uint64_t actingVersion = headerDecoder.getSchemaVersion(buffer); std::uint64_t blockLength = headerDecoder.getBlockLength(buffer); - std::shared_ptr> messageTokens = irDecoder.message(templateId, actingVersion); + std::shared_ptr> messageTokens = irDecoder.message( + static_cast(templateId), static_cast(actingVersion)); - const std::size_t result = - OtfMessageDecoder::decode(messageBuffer, length, actingVersion, blockLength, messageTokens, tokenListener); + const std::size_t result = OtfMessageDecoder::decode( + messageBuffer, length, actingVersion, blockLength, messageTokens, tokenListener); std::cout << "result = " << result << "\n"; diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index 866ad4b48c..a983c81b27 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -69,7 +69,7 @@ class IrDecoder int decode(const char *filename) { - long fileSize = getFileSize(filename); + long long fileSize = getFileSize(filename); if (fileSize < 0) { @@ -140,7 +140,7 @@ class IrDecoder protected: // OS specifics - static long getFileSize(const char *filename) + static long long getFileSize(const char *filename) { struct stat fileStat; @@ -165,7 +165,7 @@ class IrDecoder int fd = fileno(fptr); while (remaining > 0) { - long sz = ::read(fd, buffer + (length - remaining), 4098 < remaining ? 4098 : remaining); + ssize_t sz = ::read(fd, buffer + (length - remaining), 4098 < remaining ? 4098 : remaining); remaining -= sz; if (sz < 0) { From 08c74a98ba91b576cf01e611b0c58dc0a112b6cd Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 27 May 2020 14:42:33 +0100 Subject: [PATCH 0463/1594] [C++] Warnings cleanup. --- sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h | 12 ++++++------ sbe-tool/src/main/cpp/otf/IrDecoder.h | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h index 12c077bccc..302125201d 100644 --- a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h @@ -22,12 +22,12 @@ using namespace uk::co::real_logic::sbe::benchmarks; char VEHICLE_CODE[] = {'a', 'b', 'c', 'd', 'e', 'f'}; -uint32_t SOMENUMBERS[] = { 1, 2, 3, 4, 5 }; +uint32_t SOME_NUMBERS[] = { 1, 2, 3, 4, 5 }; char MANUFACTURER_CODE[] = {'1', '2', '3'}; const char *MANUFACTURER = "Honda"; -int MANUFACTURERLEN = strlen(MANUFACTURER); +size_t MANUFACTURER_LEN = strlen(MANUFACTURER); const char *MODEL = "Civic VTi"; -int MODELLEN = strlen(MODEL); +size_t MODEL_LEN = strlen(MODEL); class SbeCarCodecBench : public CodecBench { @@ -40,7 +40,7 @@ class SbeCarCodecBench : public CodecBench .available(BooleanType::T) .code(Model::A) .putVehicleCode(VEHICLE_CODE) - .putSomeNumbers((char *)SOMENUMBERS); + .putSomeNumbers((char *)SOME_NUMBERS); car.extras().clear() .cruiseControl(true) @@ -73,8 +73,8 @@ class SbeCarCodecBench : public CodecBench .next().mph(60).seconds(7.1f) .next().mph(100).seconds(11.8f); - car.putManufacturer(MANUFACTURER, MANUFACTURERLEN); - car.putModel(MODEL, MODELLEN); + car.putManufacturer(MANUFACTURER, MANUFACTURER_LEN); + car.putModel(MODEL, MODEL_LEN); return car.encodedLength(); } diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index a983c81b27..3e1f17e0bc 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -28,6 +28,7 @@ #include #include #include +#include #endif /* WIN32 */ #include From 244a216290bf818a798cae0c4e9abd64da21ae73 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 27 May 2020 14:49:37 +0100 Subject: [PATCH 0464/1594] [C++] Warnings cleanup. --- sbe-tool/src/main/cpp/otf/IrDecoder.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index 3e1f17e0bc..6b46de22a1 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -28,7 +28,6 @@ #include #include #include -#include #endif /* WIN32 */ #include @@ -166,7 +165,8 @@ class IrDecoder int fd = fileno(fptr); while (remaining > 0) { - ssize_t sz = ::read(fd, buffer + (length - remaining), 4098 < remaining ? 4098 : remaining); + unsigned int bytes = static_cast(4098 < remaining ? 4098 : remaining); + long long sz = ::read(fd, buffer + (length - remaining), bytes); remaining -= sz; if (sz < 0) { From 26160e1a28d6a02fe04dd89325ef8653d06229c4 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 27 May 2020 14:53:21 +0100 Subject: [PATCH 0465/1594] [Java] Upgrade to Agrona 1.5.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5d3977f4b0..790c3d044d 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.3.3' def junitVersion = '5.6.2' def jmhVersion = '1.23' -def agronaVersion = '1.5.0' +def agronaVersion = '1.5.1' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 87c224a54affe1fb54bec8c8357c8d79e0afc8bf Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 27 May 2020 14:54:01 +0100 Subject: [PATCH 0466/1594] [Java] README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a4186e8081..3038ed0791 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.18.1 +    1.18.2 ``` From 0b52a25eac98401e0c57b5e1df9cb66e04dc5e1d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 27 May 2020 14:59:59 +0100 Subject: [PATCH 0467/1594] [C++] Warnings cleanup. --- sbe-benchmarks/src/main/cpp/CodecBench.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sbe-benchmarks/src/main/cpp/CodecBench.h b/sbe-benchmarks/src/main/cpp/CodecBench.h index bb6a9bc9dc..0cc71b3309 100644 --- a/sbe-benchmarks/src/main/cpp/CodecBench.h +++ b/sbe-benchmarks/src/main/cpp/CodecBench.h @@ -23,12 +23,12 @@ class CodecBench public: int encode_buffer(char *buffer, const int bufferLength) { - return static_cast(this)->encode(buffer, bufferLength); + return static_cast(static_cast(this)->encode(buffer, bufferLength)); }; int decode_buffer(const char *buffer, const int bufferLength) { - return static_cast(this)->decode(buffer, bufferLength); + return static_cast(static_cast(this)->decode(buffer, bufferLength)); }; /* @@ -97,7 +97,9 @@ class CodecBench { ptr += encode_buffer(ptr, bufferLength); } + ptr = buffer; + for (int i = 0; i < n; i++) { ptr += decode_buffer(ptr, bufferLength); From b85fa969c955eabff5a48fc6f1781e9d8a78ac40 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 27 May 2020 15:09:50 +0100 Subject: [PATCH 0468/1594] [C++] Warnings cleanup. --- sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h index 302125201d..6851077284 100644 --- a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h @@ -73,8 +73,8 @@ class SbeCarCodecBench : public CodecBench .next().mph(60).seconds(7.1f) .next().mph(100).seconds(11.8f); - car.putManufacturer(MANUFACTURER, MANUFACTURER_LEN); - car.putModel(MODEL, MODEL_LEN); + car.putManufacturer(MANUFACTURER, static_cast(MANUFACTURER_LEN)); + car.putModel(MODEL, static_cast(MODEL_LEN)); return car.encodedLength(); } From eac0e6bcbcd68212a71a19da7f6d24d29892a381 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 27 May 2020 15:10:41 +0100 Subject: [PATCH 0469/1594] [C++] Formatting. --- sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h index 6851077284..e7c4478b7d 100644 --- a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h @@ -21,9 +21,9 @@ using namespace uk::co::real_logic::sbe::benchmarks; -char VEHICLE_CODE[] = {'a', 'b', 'c', 'd', 'e', 'f'}; +char VEHICLE_CODE[] = { 'a', 'b', 'c', 'd', 'e', 'f' }; uint32_t SOME_NUMBERS[] = { 1, 2, 3, 4, 5 }; -char MANUFACTURER_CODE[] = {'1', '2', '3'}; +char MANUFACTURER_CODE[] = { '1', '2', '3' }; const char *MANUFACTURER = "Honda"; size_t MANUFACTURER_LEN = strlen(MANUFACTURER); const char *MODEL = "Civic VTi"; From ba2229e04969f3cb483f971ce1f2d887bff28223 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 27 May 2020 15:26:02 +0100 Subject: [PATCH 0470/1594] [C++] Warnings cleanup. --- sbe-tool/src/test/c/CodeGenTest.cpp | 34 +++++++------- sbe-tool/src/test/cpp/CodeGenTest.cpp | 68 +++++++++++++++------------ 2 files changed, 55 insertions(+), 47 deletions(-) diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index 688c83178c..785e39e36b 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -58,7 +58,7 @@ static const std::uint8_t FUEL_FIGURES_COUNT = 3; static const std::uint8_t ACCELERATION_COUNT = 3; static const std::uint64_t expectedHeaderSize = 8; -static const std::uint64_t expectedCarSize = 191; +static const std::uint64_t expectedCarEncodedLength = 191; static const std::uint16_t fuel1Speed = 30; static const float fuel1Mpg = 35.9f; @@ -487,14 +487,14 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeHeaderPlusCarCorrectly) const char *bp = buffer; std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer)); - std::uint64_t carSz = encodeCar( + std::uint64_t carEncodedLength = encodeCar( buffer, CGT(messageHeader_encoded_length)(), sizeof(buffer) - CGT(messageHeader_encoded_length)()); EXPECT_EQ(hdrSz, expectedHeaderSize); - EXPECT_EQ(carSz, expectedCarSize); + EXPECT_EQ(carEncodedLength, expectedCarEncodedLength); EXPECT_EQ(*((std::uint16_t *)bp), CGT(car_sbe_block_length)()); - const size_t activationCodePosition = hdrSz + carSz - ACTIVATION_CODE_LENGTH; + const size_t activationCodePosition = hdrSz + carEncodedLength - ACTIVATION_CODE_LENGTH; const size_t activationCodeLengthPosition = activationCodePosition - sizeof(std::uint16_t); EXPECT_EQ(*(std::uint16_t *)(bp + activationCodeLengthPosition), ACTIVATION_CODE_LENGTH); EXPECT_EQ(std::string(bp + activationCodePosition, ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); @@ -505,11 +505,11 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) char buffer[BUFFER_LEN]; std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer)); - std::uint64_t carSz = encodeCar( + std::uint64_t carEncodedLength = encodeCar( buffer, CGT(messageHeader_encoded_length)(), sizeof(buffer) - CGT(messageHeader_encoded_length)()); EXPECT_EQ(hdrSz, expectedHeaderSize); - EXPECT_EQ(carSz, expectedCarSize); + EXPECT_EQ(carEncodedLength, expectedCarEncodedLength); if (!CGT(messageHeader_wrap)(&m_hdrDecoder, buffer, 0, 0, hdrSz)) { @@ -528,7 +528,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) CGT(messageHeader_encoded_length)(), CGT(car_sbe_block_length)(), CGT(car_sbe_schema_version)(), - hdrSz + carSz)) + hdrSz + carEncodedLength)) { throw std::runtime_error(sbe_strerror(errno)); } @@ -669,7 +669,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) EXPECT_EQ(CGT(car_activationCode_length)(&m_carDecoder), ACTIVATION_CODE_LENGTH); EXPECT_EQ(std::string(CGT(car_activationCode)(&m_carDecoder), ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); - EXPECT_EQ(CGT(car_encoded_length)(&m_carDecoder), expectedCarSize); + EXPECT_EQ(CGT(car_encoded_length)(&m_carDecoder), expectedCarEncodedLength); } struct CallbacksForEach @@ -703,10 +703,10 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) } std::uint64_t hdrSz = encodeHdr(hdr); - std::uint64_t carSz = encodeCar(car); + std::uint64_t carEncodedLength = encodeCar(car); EXPECT_EQ(hdrSz, expectedHeaderSize); - EXPECT_EQ(carSz, expectedCarSize); + EXPECT_EQ(carEncodedLength, expectedCarEncodedLength); CGT(messageHeader) hdrDecoder; if (!CGT(messageHeader_reset)(&hdrDecoder, buffer, 0, hdrSz, 0)) @@ -725,7 +725,7 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) &carDecoder, buffer + CGT(messageHeader_encoded_length)(), 0, - carSz, + carEncodedLength, CGT(car_sbe_block_length)(), CGT(car_sbe_schema_version)())) { @@ -797,7 +797,7 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) EXPECT_EQ(CGT(car_get_manufacturer)(&carDecoder, tmp, sizeof(tmp)), ACTIVATION_CODE_LENGTH); EXPECT_EQ(std::string(tmp, ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); - EXPECT_EQ(CGT(car_encoded_length)(&carDecoder), expectedCarSize); + EXPECT_EQ(CGT(car_encoded_length)(&carDecoder), expectedCarEncodedLength); } static const std::size_t offsetVehicleCode = 32; @@ -874,7 +874,7 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) const char *acti = activationCode.c_str(); CGT(car_put_activationCode)(&car, acti, strlen(acti)); - EXPECT_EQ(CGT(car_encoded_length)(&car), expectedCarSize); + EXPECT_EQ(CGT(car_encoded_length)(&car), expectedCarEncodedLength); EXPECT_EQ(std::string(buffer + baseOffset + offsetVehicleCode, VEHICLE_CODE_LENGTH), vehicleCode); @@ -915,12 +915,12 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) CGT(car) carEncoder; CGT(car_reset)(&carEncoder, buffer, 0, sizeof(buffer), CGT(car_sbe_block_length)(), CGT(car_sbe_schema_version)()); - std::uint64_t carSz = encodeCar(carEncoder); + std::uint64_t carEncodedLength = encodeCar(carEncoder); - EXPECT_EQ(carSz, expectedCarSize); + EXPECT_EQ(carEncodedLength, expectedCarEncodedLength); CGT(car) carDecoder; - CGT(car_reset)(&carDecoder, buffer, 0, carSz, CGT(car_sbe_block_length)(), CGT(car_sbe_schema_version)()); + CGT(car_reset)(&carDecoder, buffer, 0, carEncodedLength, CGT(car_sbe_block_length)(), CGT(car_sbe_schema_version)()); std::string vehicleCode(VEHICLE_CODE, CGT(car_vehicleCode_length)()); @@ -997,5 +997,5 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) std::string(ACTIVATION_CODE, ACTIVATION_CODE_LENGTH)); } - EXPECT_EQ(CGT(car_encoded_length)(&carDecoder), expectedCarSize); + EXPECT_EQ(CGT(car_encoded_length)(&carDecoder), expectedCarEncodedLength); } diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index cb3db54435..c78ffddd17 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -58,7 +58,7 @@ static const std::uint8_t FUEL_FIGURES_COUNT = 3; static const std::uint8_t ACCELERATION_COUNT = 3; static const std::uint64_t expectedHeaderSize = 8; -static const std::uint64_t expectedCarSize = 207; +static const std::uint64_t expectedCarEncodedLength = 207; static const std::uint16_t fuel1Speed = 30; static const float fuel1Mpg = 35.9f; @@ -443,6 +443,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) ACTIVATION_CODE_LENGTH, COLOR_LENGTH ); + EXPECT_EQ(sz, predictedCarSz); EXPECT_EQ(Car::isConstLength(), false); EXPECT_EQ(Car::PerformanceFigures::Acceleration::isConstLength(), true); @@ -454,14 +455,14 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeHeaderPlusCarCorrectly) const char *bp = buffer; std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer)); - std::uint64_t carSz = encodeCar(buffer, m_hdr.encodedLength(), sizeof(buffer) - m_hdr.encodedLength()); + std::uint64_t carEncodedLength = encodeCar(buffer, m_hdr.encodedLength(), sizeof(buffer) - m_hdr.encodedLength()); EXPECT_EQ(hdrSz, expectedHeaderSize); - EXPECT_EQ(carSz, expectedCarSize); + EXPECT_EQ(carEncodedLength, expectedCarEncodedLength); EXPECT_EQ(*((std::uint16_t *)bp), Car::sbeBlockLength()); const size_t activationCodePosition = - (hdrSz + carSz) - (ACTIVATION_CODE_LENGTH + sizeof(std::uint32_t) + COLOR_LENGTH); + (hdrSz + carEncodedLength) - (ACTIVATION_CODE_LENGTH + sizeof(std::uint32_t) + COLOR_LENGTH); const size_t activationCodeLengthPosition = activationCodePosition - sizeof(std::uint16_t); EXPECT_EQ(*(std::uint16_t *)(bp + activationCodeLengthPosition), ACTIVATION_CODE_LENGTH); EXPECT_EQ(std::string(bp + activationCodePosition, ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); @@ -472,10 +473,10 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) char buffer[BUFFER_LEN]; std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer)); - std::uint64_t carSz = encodeCar(buffer, m_hdr.encodedLength(), sizeof(buffer) - m_hdr.encodedLength()); + std::uint64_t carEncodedLength = encodeCar(buffer, m_hdr.encodedLength(), sizeof(buffer) - m_hdr.encodedLength()); EXPECT_EQ(hdrSz, expectedHeaderSize); - EXPECT_EQ(carSz, expectedCarSize); + EXPECT_EQ(carEncodedLength, expectedCarEncodedLength); m_hdrDecoder.wrap(buffer, 0, 0, hdrSz); @@ -485,9 +486,9 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) EXPECT_EQ(m_hdrDecoder.version(), Car::sbeSchemaVersion()); EXPECT_EQ(m_hdrDecoder.encodedLength(), expectedHeaderSize); - m_carDecoder.wrapForDecode(buffer, m_hdrDecoder.encodedLength(), Car::sbeBlockLength(), Car::sbeSchemaVersion(), hdrSz + carSz); + m_carDecoder.wrapForDecode(buffer, m_hdrDecoder.encodedLength(), Car::sbeBlockLength(), Car::sbeSchemaVersion(), hdrSz + carEncodedLength); - EXPECT_EQ(m_carDecoder.decodeLength(), expectedCarSize); + EXPECT_EQ(m_carDecoder.decodeLength(), expectedCarEncodedLength); EXPECT_EQ(m_carDecoder.serialNumber(), SERIAL_NUMBER); EXPECT_EQ(m_carDecoder.modelYear(), MODEL_YEAR); @@ -599,8 +600,8 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) EXPECT_EQ(m_carDecoder.colorLength(), COLOR_LENGTH); EXPECT_EQ(std::string(m_carDecoder.color(), COLOR_LENGTH), COLOR); - EXPECT_EQ(m_carDecoder.encodedLength(), expectedCarSize); - EXPECT_EQ(m_carDecoder.decodeLength(), expectedCarSize); + EXPECT_EQ(m_carDecoder.encodedLength(), expectedCarEncodedLength); + EXPECT_EQ(m_carDecoder.decodeLength(), expectedCarEncodedLength); } struct CallbacksForEach @@ -638,10 +639,10 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) Car car(buffer + hdr.encodedLength(), sizeof(buffer) - hdr.encodedLength()); std::uint64_t hdrSz = encodeHdr(hdr); - std::uint64_t carSz = encodeCar(car); + std::uint64_t carEncodedLength = encodeCar(car); EXPECT_EQ(hdrSz, expectedHeaderSize); - EXPECT_EQ(carSz, expectedCarSize); + EXPECT_EQ(carEncodedLength, expectedCarEncodedLength); const MessageHeader hdrDecoder(buffer, hdrSz, 0); @@ -651,7 +652,7 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) EXPECT_EQ(hdrDecoder.version(), Car::sbeSchemaVersion()); EXPECT_EQ(hdrDecoder.encodedLength(), expectedHeaderSize); - Car carDecoder(buffer + hdrDecoder.encodedLength(), carSz, hdrDecoder.blockLength(), hdrDecoder.version()); + Car carDecoder(buffer + hdrDecoder.encodedLength(), carEncodedLength, hdrDecoder.blockLength(), hdrDecoder.version()); CallbacksForEach cbs; Car::FuelFigures &fuelFigures = carDecoder.fuelFigures(); @@ -707,7 +708,7 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) EXPECT_EQ(carDecoder.getColor(tmp, sizeof(tmp)), COLOR_LENGTH); EXPECT_EQ(std::string(tmp, COLOR_LENGTH), COLOR); - EXPECT_EQ(carDecoder.encodedLength(), expectedCarSize); + EXPECT_EQ(carDecoder.encodedLength(), expectedCarEncodedLength); } static const std::size_t offsetVehicleCode = 32; @@ -762,29 +763,36 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) .putActivationCode(activationCode) .putColor(color); - EXPECT_EQ(car.encodedLength(), expectedCarSize); + EXPECT_EQ(car.encodedLength(), expectedCarEncodedLength); EXPECT_EQ(std::string(buffer + baseOffset + offsetVehicleCode, VEHICLE_CODE_LENGTH), vehicleCode); - EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc1Length), FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc1Length), + static_cast(FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH)); EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc1Data, FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH), usageDesc1); - EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc2Length), FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc2Length), + static_cast(FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH)); EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc2Data, FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH), usageDesc2); - EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc3Length), FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc3Length), + static_cast(FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH)); EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc3Data, FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH), usageDesc3); - EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetManufacturerLength), MANUFACTURER_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetManufacturerLength), + static_cast(MANUFACTURER_LENGTH)); EXPECT_EQ(std::string(buffer + baseOffset + offsetManufacturerData, MANUFACTURER_LENGTH), manufacturer); - EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetModelLength), MODEL_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetModelLength), + static_cast(MODEL_LENGTH)); EXPECT_EQ(std::string(buffer + baseOffset + offsetModelData, MODEL_LENGTH), model); - EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetActivationCodeLength), ACTIVATION_CODE_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetActivationCodeLength), + static_cast(ACTIVATION_CODE_LENGTH)); EXPECT_EQ(std::string(buffer + baseOffset + offsetActivationCodeData, ACTIVATION_CODE_LENGTH), activationCode); - EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetColorLength), COLOR_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetColorLength), + static_cast(COLOR_LENGTH)); EXPECT_EQ(std::string(buffer + baseOffset + offsetColorData, COLOR_LENGTH), color); } @@ -793,11 +801,11 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) char buffer[2048]; Car carEncoder(buffer, sizeof(buffer)); - std::uint64_t carSz = encodeCar(carEncoder); + std::uint64_t carEncodedLength = encodeCar(carEncoder); - EXPECT_EQ(carSz, expectedCarSize); + EXPECT_EQ(carEncodedLength, expectedCarEncodedLength); - Car carDecoder(buffer, carSz, Car::sbeBlockLength(), Car::sbeSchemaVersion()); + Car carDecoder(buffer, carEncodedLength, Car::sbeBlockLength(), Car::sbeSchemaVersion()); std::string vehicleCode(VEHICLE_CODE, Car::vehicleCodeLength()); std::string usageDesc1(FUEL_FIGURES_1_USAGE_DESCRIPTION, FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH); @@ -837,7 +845,7 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) EXPECT_EQ(carDecoder.getActivationCodeAsString(), activationCode); EXPECT_EQ(carDecoder.getColorAsString(), color); - EXPECT_EQ(carDecoder.encodedLength(), expectedCarSize); + EXPECT_EQ(carDecoder.encodedLength(), expectedCarEncodedLength); } TEST_F(CodeGenTest, shouldPrintFullDecodedFlyweightRegardlessOfReadPosition) @@ -861,11 +869,11 @@ TEST_F(CodeGenTest, shouldPrintFullDecodedFlyweightRegardlessOfReadPosition) memset(buffer, 0, 2048); Car carEncoder(buffer, sizeof(buffer)); - std::uint64_t carSz = encodeCar(carEncoder); + std::uint64_t carEncodedLength = encodeCar(carEncoder); - EXPECT_EQ(carSz, expectedCarSize); + EXPECT_EQ(carEncodedLength, expectedCarEncodedLength); - Car carDecoder(buffer, carSz, Car::sbeBlockLength(), Car::sbeSchemaVersion()); + Car carDecoder(buffer, carEncodedLength, Car::sbeBlockLength(), Car::sbeSchemaVersion()); std::string vehicleCode(VEHICLE_CODE, Car::vehicleCodeLength()); std::string usageDesc1(FUEL_FIGURES_1_USAGE_DESCRIPTION, FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH); @@ -916,5 +924,5 @@ TEST_F(CodeGenTest, shouldPrintFullDecodedFlyweightRegardlessOfReadPosition) expectDisplayString(expectedDisplayString, carDecoder); - EXPECT_EQ(carDecoder.encodedLength(), expectedCarSize); + EXPECT_EQ(carDecoder.encodedLength(), expectedCarEncodedLength); } From 790ce58e44cd2b72bff2146462f8b32fc2ff7b9b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 27 May 2020 15:44:14 +0100 Subject: [PATCH 0471/1594] [C++] Warnings cleanup. --- sbe-tool/src/test/c/CodeGenTest.cpp | 48 ++++++++++++++++------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index 785e39e36b..3463f67e35 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #define CGT(name) code_generation_test_##name @@ -45,14 +46,14 @@ static const char MANUFACTURER[] = "Honda"; static const char MODEL[] = "Civic VTi"; static const char ACTIVATION_CODE[] = "deadbeef"; -static const std::uint64_t VEHICLE_CODE_LENGTH = sizeof(VEHICLE_CODE); -static const std::uint64_t MANUFACTURER_CODE_LENGTH = sizeof(MANUFACTURER_CODE); -static const std::uint64_t FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH = 11; -static const std::uint64_t FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH = 14; -static const std::uint64_t FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH = 13; -static const std::uint64_t MANUFACTURER_LENGTH = 5; -static const std::uint64_t MODEL_LENGTH = 9; -static const std::uint64_t ACTIVATION_CODE_LENGTH = 8; +static const std::size_t VEHICLE_CODE_LENGTH = sizeof(VEHICLE_CODE); +static const std::size_t MANUFACTURER_CODE_LENGTH = sizeof(MANUFACTURER_CODE); +static const std::size_t FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH = strlen(FUEL_FIGURES_1_USAGE_DESCRIPTION); +static const std::size_t FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH = strlen(FUEL_FIGURES_2_USAGE_DESCRIPTION); +static const std::size_t FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH = strlen(FUEL_FIGURES_3_USAGE_DESCRIPTION); +static const std::size_t MANUFACTURER_LENGTH = strlen(MANUFACTURER); +static const std::size_t MODEL_LENGTH = strlen(MODEL); +static const std::size_t ACTIVATION_CODE_LENGTH = strlen(ACTIVATION_CODE); static const std::uint8_t PERFORMANCE_FIGURES_COUNT = 2; static const std::uint8_t FUEL_FIGURES_COUNT = 3; static const std::uint8_t ACCELERATION_COUNT = 3; @@ -393,7 +394,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) offset += sizeof(std::uint16_t); EXPECT_EQ(*(float *)(bp + offset), fuel1Mpg); offset += sizeof(float); - EXPECT_EQ(*(std::uint16_t *)(bp + offset), FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(bp + offset), static_cast(FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH)); offset += sizeof(std::uint16_t); EXPECT_EQ( std::string(bp + offset, FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH), FUEL_FIGURES_1_USAGE_DESCRIPTION); @@ -403,7 +404,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) offset += sizeof(std::uint16_t); EXPECT_EQ(*(float *)(bp + offset), fuel2Mpg); offset += sizeof(float); - EXPECT_EQ(*(std::uint16_t *)(bp + offset), FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(bp + offset), static_cast(FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH)); offset += sizeof(std::uint16_t); EXPECT_EQ( std::string(bp + offset, FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH), FUEL_FIGURES_2_USAGE_DESCRIPTION); @@ -413,7 +414,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) offset += sizeof(std::uint16_t); EXPECT_EQ(*(float *)(bp + offset), fuel3Mpg); offset += sizeof(float); - EXPECT_EQ(*(std::uint16_t *)(bp + offset), FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(bp + offset), static_cast(FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH)); offset += sizeof(std::uint16_t); EXPECT_EQ( std::string(bp + offset, FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH), FUEL_FIGURES_3_USAGE_DESCRIPTION); @@ -465,15 +466,15 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) offset += sizeof(float); // manufacturer & model - EXPECT_EQ(*(std::uint16_t *)(bp + offset), MANUFACTURER_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(bp + offset), static_cast(MANUFACTURER_LENGTH)); offset += sizeof(std::uint16_t); EXPECT_EQ(std::string(bp + offset, MANUFACTURER_LENGTH), MANUFACTURER); offset += MANUFACTURER_LENGTH; - EXPECT_EQ(*(std::uint16_t *)(bp + offset), MODEL_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(bp + offset), static_cast(MODEL_LENGTH)); offset += sizeof(std::uint16_t); EXPECT_EQ(std::string(bp + offset, MODEL_LENGTH), MODEL); offset += MODEL_LENGTH; - EXPECT_EQ(*(std::uint16_t *)(bp + offset), ACTIVATION_CODE_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(bp + offset), static_cast(ACTIVATION_CODE_LENGTH)); offset += sizeof(std::uint16_t); EXPECT_EQ(std::string(bp + offset, ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); offset += ACTIVATION_CODE_LENGTH; @@ -848,7 +849,6 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) const char *desc3 = usageDesc3.c_str(); CGT(car_fuelFigures_put_usageDescription)(&fuelFig, desc3, strlen(desc3)); - CGT(car_performanceFigures) perfFigs; if (!CGT(car_performanceFigures_set_count)(&car, &perfFigs, PERFORMANCE_FIGURES_COUNT)) { @@ -878,22 +878,28 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) EXPECT_EQ(std::string(buffer + baseOffset + offsetVehicleCode, VEHICLE_CODE_LENGTH), vehicleCode); - EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc1Length), FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc1Length), + static_cast(FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH)); EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc1Data, FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH), usageDesc1); - EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc2Length), FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc2Length), + static_cast(FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH)); EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc2Data, FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH), usageDesc2); - EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc3Length), FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc3Length), + static_cast(FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH)); EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc3Data, FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH), usageDesc3); - EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetManufacturerLength), MANUFACTURER_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetManufacturerLength), + static_cast(MANUFACTURER_LENGTH)); EXPECT_EQ(std::string(buffer + baseOffset + offsetManufacturerData, MANUFACTURER_LENGTH), manufacturer); - EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetModelLength), MODEL_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetModelLength), + static_cast(MODEL_LENGTH)); EXPECT_EQ(std::string(buffer + baseOffset + offsetModelData, MODEL_LENGTH), model); - EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetActivationCodeLength), ACTIVATION_CODE_LENGTH); + EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetActivationCodeLength), + static_cast(ACTIVATION_CODE_LENGTH)); EXPECT_EQ(std::string(buffer + baseOffset + offsetActivationCodeData, ACTIVATION_CODE_LENGTH), activationCode); } From 785194f767d29f4b95bd4a4fa1077dd03ee46773 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 27 May 2020 15:57:26 +0100 Subject: [PATCH 0472/1594] [C++] Warnings cleanup. --- sbe-tool/src/test/c/CodeGenTest.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index 3463f67e35..b9fa61baff 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -841,13 +841,13 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) } CGT(car_fuelFigures_next)(&fuelFig); const char *desc1 = usageDesc1.c_str(); - CGT(car_fuelFigures_put_usageDescription)(&fuelFig, desc1, strlen(desc1)); + CGT(car_fuelFigures_put_usageDescription)(&fuelFig, desc1, static_cast(strlen(desc1))); CGT(car_fuelFigures_next)(&fuelFig); const char *desc2 = usageDesc2.c_str(); - CGT(car_fuelFigures_put_usageDescription)(&fuelFig, desc2, strlen(desc2)); + CGT(car_fuelFigures_put_usageDescription)(&fuelFig, desc2, static_cast(strlen(desc2))); CGT(car_fuelFigures_next)(&fuelFig); const char *desc3 = usageDesc3.c_str(); - CGT(car_fuelFigures_put_usageDescription)(&fuelFig, desc3, strlen(desc3)); + CGT(car_fuelFigures_put_usageDescription)(&fuelFig, desc3, static_cast(strlen(desc3))); CGT(car_performanceFigures) perfFigs; if (!CGT(car_performanceFigures_set_count)(&car, &perfFigs, PERFORMANCE_FIGURES_COUNT)) @@ -868,11 +868,11 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) CGT(car_performanceFigures_acceleration_next)(&acc); const char *manu = manufacturer.c_str(); - CGT(car_put_manufacturer)(&car, manu, strlen(manu)); + CGT(car_put_manufacturer)(&car, manu, static_cast(strlen(manu))); const char *model_c = model.c_str(); - CGT(car_put_model)(&car, model_c, strlen(model_c)); + CGT(car_put_model)(&car, model_c, static_cast(strlen(model_c))); const char *acti = activationCode.c_str(); - CGT(car_put_activationCode)(&car, acti, strlen(acti)); + CGT(car_put_activationCode)(&car, acti, static_cast(strlen(acti))); EXPECT_EQ(CGT(car_encoded_length)(&car), expectedCarEncodedLength); From 41ba30fdb110647a79c53e553c8b6bf721d117b7 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Wed, 27 May 2020 08:34:29 -0700 Subject: [PATCH 0473/1594] 1.18.2 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 5b2c5d3f7c..753029c3a5 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.18.2-SNAPSHOT \ No newline at end of file +1.18.2 \ No newline at end of file From 39d1950752346cc99bbb0685574e1e047c819a53 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Wed, 27 May 2020 08:35:50 -0700 Subject: [PATCH 0474/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 753029c3a5..e0ae520094 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.18.2 \ No newline at end of file +1.18.3-SNAPSHOT \ No newline at end of file From f36fa8d725dc9010ed56aa49c4e55879e56ce28e Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Thu, 28 May 2020 19:34:54 +0800 Subject: [PATCH 0475/1594] constexpr -> SBE_CONSTEXPR (#793) * constexpr -> SBE_CONSTEXPR * Fixes warning warning C4267: 'argument' : conversion from 'size_t' to 'const uint16_t', possible loss of data --- sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp | 148 ++++++++++----------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp index 1ab88cf654..45ece4e655 100644 --- a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp +++ b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp @@ -25,86 +25,86 @@ using namespace code::generation::test; -constexpr const char *SCHEMA_FILENAME = "code-generation-schema.sbeir"; - -constexpr std::uint8_t fieldIdSerialNumber = 1; -constexpr std::uint8_t fieldIdModelYear = 2; -constexpr std::uint8_t fieldIdAvailable = 3; -constexpr std::uint8_t fieldIdCode = 4; -constexpr std::uint8_t fieldIdSomeNumbers = 5; -constexpr std::uint8_t fieldIdVehicleCode = 6; -constexpr std::uint8_t fieldIdExtras = 7; -constexpr std::uint8_t fieldIdDiscountedModel = 8; -constexpr std::uint8_t fieldIdEngine = 9; -constexpr std::uint8_t fieldIdFuelFigures = 10; -constexpr std::uint8_t fieldIdFuelSpeed = 11; -constexpr std::uint8_t fieldIdFuelMpg = 12; -constexpr std::uint8_t fieldIdFuelUsageDescription = 200; -constexpr std::uint8_t fieldIdPerformanceFigures = 13; -constexpr std::uint8_t fieldIdPerfOctaneRating = 14; -constexpr std::uint8_t fieldIdPerfAcceleration = 15; -constexpr std::uint8_t fieldIdPerfAccMph = 16; -constexpr std::uint8_t fieldIdPerfAccSeconds = 17; -constexpr std::uint8_t fieldIdManufacturer = 18; -constexpr std::uint8_t fieldIdModel = 19; -constexpr std::uint8_t fieldIdActivationCode = 20; -constexpr std::uint8_t fieldIdColor = 21; - -constexpr std::uint32_t SERIAL_NUMBER = 1234; -constexpr std::uint16_t MODEL_YEAR = 2013; -constexpr BooleanType::Value AVAILABLE = BooleanType::T; -constexpr Model::Value CODE = Model::A; -constexpr bool CRUISE_CONTROL = true; -constexpr bool SPORTS_PACK = true; -constexpr bool SUNROOF = false; +SBE_CONSTEXPR const char *SCHEMA_FILENAME = "code-generation-schema.sbeir"; + +SBE_CONSTEXPR std::uint8_t fieldIdSerialNumber = 1; +SBE_CONSTEXPR std::uint8_t fieldIdModelYear = 2; +SBE_CONSTEXPR std::uint8_t fieldIdAvailable = 3; +SBE_CONSTEXPR std::uint8_t fieldIdCode = 4; +SBE_CONSTEXPR std::uint8_t fieldIdSomeNumbers = 5; +SBE_CONSTEXPR std::uint8_t fieldIdVehicleCode = 6; +SBE_CONSTEXPR std::uint8_t fieldIdExtras = 7; +SBE_CONSTEXPR std::uint8_t fieldIdDiscountedModel = 8; +SBE_CONSTEXPR std::uint8_t fieldIdEngine = 9; +SBE_CONSTEXPR std::uint8_t fieldIdFuelFigures = 10; +SBE_CONSTEXPR std::uint8_t fieldIdFuelSpeed = 11; +SBE_CONSTEXPR std::uint8_t fieldIdFuelMpg = 12; +SBE_CONSTEXPR std::uint8_t fieldIdFuelUsageDescription = 200; +SBE_CONSTEXPR std::uint8_t fieldIdPerformanceFigures = 13; +SBE_CONSTEXPR std::uint8_t fieldIdPerfOctaneRating = 14; +SBE_CONSTEXPR std::uint8_t fieldIdPerfAcceleration = 15; +SBE_CONSTEXPR std::uint8_t fieldIdPerfAccMph = 16; +SBE_CONSTEXPR std::uint8_t fieldIdPerfAccSeconds = 17; +SBE_CONSTEXPR std::uint8_t fieldIdManufacturer = 18; +SBE_CONSTEXPR std::uint8_t fieldIdModel = 19; +SBE_CONSTEXPR std::uint8_t fieldIdActivationCode = 20; +SBE_CONSTEXPR std::uint8_t fieldIdColor = 21; + +SBE_CONSTEXPR std::uint32_t SERIAL_NUMBER = 1234; +SBE_CONSTEXPR std::uint16_t MODEL_YEAR = 2013; +SBE_CONSTEXPR BooleanType::Value AVAILABLE = BooleanType::T; +SBE_CONSTEXPR Model::Value CODE = Model::A; +SBE_CONSTEXPR bool CRUISE_CONTROL = true; +SBE_CONSTEXPR bool SPORTS_PACK = true; +SBE_CONSTEXPR bool SUNROOF = false; static char VEHICLE_CODE[] = { 'a', 'b', 'c', 'd', 'e', 'f' }; static char MANUFACTURER_CODE[] = { '1', '2', '3' }; -constexpr const char *FUEL_FIGURES_1_USAGE_DESCRIPTION = "Urban Cycle"; -constexpr const char *FUEL_FIGURES_2_USAGE_DESCRIPTION = "Combined Cycle"; -constexpr const char *FUEL_FIGURES_3_USAGE_DESCRIPTION = "Highway Cycle"; -constexpr const char *MANUFACTURER = "Honda"; -constexpr const char *MODEL = "Civic VTi"; -constexpr const char *ACTIVATION_CODE = "deadbeef"; -constexpr const char *COLOR = "red"; +SBE_CONSTEXPR const char *FUEL_FIGURES_1_USAGE_DESCRIPTION = "Urban Cycle"; +SBE_CONSTEXPR const char *FUEL_FIGURES_2_USAGE_DESCRIPTION = "Combined Cycle"; +SBE_CONSTEXPR const char *FUEL_FIGURES_3_USAGE_DESCRIPTION = "Highway Cycle"; +SBE_CONSTEXPR const char *MANUFACTURER = "Honda"; +SBE_CONSTEXPR const char *MODEL = "Civic VTi"; +SBE_CONSTEXPR const char *ACTIVATION_CODE = "deadbeef"; +SBE_CONSTEXPR const char *COLOR = "red"; static const int VEHICLE_CODE_LENGTH = sizeof(VEHICLE_CODE); static const int MANUFACTURER_CODE_LENGTH = sizeof(MANUFACTURER_CODE); -constexpr std::size_t MANUFACTURER_LENGTH = 5; -constexpr std::size_t MODEL_LENGTH = 9; -constexpr std::size_t ACTIVATION_CODE_LENGTH = 8; -constexpr std::size_t COLOR_LENGTH = 3; -constexpr std::size_t PERFORMANCE_FIGURES_COUNT = 2; -constexpr std::size_t FUEL_FIGURES_COUNT = 3; -constexpr std::size_t ACCELERATION_COUNT = 3; - -constexpr std::uint16_t fuel1Speed = 30; -constexpr float fuel1Mpg = 35.9f; -constexpr std::uint16_t fuel2Speed = 55; -constexpr float fuel2Mpg = 49.0f; -constexpr std::uint16_t fuel3Speed = 75; -constexpr float fuel3Mpg = 40.0f; - -constexpr std::uint8_t perf1Octane = 95; -constexpr std::uint16_t perf1aMph = 30; -constexpr float perf1aSeconds = 4.0f; -constexpr std::uint16_t perf1bMph = 60; -constexpr float perf1bSeconds = 7.5f; -constexpr std::uint16_t perf1cMph = 100; -constexpr float perf1cSeconds = 12.2f; - -constexpr std::uint8_t perf2Octane = 99; -constexpr std::uint16_t perf2aMph = 30; -constexpr float perf2aSeconds = 3.8f; -constexpr std::uint16_t perf2bMph = 60; -constexpr float perf2bSeconds = 7.1f; -constexpr std::uint16_t perf2cMph = 100; -constexpr float perf2cSeconds = 11.8f; - -constexpr std::uint16_t engineCapacity = 2000; -constexpr std::uint8_t engineNumCylinders = 4; - -constexpr std::uint64_t encodedCarAndHdrLength = 198 + 8; +SBE_CONSTEXPR std::size_t MANUFACTURER_LENGTH = 5; +SBE_CONSTEXPR std::size_t MODEL_LENGTH = 9; +SBE_CONSTEXPR std::size_t ACTIVATION_CODE_LENGTH = 8; +SBE_CONSTEXPR std::size_t COLOR_LENGTH = 3; +SBE_CONSTEXPR std::uint16_t PERFORMANCE_FIGURES_COUNT = 2; +SBE_CONSTEXPR std::uint16_t FUEL_FIGURES_COUNT = 3; +SBE_CONSTEXPR std::uint16_t ACCELERATION_COUNT = 3; + +SBE_CONSTEXPR std::uint16_t fuel1Speed = 30; +SBE_CONSTEXPR float fuel1Mpg = 35.9f; +SBE_CONSTEXPR std::uint16_t fuel2Speed = 55; +SBE_CONSTEXPR float fuel2Mpg = 49.0f; +SBE_CONSTEXPR std::uint16_t fuel3Speed = 75; +SBE_CONSTEXPR float fuel3Mpg = 40.0f; + +SBE_CONSTEXPR std::uint8_t perf1Octane = 95; +SBE_CONSTEXPR std::uint16_t perf1aMph = 30; +SBE_CONSTEXPR float perf1aSeconds = 4.0f; +SBE_CONSTEXPR std::uint16_t perf1bMph = 60; +SBE_CONSTEXPR float perf1bSeconds = 7.5f; +SBE_CONSTEXPR std::uint16_t perf1cMph = 100; +SBE_CONSTEXPR float perf1cSeconds = 12.2f; + +SBE_CONSTEXPR std::uint8_t perf2Octane = 99; +SBE_CONSTEXPR std::uint16_t perf2aMph = 30; +SBE_CONSTEXPR float perf2aSeconds = 3.8f; +SBE_CONSTEXPR std::uint16_t perf2bMph = 60; +SBE_CONSTEXPR float perf2bSeconds = 7.1f; +SBE_CONSTEXPR std::uint16_t perf2cMph = 100; +SBE_CONSTEXPR float perf2cSeconds = 11.8f; + +SBE_CONSTEXPR std::uint16_t engineCapacity = 2000; +SBE_CONSTEXPR std::uint8_t engineNumCylinders = 4; + +SBE_CONSTEXPR std::uint64_t encodedCarAndHdrLength = 198 + 8; // This enum represents the expected events that // will be received during the decoding process. From 8b2f69a111cf9d817140a409c77754110600868c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 3 Jun 2020 15:51:51 +0100 Subject: [PATCH 0476/1594] [C#] Tidy up spellings and fix schema version reference when wrapping header. --- csharp/sbe-samples-car/CarExample.cs | 11 +++-------- csharp/sbe-samples-extension/ExtensionExample.cs | 8 ++++---- csharp/sbe-tests/BigEndianTests.cs | 4 ++-- csharp/sbe-tests/DirectBufferTests.cs | 4 ++-- csharp/sbe-tests/InteropTests.cs | 4 ++-- csharp/sbe-tests/Issue435Tests.cs | 2 +- csharp/sbe-tests/Issue560Tests.cs | 3 +-- 7 files changed, 15 insertions(+), 21 deletions(-) diff --git a/csharp/sbe-samples-car/CarExample.cs b/csharp/sbe-samples-car/CarExample.cs index a43b045490..287af0ba04 100644 --- a/csharp/sbe-samples-car/CarExample.cs +++ b/csharp/sbe-samples-car/CarExample.cs @@ -33,17 +33,16 @@ public static void ExampleMain() // Before encoding a message we need to create a SBE header which specify what we are going to encode (this will allow the decoder to detect that it's an encoded 'car' object) // We will probably simplify this part soon, so the header gets applied automatically, but for now it's manual - MessageHeader.Wrap(directBuffer, bufferOffset, Car.SchemaVersion); // position the MessageHeader on the DirectBuffer, at the correct position + MessageHeader.Wrap(directBuffer, bufferOffset, MessageHeader.SbeSchemaVersion); // position the MessageHeader on the DirectBuffer, at the correct position MessageHeader.BlockLength = Car.BlockLength; // size that a car takes on the wire MessageHeader.SchemaId = Car.SchemaId; MessageHeader.TemplateId = Car.TemplateId; // identifier for the car object (SBE template ID) - MessageHeader.Version = Car.SchemaVersion; // this can be overriden if we want to support different versions of the car object (advanced functionality) + MessageHeader.Version = Car.SchemaVersion; // this can be overridden if we want to support different versions of the car object (advanced functionality) // Now that we have encoded the header in the byte array we can encode the car object itself bufferOffset += MessageHeader.Size; CarExample.Encode(Car, directBuffer, bufferOffset); - // Now we have encoded the message is the byte array, we are going to decode it // first we decode the header (in a real world scenario you would need the header to decide which SBE decoder you are going to use @@ -59,7 +58,6 @@ public static void ExampleMain() bufferOffset += MessageHeader.Size; // now we decode the message CarExample.Decode(Car, directBuffer, bufferOffset, actingBlockLength, actingVersion); - } } @@ -91,8 +89,6 @@ static CarExample() } } - - public static int Encode(Car car, DirectBuffer directBuffer, int bufferOffset) { const int srcOffset = 0; @@ -122,7 +118,7 @@ public static int Encode(Car car, DirectBuffer directBuffer, int bufferOffset) // we have written all the constant length fields, now we can write the repeatable groups - var fuelFigures = car.FuelFiguresCount(3); // we specify that we are going to write 3 FueldFigures (the API is not very .NET friendly yet, we will address that) + var fuelFigures = car.FuelFiguresCount(3); // we specify that we are going to write 3 FuelFigures (the API is not very .NET friendly yet, we will address that) fuelFigures.Next(); // move to the first element fuelFigures.Speed = 30; fuelFigures.Mpg = 35.9f; @@ -276,4 +272,3 @@ public static void Decode(Car car, } } } - diff --git a/csharp/sbe-samples-extension/ExtensionExample.cs b/csharp/sbe-samples-extension/ExtensionExample.cs index 831598f523..73b3956aa0 100644 --- a/csharp/sbe-samples-extension/ExtensionExample.cs +++ b/csharp/sbe-samples-extension/ExtensionExample.cs @@ -40,7 +40,7 @@ public static void ExampleMain() baselineMessageHeader.BlockLength = Baseline.Car.BlockLength; // size that a car takes on the wire baselineMessageHeader.SchemaId = Baseline.Car.SchemaId; baselineMessageHeader.TemplateId = Baseline.Car.TemplateId; // identifier for the car object (SBE template ID) - baselineMessageHeader.Version = Baseline.Car.SchemaVersion; // this can be overriden if we want to support different versions of the car object (advanced functionality) + baselineMessageHeader.Version = Baseline.Car.SchemaVersion; // this can be overridden if we want to support different versions of the car object (advanced functionality) // Now that we have encoded the header in the byte array we can encode the car object itself bufferOffset += Baseline.MessageHeader.Size; @@ -137,7 +137,7 @@ public static int Encode(Car car, DirectBuffer directBuffer, int bufferOffset) // we have written all the constant length fields, now we can write the repeatable groups - var fuelFigures = car.FuelFiguresCount(3); // we specify that we are going to write 3 FueldFigures (the API is not very .NET friendly yet, we will address that) + var fuelFigures = car.FuelFiguresCount(3); // we specify that we are going to write 3 FuelFigures (the API is not very .NET friendly yet, we will address that) fuelFigures.Next(); // move to the first element fuelFigures.Speed = 30; fuelFigures.Mpg = 35.9f; @@ -314,7 +314,7 @@ static ExtensionExample() } catch (Exception ex) { - throw new Exception("An error occured while reading encodings", ex); + throw new Exception("An error occurred while reading encodings", ex); } } @@ -333,7 +333,7 @@ public static void ExtensionMain() MessageHeader.BlockLength = Car.BlockLength; // size that a car takes on the wire MessageHeader.SchemaId = Car.SchemaId; MessageHeader.TemplateId = Car.TemplateId; // identifier for the car object (SBE template ID) - MessageHeader.Version = Car.SchemaVersion; // this can be overriden if we want to support different versions of the car object (advanced functionality) + MessageHeader.Version = Car.SchemaVersion; // this can be overridden if we want to support different versions of the car object (advanced functionality) // Now that we have encoded the header in the byte array we can encode the car object itself bufferOffset += MessageHeader.Size; diff --git a/csharp/sbe-tests/BigEndianTests.cs b/csharp/sbe-tests/BigEndianTests.cs index a850e56041..8e1358800a 100644 --- a/csharp/sbe-tests/BigEndianTests.cs +++ b/csharp/sbe-tests/BigEndianTests.cs @@ -44,7 +44,7 @@ public void SetUp() public void BigendianDecodeTest() { _directBuffer = new DirectBuffer(_decodeBuffer); - _messageHeader.Wrap(_directBuffer, 0, Baseline.Car.SchemaVersion); + _messageHeader.Wrap(_directBuffer, 0, Baseline.MessageHeader.SbeSchemaVersion); var Car = new Car(); Car.WrapForDecode(_directBuffer, MessageHeader.Size, _messageHeader.BlockLength, _messageHeader.Version); @@ -152,7 +152,7 @@ public void BigendianEncodeTest() { Car = new Car(); _directBuffer = new DirectBuffer(_encodeBuffer); - _messageHeader.Wrap(_directBuffer, 0, Baseline.Car.SchemaVersion); + _messageHeader.Wrap(_directBuffer, 0, Baseline.MessageHeader.SbeSchemaVersion); _messageHeader.BlockLength = Car.BlockLength; _messageHeader.SchemaId = Car.SchemaId; _messageHeader.TemplateId = Car.TemplateId; diff --git a/csharp/sbe-tests/DirectBufferTests.cs b/csharp/sbe-tests/DirectBufferTests.cs index 51ab649ac2..c42e87ddaf 100644 --- a/csharp/sbe-tests/DirectBufferTests.cs +++ b/csharp/sbe-tests/DirectBufferTests.cs @@ -58,9 +58,9 @@ public void ConstructFromNativeBuffer() const int value = 5; const int index = 0; - using (var directBufferFromUnmanagedbuffer = new DirectBuffer(unmanagedBuffer, managedBuffer.Length)) + using (var directBufferFromUnmanagedBuffer = new DirectBuffer(unmanagedBuffer, managedBuffer.Length)) { - directBufferFromUnmanagedbuffer.Int64PutLittleEndian(index, value); + directBufferFromUnmanagedBuffer.Int64PutLittleEndian(index, value); Assert.AreEqual(value, *(long*) (unmanagedBuffer + index)); } } diff --git a/csharp/sbe-tests/InteropTests.cs b/csharp/sbe-tests/InteropTests.cs index e03d31c5a6..6d9e46fa84 100644 --- a/csharp/sbe-tests/InteropTests.cs +++ b/csharp/sbe-tests/InteropTests.cs @@ -52,7 +52,7 @@ public void Setup() public void InteropDecodeTest() { _directBuffer = new DirectBuffer(_decodeBuffer); - _messageHeader.Wrap(_directBuffer, 0, Baseline.Car.SchemaVersion); + _messageHeader.Wrap(_directBuffer, 0, Baseline.MessageHeader.SbeSchemaVersion); var Car = new Car(); Car.WrapForDecode(_directBuffer, MessageHeader.Size, _messageHeader.BlockLength, _messageHeader.Version); @@ -160,7 +160,7 @@ public void InteropEncodeTest() { Car = new Car(); _directBuffer = new DirectBuffer(_encodeBuffer); - _messageHeader.Wrap(_directBuffer, 0, Baseline.Car.SchemaVersion); + _messageHeader.Wrap(_directBuffer, 0, Baseline.MessageHeader.SbeSchemaVersion); _messageHeader.BlockLength = Car.BlockLength; _messageHeader.SchemaId = Car.SchemaId; _messageHeader.TemplateId = Car.TemplateId; diff --git a/csharp/sbe-tests/Issue435Tests.cs b/csharp/sbe-tests/Issue435Tests.cs index 26b78e572b..b72a190d91 100644 --- a/csharp/sbe-tests/Issue435Tests.cs +++ b/csharp/sbe-tests/Issue435Tests.cs @@ -34,7 +34,7 @@ public void SetUp() _issue435 = new Issue435.Issue435(); _messageHeader = new Issue435.MessageHeader(); - _messageHeader.Wrap(_directBuffer, 0, Issue435.Issue435.SchemaVersion); + _messageHeader.Wrap(_directBuffer, 0, Issue435.MessageHeader.SbeSchemaVersion); _messageHeader.BlockLength = Issue435.Issue435.BlockLength; _messageHeader.SchemaId = Issue435.Issue435.SchemaId; _messageHeader.TemplateId = Issue435.Issue435.TemplateId; diff --git a/csharp/sbe-tests/Issue560Tests.cs b/csharp/sbe-tests/Issue560Tests.cs index d1e58d1655..1d42db09bb 100644 --- a/csharp/sbe-tests/Issue560Tests.cs +++ b/csharp/sbe-tests/Issue560Tests.cs @@ -36,7 +36,7 @@ public void SetUp() _issue560 = new Issue560.Issue560(); _messageHeader = new Issue560.MessageHeader(); - _messageHeader.Wrap(_directBuffer, 0, Issue560.Issue560.SchemaVersion); + _messageHeader.Wrap(_directBuffer, 0, Issue560.MessageHeader.SbeSchemaVersion); _messageHeader.BlockLength = Issue560.Issue560.BlockLength; _messageHeader.SchemaId = Issue560.Issue560.SchemaId; _messageHeader.TemplateId = Issue560.Issue560.TemplateId; @@ -48,7 +48,6 @@ public void SetUp() public void Issue560Test() { Assert.AreEqual(_issue560.DiscountedModel, Issue560.Model.C, "Incorrect const enum valueref"); - } } From e068fb05b3929882d280fdcd74d63624c5ce868a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 5 Jun 2020 16:07:46 +0100 Subject: [PATCH 0477/1594] [Java] Validate types within composites so group and data is reported when no XSD is applied. --- .../co/real_logic/sbe/xml/CompositeType.java | 8 +- .../sbe/{TestUtil.java => Tests.java} | 4 +- .../csharp/Issue567GroupSizeTest.java | 6 +- .../java/CompositeElementsGenerationTest.java | 8 +- .../java/ConstantCharArrayTest.java | 4 +- .../java/GenerateFixBinaryTest.java | 6 +- .../generation/java/JavaGeneratorTest.java | 4 +- .../generation/java/SchemaExtensionTest.java | 4 +- .../sbe/generation/java/ToStringTest.java | 4 +- .../sbe/ir/BasicXmlIrGenerationTest.java | 19 ++--- .../sbe/ir/CompositeElementsIrTest.java | 11 +-- .../sbe/ir/CompositeOffsetsTest.java | 5 +- .../real_logic/sbe/ir/CompositeRefsTest.java | 5 +- .../co/real_logic/sbe/ir/EncodedIrTest.java | 76 +++++++++---------- .../sbe/ir/GroupWithDataIrTest.java | 14 ++-- .../co/real_logic/sbe/ir/ValueRefsTest.java | 5 +- .../sbe/xml/BasicSchemaFileTest.java | 12 +-- .../sbe/xml/CompositeElementsTest.java | 7 +- .../real_logic/sbe/xml/CompositeTypeTest.java | 15 ++-- .../sbe/xml/CyclicReferencesTest.java | 9 +-- .../xml/EmbeddedLengthAndCountFileTest.java | 14 ++-- .../sbe/xml/EncodedDataTypeTest.java | 54 +++++-------- .../co/real_logic/sbe/xml/EnumTypeTest.java | 22 ++---- .../real_logic/sbe/xml/ErrorHandlerTest.java | 57 ++++++++------ .../real_logic/sbe/xml/GroupWithDataTest.java | 7 +- .../co/real_logic/sbe/xml/OffsetFileTest.java | 42 +++++----- .../sbe/xml/RelativeXIncludeTest.java | 3 +- .../uk/co/real_logic/sbe/xml/SetTypeTest.java | 13 ++-- .../error-handler-invalid-composite.xml | 33 ++++++++ 29 files changed, 225 insertions(+), 246 deletions(-) rename sbe-tool/src/test/java/uk/co/real_logic/sbe/{TestUtil.java => Tests.java} (90%) create mode 100644 sbe-tool/src/test/resources/error-handler-invalid-composite.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index 6efa092a56..ab99d62915 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -45,7 +45,7 @@ public class CompositeType extends Type * SBE schema composite type. */ public static final String COMPOSITE_TYPE = "composite"; - public static final String SUB_TYPES_EXP = "type|enum|set|composite|ref"; + public static final String SUB_TYPES_EXP = "type|enum|set|composite|ref|data|group"; private final List compositesPath = new ArrayList<>(); private final Map containedTypeByNameMap = new LinkedHashMap<>(); @@ -135,7 +135,6 @@ public int encodedLength() */ public List getTypeList() { - return new ArrayList<>(containedTypeByNameMap.values()); } @@ -462,6 +461,11 @@ private Type processType( break; } + case "data": + case "group": + XmlSchemaParser.handleError(subTypeNode, nodeName + " not valid within composite"); + break; + default: throw new IllegalStateException("Unknown node type: name=" + nodeName); } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java similarity index 90% rename from sbe-tool/src/test/java/uk/co/real_logic/sbe/TestUtil.java rename to sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java index 1bb3aa8f2d..e81b52a712 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java @@ -20,12 +20,12 @@ import java.io.InputStream; import java.net.URL; -public class TestUtil +public class Tests { public static InputStream getLocalResource(final String name) throws IOException { final String pathToResources = System.getProperty("test.resources.dir", ""); - final URL url = TestUtil.class.getClassLoader().getResource(pathToResources + name); + final URL url = Tests.class.getClassLoader().getResource(pathToResources + name); if (url == null) { throw new FileNotFoundException(pathToResources + name); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index 5216440f7a..a31ab03f98 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -4,7 +4,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; @@ -44,14 +44,14 @@ public void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupS { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); assertThrows(IllegalArgumentException.class, - () -> parse(TestUtil.getLocalResource("issue567-invalid.xml"), options)); + () -> parse(Tests.getLocalResource("issue567-invalid.xml"), options)); } @Test public void shouldGenerateWhenUsingATypeThatIsConstrainedToFitInAnIntAsTheGroupSize() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(TestUtil.getLocalResource("issue567-valid.xml"), options); + final MessageSchema schema = parse(Tests.getLocalResource("issue567-valid.xml"), options); final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java index 3972b445e0..5fba2e830d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java @@ -57,7 +57,7 @@ public class CompositeElementsGenerationTest private static final int SCHEMA_BUFFER_CAPACITY = 16 * 1024; @Test - public void shouldEncodeCorrectly() + public void shouldEncode() { final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); encodeTestMessage(encodedMsgBuffer); @@ -93,7 +93,7 @@ public void shouldEncodeCorrectly() } @Test - public void shouldDecodeCorrectly() + public void shouldDecode() { final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); encodeTestMessage(encodedMsgBuffer); @@ -124,7 +124,7 @@ public void shouldDecodeCorrectly() } @Test - public void shouldDisplayCorrectly() + public void shouldDisplay() { final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); encodeTestMessage(encodedMsgBuffer); @@ -137,7 +137,7 @@ public void shouldDisplayCorrectly() } @Test - public void shouldOtfDecodeCorrectly() throws Exception + public void shouldOtfDecode() throws Exception { final ByteBuffer encodedSchemaBuffer = ByteBuffer.allocate(SCHEMA_BUFFER_CAPACITY); encodeSchema(encodedSchemaBuffer); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java index 7839f64e1f..73c304d3f4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java @@ -19,7 +19,7 @@ import org.agrona.MutableDirectBuffer; import org.agrona.generation.StringWriterOutputManager; import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; @@ -40,7 +40,7 @@ public class ConstantCharArrayTest public void shouldGenerateConstCharArrayMethods() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(TestUtil.getLocalResource("issue505.xml"), options); + final MessageSchema schema = parse(Tests.getLocalResource("issue505.xml"), options); final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java index 66acaf41c6..f3be9150c4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java @@ -21,7 +21,7 @@ import org.agrona.generation.CompilerUtil; import org.agrona.generation.StringWriterOutputManager; import uk.co.real_logic.sbe.SbeTool; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.ir.IrDecoder; import uk.co.real_logic.sbe.ir.IrEncoder; @@ -51,7 +51,7 @@ public void shouldGenerateValidJava() throws Exception System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(TestUtil.getLocalResource("FixBinary.xml"), options); + final MessageSchema schema = parse(Tests.getLocalResource("FixBinary.xml"), options); final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); final JavaGenerator generator = new JavaGenerator( @@ -77,7 +77,7 @@ public void shouldGenerateAndEncodeIr() throws Exception System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(TestUtil.getLocalResource("FixBinary.xml"), options); + final MessageSchema schema = parse(Tests.getLocalResource("FixBinary.xml"), options); final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); final ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index b3ff43fc72..39b53cef62 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -22,7 +22,7 @@ import org.agrona.generation.StringWriterOutputManager; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; @@ -60,7 +60,7 @@ public class JavaGeneratorTest public void setUp() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(TestUtil.getLocalResource("code-generation-schema.xml"), options); + final MessageSchema schema = parse(Tests.getLocalResource("code-generation-schema.xml"), options); final IrGenerator irg = new IrGenerator(); ir = irg.generate(schema); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index 3c59f2b6a0..335cab9b7c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -22,7 +22,7 @@ import org.agrona.generation.StringWriterOutputManager; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; @@ -52,7 +52,7 @@ public class SchemaExtensionTest public void setup() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(TestUtil.getLocalResource("extension-schema.xml"), options); + final MessageSchema schema = parse(Tests.getLocalResource("extension-schema.xml"), options); final IrGenerator irg = new IrGenerator(); ir = irg.generate(schema); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java index 2e0cb1b93a..8059ca9b83 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java @@ -28,7 +28,7 @@ public class ToStringTest extends EncodedCarTestBase private static final int MSG_BUFFER_CAPACITY = 4 * 1024; @Test - public void exampleMessagePrinted() + public void shouldToStringMessage() { final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); encodeTestMessage(encodedMsgBuffer); @@ -54,7 +54,7 @@ public void exampleMessagePrinted() } @Test - public void emptyMessagePrinted() + public void shouldToStringBlankMessage() { final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); CAR.wrap(new UnsafeBuffer(encodedMsgBuffer), 0); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index 0b08890d8b..f18c4076c8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -26,14 +26,13 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static uk.co.real_logic.sbe.TestUtil.getLocalResource; +import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class BasicXmlIrGenerationTest { @Test - public void shouldGenerateCorrectIrForMessageHeader() - throws Exception + public void shouldGenerateIrForMessageHeader() throws Exception { final MessageSchema schema = parse(getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -95,8 +94,7 @@ public void shouldGenerateCorrectIrForMessageHeader() } @Test - public void shouldGenerateCorrectIrForBasicMessage() - throws Exception + public void shouldGenerateIrForBasicMessage() throws Exception { final MessageSchema schema = parse(getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -145,8 +143,7 @@ public void shouldGenerateCorrectIrForBasicMessage() } @Test - public void shouldGenerateCorrectIrForMessageWithVariableLengthField() - throws Exception + public void shouldGenerateIrForMessageWithVariableLengthField() throws Exception { final MessageSchema schema = parse(getLocalResource( "basic-variable-length-schema.xml"), ParserOptions.DEFAULT); @@ -209,8 +206,7 @@ public void shouldGenerateCorrectIrForMessageWithVariableLengthField() } @Test - public void shouldGenerateCorrectIrForMessageWithRepeatingGroupWithEmbeddedDimensions() - throws Exception + public void shouldGenerateIrForMessageWithRepeatingGroupWithEmbeddedDimensions() throws Exception { final MessageSchema schema = parse(getLocalResource( "basic-group-schema.xml"), ParserOptions.DEFAULT); @@ -244,7 +240,7 @@ public void shouldGenerateCorrectIrForMessageWithRepeatingGroupWithEmbeddedDimen } @Test - public void shouldGenerateCorrectIrForMessageWithRepeatingGroupWithEmbeddedDimensionsDefaultDimensionType() + public void shouldGenerateIrForMessageWithRepeatingGroupWithEmbeddedDimensionsDefaultDimensionType() throws Exception { final MessageSchema schema = parse(getLocalResource( @@ -271,8 +267,7 @@ public void shouldGenerateCorrectIrForMessageWithRepeatingGroupWithEmbeddedDimen } @Test - public void shouldGenerateCorrectIrForMessageWithVariableLengthFieldWithEmbeddedLength() - throws Exception + public void shouldGenerateIrForMessageWithVariableLengthFieldWithEmbeddedLength() throws Exception { final MessageSchema schema = parse(getLocalResource( "embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java index 93cce2f679..bfa392be71 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java @@ -25,14 +25,13 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static uk.co.real_logic.sbe.TestUtil.getLocalResource; +import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class CompositeElementsIrTest { @Test - public void shouldGenerateCorrectIrForCompositeElementsSchema() - throws Exception + public void shouldGenerateIrForCompositeElementsSchema() throws Exception { final MessageSchema schema = parse(getLocalResource( "composite-elements-schema.xml"), ParserOptions.DEFAULT); @@ -95,8 +94,7 @@ public void shouldGenerateCorrectIrForCompositeElementsSchema() } @Test - public void shouldGenerateCorrectIrForCompositeElementsWithOffsetsSchemaRc4() - throws Exception + public void shouldGenerateIrForCompositeElementsWithOffsetsSchemaRc4() throws Exception { final MessageSchema schema = parse(getLocalResource( "composite-elements-schema-rc4.xml"), ParserOptions.DEFAULT); @@ -151,8 +149,7 @@ public void shouldGenerateCorrectIrForCompositeElementsWithOffsetsSchemaRc4() } @Test - public void shouldGenerateCorrectIrForCompositeWithRefSchema() - throws Exception + public void shouldGenerateIrForCompositeWithRefSchema() throws Exception { final MessageSchema schema = parse(getLocalResource( "composite-elements-schema-rc4.xml"), ParserOptions.DEFAULT); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java index 4d2e27f13e..3aeb001d71 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java @@ -24,14 +24,13 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static uk.co.real_logic.sbe.TestUtil.getLocalResource; +import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class CompositeOffsetsTest { @Test - public void shouldGenerateCorrectOffsetsForFieldsWithEmbeddedComposite() - throws Exception + public void shouldGenerateOffsetsForFieldsWithEmbeddedComposite() throws Exception { final MessageSchema schema = parse(getLocalResource("composite-offsets-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java index 05fc1e3a92..3c40e56ce5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java @@ -21,14 +21,13 @@ import uk.co.real_logic.sbe.xml.ParserOptions; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static uk.co.real_logic.sbe.TestUtil.getLocalResource; +import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class CompositeRefsTest { @Test - public void shouldGenerateCorrectIrForCompositeRefs() - throws Exception + public void shouldGenerateIrForCompositeRefs() throws Exception { final MessageSchema schema = parse(getLocalResource("issue496.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index 584e581906..a09fef7f3a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -16,7 +16,7 @@ package uk.co.real_logic.sbe.ir; import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; @@ -33,10 +33,9 @@ public class EncodedIrTest private static final int CAPACITY = 1024 * 16; @Test - public void shouldEncodeIr() - throws Exception + public void shouldEncodeIr() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); + final MessageSchema schema = parse(Tests.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); final ByteBuffer buffer = ByteBuffer.allocateDirect(CAPACITY); @@ -46,10 +45,9 @@ public void shouldEncodeIr() } @Test - public void shouldEncodeThenDecodeIr() - throws Exception + public void shouldEncodeThenDecodeIr() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); + final MessageSchema schema = parse(Tests.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); final ByteBuffer buffer = ByteBuffer.allocateDirect(CAPACITY); @@ -63,10 +61,9 @@ public void shouldEncodeThenDecodeIr() } @Test - public void shouldHandleRightSizedBuffer() - throws Exception + public void shouldHandleRightSizedBuffer() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); + final MessageSchema schema = parse(Tests.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); final ByteBuffer buffer = ByteBuffer.allocateDirect(CAPACITY); @@ -84,10 +81,9 @@ public void shouldHandleRightSizedBuffer() } @Test - public void shouldDecodeCorrectFrame() - throws Exception + public void shouldDecodeFrame() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "code-generation-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); @@ -107,33 +103,10 @@ public void shouldDecodeCorrectFrame() assertThat(decodedIr.namespaceName(), is(ir.namespaceName())); } - private void assertEqual(final Token lhs, final Token rhs) - { - assertThat(lhs.name(), is(rhs.name())); - assertThat(lhs.version(), is(rhs.version())); - assertThat(lhs.offset(), is(rhs.offset())); - assertThat((long)lhs.id(), is((long)rhs.id())); - assertThat(lhs.signal(), is(rhs.signal())); - assertThat(lhs.encodedLength(), is(rhs.encodedLength())); - - assertThat(lhs.encoding().byteOrder(), is(rhs.encoding().byteOrder())); - assertThat(lhs.encoding().primitiveType(), is(rhs.encoding().primitiveType())); - assertThat(lhs.encoding().presence(), is(rhs.encoding().presence())); - assertThat(lhs.encoding().constValue(), is(rhs.encoding().constValue())); - assertThat(lhs.encoding().minValue(), is(rhs.encoding().minValue())); - assertThat(lhs.encoding().maxValue(), is(rhs.encoding().maxValue())); - assertThat(lhs.encoding().nullValue(), is(rhs.encoding().nullValue())); - assertThat(lhs.encoding().characterEncoding(), is(rhs.encoding().characterEncoding())); - assertThat(lhs.encoding().epoch(), is(rhs.encoding().epoch())); - assertThat(lhs.encoding().timeUnit(), is(rhs.encoding().timeUnit())); - assertThat(lhs.encoding().semanticType(), is(rhs.encoding().semanticType())); - } - @Test - public void shouldDecodeCorrectHeader() - throws Exception + public void shouldDecodeHeader() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "code-generation-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); @@ -155,10 +128,9 @@ public void shouldDecodeCorrectHeader() } @Test - public void shouldDecodeCorrectMessagesAndTypes() - throws Exception + public void shouldDecodeMessagesAndTypes() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "code-generation-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); @@ -197,4 +169,26 @@ public void shouldDecodeCorrectMessagesAndTypes() } } } + + private void assertEqual(final Token lhs, final Token rhs) + { + assertThat(lhs.name(), is(rhs.name())); + assertThat(lhs.version(), is(rhs.version())); + assertThat(lhs.offset(), is(rhs.offset())); + assertThat((long)lhs.id(), is((long)rhs.id())); + assertThat(lhs.signal(), is(rhs.signal())); + assertThat(lhs.encodedLength(), is(rhs.encodedLength())); + + assertThat(lhs.encoding().byteOrder(), is(rhs.encoding().byteOrder())); + assertThat(lhs.encoding().primitiveType(), is(rhs.encoding().primitiveType())); + assertThat(lhs.encoding().presence(), is(rhs.encoding().presence())); + assertThat(lhs.encoding().constValue(), is(rhs.encoding().constValue())); + assertThat(lhs.encoding().minValue(), is(rhs.encoding().minValue())); + assertThat(lhs.encoding().maxValue(), is(rhs.encoding().maxValue())); + assertThat(lhs.encoding().nullValue(), is(rhs.encoding().nullValue())); + assertThat(lhs.encoding().characterEncoding(), is(rhs.encoding().characterEncoding())); + assertThat(lhs.encoding().epoch(), is(rhs.encoding().epoch())); + assertThat(lhs.encoding().timeUnit(), is(rhs.encoding().timeUnit())); + assertThat(lhs.encoding().semanticType(), is(rhs.encoding().semanticType())); + } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java index 4ed971b141..36d54ac5c5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java @@ -25,14 +25,13 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static uk.co.real_logic.sbe.TestUtil.getLocalResource; +import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class GroupWithDataIrTest { @Test - public void shouldGenerateCorrectIrForSingleVarDataInRepeatingGroup() - throws Exception + public void shouldGenerateIrForSingleVarDataInRepeatingGroup() throws Exception { final MessageSchema schema = parse(getLocalResource("group-with-data-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -73,8 +72,7 @@ public void shouldGenerateCorrectIrForSingleVarDataInRepeatingGroup() } @Test - public void shouldGenerateCorrectIrForMultipleVarDataInRepeatingGroup() - throws Exception + public void shouldGenerateIrForMultipleVarDataInRepeatingGroup() throws Exception { final MessageSchema schema = parse(getLocalResource("group-with-data-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -102,8 +100,7 @@ public void shouldGenerateCorrectIrForMultipleVarDataInRepeatingGroup() } @Test - public void shouldGenerateCorrectIrForVarDataInNestedRepeatingGroup() - throws Exception + public void shouldGenerateIrForVarDataInNestedRepeatingGroup() throws Exception { final MessageSchema schema = parse(getLocalResource("group-with-data-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -135,8 +132,7 @@ public void shouldGenerateCorrectIrForVarDataInNestedRepeatingGroup() } @Test - public void shouldGenerateCorrectIrForOnlyMultipleVarDataInRepeatingGroup() - throws Exception + public void shouldGenerateIrForOnlyMultipleVarDataInRepeatingGroup() throws Exception { final MessageSchema schema = parse(getLocalResource("group-with-data-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java index 21bfd8f15b..13e7824454 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java @@ -22,14 +22,13 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static uk.co.real_logic.sbe.TestUtil.getLocalResource; +import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class ValueRefsTest { @Test - public void shouldGenerateValueRefToEnum() - throws Exception + public void shouldGenerateValueRefToEnum() throws Exception { final MessageSchema schema = parse(getLocalResource("value-ref-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java index c47fc48087..8ed8c345c3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java @@ -18,7 +18,7 @@ import java.util.List; import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; @@ -30,35 +30,35 @@ public class BasicSchemaFileTest public void shouldHandleBasicFile() throws Exception { - parse(TestUtil.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); + parse(Tests.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); } @Test public void shouldHandleConstantHeaderField() throws Exception { - parse(TestUtil.getLocalResource("basic-schema-constant-header-field.xml"), ParserOptions.DEFAULT); + parse(Tests.getLocalResource("basic-schema-constant-header-field.xml"), ParserOptions.DEFAULT); } @Test public void shouldHandleBasicFileWithGroup() throws Exception { - parse(TestUtil.getLocalResource("basic-group-schema.xml"), ParserOptions.DEFAULT); + parse(Tests.getLocalResource("basic-group-schema.xml"), ParserOptions.DEFAULT); } @Test public void shouldHandleBasicFileWithVariableLengthData() throws Exception { - parse(TestUtil.getLocalResource("basic-variable-length-schema.xml"), ParserOptions.DEFAULT); + parse(Tests.getLocalResource("basic-variable-length-schema.xml"), ParserOptions.DEFAULT); } @Test public void shouldHandleBasicAllTypes() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource("basic-types-schema.xml"), ParserOptions.DEFAULT); + final MessageSchema schema = parse(Tests.getLocalResource("basic-types-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(1).fields(); assertThat(fields.get(0).name(), is("header")); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java index ed4e858d05..4f9182bb89 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java @@ -16,7 +16,7 @@ package uk.co.real_logic.sbe.xml; import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import java.util.List; @@ -27,10 +27,9 @@ public class CompositeElementsTest { @Test - public void shouldParseSchemaSuccessfully() - throws Exception + public void shouldParseSchemaSuccessfully() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "composite-elements-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(1).fields(); final Field composite = fields.get(0); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java index 9f02621a2f..f1504ffa45 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java @@ -40,8 +40,7 @@ public class CompositeTypeTest { @Test - public void shouldHandleDecimalCompositeType() - throws Exception + public void shouldHandleDecimalCompositeType() throws Exception { final String testXmlString = "" + @@ -65,8 +64,7 @@ public void shouldHandleDecimalCompositeType() } @Test - public void shouldHandleDecimal32CompositeType() - throws Exception + public void shouldHandleDecimal32CompositeType() throws Exception { final String testXmlString = "" + @@ -92,8 +90,7 @@ public void shouldHandleDecimal32CompositeType() } @Test - public void shouldHandleDecimal64CompositeType() - throws Exception + public void shouldHandleDecimal64CompositeType() throws Exception { final String testXmlString = "" + @@ -118,8 +115,7 @@ public void shouldHandleDecimal64CompositeType() } @Test - public void shouldHandleCompositeTypeList() - throws Exception + public void shouldHandleCompositeTypeList() throws Exception { final String testXmlString = "" + @@ -138,8 +134,7 @@ public void shouldHandleCompositeTypeList() } @Test - public void shouldHandleCompositeHasNullableType() - throws Exception + public void shouldHandleCompositeHasNullableType() throws Exception { final String nullValStr = "9223372036854775807"; final String testXmlString = diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java index 6d7cd3b43d..0644df5422 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java @@ -16,7 +16,7 @@ package uk.co.real_logic.sbe.xml; import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; @@ -25,14 +25,13 @@ public class CyclicReferencesTest { @Test - public void shouldTestForCyclicRefs() - throws Exception + public void shouldTestForCyclicRefs() throws Exception { try { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(TestUtil.getLocalResource("cyclic-refs-schema.xml"), options); + parse(Tests.getLocalResource("cyclic-refs-schema.xml"), options); } catch (final IllegalStateException ex) { @@ -42,4 +41,4 @@ public void shouldTestForCyclicRefs() fail("Expected IllegalStateException"); } -} \ No newline at end of file +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java index 39722bb043..33712faced 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java @@ -16,7 +16,7 @@ package uk.co.real_logic.sbe.xml; import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import java.util.List; @@ -28,11 +28,10 @@ public class EmbeddedLengthAndCountFileTest { @Test - public void shouldHandleEmbeddedCountForGroup() - throws Exception + public void shouldHandleEmbeddedCountForGroup() throws Exception { final MessageSchema schema = parse( - TestUtil.getLocalResource("embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); + Tests.getLocalResource("embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(1).fields(); assertThat(fields.get(1).name(), is("ListOrdGrp")); @@ -44,9 +43,8 @@ public void shouldHandleEmbeddedCountForGroup() } @Test - public void shouldHandleEmbeddedLengthForData() - throws Exception + public void shouldHandleEmbeddedLengthForData() throws Exception { - parse(TestUtil.getLocalResource("embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); + parse(Tests.getLocalResource("embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); } -} \ No newline at end of file +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index dfbf4e59b7..46bba8a77a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -42,8 +42,7 @@ public class EncodedDataTypeTest { @Test - public void shouldHandleSettingAllAttributes() - throws Exception + public void shouldHandleSettingAllAttributes() throws Exception { final String testXmlString = "" + @@ -66,8 +65,7 @@ public void shouldHandleSettingAllAttributes() } @Test - public void shouldHandleMultipleTypes() - throws Exception + public void shouldHandleMultipleTypes() throws Exception { final String testXmlString = "" + @@ -86,8 +84,7 @@ public void shouldHandleMultipleTypes() } @Test - public void shouldSetAppropriateDefaultsWhenNoneSpecified() - throws Exception + public void shouldSetAppropriateDefaultsWhenNoneSpecified() throws Exception { final String testXmlString = "" + @@ -107,8 +104,7 @@ public void shouldSetAppropriateDefaultsWhenNoneSpecified() } @Test - public void shouldUseAppropriatePresence() - throws Exception + public void shouldUseAppropriatePresence() throws Exception { final String testXmlString = "" + @@ -160,8 +156,7 @@ public void shouldThrowExceptionWhenNoNameSpecified() } @Test - public void shouldUseAppropriatePrimitiveType() - throws Exception + public void shouldUseAppropriatePrimitiveType() throws Exception { final String testXmlString = "" + @@ -206,8 +201,7 @@ public void shouldThrowExceptionWhenUnknownPrimitiveTypeSpecified() } @Test - public void shouldReturnCorrectSizeForPrimitiveTypes() - throws Exception + public void shouldReturnCorrectSizeForPrimitiveTypes() throws Exception { final String testXmlString = "" + @@ -239,8 +233,7 @@ public void shouldReturnCorrectSizeForPrimitiveTypes() } @Test - public void shouldReturnCorrectDescriptionForType() - throws Exception + public void shouldReturnCorrectDescriptionForType() throws Exception { final String desc = "basic description attribute of a type element"; final String testXmlString = @@ -254,8 +247,7 @@ public void shouldReturnCorrectDescriptionForType() } @Test - public void shouldReturnNullOnNoDescriptionSet() - throws Exception + public void shouldReturnNullOnNoDescriptionSet() throws Exception { final String testXmlString = "" + @@ -269,8 +261,7 @@ public void shouldReturnNullOnNoDescriptionSet() } @Test - public void shouldReturnCorrectSemanticTypeForType() - throws Exception + public void shouldReturnCorrectSemanticTypeForType() throws Exception { final String semanticType = "char"; final String testXmlString = @@ -284,8 +275,7 @@ public void shouldReturnCorrectSemanticTypeForType() } @Test - public void shouldReturnNullWhenSemanticTypeNotSpecified() - throws Exception + public void shouldReturnNullWhenSemanticTypeNotSpecified() throws Exception { final String testXmlString = "" + @@ -309,8 +299,7 @@ public void shouldThrowExceptionWhenConstantPresenceButNoDataSpecified() } @Test - public void shouldReturnCorrectPresenceConstantWhenSpecified() - throws Exception + public void shouldReturnCorrectPresenceConstantWhenSpecified() throws Exception { final String testXmlString = "" + @@ -325,8 +314,7 @@ public void shouldReturnCorrectPresenceConstantWhenSpecified() } @Test - public void shouldReturnCorrectConstantStringWhenSpecified() - throws Exception + public void shouldReturnCorrectConstantStringWhenSpecified() throws Exception { final String strConst = "string constant"; final String testXmlString = @@ -343,8 +331,7 @@ public void shouldReturnCorrectConstantStringWhenSpecified() } @Test - public void shouldReturnDefaultMinValueWhenSpecified() - throws Exception + public void shouldReturnDefaultMinValueWhenSpecified() throws Exception { final String testXmlString = "" + @@ -357,8 +344,7 @@ public void shouldReturnDefaultMinValueWhenSpecified() } @Test - public void shouldReturnDefaultMaxValueWhenSpecified() - throws Exception + public void shouldReturnDefaultMaxValueWhenSpecified() throws Exception { final String testXmlString = "" + @@ -371,8 +357,7 @@ public void shouldReturnDefaultMaxValueWhenSpecified() } @Test - public void shouldReturnDefaultNullValueWhenSpecified() - throws Exception + public void shouldReturnDefaultNullValueWhenSpecified() throws Exception { final String testXmlString = "" + @@ -385,8 +370,7 @@ public void shouldReturnDefaultNullValueWhenSpecified() } @Test - public void shouldReturnCorrectMinValueWhenSpecified() - throws Exception + public void shouldReturnCorrectMinValueWhenSpecified() throws Exception { final String minVal = "10"; final String testXmlString = @@ -400,8 +384,7 @@ public void shouldReturnCorrectMinValueWhenSpecified() } @Test - public void shouldReturnCorrectMaxValueWhenSpecified() - throws Exception + public void shouldReturnCorrectMaxValueWhenSpecified() throws Exception { final String maxVal = "10"; final String testXmlString = @@ -416,8 +399,7 @@ public void shouldReturnCorrectMaxValueWhenSpecified() } @Test - public void shouldReturnCorrectNullValueWhenSpecified() - throws Exception + public void shouldReturnCorrectNullValueWhenSpecified() throws Exception { final String nullVal = "10"; final String testXmlString = diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index 5c59aea13a..88335f884a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -21,7 +21,7 @@ import org.xml.sax.SAXException; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.PrimitiveValue; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -44,8 +44,7 @@ public class EnumTypeTest { @Test - public void shouldHandleBinaryEnumType() - throws Exception + public void shouldHandleBinaryEnumType() throws Exception { final String testXmlString = "" + @@ -66,8 +65,7 @@ public void shouldHandleBinaryEnumType() } @Test - public void shouldHandleBooleanEnumType() - throws Exception + public void shouldHandleBooleanEnumType() throws Exception { final String testXmlString = "" + @@ -88,8 +86,7 @@ public void shouldHandleBooleanEnumType() } @Test - public void shouldHandleOptionalBooleanEnumType() - throws Exception + public void shouldHandleOptionalBooleanEnumType() throws Exception { final String nullValueStr = "255"; final String testXmlString = @@ -113,8 +110,7 @@ public void shouldHandleOptionalBooleanEnumType() } @Test - public void shouldHandleEnumTypeList() - throws Exception + public void shouldHandleEnumTypeList() throws Exception { final String testXmlString = "" + @@ -158,8 +154,7 @@ public void shouldHandleEnumTypeList() } @Test - public void shouldHandleCharEnumEncodingType() - throws Exception + public void shouldHandleCharEnumEncodingType() throws Exception { final String testXmlString = "" + @@ -229,10 +224,9 @@ public void shouldThrowExceptionWhenDuplicateNameSpecified() } @Test - public void shouldHandleEncodingTypesWithNamedTypes() - throws Exception + public void shouldHandleEncodingTypesWithNamedTypes() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "encoding-types-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(1).fields(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index d2f8fdaed5..3613f84fd4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -16,7 +16,7 @@ */ package uk.co.real_logic.sbe.xml; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import org.junit.jupiter.api.Test; import org.w3c.dom.Document; @@ -44,8 +44,7 @@ public class ErrorHandlerTest { @Test - public void shouldNotExitOnTypeErrorsAndWarnings() - throws Exception + public void shouldNotExitOnTypeErrorsAndWarnings() throws Exception { final String testXmlString = "" + @@ -94,13 +93,12 @@ public void shouldNotExitOnTypeErrorsAndWarnings() } @Test - public void shouldExitAfterTypes() - throws Exception + public void shouldExitAfterTypes() throws Exception { try { final ParserOptions options = ParserOptions.builder().suppressOutput(true).build(); - parse(TestUtil.getLocalResource("error-handler-types-schema.xml"), options); + parse(Tests.getLocalResource("error-handler-types-schema.xml"), options); } catch (final IllegalStateException ex) { @@ -112,13 +110,12 @@ public void shouldExitAfterTypes() } @Test - public void shouldExitAfterTypesWhenDupTypesDefined() - throws Exception + public void shouldExitAfterTypesWhenDupTypesDefined() throws Exception { try { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(TestUtil.getLocalResource("error-handler-types-dup-schema.xml"), options); + parse(Tests.getLocalResource("error-handler-types-dup-schema.xml"), options); } catch (final IllegalStateException ex) { @@ -130,13 +127,12 @@ public void shouldExitAfterTypesWhenDupTypesDefined() } @Test - public void shouldExitAfterMessageWhenDupMessageIdsDefined() - throws Exception + public void shouldExitAfterMessageWhenDupMessageIdsDefined() throws Exception { try { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(TestUtil.getLocalResource("error-handler-dup-message-schema.xml"), options); + parse(Tests.getLocalResource("error-handler-dup-message-schema.xml"), options); } catch (final IllegalStateException ex) { @@ -148,13 +144,12 @@ public void shouldExitAfterMessageWhenDupMessageIdsDefined() } @Test - public void shouldExitAfterMessage() - throws Exception + public void shouldExitAfterMessage() throws Exception { try { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(TestUtil.getLocalResource("error-handler-message-schema.xml"), options); + parse(Tests.getLocalResource("error-handler-message-schema.xml"), options); } catch (final IllegalStateException ex) { @@ -166,13 +161,12 @@ public void shouldExitAfterMessage() } @Test - public void shouldExitAfterMessageWhenGroupDimensionsNotComposite() - throws Exception + public void shouldExitAfterMessageWhenGroupDimensionsNotComposite() throws Exception { try { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(TestUtil.getLocalResource("error-handler-group-dimensions-schema.xml"), options); + parse(Tests.getLocalResource("error-handler-group-dimensions-schema.xml"), options); } catch (final IllegalStateException ex) { @@ -184,13 +178,12 @@ public void shouldExitAfterMessageWhenGroupDimensionsNotComposite() } @Test - public void shouldExitAfterTypesWhenCompositeOffsetsIncorrect() - throws Exception + public void shouldExitAfterTypesWhenCompositeOffsetsIncorrect() throws Exception { try { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(TestUtil.getLocalResource("error-handler-invalid-composite-offsets-schema.xml"), options); + parse(Tests.getLocalResource("error-handler-invalid-composite-offsets-schema.xml"), options); } catch (final IllegalStateException ex) { @@ -202,13 +195,29 @@ public void shouldExitAfterTypesWhenCompositeOffsetsIncorrect() } @Test - public void shouldExitInvalidFieldNames() - throws Exception + public void shouldExitAfterTypesWhenCompositeHasInvalidTypes() throws Exception { try { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(TestUtil.getLocalResource("error-handler-invalid-name.xml"), options); + parse(Tests.getLocalResource("error-handler-invalid-composite.xml"), options); + } + catch (final IllegalStateException ex) + { + assertEquals("had 2 errors", ex.getMessage()); + return; + } + + fail("expected IllegalStateException"); + } + + @Test + public void shouldExitInvalidFieldNames() throws Exception + { + try + { + final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); + parse(Tests.getLocalResource("error-handler-invalid-name.xml"), options); } catch (final IllegalStateException ex) { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java index 16f34fa433..8d5b0bcf0f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java @@ -16,7 +16,7 @@ package uk.co.real_logic.sbe.xml; import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import java.util.List; @@ -28,10 +28,9 @@ public class GroupWithDataTest { @Test - public void shouldParseSchemaSuccessfully() - throws Exception + public void shouldParseSchemaSuccessfully() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "group-with-data-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(1).fields(); final Field entriesGroup = fields.get(1); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java index f80b847706..05f4df47cd 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java @@ -16,7 +16,7 @@ package uk.co.real_logic.sbe.xml; import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import java.util.List; @@ -31,10 +31,9 @@ public class OffsetFileTest { @Test - public void shouldHandleAllTypeOffsets() - throws Exception + public void shouldHandleAllTypeOffsets() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "basic-types-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(1).fields(); @@ -51,10 +50,9 @@ public void shouldHandleAllTypeOffsets() } @Test - public void shouldHandleAllTypeOffsetsSetByXML() - throws Exception + public void shouldHandleAllTypeOffsetsSetByXml() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "basic-types-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(2).fields(); @@ -71,10 +69,9 @@ public void shouldHandleAllTypeOffsetsSetByXML() } @Test - public void shouldCalculateGroupOffsetWithNoPaddingFromBlockLength() - throws Exception + public void shouldCalculateGroupOffsetWithNoPaddingFromBlockLength() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "block-length-schema.xml"), ParserOptions.DEFAULT); final Message msg = schema.getMessage(1); @@ -95,10 +92,9 @@ public void shouldCalculateGroupOffsetWithNoPaddingFromBlockLength() } @Test - public void shouldCalculateGroupOffsetWithPaddingFromBlockLength() - throws Exception + public void shouldCalculateGroupOffsetWithPaddingFromBlockLength() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "block-length-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(2).fields(); @@ -118,10 +114,9 @@ public void shouldCalculateGroupOffsetWithPaddingFromBlockLength() } @Test - public void shouldCalculateGroupOffsetWithPaddingFromBlockLengthAndGroupBlockLength() - throws Exception + public void shouldCalculateGroupOffsetWithPaddingFromBlockLengthAndGroupBlockLength() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "block-length-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(3).fields(); @@ -141,10 +136,9 @@ public void shouldCalculateGroupOffsetWithPaddingFromBlockLengthAndGroupBlockLen } @Test - public void shouldCalculateDataOffsetWithPaddingFromBlockLength() - throws Exception + public void shouldCalculateDataOffsetWithPaddingFromBlockLength() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "block-length-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(4).fields(); @@ -155,10 +149,9 @@ public void shouldCalculateDataOffsetWithPaddingFromBlockLength() } @Test - public void shouldCalculateCompositeSizeWithOffsetsSpecified() - throws Exception + public void shouldCalculateCompositeSizeWithOffsetsSpecified() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "composite-offsets-schema.xml"), ParserOptions.DEFAULT); final CompositeType header = schema.messageHeader(); @@ -166,10 +159,9 @@ public void shouldCalculateCompositeSizeWithOffsetsSpecified() } @Test - public void shouldCalculateDimensionSizeWithOffsetsSpecified() - throws Exception + public void shouldCalculateDimensionSizeWithOffsetsSpecified() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "composite-offsets-schema.xml"), ParserOptions.DEFAULT); final CompositeType dimensions = schema.getMessage(1).fields().get(0).dimensionType(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java index 5591a0b1d3..838ad339d9 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java @@ -27,8 +27,7 @@ public class RelativeXIncludeTest { @Test - public void shouldParseFileInSubDir() - throws Exception + public void shouldParseFileInSubDir() throws Exception { final URL testResource = getClass().getClassLoader().getResource("sub/basic-schema.xml"); assertNotNull(testResource); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index 0813b38f5a..6eaf133380 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -21,7 +21,7 @@ import org.xml.sax.SAXException; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.PrimitiveValue; -import uk.co.real_logic.sbe.TestUtil; +import uk.co.real_logic.sbe.Tests; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -44,8 +44,7 @@ public class SetTypeTest { @Test - public void shouldHandleBinarySetType() - throws Exception + public void shouldHandleBinarySetType() throws Exception { final String testXmlString = "" + @@ -66,8 +65,7 @@ public void shouldHandleBinarySetType() } @Test - public void shouldHandleSetTypeList() - throws Exception + public void shouldHandleSetTypeList() throws Exception { final String testXmlString = "" + @@ -177,10 +175,9 @@ public void shouldThrowExceptionWhenValueOutOfBoundsSpecified() } @Test - public void shouldHandleEncodingTypesWithNamedTypes() - throws Exception + public void shouldHandleEncodingTypesWithNamedTypes() throws Exception { - final MessageSchema schema = parse(TestUtil.getLocalResource( + final MessageSchema schema = parse(Tests.getLocalResource( "encoding-types-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(1).fields(); diff --git a/sbe-tool/src/test/resources/error-handler-invalid-composite.xml b/sbe-tool/src/test/resources/error-handler-invalid-composite.xml new file mode 100644 index 0000000000..e558dcc22d --- /dev/null +++ b/sbe-tool/src/test/resources/error-handler-invalid-composite.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From a69084860ef1d4782d2146934fc87ae74bc31046 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 5 Jun 2020 16:47:35 +0100 Subject: [PATCH 0478/1594] [Java] Javadoc for packages. --- sbe-tool/src/main/java/overview.html | 9 --------- .../sbe/{util => }/ValidationUtil.java | 2 +- .../sbe/codec/java/package-info.java | 19 ++++++++++++++++++ .../co/real_logic/sbe/generation/c/CUtil.java | 2 +- .../sbe/generation/cpp/CppUtil.java | 2 +- .../sbe/generation/golang/GolangUtil.java | 2 +- .../sbe/generation/java/JavaUtil.java | 2 +- .../sbe/generation/package-info.java | 19 ++++++++++++++++++ .../uk/co/real_logic/sbe/ir/package-info.java | 20 +++++++++++++++++++ .../co/real_logic/sbe/json/package-info.java | 19 ++++++++++++++++++ .../co/real_logic/sbe/otf/package-info.java | 19 ++++++++++++++++++ .../uk/co/real_logic/sbe/package-info.java | 19 ++++++++++++++++++ .../co/real_logic/sbe/xml/CompositeType.java | 2 +- .../real_logic/sbe/xml/XmlSchemaParser.java | 2 +- .../co/real_logic/sbe/xml/package-info.java | 19 ++++++++++++++++++ 15 files changed, 141 insertions(+), 16 deletions(-) delete mode 100644 sbe-tool/src/main/java/overview.html rename sbe-tool/src/main/java/uk/co/real_logic/sbe/{util => }/ValidationUtil.java (99%) create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java diff --git a/sbe-tool/src/main/java/overview.html b/sbe-tool/src/main/java/overview.html deleted file mode 100644 index efd523814b..0000000000 --- a/sbe-tool/src/main/java/overview.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - Simple Binary Encoding - - - Documentation about how the encoders and decoders should be used. - - \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/util/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java similarity index 99% rename from sbe-tool/src/main/java/uk/co/real_logic/sbe/util/ValidationUtil.java rename to sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index b7f2ffe561..3f0bec26df 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/util/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package uk.co.real_logic.sbe.util; +package uk.co.real_logic.sbe; import java.util.Arrays; import java.util.HashSet; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java new file mode 100644 index 0000000000..cb198bd9bc --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Annotation for marking the order of groups in generated code to provide metadata. + */ +package uk.co.real_logic.sbe.codec.java; \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java index 6f21674564..ba95b8343c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java @@ -17,7 +17,7 @@ import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.SbeTool; -import uk.co.real_logic.sbe.util.ValidationUtil; +import uk.co.real_logic.sbe.ValidationUtil; import java.nio.ByteOrder; import java.util.EnumMap; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index 2abd4f163b..37b0c51ddb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -17,7 +17,7 @@ import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.SbeTool; -import uk.co.real_logic.sbe.util.ValidationUtil; +import uk.co.real_logic.sbe.ValidationUtil; import java.nio.ByteOrder; import java.util.EnumMap; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java index 1a3d3b551f..a1b88d4f14 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java @@ -17,7 +17,7 @@ import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.SbeTool; -import uk.co.real_logic.sbe.util.ValidationUtil; +import uk.co.real_logic.sbe.ValidationUtil; import java.util.EnumMap; import java.util.Map; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 35df2dd99f..5cfa2e09f4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -19,7 +19,7 @@ import uk.co.real_logic.sbe.SbeTool; import uk.co.real_logic.sbe.generation.Generators; import uk.co.real_logic.sbe.ir.Token; -import uk.co.real_logic.sbe.util.ValidationUtil; +import uk.co.real_logic.sbe.ValidationUtil; import java.io.IOException; import java.lang.reflect.Field; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java new file mode 100644 index 0000000000..4b63e831cf --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Codec generators for various programming languages which take {@link uk.co.real_logic.sbe.ir.Ir} as input. + */ +package uk.co.real_logic.sbe.generation; \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java new file mode 100644 index 0000000000..285aa0eae1 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Intermediate Representation for the parsed XML message schema which can be used for generating codecs or + * performing OTF decoding. + */ +package uk.co.real_logic.sbe.ir; \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java new file mode 100644 index 0000000000..83dd478fb9 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * An OTF decoder for decoding and printing messages in JSON format. + */ +package uk.co.real_logic.sbe.json; \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java new file mode 100644 index 0000000000..e91306582e --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * On-The-Fly (OTF) decoding of messages based on {@link uk.co.real_logic.sbe.ir.Ir} using a visitor pattern. + */ +package uk.co.real_logic.sbe.otf; \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java new file mode 100644 index 0000000000..724d6d3dbb --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * SBE Tool for generating encoders and decoders in multiple languages. + */ +package uk.co.real_logic.sbe; \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index ab99d62915..4e74dd7eed 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -45,7 +45,7 @@ public class CompositeType extends Type * SBE schema composite type. */ public static final String COMPOSITE_TYPE = "composite"; - public static final String SUB_TYPES_EXP = "type|enum|set|composite|ref|data|group"; + private static final String SUB_TYPES_EXP = "type|enum|set|composite|ref|data|group"; private final List compositesPath = new ArrayList<>(); private final Map containedTypeByNameMap = new LinkedHashMap<>(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 6d5f9e87f1..b0eb0d1520 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -20,7 +20,7 @@ import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import uk.co.real_logic.sbe.util.ValidationUtil; +import uk.co.real_logic.sbe.ValidationUtil; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilderFactory; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java new file mode 100644 index 0000000000..e755851de6 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Parser and types for the XML based messages schemas. + */ +package uk.co.real_logic.sbe.xml; \ No newline at end of file From ae28b60182f10290512870b27846b4efbc6ef614 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 5 Jun 2020 19:22:53 +0100 Subject: [PATCH 0479/1594] [Java] Javadoc and scope cleanups. --- .../co/real_logic/sbe/xml/MessageSchema.java | 5 ++++- .../co/real_logic/sbe/xml/XmlSchemaParser.java | 18 +++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index cb2a38c365..03b9b683e0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -29,9 +29,12 @@ */ public class MessageSchema { + /** + * Default message header type name for the SBE spec. + */ public static final String HEADER_TYPE_DEFAULT = "messageHeader"; - private final String packageName; // package (optional?) + private final String packageName; // package (required) private final String description; // description (optional) private final int id; // identifier for the schema (required) private final int version; // version (optional - default is 0) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index b0eb0d1520..007ef97b82 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -46,30 +46,30 @@ public class XmlSchemaParser { /** - * Key for storing {@link ErrorHandler} as user data in XML document + * Key for storing {@link ErrorHandler} as user data in XML document. */ public static final String ERROR_HANDLER_KEY = "SbeErrorHandler"; - public static final String TYPE_XPATH_EXPR = + static final String TYPE_XPATH_EXPR = "/*[local-name() = 'messageSchema']/types/" + EncodedDataType.ENCODED_DATA_TYPE; - public static final String COMPOSITE_XPATH_EXPR = + static final String COMPOSITE_XPATH_EXPR = "/*[local-name() = 'messageSchema']/types/" + CompositeType.COMPOSITE_TYPE; - public static final String ENUM_XPATH_EXPR = + static final String ENUM_XPATH_EXPR = "/*[local-name() = 'messageSchema']/types/" + EnumType.ENUM_TYPE; - public static final String SET_XPATH_EXPR = + static final String SET_XPATH_EXPR = "/*[local-name() = 'messageSchema']/types/" + SetType.SET_TYPE; - public static final String MESSAGE_SCHEMA_XPATH_EXPR = + static final String MESSAGE_SCHEMA_XPATH_EXPR = "/*[local-name() = 'messageSchema']"; - public static final String MESSAGE_XPATH_EXPR = + static final String MESSAGE_XPATH_EXPR = "//*[local-name() = 'message']"; /** - * Validate the document against a given schema. Error will be written to {@link java.lang.System#err}. + * Validate the document against a given schema. Errors will be written to {@link java.lang.System#err}. * * @param xsdFilename schema to validate against. * @param is source from which schema is read. Ideally it will have the systemId property set to resolve @@ -284,7 +284,7 @@ public static String getAttributeValue(final Node elementNode, final String attr if (attrNode == null || "".equals(attrNode.getNodeValue())) { throw new IllegalStateException( - "Element '" + elementNode.getNodeName() + "' has empty or missing attribute: " + attrName); + "element '" + elementNode.getNodeName() + "' has empty or missing attribute: " + attrName); } return attrNode.getNodeValue(); From 494b00a0918da216ff242c088ca93c5b538bef0a Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 6 Jun 2020 16:42:55 -0700 Subject: [PATCH 0480/1594] [C++]: remove constexpr from computeLength. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 7c01406678..1d45a4fba8 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1047,12 +1047,6 @@ private static CharSequence generateFileHeader( "# define SBE_NOEXCEPT\n" + "#endif\n\n" + - "#if __cplusplus >= 201402L\n" + - "# define SBE_CONSTEXPR_14 constexpr\n" + - "#else\n" + - "# define SBE_CONSTEXPR_14\n" + - "#endif\n\n" + - "#if __cplusplus >= 201703L\n" + "# include \n" + "# define SBE_NODISCARD [[nodiscard]]\n" + @@ -3043,7 +3037,7 @@ private CharSequence generateMessageLength(final List groups, final List< indent + " return " + ((groups.isEmpty() && varData.isEmpty()) ? "true" : "false") + ";\n" + indent + "}\n\n" + - indent + "SBE_NODISCARD static SBE_CONSTEXPR_14 size_t computeLength(%1$s)\n" + + indent + "SBE_NODISCARD static size_t computeLength(%1$s)\n" + indent + "{\n" + "#if defined(__GNUG__) && !defined(__clang__)\n" + "#pragma GCC diagnostic push\n" + From ca8f8d373c55039322cfb285ad415ac8c5aed8b7 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 8 Jun 2020 18:57:24 +0100 Subject: [PATCH 0481/1594] [Java] Warnings tidy up. --- .../java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 4 ++-- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 173d35830e..39d3347de0 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -2418,7 +2418,7 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu } else { - literal = "INT32_C(" + Long.toString(intValue) + ")"; + literal = "INT32_C(" + intValue + ")"; } break; } @@ -2436,7 +2436,7 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu } else { - literal = "INT64_C(" + String.valueOf(longValue) + ")"; + literal = "INT64_C(" + longValue + ")"; } break; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 1d45a4fba8..9c6e3f8495 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2415,7 +2415,7 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu } else { - literal = "INT32_C(" + Long.toString(intValue) + ")"; + literal = "INT32_C(" + intValue + ")"; } break; @@ -2431,7 +2431,7 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu } else { - literal = "INT64_C(" + String.valueOf(longValue) + ")"; + literal = "INT64_C(" + longValue + ")"; } break; From 54c5ff40c9a091ec025bd645a1c734abc25d71ec Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 9 Jun 2020 13:47:53 +0100 Subject: [PATCH 0482/1594] [Java] Improve Javadoc and reduce allocation when parsing XML. --- .../uk/co/real_logic/sbe/package-info.java | 19 ++++++++++++++++++ .../sbe/examples/ExampleTokenListener.java | 3 +++ .../examples/ExampleUsingGeneratedStub.java | 3 +++ .../ExampleUsingGeneratedStubExtension.java | 3 +++ .../real_logic/sbe/examples/OtfExample.java | 3 +++ .../real_logic/sbe/examples/package-info.java | 19 ++++++++++++++++++ .../uk/co/real_logic/sbe/PrimitiveType.java | 17 +++++----------- .../sbe/generation/c/package-info.java | 19 ++++++++++++++++++ .../sbe/generation/cpp/CppGenerator.java | 3 ++- .../cpp/NamespaceOutputManager.java | 2 +- .../sbe/generation/cpp/package-info.java | 19 ++++++++++++++++++ .../csharp/CSharpNamespaceOutputManager.java | 3 +-- .../sbe/generation/csharp/package-info.java | 19 ++++++++++++++++++ .../sbe/generation/golang/package-info.java | 19 ++++++++++++++++++ .../sbe/generation/java/package-info.java | 19 ++++++++++++++++++ .../main/java/uk/co/real_logic/sbe/ir/Ir.java | 2 +- .../java/uk/co/real_logic/sbe/ir/Signal.java | 4 ++-- .../java/uk/co/real_logic/sbe/ir/Token.java | 20 +++++++++++++------ .../co/real_logic/sbe/json/JsonPrinter.java | 2 +- .../sbe/json/JsonTokenListener.java | 2 +- .../co/real_logic/sbe/otf/TokenListener.java | 3 +-- .../java/uk/co/real_logic/sbe/xml/Field.java | 2 +- .../co/real_logic/sbe/xml/MessageSchema.java | 2 +- .../uk/co/real_logic/sbe/xml/Presence.java | 4 +++- 24 files changed, 179 insertions(+), 32 deletions(-) create mode 100644 sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java create mode 100644 sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java new file mode 100644 index 0000000000..72f29bd291 --- /dev/null +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Basic benchmarks for encoding and decoding of messages with SBE. + */ +package uk.co.real_logic.sbe; \ No newline at end of file diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java index bd911189a2..0c10eb734f 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java @@ -29,6 +29,9 @@ import java.util.Iterator; import java.util.List; +/** + * Example of a {@link TokenListener} implementation which prints a decoded message to a {@link PrintWriter}. + */ public class ExampleTokenListener implements TokenListener { private int compositeLevel = 0; diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java index db6e7b8da2..4faaff8839 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java @@ -29,6 +29,9 @@ import static java.nio.file.StandardOpenOption.READ; import static java.nio.file.StandardOpenOption.WRITE; +/** + * Example encode and decode of a complex message using generated stub codecs. + */ public class ExampleUsingGeneratedStub { private static final String ENCODING_FILENAME = "sbe.encoding.filename"; diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java index 022b426e3c..1d78e4ca86 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java @@ -32,6 +32,9 @@ import static java.nio.file.StandardOpenOption.READ; import static java.nio.file.StandardOpenOption.WRITE; +/** + * Example encode and decode of a complex message using generated stub codecs which has been extended. + */ public class ExampleUsingGeneratedStubExtension { private static final String ENCODING_FILENAME = "sbe.encoding.filename"; diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java index e7b0059a9a..763b0490be 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java @@ -36,6 +36,9 @@ import java.nio.file.Paths; import java.util.List; +/** + * Example of On-The-Fly decoding of a message based on encoded IR. + */ public class OtfExample { private static final MessageHeaderEncoder HEADER_ENCODER = new MessageHeaderEncoder(); diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java new file mode 100644 index 0000000000..cb509a8b33 --- /dev/null +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Samples showing usage of generated codecs and On-The-Fly (OTF) decoding. + */ +package uk.co.real_logic.sbe.examples; \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java index 7d2f84509c..6f37fbef0f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java @@ -34,6 +34,8 @@ public enum PrimitiveType FLOAT("float", 4, MIN_VALUE_FLOAT, MAX_VALUE_FLOAT, NULL_VALUE_FLOAT), DOUBLE("double", 8, MIN_VALUE_DOUBLE, MAX_VALUE_DOUBLE, NULL_VALUE_DOUBLE); + private static final PrimitiveType[] VALUES = PrimitiveType.values(); + private final String name; private final int size; private final PrimitiveValue minValue; @@ -139,23 +141,14 @@ public static boolean isUnsigned(final PrimitiveType type) */ public static PrimitiveType get(final String name) { - for (final PrimitiveType p : Singleton.VALUES) + for (final PrimitiveType primitiveType : VALUES) { - if (p.name.equals(name)) + if (primitiveType.name.equals(name)) { - return p; + return primitiveType; } } throw new IllegalArgumentException("No PrimitiveType for name: " + name); } - - /** - * Used to hold a reference to the values array without having it defensively copied - * on every call to {@link Enum} values(). - */ - static class Singleton - { - public static final PrimitiveType[] VALUES = PrimitiveType.values(); - } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java new file mode 100644 index 0000000000..0da617ddfc --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Generation of codecs for the C programming language. + */ +package uk.co.real_logic.sbe.generation.c; \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 9c6e3f8495..b4b5ecad08 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -39,7 +39,8 @@ import static uk.co.real_logic.sbe.ir.GenerationUtil.*; /** - * Codec generator for the C++11 programming language with conditional complication for C++14 and C++17 features. + * Codec generator for the C++11 programming language with conditional complication for additional C++14 and C++17 + * features. */ @SuppressWarnings("MethodLength") public class CppGenerator implements CodeGenerator diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java index ec50d0a246..aa74ef4a6a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java @@ -25,7 +25,7 @@ import static java.io.File.separatorChar; /** - * {@link OutputManager} for managing the creation of C++98 source files as the target of code generation. + * {@link OutputManager} for managing the creation of C++11 source files as the target of code generation. * The character encoding for the {@link java.io.Writer} is UTF-8. */ public class NamespaceOutputManager implements OutputManager diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java new file mode 100644 index 0000000000..0f8654dfb4 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Generation of codecs for the C++ programming language. + */ +package uk.co.real_logic.sbe.generation.cpp; \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java index 19a0215dc7..389d942fc4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java @@ -27,8 +27,7 @@ import static uk.co.real_logic.sbe.SbeTool.CSHARP_GENERATE_NAMESPACE_DIR; /** - * {@link OutputManager} for managing the creation of C# source files - * as the target of code generation. + * {@link OutputManager} for managing the creation of C# source files as the target of code generation. *

    * The character encoding for the {@link java.io.Writer} is UTF-8. */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java new file mode 100644 index 0000000000..ee8f94bd4d --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Generation of codecs for the C# programming language. + */ +package uk.co.real_logic.sbe.generation.csharp; \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java new file mode 100644 index 0000000000..205dd94217 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Generation of codecs for the Go Lang programming language. + */ +package uk.co.real_logic.sbe.generation.golang; \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java new file mode 100644 index 0000000000..ab6c669136 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Generation of codecs for the Java programming language. + */ +package uk.co.real_logic.sbe.generation.java; \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java index 2d77eb36fb..84b4e05b2b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java @@ -24,7 +24,7 @@ import java.util.regex.Pattern; /** - * Intermediate representation of SBE messages to be used for the generation of encoders and decoders + * Intermediate Representation (IR) of SBE messages to be used for the generation of encoders and decoders * as stubs in various languages. */ public class Ir diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java index 03a8cd9f9f..9d922375b4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java @@ -16,8 +16,8 @@ package uk.co.real_logic.sbe.ir; /** - * Signal the {@link uk.co.real_logic.sbe.ir.Token} role within a stream of tokens. These signals begin/end various entities - * such as fields, composites, messages, repeating groups, enumerations, bitsets, etc. + * Signal the {@link uk.co.real_logic.sbe.ir.Token} role within a stream of tokens. These signals begin/end various + * entities such as fields, composites, messages, repeating groups, enumerations, bitsets, etc. */ public enum Signal { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index 30ce063b4f..2eec689eb2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -75,11 +75,6 @@ public class Token */ public static final int VARIABLE_LENGTH = -1; - /** - * Offset not computed or set - */ - public static final int UNKNOWN_OFFSET = -1; - private final Signal signal; private final String name; private final String referencedName; @@ -281,7 +276,7 @@ else if (arrayLength > 1) * The offset for this token in the message. * * @return the offset of this Token. A value of 0 means the node has no relevant offset. A value of - * {@link Token#UNKNOWN_OFFSET} means this nodes true offset is dependent on variable length + * {@link Token#VARIABLE_LENGTH} means this nodes true offset is dependent on variable length * fields ahead of it in the encoding. */ public int offset() @@ -319,11 +314,21 @@ public Encoding encoding() return encoding; } + /** + * Is the encoding presence is a constant or not? + * + * @return true if the encoding presence is a constant or false if not. + */ public boolean isConstantEncoding() { return encoding.presence() == CONSTANT; } + /** + * Is the encoding presence is optional or not? + * + * @return true if the encoding presence is optional or false if not. + */ public boolean isOptionalEncoding() { return encoding.presence() == OPTIONAL; @@ -346,6 +351,9 @@ public String toString() '}'; } + /** + * Builder for Tokens which can simplify construction. + */ public static class Builder { private Signal signal; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java index 745fa2783c..3cfb9658bd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java @@ -25,7 +25,7 @@ import java.util.List; /** - * Pretty Print Json based upon the given Ir. + * Pretty Print JSON based upon the given Ir. */ public class JsonPrinter { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index 2435d347dd..df5c751891 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -28,7 +28,7 @@ import static uk.co.real_logic.sbe.PrimitiveType.CHAR; /** - * Listener for tokens when dynamically decoding a message which converts them to Json for output. + * Listener for tokens when dynamically decoding a message which converts them to JSON for output. */ public class JsonTokenListener implements TokenListener { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java index 9e68c255ef..b7d10cee82 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java @@ -23,8 +23,7 @@ /** * Callback interface to be implemented by code wanting to decode messages on-the-fly. *

    - * If all methods are not required then consider extending {@link AbstractTokenListener} - * for potential performance benefits and simpler code. + * If all methods are not required then consider extending {@link AbstractTokenListener} for simpler code. */ public interface TokenListener { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java index 089f5b573d..8b44abcaf5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java @@ -23,7 +23,7 @@ import static uk.co.real_logic.sbe.xml.XmlSchemaParser.*; /** - * Holder for Field (or Group or Data) information + * Representation for a field (or group or data) member from the SBE schema. */ public class Field { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index 03b9b683e0..416d27b7f5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -25,7 +25,7 @@ import static uk.co.real_logic.sbe.xml.XmlSchemaParser.*; /** - * Message schema composite for schema attributes, messageHeader, and reference for multiple {@link Message} objects. + * Message schema aggregate for schema attributes, messageHeader, and reference for multiple {@link Message} objects. */ public class MessageSchema { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java index 9993875732..510b5bf7f4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java @@ -35,6 +35,8 @@ public enum Presence */ OPTIONAL("optional"); + private static final Presence[] VALUES = values(); + private final String value; Presence(final String value) @@ -61,7 +63,7 @@ public String value() */ public static Presence get(final String name) { - for (final Presence p : values()) + for (final Presence p : VALUES) { if (p.value.equals(name)) { From 27c874af67379add1d9c892d2d621205a6aaff30 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 9 Jun 2020 13:55:51 +0100 Subject: [PATCH 0483/1594] [Java] Bump version. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index e0ae520094..46ea34ec4d 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.18.3-SNAPSHOT \ No newline at end of file +1.19.0-SNAPSHOT \ No newline at end of file From e2e41deb68de0571395c0f5532339bee12cc161c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 11 Jun 2020 16:34:32 +0100 Subject: [PATCH 0484/1594] [Java] Upgrade to Gradle 6.5. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 790c3d044d..991047e6cb 100644 --- a/build.gradle +++ b/build.gradle @@ -681,6 +681,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.4.1' + gradleVersion = '6.5' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 21e622da69..186b71557c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From a9d59c1d76fc62fe50ec98ae1c8c3afafadc2b44 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 16 Jun 2020 16:49:41 +0100 Subject: [PATCH 0485/1594] [Java] Upgrade to Shadow 6.0.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 991047e6cb..e0eb3c822a 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ plugins { id 'java-library' id 'idea' id 'io.freefair.javadoc-links' version '5.1.0' apply false - id 'com.github.johnrengelman.shadow' version '5.2.0' apply false + id 'com.github.johnrengelman.shadow' version '6.0.0' apply false id "com.github.ben-manes.versions" version "0.28.0" } From ed28ce464723c7f0d8bdab2a5fa612fc518d7bce Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 16 Jun 2020 23:04:43 +0200 Subject: [PATCH 0486/1594] [Java] Enable Java 14 build on CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aeef260a2d..fea54e0cd6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '11' ] + java: [ '8', '11', '14' ] steps: - name: Checkout code uses: actions/checkout@v2 From 3ffb66ffbb639f43b657fb6fc843d3c5a9f0fbd5 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 18 Jun 2020 15:16:09 +0100 Subject: [PATCH 0487/1594] [Java] Remove dependency on javadoc-links. --- build.gradle | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index e0eb3c822a..22876ca5a6 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,6 @@ buildscript { plugins { id 'java-library' id 'idea' - id 'io.freefair.javadoc-links' version '5.1.0' apply false id 'com.github.johnrengelman.shadow' version '6.0.0' apply false id "com.github.ben-manes.versions" version "0.28.0" } @@ -132,7 +131,6 @@ subprojects { apply plugin: 'java-library' apply plugin: 'checkstyle' apply plugin: 'eclipse' - apply plugin: 'io.freefair.javadoc-links' group = sbeGroup version = sbeVersion @@ -165,6 +163,12 @@ subprojects { options.encoding = 'UTF-8' options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' + options.links("https://www.javadoc.io/doc/org.agrona/agrona/${agronaVersion}/") + if (JavaVersion.current().isJava11Compatible()) { + options.links("https://docs.oracle.com/en/java/javase/${JavaVersion.current().majorVersion}/docs/api/") + } else { + options.links("https://docs.oracle.com/javase/${JavaVersion.current().majorVersion}/docs/api/") + } if (JavaVersion.current().isJava10Compatible()) { options.addBooleanOption 'html5', true } @@ -427,6 +431,7 @@ project(':sbe-samples') { javadoc { source += sourceSets.generated.allJava + source += project(':sbe-tool').sourceSets.main.allJava } java { @@ -501,6 +506,8 @@ project(':sbe-benchmarks') { } jar.finalizedBy shadowJar + + javadoc.enabled = false } /* From 2a1866a4dc62a84f3285c1a916df67051b904f61 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 23 Jun 2020 15:47:14 +0100 Subject: [PATCH 0488/1594] [cpp] Improve generate code for computeLength method on codecs. Issue #796. --- .../sbe/generation/cpp/CppGenerator.java | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index b4b5ecad08..de3ea5d77b 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2800,6 +2800,7 @@ private Object[] generateMessageLengthArgs( } final int endSignal = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); + final String groupName = formatPropertyName(groupToken.name()); if (count > 0) { @@ -2813,18 +2814,18 @@ private Object[] generateMessageLengthArgs( sb.append("std::size_t"); if (withName) { - sb.append(" ").append(groupToken.name()).append("Length = 0"); + sb.append(" ").append(groupName).append("Length = 0"); } } else { sb.append("const std::vector>&"); + sb.append(">> &"); if (withName) { - sb.append(" ").append(groupToken.name()).append("ItemLengths = {}"); + sb.append(groupName).append("ItemLengths = {}"); } } @@ -2849,7 +2850,7 @@ private Object[] generateMessageLengthArgs( sb.append("std::size_t"); if (withName) { - sb.append(" ").append(varDataToken.name()).append("Length = 0"); + sb.append(" ").append(formatPropertyName(varDataToken.name())).append("Length = 0"); } count += 1; @@ -2937,11 +2938,11 @@ private CharSequence generateMessageLength(final List groups, final List< final long minCount = numInGroupToken.encoding().applicableMinValue().longValue(); final long maxCount = numInGroupToken.encoding().applicableMaxValue().longValue(); - final String countName = groupToken.name() + + final String countName = formatPropertyName(groupToken.name()) + (isMessageConstLength(thisGroup) ? "Length" : "ItemLengths.size()"); - final String minCheck = minCount > 0 ? countName + " < " + minCount + " || " : ""; - final String maxCheck = countName + " > " + maxCount; + final String minCheck = minCount > 0 ? countName + " < " + minCount + "LL || " : ""; + final String maxCheck = countName + " > " + maxCount + "LL"; new Formatter(sbEncode).format("\n" + indent + " length += %1$s::sbeHeaderSize();\n", @@ -2955,7 +2956,7 @@ private CharSequence generateMessageLength(final List groups, final List< indent + " throw std::runtime_error(\"%5$s outside of allowed range [E110]\");\n" + indent + " }\n" + indent + " length += %1$sLength * %2$s::sbeBlockLength();\n", - groupToken.name(), + formatPropertyName(groupToken.name()), formatClassName(groupToken.name()), minCheck, maxCheck, @@ -2967,8 +2968,8 @@ private CharSequence generateMessageLength(final List groups, final List< indent + " if (%3$s%4$s)\n" + indent + " {\n" + indent + " throw std::runtime_error(\"%5$s outside of allowed range [E110]\");\n" + - indent + " }\n" + - indent + " for (const auto& e: %1$sItemLengths)\n" + + indent + " }\n\n" + + indent + " for (const auto &e: %1$sItemLengths)\n" + indent + " {\n" + indent + " #if __cpluplus >= 201703L\n" + indent + " length += std::apply(%2$s::computeLength, e);\n" + @@ -2976,7 +2977,7 @@ private CharSequence generateMessageLength(final List groups, final List< indent + " length += %2$s::computeLength(%6$s);\n" + indent + " #endif\n" + indent + " }\n", - groupToken.name(), + formatPropertyName(groupToken.name()), formatClassName(groupToken.name()), minCheck, maxCheck, @@ -2990,8 +2991,7 @@ private CharSequence generateMessageLength(final List groups, final List< indent + " e.skip();\n" + indent + " });\n", formatClassName(groupToken.name()), - formatPropertyName(groupToken.name()), - groupToken.name()); + formatPropertyName(groupToken.name())); i = endSignal; } @@ -3005,22 +3005,21 @@ private CharSequence generateMessageLength(final List groups, final List< throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); } - final String propertyName = toUpperFirstChar(varDataToken.name()); final Token lengthToken = Generators.findFirst("length", varData, i); new Formatter(sbEncode).format("\n" + indent + " length += %1$sHeaderLength();\n" + - indent + " if (%1$sLength > %2$d)\n" + + indent + " if (%1$sLength > %2$dLL)\n" + indent + " {\n" + indent + " throw std::runtime_error(\"%1$sLength too long for length type [E109]\");\n" + indent + " }\n" + indent + " length += %1$sLength;\n", - varDataToken.name(), + formatPropertyName(varDataToken.name()), lengthToken.encoding().applicableMaxValue().longValue()); new Formatter(sbSkip).format( indent + " skip%1$s();\n", - propertyName); + toUpperFirstChar(varDataToken.name())); i += varDataToken.componentTokenCount(); } @@ -3030,30 +3029,28 @@ private CharSequence generateMessageLength(final List groups, final List< new Formatter(sb).format("\n" + indent + "void skip()\n" + indent + "{\n" + - "%3$s" + + sbSkip + indent + "}\n\n" + indent + "SBE_NODISCARD static SBE_CONSTEXPR bool isConstLength() SBE_NOEXCEPT\n" + indent + "{\n" + - indent + " return " + ((groups.isEmpty() && varData.isEmpty()) ? "true" : "false") + ";\n" + + indent + " return " + (groups.isEmpty() && varData.isEmpty()) + ";\n" + indent + "}\n\n" + - indent + "SBE_NODISCARD static size_t computeLength(%1$s)\n" + + indent + "SBE_NODISCARD static std::size_t computeLength(%1$s)\n" + indent + "{\n" + "#if defined(__GNUG__) && !defined(__clang__)\n" + "#pragma GCC diagnostic push\n" + "#pragma GCC diagnostic ignored \"-Wtype-limits\"\n" + "#endif\n" + - indent + " size_t length = sbeBlockLength();\n\n" + - "%2$s" + + indent + " std::size_t length = sbeBlockLength();\n" + + sbEncode + "\n" + indent + " return length;\n" + "#if defined(__GNUG__) && !defined(__clang__)\n" + "#pragma GCC diagnostic pop\n" + "#endif\n" + indent + "}\n", - generateMessageLengthArgs(groups, varData, indent + INDENT, true)[0], - sbEncode, - sbSkip); + generateMessageLengthArgs(groups, varData, indent + INDENT, true)[0]); return sb; } From d328e7ee92dbfe4fa0799396b9c951be30f1f69b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 23 Jun 2020 15:57:25 +0100 Subject: [PATCH 0489/1594] [cpp] Reduce string parsing an allocation. --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index de3ea5d77b..86ad5a3879 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2911,7 +2911,8 @@ private CharSequence generateMessageLengthCallPre17Helper(final List toke { sb.append(", "); } - new Formatter(sb).format("std::get<%1$d>(e)", i); + + sb.append("std::get<").append(i).append(">(e)"); } return sb; From 194ae451f323b6c46676badfdea57e52ac8a7f79 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 29 Jun 2020 15:09:29 +0100 Subject: [PATCH 0490/1594] [cpp] Formatting. --- .../src/main/cpp/GeneratedStubExample.cpp | 50 ++++++---- sbe-samples/src/main/cpp/OtfExample.cpp | 94 +++++++++---------- 2 files changed, 77 insertions(+), 67 deletions(-) diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index e77aa1fdeb..2d3fac6fcf 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -23,20 +23,24 @@ #include "baseline/MessageHeader.h" #include "baseline/Car.h" -using namespace std; using namespace baseline; #if defined(WIN32) || defined(_WIN32) # define snprintf _snprintf #endif /* WIN32 */ -char VEHICLE_CODE[] = {'a', 'b', 'c', 'd', 'e', 'f'}; -char MANUFACTURER_CODE[] = {'1', '2', '3'}; +char VEHICLE_CODE[] = { 'a', 'b', 'c', 'd', 'e', 'f' }; +char MANUFACTURER_CODE[] = { '1', '2', '3' }; const char *MANUFACTURER = "Honda"; const char *MODEL = "Civic VTi"; const int messageHeaderVersion = 0; -std::size_t encodeHdr(MessageHeader &hdr, Car &car, char *buffer, std::uint64_t offset, std::uint64_t bufferLength) +std::size_t encodeHdr( + MessageHeader &hdr, + Car &car, + char *buffer, + std::uint64_t offset, + std::uint64_t bufferLength) { // encode the header hdr.wrap(buffer, offset, messageHeaderVersion, bufferLength) @@ -48,16 +52,20 @@ std::size_t encodeHdr(MessageHeader &hdr, Car &car, char *buffer, std::uint64_t return hdr.encodedLength(); } -std::size_t decodeHdr(MessageHeader &hdr, char *buffer, std::uint64_t offset, std::uint64_t bufferLength) +std::size_t decodeHdr( + MessageHeader &hdr, + char *buffer, + std::uint64_t offset, + std::uint64_t bufferLength) { hdr.wrap(buffer, offset, messageHeaderVersion, bufferLength); // decode the header - cout << "messageHeader.blockLength=" << hdr.blockLength() << endl; - cout << "messageHeader.templateId=" << hdr.templateId() << endl; - cout << "messageHeader.schemaId=" << hdr.schemaId() << endl; - cout << "messageHeader.schemaVersion=" << hdr.version() << endl; - cout << "messageHeader.encodedLength=" << hdr.encodedLength() << endl; + std::cout << "messageHeader.blockLength=" << hdr.blockLength() << std::endl; + std::cout << "messageHeader.templateId=" << hdr.templateId() << std::endl; + std::cout << "messageHeader.schemaId=" << hdr.schemaId() << std::endl; + std::cout << "messageHeader.schemaVersion=" << hdr.version() << std::endl; + std::cout << "messageHeader.encodedLength=" << hdr.encodedLength() << std::endl; return hdr.encodedLength(); } @@ -280,7 +288,7 @@ std::size_t decodeCar( performanceFigures.next(); std::cout << "\ncar.performanceFigures.octaneRating=" << (std::uint64_t)performanceFigures.octaneRating(); - Car::PerformanceFigures::Acceleration &acceleration = performanceFigures.acceleration(); + baseline::Car::PerformanceFigures::Acceleration &acceleration = performanceFigures.acceleration(); while (acceleration.hasNext()) { acceleration.next(); @@ -301,12 +309,12 @@ std::size_t decodeCar( std::cout << "\ncar.activationCodeLength=" << bytesCopied; std::cout << "\ncar.activationCode=" << std::string(tmp, bytesCopied); - std::cout << "\ncar.encodedLength=" << (int)car.encodedLength() << "\n"; + std::cout << "\ncar.encodedLength=" << (int)car.encodedLength() << std::endl; return car.encodedLength(); } -int main(int argc, const char* argv[]) +int main(int argc, const char **argv) { char buffer[2048]; MessageHeader hdr; @@ -314,29 +322,31 @@ int main(int argc, const char* argv[]) std::size_t encodeHdrLength = encodeHdr(hdr, car, buffer, 0, sizeof(buffer)); std::size_t encodeMsgLength = encodeCar(car, buffer, hdr.encodedLength(), sizeof(buffer)); - std::size_t predictedLength = Car::computeLength({11, 14, 13}, {3, 3}, 5, 9, 8); + std::size_t predictedLength = Car::computeLength({ 11, 14, 13 }, { 3, 3 }, 5, 9, 8); - cout << "Encoded Lengths are " << encodeHdrLength << " + " << encodeMsgLength << " (" << predictedLength << ")" << endl; + std::cout << "Encoded Lengths are " << encodeHdrLength << " + " << encodeMsgLength << " (" << predictedLength << ")" + << std::endl; std::size_t decodeHdrLength = decodeHdr(hdr, buffer, 0, sizeof(buffer)); - std::size_t decodeMsgLength = decodeCar(car, buffer, hdr.encodedLength(), hdr.blockLength(), hdr.version(), sizeof(buffer)); + std::size_t decodeMsgLength = decodeCar( + car, buffer, hdr.encodedLength(), hdr.blockLength(), hdr.version(), sizeof(buffer)); - cout << "Decoded Lengths are " << decodeHdrLength << " + " << decodeMsgLength << endl; + std::cout << "Decoded Lengths are " << decodeHdrLength << " + " << decodeMsgLength << std::endl; if (encodeHdrLength != decodeHdrLength) { - cerr << "Encode/Decode header lengths do not match\n"; + std::cerr << "Encode/Decode header lengths do not match" << std::endl; return EXIT_FAILURE; } if (encodeMsgLength != decodeMsgLength) { - cerr << "Encode/Decode message lengths do not match\n"; + std::cerr << "Encode/Decode message lengths do not match" << std::endl; return EXIT_FAILURE; } car.wrapForDecode(buffer, hdr.encodedLength(), hdr.blockLength(), hdr.version(), sizeof(buffer)); - cout << "Encoded json: '" << car << "'" << endl; + std::cout << "Encoded json: '" << car << "'" << std::endl; return EXIT_SUCCESS; } diff --git a/sbe-samples/src/main/cpp/OtfExample.cpp b/sbe-samples/src/main/cpp/OtfExample.cpp index fb0e967fd0..249398027b 100644 --- a/sbe-samples/src/main/cpp/OtfExample.cpp +++ b/sbe-samples/src/main/cpp/OtfExample.cpp @@ -46,31 +46,29 @@ class ExampleTokenListener } virtual std::string determineName( - Token& fieldToken, - std::vector& tokens, + Token &fieldToken, + std::vector &tokens, std::size_t fromIndex) { - return (compositeLevel > 1) ? tokens.at(fromIndex).name() : fieldToken.name(); + return compositeLevel > 1 ? tokens.at(fromIndex).name() : fieldToken.name(); } - virtual void onBeginMessage(Token& token) + virtual void onBeginMessage(Token &token) { scope.push_back(token.name() + "."); } - virtual void onEndMessage(Token& token) + virtual void onEndMessage(Token &token) { scope.pop_back(); } - std::string asString(const Token& token, const char *buffer) + std::string asString(const Token &token, const char *buffer) { - const Encoding& encoding = token.encoding(); + const Encoding &encoding = token.encoding(); const PrimitiveType type = encoding.primitiveType(); - const std::uint64_t length = - (token.isConstantEncoding()) ? - encoding.constValue().size() : - static_cast(token.encodedLength()); + const std::uint64_t length = token.isConstantEncoding() ? + encoding.constValue().size() : static_cast(token.encodedLength()); std::ostringstream result; std::uint64_t num = length / lengthOfType(type); @@ -90,6 +88,7 @@ class ExampleTokenListener } break; } + case PrimitiveType::INT8: case PrimitiveType::INT16: case PrimitiveType::INT32: @@ -99,9 +98,10 @@ class ExampleTokenListener { const char *separator = ""; - for (size_t i = 0; i < num; i++) + for (std::size_t i = 0; i < num; i++) { - result << separator << Encoding::getInt(type, encoding.byteOrder(), buffer + (i * lengthOfType(type))); + result << separator + << Encoding::getInt(type, encoding.byteOrder(), buffer + (i * lengthOfType(type))); separator = ", "; } } @@ -118,6 +118,7 @@ class ExampleTokenListener } break; } + case PrimitiveType::UINT8: case PrimitiveType::UINT16: case PrimitiveType::UINT32: @@ -136,6 +137,7 @@ class ExampleTokenListener } break; } + case PrimitiveType::FLOAT: case PrimitiveType::DOUBLE: { @@ -146,42 +148,41 @@ class ExampleTokenListener } break; } + default: - { break; - } } return result.str(); } virtual void onEncoding( - Token& fieldToken, + Token &fieldToken, const char *buffer, - Token& typeToken, + Token &typeToken, std::uint64_t actingVersion) { printScope(); - std::string name = (compositeLevel > 1) ? typeToken.name() : fieldToken.name(); + std::string name = compositeLevel > 1 ? typeToken.name() : fieldToken.name(); - std::cout << name << "=" << asString(typeToken, buffer) << "\n"; + std::cout << name << "=" << asString(typeToken, buffer) << std::endl; } virtual void onEnum( - Token& fieldToken, + Token &fieldToken, const char *buffer, std::vector& tokens, std::size_t fromIndex, std::size_t toIndex, std::uint64_t actingVersion) { - const Token& typeToken = tokens.at(fromIndex + 1); - const Encoding& encoding = typeToken.encoding(); + const Token &typeToken = tokens.at(fromIndex + 1); + const Encoding &encoding = typeToken.encoding(); printScope(); std::cout << fieldToken.name() << "="; - for (size_t i = fromIndex + 1; i < toIndex; i++) + for (std::size_t i = fromIndex + 1; i < toIndex; i++) { const Token &token = tokens.at(i); const PrimitiveValue constValue = token.encoding().constValue(); @@ -210,25 +211,25 @@ class ExampleTokenListener } } - std::cout << "\n"; + std::cout << std::endl; } virtual void onBitSet( - Token& fieldToken, + Token &fieldToken, const char *buffer, - std::vector& tokens, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex, std::uint64_t actingVersion) { - const Token& typeToken = tokens.at(fromIndex + 1); - const Encoding& encoding = typeToken.encoding(); + const Token &typeToken = tokens.at(fromIndex + 1); + const Encoding &encoding = typeToken.encoding(); const std::uint64_t value = encoding.getAsUInt(buffer); printScope(); std::cout << fieldToken.name() << ":"; - for (size_t i = fromIndex + 1; i < toIndex; i++) + for (std::size_t i = fromIndex + 1; i < toIndex; i++) { const Token &token = tokens.at(i); const std::uint64_t constValue = token.encoding().constValue().getAsUInt(); @@ -244,12 +245,12 @@ class ExampleTokenListener } } - std::cout << "\n"; + std::cout << std::endl; } virtual void onBeginComposite( - Token& fieldToken, - std::vector& tokens, + Token &fieldToken, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex) { @@ -258,8 +259,8 @@ class ExampleTokenListener } virtual void onEndComposite( - Token& fieldToken, - std::vector& tokens, + Token &fieldToken, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex) { @@ -267,16 +268,14 @@ class ExampleTokenListener scope.pop_back(); } - virtual void onGroupHeader( - Token& token, - std::uint64_t numInGroup) + virtual void onGroupHeader(Token &token, std::uint64_t numInGroup) { printScope(); std::cout << token.name() << " Group Header: numInGroup=" << numInGroup << "\n"; } virtual void onBeginGroup( - Token& token, + Token &token, std::uint64_t groupIndex, std::uint64_t numInGroup) { @@ -284,7 +283,7 @@ class ExampleTokenListener } virtual void onEndGroup( - Token& token, + Token &token, std::uint64_t groupIndex, std::uint64_t numInGroup) { @@ -292,13 +291,13 @@ class ExampleTokenListener } virtual void onVarData( - Token& fieldToken, + Token &fieldToken, const char *buffer, std::uint64_t length, - Token& typeToken) + Token &typeToken) { printScope(); - std::cout << fieldToken.name() << "=" << std::string(buffer, length) << "\n"; + std::cout << fieldToken.name() << "=" << std::string(buffer, length) << std::endl; } }; @@ -383,7 +382,7 @@ std::uint64_t encodeHdrAndCar(char *buffer, std::uint64_t length) .putManufacturerCode(MANUFACTURER_CODE) .booster().boostType(BoostType::NITROUS).horsePower(200); - Car::FuelFigures& fuelFigures = car.fuelFiguresCount(FUEL_FIGURES_COUNT); + Car::FuelFigures &fuelFigures = car.fuelFiguresCount(FUEL_FIGURES_COUNT); fuelFigures .next().speed(fuel1Speed).mpg(fuel1Mpg); @@ -435,7 +434,7 @@ int main(int argc, char **argv) if (irDecoder.decode("generated/example-schema.sbeir") != 0) { - std::cerr << "could not load SBE IR\n"; + std::cerr << "could not load SBE IR" << std::endl; return -1; } @@ -452,14 +451,15 @@ int main(int argc, char **argv) std::shared_ptr> messageTokens = irDecoder.message( static_cast(templateId), static_cast(actingVersion)); - const std::size_t result = OtfMessageDecoder::decode( + std::size_t result = OtfMessageDecoder::decode( messageBuffer, length, actingVersion, blockLength, messageTokens, tokenListener); - std::cout << "result = " << result << "\n"; + std::cout << "result = " << result << std::endl; if (result != static_cast(sz - headerDecoder.encodedLength())) { - std::cerr << "Message not properly decoded " << result << "/(" << sz << " - " << headerDecoder.encodedLength() << ")\n"; + std::cerr << "Message not properly decoded " << result << "/(" << sz << " - " << headerDecoder.encodedLength() + << ")" << std::endl; return -1; } From df414775606965238081ff7bcf223de09c92db19 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 29 Jun 2020 15:17:30 +0100 Subject: [PATCH 0491/1594] [C++] Use C++ style casts. --- .../src/main/cpp/GeneratedStubExample.cpp | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index 2d3fac6fcf..d2303392d6 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -91,7 +91,7 @@ std::size_t encodeCar(Car &car, char *buffer, std::uint64_t offset, std::uint64_ car.engine() .capacity(2000) - .numCylinders((short)4) + .numCylinders(static_cast(4)) .putManufacturerCode(MANUFACTURER_CODE) .efficiency((std::int8_t)35) .boosterEnabled(BooleanType::T) @@ -114,14 +114,14 @@ std::size_t encodeCar(Car &car, char *buffer, std::uint64_t offset, std::uint64_ Car::PerformanceFigures &performanceFigures = car.performanceFiguresCount(2); performanceFigures.next() - .octaneRating((short)95) + .octaneRating(static_cast(95)) .accelerationCount(3) .next().mph(30).seconds(4.0f) .next().mph(60).seconds(7.5f) .next().mph(100).seconds(12.2f); performanceFigures.next() - .octaneRating((short)99) + .octaneRating(static_cast(99)) .accelerationCount(3) .next().mph(30).seconds(3.8f) .next().mph(60).seconds(7.1f) @@ -210,7 +210,8 @@ std::size_t decodeCar( std::cout << "\ncar.performanceFigures.octaneRatingId=" << Car::PerformanceFigures::octaneRatingId(); std::cout << "\ncar.performanceFigures.accelerationId=" << Car::PerformanceFigures::accelerationId(); std::cout << "\ncar.performanceFigures.acceleration.mphId=" << Car::PerformanceFigures::Acceleration::mphId(); - std::cout << "\ncar.performanceFigures.acceleration.secondsId=" << Car::PerformanceFigures::Acceleration::secondsId(); + std::cout << "\ncar.performanceFigures.acceleration.secondsId=" + << Car::PerformanceFigures::Acceleration::secondsId(); std::cout << "\ncar.manufacturerId=" << Car::manufacturerId(); std::cout << "\ncar.manufacturerCharacterEncoding=" << Car::manufacturerCharacterEncoding(); std::cout << "\ncar.modelId=" << Car::modelId(); @@ -249,10 +250,10 @@ std::size_t decodeCar( std::cout << "\ncar.discountedModel=" << format(car.discountedModel()); Engine &engine = car.engine(); - std::cout << "\ncar.engine.capacity=" << (int)engine.capacity(); - std::cout << "\ncar.engine.numCylinders=" << (int)engine.numCylinders(); - std::cout << "\ncar.engine.maxRpm=" << (int)engine.maxRpm(); - std::cout << "\ncar.engine.manufacturerCodeLength=" << (int)engine.manufacturerCodeLength(); + std::cout << "\ncar.engine.capacity=" << static_cast(engine.capacity()); + std::cout << "\ncar.engine.numCylinders=" << static_cast(engine.numCylinders()); + std::cout << "\ncar.engine.maxRpm=" << static_cast(engine.maxRpm()); + std::cout << "\ncar.engine.manufacturerCodeLength=" << static_cast(engine.manufacturerCodeLength()); std::cout << "\ncar.engine.manufacturerCode="; separator = ""; for (std::uint64_t i = 0; i < Engine::manufacturerCodeLength(); i++) @@ -263,19 +264,19 @@ std::size_t decodeCar( char tmp[1024]; std::uint64_t bytesCopied = engine.getFuel(tmp, sizeof(tmp)); - std::cout << "\ncar.engine.efficiency=" << (int)engine.efficiency(); + std::cout << "\ncar.engine.efficiency=" << static_cast(engine.efficiency()); std::cout << "\ncar.engine.boosterEnabled=" << format(engine.boosterEnabled()); std::cout << "\ncar.engine.fuelLength=" << bytesCopied; std::cout << "\ncar.engine.fuel=" << std::string(tmp, bytesCopied); std::cout << "\ncar.engine.booster.boostType=" << format(engine.booster().boostType()); - std::cout << "\ncar.engine.booster.horsePower=" << (int)engine.booster().horsePower(); + std::cout << "\ncar.engine.booster.horsePower=" << static_cast(engine.booster().horsePower()); Car::FuelFigures &fuelFigures = car.fuelFigures(); while (fuelFigures.hasNext()) { fuelFigures.next(); - std::cout << "\ncar.fuelFigures.speed=" << (int)fuelFigures.speed(); - std::cout << "\ncar.fuelFigures.mpg=" << std::setprecision(1) << (double)fuelFigures.mpg(); + std::cout << "\ncar.fuelFigures.speed=" << static_cast(fuelFigures.speed()); + std::cout << "\ncar.fuelFigures.mpg=" << std::setprecision(1) << static_cast(fuelFigures.mpg()); std::string usageDesc = fuelFigures.getUsageDescriptionAsString(); std::cout << "\ncar.fuelFigures.usageDescriptionLength=" << usageDesc.length(); @@ -286,14 +287,16 @@ std::size_t decodeCar( while (performanceFigures.hasNext()) { performanceFigures.next(); - std::cout << "\ncar.performanceFigures.octaneRating=" << (std::uint64_t)performanceFigures.octaneRating(); + std::cout << "\ncar.performanceFigures.octaneRating=" + << static_cast(performanceFigures.octaneRating()); baseline::Car::PerformanceFigures::Acceleration &acceleration = performanceFigures.acceleration(); while (acceleration.hasNext()) { acceleration.next(); std::cout << "\ncar.performanceFigures.acceleration.mph=" << acceleration.mph(); - std::cout << "\ncar.performanceFigures.acceleration.seconds=" << std::setprecision(1) << acceleration.seconds(); + std::cout << "\ncar.performanceFigures.acceleration.seconds=" << + std::setprecision(1) << acceleration.seconds(); } } @@ -309,7 +312,7 @@ std::size_t decodeCar( std::cout << "\ncar.activationCodeLength=" << bytesCopied; std::cout << "\ncar.activationCode=" << std::string(tmp, bytesCopied); - std::cout << "\ncar.encodedLength=" << (int)car.encodedLength() << std::endl; + std::cout << "\ncar.encodedLength=" << static_cast(car.encodedLength()) << std::endl; return car.encodedLength(); } From 0845fe7ca45e264839702cf18eaacf7f03b7201f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 29 Jun 2020 15:31:48 +0100 Subject: [PATCH 0492/1594] [C++] Formatting. --- sbe-tool/src/main/cpp/otf/Encoding.h | 19 ++- sbe-tool/src/main/cpp/otf/IrDecoder.h | 26 ++-- sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h | 14 +- sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h | 126 ++++++++++-------- sbe-tool/src/main/cpp/otf/Token.h | 6 +- 5 files changed, 110 insertions(+), 81 deletions(-) diff --git a/sbe-tool/src/main/cpp/otf/Encoding.h b/sbe-tool/src/main/cpp/otf/Encoding.h index af007b2668..14ca5d1be1 100644 --- a/sbe-tool/src/main/cpp/otf/Encoding.h +++ b/sbe-tool/src/main/cpp/otf/Encoding.h @@ -338,8 +338,7 @@ class Encoding std::string characterEncoding, std::string epoch, std::string timeUnit, - std::string semanticType) - : + std::string semanticType) : m_presence(presence), m_primitiveType(type), m_byteOrder(byteOrder), @@ -532,42 +531,42 @@ class Encoding return getDouble(m_primitiveType, m_byteOrder, buffer); } - inline const PrimitiveValue& minValue() const + inline const PrimitiveValue &minValue() const { return m_minValue; } - inline const PrimitiveValue& maxValue() const + inline const PrimitiveValue &maxValue() const { return m_maxValue; } - inline const PrimitiveValue& nullValue() const + inline const PrimitiveValue &nullValue() const { return m_nullValue; } - inline const PrimitiveValue& constValue() const + inline const PrimitiveValue &constValue() const { return m_constValue; } - inline const std::string& characterEncoding() const + inline const std::string &characterEncoding() const { return m_characterEncoding; } - inline const std::string& epoch() const + inline const std::string &epoch() const { return m_epoch; } - inline const std::string& timeUnit() const + inline const std::string &timeUnit() const { return m_timeUnit; } - inline const std::string& semanticType() const + inline const std::string &semanticType() const { return m_semanticType; } diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index 6b46de22a1..2c1af69b22 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -109,7 +109,7 @@ class IrDecoder std::for_each(m_messages.begin(), m_messages.end(), [&](std::shared_ptr> tokens) { - Token& token = tokens->at(0); + Token &token = tokens->at(0); if (token.signal() == Signal::BEGIN_MESSAGE && token.fieldId() == id && token.tokenVersion() == version) { @@ -127,7 +127,7 @@ class IrDecoder std::for_each(m_messages.begin(), m_messages.end(), [&](std::shared_ptr> tokens) { - Token& token = tokens->at(0); + Token &token = tokens->at(0); if (token.signal() == Signal::BEGIN_MESSAGE && token.fieldId() == id) { @@ -224,12 +224,13 @@ class IrDecoder return 0; } - std::uint64_t decodeAndAddToken(std::shared_ptr>& tokens, std::uint64_t offset) + std::uint64_t decodeAndAddToken(std::shared_ptr> &tokens, std::uint64_t offset) { using namespace uk::co::real_logic::sbe::ir::generated; TokenCodec tokenCodec; - tokenCodec.wrapForDecode(m_buffer.get(), offset, tokenCodec.sbeBlockLength(), tokenCodec.sbeSchemaVersion(), m_length); + tokenCodec.wrapForDecode( + m_buffer.get(), offset, tokenCodec.sbeBlockLength(), tokenCodec.sbeSchemaVersion(), m_length); Signal signal = static_cast(tokenCodec.signal()); PrimitiveType type = static_cast(tokenCodec.primitiveType()); @@ -277,8 +278,17 @@ class IrDecoder std::string referencedName(tmpBuffer, tmpLen); Encoding encoding( - type, presence, byteOrder, minValue, maxValue, nullValue, constValue, - characterEncoding, epoch, timeUnit, semanticType); + type, + presence, + byteOrder, + minValue, + maxValue, + nullValue, + constValue, + characterEncoding, + epoch, + timeUnit, + semanticType); Token token(tokenOffset, id, version, tokenSize, componentTokenCount, signal, name, description, encoding); @@ -295,7 +305,7 @@ class IrDecoder { size += decodeAndAddToken(m_headerTokens, offset + size); - Token& token = m_headerTokens->back(); + Token &token = m_headerTokens->back(); if (token.signal() == Signal::END_COMPOSITE) { @@ -316,7 +326,7 @@ class IrDecoder { size += decodeAndAddToken(tokensForMessage, offset + size); - Token& token = tokensForMessage->back(); + Token &token = tokensForMessage->back(); if (token.signal() == Signal::END_MESSAGE) { diff --git a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h index 300760ed84..aef532ac59 100644 --- a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h @@ -30,18 +30,18 @@ namespace otf { class OtfHeaderDecoder { public: - explicit OtfHeaderDecoder(const std::shared_ptr>& tokens) + explicit OtfHeaderDecoder(const std::shared_ptr> &tokens) { m_encodedLength = tokens->at(0).encodedLength(); - Token* blockLengthToken = nullptr; - Token* templateIdToken = nullptr; - Token* schemaIdToken = nullptr; - Token* versionToken = nullptr; + Token *blockLengthToken = nullptr; + Token *templateIdToken = nullptr; + Token *schemaIdToken = nullptr; + Token *versionToken = nullptr; - std::for_each(tokens->begin(), tokens->end(), [&](Token& token) + std::for_each(tokens->begin(), tokens->end(), [&](Token &token) { - const std::string& name = token.name(); + const std::string &name = token.name(); if (name == "blockLength") { diff --git a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h index e6e6f69966..d263f69ad4 100644 --- a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h @@ -30,124 +30,124 @@ typedef std::function on_begin_message_t; typedef std::function on_end_message_t; typedef std::function on_encoding_t; typedef std::function& tokens, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex, std::uint64_t actingVersion)> on_enum_t; typedef std::function& tokens, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex, std::uint64_t actingVersion)> on_bit_set_t; typedef std::function& tokens, + Token &fieldToken, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex)> on_begin_composite_t; typedef std::function& tokens, + Token &fieldToken, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex)> on_end_composite_t; typedef std::function on_group_header_t; typedef std::function on_begin_group_t; typedef std::function on_end_group_t; typedef std::function on_var_data_t; + Token &typeToken)> on_var_data_t; class BasicTokenListener { public: - virtual void onBeginMessage(Token& token) {} + virtual void onBeginMessage(Token &token) {} - virtual void onEndMessage(Token& token) {} + virtual void onEndMessage(Token &token) {} virtual void onEncoding( - Token& fieldToken, + Token &fieldToken, const char *buffer, - Token& typeToken, + Token &typeToken, std::uint64_t actingVersion) {} virtual void onEnum( - Token& fieldToken, + Token &fieldToken, const char *buffer, - std::vector& tokens, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex, std::uint64_t actingVersion) {} virtual void onBitSet( - Token& fieldToken, + Token &fieldToken, const char *buffer, - std::vector& tokens, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex, std::uint64_t actingVersion) {} virtual void onBeginComposite( - Token& fieldToken, - std::vector& tokens, + Token &fieldToken, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex) {} virtual void onEndComposite( - Token& fieldToken, - std::vector& tokens, + Token &fieldToken, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex) {} virtual void onGroupHeader( - Token& token, + Token &token, std::uint64_t numInGroup) {} virtual void onBeginGroup( - Token& token, + Token &token, std::uint64_t groupIndex, std::uint64_t numInGroup) {} virtual void onEndGroup( - Token& token, + Token &token, std::uint64_t groupIndex, std::uint64_t numInGroup) {} virtual void onVarData( - Token& fieldToken, + Token &fieldToken, const char *buffer, std::uint64_t length, - Token& typeToken) {} + Token &typeToken) {} }; template static void decodeComposite( - Token& fieldToken, + Token &fieldToken, const char *buffer, std::size_t bufferIndex, std::size_t length, @@ -155,7 +155,7 @@ static void decodeComposite( size_t tokenIndex, size_t toIndex, std::uint64_t actingVersion, - TokenListener& listener) + TokenListener &listener) { listener.onBeginComposite(fieldToken, *tokens.get(), tokenIndex, toIndex); @@ -169,15 +169,26 @@ static void decodeComposite( switch (token.signal()) { case Signal::BEGIN_COMPOSITE: - decodeComposite(fieldToken, buffer, bufferIndex + offset, length, tokens, i, nextFieldIndex - 1, actingVersion, listener); + decodeComposite( + fieldToken, + buffer, + bufferIndex + offset, + length, + tokens, + i, + nextFieldIndex - 1, + actingVersion, + listener); break; case Signal::BEGIN_ENUM: - listener.onEnum(fieldToken, buffer + bufferIndex + offset, *tokens.get(), i, nextFieldIndex - 1, actingVersion); + listener.onEnum( + fieldToken, buffer + bufferIndex + offset, *tokens.get(), i, nextFieldIndex - 1, actingVersion); break; case Signal::BEGIN_SET: - listener.onBitSet(fieldToken, buffer + bufferIndex + offset, *tokens.get(), i, nextFieldIndex - 1, actingVersion); + listener.onBitSet( + fieldToken, buffer + bufferIndex + offset, *tokens.get(), i, nextFieldIndex - 1, actingVersion); break; case Signal::ENCODING: @@ -203,11 +214,11 @@ static size_t decodeFields( std::shared_ptr> tokens, size_t tokenIndex, const size_t numTokens, - TokenListener& listener) + TokenListener &listener) { while (tokenIndex < numTokens) { - Token& fieldToken = tokens->at(tokenIndex); + Token &fieldToken = tokens->at(tokenIndex); if (Signal::BEGIN_FIELD != fieldToken.signal()) { break; @@ -223,15 +234,25 @@ static size_t decodeFields( { case Signal::BEGIN_COMPOSITE: decodeComposite( - fieldToken, buffer, offset, length, tokens, tokenIndex, nextFieldIndex - 2, actingVersion, listener); + fieldToken, + buffer, + offset, + length, + tokens, + tokenIndex, + nextFieldIndex - 2, + actingVersion, + listener); break; case Signal::BEGIN_ENUM: - listener.onEnum(fieldToken, buffer + offset, *tokens.get(), tokenIndex, nextFieldIndex - 2, actingVersion); + listener.onEnum( + fieldToken, buffer + offset, *tokens.get(), tokenIndex, nextFieldIndex - 2, actingVersion); break; case Signal::BEGIN_SET: - listener.onBitSet(fieldToken, buffer + offset, *tokens.get(), tokenIndex, nextFieldIndex - 2, actingVersion); + listener.onBitSet( + fieldToken, buffer + offset, *tokens.get(), tokenIndex, nextFieldIndex - 2, actingVersion); break; case Signal::ENCODING: @@ -253,15 +274,15 @@ std::size_t decodeData( const char *buffer, std::size_t bufferIndex, const std::size_t length, - const std::shared_ptr>& tokens, + const std::shared_ptr> &tokens, std::size_t tokenIndex, const std::size_t numTokens, std::uint64_t actingVersion, - TokenListener& listener) + TokenListener &listener) { while (tokenIndex < numTokens) { - Token& token = tokens->at(tokenIndex); + Token &token = tokens->at(tokenIndex); if (Signal::BEGIN_VAR_DATA != token.signal()) { break; @@ -269,8 +290,8 @@ std::size_t decodeData( const bool isPresent = token.tokenVersion() <= static_cast(actingVersion); - Token& lengthToken = tokens->at(tokenIndex + 2); - Token& dataToken = tokens->at(tokenIndex + 3); + Token &lengthToken = tokens->at(tokenIndex + 2); + Token &dataToken = tokens->at(tokenIndex + 3); if ((bufferIndex + dataToken.offset()) > length) { @@ -308,7 +329,7 @@ std::pair decodeGroups( std::shared_ptr> tokens, size_t tokenIndex, const size_t numTokens, - TokenListener& listener) + TokenListener &listener) { while (tokenIndex < numTokens) { @@ -320,7 +341,7 @@ std::pair decodeGroups( const bool isPresent = token.tokenVersion() <= static_cast(actingVersion); - Token& dimensionsTypeComposite = tokens->at(tokenIndex + 1); + Token &dimensionsTypeComposite = tokens->at(tokenIndex + 1); std::size_t dimensionsLength = static_cast(dimensionsTypeComposite.encodedLength()); if ((bufferIndex + dimensionsLength) > length) @@ -328,8 +349,8 @@ std::pair decodeGroups( throw std::runtime_error("length too short for group dimensions"); } - Token& blockLengthToken = tokens->at(tokenIndex + 2); - Token& numInGroupToken = tokens->at(tokenIndex + 3); + Token &blockLengthToken = tokens->at(tokenIndex + 2); + Token &numInGroupToken = tokens->at(tokenIndex + 3); std::uint64_t blockLength = isPresent ? blockLengthToken.encoding().getAsUInt(buffer + bufferIndex + blockLengthToken.offset()) : 0; @@ -383,7 +404,7 @@ std::size_t decode( std::uint64_t actingVersion, size_t blockLength, std::shared_ptr> msgTokens, - TokenListener& listener) + TokenListener &listener) { listener.onBeginMessage(msgTokens->at(0)); @@ -408,7 +429,6 @@ std::size_t decode( return bufferIndex; } - }}} #endif diff --git a/sbe-tool/src/main/cpp/otf/Token.h b/sbe-tool/src/main/cpp/otf/Token.h index 45d7702ddc..28c53855ad 100644 --- a/sbe-tool/src/main/cpp/otf/Token.h +++ b/sbe-tool/src/main/cpp/otf/Token.h @@ -95,12 +95,12 @@ class Token return m_signal; } - inline const std::string& name() const + inline const std::string &name() const { return m_name; } - inline const std::string& description() const + inline const std::string &description() const { return m_description; } @@ -115,7 +115,7 @@ class Token return m_version; } - inline const Encoding& encoding() const + inline const Encoding &encoding() const { return m_encoding; } From 78bdd6659db4a48464dfb2346402cc15fae9a306 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 29 Jun 2020 15:38:31 +0100 Subject: [PATCH 0493/1594] [C++] Formatting. --- .../sbe/generation/cpp/CppGenerator.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 86ad5a3879..e751047075 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -39,7 +39,7 @@ import static uk.co.real_logic.sbe.ir.GenerationUtil.*; /** - * Codec generator for the C++11 programming language with conditional complication for additional C++14 and C++17 + * Codec generator for the C++11 programming language with conditional compilation for additional C++14 and C++17 * features. */ @SuppressWarnings("MethodLength") @@ -1823,12 +1823,12 @@ private CharSequence generateFixedFlyweightCode(final String className, final in " return m_offset;\n" + " }\n\n" + - " SBE_NODISCARD const char * buffer() const SBE_NOEXCEPT\n" + + " SBE_NODISCARD const char *buffer() const SBE_NOEXCEPT\n" + " {\n" + " return m_buffer;\n" + " }\n\n" + - " SBE_NODISCARD char * buffer() SBE_NOEXCEPT\n" + + " SBE_NODISCARD char *buffer() SBE_NOEXCEPT\n" + " {\n" + " return m_buffer;\n" + " }\n\n" + @@ -1963,7 +1963,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final " return %8$s;\n" + " }\n\n" + - " SBE_NODISCARD static SBE_CONSTEXPR const char * sbeSemanticType() SBE_NOEXCEPT\n" + + " SBE_NODISCARD static SBE_CONSTEXPR const char *sbeSemanticType() SBE_NOEXCEPT\n" + " {\n" + " return \"%9$s\";\n" + " }\n\n" + @@ -2040,12 +2040,12 @@ private CharSequence generateMessageFlyweightCode(final String className, final " return skipper.encodedLength();\n" + " }\n\n" + - " SBE_NODISCARD const char * buffer() const SBE_NOEXCEPT\n" + + " SBE_NODISCARD const char *buffer() const SBE_NOEXCEPT\n" + " {\n" + " return m_buffer;\n" + " }\n\n" + - " SBE_NODISCARD char * buffer() SBE_NOEXCEPT\n" + + " SBE_NODISCARD char *buffer() SBE_NOEXCEPT\n" + " {\n" + " return m_buffer;\n" + " }\n\n" + @@ -2166,7 +2166,7 @@ private static void generateFieldMetaAttributeMethod( final String semanticType = encoding.semanticType() == null ? "" : encoding.semanticType(); sb.append("\n") - .append(indent).append(" SBE_NODISCARD static const char * ") + .append(indent).append(" SBE_NODISCARD static const char *") .append(token.name()).append("MetaAttribute(const MetaAttribute metaAttribute) SBE_NOEXCEPT\n") .append(indent).append(" {\n") .append(indent).append(" switch (metaAttribute)\n") @@ -2752,7 +2752,7 @@ private CharSequence generateEnumDisplay(final List tokens, final Token e final StringBuilder sb = new StringBuilder(); new Formatter(sb).format("\n" + - " static const char* c_str(const %1$s::Value value)\n" + + " static const char *c_str(const %1$s::Value value)\n" + " {\n" + " switch (value)\n" + " {\n", @@ -2956,7 +2956,7 @@ private CharSequence generateMessageLength(final List groups, final List< indent + " {\n" + indent + " throw std::runtime_error(\"%5$s outside of allowed range [E110]\");\n" + indent + " }\n" + - indent + " length += %1$sLength * %2$s::sbeBlockLength();\n", + indent + " length += %1$sLength *%2$s::sbeBlockLength();\n", formatPropertyName(groupToken.name()), formatClassName(groupToken.name()), minCheck, From 75f599daeadfed7be53072b3a5a1403b0ff0a893 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 29 Jun 2020 20:13:34 +0100 Subject: [PATCH 0494/1594] [C++] Formatting of generated codecs. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index e751047075..6ccaa533e8 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -606,7 +606,7 @@ private void generateVarData( indent + " {\n" + indent + " throw std::runtime_error(\"std::string too long for length type [E109]\");\n" + indent + " }\n" + - indent + " return put%2$s(str.data(), static_cast<%3$s>(str.length()));" + + indent + " return put%2$s(str.data(), static_cast<%3$s>(str.length()));\n" + indent + " }\n", className, propertyName, @@ -621,7 +621,7 @@ private void generateVarData( indent + " {\n" + indent + " throw std::runtime_error(\"std::string too long for length type [E109]\");\n" + indent + " }\n" + - indent + " return put%2$s(str.data(), static_cast<%3$s>(str.length()));" + + indent + " return put%2$s(str.data(), static_cast<%3$s>(str.length()));\n" + indent + " }\n" + indent + " #endif\n", className, @@ -2034,8 +2034,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final " SBE_NODISCARD std::uint64_t decodeLength() const\n" + " {\n" + - " %10$s skipper(m_buffer, m_offset,\n" + - " m_bufferLength, sbeBlockLength(), m_actingVersion);\n" + + " %10$s skipper(m_buffer, m_offset, m_bufferLength, sbeBlockLength(), m_actingVersion);\n" + " skipper.skip();\n" + " return skipper.encodedLength();\n" + " }\n\n" + From a3f53379f1b87da70bd4721583f1d9fb71dac48d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 30 Jun 2020 10:22:18 +0100 Subject: [PATCH 0495/1594] [Java] Upgrade to Gradle 6.5.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 22876ca5a6..15df0560cb 100644 --- a/build.gradle +++ b/build.gradle @@ -688,6 +688,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.5' + gradleVersion = '6.5.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 186b71557c..ac33e9944a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 6e604be10aad02f6018a2d51b86ae0f1e04b047d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 1 Jul 2020 15:15:18 +0100 Subject: [PATCH 0496/1594] [Java] Upgrade to Checkstyle 8.34. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 15df0560cb..65147afdd4 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ plugins { defaultTasks 'clean', 'build' -def checkstyleVersion = '8.28' +def checkstyleVersion = '8.34' def hamcrestVersion = '2.2' def mockitoVersion = '3.3.3' def junitVersion = '5.6.2' From ad76638fed727295ed0f78add1359a80bff15704 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 2 Jul 2020 11:44:47 +0100 Subject: [PATCH 0497/1594] [Java] Better handling of versions and constants in JsonPrinter. Issue #798. --- .../sbe/examples/ExampleTokenListener.java | 61 ++++++--- .../real_logic/sbe/examples/OtfExample.java | 7 +- .../uk/co/real_logic/sbe/PrimitiveValue.java | 46 ++++--- .../co/real_logic/sbe/json/JsonPrinter.java | 12 +- .../sbe/json/JsonTokenListener.java | 129 ++++++++++++------ .../real_logic/sbe/otf/OtfHeaderDecoder.java | 24 ++-- .../java/uk/co/real_logic/sbe/otf/Types.java | 73 ++++++++++ .../co/real_logic/sbe/EncodedCarTestBase.java | 3 + .../sbe/generation/java/ToStringTest.java | 7 +- .../real_logic/sbe/json/JsonPrinterTest.java | 2 + .../resources/json-printer-test-schema.xml | 6 +- 11 files changed, 261 insertions(+), 109 deletions(-) diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java index 0c10eb734f..6c95440185 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java @@ -61,7 +61,7 @@ public void onEncoding( final Token typeToken, final int actingVersion) { - final CharSequence value = readEncodingAsString(buffer, index, typeToken, actingVersion); + final CharSequence value = readEncodingAsString(buffer, index, typeToken, fieldToken.version(), actingVersion); printScope(); out.append(compositeLevel > 0 ? typeToken.name() : fieldToken.name()) @@ -80,7 +80,8 @@ public void onEnum( final int actingVersion) { final Token typeToken = tokens.get(beginIndex + 1); - final long encodedValue = readEncodingAsLong(buffer, bufferIndex, typeToken, actingVersion); + final long encodedValue = readEncodingAsLong( + buffer, bufferIndex, typeToken, fieldToken.version(), actingVersion); String value = null; if (fieldToken.isConstantEncoding()) @@ -118,7 +119,8 @@ public void onBitSet( final int actingVersion) { final Token typeToken = tokens.get(beginIndex + 1); - final long encodedValue = readEncodingAsLong(buffer, bufferIndex, typeToken, actingVersion); + final long encodedValue = readEncodingAsLong( + buffer, bufferIndex, typeToken, fieldToken.version(), actingVersion); printScope(); out.append(determineName(0, fieldToken, tokens, beginIndex)).append(':'); @@ -140,14 +142,12 @@ public void onBeginComposite( final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { ++compositeLevel; - namedScope.push(determineName(1, fieldToken, tokens, fromIndex) + "."); } public void onEndComposite(final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { --compositeLevel; - namedScope.pop(); } @@ -218,17 +218,22 @@ private String determineName( } private static CharSequence readEncodingAsString( - final DirectBuffer buffer, final int index, final Token typeToken, final int actingVersion) + final DirectBuffer buffer, + final int index, + final Token typeToken, + final int fieldVersion, + final int actingVersion) { - final PrimitiveValue constOrNotPresentValue = constOrNotPresentValue(typeToken, actingVersion); + final PrimitiveValue constOrNotPresentValue = constOrNotPresentValue(typeToken, fieldVersion, actingVersion); if (null != constOrNotPresentValue) { - if (constOrNotPresentValue.size() == 1) + final String characterEncoding = constOrNotPresentValue.characterEncoding(); + if (constOrNotPresentValue.size() == 1 && null != characterEncoding) { try { final byte[] bytes = { (byte)constOrNotPresentValue.longValue() }; - return new String(bytes, constOrNotPresentValue.characterEncoding()); + return new String(bytes, characterEncoding); } catch (final UnsupportedEncodingException ex) { @@ -237,7 +242,24 @@ private static CharSequence readEncodingAsString( } else { - return constOrNotPresentValue.toString(); + final String value = constOrNotPresentValue.toString(); + final int size = typeToken.arrayLength(); + + if (size < 2) + { + return value; + } + + final StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < size; i++) + { + sb.append(value).append(", "); + } + + sb.setLength(sb.length() - 2); + + return sb; } } @@ -257,9 +279,13 @@ private static CharSequence readEncodingAsString( } private static long readEncodingAsLong( - final DirectBuffer buffer, final int bufferIndex, final Token typeToken, final int actingVersion) + final DirectBuffer buffer, + final int bufferIndex, + final Token typeToken, + final int fieldVersion, + final int actingVersion) { - final PrimitiveValue constOrNotPresentValue = constOrNotPresentValue(typeToken, actingVersion); + final PrimitiveValue constOrNotPresentValue = constOrNotPresentValue(typeToken, fieldVersion, actingVersion); if (null != constOrNotPresentValue) { return constOrNotPresentValue.longValue(); @@ -268,15 +294,16 @@ private static long readEncodingAsLong( return Types.getLong(buffer, bufferIndex, typeToken.encoding()); } - private static PrimitiveValue constOrNotPresentValue(final Token token, final int actingVersion) + private static PrimitiveValue constOrNotPresentValue( + final Token typeToken, final int fieldVersion, final int actingVersion) { - if (token.isConstantEncoding()) + if (typeToken.isConstantEncoding()) { - return token.encoding().constValue(); + return typeToken.encoding().constValue(); } - else if (token.isOptionalEncoding() && actingVersion < token.version()) + else if (typeToken.isOptionalEncoding() && actingVersion < fieldVersion) { - return token.encoding().applicableNullValue(); + return typeToken.encoding().applicableNullValue(); } return null; diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java index 763b0490be..4b6a1a530e 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java @@ -51,10 +51,10 @@ public static void main(final String[] args) throws Exception System.out.println("\n*** OTF Example ***\n"); // Encode up message and schema as if we just got them off the wire. - final ByteBuffer encodedSchemaBuffer = ByteBuffer.allocateDirect(SCHEMA_BUFFER_CAPACITY); + final ByteBuffer encodedSchemaBuffer = ByteBuffer.allocate(SCHEMA_BUFFER_CAPACITY); encodeSchema(encodedSchemaBuffer); - final ByteBuffer encodedMsgBuffer = ByteBuffer.allocateDirect(MSG_BUFFER_CAPACITY); + final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); encodeTestMessage(encodedMsgBuffer); // Now lets decode the schema IR so we have IR objects. @@ -96,7 +96,7 @@ public static void main(final String[] args) throws Exception private static void encodeSchema(final ByteBuffer byteBuffer) throws Exception { - final Path path = Paths.get("example-schema.xml"); + final Path path = Paths.get("example-extension-schema.xml"); try (InputStream in = new BufferedInputStream(Files.newInputStream(path))) { final MessageSchema schema = XmlSchemaParser.parse(in, ParserOptions.DEFAULT); @@ -111,7 +111,6 @@ private static void encodeSchema(final ByteBuffer byteBuffer) throws Exception private static void encodeTestMessage(final ByteBuffer byteBuffer) { final UnsafeBuffer buffer = new UnsafeBuffer(byteBuffer); - final int encodedLength = ExampleUsingGeneratedStub.encode(CAR_ENCODER, buffer, HEADER_ENCODER); byteBuffer.position(encodedLength); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index 664a606acf..9b851ecfe5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -379,33 +379,35 @@ public String characterEncoding() } /** - * Return String representation of this object + * Return String value representation of this object. * - * @return String representing object value + * @return String representing object value. */ public String toString() { - switch (representation) + if (Representation.LONG == representation) { - case LONG: - return Long.toString(longValue); - - case DOUBLE: - return Double.toString(doubleValue); - - case BYTE_ARRAY: - try - { - return null == characterEncoding ? - new String(byteArrayValue) : new String(byteArrayValue, characterEncoding); - } - catch (final UnsupportedEncodingException ex) - { - throw new IllegalStateException(ex); - } - - default: - throw new IllegalStateException("Unsupported Representation: " + representation); + return Long.toString(longValue); + } + else if (Representation.DOUBLE == representation) + { + return Double.toString(doubleValue); + } + else if (Representation.BYTE_ARRAY == representation) + { + try + { + return null == characterEncoding ? + new String(byteArrayValue) : new String(byteArrayValue, characterEncoding); + } + catch (final UnsupportedEncodingException ex) + { + throw new IllegalStateException(ex); + } + } + else + { + throw new IllegalStateException("Unsupported Representation: " + representation); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java index 3cfb9658bd..7265193597 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java @@ -46,13 +46,12 @@ public void print(final ByteBuffer encodedMessage, final StringBuilder output) public void print(final StringBuilder output, final UnsafeBuffer buffer, final int bufferOffset) { + final int blockLength = headerDecoder.getBlockLength(buffer, bufferOffset); final int templateId = headerDecoder.getTemplateId(buffer, bufferOffset); final int schemaId = headerDecoder.getSchemaId(buffer, bufferOffset); final int actingVersion = headerDecoder.getSchemaVersion(buffer, bufferOffset); - final int blockLength = headerDecoder.getBlockLength(buffer, bufferOffset); validateId(schemaId); - validateVersion(schemaId, actingVersion); final int messageOffset = bufferOffset + headerDecoder.encodedLength(); final List msgTokens = ir.getMessage(templateId); @@ -74,15 +73,6 @@ private void validateId(final int schemaId) } } - private void validateVersion(final int schemaId, final int actingVersion) - { - if (actingVersion > ir.version()) - { - throw new IllegalArgumentException( - "Required schema version " + actingVersion + " but was " + ir.version() + " for schema id " + schemaId); - } - } - public String print(final ByteBuffer encodedMessage) { final StringBuilder sb = new StringBuilder(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index df5c751891..719d00118d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -59,7 +59,7 @@ public void onEncoding( final int actingVersion) { property(compositeLevel > 0 ? typeToken.name() : fieldToken.name()); - appendEncodingAsString(buffer, bufferIndex, typeToken, actingVersion); + appendEncodingAsString(buffer, bufferIndex, fieldToken, typeToken, actingVersion); next(); } @@ -73,7 +73,7 @@ public void onEnum( final int actingVersion) { final Token typeToken = tokens.get(fromIndex + 1); - final long encodedValue = readEncodingAsLong(buffer, bufferIndex, typeToken, actingVersion); + final long encodedValue = readEncodingAsLong(buffer, bufferIndex, typeToken, fieldToken, actingVersion); String value = null; if (fieldToken.isConstantEncoding()) @@ -111,7 +111,7 @@ public void onBitSet( final int actingVersion) { final Token typeToken = tokens.get(fromIndex + 1); - final long encodedValue = readEncodingAsLong(buffer, bufferIndex, typeToken, actingVersion); + final long encodedValue = readEncodingAsLong(buffer, bufferIndex, typeToken, fieldToken, actingVersion); property(determineName(0, fieldToken, tokens, fromIndex)); @@ -219,57 +219,101 @@ private void property(final String name) } private void appendEncodingAsString( - final DirectBuffer buffer, final int index, final Token typeToken, final int actingVersion) + final DirectBuffer buffer, + final int index, + final Token fieldToken, + final Token typeToken, + final int actingVersion) { + final int arrayLength = typeToken.arrayLength(); final Encoding encoding = typeToken.encoding(); - final PrimitiveValue constOrNotPresentValue = constOrNotPresentValue(typeToken, actingVersion); + final PrimitiveValue constOrNotPresentValue = constOrNotPresentValue(typeToken, fieldToken, actingVersion); + if (null != constOrNotPresentValue) { - if (encoding.primitiveType() == CHAR) + final String characterEncoding = encoding.characterEncoding(); + if (null != characterEncoding) { doubleQuote(); - output.append(constOrNotPresentValue.toString()); + + if (PrimitiveValue.Representation.LONG == constOrNotPresentValue.representation()) + { + try + { + final long longValue = constOrNotPresentValue.longValue(); + if (PrimitiveValue.NULL_VALUE_CHAR != longValue) + { + escape(new String(new byte[]{ (byte)longValue }, characterEncoding)); + } + } + catch (final UnsupportedEncodingException ex) + { + throw new RuntimeException(ex); + } + } + else + { + escape(constOrNotPresentValue.toString()); + } + doubleQuote(); } else { - output.append(constOrNotPresentValue.toString()); - } - - return; - } - - final int elementSize = encoding.primitiveType().size(); + if (arrayLength < 2) + { + Types.appendAsJsonString(output, constOrNotPresentValue, encoding); + } + else + { + output.append('['); - final int size = typeToken.arrayLength(); - if (size > 1 && encoding.primitiveType() == CHAR) - { - doubleQuote(); + for (int i = 0; i < arrayLength; i++) + { + Types.appendAsJsonString(output, constOrNotPresentValue, encoding); + output.append(", "); + } - for (int i = 0; i < size; i++) - { - escape((char)buffer.getByte(index + (i * elementSize))); + backup(); + output.append(']'); + } } - - doubleQuote(); } else { - if (size > 1) - { - output.append('['); - } + final int elementSize = encoding.primitiveType().size(); + final int size = typeToken.arrayLength(); - for (int i = 0; i < size; i++) + if (size > 1 && encoding.primitiveType() == CHAR) { - Types.appendAsJsonString(output, buffer, index + (i * elementSize), encoding); - output.append(", "); - } + doubleQuote(); - backup(); - if (size > 1) + for (int i = 0; i < size; i++) + { + escape((char)buffer.getByte(index + (i * elementSize))); + } + + doubleQuote(); + } + else { - output.append(']'); + if (1 == size) + { + Types.appendAsJsonString(output, buffer, index, encoding); + } + else + { + output.append('['); + + for (int i = 0; i < size; i++) + { + Types.appendAsJsonString(output, buffer, index + (i * elementSize), encoding); + output.append(", "); + } + + backup(); + output.append(']'); + } } } } @@ -326,14 +370,15 @@ private String determineName( } } - private static PrimitiveValue constOrNotPresentValue(final Token token, final int actingVersion) + private static PrimitiveValue constOrNotPresentValue( + final Token typeToken, final Token fieldToken, final int actingVersion) { - final Encoding encoding = token.encoding(); - if (token.isConstantEncoding()) + final Encoding encoding = typeToken.encoding(); + if (typeToken.isConstantEncoding()) { return encoding.constValue(); } - else if (token.isOptionalEncoding() && actingVersion < token.version()) + else if (fieldToken.isOptionalEncoding() && actingVersion < fieldToken.version()) { return encoding.applicableNullValue(); } @@ -342,9 +387,13 @@ else if (token.isOptionalEncoding() && actingVersion < token.version()) } private static long readEncodingAsLong( - final DirectBuffer buffer, final int bufferIndex, final Token typeToken, final int actingVersion) + final DirectBuffer buffer, + final int bufferIndex, + final Token typeToken, + final Token fieldToken, + final int actingVersion) { - final PrimitiveValue constOrNotPresentValue = constOrNotPresentValue(typeToken, actingVersion); + final PrimitiveValue constOrNotPresentValue = constOrNotPresentValue(typeToken, fieldToken, actingVersion); if (null != constOrNotPresentValue) { return constOrNotPresentValue.longValue(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java index f9847c9153..efad994192 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java @@ -96,6 +96,18 @@ public int encodedLength() return length; } + /** + * Get the block length of the root block in the message. + * + * @param buffer from which to read the value. + * @param bufferOffset in the buffer at which the message header begins. + * @return the length of the root block in the coming message. + */ + public int getBlockLength(final DirectBuffer buffer, final int bufferOffset) + { + return Types.getInt(buffer, bufferOffset + blockLengthOffset, blockLengthType, blockLengthByteOrder); + } + /** * Get the template id from the message header. * @@ -131,16 +143,4 @@ public int getSchemaVersion(final DirectBuffer buffer, final int bufferOffset) { return Types.getInt(buffer, bufferOffset + schemaVersionOffset, schemaVersionType, schemaVersionByteOrder); } - - /** - * Get the block length of the root block in the message. - * - * @param buffer from which to read the value. - * @param bufferOffset in the buffer at which the message header begins. - * @return the length of the root block in the coming message. - */ - public int getBlockLength(final DirectBuffer buffer, final int bufferOffset) - { - return Types.getInt(buffer, bufferOffset + blockLengthOffset, blockLengthType, blockLengthByteOrder); - } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java index 8e9b4db9a0..9dd2d2fde7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java @@ -17,6 +17,7 @@ import org.agrona.DirectBuffer; import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.PrimitiveValue; import uk.co.real_logic.sbe.ir.Encoding; import java.nio.ByteOrder; @@ -266,4 +267,76 @@ else if (value == Double.NEGATIVE_INFINITY) } } } + + /** + * Append an value as a Json String to a {@link StringBuilder}. + * + * @param sb to append the value to. + * @param value to append. + * @param encoding representing the encoded value. + */ + public static void appendAsJsonString(final StringBuilder sb, final PrimitiveValue value, final Encoding encoding) + { + switch (encoding.primitiveType()) + { + case CHAR: + sb.append('\'').append((char)value.longValue()).append('\''); + break; + + case INT8: + case UINT8: + case INT16: + case UINT16: + case INT32: + case UINT32: + case INT64: + case UINT64: + sb.append(value.longValue()); + break; + + case FLOAT: + { + final float floatValue = (float)value.doubleValue(); + if (Float.isNaN(floatValue)) + { + sb.append("0/0"); + } + else if (floatValue == Float.POSITIVE_INFINITY) + { + sb.append("1/0"); + } + else if (floatValue == Float.NEGATIVE_INFINITY) + { + sb.append("-1/0"); + } + else + { + sb.append(value); + } + break; + } + + case DOUBLE: + { + final double doubleValue = value.doubleValue(); + if (Double.isNaN(doubleValue)) + { + sb.append("0/0"); + } + else if (doubleValue == Double.POSITIVE_INFINITY) + { + sb.append("1/0"); + } + else if (doubleValue == Double.NEGATIVE_INFINITY) + { + sb.append("-1/0"); + } + else + { + sb.append(doubleValue); + } + break; + } + } + } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java index c125a1d90d..988118b39e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java @@ -87,6 +87,9 @@ protected static void encodeTestMessage(final ByteBuffer buffer) .numCylinders((short)4) .putManufacturerCode(manufacturerCode, srcOffset); + CAR.putUuid(7L, 3L) + .cupHolderCount((byte)5); + CAR.fuelFiguresCount(3) .next().speed(30).mpg(35.9f) .next().speed(55).mpg(49.0f) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java index 8059ca9b83..301a61f4f1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java @@ -36,12 +36,14 @@ public void shouldToStringMessage() final String result = CAR.toString(); assertEquals( "[Car]" + - "(sbeTemplateId=1|sbeSchemaId=1|sbeSchemaVersion=0|sbeBlockLength=45):" + + "(sbeTemplateId=1|sbeSchemaId=1|sbeSchemaVersion=2|sbeBlockLength=62):" + "serialNumber=1234|modelYear=2013|available=T|code=A|" + "someNumbers=[0,1,2,3,4]|" + "vehicleCode=ab\"def|" + "extras={sportsPack,cruiseControl}|" + "engine=(capacity=2000|numCylinders=4|manufacturerCode=123|)|" + + "uuid=[7,3]|" + + "cupHolderCount=5|" + "fuelFigures=[" + "(speed=30|mpg=35.9)," + "(speed=55|mpg=49.0)," + @@ -62,9 +64,10 @@ public void shouldToStringBlankMessage() final String result = CAR.toString(); assertEquals( "[Car]" + - "(sbeTemplateId=1|sbeSchemaId=1|sbeSchemaVersion=0|sbeBlockLength=45):" + + "(sbeTemplateId=1|sbeSchemaId=1|sbeSchemaVersion=2|sbeBlockLength=62):" + "serialNumber=0|modelYear=0|available=F|code=NULL_VAL|someNumbers=[0,0,0,0,0]|vehicleCode=|extras={}|" + "engine=(capacity=0|numCylinders=0|manufacturerCode=|)|" + + "uuid=[0,0]|cupHolderCount=0|" + "fuelFigures=[]|performanceFigures=[]|manufacturer=''|model=''|activationCode=''", result); } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java index 115de2b821..bc2e9835f1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java @@ -70,6 +70,8 @@ public void exampleMessagePrintedAsJson() throws Exception " \"manufacturerCode\": \"123\",\n" + " \"fuel\": \"Petrol\"\n" + " },\n" + + " \"uuid\": [7, 3],\n" + + " \"cupHolderCount\": 5,\n" + " \"fuelFigures\": [\n" + " {\n" + " \"speed\": 30,\n" + diff --git a/sbe-tool/src/test/resources/json-printer-test-schema.xml b/sbe-tool/src/test/resources/json-printer-test-schema.xml index 3330c3ff1e..94044b19f7 100644 --- a/sbe-tool/src/test/resources/json-printer-test-schema.xml +++ b/sbe-tool/src/test/resources/json-printer-test-schema.xml @@ -2,7 +2,7 @@ @@ -21,6 +21,8 @@ + + @@ -58,6 +60,8 @@ + + From 0105fa071fc34a06683bdef465565a03e1041508 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 2 Jul 2020 15:25:24 +0100 Subject: [PATCH 0498/1594] [Java] Support empty JSON messages. Issue #799. --- .../sbe/json/JsonTokenListener.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index 719d00118d..15f1c34bb1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -131,7 +131,6 @@ public void onBitSet( } } output.append(" }"); - next(); } @@ -139,7 +138,6 @@ public void onBeginComposite( final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { ++compositeLevel; - property(determineName(1, fieldToken, tokens, fromIndex)); output.append('\n'); startObject(); @@ -270,11 +268,13 @@ private void appendEncodingAsString( for (int i = 0; i < arrayLength; i++) { + if (i > 0) + { + output.append(", "); + } Types.appendAsJsonString(output, constOrNotPresentValue, encoding); - output.append(", "); } - backup(); output.append(']'); } } @@ -307,11 +307,13 @@ private void appendEncodingAsString( for (int i = 0; i < size; i++) { + if (i > 0) + { + output.append(", "); + } Types.appendAsJsonString(output, buffer, index + (i * elementSize), encoding); - output.append(", "); } - backup(); output.append(']'); } } @@ -320,7 +322,11 @@ private void appendEncodingAsString( private void backup() { - output.setLength(output.length() - 2); + final int newLength = output.length() - 2; + if (output.charAt(newLength) == ',') + { + output.setLength(newLength); + } } private void indent() From aa373ee63e5b510cb1b2bd871954268e1fb666da Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Jul 2020 19:54:56 +0100 Subject: [PATCH 0499/1594] [Java] Upgrade to Agrona 1.6.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 65147afdd4..60b2062c92 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.3.3' def junitVersion = '5.6.2' def jmhVersion = '1.23' -def agronaVersion = '1.5.1' +def agronaVersion = '1.6.0' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 050697a2278d91cfca3d2a16de1404a80bccfd8c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Jul 2020 20:25:11 +0100 Subject: [PATCH 0500/1594] [Java] Revert Agrona to 1.5.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 60b2062c92..65147afdd4 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.3.3' def junitVersion = '5.6.2' def jmhVersion = '1.23' -def agronaVersion = '1.6.0' +def agronaVersion = '1.5.1' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 8bbfcc48a8760ab3891ee1b80a38869ef5cd3038 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Jul 2020 20:34:03 +0100 Subject: [PATCH 0501/1594] [Java] Upgrade to Agrona 1.6.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 65147afdd4..60b2062c92 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.3.3' def junitVersion = '5.6.2' def jmhVersion = '1.23' -def agronaVersion = '1.5.1' +def agronaVersion = '1.6.0' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 29a6231c8c975de0600b80655f7c2bb856a2bae8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Jul 2020 20:42:45 +0100 Subject: [PATCH 0502/1594] [Java] Add failOnError false to javadoc task. --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 60b2062c92..b8b7fba99e 100644 --- a/build.gradle +++ b/build.gradle @@ -158,6 +158,7 @@ subprojects { } javadoc { + failOnError false title = '

    Simple Binary Encoding (SBE)

    ' options.bottom = 'Copyright © 2013-2020 Real Logic Limited. All Rights Reserved.' options.encoding = 'UTF-8' From d19a7860094c67aea88a4635d1b9bc0942acc390 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Jul 2020 14:47:38 +0100 Subject: [PATCH 0503/1594] [Java] Output and empty array when numInGroup=0 for Json. Issue #800. --- .../uk/co/real_logic/sbe/json/JsonTokenListener.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index 15f1c34bb1..fdf98c6fa1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -153,7 +153,14 @@ public void onEndComposite( public void onGroupHeader(final Token token, final int numInGroup) { property(token.name()); - output.append("[\n"); + if (numInGroup > 0) + { + output.append("[\n"); + } + else + { + output.append("[],\n"); + } } public void onBeginGroup(final Token token, final int groupIndex, final int numInGroup) From b3bf4b812a28d4b3f67793503cabd509fcd319a3 Mon Sep 17 00:00:00 2001 From: Alexis Atkinson Date: Thu, 9 Jul 2020 20:57:40 +0100 Subject: [PATCH 0504/1594] Resolves #801 Upgrade csharp console apps to use .net core 3.1 (LTS) instead of the end of life .net core 2.2. (#803) * Upgrade csharp benchmark, samples and tests console app projects to use dotnet core 3.1 (LTS) as opposed to the end of life dotnet core 2.2 (which less people will have installed) * Update ci build for csharp to use .net core 3.1 (LTS) instead of the end of life .net core 2.2 --- .github/workflows/ci.yml | 2 +- csharp/sbe-benchmarks/sbe-benchmarks.csproj | 2 +- csharp/sbe-samples-car/sbe-samples-car.csproj | 2 +- csharp/sbe-tests/sbe-tests.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fea54e0cd6..4ad7fc405d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: strategy: fail-fast: false matrix: - dotnet: [ '2.2.103' ] + dotnet: [ '3.1.301' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 diff --git a/csharp/sbe-benchmarks/sbe-benchmarks.csproj b/csharp/sbe-benchmarks/sbe-benchmarks.csproj index 5a7f039f31..bcf5b9c996 100644 --- a/csharp/sbe-benchmarks/sbe-benchmarks.csproj +++ b/csharp/sbe-benchmarks/sbe-benchmarks.csproj @@ -1,7 +1,7 @@  - net45;netcoreapp2.2 + net45;netcoreapp3.1 Org.SbeTool.Sbe.Benchmarks Org.SbeTool.Sbe.Benchmarks exe diff --git a/csharp/sbe-samples-car/sbe-samples-car.csproj b/csharp/sbe-samples-car/sbe-samples-car.csproj index 88cb672179..1ed09464dd 100644 --- a/csharp/sbe-samples-car/sbe-samples-car.csproj +++ b/csharp/sbe-samples-car/sbe-samples-car.csproj @@ -1,7 +1,7 @@  - net45;netcoreapp2.2 + net45;netcoreapp3.1 exe Org.SbeTool.Sbe.Example.Car Org.SbeTool.Sbe.Example.Car diff --git a/csharp/sbe-tests/sbe-tests.csproj b/csharp/sbe-tests/sbe-tests.csproj index b1e73946dc..468a1ab8ba 100644 --- a/csharp/sbe-tests/sbe-tests.csproj +++ b/csharp/sbe-tests/sbe-tests.csproj @@ -1,6 +1,6 @@  - net45;netcoreapp2.2 + net45;netcoreapp3.1 Org.SbeTool.Sbe.Tests Org.SbeTool.Sbe.UnitTests True From ab75278d02d984af5b8d8c5394911b56668f77ac Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 11 Jul 2020 11:46:02 +0300 Subject: [PATCH 0505/1594] [Java] Upgrade to Mockito 3.4.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b8b7fba99e..6bb754519f 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.34' def hamcrestVersion = '2.2' -def mockitoVersion = '3.3.3' +def mockitoVersion = '3.4.0' def junitVersion = '5.6.2' def jmhVersion = '1.23' def agronaVersion = '1.6.0' From 06c66600d3231fc7fcc22a137964680543abf8dd Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 14 Jul 2020 11:49:57 +0100 Subject: [PATCH 0506/1594] [Java] Update README. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3038ed0791..40b1e068eb 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.18.2 +    1.19.0 ``` @@ -74,7 +74,7 @@ For convenience, a script is provided that does a full clean, build, and test of $ ./cppbuild/cppbuild -If you are comfortable with using CMake, then a full clean, build, and test looks like: +If you are comfortable using CMake, then a full clean, build, and test looks like: $ mkdir -p cppbuild/Debug $ cd cppbuild/Debug @@ -82,7 +82,7 @@ If you are comfortable with using CMake, then a full clean, build, and test look $ cmake --build . --clean-first $ ctest -__Note__: A C generator is included with the C++ build. And is built with the C++ build. Currently, the C generator is +__Note__: A C generator is included with the C++ build, and is built with the C++ build. Currently, the C generator is a work in progress. Golang Build From e502b86a36d6281fdc12a3689e7bb5fc9fb6f63b Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 14 Jul 2020 07:37:19 -0700 Subject: [PATCH 0507/1594] 1.19.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 46ea34ec4d..c1af674ec4 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.19.0-SNAPSHOT \ No newline at end of file +1.19.0 \ No newline at end of file From 7527bc7ca43d9e7fbc4c9ae56e2dc5203ad5fb19 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 14 Jul 2020 07:38:51 -0700 Subject: [PATCH 0508/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index c1af674ec4..37beea1ea9 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.19.0 \ No newline at end of file +1.19.1-SNAPSHOT \ No newline at end of file From 28c34f440d9279605526c4b14f3ef5b4778ab628 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 14 Jul 2020 18:27:42 +0100 Subject: [PATCH 0509/1594] [Java] Update gradle build script so IDEA recognises generated code. --- build.gradle | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/build.gradle b/build.gradle index 6bb754519f..3a1360015d 100644 --- a/build.gradle +++ b/build.gradle @@ -363,17 +363,14 @@ project(':sbe-samples') { def generatedDir = 'build/generated-src' sourceSets { - generated.java.srcDir generatedDir - } - - compileJava { - dependsOn 'compileGeneratedJava' + generated { + java.srcDir generatedDir + compileClasspath += project(':sbe-all').sourceSets.main.runtimeClasspath + } } - compileGeneratedJava { - dependsOn 'generateCodecs' - classpath += project(':sbe-all').sourceSets.main.runtimeClasspath - } + compileJava.dependsOn 'compileGeneratedJava' + compileGeneratedJava.dependsOn 'generateCodecs' task generateCodecs(type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' @@ -475,17 +472,14 @@ project(':sbe-benchmarks') { } sourceSets { - generated.java.srcDir 'build/generated-src' - } - - compileGeneratedJava { - dependsOn 'generateCodecs' - classpath += project(':sbe-all').sourceSets.main.runtimeClasspath + generated { + java.srcDir 'build/generated-src' + compileClasspath += project(':sbe-all').sourceSets.main.runtimeClasspath + } } - compileJava { - dependsOn 'compileGeneratedJava' - } + compileGeneratedJava.dependsOn 'generateCodecs' + compileJava.dependsOn 'compileGeneratedJava' task generateCodecs(type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' From f91534a9319435214d66e12f9c1c45b25f440439 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 14 Jul 2020 21:49:48 +0100 Subject: [PATCH 0510/1594] [Java] Naming and javadoc. --- .../uk/co/real_logic/sbe/PrimitiveValue.java | 5 ++- .../sbe/generation/java/JavaGenerator.java | 36 +++++++++---------- .../sbe/generation/java/JavaUtil.java | 7 ++-- .../java/uk/co/real_logic/sbe/ir/Token.java | 2 +- .../uk/co/real_logic/sbe/xml/EnumType.java | 2 +- .../java/uk/co/real_logic/sbe/xml/Field.java | 3 ++ .../co/real_logic/sbe/xml/ParserOptions.java | 3 ++ 7 files changed, 35 insertions(+), 23 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index 9b851ecfe5..f0e8a31d77 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -24,10 +24,13 @@ import static java.nio.charset.StandardCharsets.US_ASCII; /** - * Class used to encapsulate values for primitives. Used for nullValue, minValue, maxValue, and constants + * Class used to encapsulate values for primitives. Used for nullValue, minValue, maxValue, and constants. */ public class PrimitiveValue { + /** + * Representation type used for the stored value. + */ public enum Representation { /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 0279dd2484..e5492620fa 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3160,7 +3160,7 @@ private CharSequence generateCompositeDecoderDisplay(final List tokens) append(sb, INDENT, " return builder;"); append(sb, INDENT, " }"); sb.append('\n'); - Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, INDENT + INDENT, "builder"); + Separator.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, INDENT + INDENT, "builder"); int lengthBeforeLastGeneratedSeparator = -1; @@ -3177,7 +3177,7 @@ private CharSequence generateCompositeDecoderDisplay(final List tokens) sb.setLength(lengthBeforeLastGeneratedSeparator); } - Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, INDENT + INDENT, "builder"); + Separator.END_COMPOSITE.appendToGeneratedBuilder(sb, INDENT + INDENT, "builder"); sb.append('\n'); append(sb, INDENT, " return builder;"); append(sb, INDENT, "}"); @@ -3194,7 +3194,7 @@ private CharSequence generateChoiceDisplay(final List tokens) sb.append('\n'); append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, indent, "{"); - Separators.BEGIN_SET.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + Separator.BEGIN_SET.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); append(sb, indent, " boolean atLeastOne = false;"); for (final Token token : tokens) @@ -3206,7 +3206,7 @@ private CharSequence generateChoiceDisplay(final List tokens) append(sb, indent, " {"); append(sb, indent, " if (atLeastOne)"); append(sb, indent, " {"); - Separators.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT + INDENT, "builder"); + Separator.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT + INDENT, "builder"); append(sb, indent, " }"); append(sb, indent, " builder.append(\"" + choiceName + "\");"); append(sb, indent, " atLeastOne = true;"); @@ -3214,7 +3214,7 @@ private CharSequence generateChoiceDisplay(final List tokens) } } - Separators.END_SET.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + Separator.END_SET.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); sb.append('\n'); append(sb, indent, " return builder;"); append(sb, indent, "}"); @@ -3286,9 +3286,9 @@ private void appendGroupInstanceDecoderDisplay( append(sb, indent, " return builder;"); append(sb, indent, " }"); sb.append('\n'); - Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + Separator.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); appendDecoderDisplay(sb, fields, groups, varData, indent + INDENT); - Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + Separator.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); sb.append('\n'); append(sb, indent, " return builder;"); append(sb, indent, "}"); @@ -3332,21 +3332,21 @@ private void appendDecoderDisplay( final String groupDecoderName = decoderName(groupToken.name()); append( - sb, indent, "builder.append(\"" + groupName + Separators.KEY_VALUE + Separators.BEGIN_GROUP + "\");"); + sb, indent, "builder.append(\"" + groupName + Separator.KEY_VALUE + Separator.BEGIN_GROUP + "\");"); append(sb, indent, groupDecoderName + " " + groupName + " = " + groupName + "();"); append(sb, indent, "if (" + groupName + ".count() > 0)"); append(sb, indent, "{"); append(sb, indent, " while (" + groupName + ".hasNext())"); append(sb, indent, " {"); append(sb, indent, " " + groupName + ".next().appendTo(builder);"); - Separators.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT, "builder"); + Separator.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT, "builder"); append(sb, indent, " }"); append(sb, indent, " builder.setLength(builder.length() - 1);"); append(sb, indent, "}"); - Separators.END_GROUP.appendToGeneratedBuilder(sb, indent, "builder"); + Separator.END_GROUP.appendToGeneratedBuilder(sb, indent, "builder"); lengthBeforeLastGeneratedSeparator = sb.length(); - Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + Separator.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); i = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); } @@ -3361,7 +3361,7 @@ private void appendDecoderDisplay( final String characterEncoding = varData.get(i + 3).encoding().characterEncoding(); final String varDataName = formatPropertyName(varDataToken.name()); - append(sb, indent, "builder.append(\"" + varDataName + Separators.KEY_VALUE + "\");"); + append(sb, indent, "builder.append(\"" + varDataName + Separator.KEY_VALUE + "\");"); if (null == characterEncoding) { final String name = Generators.toUpperFirstChar(varDataToken.name()); @@ -3382,7 +3382,7 @@ private void appendDecoderDisplay( } lengthBeforeLastGeneratedSeparator = sb.length(); - Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + Separator.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); i += varDataToken.componentTokenCount(); } @@ -3401,7 +3401,7 @@ private int writeTokenDisplay( return -1; } - append(sb, indent, "builder.append(\"" + fieldName + Separators.KEY_VALUE + "\");"); + append(sb, indent, "builder.append(\"" + fieldName + Separator.KEY_VALUE + "\");"); switch (typeToken.signal()) { @@ -3418,17 +3418,17 @@ private int writeTokenDisplay( } else { - Separators.BEGIN_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); + Separator.BEGIN_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); append(sb, indent, "if (" + fieldName + "Length() > 0)"); append(sb, indent, "{"); append(sb, indent, " for (int i = 0; i < " + fieldName + "Length(); i++)"); append(sb, indent, " {"); append(sb, indent, " builder.append(" + fieldName + "(i));"); - Separators.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT, "builder"); + Separator.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT, "builder"); append(sb, indent, " }"); append(sb, indent, " builder.setLength(builder.length() - 1);"); append(sb, indent, "}"); - Separators.END_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); + Separator.END_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); } } else @@ -3463,7 +3463,7 @@ private int writeTokenDisplay( } final int lengthBeforeFieldSeparator = sb.length(); - Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + Separator.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); return lengthBeforeFieldSeparator; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 5cfa2e09f4..9a8efec306 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -36,7 +36,10 @@ */ public class JavaUtil { - public enum Separators + /** + * Separator symbols for {@link Object#toString()} implementations on codecs. + */ + public enum Separator { BEGIN_GROUP('['), END_GROUP(']'), @@ -52,7 +55,7 @@ public enum Separators public final char symbol; - Separators(final char symbol) + Separator(final char symbol) { this.symbol = symbol; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index 2eec689eb2..7111b353a1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -352,7 +352,7 @@ public String toString() } /** - * Builder for Tokens which can simplify construction. + * Builder for {@link Token} which can simplify construction. */ public static class Builder { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index 8c2d442bf4..e31c0a2c47 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -237,7 +237,7 @@ public String toString() } /** - * Class to hold valid values for EnumType + * Holder for valid values for and {@link EnumType}. */ public static class ValidValue { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java index 8b44abcaf5..7f743a3785 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java @@ -296,6 +296,9 @@ private void validateValueRef(final Node node, final Map typeByNam } } + /** + * Builder to make creation of {@link Field} easier. + */ public static class Builder { private String name; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java index 6165ad63a9..ed753140ef 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java @@ -112,6 +112,9 @@ public static Builder builder() return new Builder(); } + /** + * Builder to make {@link ParserOptions} easier to create. + */ public static class Builder { private boolean stopOnError; From d0db7633df4a4b7831da0041cb06094bf596a795 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 17 Jul 2020 15:56:36 +0100 Subject: [PATCH 0511/1594] [Java] Upgrade to Mockito 3.4.2 and Versions 0.29.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 3a1360015d..931339e2ea 100644 --- a/build.gradle +++ b/build.gradle @@ -23,14 +23,14 @@ plugins { id 'java-library' id 'idea' id 'com.github.johnrengelman.shadow' version '6.0.0' apply false - id "com.github.ben-manes.versions" version "0.28.0" + id "com.github.ben-manes.versions" version "0.29.0" } defaultTasks 'clean', 'build' def checkstyleVersion = '8.34' def hamcrestVersion = '2.2' -def mockitoVersion = '3.4.0' +def mockitoVersion = '3.4.3' def junitVersion = '5.6.2' def jmhVersion = '1.23' def agronaVersion = '1.6.0' From 0586aeff4616945d4e3e8d80fdb8c074f26663a8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 19 Jul 2020 13:50:49 +0100 Subject: [PATCH 0512/1594] [Java] Upgrade to Mockito 3.4.4. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 931339e2ea..8c31de4b03 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.34' def hamcrestVersion = '2.2' -def mockitoVersion = '3.4.3' +def mockitoVersion = '3.4.4' def junitVersion = '5.6.2' def jmhVersion = '1.23' def agronaVersion = '1.6.0' From eb01fb214e747477e5ec721580ad508ae78a2a53 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 19 Jul 2020 14:19:02 +0100 Subject: [PATCH 0513/1594] [Java] Modify build script to help IDEA recognise generated files. --- build.gradle | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 8c31de4b03..a2eb6d6a1b 100644 --- a/build.gradle +++ b/build.gradle @@ -214,10 +214,13 @@ project(':sbe-tool') { def generatedDir = 'build/generated-src' sourceSets { - generated.java.srcDir generatedDir + generated { + java.srcDir generatedDir + compileClasspath += sourceSets.main.runtimeClasspath + } test { - compileClasspath += generated.output - runtimeClasspath += generated.output + java.srcDir generatedDir + compileClasspath += sourceSets.main.runtimeClasspath } } From 34ac31beed623b7963d9830f96a9620606231cca Mon Sep 17 00:00:00 2001 From: Roger Orr Date: Thu, 23 Jul 2020 16:11:57 +0100 Subject: [PATCH 0514/1594] enum 'get' method is not noexcept (#806) --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 6ccaa533e8..cc4da15691 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2264,7 +2264,7 @@ private void generateEnumProperty( else { new Formatter(sb).format("\n" + - indent + " SBE_NODISCARD %1$s::Value %2$s() const SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD %1$s::Value %2$s() const\n" + indent + " {\n" + "%3$s" + indent + " %5$s val;\n" + From 2e4063e5def323ce22c060830d2046ebc8fedc5f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 23 Jul 2020 16:59:31 +0100 Subject: [PATCH 0515/1594] [Cpp] Constant presence field should also be not be SBE_NOEXCEPT for compatibility with schema change. PR #806. --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index cc4da15691..0f1fcbf35c 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2251,7 +2251,7 @@ private void generateEnumProperty( constValue.substring(constValue.indexOf(".") + 1)); new Formatter(sb).format("\n" + - indent + " SBE_NODISCARD %1$s::Value %2$s() const SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD %1$s::Value %2$s() const\n" + indent + " {\n" + "%3$s" + indent + " return %1$s::Value::%4$s;\n" + From 088481abfa5e20aedb96df1b8f367c7cddd1351c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 24 Jul 2020 11:03:41 +0100 Subject: [PATCH 0516/1594] [C++] Generate literals for enums correctly when outside int range. --- .../sbe/generation/c/CGenerator.java | 16 +++++++++----- .../sbe/generation/cpp/CppGenerator.java | 21 +++++++++++-------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 39d3347de0..dacfefcaa6 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -951,15 +951,21 @@ private static CharSequence generateEnumLookupFunction( for (final Token token : tokens) { + final CharSequence constVal = generateLiteral( + token.encoding().primitiveType(), token.encoding().constValue().toString()); + sb.append(String.format( " case %s:\n" + " *out = %s_%s;\n" + " return true;\n", - token.encoding().constValue().toString(), + constVal, enumName, token.name())); } + final CharSequence constVal = generateLiteral( + encodingToken.encoding().primitiveType(), encodingToken.encoding().applicableNullValue().toString()); + sb.append(String.format( " case %s:\n" + " *out = %s_NULL_VALUE;\n" + @@ -969,7 +975,7 @@ private static CharSequence generateEnumLookupFunction( " errno = E103;\n" + " return false;\n" + "}\n", - encodingToken.encoding().applicableNullValue().toString(), + constVal, enumName)); return sb; @@ -2387,7 +2393,7 @@ private CharSequence generateNullValueLiteral(final PrimitiveType primitiveType, return generateLiteral(primitiveType, encoding.applicableNullValue().toString()); } - private CharSequence generateLiteral(final PrimitiveType type, final String value) + private static CharSequence generateLiteral(final PrimitiveType type, final String value) { String literal = ""; @@ -2418,7 +2424,7 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu } else { - literal = "INT32_C(" + intValue + ")"; + literal = "INT32_C(" + value + ")"; } break; } @@ -2436,7 +2442,7 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu } else { - literal = "INT64_C(" + longValue + ")"; + literal = "INT64_C(" + value + ")"; } break; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 0f1fcbf35c..8e882bf803 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -920,19 +920,22 @@ private static CharSequence generateEnumLookupMethod(final List tokens, f for (final Token token : tokens) { - new Formatter(sb).format( - " case %1$s: return %2$s;\n", - token.encoding().constValue().toString(), - token.name()); + final CharSequence constVal = generateLiteral( + token.encoding().primitiveType(), token.encoding().constValue().toString()); + + sb.append(" case ").append(constVal).append(": return ").append(token.name()).append(";\n"); } + final CharSequence constVal = generateLiteral( + encodingToken.encoding().primitiveType(), encodingToken.encoding().applicableNullValue().toString()); + new Formatter(sb).format( " case %1$s: return NULL_VALUE;\n" + " }\n\n" + " throw std::runtime_error(\"unknown value for enum %2$s [E103]\");\n" + " }\n", - encodingToken.encoding().applicableNullValue().toString(), + constVal, enumName); return sb; @@ -2386,7 +2389,7 @@ private CharSequence generateNullValueLiteral(final PrimitiveType primitiveType, return generateLiteral(primitiveType, encoding.applicableNullValue().toString()); } - private CharSequence generateLiteral(final PrimitiveType type, final String value) + private static CharSequence generateLiteral(final PrimitiveType type, final String value) { String literal = ""; @@ -2398,7 +2401,7 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu case UINT16: case INT8: case INT16: - literal = "(" + castType + ")" + value; + literal = "static_cast<" + castType + ">(" + value + ")"; break; case UINT32: @@ -2415,7 +2418,7 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu } else { - literal = "INT32_C(" + intValue + ")"; + literal = "INT32_C(" + value + ")"; } break; @@ -2431,7 +2434,7 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu } else { - literal = "INT64_C(" + longValue + ")"; + literal = "INT64_C(" + value + ")"; } break; From f469c21d97a16710d781f706f9c0e4c41b5981f1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 24 Jul 2020 11:30:22 +0100 Subject: [PATCH 0517/1594] [C++] Generate C++ style casts. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 8e882bf803..41384f2064 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -270,8 +270,8 @@ private static void generateGroupClassHeader( indent + " m_buffer = buffer;\n" + indent + " m_bufferLength = bufferLength;\n" + indent + " %7$s dimensions(buffer, *pos, bufferLength, actingVersion);\n" + - indent + " dimensions.blockLength((%1$s)%2$d);\n" + - indent + " dimensions.numInGroup((%3$s)count);\n" + + indent + " dimensions.blockLength(static_cast<%1$s>(%2$d));\n" + + indent + " dimensions.numInGroup(static_cast<%3$s>(count));\n" + indent + " m_index = 0;\n" + indent + " m_count = count;\n" + indent + " m_blockLength = %2$d;\n" + @@ -355,7 +355,8 @@ private static void generateGroupClassHeader( .append(indent).append(" m_count = m_index;\n") .append(indent).append(" ").append(dimensionsClassName) .append(" dimensions(m_buffer, m_initialPosition, m_bufferLength, m_actingVersion);\n") - .append(indent).append(" dimensions.numInGroup((").append(cppTypeNumInGroup).append(")m_count);\n") + .append(indent) + .append(" dimensions.numInGroup(static_cast<").append(cppTypeNumInGroup).append(">(m_count));\n") .append(indent).append(" return m_count;\n") .append(indent).append(" }\n"); From 03c629748f03829fb0741812b802c3a0b642d7aa Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 24 Jul 2020 12:01:46 +0100 Subject: [PATCH 0518/1594] [C++] Formatting. --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 41384f2064..a227da9dc2 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2411,6 +2411,7 @@ private static CharSequence generateLiteral(final PrimitiveType type, final Stri literal = "UINT32_C(0x" + Integer.toHexString((int)intValue) + ")"; break; } + case INT32: final long intValue = Long.parseLong(value); if (intValue == Integer.MIN_VALUE) From cbce8ec2b5eb50b88228debfae7a6c5aca1d3dd4 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 24 Jul 2020 12:07:17 +0100 Subject: [PATCH 0519/1594] [C++] Formatting. --- .../uk/co/real_logic/sbe/generation/c/CGenerator.java | 8 ++------ .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index dacfefcaa6..21e00fe57e 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -2397,7 +2397,6 @@ private static CharSequence generateLiteral(final PrimitiveType type, final Stri { String literal = ""; - final String castType = cTypeName(type); switch (type) { case CHAR: @@ -2405,15 +2404,12 @@ private static CharSequence generateLiteral(final PrimitiveType type, final Stri case UINT16: case INT8: case INT16: - literal = "(" + castType + ")" + value; + literal = "(" + cTypeName(type) + ")" + value; break; case UINT32: - { - final long intValue = Long.parseLong(value); - literal = "UINT32_C(0x" + Integer.toHexString((int)intValue) + ")"; + literal = "UINT32_C(0x" + Integer.toHexString((int)Long.parseLong(value)) + ")"; break; - } case INT32: { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index a227da9dc2..7b60de7135 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2394,7 +2394,6 @@ private static CharSequence generateLiteral(final PrimitiveType type, final Stri { String literal = ""; - final String castType = cppTypeName(type); switch (type) { case CHAR: @@ -2402,15 +2401,12 @@ private static CharSequence generateLiteral(final PrimitiveType type, final Stri case UINT16: case INT8: case INT16: - literal = "static_cast<" + castType + ">(" + value + ")"; + literal = "static_cast<" + cppTypeName(type) + ">(" + value + ")"; break; case UINT32: - { - final long intValue = Long.parseLong(value); - literal = "UINT32_C(0x" + Integer.toHexString((int)intValue) + ")"; + literal = "UINT32_C(0x" + Integer.toHexString((int)Long.parseLong(value)) + ")"; break; - } case INT32: final long intValue = Long.parseLong(value); From da10a8fc22c5d96dae50dc4dd24372d2b7825152 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 26 Jul 2020 13:44:50 +0100 Subject: [PATCH 0520/1594] [C++] Add SBE header constants to messages so they can be more easily used on switch statements for compilers that do not have good support for const expressions. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 7b60de7135..8d982a3852 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1922,6 +1922,11 @@ private CharSequence generateMessageFlyweightCode(final String className, final " }\n\n" + "public:\n" + + " static const %1$s SBE_BLOCK_LENGTH = %2$s;\n" + + " static const %3$s SBE_TEMPLATE_ID = %4$s;\n" + + " static const %5$s SBE_SCHEMA_ID = %6$s;\n" + + " static const %7$s SBE_SCHEMA_VERSION = %8$s;\n\n" + + " enum MetaAttribute\n" + " {\n" + " EPOCH, TIME_UNIT, SEMANTIC_TYPE, PRESENCE\n" + From ffe8411e42f118ea715adbb1917048c7e8d06a77 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 30 Jul 2020 16:12:42 +0100 Subject: [PATCH 0521/1594] [Java] Upgrade to Mockito 3.4.6. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a2eb6d6a1b..33f3c984e2 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.34' def hamcrestVersion = '2.2' -def mockitoVersion = '3.4.4' +def mockitoVersion = '3.4.6' def junitVersion = '5.6.2' def jmhVersion = '1.23' def agronaVersion = '1.6.0' From 938449e942970d68d502ab07bc47949181827277 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 1 Aug 2020 15:30:33 +0100 Subject: [PATCH 0522/1594] [Java] Upgrade to Checkstyle 8.35. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 33f3c984e2..75e9671ca8 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ plugins { defaultTasks 'clean', 'build' -def checkstyleVersion = '8.34' +def checkstyleVersion = '8.35' def hamcrestVersion = '2.2' def mockitoVersion = '3.4.6' def junitVersion = '5.6.2' From ee29a629021a8f1c54e2483f7249deccf6143c21 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 3 Aug 2020 12:32:25 +0100 Subject: [PATCH 0523/1594] [Java] Null check for attributes when doing a lookup. --- .../real_logic/sbe/xml/XmlSchemaParser.java | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 007ef97b82..e78c312eb0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -17,24 +17,19 @@ package uk.co.real_logic.sbe.xml; import org.agrona.collections.ObjectHashSet; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; +import org.w3c.dom.*; +import org.xml.sax.InputSource; import uk.co.real_logic.sbe.ValidationUtil; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.validation.SchemaFactory; -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; +import javax.xml.xpath.*; import java.io.File; import java.io.InputStream; import java.nio.ByteOrder; import java.util.HashMap; import java.util.Map; -import org.xml.sax.InputSource; import static uk.co.real_logic.sbe.PrimitiveType.*; import static uk.co.real_logic.sbe.xml.Presence.REQUIRED; @@ -279,8 +274,14 @@ public static void handleWarning(final Node node, final String msg) */ public static String getAttributeValue(final Node elementNode, final String attrName) { - final Node attrNode = elementNode.getAttributes().getNamedItemNS(null, attrName); + final NamedNodeMap attributes = elementNode.getAttributes(); + if (null == attributes) + { + throw new IllegalStateException( + "element '" + elementNode.getNodeName() + "' has empty or missing attribute: " + attrName); + } + final Node attrNode = attributes.getNamedItemNS(null, attrName); if (attrNode == null || "".equals(attrNode.getNodeValue())) { throw new IllegalStateException( @@ -300,7 +301,13 @@ public static String getAttributeValue(final Node elementNode, final String attr */ public static String getAttributeValue(final Node elementNode, final String attrName, final String defValue) { - final Node attrNode = elementNode.getAttributes().getNamedItemNS(null, attrName); + final NamedNodeMap attributes = elementNode.getAttributes(); + if (attributes == null) + { + return defValue; + } + + final Node attrNode = attributes.getNamedItemNS(null, attrName); if (attrNode == null) { From 612318f24da28a4e73ded4c64fbd2285cc554504 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 5 Aug 2020 11:50:08 +0100 Subject: [PATCH 0524/1594] [Java] Upgrade to JMH 1.24. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 75e9671ca8..579dd61a73 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ def checkstyleVersion = '8.35' def hamcrestVersion = '2.2' def mockitoVersion = '3.4.6' def junitVersion = '5.6.2' -def jmhVersion = '1.23' +def jmhVersion = '1.24' def agronaVersion = '1.6.0' def sbeGroup = 'uk.co.real-logic' From 93e959df58771b14200c41d4a36e90848182abc9 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 5 Aug 2020 13:46:29 +0100 Subject: [PATCH 0525/1594] [Java] Improve error messages when parsing a non-SBE schema XML file. --- .../real_logic/sbe/xml/XmlSchemaParser.java | 77 ++++++++++++------- 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index e78c312eb0..9353e31849 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -61,7 +61,7 @@ public class XmlSchemaParser "/*[local-name() = 'messageSchema']"; static final String MESSAGE_XPATH_EXPR = - "//*[local-name() = 'message']"; + "/*[local-name() = 'messageSchema']/*[local-name() = 'message']"; /** * Validate the document against a given schema. Errors will be written to {@link java.lang.System#err}. @@ -141,6 +141,11 @@ public static MessageSchema parse(final InputSource is, final ParserOptions opti errorHandler.checkIfShouldExit(); final Node schemaNode = (Node)xPath.compile(MESSAGE_SCHEMA_XPATH_EXPR).evaluate(document, XPathConstants.NODE); + if (null == schemaNode) + { + throw new IllegalStateException("messageSchema element not found in document, schema is not valid for SBE"); + } + final MessageSchema messageSchema = new MessageSchema(schemaNode, typeByNameMap, messageByIdMap); errorHandler.checkIfShouldExit(); @@ -167,9 +172,9 @@ public static MessageSchema parse(final InputStream in, final ParserOptions opti /** * Scan XML for all types (encodedDataType, compositeType, enumType, and setType) and save in map. * - * @param document for the XML parsing - * @param xPath for XPath expression reuse - * @return {@link java.util.Map} of name {@link java.lang.String} to Type + * @param document for the XML parsing. + * @param xPath for XPath expression reuse. + * @return {@link java.util.Map} of name {@link java.lang.String} to {@link Type}. * @throws Exception on parsing error. */ public static Map findTypes(final Document document, final XPath xPath) throws Exception @@ -206,10 +211,10 @@ public static Map findTypes(final Document document, final XPath x /** * Scan XML for all message definitions and save in map. * - * @param document for the XML parsing - * @param xPath for XPath expression reuse - * @param typeByNameMap to use for Type objects - * @return {@link java.util.Map} of schemaId to Message + * @param document for the XML parsing. + * @param xPath for XPath expression reuse. + * @param typeByNameMap to use for Type objects. + * @return {@link java.util.Map} of schemaId to {@link Message}. * @throws Exception on parsing error. */ public static Map findMessages( @@ -221,6 +226,11 @@ public static Map findMessages( forEach((NodeList)xPath.compile(MESSAGE_XPATH_EXPR).evaluate(document, XPathConstants.NODESET), (node) -> addMessageWithIdCheck(distinctNames, messageByIdMap, new Message(node, typeByNameMap), node)); + if (messageByIdMap.isEmpty()) + { + handleWarning(document.getDocumentElement(), "no messages found in document"); + } + return messageByIdMap; } @@ -233,8 +243,7 @@ public static Map findMessages( public static void handleError(final Node node, final String msg) { final ErrorHandler handler = (ErrorHandler)node.getOwnerDocument().getUserData(ERROR_HANDLER_KEY); - - if (handler == null) + if (null == handler) { throw new IllegalStateException("ERROR: " + formatLocationInfo(node) + msg); } @@ -253,8 +262,7 @@ public static void handleError(final Node node, final String msg) public static void handleWarning(final Node node, final String msg) { final ErrorHandler handler = (ErrorHandler)node.getOwnerDocument().getUserData(ERROR_HANDLER_KEY); - - if (handler == null) + if (null == handler) { throw new IllegalStateException("WARNING: " + formatLocationInfo(node) + msg); } @@ -267,13 +275,19 @@ public static void handleWarning(final Node node, final String msg) /** * Helper function that throws an exception when the attribute is not set. * - * @param elementNode that should have the attribute - * @param attrName that is to be looked up - * @return value of the attribute - * @throws IllegalArgumentException if the attribute is not present + * @param elementNode that should have the attribute. + * @param attrName that is to be looked up. + * @return value of the attribute. + * @throws IllegalStateException if the attribute is not present. */ public static String getAttributeValue(final Node elementNode, final String attrName) { + if (null == elementNode) + { + throw new IllegalStateException( + "element node is null when looking for attribute: " + attrName); + } + final NamedNodeMap attributes = elementNode.getAttributes(); if (null == attributes) { @@ -282,7 +296,7 @@ public static String getAttributeValue(final Node elementNode, final String attr } final Node attrNode = attributes.getNamedItemNS(null, attrName); - if (attrNode == null || "".equals(attrNode.getNodeValue())) + if (null == attrNode || "".equals(attrNode.getNodeValue())) { throw new IllegalStateException( "element '" + elementNode.getNodeName() + "' has empty or missing attribute: " + attrName); @@ -294,22 +308,27 @@ public static String getAttributeValue(final Node elementNode, final String attr /** * Helper function that uses a default value when value not set. * - * @param elementNode that should have the attribute - * @param attrName that is to be looked up - * @param defValue String to return if not set - * @return value of the attribute or defValue + * @param elementNode that should have the attribute. + * @param attrName that is to be looked up. + * @param defValue value to return if not set. + * @return value of the attribute or defValue. */ public static String getAttributeValue(final Node elementNode, final String attrName, final String defValue) { + if (null == elementNode) + { + throw new IllegalStateException( + "element node is null when looking for attribute: " + attrName); + } + final NamedNodeMap attributes = elementNode.getAttributes(); - if (attributes == null) + if (null == attributes) { return defValue; } final Node attrNode = attributes.getNamedItemNS(null, attrName); - - if (attrNode == null) + if (null == attrNode) { return defValue; } @@ -320,9 +339,9 @@ public static String getAttributeValue(final Node elementNode, final String attr /** * Helper function that hides the null return from {@link org.w3c.dom.NamedNodeMap#getNamedItem(String)}. * - * @param elementNode that could be null - * @param attrName that is to be looked up - * @return null or value of the attribute + * @param elementNode that could be null. + * @param attrName that is to be looked up. + * @return null or value of the attribute. */ public static String getAttributeValueOrNull(final Node elementNode, final String attrName) { @@ -343,8 +362,8 @@ public static String getAttributeValueOrNull(final Node elementNode, final Strin /** * Helper function to convert a schema byteOrderName into a {@link ByteOrder}. * - * @param byteOrderName specified as a FIX SBE string - * @return ByteOrder representation + * @param byteOrderName specified as a FIX SBE string. + * @return ByteOrder representation. */ public static ByteOrder getByteOrder(final String byteOrderName) { From 6691e6294b669a10c086b317ac34648fca93c83b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 5 Aug 2020 16:37:02 +0100 Subject: [PATCH 0526/1594] [Java] Use sbeVersion directly for manifests to avoid embedding in a string. --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 579dd61a73..a56748e87c 100644 --- a/build.gradle +++ b/build.gradle @@ -246,7 +246,7 @@ project(':sbe-tool') { 'Specification-Title': 'Simple Binary Encoding', 'Specification-Version': '1.0', 'Implementation-Title': 'SBE', - 'Implementation-Version': "${sbeVersion}", + 'Implementation-Version': sbeVersion, 'Implementation-Vendor': 'Real Logic Limited', 'Automatic-Module-Name': 'uk.co.real_logic.sbe.tool' ) @@ -305,7 +305,7 @@ project(':sbe-all') { 'Specification-Title': 'Simple Binary Encoding', 'Specification-Version': '1.0', 'Implementation-Title': 'SBE', - 'Implementation-Version': "${sbeVersion}", + 'Implementation-Version': sbeVersion, 'Implementation-Vendor': 'Real Logic Limited', 'Automatic-Module-Name': 'uk.co.real_logic.sbe.all' ) @@ -418,7 +418,7 @@ project(':sbe-samples') { 'Specification-Title': 'Simple Binary Encoding', 'Specification-Version': '1.0', 'Implementation-Title': 'SBE', - 'Implementation-Version': "${sbeVersion}", + 'Implementation-Version': sbeVersion, 'Implementation-Vendor': 'Real Logic Limited', 'Automatic-Module-Name': 'uk.co.real_logic.sbe.samples' ) From f8cb350b2efd7ddfddd18461d49ac8e16df40321 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 13 Aug 2020 13:03:09 +0100 Subject: [PATCH 0527/1594] [Java] Upgrade to JMH 1.25. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a56748e87c..632ee94710 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ def checkstyleVersion = '8.35' def hamcrestVersion = '2.2' def mockitoVersion = '3.4.6' def junitVersion = '5.6.2' -def jmhVersion = '1.24' +def jmhVersion = '1.25' def agronaVersion = '1.6.0' def sbeGroup = 'uk.co.real-logic' From dafb4f586051b59ee8b3c6b69aec37b1c8a0b8bf Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 17 Aug 2020 12:18:48 +0100 Subject: [PATCH 0528/1594] [Java] Upgrade to Mockito 3.5.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 632ee94710..105cade217 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.35' def hamcrestVersion = '2.2' -def mockitoVersion = '3.4.6' +def mockitoVersion = '3.5.0' def junitVersion = '5.6.2' def jmhVersion = '1.25' def agronaVersion = '1.6.0' From b0b26495e39ad009d6b477894c86bd185e8a302a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 19 Aug 2020 07:37:21 +0100 Subject: [PATCH 0529/1594] [Java] Upgrade to Mockito 3.5.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 105cade217..41f440bcb4 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.35' def hamcrestVersion = '2.2' -def mockitoVersion = '3.5.0' +def mockitoVersion = '3.5.2' def junitVersion = '5.6.2' def jmhVersion = '1.25' def agronaVersion = '1.6.0' From f211425cd8332aa94e2274d8891581946b3279e5 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 24 Aug 2020 09:03:39 +0100 Subject: [PATCH 0530/1594] [Java] Upgrade to Mockito 3.5.5. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 41f440bcb4..6f08293c0d 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.35' def hamcrestVersion = '2.2' -def mockitoVersion = '3.5.2' +def mockitoVersion = '3.5.5' def junitVersion = '5.6.2' def jmhVersion = '1.25' def agronaVersion = '1.6.0' From 6311a5e5a8855235d4c2f5de60448c3f362eec29 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 25 Aug 2020 08:37:03 +0100 Subject: [PATCH 0531/1594] [Java] Upgrade to Gradle 6.6. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 58910 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- gradlew.bat | 21 +++------------------ 5 files changed, 6 insertions(+), 21 deletions(-) diff --git a/build.gradle b/build.gradle index 6f08293c0d..ef9170019e 100644 --- a/build.gradle +++ b/build.gradle @@ -686,6 +686,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.5.1' + gradleVersion = '6.6' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 62d4c053550b91381bbd28b1afc82d634bf73a8a..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch delta 6656 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 Yte!%o?r4GTrVtxD61Ym!|5fq-1K$0e!T1w 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ac33e9944a..bca17f3656 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index fbd7c51583..4f906e0c81 100755 --- a/gradlew +++ b/gradlew @@ -130,7 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index 5093609d51..107acd32c4 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -54,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -64,21 +64,6 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line @@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell From 1978b787a1bf873167b8f726c7fe2bb95628dbc7 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 25 Aug 2020 16:13:21 +0100 Subject: [PATCH 0532/1594] [Java] Upgrade to Mockito 3.5.6. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ef9170019e..b4f1da160b 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.35' def hamcrestVersion = '2.2' -def mockitoVersion = '3.5.5' +def mockitoVersion = '3.5.6' def junitVersion = '5.6.2' def jmhVersion = '1.25' def agronaVersion = '1.6.0' From ffc515417134bba36f7a61f69e9e9a880894b666 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 26 Aug 2020 10:44:09 +0100 Subject: [PATCH 0533/1594] [Java] Upgrade to Mockito 3.5.7. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b4f1da160b..70321a8d02 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.35' def hamcrestVersion = '2.2' -def mockitoVersion = '3.5.6' +def mockitoVersion = '3.5.7' def junitVersion = '5.6.2' def jmhVersion = '1.25' def agronaVersion = '1.6.0' From d0a696f6de4c8c2f19423311b997618bace1ca20 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 26 Aug 2020 10:55:06 +0100 Subject: [PATCH 0534/1594] [Java] Upgrade to Gradle 6.6.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 70321a8d02..94c6b83a1b 100644 --- a/build.gradle +++ b/build.gradle @@ -686,6 +686,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.6' + gradleVersion = '6.6.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bca17f3656..33682bbbf9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 2c4823fa2715b76ea03c8b2e178a3c1ed1fd0d89 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 27 Aug 2020 08:59:48 +0100 Subject: [PATCH 0535/1594] [Java] Upgrade to JMH 1.25.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 94c6b83a1b..a029593852 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ def checkstyleVersion = '8.35' def hamcrestVersion = '2.2' def mockitoVersion = '3.5.7' def junitVersion = '5.6.2' -def jmhVersion = '1.25' +def jmhVersion = '1.25.1' def agronaVersion = '1.6.0' def sbeGroup = 'uk.co.real-logic' From 45c039ba96bbc1141b3caa9f3afaad06164d698a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 28 Aug 2020 17:14:33 +0100 Subject: [PATCH 0536/1594] [Java] Upgrade to Agrona 1.7.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a029593852..2707556086 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.5.7' def junitVersion = '5.6.2' def jmhVersion = '1.25.1' -def agronaVersion = '1.6.0' +def agronaVersion = '1.7.0' def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 07354d92c9f47dc77a6e1826cdefc76a0347009c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 29 Aug 2020 14:59:56 +0100 Subject: [PATCH 0537/1594] [Java] Update version and readme for release. --- README.md | 15 ++++++--------- version.txt | 2 +- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 40b1e068eb..50d2407a90 100644 --- a/README.md +++ b/README.md @@ -34,14 +34,14 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.19.0 +    1.20.0 ``` Build ----- -The project is built with [Gradle](http://gradle.org/) using this [build.gradle](https://github.com/real-logic/simple-binary-encoding/blob/master/build.gradle) file. +Build the project with [Gradle](http://gradle.org/) using this [build.gradle](https://github.com/real-logic/simple-binary-encoding/blob/master/build.gradle) file. Full clean build: @@ -70,7 +70,7 @@ NOTE: Linux, Mac OS, and Windows only for the moment. See [FAQ](https://github.com/real-logic/simple-binary-encoding/wiki/Frequently-Asked-Questions). Windows builds have been tested with Visual Studio Express 12. -For convenience, a script is provided that does a full clean, build, and test of all targets as a Release build. +For convenience, the `cppbuild` script does a full clean, build, and test of all targets as a Release build. $ ./cppbuild/cppbuild @@ -82,20 +82,17 @@ If you are comfortable using CMake, then a full clean, build, and test looks lik $ cmake --build . --clean-first $ ctest -__Note__: A C generator is included with the C++ build, and is built with the C++ build. Currently, the C generator is - a work in progress. +__Note__: The C++ build includes the C generator. Currently, the C generator is a work in progress. Golang Build ------------ -First build using Gradle to generate the SBE jar and then use it to -generate the golang code for testing +First build using Gradle to generate the SBE jar and then use it to generate the golang code for testing. $ ./gradlew $ ./gradlew generateGolangCodecs -For convenience on Linux, a gnu Makefile is provided that runs some -tests and contains some examples +For convenience on Linux, a gnu Makefile is provided that runs some tests and contains some examples. $ cd gocode # make # test, examples, bench diff --git a/version.txt b/version.txt index 37beea1ea9..d3d1ecf2e7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.19.1-SNAPSHOT \ No newline at end of file +1.20.0-SNAPSHOT \ No newline at end of file From 5c7a36c3436c26d8b4b8a32a8a78d14000fb5732 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 29 Aug 2020 15:29:59 +0100 Subject: [PATCH 0538/1594] [Java] Allow patch versions of Agrona. --- build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2707556086..3e6829989a 100644 --- a/build.gradle +++ b/build.gradle @@ -34,6 +34,7 @@ def mockitoVersion = '3.5.7' def junitVersion = '5.6.2' def jmhVersion = '1.25.1' def agronaVersion = '1.7.0' +def agronaVersionRange = '[1.7,1.8[' // allow any patch release of 1.7.x def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() @@ -201,7 +202,8 @@ project(':sbe-tool') { dependencies { api("org.agrona:agrona") { version { - strictly(agronaVersion) + strictly(agronaVersionRange) + prefer(agronaVersion) } } testImplementation files('build/classes/java/generated') From 8a94c7e3746d3fcfc5c7a3b8e669dbb82d50b673 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 29 Aug 2020 08:02:08 -0700 Subject: [PATCH 0539/1594] 1.20.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index d3d1ecf2e7..f1e7f0650f 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.20.0-SNAPSHOT \ No newline at end of file +1.20.0 \ No newline at end of file From d28e863a16645d2924347b7b5a6e583fb35f84e7 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 29 Aug 2020 08:03:27 -0700 Subject: [PATCH 0540/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index f1e7f0650f..cac6ccf20a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.20.0 \ No newline at end of file +1.20.1-SNAPSHOT \ No newline at end of file From 559cb904a2be60fea6ecb851cf6eb9c9e8d01dce Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 3 Sep 2020 11:40:23 +0100 Subject: [PATCH 0541/1594] [Java] Upgrade to JMH 1.25.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3e6829989a..284dafab66 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ def checkstyleVersion = '8.35' def hamcrestVersion = '2.2' def mockitoVersion = '3.5.7' def junitVersion = '5.6.2' -def jmhVersion = '1.25.1' +def jmhVersion = '1.25.2' def agronaVersion = '1.7.0' def agronaVersionRange = '[1.7,1.8[' // allow any patch release of 1.7.x From f92f835e8e81e549bc1b0e75896bfc0beb892496 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 4 Sep 2020 12:19:21 +0100 Subject: [PATCH 0542/1594] [Java] Upgrade to Mockito 3.5.10. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 284dafab66..65e2aaa6cb 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.35' def hamcrestVersion = '2.2' -def mockitoVersion = '3.5.7' +def mockitoVersion = '3.5.10' def junitVersion = '5.6.2' def jmhVersion = '1.25.2' def agronaVersion = '1.7.0' From 1683be1fe31a42e32ff9c0913df40cef67adf82f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 5 Sep 2020 15:07:19 +0100 Subject: [PATCH 0543/1594] [Java] Upgrade to Checkstyle 8.36 and Versions 0.30.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 65e2aaa6cb..f8f4da08bb 100644 --- a/build.gradle +++ b/build.gradle @@ -23,12 +23,12 @@ plugins { id 'java-library' id 'idea' id 'com.github.johnrengelman.shadow' version '6.0.0' apply false - id "com.github.ben-manes.versions" version "0.29.0" + id "com.github.ben-manes.versions" version "0.30.0" } defaultTasks 'clean', 'build' -def checkstyleVersion = '8.35' +def checkstyleVersion = '8.36' def hamcrestVersion = '2.2' def mockitoVersion = '3.5.10' def junitVersion = '5.6.2' From 3800f7298ea205bc679dc67c4da2ced100840d3b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 6 Sep 2020 16:35:01 +0100 Subject: [PATCH 0544/1594] [Java] Upgrade to Agrona 1.7.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f8f4da08bb..a61f170d1e 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.5.10' def junitVersion = '5.6.2' def jmhVersion = '1.25.2' -def agronaVersion = '1.7.0' +def agronaVersion = '1.7.1' def agronaVersionRange = '[1.7,1.8[' // allow any patch release of 1.7.x def sbeGroup = 'uk.co.real-logic' From b428a4e08c05f7e6d4d03764fcf64a840a9e3831 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 8 Sep 2020 11:02:00 +0100 Subject: [PATCH 0545/1594] [Java] Upgrade to Versions 0.31.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a61f170d1e..fc39565427 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ plugins { id 'java-library' id 'idea' id 'com.github.johnrengelman.shadow' version '6.0.0' apply false - id "com.github.ben-manes.versions" version "0.30.0" + id "com.github.ben-manes.versions" version "0.31.0" } defaultTasks 'clean', 'build' From d792092633bbe415d1c389cb8eb5e3b479d38a9a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 10 Sep 2020 17:07:53 +0100 Subject: [PATCH 0546/1594] [Java] Validate range on enum valid values. --- .../java/uk/co/real_logic/sbe/xml/EnumType.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index e31c0a2c47..f2addf6877 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -149,6 +149,22 @@ else if (presence() == OPTIONAL) handleWarning(node, "validValue already exists for name: " + v.name()); } + if (PrimitiveType.CHAR != encodingType) + { + final long value = v.primitiveValue().longValue(); + final long minValue = null != encodedDataType && null != encodedDataType.minValue() ? + encodedDataType.minValue().longValue() : encodingType.minValue().longValue(); + final long maxValue = null != encodedDataType && null != encodedDataType.maxValue() ? + encodedDataType.maxValue().longValue() : encodingType.maxValue().longValue(); + + if (value < minValue || value > maxValue) + { + handleError( + node, + "validValue " + v.name() + " outside of range " + minValue + " - " + maxValue + ": " + value); + } + } + validValueByPrimitiveValueMap.put(v.primitiveValue(), v); validValueByNameMap.put(v.name(), v); } From aef1eed3a3065958e92fd010c716ccf1f339199b Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 10 Sep 2020 19:33:42 +0200 Subject: [PATCH 0547/1594] [Java] Handle nullValue when validating value range for EnumType. (#817) * [Java] Validate EnumType value is in the valid range, including custom ranges and nullValue handling. * [Java] Allow value out of range if it is the nullValue. * [Java] Do not allow nullValue in as an enum constant. --- .../uk/co/real_logic/sbe/xml/EnumType.java | 17 ++++-- .../co/real_logic/sbe/xml/EnumTypeTest.java | 61 ++++++++++++++++++- ...dler-enum-violates-min-max-value-range.xml | 30 +++++++++ 3 files changed, 100 insertions(+), 8 deletions(-) create mode 100644 sbe-tool/src/test/resources/error-handler-enum-violates-min-max-value-range.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index f2addf6877..8fecc2e118 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -29,11 +29,7 @@ import java.util.Map; import static uk.co.real_logic.sbe.xml.Presence.OPTIONAL; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.handleError; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.handleWarning; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.checkForValidName; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.getAttributeValue; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.getAttributeValueOrNull; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.*; /** * SBE enum type for representing an enumeration of values. @@ -156,8 +152,17 @@ else if (presence() == OPTIONAL) encodedDataType.minValue().longValue() : encodingType.minValue().longValue(); final long maxValue = null != encodedDataType && null != encodedDataType.maxValue() ? encodedDataType.maxValue().longValue() : encodingType.maxValue().longValue(); + final long nullLongValue = null != nullValue ? nullValue.longValue() : + encodingType.nullValue().longValue(); - if (value < minValue || value > maxValue) + if (nullLongValue == value) + { + handleError( + node, + "validValue " + v.name() + " uses nullValue: " + + (null != nullValue ? nullValue : encodingType.nullValue())); + } + else if (value < minValue || value > maxValue) { handleError( node, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index 88335f884a..922a98af95 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -16,6 +16,8 @@ package uk.co.real_logic.sbe.xml; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; @@ -31,14 +33,14 @@ import javax.xml.xpath.XPathFactory; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class EnumTypeTest @@ -223,6 +225,61 @@ public void shouldThrowExceptionWhenDuplicateNameSpecified() parseTestXmlWithMap("/types/enum", testXmlString)); } + @Test + public void shouldThrowExceptionWhenImplicitNullValueIsUsed() + { + final String testXmlString = + "" + + "" + + " 1" + + " 255" + + "" + + ""; + + assertThrows(IllegalArgumentException.class, () -> + parseTestXmlWithMap("/types/enum", testXmlString)); + } + + @Test + public void shouldThrowExceptionWhenExplicitNullValueIsUsed() + { + final String testXmlString = + "" + + "" + + " 1" + + " 5" + + "" + + ""; + + assertThrows(IllegalArgumentException.class, () -> + parseTestXmlWithMap("/types/enum", testXmlString)); + } + + @ParameterizedTest + @ValueSource(longs = { (long)Integer.MIN_VALUE - 1, (long)Integer.MAX_VALUE + 1 }) + public void shouldThrowExceptionWhenIntValueIsOutOfRange(final long value) + { + final String testXmlString = + "" + + "" + + " " + value + "" + + "" + + ""; + + final NumberFormatException exception = assertThrows(NumberFormatException.class, () -> + parseTestXmlWithMap("/types/enum", testXmlString)); + assertEquals("For input string: \"" + value + "\"", exception.getMessage()); + } + + @Test + public void shouldThrowExceptionIfEnumValueIsOutOfCustomValueRange() throws IOException + { + final InputStream file = Tests.getLocalResource("error-handler-enum-violates-min-max-value-range.xml"); + final IllegalStateException exception = assertThrows(IllegalStateException.class, + () -> parse(file, ParserOptions.builder().suppressOutput(true).build())); + assertEquals("had 4 errors", exception.getMessage()); + } + @Test public void shouldHandleEncodingTypesWithNamedTypes() throws Exception { diff --git a/sbe-tool/src/test/resources/error-handler-enum-violates-min-max-value-range.xml b/sbe-tool/src/test/resources/error-handler-enum-violates-min-max-value-range.xml new file mode 100644 index 0000000000..e5236b360c --- /dev/null +++ b/sbe-tool/src/test/resources/error-handler-enum-violates-min-max-value-range.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + 0 + 1 + 5 + 6 + -2147483648 + + + 3 + 4 + + + + + + From 7f5c8e417af2abe27c0641f3b8e1c60d2c775b38 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Sat, 12 Sep 2020 18:06:51 +0100 Subject: [PATCH 0548/1594] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 50d2407a90..180778a63c 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.20.0 +    1.20.1 ``` From 508b451a4ba94779752cf70e384be0278bb34b50 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 12 Sep 2020 10:18:03 -0700 Subject: [PATCH 0549/1594] 1.20.1 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index cac6ccf20a..1acb46a42a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.20.1-SNAPSHOT \ No newline at end of file +1.20.1 \ No newline at end of file From 2378ee72725f27b4fb65799278cd6059636cd1bd Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sat, 12 Sep 2020 10:19:40 -0700 Subject: [PATCH 0550/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 1acb46a42a..64ea264975 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.20.1 \ No newline at end of file +1.20.2-SNAPSHOT \ No newline at end of file From a1960ff0e171c8c0b6ef40175ff6a308434ac176 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 14 Sep 2020 13:15:37 +0100 Subject: [PATCH 0551/1594] [Java] Upgrade to Versions 0.33.0 and JUnit 5.7.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index fc39565427..3d0bdcfcfd 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ plugins { id 'java-library' id 'idea' id 'com.github.johnrengelman.shadow' version '6.0.0' apply false - id "com.github.ben-manes.versions" version "0.31.0" + id "com.github.ben-manes.versions" version "0.33.0" } defaultTasks 'clean', 'build' @@ -31,7 +31,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.36' def hamcrestVersion = '2.2' def mockitoVersion = '3.5.10' -def junitVersion = '5.6.2' +def junitVersion = '5.7.0' def jmhVersion = '1.25.2' def agronaVersion = '1.7.1' def agronaVersionRange = '[1.7,1.8[' // allow any patch release of 1.7.x From 70d5c2ea527e913be7a44345652088d2123f52a3 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 14 Sep 2020 23:31:41 +0200 Subject: [PATCH 0552/1594] [C] Use CMake 3.6.1 as a minimum version. --- .github/workflows/ci.yml | 29 ++++++++++++++++++++++------- CMakeLists.txt | 4 ++-- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ad7fc405d..1a316df0e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,7 @@ on: env: GRADLE_OPTS: "-Dorg.gradle.daemon=false" + CMAKE_VERSION: "3.6.1" jobs: java-build: @@ -112,8 +113,12 @@ jobs: - name: Install compiler run: | sudo apt-get install -y g++-${{ matrix.version }} libsparsehash-dev + + curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz + tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz + echo "::add-path::cmake-${CMAKE_VERSION}-Linux-x86_64/bin" - name: Build - run: ./cppbuild/cppbuild + run: cmake --version && ./cppbuild/cppbuild cpp-clang-build: name: C++ Clang ${{ matrix.version }} @@ -147,27 +152,31 @@ jobs: sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev + + curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz + tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz + echo "::add-path::cmake-${CMAKE_VERSION}-Linux-x86_64/bin" - name: Build - run: ./cppbuild/cppbuild + run: cmake --version && ./cppbuild/cppbuild cpp-clang-macos-build: name: C++ Xcode ${{ matrix.version }} (macOS) runs-on: macOS-latest strategy: fail-fast: false - matrix: - version: [ '11.2.1' ] env: CC: clang CXX: clang++ steps: - name: Checkout code uses: actions/checkout@v2 - - name: Install compiler + - name: Install CMake run: | - sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app + curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz + tar xf cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz + echo "::add-path::cmake-${CMAKE_VERSION}-Darwin-x86_64/bin" - name: Build - run: ./cppbuild/cppbuild + run: cmake --version && ./cppbuild/cppbuild cpp-msvc-build: name: C++ MSVC (Windows) @@ -180,5 +189,11 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v2 + - name: Install CMake + run: | + $client = new-object System.Net.WebClient + $client.DownloadFile("https://github.com/Kitware/CMake/releases/download/v$Env:CMAKE_VERSION/cmake-$Env:CMAKE_VERSION-win64-x64.zip","cmake-$Env:CMAKE_VERSION-win64-x64.zip") + 7z x cmake-$Env:CMAKE_VERSION-win64-x64.zip + echo "::add-path::cmake-$Env:CMAKE_VERSION-win64-x64/bin" - name: Build run: cppbuild/cppbuild.cmd diff --git a/CMakeLists.txt b/CMakeLists.txt index 406d03f96d..a5d9180b14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,8 +14,8 @@ # limitations under the License. # -cmake_minimum_required(VERSION 3.1.3 FATAL_ERROR) -cmake_policy(VERSION 3.1.3) +cmake_minimum_required(VERSION 3.6.1 FATAL_ERROR) +cmake_policy(VERSION 3.6.1) file(STRINGS version.txt SBE_VERSION_TXT LIMIT_COUNT 1 REGEX "^[0-9]+(\\.[0-9]+)+") string(REGEX REPLACE "^([0-9]+(\\.[0-9]+)+).*$" "\\1" SBE_VERSION_NUMERIC "${SBE_VERSION_TXT}") From 9239dbfc4b772ab98bbb127ac00b0cc4c87b30a8 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 14 Sep 2020 23:43:36 +0200 Subject: [PATCH 0553/1594] [C] Fix CMake install on MacOS. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a316df0e9..94223aa69d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -174,7 +174,7 @@ jobs: run: | curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz - echo "::add-path::cmake-${CMAKE_VERSION}-Darwin-x86_64/bin" + echo "::add-path::cmake-${CMAKE_VERSION}-Darwin-x86_64/CMake.app/Contents/bin" - name: Build run: cmake --version && ./cppbuild/cppbuild From 7f00e1fe1615d7ae5e264ef118701b276ded3594 Mon Sep 17 00:00:00 2001 From: mhoogveld Date: Tue, 15 Sep 2020 08:54:42 +0200 Subject: [PATCH 0554/1594] C# auto-generated header for generated c# codec files (#814) * Added "auto-generated" tag which is recognized by Visual Studio at the top of each generated C# file. Auto-generated files are not included in automatic code-cleanup and/or inspection processes. * Renamed all generated *.cs files to *.g.cs Like the auto-generated tag in the file's header, this causes files to be recognized as auto-generated code by Visual Studio. An added bonus of the filename change is that these files can be treated differently based on the filename in your project's .gitignore or .editorconfig files --- .../co/real_logic/sbe/generation/csharp/CSharpGenerator.java | 4 +++- .../sbe/generation/csharp/CSharpNamespaceOutputManager.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index e3671c14c0..1a45d845c0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -614,7 +614,9 @@ private CharSequence generateFileHeader(final String packageName) } return String.format( - "/* Generated SBE (Simple Binary Encoding) message codec */\n\n" + + "// \n" + + "// Generated SBE (Simple Binary Encoding) message codec\n" + + "// \n\n" + "#pragma warning disable 1591 // disable warning on missing comments\n" + "using System;\n" + "using Org.SbeTool.Sbe.Dll;\n\n" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java index 389d942fc4..b3d7c20c26 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java @@ -71,7 +71,7 @@ public CSharpNamespaceOutputManager(final String baseDirName, final String packa */ public Writer createOutput(final String name) throws IOException { - final File targetFile = new File(outputDir, name + ".cs"); + final File targetFile = new File(outputDir, name + ".g.cs"); return Files.newBufferedWriter(targetFile.toPath(), StandardCharsets.UTF_8); } } From e616134f487bd6ad304dd1cef2bdb8276da05f79 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 18 Sep 2020 17:03:36 +0100 Subject: [PATCH 0555/1594] [Java] Upgrade to Agrona 1.7.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3d0bdcfcfd..946291b240 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.5.10' def junitVersion = '5.7.0' def jmhVersion = '1.25.2' -def agronaVersion = '1.7.1' +def agronaVersion = '1.7.2' def agronaVersionRange = '[1.7,1.8[' // allow any patch release of 1.7.x def sbeGroup = 'uk.co.real-logic' From b80b0a7282ec0dd40cf2a55e3fc639c88885cb04 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 18 Sep 2020 17:05:09 +0100 Subject: [PATCH 0556/1594] [Java] README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 180778a63c..2350f565aa 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.20.1 +    1.20.2 ``` From e4573f8836291a109c592702063e214ee2433208 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 18 Sep 2020 09:27:45 -0700 Subject: [PATCH 0557/1594] 1.20.2 release. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 64ea264975..341e509f13 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.20.2-SNAPSHOT \ No newline at end of file +1.20.2 \ No newline at end of file From 42966a9c6dcbbb283a62c6dbdcc7967b39f1de9e Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 18 Sep 2020 09:29:19 -0700 Subject: [PATCH 0558/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 341e509f13..c18e58953e 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.20.2 \ No newline at end of file +1.20.3-SNAPSHOT \ No newline at end of file From 21db10869802120c8901315e88ebcd339be2c5ae Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 20 Sep 2020 19:38:05 +0200 Subject: [PATCH 0559/1594] [Java] Fix duplicate dependencies + fail build if new conflicts detected. --- build.gradle | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/build.gradle b/build.gradle index 946291b240..1b4a49ee02 100644 --- a/build.gradle +++ b/build.gradle @@ -124,6 +124,17 @@ allprojects { mavenLocal() mavenCentral() } + + configurations.all { + resolutionStrategy { + failOnVersionConflict() + + // Enforce dependency versions used by SBE + force "org.junit.jupiter:junit-jupiter-api:${junitVersion}", + "org.junit.jupiter:junit-jupiter-params:${junitVersion}", + "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" + } + } } jar.enabled = false From ff7e905c9f9f6a6aef104bd47be6cc2bd0e7ae89 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 20 Sep 2020 19:39:32 +0200 Subject: [PATCH 0560/1594] [Java] Upgrade to Mockito 3.5.11. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1b4a49ee02..4a043e716c 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.36' def hamcrestVersion = '2.2' -def mockitoVersion = '3.5.10' +def mockitoVersion = '3.5.11' def junitVersion = '5.7.0' def jmhVersion = '1.25.2' def agronaVersion = '1.7.2' From c19a6a34deaeba81c640b506ef16d1f33c683dd4 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 26 Sep 2020 14:05:22 +0100 Subject: [PATCH 0561/1594] [Java] Build with Java 15. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 94223aa69d..4ae990b7c8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '11', '14' ] + java: [ '8', '11', '15' ] steps: - name: Checkout code uses: actions/checkout@v2 From b6c91612bb8fc0bab6ed6b37a08e151e1afe50a4 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 27 Sep 2020 10:23:45 +0100 Subject: [PATCH 0562/1594] [Java] Upgrade to Mockito 3.5.13. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4a043e716c..2008055734 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.36' def hamcrestVersion = '2.2' -def mockitoVersion = '3.5.11' +def mockitoVersion = '3.5.13' def junitVersion = '5.7.0' def jmhVersion = '1.25.2' def agronaVersion = '1.7.2' From d8d176aefde11f1591a378dc64ba532f309d3ba2 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 1 Oct 2020 19:55:46 +0200 Subject: [PATCH 0563/1594] [Java] Remove force version since it breaks the update versions plugin. --- build.gradle | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 2008055734..a0e702b374 100644 --- a/build.gradle +++ b/build.gradle @@ -128,11 +128,6 @@ allprojects { configurations.all { resolutionStrategy { failOnVersionConflict() - - // Enforce dependency versions used by SBE - force "org.junit.jupiter:junit-jupiter-api:${junitVersion}", - "org.junit.jupiter:junit-jupiter-params:${junitVersion}", - "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" } } } @@ -219,7 +214,9 @@ project(':sbe-tool') { } testImplementation files('build/classes/java/generated') testImplementation "org.hamcrest:hamcrest:${hamcrestVersion}" - testImplementation "org.mockito:mockito-junit-jupiter:${mockitoVersion}" + testImplementation ("org.mockito:mockito-junit-jupiter:${mockitoVersion}") { + exclude group: 'org.junit.jupiter' + } testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}" testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" From e5532d37533cbe0f103137b014f0bc7a67a1e92a Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 1 Oct 2020 22:28:57 +0200 Subject: [PATCH 0564/1594] [Java] Fix independent compilation of test classes required for the lgtm task. --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index a0e702b374..b4faa2fec0 100644 --- a/build.gradle +++ b/build.gradle @@ -239,6 +239,8 @@ project(':sbe-tool') { classpath += sourceSets.main.runtimeClasspath } + compileTestJava.dependsOn compileGeneratedJava + task generateTestCodecs(dependsOn: 'compileJava', type: JavaExec) { main = 'uk.co.real_logic.sbe.SbeTool' classpath = sourceSets.main.runtimeClasspath From d54cc64a4c9247a32a95cdd330cfd394e7db02d9 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 7 Oct 2020 14:05:14 +0200 Subject: [PATCH 0565/1594] [Java] Replace deprecated `add-path` function with environment files. --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ae990b7c8..d4bdf092ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,7 +116,7 @@ jobs: curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - echo "::add-path::cmake-${CMAKE_VERSION}-Linux-x86_64/bin" + echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH - name: Build run: cmake --version && ./cppbuild/cppbuild @@ -155,7 +155,7 @@ jobs: curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - echo "::add-path::cmake-${CMAKE_VERSION}-Linux-x86_64/bin" + echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH - name: Build run: cmake --version && ./cppbuild/cppbuild @@ -174,7 +174,7 @@ jobs: run: | curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz - echo "::add-path::cmake-${CMAKE_VERSION}-Darwin-x86_64/CMake.app/Contents/bin" + echo "cmake-${CMAKE_VERSION}-Darwin-x86_64/CMake.app/Contents/bin" >> $GITHUB_PATH - name: Build run: cmake --version && ./cppbuild/cppbuild @@ -194,6 +194,6 @@ jobs: $client = new-object System.Net.WebClient $client.DownloadFile("https://github.com/Kitware/CMake/releases/download/v$Env:CMAKE_VERSION/cmake-$Env:CMAKE_VERSION-win64-x64.zip","cmake-$Env:CMAKE_VERSION-win64-x64.zip") 7z x cmake-$Env:CMAKE_VERSION-win64-x64.zip - echo "::add-path::cmake-$Env:CMAKE_VERSION-win64-x64/bin" + echo "cmake-$Env:CMAKE_VERSION-win64-x64/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 - name: Build run: cppbuild/cppbuild.cmd From cd075cade958add938f54565ed43d5cc3df8ac4a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 7 Oct 2020 16:44:53 +0100 Subject: [PATCH 0566/1594] [Java] Upgrade to Shadow 6.1.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b4faa2fec0..5b5d4c5878 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { plugins { id 'java-library' id 'idea' - id 'com.github.johnrengelman.shadow' version '6.0.0' apply false + id 'com.github.johnrengelman.shadow' version '6.1.0' apply false id "com.github.ben-manes.versions" version "0.33.0" } From b5ebcc6649367bb4e7e54004a58c074912ea3c08 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 7 Oct 2020 17:25:28 +0100 Subject: [PATCH 0567/1594] [Java] Upgrade to Agrona 1.8.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 5b5d4c5878..93fba755c2 100644 --- a/build.gradle +++ b/build.gradle @@ -33,8 +33,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.5.13' def junitVersion = '5.7.0' def jmhVersion = '1.25.2' -def agronaVersion = '1.7.2' -def agronaVersionRange = '[1.7,1.8[' // allow any patch release of 1.7.x +def agronaVersion = '1.8.0' +def agronaVersionRange = '[1.8,1.9[' // allow any patch release of 1.8.x def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 90213d5127e41ab2ac1d6fc3dc7273710f5de327 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 7 Oct 2020 23:45:30 +0200 Subject: [PATCH 0568/1594] [Java] Use Ubuntu 20.04 for most Linux builds excepts for CLang build that is using Ubuntu 18.04. --- .github/workflows/ci.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4bdf092ba..18fb722e9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ env: jobs: java-build: name: Java ${{ matrix.java }} - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: @@ -44,7 +44,7 @@ jobs: csharp-build: name: C# ${{ matrix.dotnet }} - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: @@ -87,7 +87,7 @@ jobs: cpp-gcc-build: name: C++ GCC ${{ matrix.version }} - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: @@ -122,7 +122,7 @@ jobs: cpp-clang-build: name: C++ Clang ${{ matrix.version }} - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 strategy: fail-fast: false matrix: @@ -147,12 +147,10 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | + curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-${{ matrix.version }} main" - sudo apt-get update - sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev - curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH From 4f17650cea1171038379fbed861439c5429e2421 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 7 Oct 2020 23:47:22 +0200 Subject: [PATCH 0569/1594] [Java] Fix GCC 6 install on Ubuntu 20.04. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 18fb722e9a..ff7a2ea97a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -112,8 +112,8 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic main universe" sudo apt-get install -y g++-${{ matrix.version }} libsparsehash-dev - curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH From 5268101d316cb6a4f094fdc38d644fe2105bbaac Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 7 Oct 2020 23:58:17 +0200 Subject: [PATCH 0570/1594] [Java] Try Ubuntu 20.04 for Clang build. --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ff7a2ea97a..5c170d5f50 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -122,7 +122,7 @@ jobs: cpp-clang-build: name: C++ Clang ${{ matrix.version }} - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: @@ -148,6 +148,7 @@ jobs: - name: Install compiler run: | curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${{ matrix.version }} main" sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-${{ matrix.version }} main" sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev From dd5269c4a318ac54111e2958ed996e4cd0a58800 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 8 Oct 2020 00:00:13 +0200 Subject: [PATCH 0571/1594] [Java] Add GCC 10 and Clang 10 to the build matrix. --- .github/workflows/ci.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c170d5f50..6f5f79c301 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,7 +91,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '6', '7', '8', '9' ] + version: [ '6', '7', '8', '9', '10' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} @@ -122,11 +122,11 @@ jobs: cpp-clang-build: name: C++ Clang ${{ matrix.version }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-18.04 strategy: fail-fast: false matrix: - version: [ '6.0', '7', '8', '9' ] + version: [ '6.0', '7', '8', '9', '10' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} @@ -148,7 +148,6 @@ jobs: - name: Install compiler run: | curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${{ matrix.version }} main" sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-${{ matrix.version }} main" sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev From c36bd6bf437094588a4bc36493ebc8fe29c35573 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 8 Oct 2020 11:34:48 +0100 Subject: [PATCH 0572/1594] [Java] Upgrade to Checkstyle 8.36.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 93fba755c2..8000e19b87 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ plugins { defaultTasks 'clean', 'build' -def checkstyleVersion = '8.36' +def checkstyleVersion = '8.36.2' def hamcrestVersion = '2.2' def mockitoVersion = '3.5.13' def junitVersion = '5.7.0' From 0a537503dce1384558b2e761d35e2c128c15ddc1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 9 Oct 2020 15:54:38 +0100 Subject: [PATCH 0573/1594] [Java] Upgrade to JMH 1.26. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8000e19b87..9b889a1ea7 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ def checkstyleVersion = '8.36.2' def hamcrestVersion = '2.2' def mockitoVersion = '3.5.13' def junitVersion = '5.7.0' -def jmhVersion = '1.25.2' +def jmhVersion = '1.26' def agronaVersion = '1.8.0' def agronaVersionRange = '[1.8,1.9[' // allow any patch release of 1.8.x From d61377fdea6f2631ba1a6d9604cfcc755c41ed1d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 12 Oct 2020 16:42:36 +0100 Subject: [PATCH 0574/1594] [Java] Reduce scope of fields in codecs. --- .../real_logic/sbe/generation/java/JavaGenerator.java | 10 +++++----- .../real_logic/sbe/ir/generated/FrameCodecDecoder.java | 10 +++++----- .../real_logic/sbe/ir/generated/FrameCodecEncoder.java | 6 +++--- .../real_logic/sbe/ir/generated/TokenCodecDecoder.java | 10 +++++----- .../real_logic/sbe/ir/generated/TokenCodecEncoder.java | 6 +++--- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index e5492620fa..7b23d32cdc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2466,8 +2466,8 @@ private CharSequence generateFlyweightCode( final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); final String actingFields = codecType == CodecType.ENCODER ? "" : - " protected int actingBlockLength;\n" + - " protected int actingVersion;\n"; + " int actingBlockLength;\n" + + " int actingVersion;\n"; return String.format( " public static final %1$s BLOCK_LENGTH = %2$s;\n" + @@ -2477,9 +2477,9 @@ private CharSequence generateFlyweightCode( " public static final java.nio.ByteOrder BYTE_ORDER = java.nio.ByteOrder.%14$s;\n\n" + " private final %9$s parentMessage = this;\n" + " private %11$s buffer;\n" + - " protected int initialOffset;\n" + - " protected int offset;\n" + - " protected int limit;\n" + + " private int initialOffset;\n" + + " private int offset;\n" + + " private int limit;\n" + "%13$s" + "\n" + " public %15$s sbeBlockLength()\n" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 7c998b888f..c79f634052 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -18,11 +18,11 @@ public class FrameCodecDecoder private final FrameCodecDecoder parentMessage = this; private DirectBuffer buffer; - protected int initialOffset; - protected int offset; - protected int limit; - protected int actingBlockLength; - protected int actingVersion; + private int initialOffset; + private int offset; + private int limit; + int actingBlockLength; + int actingVersion; public int sbeBlockLength() { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index 914a4aa4ce..5ba2f5ffdd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -18,9 +18,9 @@ public class FrameCodecEncoder private final FrameCodecEncoder parentMessage = this; private MutableDirectBuffer buffer; - protected int initialOffset; - protected int offset; - protected int limit; + private int initialOffset; + private int offset; + private int limit; public int sbeBlockLength() { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index a18ebca7c6..830a2e8e84 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -18,11 +18,11 @@ public class TokenCodecDecoder private final TokenCodecDecoder parentMessage = this; private DirectBuffer buffer; - protected int initialOffset; - protected int offset; - protected int limit; - protected int actingBlockLength; - protected int actingVersion; + private int initialOffset; + private int offset; + private int limit; + int actingBlockLength; + int actingVersion; public int sbeBlockLength() { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index 33a46e05f9..ac4ae55ddf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -18,9 +18,9 @@ public class TokenCodecEncoder private final TokenCodecEncoder parentMessage = this; private MutableDirectBuffer buffer; - protected int initialOffset; - protected int offset; - protected int limit; + private int initialOffset; + private int offset; + private int limit; public int sbeBlockLength() { From fbed609750206cdf7d0c7e8c2c12e8af2e979962 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 13 Oct 2020 15:22:50 +0100 Subject: [PATCH 0575/1594] [Java] Fix group order annotation generation. --- .../java/uk/co/real_logic/sbe/SbeTool.java | 27 ++--- .../sbe/generation/java/JavaGenerator.java | 101 +++++++++--------- .../sbe/generation/java/JavaUtil.java | 30 +++--- 3 files changed, 77 insertions(+), 81 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index dbf6fafee1..95e914a706 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -17,24 +17,13 @@ import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; -import uk.co.real_logic.sbe.generation.CodeGenerator; -import uk.co.real_logic.sbe.generation.TargetCodeGenerator; -import uk.co.real_logic.sbe.generation.TargetCodeGeneratorLoader; -import uk.co.real_logic.sbe.ir.Ir; -import uk.co.real_logic.sbe.ir.IrDecoder; -import uk.co.real_logic.sbe.ir.IrEncoder; -import uk.co.real_logic.sbe.xml.IrGenerator; -import uk.co.real_logic.sbe.xml.MessageSchema; -import uk.co.real_logic.sbe.xml.ParserOptions; -import uk.co.real_logic.sbe.xml.XmlSchemaParser; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import org.xml.sax.InputSource; +import uk.co.real_logic.sbe.generation.*; +import uk.co.real_logic.sbe.ir.*; +import uk.co.real_logic.sbe.xml.*; + +import java.io.*; +import java.nio.file.*; /** * A tool for running the SBE parser, validator, and code generator. @@ -52,7 +41,7 @@ *
  • sbe.validation.stop.on.error: Should the parser stop on first error encountered? Defaults to false.
  • *
  • sbe.validation.warnings.fatal: Are warnings in parsing considered fatal? Defaults to false.
  • *
  • - * sbe.validation.suppress.output: Should the parser suppress output during validation? Defaults to false. + * sbe.validation.suppress.output: Should the parser suppress output during validation? Defaults to false. *
  • *
  • sbe.generate.stubs: Generate stubs or not. Defaults to true.
  • *
  • sbe.target.language: Target language for code generation, defaults to Java.
  • @@ -64,7 +53,7 @@ *
  • sbe.target.namespace: Namespace for the generated code to override schema package.
  • *
  • sbe.cpp.namespaces.collapse: Namespace for the generated code to override schema package.
  • *
  • - * sbe.java.generate.group-order.annotation: Should the GroupOrder annotation be added to generated stubs. + * sbe.java.generate.group-order.annotation: Should the GroupOrder annotation be added to generated stubs. *
  • *
  • sbe.csharp.generate.namespace.dir: Should a directory be created for the namespace under * the output directory? Defaults to true
  • diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 7b23d32cdc..bf1d13f955 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -203,13 +203,16 @@ private void generateEncoder( { out.append(generateMainHeader(ir.applicableNamespace(), ENCODER, hasVarData)); - generateAnnotations(BASE_INDENT, className, groups, out, 0, this::encoderName); + if (shouldGenerateGroupOrderAnnotation) + { + generateAnnotations(BASE_INDENT, className, groups, out, this::encoderName); + } out.append(generateDeclaration(className, implementsString, msgToken)); out.append(generateEncoderFlyweightCode(className, msgToken)); final StringBuilder sb = new StringBuilder(); generateEncoderFields(sb, className, fields, BASE_INDENT); - generateEncoderGroups(sb, className, groups, BASE_INDENT, false); + generateEncoderGroups(sb, className, null, groups, BASE_INDENT, false); generateEncoderVarData(sb, className, varData, BASE_INDENT); generateEncoderDisplay(sb, decoderName(msgToken.name())); @@ -234,13 +237,16 @@ private void generateDecoder( { out.append(generateMainHeader(ir.applicableNamespace(), DECODER, hasVarData)); - generateAnnotations(BASE_INDENT, className, groups, out, 0, this::decoderName); + if (shouldGenerateGroupOrderAnnotation) + { + generateAnnotations(BASE_INDENT, className, groups, out, this::decoderName); + } out.append(generateDeclaration(className, implementsString, msgToken)); out.append(generateDecoderFlyweightCode(className, msgToken)); final StringBuilder sb = new StringBuilder(); generateDecoderFields(sb, fields, BASE_INDENT); - generateDecoderGroups(sb, className, groups, BASE_INDENT, false); + generateDecoderGroups(sb, className, null, groups, BASE_INDENT, false); generateDecoderVarData(sb, varData, BASE_INDENT); generateDecoderDisplay(sb, msgToken.name(), fields, groups, varData); @@ -253,6 +259,7 @@ private void generateDecoder( private void generateDecoderGroups( final StringBuilder sb, final String outerClassName, + final String outerGroupName, final List tokens, final String indent, final boolean isSubGroup) throws IOException @@ -265,7 +272,7 @@ private void generateDecoderGroups( throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); } - final int groupIndex = i; + final int index = i; final String groupName = decoderName(formatClassName(groupToken.name())); ++i; @@ -282,11 +289,16 @@ private void generateDecoderGroups( i = collectVarData(tokens, i, varData); generateGroupDecoderProperty(sb, groupName, groupToken, indent, isSubGroup); - generateAnnotations(indent + INDENT, groupName, tokens, sb, groupIndex + 1, this::decoderName); - generateGroupDecoderClassHeader(sb, groupName, outerClassName, tokens, groups, groupIndex, indent + INDENT); + generateTypeJavadoc(sb, indent + INDENT, groupToken); + + if (shouldGenerateGroupOrderAnnotation) + { + generateAnnotations(indent + INDENT, groupName, groups, sb, this::decoderName); + } + generateGroupDecoderClassHeader(sb, groupName, outerClassName, tokens, groups, index, indent + INDENT); generateDecoderFields(sb, fields, indent + INDENT); - generateDecoderGroups(sb, outerClassName, groups, indent + INDENT, true); + generateDecoderGroups(sb, outerClassName, groupName, groups, indent + INDENT, true); generateDecoderVarData(sb, varData, indent + INDENT); appendGroupInstanceDecoderDisplay(sb, fields, groups, varData, indent + INDENT); @@ -298,6 +310,7 @@ private void generateDecoderGroups( private void generateEncoderGroups( final StringBuilder sb, final String outerClassName, + final String outerGroupName, final List tokens, final String indent, final boolean isSubGroup) throws IOException @@ -310,7 +323,7 @@ private void generateEncoderGroups( throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); } - final int groupIndex = i; + final int index = i; final String groupName = groupToken.name(); final String groupClassName = encoderName(groupName); @@ -328,11 +341,16 @@ private void generateEncoderGroups( i = collectVarData(tokens, i, varData); generateGroupEncoderProperty(sb, groupName, groupToken, indent, isSubGroup); - generateAnnotations(indent + INDENT, groupClassName, tokens, sb, groupIndex + 1, this::encoderName); - generateGroupEncoderClassHeader(sb, groupName, outerClassName, tokens, groups, groupIndex, indent + INDENT); + generateTypeJavadoc(sb, indent + INDENT, groupToken); + + if (shouldGenerateGroupOrderAnnotation) + { + generateAnnotations(indent + INDENT, groupClassName, groups, sb, this::encoderName); + } + generateGroupEncoderClassHeader(sb, groupName, outerClassName, tokens, groups, index, indent + INDENT); generateEncoderFields(sb, groupClassName, fields, indent + INDENT); - generateEncoderGroups(sb, outerClassName, groups, indent + INDENT, true); + generateEncoderGroups(sb, outerClassName, groupClassName, groups, indent + INDENT, true); generateEncoderVarData(sb, groupClassName, varData, indent + INDENT); sb.append(indent).append(" }\n"); @@ -348,7 +366,6 @@ private void generateGroupDecoderClassHeader( final int index, final String indent) { - final Token groupToken = tokens.get(index); final String className = formatClassName(groupName); final int dimensionHeaderLen = tokens.get(index + 1).encodedLength(); @@ -367,7 +384,6 @@ private void generateGroupDecoderClassHeader( generateGroupDecoderClassDeclaration( sb, - groupToken, groupName, parentMessageClassName, findSubGroupNames(subGroupTokens), @@ -448,12 +464,10 @@ private void generateGroupEncoderClassHeader( final int index, final String ind) { - final Token groupToken = tokens.get(index); final int dimensionHeaderSize = tokens.get(index + 1).encodedLength(); generateGroupEncoderClassDeclaration( sb, - groupToken, groupName, parentMessageClassName, findSubGroupNames(subGroupTokens), @@ -549,7 +563,6 @@ private static String primitiveTypeName(final Token token) private void generateGroupDecoderClassDeclaration( final StringBuilder sb, - final Token groupToken, final String groupName, final String parentMessageClassName, final List subGroupNames, @@ -558,7 +571,6 @@ private void generateGroupDecoderClassDeclaration( { final String className = formatClassName(groupName); - generateTypeJavadoc(sb, indent, groupToken); new Formatter(sb).format("\n" + indent + "public static class %1$s\n" + indent + " implements Iterable<%1$s>, java.util.Iterator<%1$s>\n" + @@ -603,7 +615,6 @@ private void generateGroupDecoderClassDeclaration( private void generateGroupEncoderClassDeclaration( final StringBuilder sb, - final Token groupToken, final String groupName, final String parentMessageClassName, final List subGroupNames, @@ -612,7 +623,6 @@ private void generateGroupEncoderClassDeclaration( { final String className = encoderName(groupName); - generateTypeJavadoc(sb, indent, groupToken); new Formatter(sb).format("\n" + indent + "public static class %1$s\n" + indent + "{\n" + @@ -1596,47 +1606,40 @@ private void generateAnnotations( final String className, final List tokens, final Appendable out, - final int index, final Function nameMapping) throws IOException { - if (shouldGenerateGroupOrderAnnotation) - { - final List groupClassNames = new ArrayList<>(); - int level = 0; - int i = index; + final List groupClassNames = new ArrayList<>(); + int level = 0; - for (int size = tokens.size(); i < size; i++) + for (final Token token : tokens) + { + if (token.signal() == Signal.BEGIN_GROUP) { - if (tokens.get(index).signal() == Signal.BEGIN_GROUP) + if (1 == ++level) { - if (++level == 1) - { - final Token groupToken = tokens.get(index); - final String groupName = groupToken.name(); - groupClassNames.add(formatClassName(nameMapping.apply(groupName))); - } - } - else if (tokens.get(index).signal() == Signal.END_GROUP && --level < 0) - { - break; + groupClassNames.add(formatClassName(nameMapping.apply(token.name()))); } } + else if (token.signal() == Signal.END_GROUP) + { + --level; + } + } - if (!groupClassNames.isEmpty()) + if (!groupClassNames.isEmpty()) + { + out.append(indent).append("@uk.co.real_logic.sbe.codec.java.GroupOrder({\n"); + int i = 0; + for (final String name : groupClassNames) { - out.append(indent).append("@uk.co.real_logic.sbe.codec.java.GroupOrder({"); - i = 0; - for (final String name : groupClassNames) + out.append(indent).append(INDENT).append(className).append('.').append(name).append(".class"); + if (++i < groupClassNames.size()) { - out.append(className).append('.').append(name).append(".class"); - if (++i < groupClassNames.size()) - { - out.append(", "); - } + out.append(",\n"); } - - out.append("})\n"); } + + out.append("})"); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 9a8efec306..b407cb9aca 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -15,6 +15,7 @@ */ package uk.co.real_logic.sbe.generation.java; +import org.agrona.Strings; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.SbeTool; import uk.co.real_logic.sbe.generation.Generators; @@ -275,12 +276,13 @@ public static void generateTypeJavadoc( final StringBuilder sb, final String indent, final Token typeToken) { final String description = typeToken.description(); - if (null == description || description.isEmpty()) + if (Strings.isEmpty(description)) { return; } - sb.append(indent).append("/**\n") + sb.append('\n') + .append(indent).append("/**\n") .append(indent).append(" * ").append(description).append('\n') .append(indent).append(" */\n"); } @@ -298,7 +300,7 @@ public static void generateOptionDecodeJavadoc( throws IOException { final String description = optionToken.description(); - if (null == description || description.isEmpty()) + if (Strings.isEmpty(description)) { return; } @@ -306,7 +308,7 @@ public static void generateOptionDecodeJavadoc( out.append(indent).append("/**\n") .append(indent).append(" * ").append(description).append('\n') .append(indent).append(" *\n") - .append(indent).append(" * @return true if ").append(optionToken.name()).append(" is set or false if not\n") + .append(indent).append(" * @return true if ").append(optionToken.name()).append(" set or false if not.\n") .append(indent).append(" */\n"); } @@ -323,7 +325,7 @@ public static void generateOptionEncodeJavadoc( throws IOException { final String description = optionToken.description(); - if (null == description || description.isEmpty()) + if (Strings.isEmpty(description)) { return; } @@ -348,16 +350,17 @@ public static void generateFlyweightPropertyJavadoc( final StringBuilder sb, final String indent, final Token propertyToken, final String typeName) { final String description = propertyToken.description(); - if (null == description || description.isEmpty()) + if (Strings.isEmpty(description)) { return; } - sb.append(indent).append("/**\n") + sb.append('\n') + .append(indent).append("/**\n") .append(indent).append(" * ").append(description).append('\n') .append(indent).append(" *\n") .append(indent).append(" * @return ").append(typeName).append(" : ").append(description).append("\n") - .append(indent).append(" */\n"); + .append(indent).append(" */"); } /** @@ -372,16 +375,17 @@ public static void generateGroupEncodePropertyJavadoc( final StringBuilder sb, final String indent, final Token propertyToken, final String typeName) { final String description = propertyToken.description(); - if (null == description || description.isEmpty()) + if (Strings.isEmpty(description)) { return; } - sb.append(indent).append("/**\n") + sb.append('\n') + .append(indent).append("/**\n") .append(indent).append(" * ").append(description).append("\n") .append(indent).append(" *\n") - .append(indent).append(" * @param count of times the group will be encoded\n") - .append(indent).append(" * @return ").append(typeName).append(" : encoder for the group\n") - .append(indent).append(" */\n"); + .append(indent).append(" * @param count of times the group will be encoded.\n") + .append(indent).append(" * @return ").append(typeName).append(" : encoder for the group.\n") + .append(indent).append(" */"); } } From d23e116a0183003d2c0b9fe8ac354ab143fe5127 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 13 Oct 2020 17:16:50 +0200 Subject: [PATCH 0576/1594] [CI] Add Clang 11 to the build matrix. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f5f79c301..010fe8619c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -126,7 +126,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '6.0', '7', '8', '9', '10' ] + version: [ '6.0', '7', '8', '9', '10', '11' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} From 03bd0533aa0f327fed9556582e98a4ca7415cf6a Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 13 Oct 2020 17:55:58 +0100 Subject: [PATCH 0577/1594] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2350f565aa..0f6a7b6afe 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.20.2 +    1.20.3 ``` From 2c2aa16ac276dddf473799bec2b30d4978fc70e9 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 13 Oct 2020 10:17:23 -0700 Subject: [PATCH 0578/1594] 1.20.3 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index c18e58953e..3cb1511de6 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.20.3-SNAPSHOT \ No newline at end of file +1.20.3 \ No newline at end of file From 869cfb14a9bc1e83deae3e393d55dd792de681d8 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 13 Oct 2020 10:18:37 -0700 Subject: [PATCH 0579/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 3cb1511de6..6917d3d4df 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.20.3 \ No newline at end of file +1.20.4-SNAPSHOT \ No newline at end of file From c4808a9b77214a1139ff3b11aca1f6961caec207 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 14 Oct 2020 17:56:00 +0200 Subject: [PATCH 0580/1594] [Java] Do not disable individual test reports. --- build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.gradle b/build.gradle index 9b889a1ea7..fdb710e086 100644 --- a/build.gradle +++ b/build.gradle @@ -194,8 +194,6 @@ subprojects { showStandardStreams = true exceptionFormat = 'full' } - - reports.html.enabled = false // Disable individual test reports } } From 307fbe9183568ad61632146049babedd34155332 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 20 Oct 2020 18:48:32 +0100 Subject: [PATCH 0581/1594] [Java] Upgrade to Mockito 3.5.15. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9b889a1ea7..bf3e00c6ae 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ defaultTasks 'clean', 'build' def checkstyleVersion = '8.36.2' def hamcrestVersion = '2.2' -def mockitoVersion = '3.5.13' +def mockitoVersion = '3.5.15' def junitVersion = '5.7.0' def jmhVersion = '1.26' def agronaVersion = '1.8.0' From dd7f08435b71e5c9417f8152c1c5f679815ab226 Mon Sep 17 00:00:00 2001 From: AndreyNudko Date: Fri, 23 Oct 2020 14:43:36 +0100 Subject: [PATCH 0582/1594] [Java] Generate bulk put/get/wrap methods for fixed-length data (uint8 array) (#819) * [Java] Generate bulk put/get/wrap methods for fixed-length data (uint8 array) * [Java] Separated tests for encoding/decoding fixed-length data and use different schema --- .../sbe/generation/java/JavaGenerator.java | 109 +++++++++- .../java/FixedSizeDataGeneratorTest.java | 200 ++++++++++++++++++ .../generation/java/JavaGeneratorTest.java | 1 + .../sbe/generation/java/ReflectionUtil.java | 57 +++++ .../generation/java/SchemaExtensionTest.java | 130 +++++++++++- .../src/test/resources/extension-schema.xml | 5 +- 6 files changed, 494 insertions(+), 8 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index bf1d13f955..ef3e38d5a2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -981,7 +981,7 @@ private void generateVarDataWrapDecoder( indent + " }\n", propertyName, readOnlyBuffer, - generateVarWrapFieldNotPresentCondition(token.version(), indent), + generateWrapFieldNotPresentCondition(token.version(), indent), sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", generateGet(lengthType, "limit", byteOrderStr)); @@ -1860,7 +1860,7 @@ private CharSequence generatePrimitivePropertyEncode( generatePut(encoding.primitiveType(), "offset + " + offset, "value", byteOrderStr)); } - private CharSequence generateVarWrapFieldNotPresentCondition(final int sinceVersion, final String indent) + private CharSequence generateWrapFieldNotPresentCondition(final int sinceVersion, final String indent) { if (0 == sinceVersion) { @@ -1871,6 +1871,7 @@ private CharSequence generateVarWrapFieldNotPresentCondition(final int sinceVers indent + " if (parentMessage.actingVersion < " + sinceVersion + ")\n" + indent + " {\n" + indent + " wrapBuffer.wrap(buffer, offset, 0);\n" + + indent + " return;\n" + indent + " }\n\n"; } @@ -2060,6 +2061,51 @@ private CharSequence generatePrimitiveArrayPropertyDecode( offset); } } + else if (encoding.primitiveType() == PrimitiveType.UINT8) + { + new Formatter(sb).format("\n" + + indent + " public int get%s(final byte[] dst, final int dstOffset, final int length)\n" + + indent + " {\n" + + "%s" + + indent + " final int bytesCopied = Math.min(length, %d);\n" + + indent + " buffer.getBytes(offset + %d, dst, dstOffset, bytesCopied);\n" + + indent + " return bytesCopied;\n" + + indent + " }\n", + Generators.toUpperFirstChar(propertyName), + generateArrayFieldNotPresentCondition(propertyToken.version(), indent), + fieldLength, + offset + ); + + new Formatter(sb).format("\n" + + indent + " public int get%s(final %s dst, final int dstOffset, final int length)\n" + + indent + " {\n" + + "%s" + + indent + " final int bytesCopied = Math.min(length, %d);\n" + + indent + " buffer.getBytes(offset + %d, dst, dstOffset, bytesCopied);\n" + + indent + " return bytesCopied;\n" + + indent + " }\n", + Generators.toUpperFirstChar(propertyName), + fqMutableBuffer, + generateArrayFieldNotPresentCondition(propertyToken.version(), indent), + fieldLength, + offset + ); + + new Formatter(sb).format("\n" + + indent + " public void wrap%s(final %s wrapBuffer)\n" + + indent + " {\n" + + indent + " final int length = %d;\n" + + "%s" + + indent + " wrapBuffer.wrap(buffer, offset + %d, length);\n" + + indent + " }\n", + Generators.toUpperFirstChar(propertyName), + readOnlyBuffer, + fieldLength, + generateWrapFieldNotPresentCondition(propertyToken.version(), indent), + offset + ); + } return sb; } @@ -2150,6 +2196,11 @@ private CharSequence generatePrimitiveArrayPropertyEncode( generateCharArrayEncodeMethods( containingClassName, propertyName, indent, encoding, offset, arrayLength, sb); } + else if (primitiveType == PrimitiveType.UINT8) + { + generateByteArrayEncodeMethods( + containingClassName, propertyName, indent, offset, arrayLength, sb); + } return sb; } @@ -2261,6 +2312,60 @@ private void generateCharArrayEncodeMethods( } } + private void generateByteArrayEncodeMethods( + final String containingClassName, + final String propertyName, + final String indent, + final int offset, + final int fieldLength, + final StringBuilder sb) + { + new Formatter(sb).format("\n" + + indent + " public %s put%s(final byte[] src, final int srcOffset, final int length)\n" + + indent + " {\n" + + indent + " if (length > %d)\n" + + indent + " {\n" + + indent + " throw new IllegalStateException(" + + "\"length > maxValue for type: \" + length);" + + indent + " }\n\n" + + indent + " buffer.putBytes(offset + %d, src, srcOffset, length);\n" + + indent + " for (int i = length; i < %d; i++)\n" + + indent + " {\n" + + indent + " buffer.putByte(offset + %d + i, (byte)0);\n" + + indent + " }\n" + + indent + " return this;\n" + + indent + " }\n", + formatClassName(containingClassName), + Generators.toUpperFirstChar(propertyName), + fieldLength, + offset, + fieldLength, + offset); + + new Formatter(sb).format("\n" + + indent + " public %s put%s(final %s src, final int srcOffset, final int length)\n" + + indent + " {\n" + + indent + " if (length > %d)\n" + + indent + " {\n" + + indent + " throw new IllegalStateException(" + + "\"length > maxValue for type: \" + length);" + + indent + " }\n\n" + + indent + " buffer.putBytes(offset + %d, src, srcOffset, length);\n" + + indent + " for (int i = length; i < %d; i++)\n" + + indent + " {\n" + + indent + " buffer.putByte(offset + %d + i, (byte)0);\n" + + indent + " }\n" + + indent + " return this;\n" + + indent + " }\n", + formatClassName(containingClassName), + Generators.toUpperFirstChar(propertyName), + fqReadOnlyBuffer, + fieldLength, + offset, + fieldLength, + offset); + } + private static int sizeOfPrimitive(final Encoding encoding) { return encoding.primitiveType().size(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java new file mode 100644 index 0000000000..3a052473b0 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java @@ -0,0 +1,200 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.concurrent.UnsafeBuffer; +import org.agrona.generation.CompilerUtil; +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.nio.charset.StandardCharsets; +import java.util.Map; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.*; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +public class FixedSizeDataGeneratorTest +{ + private static final Class BUFFER_CLASS = MutableDirectBuffer.class; + private static final String BUFFER_NAME = BUFFER_CLASS.getName(); + private static final Class READ_ONLY_BUFFER_CLASS = DirectBuffer.class; + private static final String READ_ONLY_BUFFER_NAME = READ_ONLY_BUFFER_CLASS.getName(); + + private final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + + private Ir ir; + + @BeforeEach + public void setUp() throws Exception + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(Tests.getLocalResource("extension-schema.xml"), options); + final IrGenerator irg = new IrGenerator(); + ir = irg.generate(schema); + + outputManager.clear(); + outputManager.setPackageName(ir.applicableNamespace()); + + generator().generate(); + } + + @Test + public void shouldGeneratePutAndGetByteArrayForFixedLengthBlob() throws Exception + { + final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); + + final Object encoder = getTestMessage2Encoder(buffer); + final Object decoder = getTestMessage2Decoder(buffer, encoder); + + final byte[] encodedData = " **DATA** ".getBytes(StandardCharsets.US_ASCII); + byte[] decodedData; + int decodedDataLength; + + // Every byte written, every byte read + putByteArray(encoder, "putTag6", encodedData, 2, 8); + decodedData = " ".getBytes(StandardCharsets.US_ASCII); + decodedDataLength = getByteArray(decoder, "getTag6", decodedData, 1, 8); + assertThat(decodedDataLength, is(8)); + assertThat(new String(decodedData, StandardCharsets.US_ASCII), is(" **DATA** ")); + + // Every byte written, less bytes read + putByteArray(encoder, "putTag6", encodedData, 2, 8); + decodedData = " ".getBytes(StandardCharsets.US_ASCII); + decodedDataLength = getByteArray(decoder, "getTag6", decodedData, 1, 6); + assertThat(decodedDataLength, is(6)); + assertThat(new String(decodedData, StandardCharsets.US_ASCII), is(" **DATA ")); + + // Less bytes written (padding), every byte read + putByteArray(encoder, "putTag6", encodedData, 2, 6); + decodedData = " ".getBytes(StandardCharsets.US_ASCII); + decodedDataLength = getByteArray(decoder, "getTag6", decodedData, 1, 8); + assertThat(decodedDataLength, is(8)); + assertThat(new String(decodedData, StandardCharsets.US_ASCII), is(" **DATA\u0000\u0000 ")); + } + + @Test + public void shouldGeneratePutAndGetDirectBufferForFixedLengthBlob() throws Exception + { + final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); + + final Object encoder = getTestMessage2Encoder(buffer); + final Object decoder = getTestMessage2Decoder(buffer, encoder); + + final UnsafeBuffer encodedData = new UnsafeBuffer(" **DATA** ".getBytes(StandardCharsets.US_ASCII)); + UnsafeBuffer decodedData; + int decodedDataLength; + + // Every byte written, every byte read + putDirectBuffer(encoder, "putTag6", encodedData, 2, 8); + decodedData = new UnsafeBuffer(" ".getBytes(StandardCharsets.US_ASCII)); + decodedDataLength = getDirectBuffer(decoder, "getTag6", decodedData, 1, 8); + assertThat(decodedDataLength, is(8)); + assertThat(decodedData.getStringWithoutLengthAscii(0, 12), is(" **DATA** ")); + + // Every byte written, less bytes read + putDirectBuffer(encoder, "putTag6", encodedData, 2, 8); + decodedData = new UnsafeBuffer(" ".getBytes(StandardCharsets.US_ASCII)); + decodedDataLength = getDirectBuffer(decoder, "getTag6", decodedData, 1, 6); + assertThat(decodedDataLength, is(6)); + assertThat(decodedData.getStringWithoutLengthAscii(0, 12), is(" **DATA ")); + + // Less bytes written (padding), every byte read + putDirectBuffer(encoder, "putTag6", encodedData, 2, 6); + decodedData = new UnsafeBuffer(" ".getBytes(StandardCharsets.US_ASCII)); + decodedDataLength = getDirectBuffer(decoder, "getTag6", decodedData, 1, 8); + assertThat(decodedDataLength, is(8)); + assertThat(decodedData.getStringWithoutLengthAscii(0, 12), is(" **DATA\u0000\u0000 ")); + } + + @Test + public void shouldGenerateWrapForFixedLengthBlob() throws Exception + { + final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); + + final Object encoder = getTestMessage2Encoder(buffer); + final Object decoder = getTestMessage2Decoder(buffer, encoder); + + final UnsafeBuffer encodedData = new UnsafeBuffer(" **DATA** ".getBytes(StandardCharsets.US_ASCII)); + putDirectBuffer(encoder, "putTag6", encodedData, 2, 8); + + final UnsafeBuffer decodedData = new UnsafeBuffer(); + wrapDirectBuffer(decoder, "wrapTag6", decodedData); + assertThat(decodedData.getStringWithoutLengthAscii(0, decodedData.capacity()), is("**DATA**")); + } + + private JavaGenerator generator() + { + return new JavaGenerator(ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager); + } + + private Class compile(final String className) throws Exception + { + final String fqClassName = ir.applicableNamespace() + "." + className; + final Map sources = outputManager.getSources(); + final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); + if (aClass == null) + { + System.out.println(sources); + } + + return aClass; + } + + private Object getTestMessage2Encoder(final UnsafeBuffer buffer) throws Exception + { + final Object encoder = compile("TestMessage2Encoder").getConstructor().newInstance(); + return wrap(0, encoder, buffer, BUFFER_CLASS); + } + + private Object getTestMessage2Decoder(final UnsafeBuffer buffer, final Object encoder) throws Exception + { + final Object decoder = compile("TestMessage2Decoder").getConstructor().newInstance(); + return wrap(buffer, decoder, getSbeBlockLength(encoder), getSbeSchemaVersion(encoder)); + } + + private static Object wrap( + final UnsafeBuffer buffer, final Object decoder, final int blockLength, final int version) throws Exception + { + decoder + .getClass() + .getMethod("wrap", READ_ONLY_BUFFER_CLASS, int.class, int.class, int.class) + .invoke(decoder, buffer, 0, blockLength, version); + + return decoder; + } + + private static Object wrap( + final int bufferOffset, final Object flyweight, final MutableDirectBuffer buffer, final Class bufferClass) + throws Exception + { + flyweight + .getClass() + .getDeclaredMethod("wrap", bufferClass, int.class) + .invoke(flyweight, buffer, bufferOffset); + return flyweight; + } + +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 39b53cef62..b1b790732c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -442,6 +442,7 @@ public void shouldGeneratePutCharSequence() throws Exception assertThat(get(decoder, "vehicleCode"), is("R11R12")); } + private Class getModelClass(final Object encoder) throws ClassNotFoundException { final String className = "Model"; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java index 65428b740e..65bb022fee 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java @@ -15,6 +15,8 @@ */ package uk.co.real_logic.sbe.generation.java; +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; import uk.co.real_logic.sbe.generation.Generators; public final class ReflectionUtil @@ -110,6 +112,61 @@ static void set( object.getClass().getMethod(name, type).invoke(object, value); } + static void putByteArray( + final Object encoder, + final String name, + final byte[] value, + final int offset, + final int length) throws Exception + { + encoder.getClass().getDeclaredMethod(name, byte[].class, int.class, int.class) + .invoke(encoder, value, offset, length); + } + + static int getByteArray( + final Object decoder, + final String name, + final byte[] dst, + final int dstOffset, + final int length) throws Exception + { + return (Integer)decoder.getClass().getDeclaredMethod(name, byte[].class, int.class, int.class) + .invoke(decoder, dst, dstOffset, length); + } + + static void putDirectBuffer( + final Object encoder, + final String name, + final DirectBuffer value, + final int offset, + final int length) throws Exception + { + encoder.getClass().getDeclaredMethod(name, DirectBuffer.class, int.class, int.class) + .invoke(encoder, value, offset, length); + } + + static int getDirectBuffer( + final Object decoder, + final String name, + final MutableDirectBuffer dst, + final int dstOffset, + final int length) throws Exception + { + return (Integer)decoder.getClass().getDeclaredMethod(name, MutableDirectBuffer.class, int.class, int.class) + .invoke(decoder, dst, dstOffset, length); + } + + static void wrapDirectBuffer( + final Object decoder, + final String name, + final DirectBuffer dst) throws Exception + { + decoder + .getClass() + .getDeclaredMethod(name, DirectBuffer.class) + .invoke(decoder, dst); + } + static Object getByte(final Class clazz, final byte value) throws Exception { return clazz.getDeclaredMethod("get", byte.class).invoke(null, value); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index 335cab9b7c..9d843fb2a1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -28,13 +28,14 @@ import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.*; -import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.get; -import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.set; +import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class SchemaExtensionTest @@ -184,6 +185,7 @@ public void testMessage1() throws Exception } } + @SuppressWarnings("MethodLength") @Test public void testMessage2() throws Exception { @@ -204,24 +206,45 @@ public void testMessage2() throws Exception final Object setEncoder = encoder.getClass().getMethod("tag5").invoke(encoder); set(setEncoder, "firstChoice", boolean.class, false); set(setEncoder, "secondChoice", boolean.class, true); + + final byte[] data = " **DATA** ".getBytes(StandardCharsets.US_ASCII); + putByteArray(encoder, "putTag6", data, 2, 8); } { // Decode version 0 + final byte[] data = new byte[12]; + Arrays.fill(data, (byte)' '); + final UnsafeBuffer dataBuffer = new UnsafeBuffer(new byte[12]); + dataBuffer.setMemory(0, 12, (byte)' '); + final Object decoderVersion0 = getMessage2Decoder(buffer, 4, 0); assertEquals(100, get(decoderVersion0, "tag1")); assertEquals(Integer.MIN_VALUE, get(decoderVersion0, "tag2")); assertNull(get(decoderVersion0, "tag3")); assertThat(get(decoderVersion0, "tag4").toString(), is("NULL_VAL")); assertNull(get(decoderVersion0, "tag5")); + // tag6 (fixed-size data) + assertEquals(0, getByteArray(decoderVersion0, "getTag6", data, 1, 8)); + assertEquals(" ", new String(data, StandardCharsets.US_ASCII)); + assertEquals(0, getDirectBuffer(decoderVersion0, "getTag6", dataBuffer, 3, 8)); + assertEquals(" ", dataBuffer.getStringWithoutLengthAscii(0, 12)); + wrapDirectBuffer(decoderVersion0, "wrapTag6", dataBuffer); + assertEquals("", dataBuffer.getStringWithoutLengthAscii(0, dataBuffer.capacity())); assertEquals(0, decoderVersion0.getClass().getMethod("tag1SinceVersion").invoke(null)); assertEquals(2, decoderVersion0.getClass().getMethod("tag2SinceVersion").invoke(null)); assertEquals(1, decoderVersion0.getClass().getMethod("tag3SinceVersion").invoke(null)); assertEquals(4, decoderVersion0.getClass().getMethod("tag4SinceVersion").invoke(null)); assertEquals(3, decoderVersion0.getClass().getMethod("tag5SinceVersion").invoke(null)); + assertEquals(6, decoderVersion0.getClass().getMethod("tag6SinceVersion").invoke(null)); } { // Decode version 1 + final byte[] data = new byte[12]; + Arrays.fill(data, (byte)' '); + final UnsafeBuffer dataBuffer = new UnsafeBuffer(new byte[12]); + dataBuffer.setMemory(0, 12, (byte)' '); + final Object decoderVersion1 = getMessage2Decoder(buffer, 8, 1); assertEquals(100, get(decoderVersion1, "tag1")); assertEquals(Integer.MIN_VALUE, get(decoderVersion1, "tag2")); @@ -230,10 +253,22 @@ public void testMessage2() throws Exception assertEquals(300, get(compositeDecoder2, "value")); assertThat(get(decoderVersion1, "tag4").toString(), is("NULL_VAL")); assertNull(get(decoderVersion1, "tag5")); + // tag6 (fixed-size data) + assertEquals(0, getByteArray(decoderVersion1, "getTag6", data, 1, 8)); + assertEquals(" ", new String(data, StandardCharsets.US_ASCII)); + assertEquals(0, getDirectBuffer(decoderVersion1, "getTag6", dataBuffer, 3, 8)); + assertEquals(" ", dataBuffer.getStringWithoutLengthAscii(0, 12)); + wrapDirectBuffer(decoderVersion1, "wrapTag6", dataBuffer); + assertEquals("", dataBuffer.getStringWithoutLengthAscii(0, dataBuffer.capacity())); } { // Decode version 2 - final Object decoderVersion2 = getMessage2Decoder(buffer, 8, 2); + final byte[] data = new byte[12]; + Arrays.fill(data, (byte)' '); + final UnsafeBuffer dataBuffer = new UnsafeBuffer(new byte[12]); + dataBuffer.setMemory(0, 12, (byte)' '); + + final Object decoderVersion2 = getMessage2Decoder(buffer, 12, 2); assertEquals(100, get(decoderVersion2, "tag1")); assertEquals(200, get(decoderVersion2, "tag2")); final Object compositeDecoder2 = get(decoderVersion2, "tag3"); @@ -241,10 +276,22 @@ public void testMessage2() throws Exception assertEquals(300, get(compositeDecoder2, "value")); assertThat(get(decoderVersion2, "tag4").toString(), is("NULL_VAL")); assertNull(get(decoderVersion2, "tag5")); + // tag6 (fixed-size data) + assertEquals(0, getByteArray(decoderVersion2, "getTag6", data, 1, 8)); + assertEquals(" ", new String(data, StandardCharsets.US_ASCII)); + assertEquals(0, getDirectBuffer(decoderVersion2, "getTag6", dataBuffer, 3, 8)); + assertEquals(" ", dataBuffer.getStringWithoutLengthAscii(0, 12)); + wrapDirectBuffer(decoderVersion2, "wrapTag6", dataBuffer); + assertEquals("", dataBuffer.getStringWithoutLengthAscii(0, dataBuffer.capacity())); } { // Decode version 3 - final Object decoderVersion3 = getMessage2Decoder(buffer, 12, 3); + final byte[] data = new byte[12]; + Arrays.fill(data, (byte)' '); + final UnsafeBuffer dataBuffer = new UnsafeBuffer(new byte[12]); + dataBuffer.setMemory(0, 12, (byte)' '); + + final Object decoderVersion3 = getMessage2Decoder(buffer, 13, 3); assertEquals(100, get(decoderVersion3, "tag1")); assertEquals(200, get(decoderVersion3, "tag2")); final Object compositeDecoder3 = get(decoderVersion3, "tag3"); @@ -255,10 +302,22 @@ public void testMessage2() throws Exception assertNotNull(setDecoder); assertEquals(false, get(setDecoder, "firstChoice")); assertEquals(true, get(setDecoder, "secondChoice")); + // tag6 (fixed-size data) + assertEquals(0, getByteArray(decoderVersion3, "getTag6", data, 1, 8)); + assertEquals(" ", new String(data, StandardCharsets.US_ASCII)); + assertEquals(0, getDirectBuffer(decoderVersion3, "getTag6", dataBuffer, 3, 8)); + assertEquals(" ", dataBuffer.getStringWithoutLengthAscii(0, 12)); + wrapDirectBuffer(decoderVersion3, "wrapTag6", dataBuffer); + assertEquals("", dataBuffer.getStringWithoutLengthAscii(0, dataBuffer.capacity())); } { // Decode version 4 - final Object decoderVersion4 = getMessage2Decoder(buffer, 12, 4); + final byte[] data = new byte[12]; + Arrays.fill(data, (byte)' '); + final UnsafeBuffer dataBuffer = new UnsafeBuffer(new byte[12]); + dataBuffer.setMemory(0, 12, (byte)' '); + + final Object decoderVersion4 = getMessage2Decoder(buffer, 14, 4); assertEquals(100, get(decoderVersion4, "tag1")); assertEquals(200, get(decoderVersion4, "tag2")); final Object compositeDecoder4 = get(decoderVersion4, "tag3"); @@ -270,6 +329,67 @@ public void testMessage2() throws Exception assertNotNull(setDecoder); assertEquals(false, get(setDecoder, "firstChoice")); assertEquals(true, get(setDecoder, "secondChoice")); + // tag6 (fixed-size data) + assertEquals(0, getByteArray(decoderVersion4, "getTag6", data, 1, 8)); + assertEquals(" ", new String(data, StandardCharsets.US_ASCII)); + assertEquals(0, getDirectBuffer(decoderVersion4, "getTag6", dataBuffer, 3, 8)); + assertEquals(" ", dataBuffer.getStringWithoutLengthAscii(0, 12)); + wrapDirectBuffer(decoderVersion4, "wrapTag6", dataBuffer); + assertEquals("", dataBuffer.getStringWithoutLengthAscii(0, dataBuffer.capacity())); + } + + { // Decode version 5 + final byte[] data = new byte[12]; + Arrays.fill(data, (byte)' '); + final UnsafeBuffer dataBuffer = new UnsafeBuffer(new byte[12]); + dataBuffer.setMemory(0, 12, (byte)' '); + + final Object decoderVersion5 = getMessage2Decoder(buffer, 14, 5); + assertEquals(100, get(decoderVersion5, "tag1")); + assertEquals(200, get(decoderVersion5, "tag2")); + final Object compositeDecoder4 = get(decoderVersion5, "tag3"); + assertNotNull(compositeDecoder4); + assertEquals(300, get(compositeDecoder4, "value")); + final Object enumConstant = getAEnumConstant(decoderVersion5, "AEnum", 1); + assertEquals(enumConstant, get(decoderVersion5, "tag4")); + final Object setDecoder = get(decoderVersion5, "tag5"); + assertNotNull(setDecoder); + assertEquals(false, get(setDecoder, "firstChoice")); + assertEquals(true, get(setDecoder, "secondChoice")); + // tag6 (fixed-size data) + assertEquals(0, getByteArray(decoderVersion5, "getTag6", data, 1, 8)); + assertEquals(" ", new String(data, StandardCharsets.US_ASCII)); + assertEquals(0, getDirectBuffer(decoderVersion5, "getTag6", dataBuffer, 3, 8)); + assertEquals(" ", dataBuffer.getStringWithoutLengthAscii(0, 12)); + wrapDirectBuffer(decoderVersion5, "wrapTag6", dataBuffer); + assertEquals("", dataBuffer.getStringWithoutLengthAscii(0, dataBuffer.capacity())); + } + + { // Decode version 6 + final byte[] data = new byte[12]; + Arrays.fill(data, (byte)' '); + final UnsafeBuffer dataBuffer = new UnsafeBuffer(new byte[12]); + dataBuffer.setMemory(0, 12, (byte)' '); + + final Object decoderVersion6 = getMessage2Decoder(buffer, 22, 6); + assertEquals(100, get(decoderVersion6, "tag1")); + assertEquals(200, get(decoderVersion6, "tag2")); + final Object compositeDecoder4 = get(decoderVersion6, "tag3"); + assertNotNull(compositeDecoder4); + assertEquals(300, get(compositeDecoder4, "value")); + final Object enumConstant = getAEnumConstant(decoderVersion6, "AEnum", 1); + assertEquals(enumConstant, get(decoderVersion6, "tag4")); + final Object setDecoder = get(decoderVersion6, "tag5"); + assertNotNull(setDecoder); + assertEquals(false, get(setDecoder, "firstChoice")); + assertEquals(true, get(setDecoder, "secondChoice")); + // tag6 (fixed-size data) + assertEquals(8, getByteArray(decoderVersion6, "getTag6", data, 1, 8)); + assertEquals(" **DATA** ", new String(data, StandardCharsets.US_ASCII)); + assertEquals(8, getDirectBuffer(decoderVersion6, "getTag6", dataBuffer, 3, 8)); + assertEquals(" **DATA** ", dataBuffer.getStringWithoutLengthAscii(0, 12)); + wrapDirectBuffer(decoderVersion6, "wrapTag6", dataBuffer); + assertEquals("**DATA**", dataBuffer.getStringWithoutLengthAscii(0, dataBuffer.capacity())); } } diff --git a/sbe-tool/src/test/resources/extension-schema.xml b/sbe-tool/src/test/resources/extension-schema.xml index c50e7d8a6d..5dc79e35fa 100644 --- a/sbe-tool/src/test/resources/extension-schema.xml +++ b/sbe-tool/src/test/resources/extension-schema.xml @@ -2,7 +2,7 @@ @@ -31,6 +31,7 @@ 0 1 + @@ -54,5 +56,6 @@ + From f1f5ae476c73637274810aa87062e137423bc459 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 23 Oct 2020 15:01:46 +0100 Subject: [PATCH 0583/1594] [Java] Tidy up after merge of PR #819. --- .../sbe/generation/java/JavaGenerator.java | 9 +++------ .../generation/java/FixedSizeDataGeneratorTest.java | 12 +++++------- .../sbe/generation/java/ReflectionUtil.java | 11 ++++------- .../sbe/generation/java/SchemaExtensionTest.java | 10 ++++------ 4 files changed, 16 insertions(+), 26 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index ef3e38d5a2..f01b8e01fd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2074,8 +2074,7 @@ else if (encoding.primitiveType() == PrimitiveType.UINT8) Generators.toUpperFirstChar(propertyName), generateArrayFieldNotPresentCondition(propertyToken.version(), indent), fieldLength, - offset - ); + offset); new Formatter(sb).format("\n" + indent + " public int get%s(final %s dst, final int dstOffset, final int length)\n" + @@ -2089,8 +2088,7 @@ else if (encoding.primitiveType() == PrimitiveType.UINT8) fqMutableBuffer, generateArrayFieldNotPresentCondition(propertyToken.version(), indent), fieldLength, - offset - ); + offset); new Formatter(sb).format("\n" + indent + " public void wrap%s(final %s wrapBuffer)\n" + @@ -2103,8 +2101,7 @@ else if (encoding.primitiveType() == PrimitiveType.UINT8) readOnlyBuffer, fieldLength, generateWrapFieldNotPresentCondition(propertyToken.version(), indent), - offset - ); + offset); } return sb; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java index 3a052473b0..b890f24bc5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java @@ -166,7 +166,7 @@ private Class compile(final String className) throws Exception private Object getTestMessage2Encoder(final UnsafeBuffer buffer) throws Exception { final Object encoder = compile("TestMessage2Encoder").getConstructor().newInstance(); - return wrap(0, encoder, buffer, BUFFER_CLASS); + return wrap(encoder, buffer); } private Object getTestMessage2Decoder(final UnsafeBuffer buffer, final Object encoder) throws Exception @@ -186,15 +186,13 @@ private static Object wrap( return decoder; } - private static Object wrap( - final int bufferOffset, final Object flyweight, final MutableDirectBuffer buffer, final Class bufferClass) - throws Exception + private static Object wrap(final Object flyweight, final UnsafeBuffer buffer) throws Exception { flyweight .getClass() - .getDeclaredMethod("wrap", bufferClass, int.class) - .invoke(flyweight, buffer, bufferOffset); + .getDeclaredMethod("wrap", BUFFER_CLASS, int.class) + .invoke(flyweight, buffer, 0); + return flyweight; } - } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java index 65bb022fee..60e604be0b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java @@ -19,7 +19,7 @@ import org.agrona.MutableDirectBuffer; import uk.co.real_logic.sbe.generation.Generators; -public final class ReflectionUtil +final class ReflectionUtil { static int getSbeSchemaVersion(final Object encoder) throws Exception { @@ -90,12 +90,12 @@ static boolean getCruiseControl(final Object extras) throws Exception return (boolean)extras.getClass().getMethod("cruiseControl").invoke(extras); } - public static int getCapacity(final Object flyweight) throws Exception + static int getCapacity(final Object flyweight) throws Exception { return getInt(flyweight, "capacity"); } - public static void setCapacity(final Object flyweight, final int value) throws Exception + static void setCapacity(final Object flyweight, final int value) throws Exception { flyweight .getClass() @@ -156,10 +156,7 @@ static int getDirectBuffer( .invoke(decoder, dst, dstOffset, length); } - static void wrapDirectBuffer( - final Object decoder, - final String name, - final DirectBuffer dst) throws Exception + static void wrapDirectBuffer(final Object decoder, final String name, final DirectBuffer dst) throws Exception { decoder .getClass() diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index 9d843fb2a1..603f025ea9 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -38,6 +38,7 @@ import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; +@SuppressWarnings("MethodLength") public class SchemaExtensionTest { private static final Class BUFFER_CLASS = MutableDirectBuffer.class; @@ -63,7 +64,6 @@ public void setup() throws Exception generator().generate(); } - @SuppressWarnings("MethodLength") @Test public void testMessage1() throws Exception { @@ -185,7 +185,6 @@ public void testMessage1() throws Exception } } - @SuppressWarnings("MethodLength") @Test public void testMessage2() throws Exception { @@ -454,19 +453,18 @@ private static Object wrap( return decoder; } - private static void wrap( - final int bufferOffset, final Object flyweight, final MutableDirectBuffer buffer, final Class bufferClass) + private static void wrap(final Object flyweight, final UnsafeBuffer buffer, final Class bufferClass) throws Exception { flyweight .getClass() .getDeclaredMethod("wrap", bufferClass, int.class) - .invoke(flyweight, buffer, bufferOffset); + .invoke(flyweight, buffer, 0); } private static Object wrap(final UnsafeBuffer buffer, final Object encoder) throws Exception { - wrap(0, encoder, buffer, BUFFER_CLASS); + wrap(encoder, buffer, BUFFER_CLASS); return encoder; } From 7e5d270c58d91457a8e73775d61afcda9e96dcc3 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 23 Oct 2020 15:18:36 +0100 Subject: [PATCH 0584/1594] [Java] Clean up warnings in JavaGenerator. --- .../sbe/generation/java/JavaGenerator.java | 119 +++++++++--------- .../sbe/ir/generated/ByteOrderCodec.java | 1 + .../sbe/ir/generated/FrameCodecDecoder.java | 1 + .../sbe/ir/generated/FrameCodecEncoder.java | 1 + .../ir/generated/MessageHeaderDecoder.java | 1 + .../ir/generated/MessageHeaderEncoder.java | 1 + .../sbe/ir/generated/PresenceCodec.java | 1 + .../sbe/ir/generated/PrimitiveTypeCodec.java | 1 + .../sbe/ir/generated/SignalCodec.java | 1 + .../sbe/ir/generated/TokenCodecDecoder.java | 1 + .../sbe/ir/generated/TokenCodecEncoder.java | 1 + .../ir/generated/VarDataEncodingDecoder.java | 1 + .../ir/generated/VarDataEncodingEncoder.java | 1 + 13 files changed, 69 insertions(+), 62 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index f01b8e01fd..2c42dcf758 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -212,7 +212,7 @@ private void generateEncoder( final StringBuilder sb = new StringBuilder(); generateEncoderFields(sb, className, fields, BASE_INDENT); - generateEncoderGroups(sb, className, null, groups, BASE_INDENT, false); + generateEncoderGroups(sb, className, groups, BASE_INDENT, false); generateEncoderVarData(sb, className, varData, BASE_INDENT); generateEncoderDisplay(sb, decoderName(msgToken.name())); @@ -246,7 +246,7 @@ private void generateDecoder( final StringBuilder sb = new StringBuilder(); generateDecoderFields(sb, fields, BASE_INDENT); - generateDecoderGroups(sb, className, null, groups, BASE_INDENT, false); + generateDecoderGroups(sb, className, groups, BASE_INDENT, false); generateDecoderVarData(sb, varData, BASE_INDENT); generateDecoderDisplay(sb, msgToken.name(), fields, groups, varData); @@ -259,7 +259,6 @@ private void generateDecoder( private void generateDecoderGroups( final StringBuilder sb, final String outerClassName, - final String outerGroupName, final List tokens, final String indent, final boolean isSubGroup) throws IOException @@ -298,7 +297,7 @@ private void generateDecoderGroups( generateGroupDecoderClassHeader(sb, groupName, outerClassName, tokens, groups, index, indent + INDENT); generateDecoderFields(sb, fields, indent + INDENT); - generateDecoderGroups(sb, outerClassName, groupName, groups, indent + INDENT, true); + generateDecoderGroups(sb, outerClassName, groups, indent + INDENT, true); generateDecoderVarData(sb, varData, indent + INDENT); appendGroupInstanceDecoderDisplay(sb, fields, groups, varData, indent + INDENT); @@ -310,7 +309,6 @@ private void generateDecoderGroups( private void generateEncoderGroups( final StringBuilder sb, final String outerClassName, - final String outerGroupName, final List tokens, final String indent, final boolean isSubGroup) throws IOException @@ -350,7 +348,7 @@ private void generateEncoderGroups( generateGroupEncoderClassHeader(sb, groupName, outerClassName, tokens, groups, index, indent + INDENT); generateEncoderFields(sb, groupClassName, fields, indent + INDENT); - generateEncoderGroups(sb, outerClassName, groupClassName, groups, indent + INDENT, true); + generateEncoderGroups(sb, outerClassName, groups, indent + INDENT, true); generateEncoderVarData(sb, groupClassName, varData, indent + INDENT); sb.append(indent).append(" }\n"); @@ -3213,41 +3211,41 @@ private String generateStaticChoicePut(final PrimitiveType type, final String bi private void generateEncoderDisplay(final StringBuilder sb, final String decoderName) { - final String indent = INDENT; - appendToString(sb, indent); + appendToString(sb, INDENT); + sb.append('\n'); - append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); - append(sb, indent, "{"); - append(sb, indent, " if (null == buffer)"); - append(sb, indent, " {"); - append(sb, indent, " return builder;"); - append(sb, indent, " }"); + append(sb, INDENT, "public StringBuilder appendTo(final StringBuilder builder)"); + append(sb, INDENT, "{"); + append(sb, INDENT, " if (null == buffer)"); + append(sb, INDENT, " {"); + append(sb, INDENT, " return builder;"); + append(sb, INDENT, " }"); sb.append('\n'); - append(sb, indent, " final " + decoderName + " decoder = new " + decoderName + "();"); - append(sb, indent, " decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION);"); + append(sb, INDENT, " final " + decoderName + " decoder = new " + decoderName + "();"); + append(sb, INDENT, " decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION);"); sb.append('\n'); - append(sb, indent, " return decoder.appendTo(builder);"); - append(sb, indent, "}"); + append(sb, INDENT, " return decoder.appendTo(builder);"); + append(sb, INDENT, "}"); } private CharSequence generateCompositeEncoderDisplay(final String decoderName) { - final String indent = INDENT; final StringBuilder sb = new StringBuilder(); - appendToString(sb, indent); + + appendToString(sb, INDENT); sb.append('\n'); - append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); - append(sb, indent, "{"); - append(sb, indent, " if (null == buffer)"); - append(sb, indent, " {"); - append(sb, indent, " return builder;"); - append(sb, indent, " }"); + append(sb, INDENT, "public StringBuilder appendTo(final StringBuilder builder)"); + append(sb, INDENT, "{"); + append(sb, INDENT, " if (null == buffer)"); + append(sb, INDENT, " {"); + append(sb, INDENT, " return builder;"); + append(sb, INDENT, " }"); sb.append('\n'); - append(sb, indent, " final " + decoderName + " decoder = new " + decoderName + "();"); - append(sb, indent, " decoder.wrap(buffer, offset);"); + append(sb, INDENT, " final " + decoderName + " decoder = new " + decoderName + "();"); + append(sb, INDENT, " decoder.wrap(buffer, offset);"); sb.append('\n'); - append(sb, indent, " return decoder.appendTo(builder);"); - append(sb, indent, "}"); + append(sb, INDENT, " return decoder.appendTo(builder);"); + append(sb, INDENT, "}"); return sb; } @@ -3292,37 +3290,36 @@ private CharSequence generateCompositeDecoderDisplay(final List tokens) private CharSequence generateChoiceDisplay(final List tokens) { - final String indent = INDENT; final StringBuilder sb = new StringBuilder(); - appendToString(sb, indent); + appendToString(sb, INDENT); sb.append('\n'); - append(sb, indent, "public StringBuilder appendTo(final StringBuilder builder)"); - append(sb, indent, "{"); - Separator.BEGIN_SET.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); - append(sb, indent, " boolean atLeastOne = false;"); + append(sb, INDENT, "public StringBuilder appendTo(final StringBuilder builder)"); + append(sb, INDENT, "{"); + Separator.BEGIN_SET.appendToGeneratedBuilder(sb, INDENT + INDENT, "builder"); + append(sb, INDENT, " boolean atLeastOne = false;"); for (final Token token : tokens) { if (token.signal() == Signal.CHOICE) { final String choiceName = formatPropertyName(token.name()); - append(sb, indent, " if (" + choiceName + "())"); - append(sb, indent, " {"); - append(sb, indent, " if (atLeastOne)"); - append(sb, indent, " {"); - Separator.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT + INDENT, "builder"); - append(sb, indent, " }"); - append(sb, indent, " builder.append(\"" + choiceName + "\");"); - append(sb, indent, " atLeastOne = true;"); - append(sb, indent, " }"); + append(sb, INDENT, " if (" + choiceName + "())"); + append(sb, INDENT, " {"); + append(sb, INDENT, " if (atLeastOne)"); + append(sb, INDENT, " {"); + Separator.ENTRY.appendToGeneratedBuilder(sb, INDENT + INDENT + INDENT + INDENT, "builder"); + append(sb, INDENT, " }"); + append(sb, INDENT, " builder.append(\"" + choiceName + "\");"); + append(sb, INDENT, " atLeastOne = true;"); + append(sb, INDENT, " }"); } } - Separator.END_SET.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + Separator.END_SET.appendToGeneratedBuilder(sb, INDENT + INDENT, "builder"); sb.append('\n'); - append(sb, indent, " return builder;"); - append(sb, indent, "}"); + append(sb, INDENT, " return builder;"); + append(sb, INDENT, "}"); return sb; } @@ -3334,9 +3331,7 @@ private void generateDecoderDisplay( final List groups, final List varData) { - final String decoderName = decoderName(name); - - appendMessageToString(sb, INDENT, decoderName); + appendMessageToString(sb, decoderName(name)); sb.append('\n'); append(sb, INDENT, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, INDENT, "{"); @@ -3587,20 +3582,20 @@ private void appendToString(final StringBuilder sb, final String indent) append(sb, indent, "}"); } - private void appendMessageToString(final StringBuilder sb, final String indent, final String decoderName) + private void appendMessageToString(final StringBuilder sb, final String decoderName) { sb.append('\n'); - append(sb, indent, "public String toString()"); - append(sb, indent, "{"); - append(sb, indent, " if (null == buffer)"); - append(sb, indent, " {"); - append(sb, indent, " return \"\";"); - append(sb, indent, " }"); + append(sb, INDENT, "public String toString()"); + append(sb, INDENT, "{"); + append(sb, INDENT, " if (null == buffer)"); + append(sb, INDENT, " {"); + append(sb, INDENT, " return \"\";"); + append(sb, INDENT, " }"); sb.append('\n'); - append(sb, indent, " final " + decoderName + " decoder = new " + decoderName + "();"); - append(sb, indent, " decoder.wrap(buffer, initialOffset, actingBlockLength, actingVersion);"); + append(sb, INDENT, " final " + decoderName + " decoder = new " + decoderName + "();"); + append(sb, INDENT, " decoder.wrap(buffer, initialOffset, actingBlockLength, actingVersion);"); sb.append('\n'); - append(sb, indent, " return decoder.appendTo(new StringBuilder()).toString();"); - append(sb, indent, "}"); + append(sb, INDENT, " return decoder.appendTo(new StringBuilder()).toString();"); + append(sb, INDENT, "}"); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java index 65404dd8ad..b4333b26bd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java @@ -1,6 +1,7 @@ /* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; + /** * Number encoding byte order */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index c79f634052..d8b5d2cdd7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -4,6 +4,7 @@ import org.agrona.MutableDirectBuffer; import org.agrona.DirectBuffer; + /** * Frame Header for start of encoding IR */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index 5ba2f5ffdd..2d935add3b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -4,6 +4,7 @@ import org.agrona.MutableDirectBuffer; import org.agrona.DirectBuffer; + /** * Frame Header for start of encoding IR */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java index a1d6fb2936..28ab81a578 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java @@ -3,6 +3,7 @@ import org.agrona.DirectBuffer; + /** * Message identifiers and length of message root */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java index 1d0bd0a892..c08dc8d2fe 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java @@ -3,6 +3,7 @@ import org.agrona.MutableDirectBuffer; + /** * Message identifiers and length of message root */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java index 55ecb2a6e9..c4a389de45 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java @@ -1,6 +1,7 @@ /* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; + /** * Field presence declaration */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java index 93906b5e82..daaf41dd03 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java @@ -1,6 +1,7 @@ /* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; + /** * Primitive types in type system */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java index 9573abf7bd..60c88309b3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java @@ -1,6 +1,7 @@ /* Generated SBE (Simple Binary Encoding) message codec. */ package uk.co.real_logic.sbe.ir.generated; + /** * Token signal type in IR */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 830a2e8e84..0220ac02ba 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -4,6 +4,7 @@ import org.agrona.MutableDirectBuffer; import org.agrona.DirectBuffer; + /** * Codec for an IR Token */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index ac4ae55ddf..6f12733d1f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -4,6 +4,7 @@ import org.agrona.MutableDirectBuffer; import org.agrona.DirectBuffer; + /** * Codec for an IR Token */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java index e820dc0b27..819fa7a973 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java @@ -3,6 +3,7 @@ import org.agrona.DirectBuffer; + /** * Header for var data fields */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java index a6299907cb..74cb0aa239 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java @@ -3,6 +3,7 @@ import org.agrona.MutableDirectBuffer; + /** * Header for var data fields */ From d25219ca37e23d45aed1cc4c40dd58c7c605b066 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 23 Oct 2020 17:21:13 +0100 Subject: [PATCH 0585/1594] [Java] Improve formatting of bulk access methods to fixed size byte arrays. --- .../sbe/generation/java/JavaGenerator.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 2c42dcf758..da098e85c8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2066,7 +2066,7 @@ else if (encoding.primitiveType() == PrimitiveType.UINT8) indent + " {\n" + "%s" + indent + " final int bytesCopied = Math.min(length, %d);\n" + - indent + " buffer.getBytes(offset + %d, dst, dstOffset, bytesCopied);\n" + + indent + " buffer.getBytes(offset + %d, dst, dstOffset, bytesCopied);\n\n" + indent + " return bytesCopied;\n" + indent + " }\n", Generators.toUpperFirstChar(propertyName), @@ -2079,7 +2079,7 @@ else if (encoding.primitiveType() == PrimitiveType.UINT8) indent + " {\n" + "%s" + indent + " final int bytesCopied = Math.min(length, %d);\n" + - indent + " buffer.getBytes(offset + %d, dst, dstOffset, bytesCopied);\n" + + indent + " buffer.getBytes(offset + %d, dst, dstOffset, bytesCopied);\n\n" + indent + " return bytesCopied;\n" + indent + " }\n", Generators.toUpperFirstChar(propertyName), @@ -2091,15 +2091,14 @@ else if (encoding.primitiveType() == PrimitiveType.UINT8) new Formatter(sb).format("\n" + indent + " public void wrap%s(final %s wrapBuffer)\n" + indent + " {\n" + - indent + " final int length = %d;\n" + "%s" + - indent + " wrapBuffer.wrap(buffer, offset + %d, length);\n" + + indent + " wrapBuffer.wrap(buffer, offset + %d, %d);\n" + indent + " }\n", Generators.toUpperFirstChar(propertyName), readOnlyBuffer, - fieldLength, generateWrapFieldNotPresentCondition(propertyToken.version(), indent), - offset); + offset, + fieldLength); } return sb; @@ -2321,13 +2320,13 @@ private void generateByteArrayEncodeMethods( indent + " if (length > %d)\n" + indent + " {\n" + indent + " throw new IllegalStateException(" + - "\"length > maxValue for type: \" + length);" + + "\"length > maxValue for type: \" + length);\n" + indent + " }\n\n" + indent + " buffer.putBytes(offset + %d, src, srcOffset, length);\n" + indent + " for (int i = length; i < %d; i++)\n" + indent + " {\n" + indent + " buffer.putByte(offset + %d + i, (byte)0);\n" + - indent + " }\n" + + indent + " }\n\n" + indent + " return this;\n" + indent + " }\n", formatClassName(containingClassName), @@ -2343,13 +2342,13 @@ private void generateByteArrayEncodeMethods( indent + " if (length > %d)\n" + indent + " {\n" + indent + " throw new IllegalStateException(" + - "\"length > maxValue for type: \" + length);" + + "\"length > maxValue for type: \" + length);\n" + indent + " }\n\n" + indent + " buffer.putBytes(offset + %d, src, srcOffset, length);\n" + indent + " for (int i = length; i < %d; i++)\n" + indent + " {\n" + indent + " buffer.putByte(offset + %d + i, (byte)0);\n" + - indent + " }\n" + + indent + " }\n\n" + indent + " return this;\n" + indent + " }\n", formatClassName(containingClassName), From 6c3b0a3e364c3c8bae74fc1e6247e414ff018d0c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 2 Nov 2020 17:17:32 +0000 Subject: [PATCH 0586/1594] [Java] Upgrade to Versions 0.34.0 and Mockito 3.6.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 493b80ca1a..ef8b7f87e8 100644 --- a/build.gradle +++ b/build.gradle @@ -23,14 +23,14 @@ plugins { id 'java-library' id 'idea' id 'com.github.johnrengelman.shadow' version '6.1.0' apply false - id "com.github.ben-manes.versions" version "0.33.0" + id "com.github.ben-manes.versions" version "0.34.0" } defaultTasks 'clean', 'build' def checkstyleVersion = '8.36.2' def hamcrestVersion = '2.2' -def mockitoVersion = '3.5.15' +def mockitoVersion = '3.6.0' def junitVersion = '5.7.0' def jmhVersion = '1.26' def agronaVersion = '1.8.0' From 7895e8644c1680c364af9d1150030b1c13181f68 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 5 Nov 2020 12:36:30 +0000 Subject: [PATCH 0587/1594] [Java] Upgrade to Gradle 6.7 and Checkstyle 8.37. --- build.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index ef8b7f87e8..5a98dd7f74 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ plugins { defaultTasks 'clean', 'build' -def checkstyleVersion = '8.36.2' +def checkstyleVersion = '8.37' def hamcrestVersion = '2.2' def mockitoVersion = '3.6.0' def junitVersion = '5.7.0' @@ -696,6 +696,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.6.1' + gradleVersion = '6.7' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 33682bbbf9..14e30f7416 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 150b779c02eeb0b3dd8c6f92691400486a76574e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 6 Nov 2020 17:59:45 +0000 Subject: [PATCH 0588/1594] [Java] Generate raw getters for enum types. --- .../sbe/generation/java/JavaGenerator.java | 188 ++++++++++-------- .../sbe/ir/generated/TokenCodecDecoder.java | 20 ++ 2 files changed, 124 insertions(+), 84 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index da098e85c8..05c25c19f6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1295,26 +1295,26 @@ private void generateComposite(final List tokens) throws IOException switch (encodingToken.signal()) { case ENCODING: - out.append(sb).append(generatePrimitiveDecoder( - true, encodingToken.name(), encodingToken, encodingToken, BASE_INDENT)); + generatePrimitiveDecoder( + sb, true, encodingToken.name(), encodingToken, encodingToken, BASE_INDENT); break; case BEGIN_ENUM: - out.append(sb).append(generateEnumDecoder( - true, encodingToken, propertyName, encodingToken, BASE_INDENT)); + generateEnumDecoder(sb, true, encodingToken, propertyName, encodingToken, BASE_INDENT); break; case BEGIN_SET: - out.append(sb).append(generateBitSetProperty( - true, DECODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName)); + generateBitSetProperty( + sb, true, DECODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName); break; case BEGIN_COMPOSITE: - out.append(sb).append(generateCompositeProperty( - true, DECODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName)); + generateCompositeProperty( + sb, true, DECODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName); break; } + out.append(sb); i += encodingToken.componentTokenCount(); } @@ -1341,26 +1341,25 @@ private void generateComposite(final List tokens) throws IOException switch (encodingToken.signal()) { case ENCODING: - out.append(sb).append(generatePrimitiveEncoder( - encoderName, encodingToken.name(), encodingToken, BASE_INDENT)); + generatePrimitiveEncoder(sb, encoderName, encodingToken.name(), encodingToken, BASE_INDENT); break; case BEGIN_ENUM: - out.append(sb).append(generateEnumEncoder( - encoderName, encodingToken, propertyName, encodingToken, BASE_INDENT)); + generateEnumEncoder(sb, encoderName, encodingToken, propertyName, encodingToken, BASE_INDENT); break; case BEGIN_SET: - out.append(sb).append(generateBitSetProperty( - true, ENCODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName)); + generateBitSetProperty( + sb, true, ENCODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName); break; case BEGIN_COMPOSITE: - out.append(sb).append(generateCompositeProperty( - true, ENCODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName)); + generateCompositeProperty( + sb, true, ENCODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName); break; } + out.append(sb); i += encodingToken.componentTokenCount(); } @@ -1711,14 +1710,14 @@ private static CharSequence generateEnumDeclaration(final String name, final Tok return sb; } - private CharSequence generatePrimitiveDecoder( + private void generatePrimitiveDecoder( + final StringBuilder sb, final boolean inComposite, final String propertyName, final Token propertyToken, final Token encodingToken, final String indent) { - final StringBuilder sb = new StringBuilder(); final String formattedPropertyName = formatPropertyName(propertyName); generatePrimitiveFieldMetaMethod(sb, formattedPropertyName, encodingToken, indent); @@ -1732,14 +1731,15 @@ private CharSequence generatePrimitiveDecoder( sb.append(generatePrimitivePropertyDecodeMethods( inComposite, formattedPropertyName, propertyToken, encodingToken, indent)); } - - return sb; } - private CharSequence generatePrimitiveEncoder( - final String containingClassName, final String propertyName, final Token token, final String indent) + private void generatePrimitiveEncoder( + final StringBuilder sb, + final String containingClassName, + final String propertyName, + final Token token, + final String indent) { - final StringBuilder sb = new StringBuilder(); final String formattedPropertyName = formatPropertyName(propertyName); generatePrimitiveFieldMetaMethod(sb, formattedPropertyName, token, indent); @@ -1753,8 +1753,6 @@ private CharSequence generatePrimitiveEncoder( { generateConstPropertyMethods(sb, formattedPropertyName, token, indent); } - - return sb; } private CharSequence generatePrimitivePropertyDecodeMethods( @@ -2727,22 +2725,21 @@ private void generateEncoderFields( switch (typeToken.signal()) { case ENCODING: - sb.append(generatePrimitiveEncoder(containingClassName, propertyName, typeToken, indent)); + generatePrimitiveEncoder(sb, containingClassName, propertyName, typeToken, indent); break; case BEGIN_ENUM: - sb.append(generateEnumEncoder( - containingClassName, fieldToken, propertyName, typeToken, indent)); + generateEnumEncoder(sb, containingClassName, fieldToken, propertyName, typeToken, indent); break; case BEGIN_SET: - sb.append(generateBitSetProperty( - false, ENCODER, propertyName, fieldToken, typeToken, indent, typeName)); + generateBitSetProperty( + sb, false, ENCODER, propertyName, fieldToken, typeToken, indent, typeName); break; case BEGIN_COMPOSITE: - sb.append(generateCompositeProperty( - false, ENCODER, propertyName, fieldToken, typeToken, indent, typeName)); + generateCompositeProperty( + sb, false, ENCODER, propertyName, fieldToken, typeToken, indent, typeName); break; } }); @@ -2766,21 +2763,21 @@ private void generateDecoderFields(final StringBuilder sb, final List tok switch (typeToken.signal()) { case ENCODING: - sb.append(generatePrimitiveDecoder(false, propertyName, fieldToken, typeToken, indent)); + generatePrimitiveDecoder(sb, false, propertyName, fieldToken, typeToken, indent); break; case BEGIN_ENUM: - sb.append(generateEnumDecoder(false, fieldToken, propertyName, typeToken, indent)); + generateEnumDecoder(sb, false, fieldToken, propertyName, typeToken, indent); break; case BEGIN_SET: - sb.append(generateBitSetProperty( - false, DECODER, propertyName, fieldToken, typeToken, indent, typeName)); + generateBitSetProperty( + sb, false, DECODER, propertyName, fieldToken, typeToken, indent, typeName); break; case BEGIN_COMPOSITE: - sb.append(generateCompositeProperty( - false, DECODER, propertyName, fieldToken, typeToken, indent, typeName)); + generateCompositeProperty( + sb, false, DECODER, propertyName, fieldToken, typeToken, indent, typeName); break; } }); @@ -2875,7 +2872,8 @@ private static void generateFieldMetaAttributeMethod(final StringBuilder sb, fin .append(indent).append(" }\n"); } - private CharSequence generateEnumDecoder( + private void generateEnumDecoder( + final StringBuilder sb, final boolean inComposite, final Token fieldToken, final String propertyName, @@ -2884,10 +2882,23 @@ private CharSequence generateEnumDecoder( { final String enumName = formatClassName(typeToken.applicableTypeName()); final Encoding encoding = typeToken.encoding(); + final String javaTypeName = javaTypeName(encoding.primitiveType()); if (fieldToken.isConstantEncoding()) { - return String.format( + final String enumValueStr = fieldToken.encoding().constValue().toString(); + + new Formatter(sb).format( + "\n" + + indent + " public %s %sRaw()\n" + + indent + " {\n" + + indent + " return %s.value();\n" + + indent + " }\n\n", + javaTypeName, + propertyName, + enumValueStr); + + new Formatter(sb).format( "\n" + indent + " public %s %s()\n" + indent + " {\n" + @@ -2895,11 +2906,26 @@ private CharSequence generateEnumDecoder( indent + " }\n\n", enumName, propertyName, - fieldToken.encoding().constValue().toString()); + enumValueStr); } else { - return String.format( + final String rawGetStr = generateGet( + encoding.primitiveType(), "offset + " + typeToken.offset(), byteOrderString(encoding)); + + new Formatter(sb).format( + "\n" + + indent + " public %s %sRaw()\n" + + indent + " {\n" + + "%s" + + indent + " return %s;\n" + + indent + " }\n", + javaTypeName, + formatPropertyName(propertyName), + generateFieldNotPresentCondition(inComposite, fieldToken.version(), encoding, indent), + rawGetStr); + + new Formatter(sb).format( "\n" + indent + " public %s %s()\n" + indent + " {\n" + @@ -2910,39 +2936,40 @@ private CharSequence generateEnumDecoder( propertyName, generatePropertyNotPresentCondition(inComposite, DECODER, fieldToken, enumName, indent), enumName, - generateGet(encoding.primitiveType(), "offset + " + typeToken.offset(), byteOrderString(encoding))); + rawGetStr); } } - private CharSequence generateEnumEncoder( + private void generateEnumEncoder( + final StringBuilder sb, final String containingClassName, final Token fieldToken, final String propertyName, final Token typeToken, final String indent) { - if (fieldToken.isConstantEncoding()) + if (!fieldToken.isConstantEncoding()) { - return ""; - } + final String enumName = formatClassName(typeToken.applicableTypeName()); + final Encoding encoding = typeToken.encoding(); + final int offset = typeToken.offset(); + final String byteOrderString = byteOrderString(encoding); - final String enumName = formatClassName(typeToken.applicableTypeName()); - final Encoding encoding = typeToken.encoding(); - final int offset = typeToken.offset(); - - return String.format("\n" + - indent + " public %s %s(final %s value)\n" + - indent + " {\n" + - indent + " %s;\n" + - indent + " return this;\n" + - indent + " }\n", - formatClassName(containingClassName), - propertyName, - enumName, - generatePut(encoding.primitiveType(), "offset + " + offset, "value.value()", byteOrderString(encoding))); + new Formatter(sb).format("\n" + + indent + " public %s %s(final %s value)\n" + + indent + " {\n" + + indent + " %s;\n" + + indent + " return this;\n" + + indent + " }\n", + formatClassName(containingClassName), + propertyName, + enumName, + generatePut(encoding.primitiveType(), "offset + " + offset, "value.value()", byteOrderString)); + } } - private CharSequence generateBitSetProperty( + private void generateBitSetProperty( + final StringBuilder sb, final boolean inComposite, final CodecType codecType, final String propertyName, @@ -2951,8 +2978,6 @@ private CharSequence generateBitSetProperty( final String indent, final String bitSetName) { - final StringBuilder sb = new StringBuilder(); - new Formatter(sb).format("\n" + indent + " private final %s %s = new %s();\n", bitSetName, @@ -2973,11 +2998,10 @@ private CharSequence generateBitSetProperty( propertyName, bitsetToken.offset(), propertyName); - - return sb; } - private CharSequence generateCompositeProperty( + private void generateCompositeProperty( + final StringBuilder sb, final boolean inComposite, final CodecType codecType, final String propertyName, @@ -2986,8 +3010,6 @@ private CharSequence generateCompositeProperty( final String indent, final String compositeName) { - final StringBuilder sb = new StringBuilder(); - new Formatter(sb).format("\n" + indent + " private final %s %s = new %s();\n", compositeName, @@ -3008,8 +3030,6 @@ private CharSequence generateCompositeProperty( propertyName, compositeToken.offset(), propertyName); - - return sb; } private String generateGet(final PrimitiveType type, final String index, final String byteOrder) @@ -3210,7 +3230,7 @@ private String generateStaticChoicePut(final PrimitiveType type, final String bi private void generateEncoderDisplay(final StringBuilder sb, final String decoderName) { - appendToString(sb, INDENT); + appendToString(sb); sb.append('\n'); append(sb, INDENT, "public StringBuilder appendTo(final StringBuilder builder)"); @@ -3231,7 +3251,7 @@ private CharSequence generateCompositeEncoderDisplay(final String decoderName) { final StringBuilder sb = new StringBuilder(); - appendToString(sb, INDENT); + appendToString(sb); sb.append('\n'); append(sb, INDENT, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, INDENT, "{"); @@ -3253,7 +3273,7 @@ private CharSequence generateCompositeDecoderDisplay(final List tokens) { final StringBuilder sb = new StringBuilder(); - appendToString(sb, INDENT); + appendToString(sb); sb.append('\n'); append(sb, INDENT, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, INDENT, "{"); @@ -3291,7 +3311,7 @@ private CharSequence generateChoiceDisplay(final List tokens) { final StringBuilder sb = new StringBuilder(); - appendToString(sb, INDENT); + appendToString(sb); sb.append('\n'); append(sb, INDENT, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, INDENT, "{"); @@ -3567,18 +3587,18 @@ private int writeTokenDisplay( return lengthBeforeFieldSeparator; } - private void appendToString(final StringBuilder sb, final String indent) + private void appendToString(final StringBuilder sb) { sb.append('\n'); - append(sb, indent, "public String toString()"); - append(sb, indent, "{"); - append(sb, indent, " if (null == buffer)"); - append(sb, indent, " {"); - append(sb, indent, " return \"\";"); - append(sb, indent, " }"); + append(sb, INDENT, "public String toString()"); + append(sb, INDENT, "{"); + append(sb, INDENT, " if (null == buffer)"); + append(sb, INDENT, " {"); + append(sb, INDENT, " return \"\";"); + append(sb, INDENT, " }"); sb.append('\n'); - append(sb, indent, " return appendTo(new StringBuilder()).toString();"); - append(sb, indent, "}"); + append(sb, INDENT, " return appendTo(new StringBuilder()).toString();"); + append(sb, INDENT, "}"); } private void appendMessageToString(final StringBuilder sb, final String decoderName) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 0220ac02ba..e283d77025 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -384,6 +384,11 @@ public static String signalMetaAttribute(final MetaAttribute metaAttribute) return ""; } + public short signalRaw() + { + return ((short)(buffer.getByte(offset + 20) & 0xFF)); + } + public SignalCodec signal() { return SignalCodec.get(((short)(buffer.getByte(offset + 20) & 0xFF))); @@ -420,6 +425,11 @@ public static String primitiveTypeMetaAttribute(final MetaAttribute metaAttribut return ""; } + public short primitiveTypeRaw() + { + return ((short)(buffer.getByte(offset + 21) & 0xFF)); + } + public PrimitiveTypeCodec primitiveType() { return PrimitiveTypeCodec.get(((short)(buffer.getByte(offset + 21) & 0xFF))); @@ -456,6 +466,11 @@ public static String byteOrderMetaAttribute(final MetaAttribute metaAttribute) return ""; } + public short byteOrderRaw() + { + return ((short)(buffer.getByte(offset + 22) & 0xFF)); + } + public ByteOrderCodec byteOrder() { return ByteOrderCodec.get(((short)(buffer.getByte(offset + 22) & 0xFF))); @@ -492,6 +507,11 @@ public static String presenceMetaAttribute(final MetaAttribute metaAttribute) return ""; } + public short presenceRaw() + { + return ((short)(buffer.getByte(offset + 23) & 0xFF)); + } + public PresenceCodec presence() { return PresenceCodec.get(((short)(buffer.getByte(offset + 23) & 0xFF))); From 165c697ea182a1cf0787d76fd48018a39c572271 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 9 Nov 2020 19:06:50 +0000 Subject: [PATCH 0589/1594] [Java] Upgrade to Versions 0.36.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5a98dd7f74..a4af5fea2c 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ plugins { id 'java-library' id 'idea' id 'com.github.johnrengelman.shadow' version '6.1.0' apply false - id "com.github.ben-manes.versions" version "0.34.0" + id "com.github.ben-manes.versions" version "0.36.0" } defaultTasks 'clean', 'build' From ace115557c79d74403dbf4afb4ad68e3e2de6797 Mon Sep 17 00:00:00 2001 From: danielcranford Date: Tue, 10 Nov 2020 09:19:43 -0500 Subject: [PATCH 0590/1594] [C] Fixing argument order for *_wrap_and_apply_header (#821) Co-authored-by: Daniel Cranford --- .../main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 21e00fe57e..7e113a9548 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1965,7 +1965,7 @@ private CharSequence generateMessageFlyweightFunctions( " struct %11$s *const hdr)\n" + "{\n" + " %11$s_wrap(\n" + - " hdr, buffer + offset, 0, buffer_length, %11$s_sbe_schema_version());\n\n" + + " hdr, buffer + offset, 0, %11$s_sbe_schema_version(), buffer_length);\n\n" + " %11$s_set_blockLength(hdr, %10$s_sbe_block_length());\n" + " %11$s_set_templateId(hdr, %10$s_sbe_template_id());\n" + From 7fa530b5c650d41521ec8203a44d04970f96e058 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 17 Nov 2020 13:22:54 +0000 Subject: [PATCH 0591/1594] [Java] Upgrade to Gradle 6.7.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index a4af5fea2c..a4776a8b07 100644 --- a/build.gradle +++ b/build.gradle @@ -696,6 +696,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.7' + gradleVersion = '6.7.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 14e30f7416..1f3fdbc528 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 627b45056992c5e8a9b89dd8b70408ec823503a8 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 24 Nov 2020 13:03:00 +0100 Subject: [PATCH 0592/1594] [Java] Add Java 16-ea to the build matrix. --- .github/workflows/ci.yml | 11 +++++++++- build.gradle | 43 ++++++++++++++++++++++++++++++++++------ gradle.properties | 3 ++- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 010fe8619c..b6a637df35 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '11', '15' ] + java: [ '8', '11', '15', '16-ea' ] steps: - name: Checkout code uses: actions/checkout@v2 @@ -39,8 +39,17 @@ jobs: uses: actions/setup-java@v1 with: java-version: ${{ matrix.java }} + - name: Setup BUILD_JAVA_HOME + if: runner.os == 'Linux' + run: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + - name: Setup java 8 to run the Gradle script + uses: actions/setup-java@v1 + with: + java-version: 8 - name: Build with Gradle run: ./gradlew + env: + BUILD_JAVA_VERSION: ${{ matrix.java }} csharp-build: name: C# ${{ matrix.dotnet }} diff --git a/build.gradle b/build.gradle index a4776a8b07..d5b0b92a67 100644 --- a/build.gradle +++ b/build.gradle @@ -28,6 +28,25 @@ plugins { defaultTasks 'clean', 'build' +static def getBuildJavaVersion() +{ + def buildJavaVersion = System.getenv('BUILD_JAVA_VERSION') ?: JavaVersion.current().getMajorVersion() + if (buildJavaVersion.indexOf('.') > 0) + { + buildJavaVersion = buildJavaVersion.substring(0, buildJavaVersion.indexOf('.')) + } + if (buildJavaVersion.indexOf('-') > 0) + { + buildJavaVersion = buildJavaVersion.substring(0, buildJavaVersion.indexOf('-')) + } + Integer.parseInt(buildJavaVersion) +} +int buildJavaVersion = getBuildJavaVersion() + +def javaLauncher = javaToolchains.launcherFor { + languageVersion = JavaLanguageVersion.of(buildJavaVersion) +} + def checkstyleVersion = '8.37' def hamcrestVersion = '2.2' def mockitoVersion = '3.6.0' @@ -130,6 +149,10 @@ allprojects { failOnVersionConflict() } } + + tasks.withType(JavaExec).configureEach { + executable = javaLauncher.get().executablePath + } } jar.enabled = false @@ -142,6 +165,12 @@ subprojects { group = sbeGroup version = sbeVersion + java { + toolchain { + languageVersion = JavaLanguageVersion.of(buildJavaVersion) + } + } + checkstyle.toolVersion = "${checkstyleVersion}" tasks.withType(Sign) { @@ -156,7 +185,7 @@ subprojects { } tasks.withType(JavaCompile) { - if (JavaVersion.current().isJava9Compatible()) { + if (buildJavaVersion >= 9) { options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) } @@ -172,18 +201,20 @@ subprojects { options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' options.links("https://www.javadoc.io/doc/org.agrona/agrona/${agronaVersion}/") - if (JavaVersion.current().isJava11Compatible()) { - options.links("https://docs.oracle.com/en/java/javase/${JavaVersion.current().majorVersion}/docs/api/") + if (buildJavaVersion >= 16) { // Work around for early access versions for which no JavaDoc is published + options.links("https://docs.oracle.com/en/java/javase/15/docs/api/") + } else if (buildJavaVersion >= 11) { + options.links("https://docs.oracle.com/en/java/javase/${buildJavaVersion}/docs/api/") } else { - options.links("https://docs.oracle.com/javase/${JavaVersion.current().majorVersion}/docs/api/") + options.links("https://docs.oracle.com/javase/${buildJavaVersion}/docs/api/") } - if (JavaVersion.current().isJava10Compatible()) { + if (buildJavaVersion >= 10) { options.addBooleanOption 'html5', true } } test { - if (JavaVersion.current().isJava9Compatible()) { + if (buildJavaVersion >= 9) { jvmArgs('--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED') jvmArgs('--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED') } diff --git a/gradle.properties b/gradle.properties index 0dfc37be2d..b46e828b0d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,5 @@ -org.gradle.daemon=true +org.gradle.java.installations.auto-download=false +org.gradle.java.installations.fromEnv=BUILD_JAVA_HOME # HTTP timeouts for Gradle systemProp.org.gradle.internal.http.connectionTimeout=300000 From 4437ae5eb8395f6227da2b0f7980846e15e5a816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Bartmi=C5=84ski?= Date: Thu, 26 Nov 2020 18:37:42 +0000 Subject: [PATCH 0593/1594] [C#] Fix repeated group buffer overflow (#823) On a repeated group in the WrapForEncode, the parentMessage.Limit has two purposes: 1. It is used as a buffer offset for the _dimensions helper Wrap method 2. The assignment to it has a side effect of checking that we do not exceed the underlying DirectBuffer's capacity However notice that currently this assignment happens after writing to the _dimensions helper properties BlockLength and NumInGroup, i.e. the writes are done *before* we check for buffer overflow. Underneath these are direct writes to the byte* managed by the DirectBuffer, resulting in an unchecked, unsafe buffer overflow. To fix this the Limit has to be increased right after the call to the _dimensions.Wrap, before writes to BlockLength and NumInGroup The same occurs in the Decode method, only reading unsafe, invalid memory instead of writing to it. Also fixed _actingVersion was being used before it's assigned in the Encode --- .../real_logic/sbe/generation/csharp/CSharpGenerator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 1a45d845c0..1249ceab93 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -207,11 +207,11 @@ private void generateGroupClassHeader( indent + INDENT + INDENT + "_parentMessage = parentMessage;\n" + indent + INDENT + INDENT + "_buffer = buffer;\n" + indent + INDENT + INDENT + "_dimensions.Wrap(buffer, parentMessage.Limit, actingVersion);\n" + + indent + INDENT + INDENT + "_parentMessage.Limit = parentMessage.Limit + SbeHeaderSize;\n" + indent + INDENT + INDENT + "_blockLength = _dimensions.BlockLength;\n" + indent + INDENT + INDENT + "_count = (int) _dimensions.NumInGroup;\n" + // cast safety checked above indent + INDENT + INDENT + "_actingVersion = actingVersion;\n" + indent + INDENT + INDENT + "_index = 0;\n" + - indent + INDENT + INDENT + "_parentMessage.Limit = parentMessage.Limit + SbeHeaderSize;\n" + indent + INDENT + "}\n", parentMessageClassName)); @@ -232,14 +232,14 @@ private void generateGroupClassHeader( indent + INDENT + INDENT + "}\n\n" + indent + INDENT + INDENT + "_parentMessage = parentMessage;\n" + indent + INDENT + INDENT + "_buffer = buffer;\n" + - indent + INDENT + INDENT + "_dimensions.Wrap(buffer, parentMessage.Limit, _actingVersion);\n" + + indent + INDENT + INDENT + "_dimensions.Wrap(buffer, parentMessage.Limit, SchemaVersion);\n" + + indent + INDENT + INDENT + "parentMessage.Limit = parentMessage.Limit + SbeHeaderSize;\n" + indent + INDENT + INDENT + "_dimensions.BlockLength = SbeBlockLength;\n" + indent + INDENT + INDENT + "_dimensions.NumInGroup = (%5$s) count;\n" + indent + INDENT + INDENT + "_index = 0;\n" + indent + INDENT + INDENT + "_count = count;\n" + indent + INDENT + INDENT + "_blockLength = SbeBlockLength;\n" + indent + INDENT + INDENT + "_actingVersion = SchemaVersion;\n" + - indent + INDENT + INDENT + "parentMessage.Limit = parentMessage.Limit + SbeHeaderSize;\n" + indent + INDENT + "}\n", parentMessageClassName, numInGroupToken.encoding().applicableMinValue().longValue(), From 6a9d4532eed95a15f6abf1b60371ddb8ab582070 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 28 Nov 2020 14:50:11 +0000 Subject: [PATCH 0594/1594] [Java] Upgrade to Mockito 3.6.28. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d5b0b92a67..5744b7e860 100644 --- a/build.gradle +++ b/build.gradle @@ -49,7 +49,7 @@ def javaLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.37' def hamcrestVersion = '2.2' -def mockitoVersion = '3.6.0' +def mockitoVersion = '3.6.28' def junitVersion = '5.7.0' def jmhVersion = '1.26' def agronaVersion = '1.8.0' From 1c56186ec6e7cbbb5b1aa36850741720033d7ab0 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 1 Dec 2020 13:01:01 +0000 Subject: [PATCH 0595/1594] [C++] Correct spelling of __cplusplus macro. Issue #824. --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 8d982a3852..aee24d877c 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2977,7 +2977,7 @@ private CharSequence generateMessageLength(final List groups, final List< indent + " }\n\n" + indent + " for (const auto &e: %1$sItemLengths)\n" + indent + " {\n" + - indent + " #if __cpluplus >= 201703L\n" + + indent + " #if __cplusplus >= 201703L\n" + indent + " length += std::apply(%2$s::computeLength, e);\n" + indent + " #else\n" + indent + " length += %2$s::computeLength(%6$s);\n" + From f5c8f5298393f59ea515ecaf3ec9c24b537796b6 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 2 Dec 2020 12:58:11 +0000 Subject: [PATCH 0596/1594] [Java] Upgrade to Checkstyle 8.38. --- build.gradle | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index 5744b7e860..6997794e2c 100644 --- a/build.gradle +++ b/build.gradle @@ -28,15 +28,12 @@ plugins { defaultTasks 'clean', 'build' -static def getBuildJavaVersion() -{ +static def getBuildJavaVersion() { def buildJavaVersion = System.getenv('BUILD_JAVA_VERSION') ?: JavaVersion.current().getMajorVersion() - if (buildJavaVersion.indexOf('.') > 0) - { + if (buildJavaVersion.indexOf('.') > 0) { buildJavaVersion = buildJavaVersion.substring(0, buildJavaVersion.indexOf('.')) } - if (buildJavaVersion.indexOf('-') > 0) - { + if (buildJavaVersion.indexOf('-') > 0) { buildJavaVersion = buildJavaVersion.substring(0, buildJavaVersion.indexOf('-')) } Integer.parseInt(buildJavaVersion) @@ -47,7 +44,7 @@ def javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } -def checkstyleVersion = '8.37' +def checkstyleVersion = '8.38' def hamcrestVersion = '2.2' def mockitoVersion = '3.6.28' def junitVersion = '5.7.0' From 08cee75d60fd37f05f069964ffd0a048bc9f64e5 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 9 Dec 2020 12:54:12 +0000 Subject: [PATCH 0597/1594] [Java] Upgrade to JMH 1.27. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6997794e2c..54e6f88e2d 100644 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,7 @@ def checkstyleVersion = '8.38' def hamcrestVersion = '2.2' def mockitoVersion = '3.6.28' def junitVersion = '5.7.0' -def jmhVersion = '1.26' +def jmhVersion = '1.27' def agronaVersion = '1.8.0' def agronaVersionRange = '[1.8,1.9[' // allow any patch release of 1.8.x From cd9c39e14a1542efdc7f021685d6177af5eb63cc Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 9 Dec 2020 15:20:23 +0000 Subject: [PATCH 0598/1594] [Java] Fix Gradle warnings. --- build.gradle | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 54e6f88e2d..b320c28967 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + buildscript { repositories { mavenCentral() @@ -200,9 +201,11 @@ subprojects { options.links("https://www.javadoc.io/doc/org.agrona/agrona/${agronaVersion}/") if (buildJavaVersion >= 16) { // Work around for early access versions for which no JavaDoc is published options.links("https://docs.oracle.com/en/java/javase/15/docs/api/") - } else if (buildJavaVersion >= 11) { + } + else if (buildJavaVersion >= 11) { options.links("https://docs.oracle.com/en/java/javase/${buildJavaVersion}/docs/api/") - } else { + } + else { options.links("https://docs.oracle.com/javase/${buildJavaVersion}/docs/api/") } if (buildJavaVersion >= 10) { @@ -313,7 +316,7 @@ project(':sbe-tool') { repositories { maven { - url = !isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl + url(!isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl) credentials { username = ossrhUsername password = ossrhPassword @@ -379,7 +382,7 @@ project(':sbe-all') { } repositories { maven { - url = !isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl + url(!isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl) credentials { username = ossrhUsername password = ossrhPassword @@ -488,7 +491,7 @@ project(':sbe-samples') { repositories { maven { - url = !isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl + url(!isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl) credentials { username = ossrhUsername password = ossrhPassword @@ -542,7 +545,6 @@ project(':sbe-benchmarks') { } jar.finalizedBy shadowJar - javadoc.enabled = false } From fa12de255962d51707128c2d582a4c48a28389ba Mon Sep 17 00:00:00 2001 From: Ethan Date: Sun, 13 Dec 2020 11:09:30 +0100 Subject: [PATCH 0599/1594] [Go] Fix for decoding into a struct with pre-allocated slices. (#825) * [Go] Fix for decoding into a struct with pre-allocated slices. This change allows you to call `Decode()` on an sbe struct where the struct has pre-allocated slices. Before, the code would allocate a new slice if the capacity on the existing slice was less than the number of groups in the message. If the old slice had a greater capacity, it wouldn't truncate the number of elements to the new length. * [Go] Add test for decoding groups onto a pre-populated message. * [Go] Add test for decoding when existing vardata values are shorter. This tests that if the existing decoded struct has a vardata value with length = 5, and the message to decode has length = 4, then the vardata value is truncated to length 4. --- .../src/group_with_data/TestMessages_test.go | 94 ++++++++++++++++++- gocode/src/mktdata/preallocated_test.go | 69 ++++++++++++++ .../generation/golang/GolangGenerator.java | 2 + 3 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 gocode/src/mktdata/preallocated_test.go diff --git a/gocode/src/group_with_data/TestMessages_test.go b/gocode/src/group_with_data/TestMessages_test.go index cfa6b46e10..9eee9d1ad6 100644 --- a/gocode/src/group_with_data/TestMessages_test.go +++ b/gocode/src/group_with_data/TestMessages_test.go @@ -23,7 +23,7 @@ func TestEncodeDecodeTestMessage1(t *testing.T) { t.Fail() } - var out TestMessage1 = *new(TestMessage1) + var out = *new(TestMessage1) if err := out.Decode(m, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil { t.Log("Decoding Error", err) t.Fail() @@ -71,7 +71,7 @@ func TestEncodeDecodeTestMessage2(t *testing.T) { t.Fail() } - var out TestMessage2 = *new(TestMessage2) + var out = *new(TestMessage2) if err := out.Decode(m, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil { t.Log("Decoding Error", err) t.Fail() @@ -129,7 +129,7 @@ func TestEncodeDecodeTestMessage3(t *testing.T) { t.Fail() } - var out TestMessage3 = *new(TestMessage3) + var out = *new(TestMessage3) if err := out.Decode(m, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil { t.Log("Decoding Error", err) t.Fail() @@ -186,7 +186,7 @@ func TestEncodeDecodeTestMessage4(t *testing.T) { t.Fail() } - var out TestMessage4 = *new(TestMessage4) + var out = *new(TestMessage4) if err := out.Decode(m, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil { t.Log("Decoding Error", err) t.Fail() @@ -212,3 +212,89 @@ func TestEncodeDecodeTestMessage4(t *testing.T) { } return } + +func TestEncodeDecodeTestPreAlloc(t *testing.T) { + m := NewSbeGoMarshaller() + + in := TestMessage4{ + Tag1: 9876, + Entries: []TestMessage4Entries{ + { + VarDataField1: []byte("abcdef"), + VarDataField2: []byte("ghij"), + }, + { + VarDataField1: []byte("abc"), + VarDataField2: []byte("gh"), + }, + }, + } + + var buf = new(bytes.Buffer) + if err := in.Encode(m, buf, true); err != nil { + t.Log("Encoding Error", err) + t.Fail() + } + + var out = *new(TestMessage4) + if err := out.Decode(m, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil { + t.Log("Decoding Error", err) + t.Fail() + } + + if in.Tag1 != out.Tag1 { + t.Logf("in.Tag1 != out.Tag1") + t.Fail() + } + + for i := 0; i < len(in.Entries); i++ { + if !bytes.Equal(in.Entries[i].VarDataField1, out.Entries[i].VarDataField1) { + t.Logf("in.Entries[%d].VarDataField (%v)!= out.Entries[%d].VarDataField (%v)", i, i, in.Entries[i].VarDataField1, out.Entries[i].VarDataField1) + t.Fail() + } + if !bytes.Equal(in.Entries[i].VarDataField2, out.Entries[i].VarDataField2) { + t.Logf("in.Entries[%d].VarDataField (%v) != out.Entries[%d].VarDataField (%v)", i, i, in.Entries[i].VarDataField2, out.Entries[i].VarDataField2) + t.Fail() + } + } + + // new messages with newer group elements, shorter vardata + in = TestMessage4{ + Tag1: 9876, + Entries: []TestMessage4Entries{ + { + VarDataField1: []byte("abc"), + VarDataField2: []byte("ghijk"), + }, + }, + } + + buf.Reset() + if err := in.Encode(m, buf, true); err != nil { + t.Log("Encoding Error", err) + t.Fail() + } + + if err := out.Decode(m, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil { + t.Log("Decoding Error", err) + t.Fail() + } + + if in.Tag1 != out.Tag1 { + t.Logf("in.Tag1 != out.Tag1") + t.Fail() + } + + for i := 0; i < len(in.Entries); i++ { + if !bytes.Equal(in.Entries[i].VarDataField1, out.Entries[i].VarDataField1) { + t.Logf("in.Entries[%d].VarDataField (%v)!= out.Entries[%d].VarDataField (%v)", i, i, in.Entries[i].VarDataField1, out.Entries[i].VarDataField1) + t.Fail() + } + if !bytes.Equal(in.Entries[i].VarDataField2, out.Entries[i].VarDataField2) { + t.Logf("in.Entries[%d].VarDataField (%v) != out.Entries[%d].VarDataField (%v)", i, i, in.Entries[i].VarDataField2, out.Entries[i].VarDataField2) + t.Fail() + } + } + + return +} diff --git a/gocode/src/mktdata/preallocated_test.go b/gocode/src/mktdata/preallocated_test.go new file mode 100644 index 0000000000..962db2c4a5 --- /dev/null +++ b/gocode/src/mktdata/preallocated_test.go @@ -0,0 +1,69 @@ +package mktdata + +import ( + "bytes" + "fmt" + "os" + "testing" +) + +func TestPreallocated(t *testing.T) { + in := &MDIncrementalRefreshBook32{ + TransactTime: 1, + NoMDEntries: []MDIncrementalRefreshBook32NoMDEntries{ + { + MDEntryPx: PRICENULL{}, + MDEntrySize: 5, + SecurityID: 1, + }, + { + MDEntryPx: PRICENULL{}, + MDEntrySize: 6, + SecurityID: 1, + }, + }, + } + min := NewSbeGoMarshaller() + + buf := &bytes.Buffer{} + if err := in.Encode(min, buf, true); err != nil { + fmt.Println("Encoding Error", err) + os.Exit(1) + } + + out := &MDIncrementalRefreshBook32{} + if err := out.Decode(min, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil { + fmt.Println("Decoding Error", err) + os.Exit(1) + } + if len(out.NoMDEntries) != len(in.NoMDEntries) { + fmt.Printf("expected %d entries, got %d\n", len(in.NoMDEntries), len(out.NoMDEntries)) + os.Exit(1) + } + + // decode a message with fewer entries on top of existing message + in = &MDIncrementalRefreshBook32{ + TransactTime: 1, + NoMDEntries: []MDIncrementalRefreshBook32NoMDEntries{ + { + MDEntryPx: PRICENULL{}, + MDEntrySize: 5, + SecurityID: 1, + }, + }, + } + buf.Reset() + if err := in.Encode(min, buf, true); err != nil { + fmt.Println("Encoding Error", err) + os.Exit(1) + } + + if err := out.Decode(min, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil { + fmt.Println("Decoding Error", err) + os.Exit(1) + } + if len(out.NoMDEntries) != len(in.NoMDEntries) { + fmt.Printf("expected %d entries, got %d\n", len(in.NoMDEntries), len(out.NoMDEntries)) + os.Exit(1) + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index e2f2468b0e..3d6d97b100 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -1164,6 +1164,7 @@ private int generateVarDataEncodeDecode( "\t\tif cap(%1$c.%2$s) < int(%2$sLength) {\n" + "\t\t\t%1$s.%2$s = make([]%5$s, %2$sLength)\n" + "\t\t}\n" + + "\t\t%1$c.%2$s = %1$c.%2$s[:%2$sLength]\n" + "\t\tif err := _m.ReadBytes(_r, %1$c.%2$s); err != nil {\n" + "\t\t\treturn err\n" + "\t\t}\n" + @@ -1271,6 +1272,7 @@ private int generateGroupEncodeDecode( "\t\tif cap(%1$c.%2$s) < int(%2$sNumInGroup) {\n" + "\t\t\t%1$s.%2$s = make([]%3$s%2$s, %2$sNumInGroup)\n" + "\t\t}\n" + + "\t\t%1$c.%2$s = %1$c.%2$s[:%2$sNumInGroup]\n" + "\t\tfor i, _ := range %1$s.%2$s {\n" + "\t\t\tif err := %1$s.%2$s[i].Decode(_m, _r, actingVersion, uint(%4$sBlockLength)); err != nil {\n" + "\t\t\t\treturn err\n" + From 0fbbe7aef25a972b5ed6dfbd388f0a25bc31119e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 15 Dec 2020 15:08:01 +0100 Subject: [PATCH 0600/1594] [Java] Workaround for https://github.com/gradle/gradle/issues/15538. --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index b320c28967..b5756c8046 100644 --- a/build.gradle +++ b/build.gradle @@ -186,6 +186,9 @@ subprojects { if (buildJavaVersion >= 9) { options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) + // -- Workaround for https://github.com/gradle/gradle/issues/15538 + options.forkOptions.jvmArgs.addAll( ['--add-opens', 'jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED'] ) + // -- } options.encoding = 'UTF-8' options.deprecation = true From ccc02613f4182b068550dd9964c1cdbcacc56090 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 17 Dec 2020 14:21:57 +0000 Subject: [PATCH 0601/1594] [Java] Escape javadoc for basic html characters. Issue #826. --- .../sbe/generation/java/JavaUtil.java | 86 +++++++++++++++++-- 1 file changed, 79 insertions(+), 7 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index b407cb9aca..9f74af9cd9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -283,7 +283,11 @@ public static void generateTypeJavadoc( sb.append('\n') .append(indent).append("/**\n") - .append(indent).append(" * ").append(description).append('\n') + .append(indent).append(" * "); + + escapeJavadoc(sb, description); + + sb.append('\n') .append(indent).append(" */\n"); } @@ -306,7 +310,11 @@ public static void generateOptionDecodeJavadoc( } out.append(indent).append("/**\n") - .append(indent).append(" * ").append(description).append('\n') + .append(indent).append(" * "); + + escapeJavadoc(out, description); + + out.append('\n') .append(indent).append(" *\n") .append(indent).append(" * @return true if ").append(optionToken.name()).append(" set or false if not.\n") .append(indent).append(" */\n"); @@ -330,9 +338,13 @@ public static void generateOptionEncodeJavadoc( return; } - final String name = optionToken.name(); out.append(indent).append("/**\n") - .append(indent).append(" * ").append(description).append('\n') + .append(indent).append(" * "); + + escapeJavadoc(out, description); + + final String name = optionToken.name(); + out.append('\n') .append(indent).append(" *\n") .append(indent).append(" * @param value true if ").append(name).append(" is set or false if not.\n") .append(indent).append(" */\n"); @@ -357,9 +369,17 @@ public static void generateFlyweightPropertyJavadoc( sb.append('\n') .append(indent).append("/**\n") - .append(indent).append(" * ").append(description).append('\n') + .append(indent).append(" * "); + + escapeJavadoc(sb, description); + + sb.append('\n') .append(indent).append(" *\n") - .append(indent).append(" * @return ").append(typeName).append(" : ").append(description).append("\n") + .append(indent).append(" * @return ").append(typeName).append(" : "); + + escapeJavadoc(sb, description); + + sb.append("\n") .append(indent).append(" */"); } @@ -382,10 +402,62 @@ public static void generateGroupEncodePropertyJavadoc( sb.append('\n') .append(indent).append("/**\n") - .append(indent).append(" * ").append(description).append("\n") + .append(indent).append(" * "); + + escapeJavadoc(sb, description); + + sb.append("\n") .append(indent).append(" *\n") .append(indent).append(" * @param count of times the group will be encoded.\n") .append(indent).append(" * @return ").append(typeName).append(" : encoder for the group.\n") .append(indent).append(" */"); } + + private static void escapeJavadoc(final Appendable out, final String doc) throws IOException + { + for (int i = 0, length = doc.length(); i < length; i++) + { + final char c = doc.charAt(i); + switch (c) + { + case '<': + out.append("<"); + break; + + case '>': + out.append(">"); + break; + + default: + out.append(c); + break; + } + } + } + + private static void escapeJavadoc(final StringBuilder sb, final String doc) + { + for (int i = 0, length = doc.length(); i < length; i++) + { + final char c = doc.charAt(i); + switch (c) + { + case '<': + sb.append("<"); + break; + + case '>': + sb.append(">"); + break; + + case '&': + sb.append("&"); + break; + + default: + sb.append(c); + break; + } + } + } } From 62d38a7c6cb3b43a8090f634fd990d9a104bca4c Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Thu, 17 Dec 2020 15:25:41 +0000 Subject: [PATCH 0602/1594] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0f6a7b6afe..6899b4dee6 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,8 @@ For the latest version information and changes see the [Change Log](https://gith The Java and C++ SBE implementations work very efficiently with the [Aeron](https://github.com/real-logic/aeron) messaging system for low-latency and high-throughput communications. The Java SBE implementation has a dependency on -[Agrona](https://github.com/real-logic/agrona) for its buffer implementations. +[Agrona](https://github.com/real-logic/agrona) for its buffer implementations. Commercial support is available from +[sales@real-logic.co.uk](mailto:sales@real-logic.co.uk?subject=SBE). Binaries -------- From aadbe73c36f1e0b220dd75d2351851e4d3f81db8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 18 Dec 2020 10:30:04 +0000 Subject: [PATCH 0603/1594] [Java] Generate @return for bitset encoding of values on javadoc is a description is provided. Issue #828. --- .../main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 9f74af9cd9..1d66e6cd1f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -347,6 +347,7 @@ public static void generateOptionEncodeJavadoc( out.append('\n') .append(indent).append(" *\n") .append(indent).append(" * @param value true if ").append(name).append(" is set or false if not.\n") + .append(indent).append(" * @return this for a fluent API.\n") .append(indent).append(" */\n"); } From 18222bc42b215bb38fea3e4ca3eb3cd7dbb9bee7 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 18 Dec 2020 11:40:45 +0000 Subject: [PATCH 0604/1594] [Java] Add test build of iLink binary protocol. --- .../java/GenerateFixBinaryTest.java | 28 +- .../java/GenerateIlinkBinaryTest.java | 104 ++ sbe-tool/src/test/resources/ilinkbinary.xml | 1584 +++++++++++++++++ 3 files changed, 1704 insertions(+), 12 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java create mode 100644 sbe-tool/src/test/resources/ilinkbinary.xml diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java index f3be9150c4..450737cbf0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java @@ -15,19 +15,15 @@ */ package uk.co.real_logic.sbe.generation.java; -import org.junit.jupiter.api.Test; import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; import org.agrona.generation.CompilerUtil; import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.SbeTool; import uk.co.real_logic.sbe.Tests; -import uk.co.real_logic.sbe.ir.Ir; -import uk.co.real_logic.sbe.ir.IrDecoder; -import uk.co.real_logic.sbe.ir.IrEncoder; -import uk.co.real_logic.sbe.xml.IrGenerator; -import uk.co.real_logic.sbe.xml.MessageSchema; -import uk.co.real_logic.sbe.xml.ParserOptions; +import uk.co.real_logic.sbe.ir.*; +import uk.co.real_logic.sbe.xml.*; import java.nio.ByteBuffer; import java.util.Map; @@ -63,12 +59,20 @@ public void shouldGenerateValidJava() throws Exception generator.generate(); final Map sources = outputManager.getSources(); - final String className = "MDIncrementalRefreshTradeSummary42Decoder"; - final String fqClassName = ir.applicableNamespace() + "." + className; - - final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); - assertNotNull(aClass); + { + final String className = "MDIncrementalRefreshTradeSummary42Encoder"; + final String fqClassName = ir.applicableNamespace() + "." + className; + final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); + assertNotNull(aClass); + } + + { + final String className = "MDIncrementalRefreshTradeSummary42Decoder"; + final String fqClassName = ir.applicableNamespace() + "." + className; + final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); + assertNotNull(aClass); + } } @Test diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java new file mode 100644 index 0000000000..aff95815a2 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java @@ -0,0 +1,104 @@ +/* + * Copyright 2013-2020 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.generation.CompilerUtil; +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.SbeTool; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.ir.*; +import uk.co.real_logic.sbe.xml.*; + +import java.nio.ByteBuffer; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +public class GenerateIlinkBinaryTest +{ + private static final Class BUFFER_CLASS = MutableDirectBuffer.class; + private static final String BUFFER_NAME = BUFFER_CLASS.getName(); + private static final Class READ_ONLY_BUFFER_CLASS = DirectBuffer.class; + private static final String READ_ONLY_BUFFER_NAME = READ_ONLY_BUFFER_CLASS.getName(); + + private final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + + @Test + public void shouldGenerateValidJava() throws Exception + { + System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); + + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(Tests.getLocalResource("ilinkbinary.xml"), options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager); + + outputManager.setPackageName(ir.applicableNamespace()); + generator.generateMessageHeaderStub(); + generator.generateTypeStubs(); + generator.generate(); + + final Map sources = outputManager.getSources(); + + { + final String className = "NewOrderSingle514Encoder"; + final String fqClassName = ir.applicableNamespace() + "." + className; + final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); + assertNotNull(aClass); + } + + { + final String className = "NewOrderSingle514Decoder"; + final String fqClassName = ir.applicableNamespace() + "." + className; + final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); + assertNotNull(aClass); + } + } + + @Test + public void shouldGenerateAndEncodeIr() throws Exception + { + System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); + + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(Tests.getLocalResource("ilinkbinary.xml"), options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); + + final IrEncoder irEncoder = new IrEncoder(buffer, ir); + irEncoder.encode(); + + buffer.flip(); + final IrDecoder irDecoder = new IrDecoder(buffer); + final Ir decodedIr = irDecoder.decode(); + + assertEquals(ir.id(), decodedIr.id()); + assertEquals(ir.version(), decodedIr.version()); + assertEquals(ir.byteOrder(), decodedIr.byteOrder()); + assertEquals(ir.applicableNamespace(), decodedIr.applicableNamespace()); + assertEquals(ir.packageName(), decodedIr.packageName()); + assertEquals(ir.types().size(), decodedIr.types().size()); + assertEquals(ir.messages().size(), decodedIr.messages().size()); + } +} diff --git a/sbe-tool/src/test/resources/ilinkbinary.xml b/sbe-tool/src/test/resources/ilinkbinary.xml new file mode 100644 index 0000000000..6ef8c5cf9a --- /dev/null +++ b/sbe-tool/src/test/resources/ilinkbinary.xml @@ -0,0 +1,1584 @@ + + + + + IDEMPOTENT + 2 + 0 + 3 + 1 + 2 + RECOVERABLE + 0 + 8 + I + 4 + C + 5 + F + CME-1-SHA-256 + + + 8 + + 3 + 5 + 1 + 4 + U + U + C + 0 + 8 + C + 8 + 1 + + + + + + + + + + + + + + + + + + + + + Y + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -9 + + + + -9 + + + + + + + + + + + + + + + + + 0 + 1 + 3 + + + 0 + 1 + + + 0 + 1 + + + 0 + 1 + + + G + S + + + C + D + G + H + W + Y + + + 1 + 2 + 3 + 4 + + + A + B + C + D + E + F + G + Z + + + 1 + 2 + + + A + P + + + 8 + 9 + 100 + 103 + 104 + 105 + 106 + 107 + 108 + + + G + H + + + 0 + 2 + + + 0 + 1 + + + 0 + 1 + + + A + D + + + 0 + 1 + + + 0 + 1 + + + 2 + 4 + + + 0 + 1 + + + 1 + 7 + 9 + 10 + 100 + + + 0 + 1 + 6 + + + 100 + 101 + + + 100 + 101 + + + 1 + 3 + 100 + + + 0 + 1 + 6 + + + 0 + 1 + + + 1 + 2 + + + G + H + + + 4 + 5 + + + 0 + 1 + 2 + 4 + 5 + 8 + C + U + + + 1 + 2 + 4 + K + + + 1 + 2 + 3 + 4 + K + + + 1 + 24 + 96 + 118 + 1000 + + + 0 + 5 + + + 1 + 3 + 4 + 5 + 100 + + + 1 + 3 + 4 + 100 + + + 1 + + + 1 + 2 + 8 + + + 0 + 2 + 3 + 4 + + + 0 + 1 + + + N + O + + + 1 + 2 + 5 + + + 0 + 1 + 2 + 3 + + + 1 + 2 + + + 1 + 2 + + + 0 + 3 + + + 0 + 1 + 2 + + + 0 + 1 + 3 + 4 + 6 + + + 4 + 5 + 100 + 101 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From cb95084626adcbeaae136895f847a9ec25d68ff7 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 20 Dec 2020 17:03:17 +0100 Subject: [PATCH 0605/1594] [C++] Use generated literal as the constant one to be shifted in the bitset code. (#829) * [C++] Use generated literal as the constant one to be shifted in the bitset code. * [C++] Add dedicated test. * [C++] Simplfiy test. --- .../sbe/generation/cpp/CppGenerator.java | 29 ++++++----- .../sbe/generation/cpp/CppGeneratorTest.java | 49 +++++++++++++++++++ sbe-tool/src/test/resources/issue827.xml | 24 +++++++++ 3 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java create mode 100644 sbe-tool/src/test/resources/issue827.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index aee24d877c..d293b826df 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -822,29 +822,32 @@ private CharSequence generateChoices(final String bitsetClassName, final List { final String choiceName = formatPropertyName(token.name()); - final String typeName = cppTypeName(token.encoding().primitiveType()); + final PrimitiveType type = token.encoding().primitiveType(); + final String typeName = cppTypeName(type); final String choiceBitPosition = token.encoding().constValue().toString(); - final String byteOrderStr = formatByteOrderEncoding( - token.encoding().byteOrder(), token.encoding().primitiveType()); + final String byteOrderStr = formatByteOrderEncoding(token.encoding().byteOrder(), type); + final CharSequence constantOne = generateLiteral(type, "1"); new Formatter(sb).format("\n" + " static bool %1$s(const %2$s bits)\n" + " {\n" + - " return (bits & (1u << %3$su)) != 0;\n" + + " return (bits & (%4$s << %3$su)) != 0;\n" + " }\n", choiceName, typeName, - choiceBitPosition); + choiceBitPosition, + constantOne); new Formatter(sb).format("\n" + " static %2$s %1$s(const %2$s bits, const bool value)\n" + " {\n" + " return value ?" + - " static_cast<%2$s>(bits | (1u << %3$su)) : static_cast<%2$s>(bits & ~(1u << %3$su));\n" + + " static_cast<%2$s>(bits | (%4$s << %3$su)) : static_cast<%2$s>(bits & ~(%4$s << %3$su));\n" + " }\n", choiceName, typeName, - choiceBitPosition); + choiceBitPosition, + constantOne); new Formatter(sb).format("\n" + " SBE_NODISCARD bool %1$s() const\n" + @@ -852,13 +855,14 @@ private CharSequence generateChoices(final String bitsetClassName, final List(%4$s(bits) | (1u << %5$su)) " + - ": static_cast<%3$s>(%4$s(bits) & ~(1u << %5$su)));\n" + + " static_cast<%3$s>(%4$s(bits) | (%6$s << %5$su)) " + + ": static_cast<%3$s>(%4$s(bits) & ~(%6$s << %5$su)));\n" + " std::memcpy(m_buffer + m_offset, &bits, sizeof(%3$s));\n" + " return *this;\n" + " }\n", @@ -875,7 +879,8 @@ private CharSequence generateChoices(final String bitsetClassName, final List + + + + 0 + 35 + + + + + + + + + + + + From f62dbbd2207afaf55d48406636235524e36eb5fd Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 21 Dec 2020 17:57:49 +0000 Subject: [PATCH 0606/1594] [Java] Upgrade to Agrona 1.9.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b5756c8046..e667525200 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.6.28' def junitVersion = '5.7.0' def jmhVersion = '1.27' -def agronaVersion = '1.8.0' +def agronaVersion = '1.9.0' def agronaVersionRange = '[1.8,1.9[' // allow any patch release of 1.8.x def sbeGroup = 'uk.co.real-logic' From 1a13d0a4aea1d28b9f52913b5e8011eb8f6475b8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 21 Dec 2020 18:05:13 +0000 Subject: [PATCH 0607/1594] [Java] Upgrade to Agrona 1.9.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e667525200..aa9fbf6757 100644 --- a/build.gradle +++ b/build.gradle @@ -51,7 +51,7 @@ def mockitoVersion = '3.6.28' def junitVersion = '5.7.0' def jmhVersion = '1.27' def agronaVersion = '1.9.0' -def agronaVersionRange = '[1.8,1.9[' // allow any patch release of 1.8.x +def agronaVersionRange = '[1.9,1.10[' // allow any patch release of 1.9.x def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From a1915050b4197031e3e84f26849215390016fa0d Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Tue, 22 Dec 2020 15:27:11 +0000 Subject: [PATCH 0608/1594] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6899b4dee6..4c7a34ac3e 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Example for Maven:     uk.co.real-logic     sbe-all -    1.20.3 +    ${sbe.tool.version} ``` @@ -63,7 +63,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-${SBE_LIB_VERSION}.jar my-sbe-messages.xml + java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-${SBE_TOOL_VERSION}.jar my-sbe-messages.xml C++ Build using CMake --------------------- From 80367ca982b52b709e5e5f1e5da2a0b8200f98ba Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 22 Dec 2020 08:27:13 -0800 Subject: [PATCH 0609/1594] 1.20.4 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 6917d3d4df..1b9335f13b 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.20.4-SNAPSHOT \ No newline at end of file +1.20.4 \ No newline at end of file From b5a02be71a494d4d3d34cf94d3b8b0670abe62a6 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 22 Dec 2020 08:29:12 -0800 Subject: [PATCH 0610/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 1b9335f13b..c4909f2428 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.20.4 \ No newline at end of file +1.20.5-SNAPSHOT \ No newline at end of file From 456dc02465b2d767e2e0679a5d793251fc1a2715 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 28 Dec 2020 10:46:08 +0100 Subject: [PATCH 0611/1594] [Java] Fix early access JavaDoc location. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index aa9fbf6757..2002411173 100644 --- a/build.gradle +++ b/build.gradle @@ -202,8 +202,8 @@ subprojects { options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' options.links("https://www.javadoc.io/doc/org.agrona/agrona/${agronaVersion}/") - if (buildJavaVersion >= 16) { // Work around for early access versions for which no JavaDoc is published - options.links("https://docs.oracle.com/en/java/javase/15/docs/api/") + if (buildJavaVersion >= 16) { // early access JavaDoc location is different + options.links("https://download.java.net/java/early_access/jdk${buildJavaVersion}/docs/api/") } else if (buildJavaVersion >= 11) { options.links("https://docs.oracle.com/en/java/javase/${buildJavaVersion}/docs/api/") From 8538731b0db513a1e6718147da6f0df39027dd42 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 30 Dec 2020 15:32:52 +0000 Subject: [PATCH 0612/1594] [Java] Add javadoc to enum methods. --- build.gradle | 1 + .../java/uk/co/real_logic/sbe/SbeTool.java | 2 +- .../sbe/generation/java/JavaGenerator.java | 18 +++++++++++++++--- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index aa9fbf6757..d7a1b7ab62 100644 --- a/build.gradle +++ b/build.gradle @@ -427,6 +427,7 @@ project(':sbe-samples') { 'sbe.target.language': 'Java', 'sbe.java.generate.interfaces': 'true', 'sbe.validation.stop.on.error': 'true', + 'sbe.decode.unknown.enum.values': 'true', 'sbe.xinclude.aware': 'true', 'sbe.validation.xsd': validationXsdPath) args = ['src/main/resources/example-schema.xml', 'src/main/resources/example-extension-schema.xml'] diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index 95e914a706..5d9a1ac976 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -58,7 +58,7 @@ *
  • sbe.csharp.generate.namespace.dir: Should a directory be created for the namespace under * the output directory? Defaults to true
  • *
  • sbe.keyword.append.token: Token to be appended to keywords.
  • - *
  • sbe.decode.unknown.enum.values: Support unknown decoded enum values.
  • + *
  • sbe.decode.unknown.enum.values: Support unknown decoded enum values. Defaults to false.
  • *
  • sbe.xinclude.aware: Is XInclude supported for the schema. Defaults to false.
  • * */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 05c25c19f6..43f00a560a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1488,7 +1488,7 @@ private CharSequence generateEnumValues(final List tokens) if (shouldDecodeUnknownEnumValues) { sb.append(INDENT).append("/**\n"); - sb.append(INDENT).append(" * To be used to represent a not known value from a later version.\n"); + sb.append(INDENT).append(" * To be used to represent a unknown value from a later version.\n"); sb.append(INDENT).append(" */\n"); sb.append(INDENT).append("SBE_UNKNOWN").append('(').append(nullVal).append("),\n\n"); } @@ -1511,6 +1511,11 @@ private CharSequence generateEnumBody(final Token token, final String enumName) " {\n" + " this.value = value;\n" + " }\n\n" + + " /**\n" + + " * The raw encoded value in the Java type representation.\n" + + " *\n" + + " * @return the raw value encoded.\n" + + " */\n" + " public " + javaEncodingType + " value()\n" + " {\n" + " return value;\n" + @@ -1520,9 +1525,16 @@ private CharSequence generateEnumBody(final Token token, final String enumName) private CharSequence generateEnumLookupMethod(final List tokens, final String enumName) { final StringBuilder sb = new StringBuilder(); - final PrimitiveType primitiveType = tokens.get(0).encoding().primitiveType(); - sb.append("\n").append(" public static ").append(enumName) + + sb.append("\n") + .append(" /**\n") + .append(" * Lookup the enum value representing the value.\n") + .append(" *\n") + .append(" * @param value encoded to be looked up.\n") + .append(" * @return the enum value representing the value.\n") + .append(" */\n") + .append(" public static ").append(enumName) .append(" get(final ").append(javaTypeName(primitiveType)).append(" value)\n").append(" {\n") .append(" switch (value)\n").append(" {\n"); From 5dacc79d78ba8371b325b4d3005afc04e7abc777 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 31 Dec 2020 15:46:59 +0000 Subject: [PATCH 0613/1594] [C++] Add optional support for decoding unknown enum values. --- .../generation/TargetCodeGeneratorLoader.java | 5 +- .../sbe/generation/cpp/CppGenerator.java | 57 +++++++++++++------ .../sbe/generation/cpp/CppGeneratorTest.java | 2 +- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index ae0b51d873..81b800c754 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -69,7 +69,10 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) { public CodeGenerator newInstance(final Ir ir, final String outputDir) { - return new CppGenerator(ir, new NamespaceOutputManager(outputDir, ir.applicableNamespace())); + return new CppGenerator( + ir, + Boolean.getBoolean(DECODE_UNKNOWN_ENUM_VALUES), + new NamespaceOutputManager(outputDir, ir.applicableNamespace())); } }, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index d293b826df..b965d068c5 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -50,13 +50,15 @@ public class CppGenerator implements CodeGenerator private final Ir ir; private final OutputManager outputManager; + private final boolean shouldDecodeUnknownEnumValues; - public CppGenerator(final Ir ir, final OutputManager outputManager) + public CppGenerator(final Ir ir, final boolean shouldDecodeUnknownEnumValues, final OutputManager outputManager) { Verify.notNull(ir, "ir"); Verify.notNull(outputManager, "outputManager"); this.ir = ir; + this.shouldDecodeUnknownEnumValues = shouldDecodeUnknownEnumValues; this.outputManager = outputManager; } @@ -902,16 +904,20 @@ private CharSequence generateEnumValues(final List tokens, final Token en sb.append(" ").append(token.name()).append(" = ").append(constVal).append(",\n"); } - sb.append(String.format( - " NULL_VALUE = %1$s", - generateLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString()))); + final CharSequence nullLiteral = generateLiteral( + encoding.primitiveType(), encoding.applicableNullValue().toString()); + if (shouldDecodeUnknownEnumValues) + { + sb.append(" SBE_UNKNOWN = ").append(nullLiteral).append(",\n"); + } + sb.append(" NULL_VALUE = ").append(nullLiteral); sb.append("\n };\n\n"); return sb; } - private static CharSequence generateEnumLookupMethod(final List tokens, final Token encodingToken) + private CharSequence generateEnumLookupMethod(final List tokens, final Token encodingToken) { final String enumName = formatClassName(encodingToken.applicableTypeName()); final StringBuilder sb = new StringBuilder(); @@ -932,17 +938,23 @@ private static CharSequence generateEnumLookupMethod(final List tokens, f sb.append(" case ").append(constVal).append(": return ").append(token.name()).append(";\n"); } - final CharSequence constVal = generateLiteral( + final CharSequence nullVal = generateLiteral( encodingToken.encoding().primitiveType(), encodingToken.encoding().applicableNullValue().toString()); - new Formatter(sb).format( - " case %1$s: return NULL_VALUE;\n" + - " }\n\n" + + sb.append(" case ").append(nullVal).append(": return NULL_VALUE;\n") + .append(" }\n\n"); - " throw std::runtime_error(\"unknown value for enum %2$s [E103]\");\n" + - " }\n", - constVal, - enumName); + if (shouldDecodeUnknownEnumValues) + { + sb.append(" return SBE_UNKNOWN;\n").append(" }\n"); + } + else + { + new Formatter(sb).format( + " throw std::runtime_error(\"unknown value for enum %s [E103]\");\n" + + " }\n", + enumName); + } return sb; } @@ -2775,12 +2787,21 @@ private CharSequence generateEnumDisplay(final List tokens, final Token e token.name()); } - new Formatter(sb).format( - " case NULL_VALUE: return \"NULL_VALUE\";\n" + - " }\n\n" + - " throw std::runtime_error(\"unknown value for enum %1$s [E103]:\");\n" + - " }\n\n" + + sb.append(" case NULL_VALUE: return \"NULL_VALUE\";\n").append(" }\n\n"); + if (shouldDecodeUnknownEnumValues) + { + sb.append(" return \"SBE_UNKNOWN\";\n").append(" }\n\n"); + } + else + { + new Formatter(sb).format( + " throw std::runtime_error(\"unknown value for enum %1$s [E103]:\");\n" + + " }\n\n", + enumName); + } + + new Formatter(sb).format( " template\n" + " friend std::basic_ostream& operator << (\n" + " std::basic_ostream& os, %1$s::Value m)\n" + diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index 95902bc6d9..91fec0293f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -39,7 +39,7 @@ public void shouldUseGeneratedLiteralForConstantOneWhenGeneratingBitsetCode() th final StringWriterOutputManager outputManager = new StringWriterOutputManager(); outputManager.setPackageName(ir.applicableNamespace()); - final CppGenerator generator = new CppGenerator(ir, outputManager); + final CppGenerator generator = new CppGenerator(ir, false, outputManager); generator.generate(); final String source = outputManager.getSource("issue827.FlagsSet").toString(); From 15b23b81cb909d6f4b3ad0370b8109803437408b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 31 Dec 2020 16:13:36 +0000 Subject: [PATCH 0614/1594] [C++] Null terminate constant char arrays to avoid warnings. Issue #832. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index b965d068c5..cdf677707a 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1717,7 +1717,7 @@ private void generateConstPropertyMethods( new Formatter(sb).format("\n" + indent + " SBE_NODISCARD const char *%1$s() const\n" + indent + " {\n" + - indent + " static const std::uint8_t %1$sValues[] = { %2$s };\n\n" + + indent + " static const std::uint8_t %1$sValues[] = { %2$s, 0 };\n\n" + indent + " return (const char *)%1$sValues;\n" + indent + " }\n", @@ -1727,7 +1727,7 @@ private void generateConstPropertyMethods( sb.append(String.format("\n" + indent + " SBE_NODISCARD %1$s %2$s(const std::uint64_t index) const\n" + indent + " {\n" + - indent + " static const std::uint8_t %2$sValues[] = { %3$s };\n\n" + + indent + " static const std::uint8_t %2$sValues[] = { %3$s, 0 };\n\n" + indent + " return (char)%2$sValues[index];\n" + indent + " }\n", From b1b905ec7821f4caeb04ac9526577d782e02c236 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 1 Jan 2021 12:40:14 +0000 Subject: [PATCH 0615/1594] [C++] Consistent use of std namespace. --- .../sbe/generation/cpp/CppGenerator.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index cdf677707a..0ed6106537 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -525,7 +525,7 @@ private void generateVarData( indent + " std::uint64_t bytesToCopy = length < dataLength ? length : dataLength;\n" + indent + " std::uint64_t pos = sbePosition();\n" + indent + " sbePosition(pos + dataLength);\n" + - indent + " std::memcpy(dst, m_buffer + pos, static_cast(bytesToCopy));\n" + + indent + " std::memcpy(dst, m_buffer + pos, static_cast(bytesToCopy));\n" + indent + " return bytesToCopy;\n" + indent + " }\n", propertyName, @@ -1502,7 +1502,7 @@ private void generateArrayProperty( "%3$s" + indent + " std::memcpy(dst, m_buffer + m_offset + %4$d, " + - "sizeof(%5$s) * static_cast(length));\n" + + "sizeof(%5$s) * static_cast(length));\n" + indent + " return length;\n" + indent + " }\n", toUpperFirstChar(propertyName), @@ -1564,7 +1564,7 @@ private void generateArrayProperty( indent + " SBE_NODISCARD std::string get%1$sAsString() const\n" + indent + " {\n" + indent + " const char *buffer = m_buffer + m_offset + %2$d;\n" + - indent + " size_t length = 0;\n\n" + + indent + " std::size_t length = 0;\n\n" + indent + " for (; length < %3$d && *(buffer + length) != '\\0'; ++length);\n" + indent + " std::string result(buffer, length);\n\n" + @@ -1582,7 +1582,7 @@ private void generateArrayProperty( indent + " SBE_NODISCARD std::string_view get%1$sAsStringView() const SBE_NOEXCEPT\n" + indent + " {\n" + indent + " const char *buffer = m_buffer + m_offset + %2$d;\n" + - indent + " size_t length = 0;\n\n" + + indent + " std::size_t length = 0;\n\n" + indent + " for (; length < %3$d && *(buffer + length) != '\\0'; ++length);\n" + indent + " std::string_view result(buffer, length);\n\n" + @@ -1598,14 +1598,14 @@ private void generateArrayProperty( indent + " #if __cplusplus >= 201703L\n" + indent + " %1$s &put%2$s(const std::string_view str)\n" + indent + " {\n" + - indent + " const size_t srcLength = str.length();\n" + + indent + " const std::size_t srcLength = str.length();\n" + indent + " if (srcLength > %4$d)\n" + indent + " {\n" + indent + " throw std::runtime_error(\"string too large for put%2$s [E106]\");\n" + indent + " }\n\n" + indent + " std::memcpy(m_buffer + m_offset + %3$d, str.data(), srcLength);\n" + - indent + " for (size_t start = srcLength; start < %4$d; ++start)\n" + + indent + " for (std::size_t start = srcLength; start < %4$d; ++start)\n" + indent + " {\n" + indent + " m_buffer[m_offset + %3$d + start] = 0;\n" + indent + " }\n\n" + @@ -1615,14 +1615,14 @@ private void generateArrayProperty( indent + " #else\n" + indent + " %1$s &put%2$s(const std::string& str)\n" + indent + " {\n" + - indent + " const size_t srcLength = str.length();\n" + + indent + " const std::size_t srcLength = str.length();\n" + indent + " if (srcLength > %4$d)\n" + indent + " {\n" + indent + " throw std::runtime_error(\"string too large for put%2$s [E106]\");\n" + indent + " }\n\n" + indent + " std::memcpy(m_buffer + m_offset + %3$d, str.c_str(), srcLength);\n" + - indent + " for (size_t start = srcLength; start < %4$d; ++start)\n" + + indent + " for (std::size_t start = srcLength; start < %4$d; ++start)\n" + indent + " {\n" + indent + " m_buffer[m_offset + %3$d + start] = 0;\n" + indent + " }\n\n" + @@ -1742,7 +1742,7 @@ private void generateConstPropertyMethods( indent + " std::uint64_t bytesToCopy = " + "length < sizeof(%2$sValues) ? length : sizeof(%2$sValues);\n\n" + - indent + " std::memcpy(dst, %2$sValues, static_cast(bytesToCopy));\n" + + indent + " std::memcpy(dst, %2$sValues, static_cast(bytesToCopy));\n" + indent + " return bytesToCopy;\n" + indent + " }\n", toUpperFirstChar(propertyName), @@ -2667,7 +2667,8 @@ private void writeTokenDisplay( indent + "builder << '[';\n" + indent + "if (" + fieldName + "Length() > 0)\n" + indent + "{\n" + - indent + " for (size_t i = 0, length = " + fieldName + "Length(); i < length; i++)\n" + + indent + " for (" + + "std::size_t i = 0, length = " + fieldName + "Length(); i < length; i++)\n" + indent + " {\n" + indent + " if (i)\n" + indent + " {\n" + From 517399092b7af1dcbfb1862b1e1e82500a8dde41 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 1 Jan 2021 15:23:58 +0000 Subject: [PATCH 0616/1594] [C++] Provide raw access to enum value for handling unknown case. --- .../sbe/generation/cpp/CppGenerator.java | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 0ed6106537..a77404e44b 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2225,9 +2225,7 @@ private static void generateFieldMetaAttributeMethod( } private static CharSequence generateEnumFieldNotPresentCondition( - final int sinceVersion, - final String enumName, - final String indent) + final int sinceVersion, final String enumName, final String indent) { if (0 == sinceVersion) { @@ -2248,12 +2246,13 @@ private void generateEnumProperty( final String containingClassName, final Token fieldToken, final String propertyName, - final Token token, + final Token encodingToken, final String indent) { - final String enumName = formatClassName(token.applicableTypeName()); - final String typeName = cppTypeName(token.encoding().primitiveType()); - final int offset = token.offset(); + final String enumName = formatClassName(encodingToken.applicableTypeName()); + final PrimitiveType primitiveType = encodingToken.encoding().primitiveType(); + final String typeName = cppTypeName(primitiveType); + final int offset = encodingToken.offset(); new Formatter(sb).format("\n" + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::size_t %1$sEncodingLength() SBE_NOEXCEPT\n" + @@ -2286,9 +2285,31 @@ private void generateEnumProperty( propertyName, generateEnumFieldNotPresentCondition(fieldToken.version(), enumName, indent), constValue.substring(constValue.indexOf(".") + 1)); + + new Formatter(sb).format("\n" + + indent + " SBE_NODISCARD %1$s %2$sRaw() const\n" + + indent + " {\n" + + indent + " return static_cast<%1$s>(%3$s::Value::%4$s);\n" + + indent + " }\n", + typeName, + propertyName, + enumName, + constValue.substring(constValue.indexOf(".") + 1)); } else { + final String offsetStr = Integer.toString(offset); + new Formatter(sb).format("\n" + + indent + " SBE_NODISCARD %1$s %2$sRaw() const SBE_NOEXCEPT\n" + + indent + " {\n" + + "%3$s" + + "%4$s" + + indent + " }\n", + typeName, + propertyName, + generateFieldNotPresentCondition(fieldToken.version(), encodingToken.encoding(), indent), + generateLoadValue(primitiveType, offsetStr, encodingToken.encoding().byteOrder(), indent)); + new Formatter(sb).format("\n" + indent + " SBE_NODISCARD %1$s::Value %2$s() const\n" + indent + " {\n" + @@ -2300,7 +2321,7 @@ private void generateEnumProperty( enumName, propertyName, generateEnumFieldNotPresentCondition(fieldToken.version(), enumName, indent), - formatByteOrderEncoding(token.encoding().byteOrder(), token.encoding().primitiveType()), + formatByteOrderEncoding(encodingToken.encoding().byteOrder(), primitiveType), typeName, offset); @@ -2316,7 +2337,7 @@ private void generateEnumProperty( enumName, typeName, offset, - formatByteOrderEncoding(token.encoding().byteOrder(), token.encoding().primitiveType())); + formatByteOrderEncoding(encodingToken.encoding().byteOrder(), primitiveType)); } } From b2b30ce3ade2ecfd2c24c3a036b2f3f6664f9434 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 1 Jan 2021 15:24:25 +0000 Subject: [PATCH 0617/1594] [C++] Fix formatting. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index a77404e44b..7d5eef9300 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2287,10 +2287,10 @@ private void generateEnumProperty( constValue.substring(constValue.indexOf(".") + 1)); new Formatter(sb).format("\n" + - indent + " SBE_NODISCARD %1$s %2$sRaw() const\n" + - indent + " {\n" + - indent + " return static_cast<%1$s>(%3$s::Value::%4$s);\n" + - indent + " }\n", + indent + " SBE_NODISCARD %1$s %2$sRaw() const\n" + + indent + " {\n" + + indent + " return static_cast<%1$s>(%3$s::Value::%4$s);\n" + + indent + " }\n", typeName, propertyName, enumName, From 0fc9263b688c3e0c947a7231e245303a9621f87a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 1 Jan 2021 15:26:37 +0000 Subject: [PATCH 0618/1594] [C++] Raw access can be noexcept. --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 7d5eef9300..0da9907dda 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2287,7 +2287,7 @@ private void generateEnumProperty( constValue.substring(constValue.indexOf(".") + 1)); new Formatter(sb).format("\n" + - indent + " SBE_NODISCARD %1$s %2$sRaw() const\n" + + indent + " SBE_NODISCARD %1$s %2$sRaw() const SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return static_cast<%1$s>(%3$s::Value::%4$s);\n" + indent + " }\n", From 3633676c3192cca33ff363c8e285bd1375cbde0d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 2 Jan 2021 15:34:15 +0000 Subject: [PATCH 0619/1594] [Java] Generate final classes to improve performance. --- .../real_logic/sbe/generation/java/JavaGenerator.java | 6 +++--- .../real_logic/sbe/ir/generated/ByteOrderCodec.java | 11 +++++++++++ .../sbe/ir/generated/FrameCodecDecoder.java | 2 +- .../sbe/ir/generated/FrameCodecEncoder.java | 2 +- .../sbe/ir/generated/MessageHeaderDecoder.java | 2 +- .../sbe/ir/generated/MessageHeaderEncoder.java | 2 +- .../co/real_logic/sbe/ir/generated/PresenceCodec.java | 11 +++++++++++ .../sbe/ir/generated/PrimitiveTypeCodec.java | 11 +++++++++++ .../co/real_logic/sbe/ir/generated/SignalCodec.java | 11 +++++++++++ .../sbe/ir/generated/TokenCodecDecoder.java | 2 +- .../sbe/ir/generated/TokenCodecEncoder.java | 2 +- .../sbe/ir/generated/VarDataEncodingDecoder.java | 2 +- .../sbe/ir/generated/VarDataEncodingEncoder.java | 2 +- 13 files changed, 55 insertions(+), 11 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 43f00a560a..d7f6075b0b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -570,7 +570,7 @@ private void generateGroupDecoderClassDeclaration( final String className = formatClassName(groupName); new Formatter(sb).format("\n" + - indent + "public static class %1$s\n" + + indent + "public static final class %1$s\n" + indent + " implements Iterable<%1$s>, java.util.Iterator<%1$s>\n" + indent + "{\n" + indent + " public static final int HEADER_SIZE = %2$d;\n" + @@ -622,7 +622,7 @@ private void generateGroupEncoderClassDeclaration( final String className = encoderName(groupName); new Formatter(sb).format("\n" + - indent + "public static class %1$s\n" + + indent + "public static final class %1$s\n" + indent + "{\n" + indent + " public static final int HEADER_SIZE = %2$d;\n" + indent + " private final %3$s parentMessage;\n" + @@ -1659,7 +1659,7 @@ private static CharSequence generateDeclaration( generateTypeJavadoc(sb, BASE_INDENT, typeToken); sb.append("@SuppressWarnings(\"all\")\n") - .append("public class ").append(className).append(implementsString).append('\n') + .append("public final class ").append(className).append(implementsString).append('\n') .append("{\n"); return sb; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java index b4333b26bd..cec61c4eed 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java @@ -23,11 +23,22 @@ public enum ByteOrderCodec this.value = value; } + /** + * The raw encoded value in the Java type representation. + * + * @return the raw value encoded. + */ public short value() { return value; } + /** + * Lookup the enum value representing the value. + * + * @param value encoded to be looked up. + * @return the enum value representing the value. + */ public static ByteOrderCodec get(final short value) { switch (value) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index d8b5d2cdd7..9325c7d381 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -9,7 +9,7 @@ * Frame Header for start of encoding IR */ @SuppressWarnings("all") -public class FrameCodecDecoder +public final class FrameCodecDecoder { public static final int BLOCK_LENGTH = 12; public static final int TEMPLATE_ID = 1; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index 2d935add3b..e2534e99b9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -9,7 +9,7 @@ * Frame Header for start of encoding IR */ @SuppressWarnings("all") -public class FrameCodecEncoder +public final class FrameCodecEncoder { public static final int BLOCK_LENGTH = 12; public static final int TEMPLATE_ID = 1; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java index 28ab81a578..04223e1e06 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java @@ -8,7 +8,7 @@ * Message identifiers and length of message root */ @SuppressWarnings("all") -public class MessageHeaderDecoder +public final class MessageHeaderDecoder { public static final int SCHEMA_ID = 1; public static final int SCHEMA_VERSION = 0; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java index c08dc8d2fe..6aa30f16eb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java @@ -8,7 +8,7 @@ * Message identifiers and length of message root */ @SuppressWarnings("all") -public class MessageHeaderEncoder +public final class MessageHeaderEncoder { public static final int SCHEMA_ID = 1; public static final int SCHEMA_VERSION = 0; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java index c4a389de45..638926218e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java @@ -25,11 +25,22 @@ public enum PresenceCodec this.value = value; } + /** + * The raw encoded value in the Java type representation. + * + * @return the raw value encoded. + */ public short value() { return value; } + /** + * Lookup the enum value representing the value. + * + * @param value encoded to be looked up. + * @return the enum value representing the value. + */ public static PresenceCodec get(final short value) { switch (value) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java index daaf41dd03..4dca2be18d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java @@ -43,11 +43,22 @@ public enum PrimitiveTypeCodec this.value = value; } + /** + * The raw encoded value in the Java type representation. + * + * @return the raw value encoded. + */ public short value() { return value; } + /** + * Lookup the enum value representing the value. + * + * @param value encoded to be looked up. + * @return the enum value representing the value. + */ public static PrimitiveTypeCodec get(final short value) { switch (value) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java index 60c88309b3..3a932483bc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java @@ -53,11 +53,22 @@ public enum SignalCodec this.value = value; } + /** + * The raw encoded value in the Java type representation. + * + * @return the raw value encoded. + */ public short value() { return value; } + /** + * Lookup the enum value representing the value. + * + * @param value encoded to be looked up. + * @return the enum value representing the value. + */ public static SignalCodec get(final short value) { switch (value) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index e283d77025..80cc4f5e47 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -9,7 +9,7 @@ * Codec for an IR Token */ @SuppressWarnings("all") -public class TokenCodecDecoder +public final class TokenCodecDecoder { public static final int BLOCK_LENGTH = 28; public static final int TEMPLATE_ID = 2; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index 6f12733d1f..1af7ed2f53 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -9,7 +9,7 @@ * Codec for an IR Token */ @SuppressWarnings("all") -public class TokenCodecEncoder +public final class TokenCodecEncoder { public static final int BLOCK_LENGTH = 28; public static final int TEMPLATE_ID = 2; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java index 819fa7a973..b227f42d29 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java @@ -8,7 +8,7 @@ * Header for var data fields */ @SuppressWarnings("all") -public class VarDataEncodingDecoder +public final class VarDataEncodingDecoder { public static final int SCHEMA_ID = 1; public static final int SCHEMA_VERSION = 0; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java index 74cb0aa239..1909b37f7d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java @@ -8,7 +8,7 @@ * Header for var data fields */ @SuppressWarnings("all") -public class VarDataEncodingEncoder +public final class VarDataEncodingEncoder { public static final int SCHEMA_ID = 1; public static final int SCHEMA_VERSION = 0; From 45ef14c52e99170f6afffd38917a99366c340421 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 2 Jan 2021 15:38:53 +0000 Subject: [PATCH 0620/1594] Update copyright. --- CMakeLists.txt | 2 +- CONTRIBUTING.md | 2 +- build.gradle | 2 +- sbe-benchmarks/src/main/cpp/CMakeLists.txt | 2 +- sbe-benchmarks/src/main/cpp/CarBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/CodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/MarketDataBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/benchlet-main.cpp | 2 +- sbe-benchmarks/src/main/cpp/benchlet.h | 2 +- .../src/main/java/uk/co/real_logic/sbe/CarBenchmark.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/package-info.java | 2 +- sbe-samples/src/main/cpp/CMakeLists.txt | 2 +- sbe-samples/src/main/cpp/GeneratedStubExample.cpp | 2 +- sbe-samples/src/main/cpp/OtfExample.cpp | 2 +- .../uk/co/real_logic/sbe/examples/ExampleTokenListener.java | 2 +- .../co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java | 2 +- .../sbe/examples/ExampleUsingGeneratedStubExtension.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java | 2 +- .../main/java/uk/co/real_logic/sbe/examples/package-info.java | 2 +- sbe-tool/src/main/cpp/CMakeLists.txt | 2 +- sbe-tool/src/main/cpp/otf/Encoding.h | 2 +- sbe-tool/src/main/cpp/otf/IrDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/Token.h | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java | 2 +- .../main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java | 2 +- .../java/uk/co/real_logic/sbe/codec/java/MethodSelector.java | 2 +- .../main/java/uk/co/real_logic/sbe/codec/java/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/CodeGenerator.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/Generators.java | 2 +- .../uk/co/real_logic/sbe/generation/TargetCodeGenerator.java | 2 +- .../co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/c/COutputManager.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/c/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java | 2 +- .../real_logic/sbe/generation/cpp/NamespaceOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/cpp/package-info.java | 2 +- .../uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java | 2 +- .../sbe/generation/csharp/CSharpNamespaceOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/csharp/package-info.java | 2 +- .../uk/co/real_logic/sbe/generation/golang/package-info.java | 2 +- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/JavaUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/package-info.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/package-info.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/package-info.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java | 2 +- .../main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/json/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java | 2 +- .../main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java | 2 +- .../main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/otf/package-info.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/package-info.java | 2 +- sbe-tool/src/test/c/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/c/CMakeLists.txt | 2 +- sbe-tool/src/test/c/CodeGenTest.cpp | 2 +- sbe-tool/src/test/c/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/cpp/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/cpp/CMakeLists.txt | 2 +- sbe-tool/src/test/cpp/CodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeElementsTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp | 2 +- sbe-tool/src/test/cpp/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp | 2 +- sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp | 2 +- .../src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java | 2 +- .../test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java | 2 +- sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java | 2 +- .../test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java | 2 +- .../uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java | 2 +- .../sbe/generation/java/CompositeElementsGenerationTest.java | 2 +- .../real_logic/sbe/generation/java/ConstantCharArrayTest.java | 2 +- .../sbe/generation/java/FixedSizeDataGeneratorTest.java | 2 +- .../real_logic/sbe/generation/java/GenerateFixBinaryTest.java | 2 +- .../real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java | 2 +- .../sbe/generation/java/PackageOutputManagerTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/ReflectionUtil.java | 2 +- .../co/real_logic/sbe/generation/java/SchemaExtensionTest.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/ToStringTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java | 2 +- .../co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java | 2 +- 139 files changed, 139 insertions(+), 139 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a5d9180b14..1b8a969c05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2020 Real Logic Limited. +# Copyright 2013-2021 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4b67622291..882484f46e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ If you are adding a new file it should have the following header: ``` /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/build.gradle b/build.gradle index be97d10348..1ff9c3e48e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/CMakeLists.txt b/sbe-benchmarks/src/main/cpp/CMakeLists.txt index 2165c6c3d7..51aa80dca9 100644 --- a/sbe-benchmarks/src/main/cpp/CMakeLists.txt +++ b/sbe-benchmarks/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2020 Real Logic Limited. +# Copyright 2013-2021 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/CarBench.cpp b/sbe-benchmarks/src/main/cpp/CarBench.cpp index 9c789203c4..fd33ba06ae 100644 --- a/sbe-benchmarks/src/main/cpp/CarBench.cpp +++ b/sbe-benchmarks/src/main/cpp/CarBench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/CodecBench.h b/sbe-benchmarks/src/main/cpp/CodecBench.h index 0cc71b3309..f704b3352c 100644 --- a/sbe-benchmarks/src/main/cpp/CodecBench.h +++ b/sbe-benchmarks/src/main/cpp/CodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp index 56df14ee27..fd0cd221a5 100644 --- a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp +++ b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h index e7c4478b7d..615c6ba108 100644 --- a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h index 1af630f8c5..18723e9714 100644 --- a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp index 9dc05bda18..3515ce1b31 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp +++ b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/benchlet.h b/sbe-benchmarks/src/main/cpp/benchlet.h index fa4b5926b9..351c3e3dc6 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet.h +++ b/sbe-benchmarks/src/main/cpp/benchlet.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java index 87effdb2b3..43bfc15a5f 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java index 2a95866ce9..125af11b69 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java index 72f29bd291..c23c5cbf62 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/CMakeLists.txt b/sbe-samples/src/main/cpp/CMakeLists.txt index 73a313af81..5c5eba141a 100644 --- a/sbe-samples/src/main/cpp/CMakeLists.txt +++ b/sbe-samples/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2020 Real Logic Limited. +# Copyright 2013-2021 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index d2303392d6..5a5a454e15 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/OtfExample.cpp b/sbe-samples/src/main/cpp/OtfExample.cpp index 249398027b..e611952503 100644 --- a/sbe-samples/src/main/cpp/OtfExample.cpp +++ b/sbe-samples/src/main/cpp/OtfExample.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java index 6c95440185..5f11e3fa7d 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java index 4faaff8839..e7968d42cb 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java index 1d78e4ca86..6839c4db70 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java index 4b6a1a530e..d682400374 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java index cb509a8b33..4365a35946 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/CMakeLists.txt b/sbe-tool/src/main/cpp/CMakeLists.txt index b0a0a91611..5306731b2d 100644 --- a/sbe-tool/src/main/cpp/CMakeLists.txt +++ b/sbe-tool/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2020 Real Logic Limited. +# Copyright 2013-2021 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/Encoding.h b/sbe-tool/src/main/cpp/otf/Encoding.h index 14ca5d1be1..4607508c0e 100644 --- a/sbe-tool/src/main/cpp/otf/Encoding.h +++ b/sbe-tool/src/main/cpp/otf/Encoding.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index 2c1af69b22..6f116f4eef 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h index aef532ac59..b68d6b9d67 100644 --- a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h index d263f69ad4..9d646637a2 100644 --- a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/Token.h b/sbe-tool/src/main/cpp/otf/Token.h index 28c53855ad..6cf5bb5b17 100644 --- a/sbe-tool/src/main/cpp/otf/Token.h +++ b/sbe-tool/src/main/cpp/otf/Token.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java index 6f37fbef0f..7fe416e754 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index f0e8a31d77..b46c9babb9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index 5d9a1ac976..565aea2145 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index 3f0bec26df..261ae82a97 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java index a0086feb5e..f2834a2a17 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java index f2112e2a52..281eeb8a11 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java index cb198bd9bc..7f1c6eaa83 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java index 23bb089e3b..e5e43a10a5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java index 8b9d02c964..3c2e2216b7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java index 7575ca3b79..495641924b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 81b800c754..2bcb3bf0b7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 7e113a9548..34f7b374ce 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java index 11354f8df3..29c7530b15 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java index ba95b8343c..40e8b9ce80 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java index 0da617ddfc..055906cf21 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 0da9907dda..6d3c9d916a 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index 37b0c51ddb..d03c1c41d0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java index aa74ef4a6a..e6692adc28 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java index 0f8654dfb4..211ee9b813 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 1249ceab93..942b1382d6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java index b3d7c20c26..9dca1481b2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index d86109f7e8..a43b5ce522 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java index ee8f94bd4d..fd0fb30ac8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java index 205dd94217..e52fa637bd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index d7f6075b0b..45b6acfb34 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 1d66e6cd1f..dba9022d1e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java index ab6c669136..5207eb5f1c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java index 4b63e831cf..a5562a22b6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java index 96cbc1700b..de1d6304ae 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java index 7d5fbe3d06..4d9fa6276b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java index 9549b82e19..8bc3144538 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java index 84b4e05b2b..9c3f497deb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index db6b07d1bc..420b955864 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java index e713e16047..da10d93de8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java index d8be88b3ec..f198460ae6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java index 9d922375b4..cf361733d4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index 7111b353a1..c0fb835f52 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java index 285aa0eae1..fdb8989cf5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java index 7265193597..64737c3970 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index fdf98c6fa1..02a8a3a85d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java index 83dd478fb9..3887d90370 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java index 9ffaec5aab..2e1892fe07 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java index efad994192..60f3f2a9ff 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java index db4a2affd5..56c4d6ef7f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java index b7d10cee82..943f5bb40b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java index 9dd2d2fde7..677801179f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java index e91306582e..796ac53ce8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java index 724d6d3dbb..9689cfd029 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index 4e74dd7eed..02010278e3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index 1476896056..8b9a26fde0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index 8fecc2e118..61934496b5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java index ca83e1edbf..d9490a42bb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java index 7f743a3785..7b4a33f0cc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index 58742e1108..80be549ee5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -1,4 +1,4 @@ -/* Copyright 2013-2020 Real Logic Limited. +/* Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java index 541893d2e5..4320d267d4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index 416d27b7f5..04b20183d8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java index ed753140ef..2a88afa691 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java @@ -1,6 +1,6 @@ /* -*- mode: java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java index 510b5bf7f4..8c3697f311 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index d0167f5f3f..b614b83ead 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java index 4553db0c8d..850ff02398 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 9353e31849..e20562b4f5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java index e755851de6..e1d75032cf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/BoundsCheckTest.cpp b/sbe-tool/src/test/c/BoundsCheckTest.cpp index 64b2141e25..0b17a3d9a0 100644 --- a/sbe-tool/src/test/c/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/c/BoundsCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index aff6c9aa7d..97043728fa 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2020 Real Logic Limited. +# Copyright 2013-2021 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index b9fa61baff..841d749ad2 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/GroupWithDataTest.cpp b/sbe-tool/src/test/c/GroupWithDataTest.cpp index b7c3b91e99..f796fc0d9d 100644 --- a/sbe-tool/src/test/c/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/c/GroupWithDataTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp index fca2b0740f..8fe13f6fb1 100644 --- a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index 267f2109bb..5345e93eb4 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2020 Real Logic Limited. +# Copyright 2013-2021 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index c78ffddd17..caea987a7f 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp index e423b453de..4a67d59144 100644 --- a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp index cf193c3a11..5861549525 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp index 3aabea3243..c3dd645504 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp index ab2c5502fc..af695b54ba 100644 --- a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp index 9c5c576a22..ec0a6b0844 100644 --- a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp +++ b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp index 45ece4e655..edf4e878c7 100644 --- a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp +++ b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java index 988118b39e..14679eb22c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java index 0a39a3bbde..b49797e788 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java index 5364804ad5..54f1fc0adb 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java index e81b52a712..ea148677fc 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java index 13747e94f4..bcfe7b5fc0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index 91fec0293f..5106c1a7bf 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java index 5fba2e830d..462546a9d3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java index 73c304d3f4..db15186444 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java index b890f24bc5..be2c9556f7 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java index 450737cbf0..d0351dfc76 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java index aff95815a2..93925c5206 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index b1b790732c..14726825a1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java index a995d1fd7c..465e9c6738 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java index 60e604be0b..03fdf60176 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index 603f025ea9..e3afb850f0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java index 301a61f4f1..1576ec9ea9 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index f18c4076c8..a543f737ca 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java index bfa392be71..ea79e33f30 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java index 3aeb001d71..298468d454 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java index 3c40e56ce5..f76f153f34 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index a09fef7f3a..f63b7aef35 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java index 36d54ac5c5..2e1a7861b5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java index 13e7824454..33dcac5396 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java index bc2e9835f1..7792413a94 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java index 8ed8c345c3..350515db92 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java index 4f9182bb89..d60d49c838 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java index f1504ffa45..6ea423f870 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java index 0644df5422..c3657df172 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java index 33712faced..2262665723 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index 46bba8a77a..4e31d104be 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index 922a98af95..0fdd149c40 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index 3613f84fd4..8e187211b0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * Copyright 2017 MarketFactory Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java index 8d5b0bcf0f..f9c1f8da5e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java index 05f4df47cd..9e37f61749 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java index 838ad339d9..68b7915d3a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index 6eaf133380..ed49028ff5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 Real Logic Limited. + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From ab94844ca2e0b258e894d20e89b7f2614e10a630 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 2 Jan 2021 15:44:00 +0000 Subject: [PATCH 0621/1594] Update copyright. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4c7a34ac3e..5e18d745cd 100644 --- a/README.md +++ b/README.md @@ -112,8 +112,8 @@ Developers wishing to enhance the CSharp generator should see the [developer doc License (See LICENSE file for full license) ------------------------------------------- -Copyright 2013-2020 Real Logic Limited -Copyright 2017 MarketFactory Inc +Copyright 2013-2021 Real Logic Limited. +Copyright 2017 MarketFactory Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 2076d2507044851b8d95e8cd706513fd666fdfeb Mon Sep 17 00:00:00 2001 From: vdaniloff Date: Tue, 12 Jan 2021 16:24:28 +0300 Subject: [PATCH 0622/1594] added maximum and minimum meta methods for allowed repeating group count (#834) --- .../sbe/generation/java/JavaGenerator.java | 9 +++++++++ .../sbe/generation/java/JavaGeneratorTest.java | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 45b6acfb34..71bf12917a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -483,6 +483,15 @@ private void generateGroupEncoderClassHeader( blockLengthType, blockLengthOffset, blockLengthValue, byteOrderString(blockLengthToken.encoding())); final PrimitiveType numInGroupType = numInGroupToken.encoding().primitiveType(); + + final String javaTypeName = javaTypeName(numInGroupType); + final String minValue = generateLiteral(numInGroupType, + numInGroupToken.encoding().applicableMinValue().toString()); + generatePrimitiveFieldMetaMethod(sb, ind, javaTypeName, "count", "Min", minValue); + final String maxValue = generateLiteral(numInGroupType, + numInGroupToken.encoding().applicableMaxValue().toString()); + generatePrimitiveFieldMetaMethod(sb, ind, javaTypeName, "count", "Max", maxValue); + final PrimitiveType newInGroupTypeCast = PrimitiveType.UINT32 == numInGroupType ? PrimitiveType.INT32 : numInGroupType; final String numInGroupOffset = "limit + " + numInGroupToken.offset(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 14726825a1..bccbba67c9 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -442,6 +442,22 @@ public void shouldGeneratePutCharSequence() throws Exception assertThat(get(decoder, "vehicleCode"), is("R11R12")); } + @Test + public void shouldGenerateRepeatingGroupCountLimits() throws Exception + { + generator().generate(); + + final String className = "CarEncoder$FuelFiguresEncoder"; + final String fqClassName = ir.applicableNamespace() + "." + className; + + final Class clazz = compile(fqClassName); + final Method minValue = clazz.getMethod("countMinValue"); + assertNotNull(minValue); + assertEquals(0, minValue.invoke(null)); + final Method maxValue = clazz.getMethod("countMaxValue"); + assertNotNull(maxValue); + assertEquals(65534, maxValue.invoke(null)); + } private Class getModelClass(final Object encoder) throws ClassNotFoundException { From b221cdee05fce68a20607f408d5c0b97100d24a8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 12 Jan 2021 13:41:18 +0000 Subject: [PATCH 0623/1594] [Java] Tidy up after merge of PR #834. --- .../sbe/generation/java/JavaGenerator.java | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 71bf12917a..ce627c54e5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -418,6 +418,14 @@ private void generateGroupDecoderClassHeader( .append(indent).append(" return this;\n") .append(indent).append(" }\n"); + final String numInGroupJavaTypeName = javaTypeName(numInGroupType); + final String numInGroupMinValue = generateLiteral( + numInGroupType, numInGroupToken.encoding().applicableMinValue().toString()); + generatePrimitiveFieldMetaMethod(sb, indent, numInGroupJavaTypeName, "count", "Min", numInGroupMinValue); + final String numInGroupMaxValue = generateLiteral( + numInGroupType, numInGroupToken.encoding().applicableMaxValue().toString()); + generatePrimitiveFieldMetaMethod(sb, indent, numInGroupJavaTypeName, "count", "Max", numInGroupMaxValue); + sb.append("\n") .append(indent).append(" public static int sbeHeaderSize()\n") .append(indent).append(" {\n") @@ -484,20 +492,12 @@ private void generateGroupEncoderClassHeader( final PrimitiveType numInGroupType = numInGroupToken.encoding().primitiveType(); - final String javaTypeName = javaTypeName(numInGroupType); - final String minValue = generateLiteral(numInGroupType, - numInGroupToken.encoding().applicableMinValue().toString()); - generatePrimitiveFieldMetaMethod(sb, ind, javaTypeName, "count", "Min", minValue); - final String maxValue = generateLiteral(numInGroupType, - numInGroupToken.encoding().applicableMaxValue().toString()); - generatePrimitiveFieldMetaMethod(sb, ind, javaTypeName, "count", "Max", maxValue); - - final PrimitiveType newInGroupTypeCast = PrimitiveType.UINT32 == numInGroupType ? + final PrimitiveType numInGroupTypeCast = PrimitiveType.UINT32 == numInGroupType ? PrimitiveType.INT32 : numInGroupType; final String numInGroupOffset = "limit + " + numInGroupToken.offset(); final String numInGroupValue = "count"; final String numInGroupPut = generatePut( - newInGroupTypeCast, numInGroupOffset, numInGroupValue, byteOrderString(numInGroupToken.encoding())); + numInGroupTypeCast, numInGroupOffset, numInGroupValue, byteOrderString(numInGroupToken.encoding())); new Formatter(sb).format("\n" + ind + " public void wrap(final %2$s buffer, final int count)\n" + @@ -540,7 +540,7 @@ private void generateGroupEncoderClassHeader( final String countOffset = "initialLimit + " + numInGroupToken.offset(); final String resetCountPut = generatePut( - newInGroupTypeCast, countOffset, numInGroupValue, byteOrderString(numInGroupToken.encoding())); + numInGroupTypeCast, countOffset, numInGroupValue, byteOrderString(numInGroupToken.encoding())); sb.append("\n") .append(ind).append(" public int resetCountToIndex()\n") @@ -550,6 +550,14 @@ private void generateGroupEncoderClassHeader( .append(ind).append(" return count;\n") .append(ind).append(" }\n"); + final String numInGroupJavaTypeName = javaTypeName(numInGroupType); + final String numInGroupMinValue = generateLiteral( + numInGroupType, numInGroupToken.encoding().applicableMinValue().toString()); + generatePrimitiveFieldMetaMethod(sb, ind, numInGroupJavaTypeName, "count", "Min", numInGroupMinValue); + final String numInGroupMaxValue = generateLiteral( + numInGroupType, numInGroupToken.encoding().applicableMaxValue().toString()); + generatePrimitiveFieldMetaMethod(sb, ind, numInGroupJavaTypeName, "count", "Max", numInGroupMaxValue); + sb.append("\n") .append(ind).append(" public static int sbeHeaderSize()\n") .append(ind).append(" {\n") From eaeabfbfb1409d33a701e8eee11b4bd754129a91 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 12 Jan 2021 13:50:06 +0000 Subject: [PATCH 0624/1594] [Java] Upgrade to Checkstyle 8.39 and Mockito 3.7.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 1ff9c3e48e..e2f0c4bbe4 100644 --- a/build.gradle +++ b/build.gradle @@ -45,9 +45,9 @@ def javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } -def checkstyleVersion = '8.38' +def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' -def mockitoVersion = '3.6.28' +def mockitoVersion = '3.7.0' def junitVersion = '5.7.0' def jmhVersion = '1.27' def agronaVersion = '1.9.0' From 890ba441561ff722af95ccd62cbe25fcf645a016 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 14 Jan 2021 11:09:16 +0000 Subject: [PATCH 0625/1594] Fix warnings. --- cppbuild/cppbuild | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cppbuild/cppbuild b/cppbuild/cppbuild index 88763c769c..7fdbb97d71 100755 --- a/cppbuild/cppbuild +++ b/cppbuild/cppbuild @@ -1,12 +1,12 @@ #!/usr/bin/env bash -SOURCE_DIR="`pwd`" -BUILD_DIR="`pwd`/cppbuild/Release" +SOURCE_DIR="$(pwd)" +BUILD_DIR="$(pwd)/cppbuild/Release" ncpus=1 -case "`uname`" in +case "$(uname)" in Darwin* ) - ncpus=`sysctl -n hw.ncpu` + ncpus=$(sysctl -n hw.ncpu) ;; Linux*) ncpus=$(lscpu -p | egrep -v '^#' | wc -l) @@ -17,9 +17,9 @@ echo "Will make with \"-j $ncpus\"." if [ -d "$BUILD_DIR" ] ; then echo "Build directory ($BUILD_DIR) exists, removing." - rm -rf $BUILD_DIR + rm -rf "$BUILD_DIR" fi -mkdir -p $BUILD_DIR +mkdir -p "$BUILD_DIR" -(cd $BUILD_DIR && cmake -G "Unix Makefiles" $SOURCE_DIR && make clean && make -j "$ncpus" all && ctest -C Release --output-on-failure) +(cd "$BUILD_DIR" && cmake -G "Unix Makefiles" "$SOURCE_DIR" && make clean && make -j "$ncpus" all && ctest -C Release --output-on-failure) From b7b9361f7d7eff4f6982843195b982cd7c055877 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 14 Jan 2021 12:06:53 +0000 Subject: [PATCH 0626/1594] Fix Warnings. --- csharp/sbe-dll/sbe-tool.sh | 16 ++++++++-------- gocode/sbe-tool | 18 +++++++++--------- .../java/uk/co/real_logic/sbe/xml/SetType.java | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/csharp/sbe-dll/sbe-tool.sh b/csharp/sbe-dll/sbe-tool.sh index a31127964d..d2fcf8c7f3 100644 --- a/csharp/sbe-dll/sbe-tool.sh +++ b/csharp/sbe-dll/sbe-tool.sh @@ -4,10 +4,10 @@ ROOTDIR=`dirname $0` SBE_JAR=$ROOTDIR/sbe-tool-all.jar -[ -f $SBE_JAR ] || (echo "Missing $SBE_JAR"; exit 1) +[ -f "$SBE_JAR" ] || (echo "Missing $SBE_JAR"; exit 1) function usage { - echo usage: `basename $0` [-d output_dir] -s schema + echo usage: $(basename "$0") [-d output_dir] -s schema } # defaults @@ -22,7 +22,7 @@ while getopts "d:s:" OPT "$@"; do SCHEMA=$OPTARG ;; *) - echo $OPT + echo "$OPT" usage exit 1 ;; @@ -31,12 +31,12 @@ done shift $(($OPTIND - 1)) # Check args -if [ -z $SCHEMA ]; then usage; exit 1; fi -if [ ! -f $SCHEMA ]; then echo no schema at $SCHEMA; exit 1; fi +if [ -z "$SCHEMA" ]; then usage; exit 1; fi +if [ ! -f "$SCHEMA" ]; then echo no schema at "$SCHEMA"; exit 1; fi java \ --Dsbe.output.dir=$OUTPUTDIR \ +-Dsbe.output.dir="$OUTPUTDIR" \ -Dsbe.generate.ir="false" \ -Dsbe.target.language="uk.co.real_logic.sbe.generation.csharp.CSharp" \ --jar $SBE_JAR \ -$SCHEMA +-jar "$SBE_JAR" \ +"$SCHEMA" diff --git a/gocode/sbe-tool b/gocode/sbe-tool index def3aae312..61e4c903e1 100755 --- a/gocode/sbe-tool +++ b/gocode/sbe-tool @@ -1,13 +1,13 @@ #! /usr/bin/env bash -ROOTDIR=`dirname $0`/.. -SBE_TOOL_VERSION=`cat $ROOTDIR/version.txt` +ROOTDIR=$(dirname "$0")/.. +SBE_TOOL_VERSION=$(cat "$ROOTDIR"/version.txt) SBE_JAR=$ROOTDIR/sbe-all/build/libs/sbe-all-$SBE_TOOL_VERSION.jar [ -f $SBE_JAR ] || (echo "Missing $SBE_JAR. Run gradle first"; exit 1) function usage { - echo usage: `basename $0` [-d output_dir] -s schema + echo usage: $(basename "$0") [-d output_dir] -s schema } # defaults @@ -22,7 +22,7 @@ while getopts "d:s:" OPT "$@"; do SCHEMA=$OPTARG ;; *) - echo $OPT + echo "$OPT" usage exit 1 ;; @@ -31,12 +31,12 @@ done shift $(($OPTIND - 1)) # Check args -[ -z $SCHEMA ] && (usage; exit 1) -[ -f $SCHEMA ] || (echo invalid schema $SCHEMA; exit 1) +[ -z "$SCHEMA" ] && (usage; exit 1) +[ -f "$SCHEMA" ] || (echo invalid schema "$SCHEMA"; exit 1) java \ --Dsbe.output.dir=$OUTPUTDIR \ +-Dsbe.output.dir="$OUTPUTDIR" \ -Dsbe.generate.ir="false" \ -Dsbe.target.language="golang" \ --jar $SBE_JAR \ -$SCHEMA +-jar "$SBE_JAR" \ +"$SCHEMA" diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index b614b83ead..6dd1692734 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -221,7 +221,7 @@ public Choice(final Node node, final PrimitiveType encodingType) deprecated = Integer.parseInt(getAttributeValue(node, "deprecated", "0")); // choice values are bit positions (0, 1, 2, 3, 4, etc.) from LSB to MSB - if (value.longValue() >= (encodingType.size() * 8)) + if (value.longValue() >= (encodingType.size() * 8L)) { throw new IllegalArgumentException("Choice value out of bounds: " + value.longValue()); } From ada399d161d4713eca24079ccc40b72592c80ef8 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 15 Jan 2021 11:35:54 -0800 Subject: [PATCH 0627/1594] 1.21.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index c4909f2428..e4264e9848 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.20.5-SNAPSHOT \ No newline at end of file +1.21.0 \ No newline at end of file From 16afc6837e6424003102e9ca8bae935ae44e3667 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 15 Jan 2021 11:37:16 -0800 Subject: [PATCH 0628/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index e4264e9848..0424f834fd 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.21.0 \ No newline at end of file +1.21.1-SNAPSHOT \ No newline at end of file From 8afa1eeef82d647be0b8d279d18ff0b7babf9d99 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 18 Jan 2021 13:40:00 +0000 Subject: [PATCH 0629/1594] Upgrade to Mockito 3.7.7. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e2f0c4bbe4..f438dcf3ce 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ def javaLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' -def mockitoVersion = '3.7.0' +def mockitoVersion = '3.7.7' def junitVersion = '5.7.0' def jmhVersion = '1.27' def agronaVersion = '1.9.0' From 6fe8b1a4c8ec9eaf3682849e91ea02474fca561b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 21 Jan 2021 14:52:08 +0000 Subject: [PATCH 0630/1594] [C++] Pass element by reference rather than value for skip and test, plus make generated formatting more consistent. --- .../sbe/generation/cpp/CppGenerator.java | 46 +++++++++---------- sbe-tool/src/test/cpp/CodeGenTest.cpp | 2 + 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 6d3c9d916a..3ccfc0e8e8 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -603,7 +603,7 @@ private void generateVarData( lengthCppType); new Formatter(sb).format("\n" + - indent + " %1$s &put%2$s(const std::string& str)\n" + + indent + " %1$s &put%2$s(const std::string &str)\n" + indent + " {\n" + indent + " if (str.length() > %4$d)\n" + indent + " {\n" + @@ -1613,7 +1613,7 @@ private void generateArrayProperty( indent + " return *this;\n" + indent + " }\n" + indent + " #else\n" + - indent + " %1$s &put%2$s(const std::string& str)\n" + + indent + " %1$s &put%2$s(const std::string &str)\n" + indent + " {\n" + indent + " const std::size_t srcLength = str.length();\n" + indent + " if (srcLength > %4$d)\n" + @@ -2500,8 +2500,8 @@ private void generateDisplay( { new Formatter(sb).format("\n" + "template\n" + - "friend std::basic_ostream& operator << (\n" + - " std::basic_ostream& builder, %1$s _writer)\n" + + "friend std::basic_ostream & operator << (\n" + + " std::basic_ostream &builder, %1$s _writer)\n" + "{\n" + " %1$s writer(_writer.m_buffer, _writer.m_offset,\n" + " _writer.m_bufferLength, _writer.sbeBlockLength(), _writer.m_actingVersion);\n" + @@ -2527,8 +2527,8 @@ private CharSequence generateGroupDisplay( { return String.format("\n" + indent + "template\n" + - indent + "friend std::basic_ostream& operator << (\n" + - indent + " std::basic_ostream& builder, %1$s writer)\n" + + indent + "friend std::basic_ostream & operator << (\n" + + indent + " std::basic_ostream &builder, %1$s writer)\n" + indent + "{\n" + indent + " builder << '{';\n" + "%2$s" + @@ -2543,8 +2543,8 @@ private CharSequence generateCompositeDisplay(final String name, final List\n" + - "friend std::basic_ostream& operator << (\n" + - " std::basic_ostream& builder, %1$s writer)\n" + + "friend std::basic_ostream & operator << (\n" + + " std::basic_ostream &builder, %1$s writer)\n" + "{\n" + " builder << '{';\n" + "%2$s" + @@ -2588,15 +2588,16 @@ private CharSequence appendDisplay( indent + "{\n" + indent + " bool atLeastOne = false;\n" + indent + " builder << R\"(\"%3$s\": [)\";\n" + - indent + " writer.%2$s().forEach([&](%1$s& %2$s)\n" + - indent + " {\n" + - indent + " if (atLeastOne)\n" + + indent + " writer.%2$s().forEach(\n" + + indent + " [&](%1$s &%2$s)\n" + indent + " {\n" + - indent + " builder << \", \";\n" + - indent + " }\n" + - indent + " atLeastOne = true;\n" + - indent + " builder << %2$s;\n" + - indent + " });\n" + + indent + " if (atLeastOne)\n" + + indent + " {\n" + + indent + " builder << \", \";\n" + + indent + " }\n" + + indent + " atLeastOne = true;\n" + + indent + " builder << %2$s;\n" + + indent + " });\n" + indent + " builder << ']';\n" + indent + "}\n\n", formatClassName(groupToken.name()), @@ -2745,8 +2746,8 @@ private CharSequence generateChoicesDisplay(final String name, final List new Formatter(sb).format("\n" + indent + "template\n" + - indent + "friend std::basic_ostream& operator << (\n" + - indent + " std::basic_ostream& builder, %1$s writer)\n" + + indent + "friend std::basic_ostream & operator << (\n" + + indent + " std::basic_ostream &builder, %1$s writer)\n" + indent + "{\n" + indent + " builder << '[';\n", name); @@ -2825,8 +2826,8 @@ private CharSequence generateEnumDisplay(final List tokens, final Token e new Formatter(sb).format( " template\n" + - " friend std::basic_ostream& operator << (\n" + - " std::basic_ostream& os, %1$s::Value m)\n" + + " friend std::basic_ostream & operator << (\n" + + " std::basic_ostream &os, %1$s::Value m)\n" + " {\n" + " return os << %1$s::c_str(m);\n" + " }\n", @@ -3040,10 +3041,7 @@ private CharSequence generateMessageLength(final List groups, final List< } new Formatter(sbSkip).format( - indent + " %2$s().forEach([](%1$s e)\n" + - indent + " {\n" + - indent + " e.skip();\n" + - indent + " });\n", + indent + " %2$s().forEach([](%1$s &e){ e.skip(); });\n", formatClassName(groupToken.name()), formatPropertyName(groupToken.name())); diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index caea987a7f..fff8f23e00 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -875,6 +875,8 @@ TEST_F(CodeGenTest, shouldPrintFullDecodedFlyweightRegardlessOfReadPosition) Car carDecoder(buffer, carEncodedLength, Car::sbeBlockLength(), Car::sbeSchemaVersion()); + EXPECT_EQ(carDecoder.decodeLength(), expectedCarEncodedLength); + std::string vehicleCode(VEHICLE_CODE, Car::vehicleCodeLength()); std::string usageDesc1(FUEL_FIGURES_1_USAGE_DESCRIPTION, FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH); std::string usageDesc2(FUEL_FIGURES_2_USAGE_DESCRIPTION, FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH); From 347e35921d9031b0954456ffea71bcb77c548674 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 21 Jan 2021 15:01:58 +0000 Subject: [PATCH 0631/1594] [C++] Remove generation of redundant branch with building string output for arrays. --- .../real_logic/sbe/generation/cpp/CppGenerator.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 3ccfc0e8e8..2f737e83e1 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2687,17 +2687,13 @@ private void writeTokenDisplay( { sb.append( indent + "builder << '[';\n" + - indent + "if (" + fieldName + "Length() > 0)\n" + + indent + "for (std::size_t i = 0, length = " + fieldName + "Length(); i < length; i++)\n" + indent + "{\n" + - indent + " for (" + - "std::size_t i = 0, length = " + fieldName + "Length(); i < length; i++)\n" + + indent + " if (i)\n" + indent + " {\n" + - indent + " if (i)\n" + - indent + " {\n" + - indent + " builder << ',';\n" + - indent + " }\n" + - indent + " builder << +" + fieldName + "(i);\n" + + indent + " builder << ',';\n" + indent + " }\n" + + indent + " builder << +" + fieldName + "(i);\n" + indent + "}\n" + indent + "builder << ']';\n"); } From 8b7ceaa4ad1809a4a8cf4946f49c732053cdee00 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 22 Jan 2021 16:10:51 +0000 Subject: [PATCH 0632/1594] [C++] Samples and tests code improvements. --- .../src/main/cpp/GeneratedStubExample.cpp | 106 +++++++++--------- sbe-samples/src/main/cpp/OtfExample.cpp | 24 ++-- sbe-tool/src/test/cpp/BoundsCheckTest.cpp | 58 +++++----- sbe-tool/src/test/cpp/CodeGenTest.cpp | 55 +++++---- .../src/test/cpp/CompositeElementsTest.cpp | 65 ++++++----- .../test/cpp/CompositeOffsetsCodeGenTest.cpp | 19 ++-- .../src/test/cpp/CompositeOffsetsIrTest.cpp | 18 +-- sbe-tool/src/test/cpp/GroupWithDataTest.cpp | 75 ++++++++----- .../src/test/cpp/MessageBlockLengthTest.cpp | 46 ++++---- sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp | 103 ++++++++--------- 10 files changed, 308 insertions(+), 261 deletions(-) diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index 5a5a454e15..7e59b8cfab 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -16,8 +16,8 @@ #include #include -#include -#include +#include +#include #include #include "baseline/MessageHeader.h" @@ -44,10 +44,10 @@ std::size_t encodeHdr( { // encode the header hdr.wrap(buffer, offset, messageHeaderVersion, bufferLength) - .blockLength(Car::sbeBlockLength()) - .templateId(Car::sbeTemplateId()) - .schemaId(Car::sbeSchemaId()) - .version(Car::sbeSchemaVersion()); + .blockLength(Car::sbeBlockLength()) + .templateId(Car::sbeTemplateId()) + .schemaId(Car::sbeSchemaId()) + .version(Car::sbeSchemaVersion()); return hdr.encodedLength(); } @@ -73,11 +73,11 @@ std::size_t decodeHdr( std::size_t encodeCar(Car &car, char *buffer, std::uint64_t offset, std::uint64_t bufferLength) { car.wrapForEncode(buffer, offset, bufferLength) - .serialNumber(1234) - .modelYear(2013) - .available(BooleanType::T) - .code(Model::A) - .putVehicleCode(VEHICLE_CODE); + .serialNumber(1234) + .modelYear(2013) + .available(BooleanType::T) + .code(Model::A) + .putVehicleCode(VEHICLE_CODE); for (std::uint64_t i = 0, size = car.someNumbersLength(); i < size; i++) { @@ -85,19 +85,19 @@ std::size_t encodeCar(Car &car, char *buffer, std::uint64_t offset, std::uint64_ } car.extras().clear() - .cruiseControl(true) - .sportsPack(true) - .sunRoof(false); + .cruiseControl(true) + .sportsPack(true) + .sunRoof(false); car.engine() - .capacity(2000) - .numCylinders(static_cast(4)) - .putManufacturerCode(MANUFACTURER_CODE) - .efficiency((std::int8_t)35) - .boosterEnabled(BooleanType::T) - .booster().boostType(BoostType::NITROUS).horsePower(200); + .capacity(2000) + .numCylinders(static_cast(4)) + .putManufacturerCode(MANUFACTURER_CODE) + .efficiency((std::int8_t)35) + .boosterEnabled(BooleanType::T) + .booster().boostType(BoostType::NITROUS).horsePower(200); - Car::FuelFigures& fuelFigures = car.fuelFiguresCount(3); + Car::FuelFigures &fuelFigures = car.fuelFiguresCount(3); fuelFigures .next().speed(30).mpg(35.9f) @@ -136,25 +136,23 @@ std::size_t encodeCar(Car &car, char *buffer, std::uint64_t offset, std::uint64_ const char *format(BooleanType::Value value) { - if (value == BooleanType::T) - { - return "T"; - } - else - { - return "F"; - } + return BooleanType::T == value ? "T" : "F"; } const char *format(Model::Value value) { switch (value) { - case Model::A: return "A"; - case Model::B: return "B"; - case Model::C: return "C"; - case Model::NULL_VALUE: return "NULL"; - default: return "unknown"; + case Model::A: + return "A"; + case Model::B: + return "B"; + case Model::C: + return "C"; + case Model::NULL_VALUE: + return "NULL"; + default: + return "unknown"; } } @@ -162,24 +160,22 @@ const char *format(BoostType::Value value) { switch (value) { - case BoostType::NITROUS: return "NITROUS"; - case BoostType::TURBO: return "TURBO"; - case BoostType::SUPERCHARGER: return "SUPERCHARGER"; - case BoostType::KERS: return "KERS"; - default: return "unknown"; + case BoostType::NITROUS: + return "NITROUS"; + case BoostType::TURBO: + return "TURBO"; + case BoostType::SUPERCHARGER: + return "SUPERCHARGER"; + case BoostType::KERS: + return "KERS"; + default: + return "unknown"; } } const char *format(bool value) { - if (value) - { - return "true"; - } - else - { - return "false"; - } + return value ? "true" : "false"; } std::size_t decodeCar( @@ -211,7 +207,7 @@ std::size_t decodeCar( std::cout << "\ncar.performanceFigures.accelerationId=" << Car::PerformanceFigures::accelerationId(); std::cout << "\ncar.performanceFigures.acceleration.mphId=" << Car::PerformanceFigures::Acceleration::mphId(); std::cout << "\ncar.performanceFigures.acceleration.secondsId=" - << Car::PerformanceFigures::Acceleration::secondsId(); + << Car::PerformanceFigures::Acceleration::secondsId(); std::cout << "\ncar.manufacturerId=" << Car::manufacturerId(); std::cout << "\ncar.manufacturerCharacterEncoding=" << Car::manufacturerCharacterEncoding(); std::cout << "\ncar.modelId=" << Car::modelId(); @@ -227,7 +223,7 @@ std::size_t decodeCar( std::cout << "\ncar.code=" << format(car.code()); std::cout << "\ncar.someNumbers="; - std::string separator(""); + std::string separator; for (std::uint64_t i = 0; i < Car::someNumbersLength(); i++) { std::cout << separator << car.someNumbers(i); @@ -262,7 +258,7 @@ std::size_t decodeCar( separator = ", "; } - char tmp[1024]; + char tmp[1024] = {}; std::uint64_t bytesCopied = engine.getFuel(tmp, sizeof(tmp)); std::cout << "\ncar.engine.efficiency=" << static_cast(engine.efficiency()); std::cout << "\ncar.engine.boosterEnabled=" << format(engine.boosterEnabled()); @@ -288,15 +284,15 @@ std::size_t decodeCar( { performanceFigures.next(); std::cout << "\ncar.performanceFigures.octaneRating=" - << static_cast(performanceFigures.octaneRating()); + << static_cast(performanceFigures.octaneRating()); baseline::Car::PerformanceFigures::Acceleration &acceleration = performanceFigures.acceleration(); while (acceleration.hasNext()) { acceleration.next(); std::cout << "\ncar.performanceFigures.acceleration.mph=" << acceleration.mph(); - std::cout << "\ncar.performanceFigures.acceleration.seconds=" << - std::setprecision(1) << acceleration.seconds(); + std::cout << "\ncar.performanceFigures.acceleration.seconds=" + << std::setprecision(1) << acceleration.seconds(); } } @@ -319,7 +315,7 @@ std::size_t decodeCar( int main(int argc, const char **argv) { - char buffer[2048]; + char buffer[2048] = {}; MessageHeader hdr; Car car; @@ -328,7 +324,7 @@ int main(int argc, const char **argv) std::size_t predictedLength = Car::computeLength({ 11, 14, 13 }, { 3, 3 }, 5, 9, 8); std::cout << "Encoded Lengths are " << encodeHdrLength << " + " << encodeMsgLength << " (" << predictedLength << ")" - << std::endl; + << std::endl; std::size_t decodeHdrLength = decodeHdr(hdr, buffer, 0, sizeof(buffer)); std::size_t decodeMsgLength = decodeCar( diff --git a/sbe-samples/src/main/cpp/OtfExample.cpp b/sbe-samples/src/main/cpp/OtfExample.cpp index e611952503..bb1f3c4988 100644 --- a/sbe-samples/src/main/cpp/OtfExample.cpp +++ b/sbe-samples/src/main/cpp/OtfExample.cpp @@ -39,7 +39,7 @@ class ExampleTokenListener void printScope() const { std::for_each(scope.begin(), scope.end(), - [&](const std::string& scope) + [&](const std::string &scope) { std::cout << scope; }); @@ -63,12 +63,12 @@ class ExampleTokenListener scope.pop_back(); } - std::string asString(const Token &token, const char *buffer) + static std::string asString(const Token &token, const char *buffer) { const Encoding &encoding = token.encoding(); const PrimitiveType type = encoding.primitiveType(); const std::uint64_t length = token.isConstantEncoding() ? - encoding.constValue().size() : static_cast(token.encodedLength()); + encoding.constValue().size() : static_cast(token.encodedLength()); std::ostringstream result; std::uint64_t num = length / lengthOfType(type); @@ -101,7 +101,7 @@ class ExampleTokenListener for (std::size_t i = 0; i < num; i++) { result << separator - << Encoding::getInt(type, encoding.byteOrder(), buffer + (i * lengthOfType(type))); + << Encoding::getInt(type, encoding.byteOrder(), buffer + (i * lengthOfType(type))); separator = ", "; } } @@ -171,7 +171,7 @@ class ExampleTokenListener virtual void onEnum( Token &fieldToken, const char *buffer, - std::vector& tokens, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex, std::uint64_t actingVersion) @@ -405,16 +405,16 @@ std::uint64_t encodeHdrAndCar(char *buffer, std::uint64_t length) perfFigs.next() .octaneRating(perf1Octane) .accelerationCount(ACCELERATION_COUNT) - .next().mph(perf1aMph).seconds(perf1aSeconds) - .next().mph(perf1bMph).seconds(perf1bSeconds) - .next().mph(perf1cMph).seconds(perf1cSeconds); + .next().mph(perf1aMph).seconds(perf1aSeconds) + .next().mph(perf1bMph).seconds(perf1bSeconds) + .next().mph(perf1cMph).seconds(perf1cSeconds); perfFigs.next() .octaneRating(perf2Octane) .accelerationCount(ACCELERATION_COUNT) - .next().mph(perf2aMph).seconds(perf2aSeconds) - .next().mph(perf2bMph).seconds(perf2bSeconds) - .next().mph(perf2cMph).seconds(perf2cSeconds); + .next().mph(perf2aMph).seconds(perf2aSeconds) + .next().mph(perf2bMph).seconds(perf2bSeconds) + .next().mph(perf2cMph).seconds(perf2cSeconds); car.putManufacturer(MANUFACTURER, static_cast(strlen(MANUFACTURER))) .putModel(MODEL, static_cast(strlen(MODEL))) @@ -459,7 +459,7 @@ int main(int argc, char **argv) if (result != static_cast(sz - headerDecoder.encodedLength())) { std::cerr << "Message not properly decoded " << result << "/(" << sz << " - " << headerDecoder.encodedLength() - << ")" << std::endl; + << ")" << std::endl; return -1; } diff --git a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp index 8fe13f6fb1..3cd1a22ca5 100644 --- a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp @@ -97,7 +97,7 @@ class BoundsCheckTest : public testing::Test std::uint64_t encodeCarFuelFigures() { - Car::FuelFigures& fuelFigures = m_car.fuelFiguresCount(3); + Car::FuelFigures &fuelFigures = m_car.fuelFiguresCount(3); fuelFigures .next().speed(30).mpg(35.9f); @@ -276,10 +276,10 @@ class BoundsCheckTest : public testing::Test return m_carDecoder.encodedLength(); } - MessageHeader m_hdr; - MessageHeader m_hdrDecoder; - Car m_car; - Car m_carDecoder; + MessageHeader m_hdr = {}; + MessageHeader m_hdrDecoder = {}; + Car m_car = {}; + Car m_carDecoder = {}; }; class HeaderBoundsCheckTest : public BoundsCheckTest, public ::testing::WithParamInterface @@ -292,24 +292,26 @@ TEST_P(HeaderBoundsCheckTest, shouldExceptionWhenBufferTooShortForEncodeOfHeader std::unique_ptr buffer(new char[length]); EXPECT_THROW( - { - encodeHdr(buffer.get(), 0, length); - }, std::runtime_error); + { + encodeHdr(buffer.get(), 0, length); + }, + std::runtime_error); } TEST_P(HeaderBoundsCheckTest, shouldExceptionWhenBufferTooShortForDecodeOfHeader) { const int length = GetParam(); - char encodeBuffer[8]; + char encodeBuffer[8] = {}; std::unique_ptr buffer(new char[length]); encodeHdr(encodeBuffer, 0, sizeof(encodeBuffer)); EXPECT_THROW( - { - std::memcpy(buffer.get(), encodeBuffer, length); - decodeHdr(buffer.get(), 0, length); - }, std::runtime_error); + { + std::memcpy(buffer.get(), encodeBuffer, length); + decodeHdr(buffer.get(), 0, length); + }, + std::runtime_error); } INSTANTIATE_TEST_SUITE_P( @@ -327,18 +329,19 @@ TEST_P(MessageBoundsCheckTest, shouldExceptionWhenBufferTooShortForEncodeOfMessa std::unique_ptr buffer(new char[length]); EXPECT_THROW( - { - encodeCarRoot(buffer.get(), 0, length); - encodeCarFuelFigures(); - encodeCarPerformanceFigures(); - encodeCarManufacturerModelAndActivationCode(); - }, std::runtime_error); + { + encodeCarRoot(buffer.get(), 0, length); + encodeCarFuelFigures(); + encodeCarPerformanceFigures(); + encodeCarManufacturerModelAndActivationCode(); + }, + std::runtime_error); } TEST_P(MessageBoundsCheckTest, shouldExceptionWhenBufferTooShortForDecodeOfMessage) { const int length = GetParam(); - char encodeBuffer[191]; + char encodeBuffer[191] = {}; std::unique_ptr buffer(new char[length]); encodeCarRoot(encodeBuffer, 0, sizeof(encodeBuffer)); @@ -347,13 +350,14 @@ TEST_P(MessageBoundsCheckTest, shouldExceptionWhenBufferTooShortForDecodeOfMessa encodeCarManufacturerModelAndActivationCode(); EXPECT_THROW( - { - std::memcpy(buffer.get(), encodeBuffer, length); - decodeCarRoot(buffer.get(), 0, length); - decodeCarFuelFigures(); - decodeCarPerformanceFigures(); - decodeCarManufacturerModelAndActivationCode(); - }, std::runtime_error); + { + std::memcpy(buffer.get(), encodeBuffer, length); + decodeCarRoot(buffer.get(), 0, length); + decodeCarFuelFigures(); + decodeCarPerformanceFigures(); + decodeCarManufacturerModelAndActivationCode(); + }, + std::runtime_error); } INSTANTIATE_TEST_SUITE_P( diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index fff8f23e00..23f36fb15c 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -90,7 +90,7 @@ class CodeGenTest : public testing::Test { public: - static std::uint64_t encodeHdr(MessageHeader& hdr) + static std::uint64_t encodeHdr(MessageHeader &hdr) { hdr.blockLength(Car::sbeBlockLength()) .templateId(Car::sbeTemplateId()) @@ -100,7 +100,7 @@ class CodeGenTest : public testing::Test return hdr.encodedLength(); } - static std::uint64_t encodeCar(Car& car) + static std::uint64_t encodeCar(Car &car) { car.serialNumber(SERIAL_NUMBER) .modelYear(MODEL_YEAR) @@ -124,7 +124,7 @@ class CodeGenTest : public testing::Test .putManufacturerCode(MANUFACTURER_CODE) .booster().boostType(BOOST_TYPE).horsePower(BOOSTER_HORSEPOWER); - Car::FuelFigures& fuelFigures = car.fuelFiguresCount(FUEL_FIGURES_COUNT); + Car::FuelFigures &fuelFigures = car.fuelFiguresCount(FUEL_FIGURES_COUNT); fuelFigures .next().speed(fuel1Speed).mpg(fuel1Mpg) @@ -177,7 +177,7 @@ class CodeGenTest : public testing::Test return encodeCar(m_car); } - void expectDisplayString(const char *expectedDisplayString, Car& carDecoder) + void expectDisplayString(const char *expectedDisplayString, Car &carDecoder) { std::stringstream displayStream; @@ -323,7 +323,8 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) offset += sizeof(std::uint16_t); EXPECT_EQ(*(bp + offset), engineNumCylinders); offset += sizeof(std::uint8_t); - EXPECT_EQ(std::string(bp + offset, MANUFACTURER_CODE_LENGTH), std::string(MANUFACTURER_CODE, MANUFACTURER_CODE_LENGTH)); + EXPECT_EQ(std::string(bp + offset, MANUFACTURER_CODE_LENGTH), + std::string(MANUFACTURER_CODE, MANUFACTURER_CODE_LENGTH)); offset += MANUFACTURER_CODE_LENGTH; EXPECT_EQ(*(bp + offset), 'N'); offset += sizeof(char); @@ -486,7 +487,8 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) EXPECT_EQ(m_hdrDecoder.version(), Car::sbeSchemaVersion()); EXPECT_EQ(m_hdrDecoder.encodedLength(), expectedHeaderSize); - m_carDecoder.wrapForDecode(buffer, m_hdrDecoder.encodedLength(), Car::sbeBlockLength(), Car::sbeSchemaVersion(), hdrSz + carEncodedLength); + m_carDecoder.wrapForDecode( + buffer, m_hdrDecoder.encodedLength(), Car::sbeBlockLength(), Car::sbeSchemaVersion(), hdrSz + carEncodedLength); EXPECT_EQ(m_carDecoder.decodeLength(), expectedCarEncodedLength); @@ -502,7 +504,8 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) } EXPECT_EQ(m_carDecoder.vehicleCodeLength(), VEHICLE_CODE_LENGTH); - EXPECT_EQ(std::string(m_carDecoder.vehicleCode(), VEHICLE_CODE_LENGTH), std::string(VEHICLE_CODE, VEHICLE_CODE_LENGTH)); + EXPECT_EQ(std::string(m_carDecoder.vehicleCode(), VEHICLE_CODE_LENGTH), + std::string(VEHICLE_CODE, VEHICLE_CODE_LENGTH)); EXPECT_EQ(m_carDecoder.extras().cruiseControl(), true); EXPECT_EQ(m_carDecoder.extras().sportsPack(), true); @@ -515,7 +518,8 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) EXPECT_EQ(engine.numCylinders(), engineNumCylinders); EXPECT_EQ(engine.maxRpm(), 9000); EXPECT_EQ(engine.manufacturerCodeLength(), MANUFACTURER_CODE_LENGTH); - EXPECT_EQ(std::string(engine.manufacturerCode(), MANUFACTURER_CODE_LENGTH), std::string(MANUFACTURER_CODE, MANUFACTURER_CODE_LENGTH)); + EXPECT_EQ(std::string(engine.manufacturerCode(), MANUFACTURER_CODE_LENGTH), + std::string(MANUFACTURER_CODE, MANUFACTURER_CODE_LENGTH)); EXPECT_EQ(engine.fuelLength(), 6u); EXPECT_EQ(std::string(engine.fuel(), 6), std::string("Petrol")); @@ -527,21 +531,24 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) EXPECT_EQ(fuelFigures.speed(), fuel1Speed); EXPECT_EQ(fuelFigures.mpg(), fuel1Mpg); EXPECT_EQ(fuelFigures.usageDescriptionLength(), FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH); - EXPECT_EQ(std::string(fuelFigures.usageDescription(), FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH), FUEL_FIGURES_1_USAGE_DESCRIPTION); + EXPECT_EQ(std::string(fuelFigures.usageDescription(), FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH), + FUEL_FIGURES_1_USAGE_DESCRIPTION); ASSERT_TRUE(fuelFigures.hasNext()); fuelFigures.next(); EXPECT_EQ(fuelFigures.speed(), fuel2Speed); EXPECT_EQ(fuelFigures.mpg(), fuel2Mpg); EXPECT_EQ(fuelFigures.usageDescriptionLength(), FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH); - EXPECT_EQ(std::string(fuelFigures.usageDescription(), FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH), FUEL_FIGURES_2_USAGE_DESCRIPTION); + EXPECT_EQ(std::string(fuelFigures.usageDescription(), FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH), + FUEL_FIGURES_2_USAGE_DESCRIPTION); ASSERT_TRUE(fuelFigures.hasNext()); fuelFigures.next(); EXPECT_EQ(fuelFigures.speed(), fuel3Speed); EXPECT_EQ(fuelFigures.mpg(), fuel3Mpg); EXPECT_EQ(fuelFigures.usageDescriptionLength(), FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH); - EXPECT_EQ(std::string(fuelFigures.usageDescription(), FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH), FUEL_FIGURES_3_USAGE_DESCRIPTION); + EXPECT_EQ(std::string(fuelFigures.usageDescription(), FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH), + FUEL_FIGURES_3_USAGE_DESCRIPTION); Car::PerformanceFigures &performanceFigures = m_carDecoder.performanceFigures(); EXPECT_EQ(performanceFigures.count(), PERFORMANCE_FIGURES_COUNT); @@ -610,15 +617,17 @@ struct CallbacksForEach int countOfPerformanceFigures; int countOfAccelerations; - CallbacksForEach() : countOfFuelFigures(0), countOfPerformanceFigures(0), countOfAccelerations(0) {} + CallbacksForEach() : countOfFuelFigures(0), countOfPerformanceFigures(0), countOfAccelerations(0) + { + } - void operator()(Car::FuelFigures& fuelFigures) + void operator()(Car::FuelFigures &fuelFigures) { countOfFuelFigures++; static_cast(fuelFigures.usageDescription()); } - void operator()(Car::PerformanceFigures& performanceFigures) + void operator()(Car::PerformanceFigures &performanceFigures) { Car::PerformanceFigures::Acceleration acceleration = performanceFigures.acceleration(); @@ -626,7 +635,7 @@ struct CallbacksForEach acceleration.forEach(*this); } - void operator()(Car::PerformanceFigures::Acceleration&) + void operator()(Car::PerformanceFigures::Acceleration &) { countOfAccelerations++; } @@ -652,7 +661,8 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) EXPECT_EQ(hdrDecoder.version(), Car::sbeSchemaVersion()); EXPECT_EQ(hdrDecoder.encodedLength(), expectedHeaderSize); - Car carDecoder(buffer + hdrDecoder.encodedLength(), carEncodedLength, hdrDecoder.blockLength(), hdrDecoder.version()); + Car carDecoder( + buffer + hdrDecoder.encodedLength(), carEncodedLength, hdrDecoder.blockLength(), hdrDecoder.version()); CallbacksForEach cbs; Car::FuelFigures &fuelFigures = carDecoder.fuelFigures(); @@ -675,13 +685,13 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) EXPECT_EQ(performanceFigures.count(), PERFORMANCE_FIGURES_COUNT); #if __cplusplus >= 201103L - performanceFigures.forEach([&](Car::PerformanceFigures&figures) + performanceFigures.forEach([&](Car::PerformanceFigures &figures) { Car::PerformanceFigures::Acceleration acceleration = figures.acceleration(); cbs.countOfPerformanceFigures++; acceleration.forEach( - [&](Car::PerformanceFigures::Acceleration&) + [&](Car::PerformanceFigures::Acceleration &) { cbs.countOfAccelerations++; }); @@ -769,15 +779,18 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc1Length), static_cast(FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH)); - EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc1Data, FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH), usageDesc1); + EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc1Data, FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH), + usageDesc1); EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc2Length), static_cast(FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH)); - EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc2Data, FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH), usageDesc2); + EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc2Data, FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH), + usageDesc2); EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc3Length), static_cast(FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH)); - EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc3Data, FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH), usageDesc3); + EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc3Data, FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH), + usageDesc3); EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetManufacturerLength), static_cast(MANUFACTURER_LENGTH)); diff --git a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp index 4a67d59144..c3b383de15 100644 --- a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp @@ -40,11 +40,11 @@ enum EventNumber class CompositeElementsTest : public testing::Test, public OtfMessageDecoder::BasicTokenListener { public: - char m_buffer[2048]; + char m_buffer[2048] = {}; IrDecoder m_irDecoder; - int m_eventNumber; + int m_eventNumber = 0; - virtual void SetUp() + void SetUp() override { m_eventNumber = 0; } @@ -79,16 +79,18 @@ class CompositeElementsTest : public testing::Test, public OtfMessageDecoder::Ba Token &fieldToken, std::vector &tokens, std::size_t fromIndex, - std::size_t toIndex) + std::size_t toIndex) override { switch (EventNumber(m_eventNumber++)) { case EN_beginOuter: EXPECT_EQ(tokens.at(fromIndex).name(), "outer"); break; + case EN_beginInner: EXPECT_EQ(tokens.at(fromIndex).name(), "inner"); break; + default: FAIL() << "unknown beginComposite event number " << m_eventNumber - 1; } @@ -98,26 +100,28 @@ class CompositeElementsTest : public testing::Test, public OtfMessageDecoder::Ba Token &fieldToken, std::vector &tokens, std::size_t fromIndex, - std::size_t toIndex) + std::size_t toIndex) override { switch (EventNumber(m_eventNumber++)) { case EN_endInner: EXPECT_EQ(tokens.at(fromIndex).name(), "inner"); break; + case EN_endOuter: EXPECT_EQ(tokens.at(fromIndex).name(), "outer"); break; + default: FAIL() << "unknown endComposite event number " << m_eventNumber - 1; } } void onEncoding( - Token& fieldToken, + Token &fieldToken, const char *buffer, - Token& typeToken, - std::uint64_t actingVersion) + Token &typeToken, + std::uint64_t actingVersion) override { switch (EventNumber(m_eventNumber++)) { @@ -127,48 +131,51 @@ class CompositeElementsTest : public testing::Test, public OtfMessageDecoder::Ba EXPECT_EQ(typeToken.encoding().getAsUInt(buffer), 42u); break; } + case EN_innerFirst: { EXPECT_EQ(typeToken.encoding().primitiveType(), PrimitiveType::INT64); EXPECT_EQ(typeToken.encoding().getAsInt(buffer), 101l); break; } + case EN_innerSecond: { EXPECT_EQ(typeToken.encoding().primitiveType(), PrimitiveType::INT64); EXPECT_EQ(typeToken.encoding().getAsInt(buffer), 202l); break; } + default: FAIL() << "unknown Encoding event number " << m_eventNumber - 1; } - } void onBitSet( - Token& fieldToken, + Token &fieldToken, const char *buffer, - std::vector& tokens, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex, - std::uint64_t actingVersion) + std::uint64_t actingVersion) override { switch (EventNumber(m_eventNumber++)) { case EN_setOne: { - const Token& typeToken = tokens.at(fromIndex + 1); - const Encoding& encoding = typeToken.encoding(); + const Token &typeToken = tokens.at(fromIndex + 1); + const Encoding &encoding = typeToken.encoding(); EXPECT_EQ(encoding.primitiveType(), PrimitiveType::UINT32); EXPECT_EQ(encoding.getAsUInt(buffer), 0x00010000u); - EXPECT_EQ(tokens.at(fromIndex+1).name(), "Bit0"); - EXPECT_EQ(tokens.at(fromIndex+2).name(), "Bit16"); - EXPECT_EQ(tokens.at(fromIndex+3).name(), "Bit26"); - EXPECT_EQ(toIndex - 1 - fromIndex, 3u); + EXPECT_EQ(tokens.at(fromIndex + 1).name(), "Bit0"); + EXPECT_EQ(tokens.at(fromIndex + 2).name(), "Bit16"); + EXPECT_EQ(tokens.at(fromIndex + 3).name(), "Bit26"); + EXPECT_EQ(toIndex - 1 - fromIndex, 3u); break; } + default: FAIL() << "unknown BitSet event number " << m_eventNumber - 1; } @@ -180,23 +187,24 @@ class CompositeElementsTest : public testing::Test, public OtfMessageDecoder::Ba std::vector &tokens, std::size_t fromIndex, std::size_t toIndex, - std::uint64_t actingVersion) + std::uint64_t actingVersion) override { switch (EventNumber(m_eventNumber++)) { case EN_enumOne: { - const Token& typeToken = tokens.at(fromIndex + 1); - const Encoding& encoding = typeToken.encoding(); + const Token &typeToken = tokens.at(fromIndex + 1); + const Encoding &encoding = typeToken.encoding(); EXPECT_EQ(encoding.primitiveType(), PrimitiveType::UINT8); EXPECT_EQ(encoding.getAsUInt(buffer), 10u); - EXPECT_EQ(tokens.at(fromIndex+1).name(), "Value1"); - EXPECT_EQ(tokens.at(fromIndex+2).name(), "Value10"); - EXPECT_EQ(toIndex - 1 - fromIndex, 2u); + EXPECT_EQ(tokens.at(fromIndex + 1).name(), "Value1"); + EXPECT_EQ(tokens.at(fromIndex + 2).name(), "Value10"); + EXPECT_EQ(toIndex - 1 - fromIndex, 2u); break; } + default: FAIL() << "unknown Enum event number " << m_eventNumber - 1; } @@ -278,10 +286,11 @@ TEST_F(CompositeElementsTest, shouldHandleAllEventsCorrectlyInOrder) ASSERT_GE(m_irDecoder.decode("composite-elements-schema.sbeir"), 0); std::shared_ptr> headerTokens = m_irDecoder.header(); - std::shared_ptr> messageTokens = m_irDecoder.message(Msg::sbeTemplateId(), Msg::sbeSchemaVersion()); + std::shared_ptr> messageTokens = m_irDecoder.message( + Msg::sbeTemplateId(), Msg::sbeSchemaVersion()); ASSERT_TRUE(headerTokens != nullptr); - ASSERT_TRUE(messageTokens!= nullptr); + ASSERT_TRUE(messageTokens != nullptr); OtfHeaderDecoder headerDecoder(headerTokens); @@ -291,8 +300,8 @@ TEST_F(CompositeElementsTest, shouldHandleAllEventsCorrectlyInOrder) std::uint64_t actingVersion = headerDecoder.getSchemaVersion(m_buffer); std::uint64_t blockLength = headerDecoder.getBlockLength(m_buffer); - const std::size_t result = - OtfMessageDecoder::decode(messageBuffer, length, actingVersion, blockLength, messageTokens, *this); + const std::size_t result = OtfMessageDecoder::decode( + messageBuffer, length, actingVersion, blockLength, messageTokens, *this); EXPECT_EQ(result, static_cast(Msg::sbeBlockLength())); EXPECT_EQ(m_eventNumber, 9); diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp index 5861549525..12361521bd 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp @@ -53,10 +53,10 @@ class CompositeOffsetsCodeGenTest : public testing::Test return m_msg.encodedLength(); } - MessageHeader m_hdr; - MessageHeader m_hdrDecoder; - TestMessage1 m_msg; - TestMessage1 m_msgDecoder; + MessageHeader m_hdr = {}; + MessageHeader m_hdrDecoder = {}; + TestMessage1 m_msg = {}; + TestMessage1 m_msgDecoder = {}; }; TEST_F(CompositeOffsetsCodeGenTest, shouldReturnCorrectValuesForMessageHeaderStaticFields) @@ -81,7 +81,7 @@ TEST_F(CompositeOffsetsCodeGenTest, shouldReturnCorrectValuesForTestMessage1Stat TEST_F(CompositeOffsetsCodeGenTest, shouldBeAbleToEncodeMessageHeaderCorrectly) { - char buffer[2048]; + char buffer[2048] = {}; const char *bp = buffer; std::uint64_t sz = encodeHdr(buffer, 0, sizeof(buffer)); @@ -95,7 +95,7 @@ TEST_F(CompositeOffsetsCodeGenTest, shouldBeAbleToEncodeMessageHeaderCorrectly) TEST_F(CompositeOffsetsCodeGenTest, shouldBeAbleToEncodeAndDecodeMessageHeaderCorrectly) { - char buffer[2048]; + char buffer[2048] = {}; encodeHdr(buffer, 0, sizeof(buffer)); @@ -108,7 +108,7 @@ TEST_F(CompositeOffsetsCodeGenTest, shouldBeAbleToEncodeAndDecodeMessageHeaderCo TEST_F(CompositeOffsetsCodeGenTest, shouldBeAbleToEncodeMessageCorrectly) { - char buffer[2048]; + char buffer[2048] = {}; const char *bp = buffer; std::uint64_t sz = encodeMsg(buffer, 0, sizeof(buffer)); @@ -124,7 +124,7 @@ TEST_F(CompositeOffsetsCodeGenTest, shouldBeAbleToEncodeMessageCorrectly) TEST_F(CompositeOffsetsCodeGenTest, shouldBeAbleToDecodeHeaderAndMsgCorrectly) { - char buffer[2048]; + char buffer[2048] = {}; std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer)); std::uint64_t sz = encodeMsg(buffer, hdrSz, sizeof(buffer)); @@ -138,7 +138,8 @@ TEST_F(CompositeOffsetsCodeGenTest, shouldBeAbleToDecodeHeaderAndMsgCorrectly) EXPECT_EQ(m_hdrDecoder.schemaId(), TestMessage1::sbeSchemaId()); EXPECT_EQ(m_hdrDecoder.version(), TestMessage1::sbeSchemaVersion()); - m_msgDecoder.wrapForDecode(buffer, hdrSz, TestMessage1::sbeBlockLength(), TestMessage1::sbeSchemaVersion(), hdrSz + sz); + m_msgDecoder.wrapForDecode( + buffer, hdrSz, TestMessage1::sbeBlockLength(), TestMessage1::sbeSchemaVersion(), hdrSz + sz); TestMessage1::Entries entries = m_msgDecoder.entries(); EXPECT_EQ(entries.count(), 2u); diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp index c3dd645504..8500cc46e4 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp @@ -40,8 +40,8 @@ class CompositeOffsetsIrTest : public testing::Test, public OtfMessageDecoder::B std::uint64_t encodeHdrAndMsg() { - MessageHeader hdr; - TestMessage1 msg; + MessageHeader hdr = {}; + TestMessage1 msg = {}; hdr.wrap(m_buffer, 0, 0, sizeof(m_buffer)) .blockLength(TestMessage1::sbeBlockLength()) @@ -65,10 +65,10 @@ class CompositeOffsetsIrTest : public testing::Test, public OtfMessageDecoder::B } void onEncoding( - Token& fieldToken, + Token &fieldToken, const char *buffer, - Token& typeToken, - std::uint64_t actingVersion) + Token &typeToken, + std::uint64_t actingVersion) override { switch (m_eventNumber++) { @@ -102,7 +102,7 @@ class CompositeOffsetsIrTest : public testing::Test, public OtfMessageDecoder::B } - void onGroupHeader(Token& token, std::uint64_t numInGroup) + void onGroupHeader(Token &token, std::uint64_t numInGroup) override { switch (m_eventNumber++) { @@ -147,7 +147,7 @@ TEST_F(CompositeOffsetsIrTest, shouldHandleAllEventsCorrectlyInOrder) TestMessage1::sbeTemplateId(), TestMessage1::sbeSchemaVersion()); ASSERT_TRUE(headerTokens != nullptr); - ASSERT_TRUE(messageTokens!= nullptr); + ASSERT_TRUE(messageTokens != nullptr); OtfHeaderDecoder headerDecoder(headerTokens); @@ -157,8 +157,8 @@ TEST_F(CompositeOffsetsIrTest, shouldHandleAllEventsCorrectlyInOrder) std::uint64_t actingVersion = headerDecoder.getSchemaVersion(m_buffer); std::uint64_t blockLength = headerDecoder.getBlockLength(m_buffer); - const std::size_t result = - OtfMessageDecoder::decode(messageBuffer, length, actingVersion, blockLength, messageTokens, *this); + const std::size_t result = OtfMessageDecoder::decode( + messageBuffer, length, actingVersion, blockLength, messageTokens, *this); EXPECT_EQ(result, static_cast(52 - MessageHeader::encodedLength())); EXPECT_EQ(m_eventNumber, 5); diff --git a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp index af695b54ba..2e09950162 100644 --- a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp @@ -204,15 +204,15 @@ class GroupWithDataTest : public testing::Test return m_msg4.encodedLength(); } - TestMessage1 m_msg1; - TestMessage2 m_msg2; - TestMessage3 m_msg3; - TestMessage4 m_msg4; + TestMessage1 m_msg1 = {}; + TestMessage2 m_msg2 = {}; + TestMessage3 m_msg3 = {}; + TestMessage4 m_msg4 = {}; }; TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage1Correctly) { - char buffer[2048]; + char buffer[2048] = {}; const char *bp = buffer; std::uint64_t sz = encodeTestMessage1(buffer, 0, sizeof(buffer)); @@ -227,7 +227,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage1Correctly) EXPECT_EQ(*(std::uint8_t *)(bp + offset), ENTRIES_COUNT); offset += sizeof(std::uint8_t); - EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_0_LENGTH), std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); + EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_0_LENGTH), + std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); offset += TAG_GROUP_1_IDX_0_LENGTH; EXPECT_EQ(*(std::int64_t *)(bp + offset), TAG_GROUP_2_IDX_0); offset += sizeof(std::int64_t); @@ -236,7 +237,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage1Correctly) EXPECT_EQ(std::string(bp + offset, VAR_DATA_FIELD_IDX_0_LENGTH), VAR_DATA_FIELD_IDX_0); offset += VAR_DATA_FIELD_IDX_0_LENGTH; - EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_1_LENGTH), std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); + EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_1_LENGTH), + std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); offset += TAG_GROUP_1_IDX_1_LENGTH; EXPECT_EQ(*(std::int64_t *)(bp + offset), TAG_GROUP_2_IDX_1); offset += sizeof(std::int64_t); @@ -250,7 +252,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage1Correctly) TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage1Correctly) { - char buffer[2048]; + char buffer[2048] = {}; std::uint64_t sz = encodeTestMessage1(buffer, 0, sizeof(buffer)); EXPECT_EQ(sz, expectedTestMessage1Size); @@ -266,7 +268,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage1Correctly) entries.next(); EXPECT_EQ(entries.tagGroup1Length(), TAG_GROUP_1_IDX_0_LENGTH); - EXPECT_EQ(std::string(entries.tagGroup1(), entries.tagGroup1Length()), std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); + EXPECT_EQ(std::string(entries.tagGroup1(), entries.tagGroup1Length()), + std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); EXPECT_EQ(entries.tagGroup2(), TAG_GROUP_2_IDX_0); EXPECT_EQ(entries.varDataFieldLength(), VAR_DATA_FIELD_IDX_0_LENGTH); EXPECT_EQ(std::string(entries.varDataField(), VAR_DATA_FIELD_IDX_0_LENGTH), VAR_DATA_FIELD_IDX_0); @@ -275,7 +278,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage1Correctly) entries.next(); EXPECT_EQ(entries.tagGroup1Length(), TAG_GROUP_1_IDX_1_LENGTH); - EXPECT_EQ(std::string(entries.tagGroup1(), entries.tagGroup1Length()), std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); + EXPECT_EQ(std::string(entries.tagGroup1(), entries.tagGroup1Length()), + std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); EXPECT_EQ(entries.tagGroup2(), TAG_GROUP_2_IDX_1); EXPECT_EQ(entries.varDataFieldLength(), VAR_DATA_FIELD_IDX_1_LENGTH); EXPECT_EQ(std::string(entries.varDataField(), VAR_DATA_FIELD_IDX_1_LENGTH), VAR_DATA_FIELD_IDX_1); @@ -285,7 +289,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage1Correctly) TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage2Correctly) { - char buffer[2048]; + char buffer[2048] = {}; const char *bp = buffer; std::uint64_t sz = encodeTestMessage2(buffer, 0, sizeof(buffer)); @@ -300,7 +304,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage2Correctly) EXPECT_EQ(*(std::uint8_t *)(bp + offset), ENTRIES_COUNT); offset += sizeof(std::uint8_t); - EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_0_LENGTH), std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); + EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_0_LENGTH), + std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); offset += TAG_GROUP_1_IDX_0_LENGTH; EXPECT_EQ(*(std::int64_t *)(bp + offset), TAG_GROUP_2_IDX_0); offset += sizeof(std::int64_t); @@ -313,7 +318,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage2Correctly) EXPECT_EQ(std::string(bp + offset, VAR_DATA_FIELD_2_IDX_0_LENGTH), VAR_DATA_FIELD_2_IDX_0); offset += VAR_DATA_FIELD_2_IDX_0_LENGTH; - EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_1_LENGTH), std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); + EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_1_LENGTH), + std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); offset += TAG_GROUP_1_IDX_1_LENGTH; EXPECT_EQ(*(std::int64_t *)(bp + offset), TAG_GROUP_2_IDX_1); offset += sizeof(std::int64_t); @@ -331,7 +337,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage2Correctly) TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage2Correctly) { - char buffer[2048]; + char buffer[2048] = {}; std::uint64_t sz = encodeTestMessage2(buffer, 0, sizeof(buffer)); EXPECT_EQ(sz, expectedTestMessage2Size); @@ -347,7 +353,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage2Correctly) entries.next(); EXPECT_EQ(entries.tagGroup1Length(), TAG_GROUP_1_IDX_0_LENGTH); - EXPECT_EQ(std::string(entries.tagGroup1(), entries.tagGroup1Length()), std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); + EXPECT_EQ(std::string(entries.tagGroup1(), entries.tagGroup1Length()), + std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); EXPECT_EQ(entries.tagGroup2(), TAG_GROUP_2_IDX_0); EXPECT_EQ(entries.varDataField1Length(), VAR_DATA_FIELD_1_IDX_0_LENGTH); EXPECT_EQ(std::string(entries.varDataField1(), VAR_DATA_FIELD_1_IDX_0_LENGTH), VAR_DATA_FIELD_1_IDX_0); @@ -358,7 +365,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage2Correctly) entries.next(); EXPECT_EQ(entries.tagGroup1Length(), TAG_GROUP_1_IDX_1_LENGTH); - EXPECT_EQ(std::string(entries.tagGroup1(), entries.tagGroup1Length()), std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); + EXPECT_EQ(std::string(entries.tagGroup1(), entries.tagGroup1Length()), + std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); EXPECT_EQ(entries.tagGroup2(), TAG_GROUP_2_IDX_1); EXPECT_EQ(entries.varDataField1Length(), VAR_DATA_FIELD_1_IDX_1_LENGTH); EXPECT_EQ(std::string(entries.varDataField1(), VAR_DATA_FIELD_1_IDX_1_LENGTH), VAR_DATA_FIELD_1_IDX_1); @@ -370,7 +378,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage2Correctly) TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage3Correctly) { - char buffer[2048]; + char buffer[2048] = {}; const char *bp = buffer; std::uint64_t sz = encodeTestMessage3(buffer, 0, sizeof(buffer)); @@ -385,7 +393,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage3Correctly) EXPECT_EQ(*(std::uint8_t *)(bp + offset), ENTRIES_COUNT); offset += sizeof(std::uint8_t); - EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_0_LENGTH), std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); + EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_0_LENGTH), + std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); offset += TAG_GROUP_1_IDX_0_LENGTH; // nested entries @@ -420,7 +429,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage3Correctly) EXPECT_EQ(std::string(bp + offset, VAR_DATA_FIELD_IDX_0_LENGTH), VAR_DATA_FIELD_IDX_0); offset += VAR_DATA_FIELD_IDX_0_LENGTH; - EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_1_LENGTH), std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); + EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_1_LENGTH), + std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); offset += TAG_GROUP_1_IDX_1_LENGTH; // nested entries @@ -460,7 +470,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage3Correctly) TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage3Correctly) { - char buffer[2048]; + char buffer[2048] = {}; std::uint64_t sz = encodeTestMessage3(buffer, 0, sizeof(buffer)); EXPECT_EQ(sz, expectedTestMessage3Size); @@ -476,7 +486,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage3Correctly) entries.next(); EXPECT_EQ(entries.tagGroup1Length(), TAG_GROUP_1_IDX_0_LENGTH); - EXPECT_EQ(std::string(entries.tagGroup1(), entries.tagGroup1Length()), std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); + EXPECT_EQ(std::string(entries.tagGroup1(), entries.tagGroup1Length()), + std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); TestMessage3::Entries::NestedEntries &nestedEntries0 = entries.nestedEntries(); EXPECT_EQ(nestedEntries0.count(), NESTED_ENTRIES_COUNT); @@ -486,21 +497,24 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage3Correctly) EXPECT_EQ(nestedEntries0.tagGroup2(), TAG_GROUP_2_IDX_0); EXPECT_EQ(nestedEntries0.varDataFieldNestedLength(), VAR_DATA_FIELD_NESTED_IDX_0_LENGTH); - EXPECT_EQ(std::string(nestedEntries0.varDataFieldNested(), VAR_DATA_FIELD_NESTED_IDX_0_LENGTH), VAR_DATA_FIELD_NESTED_IDX_0); + EXPECT_EQ(std::string(nestedEntries0.varDataFieldNested(), VAR_DATA_FIELD_NESTED_IDX_0_LENGTH), + VAR_DATA_FIELD_NESTED_IDX_0); ASSERT_TRUE(nestedEntries0.hasNext()); nestedEntries0.next(); EXPECT_EQ(nestedEntries0.tagGroup2(), TAG_GROUP_2_IDX_1); EXPECT_EQ(nestedEntries0.varDataFieldNestedLength(), VAR_DATA_FIELD_NESTED_IDX_1_LENGTH); - EXPECT_EQ(std::string(nestedEntries0.varDataFieldNested(), VAR_DATA_FIELD_NESTED_IDX_1_LENGTH), VAR_DATA_FIELD_NESTED_IDX_1); + EXPECT_EQ(std::string(nestedEntries0.varDataFieldNested(), VAR_DATA_FIELD_NESTED_IDX_1_LENGTH), + VAR_DATA_FIELD_NESTED_IDX_1); ASSERT_TRUE(nestedEntries0.hasNext()); nestedEntries0.next(); EXPECT_EQ(nestedEntries0.tagGroup2(), TAG_GROUP_2_IDX_2); EXPECT_EQ(nestedEntries0.varDataFieldNestedLength(), VAR_DATA_FIELD_NESTED_IDX_2_LENGTH); - EXPECT_EQ(std::string(nestedEntries0.varDataFieldNested(), VAR_DATA_FIELD_NESTED_IDX_2_LENGTH), VAR_DATA_FIELD_NESTED_IDX_2); + EXPECT_EQ(std::string(nestedEntries0.varDataFieldNested(), VAR_DATA_FIELD_NESTED_IDX_2_LENGTH), + VAR_DATA_FIELD_NESTED_IDX_2); EXPECT_EQ(entries.varDataFieldLength(), VAR_DATA_FIELD_IDX_0_LENGTH); EXPECT_EQ(std::string(entries.varDataField(), VAR_DATA_FIELD_IDX_0_LENGTH), VAR_DATA_FIELD_IDX_0); @@ -516,21 +530,24 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage3Correctly) EXPECT_EQ(nestedEntries1.tagGroup2(), TAG_GROUP_2_IDX_3); EXPECT_EQ(nestedEntries1.varDataFieldNestedLength(), VAR_DATA_FIELD_NESTED_IDX_3_LENGTH); - EXPECT_EQ(std::string(nestedEntries1.varDataFieldNested(), VAR_DATA_FIELD_NESTED_IDX_3_LENGTH), VAR_DATA_FIELD_NESTED_IDX_3); + EXPECT_EQ(std::string(nestedEntries1.varDataFieldNested(), VAR_DATA_FIELD_NESTED_IDX_3_LENGTH), + VAR_DATA_FIELD_NESTED_IDX_3); ASSERT_TRUE(nestedEntries1.hasNext()); nestedEntries1.next(); EXPECT_EQ(nestedEntries1.tagGroup2(), TAG_GROUP_2_IDX_4); EXPECT_EQ(nestedEntries1.varDataFieldNestedLength(), VAR_DATA_FIELD_NESTED_IDX_4_LENGTH); - EXPECT_EQ(std::string(nestedEntries1.varDataFieldNested(), VAR_DATA_FIELD_NESTED_IDX_4_LENGTH), VAR_DATA_FIELD_NESTED_IDX_4); + EXPECT_EQ(std::string(nestedEntries1.varDataFieldNested(), VAR_DATA_FIELD_NESTED_IDX_4_LENGTH), + VAR_DATA_FIELD_NESTED_IDX_4); ASSERT_TRUE(nestedEntries1.hasNext()); nestedEntries1.next(); EXPECT_EQ(nestedEntries1.tagGroup2(), TAG_GROUP_2_IDX_5); EXPECT_EQ(nestedEntries1.varDataFieldNestedLength(), VAR_DATA_FIELD_NESTED_IDX_5_LENGTH); - EXPECT_EQ(std::string(nestedEntries1.varDataFieldNested(), VAR_DATA_FIELD_NESTED_IDX_5_LENGTH), VAR_DATA_FIELD_NESTED_IDX_5); + EXPECT_EQ(std::string(nestedEntries1.varDataFieldNested(), VAR_DATA_FIELD_NESTED_IDX_5_LENGTH), + VAR_DATA_FIELD_NESTED_IDX_5); EXPECT_EQ(entries.varDataFieldLength(), VAR_DATA_FIELD_IDX_1_LENGTH); EXPECT_EQ(std::string(entries.varDataField(), VAR_DATA_FIELD_IDX_1_LENGTH), VAR_DATA_FIELD_IDX_1); @@ -540,7 +557,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage3Correctly) TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage4Correctly) { - char buffer[2048]; + char buffer[2048] = {}; const char *bp = buffer; std::uint64_t sz = encodeTestMessage4(buffer, 0, sizeof(buffer)); @@ -578,7 +595,7 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage4Correctly) TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage4Correctly) { - char buffer[2048]; + char buffer[2048] = {}; std::uint64_t sz = encodeTestMessage4(buffer, 0, sizeof(buffer)); EXPECT_EQ(sz, expectedTestMessage4Size); diff --git a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp index ec0a6b0844..d7cd2e536e 100644 --- a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp +++ b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp @@ -27,11 +27,11 @@ using namespace message::block::length::test; class MessageBlockLengthIrTest : public testing::Test, public OtfMessageDecoder::BasicTokenListener { public: - char m_buffer[2048]; - IrDecoder m_irDecoder; - int m_eventNumber; + char m_buffer[2048] = {}; + IrDecoder m_irDecoder = {}; + int m_eventNumber = 0; - virtual void SetUp() + void SetUp() override { m_eventNumber = 0; } @@ -56,21 +56,21 @@ class MessageBlockLengthIrTest : public testing::Test, public OtfMessageDecoder: MsgName::GrName &grp = msg.grNameCount(2); grp.next() - .grField1(10) - .grField2(20); + .grField1(10) + .grField2(20); grp.next() - .grField1(30) - .grField2(40); + .grField1(30) + .grField2(40); return hdr.encodedLength() + msg.encodedLength(); } void onEncoding( - Token& fieldToken, + Token &fieldToken, const char *buffer, - Token& typeToken, - std::uint64_t actingVersion) + Token &typeToken, + std::uint64_t actingVersion) override { switch (m_eventNumber++) { @@ -80,63 +80,68 @@ class MessageBlockLengthIrTest : public testing::Test, public OtfMessageDecoder: EXPECT_EQ(typeToken.encoding().getAsUInt(buffer), 187u); break; } + case 3: { EXPECT_EQ(typeToken.encoding().primitiveType(), PrimitiveType::UINT64); EXPECT_EQ(typeToken.encoding().getAsUInt(buffer), 10u); break; } + case 4: { EXPECT_EQ(typeToken.encoding().primitiveType(), PrimitiveType::INT64); EXPECT_EQ(typeToken.encoding().getAsInt(buffer), 20); break; } + case 5: { EXPECT_EQ(typeToken.encoding().primitiveType(), PrimitiveType::UINT64); EXPECT_EQ(typeToken.encoding().getAsUInt(buffer), 30u); break; } + case 6: { EXPECT_EQ(typeToken.encoding().primitiveType(), PrimitiveType::INT64); EXPECT_EQ(typeToken.encoding().getAsInt(buffer), 40); break; } + default: FAIL() << "unknown event number " << m_eventNumber; } - } void onBitSet( - Token& fieldToken, + Token &fieldToken, const char *buffer, - std::vector& tokens, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex, - std::uint64_t actingVersion) + std::uint64_t actingVersion) override { switch (m_eventNumber++) { case 1: { - const Token& typeToken = tokens.at(fromIndex + 1); - const Encoding& encoding = typeToken.encoding(); + const Token &typeToken = tokens.at(fromIndex + 1); + const Encoding &encoding = typeToken.encoding(); EXPECT_EQ(encoding.primitiveType(), PrimitiveType::UINT8); EXPECT_EQ(encoding.getAsUInt(buffer), 0x2u); break; } + default: FAIL() << "unknown event number " << m_eventNumber; } } void onGroupHeader( - Token& token, - std::uint64_t numInGroup) + Token &token, + std::uint64_t numInGroup) override { switch (m_eventNumber++) { @@ -145,6 +150,7 @@ class MessageBlockLengthIrTest : public testing::Test, public OtfMessageDecoder: EXPECT_EQ(numInGroup, 2u); break; } + default: FAIL() << "unknown event number " << m_eventNumber; } @@ -175,7 +181,7 @@ TEST_F(MessageBlockLengthIrTest, shouldHandleAllEventsCorrectlyInOrder) MsgName::sbeTemplateId(), MsgName::sbeSchemaVersion()); ASSERT_TRUE(headerTokens != nullptr); - ASSERT_TRUE(messageTokens!= nullptr); + ASSERT_TRUE(messageTokens != nullptr); OtfHeaderDecoder headerDecoder(headerTokens); diff --git a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp index edf4e878c7..b4df6d3f38 100644 --- a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp +++ b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp @@ -190,21 +190,21 @@ enum EventNumber class Rc3OtfFullIrTest : public testing::Test { public: - char m_buffer[2048]; - IrDecoder m_irDecoder; - int m_eventNumber; - int m_compositeLevel; + char m_buffer[2048] = {}; + IrDecoder m_irDecoder = {}; + int m_eventNumber = 0; + int m_compositeLevel = 0; - virtual void SetUp() + void SetUp() override { m_eventNumber = 0; m_compositeLevel = 0; } std::string determineName( - Token& fieldToken, - std::vector& tokens, - std::size_t fromIndex) + Token &fieldToken, + std::vector &tokens, + std::size_t fromIndex) const { return (m_compositeLevel > 1) ? tokens.at(fromIndex).name() : fieldToken.name(); } @@ -243,7 +243,7 @@ class Rc3OtfFullIrTest : public testing::Test .putManufacturerCode(MANUFACTURER_CODE) .booster().boostType(BoostType::NITROUS).horsePower(200); - Car::FuelFigures& fuelFigures = car.fuelFiguresCount(FUEL_FIGURES_COUNT); + Car::FuelFigures &fuelFigures = car.fuelFiguresCount(FUEL_FIGURES_COUNT); fuelFigures .next().speed(fuel1Speed).mpg(fuel1Mpg); @@ -266,16 +266,16 @@ class Rc3OtfFullIrTest : public testing::Test perfFigs.next() .octaneRating(perf1Octane) .accelerationCount(ACCELERATION_COUNT) - .next().mph(perf1aMph).seconds(perf1aSeconds) - .next().mph(perf1bMph).seconds(perf1bSeconds) - .next().mph(perf1cMph).seconds(perf1cSeconds); + .next().mph(perf1aMph).seconds(perf1aSeconds) + .next().mph(perf1bMph).seconds(perf1bSeconds) + .next().mph(perf1cMph).seconds(perf1cSeconds); perfFigs.next() .octaneRating(perf2Octane) .accelerationCount(ACCELERATION_COUNT) - .next().mph(perf2aMph).seconds(perf2aSeconds) - .next().mph(perf2bMph).seconds(perf2bSeconds) - .next().mph(perf2cMph).seconds(perf2cSeconds); + .next().mph(perf2aMph).seconds(perf2aSeconds) + .next().mph(perf2bMph).seconds(perf2bSeconds) + .next().mph(perf2cMph).seconds(perf2cSeconds); car.putManufacturer(MANUFACTURER, static_cast(strlen(MANUFACTURER))); car.putModel(MODEL, static_cast(strlen(MODEL))); @@ -285,7 +285,7 @@ class Rc3OtfFullIrTest : public testing::Test return hdr.encodedLength() + car.encodedLength(); } - void onBeginMessage(Token& token) + void onBeginMessage(Token &token) { std::cout << m_eventNumber << ": Begin Message " << token.name() << " id " << token.fieldId() << "\n"; @@ -294,7 +294,7 @@ class Rc3OtfFullIrTest : public testing::Test m_eventNumber++; } - void onEndMessage(Token& token) + void onEndMessage(Token &token) { std::cout << m_eventNumber << ": End Message " << token.name() << "\n"; @@ -304,15 +304,15 @@ class Rc3OtfFullIrTest : public testing::Test } void onEncoding( - Token& fieldToken, + Token &fieldToken, const char *buffer, - Token& typeToken, + Token &typeToken, std::uint64_t actingVersion) { std::string name = (m_compositeLevel > 1) ? typeToken.name() : fieldToken.name(); - std::cout << m_eventNumber << ": Encoding " << name << " offset " << typeToken.offset() << "\n"; + std::cout << m_eventNumber << ": Encoding " << name << " offset " << typeToken.offset() << "\n"; - const Encoding& encoding = typeToken.encoding(); + const Encoding &encoding = typeToken.encoding(); switch (EventNumber(m_eventNumber)) { @@ -390,7 +390,7 @@ class Rc3OtfFullIrTest : public testing::Test EXPECT_TRUE(typeToken.isConstantEncoding()); EXPECT_EQ(encoding.primitiveType(), PrimitiveType::CHAR); - const PrimitiveValue& value = encoding.constValue(); + const PrimitiveValue &value = encoding.constValue(); EXPECT_EQ(value.size(), static_cast(6)); EXPECT_EQ(std::string(value.getArray(), value.size()), std::string("Petrol")); break; @@ -571,17 +571,17 @@ class Rc3OtfFullIrTest : public testing::Test } void onEnum( - Token& fieldToken, + Token &fieldToken, const char *buffer, - std::vector& tokens, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex, std::uint64_t actingVersion) { std::cout << m_eventNumber << ": Enum " << determineName(fieldToken, tokens, fromIndex) << "\n"; - const Token& typeToken = tokens.at(fromIndex + 1); - const Encoding& encoding = typeToken.encoding(); + const Token &typeToken = tokens.at(fromIndex + 1); + const Encoding &encoding = typeToken.encoding(); switch (EventNumber(m_eventNumber)) { @@ -596,7 +596,7 @@ class Rc3OtfFullIrTest : public testing::Test bool found = false; for (size_t i = fromIndex + 1; i < toIndex; i++) { - const Token& token = tokens.at(i); + const Token &token = tokens.at(i); const std::uint64_t constValue = token.encoding().constValue().getAsUInt(); std::cout << " " << token.name() << " = " << constValue << "\n"; @@ -622,7 +622,7 @@ class Rc3OtfFullIrTest : public testing::Test bool found = false; for (size_t i = fromIndex + 1; i < toIndex; i++) { - const Token& token = tokens.at(i); + const Token &token = tokens.at(i); const std::int64_t constValue = token.encoding().constValue().getAsUInt(); std::cout << " " << token.name() << " = " << constValue << "\n"; @@ -657,7 +657,7 @@ class Rc3OtfFullIrTest : public testing::Test bool found = false; for (size_t i = fromIndex + 1; i < toIndex; i++) { - const Token& token = tokens.at(i); + const Token &token = tokens.at(i); const std::int64_t constValue = token.encoding().constValue().getAsUInt(); std::cout << " " << token.name() << " = " << constValue << "\n"; @@ -680,17 +680,17 @@ class Rc3OtfFullIrTest : public testing::Test } void onBitSet( - Token& fieldToken, + Token &fieldToken, const char *buffer, - std::vector& tokens, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex, std::uint64_t actingVersion) { std::cout << m_eventNumber << ": Bit Set " << fieldToken.name() << "\n"; - const Token& typeToken = tokens.at(fromIndex + 1); - const Encoding& encoding = typeToken.encoding(); + const Token &typeToken = tokens.at(fromIndex + 1); + const Encoding &encoding = typeToken.encoding(); switch (EventNumber(m_eventNumber)) { @@ -705,7 +705,7 @@ class Rc3OtfFullIrTest : public testing::Test int bitsSet = 0; for (size_t i = fromIndex + 1; i < toIndex; i++) { - const Token& token = tokens.at(i); + const Token &token = tokens.at(i); const std::uint64_t constValue = token.encoding().constValue().getAsUInt(); if (constValue && value) @@ -732,8 +732,8 @@ class Rc3OtfFullIrTest : public testing::Test } void onBeginComposite( - Token& fieldToken, - std::vector& tokens, + Token &fieldToken, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex) { @@ -764,8 +764,8 @@ class Rc3OtfFullIrTest : public testing::Test } void onEndComposite( - Token& fieldToken, - std::vector& tokens, + Token &fieldToken, + std::vector &tokens, std::size_t fromIndex, std::size_t toIndex) { @@ -795,7 +795,7 @@ class Rc3OtfFullIrTest : public testing::Test m_eventNumber++; } - void onGroupHeader(Token& token, std::uint64_t numInGroup) + void onGroupHeader(Token &token, std::uint64_t numInGroup) { std::cout << m_eventNumber << ": Group Header " << token.name() << " num " << numInGroup << "\n"; @@ -837,7 +837,7 @@ class Rc3OtfFullIrTest : public testing::Test } - void onBeginGroup(Token& token, std::uint64_t groupIndex, std::uint64_t numInGroup) + void onBeginGroup(Token &token, std::uint64_t groupIndex, std::uint64_t numInGroup) { std::cout << m_eventNumber << ": Begin Group " << token.name() << " " << groupIndex + 1 << "/" << numInGroup << "\n"; @@ -939,7 +939,7 @@ class Rc3OtfFullIrTest : public testing::Test m_eventNumber++; } - void onEndGroup(Token& token, std::uint64_t groupIndex, std::uint64_t numInGroup) + void onEndGroup(Token &token, std::uint64_t groupIndex, std::uint64_t numInGroup) { std::cout << m_eventNumber << ": End Group " << token.name() << " " << groupIndex + 1 << "/" << numInGroup << "\n"; @@ -1042,10 +1042,10 @@ class Rc3OtfFullIrTest : public testing::Test } void onVarData( - Token& fieldToken, + Token &fieldToken, const char *buffer, std::uint64_t length, - Token& typeToken) + Token &typeToken) { std::cout << m_eventNumber << ": Data " << fieldToken.name() << "\n"; @@ -1149,7 +1149,7 @@ TEST_F(Rc3OtfFullIrTest, shouldHandleAllEventsCorrectlyAndInOrder) Car::sbeTemplateId(), Car::sbeSchemaVersion()); ASSERT_TRUE(headerTokens != nullptr); - ASSERT_TRUE(messageTokens!= nullptr); + ASSERT_TRUE(messageTokens != nullptr); OtfHeaderDecoder headerDecoder(headerTokens); @@ -1175,24 +1175,25 @@ TEST_P(Rc3OtfFullIrLengthTest, shouldExceptionIfLengthTooShort) Car::sbeTemplateId(), Car::sbeSchemaVersion()); ASSERT_TRUE(headerTokens != nullptr); - ASSERT_TRUE(messageTokens!= nullptr); + ASSERT_TRUE(messageTokens != nullptr); OtfHeaderDecoder headerDecoder(headerTokens); EXPECT_EQ(headerDecoder.encodedLength(), MessageHeader::encodedLength()); - std::size_t length = static_cast(GetParam()); + auto length = static_cast(GetParam()); std::uint64_t actingVersion = headerDecoder.getSchemaVersion(m_buffer); std::uint64_t blockLength = headerDecoder.getBlockLength(m_buffer); // set up so that if an error occurs, we intentionally write off the end of a new buffer so that valgrind can help // catch errors as well. EXPECT_THROW( - { - std::unique_ptr decodeBuffer(new char[length]); + { + std::unique_ptr decodeBuffer(new char[length]); - ::memcpy(decodeBuffer.get(), m_buffer + headerDecoder.encodedLength(), length); - OtfMessageDecoder::decode(decodeBuffer.get(), length, actingVersion, blockLength, messageTokens, *this); - }, std::runtime_error); + ::memcpy(decodeBuffer.get(), m_buffer + headerDecoder.encodedLength(), length); + OtfMessageDecoder::decode(decodeBuffer.get(), length, actingVersion, blockLength, messageTokens, *this); + }, + std::runtime_error); } INSTANTIATE_TEST_SUITE_P( From f3a1f15e01ee632cf2565d2bf363a8c8b3843106 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 22 Jan 2021 16:12:49 +0000 Subject: [PATCH 0633/1594] [C++] Samples and tests code improvements. --- sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp index b4df6d3f38..f6ae957bec 100644 --- a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp +++ b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp @@ -594,7 +594,7 @@ class Rc3OtfFullIrTest : public testing::Test EXPECT_EQ(value, static_cast(1)); bool found = false; - for (size_t i = fromIndex + 1; i < toIndex; i++) + for (std::size_t i = fromIndex + 1; i < toIndex; i++) { const Token &token = tokens.at(i); const std::uint64_t constValue = token.encoding().constValue().getAsUInt(); @@ -620,7 +620,7 @@ class Rc3OtfFullIrTest : public testing::Test EXPECT_EQ(value, static_cast('A')); bool found = false; - for (size_t i = fromIndex + 1; i < toIndex; i++) + for (std::size_t i = fromIndex + 1; i < toIndex; i++) { const Token &token = tokens.at(i); const std::int64_t constValue = token.encoding().constValue().getAsUInt(); @@ -655,7 +655,7 @@ class Rc3OtfFullIrTest : public testing::Test EXPECT_EQ(value, static_cast('N')); bool found = false; - for (size_t i = fromIndex + 1; i < toIndex; i++) + for (std::size_t i = fromIndex + 1; i < toIndex; i++) { const Token &token = tokens.at(i); const std::int64_t constValue = token.encoding().constValue().getAsUInt(); @@ -703,7 +703,7 @@ class Rc3OtfFullIrTest : public testing::Test EXPECT_EQ(value, static_cast(0x6)); int bitsSet = 0; - for (size_t i = fromIndex + 1; i < toIndex; i++) + for (std::size_t i = fromIndex + 1; i < toIndex; i++) { const Token &token = tokens.at(i); const std::uint64_t constValue = token.encoding().constValue().getAsUInt(); From ee4c65abb28c67019282e11e2bdc72a202420dcf Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 22 Jan 2021 16:23:19 +0000 Subject: [PATCH 0634/1594] [C++] Samples and tests code improvements. --- sbe-tool/src/test/cpp/CodeGenTest.cpp | 47 +++++++++---------- .../src/test/cpp/CompositeOffsetsIrTest.cpp | 8 ++-- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index 23f36fb15c..04df822fa2 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -177,7 +177,7 @@ class CodeGenTest : public testing::Test return encodeCar(m_car); } - void expectDisplayString(const char *expectedDisplayString, Car &carDecoder) + static void expectDisplayString(const char *expectedDisplayString, Car &carDecoder) { std::stringstream displayStream; @@ -186,10 +186,10 @@ class CodeGenTest : public testing::Test displayStream.clear(); } - MessageHeader m_hdr; - MessageHeader m_hdrDecoder; - Car m_car; - Car m_carDecoder; + MessageHeader m_hdr = {}; + MessageHeader m_hdrDecoder = {}; + Car m_car = {}; + Car m_carDecoder = {}; }; TEST_F(CodeGenTest, shouldReturnCorrectValuesForMessageHeaderStaticFields) @@ -212,7 +212,7 @@ TEST_F(CodeGenTest, shouldReturnCorrectValuesForCarStaticFields) TEST_F(CodeGenTest, shouldBeAbleToEncodeMessageHeaderCorrectly) { - char buffer[BUFFER_LEN]; + char buffer[BUFFER_LEN] = {}; const char *bp = buffer; std::uint64_t sz = encodeHdr(buffer, 0, sizeof(buffer)); @@ -226,7 +226,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeMessageHeaderCorrectly) TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeMessageHeaderCorrectly) { - char buffer[BUFFER_LEN]; + char buffer[BUFFER_LEN] = {}; encodeHdr(buffer, 0, sizeof(buffer)); @@ -290,7 +290,7 @@ TEST_F(CodeGenTest, shouldReturnCorrectValuesForCarFieldIdsAndCharacterEncoding) TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) { - char buffer[BUFFER_LEN]; + char buffer[BUFFER_LEN] = {}; const char *bp = buffer; std::uint64_t sz = encodeCar(buffer, 0, sizeof(buffer)); @@ -452,7 +452,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) TEST_F(CodeGenTest, shouldBeAbleToEncodeHeaderPlusCarCorrectly) { - char buffer[BUFFER_LEN]; + char buffer[BUFFER_LEN] = {}; const char *bp = buffer; std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer)); @@ -462,16 +462,16 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeHeaderPlusCarCorrectly) EXPECT_EQ(carEncodedLength, expectedCarEncodedLength); EXPECT_EQ(*((std::uint16_t *)bp), Car::sbeBlockLength()); - const size_t activationCodePosition = + const std::size_t activationCodePosition = (hdrSz + carEncodedLength) - (ACTIVATION_CODE_LENGTH + sizeof(std::uint32_t) + COLOR_LENGTH); - const size_t activationCodeLengthPosition = activationCodePosition - sizeof(std::uint16_t); + const std::size_t activationCodeLengthPosition = activationCodePosition - sizeof(std::uint16_t); EXPECT_EQ(*(std::uint16_t *)(bp + activationCodeLengthPosition), ACTIVATION_CODE_LENGTH); EXPECT_EQ(std::string(bp + activationCodePosition, ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); } TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) { - char buffer[BUFFER_LEN]; + char buffer[BUFFER_LEN] = {}; std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer)); std::uint64_t carEncodedLength = encodeCar(buffer, m_hdr.encodedLength(), sizeof(buffer) - m_hdr.encodedLength()); @@ -613,13 +613,9 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) struct CallbacksForEach { - int countOfFuelFigures; - int countOfPerformanceFigures; - int countOfAccelerations; - - CallbacksForEach() : countOfFuelFigures(0), countOfPerformanceFigures(0), countOfAccelerations(0) - { - } + int countOfFuelFigures = 0; + int countOfPerformanceFigures = 0; + int countOfAccelerations = 0; void operator()(Car::FuelFigures &fuelFigures) { @@ -643,7 +639,7 @@ struct CallbacksForEach TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) { - char buffer[BUFFER_LEN]; + char buffer[BUFFER_LEN] = {}; MessageHeader hdr(buffer, sizeof(buffer), 0); Car car(buffer + hdr.encodedLength(), sizeof(buffer) - hdr.encodedLength()); @@ -674,7 +670,7 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) { cbs.countOfFuelFigures++; - char tmp[256]; + char tmp[256] = {}; figures.getUsageDescription(tmp, sizeof(tmp)); }); #else @@ -704,7 +700,7 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) EXPECT_EQ(cbs.countOfPerformanceFigures, PERFORMANCE_FIGURES_COUNT); EXPECT_EQ(cbs.countOfAccelerations, ACCELERATION_COUNT * PERFORMANCE_FIGURES_COUNT); - char tmp[256]; + char tmp[256] = {}; EXPECT_EQ(carDecoder.getManufacturer(tmp, sizeof(tmp)), MANUFACTURER_LENGTH); EXPECT_EQ(std::string(tmp, MANUFACTURER_LENGTH), MANUFACTURER); @@ -748,7 +744,7 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) std::string activationCode(ACTIVATION_CODE, ACTIVATION_CODE_LENGTH); std::string color(COLOR, COLOR_LENGTH); - char buffer[BUFFER_LEN]; + char buffer[BUFFER_LEN] = {}; std::uint64_t baseOffset = MessageHeader::encodedLength(); Car car; car.wrapForEncode(buffer, baseOffset, sizeof(buffer)); @@ -811,7 +807,7 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) { - char buffer[2048]; + char buffer[BUFFER_LEN] = {}; Car carEncoder(buffer, sizeof(buffer)); std::uint64_t carEncodedLength = encodeCar(carEncoder); @@ -878,8 +874,7 @@ TEST_F(CodeGenTest, shouldPrintFullDecodedFlyweightRegardlessOfReadPosition) "{\"mph\": 100, \"seconds\": 11.8}]}], \"manufacturer\": \"Honda\", \"model\": \"Civic VTi\", " "\"activationCode\": \"deadbeef\", \"color\": \"racing green\"}"; - char buffer[2048]; - memset(buffer, 0, 2048); + char buffer[BUFFER_LEN] = {}; Car carEncoder(buffer, sizeof(buffer)); std::uint64_t carEncodedLength = encodeCar(carEncoder); diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp index 8500cc46e4..879ab2bde3 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp @@ -29,11 +29,11 @@ static const char *SCHEMA_FILENAME = "composite-offsets-schema.sbeir"; class CompositeOffsetsIrTest : public testing::Test, public OtfMessageDecoder::BasicTokenListener { public: - char m_buffer[2048]; - IrDecoder m_irDecoder; - int m_eventNumber; + char m_buffer[2048] = {}; + IrDecoder m_irDecoder = {}; + int m_eventNumber = 0; - virtual void SetUp() + void SetUp() override { m_eventNumber = 0; } From 3cb6b605286c5c0dca0bf34960a265f0ca80679a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 22 Jan 2021 16:43:02 +0000 Subject: [PATCH 0635/1594] [C] Samples and tests code improvements. --- sbe-tool/src/test/c/BoundsCheckTest.cpp | 64 ++++---- sbe-tool/src/test/c/CComplianceTest.c | 27 +++- sbe-tool/src/test/c/CodeGenTest.cpp | 98 ++++++------ sbe-tool/src/test/c/GroupWithDataTest.cpp | 178 ++++++++++++++-------- 4 files changed, 222 insertions(+), 145 deletions(-) diff --git a/sbe-tool/src/test/c/BoundsCheckTest.cpp b/sbe-tool/src/test/c/BoundsCheckTest.cpp index 0b17a3d9a0..ed809cfd11 100644 --- a/sbe-tool/src/test/c/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/c/BoundsCheckTest.cpp @@ -20,8 +20,8 @@ #include -#include -#include +#include "code_generation_test/car.h" +#include "code_generation_test/messageHeader.h" #define CGT(name) code_generation_test_##name @@ -320,7 +320,7 @@ class BoundsCheckTest : public testing::Test std::uint64_t decodeCarFuelFigures() { - char tmp[256]; + char tmp[256] = { 0 }; CGT(car_fuelFigures) fuelFigures; if (!CGT(car_get_fuelFigures)(&m_carDecoder, &fuelFigures)) { @@ -465,7 +465,7 @@ class BoundsCheckTest : public testing::Test std::uint64_t decodeCarManufacturerModelAndActivationCode() { - char tmp[256]; + char tmp[256] = { 0 }; std::uint64_t lengthOfField = CGT(car_get_manufacturer)(&m_carDecoder, tmp, sizeof(tmp)); if (!lengthOfField) { @@ -496,10 +496,10 @@ class BoundsCheckTest : public testing::Test } private: - CGT(messageHeader) m_hdr; - CGT(messageHeader) m_hdrDecoder; - CGT(car) m_car; - CGT(car) m_carDecoder; + CGT(messageHeader) m_hdr = {}; + CGT(messageHeader) m_hdrDecoder = {}; + CGT(car) m_car = {}; + CGT(car) m_carDecoder = {}; }; class HeaderBoundsCheckTest : public BoundsCheckTest, public ::testing::WithParamInterface @@ -512,24 +512,26 @@ TEST_P(HeaderBoundsCheckTest, shouldExceptionWhenBufferTooShortForEncodeOfHeader std::unique_ptr buffer(new char[length]); EXPECT_THROW( - { - encodeHdr(buffer.get(), 0, length); - }, std::runtime_error); + { + encodeHdr(buffer.get(), 0, length); + }, + std::runtime_error); } TEST_P(HeaderBoundsCheckTest, shouldExceptionWhenBufferTooShortForDecodeOfHeader) { const int length = GetParam(); - char encodeBuffer[8]; + char encodeBuffer[8] = { 0 }; std::unique_ptr buffer(new char[length]); encodeHdr(encodeBuffer, 0, sizeof(encodeBuffer)); EXPECT_THROW( - { - std::memcpy(buffer.get(), encodeBuffer, length); - decodeHdr(buffer.get(), 0, length); - }, std::runtime_error); + { + std::memcpy(buffer.get(), encodeBuffer, length); + decodeHdr(buffer.get(), 0, length); + }, + std::runtime_error); } INSTANTIATE_TEST_SUITE_P( @@ -547,18 +549,19 @@ TEST_P(MessageBoundsCheckTest, shouldExceptionWhenBufferTooShortForEncodeOfMessa std::unique_ptr buffer(new char[length]); EXPECT_THROW( - { - encodeCarRoot(buffer.get(), 0, length); - encodeCarFuelFigures(); - encodeCarPerformanceFigures(); - encodeCarManufacturerModelAndActivationCode(); - }, std::runtime_error); + { + encodeCarRoot(buffer.get(), 0, length); + encodeCarFuelFigures(); + encodeCarPerformanceFigures(); + encodeCarManufacturerModelAndActivationCode(); + }, + std::runtime_error); } TEST_P(MessageBoundsCheckTest, shouldExceptionWhenBufferTooShortForDecodeOfMessage) { const int length = GetParam(); - char encodeBuffer[191]; + char encodeBuffer[191] = { 0 }; std::unique_ptr buffer(new char[length]); encodeCarRoot(encodeBuffer, 0, sizeof(encodeBuffer)); @@ -567,13 +570,14 @@ TEST_P(MessageBoundsCheckTest, shouldExceptionWhenBufferTooShortForDecodeOfMessa encodeCarManufacturerModelAndActivationCode(); EXPECT_THROW( - { - std::memcpy(buffer.get(), encodeBuffer, length); - decodeCarRoot(buffer.get(), 0, length); - decodeCarFuelFigures(); - decodeCarPerformanceFigures(); - decodeCarManufacturerModelAndActivationCode(); - }, std::runtime_error); + { + std::memcpy(buffer.get(), encodeBuffer, length); + decodeCarRoot(buffer.get(), 0, length); + decodeCarFuelFigures(); + decodeCarPerformanceFigures(); + decodeCarManufacturerModelAndActivationCode(); + }, + std::runtime_error); } INSTANTIATE_TEST_SUITE_P( diff --git a/sbe-tool/src/test/c/CComplianceTest.c b/sbe-tool/src/test/c/CComplianceTest.c index 5e7d93c89a..8cead8201b 100644 --- a/sbe-tool/src/test/c/CComplianceTest.c +++ b/sbe-tool/src/test/c/CComplianceTest.c @@ -1,10 +1,25 @@ -#include -#include +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "code_generation_test/car.h" +#include "code_generation_test/messageHeader.h" -#include -#include -#include -#include +#include "group_with_data/testMessage1.h" +#include "group_with_data/testMessage2.h" +#include "group_with_data/testMessage3.h" +#include "group_with_data/testMessage4.h" int main() { diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index 841d749ad2..f9198e35ae 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -15,13 +15,14 @@ */ #include +#include +#include #include -#include -#include -#include -#include +#include "code_generation_test/car.h" +#include "code_generation_test/messageHeader.h" + #define CGT(name) code_generation_test_##name @@ -90,7 +91,7 @@ static const std::uint8_t engineNumCylinders = 4; class CodeGenTest : public testing::Test { public: - static std::uint64_t encodeHdr(CGT(messageHeader)& hdr) + static std::uint64_t encodeHdr(CGT(messageHeader) &hdr) { CGT(messageHeader_set_blockLength)(&hdr, CGT(car_sbe_block_length)()); CGT(messageHeader_set_templateId)(&hdr, CGT(car_sbe_template_id)()); @@ -100,7 +101,7 @@ class CodeGenTest : public testing::Test return CGT(messageHeader_encoded_length)(); } - static std::uint64_t encodeCar(CGT(car)& car) + static std::uint64_t encodeCar(CGT(car) &car) { CGT(car_set_serialNumber)(&car, SERIAL_NUMBER); CGT(car_set_modelYear)(&car, MODEL_YEAR); @@ -171,9 +172,9 @@ class CodeGenTest : public testing::Test CGT(car_performanceFigures) perfFigs; if (!CGT(car_performanceFigures_set_count)( - &car, - &perfFigs, - PERFORMANCE_FIGURES_COUNT)) + &car, + &perfFigs, + PERFORMANCE_FIGURES_COUNT)) { throw std::runtime_error(sbe_strerror(errno)); } @@ -237,10 +238,10 @@ class CodeGenTest : public testing::Test return encodeCar(m_car); } - CGT(messageHeader) m_hdr; - CGT(messageHeader) m_hdrDecoder; - CGT(car) m_car; - CGT(car) m_carDecoder; + CGT(messageHeader) m_hdr = {}; + CGT(messageHeader) m_hdrDecoder ={}; + CGT(car) m_car = {}; + CGT(car) m_carDecoder = {}; }; TEST_F(CodeGenTest, shouldReturnCorrectValuesForMessageHeaderStaticFields) @@ -263,7 +264,7 @@ TEST_F(CodeGenTest, shouldReturnCorrectValuesForCarStaticFields) TEST_F(CodeGenTest, shouldBeAbleToEncodeMessageHeaderCorrectly) { - char buffer[BUFFER_LEN]; + char buffer[BUFFER_LEN] = {}; const char *bp = buffer; std::uint64_t sz = encodeHdr(buffer, 0, sizeof(buffer)); @@ -277,7 +278,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeMessageHeaderCorrectly) TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeMessageHeaderCorrectly) { - char buffer[BUFFER_LEN]; + char buffer[BUFFER_LEN] = {}; encodeHdr(buffer, 0, sizeof(buffer)); @@ -344,7 +345,7 @@ TEST_F(CodeGenTest, shouldReturnCorrectValuesForCarFieldIdsAndCharacterEncoding) TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) { - char buffer[BUFFER_LEN]; + char buffer[BUFFER_LEN] = {}; const char *bp = buffer; std::uint64_t sz = encodeCar(buffer, 0, sizeof(buffer)); @@ -377,7 +378,8 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) offset += sizeof(std::uint16_t); EXPECT_EQ(*(bp + offset), engineNumCylinders); offset += sizeof(std::uint8_t); - EXPECT_EQ(std::string(bp + offset, MANUFACTURER_CODE_LENGTH), std::string(MANUFACTURER_CODE, MANUFACTURER_CODE_LENGTH)); + EXPECT_EQ(std::string(bp + offset, MANUFACTURER_CODE_LENGTH), + std::string(MANUFACTURER_CODE, MANUFACTURER_CODE_LENGTH)); offset += MANUFACTURER_CODE_LENGTH; EXPECT_EQ(*(bp + offset), 'N'); offset += sizeof(char); @@ -484,7 +486,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) TEST_F(CodeGenTest, shouldBeAbleToEncodeHeaderPlusCarCorrectly) { - char buffer[BUFFER_LEN]; + char buffer[BUFFER_LEN] = {}; const char *bp = buffer; std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer)); @@ -503,7 +505,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeHeaderPlusCarCorrectly) TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) { - char buffer[BUFFER_LEN]; + char buffer[BUFFER_LEN] = {}; std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer)); std::uint64_t carEncodedLength = encodeCar( @@ -560,7 +562,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) CGT(optionalExtras) extras; if (!CGT(car_extras)(&m_carDecoder, &extras)) { - throw std::runtime_error(sbe_strerror(errno)); + throw std::runtime_error(sbe_strerror(errno)); } EXPECT_TRUE(CGT(optionalExtras_cruiseControl)(&extras)); @@ -675,16 +677,14 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) struct CallbacksForEach { - int countOfFuelFigures; - int countOfPerformanceFigures; - int countOfAccelerations; - - CallbacksForEach() : countOfFuelFigures(0), countOfPerformanceFigures(0), countOfAccelerations(0) {} + int countOfFuelFigures = 0; + int countOfPerformanceFigures = 0; + int countOfAccelerations = 0; }; TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) { - char buffer[BUFFER_LEN]; + char buffer[BUFFER_LEN] = {}; CGT(messageHeader) hdr; if (!CGT(messageHeader_reset)(&hdr, buffer, 0, sizeof(buffer), 0)) { @@ -733,7 +733,7 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) throw std::runtime_error(sbe_strerror(errno)); } - CallbacksForEach cbs; + CallbacksForEach cbs = {}; CGT(car_fuelFigures) fuelFigures; if (!CGT(car_get_fuelFigures)(&carDecoder, &fuelFigures)) @@ -749,7 +749,7 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) { reinterpret_cast(cbs)->countOfFuelFigures++; - char tmp[256]; + char tmp[256] = {}; CGT(car_fuelFigures_get_usageDescription)(figures, tmp, sizeof(tmp)); }, &cbs)); @@ -773,11 +773,11 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) } reinterpret_cast(cbs)->countOfPerformanceFigures++; ASSERT_TRUE(CGT(car_performanceFigures_acceleration_for_each)( - &acceleration, - [](CGT(car_performanceFigures_acceleration) *const, void *cbs) - { - reinterpret_cast(cbs)->countOfAccelerations++; - }, + &acceleration, + [](CGT(car_performanceFigures_acceleration) *const, void *cbs) + { + reinterpret_cast(cbs)->countOfAccelerations++; + }, cbs )); }, @@ -787,7 +787,7 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) EXPECT_EQ(cbs.countOfPerformanceFigures, PERFORMANCE_FIGURES_COUNT); EXPECT_EQ(cbs.countOfAccelerations, ACCELERATION_COUNT * PERFORMANCE_FIGURES_COUNT); - char tmp[256]; + char tmp[256] = {}; EXPECT_EQ(CGT(car_get_manufacturer)(&carDecoder, tmp, sizeof(tmp)), MANUFACTURER_LENGTH); EXPECT_EQ(std::string(tmp, MANUFACTURER_LENGTH), MANUFACTURER); @@ -825,8 +825,8 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) std::string model(MODEL, MODEL_LENGTH); std::string activationCode(ACTIVATION_CODE, ACTIVATION_CODE_LENGTH); - char buffer[BUFFER_LEN]; - std::uint64_t baseOffset = static_cast(CGT(messageHeader_encoded_length)()); + char buffer[BUFFER_LEN] = {}; + auto baseOffset = static_cast(CGT(messageHeader_encoded_length)()); CGT(car) car; if (!CGT(car_wrap_for_encode)(&car, buffer, baseOffset, sizeof(buffer))) { @@ -880,15 +880,18 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc1Length), static_cast(FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH)); - EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc1Data, FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH), usageDesc1); + EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc1Data, FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH), + usageDesc1); EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc2Length), static_cast(FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH)); - EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc2Data, FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH), usageDesc2); + EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc2Data, FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH), + usageDesc2); EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetUsageDesc3Length), static_cast(FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH)); - EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc3Data, FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH), usageDesc3); + EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc3Data, FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH), + usageDesc3); EXPECT_EQ(*(std::uint16_t *)(buffer + baseOffset + offsetManufacturerLength), static_cast(MANUFACTURER_LENGTH)); @@ -903,11 +906,11 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) EXPECT_EQ(std::string(buffer + baseOffset + offsetActivationCodeData, ACTIVATION_CODE_LENGTH), activationCode); } -void testUsageDescription(CGT(car_fuelFigures) *const fuelFigures, const std::string& expected) +void testUsageDescription(CGT(car_fuelFigures) *const fuelFigures, const std::string &expected) { CGT(car_fuelFigures_next)(fuelFigures); const std::uint16_t length = CGT(car_fuelFigures_usageDescription_length)(fuelFigures); - const char* const ptr = CGT(car_fuelFigures_usageDescription)(fuelFigures); + const char *const ptr = CGT(car_fuelFigures_usageDescription)(fuelFigures); if (!ptr) { throw std::runtime_error(sbe_strerror(errno)); @@ -917,7 +920,7 @@ void testUsageDescription(CGT(car_fuelFigures) *const fuelFigures, const std::st TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) { - char buffer[2048]; + char buffer[2048] = {}; CGT(car) carEncoder; CGT(car_reset)(&carEncoder, buffer, 0, sizeof(buffer), CGT(car_sbe_block_length)(), CGT(car_sbe_schema_version)()); @@ -926,11 +929,12 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) EXPECT_EQ(carEncodedLength, expectedCarEncodedLength); CGT(car) carDecoder; - CGT(car_reset)(&carDecoder, buffer, 0, carEncodedLength, CGT(car_sbe_block_length)(), CGT(car_sbe_schema_version)()); + CGT(car_reset)( + &carDecoder, buffer, 0, carEncodedLength, CGT(car_sbe_block_length)(), CGT(car_sbe_schema_version)()); std::string vehicleCode(VEHICLE_CODE, CGT(car_vehicleCode_length)()); - EXPECT_EQ(std::string(CGT(car_vehicleCode_buffer)(&carDecoder),CGT(car_vehicleCode_length)()), vehicleCode); + EXPECT_EQ(std::string(CGT(car_vehicleCode_buffer)(&carDecoder), CGT(car_vehicleCode_length)()), vehicleCode); CGT(car_fuelFigures) fuelFigures; if (!CGT(car_get_fuelFigures)(&carDecoder, &fuelFigures)) @@ -968,7 +972,7 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) { const uint16_t length = CGT(car_manufacturer_length)(&carDecoder); - const char* const ptr = CGT(car_manufacturer)(&carDecoder); + const char *const ptr = CGT(car_manufacturer)(&carDecoder); if (!ptr) { throw std::runtime_error(sbe_strerror(errno)); @@ -980,7 +984,7 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) } { const uint16_t length = CGT(car_model_length)(&carDecoder); - const char* const ptr = CGT(car_model)(&carDecoder); + const char *const ptr = CGT(car_model)(&carDecoder); if (!ptr) { throw std::runtime_error(sbe_strerror(errno)); @@ -992,7 +996,7 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) } { const uint16_t length = CGT(car_activationCode_length)(&carDecoder); - const char* const ptr = CGT(car_activationCode)(&carDecoder); + const char *const ptr = CGT(car_activationCode)(&carDecoder); if (!ptr) { throw std::runtime_error(sbe_strerror(errno)); diff --git a/sbe-tool/src/test/c/GroupWithDataTest.cpp b/sbe-tool/src/test/c/GroupWithDataTest.cpp index f796fc0d9d..404158839c 100644 --- a/sbe-tool/src/test/c/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/c/GroupWithDataTest.cpp @@ -19,10 +19,10 @@ #include -#include -#include -#include -#include +#include "group_with_data/testMessage1.h" +#include "group_with_data/testMessage2.h" +#include "group_with_data/testMessage3.h" +#include "group_with_data/testMessage4.h" #define GWD(name) group_with_data_##name @@ -171,17 +171,20 @@ class GroupWithDataTest : public testing::Test GWD(testMessage3_entries_nestedEntries_next)(&nestedEntries0); GWD(testMessage3_entries_nestedEntries_set_tagGroup2)(&nestedEntries0, TAG_GROUP_2_IDX_0); - GWD(testMessage3_entries_nestedEntries_put_varDataFieldNested)(&nestedEntries0, VAR_DATA_FIELD_NESTED_IDX_0, VAR_DATA_FIELD_NESTED_IDX_0_LENGTH); + GWD(testMessage3_entries_nestedEntries_put_varDataFieldNested)(&nestedEntries0, VAR_DATA_FIELD_NESTED_IDX_0, + VAR_DATA_FIELD_NESTED_IDX_0_LENGTH); GWD(testMessage3_entries_nestedEntries_next)(&nestedEntries0); GWD(testMessage3_entries_nestedEntries_set_tagGroup2)(&nestedEntries0, TAG_GROUP_2_IDX_1); - GWD(testMessage3_entries_nestedEntries_put_varDataFieldNested)(&nestedEntries0, VAR_DATA_FIELD_NESTED_IDX_1, VAR_DATA_FIELD_NESTED_IDX_1_LENGTH); + GWD(testMessage3_entries_nestedEntries_put_varDataFieldNested)(&nestedEntries0, VAR_DATA_FIELD_NESTED_IDX_1, + VAR_DATA_FIELD_NESTED_IDX_1_LENGTH); GWD(testMessage3_entries_nestedEntries_next)(&nestedEntries0); GWD(testMessage3_entries_nestedEntries_set_tagGroup2)(&nestedEntries0, TAG_GROUP_2_IDX_2); - GWD(testMessage3_entries_nestedEntries_put_varDataFieldNested)(&nestedEntries0, VAR_DATA_FIELD_NESTED_IDX_2, VAR_DATA_FIELD_NESTED_IDX_2_LENGTH); + GWD(testMessage3_entries_nestedEntries_put_varDataFieldNested)(&nestedEntries0, VAR_DATA_FIELD_NESTED_IDX_2, + VAR_DATA_FIELD_NESTED_IDX_2_LENGTH); GWD(testMessage3_entries_put_varDataField)(&entries, VAR_DATA_FIELD_IDX_0, VAR_DATA_FIELD_IDX_0_LENGTH); @@ -196,18 +199,21 @@ class GroupWithDataTest : public testing::Test GWD(testMessage3_entries_nestedEntries_next)(&nestedEntries1); GWD(testMessage3_entries_nestedEntries_set_tagGroup2)(&nestedEntries1, TAG_GROUP_2_IDX_3); - GWD(testMessage3_entries_nestedEntries_put_varDataFieldNested)(&nestedEntries1, VAR_DATA_FIELD_NESTED_IDX_3, VAR_DATA_FIELD_NESTED_IDX_3_LENGTH); + GWD(testMessage3_entries_nestedEntries_put_varDataFieldNested)(&nestedEntries1, VAR_DATA_FIELD_NESTED_IDX_3, + VAR_DATA_FIELD_NESTED_IDX_3_LENGTH); GWD(testMessage3_entries_nestedEntries_next)(&nestedEntries1); GWD(testMessage3_entries_nestedEntries_set_tagGroup2)(&nestedEntries1, TAG_GROUP_2_IDX_4); - GWD(testMessage3_entries_nestedEntries_put_varDataFieldNested)(&nestedEntries1, VAR_DATA_FIELD_NESTED_IDX_4, VAR_DATA_FIELD_NESTED_IDX_4_LENGTH); + GWD(testMessage3_entries_nestedEntries_put_varDataFieldNested)(&nestedEntries1, VAR_DATA_FIELD_NESTED_IDX_4, + VAR_DATA_FIELD_NESTED_IDX_4_LENGTH); GWD(testMessage3_entries_nestedEntries_next)(&nestedEntries1); GWD(testMessage3_entries_nestedEntries_set_tagGroup2)(&nestedEntries1, TAG_GROUP_2_IDX_5); - GWD(testMessage3_entries_nestedEntries_put_varDataFieldNested)(&nestedEntries1, VAR_DATA_FIELD_NESTED_IDX_5, VAR_DATA_FIELD_NESTED_IDX_5_LENGTH); + GWD(testMessage3_entries_nestedEntries_put_varDataFieldNested)(&nestedEntries1, VAR_DATA_FIELD_NESTED_IDX_5, + VAR_DATA_FIELD_NESTED_IDX_5_LENGTH); GWD(testMessage3_entries_put_varDataField)(&entries, VAR_DATA_FIELD_IDX_1, VAR_DATA_FIELD_IDX_1_LENGTH); @@ -242,15 +248,15 @@ class GroupWithDataTest : public testing::Test return GWD(testMessage4_encoded_length)(&m_msg4); } - GWD(testMessage1) m_msg1; - GWD(testMessage2) m_msg2; - GWD(testMessage3) m_msg3; - GWD(testMessage4) m_msg4; + GWD(testMessage1) m_msg1 = {}; + GWD(testMessage2) m_msg2 = {}; + GWD(testMessage3) m_msg3 = {}; + GWD(testMessage4) m_msg4 = {}; }; TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage1Correctly) { - char buffer[2048]; + char buffer[2048] = {}; const char *bp = buffer; std::uint64_t sz = encodeTestMessage1(buffer, 0, sizeof(buffer)); @@ -265,7 +271,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage1Correctly) EXPECT_EQ(*(std::uint8_t *)(bp + offset), ENTRIES_COUNT); offset += sizeof(std::uint8_t); - EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_0_LENGTH), std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); + EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_0_LENGTH), + std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); offset += TAG_GROUP_1_IDX_0_LENGTH; EXPECT_EQ(*(std::int64_t *)(bp + offset), TAG_GROUP_2_IDX_0); offset += sizeof(std::int64_t); @@ -274,7 +281,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage1Correctly) EXPECT_EQ(std::string(bp + offset, VAR_DATA_FIELD_IDX_0_LENGTH), VAR_DATA_FIELD_IDX_0); offset += VAR_DATA_FIELD_IDX_0_LENGTH; - EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_1_LENGTH), std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); + EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_1_LENGTH), + std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); offset += TAG_GROUP_1_IDX_1_LENGTH; EXPECT_EQ(*(std::int64_t *)(bp + offset), TAG_GROUP_2_IDX_1); offset += sizeof(std::int64_t); @@ -288,13 +296,19 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage1Correctly) TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage1Correctly) { - char buffer[2048]; + char buffer[2048] = {}; std::uint64_t sz = encodeTestMessage1(buffer, 0, sizeof(buffer)); EXPECT_EQ(sz, expectedTestMessage1Size); GWD(testMessage1) msg1Decoder; - if (!GWD(testMessage1_reset)(&msg1Decoder, buffer, 0, sizeof(buffer), GWD(testMessage1_sbe_block_length)(), GWD(testMessage1_sbe_schema_version)())) + if (!GWD(testMessage1_reset)( + &msg1Decoder, + buffer, + 0, + sizeof(buffer), + GWD(testMessage1_sbe_block_length)(), + GWD(testMessage1_sbe_schema_version)())) { throw std::runtime_error(sbe_strerror(errno)); } @@ -312,26 +326,32 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage1Correctly) GWD(testMessage1_entries_next)(&entries); EXPECT_EQ(GWD(testMessage1_entries_tagGroup1_length)(), TAG_GROUP_1_IDX_0_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage1_entries_tagGroup1_buffer)(&entries), GWD(testMessage1_entries_tagGroup1_length)()), std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); + EXPECT_EQ( + std::string(GWD(testMessage1_entries_tagGroup1_buffer)(&entries), GWD(testMessage1_entries_tagGroup1_length)()), + std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); EXPECT_EQ(GWD(testMessage1_entries_tagGroup2)(&entries), TAG_GROUP_2_IDX_0); EXPECT_EQ(GWD(testMessage1_entries_varDataField_length)(&entries), VAR_DATA_FIELD_IDX_0_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage1_entries_varDataField)(&entries), VAR_DATA_FIELD_IDX_0_LENGTH), VAR_DATA_FIELD_IDX_0); + EXPECT_EQ(std::string(GWD(testMessage1_entries_varDataField)(&entries), VAR_DATA_FIELD_IDX_0_LENGTH), + VAR_DATA_FIELD_IDX_0); ASSERT_TRUE(GWD(testMessage1_entries_has_next)(&entries)); GWD(testMessage1_entries_next)(&entries); EXPECT_EQ(GWD(testMessage1_entries_tagGroup1_length)(), TAG_GROUP_1_IDX_1_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage1_entries_tagGroup1_buffer)(&entries), GWD(testMessage1_entries_tagGroup1_length)()), std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); + EXPECT_EQ( + std::string(GWD(testMessage1_entries_tagGroup1_buffer)(&entries), GWD(testMessage1_entries_tagGroup1_length)()), + std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); EXPECT_EQ(GWD(testMessage1_entries_tagGroup2)(&entries), TAG_GROUP_2_IDX_1); EXPECT_EQ(GWD(testMessage1_entries_varDataField_length)(&entries), VAR_DATA_FIELD_IDX_1_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage1_entries_varDataField)(&entries), VAR_DATA_FIELD_IDX_1_LENGTH), VAR_DATA_FIELD_IDX_1); + EXPECT_EQ(std::string(GWD(testMessage1_entries_varDataField)(&entries), VAR_DATA_FIELD_IDX_1_LENGTH), + VAR_DATA_FIELD_IDX_1); EXPECT_EQ(GWD(testMessage1_encoded_length)(&msg1Decoder), expectedTestMessage1Size); } TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage2Correctly) { - char buffer[2048]; + char buffer[2048] = {}; const char *bp = buffer; std::uint64_t sz = encodeTestMessage2(buffer, 0, sizeof(buffer)); @@ -346,7 +366,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage2Correctly) EXPECT_EQ(*(std::uint8_t *)(bp + offset), ENTRIES_COUNT); offset += sizeof(std::uint8_t); - EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_0_LENGTH), std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); + EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_0_LENGTH), + std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); offset += TAG_GROUP_1_IDX_0_LENGTH; EXPECT_EQ(*(std::int64_t *)(bp + offset), TAG_GROUP_2_IDX_0); offset += sizeof(std::int64_t); @@ -359,7 +380,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage2Correctly) EXPECT_EQ(std::string(bp + offset, VAR_DATA_FIELD_2_IDX_0_LENGTH), VAR_DATA_FIELD_2_IDX_0); offset += VAR_DATA_FIELD_2_IDX_0_LENGTH; - EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_1_LENGTH), std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); + EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_1_LENGTH), + std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); offset += TAG_GROUP_1_IDX_1_LENGTH; EXPECT_EQ(*(std::int64_t *)(bp + offset), TAG_GROUP_2_IDX_1); offset += sizeof(std::int64_t); @@ -377,13 +399,14 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage2Correctly) TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage2Correctly) { - char buffer[2048]; + char buffer[2048] = {}; std::uint64_t sz = encodeTestMessage2(buffer, 0, sizeof(buffer)); EXPECT_EQ(sz, expectedTestMessage2Size); GWD(testMessage2) msg2Decoder; - if (!GWD(testMessage2_reset)(&msg2Decoder, buffer, 0, sizeof(buffer), GWD(testMessage2_sbe_block_length)(), GWD(testMessage2_sbe_schema_version)())) + if (!GWD(testMessage2_reset)(&msg2Decoder, buffer, 0, sizeof(buffer), GWD(testMessage2_sbe_block_length)(), + GWD(testMessage2_sbe_schema_version)())) { throw std::runtime_error(sbe_strerror(errno)); } @@ -401,32 +424,39 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage2Correctly) GWD(testMessage2_entries_next)(&entries); EXPECT_EQ(GWD(testMessage2_entries_tagGroup1_length)(), TAG_GROUP_1_IDX_0_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage2_entries_tagGroup1_buffer)(&entries), GWD(testMessage2_entries_tagGroup1_length)()), std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); + EXPECT_EQ( + std::string(GWD(testMessage2_entries_tagGroup1_buffer)(&entries), GWD(testMessage2_entries_tagGroup1_length)()), + std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); EXPECT_EQ(GWD(testMessage2_entries_tagGroup2)(&entries), TAG_GROUP_2_IDX_0); EXPECT_EQ(GWD(testMessage2_entries_varDataField1_length)(&entries), VAR_DATA_FIELD_1_IDX_0_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage2_entries_varDataField1)(&entries), VAR_DATA_FIELD_1_IDX_0_LENGTH), VAR_DATA_FIELD_1_IDX_0); + EXPECT_EQ(std::string(GWD(testMessage2_entries_varDataField1)(&entries), VAR_DATA_FIELD_1_IDX_0_LENGTH), + VAR_DATA_FIELD_1_IDX_0); EXPECT_EQ(GWD(testMessage2_entries_varDataField2_length)(&entries), VAR_DATA_FIELD_2_IDX_0_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage2_entries_varDataField2)(&entries), VAR_DATA_FIELD_2_IDX_0_LENGTH), VAR_DATA_FIELD_2_IDX_0); + EXPECT_EQ(std::string(GWD(testMessage2_entries_varDataField2)(&entries), VAR_DATA_FIELD_2_IDX_0_LENGTH), + VAR_DATA_FIELD_2_IDX_0); ASSERT_TRUE(GWD(testMessage2_entries_has_next)(&entries)); GWD(testMessage2_entries_next)(&entries); EXPECT_EQ(GWD(testMessage2_entries_tagGroup1_length)(), TAG_GROUP_1_IDX_1_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage2_entries_tagGroup1_buffer)(&entries), GWD(testMessage2_entries_tagGroup1_length)()), std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); - + EXPECT_EQ( + std::string(GWD(testMessage2_entries_tagGroup1_buffer)(&entries), GWD(testMessage2_entries_tagGroup1_length)()), + std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); EXPECT_EQ(GWD(testMessage2_entries_tagGroup2)(&entries), TAG_GROUP_2_IDX_1); EXPECT_EQ(GWD(testMessage2_entries_varDataField1_length)(&entries), VAR_DATA_FIELD_1_IDX_1_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage2_entries_varDataField1)(&entries), VAR_DATA_FIELD_1_IDX_1_LENGTH), VAR_DATA_FIELD_1_IDX_1); + EXPECT_EQ(std::string(GWD(testMessage2_entries_varDataField1)(&entries), VAR_DATA_FIELD_1_IDX_1_LENGTH), + VAR_DATA_FIELD_1_IDX_1); EXPECT_EQ(GWD(testMessage2_entries_varDataField2_length)(&entries), VAR_DATA_FIELD_2_IDX_1_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage2_entries_varDataField2)(&entries), VAR_DATA_FIELD_2_IDX_1_LENGTH), VAR_DATA_FIELD_2_IDX_1); + EXPECT_EQ(std::string(GWD(testMessage2_entries_varDataField2)(&entries), VAR_DATA_FIELD_2_IDX_1_LENGTH), + VAR_DATA_FIELD_2_IDX_1); EXPECT_EQ(GWD(testMessage2_encoded_length)(&msg2Decoder), expectedTestMessage2Size); } TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage3Correctly) { - char buffer[2048]; + char buffer[2048] = {}; const char *bp = buffer; std::uint64_t sz = encodeTestMessage3(buffer, 0, sizeof(buffer)); @@ -441,7 +471,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage3Correctly) EXPECT_EQ(*(std::uint8_t *)(bp + offset), ENTRIES_COUNT); offset += sizeof(std::uint8_t); - EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_0_LENGTH), std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); + EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_0_LENGTH), + std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); offset += TAG_GROUP_1_IDX_0_LENGTH; // nested entries @@ -476,7 +507,8 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage3Correctly) EXPECT_EQ(std::string(bp + offset, VAR_DATA_FIELD_IDX_0_LENGTH), VAR_DATA_FIELD_IDX_0); offset += VAR_DATA_FIELD_IDX_0_LENGTH; - EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_1_LENGTH), std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); + EXPECT_EQ(std::string(bp + offset, TAG_GROUP_1_IDX_1_LENGTH), + std::string(TAG_GROUP_1_IDX_1, TAG_GROUP_1_IDX_1_LENGTH)); offset += TAG_GROUP_1_IDX_1_LENGTH; // nested entries @@ -516,13 +548,14 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage3Correctly) TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage3Correctly) { - char buffer[2048]; + char buffer[2048] = {}; std::uint64_t sz = encodeTestMessage3(buffer, 0, sizeof(buffer)); EXPECT_EQ(sz, expectedTestMessage3Size); GWD(testMessage3) msg3Decoder; - if (!GWD(testMessage3_reset)(&msg3Decoder, buffer, 0, sizeof(buffer), GWD(testMessage3_sbe_block_length)(), GWD(testMessage3_sbe_schema_version)())) + if (!GWD(testMessage3_reset)(&msg3Decoder, buffer, 0, sizeof(buffer), GWD(testMessage3_sbe_block_length)(), + GWD(testMessage3_sbe_schema_version)())) { throw std::runtime_error(sbe_strerror(errno)); } @@ -540,7 +573,9 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage3Correctly) GWD(testMessage3_entries_next)(&entries); EXPECT_EQ(GWD(testMessage3_entries_tagGroup1_length)(), TAG_GROUP_1_IDX_0_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage3_entries_tagGroup1_buffer)(&entries), GWD(testMessage3_entries_tagGroup1_length)()), std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); + EXPECT_EQ( + std::string(GWD(testMessage3_entries_tagGroup1_buffer)(&entries), GWD(testMessage3_entries_tagGroup1_length)()), + std::string(TAG_GROUP_1_IDX_0, TAG_GROUP_1_IDX_0_LENGTH)); GWD(testMessage3_entries_nestedEntries) nestedEntries0; if (!GWD(testMessage3_entries_get_nestedEntries)(&entries, &nestedEntries0)) @@ -553,25 +588,32 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage3Correctly) GWD(testMessage3_entries_nestedEntries_next)(&nestedEntries0); EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_tagGroup2)(&nestedEntries0), TAG_GROUP_2_IDX_0); - EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_varDataFieldNested_length)(&nestedEntries0), VAR_DATA_FIELD_NESTED_IDX_0_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage3_entries_nestedEntries_varDataFieldNested)(&nestedEntries0), VAR_DATA_FIELD_NESTED_IDX_0_LENGTH), VAR_DATA_FIELD_NESTED_IDX_0); + EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_varDataFieldNested_length)(&nestedEntries0), + VAR_DATA_FIELD_NESTED_IDX_0_LENGTH); + EXPECT_EQ(std::string(GWD(testMessage3_entries_nestedEntries_varDataFieldNested)(&nestedEntries0), + VAR_DATA_FIELD_NESTED_IDX_0_LENGTH), VAR_DATA_FIELD_NESTED_IDX_0); ASSERT_TRUE(GWD(testMessage3_entries_nestedEntries_has_next)(&nestedEntries0)); GWD(testMessage3_entries_nestedEntries_next)(&nestedEntries0); EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_tagGroup2)(&nestedEntries0), TAG_GROUP_2_IDX_1); - EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_varDataFieldNested_length)(&nestedEntries0), VAR_DATA_FIELD_NESTED_IDX_1_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage3_entries_nestedEntries_varDataFieldNested)(&nestedEntries0), VAR_DATA_FIELD_NESTED_IDX_1_LENGTH), VAR_DATA_FIELD_NESTED_IDX_1); + EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_varDataFieldNested_length)(&nestedEntries0), + VAR_DATA_FIELD_NESTED_IDX_1_LENGTH); + EXPECT_EQ(std::string(GWD(testMessage3_entries_nestedEntries_varDataFieldNested)(&nestedEntries0), + VAR_DATA_FIELD_NESTED_IDX_1_LENGTH), VAR_DATA_FIELD_NESTED_IDX_1); ASSERT_TRUE(GWD(testMessage3_entries_nestedEntries_has_next)(&nestedEntries0)); GWD(testMessage3_entries_nestedEntries_next)(&nestedEntries0); EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_tagGroup2)(&nestedEntries0), TAG_GROUP_2_IDX_2); - EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_varDataFieldNested_length)(&nestedEntries0), VAR_DATA_FIELD_NESTED_IDX_2_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage3_entries_nestedEntries_varDataFieldNested)(&nestedEntries0), VAR_DATA_FIELD_NESTED_IDX_2_LENGTH), VAR_DATA_FIELD_NESTED_IDX_2); + EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_varDataFieldNested_length)(&nestedEntries0), + VAR_DATA_FIELD_NESTED_IDX_2_LENGTH); + EXPECT_EQ(std::string(GWD(testMessage3_entries_nestedEntries_varDataFieldNested)(&nestedEntries0), + VAR_DATA_FIELD_NESTED_IDX_2_LENGTH), VAR_DATA_FIELD_NESTED_IDX_2); EXPECT_EQ(GWD(testMessage3_entries_varDataField_length)(&entries), VAR_DATA_FIELD_IDX_0_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage3_entries_varDataField)(&entries), VAR_DATA_FIELD_IDX_0_LENGTH), VAR_DATA_FIELD_IDX_0); + EXPECT_EQ(std::string(GWD(testMessage3_entries_varDataField)(&entries), VAR_DATA_FIELD_IDX_0_LENGTH), + VAR_DATA_FIELD_IDX_0); ASSERT_TRUE(GWD(testMessage3_entries_has_next)(&entries)); GWD(testMessage3_entries_next)(&entries); @@ -587,32 +629,39 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage3Correctly) GWD(testMessage3_entries_nestedEntries_next)(&nestedEntries1); EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_tagGroup2)(&nestedEntries1), TAG_GROUP_2_IDX_3); - EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_varDataFieldNested_length)(&nestedEntries1), VAR_DATA_FIELD_NESTED_IDX_3_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage3_entries_nestedEntries_varDataFieldNested)(&nestedEntries1), VAR_DATA_FIELD_NESTED_IDX_3_LENGTH), VAR_DATA_FIELD_NESTED_IDX_3); + EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_varDataFieldNested_length)(&nestedEntries1), + VAR_DATA_FIELD_NESTED_IDX_3_LENGTH); + EXPECT_EQ(std::string(GWD(testMessage3_entries_nestedEntries_varDataFieldNested)(&nestedEntries1), + VAR_DATA_FIELD_NESTED_IDX_3_LENGTH), VAR_DATA_FIELD_NESTED_IDX_3); ASSERT_TRUE(GWD(testMessage3_entries_nestedEntries_has_next)(&nestedEntries1)); GWD(testMessage3_entries_nestedEntries_next)(&nestedEntries1); EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_tagGroup2)(&nestedEntries1), TAG_GROUP_2_IDX_4); - EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_varDataFieldNested_length)(&nestedEntries1), VAR_DATA_FIELD_NESTED_IDX_4_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage3_entries_nestedEntries_varDataFieldNested)(&nestedEntries1), VAR_DATA_FIELD_NESTED_IDX_4_LENGTH), VAR_DATA_FIELD_NESTED_IDX_4); + EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_varDataFieldNested_length)(&nestedEntries1), + VAR_DATA_FIELD_NESTED_IDX_4_LENGTH); + EXPECT_EQ(std::string(GWD(testMessage3_entries_nestedEntries_varDataFieldNested)(&nestedEntries1), + VAR_DATA_FIELD_NESTED_IDX_4_LENGTH), VAR_DATA_FIELD_NESTED_IDX_4); ASSERT_TRUE(GWD(testMessage3_entries_nestedEntries_has_next)(&nestedEntries1)); GWD(testMessage3_entries_nestedEntries_next)(&nestedEntries1); EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_tagGroup2)(&nestedEntries1), TAG_GROUP_2_IDX_5); - EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_varDataFieldNested_length)(&nestedEntries1), VAR_DATA_FIELD_NESTED_IDX_5_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage3_entries_nestedEntries_varDataFieldNested)(&nestedEntries1), VAR_DATA_FIELD_NESTED_IDX_5_LENGTH), VAR_DATA_FIELD_NESTED_IDX_5); + EXPECT_EQ(GWD(testMessage3_entries_nestedEntries_varDataFieldNested_length)(&nestedEntries1), + VAR_DATA_FIELD_NESTED_IDX_5_LENGTH); + EXPECT_EQ(std::string(GWD(testMessage3_entries_nestedEntries_varDataFieldNested)(&nestedEntries1), + VAR_DATA_FIELD_NESTED_IDX_5_LENGTH), VAR_DATA_FIELD_NESTED_IDX_5); EXPECT_EQ(GWD(testMessage3_entries_varDataField_length)(&entries), VAR_DATA_FIELD_IDX_1_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage3_entries_varDataField)(&entries), VAR_DATA_FIELD_IDX_1_LENGTH), VAR_DATA_FIELD_IDX_1); + EXPECT_EQ(std::string(GWD(testMessage3_entries_varDataField)(&entries), VAR_DATA_FIELD_IDX_1_LENGTH), + VAR_DATA_FIELD_IDX_1); EXPECT_EQ(GWD(testMessage3_encoded_length)(&msg3Decoder), expectedTestMessage3Size); } TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage4Correctly) { - char buffer[2048]; + char buffer[2048] = {}; const char *bp = buffer; std::uint64_t sz = encodeTestMessage4(buffer, 0, sizeof(buffer)); @@ -650,13 +699,14 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeTestMessage4Correctly) TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage4Correctly) { - char buffer[2048]; + char buffer[2048] = {}; std::uint64_t sz = encodeTestMessage4(buffer, 0, sizeof(buffer)); EXPECT_EQ(sz, expectedTestMessage4Size); GWD(testMessage4) msg4Decoder; - if (!GWD(testMessage4_reset)(&msg4Decoder, buffer, 0, sizeof(buffer), GWD(testMessage4_sbe_block_length)(), GWD(testMessage4_sbe_schema_version)())) + if (!GWD(testMessage4_reset)(&msg4Decoder, buffer, 0, sizeof(buffer), GWD(testMessage4_sbe_block_length)(), + GWD(testMessage4_sbe_schema_version)())) { throw std::runtime_error(sbe_strerror(errno)); } @@ -674,17 +724,21 @@ TEST_F(GroupWithDataTest, shouldBeAbleToEncodeAndDecodeTestMessage4Correctly) GWD(testMessage4_entries_next)(&entries); EXPECT_EQ(GWD(testMessage4_entries_varDataField1_length)(&entries), VAR_DATA_FIELD_1_IDX_0_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage4_entries_varDataField1)(&entries), VAR_DATA_FIELD_1_IDX_0_LENGTH), VAR_DATA_FIELD_1_IDX_0); + EXPECT_EQ(std::string(GWD(testMessage4_entries_varDataField1)(&entries), VAR_DATA_FIELD_1_IDX_0_LENGTH), + VAR_DATA_FIELD_1_IDX_0); EXPECT_EQ(GWD(testMessage4_entries_varDataField2_length)(&entries), VAR_DATA_FIELD_2_IDX_0_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage4_entries_varDataField2)(&entries), VAR_DATA_FIELD_2_IDX_0_LENGTH), VAR_DATA_FIELD_2_IDX_0); + EXPECT_EQ(std::string(GWD(testMessage4_entries_varDataField2)(&entries), VAR_DATA_FIELD_2_IDX_0_LENGTH), + VAR_DATA_FIELD_2_IDX_0); ASSERT_TRUE(GWD(testMessage4_entries_has_next)(&entries)); GWD(testMessage4_entries_next)(&entries); EXPECT_EQ(GWD(testMessage4_entries_varDataField1_length)(&entries), VAR_DATA_FIELD_1_IDX_1_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage4_entries_varDataField1)(&entries), VAR_DATA_FIELD_1_IDX_1_LENGTH), VAR_DATA_FIELD_1_IDX_1); + EXPECT_EQ(std::string(GWD(testMessage4_entries_varDataField1)(&entries), VAR_DATA_FIELD_1_IDX_1_LENGTH), + VAR_DATA_FIELD_1_IDX_1); EXPECT_EQ(GWD(testMessage4_entries_varDataField2_length)(&entries), VAR_DATA_FIELD_2_IDX_1_LENGTH); - EXPECT_EQ(std::string(GWD(testMessage4_entries_varDataField2)(&entries), VAR_DATA_FIELD_2_IDX_1_LENGTH), VAR_DATA_FIELD_2_IDX_1); + EXPECT_EQ(std::string(GWD(testMessage4_entries_varDataField2)(&entries), VAR_DATA_FIELD_2_IDX_1_LENGTH), + VAR_DATA_FIELD_2_IDX_1); EXPECT_EQ(GWD(testMessage4_encoded_length)(&msg4Decoder), expectedTestMessage4Size); } From 9212aeaaa72d0b8f2c7972ad8e221b1c5d9bb47e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 22 Jan 2021 18:07:10 +0000 Subject: [PATCH 0636/1594] Update CME FixBinary schema to version 9. --- sbe-tool/src/test/resources/FixBinary.xml | 391 ++++++++++++++++++++-- 1 file changed, 362 insertions(+), 29 deletions(-) diff --git a/sbe-tool/src/test/resources/FixBinary.xml b/sbe-tool/src/test/resources/FixBinary.xml index da7bb94f95..54808a52e1 100644 --- a/sbe-tool/src/test/resources/FixBinary.xml +++ b/sbe-tool/src/test/resources/FixBinary.xml @@ -2,9 +2,9 @@ @@ -16,7 +16,7 @@ - + J g @@ -37,11 +37,19 @@ - + - + + + + -9 + + + + -9 + -4 @@ -60,10 +68,18 @@ -7 + + + -9 + -7 + + + -9 + @@ -155,14 +171,14 @@ 0 5 - - 0 - 1 - 2 + + 0 + 1 + 2 - - 0 - 1 + + 0 + 1 0 @@ -210,6 +226,8 @@ 17 18 19 + 20 + 21 0 @@ -222,7 +240,7 @@ 7 - 0 + 0 1 2 3 @@ -446,21 +464,6 @@
    - - - - - - - - - - - - - - - @@ -607,7 +610,7 @@ - + @@ -625,4 +628,334 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From c16335150318311ca16aebda48319e4657cc232f Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 Jan 2021 12:28:37 +0100 Subject: [PATCH 0637/1594] [CI] Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION together. --- .github/workflows/ci.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6a637df35..27ce6661a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,17 +39,16 @@ jobs: uses: actions/setup-java@v1 with: java-version: ${{ matrix.java }} - - name: Setup BUILD_JAVA_HOME - if: runner.os == 'Linux' - run: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - name: Setup java 8 to run the Gradle script uses: actions/setup-java@v1 with: java-version: 8 - name: Build with Gradle run: ./gradlew - env: - BUILD_JAVA_VERSION: ${{ matrix.java }} csharp-build: name: C# ${{ matrix.dotnet }} From 257e757f63c9f70b6a07a5e51e312f85dea5f71a Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 Jan 2021 13:51:01 +0100 Subject: [PATCH 0638/1594] [Java] Set javaLauncher directly for all JavaExec tasks + use javaToolchain for running benchmarks. --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index f438dcf3ce..077133ef3f 100644 --- a/build.gradle +++ b/build.gradle @@ -41,7 +41,7 @@ static def getBuildJavaVersion() { } int buildJavaVersion = getBuildJavaVersion() -def javaLauncher = javaToolchains.launcherFor { +def toolChainLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } @@ -149,7 +149,7 @@ allprojects { } tasks.withType(JavaExec).configureEach { - executable = javaLauncher.get().executablePath + javaLauncher = toolChainLauncher } } @@ -717,7 +717,7 @@ task generateIrCodecs { } task runJavaBenchmarks(type: Exec) { - commandLine 'java', + commandLine toolChainLauncher.get().executablePath, '-jar', 'sbe-benchmarks/build/libs/sbe-benchmarks.jar', '-jvmArgs', '-Dagrona.disable.bounds.checks=true -XX:+UseParallelOldGC', '-w', '1s', '-r', '1s','-wi', '3', '-i', '5', '-tu', 'ns', '-f', '5' From 93e9fcc7ce6d655a6501ee257f8254a3c1312b01 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 Jan 2021 14:02:30 +0100 Subject: [PATCH 0639/1594] [CI] Try a workaround for missing libidn11 library. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 27ce6661a3..eb9d5aa1a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,7 +121,7 @@ jobs: - name: Install compiler run: | sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic main universe" - sudo apt-get install -y g++-${{ matrix.version }} libsparsehash-dev + sudo apt-get install -y g++-${{ matrix.version }} libsparsehash-dev libidn11 curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH From 6c53121b54449ebaa8196c88d5d0abbfbf26d8ab Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 Jan 2021 14:04:59 +0100 Subject: [PATCH 0640/1594] [CI] Install libidn11 on Ubuntu. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb9d5aa1a5..a9c9513d04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -158,7 +158,7 @@ jobs: curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-${{ matrix.version }} main" sudo apt-get update - sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev + sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev libidn11 curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH From 58cc7ba868688c94168a3762f7d9dd5616a569fe Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 Jan 2021 14:21:21 +0100 Subject: [PATCH 0641/1594] [Java] Rename launcher field. --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 077133ef3f..ed2e400419 100644 --- a/build.gradle +++ b/build.gradle @@ -41,7 +41,7 @@ static def getBuildJavaVersion() { } int buildJavaVersion = getBuildJavaVersion() -def toolChainLauncher = javaToolchains.launcherFor { +def toolchainLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } @@ -149,7 +149,7 @@ allprojects { } tasks.withType(JavaExec).configureEach { - javaLauncher = toolChainLauncher + javaLauncher = toolchainLauncher } } @@ -717,7 +717,7 @@ task generateIrCodecs { } task runJavaBenchmarks(type: Exec) { - commandLine toolChainLauncher.get().executablePath, + commandLine toolchainLauncher.get().executablePath, '-jar', 'sbe-benchmarks/build/libs/sbe-benchmarks.jar', '-jvmArgs', '-Dagrona.disable.bounds.checks=true -XX:+UseParallelOldGC', '-w', '1s', '-r', '1s','-wi', '3', '-i', '5', '-tu', 'ns', '-f', '5' From 079f874d861fb3f2d56471b3f28bcfc77f1da982 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 Jan 2021 14:29:17 +0100 Subject: [PATCH 0642/1594] [Java] Add missing dependency for runJavaBenchmarks task. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ed2e400419..464ae70089 100644 --- a/build.gradle +++ b/build.gradle @@ -716,7 +716,7 @@ task generateIrCodecs { dependsOn 'generateJavaIrCodecs', 'generateCppIrCodecs', 'generateGolangIrCodecs' } -task runJavaBenchmarks(type: Exec) { +task runJavaBenchmarks(type: Exec, dependsOn: 'sbe-benchmarks:jar') { commandLine toolchainLauncher.get().executablePath, '-jar', 'sbe-benchmarks/build/libs/sbe-benchmarks.jar', '-jvmArgs', '-Dagrona.disable.bounds.checks=true -XX:+UseParallelOldGC', From f036bc7ec7d135718f612b67651553ceb7c2b9d8 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 27 Jan 2021 14:36:50 +0100 Subject: [PATCH 0643/1594] [Java] Remove unnecessary compiler flags on JDK 9+. --- build.gradle | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 464ae70089..2c91f82665 100644 --- a/build.gradle +++ b/build.gradle @@ -183,9 +183,7 @@ subprojects { } tasks.withType(JavaCompile) { - if (buildJavaVersion >= 9) { - options.compilerArgs.addAll(['--add-exports', 'java.base/java.lang.reflect=ALL-UNNAMED']) - options.compilerArgs.addAll(['--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED']) + if (buildJavaVersion >= 16) { // -- Workaround for https://github.com/gradle/gradle/issues/15538 options.forkOptions.jvmArgs.addAll( ['--add-opens', 'jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED'] ) // -- @@ -217,11 +215,6 @@ subprojects { } test { - if (buildJavaVersion >= 9) { - jvmArgs('--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED') - jvmArgs('--add-exports', 'jdk.unsupported/sun.misc=ALL-UNNAMED') - } - useJUnitPlatform() testLogging { From 9dda80a4bff84af57598e5f91380adeb6cd12981 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 27 Jan 2021 14:59:59 +0000 Subject: [PATCH 0644/1594] Upgrade to Gradle 6.8.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 2c91f82665..ffd00835ce 100644 --- a/build.gradle +++ b/build.gradle @@ -723,6 +723,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.7.1' + gradleVersion = '6.8.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1f3fdbc528..1c4bcc29e1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From b7fb09f02d079fd11444d86e5ba983b8d32662f8 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 29 Jan 2021 00:09:53 +0100 Subject: [PATCH 0645/1594] [Java] Use `-XX:+UseParallelGC` instead of `-XX:+UseParallelOldGC` in launcher scripts. The latter was deprecated in JDK 14 and removed in JDK 16. See http://openjdk.java.net/jeps/366. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ffd00835ce..6319b51af7 100644 --- a/build.gradle +++ b/build.gradle @@ -712,7 +712,7 @@ task generateIrCodecs { task runJavaBenchmarks(type: Exec, dependsOn: 'sbe-benchmarks:jar') { commandLine toolchainLauncher.get().executablePath, '-jar', 'sbe-benchmarks/build/libs/sbe-benchmarks.jar', - '-jvmArgs', '-Dagrona.disable.bounds.checks=true -XX:+UseParallelOldGC', + '-jvmArgs', '-Dagrona.disable.bounds.checks=true -XX:+UseParallelGC', '-w', '1s', '-r', '1s','-wi', '3', '-i', '5', '-tu', 'ns', '-f', '5' } From 4b505cc404174568a71c10891e4070e0758d355b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 5 Feb 2021 13:58:15 +0000 Subject: [PATCH 0646/1594] [Java] Upgrade to JUnit 5.7.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6319b51af7..5248743b17 100644 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' def mockitoVersion = '3.7.7' -def junitVersion = '5.7.0' +def junitVersion = '5.7.1' def jmhVersion = '1.27' def agronaVersion = '1.9.0' def agronaVersionRange = '[1.9,1.10[' // allow any patch release of 1.9.x From fadf63dde52c92cfdaebbab594e6c8914ac2f703 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 5 Feb 2021 15:28:53 +0000 Subject: [PATCH 0647/1594] [Java] Upgrade to Gradle 6.8.2. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 5248743b17..f82dd3bca6 100644 --- a/build.gradle +++ b/build.gradle @@ -723,6 +723,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.8.1' + gradleVersion = '6.8.2' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1c4bcc29e1..25d3265315 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 94e64e4fe68c30927747df5f7f8a65a16260d464 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 8 Feb 2021 16:41:05 +0000 Subject: [PATCH 0648/1594] [C++] Add test case for Issue #835 which demonstrates that no issue exists. --- sbe-tool/src/test/cpp/CMakeLists.txt | 3 + sbe-tool/src/test/cpp/GroupWithDataTest.cpp | 1 - sbe-tool/src/test/cpp/Issue835Test.cpp | 72 ++++++ sbe-tool/src/test/resources/issue835.xml | 267 ++++++++++++++++++++ 4 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 sbe-tool/src/test/cpp/Issue835Test.cpp create mode 100644 sbe-tool/src/test/resources/issue835.xml diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index 5345e93eb4..9d4bcd4b3a 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -38,6 +38,7 @@ set(COMPOSITE_OFFSETS_SCHEMA ${CODEC_SCHEMA_DIR}/composite-offsets-schema.xml) set(MESSAGE_BLOCK_LENGTH_TEST ${CODEC_SCHEMA_DIR}/message-block-length-test.xml) set(GROUP_WITH_DATA_SCHEMA ${CODEC_SCHEMA_DIR}/group-with-data-schema.xml) set(COMPOSITE_ELEMENTS_SCHEMA ${CODEC_SCHEMA_DIR}/composite-elements-schema.xml) +set(ISSUE835_SCHEMA ${CODEC_SCHEMA_DIR}/issue835.xml) set(GENERATED_CODECS ${CXX_CODEC_TARGET_DIR} @@ -58,6 +59,7 @@ add_custom_command( ${MESSAGE_BLOCK_LENGTH_TEST} ${GROUP_WITH_DATA_SCHEMA} ${COMPOSITE_ELEMENTS_SCHEMA} + ${ISSUE835_SCHEMA} ) add_custom_target(codecs DEPENDS ${GENERATED_CODECS}) @@ -71,3 +73,4 @@ sbe_test(MessageBlockLengthTest codecs) sbe_test(GroupWithDataTest codecs) sbe_test(Rc3OtfFullIrTest codecs) sbe_test(CompositeElementsTest codecs) +sbe_test(Issue835Test codecs) diff --git a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp index 2e09950162..f1f80496f2 100644 --- a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp @@ -21,7 +21,6 @@ #include "group_with_data/TestMessage3.h" #include "group_with_data/TestMessage4.h" -// using namespace std; using namespace group::with::data; static const std::uint32_t TAG_1 = 32; diff --git a/sbe-tool/src/test/cpp/Issue835Test.cpp b/sbe-tool/src/test/cpp/Issue835Test.cpp new file mode 100644 index 0000000000..068519c0c2 --- /dev/null +++ b/sbe-tool/src/test/cpp/Issue835Test.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" +#include "simple/MDUpdateAction.h" +#include "simple/MDEntryTypeBook.h" +#include "simple/MDIncrementalRefreshOrderBook47.h" + +static const std::size_t BUFFER_LEN = 2048u; + +using namespace simple; + +class Issue835Test : public testing::Test +{ +}; + +TEST_F(Issue835Test, shouldCompileWithSkipper) +{ + const std::uint64_t timeNs = 777; + const std::size_t offset = 0; + char buffer[BUFFER_LEN] = {}; + MDIncrementalRefreshOrderBook47 encoder = {}; + + encoder + .wrapForEncode(buffer, offset, BUFFER_LEN) + .transactTime(timeNs) + .matchEventIndicator() + .lastQuoteMsg(true) + .recoveryMsg(false) + .reserved(true); + + MDIncrementalRefreshOrderBook47::NoMDEntries &entries = encoder.noMDEntriesCount(2); + + entries.next(); + entries.orderID(1); + entries.mDOrderPriority(2); + entries.mDEntryPx().mantissa(77); + entries.securityID(33); + entries.mDUpdateAction(MDUpdateAction::Value::New); + entries.mDEntryType(MDEntryTypeBook::Value::Bid); + + entries.next(); + entries.orderID(2); + entries.mDOrderPriority(3); + entries.mDEntryPx().mantissa(88); + entries.securityID(44); + entries.mDUpdateAction(MDUpdateAction::Value::New); + entries.mDEntryType(MDEntryTypeBook::Value::Offer); + + MDIncrementalRefreshOrderBook47 decoder = {}; + decoder.wrapForDecode( + buffer, + offset, + MDIncrementalRefreshOrderBook47::sbeBlockLength(), + MDIncrementalRefreshOrderBook47::sbeSchemaVersion(), + BUFFER_LEN); + + EXPECT_EQ(decoder.decodeLength(), encoder.encodedLength()); +} diff --git a/sbe-tool/src/test/resources/issue835.xml b/sbe-tool/src/test/resources/issue835.xml new file mode 100644 index 0000000000..57b2f507a6 --- /dev/null +++ b/sbe-tool/src/test/resources/issue835.xml @@ -0,0 +1,267 @@ + + + + + + + + 24 + + + + + + + J + g + 2 + e + + 0 + 0 + + + + 8 + + + + + + + + + + + + + + + + -9 + + + + -9 + + + + -4 + + + + -7 + + + + + + + + + + -7 + + + + -9 + + + + -7 + + + + -9 + + + + + + + + + + + + + + + + + + + + + 0 + 1 + 2 + + + 5 + 7 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + + + 1 + 2 + + + 0 + 1 + 2 + 4 + 6 + 7 + 8 + B + C + E + F + J + N + O + W + e + g + + + 0 + 1 + E + F + J + + + 6 + B + C + W + + + 4 + 7 + 8 + N + O + + + 0 + 1 + 2 + 3 + 4 + 5 + + + 0 + 5 + + + 0 + 1 + 2 + + + 0 + 1 + + + 0 + 1 + 4 + 5 + 6 + + + 2 + 4 + 15 + 17 + 18 + 20 + 21 + 24 + 25 + 26 + 103 + + + A + D + M + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + + + 0 + 1 + 2 + 3 + 4 + 7 + + + + + + + + + + + + + + + + From 7ddc19ceb1881a4764e71c5593731cd1c12a1624 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 16 Feb 2021 11:12:52 +0000 Subject: [PATCH 0649/1594] [Java] Add checkstyle rule for copyright. --- config/checkstyle/checkstyle.xml | 5 +++++ config/checkstyle/suppressions.xml | 1 + .../real_logic/sbe/generation/csharp/CSharp.java | 1 + .../sbe/generation/golang/GolangGenerator.java | 1 + .../generation/golang/GolangOutputManager.java | 1 + .../sbe/generation/golang/GolangUtil.java | 1 + .../uk/co/real_logic/sbe/xml/IrGenerator.java | 3 ++- .../uk/co/real_logic/sbe/xml/ParserOptions.java | 1 - .../generation/csharp/Issue567GroupSizeTest.java | 15 +++++++++++++++ 9 files changed, 27 insertions(+), 2 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 661cc5f88e..9240d25c80 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -22,6 +22,11 @@ + + + + + diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml index dcc9f236fa..19af0e6028 100644 --- a/config/checkstyle/suppressions.xml +++ b/config/checkstyle/suppressions.xml @@ -4,4 +4,5 @@ "https://checkstyle.org/dtds/suppressions_1_0.dtd"> + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java index 22234384de..9b091f8519 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java @@ -1,4 +1,5 @@ /* + * Copyright 2013-2021 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index 3d6d97b100..abfb1a75b3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -1,4 +1,5 @@ /* + * Copyright 2013-2021 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java index db6e58c50c..29fba30b4a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java @@ -1,4 +1,5 @@ /* + * Copyright 2013-2021 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java index a1b88d4f14..44362a06cb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java @@ -1,4 +1,5 @@ /* + * Copyright 2013-2021 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index 80be549ee5..5f9850e983 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -1,4 +1,5 @@ -/* Copyright 2013-2021 Real Logic Limited. +/* + * Copyright 2013-2021 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java index 2a88afa691..9ff509d56d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java @@ -1,4 +1,3 @@ -/* -*- mode: java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */ /* * Copyright 2013-2021 Real Logic Limited. * diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index a31ab03f98..b59caa3f4a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package uk.co.real_logic.sbe.generation.csharp; import org.agrona.generation.StringWriterOutputManager; From b404c6b13ebd02ed06d701d6900d72b2045d4231 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 18 Feb 2021 18:47:59 +0000 Subject: [PATCH 0650/1594] [Java] Add checkstyle rule for javadoc and add missing javadoc. --- config/checkstyle/checkstyle.xml | 4 + config/checkstyle/suppressions.xml | 2 + .../sbe/examples/ExampleTokenListener.java | 38 +++++ .../examples/ExampleUsingGeneratedStub.java | 10 +- .../ExampleUsingGeneratedStubExtension.java | 10 +- .../real_logic/sbe/examples/OtfExample.java | 10 +- .../uk/co/real_logic/sbe/ValidationUtil.java | 50 +++++- .../real_logic/sbe/codec/java/GroupOrder.java | 5 + .../sbe/codec/java/MethodSelector.java | 22 ++- .../sbe/generation/CodeGenerator.java | 7 + .../generation/TargetCodeGeneratorLoader.java | 12 ++ .../sbe/generation/c/CGenerator.java | 16 +- .../sbe/generation/cpp/CppGenerator.java | 17 +- .../sbe/generation/cpp/CppUtil.java | 14 +- .../sbe/generation/csharp/CSharp.java | 3 + .../generation/csharp/CSharpGenerator.java | 26 ++- .../generation/golang/GolangGenerator.java | 24 +++ .../sbe/generation/java/JavaGenerator.java | 110 ++++++++----- .../sbe/generation/java/JavaUtil.java | 9 +- .../uk/co/real_logic/sbe/ir/Encoding.java | 78 ++++++++- .../co/real_logic/sbe/ir/GenerationUtil.java | 65 +++++++- .../java/uk/co/real_logic/sbe/ir/IrUtil.java | 26 +-- .../java/uk/co/real_logic/sbe/ir/Token.java | 74 +++++++++ .../co/real_logic/sbe/json/JsonPrinter.java | 52 ++++-- .../sbe/json/JsonTokenListener.java | 38 +++++ .../sbe/otf/AbstractTokenListener.java | 33 ++++ .../co/real_logic/sbe/xml/CompositeType.java | 10 +- .../real_logic/sbe/xml/EncodedDataType.java | 3 + .../uk/co/real_logic/sbe/xml/EnumType.java | 13 +- .../co/real_logic/sbe/xml/ErrorHandler.java | 3 + .../java/uk/co/real_logic/sbe/xml/Field.java | 150 +++++++++++++++--- .../uk/co/real_logic/sbe/xml/Message.java | 3 + .../co/real_logic/sbe/xml/MessageSchema.java | 2 +- .../uk/co/real_logic/sbe/xml/SetType.java | 13 +- .../java/uk/co/real_logic/sbe/xml/Type.java | 5 + 35 files changed, 832 insertions(+), 125 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 9240d25c80..5197f7bb3e 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -33,6 +33,10 @@ + + + + diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml index 19af0e6028..84e7e82814 100644 --- a/config/checkstyle/suppressions.xml +++ b/config/checkstyle/suppressions.xml @@ -5,4 +5,6 @@ + + diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java index 5f11e3fa7d..27ff7e745d 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java @@ -39,21 +39,35 @@ public class ExampleTokenListener implements TokenListener private final Deque namedScope = new ArrayDeque<>(); private final byte[] tempBuffer = new byte[1024]; + /** + * Construct an example {@link TokenListener} that prints tokens out. + * + * @param out to print the tokens to. + */ public ExampleTokenListener(final PrintWriter out) { this.out = out; } + /** + * {@inheritDoc} + */ public void onBeginMessage(final Token token) { namedScope.push(token.name() + "."); } + /** + * {@inheritDoc} + */ public void onEndMessage(final Token token) { namedScope.pop(); } + /** + * {@inheritDoc} + */ public void onEncoding( final Token fieldToken, final DirectBuffer buffer, @@ -70,6 +84,9 @@ public void onEncoding( .println(); } + /** + * {@inheritDoc} + */ public void onEnum( final Token fieldToken, final DirectBuffer buffer, @@ -109,6 +126,9 @@ public void onEnum( .println(); } + /** + * {@inheritDoc} + */ public void onBitSet( final Token fieldToken, final DirectBuffer buffer, @@ -138,6 +158,9 @@ public void onBitSet( out.println(); } + /** + * {@inheritDoc} + */ public void onBeginComposite( final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { @@ -145,12 +168,18 @@ public void onBeginComposite( namedScope.push(determineName(1, fieldToken, tokens, fromIndex) + "."); } + /** + * {@inheritDoc} + */ public void onEndComposite(final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { --compositeLevel; namedScope.pop(); } + /** + * {@inheritDoc} + */ public void onGroupHeader(final Token token, final int numInGroup) { printScope(); @@ -160,16 +189,25 @@ public void onGroupHeader(final Token token, final int numInGroup) .println(); } + /** + * {@inheritDoc} + */ public void onBeginGroup(final Token token, final int groupIndex, final int numInGroup) { namedScope.push(token.name() + "."); } + /** + * {@inheritDoc} + */ public void onEndGroup(final Token token, final int groupIndex, final int numInGroup) { namedScope.pop(); } + /** + * {@inheritDoc} + */ public void onVarData( final Token fieldToken, final DirectBuffer buffer, diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java index e7968d42cb..cfd8a27181 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java @@ -62,6 +62,12 @@ public class ExampleUsingGeneratedStub } } + /** + * Main entry point for the example. + * + * @param args which are ignored. + * @throws Exception if an error occurs when parsing the XML or doing IO. + */ public static void main(final String[] args) throws Exception { System.out.println("\n*** Basic Stub Example ***"); @@ -102,7 +108,7 @@ public static void main(final String[] args) throws Exception decode(CAR_DECODER, directBuffer, bufferOffset, actingBlockLength, actingVersion); } - public static int encode( + static int encode( final CarEncoder car, final UnsafeBuffer directBuffer, final MessageHeaderEncoder messageHeaderEncoder) { car.wrapAndApplyHeader(directBuffer, 0, messageHeaderEncoder) @@ -156,7 +162,7 @@ public static int encode( return MessageHeaderEncoder.ENCODED_LENGTH + car.encodedLength(); } - public static void decode( + static void decode( final CarDecoder car, final UnsafeBuffer directBuffer, final int bufferOffset, diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java index 6839c4db70..4a6eb7b889 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java @@ -66,6 +66,12 @@ public class ExampleUsingGeneratedStubExtension } } + /** + * Main entry point for the example. + * + * @param args which are ignored. + * @throws Exception if an error occurs when parsing the XML or doing IO. + */ public static void main(final String[] args) throws Exception { System.out.println("\n*** Extension Stub Example ***"); @@ -106,7 +112,7 @@ public static void main(final String[] args) throws Exception decode(CAR_DECODER_1, directBuffer, bufferOffset, actingBlockLength, actingVersion); } - public static int encode( + static int encode( final baseline.CarEncoder car, final UnsafeBuffer directBuffer, final baseline.MessageHeaderEncoder headerEncoder) @@ -163,7 +169,7 @@ public static int encode( return MessageHeaderEncoder.ENCODED_LENGTH + car.encodedLength(); } - public static void decode( + static void decode( final extension.CarDecoder car, final UnsafeBuffer directBuffer, final int bufferOffset, diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java index d682400374..a3bb59fb84 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java @@ -46,15 +46,21 @@ public class OtfExample private static final int MSG_BUFFER_CAPACITY = 4 * 1024; private static final int SCHEMA_BUFFER_CAPACITY = 16 * 1024; + /** + * Main entry point for the example. + * + * @param args which are ignored. + * @throws Exception if an error occurs when parsing the XML or doing IO. + */ public static void main(final String[] args) throws Exception { System.out.println("\n*** OTF Example ***\n"); // Encode up message and schema as if we just got them off the wire. - final ByteBuffer encodedSchemaBuffer = ByteBuffer.allocate(SCHEMA_BUFFER_CAPACITY); + final ByteBuffer encodedSchemaBuffer = ByteBuffer.allocateDirect(SCHEMA_BUFFER_CAPACITY); encodeSchema(encodedSchemaBuffer); - final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); + final ByteBuffer encodedMsgBuffer = ByteBuffer.allocateDirect(MSG_BUFFER_CAPACITY); encodeTestMessage(encodedMsgBuffer); // Now lets decode the schema IR so we have IR objects. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index 261ae82a97..34d04f252c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -65,11 +65,23 @@ public static boolean isSbeCName(final String value) return true; } + /** + * Is the token a C language keyword? + * + * @param token to be checked. + * @return true if the token a C language keyword. + */ public static boolean isCKeyword(final String token) { return C_KEYWORDS.contains(token); } + /** + * Is the value a possible C language keyword? + * + * @param value to be checked. + * @return true if the value a possible C language keyword. + */ private static boolean possibleCKeyword(final String value) { for (int i = 0, size = value.length(); i < size; i++) @@ -151,11 +163,23 @@ public static boolean isSbeCppName(final String value) return true; } + /** + * Is the token a C++ language keyword? + * + * @param token to be checked. + * @return true if the token a C++ language keyword. + */ public static boolean isCppKeyword(final String token) { return CPP_KEYWORDS.contains(token); } + /** + * Is the value a possible C++ language keyword? + * + * @param value to be checked. + * @return true if the value a possible C++ language keyword. + */ private static boolean possibleCppKeyword(final String value) { for (int i = 0, size = value.length(); i < size; i++) @@ -319,11 +343,23 @@ public static boolean isSbeGolangName(final String value) return true; } + /** + * Is the token a Go language keyword? + * + * @param token to be checked. + * @return true if the token a Go language keyword. + */ public static boolean isGolangKeyword(final String token) { return GOLANG_KEYWORDS.contains(token); } + /** + * Is the value a possible Go language keyword? + * + * @param value to be checked. + * @return true if the value a possible Go language keyword. + */ private static boolean possibleGolangKeyword(final String value) { for (int i = 0, size = value.length(); i < size; i++) @@ -417,12 +453,24 @@ public static boolean isSbeCSharpName(final String value) return true; } + /** + * Is the token a C# language keyword? + * + * @param token to be checked. + * @return true if the token a C# language keyword. + */ public static boolean isCSharpKeyword(final String token) { return CSHARP_KEYWORDS.contains(token); } - private static boolean possibleCSharpKeyword(final String value) + /** + * Is the value a possible C# language keyword? + * + * @param value to be checked. + * @return true if the value a possible C# language keyword. + */ + public static boolean possibleCSharpKeyword(final String value) { for (int i = 0, size = value.length(); i < size; i++) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java index f2834a2a17..8ab31806a3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java @@ -27,5 +27,10 @@ @Target({ ElementType.TYPE }) public @interface GroupOrder { + /** + * Array of class values in order. + * + * @return array of class values in order. + */ Class[] value(); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java index 281eeb8a11..437d984943 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java @@ -35,17 +35,33 @@ public class MethodSelector private final Set ignoredMethods; private final Map, Set> sortedMethods = new HashMap<>(); + /** + * The method names for method belonging to Object and Iterator. + * + * @return the method names for method belonging to Object and Iterator. + */ public static Set objectAndIteratorMethods() { return new HashSet<>( Arrays.asList("hashCode", "clone", "toString", "getClass", "next", "hasNext", "remove", "iterator")); } + /** + * Create a method selector with a set of methods to be ignored. + * + * @param ignoredMethods to be skipped over. + */ public MethodSelector(final Set ignoredMethods) { this.ignoredMethods = ignoredMethods; } + /** + * Select a list of methods from a given class. + * + * @param clazz to select the method for. + * @return the list of methods + */ public List select(final Class clazz) { final Method[] methods = clazz.getMethods(); @@ -69,10 +85,10 @@ public List select(final Class clazz) private Set getSortedMethods(final Class clazz, final Method[] methods) { final Set sortedMethodNames = sortedMethods.get(clazz); - if (sortedMethodNames == null) + if (null == sortedMethodNames) { final GroupOrder order = clazz.getAnnotation(GroupOrder.class); - if (order == null) + if (null == order) { sortedMethods.put(clazz, Collections.emptySet()); @@ -116,7 +132,7 @@ private void selectMethod( return; } - if (sortedMethodNames == null) + if (null == sortedMethodNames) { unsortedMethods.add(method); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java index e5e43a10a5..3f714cc3e1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java @@ -35,4 +35,11 @@ public interface CodeGenerator * @throws IOException if an error is encountered when writing the output. */ void generate() throws IOException; + + /** + * Generate the composites for dealing with the message header. + * + * @throws IOException if an error is encountered when writing the output. + */ + void generateMessageHeaderStub() throws IOException; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 2bcb3bf0b7..ba36941a7b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -38,6 +38,9 @@ public enum TargetCodeGeneratorLoader implements TargetCodeGenerator */ JAVA() { + /** + * {@inheritDoc} + */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { return new JavaGenerator( @@ -56,6 +59,9 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) */ C() { + /** + * {@inheritDoc} + */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { return new CGenerator(ir, new COutputManager(outputDir, ir.applicableNamespace())); @@ -67,6 +73,9 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) */ CPP() { + /** + * {@inheritDoc} + */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { return new CppGenerator( @@ -81,6 +90,9 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) */ GOLANG() { + /** + * {@inheritDoc} + */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { return new GolangGenerator(ir, new GolangOutputManager(outputDir, ir.applicableNamespace())); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 34f7b374ce..f86e1cc03a 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -45,6 +45,12 @@ public class CGenerator implements CodeGenerator private final Ir ir; private final OutputManager outputManager; + /** + * Create a new C language {@link CodeGenerator}. + * + * @param ir for the messages and types. + * @param outputManager for generating the codecs to. + */ public CGenerator(final Ir ir, final OutputManager outputManager) { Verify.notNull(ir, "ir"); @@ -54,12 +60,15 @@ public CGenerator(final Ir ir, final OutputManager outputManager) this.outputManager = outputManager; } + /** + * {@inheritDoc} + */ public void generateMessageHeaderStub() throws IOException { generateComposite(ir.namespaces(), ir.headerStructure().tokens()); } - public List generateTypeStubs(final CharSequence[] scope) throws IOException + List generateTypeStubs(final CharSequence[] scope) throws IOException { final List typesToInclude = new ArrayList<>(); @@ -86,7 +95,7 @@ public List generateTypeStubs(final CharSequence[] scope) throws IOExcep return typesToInclude; } - public List generateTypesToIncludes(final List tokens) + List generateTypesToIncludes(final List tokens) { final List typesToInclude = new ArrayList<>(); @@ -105,6 +114,9 @@ public List generateTypesToIncludes(final List tokens) return typesToInclude; } + /** + * {@inheritDoc} + */ public void generate() throws IOException { generateMessageHeaderStub(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 2f737e83e1..fa7c596cb5 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -52,6 +52,13 @@ public class CppGenerator implements CodeGenerator private final OutputManager outputManager; private final boolean shouldDecodeUnknownEnumValues; + /** + * Create a new Go language {@link CodeGenerator}. + * + * @param ir for the messages and types. + * @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding. + * @param outputManager for generating the codecs to. + */ public CppGenerator(final Ir ir, final boolean shouldDecodeUnknownEnumValues, final OutputManager outputManager) { Verify.notNull(ir, "ir"); @@ -62,12 +69,15 @@ public CppGenerator(final Ir ir, final boolean shouldDecodeUnknownEnumValues, fi this.outputManager = outputManager; } + /** + * {@inheritDoc} + */ public void generateMessageHeaderStub() throws IOException { generateComposite(ir.headerStructure().tokens()); } - public List generateTypeStubs() throws IOException + private List generateTypeStubs() throws IOException { final List typesToInclude = new ArrayList<>(); @@ -94,7 +104,7 @@ public List generateTypeStubs() throws IOException return typesToInclude; } - public List generateTypesToIncludes(final List tokens) + private List generateTypesToIncludes(final List tokens) { final List typesToInclude = new ArrayList<>(); @@ -113,6 +123,9 @@ public List generateTypesToIncludes(final List tokens) return typesToInclude; } + /** + * {@inheritDoc} + */ public void generate() throws IOException { generateMessageHeaderStub(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index d03c1c41d0..ccb4898421 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -121,8 +121,20 @@ public static String formatByteOrderEncoding(final ByteOrder byteOrder, final Pr } } + /** + * Generate a count of closing braces, one on each line. + * + * @param count of closing braces. + * @return A string with count of closing braces. + */ public static String closingBraces(final int count) { - return new String(new char[count]).replace("\0", "}\n"); + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < count; i++) + { + sb.append("}\n"); + } + + return sb.toString(); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java index 9b091f8519..46b13bc35a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java @@ -25,6 +25,9 @@ */ public class CSharp implements TargetCodeGenerator { + /** + * {@inheritDoc} + */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { return new CSharpGenerator(ir, new CSharpNamespaceOutputManager(outputDir, ir.applicableNamespace())); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 942b1382d6..995d6050a7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -50,6 +50,12 @@ public class CSharpGenerator implements CodeGenerator private final Ir ir; private final OutputManager outputManager; + /** + * Create a new C# language {@link CodeGenerator}. + * + * @param ir for the messages and types. + * @param outputManager for generating the codecs to. + */ public CSharpGenerator(final Ir ir, final OutputManager outputManager) { Verify.notNull(ir, "ir"); @@ -59,11 +65,19 @@ public CSharpGenerator(final Ir ir, final OutputManager outputManager) this.outputManager = outputManager; } + /** + * {@inheritDoc} + */ public void generateMessageHeaderStub() throws IOException { generateComposite(ir.headerStructure().tokens()); } + /** + * Generate the stubs for the types used as message fields. + * + * @throws IOException if an error is encountered when writing the output. + */ public void generateTypeStubs() throws IOException { generateMetaAttributeEnum(); @@ -87,6 +101,9 @@ public void generateTypeStubs() throws IOException } } + /** + * {@inheritDoc} + */ public void generate() throws IOException { generateMessageHeaderStub(); @@ -633,7 +650,7 @@ private CharSequence generateClassDeclaration(final String className) className); } - public static String generateDocumentation(final String indent, final Token token) + private static String generateDocumentation(final String indent, final Token token) { final String description = token.description(); if (null == description || description.isEmpty()) @@ -641,11 +658,10 @@ public static String generateDocumentation(final String indent, final Token toke return ""; } - return String.format( + return indent + "/// \n" + - indent + "/// %s\n" + - indent + "/// \n", - description); + indent + "/// " + description + "\n" + + indent + "/// \n"; } private void generateMetaAttributeEnum() throws IOException diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index abfb1a75b3..f6530306a4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -51,6 +51,12 @@ public class GolangGenerator implements CodeGenerator private TreeSet imports; + /** + * Create a new Go language {@link CodeGenerator}. + * + * @param ir for the messages and types. + * @param outputManager for generating the codecs to. + */ public GolangGenerator(final Ir ir, final OutputManager outputManager) { Verify.notNull(ir, "ir"); @@ -60,6 +66,13 @@ public GolangGenerator(final Ir ir, final OutputManager outputManager) this.outputManager = outputManager; } + /** + * Generate a file for the Ir based on a template. + * + * @param fileName to generate. + * @param templateName for the file. + * @throws IOException if an error is encountered when writing the output. + */ public void generateFileFromTemplate(final String fileName, final String templateName) throws IOException { try (Writer out = outputManager.createOutput(fileName)) @@ -68,6 +81,11 @@ public void generateFileFromTemplate(final String fileName, final String templat } } + /** + * Generate the stubs for the types used as message fields. + * + * @throws IOException if an error is encountered when writing the output. + */ public void generateTypeStubs() throws IOException { for (final List tokens : ir.types()) @@ -95,6 +113,9 @@ public void generateTypeStubs() throws IOException // MessageHeader is special but the standard allows it to be // pretty arbitrary after the first four fields. // All we need is the imports, type declaration, and encode/decode + /** + * {@inheritDoc} + */ public void generateMessageHeaderStub() throws IOException { final String messageHeader = "MessageHeader"; @@ -116,6 +137,9 @@ public void generateMessageHeaderStub() throws IOException } } + /** + * {@inheritDoc} + */ public void generate() throws IOException { // Add the Marshalling from the big or little endian diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index ce627c54e5..dbfaeb6338 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -63,6 +63,17 @@ enum CodecType private final boolean shouldGenerateInterfaces; private final boolean shouldDecodeUnknownEnumValues; + /** + * Create a new Java language {@link CodeGenerator}. + * + * @param ir for the messages and types. + * @param mutableBuffer implementation used for mutating underlying buffers. + * @param readOnlyBuffer implementation used for reading underlying buffers. + * @param shouldGenerateGroupOrderAnnotation in the codecs. + * @param shouldGenerateInterfaces for common methods. + * @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding. + * @param outputManager for generating the codecs to. + */ public JavaGenerator( final Ir ir, final String mutableBuffer, @@ -89,55 +100,19 @@ public JavaGenerator( this.shouldDecodeUnknownEnumValues = shouldDecodeUnknownEnumValues; } - private static String validateBufferImplementation( - final String fullyQualifiedBufferImplementation, final Class bufferClass) - { - Verify.notNull(fullyQualifiedBufferImplementation, "fullyQualifiedBufferImplementation"); - - try - { - final Class clazz = Class.forName(fullyQualifiedBufferImplementation); - if (!bufferClass.isAssignableFrom(clazz)) - { - throw new IllegalArgumentException( - fullyQualifiedBufferImplementation + " doesn't implement " + bufferClass.getName()); - } - - return clazz.getSimpleName(); - } - catch (final ClassNotFoundException ex) - { - throw new IllegalArgumentException("Unable to find " + fullyQualifiedBufferImplementation, ex); - } - } - - private String encoderName(final String className) - { - return formatClassName(className) + "Encoder"; - } - - private String decoderName(final String className) - { - return formatClassName(className) + "Decoder"; - } - - private String implementsInterface(final String interfaceName) - { - if (!shouldGenerateInterfaces) - { - return ""; - } - else - { - return " implements " + interfaceName; - } - } - + /** + * {@inheritDoc} + */ public void generateMessageHeaderStub() throws IOException { generateComposite(ir.headerStructure().tokens()); } + /** + * Generate the stubs for the types used as message fields. + * + * @throws IOException if an error is encountered when writing the output. + */ public void generateTypeStubs() throws IOException { generateMetaAttributeEnum(); @@ -161,6 +136,9 @@ public void generateTypeStubs() throws IOException } } + /** + * {@inheritDoc} + */ public void generate() throws IOException { generatePackageInfo(); @@ -3646,4 +3624,48 @@ private void appendMessageToString(final StringBuilder sb, final String decoderN append(sb, INDENT, " return decoder.appendTo(new StringBuilder()).toString();"); append(sb, INDENT, "}"); } + + private static String validateBufferImplementation( + final String fullyQualifiedBufferImplementation, final Class bufferClass) + { + Verify.notNull(fullyQualifiedBufferImplementation, "fullyQualifiedBufferImplementation"); + + try + { + final Class clazz = Class.forName(fullyQualifiedBufferImplementation); + if (!bufferClass.isAssignableFrom(clazz)) + { + throw new IllegalArgumentException( + fullyQualifiedBufferImplementation + " doesn't implement " + bufferClass.getName()); + } + + return clazz.getSimpleName(); + } + catch (final ClassNotFoundException ex) + { + throw new IllegalArgumentException("Unable to find " + fullyQualifiedBufferImplementation, ex); + } + } + + private String encoderName(final String className) + { + return formatClassName(className) + "Encoder"; + } + + private String decoderName(final String className) + { + return formatClassName(className) + "Decoder"; + } + + private String implementsInterface(final String interfaceName) + { + if (!shouldGenerateInterfaces) + { + return ""; + } + else + { + return " implements " + interfaceName; + } + } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index dba9022d1e..4da409b6d8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -40,7 +40,7 @@ public class JavaUtil /** * Separator symbols for {@link Object#toString()} implementations on codecs. */ - public enum Separator + enum Separator { BEGIN_GROUP('['), END_GROUP(']'), @@ -54,7 +54,7 @@ public enum Separator KEY_VALUE('='), ENTRY(','); - public final char symbol; + private final char symbol; Separator(final char symbol) { @@ -68,11 +68,14 @@ public enum Separator * @param indent the current generated code indentation * @param builderName of the generated StringBuilder to which separator should be added */ - public void appendToGeneratedBuilder(final StringBuilder builder, final String indent, final String builderName) + void appendToGeneratedBuilder(final StringBuilder builder, final String indent, final String builderName) { builder.append(indent).append(builderName).append(".append('").append(symbol).append("');").append('\n'); } + /** + * {@inheritDoc} + */ public String toString() { return String.valueOf(symbol); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java index de1d6304ae..cf6cedf16b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java @@ -59,7 +59,7 @@ public enum Presence private final String timeUnit; private final String semanticType; - public Encoding() + Encoding() { presence = Presence.REQUIRED; primitiveType = null; @@ -74,7 +74,7 @@ public Encoding() semanticType = null; } - public Encoding( + Encoding( final Presence presence, final PrimitiveType primitiveType, final ByteOrder byteOrder, @@ -268,6 +268,9 @@ public String semanticType() return semanticType; } + /** + * {@inheritDoc} + */ public String toString() { return @@ -303,72 +306,143 @@ public static class Builder private String timeUnit = null; private String semanticType = null; + /** + * PrimitiveType for the Encoding. + * + * @param primitiveType for the Encoding. + * @return this for a fluent API. + */ public Builder primitiveType(final PrimitiveType primitiveType) { this.primitiveType = primitiveType; return this; } + /** + * Presence for the Encoding. + * + * @param presence for the Encoding. + * @return this for a fluent API. + */ public Builder presence(final Presence presence) { this.presence = presence; return this; } + /** + * ByteOrder for the Encoding. + * + * @param byteOrder for the Encoding. + * @return this for a fluent API. + */ public Builder byteOrder(final ByteOrder byteOrder) { this.byteOrder = byteOrder; return this; } + /** + * Minimum value for the Encoding. + * + * @param minValue for the Encoding. + * @return this for a fluent API. + */ public Builder minValue(final PrimitiveValue minValue) { this.minValue = minValue; return this; } + /** + * Maximum value for the Encoding. + * + * @param maxValue for the Encoding. + * @return this for a fluent API. + */ public Builder maxValue(final PrimitiveValue maxValue) { this.maxValue = maxValue; return this; } + /** + * Null value for the Encoding. + * + * @param nullValue for the Encoding. + * @return this for a fluent API. + */ public Builder nullValue(final PrimitiveValue nullValue) { this.nullValue = nullValue; return this; } + /** + * Const value for the Encoding. + * + * @param constValue for the Encoding. + * @return this for a fluent API. + */ public Builder constValue(final PrimitiveValue constValue) { this.constValue = constValue; return this; } + /** + * Character encoding for the Encoding. + * + * @param characterEncoding for the Encoding. + * @return this for a fluent API. + */ public Builder characterEncoding(final String characterEncoding) { this.characterEncoding = characterEncoding; return this; } + /** + * Epoch value for the Encoding. + * + * @param epoch for the Encoding. + * @return this for a fluent API. + */ public Builder epoch(final String epoch) { this.epoch = epoch; return this; } + /** + * Time unit for the Encoding. + * + * @param timeUnit for the Encoding. + * @return this for a fluent API. + */ public Builder timeUnit(final String timeUnit) { this.timeUnit = timeUnit; return this; } + /** + * Semantic type for the Encoding. + * + * @param semanticType for the Encoding. + * @return this for a fluent API. + */ public Builder semanticType(final String semanticType) { this.semanticType = semanticType; return this; } + /** + * Build a new Encoding based on the values. + * + * @return a new Encoding based on the values. + */ public Encoding build() { return new Encoding( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java index 4d9fa6276b..d2f63750d9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java @@ -23,21 +23,54 @@ */ public final class GenerationUtil { + /** + * Collect the fields for a message. + * + * @param tokens for the message. + * @param index index at which to begin. + * @param fields to collect the field tokens into. + * @return resulting index. + */ public static int collectFields(final List tokens, final int index, final List fields) { return collect(Signal.BEGIN_FIELD, tokens, index, fields); } + /** + * Collect the groups for a message. + * + * @param tokens for the message. + * @param index index at which to begin. + * @param groups to collect the group tokens into. + * @return resulting index. + */ public static int collectGroups(final List tokens, final int index, final List groups) { return collect(Signal.BEGIN_GROUP, tokens, index, groups); } + /** + * Collect the var data for a message. + * + * @param tokens for the message. + * @param index index at which to begin. + * @param varData to collect the var data tokens into. + * @return resulting index. + */ public static int collectVarData(final List tokens, final int index, final List varData) { return collect(Signal.BEGIN_VAR_DATA, tokens, index, varData); } + /** + * Collect a run of tokens matching a signal. + * + * @param signal to match against. + * @param tokens for the message. + * @param index index at which to begin. + * @param collected to collect the tokens into. + * @return resulting index. + */ public static int collect( final Signal signal, final List tokens, final int index, final List collected) { @@ -60,17 +93,32 @@ public static int collect( return i; } + /** + * Get the tokens for the message body by subtracting the message wrapper. + * + * @param tokens for the message. + * @return the tokens for the message body by subtracting the message wrapper. + */ public static List getMessageBody(final List tokens) { return tokens.subList(1, tokens.size() - 1); } + /** + * Find the index of the end signal for a given name. + * + * @param tokens to search. + * @param index to start from. + * @param signal to match. + * @param name to match. + * @return index where found. + */ public static int findEndSignal( - final List tokens, final int startIndex, final Signal signal, final String name) + final List tokens, final int index, final Signal signal, final String name) { int result = tokens.size() - 1; - for (int i = startIndex, endIndex = tokens.size() - 1; i < endIndex; i++) + for (int i = index, endIndex = tokens.size() - 1; i < endIndex; i++) { final Token token = tokens.get(i); @@ -84,6 +132,12 @@ public static int findEndSignal( return result; } + /** + * Find a list of sub group names. + * + * @param tokens to search. + * @return list of names for the sub groups. + */ public static List findSubGroupNames(final List tokens) { final ArrayList groupNames = new ArrayList<>(); @@ -108,6 +162,13 @@ public static List findSubGroupNames(final List tokens) return groupNames; } + /** + * Find the first instance of a given signal. + * + * @param tokens to search. + * @param signal to search for. + * @return index the signal was found at or -1 if not found. + */ public static int findSignal(final List tokens, final Signal signal) { for (int i = 0, endIndex = tokens.size() - 1; i < endIndex; i++) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java index f198460ae6..febe9c4df0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java @@ -30,11 +30,11 @@ /** * Utility functions for working with {@link Ir}. */ -public class IrUtil +class IrUtil { - public static final byte[] EMPTY_BUFFER = new byte[0]; + static final byte[] EMPTY_BUFFER = new byte[0]; - public static ByteOrderCodec mapByteOrder(final ByteOrder byteOrder) + static ByteOrderCodec mapByteOrder(final ByteOrder byteOrder) { if (byteOrder == ByteOrder.BIG_ENDIAN) { @@ -44,7 +44,7 @@ public static ByteOrderCodec mapByteOrder(final ByteOrder byteOrder) return ByteOrderCodec.SBE_LITTLE_ENDIAN; } - public static ByteOrder mapByteOrder(final ByteOrderCodec byteOrder) + static ByteOrder mapByteOrder(final ByteOrderCodec byteOrder) { switch (byteOrder) { @@ -58,7 +58,7 @@ public static ByteOrder mapByteOrder(final ByteOrderCodec byteOrder) return ByteOrder.LITTLE_ENDIAN; } - public static SignalCodec mapSignal(final Signal signal) + static SignalCodec mapSignal(final Signal signal) { switch (signal) { @@ -116,7 +116,7 @@ public static SignalCodec mapSignal(final Signal signal) } } - public static Signal mapSignal(final SignalCodec signal) + static Signal mapSignal(final SignalCodec signal) { switch (signal) { @@ -174,7 +174,7 @@ public static Signal mapSignal(final SignalCodec signal) } } - public static PrimitiveTypeCodec mapPrimitiveType(final PrimitiveType type) + static PrimitiveTypeCodec mapPrimitiveType(final PrimitiveType type) { if (type == null) { @@ -221,7 +221,7 @@ public static PrimitiveTypeCodec mapPrimitiveType(final PrimitiveType type) } } - public static PrimitiveType mapPrimitiveType(final PrimitiveTypeCodec type) + static PrimitiveType mapPrimitiveType(final PrimitiveTypeCodec type) { switch (type) { @@ -264,7 +264,7 @@ public static PrimitiveType mapPrimitiveType(final PrimitiveTypeCodec type) } } - public static int put(final MutableDirectBuffer buffer, final PrimitiveValue value, final PrimitiveType type) + static int put(final MutableDirectBuffer buffer, final PrimitiveValue value, final PrimitiveType type) { if (value == null) { @@ -337,7 +337,7 @@ public static int put(final MutableDirectBuffer buffer, final PrimitiveValue val } } - public static PrimitiveValue get(final DirectBuffer buffer, final PrimitiveType type, final int length) + static PrimitiveValue get(final DirectBuffer buffer, final PrimitiveType type, final int length) { if (length == 0) { @@ -393,7 +393,7 @@ public static PrimitiveValue get(final DirectBuffer buffer, final PrimitiveType } } - public static byte[] getBytes(final String value, final String characterEncoding) + static byte[] getBytes(final String value, final String characterEncoding) throws UnsupportedEncodingException { if (null == value) @@ -405,7 +405,7 @@ public static byte[] getBytes(final String value, final String characterEncoding } - public static Encoding.Presence mapPresence(final PresenceCodec presence) + static Encoding.Presence mapPresence(final PresenceCodec presence) { switch (presence) { @@ -419,7 +419,7 @@ public static Encoding.Presence mapPresence(final PresenceCodec presence) return Encoding.Presence.REQUIRED; } - public static PresenceCodec mapPresence(final Encoding.Presence presence) + static PresenceCodec mapPresence(final Encoding.Presence presence) { switch (presence) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index c0fb835f52..c03b4553a3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -334,6 +334,9 @@ public boolean isOptionalEncoding() return encoding.presence() == OPTIONAL; } + /** + * {@inheritDoc} + */ public String toString() { return "Token{" + @@ -368,72 +371,143 @@ public static class Builder private int componentTokenCount = 1; private Encoding encoding = new Encoding(); + /** + * Signal for the Token. + * + * @param signal for the Token. + * @return this for a fluent API. + */ public Builder signal(final Signal signal) { this.signal = signal; return this; } + /** + * Name for the Token. + * + * @param name for the Token. + * @return this for a fluent API. + */ public Builder name(final String name) { this.name = name; return this; } + /** + * Referenced type name for the Token. + * + * @param referencedName for the Token. + * @return this for a fluent API. + */ public Builder referencedName(final String referencedName) { this.referencedName = referencedName; return this; } + /** + * Description attribute for the Token. + * + * @param description for the Token. + * @return this for a fluent API. + */ public Builder description(final String description) { this.description = description; return this; } + /** + * ID attribute for the Token. + * + * @param id for the Token. + * @return this for a fluent API. + */ public Builder id(final int id) { this.id = id; return this; } + /** + * Version attribute for the Token. + * + * @param version for the Token. + * @return this for a fluent API. + */ public Builder version(final int version) { this.version = version; return this; } + /** + * Deprecated version attribute for the Token. + * + * @param deprecated version for the Token. + * @return this for a fluent API. + */ public Builder deprecated(final int deprecated) { this.deprecated = deprecated; return this; } + /** + * Size of the type for the Token. + * + * @param size for the Token. + * @return this for a fluent API. + */ public Builder size(final int size) { this.size = size; return this; } + /** + * Offset in the message for the Token. + * + * @param offset for the Token. + * @return this for a fluent API. + */ public Builder offset(final int offset) { this.offset = offset; return this; } + /** + * Count of tokens in the component. + * + * @param componentTokenCount for the component. + * @return this for a fluent API. + */ public Builder componentTokenCount(final int componentTokenCount) { this.componentTokenCount = componentTokenCount; return this; } + /** + * Encoding type for the Token. + * + * @param encoding for the Token. + * @return this for a fluent API. + */ public Builder encoding(final Encoding encoding) { this.encoding = encoding; return this; } + /** + * Build a new Token based on the values. + * + * @return a new Token based on the values. + */ public Token build() { return new Token( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java index 64737c3970..d89dab0b9a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java @@ -32,28 +32,46 @@ public class JsonPrinter private final OtfHeaderDecoder headerDecoder; private final Ir ir; + /** + * Create a new JSON printer for a given message Ir. + * + * @param ir for the message type. + */ public JsonPrinter(final Ir ir) { this.ir = ir; headerDecoder = new OtfHeaderDecoder(ir.headerStructure()); } + /** + * Print the encoded message to the output. + * + * @param encodedMessage with header in buffer. + * @param output to write to. + */ public void print(final ByteBuffer encodedMessage, final StringBuilder output) { final UnsafeBuffer buffer = new UnsafeBuffer(encodedMessage); print(output, buffer, 0); } - public void print(final StringBuilder output, final UnsafeBuffer buffer, final int bufferOffset) + /** + * Print the encoded message to the output. + * + * @param output to write too. + * @param buffer with encoded message and header. + * @param offset at which the header begins. + */ + public void print(final StringBuilder output, final UnsafeBuffer buffer, final int offset) { - final int blockLength = headerDecoder.getBlockLength(buffer, bufferOffset); - final int templateId = headerDecoder.getTemplateId(buffer, bufferOffset); - final int schemaId = headerDecoder.getSchemaId(buffer, bufferOffset); - final int actingVersion = headerDecoder.getSchemaVersion(buffer, bufferOffset); + final int blockLength = headerDecoder.getBlockLength(buffer, offset); + final int templateId = headerDecoder.getTemplateId(buffer, offset); + final int schemaId = headerDecoder.getSchemaId(buffer, offset); + final int actingVersion = headerDecoder.getSchemaVersion(buffer, offset); validateId(schemaId); - final int messageOffset = bufferOffset + headerDecoder.encodedLength(); + final int messageOffset = offset + headerDecoder.encodedLength(); final List msgTokens = ir.getMessage(templateId); OtfMessageDecoder.decode( @@ -65,14 +83,12 @@ public void print(final StringBuilder output, final UnsafeBuffer buffer, final i new JsonTokenListener(output)); } - private void validateId(final int schemaId) - { - if (schemaId != ir.id()) - { - throw new IllegalArgumentException("Required schema id " + ir.id() + " but was " + schemaId); - } - } - + /** + * Print an encoded message to a String. + * + * @param encodedMessage with header in buffer. + * @return encoded message in JSON format. + */ public String print(final ByteBuffer encodedMessage) { final StringBuilder sb = new StringBuilder(); @@ -80,4 +96,12 @@ public String print(final ByteBuffer encodedMessage) return sb.toString(); } + + private void validateId(final int schemaId) + { + if (schemaId != ir.id()) + { + throw new IllegalArgumentException("Required schema id " + ir.id() + " but was " + schemaId); + } + } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index 02a8a3a85d..a0cc32cebc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -36,21 +36,35 @@ public class JsonTokenListener implements TokenListener private int indentation = 0; private int compositeLevel = 0; + /** + * Construct a new TokenListener that will write JSON formatted output. + * + * @param output to write the JSON formatted output to. + */ public JsonTokenListener(final StringBuilder output) { this.output = output; } + /** + * {@inheritDoc} + */ public void onBeginMessage(final Token token) { startObject(); } + /** + * {@inheritDoc} + */ public void onEndMessage(final Token token) { endObject(); } + /** + * {@inheritDoc} + */ public void onEncoding( final Token fieldToken, final DirectBuffer buffer, @@ -63,6 +77,9 @@ public void onEncoding( next(); } + /** + * {@inheritDoc} + */ public void onEnum( final Token fieldToken, final DirectBuffer buffer, @@ -101,6 +118,9 @@ public void onEnum( next(); } + /** + * {@inheritDoc} + */ public void onBitSet( final Token fieldToken, final DirectBuffer buffer, @@ -134,6 +154,9 @@ public void onBitSet( next(); } + /** + * {@inheritDoc} + */ public void onBeginComposite( final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { @@ -143,6 +166,9 @@ public void onBeginComposite( startObject(); } + /** + * {@inheritDoc} + */ public void onEndComposite( final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { @@ -150,6 +176,9 @@ public void onEndComposite( endObject(); } + /** + * {@inheritDoc} + */ public void onGroupHeader(final Token token, final int numInGroup) { property(token.name()); @@ -163,11 +192,17 @@ public void onGroupHeader(final Token token, final int numInGroup) } } + /** + * {@inheritDoc} + */ public void onBeginGroup(final Token token, final int groupIndex, final int numInGroup) { startObject(); } + /** + * {@inheritDoc} + */ public void onEndGroup(final Token token, final int groupIndex, final int numInGroup) { endObject(); @@ -178,6 +213,9 @@ public void onEndGroup(final Token token, final int groupIndex, final int numInG } } + /** + * {@inheritDoc} + */ public void onVarData( final Token fieldToken, final DirectBuffer buffer, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java index 2e1892fe07..8323b0d3f4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java @@ -28,16 +28,25 @@ */ public abstract class AbstractTokenListener implements TokenListener { + /** + * {@inheritDoc} + */ public void onBeginMessage(final Token token) { // no op } + /** + * {@inheritDoc} + */ public void onEndMessage(final Token token) { // no op } + /** + * {@inheritDoc} + */ public void onEncoding( final Token fieldToken, final DirectBuffer buffer, @@ -48,6 +57,9 @@ public void onEncoding( // no op } + /** + * {@inheritDoc} + */ public void onEnum( final Token fieldToken, final DirectBuffer buffer, @@ -60,6 +72,9 @@ public void onEnum( // no op } + /** + * {@inheritDoc} + */ public void onBitSet( final Token fieldToken, final DirectBuffer buffer, @@ -72,33 +87,51 @@ public void onBitSet( // no op } + /** + * {@inheritDoc} + */ public void onBeginComposite( final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { // no op } + /** + * {@inheritDoc} + */ public void onEndComposite( final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { // no op } + /** + * {@inheritDoc} + */ public void onGroupHeader(final Token token, final int numInGroup) { // no op } + /** + * {@inheritDoc} + */ public void onBeginGroup(final Token token, final int groupIndex, final int numInGroup) { // no op } + /** + * {@inheritDoc} + */ public void onEndGroup(final Token token, final int groupIndex, final int numInGroup) { // no op } + /** + * {@inheritDoc} + */ public void onVarData( final Token fieldToken, final DirectBuffer buffer, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index 02010278e3..8b740ffe42 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -50,7 +50,7 @@ public class CompositeType extends Type private final List compositesPath = new ArrayList<>(); private final Map containedTypeByNameMap = new LinkedHashMap<>(); - public CompositeType(final Node node) throws XPathExpressionException + CompositeType(final Node node) throws XPathExpressionException { this(node, null, null, new ArrayList<>()); } @@ -64,7 +64,7 @@ public CompositeType(final Node node) throws XPathExpressionException * @param compositesPath with the path of composites that represents the levels of composition. * @throws XPathExpressionException if the XPath is invalid. */ - public CompositeType( + CompositeType( final Node node, final String givenName, final String referencedName, final List compositesPath) throws XPathExpressionException { @@ -394,6 +394,9 @@ public void checkForValidOffsets(final Node node) } } + /** + * {@inheritDoc} + */ public boolean isVariableLength() { return false; @@ -483,6 +486,9 @@ private Type addType(final Node subTypeNode, final String name, final Type type) return type; } + /** + * {@inheritDoc} + */ public String toString() { return "CompositeType{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index 8b9a26fde0..4c76c27184 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -393,6 +393,9 @@ private PrimitiveValue processConstantChar(final Node node, final String lengthA return primitiveValue; } + /** + * {@inheritDoc} + */ public String toString() { return "EncodedDataType{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index 61934496b5..95da6fcf05 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -46,7 +46,7 @@ public class EnumType extends Type private final Map validValueByPrimitiveValueMap = new LinkedHashMap<>(); private final Map validValueByNameMap = new LinkedHashMap<>(); - public EnumType(final Node node) throws XPathExpressionException + EnumType(final Node node) throws XPathExpressionException { this(node, null, null); } @@ -59,7 +59,7 @@ public EnumType(final Node node) throws XPathExpressionException * @param referencedName of the type when created from a ref in a composite. * @throws XPathExpressionException if the XPath is invalid */ - public EnumType(final Node node, final String givenName, final String referencedName) + EnumType(final Node node, final String givenName, final String referencedName) throws XPathExpressionException { super(node, givenName, referencedName); @@ -242,11 +242,17 @@ public Collection validValues() return validValueByNameMap.values(); } + /** + * {@inheritDoc} + */ public boolean isVariableLength() { return false; } + /** + * {@inheritDoc} + */ public String toString() { return "EnumType{" + @@ -335,6 +341,9 @@ public int deprecated() return deprecated; } + /** + * {@inheritDoc} + */ public String toString() { return "ValidValue{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java index d9490a42bb..29b06481c5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java @@ -130,6 +130,9 @@ public int warningCount() return warnings; } + /** + * {@inheritDoc} + */ public String toString() { return "ErrorHandler{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java index 7b4a33f0cc..a4f2b6235a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java @@ -48,7 +48,7 @@ public class Field private final String epoch; // optional, epoch from which a timestamps start, defaults to "unix" private final String timeUnit; // optional, defaults to "nanosecond". - public Field( + Field( final String name, final String description, final int id, @@ -85,6 +85,12 @@ public Field( this.timeUnit = timeUnit; } + /** + * Validate the node is correct for the type. + * + * @param node in the XML. + * @param typeByNameMap for validating refs. + */ public void validate(final Node node, final Map typeByNameMap) { if (type != null && @@ -137,111 +143,219 @@ else if (!valueRefType.equals(type.name())) } } + /** + * Set the group fields when a group. + * + * @param fields for the group. + */ public void groupFields(final List fields) { groupFieldList = fields; } + /** + * Get the list of group fields. + * + * @return the list of group fields. + */ public List groupFields() { return groupFieldList; } + /** + * Set the computed offset at which the field begins. + * + * @param offset at which the field begins. + */ public void computedOffset(final int offset) { computedOffset = offset; } + /** + * The computed offset at which the field begins. + * + * @return the computed offset at which the field begins. + */ public int computedOffset() { return computedOffset; } + /** + * Name value for the field. + * + * @return name value for the field. + */ public String name() { return name; } + /** + * Description attribute for the field. + * + * @return the description attribute for the field. + */ public String description() { return description; } + /** + * ID attribute for the field. + * + * @return the ID attribute for the field. + */ public int id() { return id; } + /** + * Type attribute for the field. + * + * @return the Type attribute for the field. + */ public Type type() { return type; } + /** + * The offset at which the field begins. + * + * @return the offset at which the field begins. + */ public int offset() { return offset; } + /** + * The block length of the field. + * + * @return the block length the field. + */ public int blockLength() { return blockLength; } + /** + * The computed block length of the field. + * + * @param length computed for the block length, + */ public void computedBlockLength(final int length) { computedBlockLength = length; } + /** + * The computed block length of the field. + * + * @return the computed block length the field. + */ public int computedBlockLength() { return computedBlockLength; } + /** + * Presence attribute for the field. + * + * @return the Presence attribute for the field. + */ public Presence presence() { return presence; } + /** + * Ref attribute for the field. + * + * @return the Ref attribute for the field. + */ public String valueRef() { return valueRef; } + /** + * Semantic type attribute for the field. + * + * @return the Semantic type attribute for the field. + */ public String semanticType() { return semanticType; } + /** + * Dimension type for the field when group or var data. + * + * @return the Dimension type for the field when group or var data. + */ public CompositeType dimensionType() { return dimensionType; } + /** + * Is the field variable length when encoded? + * + * @return true if the field is variable length when encoded. + */ public boolean isVariableLength() { return variableLength; } + /** + * Since version attribute for the field. + * + * @return the Since version attribute for the field. + */ public int sinceVersion() { return sinceVersion; } + /** + * Deprecated version attribute for the field. + * + * @return the Deprecated version attribute for the field. + */ public int deprecated() { return deprecated; } + /** + * Epoch attribute for the field. + * + * @return the Epoch attribute for the field. + */ public String epoch() { return epoch; } + /** + * Time unit attribute for the field. + * + * @return the time unit attribute for the field. + */ public String timeUnit() { return timeUnit; } + /** + * {@inheritDoc} + */ public String toString() { return "Field{name='" + name + '\'' + @@ -299,7 +413,7 @@ private void validateValueRef(final Node node, final Map typeByNam /** * Builder to make creation of {@link Field} easier. */ - public static class Builder + static class Builder { private String name; private String description; @@ -317,97 +431,97 @@ public static class Builder private String epoch; private String timeUnit; - public Builder name(final String name) + Builder name(final String name) { this.name = name; return this; } - public Builder description(final String description) + Builder description(final String description) { this.description = description; return this; } - public Builder id(final int id) + Builder id(final int id) { this.id = id; return this; } - public Builder type(final Type type) + Builder type(final Type type) { this.type = type; return this; } - public Builder offset(final int offset) + Builder offset(final int offset) { this.offset = offset; return this; } - public Builder semanticType(final String semanticType) + Builder semanticType(final String semanticType) { this.semanticType = semanticType; return this; } - public Builder presence(final Presence presence) + Builder presence(final Presence presence) { this.presence = presence; return this; } - public Builder valueRef(final String refValue) + Builder valueRef(final String refValue) { this.refValue = refValue; return this; } - public Builder blockLength(final int blockLength) + Builder blockLength(final int blockLength) { this.blockLength = blockLength; return this; } - public Builder dimensionType(final CompositeType dimensionType) + Builder dimensionType(final CompositeType dimensionType) { this.dimensionType = dimensionType; return this; } - public Builder variableLength(final boolean variableLength) + Builder variableLength(final boolean variableLength) { this.variableLength = variableLength; return this; } - public Builder sinceVersion(final int sinceVersion) + Builder sinceVersion(final int sinceVersion) { this.sinceVersion = sinceVersion; return this; } - public Builder deprecated(final int deprecated) + Builder deprecated(final int deprecated) { this.deprecated = deprecated; return this; } - public Builder epoch(final String epoch) + Builder epoch(final String epoch) { this.epoch = epoch; return this; } - public Builder timeUnit(final String timeUnit) + Builder timeUnit(final String timeUnit) { this.timeUnit = timeUnit; return this; } - public Field build() + Field build() { return new Field( name, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java index 4320d267d4..cb35a143f5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java @@ -462,6 +462,9 @@ private static void validateBlockLength( } } + /** + * {@inheritDoc} + */ public String toString() { return "Message{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index 04b20183d8..c649ae6f20 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -44,7 +44,7 @@ public class MessageSchema private final Map typeByNameMap; private final Map messageByIdMap; - public MessageSchema( + MessageSchema( final Node schemaNode, final Map typeByNameMap, final Map messageByIdMap) { this.packageName = getAttributeValue(schemaNode, "package"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index 6dd1692734..148da894a2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -44,8 +44,8 @@ public class SetType extends Type private final Map choiceByPrimitiveValueMap = new LinkedHashMap<>(); private final Map choiceByNameMap = new LinkedHashMap<>(); - public SetType(final Node node) - throws XPathExpressionException, IllegalArgumentException + SetType(final Node node) + throws XPathExpressionException { this(node, null, null); } @@ -57,10 +57,9 @@ public SetType(final Node node) * @param givenName for the node. * @param referencedName of the type when created from a ref in a composite. * @throws XPathExpressionException on invalid XPath. - * @throws IllegalArgumentException on illegal encoding type. */ public SetType(final Node node, final String givenName, final String referencedName) - throws XPathExpressionException, IllegalArgumentException + throws XPathExpressionException { super(node, givenName, referencedName); @@ -186,6 +185,9 @@ public boolean isVariableLength() return false; } + /** + * {@inheritDoc} + */ public String toString() { return "SetType{" + @@ -279,6 +281,9 @@ public int deprecated() return deprecated; } + /** + * {@inheritDoc} + */ public String toString() { return "Choice{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java index 850ff02398..886141634f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java @@ -170,6 +170,11 @@ public String semanticType() return semanticType; } + /** + * Is the type variable length when encoded. + * + * @return true if the type is variable length when encoded. + */ public abstract boolean isVariableLength(); /** From e35f4b099ac99202db8fafc54284a6c41336b546 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 20 Feb 2021 18:02:55 +0000 Subject: [PATCH 0651/1594] Build variables consistency. --- cppbuild/cppbuild | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/cppbuild/cppbuild b/cppbuild/cppbuild index 7fdbb97d71..1b74d834e7 100755 --- a/cppbuild/cppbuild +++ b/cppbuild/cppbuild @@ -1,7 +1,7 @@ #!/usr/bin/env bash SOURCE_DIR="$(pwd)" -BUILD_DIR="$(pwd)/cppbuild/Release" +BUILD_DIR="${SOURCE_DIR}/cppbuild/Release" ncpus=1 case "$(uname)" in @@ -13,13 +13,14 @@ case "$(uname)" in ;; esac -echo "Will make with \"-j $ncpus\"." +echo "Will make with \"-j ${ncpus}\"." -if [ -d "$BUILD_DIR" ] ; then - echo "Build directory ($BUILD_DIR) exists, removing." - rm -rf "$BUILD_DIR" +if [ -d "${BUILD_DIR}" ] ; then + echo "Build directory (${BUILD_DIR}) exists, removing." + rm -rf "${BUILD_DIR}" fi -mkdir -p "$BUILD_DIR" +mkdir -p "${BUILD_DIR}" +cd "${BUILD_DIR}" || exit -(cd "$BUILD_DIR" && cmake -G "Unix Makefiles" "$SOURCE_DIR" && make clean && make -j "$ncpus" all && ctest -C Release --output-on-failure) +(cmake -G "Unix Makefiles" "${SOURCE_DIR}" && make clean && make -j ${ncpus} all && ctest -C Release --output-on-failure) From 8f7650b0de5ac6f70c16811c1a4b6ef288b5e2f0 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 24 Feb 2021 19:26:47 +0000 Subject: [PATCH 0652/1594] [Java] Upgrade to Gradle 6.8.3 and Mockito 3.8.0. --- build.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index f82dd3bca6..7b82d3cfec 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' -def mockitoVersion = '3.7.7' +def mockitoVersion = '3.8.0' def junitVersion = '5.7.1' def jmhVersion = '1.27' def agronaVersion = '1.9.0' @@ -723,6 +723,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.8.2' + gradleVersion = '6.8.3' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 25d3265315..8cf6eb5ad2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 2131ff04aa27fd3d189002522a5fbcf4e3d4f6c3 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 25 Feb 2021 11:55:49 +0000 Subject: [PATCH 0653/1594] [Java] Make CodeGenerator a FunctionalInterface. --- .../real_logic/sbe/generation/CodeGenerator.java | 15 +-------------- .../real_logic/sbe/generation/c/CGenerator.java | 4 +++- .../sbe/generation/cpp/CppGenerator.java | 4 +++- .../sbe/generation/csharp/CSharpGenerator.java | 4 +++- .../sbe/generation/golang/GolangGenerator.java | 6 ++++-- .../sbe/generation/java/JavaGenerator.java | 7 ++++++- .../sbe/generation/java/JavaGeneratorTest.java | 5 ++--- 7 files changed, 22 insertions(+), 23 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java index 3f714cc3e1..a74a8ee417 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java @@ -20,26 +20,13 @@ /** * Abstraction for code generators to implement. */ +@FunctionalInterface public interface CodeGenerator { - /** - * Class name to be used for visitor pattern that accesses the message headerStructure. - */ - String MESSAGE_HEADER_ENCODER_TYPE = "MessageHeaderEncoder"; - - String MESSAGE_HEADER_DECODER_TYPE = "MessageHeaderDecoder"; - /** * Generate the complete set of types and messages for a schema. * * @throws IOException if an error is encountered when writing the output. */ void generate() throws IOException; - - /** - * Generate the composites for dealing with the message header. - * - * @throws IOException if an error is encountered when writing the output. - */ - void generateMessageHeaderStub() throws IOException; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index f86e1cc03a..5f978e5fea 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -61,7 +61,9 @@ public CGenerator(final Ir ir, final OutputManager outputManager) } /** - * {@inheritDoc} + * Generate the composites for dealing with the message header. + * + * @throws IOException if an error is encountered when writing the output. */ public void generateMessageHeaderStub() throws IOException { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index fa7c596cb5..599f9149e9 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -70,7 +70,9 @@ public CppGenerator(final Ir ir, final boolean shouldDecodeUnknownEnumValues, fi } /** - * {@inheritDoc} + * Generate the composites for dealing with the message header. + * + * @throws IOException if an error is encountered when writing the output. */ public void generateMessageHeaderStub() throws IOException { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 995d6050a7..3a0fbba366 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -66,7 +66,9 @@ public CSharpGenerator(final Ir ir, final OutputManager outputManager) } /** - * {@inheritDoc} + * Generate the composites for dealing with the message header. + * + * @throws IOException if an error is encountered when writing the output. */ public void generateMessageHeaderStub() throws IOException { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index f6530306a4..33d12c305c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -112,9 +112,11 @@ public void generateTypeStubs() throws IOException // MessageHeader is special but the standard allows it to be // pretty arbitrary after the first four fields. - // All we need is the imports, type declaration, and encode/decode + // All we need is the imports, type declaration, and encode/decode. /** - * {@inheritDoc} + * Generate the composites for dealing with the message header. + * + * @throws IOException if an error is encountered when writing the output. */ public void generateMessageHeaderStub() throws IOException { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index dbfaeb6338..8b613b9880 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -42,6 +42,9 @@ @SuppressWarnings("MethodLength") public class JavaGenerator implements CodeGenerator { + static final String MESSAGE_HEADER_ENCODER_TYPE = "MessageHeaderEncoder"; + static final String MESSAGE_HEADER_DECODER_TYPE = "MessageHeaderDecoder"; + enum CodecType { DECODER, @@ -101,7 +104,9 @@ public JavaGenerator( } /** - * {@inheritDoc} + * Generate the composites for dealing with the message header. + * + * @throws IOException if an error is encountered when writing the output. */ public void generateMessageHeaderStub() throws IOException { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index bccbba67c9..e5101effd6 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -38,8 +38,7 @@ import static org.hamcrest.Matchers.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; -import static uk.co.real_logic.sbe.generation.CodeGenerator.MESSAGE_HEADER_DECODER_TYPE; -import static uk.co.real_logic.sbe.generation.java.JavaGenerator.MESSAGE_HEADER_ENCODER_TYPE; +import static uk.co.real_logic.sbe.generation.java.JavaGenerator.MESSAGE_HEADER_DECODER_TYPE; import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -75,7 +74,7 @@ public void shouldGenerateMessageHeaderStub() throws Exception final int templateIdOffset = 2; final short templateId = (short)7; final int blockLength = 32; - final String fqClassName = ir.applicableNamespace() + "." + MESSAGE_HEADER_ENCODER_TYPE; + final String fqClassName = ir.applicableNamespace() + "." + JavaGenerator.MESSAGE_HEADER_ENCODER_TYPE; when(mockBuffer.getShort(bufferOffset + templateIdOffset, BYTE_ORDER)).thenReturn(templateId); From e26bb17e86da54a1cc827a5f2c800b1d773f8037 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 25 Feb 2021 13:15:53 +0000 Subject: [PATCH 0654/1594] [Java] Generate wrapAndApplyHeader method for decoders for convenience. Issue #837. --- .../examples/ExampleUsingGeneratedStub.java | 39 +++++++++---------- .../ExampleUsingGeneratedStubExtension.java | 32 +++++++-------- .../real_logic/sbe/examples/OtfExample.java | 4 +- .../sbe/generation/java/JavaGenerator.java | 24 +++++++++++- .../sbe/ir/generated/FrameCodecDecoder.java | 20 ++++++++++ .../sbe/ir/generated/TokenCodecDecoder.java | 20 ++++++++++ 6 files changed, 95 insertions(+), 44 deletions(-) diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java index cfd8a27181..d77a8aab29 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java @@ -41,11 +41,6 @@ public class ExampleUsingGeneratedStub private static final byte[] MODEL; private static final UnsafeBuffer ACTIVATION_CODE; - private static final MessageHeaderDecoder MESSAGE_HEADER_DECODER = new MessageHeaderDecoder(); - private static final MessageHeaderEncoder MESSAGE_HEADER_ENCODER = new MessageHeaderEncoder(); - private static final CarDecoder CAR_DECODER = new CarDecoder(); - private static final CarEncoder CAR_ENCODER = new CarEncoder(); - static { try @@ -72,10 +67,15 @@ public static void main(final String[] args) throws Exception { System.out.println("\n*** Basic Stub Example ***"); - final ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4096); + final ByteBuffer byteBuffer = ByteBuffer.allocate(4096); final UnsafeBuffer directBuffer = new UnsafeBuffer(byteBuffer); - final int encodingLengthPlusHeader = encode(CAR_ENCODER, directBuffer, MESSAGE_HEADER_ENCODER); + final MessageHeaderDecoder messageHeaderDecoder = new MessageHeaderDecoder(); + final MessageHeaderEncoder messageHeaderEncoder = new MessageHeaderEncoder(); + final CarDecoder carDecoder = new CarDecoder(); + final CarEncoder carEncoder = new CarEncoder(); + + final int encodingLengthPlusHeader = encode(carEncoder, directBuffer, messageHeaderEncoder); // Optionally write the encoded buffer to a file for decoding by the On-The-Fly decoder @@ -91,21 +91,22 @@ public static void main(final String[] args) throws Exception // Decode the encoded message - int bufferOffset = 0; - MESSAGE_HEADER_DECODER.wrap(directBuffer, bufferOffset); + final int bufferOffset = 0; + messageHeaderDecoder.wrap(directBuffer, bufferOffset); + + if (messageHeaderDecoder.schemaId() != CarEncoder.SCHEMA_ID) + { + throw new IllegalStateException("Schema ids do not match"); + } // Lookup the applicable flyweight to decode this type of message based on templateId and version. - final int templateId = MESSAGE_HEADER_DECODER.templateId(); + final int templateId = messageHeaderDecoder.templateId(); if (templateId != baseline.CarEncoder.TEMPLATE_ID) { throw new IllegalStateException("Template ids do not match"); } - final int actingBlockLength = MESSAGE_HEADER_DECODER.blockLength(); - final int actingVersion = MESSAGE_HEADER_DECODER.version(); - - bufferOffset += MESSAGE_HEADER_DECODER.encodedLength(); - decode(CAR_DECODER, directBuffer, bufferOffset, actingBlockLength, actingVersion); + decode(carDecoder, directBuffer, messageHeaderDecoder); } static int encode( @@ -163,17 +164,13 @@ static int encode( } static void decode( - final CarDecoder car, - final UnsafeBuffer directBuffer, - final int bufferOffset, - final int actingBlockLength, - final int actingVersion) + final CarDecoder car, final UnsafeBuffer directBuffer, final MessageHeaderDecoder headerDecoder) throws Exception { final byte[] buffer = new byte[128]; final StringBuilder sb = new StringBuilder(); - car.wrap(directBuffer, bufferOffset, actingBlockLength, actingVersion); + car.wrapAndApplyHeader(directBuffer, 0, headerDecoder); sb.append("\ncar.serialNumber=").append(car.serialNumber()); sb.append("\ncar.modelYear=").append(car.modelYear()); diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java index 4a6eb7b889..fcacc3e4fb 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java @@ -44,11 +44,6 @@ public class ExampleUsingGeneratedStubExtension private static final byte[] MODEL; private static final UnsafeBuffer ACTIVATION_CODE; - private static final baseline.MessageHeaderDecoder MESSAGE_HEADER_DECODER = new baseline.MessageHeaderDecoder(); - private static final baseline.MessageHeaderEncoder MESSAGE_HEADER_ENCODER = new baseline.MessageHeaderEncoder(); - private static final baseline.CarEncoder CAR_ENCODER_0 = new baseline.CarEncoder(); - private static final extension.CarDecoder CAR_DECODER_1 = new extension.CarDecoder(); - static { try @@ -76,10 +71,15 @@ public static void main(final String[] args) throws Exception { System.out.println("\n*** Extension Stub Example ***"); - final ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4096); + final ByteBuffer byteBuffer = ByteBuffer.allocate(4096); final UnsafeBuffer directBuffer = new UnsafeBuffer(byteBuffer); - final int encodingLengthPlusHeader = encode(CAR_ENCODER_0, directBuffer, MESSAGE_HEADER_ENCODER); + final extension.MessageHeaderDecoder messageHeaderDecoder = new extension.MessageHeaderDecoder(); + final baseline.MessageHeaderEncoder messageHeaderEncoder = new baseline.MessageHeaderEncoder(); + final baseline.CarEncoder carEncoder = new baseline.CarEncoder(); + final extension.CarDecoder carDecoder = new extension.CarDecoder(); + + final int encodingLengthPlusHeader = encode(carEncoder, directBuffer, messageHeaderEncoder); // Optionally write the encoded buffer to a file for decoding by the On-The-Fly decoder @@ -95,21 +95,17 @@ public static void main(final String[] args) throws Exception // Decode the encoded message - int bufferOffset = 0; - MESSAGE_HEADER_DECODER.wrap(directBuffer, bufferOffset); + final int bufferOffset = 0; + messageHeaderDecoder.wrap(directBuffer, bufferOffset); // Lookup the applicable flyweight to decode this type of message based on templateId and version. - final int templateId = MESSAGE_HEADER_DECODER.templateId(); + final int templateId = messageHeaderDecoder.templateId(); if (templateId != extension.CarEncoder.TEMPLATE_ID) { throw new IllegalStateException("Template ids do not match"); } - final int actingBlockLength = MESSAGE_HEADER_DECODER.blockLength(); - final int actingVersion = MESSAGE_HEADER_DECODER.version(); - - bufferOffset += MESSAGE_HEADER_DECODER.encodedLength(); - decode(CAR_DECODER_1, directBuffer, bufferOffset, actingBlockLength, actingVersion); + decode(carDecoder, directBuffer, messageHeaderDecoder); } static int encode( @@ -172,15 +168,13 @@ static int encode( static void decode( final extension.CarDecoder car, final UnsafeBuffer directBuffer, - final int bufferOffset, - final int actingBlockLength, - final int actingVersion) + final extension.MessageHeaderDecoder headerDecoder) throws Exception { final byte[] buffer = new byte[128]; final StringBuilder sb = new StringBuilder(); - car.wrap(directBuffer, bufferOffset, actingBlockLength, actingVersion); + car.wrapAndApplyHeader(directBuffer, 0, headerDecoder); sb.append("\ncar.serialNumber=").append(car.serialNumber()); sb.append("\ncar.modelYear=").append(car.modelYear()); diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java index a3bb59fb84..564297abb8 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java @@ -57,10 +57,10 @@ public static void main(final String[] args) throws Exception System.out.println("\n*** OTF Example ***\n"); // Encode up message and schema as if we just got them off the wire. - final ByteBuffer encodedSchemaBuffer = ByteBuffer.allocateDirect(SCHEMA_BUFFER_CAPACITY); + final ByteBuffer encodedSchemaBuffer = ByteBuffer.allocate(SCHEMA_BUFFER_CAPACITY); encodeSchema(encodedSchemaBuffer); - final ByteBuffer encodedMsgBuffer = ByteBuffer.allocateDirect(MSG_BUFFER_CAPACITY); + final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); encodeTestMessage(encodedMsgBuffer); // Now lets decode the schema IR so we have IR objects. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 8b613b9880..4281368419 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2537,7 +2537,9 @@ private CharSequence generateFixedFlyweightCode( private CharSequence generateDecoderFlyweightCode(final String className, final Token token) { - final String wrapMethod = + final String headerClassName = formatClassName(ir.headerStructure().tokens().get(0).applicableTypeName()); + + final String methods = " public " + className + " wrap(\n" + " final " + readOnlyBuffer + " buffer,\n" + " final int offset,\n" + @@ -2554,9 +2556,27 @@ private CharSequence generateDecoderFlyweightCode(final String className, final " this.actingVersion = actingVersion;\n" + " limit(offset + actingBlockLength);\n\n" + " return this;\n" + + " }\n\n" + + + " public " + className + " wrapAndApplyHeader(\n" + + " final " + readOnlyBuffer + " buffer,\n" + + " final int offset,\n" + + " final " + headerClassName + "Decoder headerDecoder)\n" + + " {\n" + + " headerDecoder.wrap(buffer, offset);\n\n" + + " final int templateId = headerDecoder.templateId();\n" + + " if (TEMPLATE_ID != templateId)\n" + + " {\n" + + " throw new IllegalStateException(\"Invalid TEMPLATE_ID: \" + templateId);\n" + + " }\n\n" + + " return wrap(\n" + + " buffer,\n" + + " offset + " + headerClassName + "Decoder.ENCODED_LENGTH,\n" + + " headerDecoder.blockLength(),\n" + + " headerDecoder.version());\n" + " }\n\n"; - return generateFlyweightCode(DECODER, className, token, wrapMethod, readOnlyBuffer); + return generateFlyweightCode(DECODER, className, token, methods, readOnlyBuffer); } private CharSequence generateFlyweightCode( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 9325c7d381..f14c56220f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -84,6 +84,26 @@ public FrameCodecDecoder wrap( return this; } + public FrameCodecDecoder wrapAndApplyHeader( + final DirectBuffer buffer, + final int offset, + final MessageHeaderDecoder headerDecoder) + { + headerDecoder.wrap(buffer, offset); + + final int templateId = headerDecoder.templateId(); + if (TEMPLATE_ID != templateId) + { + throw new IllegalStateException("Invalid TEMPLATE_ID: " + templateId); + } + + return wrap( + buffer, + offset + MessageHeaderDecoder.ENCODED_LENGTH, + headerDecoder.blockLength(), + headerDecoder.version()); + } + public int encodedLength() { return limit - offset; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 80cc4f5e47..a8d049642a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -84,6 +84,26 @@ public TokenCodecDecoder wrap( return this; } + public TokenCodecDecoder wrapAndApplyHeader( + final DirectBuffer buffer, + final int offset, + final MessageHeaderDecoder headerDecoder) + { + headerDecoder.wrap(buffer, offset); + + final int templateId = headerDecoder.templateId(); + if (TEMPLATE_ID != templateId) + { + throw new IllegalStateException("Invalid TEMPLATE_ID: " + templateId); + } + + return wrap( + buffer, + offset + MessageHeaderDecoder.ENCODED_LENGTH, + headerDecoder.blockLength(), + headerDecoder.version()); + } + public int encodedLength() { return limit - offset; From 0ae903585ce0059f88a602e8313051eb3d530e85 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 25 Feb 2021 17:23:50 +0000 Subject: [PATCH 0655/1594] [Java] Increase minor version. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 0424f834fd..2fbf9b3a48 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.21.1-SNAPSHOT \ No newline at end of file +1.22.0-SNAPSHOT \ No newline at end of file From b00119417d528582d2e7de39e72faef339d3d375 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 1 Mar 2021 13:18:12 +0000 Subject: [PATCH 0656/1594] [Java] Upgrade to JMH 1.28. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 7b82d3cfec..cd8637ac64 100644 --- a/build.gradle +++ b/build.gradle @@ -49,7 +49,7 @@ def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' def mockitoVersion = '3.8.0' def junitVersion = '5.7.1' -def jmhVersion = '1.27' +def jmhVersion = '1.28' def agronaVersion = '1.9.0' def agronaVersionRange = '[1.9,1.10[' // allow any patch release of 1.9.x @@ -74,7 +74,7 @@ def projectPom = { name = 'sbe' packaging = 'pom' description = 'FIX/SBE - OSI layer 6 presentation for encoding and decoding application messages' + - ' in binary format for low-latency applications' + ' in binary format for low-latency applications.' url = 'https://github.com/real-logic/simple-binary-encoding' scm { From 6cf590c0e25fd83dfa37ce760ab36c5a073d3953 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 4 Mar 2021 13:31:28 +0000 Subject: [PATCH 0657/1594] [Java] Upgrade to Versions 0.38.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cd8637ac64..4aa19da29c 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ plugins { id 'java-library' id 'idea' id 'com.github.johnrengelman.shadow' version '6.1.0' apply false - id "com.github.ben-manes.versions" version "0.36.0" + id "com.github.ben-manes.versions" version "0.38.0" } defaultTasks 'clean', 'build' From c0040ad79766a51cd6a5dad08db1960ab2768f9f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 5 Mar 2021 11:50:53 +0000 Subject: [PATCH 0658/1594] [Java] Remove invalid use of noexcept and fix formatting. Fixes Issue #838. --- .../real_logic/sbe/generation/cpp/CppGenerator.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 599f9149e9..4d088c45c2 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -367,7 +367,7 @@ private static void generateGroupClassHeader( formatClassName(groupName)); sb.append("\n") - .append(indent).append(" inline std::uint64_t resetCountToIndex() SBE_NOEXCEPT\n") + .append(indent).append(" inline std::uint64_t resetCountToIndex()\n") .append(indent).append(" {\n") .append(indent).append(" m_count = m_index;\n") .append(indent).append(" ").append(dimensionsClassName) @@ -379,7 +379,7 @@ private static void generateGroupClassHeader( sb.append("\n") .append(indent).append("#if __cplusplus < 201103L\n") - .append(indent).append(" template inline void forEach(Func& func)\n") + .append(indent).append(" template inline void forEach(Func &func)\n") .append(indent).append(" {\n") .append(indent).append(" while (hasNext())\n") .append(indent).append(" {\n") @@ -389,7 +389,7 @@ private static void generateGroupClassHeader( .append(indent).append(" }\n\n") .append(indent).append("#else\n") - .append(indent).append(" template inline void forEach(Func&& func)\n") + .append(indent).append(" template inline void forEach(Func &&func)\n") .append(indent).append(" {\n") .append(indent).append(" while (hasNext())\n") .append(indent).append(" {\n") @@ -1134,11 +1134,11 @@ private static CharSequence generateFileHeader( "#endif\n\n" + "#if defined(SBE_NO_BOUNDS_CHECK)\n" + - "# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)\n" + + "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (false)\n" + "#elif defined(_MSC_VER)\n" + - "# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)\n" + + "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (exp)\n" + "#else\n" + - "# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))\n" + + "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (__builtin_expect(exp,c))\n" + "#endif\n\n" + "#define SBE_NULLVALUE_INT8 (std::numeric_limits::min)()\n" + From 2d8d380d5635c90829d93075dbfa2ba526aac544 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 5 Mar 2021 11:52:28 +0000 Subject: [PATCH 0659/1594] [Java] Formatting. --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 4d088c45c2..c1e0f8478e 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1138,7 +1138,7 @@ private static CharSequence generateFileHeader( "#elif defined(_MSC_VER)\n" + "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (exp)\n" + "#else\n" + - "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (__builtin_expect(exp,c))\n" + + "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (__builtin_expect(exp, c))\n" + "#endif\n\n" + "#define SBE_NULLVALUE_INT8 (std::numeric_limits::min)()\n" + From 004455fb2d9505829739cf881687d3b04eb4b2aa Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 10 Mar 2021 12:11:33 +0000 Subject: [PATCH 0660/1594] [C++] Capture acting block length and use it with << operator. Issue #839. --- .../co/real_logic/sbe/generation/cpp/CppGenerator.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index c1e0f8478e..eac73c3af5 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1911,6 +1911,7 @@ private static CharSequence generateConstructorsAndOperators(final String classN " m_bufferLength(bufferLength),\n" + " m_offset(offset),\n" + " m_position(sbeCheckPosition(offset + actingBlockLength)),\n" + + " m_actingBlockLength(actingBlockLength),\n" + " m_actingVersion(actingVersion)\n" + " {\n" + " }\n\n" + @@ -1946,6 +1947,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final " std::uint64_t m_bufferLength = 0;\n" + " std::uint64_t m_offset = 0;\n" + " std::uint64_t m_position = 0;\n" + + " std::uint64_t m_actingBlockLength = 0;\n" + " std::uint64_t m_actingVersion = 0;\n\n" + " inline std::uint64_t *sbePositionPtr() SBE_NOEXCEPT\n" + @@ -2518,8 +2520,12 @@ private void generateDisplay( "friend std::basic_ostream & operator << (\n" + " std::basic_ostream &builder, %1$s _writer)\n" + "{\n" + - " %1$s writer(_writer.m_buffer, _writer.m_offset,\n" + - " _writer.m_bufferLength, _writer.sbeBlockLength(), _writer.m_actingVersion);\n" + + " %1$s writer(\n" + + " _writer.m_buffer,\n" + + " _writer.m_offset,\n" + + " _writer.m_bufferLength,\n" + + " _writer.m_actingBlockLength,\n" + + " _writer.m_actingVersion);\n\n" + " builder << '{';\n" + " builder << R\"(\"Name\": \"%1$s\", )\";\n" + " builder << R\"(\"sbeTemplateId\": )\";\n" + From 9212a4fd95b3208b70f742ee375c323f3695e357 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 10 Mar 2021 12:22:12 +0000 Subject: [PATCH 0661/1594] [C++] Formatting. --- sbe-tool/src/test/cpp/CodeGenTest.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index 04df822fa2..e738e28363 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -442,8 +442,7 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) MANUFACTURER_LENGTH, MODEL_LENGTH, ACTIVATION_CODE_LENGTH, - COLOR_LENGTH - ); + COLOR_LENGTH); EXPECT_EQ(sz, predictedCarSz); EXPECT_EQ(Car::isConstLength(), false); From 27cc88eddf63ade47ef256a8e8fd9451b59c8b94 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 10 Mar 2021 12:24:15 +0000 Subject: [PATCH 0662/1594] [C++] gitignore. --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ba860d57dc..2e20d39e2c 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,7 @@ out .vscode # cmake - +cmake-build-debug codecs # cpp build linux From bd2d494b2df30bcd04478c104de894be14ee84bd Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 16 Mar 2021 16:48:11 +0100 Subject: [PATCH 0663/1594] [CI] Add Java 16 GA to the test matrix. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9c9513d04..d77ab075dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '11', '15', '16-ea' ] + java: [ '8', '11', '16' ] steps: - name: Checkout code uses: actions/checkout@v2 From 4761de951e2b20260b18650730cb498b4ebb84b9 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 16 Mar 2021 17:00:02 +0100 Subject: [PATCH 0664/1594] [CI] Add Java 17-ea to the test matrix. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d77ab075dc..6779b3dbea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '11', '16' ] + java: [ '8', '11', '16', '17-ea' ] steps: - name: Checkout code uses: actions/checkout@v2 From 5a602ff16e1c410cf9de1957f2cb29d817dfad77 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 24 Mar 2021 12:53:07 +0000 Subject: [PATCH 0665/1594] [Java] Upgrade to JMH 1.29. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4aa19da29c..f17d482919 100644 --- a/build.gradle +++ b/build.gradle @@ -49,7 +49,7 @@ def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' def mockitoVersion = '3.8.0' def junitVersion = '5.7.1' -def jmhVersion = '1.28' +def jmhVersion = '1.29' def agronaVersion = '1.9.0' def agronaVersionRange = '[1.9,1.10[' // allow any patch release of 1.9.x From 4237e5292d20f9bd7e0e34569193f2fe72e61ed3 Mon Sep 17 00:00:00 2001 From: szehetner <32911487+szehetner@users.noreply.github.com> Date: Wed, 31 Mar 2021 13:15:22 +0200 Subject: [PATCH 0666/1594] ensure DirectBuffer.CheckLimit can be inlined (#840) --- csharp/sbe-dll/DirectBuffer.cs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/csharp/sbe-dll/DirectBuffer.cs b/csharp/sbe-dll/DirectBuffer.cs index d71783aff1..5f99778924 100644 --- a/csharp/sbe-dll/DirectBuffer.cs +++ b/csharp/sbe-dll/DirectBuffer.cs @@ -120,7 +120,7 @@ public int Capacity { get { return _capacity; } } - + /// /// Check that a given limit is not greater than the capacity of a buffer from a given offset. /// @@ -129,17 +129,22 @@ public void CheckLimit(int limit) { if (limit > _capacity) { - if (bufferOverflow == null) - throw new IndexOutOfRangeException(string.Format("limit={0} is beyond capacity={1}", limit, _capacity)); + TryResizeBuffer(limit); + } + } - var newBuffer = bufferOverflow(_capacity, limit); + private void TryResizeBuffer(int limit) + { + if (bufferOverflow == null) + throw new IndexOutOfRangeException(string.Format("limit={0} is beyond capacity={1}", limit, _capacity)); - if (newBuffer == null) - throw new IndexOutOfRangeException(string.Format("limit={0} is beyond capacity={1}", limit, _capacity)); + var newBuffer = bufferOverflow(_capacity, limit); - Marshal.Copy((IntPtr)_pBuffer, newBuffer, 0, _capacity); - Wrap(newBuffer); - } + if (newBuffer == null) + throw new IndexOutOfRangeException(string.Format("limit={0} is beyond capacity={1}", limit, _capacity)); + + Marshal.Copy((IntPtr)_pBuffer, newBuffer, 0, _capacity); + Wrap(newBuffer); } /// From 2012cd1e6f0ac2645cffc2a917cccab5073c03f5 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 31 Mar 2021 12:18:24 +0100 Subject: [PATCH 0667/1594] [C#] Clean up script. --- csharp/sbe-dll/README.txt | 2 +- csharp/sbe-dll/sbe-tool.sh | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/csharp/sbe-dll/README.txt b/csharp/sbe-dll/README.txt index c68e9e5c3d..7a1cdf0ced 100644 --- a/csharp/sbe-dll/README.txt +++ b/csharp/sbe-dll/README.txt @@ -62,5 +62,5 @@ To get all the details please refer to our wiki (https://github.com/real-logic/s - schema definition: https://github.com/real-logic/simple-binary-encoding/wiki/FIX-SBE-XML-Primer - SBE Tool command line: https://github.com/real-logic/simple-binary-encoding/wiki/Sbe-Tool-Guide - If you face an issue, a suggestion or a question, please use the issue tracker on the main GitHub repo: https://github.com/real-logic/simple-binary-encoding/issues?state=open +If you face an issue, a suggestion or a question, please use the issue tracker on the main GitHub repo: https://github.com/real-logic/simple-binary-encoding/issues?state=open diff --git a/csharp/sbe-dll/sbe-tool.sh b/csharp/sbe-dll/sbe-tool.sh index d2fcf8c7f3..99ea957e46 100644 --- a/csharp/sbe-dll/sbe-tool.sh +++ b/csharp/sbe-dll/sbe-tool.sh @@ -1,42 +1,42 @@ #! /usr/bin/env bash -ROOTDIR=`dirname $0` -SBE_JAR=$ROOTDIR/sbe-tool-all.jar +ROOTDIR=$(dirname ${0}) +SBE_JAR=${ROOTDIR}/sbe-tool-all.jar -[ -f "$SBE_JAR" ] || (echo "Missing $SBE_JAR"; exit 1) +[ -f "${SBE_JAR}" ] || (echo "Missing ${SBE_JAR}"; exit 1) function usage { - echo usage: $(basename "$0") [-d output_dir] -s schema + echo usage: $(basename "${0}") [-d output_dir] -s schema } # defaults OUTPUTDIR=. while getopts "d:s:" OPT "$@"; do - case $OPT in + case ${OPT} in d) - OUTPUTDIR=$OPTARG + OUTPUTDIR=${OPTARG} ;; s) - SCHEMA=$OPTARG + SCHEMA=${OPTARG} ;; *) - echo "$OPT" + echo "${OPT}" usage exit 1 ;; esac done -shift $(($OPTIND - 1)) +shift $((${OPTIND} - 1)) # Check args -if [ -z "$SCHEMA" ]; then usage; exit 1; fi -if [ ! -f "$SCHEMA" ]; then echo no schema at "$SCHEMA"; exit 1; fi +if [ -z "${SCHEMA}" ]; then usage; exit 1; fi +if [ ! -f "${SCHEMA}" ]; then echo no schema at "${SCHEMA}"; exit 1; fi java \ --Dsbe.output.dir="$OUTPUTDIR" \ +-Dsbe.output.dir="${OUTPUTDIR}" \ -Dsbe.generate.ir="false" \ -Dsbe.target.language="uk.co.real_logic.sbe.generation.csharp.CSharp" \ --jar "$SBE_JAR" \ -"$SCHEMA" +-jar "${SBE_JAR}" \ +"${SCHEMA}" From e9338e3b3c2d92532f5714c82a2b5cc14b7ef969 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 31 Mar 2021 12:23:59 +0100 Subject: [PATCH 0668/1594] [C#] Avoid use of string.Format in DirectBuffer. --- csharp/sbe-dll/DirectBuffer.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/csharp/sbe-dll/DirectBuffer.cs b/csharp/sbe-dll/DirectBuffer.cs index 5f99778924..73245532ac 100644 --- a/csharp/sbe-dll/DirectBuffer.cs +++ b/csharp/sbe-dll/DirectBuffer.cs @@ -136,12 +136,16 @@ public void CheckLimit(int limit) private void TryResizeBuffer(int limit) { if (bufferOverflow == null) - throw new IndexOutOfRangeException(string.Format("limit={0} is beyond capacity={1}", limit, _capacity)); + { + throw new IndexOutOfRangeException("limit=" + limit + " is beyond capacity=" + _capacity)); + } var newBuffer = bufferOverflow(_capacity, limit); if (newBuffer == null) - throw new IndexOutOfRangeException(string.Format("limit={0} is beyond capacity={1}", limit, _capacity)); + { + throw new IndexOutOfRangeException("limit=" + limit + " is beyond capacity=" + _capacity)); + } Marshal.Copy((IntPtr)_pBuffer, newBuffer, 0, _capacity); Wrap(newBuffer); @@ -671,7 +675,9 @@ public void Dispose() private void Dispose(bool disposing) { if (_disposed) + { return; + } FreeGCHandle(); From 60b0fd7421a1e6e998edd2c3f7dff3a7148dcc09 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 31 Mar 2021 12:26:43 +0100 Subject: [PATCH 0669/1594] [C#] Fix typo with extra bracket. --- csharp/sbe-dll/DirectBuffer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/sbe-dll/DirectBuffer.cs b/csharp/sbe-dll/DirectBuffer.cs index 73245532ac..e8ef4c012e 100644 --- a/csharp/sbe-dll/DirectBuffer.cs +++ b/csharp/sbe-dll/DirectBuffer.cs @@ -137,14 +137,14 @@ private void TryResizeBuffer(int limit) { if (bufferOverflow == null) { - throw new IndexOutOfRangeException("limit=" + limit + " is beyond capacity=" + _capacity)); + throw new IndexOutOfRangeException("limit=" + limit + " is beyond capacity=" + _capacity); } var newBuffer = bufferOverflow(_capacity, limit); if (newBuffer == null) { - throw new IndexOutOfRangeException("limit=" + limit + " is beyond capacity=" + _capacity)); + throw new IndexOutOfRangeException("limit=" + limit + " is beyond capacity=" + _capacity); } Marshal.Copy((IntPtr)_pBuffer, newBuffer, 0, _capacity); From 24c956dffbb2d9f1387e60c41ccf769f71fcdb89 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 2 Apr 2021 15:19:13 +0100 Subject: [PATCH 0670/1594] Add build options to build script. --- cppbuild/cppbuild | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/cppbuild/cppbuild b/cppbuild/cppbuild index 1b74d834e7..9979f7e2d9 100755 --- a/cppbuild/cppbuild +++ b/cppbuild/cppbuild @@ -2,6 +2,7 @@ SOURCE_DIR="$(pwd)" BUILD_DIR="${SOURCE_DIR}/cppbuild/Release" +EXTRA_CMAKE_ARGS="" ncpus=1 case "$(uname)" in @@ -13,6 +14,43 @@ case "$(uname)" in ;; esac +while [[ $# -gt 0 ]] +do + option="${1}" + case ${option} in + --c-warnings-as-errors) + EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DC_WARNINGS_AS_ERRORS=ON" + echo "Enabling warnings as errors for C" + shift + ;; + --cxx-warnings-as-errors) + EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DCXX_WARNINGS_AS_ERRORS=ON" + echo "Enabling warnings as errors for C++" + shift + ;; + -d|--debug-build) + EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=Debug" + export BUILD_DIR="${SOURCE_DIR}/cppbuild/Debug" + export BUILD_CONFIG=Debug + shift + ;; + --sanitise-build) + EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DSANITISE_BUILD=ON" + echo "Enabling sanitise build" + shift + ;; + -h|--help) + echo "${0} [--c-warnings-as-errors] [--cxx-warnings-as-errors] [--debug-build] [--sanitise-build]" + exit + ;; + *) + echo "Unknown option ${option}" + echo "Use --help for help" + exit + ;; + esac +done + echo "Will make with \"-j ${ncpus}\"." if [ -d "${BUILD_DIR}" ] ; then @@ -23,4 +61,4 @@ fi mkdir -p "${BUILD_DIR}" cd "${BUILD_DIR}" || exit -(cmake -G "Unix Makefiles" "${SOURCE_DIR}" && make clean && make -j ${ncpus} all && ctest -C Release --output-on-failure) +(cmake -G "Unix Makefiles" ${EXTRA_CMAKE_ARGS} "${SOURCE_DIR}" && make clean && make -j ${ncpus} all && ctest -C Release --output-on-failure) From 448c45bf1392ceb0704bb20b9acc802bb5040447 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 2 Apr 2021 15:52:29 +0100 Subject: [PATCH 0671/1594] [C++] Warnings and consistency cleanup. --- sbe-benchmarks/src/main/cpp/CarBench.cpp | 11 ++-- .../src/main/cpp/MarketDataBench.cpp | 9 +-- sbe-benchmarks/src/main/cpp/benchlet-main.cpp | 4 +- sbe-benchmarks/src/main/cpp/benchlet.h | 66 +++++++++---------- sbe-samples/src/main/cpp/OtfExample.cpp | 6 +- sbe-tool/src/test/cpp/BoundsCheckTest.cpp | 4 +- .../src/test/cpp/CompositeOffsetsIrTest.cpp | 4 +- sbe-tool/src/test/cpp/Issue835Test.cpp | 4 +- 8 files changed, 54 insertions(+), 54 deletions(-) diff --git a/sbe-benchmarks/src/main/cpp/CarBench.cpp b/sbe-benchmarks/src/main/cpp/CarBench.cpp index fd33ba06ae..5e8c42c8e4 100644 --- a/sbe-benchmarks/src/main/cpp/CarBench.cpp +++ b/sbe-benchmarks/src/main/cpp/CarBench.cpp @@ -16,29 +16,30 @@ #include "benchlet.h" #include "SbeCarCodecBench.h" -#define MAX_CAR_BUFFER (1000*1000) +#define MAX_CAR_BUFFER (1000 * 1000) #define MAX_N 10 class SbeCarBench : public Benchmark { public: - virtual void setUp(void) + void setUp() override { buffer_ = new char[MAX_CAR_BUFFER]; bench_.runEncode(buffer_, MAX_N, MAX_CAR_BUFFER); // set buffer up for decoding runs std::cout << "MAX N = " << MAX_N << " [for Multiple runs]" << std::endl; }; - virtual void tearDown(void) + void tearDown() override { delete[] buffer_; }; SbeCarCodecBench bench_; - char *buffer_; + char *buffer_ = nullptr; }; -static struct Benchmark::Config cfg[] = { +static struct Benchmark::Config cfg[] = +{ { Benchmark::ITERATIONS, "1000000" }, { Benchmark::BATCHES, "20" } }; diff --git a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp index fd0cd221a5..75cd518b9c 100644 --- a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp +++ b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp @@ -21,22 +21,23 @@ class SbeMarketDataBench : public Benchmark { public: - virtual void setUp(void) + void setUp() override { buffer_ = new char[MAX_MD_BUFFER]; bench_.runEncode(buffer_, MAX_MD_BUFFER); // set buffer up for decoding runs }; - virtual void tearDown(void) + void tearDown() override { delete[] buffer_; }; SbeMarketDataCodecBench bench_; - char *buffer_; + char *buffer_ = nullptr; }; -static struct Benchmark::Config cfg[] = { +static struct Benchmark::Config cfg[] = +{ { Benchmark::ITERATIONS, "10000000" }, { Benchmark::BATCHES, "20" } }; diff --git a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp index 3515ce1b31..0fcddad03c 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp +++ b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp @@ -23,7 +23,7 @@ int main(int argc, char **argv) #ifdef _WIN32 #include -uint64_t BenchmarkRunner::currentTimestamp(void) +uint64_t BenchmarkRunner::currentTimestamp() { static LARGE_INTEGER freq; static int first = 1; @@ -35,7 +35,7 @@ uint64_t BenchmarkRunner::currentTimestamp(void) ::QueryPerformanceFrequency(&freq); first = 0; } - return (1000000000 * counter.QuadPart)/freq.QuadPart; + return (1000000000 * counter.QuadPart) / freq.QuadPart; } #endif \ No newline at end of file diff --git a/sbe-benchmarks/src/main/cpp/benchlet.h b/sbe-benchmarks/src/main/cpp/benchlet.h index 351c3e3dc6..948b025e96 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet.h +++ b/sbe-benchmarks/src/main/cpp/benchlet.h @@ -17,10 +17,10 @@ #define _BENCHLET_HPP #define __STDC_LIMIT_MACROS 1 -#include -#include -#include -#include +#include +#include +#include +#include #if defined(Darwin) # include @@ -59,40 +59,40 @@ class Benchmark const char *value; }; - virtual void setUp(void) {}; - virtual void tearDown(void) {}; + virtual void setUp() {}; + virtual void tearDown() {}; virtual uint64_t run(int iterations) = 0; void name(const char *name) { name_ = name; }; - const char *name(void ) const { return name_; }; + const char *name() const { return name_; }; void runName(const char *runName) { runName_ = runName; }; - const char *runName(void ) const { return runName_; }; + const char *runName() const { return runName_; }; void iterations(const unsigned int i) { iterations_ = i; }; - unsigned int iterations(void) const { return iterations_; }; + unsigned int iterations() const { return iterations_; }; void batches(const unsigned int i) { batches_ = i; }; - unsigned int batches(void) const { return batches_; }; + unsigned int batches() const { return batches_; }; void config(const struct Config *cfg, unsigned int numConfigs) { config_ = cfg; numConfigs_ = numConfigs; }; - const struct Config *config(void) const { return config_; }; - unsigned int numConfigs(void) const { return numConfigs_; }; + const struct Config *config() const { return config_; }; + unsigned int numConfigs() const { return numConfigs_; }; void stats(uint64_t *stats) { stats_ = stats; }; - uint64_t *stats(void) { return stats_; }; + uint64_t *stats() { return stats_; }; void retainStats(bool retain) { retainStats_ = retain; }; - bool retainStats(void) const { return retainStats_; }; + bool retainStats() const { return retainStats_; }; private: - const char *name_; - const char *runName_; - unsigned int iterations_; - unsigned int batches_; - const struct Config *config_; - unsigned int numConfigs_; - uint64_t *stats_; - bool retainStats_; + const char *name_ = nullptr; + const char *runName_ = nullptr; + unsigned int iterations_ = 0; + unsigned int batches_ = 0; + const struct Config *config_ = nullptr; + unsigned int numConfigs_ = 0; + uint64_t *stats_ = nullptr; + bool retainStats_ = false; // save start time, etc. }; @@ -134,7 +134,7 @@ class BenchmarkRunner return impl; }; - static void run(void) + static void run() { for (std::vector::iterator it = table().begin(); it != table().end(); ++it) { @@ -175,7 +175,7 @@ class BenchmarkRunner } }; - static std::vector &table(void) + static std::vector &table() { static std::vector table; return table; @@ -199,9 +199,9 @@ class BenchmarkRunner return (end_timestamp - start_timestamp) * timebaseInfo.numer / timebaseInfo.denom; }; #elif defined(__linux__) - static uint64_t currentTimestamp(void) + static uint64_t currentTimestamp() { - struct timespec ts; + struct timespec ts = {}; clock_gettime(CLOCK_REALTIME, &ts); return ts.tv_sec * 1000000000 + ts.tv_nsec; @@ -223,15 +223,13 @@ class BenchmarkRunner template uint64_t runBenchmark(C *obj, int iterations) { - uint64_t start, end; - int i = 0; - - start = BenchmarkRunner::currentTimestamp(); - for (; i < iterations; i++) + uint64_t start = BenchmarkRunner::currentTimestamp(); + for (int i = 0; i < iterations; i++) { obj->benchmarkBody(); } - end = BenchmarkRunner::currentTimestamp(); + uint64_t end = BenchmarkRunner::currentTimestamp(); + return BenchmarkRunner::elapsedNanoseconds(start, end); } @@ -242,12 +240,12 @@ uint64_t runBenchmark(C *obj, int iterations) public: \ BENCHMARK_CLASS_NAME(c,r)() {}; \ virtual uint64_t run(int iterations) { return runBenchmark(this, iterations); }; \ - void benchmarkBody(void); \ + void benchmarkBody(); \ private: \ static Benchmark *instance_; \ }; \ Benchmark *BENCHMARK_CLASS_NAME(c,r)::instance_ = BenchmarkRunner::registerBenchmark(#c, #r, new BENCHMARK_CLASS_NAME(c,r)(), i, sizeof(i)/sizeof(Benchmark::Config)); \ - void BENCHMARK_CLASS_NAME(c,r)::benchmarkBody(void) + void BENCHMARK_CLASS_NAME(c,r)::benchmarkBody() #define BENCHMARK_ITERATIONS(c,r,i) \ struct Benchmark::Config c ## r ## _cfg[] = {{Benchmark::ITERATIONS, #i},{Benchmark::BATCHES, DEFAULT_BATCHES_STRING}}; \ diff --git a/sbe-samples/src/main/cpp/OtfExample.cpp b/sbe-samples/src/main/cpp/OtfExample.cpp index bb1f3c4988..ef2df6d891 100644 --- a/sbe-samples/src/main/cpp/OtfExample.cpp +++ b/sbe-samples/src/main/cpp/OtfExample.cpp @@ -39,9 +39,9 @@ class ExampleTokenListener void printScope() const { std::for_each(scope.begin(), scope.end(), - [&](const std::string &scope) + [&](const std::string &s) { - std::cout << scope; + std::cout << s; }); } @@ -425,7 +425,7 @@ std::uint64_t encodeHdrAndCar(char *buffer, std::uint64_t length) int main(int argc, char **argv) { - char buffer[2048]; + char buffer[2048] = {}; ExampleTokenListener tokenListener; std::uint64_t sz = encodeHdrAndCar(buffer, sizeof(buffer)); diff --git a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp index 3cd1a22ca5..6924088137 100644 --- a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp @@ -180,7 +180,7 @@ class BoundsCheckTest : public testing::Test std::uint64_t decodeCarFuelFigures() { - char tmp[256]; + char tmp[256] = {}; Car::FuelFigures &fuelFigures = m_carDecoder.fuelFigures(); EXPECT_EQ(fuelFigures.count(), 3u); @@ -260,7 +260,7 @@ class BoundsCheckTest : public testing::Test std::uint64_t decodeCarManufacturerModelAndActivationCode() { - char tmp[256]; + char tmp[256] = {}; EXPECT_EQ(m_carDecoder.getManufacturer(tmp, sizeof(tmp)), 5u); EXPECT_EQ(std::string(tmp, 5), "Honda"); diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp index 879ab2bde3..3e4ad3abc4 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp @@ -40,8 +40,8 @@ class CompositeOffsetsIrTest : public testing::Test, public OtfMessageDecoder::B std::uint64_t encodeHdrAndMsg() { - MessageHeader hdr = {}; - TestMessage1 msg = {}; + MessageHeader hdr; + TestMessage1 msg; hdr.wrap(m_buffer, 0, 0, sizeof(m_buffer)) .blockLength(TestMessage1::sbeBlockLength()) diff --git a/sbe-tool/src/test/cpp/Issue835Test.cpp b/sbe-tool/src/test/cpp/Issue835Test.cpp index 068519c0c2..820fd42f32 100644 --- a/sbe-tool/src/test/cpp/Issue835Test.cpp +++ b/sbe-tool/src/test/cpp/Issue835Test.cpp @@ -32,7 +32,7 @@ TEST_F(Issue835Test, shouldCompileWithSkipper) const std::uint64_t timeNs = 777; const std::size_t offset = 0; char buffer[BUFFER_LEN] = {}; - MDIncrementalRefreshOrderBook47 encoder = {}; + MDIncrementalRefreshOrderBook47 encoder; encoder .wrapForEncode(buffer, offset, BUFFER_LEN) @@ -60,7 +60,7 @@ TEST_F(Issue835Test, shouldCompileWithSkipper) entries.mDUpdateAction(MDUpdateAction::Value::New); entries.mDEntryType(MDEntryTypeBook::Value::Offer); - MDIncrementalRefreshOrderBook47 decoder = {}; + MDIncrementalRefreshOrderBook47 decoder; decoder.wrapForDecode( buffer, offset, From fc54b03248275f38a86409bae15f204795a58f8e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 2 Apr 2021 17:22:45 +0100 Subject: [PATCH 0672/1594] [CI] Fix macos schema violation. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6779b3dbea..dfdd921125 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -167,7 +167,7 @@ jobs: cpp-clang-macos-build: name: C++ Xcode ${{ matrix.version }} (macOS) - runs-on: macOS-latest + runs-on: macos-latest strategy: fail-fast: false env: From 28514717602dc7b91cab70f708a5c3d4817b175d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 2 Apr 2021 17:26:59 +0100 Subject: [PATCH 0673/1594] [C#] Fix script warnings. --- csharp/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/build.sh b/csharp/build.sh index 82b872690c..8e6bef9384 100755 --- a/csharp/build.sh +++ b/csharp/build.sh @@ -1,7 +1,7 @@ #!/bin/bash DIR="$(dirname "${BASH_SOURCE[0]}")" -cd $DIR +cd "${DIR}" || exit (cd ../ && ./gradlew generateCSharpCodecs) dotnet build -c debug dotnet build -c release From 7ebb222bae92c374f0181828ba08ccb742053700 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 2 Apr 2021 17:28:23 +0100 Subject: [PATCH 0674/1594] [C#] Fix script warnings. --- csharp/pack.sh | 2 +- csharp/runtests.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/pack.sh b/csharp/pack.sh index 421cf256fc..22477952c6 100755 --- a/csharp/pack.sh +++ b/csharp/pack.sh @@ -1,5 +1,5 @@ #!/bin/bash DIR="$(dirname "${BASH_SOURCE[0]}")" -cd $DIR +cd "${DIR}" || exit (cd .. && ./gradlew build) (cd sbe-dll && dotnet pack -c release -o ../nuget) diff --git a/csharp/runtests.sh b/csharp/runtests.sh index 4a1d539a50..f058e483b1 100755 --- a/csharp/runtests.sh +++ b/csharp/runtests.sh @@ -1,5 +1,5 @@ #!/bin/bash DIR="$(dirname "${BASH_SOURCE[0]}")" -cd $DIR +cd "${DIR}" || exit (cd ../; ./gradlew runExampleUsingGeneratedStub -Dsbe.encoding.filename=csharp/sbe-tests/ExampleUsingGeneratedStub.sbe) (cd sbe-tests && dotnet test) From 13a200009a3a42d8f8c88e1460c7e76d004f0a7b Mon Sep 17 00:00:00 2001 From: szehetner <32911487+szehetner@users.noreply.github.com> Date: Fri, 2 Apr 2021 18:38:12 +0200 Subject: [PATCH 0675/1594] [C#] convert benchmarks to BenchmarkDotNet (#841) --- .../Bench/SBE/BenchmarkState.cs | 47 ---- .../sbe-benchmarks/Bench/SBE/CarBenchmark.cs | 205 ++++++++++++++++++ .../Bench/SBE/MarketDataBenchmark.cs | 82 ++++--- .../Bench/SBE/SbePerfTestRunner.cs | 63 ------ csharp/sbe-benchmarks/Program.cs | 31 +-- csharp/sbe-benchmarks/sbe-benchmarks.csproj | 6 +- 6 files changed, 265 insertions(+), 169 deletions(-) delete mode 100644 csharp/sbe-benchmarks/Bench/SBE/BenchmarkState.cs create mode 100644 csharp/sbe-benchmarks/Bench/SBE/CarBenchmark.cs delete mode 100644 csharp/sbe-benchmarks/Bench/SBE/SbePerfTestRunner.cs diff --git a/csharp/sbe-benchmarks/Bench/SBE/BenchmarkState.cs b/csharp/sbe-benchmarks/Bench/SBE/BenchmarkState.cs deleted file mode 100644 index e82c8ac27d..0000000000 --- a/csharp/sbe-benchmarks/Bench/SBE/BenchmarkState.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Org.SbeTool.Sbe.Dll; -using Uk.Co.Real_logic.Sbe.Benchmarks.Fix; - -namespace Org.SbeTool.Sbe.Benchmarks -{ - public class BenchmarkState - { - private readonly byte[] _eBuffer = new byte[1024]; - private readonly byte[] _dBuffer = new byte[1024]; - private readonly DirectBuffer _encodeBuffer; - private readonly DirectBuffer _decodeBuffer; - private readonly MarketDataIncrementalRefreshTrades _marketData = new MarketDataIncrementalRefreshTrades(); - private readonly MessageHeader _messageHeader = new MessageHeader(); - - public int BufferIndex - { - get { return 0; } - } - - public BenchmarkState() - { - _encodeBuffer = new DirectBuffer(_eBuffer); - _decodeBuffer = new DirectBuffer(_dBuffer); - MarketDataBenchmark.Encode(_messageHeader, _marketData, _decodeBuffer, BufferIndex); - } - - public DirectBuffer EncodeBuffer - { - get { return _encodeBuffer; } - } - - public DirectBuffer DecodeBuffer - { - get { return _decodeBuffer; } - } - - public MarketDataIncrementalRefreshTrades MarketData - { - get { return _marketData; } - } - - public MessageHeader MessageHeader - { - get { return _messageHeader; } - } - } -} \ No newline at end of file diff --git a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark.cs b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark.cs new file mode 100644 index 0000000000..d0ba027173 --- /dev/null +++ b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark.cs @@ -0,0 +1,205 @@ +using System.Text; +using Baseline; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Diagnosers; +using Org.SbeTool.Sbe.Dll; + +namespace Org.SbeTool.Sbe.Benchmarks.Bench.Benchmarks +{ + [MemoryDiagnoser] + public class CarBenchmark + { + // string values are deliberately encoded outside of the benchmark + private static readonly byte[] VehicleCode = Encoding.GetEncoding(Car.VehicleCodeCharacterEncoding).GetBytes("CODE12"); + private static readonly byte[] ManufacturerCode = Encoding.GetEncoding(Engine.ManufacturerCodeCharacterEncoding).GetBytes("123"); + private static readonly byte[] Manufacturer = Encoding.GetEncoding(Car.ManufacturerCharacterEncoding).GetBytes("Honda"); + private static readonly byte[] Model = Encoding.GetEncoding(Car.ModelCharacterEncoding).GetBytes("Civic VTi"); + private static readonly byte[] ActivationCode = Encoding.GetEncoding(Car.ActivationCodeCharacterEncoding).GetBytes("code"); + private static readonly byte[] UrbanCycle = Encoding.GetEncoding(Car.FuelFiguresGroup.UsageDescriptionCharacterEncoding).GetBytes("Urban Cycle"); + private static readonly byte[] CombinedCycle = Encoding.GetEncoding(Car.FuelFiguresGroup.UsageDescriptionCharacterEncoding).GetBytes("Combined Cycle"); + private static readonly byte[] HighwayCycle = Encoding.GetEncoding(Car.FuelFiguresGroup.UsageDescriptionCharacterEncoding).GetBytes("Highway Cycle"); + + private readonly byte[] _eBuffer = new byte[1024]; + private readonly byte[] _dBuffer = new byte[1024]; + private DirectBuffer _encodeBuffer; + private DirectBuffer _decodeBuffer; + private readonly Car _car = new Car(); + private readonly MessageHeader _messageHeader = new MessageHeader(); + + [GlobalSetup] + public void Setup() + { + _encodeBuffer = new DirectBuffer(_eBuffer); + _decodeBuffer = new DirectBuffer(_dBuffer); + Encode(_car, _decodeBuffer, 0); + } + + [Benchmark] + public int Encode() + { + return Encode(_car, _encodeBuffer, 0); + } + + [Benchmark] + public int Decode() + { + return Decode(_car, _decodeBuffer, 0); + } + + public int Encode(Car car, DirectBuffer directBuffer, int bufferOffset) + { + _car.WrapForEncodeAndApplyHeader(directBuffer, bufferOffset, _messageHeader); + + const int srcOffset = 0; + + car.SerialNumber = 1234; + car.ModelYear = 2013; + car.Available = BooleanType.T; + car.Code = Baseline.Model.A; + car.SetVehicleCode(VehicleCode, srcOffset); + + for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) + { + car.SetSomeNumbers(i, (uint)i); + } + + car.Extras = OptionalExtras.CruiseControl | OptionalExtras.SportsPack; + car.Engine.Capacity = 2000; + car.Engine.NumCylinders = 4; + car.Engine.SetManufacturerCode(ManufacturerCode, srcOffset); + car.Engine.Efficiency = 35; + car.Engine.BoosterEnabled = BooleanType.T; + car.Engine.Booster.BoostType = BoostType.NITROUS; + car.Engine.Booster.HorsePower = 200; + + var fuelFigures = car.FuelFiguresCount(3); + fuelFigures.Next(); + fuelFigures.Speed = 30; + fuelFigures.Mpg = 35.9f; + fuelFigures.SetUsageDescription(UrbanCycle); + + fuelFigures.Next(); + fuelFigures.Speed = 55; + fuelFigures.Mpg = 49.0f; + fuelFigures.SetUsageDescription(CombinedCycle); + + fuelFigures.Next(); + fuelFigures.Speed = 75; + fuelFigures.Mpg = 40.0f; + fuelFigures.SetUsageDescription(HighwayCycle); + + + Car.PerformanceFiguresGroup perfFigures = car.PerformanceFiguresCount(2); + perfFigures.Next(); + perfFigures.OctaneRating = 95; + + Car.PerformanceFiguresGroup.AccelerationGroup acceleration = perfFigures.AccelerationCount(3).Next(); + acceleration.Mph = 30; + acceleration.Seconds = 4.0f; + + acceleration.Next(); + acceleration.Mph = 60; + acceleration.Seconds = 7.5f; + + acceleration.Next(); + acceleration.Mph = 100; + acceleration.Seconds = 12.2f; + + perfFigures.Next(); + perfFigures.OctaneRating = 99; + acceleration = perfFigures.AccelerationCount(3).Next(); + + acceleration.Mph = 30; + acceleration.Seconds = 3.8f; + + acceleration.Next(); + acceleration.Mph = 60; + acceleration.Seconds = 7.1f; + + acceleration.Next(); + acceleration.Mph = 100; + acceleration.Seconds = 11.8f; + + car.SetManufacturer(Manufacturer, srcOffset, Manufacturer.Length); + car.SetModel(Model, srcOffset, Model.Length); + car.SetActivationCode(ActivationCode, srcOffset, ActivationCode.Length); + + return car.Size; + } + + private readonly byte[] _buffer = new byte[128]; + + public int Decode(Car car, DirectBuffer directBuffer, int bufferOffset) + { + _messageHeader.Wrap(directBuffer, bufferOffset, 0); + + car.WrapForDecode(directBuffer, bufferOffset + MessageHeader.Size, _messageHeader.BlockLength, _messageHeader.Version); + + var templateId = Car.TemplateId; + var schemaVersion = Car.SchemaVersion; + var serialNumber = car.SerialNumber; + var modelYear = car.ModelYear; + var available = car.Available; + var code = car.Code; + + for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) + { + var number = car.GetSomeNumbers(i); + } + + // strings are not actually decoded, only copied out into a buffer + car.GetVehicleCode(_buffer, 0); + + OptionalExtras extras = car.Extras; + var cruiseControl = (extras & OptionalExtras.CruiseControl) == OptionalExtras.CruiseControl; + var sportsPack = (extras & OptionalExtras.SportsPack) == OptionalExtras.SportsPack; + var sunRoof = (extras & OptionalExtras.SunRoof) == OptionalExtras.SunRoof; + + Engine engine = car.Engine; + var capacity = engine.Capacity; + var numCylinders = engine.NumCylinders; + var maxRpm = engine.MaxRpm; + for (int i = 0, size = Engine.ManufacturerCodeLength; i < size; i++) + { + engine.GetManufacturerCode(i); + } + + int length = engine.GetFuel(_buffer, 0, _buffer.Length); + + var efficiency = engine.Efficiency; + var boosterEnabled = engine.BoosterEnabled; + var boostType = engine.Booster.BoostType; + var horsePower = engine.Booster.HorsePower; + + var fuelFiguresGroup = car.FuelFigures; + while (fuelFiguresGroup.HasNext) + { + var fuelFigures = fuelFiguresGroup.Next(); + var speed = fuelFigures.Speed; + var mpg = fuelFigures.Mpg; + fuelFigures.GetUsageDescription(_buffer, 0, _buffer.Length); + } + + var performanceFiguresGroup = car.PerformanceFigures; + while (performanceFiguresGroup.HasNext) + { + performanceFiguresGroup.Next(); + var octanceRating = performanceFiguresGroup.OctaneRating; + + var accelerationGroup = performanceFiguresGroup.Acceleration; + for (int i = 0; i < accelerationGroup.Count; i++) + { + var acceleration = accelerationGroup.Next(); + var mpg = acceleration.Mph; + var seconds = acceleration.Seconds; + } + } + + length = car.GetManufacturer(_buffer, 0, _buffer.Length); + length = car.GetModel(_buffer, 0, _buffer.Length); + length = car.GetActivationCode(_buffer, 0, _buffer.Length); + + return car.Size; + } + } +} diff --git a/csharp/sbe-benchmarks/Bench/SBE/MarketDataBenchmark.cs b/csharp/sbe-benchmarks/Bench/SBE/MarketDataBenchmark.cs index 5797fbb493..79be30bf68 100644 --- a/csharp/sbe-benchmarks/Bench/SBE/MarketDataBenchmark.cs +++ b/csharp/sbe-benchmarks/Bench/SBE/MarketDataBenchmark.cs @@ -1,27 +1,48 @@ -using Org.SbeTool.Sbe.Dll; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Diagnosers; +using Org.SbeTool.Sbe.Dll; using Uk.Co.Real_logic.Sbe.Benchmarks.Fix; namespace Org.SbeTool.Sbe.Benchmarks { - public static class MarketDataBenchmark + [MemoryDiagnoser] + public class MarketDataBenchmark { - public static int Encode(MessageHeader messageHeader, - MarketDataIncrementalRefreshTrades marketData, - DirectBuffer buffer, - int bufferIndex) + private readonly byte[] _eBuffer = new byte[1024]; + private readonly byte[] _dBuffer = new byte[1024]; + private DirectBuffer _encodeBuffer; + private DirectBuffer _decodeBuffer; + private readonly MarketDataIncrementalRefreshTrades _marketData = new MarketDataIncrementalRefreshTrades(); + private readonly MessageHeader _messageHeader = new MessageHeader(); + + [GlobalSetup] + public void Setup() + { + _encodeBuffer = new DirectBuffer(_eBuffer); + _decodeBuffer = new DirectBuffer(_dBuffer); + Encode(_decodeBuffer, 0); + } + + [Benchmark] + public int Encode() + { + return Encode(_encodeBuffer, 0); + } + + public int Encode(DirectBuffer buffer, int bufferOffset) { - messageHeader.Wrap(buffer, bufferIndex, 0); - messageHeader.BlockLength = MarketDataIncrementalRefreshTrades.BlockLength; - messageHeader.TemplateId = MarketDataIncrementalRefreshTrades.TemplateId; - messageHeader.SchemaId = MarketDataIncrementalRefreshTrades.SchemaId; - messageHeader.Version = MarketDataIncrementalRefreshTrades.SchemaVersion; + _messageHeader.Wrap(buffer, bufferOffset, 0); + _messageHeader.BlockLength = MarketDataIncrementalRefreshTrades.BlockLength; + _messageHeader.TemplateId = MarketDataIncrementalRefreshTrades.TemplateId; + _messageHeader.SchemaId = MarketDataIncrementalRefreshTrades.SchemaId; + _messageHeader.Version = MarketDataIncrementalRefreshTrades.SchemaVersion; - marketData.WrapForEncode(buffer, bufferIndex + MessageHeader.Size); - marketData.TransactTime = 1234L; - marketData.EventTimeDelta = 987; - marketData.MatchEventIndicator = MatchEventIndicator.END_EVENT; + _marketData.WrapForEncode(buffer, bufferOffset + MessageHeader.Size); + _marketData.TransactTime = 1234L; + _marketData.EventTimeDelta = 987; + _marketData.MatchEventIndicator = MatchEventIndicator.END_EVENT; - var mdIncGrp = marketData.MdIncGrpCount(2); + var mdIncGrp = _marketData.MdIncGrpCount(2); mdIncGrp.Next(); mdIncGrp.TradeId = 1234L; @@ -43,25 +64,28 @@ public static int Encode(MessageHeader messageHeader, mdIncGrp.RptSeq = 1; mdIncGrp.AggressorSide = Side.SELL; - return marketData.Size; + return _marketData.Size; + } + + [Benchmark] + public int Decode() + { + return Decode(_decodeBuffer, 0); } - public static int Decode(MessageHeader messageHeader, - MarketDataIncrementalRefreshTrades marketData, - DirectBuffer buffer, - int bufferIndex) + public int Decode(DirectBuffer buffer, int bufferOffset) { - messageHeader.Wrap(buffer, bufferIndex, 0); + _messageHeader.Wrap(buffer, bufferOffset, 0); - int actingVersion = messageHeader.Version; - int actingBlockLength = messageHeader.BlockLength; + int actingVersion = _messageHeader.Version; + int actingBlockLength = _messageHeader.BlockLength; - marketData.WrapForDecode(buffer, bufferIndex + MessageHeader.Size, actingBlockLength, actingVersion); + _marketData.WrapForDecode(buffer, bufferOffset + MessageHeader.Size, actingBlockLength, actingVersion); - var transactTime = marketData.TransactTime; - var matchEventIndicator = marketData.MatchEventIndicator; + var transactTime = _marketData.TransactTime; + var matchEventIndicator = _marketData.MatchEventIndicator; - var mdIncGrpGroup = marketData.MdIncGrp; + var mdIncGrpGroup = _marketData.MdIncGrp; while (mdIncGrpGroup.HasNext) { mdIncGrpGroup.Next(); @@ -76,7 +100,7 @@ public static int Decode(MessageHeader messageHeader, var mdEntryType = mdIncGrpGroup.MdEntryType; } - return marketData.Size; + return _marketData.Size; } } } \ No newline at end of file diff --git a/csharp/sbe-benchmarks/Bench/SBE/SbePerfTestRunner.cs b/csharp/sbe-benchmarks/Bench/SBE/SbePerfTestRunner.cs deleted file mode 100644 index 5f0b79e3eb..0000000000 --- a/csharp/sbe-benchmarks/Bench/SBE/SbePerfTestRunner.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Diagnostics; -using Org.SbeTool.Sbe.Dll; -using Uk.Co.Real_logic.Sbe.Benchmarks.Fix; - -namespace Org.SbeTool.Sbe.Benchmarks -{ - public static class SbePerfTestRunner - { - static readonly double TicksToNanos = 1000 * 1000 * 1000 / (double)Stopwatch.Frequency; - - public static long PerfTestEncode(int runNumber) - { - const int reps = 10 * 1000 * 1000; - var state = new BenchmarkState(); - var gcCount = GC.CollectionCount(0); - - var sw = Stopwatch.StartNew(); - var size = 0; - for (int i = 0; i < reps; i++) - { - size = MarketDataBenchmark.Encode(state.MessageHeader, state.MarketData, state.EncodeBuffer, state.BufferIndex); - } - - var elapsedTicks = sw.ElapsedTicks; - var avgOpLatency = (long)((elapsedTicks / (double)reps) * TicksToNanos); - - Console.WriteLine("[{0}/Encode/SBE] - {1}(ns) average latency - message size: {2} - GC count: {3}", - runNumber, - avgOpLatency, - size + MessageHeader.Size, - GC.CollectionCount(0) - gcCount); - - return avgOpLatency; - } - - public static long PerfTestDecode(int runNumber) - { - const int reps = 10 * 1000 * 1000; - var state = new BenchmarkState(); - var marketDataSize = 0; - - var gcCount = GC.CollectionCount(0); - - var sw = Stopwatch.StartNew(); - for (int i = 0; i < reps; i++) - { - marketDataSize = MarketDataBenchmark.Decode(state.MessageHeader, state.MarketData, state.DecodeBuffer, state.BufferIndex); - } - - var elapsedTicks = sw.ElapsedTicks; - var avgOpLatency = (long)((elapsedTicks / (double)reps) * TicksToNanos); - - Console.WriteLine("[{0}/Decode/SBE] - {1}(ns) average latency - message size: {2} - GC count: {3}", - runNumber, - avgOpLatency, - marketDataSize + MessageHeader.Size, - GC.CollectionCount(0) - gcCount); - - return avgOpLatency; - } - } -} \ No newline at end of file diff --git a/csharp/sbe-benchmarks/Program.cs b/csharp/sbe-benchmarks/Program.cs index fbacc9b642..688229e63e 100644 --- a/csharp/sbe-benchmarks/Program.cs +++ b/csharp/sbe-benchmarks/Program.cs @@ -12,40 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; +using BenchmarkDotNet.Running; namespace Org.SbeTool.Sbe.Benchmarks { public class Program { - public static void Main() + public static void Main(string[] args) { - Console.WriteLine("WARM UP"); - SbePerfTestRunner.PerfTestEncode(-1); - SbePerfTestRunner.PerfTestDecode(-1); - - long sbeDecodeLatency = 0L; - long sbeEncodeLatency = 0L; - - Console.WriteLine(); - Console.WriteLine("Running ..."); - - const int runsCount = 5; - - for (int i = 0; i < runsCount; i++) - { - sbeEncodeLatency += SbePerfTestRunner.PerfTestEncode(i); - GC.Collect(2); - - sbeDecodeLatency += SbePerfTestRunner.PerfTestDecode(i); - GC.Collect(2); - } - - Console.WriteLine("##teamcity[buildStatisticValue key='AverageEncodeLatencyNanos' value='{0:0.0}']", (double) sbeEncodeLatency / runsCount); - Console.WriteLine("##teamcity[buildStatisticValue key='AverageDecodeLatencyNanos' value='{0:0.0}']", (double) sbeDecodeLatency / runsCount); - - Console.WriteLine("Press a key to continue..."); - Console.ReadKey(); + BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args); } } } diff --git a/csharp/sbe-benchmarks/sbe-benchmarks.csproj b/csharp/sbe-benchmarks/sbe-benchmarks.csproj index bcf5b9c996..8d10e86c4f 100644 --- a/csharp/sbe-benchmarks/sbe-benchmarks.csproj +++ b/csharp/sbe-benchmarks/sbe-benchmarks.csproj @@ -1,9 +1,9 @@  - net45;netcoreapp3.1 + net461;netcoreapp3.1 Org.SbeTool.Sbe.Benchmarks - Org.SbeTool.Sbe.Benchmarks + sbe-benchmarks exe Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. SBE @@ -16,6 +16,8 @@ + + From 97f011214e24eaf8c4d4817aa51b398f55e7c331 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 8 Apr 2021 15:15:07 +0100 Subject: [PATCH 0676/1594] [Java] Upgrade to Mockito 3.9.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f17d482919..774693ffec 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' -def mockitoVersion = '3.8.0' +def mockitoVersion = '3.9.0' def junitVersion = '5.7.1' def jmhVersion = '1.29' def agronaVersion = '1.9.0' From f31ca0bfd3abcb314c4b39e468831e58b5a3ca19 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 8 Apr 2021 15:29:50 +0100 Subject: [PATCH 0677/1594] [Java] Account for Java 16 being a release version. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 774693ffec..f5b964f69b 100644 --- a/build.gradle +++ b/build.gradle @@ -200,7 +200,7 @@ subprojects { options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' options.links("https://www.javadoc.io/doc/org.agrona/agrona/${agronaVersion}/") - if (buildJavaVersion >= 16) { // early access JavaDoc location is different + if (buildJavaVersion >= 17) { // early access JavaDoc location is different options.links("https://download.java.net/java/early_access/jdk${buildJavaVersion}/docs/api/") } else if (buildJavaVersion >= 11) { From 7b4a2f962eea71bbdd8691cfb79fd9689d85c534 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 8 Apr 2021 15:32:24 +0100 Subject: [PATCH 0678/1594] [Java] Copyright. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f5b964f69b..3e05fe57b7 100644 --- a/build.gradle +++ b/build.gradle @@ -195,7 +195,7 @@ subprojects { javadoc { failOnError false title = '

    Simple Binary Encoding (SBE)

    ' - options.bottom = 'Copyright © 2013-2020 Real Logic Limited. All Rights Reserved.' + options.bottom = 'Copyright © 2013-2021 Real Logic Limited. All Rights Reserved.' options.encoding = 'UTF-8' options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' From f186cec6c22552d0e5f2cf68384b312049a0841f Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 8 Apr 2021 21:24:11 +0200 Subject: [PATCH 0679/1594] [CI] Upgrade to setup-java@v2. --- .github/workflows/ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dfdd921125..1842455e64 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,16 +36,19 @@ jobs: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Setup java - uses: actions/setup-java@v1 + uses: actions/setup-java@v2 with: + distribution: 'zulu' java-version: ${{ matrix.java }} - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION run: | + java -Xinternalversion echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - name: Setup java 8 to run the Gradle script - uses: actions/setup-java@v1 + uses: actions/setup-java@v2 with: + distribution: 'zulu' java-version: 8 - name: Build with Gradle run: ./gradlew From 0bfb2ab7fa21d2dbbd327b9b80aacfb63d97431b Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 8 Apr 2021 21:30:33 +0200 Subject: [PATCH 0680/1594] [CI] Upgrade to actions/cache@v2. --- .github/workflows/ci.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1842455e64..6c026bd6c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,14 +24,14 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - name: Cache Gradle dependencies - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} @@ -67,19 +67,19 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - name: Cache Gradle dependencies - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Cache NuGet dependencies - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ~/.nuget/packages key: ${{ runner.os }}-nuget-${{ hashFiles('csharp/**/*.sln') }} @@ -110,14 +110,14 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - name: Cache Gradle dependencies - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} @@ -145,14 +145,14 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - name: Cache Gradle dependencies - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} From 14ed39d20349ca50c216b04a827cc81105e7573b Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 9 Apr 2021 10:33:24 +0200 Subject: [PATCH 0681/1594] [Build] Use `mockito-core` + force latest ByteBuddy dependency. --- build.gradle | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 3e05fe57b7..059066efd4 100644 --- a/build.gradle +++ b/build.gradle @@ -48,6 +48,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' def mockitoVersion = '3.9.0' +def byteBuddyVersion = '1.10.22' def junitVersion = '5.7.1' def jmhVersion = '1.29' def agronaVersion = '1.9.0' @@ -145,6 +146,9 @@ allprojects { configurations.all { resolutionStrategy { failOnVersionConflict() + + force "net.bytebuddy:byte-buddy:${byteBuddyVersion}", + "net.bytebuddy:byte-buddy-agent:${byteBuddyVersion}" } } @@ -239,10 +243,7 @@ project(':sbe-tool') { } testImplementation files('build/classes/java/generated') testImplementation "org.hamcrest:hamcrest:${hamcrestVersion}" - testImplementation ("org.mockito:mockito-junit-jupiter:${mockitoVersion}") { - exclude group: 'org.junit.jupiter' - } - testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}" + testImplementation "org.mockito:mockito-core:${mockitoVersion}" testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" } From 5d90adef27a35396a289dcc67dd2ae837d6cba8c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 15 Apr 2021 18:45:15 +0100 Subject: [PATCH 0682/1594] [Java] Upgrade to Agrona 1.10.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 059066efd4..edb76c3ec8 100644 --- a/build.gradle +++ b/build.gradle @@ -51,8 +51,8 @@ def mockitoVersion = '3.9.0' def byteBuddyVersion = '1.10.22' def junitVersion = '5.7.1' def jmhVersion = '1.29' -def agronaVersion = '1.9.0' -def agronaVersionRange = '[1.9,1.10[' // allow any patch release of 1.9.x +def agronaVersion = '1.10.0' +def agronaVersionRange = '[1.10,1.11[' // allow any patch release of 1.10.x def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From aefb35990b738957c3700f0dcd4ba475ef92701f Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 16 Apr 2021 09:06:11 -0700 Subject: [PATCH 0683/1594] 1.22.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 2fbf9b3a48..80a81c0e7f 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.22.0-SNAPSHOT \ No newline at end of file +1.22.0 \ No newline at end of file From 6c7d63da2a54da41dd85207b04665708bc69675b Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 16 Apr 2021 09:07:43 -0700 Subject: [PATCH 0684/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 80a81c0e7f..58699d5d32 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.22.0 \ No newline at end of file +1.22.1-SNAPSHOT \ No newline at end of file From d7ebefdb7caa4ede00762cbe737e09f9f7ed1118 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 19 Apr 2021 13:57:57 +0200 Subject: [PATCH 0685/1594] [CI] Add Clang 12 to the build matrix. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c026bd6c6..2401f78813 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -137,7 +137,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '6.0', '7', '8', '9', '10', '11' ] + version: [ '6.0', '7', '8', '9', '10', '11', '12' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} From 596bfff6ac82040dd97f0953f1a0eb2f135bf2c4 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 20 Apr 2021 11:11:45 +0200 Subject: [PATCH 0686/1594] [Java] Upgrade to ByteBuddy 1.11.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index edb76c3ec8..cfe304ae52 100644 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' def mockitoVersion = '3.9.0' -def byteBuddyVersion = '1.10.22' +def byteBuddyVersion = '1.11.0' def junitVersion = '5.7.1' def jmhVersion = '1.29' def agronaVersion = '1.10.0' From 8f001bab8910045064b6ae99650108895a58483d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 5 May 2021 16:33:35 +0100 Subject: [PATCH 0687/1594] [Java] Upgrade to JMH 1.30. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cfe304ae52..e73c6dbc20 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.9.0' def byteBuddyVersion = '1.11.0' def junitVersion = '5.7.1' -def jmhVersion = '1.29' +def jmhVersion = '1.30' def agronaVersion = '1.10.0' def agronaVersionRange = '[1.10,1.11[' // allow any patch release of 1.10.x From f3c8d813a5d6930d05155b6589a4bd43a32f790a Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 11 May 2021 10:34:13 +0200 Subject: [PATCH 0688/1594] [Build] Upgrade to Gradle 7.0.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index e73c6dbc20..ab166522ec 100644 --- a/build.gradle +++ b/build.gradle @@ -724,6 +724,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '6.8.3' + gradleVersion = '7.0.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8cf6eb5ad2..d435ce29db 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From ad8fe633843f70f77a6a735eef3b784ff51fb0e8 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 11 May 2021 10:35:30 +0200 Subject: [PATCH 0689/1594] [Build] Upgrade to Shadow 7.0.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ab166522ec..0c66c98890 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ buildscript { plugins { id 'java-library' id 'idea' - id 'com.github.johnrengelman.shadow' version '6.1.0' apply false + id 'com.github.johnrengelman.shadow' version '7.0.0' apply false id "com.github.ben-manes.versions" version "0.38.0" } From 87f865f52f8ea5e0bf304ead76315b39ff144d9b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 12 May 2021 12:27:28 +0100 Subject: [PATCH 0690/1594] [Java] Upgrade to JMH 1.31. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0c66c98890..dc0fae88dd 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.9.0' def byteBuddyVersion = '1.11.0' def junitVersion = '5.7.1' -def jmhVersion = '1.30' +def jmhVersion = '1.31' def agronaVersion = '1.10.0' def agronaVersionRange = '[1.10,1.11[' // allow any patch release of 1.10.x From e35336656f223c9a4bd2b081e796462f014f3c90 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 12 May 2021 10:10:22 -0400 Subject: [PATCH 0691/1594] [Go] GolangGenerator improvements (#846) * [Go] Refactor whitespace in GolangGenerator (#844) Adds function `generateWhitespace` which uses the same String.format technique, but validates the input. It also always generates at least one space. This change should only affect the whitespace of the output. It does not attempt to change the logic that might be the underlying cause of #844. * [Go] Fix type name for nested composites (#847) There was a typo in type name generation of nested composites. It was using the `propertyName` instead of `propertyType`. Add a test case and unit test. This situation wasn't elicited before because nested property types and names are the same in tests (e.g. `Engine`). Prior to the change, the test case in this changeset would show: `./MessageHeader.go:16:14: undefined: MessageHeaderC1` Also set GO111MODULE in Makefile for Go 1.16 builds. * [Go] fix excess import generation (#848) The previous implementation used a single `TreeSet` member to track the import names. This was done as a member to not have to pass the imports to many functions. A given file should only have its imports. Due to traversal of messages and components, there are times where there are too many. The `TreeSet` needs to be fresh for each file. This commit changes `imports` from a single `TreeSet` to a `Stack`. Each time where there was a line: `imports = new TreeSet<>()` (always near a `outputManager.createOutput` new file) We now push that TreeSet on the stack: `imports.push(new TreeSet<>())` At the end of the block, that is popped. This keeps the imports scoped to releveant generators. All those generators now `peek()` at the current `TreeSet`. --- build.gradle | 2 + gocode/Makefile | 10 +- gocode/src/issue847/issue847_test.go | 9 ++ gocode/src/issue848/issue848_test.go | 9 ++ .../generation/golang/GolangGenerator.java | 135 ++++++++++-------- sbe-tool/src/test/resources/issue827.xml | 2 +- sbe-tool/src/test/resources/issue847.xml | 25 ++++ sbe-tool/src/test/resources/issue848.xml | 29 ++++ 8 files changed, 157 insertions(+), 64 deletions(-) create mode 100644 gocode/src/issue847/issue847_test.go create mode 100644 gocode/src/issue848/issue848_test.go create mode 100644 sbe-tool/src/test/resources/issue847.xml create mode 100644 sbe-tool/src/test/resources/issue848.xml diff --git a/build.gradle b/build.gradle index dc0fae88dd..5940c10e59 100644 --- a/build.gradle +++ b/build.gradle @@ -619,6 +619,8 @@ task generateGolangCodecsWithXSD(type: JavaExec) { 'sbe-tool/src/test/resources/issue488.xml', 'sbe-tool/src/test/resources/issue560.xml', 'sbe-tool/src/test/resources/issue661.xml', + 'sbe-tool/src/test/resources/issue847.xml', + 'sbe-tool/src/test/resources/issue848.xml', 'sbe-tool/src/test/resources/since-deprecated-test-schema.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', 'gocode/resources/example-composite.xml', diff --git a/gocode/Makefile b/gocode/Makefile index 7a471aee87..a03af97779 100644 --- a/gocode/Makefile +++ b/gocode/Makefile @@ -1,9 +1,13 @@ ROOT=.. SBE_TOOL_VERSION=$(shell cat $(ROOT)/version.txt) SBE_JAR=$(ROOT)/sbe-all/build/libs/sbe-all-${SBE_TOOL_VERSION}.jar + # FIXME: Go doesn't like relative paths so us a gnumake extension for now GOPATH=$(realpath $(ROOT)/gocode) +# GO111MODULE=off is required for building with Go 1.16 +# GOPATH-style support will be removed in Go 1.17 +export GO111MODULE=off # Convenience during development #SAVE_FORMAT=mkdir -p fmt && cp *.go fmt && @@ -25,7 +29,7 @@ $(DEP): $(SBE_JAR) go fmt && \ go test) -# Wil regenerate codecs by removing dependencies +# Will regenerate codecs by removing dependencies clean: rm -f src/*/SbeMarshalling.go src/*/*/SbeMarshalling.go @@ -56,7 +60,7 @@ src/baseline/SbeMarshalling.go: $(DEP) # The first set does a make install as there is a test that uses # multiple packages and needs them in GOPATH The second set work in # src/foo, and the third need a GOPATH addition as for Java and C++ -# they geenrate into the same directory but golang doesn't allow that +# they generate into the same directory but golang doesn't allow that test: $(DEP) (export GOPATH=$(GOPATH) && \ (for t in baseline extension; do \ @@ -68,7 +72,7 @@ test: $(DEP) go install \ ;done)) (export GOPATH=$(GOPATH) && \ - (for t in baseline-bigendian mktdata group_with_data group_with_data_extension composite_elements composite since-deprecated simple issue435 issue472 issue483 issue488 issue560; do \ + (for t in baseline-bigendian mktdata group_with_data group_with_data_extension composite_elements composite since-deprecated simple issue435 issue472 issue483 issue488 issue560 issue847 issue848; do \ cd $(GOPATH)/src/$$t && \ go build && \ go fmt && \ diff --git a/gocode/src/issue847/issue847_test.go b/gocode/src/issue847/issue847_test.go new file mode 100644 index 0000000000..1fb14887ad --- /dev/null +++ b/gocode/src/issue847/issue847_test.go @@ -0,0 +1,9 @@ +package issue847 + +import ( + "testing" +) + +func TestNothing(t *testing.T) { + // placeholder, really just looking for clean builds +} diff --git a/gocode/src/issue848/issue848_test.go b/gocode/src/issue848/issue848_test.go new file mode 100644 index 0000000000..1106e74b01 --- /dev/null +++ b/gocode/src/issue848/issue848_test.go @@ -0,0 +1,9 @@ +package issue848 + +import ( + "testing" +) + +func TestNothing(t *testing.T) { + // placeholder, really just looking for clean builds +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index 33d12c305c..2a62192150 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Scanner; +import java.util.Stack; import java.util.TreeSet; import static uk.co.real_logic.sbe.PrimitiveType.CHAR; @@ -49,7 +50,7 @@ public class GolangGenerator implements CodeGenerator private final Ir ir; private final OutputManager outputManager; - private TreeSet imports; + private Stack> imports; /** * Create a new Go language {@link CodeGenerator}. @@ -64,6 +65,8 @@ public GolangGenerator(final Ir ir, final OutputManager outputManager) this.ir = ir; this.outputManager = outputManager; + this.imports = new Stack>(); + this.imports.push(new TreeSet<>()); // ensure at least one } /** @@ -126,8 +129,8 @@ public void generateMessageHeaderStub() throws IOException final StringBuilder sb = new StringBuilder(); final List tokens = ir.headerStructure().tokens(); - imports = new TreeSet<>(); - imports.add("io"); + imports.push(new TreeSet<>()); + imports.peek().add("io"); generateTypeDeclaration(sb, messageHeader); generateTypeBodyComposite(sb, messageHeader, tokens.subList(1, tokens.size() - 1)); @@ -136,6 +139,7 @@ public void generateMessageHeaderStub() throws IOException generateCompositePropertyElements(sb, messageHeader, tokens.subList(1, tokens.size() - 1)); out.append(generateFileHeader(ir.namespaces())); out.append(sb); + imports.pop(); } } @@ -172,8 +176,8 @@ public void generate() throws IOException { final StringBuilder sb = new StringBuilder(); - imports = new TreeSet<>(); - this.imports.add("io"); + imports.push(new TreeSet<>()); + imports.peek().add("io"); generateTypeDeclaration(sb, typeName); generateTypeBody(sb, typeName, tokens.subList(1, tokens.size() - 1)); @@ -199,6 +203,7 @@ public void generate() throws IOException out.append(generateFileHeader(ir.namespaces())); out.append(sb); + imports.pop(); } } } @@ -223,8 +228,8 @@ private String generateDecodeOffset(final int gap, final String indent) { if (gap > 0) { - this.imports.add("io"); - this.imports.add("io/ioutil"); + imports.peek().add("io"); + imports.peek().add("io/ioutil"); return String.format("%1$s\tio.CopyN(ioutil.Discard, _r, %2$d)\n", indent, gap); } @@ -243,7 +248,7 @@ private void generateCharacterEncodingRangeCheck( switch (token.encoding().characterEncoding()) { case "ASCII": - this.imports.add("fmt"); + imports.peek().add("fmt"); sb.append(String.format( "\tfor idx, ch := range %1$s {\n" + "\t\tif ch > 127 {\n" + @@ -255,8 +260,8 @@ private void generateCharacterEncodingRangeCheck( break; case "UTF-8": - this.imports.add("errors"); - this.imports.add("unicode/utf8"); + imports.peek().add("errors"); + imports.peek().add("unicode/utf8"); sb.append(String.format( "\tif !utf8.Valid(%1$s[:]) {\n" + "\t\treturn errors.New(\"%1$s failed UTF-8 validation\")\n" + @@ -466,7 +471,7 @@ private void generateRangeCheckPrimitive( // If this field is unknown then we have nothing to check // Otherwise do the Min,MaxValue checks (possibly for arrays) - this.imports.add("fmt"); + imports.peek().add("fmt"); if (token.arrayLength() > 1) { sb.append(String.format( @@ -616,8 +621,8 @@ private void generateExtensionCheck( final StringBuilder sb, final char varName) { - this.imports.add("io"); - this.imports.add("io/ioutil"); + imports.peek().add("io"); + imports.peek().add("io/ioutil"); sb.append(String.format( "\tif actingVersion > %1$s.SbeSchemaVersion() && blockLength > %1$s.SbeBlockLength() {\n" + "\t\tio.CopyN(ioutil.Discard, _r, int64(blockLength-%1$s.SbeBlockLength()))\n" + @@ -867,8 +872,8 @@ private void generateEnumEncodeDecode(final StringBuilder sb, final String enumN // Range check // We use golang's reflect to range over the values in the // struct to check which are legitimate - imports.add("fmt"); - imports.add("reflect"); + imports.peek().add("fmt"); + imports.peek().add("reflect"); generateRangeCheckHeader(sb, varName, enumName + "Enum", true); // For enums we can add new fields so if we're decoding a @@ -1437,8 +1442,8 @@ private void generateChoiceSet(final List tokens) throws IOException try (Writer out = outputManager.createOutput(choiceName)) { - imports = new TreeSet<>(); - imports.add("io"); + imports.push(new TreeSet<>()); + imports.peek().add("io"); generateChoiceDecls( sb, @@ -1462,6 +1467,7 @@ private void generateChoiceSet(final List tokens) throws IOException } out.append(generateFileHeader(ir.namespaces())); out.append(sb); + imports.pop(); } } @@ -1474,8 +1480,8 @@ private void generateEnum(final List tokens) throws IOException try (Writer out = outputManager.createOutput(enumName)) { - imports = new TreeSet<>(); - imports.add("io"); + imports.push(new TreeSet<>()); + imports.peek().add("io"); generateEnumDecls( sb, @@ -1501,6 +1507,7 @@ private void generateEnum(final List tokens) throws IOException out.append(generateFileHeader(ir.namespaces())); out.append(sb); + imports.pop(); } } @@ -1511,8 +1518,8 @@ private void generateComposite(final List tokens, final String namePrefix try (Writer out = outputManager.createOutput(compositeName)) { - imports = new TreeSet<>(); - imports.add("io"); + imports.push(new TreeSet<>()); + imports.peek().add("io"); generateTypeDeclaration(sb, compositeName); generateTypeBodyComposite(sb, compositeName, tokens.subList(1, tokens.size() - 1)); @@ -1526,6 +1533,7 @@ private void generateComposite(final List tokens, final String namePrefix // it's created last once that's known. out.append(generateFileHeader(ir.namespaces())); out.append(sb); + imports.pop(); } } @@ -1559,7 +1567,7 @@ private void generateEnumDecls( sb.append(String.format( "\t%1$s%2$s%3$sEnum\n", token.name(), - String.format(String.format("%%%ds", longest - token.name().length() + 1), " "), + generateWhitespace(longest - token.name().length() + 1), enumName)); } @@ -1568,7 +1576,7 @@ private void generateEnumDecls( "\t%1$s%2$s%3$sEnum\n" + "}\n", nullValue, - String.format(String.format("%%%ds", longest - nullValue.length() + 1), " "), + generateWhitespace(longest - nullValue.length() + 1), enumName)); // And now the Enum Values expressed as a variable @@ -1616,7 +1624,7 @@ private void generateChoiceDecls( sb.append(String.format( "\t%1$s%2$s%3$sChoiceValue\n", toUpperFirstChar(token.name()), - String.format(String.format("%%%ds", longest - token.name().length() + 1), " "), + generateWhitespace(longest - token.name().length() + 1), toUpperFirstChar(encodingToken.applicableTypeName()))); } @@ -1653,7 +1661,7 @@ private StringBuilder generateFileHeader(final CharSequence[] namespaces) "import (\n", namespacesToPackageName(namespaces))); - for (final String s : imports) + for (final String s : imports.peek()) { sb.append("\t\"").append(s).append("\"\n"); } @@ -1747,7 +1755,7 @@ private void generateTypeBody( { case BEGIN_ENUM: sb.append("\t").append(propertyName) - .append(String.format(String.format("%%%ds", length), " ")) + .append(generateWhitespace(length)) .append(arrayspec) .append(encodingToken.applicableTypeName()) .append("Enum\n"); @@ -1755,7 +1763,7 @@ private void generateTypeBody( case BEGIN_SET: sb.append("\t").append(propertyName) - .append(String.format(String.format("%%%ds", length), " ")) + .append(generateWhitespace(length)) .append(arrayspec) .append(encodingToken.applicableTypeName()) .append("\n"); @@ -1778,7 +1786,7 @@ private void generateTypeBody( arrayspec = "[" + encodingToken.encoding().constValue().size() + "]"; } sb.append("\t").append(propertyName) - .append(String.format(String.format("%%%ds", length), " ")) + .append(generateWhitespace(length)) .append(arrayspec).append(golangType).append("\n"); break; } @@ -1790,7 +1798,7 @@ private void generateTypeBody( sb.append(String.format( "\t%1$s%2$s[]%3$s%1$s\n", toUpperFirstChar(signalToken.name()), - String.format(String.format("%%%ds", length), " "), + generateWhitespace(length), typeName)); generateTypeDeclaration( nested, @@ -1812,7 +1820,7 @@ private void generateTypeBody( sb.append(String.format( "\t%1$s%2$s[]%3$s\n", toUpperFirstChar(signalToken.name()), - String.format(String.format("%%%ds", length), " "), + generateWhitespace(length), golangTypeName(tokens.get(i + 3).encoding().primitiveType()))); break; @@ -2009,14 +2017,14 @@ private void generateTypeBodyComposite( { arrayLength = token.encoding().constValue().size(); // can be 1 sb.append("\t").append(propertyName) - .append(String.format(String.format("%%%ds", longest - propertyName.length() + 1), " ")) + .append(generateWhitespace(longest - propertyName.length() + 1)) .append("[").append(arrayLength).append("]") .append(golangTypeName(token.encoding().primitiveType())).append("\n"); } else { sb.append("\t").append(propertyName) - .append(String.format(String.format("%%%ds", longest - propertyName.length() + 1), " ")) + .append(generateWhitespace(longest - propertyName.length() + 1)) .append((arrayLength > 1) ? ("[" + arrayLength + "]") : "") .append(golangTypeName(token.encoding().primitiveType())).append("\n"); } @@ -2024,14 +2032,14 @@ private void generateTypeBodyComposite( case BEGIN_ENUM: sb.append("\t").append(propertyName) - .append(String.format(String.format("%%%ds", longest - propertyName.length() + 1), " ")) + .append(generateWhitespace(longest - propertyName.length() + 1)) .append((arrayLength > 1) ? ("[" + arrayLength + "]") : "") .append(propertyType).append("Enum\n"); break; case BEGIN_SET: sb.append("\t").append(propertyName) - .append(String.format(String.format("%%%ds", longest - propertyName.length() + 1), " ")) + .append(generateWhitespace(longest - propertyName.length() + 1)) .append((arrayLength > 1) ? ("[" + arrayLength + "]") : "").append(propertyType).append("\n"); break; @@ -2041,9 +2049,9 @@ private void generateTypeBodyComposite( i += token.componentTokenCount() - 2; sb.append("\t").append(propertyName) - .append(String.format(String.format("%%%ds", longest - propertyName.length() + 1), " ")) + .append(generateWhitespace(longest - propertyName.length() + 1)) .append((arrayLength > 1) ? ("[" + arrayLength + "]") : "") - .append(typeName).append(propertyName).append("\n"); + .append(typeName).append(propertyType).append("\n"); break; } } @@ -2194,16 +2202,16 @@ private CharSequence generateMinValueLiteral(final PrimitiveType primitiveType, case CHAR: return "byte(32)"; case INT8: - imports.add("math"); + imports.peek().add("math"); return "math.MinInt8 + 1"; case INT16: - imports.add("math"); + imports.peek().add("math"); return "math.MinInt16 + 1"; case INT32: - imports.add("math"); + imports.peek().add("math"); return "math.MinInt32 + 1"; case INT64: - imports.add("math"); + imports.peek().add("math"); return "math.MinInt64 + 1"; case UINT8: case UINT16: @@ -2211,10 +2219,10 @@ private CharSequence generateMinValueLiteral(final PrimitiveType primitiveType, case UINT64: return "0"; case FLOAT: - imports.add("math"); + imports.peek().add("math"); return "-math.MaxFloat32"; case DOUBLE: - imports.add("math"); + imports.peek().add("math"); return "-math.MaxFloat64"; } } @@ -2231,34 +2239,34 @@ private CharSequence generateMaxValueLiteral(final PrimitiveType primitiveType, case CHAR: return "byte(126)"; case INT8: - imports.add("math"); + imports.peek().add("math"); return "math.MaxInt8"; case INT16: - imports.add("math"); + imports.peek().add("math"); return "math.MaxInt16"; case INT32: - imports.add("math"); + imports.peek().add("math"); return "math.MaxInt32"; case INT64: - imports.add("math"); + imports.peek().add("math"); return "math.MaxInt64"; case UINT8: - imports.add("math"); + imports.peek().add("math"); return "math.MaxUint8 - 1"; case UINT16: - imports.add("math"); + imports.peek().add("math"); return "math.MaxUint16 - 1"; case UINT32: - imports.add("math"); + imports.peek().add("math"); return "math.MaxUint32 - 1"; case UINT64: - imports.add("math"); + imports.peek().add("math"); return "math.MaxUint64 - 1"; case FLOAT: - imports.add("math"); + imports.peek().add("math"); return "math.MaxFloat32"; case DOUBLE: - imports.add("math"); + imports.peek().add("math"); return "math.MaxFloat64"; } } @@ -2273,28 +2281,28 @@ private CharSequence generateNullValueLiteral(final PrimitiveType primitiveType, switch (primitiveType) { case INT8: - imports.add("math"); + imports.peek().add("math"); return "math.MinInt8"; case INT16: - imports.add("math"); + imports.peek().add("math"); return "math.MinInt16"; case INT32: - imports.add("math"); + imports.peek().add("math"); return "math.MinInt32"; case INT64: - imports.add("math"); + imports.peek().add("math"); return "math.MinInt64"; case UINT8: - imports.add("math"); + imports.peek().add("math"); return "math.MaxUint8"; case UINT16: - imports.add("math"); + imports.peek().add("math"); return "math.MaxUint16"; case UINT32: - imports.add("math"); + imports.peek().add("math"); return "math.MaxUint32"; case UINT64: - imports.add("math"); + imports.peek().add("math"); return "math.MaxUint64"; } } @@ -2347,5 +2355,12 @@ private CharSequence generateLiteral(final PrimitiveType type, final String valu return literal; } + + // Always generates at least one space + private String generateWhitespace(final int spaces) + { + final int limitedSpaces = Math.max(1, spaces); + return String.format(String.format("%%%ds", limitedSpaces), " "); + } } diff --git a/sbe-tool/src/test/resources/issue827.xml b/sbe-tool/src/test/resources/issue827.xml index 07db19475e..08430a6e73 100644 --- a/sbe-tool/src/test/resources/issue827.xml +++ b/sbe-tool/src/test/resources/issue827.xml @@ -4,7 +4,7 @@ id="827" version="1" semanticVersion="1.0" - description="issue 661 test case" + description="issue 827 test case" byteOrder="bigEndian"> diff --git a/sbe-tool/src/test/resources/issue847.xml b/sbe-tool/src/test/resources/issue847.xml new file mode 100644 index 0000000000..ce015bbb1c --- /dev/null +++ b/sbe-tool/src/test/resources/issue847.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/sbe-tool/src/test/resources/issue848.xml b/sbe-tool/src/test/resources/issue848.xml new file mode 100644 index 0000000000..cf31b53740 --- /dev/null +++ b/sbe-tool/src/test/resources/issue848.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From c8c280b3c6dc7744c51774e91f5cc1f968e25331 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 13 May 2021 10:54:54 +0100 Subject: [PATCH 0692/1594] [Java] Upgrade to Mockito 3.10.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5940c10e59..8cd0a2c0f2 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' -def mockitoVersion = '3.9.0' +def mockitoVersion = '3.10.0' def byteBuddyVersion = '1.11.0' def junitVersion = '5.7.1' def jmhVersion = '1.31' From 1525313878ea36c00100694987ed34d2d1175757 Mon Sep 17 00:00:00 2001 From: Evan Date: Fri, 14 May 2021 04:12:16 -0400 Subject: [PATCH 0693/1594] [Go] Fix tokens passed to generateComposite (#849) (#850) * [Go] Fix tokens passed to generateComposite (#849) Too many tokens were passed to `generateComposite` causing weird errors like(#844 and #849). * [Go] Fix Group decoder style warning The `Decode` generator for groups would produce the following code: ``` for i, _ := range o.GroupName { ``` The `gofmt` tools suggest [simplify range expression](https://github.com/golang/tools/blob/master/internal/lsp/analysis/simplifyrange/simplifyrange.go#L23): ``` A range of the form: for x, _ = range v {...} will be simplified to: for x = range v {...} ``` This patch fixes that. --- build.gradle | 1 + gocode/Makefile | 2 +- gocode/src/issue849/issue849_test.go | 9 ++++ .../generation/golang/GolangGenerator.java | 6 +-- sbe-tool/src/test/resources/issue849.xml | 43 +++++++++++++++++++ 5 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 gocode/src/issue849/issue849_test.go create mode 100644 sbe-tool/src/test/resources/issue849.xml diff --git a/build.gradle b/build.gradle index 8cd0a2c0f2..9ada9703a7 100644 --- a/build.gradle +++ b/build.gradle @@ -621,6 +621,7 @@ task generateGolangCodecsWithXSD(type: JavaExec) { 'sbe-tool/src/test/resources/issue661.xml', 'sbe-tool/src/test/resources/issue847.xml', 'sbe-tool/src/test/resources/issue848.xml', + 'sbe-tool/src/test/resources/issue849.xml', 'sbe-tool/src/test/resources/since-deprecated-test-schema.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', 'gocode/resources/example-composite.xml', diff --git a/gocode/Makefile b/gocode/Makefile index a03af97779..456cced904 100644 --- a/gocode/Makefile +++ b/gocode/Makefile @@ -72,7 +72,7 @@ test: $(DEP) go install \ ;done)) (export GOPATH=$(GOPATH) && \ - (for t in baseline-bigendian mktdata group_with_data group_with_data_extension composite_elements composite since-deprecated simple issue435 issue472 issue483 issue488 issue560 issue847 issue848; do \ + (for t in baseline-bigendian mktdata group_with_data group_with_data_extension composite_elements composite since-deprecated simple issue435 issue472 issue483 issue488 issue560 issue847 issue848 issue849; do \ cd $(GOPATH)/src/$$t && \ go build && \ go fmt && \ diff --git a/gocode/src/issue849/issue849_test.go b/gocode/src/issue849/issue849_test.go new file mode 100644 index 0000000000..0149615810 --- /dev/null +++ b/gocode/src/issue849/issue849_test.go @@ -0,0 +1,9 @@ +package issue849 + +import ( + "testing" +) + +func TestNothing(t *testing.T) { + // placeholder, really just looking for clean builds +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index 2a62192150..16b1385bfe 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -1305,7 +1305,7 @@ private int generateGroupEncodeDecode( "\t\t\t%1$s.%2$s = make([]%3$s%2$s, %2$sNumInGroup)\n" + "\t\t}\n" + "\t\t%1$c.%2$s = %1$c.%2$s[:%2$sNumInGroup]\n" + - "\t\tfor i, _ := range %1$s.%2$s {\n" + + "\t\tfor i := range %1$s.%2$s {\n" + "\t\t\tif err := %1$s.%2$s[i].Decode(_m, _r, actingVersion, uint(%4$sBlockLength)); err != nil {\n" + "\t\t\t\treturn err\n" + "\t\t\t}\n" + @@ -2045,8 +2045,8 @@ private void generateTypeBodyComposite( case BEGIN_COMPOSITE: // recurse - generateComposite(tokens.subList(i, tokens.size()), typeName); - i += token.componentTokenCount() - 2; + generateComposite(tokens.subList(i, i + token.componentTokenCount()), typeName); + i += token.componentTokenCount() - 1; sb.append("\t").append(propertyName) .append(generateWhitespace(longest - propertyName.length() + 1)) diff --git a/sbe-tool/src/test/resources/issue849.xml b/sbe-tool/src/test/resources/issue849.xml new file mode 100644 index 0000000000..4eb45ce8ee --- /dev/null +++ b/sbe-tool/src/test/resources/issue849.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 430988b878c55a86a10fccd765f3c8e30b5bdbe2 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 15 May 2021 16:13:50 +0100 Subject: [PATCH 0694/1594] [Java] Upgrade to Gradle 7.0.2. --- build.gradle | 3 +-- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index dc0fae88dd..9f4f3398f2 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,6 @@ buildscript { plugins { id 'java-library' - id 'idea' id 'com.github.johnrengelman.shadow' version '7.0.0' apply false id "com.github.ben-manes.versions" version "0.38.0" } @@ -724,6 +723,6 @@ task testReport(type: TestReport) { } wrapper { - gradleVersion = '7.0.1' + gradleVersion = '7.0.2' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d435ce29db..29e4134576 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 19a6a3495859863df0f0033fc5a1f161c3fd8025 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 18 May 2021 14:18:27 +0100 Subject: [PATCH 0695/1594] [Java] Consistent use of System properties. --- .../sbe/generation/TargetCodeGeneratorLoader.java | 8 ++++---- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/CompositeType.java | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index ba36941a7b..1eb76f35d8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -47,9 +47,9 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) ir, System.getProperty(JAVA_ENCODING_BUFFER_TYPE, JAVA_DEFAULT_ENCODING_BUFFER_TYPE), System.getProperty(JAVA_DECODING_BUFFER_TYPE, JAVA_DEFAULT_DECODING_BUFFER_TYPE), - Boolean.getBoolean(JAVA_GROUP_ORDER_ANNOTATION), - Boolean.getBoolean(JAVA_GENERATE_INTERFACES), - Boolean.getBoolean(DECODE_UNKNOWN_ENUM_VALUES), + "true".equals(System.getProperty(JAVA_GROUP_ORDER_ANNOTATION)), + "true".equals(System.getProperty(JAVA_GENERATE_INTERFACES)), + "true".equals(System.getProperty(DECODE_UNKNOWN_ENUM_VALUES)), new PackageOutputManager(outputDir, ir.applicableNamespace())); } }, @@ -80,7 +80,7 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) { return new CppGenerator( ir, - Boolean.getBoolean(DECODE_UNKNOWN_ENUM_VALUES), + "true".equals(System.getProperty(DECODE_UNKNOWN_ENUM_VALUES)), new NamespaceOutputManager(outputDir, ir.applicableNamespace())); } }, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java index 9c3f497deb..32a0a8ebee 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java @@ -79,7 +79,7 @@ public Ir( captureTypes(headerTokens, 0, headerTokens.size() - 1); - if (Boolean.getBoolean(SbeTool.CPP_NAMESPACES_COLLAPSE)) + if ("true".equals(System.getProperty(SbeTool.CPP_NAMESPACES_COLLAPSE))) { this.namespaces = new String[]{ (namespaceName == null ? packageName : namespaceName).replace(".", "_") }; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index 8b740ffe42..5ec25a6c2d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -302,7 +302,7 @@ else if (primitiveType == UINT32) */ public void checkForWellFormedMessageHeader(final Node node) { - final boolean shouldGenerateInterfaces = Boolean.getBoolean(JAVA_GENERATE_INTERFACES); + final boolean shouldGenerateInterfaces = "true".equals(System.getProperty(JAVA_GENERATE_INTERFACES)); final EncodedDataType blockLengthType = (EncodedDataType)containedTypeByNameMap.get("blockLength"); final EncodedDataType templateIdType = (EncodedDataType)containedTypeByNameMap.get("templateId"); From 971924888b55a06eaa9fca942a1ae89cc0db3235 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 19 May 2021 10:53:41 +0200 Subject: [PATCH 0696/1594] [Build] Filter out non-stable version from the dependency update report. --- build.gradle | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/build.gradle b/build.gradle index ec324c34be..82f6d95133 100644 --- a/build.gradle +++ b/build.gradle @@ -725,6 +725,19 @@ task testReport(type: TestReport) { reportOn subprojects*.test } +def isNonStable = { String version -> + def stableKeyword = ['RELEASE', 'FINAL', 'GA'].any { it -> version.toUpperCase().contains(it) } + def regex = /^[0-9,.v-]+(-r)?$/ + return !stableKeyword && !(version ==~ regex) +} + +tasks.named("dependencyUpdates").configure { + // Reject all non stable versions + rejectVersionIf { + isNonStable(it.candidate.version) + } +} + wrapper { gradleVersion = '7.0.2' distributionType = 'ALL' From 521c16be06b895deb19a03a9d28deee994a6cdac Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 19 May 2021 10:54:04 +0200 Subject: [PATCH 0697/1594] [Java] Upgrade to JUnit 5.7.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 82f6d95133..b839c3c6a7 100644 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,7 @@ def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' def mockitoVersion = '3.10.0' def byteBuddyVersion = '1.11.0' -def junitVersion = '5.7.1' +def junitVersion = '5.7.2' def jmhVersion = '1.31' def agronaVersion = '1.10.0' def agronaVersionRange = '[1.10,1.11[' // allow any patch release of 1.10.x From 8b687f4ed9b494dd817a9b6e364cc2887a89a027 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 19 May 2021 11:44:16 +0100 Subject: [PATCH 0698/1594] [Java] Remove redundant buildscript block. --- build.gradle | 6 ------ 1 file changed, 6 deletions(-) diff --git a/build.gradle b/build.gradle index b839c3c6a7..9685b779f5 100644 --- a/build.gradle +++ b/build.gradle @@ -14,12 +14,6 @@ * limitations under the License. */ -buildscript { - repositories { - mavenCentral() - } -} - plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '7.0.0' apply false From 11cda3a07c2779db204262682989057b352883e1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 19 May 2021 11:50:31 +0100 Subject: [PATCH 0699/1594] [Java] Remove eclipse plugin. --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9685b779f5..689848c27f 100644 --- a/build.gradle +++ b/build.gradle @@ -155,7 +155,6 @@ jar.enabled = false subprojects { apply plugin: 'java-library' apply plugin: 'checkstyle' - apply plugin: 'eclipse' group = sbeGroup version = sbeVersion From 7690fae78d34a75ace25a3bdfd802677180e6414 Mon Sep 17 00:00:00 2001 From: Robert Purdy Date: Tue, 25 May 2021 06:57:40 -0700 Subject: [PATCH 0700/1594] [C#] Added more string read/write methods to the DirectBuffer #729 (#845) * [C#] Add more string reading/writing methods to DirectBuffer More, hopefully efficient, mechanisms to read and write strings to and from the DirectBuffer. * [C#] Reverted to .net45 * [C#] Reverted to .net45 * [C#] Updated Samples to use the new String methods * [C#] Fixed checkstyle * [C#] Cleaning * Added Modified Benchmarks\nBoth a modified version of the the CarBenchmark which encodes and decodes to/from string; and a version wich uses the new methods to encode and decode strings Co-authored-by: Rob Purdy --- .../SBE/CarBenchmark_with_strings_new.cs | 193 ++++++++++++++++ .../SBE/CarBenchmark_with_strings_original.cs | 213 ++++++++++++++++++ csharp/sbe-dll/DirectBuffer.cs | 111 +++++++++ csharp/sbe-samples-car/CarExample.cs | 39 ++-- csharp/sbe-samples-car/sbe-samples-car.csproj | 2 +- csharp/sbe-tests/DirectBufferTests.cs | 177 +++++++++++++++ .../generation/csharp/CSharpGenerator.java | 44 +++- 7 files changed, 754 insertions(+), 25 deletions(-) create mode 100644 csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_new.cs create mode 100644 csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_original.cs diff --git a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_new.cs b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_new.cs new file mode 100644 index 0000000000..d3badedd18 --- /dev/null +++ b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_new.cs @@ -0,0 +1,193 @@ +using System.Text; +using Baseline; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Diagnosers; +using Org.SbeTool.Sbe.Dll; + +namespace Org.SbeTool.Sbe.Benchmarks.Bench.Benchmarks +{ + [MemoryDiagnoser] + public class CarBenchmark_with_strings_new + { + + private readonly byte[] _eBuffer = new byte[1024]; + private readonly byte[] _dBuffer = new byte[1024]; + private DirectBuffer _encodeBuffer; + private DirectBuffer _decodeBuffer; + private readonly Car _car = new Car(); + private readonly MessageHeader _messageHeader = new MessageHeader(); + + [GlobalSetup] + public void Setup() + { + _encodeBuffer = new DirectBuffer(_eBuffer); + _decodeBuffer = new DirectBuffer(_dBuffer); + Encode(_car, _decodeBuffer, 0); + } + + [Benchmark] + public int Encode() + { + return Encode(_car, _encodeBuffer, 0); + } + + [Benchmark] + public int Decode() + { + return Decode(_car, _decodeBuffer, 0); + } + + public int Encode(Car car, DirectBuffer directBuffer, int bufferOffset) + { + _car.WrapForEncodeAndApplyHeader(directBuffer, bufferOffset, _messageHeader); + + const int srcOffset = 0; + + car.SerialNumber = 1234; + car.ModelYear = 2013; + car.Available = BooleanType.T; + car.Code = Baseline.Model.A; + car.SetVehicleCode("CODE12"); + + for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) + { + car.SetSomeNumbers(i, (uint)i); + } + + car.Extras = OptionalExtras.CruiseControl | OptionalExtras.SportsPack; + car.Engine.Capacity = 2000; + car.Engine.NumCylinders = 4; + car.Engine.SetManufacturerCode("123"); + car.Engine.Efficiency = 35; + car.Engine.BoosterEnabled = BooleanType.T; + car.Engine.Booster.BoostType = BoostType.NITROUS; + car.Engine.Booster.HorsePower = 200; + + var fuelFigures = car.FuelFiguresCount(3); + fuelFigures.Next(); + fuelFigures.Speed = 30; + fuelFigures.Mpg = 35.9f; + fuelFigures.SetUsageDescription("Urban Cycle"); + + fuelFigures.Next(); + fuelFigures.Speed = 55; + fuelFigures.Mpg = 49.0f; + fuelFigures.SetUsageDescription("Combined Cycle"); + + fuelFigures.Next(); + fuelFigures.Speed = 75; + fuelFigures.Mpg = 40.0f; + fuelFigures.SetUsageDescription("Highway Cycle"); + + Car.PerformanceFiguresGroup perfFigures = car.PerformanceFiguresCount(2); + perfFigures.Next(); + perfFigures.OctaneRating = 95; + + Car.PerformanceFiguresGroup.AccelerationGroup acceleration = perfFigures.AccelerationCount(3).Next(); + acceleration.Mph = 30; + acceleration.Seconds = 4.0f; + + acceleration.Next(); + acceleration.Mph = 60; + acceleration.Seconds = 7.5f; + + acceleration.Next(); + acceleration.Mph = 100; + acceleration.Seconds = 12.2f; + + perfFigures.Next(); + perfFigures.OctaneRating = 99; + acceleration = perfFigures.AccelerationCount(3).Next(); + + acceleration.Mph = 30; + acceleration.Seconds = 3.8f; + + acceleration.Next(); + acceleration.Mph = 60; + acceleration.Seconds = 7.1f; + + acceleration.Next(); + acceleration.Mph = 100; + acceleration.Seconds = 11.8f; + + car.SetManufacturer("Honda"); + car.SetModel("Civic VTi"); + car.SetActivationCode("code"); + + return car.Size; + } + + private readonly byte[] _buffer = new byte[128]; + + public int Decode(Car car, DirectBuffer directBuffer, int bufferOffset) + { + _messageHeader.Wrap(directBuffer, bufferOffset, 0); + + car.WrapForDecode(directBuffer, bufferOffset + MessageHeader.Size, _messageHeader.BlockLength, _messageHeader.Version); + + var templateId = Car.TemplateId; + var schemaVersion = Car.SchemaVersion; + var serialNumber = car.SerialNumber; + var modelYear = car.ModelYear; + var available = car.Available; + var code = car.Code; + + for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) + { + var number = car.GetSomeNumbers(i); + } + + var vehicleCode = car.GetVehicleCode(); + + OptionalExtras extras = car.Extras; + var cruiseControl = (extras & OptionalExtras.CruiseControl) == OptionalExtras.CruiseControl; + var sportsPack = (extras & OptionalExtras.SportsPack) == OptionalExtras.SportsPack; + var sunRoof = (extras & OptionalExtras.SunRoof) == OptionalExtras.SunRoof; + + Engine engine = car.Engine; + var capacity = engine.Capacity; + var numCylinders = engine.NumCylinders; + var maxRpm = engine.MaxRpm; + for (int i = 0, size = Engine.ManufacturerCodeLength; i < size; i++) + { + engine.GetManufacturerCode(i); + } + + var length = engine.GetFuel(_buffer, 0, _buffer.Length); + + var efficiency = engine.Efficiency; + var boosterEnabled = engine.BoosterEnabled; + var boostType = engine.Booster.BoostType; + var horsePower = engine.Booster.HorsePower; + + var fuelFiguresGroup = car.FuelFigures; + while (fuelFiguresGroup.HasNext) + { + var fuelFigures = fuelFiguresGroup.Next(); + var speed = fuelFigures.Speed; + var mpg = fuelFigures.Mpg; + var usage = fuelFigures.GetUsageDescription(); + } + + var performanceFiguresGroup = car.PerformanceFigures; + while (performanceFiguresGroup.HasNext) + { + performanceFiguresGroup.Next(); + var octanceRating = performanceFiguresGroup.OctaneRating; + + var accelerationGroup = performanceFiguresGroup.Acceleration; + for (int i = 0; i < accelerationGroup.Count; i++) + { + var acceleration = accelerationGroup.Next(); + var mpg = acceleration.Mph; + var seconds = acceleration.Seconds; + } + } + + var man = car.GetManufacturer(); + var model = car.GetModel(); + var actCode = car.GetActivationCode(); + return car.Size; + } + } +} diff --git a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_original.cs b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_original.cs new file mode 100644 index 0000000000..20a94641c4 --- /dev/null +++ b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_original.cs @@ -0,0 +1,213 @@ +using System.Text; +using Baseline; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Diagnosers; +using Org.SbeTool.Sbe.Dll; + +namespace Org.SbeTool.Sbe.Benchmarks.Bench.Benchmarks +{ + [MemoryDiagnoser] + public class CarBenchmark_with_strings_original + { + + private static readonly Encoding VehicleCodeEncoding = Encoding.GetEncoding(Car.VehicleCodeCharacterEncoding); + private static readonly Encoding ManufacturerCodeEncoding = Encoding.GetEncoding(Engine.ManufacturerCodeCharacterEncoding); + private static readonly Encoding ManufacturerEncoding = Encoding.GetEncoding(Car.ManufacturerCharacterEncoding); + private static readonly Encoding ModelEncoding = Encoding.GetEncoding(Car.ModelCharacterEncoding); + private static readonly Encoding ActivationCodeEncoding = Encoding.GetEncoding(Car.ActivationCodeCharacterEncoding); + private static readonly Encoding UsageDescriptionEncoding = Encoding.GetEncoding(Car.FuelFiguresGroup.UsageDescriptionCharacterEncoding); + + + private readonly byte[] _eBuffer = new byte[1024]; + private readonly byte[] _dBuffer = new byte[1024]; + private DirectBuffer _encodeBuffer; + private DirectBuffer _decodeBuffer; + private readonly Car _car = new Car(); + private readonly MessageHeader _messageHeader = new MessageHeader(); + + [GlobalSetup] + public void Setup() + { + _encodeBuffer = new DirectBuffer(_eBuffer); + _decodeBuffer = new DirectBuffer(_dBuffer); + Encode(_car, _decodeBuffer, 0); + } + + [Benchmark] + public int Encode() + { + return Encode(_car, _encodeBuffer, 0); + } + + [Benchmark] + public int Decode() + { + return Decode(_car, _decodeBuffer, 0); + } + + public int Encode(Car car, DirectBuffer directBuffer, int bufferOffset) + { + _car.WrapForEncodeAndApplyHeader(directBuffer, bufferOffset, _messageHeader); + + const int srcOffset = 0; + + car.SerialNumber = 1234; + car.ModelYear = 2013; + car.Available = BooleanType.T; + car.Code = Baseline.Model.A; + car.SetVehicleCode(VehicleCodeEncoding.GetBytes("CODE12"), 0); + + for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) + { + car.SetSomeNumbers(i, (uint)i); + } + + car.Extras = OptionalExtras.CruiseControl | OptionalExtras.SportsPack; + car.Engine.Capacity = 2000; + car.Engine.NumCylinders = 4; + car.Engine.SetManufacturerCode(ManufacturerCodeEncoding.GetBytes("123"), 0); + car.Engine.Efficiency = 35; + car.Engine.BoosterEnabled = BooleanType.T; + car.Engine.Booster.BoostType = BoostType.NITROUS; + car.Engine.Booster.HorsePower = 200; + + var fuelFigures = car.FuelFiguresCount(3); + fuelFigures.Next(); + fuelFigures.Speed = 30; + fuelFigures.Mpg = 35.9f; + fuelFigures.SetUsageDescription(UsageDescriptionEncoding.GetBytes("Urban Cycle")); + + fuelFigures.Next(); + fuelFigures.Speed = 55; + fuelFigures.Mpg = 49.0f; + fuelFigures.SetUsageDescription(UsageDescriptionEncoding.GetBytes("Combined Cycle")); + + fuelFigures.Next(); + fuelFigures.Speed = 75; + fuelFigures.Mpg = 40.0f; + fuelFigures.SetUsageDescription(UsageDescriptionEncoding.GetBytes("Highway Cycle")); + + Car.PerformanceFiguresGroup perfFigures = car.PerformanceFiguresCount(2); + perfFigures.Next(); + perfFigures.OctaneRating = 95; + + Car.PerformanceFiguresGroup.AccelerationGroup acceleration = perfFigures.AccelerationCount(3).Next(); + acceleration.Mph = 30; + acceleration.Seconds = 4.0f; + + acceleration.Next(); + acceleration.Mph = 60; + acceleration.Seconds = 7.5f; + + acceleration.Next(); + acceleration.Mph = 100; + acceleration.Seconds = 12.2f; + + perfFigures.Next(); + perfFigures.OctaneRating = 99; + acceleration = perfFigures.AccelerationCount(3).Next(); + + acceleration.Mph = 30; + acceleration.Seconds = 3.8f; + + acceleration.Next(); + acceleration.Mph = 60; + acceleration.Seconds = 7.1f; + + acceleration.Next(); + acceleration.Mph = 100; + acceleration.Seconds = 11.8f; + + byte[] Manufacturer = ManufacturerEncoding.GetBytes("Honda"); + byte[] Model = ModelEncoding.GetBytes("Civic VTi"); + byte[] ActivationCode = ActivationCodeEncoding.GetBytes("code"); + + car.SetManufacturer(Manufacturer, srcOffset, Manufacturer.Length); + car.SetModel(Model, srcOffset, Model.Length); + car.SetActivationCode(ActivationCode, srcOffset, ActivationCode.Length); + + return car.Size; + } + + private readonly byte[] _buffer = new byte[128]; + + public int Decode(Car car, DirectBuffer directBuffer, int bufferOffset) + { + _messageHeader.Wrap(directBuffer, bufferOffset, 0); + + car.WrapForDecode(directBuffer, bufferOffset + MessageHeader.Size, _messageHeader.BlockLength, _messageHeader.Version); + + var templateId = Car.TemplateId; + var schemaVersion = Car.SchemaVersion; + var serialNumber = car.SerialNumber; + var modelYear = car.ModelYear; + var available = car.Available; + var code = car.Code; + + for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) + { + var number = car.GetSomeNumbers(i); + } + + var length = car.GetVehicleCode(_buffer, 0); + var vehicleCode = VehicleCodeEncoding.GetString(_buffer, 0, length); + + OptionalExtras extras = car.Extras; + var cruiseControl = (extras & OptionalExtras.CruiseControl) == OptionalExtras.CruiseControl; + var sportsPack = (extras & OptionalExtras.SportsPack) == OptionalExtras.SportsPack; + var sunRoof = (extras & OptionalExtras.SunRoof) == OptionalExtras.SunRoof; + + Engine engine = car.Engine; + var capacity = engine.Capacity; + var numCylinders = engine.NumCylinders; + var maxRpm = engine.MaxRpm; + for (int i = 0, size = Engine.ManufacturerCodeLength; i < size; i++) + { + engine.GetManufacturerCode(i); + } + + length = engine.GetFuel(_buffer, 0, _buffer.Length); + + var efficiency = engine.Efficiency; + var boosterEnabled = engine.BoosterEnabled; + var boostType = engine.Booster.BoostType; + var horsePower = engine.Booster.HorsePower; + + var fuelFiguresGroup = car.FuelFigures; + while (fuelFiguresGroup.HasNext) + { + var fuelFigures = fuelFiguresGroup.Next(); + var speed = fuelFigures.Speed; + var mpg = fuelFigures.Mpg; + length = fuelFigures.GetUsageDescription(_buffer, 0, _buffer.Length); + var fuelUsage = UsageDescriptionEncoding.GetString(_buffer, 0, length); + } + + var performanceFiguresGroup = car.PerformanceFigures; + while (performanceFiguresGroup.HasNext) + { + performanceFiguresGroup.Next(); + var octanceRating = performanceFiguresGroup.OctaneRating; + + var accelerationGroup = performanceFiguresGroup.Acceleration; + for (int i = 0; i < accelerationGroup.Count; i++) + { + var acceleration = accelerationGroup.Next(); + var mpg = acceleration.Mph; + var seconds = acceleration.Seconds; + } + } + + length = car.GetManufacturer(_buffer, 0, _buffer.Length); + var usage = ManufacturerEncoding.GetString(_buffer, 0, length); + + length = car.GetModel(_buffer, 0, _buffer.Length); + usage = ModelEncoding.GetString(_buffer, 0, length); + + length = car.GetActivationCode(_buffer, 0, _buffer.Length); + usage = ActivationCodeEncoding.GetString(_buffer, 0, length); + + return car.Size; + } + } +} diff --git a/csharp/sbe-dll/DirectBuffer.cs b/csharp/sbe-dll/DirectBuffer.cs index e8ef4c012e..f478a481eb 100644 --- a/csharp/sbe-dll/DirectBuffer.cs +++ b/csharp/sbe-dll/DirectBuffer.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using System.Text; namespace Org.SbeTool.Sbe.Dll { @@ -654,6 +655,116 @@ public int SetBytes(int index, ReadOnlySpan src) return count; } + /// + /// Writes a string into the underlying buffer, encoding using the provided . + /// If there is not enough room in the buffer for the bytes it will throw IndexOutOfRangeExcpetion. + /// + /// encoding to use to write the bytes from the string + /// source string + /// index in the underlying buffer to start writing bytes + /// count of bytes written + public unsafe int SetBytesFromString(Encoding encoding, string src, int index) + { + + int available = _capacity - index; + + int byteCount = encoding.GetByteCount(src); + + if (byteCount > available) + { + ThrowHelper.ThrowIndexOutOfRangeException(_capacity); + } + fixed (char* ptr = src) + { + return encoding.GetBytes(ptr, src.Length, _pBuffer + index, byteCount); + } + } + + /// + /// Reads a string from the buffer; converting the bytes to characters using + /// the provided . + /// If there are not enough bytes in the buffer it will throw an IndexOutOfRangeException. + /// + /// encoding to use to convert the bytes into characters + /// index in theunderlying buffer to start writing bytes + /// the number of bytes to read into the string + /// the string representing the decoded bytes read from the buffer + public string GetStringFromBytes(Encoding encoding, int index, int byteCount) + { + int num = _capacity - index; + if (byteCount > num) + { + ThrowHelper.ThrowIndexOutOfRangeException(_capacity); + } + + return new String((sbyte*)_pBuffer, index, byteCount, encoding); + } + + /// + /// Reads a number of bytes from the buffer to create a string, truncating the string if a null byte is found + /// + /// The text encoding to use for string creation + /// index in the underlying buffer to start from + /// The maximum number of bytes to read + /// The null value for this string + /// The created string + public unsafe string GetStringFromNullTerminatedBytes(Encoding encoding, int index, int maxLength, byte nullByte) + { + int count = Math.Min(maxLength, _capacity - index); + if (count <= 0) + { + ThrowHelper.ThrowIndexOutOfRangeException(index); + } + if (_pBuffer[index] == nullByte) + { + return null; + } + int byteCount2 = 0; + for (byteCount2 = 0; byteCount2 < count && _pBuffer[byteCount2 + index] != nullByte; byteCount2++) + { + } + return new String((sbyte*) _pBuffer, index, byteCount2, encoding); + } + + /// + /// Writes a number of bytes into the buffer using the given encoding and string. + /// Note that pre-computing the bytes to be written, when possible, will be quicker than using the encoder to convert on-the-fly. + /// + /// The text encoding to use + /// String to write + /// + /// Maximum number of bytes to write + /// + /// The number of bytes written. + public unsafe int SetNullTerminatedBytesFromString(Encoding encoding, string src, int index, int maxLength, byte nullByte) + { + int available = Math.Min(maxLength, _capacity - index); + if (available <= 0) + { + ThrowHelper.ThrowIndexOutOfRangeException(index); + } + if (src == null) + { + _pBuffer[index] = nullByte; + return 1; + } + int byteCount = encoding.GetByteCount(src); + if (byteCount > available) + { + ThrowHelper.ThrowIndexOutOfRangeException(index + available); + } + fixed (char* ptr = src) + { + encoding.GetBytes(ptr, src.Length, _pBuffer + index, byteCount); + } + if (byteCount < available) + { + *(_pBuffer + index + byteCount) = nullByte; + return byteCount + 1; + } + return byteCount; + } + /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// diff --git a/csharp/sbe-samples-car/CarExample.cs b/csharp/sbe-samples-car/CarExample.cs index 287af0ba04..3a51103d8a 100644 --- a/csharp/sbe-samples-car/CarExample.cs +++ b/csharp/sbe-samples-car/CarExample.cs @@ -65,23 +65,20 @@ namespace Baseline { public static class CarExample { - private static readonly byte[] VehicleCode; private static readonly byte[] ManufacturerCode; - private static readonly byte[] Manufacturer; - private static readonly byte[] Model; private static readonly byte[] ActivationCode; + private static readonly string VehicleCode = "abcdef"; + private static readonly string Model = "Civic VTi"; + private static readonly string Manufacturer = "Honda"; static CarExample() { try { // convert some sample strings to the correct encoding for this sample - VehicleCode = Encoding.GetEncoding(Car.VehicleCodeCharacterEncoding).GetBytes("abcdef"); - ManufacturerCode = Encoding.GetEncoding(Engine.ManufacturerCodeCharacterEncoding).GetBytes("123"); - Manufacturer = Encoding.GetEncoding(Car.ManufacturerCharacterEncoding).GetBytes("Honda"); - Model = Encoding.GetEncoding(Car.ModelCharacterEncoding).GetBytes("Civic VTi"); - ActivationCode = Encoding.GetEncoding(Car.ActivationCodeCharacterEncoding).GetBytes("abcdef"); + ManufacturerCode = Engine.ManufacturerCodeResolvedCharacterEncoding.GetBytes("123"); + ActivationCode = Car.ActivationCodeResolvedCharacterEncoding.GetBytes("abcdef"); } catch (Exception ex) { @@ -99,7 +96,7 @@ public static int Encode(Car car, DirectBuffer directBuffer, int bufferOffset) car.ModelYear = 2013; car.Available = BooleanType.T; // enums are directly supported car.Code = Baseline.Model.A; - car.SetVehicleCode(VehicleCode, srcOffset); // we set a constant string + car.SetVehicleCode(VehicleCode); // we set a constant string for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) { @@ -122,17 +119,17 @@ public static int Encode(Car car, DirectBuffer directBuffer, int bufferOffset) fuelFigures.Next(); // move to the first element fuelFigures.Speed = 30; fuelFigures.Mpg = 35.9f; - fuelFigures.SetUsageDescription(Encoding.GetEncoding(Car.FuelFiguresGroup.UsageDescriptionCharacterEncoding).GetBytes("Urban Cycle")); + fuelFigures.SetUsageDescription("Urban Cycle"); fuelFigures.Next(); // second fuelFigures.Speed = 55; fuelFigures.Mpg = 49.0f; - fuelFigures.SetUsageDescription(Encoding.GetEncoding(Car.FuelFiguresGroup.UsageDescriptionCharacterEncoding).GetBytes("Combined Cycle")); + fuelFigures.SetUsageDescription("Combined Cycle"); fuelFigures.Next(); fuelFigures.Speed = 75; fuelFigures.Mpg = 40.0f; - fuelFigures.SetUsageDescription(Encoding.GetEncoding(Car.FuelFiguresGroup.UsageDescriptionCharacterEncoding).GetBytes("Highway Cycle")); + fuelFigures.SetUsageDescription("Highway Cycle"); Car.PerformanceFiguresGroup perfFigures = car.PerformanceFiguresCount(2); // demonstrates how to create a nested group @@ -168,8 +165,8 @@ public static int Encode(Car car, DirectBuffer directBuffer, int bufferOffset) // once we have written all the repeatable groups we can write the variable length properties (you would use that for strings, byte[], etc) - car.SetManufacturer(Manufacturer, srcOffset, Manufacturer.Length); - car.SetModel(Model, srcOffset, Model.Length); + car.SetManufacturer(Manufacturer); + car.SetModel(Model); car.SetActivationCode(ActivationCode, srcOffset, ActivationCode.Length); return car.Size; @@ -202,9 +199,7 @@ public static void Decode(Car car, } sb.Append("\ncar.vehicleCode="); - var vehicleCode = new byte[Car.VehicleCodeLength]; - car.GetVehicleCode(vehicleCode, 0); - sb.Append(Encoding.GetEncoding(Car.VehicleCodeCharacterEncoding).GetString(vehicleCode, 0, Car.VehicleCodeLength)); + sb.Append(car.GetVehicleCode()); OptionalExtras extras = car.Extras; sb.Append("\ncar.extras.cruiseControl=").Append((extras & OptionalExtras.CruiseControl) == OptionalExtras.CruiseControl); // this is how you can find out if a specific flag is set in a flag enum @@ -237,7 +232,7 @@ public static void Decode(Car car, var fuelFigures = fuelFiguresGroup.Next(); sb.Append("\ncar.fuelFigures.speed=").Append(fuelFigures.Speed); sb.Append("\ncar.fuelFigures.mpg=").Append(fuelFigures.Mpg); - sb.Append("\ncar.fuelFigures.UsageDescription=").Append(Encoding.GetEncoding(Car.FuelFiguresGroup.UsageDescriptionCharacterEncoding).GetString(fuelFigures.GetUsageDescriptionBytes())); + sb.Append("\ncar.fuelFigures.UsageDescription=").Append(fuelFigures.GetUsageDescription()); } // The second way to access a repeating group is to use an iterator @@ -258,13 +253,11 @@ public static void Decode(Car car, // variable length fields sb.Append("\ncar.manufacturer.semanticType=").Append(Car.ManufacturerMetaAttribute(MetaAttribute.SemanticType)); length = car.GetManufacturer(buffer, 0, buffer.Length); - sb.Append("\ncar.manufacturer=").Append(Encoding.GetEncoding(Car.ManufacturerCharacterEncoding).GetString(buffer, 0, length)); + sb.Append("\ncar.manufacturer=").Append(Car.ManufacturerResolvedCharacterEncoding.GetString(buffer, 0, length)); - length = car.GetModel(buffer, 0, buffer.Length); - sb.Append("\ncar.model=").Append(Encoding.GetEncoding(Car.ModelCharacterEncoding).GetString(buffer, 0, length)); + sb.Append("\ncar.model=").Append(car.GetModel()); - length = car.GetActivationCode(buffer, 0, buffer.Length); - sb.Append("\ncar.activationcode=").Append(Encoding.GetEncoding(Car.ActivationCodeCharacterEncoding).GetString(buffer, 0, length)); + sb.Append("\ncar.activationcode=").Append(car.GetActivationCode()); sb.Append("\ncar.size=").Append(car.Size); diff --git a/csharp/sbe-samples-car/sbe-samples-car.csproj b/csharp/sbe-samples-car/sbe-samples-car.csproj index 1ed09464dd..8ee29c2329 100644 --- a/csharp/sbe-samples-car/sbe-samples-car.csproj +++ b/csharp/sbe-samples-car/sbe-samples-car.csproj @@ -2,7 +2,7 @@ net45;netcoreapp3.1 - exe + exe Org.SbeTool.Sbe.Example.Car Org.SbeTool.Sbe.Example.Car diff --git a/csharp/sbe-tests/DirectBufferTests.cs b/csharp/sbe-tests/DirectBufferTests.cs index c42e87ddaf..d189b2917c 100644 --- a/csharp/sbe-tests/DirectBufferTests.cs +++ b/csharp/sbe-tests/DirectBufferTests.cs @@ -13,6 +13,7 @@ // limitations under the License. using System; +using System.Text; using System.Runtime.InteropServices; using Microsoft.VisualStudio.TestTools.UnitTesting; using Org.SbeTool.Sbe.Dll; @@ -620,5 +621,181 @@ public void ShouldGetDoubleBigEndian() } #endregion + + #region NullTerminatedBytesFromString + const byte Terminator = (byte)0; + readonly static Encoding AsciiEncoding = Encoding.UTF8; + + + [TestMethod] + public void ShouldPutStringWithNullTermination() + { + // the string length is less than the max and less than the capacity - should add null terminator + const string value = "abc123"; + const int index = 0; + var written = _directBuffer.SetNullTerminatedBytesFromString(AsciiEncoding, value, index, 100, Terminator); + var read = new byte[written]; + var numBytesWritten = _directBuffer.GetBytes(index, read, 0, written); + Assert.AreEqual(7, numBytesWritten); + Assert.AreEqual(Terminator, read[read.Length - 1]); // should be terminated with the null value + string result = AsciiEncoding.GetString(read); + Assert.AreEqual(value, result.Substring(0, read.Length - 1)); + } + + [TestMethod] + public void ShouldPutStringWitoutNullTerminator() + { + // the string length is equal to the max legth parameter + const string value = "abc123"; + const int index = 0; + var written = _directBuffer.SetNullTerminatedBytesFromString(AsciiEncoding, value, index, value.Length, Terminator); + var read = new byte[written]; + var numBytesWritten = _directBuffer.GetBytes(index, read, 0, written); + Assert.AreEqual(6, numBytesWritten); + Assert.AreNotEqual(Terminator, read[read.Length - 1]); // should NOT be terminated with the null value + string result = AsciiEncoding.GetString(read); + Assert.AreEqual(value, result.Substring(0, read.Length)); + } + + [TestMethod] + public void ShouldPutStringWitoutNullTerminatorIfBytesToWriteEqualsRemainingCapacity() + { + // the string length is equal to the remaining space in the buffer + const string value = "abc123"; + int index = _directBuffer.Capacity - value.Length; + var written = _directBuffer.SetNullTerminatedBytesFromString(AsciiEncoding, value, index, 100, Terminator); + var read = new byte[written]; + var numBytesWritten = _directBuffer.GetBytes(index, read, 0, written); + Assert.AreEqual(6, numBytesWritten); + Assert.AreNotEqual(Terminator, read[read.Length - 1]); // should NOT be terminated with the null value + string result = AsciiEncoding.GetString(read); + Assert.AreEqual(value, result.Substring(0, read.Length)); + } + + + [TestMethod] + public void ShouldThrowIndexOutOfRangeExceptionWhenStringLengthGreaterThanMax() + { + const string value = "abc123"; + const int index = 0; + int maxLength = value.Length - 1; // max length is less than the value length + Assert.ThrowsException(() => _directBuffer.SetNullTerminatedBytesFromString(AsciiEncoding, value, index, maxLength, Terminator)); + } + + + [TestMethod] + public void ShouldThrowIndexOutOfRangeExceptionWhenStringLengthGreaterThanCapacity() + { + const string value = "abc123"; + int index = _directBuffer.Capacity - value.Length + 1; // remaining capacity will be too short to write the string bytes + Assert.ThrowsException(() => _directBuffer.SetNullTerminatedBytesFromString(AsciiEncoding, value, index, 100, Terminator)); + } + + + [TestMethod] + public void ShouldPutNullStringNullTerminated() + { + const string value = null; + + const int index = 0; + var written = _directBuffer.SetNullTerminatedBytesFromString(AsciiEncoding, value, index, 100, Terminator); + var read = new byte[written]; + var len = _directBuffer.GetBytes(index, read, 0, written); + Assert.AreEqual(1, len); + Assert.AreEqual(Terminator, read[read.Length - 1]); + } + + [TestMethod] + public void ShouldPutEmptyStringNullTerminated() + { + const string value = ""; + + const int index = 0; + var written = _directBuffer.SetNullTerminatedBytesFromString(AsciiEncoding, value, index, 100, Terminator); + var read = new byte[written]; + var len = _directBuffer.GetBytes(index, read, 0, written); + Assert.AreEqual(1, len); + Assert.AreEqual(Terminator, read[read.Length - 1]); + } + + + [TestMethod] + public void ShouldGetStringNullTerminated() + { + var encoding = System.Text.Encoding.ASCII; + const string value = "abc123"; + var bytes = encoding.GetBytes(value); + const int index = 0; + var written = _directBuffer.SetBytes(index, bytes, 0, bytes.Length); + Assert.AreEqual(bytes.Length, written); + var written2 = _directBuffer.SetBytes(index + bytes.Length, new byte[] { Terminator }, 0, 1); + Assert.AreEqual(1, written2); + string result = _directBuffer.GetStringFromNullTerminatedBytes(encoding, index, _directBuffer.Capacity - index, Terminator); + Assert.AreEqual(value, result); + } + + [TestMethod] + public void ShouldGetStringWithoutNullTermination() + { + var encoding = System.Text.Encoding.UTF8; + const string value = "abc123"; + var bytes = encoding.GetBytes(value); + const int index = 10; // pushes the write to the end of the buffer so no terminator will be added + var written = _directBuffer.SetBytes(index, bytes, 0, bytes.Length); + Assert.AreEqual(bytes.Length, written); + string result = _directBuffer.GetStringFromNullTerminatedBytes(encoding, index, 100, Terminator); + Assert.AreEqual(value, result); + } + + #endregion + + #region SetBytesFromString + + [TestMethod] + public void ShouldSetBytesFromString() { + const string value = "abc123"; + var written = _directBuffer.SetBytesFromString(AsciiEncoding, value, 0); + Assert.AreEqual(6, written); + string result = _directBuffer.GetStringFromBytes(AsciiEncoding, 0, 6); + Assert.AreEqual(value, result); + } + + [TestMethod] + public void ShouldSetZeroBytesFromEmptyString() { + const string value = ""; + var written = _directBuffer.SetBytesFromString(AsciiEncoding, value, 0); + Assert.AreEqual(0, written); + string result = _directBuffer.GetStringFromBytes(AsciiEncoding, 0, 0); + Assert.AreEqual(value, result); + } + + + [TestMethod] + public void ShouldThrowExceptionIfNotEnoughRoomInBufferForBytes() { + const string value = "a"; + Assert.ThrowsException(() => _directBuffer.SetBytesFromString(AsciiEncoding, value, _directBuffer.Capacity - value.Length + 1)); + } + + + #endregion + + #region GetStringFromBytes + + [TestMethod] + public void ShouldGetStringFromBytes() { + const string value = "abc123"; + _directBuffer.SetBytesFromString(AsciiEncoding, value, 0); + string result = _directBuffer.GetStringFromBytes(AsciiEncoding, 0, AsciiEncoding.GetByteCount(value)); + Assert.AreEqual(value, result); + } + + [TestMethod] + public void ShouldThrowExceptionIfNotEnoughBytesToGetStringFromBytes() { + Assert.ThrowsException(() => _directBuffer.GetStringFromBytes(AsciiEncoding, _directBuffer.Capacity, 1)); + } + + #endregion } + + } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 3a0fbba366..92a39844f5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -30,6 +30,8 @@ import java.util.ArrayList; import java.util.List; +import static java.lang.System.lineSeparator; + import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; import static uk.co.real_logic.sbe.generation.csharp.CSharpUtil.*; @@ -478,6 +480,30 @@ private CharSequence generateVarData(final List tokens, final String inde lengthTypePrefix, lengthCSharpType, byteOrderStr)); + + sb.append(lineSeparator()) + .append(String.format( + indent + "public string Get%1$s()\n" + + indent + "{\n" + + indent + INDENT + "const int sizeOfLengthField = %2$d;\n" + + indent + INDENT + "int limit = _parentMessage.Limit;\n" + + indent + INDENT + "_buffer.CheckLimit(limit + sizeOfLengthField);\n" + + indent + INDENT + "int dataLength = (int)_buffer.%3$sGet%4$s(limit);\n" + + indent + INDENT + "_parentMessage.Limit = limit + sizeOfLengthField + dataLength;\n" + + indent + INDENT + "return _buffer.GetStringFromBytes(%1$sResolvedCharacterEncoding," + + " limit + sizeOfLengthField, dataLength);\n" + + indent + "}\n\n" + + indent + "public void Set%1$s(string value)\n" + + indent + "{\n" + + indent + INDENT + "var encoding = %1$sResolvedCharacterEncoding;\n" + + indent + INDENT + "const int sizeOfLengthField = %2$d;\n" + + indent + INDENT + "int limit = _parentMessage.Limit;\n" + + indent + INDENT + "int byteCount = _buffer.SetBytesFromString(encoding, value, " + + "limit + sizeOfLengthField);\n" + + indent + INDENT + "_parentMessage.Limit = limit + sizeOfLengthField + byteCount;\n" + + indent + INDENT + "_buffer.%3$sPut%4$s(limit, (ushort)byteCount);\n" + + indent + "}\n", + propertyName, sizeOfLengthField, lengthTypePrefix, byteOrderStr)); } } @@ -638,6 +664,7 @@ private CharSequence generateFileHeader(final String packageName) "// \n\n" + "#pragma warning disable 1591 // disable warning on missing comments\n" + "using System;\n" + + "using System.Text;\n" + "using Org.SbeTool.Sbe.Dll;\n\n" + "namespace %s\n" + "{\n", @@ -978,6 +1005,19 @@ private CharSequence generateArrayProperty( indent + INDENT + "_buffer.SetBytes(_offset + %3$d, src);\n" + indent + "}\n", propName, fieldLength, offset)); + + sb.append(String.format("\n" + + indent + "public void Set%1$s(string value)\n" + + indent + "{\n" + + indent + INDENT + "_buffer.SetNullTerminatedBytesFromString(%1$sResolvedCharacterEncoding, " + + "value, _offset + %2$s, %1$sLength, %1$sNullValue);\n" + + indent + "}\n" + + indent + "public string Get%1$s()\n" + + indent + "{\n" + + indent + INDENT + "return _buffer.GetStringFromNullTerminatedBytes(%1$sResolvedCharacterEncoding, " + + "_offset + %2$s, %1$sLength, %1$sNullValue);\n" + + indent + "}\n", + propName, offset)); } return sb; @@ -990,7 +1030,9 @@ private void generateCharacterEncodingMethod( final String indent) { sb.append(String.format("\n" + - indent + "public const string %sCharacterEncoding = \"%s\";\n\n", + indent + "public const string %1$sCharacterEncoding = \"%2$s\";\n" + + indent + "public static Encoding %1$sResolvedCharacterEncoding = " + + "Encoding.GetEncoding(%1$sCharacterEncoding);\n\n", formatPropertyName(propertyName), encoding)); } From 43ee6581662fb21a348d39b4f7888880053b703b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 25 May 2021 15:18:21 +0100 Subject: [PATCH 0701/1594] [C#] Tidy up after merge of PR #845. --- .../sbe-benchmarks/Bench/SBE/CarBenchmark.cs | 2 +- .../SBE/CarBenchmark_with_strings_new.cs | 4 +- .../SBE/CarBenchmark_with_strings_original.cs | 4 +- .../Bench/SBE/MarketDataBenchmark.cs | 2 +- csharp/sbe-dll/DirectBuffer.cs | 15 +- csharp/sbe-dll/EndianessConverter.cs | 3 +- csharp/sbe-dll/PrimitiveType.cs | 2 +- csharp/sbe-dll/PrimitiveValue.cs | 3 +- csharp/sbe-dll/SbePrimitiveType.cs | 2 +- csharp/sbe-dll/sbe-tool.sh | 1 - csharp/sbe-tests/DirectBufferTests.cs | 362 +++++++++--------- csharp/sbe-tests/Issue435Tests.cs | 2 +- csharp/sbe-tests/Issue483Tests.cs | 1 - csharp/sbe-tests/Issue560Tests.cs | 2 +- 14 files changed, 203 insertions(+), 202 deletions(-) diff --git a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark.cs b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark.cs index d0ba027173..3b6863f711 100644 --- a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark.cs +++ b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark.cs @@ -184,7 +184,7 @@ public int Decode(Car car, DirectBuffer directBuffer, int bufferOffset) while (performanceFiguresGroup.HasNext) { performanceFiguresGroup.Next(); - var octanceRating = performanceFiguresGroup.OctaneRating; + var octaneRating = performanceFiguresGroup.OctaneRating; var accelerationGroup = performanceFiguresGroup.Acceleration; for (int i = 0; i < accelerationGroup.Count; i++) diff --git a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_new.cs b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_new.cs index d3badedd18..afdb71ee98 100644 --- a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_new.cs +++ b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_new.cs @@ -9,7 +9,6 @@ namespace Org.SbeTool.Sbe.Benchmarks.Bench.Benchmarks [MemoryDiagnoser] public class CarBenchmark_with_strings_new { - private readonly byte[] _eBuffer = new byte[1024]; private readonly byte[] _dBuffer = new byte[1024]; private DirectBuffer _encodeBuffer; @@ -173,7 +172,7 @@ public int Decode(Car car, DirectBuffer directBuffer, int bufferOffset) while (performanceFiguresGroup.HasNext) { performanceFiguresGroup.Next(); - var octanceRating = performanceFiguresGroup.OctaneRating; + var octaneRating = performanceFiguresGroup.OctaneRating; var accelerationGroup = performanceFiguresGroup.Acceleration; for (int i = 0; i < accelerationGroup.Count; i++) @@ -187,6 +186,7 @@ public int Decode(Car car, DirectBuffer directBuffer, int bufferOffset) var man = car.GetManufacturer(); var model = car.GetModel(); var actCode = car.GetActivationCode(); + return car.Size; } } diff --git a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_original.cs b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_original.cs index 20a94641c4..eb5ebdff51 100644 --- a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_original.cs +++ b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_original.cs @@ -9,7 +9,6 @@ namespace Org.SbeTool.Sbe.Benchmarks.Bench.Benchmarks [MemoryDiagnoser] public class CarBenchmark_with_strings_original { - private static readonly Encoding VehicleCodeEncoding = Encoding.GetEncoding(Car.VehicleCodeCharacterEncoding); private static readonly Encoding ManufacturerCodeEncoding = Encoding.GetEncoding(Engine.ManufacturerCodeCharacterEncoding); private static readonly Encoding ManufacturerEncoding = Encoding.GetEncoding(Car.ManufacturerCharacterEncoding); @@ -17,7 +16,6 @@ public class CarBenchmark_with_strings_original private static readonly Encoding ActivationCodeEncoding = Encoding.GetEncoding(Car.ActivationCodeCharacterEncoding); private static readonly Encoding UsageDescriptionEncoding = Encoding.GetEncoding(Car.FuelFiguresGroup.UsageDescriptionCharacterEncoding); - private readonly byte[] _eBuffer = new byte[1024]; private readonly byte[] _dBuffer = new byte[1024]; private DirectBuffer _encodeBuffer; @@ -187,7 +185,7 @@ public int Decode(Car car, DirectBuffer directBuffer, int bufferOffset) while (performanceFiguresGroup.HasNext) { performanceFiguresGroup.Next(); - var octanceRating = performanceFiguresGroup.OctaneRating; + var octaneRating = performanceFiguresGroup.OctaneRating; var accelerationGroup = performanceFiguresGroup.Acceleration; for (int i = 0; i < accelerationGroup.Count; i++) diff --git a/csharp/sbe-benchmarks/Bench/SBE/MarketDataBenchmark.cs b/csharp/sbe-benchmarks/Bench/SBE/MarketDataBenchmark.cs index 79be30bf68..437032869c 100644 --- a/csharp/sbe-benchmarks/Bench/SBE/MarketDataBenchmark.cs +++ b/csharp/sbe-benchmarks/Bench/SBE/MarketDataBenchmark.cs @@ -103,4 +103,4 @@ public int Decode(DirectBuffer buffer, int bufferOffset) return _marketData.Size; } } -} \ No newline at end of file +} diff --git a/csharp/sbe-dll/DirectBuffer.cs b/csharp/sbe-dll/DirectBuffer.cs index f478a481eb..52b78ea4af 100644 --- a/csharp/sbe-dll/DirectBuffer.cs +++ b/csharp/sbe-dll/DirectBuffer.cs @@ -657,7 +657,7 @@ public int SetBytes(int index, ReadOnlySpan src) /// /// Writes a string into the underlying buffer, encoding using the provided . - /// If there is not enough room in the buffer for the bytes it will throw IndexOutOfRangeExcpetion. + /// If there is not enough room in the buffer for the bytes it will throw IndexOutOfRangeException. /// /// encoding to use to write the bytes from the string /// source string @@ -665,15 +665,14 @@ public int SetBytes(int index, ReadOnlySpan src) /// count of bytes written public unsafe int SetBytesFromString(Encoding encoding, string src, int index) { - int available = _capacity - index; - int byteCount = encoding.GetByteCount(src); if (byteCount > available) { ThrowHelper.ThrowIndexOutOfRangeException(_capacity); } + fixed (char* ptr = src) { return encoding.GetBytes(ptr, src.Length, _pBuffer + index, byteCount); @@ -686,7 +685,7 @@ public unsafe int SetBytesFromString(Encoding encoding, string src, int index) /// If there are not enough bytes in the buffer it will throw an IndexOutOfRangeException. ///
    /// encoding to use to convert the bytes into characters - /// index in theunderlying buffer to start writing bytes + /// index in the underlying buffer to start writing bytes /// the number of bytes to read into the string /// the string representing the decoded bytes read from the buffer public string GetStringFromBytes(Encoding encoding, int index, int byteCount) @@ -715,14 +714,17 @@ public unsafe string GetStringFromNullTerminatedBytes(Encoding encoding, int ind { ThrowHelper.ThrowIndexOutOfRangeException(index); } + if (_pBuffer[index] == nullByte) { return null; } + int byteCount2 = 0; for (byteCount2 = 0; byteCount2 < count && _pBuffer[byteCount2 + index] != nullByte; byteCount2++) { } + return new String((sbyte*) _pBuffer, index, byteCount2, encoding); } @@ -743,25 +745,30 @@ public unsafe int SetNullTerminatedBytesFromString(Encoding encoding, string src { ThrowHelper.ThrowIndexOutOfRangeException(index); } + if (src == null) { _pBuffer[index] = nullByte; return 1; } + int byteCount = encoding.GetByteCount(src); if (byteCount > available) { ThrowHelper.ThrowIndexOutOfRangeException(index + available); } + fixed (char* ptr = src) { encoding.GetBytes(ptr, src.Length, _pBuffer + index, byteCount); } + if (byteCount < available) { *(_pBuffer + index + byteCount) = nullByte; return byteCount + 1; } + return byteCount; } diff --git a/csharp/sbe-dll/EndianessConverter.cs b/csharp/sbe-dll/EndianessConverter.cs index 6046e69d85..bd090c6f8f 100644 --- a/csharp/sbe-dll/EndianessConverter.cs +++ b/csharp/sbe-dll/EndianessConverter.cs @@ -8,7 +8,8 @@ namespace Org.SbeTool.Sbe.Dll /// public static class EndianessConverter { - // TODO: we could assume the system is always little endian and have two methods for each (one no-op and another one which reverse, so we do not have branching) + // TODO: we could assume the system is always little endian and have two methods for each + // TODO: (one no-op and another one which reverse, so we do not have branching) private static readonly ByteOrder NativeByteOrder = BitConverter.IsLittleEndian ? ByteOrder.LittleEndian diff --git a/csharp/sbe-dll/PrimitiveType.cs b/csharp/sbe-dll/PrimitiveType.cs index 682d46cc9b..5643f747ea 100644 --- a/csharp/sbe-dll/PrimitiveType.cs +++ b/csharp/sbe-dll/PrimitiveType.cs @@ -208,4 +208,4 @@ public SbePrimitiveType Type get { return _sbePrimitiveType; } } } -} \ No newline at end of file +} diff --git a/csharp/sbe-dll/PrimitiveValue.cs b/csharp/sbe-dll/PrimitiveValue.cs index 2f592130e4..01d57bc1fd 100644 --- a/csharp/sbe-dll/PrimitiveValue.cs +++ b/csharp/sbe-dll/PrimitiveValue.cs @@ -104,7 +104,6 @@ private enum Representation #endregion - /// /// Minimum value for INT8 SBE type /// @@ -537,4 +536,4 @@ public override int GetHashCode() } } } -} \ No newline at end of file +} diff --git a/csharp/sbe-dll/SbePrimitiveType.cs b/csharp/sbe-dll/SbePrimitiveType.cs index a16defd1dc..cb499a7301 100644 --- a/csharp/sbe-dll/SbePrimitiveType.cs +++ b/csharp/sbe-dll/SbePrimitiveType.cs @@ -60,4 +60,4 @@ public enum SbePrimitiveType /// Double } -} \ No newline at end of file +} diff --git a/csharp/sbe-dll/sbe-tool.sh b/csharp/sbe-dll/sbe-tool.sh index 99ea957e46..2e35d82257 100644 --- a/csharp/sbe-dll/sbe-tool.sh +++ b/csharp/sbe-dll/sbe-tool.sh @@ -3,7 +3,6 @@ ROOTDIR=$(dirname ${0}) SBE_JAR=${ROOTDIR}/sbe-tool-all.jar - [ -f "${SBE_JAR}" ] || (echo "Missing ${SBE_JAR}"; exit 1) function usage { diff --git a/csharp/sbe-tests/DirectBufferTests.cs b/csharp/sbe-tests/DirectBufferTests.cs index d189b2917c..2ac82e4e07 100644 --- a/csharp/sbe-tests/DirectBufferTests.cs +++ b/csharp/sbe-tests/DirectBufferTests.cs @@ -416,220 +416,219 @@ public void ShouldGetUInt16BigEndian() #region UInt32 - [TestMethod] - public void ShouldPutUInt32LittleEndian() - { - const uint value = 5; - const int index = 0; - _directBuffer.Uint32PutLittleEndian(index, value); + [TestMethod] + public void ShouldPutUInt32LittleEndian() + { + const uint value = 5; + const int index = 0; + _directBuffer.Uint32PutLittleEndian(index, value); - Assert.AreEqual(value, *(uint*)(_pBuffer + index)); - } + Assert.AreEqual(value, *(uint*)(_pBuffer + index)); + } - [TestMethod] - public void ShouldPutUInt32BigEndian() - { - const uint value = 5; - const int index = 0; - _directBuffer.Uint32PutBigEndian(index, value); + [TestMethod] + public void ShouldPutUInt32BigEndian() + { + const uint value = 5; + const int index = 0; + _directBuffer.Uint32PutBigEndian(index, value); - var expected = EndianessConverter.ApplyUint32(ByteOrder.BigEndian, value); - Assert.AreEqual(expected, *(uint*)(_pBuffer + index)); - } + var expected = EndianessConverter.ApplyUint32(ByteOrder.BigEndian, value); + Assert.AreEqual(expected, *(uint*)(_pBuffer + index)); + } - [TestMethod] - public void ShouldGetUInt32LittleEndian() - { - const uint value = 5; - const int index = 0; - var bytes = BitConverter.GetBytes(value); - Array.Copy(bytes, 0, _buffer, index, 4); + [TestMethod] + public void ShouldGetUInt32LittleEndian() + { + const uint value = 5; + const int index = 0; + var bytes = BitConverter.GetBytes(value); + Array.Copy(bytes, 0, _buffer, index, 4); - var result = _directBuffer.Uint32GetLittleEndian(index); + var result = _directBuffer.Uint32GetLittleEndian(index); - Assert.AreEqual(value, result); - } + Assert.AreEqual(value, result); + } - [TestMethod] - public void ShouldGetUInt32BigEndian() - { - const uint value = 5; - const int index = 0; - var bytes = BitConverter.GetBytes(value); - Array.Copy(bytes, 0, _buffer, index, 4); + [TestMethod] + public void ShouldGetUInt32BigEndian() + { + const uint value = 5; + const int index = 0; + var bytes = BitConverter.GetBytes(value); + Array.Copy(bytes, 0, _buffer, index, 4); - var result = _directBuffer.Uint32GetBigEndian(index); + var result = _directBuffer.Uint32GetBigEndian(index); - var expected = EndianessConverter.ApplyUint32(ByteOrder.BigEndian, value); - Assert.AreEqual(expected, result); - } + var expected = EndianessConverter.ApplyUint32(ByteOrder.BigEndian, value); + Assert.AreEqual(expected, result); + } - #endregion + #endregion #region UInt64 - [TestMethod] - public void ShouldPutUInt64LittleEndian() - { - const ulong value = ulong.MaxValue - 1; - const int index = 0; - _directBuffer.Uint64PutLittleEndian(index, value); + [TestMethod] + public void ShouldPutUInt64LittleEndian() + { + const ulong value = ulong.MaxValue - 1; + const int index = 0; + _directBuffer.Uint64PutLittleEndian(index, value); - Assert.AreEqual(value, *(ulong*)(_pBuffer + index)); - } + Assert.AreEqual(value, *(ulong*)(_pBuffer + index)); + } - [TestMethod] - public void ShouldPutUInt64BigEndian() - { - const ulong value = ulong.MaxValue - 1; - const int index = 0; - _directBuffer.Uint64PutBigEndian(index, value); + [TestMethod] + public void ShouldPutUInt64BigEndian() + { + const ulong value = ulong.MaxValue - 1; + const int index = 0; + _directBuffer.Uint64PutBigEndian(index, value); - var expected = EndianessConverter.ApplyUint64(ByteOrder.BigEndian, value); - Assert.AreEqual(expected, *(ulong*)(_pBuffer + index)); - } + var expected = EndianessConverter.ApplyUint64(ByteOrder.BigEndian, value); + Assert.AreEqual(expected, *(ulong*)(_pBuffer + index)); + } - [TestMethod] - public void ShouldGetUInt64LittleEndian() - { - const ulong value = ulong.MaxValue - 1; - const int index = 0; - var bytes = BitConverter.GetBytes(value); - Array.Copy(bytes, 0, _buffer, index, 8); + [TestMethod] + public void ShouldGetUInt64LittleEndian() + { + const ulong value = ulong.MaxValue - 1; + const int index = 0; + var bytes = BitConverter.GetBytes(value); + Array.Copy(bytes, 0, _buffer, index, 8); - var result = _directBuffer.Uint64GetLittleEndian(index); + var result = _directBuffer.Uint64GetLittleEndian(index); - Assert.AreEqual(value, result); - } + Assert.AreEqual(value, result); + } - [TestMethod] - public void ShouldGetUInt64BigEndian() - { - const ulong value = ulong.MaxValue - 1; - const int index = 0; - var bytes = BitConverter.GetBytes(value); - Array.Copy(bytes, 0, _buffer, index, 8); + [TestMethod] + public void ShouldGetUInt64BigEndian() + { + const ulong value = ulong.MaxValue - 1; + const int index = 0; + var bytes = BitConverter.GetBytes(value); + Array.Copy(bytes, 0, _buffer, index, 8); - var result = _directBuffer.Uint64GetBigEndian(index); + var result = _directBuffer.Uint64GetBigEndian(index); - var expected = EndianessConverter.ApplyUint64(ByteOrder.BigEndian, value); - Assert.AreEqual(expected, result); - } + var expected = EndianessConverter.ApplyUint64(ByteOrder.BigEndian, value); + Assert.AreEqual(expected, result); + } - #endregion + #endregion #region Float - [TestMethod] - public void ShouldPutFloatLittleEndian() - { - const float value = float.MaxValue - 1; - const int index = 0; - _directBuffer.FloatPutLittleEndian(index, value); + [TestMethod] + public void ShouldPutFloatLittleEndian() + { + const float value = float.MaxValue - 1; + const int index = 0; + _directBuffer.FloatPutLittleEndian(index, value); - Assert.AreEqual(value, *(float*)(_pBuffer + index)); - } + Assert.AreEqual(value, *(float*)(_pBuffer + index)); + } - [TestMethod] - public void ShouldPutFloatBigEndian() - { - const float value = float.MaxValue - 1; - const int index = 0; - _directBuffer.FloatPutBigEndian(index, value); + [TestMethod] + public void ShouldPutFloatBigEndian() + { + const float value = float.MaxValue - 1; + const int index = 0; + _directBuffer.FloatPutBigEndian(index, value); - var expected = EndianessConverter.ApplyFloat(ByteOrder.BigEndian, value); - Assert.AreEqual(expected, *(float*)(_pBuffer + index)); - } + var expected = EndianessConverter.ApplyFloat(ByteOrder.BigEndian, value); + Assert.AreEqual(expected, *(float*)(_pBuffer + index)); + } - [TestMethod] - public void ShouldGetFloatLittleEndian() - { - const float value = float.MaxValue - 1; - const int index = 0; - var bytes = BitConverter.GetBytes(value); - Array.Copy(bytes, 0, _buffer, index, 4); + [TestMethod] + public void ShouldGetFloatLittleEndian() + { + const float value = float.MaxValue - 1; + const int index = 0; + var bytes = BitConverter.GetBytes(value); + Array.Copy(bytes, 0, _buffer, index, 4); - var result = _directBuffer.FloatGetLittleEndian(index); + var result = _directBuffer.FloatGetLittleEndian(index); - Assert.AreEqual(value, result); - } + Assert.AreEqual(value, result); + } - [TestMethod] - public void ShouldGetFloatBigEndian() - { - const float value = float.MaxValue - 1; - const int index = 0; - var bytes = BitConverter.GetBytes(value); - Array.Copy(bytes, 0, _buffer, index, 4); + [TestMethod] + public void ShouldGetFloatBigEndian() + { + const float value = float.MaxValue - 1; + const int index = 0; + var bytes = BitConverter.GetBytes(value); + Array.Copy(bytes, 0, _buffer, index, 4); - var result = _directBuffer.FloatGetBigEndian(index); + var result = _directBuffer.FloatGetBigEndian(index); - var expected = EndianessConverter.ApplyFloat(ByteOrder.BigEndian, value); - Assert.AreEqual(expected, result); - } + var expected = EndianessConverter.ApplyFloat(ByteOrder.BigEndian, value); + Assert.AreEqual(expected, result); + } - #endregion + #endregion #region Double - [TestMethod] - public void ShouldPutDoubleLittleEndian() - { - const double value = double.MaxValue - 1; - const int index = 0; - _directBuffer.DoublePutLittleEndian(index, value); - - Assert.AreEqual(value, *(double*)(_pBuffer + index)); - } + [TestMethod] + public void ShouldPutDoubleLittleEndian() + { + const double value = double.MaxValue - 1; + const int index = 0; + _directBuffer.DoublePutLittleEndian(index, value); - [TestMethod] - public void ShouldPutDoubleBigEndian() - { - const double value = double.MaxValue - 1; - const int index = 0; - _directBuffer.DoublePutBigEndian(index, value); + Assert.AreEqual(value, *(double*)(_pBuffer + index)); + } - var expected = EndianessConverter.ApplyDouble(ByteOrder.BigEndian, value); - Assert.AreEqual(expected, *(double*)(_pBuffer + index)); - } + [TestMethod] + public void ShouldPutDoubleBigEndian() + { + const double value = double.MaxValue - 1; + const int index = 0; + _directBuffer.DoublePutBigEndian(index, value); - [TestMethod] - public void ShouldGetDoubleLittleEndian() - { - const double value = double.MaxValue - 1; - const int index = 0; - var bytes = BitConverter.GetBytes(value); - Array.Copy(bytes, 0, _buffer, index, 8); + var expected = EndianessConverter.ApplyDouble(ByteOrder.BigEndian, value); + Assert.AreEqual(expected, *(double*)(_pBuffer + index)); + } - var result = _directBuffer.DoubleGetLittleEndian(index); + [TestMethod] + public void ShouldGetDoubleLittleEndian() + { + const double value = double.MaxValue - 1; + const int index = 0; + var bytes = BitConverter.GetBytes(value); + Array.Copy(bytes, 0, _buffer, index, 8); - Assert.AreEqual(value, result); - } + var result = _directBuffer.DoubleGetLittleEndian(index); - [TestMethod] - public void ShouldGetDoubleBigEndian() - { - const double value = double.MaxValue - 1; - const int index = 0; - var bytes = BitConverter.GetBytes(value); - Array.Copy(bytes, 0, _buffer, index, 8); + Assert.AreEqual(value, result); + } - var result = _directBuffer.DoubleGetBigEndian(index); + [TestMethod] + public void ShouldGetDoubleBigEndian() + { + const double value = double.MaxValue - 1; + const int index = 0; + var bytes = BitConverter.GetBytes(value); + Array.Copy(bytes, 0, _buffer, index, 8); - var expected = EndianessConverter.ApplyDouble(ByteOrder.BigEndian, value); - Assert.AreEqual(expected, result); - } + var result = _directBuffer.DoubleGetBigEndian(index); - #endregion + var expected = EndianessConverter.ApplyDouble(ByteOrder.BigEndian, value); + Assert.AreEqual(expected, result); + } - #region NullTerminatedBytesFromString - const byte Terminator = (byte)0; - readonly static Encoding AsciiEncoding = Encoding.UTF8; + #endregion + #region NullTerminatedBytesFromString + const byte Terminator = (byte)0; + readonly static Encoding AsciiEncoding = Encoding.UTF8; - [TestMethod] - public void ShouldPutStringWithNullTermination() - { + [TestMethod] + public void ShouldPutStringWithNullTermination() + { // the string length is less than the max and less than the capacity - should add null terminator const string value = "abc123"; const int index = 0; @@ -643,9 +642,9 @@ public void ShouldPutStringWithNullTermination() } [TestMethod] - public void ShouldPutStringWitoutNullTerminator() + public void ShouldPutStringWithoutNullTerminator() { - // the string length is equal to the max legth parameter + // the string length is equal to the max length parameter const string value = "abc123"; const int index = 0; var written = _directBuffer.SetNullTerminatedBytesFromString(AsciiEncoding, value, index, value.Length, Terminator); @@ -658,7 +657,7 @@ public void ShouldPutStringWitoutNullTerminator() } [TestMethod] - public void ShouldPutStringWitoutNullTerminatorIfBytesToWriteEqualsRemainingCapacity() + public void ShouldPutStringWithoutNullTerminatorIfBytesToWriteEqualsRemainingCapacity() { // the string length is equal to the remaining space in the buffer const string value = "abc123"; @@ -672,7 +671,6 @@ public void ShouldPutStringWitoutNullTerminatorIfBytesToWriteEqualsRemainingCapa Assert.AreEqual(value, result.Substring(0, read.Length)); } - [TestMethod] public void ShouldThrowIndexOutOfRangeExceptionWhenStringLengthGreaterThanMax() { @@ -682,7 +680,6 @@ public void ShouldThrowIndexOutOfRangeExceptionWhenStringLengthGreaterThanMax() Assert.ThrowsException(() => _directBuffer.SetNullTerminatedBytesFromString(AsciiEncoding, value, index, maxLength, Terminator)); } - [TestMethod] public void ShouldThrowIndexOutOfRangeExceptionWhenStringLengthGreaterThanCapacity() { @@ -691,7 +688,6 @@ public void ShouldThrowIndexOutOfRangeExceptionWhenStringLengthGreaterThanCapaci Assert.ThrowsException(() => _directBuffer.SetNullTerminatedBytesFromString(AsciiEncoding, value, index, 100, Terminator)); } - [TestMethod] public void ShouldPutNullStringNullTerminated() { @@ -728,7 +724,7 @@ public void ShouldGetStringNullTerminated() const int index = 0; var written = _directBuffer.SetBytes(index, bytes, 0, bytes.Length); Assert.AreEqual(bytes.Length, written); - var written2 = _directBuffer.SetBytes(index + bytes.Length, new byte[] { Terminator }, 0, 1); + var written2 = _directBuffer.SetBytes(index + bytes.Length, new byte[]{ Terminator }, 0, 1); Assert.AreEqual(1, written2); string result = _directBuffer.GetStringFromNullTerminatedBytes(encoding, index, _directBuffer.Capacity - index, Terminator); Assert.AreEqual(value, result); @@ -752,7 +748,8 @@ public void ShouldGetStringWithoutNullTermination() #region SetBytesFromString [TestMethod] - public void ShouldSetBytesFromString() { + public void ShouldSetBytesFromString() + { const string value = "abc123"; var written = _directBuffer.SetBytesFromString(AsciiEncoding, value, 0); Assert.AreEqual(6, written); @@ -760,8 +757,9 @@ public void ShouldSetBytesFromString() { Assert.AreEqual(value, result); } - [TestMethod] - public void ShouldSetZeroBytesFromEmptyString() { + [TestMethod] + public void ShouldSetZeroBytesFromEmptyString() + { const string value = ""; var written = _directBuffer.SetBytesFromString(AsciiEncoding, value, 0); Assert.AreEqual(0, written); @@ -770,32 +768,32 @@ public void ShouldSetZeroBytesFromEmptyString() { } - [TestMethod] - public void ShouldThrowExceptionIfNotEnoughRoomInBufferForBytes() { + [TestMethod] + public void ShouldThrowExceptionIfNotEnoughRoomInBufferForBytes() + { const string value = "a"; Assert.ThrowsException(() => _directBuffer.SetBytesFromString(AsciiEncoding, value, _directBuffer.Capacity - value.Length + 1)); } - #endregion #region GetStringFromBytes - [TestMethod] - public void ShouldGetStringFromBytes() { + [TestMethod] + public void ShouldGetStringFromBytes() + { const string value = "abc123"; _directBuffer.SetBytesFromString(AsciiEncoding, value, 0); string result = _directBuffer.GetStringFromBytes(AsciiEncoding, 0, AsciiEncoding.GetByteCount(value)); Assert.AreEqual(value, result); } - [TestMethod] - public void ShouldThrowExceptionIfNotEnoughBytesToGetStringFromBytes() { + [TestMethod] + public void ShouldThrowExceptionIfNotEnoughBytesToGetStringFromBytes() + { Assert.ThrowsException(() => _directBuffer.GetStringFromBytes(AsciiEncoding, _directBuffer.Capacity, 1)); } #endregion } - - } diff --git a/csharp/sbe-tests/Issue435Tests.cs b/csharp/sbe-tests/Issue435Tests.cs index b72a190d91..9f67c3734d 100644 --- a/csharp/sbe-tests/Issue435Tests.cs +++ b/csharp/sbe-tests/Issue435Tests.cs @@ -60,7 +60,7 @@ public void Issue435RefTest() _issue435.Example.E = Issue435.EnumRef.Two; // Check size is normal eight bytes plus one extra for S - Assert.IsTrue(Issue435.Issue435.BlockLength == 1, "Issue435 size has unexpected blocklength"); + Assert.IsTrue(Issue435.Issue435.BlockLength == 1, "Issue435 size has unexpected BlockLength"); // Now let's decode _messageHeader.Wrap(_directBuffer, 0, Issue435.Issue435.SchemaVersion); diff --git a/csharp/sbe-tests/Issue483Tests.cs b/csharp/sbe-tests/Issue483Tests.cs index 4a6cc78b84..f9e41041ba 100644 --- a/csharp/sbe-tests/Issue483Tests.cs +++ b/csharp/sbe-tests/Issue483Tests.cs @@ -39,6 +39,5 @@ public void PresenceTest() Assert.AreEqual(Issue483.Issue483.ConstantMetaAttribute(Issue483.MetaAttribute.Presence), "constant"); Assert.AreEqual(Issue483.Issue483.OptionalMetaAttribute(Issue483.MetaAttribute.Presence), "optional"); } - } } diff --git a/csharp/sbe-tests/Issue560Tests.cs b/csharp/sbe-tests/Issue560Tests.cs index 1d42db09bb..bed7367ba0 100644 --- a/csharp/sbe-tests/Issue560Tests.cs +++ b/csharp/sbe-tests/Issue560Tests.cs @@ -49,6 +49,6 @@ public void Issue560Test() { Assert.AreEqual(_issue560.DiscountedModel, Issue560.Model.C, "Incorrect const enum valueref"); } - += } } From 3af940419038aa706675990ea7bc447ef0dcdd3b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 25 May 2021 15:22:28 +0100 Subject: [PATCH 0702/1594] [C#] Fix typo. --- csharp/sbe-tests/Issue560Tests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/csharp/sbe-tests/Issue560Tests.cs b/csharp/sbe-tests/Issue560Tests.cs index bed7367ba0..7f85f5963d 100644 --- a/csharp/sbe-tests/Issue560Tests.cs +++ b/csharp/sbe-tests/Issue560Tests.cs @@ -49,6 +49,5 @@ public void Issue560Test() { Assert.AreEqual(_issue560.DiscountedModel, Issue560.Model.C, "Incorrect const enum valueref"); } -= } } From c6548d2a1bb9d1b451966940eac40e9af0f2e98e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 26 May 2021 19:16:02 +0100 Subject: [PATCH 0703/1594] [Java] Upgrade to JMH 1.32. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 689848c27f..e647c2b184 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.10.0' def byteBuddyVersion = '1.11.0' def junitVersion = '5.7.2' -def jmhVersion = '1.31' +def jmhVersion = '1.32' def agronaVersion = '1.10.0' def agronaVersionRange = '[1.10,1.11[' // allow any patch release of 1.10.x From 672ee738881f6ea88f53f98d1f922956e0347fbb Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 28 May 2021 10:21:03 +0100 Subject: [PATCH 0704/1594] [Java] Upgrade to Versions 0.39.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e647c2b184..91faf241c4 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '7.0.0' apply false - id "com.github.ben-manes.versions" version "0.38.0" + id "com.github.ben-manes.versions" version "0.39.0" } defaultTasks 'clean', 'build' From f1db0492a102697ad3fa264a794e68ee2460b69d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 29 May 2021 08:22:16 +0100 Subject: [PATCH 0705/1594] [Java] Increase minor version to reflect new features. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 58699d5d32..3784558ee9 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.22.1-SNAPSHOT \ No newline at end of file +1.23.0-SNAPSHOT \ No newline at end of file From 28db1ed27fcf5dc7dd3c4c0d4e05cebd4d2d5780 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 31 May 2021 16:51:06 +0100 Subject: [PATCH 0706/1594] [C++] Update grep for CPU count. --- cppbuild/cppbuild | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppbuild/cppbuild b/cppbuild/cppbuild index 9979f7e2d9..28f48c15aa 100755 --- a/cppbuild/cppbuild +++ b/cppbuild/cppbuild @@ -10,7 +10,7 @@ case "$(uname)" in ncpus=$(sysctl -n hw.ncpu) ;; Linux*) - ncpus=$(lscpu -p | egrep -v '^#' | wc -l) + ncpus=$(lscpu -p | grep -c -E -v '^#') ;; esac From 91aabea4d13dd30616adcdac9e033874fd7e5c39 Mon Sep 17 00:00:00 2001 From: Robert Purdy Date: Fri, 4 Jun 2021 01:36:45 -0700 Subject: [PATCH 0707/1594] [C#] Add ToString (#853) * [C#] Add more string reading/writing methods to DirectBuffer More, hopefully efficient, mechanisms to read and write strings to and from the DirectBuffer. * [C#] Reverted to .net45 * [C#] Reverted to .net45 * [C#] Updated Samples to use the new String methods * [C#] Fixed checkstyle * [C#] Cleaning * Added Modified Benchmarks\nBoth a modified version of the the CarBenchmark which encodes and decodes to/from string; and a version wich uses the new methods to encode and decode strings * Added ToString * Added support for contant tokens * Fixed issue with ToString of tokens without an encoding - like raw data fields * Fixed bracing issue in generated CSharp code. Also Fixed an indent issue. Co-authored-by: Rob Purdy --- .../generation/csharp/CSharpGenerator.java | 385 ++++++++++++++++-- .../sbe/generation/csharp/CSharpUtil.java | 105 ++++- 2 files changed, 460 insertions(+), 30 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 92a39844f5..02ae2a938f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -38,6 +38,7 @@ import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; +import static uk.co.real_logic.sbe.ir.GenerationUtil.findEndSignal; /** * Codec generator for the CSharp programming language. @@ -47,6 +48,8 @@ public class CSharpGenerator implements CodeGenerator { private static final String META_ATTRIBUTE_ENUM = "MetaAttribute"; private static final String INDENT = " "; + private static final String TWO_INDENT = INDENT + INDENT; + private static final String THREE_INDENT = INDENT + INDENT + INDENT; private static final String BASE_INDENT = INDENT; private final Ir ir; @@ -142,6 +145,8 @@ public void generate() throws IOException collectVarData(messageBody, offset, varData); out.append(generateVarData(varData, BASE_INDENT + INDENT)); + out.append(generateDisplay(toUpperFirstChar(msgToken.name()), fields, groups, varData)); + out.append(INDENT + "}\n"); out.append("}\n"); } @@ -180,6 +185,8 @@ private void generateGroups( i = collectVarData(tokens, i, varData); sb.append(generateVarData(varData, indent + INDENT + INDENT)); + appendGroupInstanceDisplay(sb, fields, groups, varData, indent + TWO_INDENT); + sb.append(indent).append(INDENT + "}\n"); } } @@ -481,29 +488,32 @@ private CharSequence generateVarData(final List tokens, final String inde lengthCSharpType, byteOrderStr)); - sb.append(lineSeparator()) - .append(String.format( - indent + "public string Get%1$s()\n" + - indent + "{\n" + - indent + INDENT + "const int sizeOfLengthField = %2$d;\n" + - indent + INDENT + "int limit = _parentMessage.Limit;\n" + - indent + INDENT + "_buffer.CheckLimit(limit + sizeOfLengthField);\n" + - indent + INDENT + "int dataLength = (int)_buffer.%3$sGet%4$s(limit);\n" + - indent + INDENT + "_parentMessage.Limit = limit + sizeOfLengthField + dataLength;\n" + - indent + INDENT + "return _buffer.GetStringFromBytes(%1$sResolvedCharacterEncoding," + - " limit + sizeOfLengthField, dataLength);\n" + - indent + "}\n\n" + - indent + "public void Set%1$s(string value)\n" + - indent + "{\n" + - indent + INDENT + "var encoding = %1$sResolvedCharacterEncoding;\n" + - indent + INDENT + "const int sizeOfLengthField = %2$d;\n" + - indent + INDENT + "int limit = _parentMessage.Limit;\n" + - indent + INDENT + "int byteCount = _buffer.SetBytesFromString(encoding, value, " + - "limit + sizeOfLengthField);\n" + - indent + INDENT + "_parentMessage.Limit = limit + sizeOfLengthField + byteCount;\n" + - indent + INDENT + "_buffer.%3$sPut%4$s(limit, (ushort)byteCount);\n" + - indent + "}\n", - propertyName, sizeOfLengthField, lengthTypePrefix, byteOrderStr)); + if (characterEncoding != null) // only generate these string based methods if there is an encoding + { + sb.append(lineSeparator()) + .append(String.format( + indent + "public string Get%1$s()\n" + + indent + "{\n" + + indent + INDENT + "const int sizeOfLengthField = %2$d;\n" + + indent + INDENT + "int limit = _parentMessage.Limit;\n" + + indent + INDENT + "_buffer.CheckLimit(limit + sizeOfLengthField);\n" + + indent + INDENT + "int dataLength = (int)_buffer.%3$sGet%4$s(limit);\n" + + indent + INDENT + "_parentMessage.Limit = limit + sizeOfLengthField + dataLength;\n" + + indent + INDENT + "return _buffer.GetStringFromBytes(%1$sResolvedCharacterEncoding," + + " limit + sizeOfLengthField, dataLength);\n" + + indent + "}\n\n" + + indent + "public void Set%1$s(string value)\n" + + indent + "{\n" + + indent + INDENT + "var encoding = %1$sResolvedCharacterEncoding;\n" + + indent + INDENT + "const int sizeOfLengthField = %2$d;\n" + + indent + INDENT + "int limit = _parentMessage.Limit;\n" + + indent + INDENT + "int byteCount = _buffer.SetBytesFromString(encoding, value, " + + "limit + sizeOfLengthField);\n" + + indent + INDENT + "_parentMessage.Limit = limit + sizeOfLengthField + byteCount;\n" + + indent + INDENT + "_buffer.%3$sPut%4$s(limit, (ushort)byteCount);\n" + + indent + "}\n", + propertyName, sizeOfLengthField, lengthTypePrefix, byteOrderStr)); + } } } @@ -525,6 +535,7 @@ private void generateBitSet(final List tokens) throws IOException out.append(generateChoices(tokens.subList(1, tokens.size() - 1))); out.append(INDENT + "}\n"); + out.append(generateChoiceDisplay(enumName)); out.append("}\n"); } } @@ -560,6 +571,7 @@ private void generateComposite(final List tokens) throws IOException out.append(generateFixedFlyweightCode(tokens.get(0).encodedLength())); out.append(generateCompositePropertyElements(tokens.subList(1, tokens.size() - 1), BASE_INDENT)); + out.append(generateCompositeDisplay(tokens)); out.append(INDENT + "}\n"); out.append("}\n"); } @@ -1029,12 +1041,14 @@ private void generateCharacterEncodingMethod( final String encoding, final String indent) { - sb.append(String.format("\n" + - indent + "public const string %1$sCharacterEncoding = \"%2$s\";\n" + - indent + "public static Encoding %1$sResolvedCharacterEncoding = " + - "Encoding.GetEncoding(%1$sCharacterEncoding);\n\n", - formatPropertyName(propertyName), - encoding)); + if (encoding != null) // Raw data fields might not have encodings + { + sb.append(String.format("\n" + + indent + "public const string %1$sCharacterEncoding = \"%2$s\";\n" + + indent + "public static Encoding %1$sResolvedCharacterEncoding = " + + "Encoding.GetEncoding(%1$sCharacterEncoding);\n\n", + formatPropertyName(propertyName), encoding)); + } } private CharSequence generateConstPropertyMethods( @@ -1540,4 +1554,317 @@ private String generateLiteral(final PrimitiveType type, final String value) return literal; } + + private void appendGroupInstanceDisplay( + final StringBuilder sb, + final List fields, + final List groups, + final List varData, + final String baseIndent) + { + final String indent = baseIndent + INDENT; + + sb.append('\n'); + append(sb, indent, "internal void BuildString(StringBuilder builder)"); + append(sb, indent, "{"); + append(sb, indent, " if (_buffer == null)"); + append(sb, indent, " {"); + append(sb, indent, " return;"); + append(sb, indent, " }"); + sb.append('\n'); + Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + appendDisplay(sb, fields, groups, varData, indent + INDENT); + Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + sb.append('\n'); + append(sb, indent, "}"); + } + + private void appendDisplay( + final StringBuilder sb, + final List fields, + final List groups, + final List varData, + final String indent) + { + int lengthBeforeLastGeneratedSeparator = -1; + + for (int i = 0, size = fields.size(); i < size;) + { + final Token fieldToken = fields.get(i); + if (fieldToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = fields.get(i + 1); + final String fieldName = formatPropertyName(fieldToken.name()); + lengthBeforeLastGeneratedSeparator = writeTokenDisplay(fieldName, encodingToken, sb, indent); + + i += fieldToken.componentTokenCount(); + } + else + { + i++; + } + } + + for (int i = 0, size = groups.size(); i < size; i++) + { + final Token groupToken = groups.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + final String groupName = formatPropertyName(groupToken.name()); + final String varName = formatVariableName(groupToken.name()); + + append(sb, indent, "builder.Append(\"" + groupName + Separators.KEY_VALUE + + Separators.BEGIN_GROUP + "\");"); + append(sb, indent, "var " + varName + " = this." + groupName + ";"); + append(sb, indent, "if (" + varName + ".Count > 0)"); + append(sb, indent, "{"); + append(sb, indent, " var first = true;"); + append(sb, indent, " while (" + varName + ".HasNext)"); + append(sb, indent, " {"); + append(sb, indent, " if (!first)"); + append(sb, indent, " {"); + append(sb, indent, " builder.Append(',');"); + append(sb, indent, " }"); + append(sb, indent, " first = false;"); + append(sb, indent, " " + varName + ".Next().BuildString(builder);"); + append(sb, indent, " }"); + append(sb, indent, "}"); + append(sb, indent, "builder.Append(\"" + Separators.END_GROUP + "\");"); + + lengthBeforeLastGeneratedSeparator = sb.length(); + Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + + i = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); + } + + for (int i = 0, size = varData.size(); i < size;) + { + final Token lengthToken = Generators.findFirst("length", varData, i); + final int sizeOfLengthField = lengthToken.encodedLength(); + final Token varDataToken = varData.get(i); + if (varDataToken.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); + } + + final String characterEncoding = varData.get(i + 3).encoding().characterEncoding(); + final String varDataName = formatPropertyName(varDataToken.name()); + final String getterName = formatGetterName(varDataToken.name()); + append(sb, indent, "builder.Append(\"" + varDataName + Separators.KEY_VALUE + "\");"); + if (characterEncoding == null) + { + final String name = Generators.toUpperFirstChar(varDataToken.name()); + append(sb, indent, "builder.Append(" + name + "Length()).Append(\" bytes of raw data\");"); + append(sb, indent, "_parentMessage.Limit = _parentMessage.Limit + " + + sizeOfLengthField + " + " + name + "Length();\n"); + } + else + { + append(sb, indent, "builder.Append('\\'').Append(" + getterName + "()).Append('\\'');"); + } + + lengthBeforeLastGeneratedSeparator = sb.length(); + Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + + i += varDataToken.componentTokenCount(); + } + + if (lengthBeforeLastGeneratedSeparator > -1) + { + sb.setLength(lengthBeforeLastGeneratedSeparator); + } + } + + private int writeTokenDisplay( + final String fieldName, + final Token typeToken, + final StringBuilder sb, + final String indent) + { + if (typeToken.encodedLength() <= 0) + { + return -1; + } + + append(sb, indent, "builder.Append(\"" + fieldName + Separators.KEY_VALUE + "\");"); + + if (typeToken.isConstantEncoding()) + { + append(sb, indent, "builder.Append(\"" + typeToken.encoding().constValue() + "\");"); + } + else + { + switch (typeToken.signal()) + { + case ENCODING: + if (typeToken.arrayLength() > 1) + { + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + append(sb, indent, "for (int i = 0; i < " + fieldName + + "Length && this.Get" + fieldName + "(i) > 0; ++i)"); + append(sb, indent, "{"); + append(sb, indent, " builder.Append((char)this.Get" + fieldName + "(i));"); + append(sb, indent, "}"); + } + else + { + Separators.BEGIN_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); + append(sb, indent, "for (int i = 0; i < " + fieldName + "Length; ++i)"); + append(sb, indent, "{"); + append(sb, indent, " if (i > 0) builder.Append(',');"); + append(sb, indent, " builder.Append(Get" + fieldName + "(i));"); + append(sb, indent, "}"); + Separators.END_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); + } + } + else + { + append(sb, indent, "builder.Append(this." + fieldName + ");"); + } + break; + + case BEGIN_ENUM: + append(sb, indent, "builder.Append(this." + fieldName + ");"); + break; + + case BEGIN_SET: + append(sb, indent, "this." + fieldName + ".BuildString(builder);"); + break; + + case BEGIN_COMPOSITE: + { + append(sb, indent, "if (this." + fieldName + " != null)"); + append(sb, indent, "{"); + append(sb, indent, " this." + fieldName + ".BuildString(builder);"); + append(sb, indent, "}"); + append(sb, indent, "else"); + append(sb, indent, "{"); + append(sb, indent, " builder.Append(\"null\");"); + append(sb, indent, "}"); + break; + } + } + } + + final int lengthBeforeFieldSeparator = sb.length(); + Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + + return lengthBeforeFieldSeparator; + } + + private void appendToString(final StringBuilder sb, final String indent) + { + sb.append('\n'); + append(sb, indent, "public override string ToString()"); + append(sb, indent, "{"); + append(sb, indent, " var sb = new StringBuilder(100);"); + append(sb, indent, " this.BuildString(sb);"); + append(sb, indent, " return sb.ToString();"); + append(sb, indent, "}"); + } + + private CharSequence generateChoiceDisplay(final String enumName) + { + final StringBuilder sb = new StringBuilder(); + + sb.append('\n'); + append(sb, INDENT, "static class " + enumName + "Ext"); + append(sb, INDENT, "{"); + append(sb, TWO_INDENT, "internal static void BuildString(this " + enumName + " val, StringBuilder builder)"); + append(sb, TWO_INDENT, "{"); + Separators.BEGIN_SET.appendToGeneratedBuilder(sb, THREE_INDENT, "builder"); + append(sb, THREE_INDENT, "builder.Append(val.ToString());"); + Separators.END_SET.appendToGeneratedBuilder(sb, THREE_INDENT, "builder"); + append(sb, TWO_INDENT, "}"); + append(sb, INDENT, "}"); + return sb; + } + + private CharSequence generateDisplay( + final String name, + final List tokens, + final List groups, + final List varData) + { + final StringBuilder sb = new StringBuilder(100); + + appendToString(sb, TWO_INDENT); + sb.append('\n'); + append(sb, TWO_INDENT, "internal void BuildString(StringBuilder builder)"); + append(sb, TWO_INDENT, "{"); + append(sb, TWO_INDENT, " if (_buffer == null)"); + append(sb, TWO_INDENT, "{"); + append(sb, TWO_INDENT, " throw new ArgumentNullException(\"_buffer\");"); + append(sb, TWO_INDENT, "}"); + sb.append('\n'); + append(sb, TWO_INDENT, " int originalLimit = this.Limit;"); + append(sb, TWO_INDENT, " this.Limit = _offset + _actingBlockLength;"); + append(sb, TWO_INDENT, " builder.Append(\"[" + name + "](sbeTemplateId=\");"); + append(sb, TWO_INDENT, " builder.Append(" + name + ".TemplateId);"); + append(sb, TWO_INDENT, " builder.Append(\"|sbeSchemaId=\");"); + append(sb, TWO_INDENT, " builder.Append(" + name + ".SchemaId);"); + append(sb, TWO_INDENT, " builder.Append(\"|sbeSchemaVersion=\");"); + append(sb, TWO_INDENT, " if (_parentMessage._actingVersion != " + name + ".SchemaVersion)"); + append(sb, TWO_INDENT, " {"); + append(sb, TWO_INDENT, " builder.Append(_parentMessage._actingVersion);"); + append(sb, TWO_INDENT, " builder.Append('/');"); + append(sb, TWO_INDENT, " }"); + append(sb, TWO_INDENT, " builder.Append(" + name + ".SchemaVersion);"); + append(sb, TWO_INDENT, " builder.Append(\"|sbeBlockLength=\");"); + append(sb, TWO_INDENT, " if (_actingBlockLength != " + name + ".BlockLength)"); + append(sb, TWO_INDENT, " {"); + append(sb, TWO_INDENT, " builder.Append(_actingBlockLength);"); + append(sb, TWO_INDENT, " builder.Append('/');"); + append(sb, TWO_INDENT, " }"); + append(sb, TWO_INDENT, " builder.Append(" + name + ".BlockLength);"); + append(sb, TWO_INDENT, " builder.Append(\"):\");"); + sb.append('\n'); + appendDisplay(sb, tokens, groups, varData, THREE_INDENT); + sb.append('\n'); + append(sb, TWO_INDENT, " this.Limit = originalLimit;"); + sb.append('\n'); + append(sb, TWO_INDENT, "}"); + return sb; + } + + private CharSequence generateCompositeDisplay(final List tokens) + { + final StringBuilder sb = new StringBuilder(); + + appendToString(sb, TWO_INDENT); + sb.append('\n'); + append(sb, TWO_INDENT, "internal void BuildString(StringBuilder builder)"); + append(sb, TWO_INDENT, "{"); + append(sb, TWO_INDENT, " if (_buffer == null)"); + append(sb, TWO_INDENT, " {"); + append(sb, TWO_INDENT, " return;"); + append(sb, TWO_INDENT, " }"); + sb.append('\n'); + Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, THREE_INDENT, "builder"); + + int lengthBeforeLastGeneratedSeparator = -1; + + for (int i = 1, end = tokens.size() - 1; i < end;) + { + final Token encodingToken = tokens.get(i); + final String propertyName = formatPropertyName(encodingToken.name()); + lengthBeforeLastGeneratedSeparator = writeTokenDisplay(propertyName, encodingToken, sb, THREE_INDENT); + i += encodingToken.componentTokenCount(); + } + + if (lengthBeforeLastGeneratedSeparator > -1) + { + sb.setLength(lengthBeforeLastGeneratedSeparator); + } + + Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, THREE_INDENT, "builder"); + sb.append('\n'); + append(sb, TWO_INDENT, "}"); + + return sb; + } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index a43b5ce522..5985470789 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -21,13 +21,59 @@ import java.util.EnumMap; import java.util.Map; -import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; /** * Utilities for mapping between IR and the C# language. */ public class CSharpUtil { + + /** + * Useful separator constants for code generation + */ + public enum Separators + { + BEGIN_GROUP('['), + END_GROUP(']'), + BEGIN_COMPOSITE('('), + END_COMPOSITE(')'), + BEGIN_SET('{'), + END_SET('}'), + BEGIN_ARRAY('['), + END_ARRAY(']'), + FIELD('|'), + KEY_VALUE('='), + ENTRY(','); + + private final char symbol; + + Separators(final char symbol) + { + this.symbol = symbol; + } + + /** + * Add separator to a generated append to a {@link StringBuilder}. + * + * @param builder the code generation builder to which information should be added + * @param indent the current generated code indentation + * @param builderName the generated StringBuilder to which separator should be added + */ + public void appendToGeneratedBuilder(final StringBuilder builder, final String indent, final String builderName) + { + builder.append(indent).append(builderName).append(".Append('").append(symbol).append("');").append('\n'); + } + + /** + * Returns the string value of this separator. + * @return the string value of this separator + */ + public String toString() + { + return String.valueOf(symbol); + } + } + private static final Map PRIMITIVE_TYPE_STRING_ENUM_MAP = new EnumMap<>(PrimitiveType.class); /* @@ -59,6 +105,28 @@ public static String cSharpTypeName(final PrimitiveType primitiveType) return PRIMITIVE_TYPE_STRING_ENUM_MAP.get(primitiveType); } + /** + * Uppercase the first character of a given String. + * + * @param str to have the first character upper cased. + * @return a new String with the first character in uppercase. + */ + public static String toUpperFirstChar(final String str) + { + return Character.toUpperCase(str.charAt(0)) + str.substring(1); + } + + /** + * Lowercase the first character of a given String. + * + * @param str to have the first character upper cased. + * @return a new String with the first character in uppercase. + */ + public static String toLowerFirstChar(final String str) + { + return Character.toLowerCase(str.charAt(0)) + str.substring(1); + } + /** * Format a String as a property name. * @@ -70,6 +138,17 @@ public static String formatPropertyName(final String str) return toUpperFirstChar(str); } + /** + * Format a String as a variable name. + * + * @param str to be formatted. + * @return the string formatted as a property name. + */ + public static String formatVariableName(final String str) + { + return toLowerFirstChar(str); + } + /** * Format a String as a class name. * @@ -80,4 +159,28 @@ public static String formatClassName(final String str) { return toUpperFirstChar(str); } + + /** + * Format a Getter name for generated code. + * + * @param propertyName to be formatted. + * @return the property name formatted as a getter name. + */ + public static String formatGetterName(final String propertyName) + { + return "Get" + toUpperFirstChar(propertyName); + } + + /** + * Shortcut to append a line of generated code + * + * @param builder string builder to which to append the line + * @param indent current text indentation + * @param line line to be appended + */ + public static void append(final StringBuilder builder, final String indent, final String line) + { + builder.append(indent).append(line).append('\n'); + } + } From 5eee46222318da39e2b445e12d42f315b18c2c11 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 4 Jun 2021 09:46:36 +0100 Subject: [PATCH 0708/1594] [Java] Fix formatting after merge of PR #853. --- .../sbe/generation/csharp/CSharpGenerator.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 02ae2a938f..6d9f9d7a38 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1616,8 +1616,8 @@ private void appendDisplay( final String groupName = formatPropertyName(groupToken.name()); final String varName = formatVariableName(groupToken.name()); - append(sb, indent, "builder.Append(\"" + groupName + Separators.KEY_VALUE + - Separators.BEGIN_GROUP + "\");"); + append( + sb, indent, "builder.Append(\"" + groupName + Separators.KEY_VALUE + Separators.BEGIN_GROUP + "\");"); append(sb, indent, "var " + varName + " = this." + groupName + ";"); append(sb, indent, "if (" + varName + ".Count > 0)"); append(sb, indent, "{"); @@ -1715,7 +1715,10 @@ private int writeTokenDisplay( Separators.BEGIN_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); append(sb, indent, "for (int i = 0; i < " + fieldName + "Length; ++i)"); append(sb, indent, "{"); - append(sb, indent, " if (i > 0) builder.Append(',');"); + append(sb, indent, " if (i > 0)"); + append(sb, indent, " {"); + append(sb, indent, " builder.Append(',');"); + append(sb, indent, " }"); append(sb, indent, " builder.Append(Get" + fieldName + "(i));"); append(sb, indent, "}"); Separators.END_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); @@ -1739,7 +1742,7 @@ private int writeTokenDisplay( { append(sb, indent, "if (this." + fieldName + " != null)"); append(sb, indent, "{"); - append(sb, indent, " this." + fieldName + ".BuildString(builder);"); + append(sb, indent, " this." + fieldName + ".BuildString(builder);"); append(sb, indent, "}"); append(sb, indent, "else"); append(sb, indent, "{"); @@ -1797,9 +1800,9 @@ private CharSequence generateDisplay( append(sb, TWO_INDENT, "internal void BuildString(StringBuilder builder)"); append(sb, TWO_INDENT, "{"); append(sb, TWO_INDENT, " if (_buffer == null)"); - append(sb, TWO_INDENT, "{"); + append(sb, TWO_INDENT, " {"); append(sb, TWO_INDENT, " throw new ArgumentNullException(\"_buffer\");"); - append(sb, TWO_INDENT, "}"); + append(sb, TWO_INDENT, " }"); sb.append('\n'); append(sb, TWO_INDENT, " int originalLimit = this.Limit;"); append(sb, TWO_INDENT, " this.Limit = _offset + _actingBlockLength;"); From 062479e658def3749e2cff5d820ac49db9808a4f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 5 Jun 2021 09:03:26 +0100 Subject: [PATCH 0709/1594] [Java] Upgrade to Mockito 3.11.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 91faf241c4..b12b380681 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' -def mockitoVersion = '3.10.0' +def mockitoVersion = '3.11.0' def byteBuddyVersion = '1.11.0' def junitVersion = '5.7.2' def jmhVersion = '1.32' From ffd6696258fc23e3ef8091106563745fcb8004e4 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 11 Jun 2021 14:02:59 +0100 Subject: [PATCH 0710/1594] [Java] Upgrade to Mockito 3.11.1 and ByteBuddy 1.11.2. --- build.gradle | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index b12b380681..fc055e89e0 100644 --- a/build.gradle +++ b/build.gradle @@ -40,8 +40,8 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' -def mockitoVersion = '3.11.0' -def byteBuddyVersion = '1.11.0' +def mockitoVersion = '3.11.1' +def byteBuddyVersion = '1.11.2' def junitVersion = '5.7.2' def jmhVersion = '1.32' def agronaVersion = '1.10.0' @@ -140,8 +140,7 @@ allprojects { resolutionStrategy { failOnVersionConflict() - force "net.bytebuddy:byte-buddy:${byteBuddyVersion}", - "net.bytebuddy:byte-buddy-agent:${byteBuddyVersion}" + force "net.bytebuddy:byte-buddy:${byteBuddyVersion}", "net.bytebuddy:byte-buddy-agent:${byteBuddyVersion}" } } From 4603f9c0a7327f63de1d8630e62c6b1d6095a1c1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 11 Jun 2021 22:38:12 +0100 Subject: [PATCH 0711/1594] [Java] Upgrade to Agrona 1.11.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index fc055e89e0..49e4a7da7d 100644 --- a/build.gradle +++ b/build.gradle @@ -44,8 +44,8 @@ def mockitoVersion = '3.11.1' def byteBuddyVersion = '1.11.2' def junitVersion = '5.7.2' def jmhVersion = '1.32' -def agronaVersion = '1.10.0' -def agronaVersionRange = '[1.10,1.11[' // allow any patch release of 1.10.x +def agronaVersion = '1.11.0' +def agronaVersionRange = '[1.11,1.12[' // allow any patch release of 1.11.x def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 6171905f6aa2a9262acc8bf3f85e96aae56ded85 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sun, 13 Jun 2021 07:54:15 -0700 Subject: [PATCH 0712/1594] 1.23.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 3784558ee9..bfbadb3a2a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.23.0-SNAPSHOT \ No newline at end of file +1.23.0 \ No newline at end of file From 3cd9ed652931b1b9a56eef690e91b5d05921ea27 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Sun, 13 Jun 2021 07:56:14 -0700 Subject: [PATCH 0713/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index bfbadb3a2a..2f18f2d7ee 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.23.0 \ No newline at end of file +1.23.1-SNAPSHOT \ No newline at end of file From c62b3dfabaff1feffcf012b1f33c0e7c656d4904 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 14 Jun 2021 15:48:37 +0200 Subject: [PATCH 0714/1594] [CI] Disable Gradle's `auto-detect` feature when selecting the Java toolchain JVM. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2401f78813..9f7e01b07b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ on: - master env: - GRADLE_OPTS: "-Dorg.gradle.daemon=false" + GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false" CMAKE_VERSION: "3.6.1" jobs: From c7e8cec9881fae38a879bb15ecc8700ec2c7bf5a Mon Sep 17 00:00:00 2001 From: Bill Segall Date: Tue, 15 Jun 2021 16:47:40 +1000 Subject: [PATCH 0715/1594] Release 1.23 (#855) * Restore the now fixed SinceDeprecated tests * Suppress warnings so new errors become clear. * Version bump for nuget release --- csharp/sbe-benchmarks/Bench/SBE/CarBenchmark.cs | 4 ++++ .../sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_new.cs | 3 +++ .../Bench/SBE/CarBenchmark_with_strings_original.cs | 3 +++ csharp/sbe-dll/sbe-dll.csproj | 4 ++-- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark.cs b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark.cs index 3b6863f711..156600466c 100644 --- a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark.cs +++ b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark.cs @@ -4,6 +4,9 @@ using BenchmarkDotNet.Diagnosers; using Org.SbeTool.Sbe.Dll; +// Whilst running decoding timing tests there are values we don't use +#pragma warning disable 219 + namespace Org.SbeTool.Sbe.Benchmarks.Bench.Benchmarks { [MemoryDiagnoser] @@ -137,6 +140,7 @@ public int Decode(Car car, DirectBuffer directBuffer, int bufferOffset) var templateId = Car.TemplateId; var schemaVersion = Car.SchemaVersion; +#pragma warning restore 2019 var serialNumber = car.SerialNumber; var modelYear = car.ModelYear; var available = car.Available; diff --git a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_new.cs b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_new.cs index afdb71ee98..90f86c548a 100644 --- a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_new.cs +++ b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_new.cs @@ -4,6 +4,9 @@ using BenchmarkDotNet.Diagnosers; using Org.SbeTool.Sbe.Dll; +// Whilst running decoding timing tests there are values we don't use +#pragma warning disable 219 + namespace Org.SbeTool.Sbe.Benchmarks.Bench.Benchmarks { [MemoryDiagnoser] diff --git a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_original.cs b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_original.cs index eb5ebdff51..8257dac40d 100644 --- a/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_original.cs +++ b/csharp/sbe-benchmarks/Bench/SBE/CarBenchmark_with_strings_original.cs @@ -4,6 +4,9 @@ using BenchmarkDotNet.Diagnosers; using Org.SbeTool.Sbe.Dll; +// Whilst running decoding timing tests there are values we don't use +#pragma warning disable 219 + namespace Org.SbeTool.Sbe.Benchmarks.Bench.Benchmarks { [MemoryDiagnoser] diff --git a/csharp/sbe-dll/sbe-dll.csproj b/csharp/sbe-dll/sbe-dll.csproj index 97571f1ae3..2c369ba21e 100644 --- a/csharp/sbe-dll/sbe-dll.csproj +++ b/csharp/sbe-dll/sbe-dll.csproj @@ -5,7 +5,7 @@ SBE Org.SbeTool.Sbe.Dll Org.SbeTool.Sbe.Dll - Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. + Copyright (C) Bill Segall 2018-2021, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. true Bill Segall, MarketFactory Inc, Adaptive Consulting Apache-2.0 @@ -13,7 +13,7 @@ https://github.com/real-logic/simple-binary-encoding SBE;Marshaling;Low;Latency;Simple;Binary;Encoding sbe-tool - 1.13.1 + 1.23.1.1 Simple Binary Encoding for .NET This package contains all you need to define SBE messages and generate C# encoders and decoders. See https://github.com/real-logic/simple-binary-encoding for more detailed instructions git From b07fbe51cadccc6352ae2a9c4f1589ab48912baa Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 29 Jun 2021 14:54:39 +0100 Subject: [PATCH 0716/1594] [Java] Upgrade to ByteBuddy 1.11.3 and Mockito 3.11.2. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 49e4a7da7d..e69b2bfc72 100644 --- a/build.gradle +++ b/build.gradle @@ -40,8 +40,8 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' -def mockitoVersion = '3.11.1' -def byteBuddyVersion = '1.11.2' +def mockitoVersion = '3.11.2' +def byteBuddyVersion = '1.11.3' def junitVersion = '5.7.2' def jmhVersion = '1.32' def agronaVersion = '1.11.0' From 4ac0b25c8db56d02c039d0353fd362b522bca644 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 5 Jul 2021 12:06:01 +0100 Subject: [PATCH 0717/1594] [Java] Upgrade to Gradle 7.1.1. --- build.gradle | 6 +++--- gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index e69b2bfc72..89224551f2 100644 --- a/build.gradle +++ b/build.gradle @@ -145,7 +145,7 @@ allprojects { } tasks.withType(JavaExec).configureEach { - javaLauncher = toolchainLauncher + javaLauncher.set(toolchainLauncher) } } @@ -259,7 +259,7 @@ project(':sbe-tool') { compileTestJava.dependsOn compileGeneratedJava task generateTestCodecs(dependsOn: 'compileJava', type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': generatedDir, @@ -731,6 +731,6 @@ tasks.named("dependencyUpdates").configure { } wrapper { - gradleVersion = '7.0.2' + gradleVersion = '7.1.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch delta 18435 zcmY&<19zBR)MXm8v2EM7ZQHi-#I|kQZfv7Tn#Q)%81v4zX3d)U4d4 zYYc!v@NU%|U;_sM`2z(4BAilWijmR>4U^KdN)D8%@2KLcqkTDW%^3U(Wg>{qkAF z&RcYr;D1I5aD(N-PnqoEeBN~JyXiT(+@b`4Pv`;KmkBXYN48@0;iXuq6!ytn`vGp$ z6X4DQHMx^WlOek^bde&~cvEO@K$oJ}i`T`N;M|lX0mhmEH zuRpo!rS~#&rg}ajBdma$$}+vEhz?JAFUW|iZEcL%amAg_pzqul-B7Itq6Y_BGmOCC zX*Bw3rFz3R)DXpCVBkI!SoOHtYstv*e-May|+?b80ZRh$MZ$FerlC`)ZKt} zTd0Arf9N2dimjs>mg5&@sfTPsRXKXI;0L~&t+GH zkB<>wxI9D+k5VHHcB7Rku{Z>i3$&hgd9Mt_hS_GaGg0#2EHzyV=j=u5xSyV~F0*qs zW{k9}lFZ?H%@4hII_!bzao!S(J^^ZZVmG_;^qXkpJb7OyR*sPL>))Jx{K4xtO2xTr@St!@CJ=y3q2wY5F`77Tqwz8!&Q{f7Dp zifvzVV1!Dj*dxG%BsQyRP6${X+Tc$+XOG zzvq5xcC#&-iXlp$)L=9t{oD~bT~v^ZxQG;FRz|HcZj|^L#_(VNG)k{=_6|6Bs-tRNCn-XuaZ^*^hpZ@qwi`m|BxcF6IWc?_bhtK_cDZRTw#*bZ2`1@1HcB
    `mLUmo_>@2R&nj7&CiH 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 B8dv}T delta 17845 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 X49Luk)baa85H9$5YCsTPT`SVRWMtMW diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 29e4134576..af7be50b10 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0c81..744e882ed5 100755 --- a/gradlew +++ b/gradlew @@ -72,7 +72,7 @@ case "`uname`" in Darwin* ) darwin=true ;; - MINGW* ) + MSYS* | MINGW* ) msys=true ;; NONSTOP* ) From 35fa8d30968da81c521381039e4aadfb5c2b160d Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 16 Jul 2021 13:41:35 +0200 Subject: [PATCH 0718/1594] [Gradle] Use `mainClass` instead of deprecated `main` property for JavaExec tasks. --- build.gradle | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/build.gradle b/build.gradle index 89224551f2..6d201d442b 100644 --- a/build.gradle +++ b/build.gradle @@ -405,7 +405,7 @@ project(':sbe-samples') { compileGeneratedJava.dependsOn 'generateCodecs' task generateCodecs(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': generatedDir, @@ -419,20 +419,20 @@ project(':sbe-samples') { } task runExampleUsingGeneratedStub(dependsOn: 'compileJava', type: JavaExec) { + mainClass = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub' classpath = sourceSets.main.runtimeClasspath - main = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub' systemProperties System.getProperties() } task runExampleUsingGeneratedStubExtension(dependsOn: 'compileJava', type: JavaExec) { + mainClass = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension' classpath = sourceSets.main.runtimeClasspath - main = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension' systemProperties System.getProperties() } task runOtfExample(dependsOn: 'compileJava', type: JavaExec) { + mainClass = 'uk.co.real_logic.sbe.examples.OtfExample' classpath = sourceSets.main.runtimeClasspath - main = 'uk.co.real_logic.sbe.examples.OtfExample' workingDir = 'src/main/resources' } @@ -515,7 +515,7 @@ project(':sbe-benchmarks') { compileJava.dependsOn 'compileGeneratedJava' task generateCodecs(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'build/generated-src', @@ -547,7 +547,7 @@ project(':sbe-benchmarks') { * *) Some examples need to fiddle with WorkingDir to deal with XInclude */ task generateGolangCodecTestComposite(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src', @@ -556,7 +556,7 @@ task generateGolangCodecTestComposite(type: JavaExec) { } task generateGolangCodecTestBasic(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src/basic', @@ -565,7 +565,7 @@ task generateGolangCodecTestBasic(type: JavaExec) { } task generateGolangCodecTestGroup(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src/group', @@ -574,7 +574,7 @@ task generateGolangCodecTestGroup(type: JavaExec) { } task generateGolangCodecTestVarData(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src/vardata', @@ -583,7 +583,7 @@ task generateGolangCodecTestVarData(type: JavaExec) { } task generateGolangCodecsWithXIncludes(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src', @@ -595,7 +595,7 @@ task generateGolangCodecsWithXIncludes(type: JavaExec) { } task generateGolangCodecsWithXSD(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src', @@ -635,7 +635,7 @@ task generateGolangCodecs { * multiple targets as XInclude forces us to change working dir */ task generateCSharpCodecsWithXIncludes(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'csharp/sbe-generated', @@ -647,7 +647,7 @@ task generateCSharpCodecsWithXIncludes(type: JavaExec) { } task generateCSharpCodecsTests(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'csharp/sbe-generated', @@ -670,7 +670,7 @@ task generateCSharpCodecs { } task generateJavaIrCodecs(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/java', @@ -680,7 +680,7 @@ task generateJavaIrCodecs(type: JavaExec) { } task generateCppIrCodecs(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/cpp', @@ -690,7 +690,7 @@ task generateCppIrCodecs(type: JavaExec) { } task generateGolangIrCodecs(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/golang', From d8af39339d04f18d02bf48f231b5c2883291ceb9 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 16 Jul 2021 14:14:41 +0200 Subject: [PATCH 0719/1594] [CI] Fail the build if Gradle build file has warnings. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9f7e01b07b..801519bcf7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ on: - master env: - GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false" + GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail" CMAKE_VERSION: "3.6.1" jobs: From 72825f21af6cb1da65e9899f425ac2eb786f3b38 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 16 Jul 2021 14:45:02 +0200 Subject: [PATCH 0720/1594] [Gradle] Remove workaround for https://github.com/gradle/gradle/issues/15538 as the issue was fixed in Gradle 7.x. --- build.gradle | 5 ----- 1 file changed, 5 deletions(-) diff --git a/build.gradle b/build.gradle index 6d201d442b..691c6eb1de 100644 --- a/build.gradle +++ b/build.gradle @@ -178,11 +178,6 @@ subprojects { } tasks.withType(JavaCompile) { - if (buildJavaVersion >= 16) { - // -- Workaround for https://github.com/gradle/gradle/issues/15538 - options.forkOptions.jvmArgs.addAll( ['--add-opens', 'jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED'] ) - // -- - } options.encoding = 'UTF-8' options.deprecation = true } From 4cd7eaf00b22f506492754de683a528e45faca5a Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 19 Jul 2021 13:49:18 +0200 Subject: [PATCH 0721/1594] [Build] Do not override packaging declaration in the generated POM file. --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 691c6eb1de..be022589a4 100644 --- a/build.gradle +++ b/build.gradle @@ -66,7 +66,6 @@ ext { def projectPom = { name = 'sbe' - packaging = 'pom' description = 'FIX/SBE - OSI layer 6 presentation for encoding and decoding application messages' + ' in binary format for low-latency applications.' url = 'https://github.com/real-logic/simple-binary-encoding' From 1e6ac14a1490c66be5c02b987006086f87296d58 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 19 Jul 2021 15:01:05 +0100 Subject: [PATCH 0722/1594] [C++] Upgrade to Google Test 1.11.0. --- CMakeLists.txt | 4 ++-- cppbuild/googletest-release-1.10.0.zip | Bin 1146687 -> 0 bytes cppbuild/googletest-release-1.11.0.zip | Bin 0 -> 1121369 bytes 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 cppbuild/googletest-release-1.10.0.zip create mode 100644 cppbuild/googletest-release-1.11.0.zip diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b8a969c05..8a6df0e561 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,8 +67,8 @@ if (SBE_TESTS) ExternalProject_Add( gtest - URL ${CMAKE_CURRENT_SOURCE_DIR}/cppbuild/googletest-release-1.10.0.zip - URL_MD5 82358affdd7ab94854c8ee73a180fc53 + URL ${CMAKE_CURRENT_SOURCE_DIR}/cppbuild/googletest-release-1.11.0.zip + URL_MD5 52943a59cefce0ae0491d4d2412c120b PREFIX "${SBE_THIRDPARTY_BINARY_DIR}/gtest" CMAKE_ARGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER};-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} BUILD_BYPRODUCTS "${SBE_THIRDPARTY_BINARY_DIR}/gtest/src/gtest-build/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX};${SBE_THIRDPARTY_BINARY_DIR}/gtest/src/gtest-build/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock_main${CMAKE_STATIC_LIBRARY_SUFFIX}" diff --git a/cppbuild/googletest-release-1.10.0.zip b/cppbuild/googletest-release-1.10.0.zip deleted file mode 100644 index 87570a3086970824be1a80ef6bb237cb1eab5793..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1146687 zcma&NW0a*`lP#LIZQHhO+qP}nwr$(2%&e@mZQIT~)qVQ(>9_B_U*A2(#;|K6IL{!hZyS`1b%V%va_{e*?JueUtyo0CdJShIZz(X7*0DhA#gZO<4_sYD#%r z_7An}pNUEpiV1ZJDcMQ--?B7{5-JjteyZ z8yY;tdC~sffCqPSZyY`nL%*)nb+sO{Pj*gq}m8U}mX&MIB_P137?Gm8B6& zkErtzFIWuvgh+Gowy|#vUYCDVp=Hf`O&kX&2RM&@2+dS#2zL~>f_`C|ax;K@ zAx)LXpY=fZY1aq>vF3z;&39HMZbOjIEU(N*mBcuSLTP=K!nOM{!HM(UFQLRO-V*HEZfU0UNg4g1JJy!8Y z#Zm>J&ZKs=n%tZ6LoTQctuC2xV7KpMc_ph{tT|i8s{*~6();%eZO)14wQIo*9~553 z{%mob;;1A}JZ&NDjoc6gwCx+3{1lrWqfeu><4>vOmH~PZW15sFkvHbE$@^)9QG8#- zON0A#{*&#|?VhS(-Ko}$d z0O`NZG8ZR9H%n(aPg|S+OtVonTl)<*gzq|iM}erKTw%z;cT*r37J4o7fkxml+h%z% z(K#gUD3sUzb^6I%o9oUKxtAg2j$0u#1!eOQG^AZC;utknbvU*~ zh%9NiMTgxDF{MHeK&{d_NR??;HrXU0W^8U@_8}xPqq2(;Z9Amn+J)8*^eU3NeG+&- zBo-aDp&=~-nqnxYIJ**x3T`1W1IiR`faNloA_*l`FRgnNjRlbkpV1WwsM%ozVFIcQ z2PgL^_20^r?t4j9K%FgF5=`h(T!pEiyd0~@anwbj;!7GeL@;C%bTE>s#au)Gg zo$d-)RXL#Xh6)Q4D@pdEbR`bm9On@whye;R??K`606^j+C3KO>mb6mjk*u#I}jO-y zKcVJNhz_?~=M|Y}Mu4w40Gz0WHIAOE>kn2I)WojELRogzdKZF3Eh^L4U>H*&9GD#p zpm#VIo}m*TOfOJw5m9-K6|DQ1*%pN>s%`is`6ily$8fHL(eQzV#V&=(Q$?iyXP-`v z|3Fj5PMz7w${N0|bdg$l_?fTJiQ$U4IP4B>&U2r>YFcvxMOexj8`vmjdzz5~Xp$PJ zIt((hcngI?Imj{!;Re1RkaCWe;gnBZ$N>_3$GH%lminy1Gqzm|-2varZ_jy*>5wh^ z@z&?pd@8$F0LYIoZ7B7(o~`Z=)64?r`Gch16_Ru=d8?>zS*Od>>fXWe{$Mfl zJCf+vxU=2>JME2eo7ue2~ zCs~hx5{ydtPK+#aUz7+&8cV(crsrp9tAfYpDdBMmOY-F)SNS-A5o;<3-rCBM%OB8x z);D4|ch>0N8zcqwf2waGRY@5UIwM0b)BjT68rt^j5-5H%^&C$6Np!HX8@-KHD!|Dj zNR65sEZCxntgFB=`_T6=6J@GDA9>7d?I;kJb#9R;mz?c4I_6>Ovy^4>r8x2|J>K5W z%sMEe9H_g8cV~0d4GSnfL{zt-NJqgE4w>J#yopljP85#OweSHHV|BLju&4Ij;aUg-AwDqS0+?pazx zfx7M+R9H|X2o8nd8B`r~4(w5ohFkA{z>S_xsN>a3_W<0m zMOW8Vc+&!2cmiHA+60`^3NztmAMiEzqKOc2670Nm!&w3M^wEaRMPm_g;N}%vcc8}t zpc-%yT2XwW!%4^#rZby52fWz}Py{&qM}RXuAKv0(RtfyrFw zhMVsybZ_~#I0!&Aq6hp0;=Am4i)cJFOT5uw(N0>n5B=5-SfBrY=V zAneZz_}A>+CbG;ks~EWBI>jcd;j@m@>LSd;C$^GIBZH^Kz!T}PYd(=Rk(n|DP>c?_ zj;U}ohQz(q8Fj~H(TNU2`*6f{VxBd*0eJ=+IRV&M#xEs-YTyHoQs_j*qUn|B4#Rn< zY0lNH8MwguwMGP>ayo3}u4z-;*99-Nwm0-dA#bvU5V855aBlujfI@|=vI);f-cOB` zmoe5v2y$_8%fV#h3uR8}(5U^6wU`4nBC&IqSJGB2gHgwn--eOHb$$yJ=7qZ{V=q25 zafz8TO1Qidq~T1d?~r^$wM#a1=voVF45^K-;?E9H$5Iss+SOQ*W~k)9CE|!lSps?a zitbFn=EWNvFvv!Wo3PAKIUSSsM#Q6ea`!Zdtn zsVd^e9k`aUiiu46panxsh8h84&?uI#+Cib=?VTmgns-B!jGJS*`0oA5?HLBwYp~2v z(}Kl*$FfJ8FN*)gdEUT#c;V61yxPS~W3F2eOV4Y)(k<6Dczr!Hxz&m}Q^%`?c-=a1 z4RIKBXKSLzzC25YGBHX6-(QzXlf@F+PF*M#*~F8_YDqcFqlR6Xml9O|c=V^1jnRHE zRt)V+7K^TewOE=v;?iw)IBk3En%SCo@Tq3g%x<*&4Ip|Xf1zj*v5a0xehoo@IMLzoy^d*W|ZTxG&Mh>0DLtVc$^(45fH;t=_+Wa!1Rt8QCvphVK z$AP=+go`O<`~3NmE7ub|@nQ?#pN=iw=IierzG~{*Wh+(f9Uo}e6*|k~O%P${dnKOi zvL#+iC7yZH2)lXXbsK#y0F|PVI~oz}k0v%1|NL6`*Q=PDXVcFHlOApU)Jv3K(As1~ zQ{k^omiem@zWjae-uJ!!#1Ag=+whaT=ReggRkjdY&rKQa{X?CCEUATqUbXMGcDXPqSEU6p) zmaZF}7)-^Qa_X8g=D*Z#0+;UL*VrE(MB>Mzxm)=Ag->%g2^N{kt34Ml#%Oka_3ooR z*W-zzdi1k}(7&PAQ< z>;(`2!2K`jrTCYGS6J52+Em8U*~OX8#pD0#Kv$(fyKDi3-Un3Tk0vz}lXhN_R4<7? zV1)(}uy#4fKyFtyz}?r^MN$1XG^?;xS-@H>4`#r6ITdhI-%qXmmnmsoVS&3>wr zvzQ-(Z<#7)4UqpV_v?D(aR7Nr9auaB+2*NL(_?^OM9)+qy2>+U={qOPo`jB(e&}bq zFQ1dw({fU}T6G-#qRafN3#yuhCPK|SNDZ^X7^f`L(ADXz{d@1#(V4QZwury7yLv=r znqkcHzn=cgQDahL@bBBz)e}k^ueHA)oAru0#qNy+ZZta^vFsg&OoTC>n=!mE;F z`7_WBl!x`6^x=yFF4`f>9?#H?uZTv=YH8YaUbJho`lEzN`uCrq6Dr62bJ_s!WxK1! z1yONeQWQUpv4OE`JBm5nOYZ672;VPlIY`xzn>G#%8~^fveqiu8m~x})csMpY+^X6| zuDp*t$3FxcyrcRC{Ld_^7{;L0{o96Yx1AcDObbL zezODdYg&Jh2=ua7+j>sNixvn6YRr*NF!^uUS-_tS?n$MLXb`!Q96c4C`rl*|wpP1h z>2J_Gsv(6BXR_OG-$wdeu`zLVE|*@ksx-NT` z8Py`O1iL1s$EOaf z4VMtrLlOSB{(#0feTV9cy5*A+X<#>CR|jsA^)&Uvk~PbyxcnKvhVbZrI5zP4zMVFI zafF;ytCrrlh^q3DBu~7|17SS2rnFe_7?&xpl-ov^SO641f43xIxRSq+o}# zI9+$aVHC>W8H2;;CP`MOUv95#$#2i>|MYYBYs+MM9<3JVSQ-QcVX@1({n`erTxOmP z9k5>#aC|1Sm#0Mf6?Qttgk=s4ULaeVV5}!ue{h=ktT7I)&7{yv*Ba=G3|Z>3$Qo16 zy)KUv;4{Kq?~m&m0iulZ$1(_L|C1Ph@kca*bD(TYnv+E4MFnvnH%jq^L8hFNH3szDsr9|JLJ zKLMtKLhgt(wFAMQqNHbC8{TlSX})kI{ZSVR<$fP%H|Zrrm_q`Lr#?b2wSE1DaDm|N zAj>g{Ao)im2kF%#N|%{hWg1U(E!%qydBMRUXQ`m{SIUPokS`~cqO0`25G$AzQ@5a{ z1cj9>fVqvJT;858GlF|yX;k4DrF}QBBBQDtc*oFl#(KqS&x)Y~h4cs!?vhDRM!q+A z_`G!x{U`m1JI8?~`X-WDPB^Gnv!IU2VpV$Y^-4uW3;R)b@JU2t_QseQ49sr7!C0Lm zA0!)y`BCW~*f1V(h4CpUmYDHG+A4&S0(@HD)syB)m(tXmHUTMzra3k5*>SYX+Ny+i zSb^RP&`=LGnUF_P5;us&B_|^FIHI>wu8`7or7FR8i18R_JW?-D9F{>wss+<|0FQ47 ze!aO$O1XimyQ~O#E&_hC^*v`5a~|w$wCbN@zeAj0 z03A|b@!%_WE4R;91ig33o2%-3&shUq6PtjYGXW`G2Njmk0tRZgGYUGF@Lqp5=z=s_ zC817#TwBKEqJ_S5?kTBsv27|F!`o)r^;jz{r?qUrCT)fxze$@Jtg4r`2*wC*&uW*2 zfz)+{bpvu}pZYfm)=(8NhI+Tn&WQk$L1I>i=K`@4DYgS}HVLeL8SSfA0emIvmyN}?ZEJ`04(JCByJ!OD4wNkBCvJYZC{p@bqOQ$1p2f=c ztzg&&SE8Zd>g^j6tmMc3j3-4>VVPsu_IK-$V$3{zh4hl?Z zLYbv#r;H&|Sfm;=53q__s*C62S-Y%k5qeN#Tj6!Zm;uHJ2y_k=*Aa?b=NL)h^dzRt zD`c=eOV5E8VT+VfdTC}RvF?ydG-z|0pawZ(DyQKVxB{_-wvR|M%apH&ue8^You+&N z$AICXv)Xz9Wl#PFi3h&{oH zYu%AD#h3qY&^8R@$Stb7!~p&c<~z6T^^Uc)YA1|Weo<_17=`vNp~_T$Rt8 z$1|&~&ZjDMh2%|8puR1k9Ll^zj@cy*pynUUEI*d!9Zyr+azpcWH1 z<%2f7S#?>&Zk#vak-;yx^p;^*vOvpNL&Tkt40O#21XGH^Op$e;f96gsW4=8)V{4l~ zAZ*#PjdsmLAEvAbZ}QM~5W6*c10#*O^6_g;UuSzos^(eDo0uzyb4W}lY5*O{eDrxXJcknfGv6Vv?jpd5wuVPWfsa&<90=u8 zc~CCx6_X5d95~y#4Y^x4F8)NuSJL0Q$0zk0-=(@|(cyjCQ7_+9-6oh<)9fN&)hHgd zb4yYQ6#GCdVRogDGk>vc&5{OAums@vjxsyJxI{NY$!Q2yd6BDX_8}NMPz506HQQ0| z*6uK|y-8}~ejg_1_SlT?!}9kV9`Nh*l#h`#;PHKb@%#7i^>_8XIrw=xKHN`*`#VO= zzA+fgA~ekzxatkBaH1Wu@+0`W)wY1QE@{IxNZ2VZ>{eyEqn+>XxBKSjko+7X zCtUy@`t3sadt01QkNLVgKCjek7`2c{?{DFdR^F9RrMl1u9S;wyt)}k$!8~L|C*0ch zl$pZP9Xo#FfkUoDbZzQ%!mkz1r(-+oVWqY=vNi(qvcya z$+%^UK#|zJ9^2;Sm(fQ5{03OEURR_|ij^!H801@jbKn$yL(h>mY5WAB%x%gHo875H zSMxf?zP!26V5AWqM`#I@=dz;R*qvh_p-g$ti$N>i?)LHW36m6hhRXw3GT@Y=P=%RpTU&-grJfK!4gJK0?B=-H*Y(OfXsX9o#(&c zBUTnz)r39g*J-1+@TKzZiPRp<7g%%_)rN7Jml2$TwRsr#y1%eiBb%HGzB2DZ0Rn3l z313bJ`5Pn&N$-nCh`BL^h(Rlhl7LPZ~9ksu@Ei7@ zWHk>u_7(WA+!+Q103iIAWK~8|SX53~^gl^zsnV3)0UJW!10|UEIa-kWobp_rMPwUz zf@o^V{(FUli_icPaH3p7`%Qu)+cs?!-ZFUhu|r>f<~)Bd-Sr;hkiCBYx8A_=M|d-6 zPB`kp3G<;=z$jQZ&xYe@MpH4gqvK2Z=_kw=&k(7G12c%fCRn!p_0}eRy~F(^3Y3TA z9pYz_{}*Y~MEvz(7#|?YEInG@B~vHH6@+}WzZ)^`zA^sUB+~fXrT*q8KybczdX|ut zQF5$51K8smYM(mlK>qd-j9&|bt`G@wBY7rdbN|asr3>qf8UB_5bX6ySxsVhpw*h%54NH^@D^p2RXc>SZ?6D<Yw8hp}+;$&nu#`x4H*kQUrOud8sf?t9Iyc^!x za+xXtXmUK-_I?2@wj>rUMoz_m6To2pzO+`{#kzn;lkhsWm6K(5S_|XD#&t+SD08zg ztd`xMKx#l2yVRaxDU}AkpfyMeQ*V`yEzH%4E+i>nd#Wzmm?2m5lKD&ImBlwobPs2c zJNN34WdhXQzS_hA2;IA11+$ z%NB8&_Q7S6I@pyM;c3*trs~e1w&hxtpd{L;=S{~Q=u1(nk%%L?7BHu{^%pm~Or91Y zQuFq-Ls|l{KDyB&DY9x6B9=+n@ye2ei9KBgU8tnmmz*u*L4TER_kG6%d0R3(YZ)~Um(vQ1LlL?v8gvnhhpeF4LAv%OND$0Z(70?J0E zoxWl|C&Tkvq@_qn)X~Az5SnK~0QT+@ zF4@}37>ifz3hP8-YPa;8h?jn z97unMWrH^SI$Nt?_tvUHLQKw^#3k|`t6B36>W<6c&Fn1v_OoGsf0 ztRsoc^E{7JeF>*)YOzSKQ{W}DXI!mxTPrknZ;=Vuo~qAnk4q*l*lQmJJJ+s1^>cEsSU$+J97Wu=q-<-X zoi~t@L{BdLRq;NF?DRf|zwf)Ohj#Fpy%){jE<{5bBN(=URs}1^0>OMQCze zws?K>3O3QXjqygu_#WjVFT}9;8N5^a2<43)iFPxdfrbYDFtaFi#p4ZjF}JOZ_%&%_NsuUW>pit0Y_?LEK7X zUMbzVPIcJ$VHb6@2h31*kADB5u9h906>Sh|_pwVHrde>0ma`L4@U)c(p-@3nx+@La zRItXE-%Gb4*@q$mt20mt0gw6ybrv)#jY_QXC3wvv={9e47D7>8FKfIo@l5h8#da)I zPrx3jmqIJ5b~Wz3I-equ_t3AR&9lKr>*mFw+mE&aP)}^E*OPU+U#cD^6#Y2{)gi|a zIy0#r{}W8oNt~Q}Ub8aT1&c{1TCG!>(@51e)U&i^lh}Q&N5C6t5IS zZMiKYvd0Z1gf(DREnJb`tYL^3OhK|kKzb!uP;1!;pa)a!%cF?mT+)TpAzzd*l^v>c zpYw}Tks1C7L^=qK9bZmQ|EGXN;MM%lU1$(9c8B*30&u1Yh(Ry{?kPB^!Z7h9B(!#; z_vU3vBofss`~HD~hCnRB{z$~pfqC&TU3`k<%DbR@)ohYBSTAkgeA!y^ri3OKvbbR2 z`yQL)l?X@fN&&e-7=mS7F}dGY%!+5>-@e7mLi`P2gPG{?kT|A7&^Y$5EYAshQVwG3 z{W$NnM=QBJ3)IF3a?=^PfvvKS!4+>vE^m69F@g-w6>Q-+a&-ANzuuk*7zIX$aXix$ zY~oldY@~D{oI|+1fo|(FMHEGDZ}=sLIuvRORYT!JmxIEC(5%<-CjK<2%uqO^Rhb0iX@yXsPOc^qxhMrp78|Qsn zeldiR5jyoNmV7=(5jm0RnN^1L+!63piJThsIzXN{G{g5xS2SCcogE$ho4;+dmMH9P zmK`td*Vhc3Hw>hxrCV{EQvvbQUV$5J!xf8y+dG-8Ps!`%3riO(CXi; zfGWl`1J`14<}73cjNNDz^VuGTGRz%g@!R2>jTMWnmD-1T9L5KrKy5)$?2b#7Rl-!r zXIXH@zSxE<&u=-9fj`YGWJ7c|*SC)_`oY`{SGf)lIt1?(QvJZPDs6+?!a5s^{$y}( zb4BAm@$cmm39nEgt$}a+!t2;T-Ka=DynWLdLk$e+m%wes<{IZ^q=vcHCX|M7Ib?sTjjz2pdy<|h^f|*Du4VH z873xX<-*72p|lSB_N=ZOQS#|##D*ax`?Qf!%B&_*zySZ&2Pp3=@LaOrljC9Rpc3EU zjv)hMr$6gEZfD7Oou;C|U|;A$7#5LgLE#!#rZ@#}kKoN69^l8vBb4)`m_yWtL2?*% z#{mi{d(aiY?`rB28Nn_{0Hw-!)2+M6R81Z_a>?(gLA@0W1(BmuN`cP{<#Y;di`f8I z^<;mxBR_t}e&fhVWB1TyuK=R}>4GJjsCY_aD1B`|S_zu9wMjCT1Xn{H3q3h9!&5!r zQ$_tq`->??e;02~ojd)tvFdZq8r|4vgLBMIiJ~Y#Do~Vo6c?aTHrTB?)=m+8^N`_c z;*|>9oITY+)4Cm;tJYr$Ykj-)}$hBt`XJn3B@92dx z_625L`YXxmGTw3nKax_3)T78M-=#vgNlExXuP@nO4w<-kCB?Kb9Pr})5ve_W;wYbv zxpA~~e_?4W+<1`a)K1nm@^17eX0;%qrP1UPe#nswpByO!s4z~Glv*c-$BSmdXlauz#&^H>M2g!X%Sv{Dwd%xM(B@==JFOU+a!>Eu z&+F;z`uKC}r29eM9HZO+=lOm@sz$}}@MK)573@Qj?>9c3)q4CLR6+mmx{ZdwS-*tO z|He=%&|}k&{#x8L{#wWWHA7LCSCUp%5ET9|bU$IsYJ>nm?B)T*$X@Bx>>3^F$~lF| z$_!bvIm)VP z?OSvbvKC@)Ge|--R;;aPG@zP`Iaevh}A)$U>4_RV|vewdD{*Z<~^ z0028q8T+e?j*tNW$o?gvGjwopGxfB0`iBAPNPS0sLju9?MW4}W?(U#VvLHdN(jx!? zfr_LPKr}UhW=u1wcU{ljJvYSqZO7hi1Kplk;$g!g<7lhK1E_XB;f~%w0zj<0U5mB7I1<6?p&YXD;`wouG;E~)ZocW)O3CcW94UwZXCBbj@BkhVc#MSl54-(cIRdnMyuynt_&D!x5*)b zq16*7cM%CcTXlr7`!bUnMKG@5t|5-rJPeN;Hmdw&u;BzjLV1Hn-qT_bm84gdtQxST zKW_^2vOh9)qHfFMK^eN#MJcm#24`=fwSwk)(U&-+J4DVPoI(R-0_PnS@LZ_|e|lK0MvtSQ&FsxScf+s24-EZuM_oN9vg|`t1A+$(?&m|{>&Vagcf;w`z zwpCMuvL`SG#i8qp{AC@0q6!e=2fWgfgM`E{S@sB5h<~SveXOg1@QF0_NzqKxe$kC@vF(bfk$*g9w1aNqQ+UDpdigX5XpXSUPsA2{ z@g|Cr7kCGv6XXY$K;)5_ykH`NR2j)E0;{H@SZ5PDI`ji{ulDB1Od+P|CnnYoy5Z+m z2bl%(E5NQ}mGV6(J`_JtPJTOw!8KW`(0fq)g|_3`Y+?&YY}=Mb5igWB{M#9SGoF;W zz2#$@lHX7={4ovs+%&gzm8(X7uyb9Xx^i~9;9z@A(R^3smX+O_*TbQC`)ER-K_nHp zH&Cx1pb7$ zLP}I;$;jmwQz76mBU*t-Lw~jpEh9X%vA<~Jc|Sj1lwb3#{Bb_W05a&4mvs$;wEVlG z(&0DJZYI5|`Ls%QduJO~mkJ#vF$i88thGL?@_bM0a z>uQ@(fsn&pMkg|z>QzuxG^G4+B3$Pj1vFtjuGmXsnMRY9x)sqY4EgUIu<`D=ZD+aC z$FWCBNE%!vMbzh*Fn5Ncc0a7D{kN8xhYcYXAbRRcMs&bX`~V~ZU6LA2_n^e{eEr+4#w+g?rx2c z7)hUE*8*nx%~#sn&b3=DLUxAR5Wnfm=g->*#hs$pCm%3F9_f1Bpw=K9n?^BnY0F7NcpRVK^7qGkN$pi^ghbF+xxGmKu zwHhOwdLY=aVLwNwY7=fVPC1jH-Zw4jsePA(xcd|?m*H!U6{nxMx7y~rC`&s1irA_i+Cl&Jtv+L+MVSlYRI(EhstkIvcR z|MuWi2IKyEY4QBz9v?UA@%_t7Tj6ubw(-j# z%5=qvKyV?i9vzlx>xS|3v=2TFo{QPr%FFC6U9x24r{jhN$FLu*!qBu2fDcWyoms-k1V|QPvhp4sn6@v{^1!^=XyLva?_TEv&bU5o-od$6`&bLdLyG`P zzRD%2ef-|Sa)`Zsj9nXQ%N9;~VAt6VumiGtdBbN%AqO6pvxDUjSmU@1KqEHld_Q1G zS$JGxInNB=g|RH$55}=!A#BAJK88S^^gBN3$pE@2Y_1G>&bHa@hqDaf&=LdXVpoDK zx!hfO;GhH-cc40;s9Pgj0lVzwxE#9Ha1#1{6@C2buBh?{Z4MURL0`XUU_mgDe4({- zU4_5p(5ydO!no9f4$|P|A_B;;2yGVs!C^aYl0D3OB&0$9Eu+yySflvUr7+z)FW#u- zDA}Y{VM~Rv*MqpkJEJN0fEyIkWYvu9)2Y-_6_o=iX_yeV&s(83G_^S{k5u%c?G+qKbs=uP?C_v@Byn z%~R&A=g=CBi>{MexKV_(M_MXNg)(zagxXR$T9ytJK(@^AYhmiGU(bd}X8{;rHbj7!o;{#_J#dQ_L7n))M2c}x`$WpW&h;sE&H z9!w1_HuC%zG=jkYCs)Z|;4!sx``?i9U!Pd2vh#0-e7_leN7skhn(25u;4s?pV468L zK+Ssz$~Z-oK$=Tgp5cP~+aBeN8v&8l!E^ zb!A0$=h|3JtgW`%C}a5rYl=LJO0Ab|^YLumA*Q zEub1q4vY@*Hdxk!7+9^W%|9Bp($)ryB7`emoO4S-Xw*SjMJp2WSXT5^C4jH^%Er3ufE{y?j zP-?N&o=8oKot?a}+IOUYgx+(TlSGevbjz7JoVKslokPRw@u&kV_Hz^^)k}*s{ zAye*5Dt-|2%Mu5&lv08yhb%KGm`6GlOp1Q?_R3Q^;g95|OzLcwlBg3?Ea`4QeGo~q z(2FFQVU9Qx<`X1BN(m-|5oaPMotfnh_;)#Rsc;qqYFr~M7*pEXrZ~=TnmvnQl{?~6 z%K|3MW5)uEtZK_DP)Dc4MMIqN$cX6y07XfiXcA&xxc%1+oxk&6q(Y9sVHHb)0cMPm zpx`$Z;!2SWN4ffH1fU?JP4Kw9CG|fesky$L?ofRIpAx;s^a)s!dSst$kz__z@N^aJO)sua@O--t3zhNjV%GKH z?d?8eyI*efFUKtovf>Q7jfT(a&HG;{U>Yf<`#VD@e!_wpwSEvR?RmbAFsJZeYsZFf z?Eepa`QM9fi(1D;fgk_?a)0L(|9a8wKTyQp+2bD=qH6fp^pEhBr_WfLSl6j!kqxh^ zEXrkUZ$N77tjBGsqMF!;y_5I@AoDlNp(giP$pm}rI)!Fp;ebo)m!e*vvog~W`Fjs9YwYsWU#J#nBjW?Q%gXLNMMODofT{qCZ^hMKwj#jXvV&`Mb?s(J`BSKhPK zGI!P0q?X=dIc2MAWT@Ub8V@F;o84WdsbrYdWKDFeUtISuE?$!+K#M4b<>2lU9s7^qHbd@+?gveO2sEp&oh#s#$3{e5*Tsz z6iZCdkEdJi&?9M{1P(Zn;=Tx=TQO@~G3{3*kkpLw?G#rvMfI!QaX{8q-+m^Pad_wezgQi&VXSR z3)1dctkB?~PF0{xNWPPtJT?Ab5LpF}%YxMZcM!Qxy72~GsEKaWk^t^QE~ zJGyHYk;&vZR9KTJWtvhFJm7%K*_R?opGQAO4sCQQGL>RT9gyZl$03-70dK%FmEw9b zNr@tvFsqCyMn?I7Iu9rZKN*<75zlG3z(gcpf%&7=!S&aQLe!Ao&?LtgU#g%mEe{`0 zNEC8dljl?_5hKirmPo&f$2^^?vJYaK90f0dj#V2_ktv-s32LTO5q%=N>26BuDX8Z_ znfdw6fh9QMyTNhxIidGDICo8VE2^c^(TZEApnLDTIW^IA0|p%ie|FQgdM_}|Xj9R= zI%B=CYci*XJ=q>rxKH5cDrA2O7tCT`p>ej4ts1>$I_h5M$#ym8c=2}TaacJ4tD;U3 z2;H%v=$Q7pKelR{E>Brp|uF-k}f>}$m z`)oRFnAB{;jgR7w7YCy?ul>_j!}4TLhkvt|$1jJCbGz5?gYbm~ah&vDq6IA^61kjV@0J>zoeD0;9Ojf=BU4gDaFs zDY?ZGK~UVA;7Z+tY|qs_TyT4*8Iuamg|7#QI^LL>o4*`?zK5?Fe5|RtGcRo|w6%Q9 zSwl_jHLkdOi{H@sy@#Ux+GLF~QI|!8$qHkF)B2sF`qlf_X6S#{yS)75#m!;MMb(`J zRxROfGBvCIyI-)b$-gA`Oq;t5{OZ}n>&FrdJYjj!tGqgi@R!PS6kL^kt8-PEu>G}b zEOfDi(1SE$e_$#6pek7c41BO_ox7RsJ_MYzepGVI~+lZ zmzoB)rP-?K)S0QQLU^#my!H7?z4TaL#Z7i7!ApMH-O>gT%l`Dj?k3egXC_Vp@1(~| zE7R{)UE~Z4+K0X+wflvFfMF`?2etce0P)KlqVhuq&sGQ{r*m+C10Iw$Yn|YE83!zh zycJR5kQ*%Unlr|Wys#;)@{f(38ozVyAFDbbnFKxb%+Fe5L_{96K|n*#-r16)O$8@e z;zZJv6GS|+Q8IJvqgW;bozM0E?CeTb#`IU9G9JkgG0`2gsHQ+Yz#cRlnDnhk zm=V!*7ABP;00kNGfXVfv74{LcAXHFH+7F1W==^pJFoRG)s|^BycD~D*EaW>TMxr8x z<9wKBpfzov1fyAEd-glW>r5%`;Ze#v(QT8V%aA}tcawoZvJ3(9PO^2po=lV?Xf|q~ zGs#XYo?#aOX8^K^>7BD22K~%LvbLBQtoJ?`%CbubK4MazqCjax;f{v(T`-x1Bv1zl(}KOH&2 z2-C+J@8&}%i*FYY)knuH${o$_&hX%G_sTqZutGOukF-y>j?)cI+(LR|ART7qls@9V2Bf5^XEL*5Ac7Y9<~?5N&a8dYyFFQwEq+8S=u?f7~0tUzsNx~>%Vdk(G`b&;8e0`nI zqs@G_U6az32-`{nk{LHgkVJcX?z#=F&&&B!Ji~&QvUGtgrU65ZwE>+)fFyCZwdP*a z$MA;~=0>HeeX5-R3+kg-kk!CxA9bm|Al=;7kd`|)a}c&^dja=Pt#>p5w{B%CRcJ6q z;3-K<(*~ur>0i%Ly=o}B8#T>$GKBKVyBI4rg{v}Ux`|E_aME*b`VrrbAK`R>-cBWz zE2-fMHgs+a&=QwHPwe{F6Id@XlnDUuxJH>Y^ZfoEBF=0<+UNbjH}+L zP$SF1tY8Sgv<)BEw>#oEU63=>(&{o9WIM?&bg)@J!kEnH@sl4oj|Q3-K6y+)ZoMX& zn6Z*E%F;1N5KJef#mpaYjx~{xe-X+U>&QBbm5b&v#!(C>7+=qZ4?QA{k0v2b6B-Mk zPlgcT>^Cz^QSK2JSf-#b%9;}k{GH0+Fd}soaN7N8P9*>4LTpmjKtP+iW6PNjIZn^J zOF6DI=AO#%mN3L@$`KPqV$wjf$#ev&>&UpLfIJHt0i+U8BQPhK3Y-}x@zkOoGC83% ztP2<`9ZD&fcE~~yKbDTABv!n(^6H416-dd5K?tXp6uCp3P zL*Ije{yf&t9XyDH5<`>YSRah0oUzn91ToV@^B&_gG-o0D1WAhVUVxIzN#Xb-EFVX3 zifK1+VL4do9$&_3Sfg>wBCWq~m|x6Y!8~%fx{*`*zu0@HC|!dkUAJu4EZeqi+qP}n zHfGJTZQHgv%eJju>-6c}Yj=-cr^mV87vF7;f8;+RGvbXmpQzT~W+FEF4Y%sCJ7WNH z>=bxD$#ISYorQv(6?HeV5sw(-tirPhMe&EkS#&tF&ZTm4CS( z?J5>Jr7eilXMK>!uaaMmAbO@0*>5#AruQ_@rqgBaL*JVo9o@o!`n`|8Y8MzL=Q|cf z|EVO}PjUeC)d^x|YroUtZRX~7kY{qLm*>6yuO)i%dZ7QHm|9nP#g7-F+-CDdA*L?B z`m+$@%88c>x(3XOJdx@Jzuoa&_o5tc%R9KL>9S*Na0dYq z3&Z+j6|ss@pv)~PfnvecDF%&(c`MXN31)KOGB!ZhaiJgElN;LR$r>#fO z(X&lR5}IzOd%Jfn{4hHX4yX0F;|HlbbjH5XcT7XqT67Qm7M!uqv8l5|o!cCETwD&O z2M8$Ka{aGER6XMUG~Z*mvsZ2{gl8v!WJ%)R2Cb%!vh+w*|%!NtgMsaN1;>tBZnrS%m= zJ@14)T#tm~gKxKYSy=|A3Gk@1ukY>{Hqu~&fA45&559Bm#fhX<-^W$=1Pwn|6%_JI zfEe$`MWFh0zeQ^U^!S-By)5?|z#xKQSs6?9K2Gz=pIm_SKk&8>Pt%_PIfsiN{8o8? zVv=y9{6CW$gQi)BZw32H~W#_F=-c#ydYY)iJ{376oHp zoP(>r>W|tlQ$Qd5kOHLZmpoUb6?lH^Ln?_H6PTx~JLrxgC_9tW_k~b@hICC01p{@j z^@-|8Jp%T?_HMLi1T(7<31s)I9RcVkrV8915lc_IXBJ>z4-JJ}z=mDpH(JaAqYOs& zk!GdJ6PO5TGl>MQW|Q0s&pf8zHjEb{Wz!-_r2?kXIMBAxH;L^iQZUrTC}Yl-{xkg7 z0;p=CAA65V6|?UVM)(hk3hnqI3<8j(1wsLWmBCGJLWA;4P6R$$ z?GdHcE>T95V46*ND?)LhC3M*dNeHZxsIf}lFKf!CgmmDDiI8b1(q--*K`?cc7g##j z6BMdQxhBHsPMS7Cz~71n(+Ol5Xqk~DWo`1@OogW=DR}|nb!h~#TQ|}>NIbix;boT> z(dDmnD7XXo2i8-mo2?CW_IZLIyup#zHJ+#JB;6Y~P)pdSW6&<8`j15|hGG1z zX1}6xWaSthg^HOrIl4nv6(*8cic%$itw)g3HO<^hw6_g8va7WbTmVdv+$YyxqJ%7Q zC1A2#+*=^XE@}=`2biz}N#Mg95t!ZMW*uv{c47UpWQ1hxUvbTp{)_7ybc*Je4>ajZ z_xPSz^{S`j{)jB?^Fkl8y*)SaSMFr9WvVO8;*@Cd1&mE`z}8vk9j+hm%DwP>g6152^i_l2+!2&@@WzKXDpL`HR1Z>AtNs8ATFW5lKoh z;Sv8JFH!qHsqd_H)YW@G=MT+K%0>DA^^2_S%xH}4Y)vi9{<+4iQtA7LU;ZDxx;5N( z9Wo0qidqr)df^Qa<1vylcHVKMEQEOBpk$oF%?~d#a*`+8I`YUWSassC`=hChxtC41 z7O`tvx8jbaO-R=wzs$~{Rov_>5BH1R-#NZtD5%T4%$V+Ko4E{@mC)9g;w0f zbXQjUUS_T%TdQ#6)u9C|`kXgUCzLp{^s1-X26j5{XmzoRD?V&*pWJ>$_e$-wca}W#6Ph-yT@@v(s2M1#j{?6YFv-vY|dhz%A&oz~l zT2|(9-QXqfNNY&;Z4G3MF_QSwW?o9C6q+$%V093CjFxJC0+7I}G8USbw%wAz13Kh) zlEBDSapIRTkZ(N>ucV|9%%sy9Q5eT;I*q{PA+fhB*Cyj4rJ#f94hyG*&&FnRbyEmr+3G$~>4T`@;QgxQzSwMWqiH#oD8WQU6v8LZ9SJ;HJA5#{X z-)qlGL7j_}+6KO&|=6tLjHEZyhV|+jRzD3bsb>@b;Kw-J#HhE?jB3a1))_6 z!4S%xqc-_PUHDVx8H#XZsWCu>|5~8f8)b>&pjAK)#Sk&%!cic3FX**04<^C!3TGcDi29?fjS|^MIFppyYP=UaBK-wsK^tTqVk}G&q5Lb52;!%cYtKVP z41abj%|H;@wCC}J8`UM?5^okfEfLQ#L%uu9M2)5eL`oxwQ(UXT$cu?K~8nU zAv}gdcDL_h4Kg;;3^_kEq41J1Hh7L({TRG8US4^lGt?F@)fy&yo-UelJyDEtG_=Jo zr!;4Ahk5OVNs1emloL(1vf^iHRx`FkhOEP*c_H2O@%i3!a?6OTGt|tJ237(d8`R~& z-i~mvzoZ{~eLV;0r#I{)z43B5#VJ=1f?XYai19oC9*kWlxBd#~0wCnLkLdjd5;S05 zMl(&0-LTVSYw_!Ke^-C=CdbKjgY9qtz`WtE=oFf>--4b)1Q$vb;-h!GKr$)l7m8LX%H!^5YfU* zqNxnf+I2oxn|~7HzMilC#BmB74wY>D>B?H$eGzI9&!p_LNXN$)W!dWgj|hq$C!}|BGAh7oEaX-f7c># z;vQkILZyTkk4}{^vWQyD9yOu7?Jr2YCwMN{ls;7^o?Kwkxi>D`niL)ll51TK5U zri04bWgsV+Et@d{|1ch1Vjd-UAI&$C9+f%wvfZaUpvzSzEzBDl6h#?RNo2cd1p z4g)sO?BWR!WBEva|oG&`)3DAq8tP=Fq*o{a^o8_~;VNQHTk0hB{!xVHBN63Nvx|N)({QUA?u6jJ|>~2GE4;y(=OG%+%{xX zBh;)VHU-8&dp;g~bdFiP?W2%l#7Ewlfiu!e3aUgB>6B&cOJx2nQ8|6u-L$9#|Ex?)c>wzWc$ZHgOfTLL;R01)-PLv{n_rj_#(+jYJ_o%QBbS4oOdO=@pQVc z3tcx~r_U>EMu)I$KAb61ot5iHGCjJ~(cM65zW7n9o|z0YSg_?$E$0(pF;TuO7U4qS z3g0t!G%2M1zmY<1<_VoVfP_#(^U^OCsULv(?>EbIihd;ZO`|5cmvfv(*v=e|U~hv0 z%E9@dUY~QdOaL6S=$mtoE@rD<+DOXR#v`TNijczMzbH&= z@^eMTQAM!hx7P@zmZQV+Y9c*O^PLEX3cOQ(O`wF5K&x`=1`1pew_+m)(xIZeyg~^| zGh{2NgNvj_p#Q}nF0=O^N4`*FcyBP_a<{K+YrZxnmp{io6kdUQ)zqKO?-Xsc#H2F@ zv6PfnD!Tw3Z;+-I4xNjlYap&u=zz7s??(ZaQ|eakPcbZfbEGwbE31`(s@|#ddF|%A zknWz9l3oT(>)w&-OW!12u9W^L@ed&qEXynb77bxX)?%Qk;h}RijD0P)D;foA@m{tE96J$%Mq;G5lI%J zz9@ONWw12Ns~XxInnt0=d8$eA_YKBDt^{=9jb&YA6$cBKdZA<6To?v>nF`)@XMFp; z@%UkIyl$doxA*0>j8RL<5Sq_s0Ix?i;mie+W9+D#OOf7w(v|ZF&g1u%$K>GkmHX`* zneQ*+6rW_4=kQ1~L!2YFhpoxdDAg#Bkhf_Z`-o^1P^!=qGQ$rFA@xwPDD!T)Jd$pj zZkSbO5otNZz(K?@<4^P}N!5OvcE(UdSonrMLdS7PuTOIZ2#iTL#Vk@RS_Y>eRyIrSRsJrSJq1 zqrBj|vj(CFPbe&vZ!}bvI&(EMn>sYSf==gm-$7q1B^Pu?czfo>wN^-$$_TxPrlQeB z=dwpsbC~#_J-t_=jc9{B70H{%b`Fhzy!NQK=j=lZdKd6plfIOE1Y5FUh zLtZhuaCH=AR=_UhSHp%JXeGzp$4pEv#c}+L-x$o$kf*)J5_Kk(T33$`M!z+WKf7v% zwoguiX3G6~E8In(G>(q_)1BZ#ENc=8aQ*#tlp4fp^D5GZu+b;ns1S`bNR#^v5<`CNy&$97XOYoB zVi3{G%o7HZ7q_KsO6m%|%NH~=w&LsRYdlm-L?|+Br`%~KRg0M zhA+`~#`)-~GskjJQan{YW>5O@^KR#x6GuSuVydEY8UzAZ$?jl!K|?b$avH?HQKAHB zTi+N}LS5>{TxgAshz$O2mrQ1k4=w;N1LkiKralL{8OanijqF)8@NmhJJ#GCQ4o zXXVD+d7;>FhO!D$mdAa;yt`Hl0=;Kd>&Z)^NfLIt`Iny^t8Vzq(-gX8 zfv*C=?aUoS^=GdxzmB{zL2Vf#!U=p0@0|MmAr$k6?q|15g=(z^;hD+hQ&#lA0o-py z@Fnhd+D&Vmxmd2!Jt8k~oo_w1nP|qc$}%}qQ%=71Wd9DZvK^L5DZJNU?i0Nj^clbfimjyW-|!#YPy7{0HWtK-|}N*zIC@Yi|Dsy4dDTLB9|rVSgcEl5v@ z2{x>93o{r6K=S~+zgf$bCvIf>`pMaZ6TIM+!!MQHuIBEIKo+{;Gi%c;Nj)|=x_TL# zR=_HTiDrv|jNNIg8u#kuWcU=V`n3qa!8^spIdv4enRQ&(P3k2CL0m=3Us|zN`@k^g z2%gE0l~Wc1f4hU=Gz>I5FHRV^9NNocSB&%COP*lQcJ$ZlewK4Tb~imlyf*P3VTFG! z#j4IAm6J8rDtSf>UOsc01}RejFC_#nIJUQwYyrIC4GGJV$X_mkg(k8rcr6j`A8~1> zLD@gY1&O7TlK{$X)OaGsV;zmsQ8?ziB9pltmQ(-Y2)i;zRcoZ+864>|$#`AoTG?I! z0w)w}NH*Qy$puD)DMz@a{zD*y;103LwWe7pY;B0a7Uh|c+%X-4 z60m7s=Wg5JdAVTc)_q^BGB${U z<^fBfi)KpHhRL8G;J@e8|7PLpK_!nY`>886e(K79?H>QU&`AIZoZz-fHo)t&{&xp0 zku*O1Iz*&Eps^$sc8F+#P#(F7Ff61)2XZ+~t<bHNV5%Ls@a>3-Q##PBIE>HVLa}65`-o5{ zIfg1M4HdLC9nMoRJ^3fe8;50`bJt8X4!segZv+PB3bz;C{g$hpxW(<$wpz9eATKzG ztpKRQP!?JWUOJ0e1zA^*@>Sx+lxe%6rL8XBc55E-OzRsF56D+Y{-ie*GgxotB3eS)<1NcR{1# z&U*v|r)npum+KO;-1|EGoE|D~7wUwX;^rI-8*dWpr8KN9UvhlA~>!%F)Ci~|L>S*jW7B0&h=TvBsh>n1l!o|r+$WM=57n@FUDNQY69Y??>yixc!iLRHF zQ)10?jotzTEn|>ugpyDW6UJrPu|Yn|nzSBA3LLY$){kGFc8Or;rY;JFJqr%AbmvJ~c;}N9C+DZuKJ(M8 zQwcG!h6n9`-NM?B$F04Ew%9iaXeHuFLW^rQKwzzB8nn%ixea+k*dOQq$$LOH~ z5RP;{^XE|mAty9LKQD=bji&+EvIt63TV_e{azCP1#@bUoZvem25H4vXJ7c(EJxOMw zDdSRP;f2)aY4SQSkVe6IC+~ z82_HzT{(X4)RsvWn_YT7(kz45KT6?Ct(+GvInB z3}5x-Afh_@j*vb5vSAOF1Aq6K z6k$6)+n3GYK#)C{!x~!GxX|^7G|0Y&KAREmy8+bo%A>ldh29LEBiH1vH?3sF z$)z5xRfTJUq|+MUJVriO07%e{(Qquy{c7odye;~#YU#f=Is8**XJqq3BL43*(_$BX zVxS+Oaq!Q_`accoe_PS)A6hJ}y%DX2?f*^~ed7D9g6Mw@U%yg0p5*Z;U-#q73T4n( zMp)G3v#!^gXNs~Sd_RkjT`cwm9gy@~@B7r8i;(o_xhkotDn@i%n5{Ti1Cl^*(C|?) zc94gExMe1=AMzGqkkk+uK#Vpk@9TU_B(mqOAk=V&-;27}+B&}i3Nj>jT|_Tdfy-&G zND4pUT=f)soXqu-{=WPIsHmesI{~oG$5X}BQNIfX&fcV#l0YJ|H(3mVH)`*5+FZws z4pBNAu2S2+q&KAZkC;(-GORVKV!sPAxD~<@=wy!uYbY=l|H=sGpDP|Ht;~*%(;Z{+B(L zu?wPy3B7(r;jlM{r*SKkFhFQp15yrn!W6(XZ@giESSKFz)6*B{u}LJ^xVzW%-F&Q9 z-lm&gj8L@jQ2V^Vjbrs!4Y^Dmi=3o|BK*d2LMr(qM^SRXLJR}A1i`a)*h3uw>iW#1YXgOg4a2%0xZZ8uInP&6ay}2qh*1yM)22%;@%&+eq+GVdQkA9Pv&VLG9OxM z%Rc@V%alUG5TrWV^Tt4$&AnPn<53-3M5|+|-C0T$4vhYlqg)qmgTTMMe;NEtx~JRB zeRc+U_lS&(=^`xZanX|y14y9k-ckX{%+uE}^dxzgdEboh@V5-gE1=ZucEx|}@qZ19 zf8BZir=T#lGjjUxVuI!NfGvj{0Kg;`0D%2}`ltOr3mTc57&z-WnVXn6|1-O5)92G^ zL$rS9`i08$kQ2O+VqKB-{fbzFLPHg4WxRgIkkyVV1&QBKd=CQz9pGoqg|FZH;|dHI zzPLiY+x3}pM=S`8r>Ezem#1kqw?b0O+DQRt&RMPUic*!-4A<+#SNGfPW(OV}9T?h5 zP{w@=oi6qV-Q!zUyC<7`4c$%M`Zk}9-RotG4NVTWN51a4L+0?Qa7ZMVOn-i^n%oIs zPy6_tM%s9rOpRY`}1l=N`a1`Eer4xPUUg~4ZoF3|-Rd1bATyjhKD z3EW(esu|O-EF!L6wO23CL~O0DPRJ9npim#)xSp|7ar|KC*M1E78s912PsE}JljOdb zd%WRx?APPr#qe^vX@#vb6JJ~M0r!zZzNoZTHGR)MkCWf}4y#mZCSly|PzE)F3(~9T zaULdqmz~GaXkFk5>`(BGuT+42AOOsERdg$Uji}*e$q^%_gd#Uj{WG5{NtnhzM+(+2 zWfX$Q9mHo>ZP&OyafbWL8so?!uip9IO(QmEFI>!|YXWJG!k_2?hRh9ncnpY_w|=3M z9ASD+VGJQIwi>`Db7MbMEqo)?ZDo<8=K&@f*&tCVWUv*(Y^^Ro=XhpGzubaR83sgQ z$Z*s;B?i{)k!K?Z7#vT7zayYbzG8>I3S`z+-#oNqlPbQJD885}HO=}(&r^BNtUx6D zyir;;x)8HkzO!FM@o9-pbE+TZkbzk+DtqKjYL}3Po}O;6zgP-TVTs@ z$@B~4a`;-xLq6U(sFui=Q}G*gz9tdf6K)|T-{CPr<+ke(_`Zo#fHBv-3|jw9DdFjy z5!=T*D3c8i@ENsB!|qle#WQ0l!Lx_FnDA)zRmr7AqbHAk^1-^)DOZb=(&$Bc>%jDa zyuNfWKDrMxG+?C|^SvVxge-txm9lng0J7;Tk`vKlk%&;k#(cCtJ#(w3Bk&Il)({TqG|-5B5D49L2um|LKhH9<=GR#C;oi+4a4$LXn^{X8*qkG@G{3#>J2E#>)=?uIz1BIVKGgY4WgUKfry8wkD4>bmyt-@xm^2W-E&@Hq+R(h6MF3nOSpPb$^X2NbeV%!?S^Q|XL$@O~YXUgH4K9$Paa zqKOst>-U8GzCIeo=HF0}Lus$P)gf1e*Yy0{@97^|xdFVb>jq|}7P82$W>Nc+8K4Eb$n7P!&%bEI zavxrOoeaD;bLXx=FC-Hh7qc{_kC~RUkTOP3g9CcQ58)sW9Iv~hUBKgRg#2xJ-MQKK zr3%978!hdxTE)twI&a(npZ+EQtbiZWb@eT-rK`EqZO%2_G&mg4a?^J;3h2d0P4T?| zOya)ZhC{+@?lC!vLOtW^Mb^M}61860^^+z-g^W2)Mb!7@HK3M=7tfBMb1yOM4huw=$~U)y7hg)CX zh3Zh$vk3DEeLrP<7~Sz>e2e2=fWNJSU5}7BC1Yb(aX`VqU%z08%mzmjlXIPx*ukI| zt*|JEc>ypD0vBZW66q8nsWD*qjF~eD>TS;0771n7rx3QzKZ?}?wldC$$M_2(FuA4F z)S#WuKj8|ZmZf*yz!9KZ`QNPQV>ge&xLD9&YG^;46NvdAai5zm4-NK7eB`?f*BfgO zh1^R=B44-+W_ z+bx-SxYI(DkTho#!}vfEP}@W2U$iEhn zBeEl6)vSm^&__Lyz;1#*5T^SJjlUU)Tp2XdG+@ zDf|@rwWt)+wP>B7?vorAkM-VA}JbhErp%?id> zNwPedkhqZKhMHYK12^w(l)s%};FM8PpN1^}{mdb?!82ExD8z~WFDQp}13jS~_!ig_ zHh88GmPvy~tDbrE)|{85;h z%K!xc6?CBG_L~t|2%t|OMe?^mO{M)XLS4Rc_=__L4{9jtU+h=>c{ET2TEk=b;6~_4 zQarrg6)DzFbBSDsa-(|U026QXMAN(8-CJ4v3qi^A_;{K?=F$L)UzT^wR)8UuQObfG zy)&|U{7Qo}PdY+)U*W(H8BdA@R)n+F0=Gt*x7= z31?5-7o9_av_k^4eb?d|qidH$C|}F=gC%5l=Op5z$4^Cd186o-h(t-@P0rU++3 z+86N*R9g7ez|sxQc=tpb{7C!_srxh9@iP7bq*Jo8z{tdf2tFktkKE!}3xa!-t7Crt zKkk2|{qdx}vQq=tCmObf+!76>Iv*(H@uZYno1z)83q0G?ry$&S5ab6{mQokYLrf>O zovL~5bh^MV%nI1t?UOyXxz5lSD*%S1y;7|^pFCs;pFVj8cVipZx7v$djk*0oyxICi zfYz2MU~W&+{>&c`>>pr!BOFFzMM0-Dx+Ei$$gbP_1gOwZEX&;xooSn!bIj6Y z=-EbshLE@*Xg3I(0_6!kj13>OV6(zVcV!H`1|YKCoig!a3S3)vPySGKZAit)6>=|QKO0xg%9rj87KKY0)Or*dDbz0 z$AC2;XWD!GS)jeT@fc9P$v%OX3g%cP$rH}>RV{7{H<({gbw41X!OaF68X8(Tc^=9M zj1m_4=~X|>6bZUXdc0v8IuL&S5r4M?o{(q_YuqM)6e!gEiy@x$qrMZAwE$7590__1 zNeZevznHwL{tt!X$z^F;=wY^+;j8*=R7Fs&HPlcTROM?ER{9b4woj;Oo_q{S=Qq!x z*08}ckRE5L3zDF(}`y-3Nf$Q&;eKiyWW^{hCqN1 z3hHV!A#-(u7O+`S8Ne1uW%8z}_mAF~M|ah9BHx#I4-i)#kV}RC06V_9V1~$DS@PC5QZ|z^53WC`H|L~Ki_zFyOUsLplx}nilZjssGtAi; z&c-*pg!Ds1CpneeN;eDr=86LNDh=7xhtKabyM8Hn&)nmpL-+LUumn%B_C9+2muk6B z7{6M*;k5LBok*9zDs9c?re&kEDf!SGl{zSdP=ubXYMl`?^ra(!xp&WZ+BwiXd)h++ zwMjN6s6S{;rHkL(kvOXv7iXtiQ3F8lOKh#iaR!8O{6-htOMzP6R`OwyGEsL4`QxfR zST{%AZl~VcIB7&NJ~Ty_Oc}S}qkK{y+nXU-%4wK+(%~LX((d0U{QHAh_74ZYiaS%K zcb0xp0#kgA38&`Er?1f+KA8i!Q9t98q}<-G#m{qep2wd`Q=Zat6S9<4pF;#3AARq) zsy;v2Jfm?$1*7^&;6(P4A!q757j%LH=eSAi8Ao{(ulXx$AsmUp=G|F+a7)@&?>tBt z3B?d0)^KkGMQJB%JPK+uoIC!&P$9AnKVTsXdYyuFRD89=61gPYbv2FQ(suiVim{lx zi6o>RMYsjy+65qLWC8L-i(-AON(RcBheLXv0*eYxPrn{?aRsxnrT&T(G!RbOXz8i2 z#4qtj;mM)-O%e9=YPY6g!q(#DqWQk+%lD{ul=aNR^%Xi#NxX;JY$RWajrkaX^6avp z-o!=fGNRjd2e+QgW_=X4xpml_25xw@uM#lT90}kW7HFN%m1X}yC_rH>fSsQD<*r>D zIo8jr`%qVt@5d_%!y)l+z}R(Cj4$$`NJ! zJRjOB2#pSOdxnhP6-`AQX>DlR93O|^PtV<{*PN(Gp6Tu0Y+LkXvO!1I>@}G8JH7|g z{P%5A@2G0bFC0aNq&RI(4&dfn7|hqak_IvXi?k5!P`oVb-f+>#hGtW$;402(13Ay~ z{j3%RAwFw@F=qp$JZE;=k=k5B{n2mLAW+L-7|xTCV26ngQL%jIWp4`L?6vsD)_I6)}Ea8#(Sl&?cs*FPsOiFfXlOYVLx znkCZ67|Uy{zvDnRF37q>xIlq~JAfR>S$&ihs2+JFxAjWs=pV+NQk7kTZc z=d4vMEH1MY87s90(kd%(7n86c9HHM6bZDkGGuSY3WNfgJcsosmw%P%nj(_n?v8ER- zYrOkS@@inWlx94!UV0uQJ+s-(=_o7HZd{M;7a*yNAw%l6GVEaj(cwh6&&fu#N25G! zDR&wC^#o#MK6Y5xA{?ksp~ke?hsa$>;ZmTlAIN@dZYVZiSFTtp_&||dYmsFQ5N%_v zSEI^NgGS$8;{;zSo7LLKp8itiw}c)i3#i&00iujFq&Yhe0=G6F=nr-cI4ZT%arBk~ z=0eC?%y!<9c^y({nOLe0dK+gt1Brw`8ADWw*uzy1&vkFhK~IYOQRm80&waEZNFSra zEN)V*v@IWVLbLRG-eEfnExG6sa(qWAnBjTif%i-H`b_}EXi@#%DraI$n@?L0)woByRgt=7IdFO%lk4r zFm%n+)H1SRcq@i_BmJI)R-z9{n)L;0dJeVC%eQlk1NQQ#C3*H|oWV+>7B=TJV{O~g zqQVS$7;9KC4NU8qc0h~wn_$WhgkvldybAmxe$r#s)4wurh%@4&#QE>Q+#LG%4_%VJ z(X&d9u8&P%xEV`R_VCnkGt{58w;!bdnRD5gJ+yzhifw>x?cJt4`Db!3*4(|{3RRB= zo&r%tl(TMYUH`xxMCGVWJIH%i;pH@rt`OmQQ=-mst3QjI68TxduoIka`L*>9;&2-u zun;SkwNMX9G;H|(@r{mty*VQ>VdwrMZa5y|K!!%n1h5eq)!84m z6HS(*O`pf>j1L+sUppC91eGIjPDg*XyFWZTJYTS%fDfzqPne^ezm&GnipymR?>Mg z$9%X~h?^6xoT7Cn7`F*cj3Q=cS<`*#I1|f8%gspzh4cF@m1Bv7u1c!Hai@z!qPgXyGwx)pXyGIn zONTQ?_GBz&;e>8+)ah9~rO5$x$0ODp1B^|^5m7zGwc?r#P-*8-vsqpCv2p;5#sSNP zd*o87-e-t<(R)awwx$vXw+eSU5oEPdT@4-p!Fvf^J>l<5w8+J=U>q9cuy`W^bh|6a zVpcFm$gfV7Rv?QcrI+V1lox2Vutb>FH}hnGEMMVCv(!{RFvh6fJYKIYxEJp4ZmdD6OHI8h`@^iqJL#1k!c6izXb$AMS2F3Dq^- z((PP1-c6iaoNoR+reboWw#}&`f9th=Z*mxBFWv$5CsS`-fC6yW#&bj+Gn*G*W~#+- zXT2w6q*?K9r$y}NH5YDu;ZQU;I6ne#8u=3ZI_!b&Lwr#URD)fH(CxBB`ukccdNX`K z1yaKBtw;ExqFQ}?AQS5^v$wAk_1!jSz#i4_5g}9%^wC{C@`~cR#A{7dh3`n4{ihD! z&(J_w!)dCNI^DHzlx=p){@8_mnI`^Axd-)zRD+>$xDW3IhD~X;E5GB3brfw3>U_R8 z+CRXp{QZK7?SMW^ZI=@Q56<7BCyjA4&1VowYRffNtJ|8{(13@O5^_2pq9UvMP@j!k zIY@|G$-Y0xKD+w2Ip~p%e)-Il1|k8?aWI9Z%fjd)&zM1o=oi1_c18lb*LGAxzNfUA zq~B%?6}(f-6^j@AeY7P>YH!4JbM-Qh@6uN3dVAJ+4(F^s5c1-BvXO3~LAT>8pcT~> z`6j=fJ$Lk)#v0P}G5l8U(?T(VnOh;bSa`3DZ9w0g8|>(kC=bA12J9(3X}@aDL^kpl z-MEA=P1Xy!E)s3x!%fECo@z-V9_t?iWu`N~(gC<(DZ1FDWB=NrL>jj-uAR8gSS_Tq zy)omm%DHE&tj*4_E8US6hXAtHE}(lWuB#seTvldjS2-*B3X^_pc%W2M7#-+Pqtjo0 z&du<~zO}wyIjh!;@xal>Tp{JE2E#B1h<*2>i6YVQ5FVBb2ga-)wM1FYUEs~D39Vph zOG)enEBXOLpYMQfx5X@XV6PF|SX=5k>@NVy>Dz?C$e%m}B1P<*g^~xn7pqpAY!EHH zgev$y_ryrjiAMRpu!0Zyp?!88RVllK=qTUN0XO&ryyYm1Fw4V#;&o%8%dl`bB;Mrx z(F?;g8tX&zxbzOp?WWue=9?xYi;=gA{#5^Z>YHHQXTaIgpH@LE66C*)5})ZaDlDj& zeC2e+U1v7-L~wvm^{JZRXC7TI2yq~Qj?1VzU47%;V)#5A-0N&)Linq2iU8-24I*u* zFr#QZQ_`g@rhjMWxGdE|Mc1xlA}e{+r5wZ4S|5pOlDVA-Y!MxEh%ES;D==RJzv#8G zv^n5=rQiiWMUlo#ixaTkO?xBo)Rdq^XBN0Twqmzqw$qe}B;VJtQEIYMr{U80o(gTL zx0E-^+od_P{p(7>kLTIQfOtCXb~+4cpMz`7 zs*O*HSX3gL^#)?jVNz1XLKDs>qoHK7HmJJPp_F5xWTY~)^N!9b3Fk^)#8-cu@hmLp zt?;P8=cPlHbC_=?(L)&+zT>oHxy!O+r@#^hX22OtV6zN@%z+H5mo8_=uH~RUq*=Uo zE@~QzIc_6T!6P*Qc#qCBfO)SM+i;Mk4(}!iJT%l1RTy8K1;__;gdI!U)(*MsO%F=N z-xdv+$1l*+{V+}?u8)gqEmx;v+{{SINcY4yxhd^%HETGlKsQzWQvhmP66sgXebgk$ z{Mo?$q)S6%RrRddG5gBk>K3r#A4ySCjyX{a5LwCPFe4XEhTVr~mX+5}*sMLcn-@V% zQO|0yu>{GfM0z?huE6WP>hU1ja-(tSjnT+kUhJW;sl_VEeLYwKFAa#$4aTbAY}D93 zszGbZ(bsGCJMIg*rGs1h4=*A@mHD%|7Pbo{6hSH>tC>+OWxWV*Iktc z|3nc_ZVSv{ap{mOE(x)n`>8B-8>MwNSRQ-e?hkeo&}qa}$doNX#c3eh-mXcH+faip z2^uxP`}@D`$1VW7KDYATNNF{2OVk^ransF?VJ#U})h5g%60bV7BN|*#C^Zs-hjF6c zoicj+GdU%?>%a?jEc4J#nnWcoAEqCuSBz{~Sc}6lMi(;r1JfvCaeX-=tya|M&KNqC zRLh2Pikezq>F5y83pOU+7V>$0e|rfUp1-g}VegIbMz{n?k^M9xN4EY@uH z+mC2D@lZyyDUSZAG-E9-FCTNWNJFAzLEEammq>rm+qjMy5g{S0yA1A_UdV`sZ9OtrVimT$wYTx*-$QyWk{bj(&DTg zle%AB{tmB8;{CYlk+^H2s*_9fGpfeB*Y9(aLC==N``Ty#j+efr9MFu0N&7pIspBh9 zrIw{Nj0>1oJ1o;E#&Y*HPOG{t5fLV*-f=ODUpaoIG~*v$O&UWwu&Q2< z8Clrc)(W2V(mzJ1LW-e)r6168{)34%sMT*Gg1wBkG7rydixpoVmlkh39oU+ZAG;19 z(%G(;D<^%3`^2@;N(=jy#2(4GlZ9Fdlj(|M% zI3wEMDWQs~h@~xoLlf&uc+)AZqxYD91Xsj~xD`M>aU}gvq3Z68FhH}=+Up0^ts2~H z&0rI04uUV+>t4A^Nd|-H1OCZ|7R{PbLmIA>s>z7U1B9!bh4F*E`ZrV1{5`2P zoxK%ThOFuSjv9Agrfk&26)m}FFFRH{>v+lEj!4(Wb|nu;{RDYs;CD5ANE(yLkkVU7 zBnQ&JBD^d~1g7MMl9;_X+=Bn|p5mh2e^aWBB{K0B4~HZ&alyYCNjZ0?F)BS%{-Y2! z_ve>;u1X_>q{Y-kkloBgxEf*WJw%)<#cA6?YnN~GQU2t3^P0jnmCXUw!4NbJwIU=wAwaD^u(^zL|cw86kVAw(vNV&|M~YMHP&jCn&mVi$zp_Q8bM|7%Gp8}YXc z$d*zvZ&+FEPTsPz$;r*8_BE{Bpyb1otTL=?7kQA%G0xao9m=LZDR|ht1q@H2$E!+B z(;!LMgtzDJG+(q-mzcD3YzouEW2V}`Uyt36o(ySu(9pJ>HUXz3kB zZ3$##d{l4_V&9T}@-&C6q)6f*lVw(elL?$R>6Io$o)s~f!S^f#6j3h)jX&EtqRzKH z3b%7+9y`>Y$1fYzyvx;V3NSzl0jup!)8yyuhI~XpayfSvxfyjE?`&wI0=kN}4(#wZ zc-kSA1IavhbZ;E$s{;T!{7J*QEWyR)eKVNG@RG-{A!Pxk#baeRM2;0QFApK#2i;tD z@q7e-jwL6`km6c)S0vBcZLJT8oi7UQp4Jtg=JId;cJD{@8}pkq>fSdHx|>#tJL!v} zKLPV}t{>!PP^8*7B9JD5fkW+NLJKBpP{Do{0G^J46#lEs$|}a?JDGC6l049Af~-@I zT!gvdHnEzvYOyFt^|j68HK7n->fv&B;1OS5b@cZdlUW7bdMJO0i(!n!bR(S?&&P>k1&9+ zeJd>AGVh@BxAW1vo5-NTq)7B%0Eb9xhkY6*0sX1hsgAsusDRq|VfV1%5hbxrChe|F+JWdf?iY1;d+iOVw)zH-_!RoTr9)v-r$c7ecgMFdIe6Z%_Jo9bf&w9#`qR zO29c9_HJD%17rjxxE%19t2WR@wO7GW2`kBDVl@2L$|lRn3$#G&K-~X1Ic`Jvxc5;B z@7fk`Chp#ln)bxK8XjQ5ne)W8%(iX*9-B2}ly{6Lz5#s^EvqYbPOA4ine1A0gt2thRxt8-2~1`;A)~)nN+#TvMq3s5DD}xJ~Ol zezN4For%=xsgxQok z-?BdE;?!l+4}~H4+iSAZJC4F<4<>g5dLD-l%l2iXOkkv;QxyiU9z;@QmrJKg)D-<5 z92#*W)t0vW-%h8$G+o&5<^d_?=!9IFF;e6 zdTdrQ1{=P=p=EBNND^^Pl5sl-zK>yb7WCNtW=fG|9o(W)w2o<%QO~jC`qT%j=IH6^ zf9&lko7ti*SIWV6=;HT`4<``s#&oN=G(wbOXf|JuraZDD3D1p8O!yti??xDI|372= zKj|?}og37KdLSS@9+3Y#5&S>&qphu_uEBrL|7IVry3G?eRZ`gA@Owd$W8x(;0M^Gh zt&0v^3Jq438YxRE9b4!=)CqsWr$oZR)PTy+t{1*uIA_&wKmwK&YI0nOOA0%yN&Px= zJa5!3ck1j=sh#A0tQkx4J!VeLkimpWY)M zpE4=lIR8rz$RzYCWjf^~pBu~5EpX*xUUmWKE4j8=MBR(wbx)o70J%CPnjW8Ao{6cg zn@*Xnhfdv7jpU_>jiL`yp4u$F_;aI}k<%8+N7F{lSPGNQizU{{H4Uro8&(%tnd?cB zSp-H))}Gm=ja8H<)1&~g!c*nU+$gb)*9JFX5-Ld_%Z(Emsl$vCI(W&bLAPwCn4cV^D!wL zd0FOhXZ*6qpw6s?%SEU7MGyJL#_A}CgrBU^<%kb!wnxirql|^8jV!Ub{|>0+)(`HQ zN@OV<>C5l91h-a;4;d`0%O>p-nCPDW|DSRd223zGz9H zOFG|TZ1_#FG*)x<R#t-ZvA;Pv%-`jq)QZ`o|2hoSHIa z3&Z5r)#ZZpqSL47F6ZRMEP|q@J74Klbs6f#1)ChwaVM_q+Er-Rl%Kj|`|p&Z%V{h1 zDY*m|_zt|UwARcHp52;9`wvjphb#@8(!j=#igao6!TnUiPw?-@Wv<-K)!Uw-umms? zOrifmYN@Iflq#3UDXYTdl9u9wrQmtqIH=LI?#y8UZ;L5mXw~2K-7mDo>s~pv<^U#* zlZt#+O^hW~=ky=%MB2#705058_Em6XaTj+0OCOpsthJQ%CA;LJ6HCTSWrKOC6I9G1 z;n^AsQs{zc0RU^IJwuXLGWDkB<}2kwVFPw`lDD`jX44Z?kye z@k{lNoBNt;@%+fN*Mz%I*B7dlM9H4WarYwoW+1I5@JIa(Lz;xSDy*r5ucf=kD4;hW zSmh+#WVMI=pbkg8HrB4bBgj1mK~vMU4mzHy%uv(o-0Cn)|6xlvj&yb53eO75yynl5 z>Ez&4Hx>Pkvq?V23f*(c@=0x_KWFDMbLv}on#q1Tg?R;@HkI*uM9daDS{z+{|9VDT z&*(W&QCuWU3M6pdL+2Mkjbt#UJg`-G4)VZCgfY*X-D8r z^xmENC}neUbVTik7k^4^=80^^o6AtgRjaVhpR;g{acb6gD`$v3=AfKl7YU4fxD69jJ3P^v&Aoe7x2~E4RDYXRd5Z?*B{6?*;sr( zD430W&F641x{3nLP(#*e45B)W7KcQDI`E?^Cy#kbzB?u^hM7u-TS^x`XhyM~LE`wE z`p-Gixe%D~4Zoh)XN@fk7U7t1T>ZJTijWL~h6WbSBTq5)927S`M47xFcIk6@_*Qk# zdMY2KP`>_PwcG31NG9v{xmL(*&NbI@Cjyw>VBIj{i=LB_Z8M?qtGW_g?41{4 zr4DSQnv#k=g5PE$n9ijQ)A-yo=ex6AMPu+kiah;(dRd`iBxWzGtj=K6;Cm)9NXO&K zI7wkTKaGV5HxzQfbi2#X+`iM;ov0v%-6JtMyh6uNg1mI99xyXq{wS?*a!_#9co%Mw z8M7-D81t)r4AvYG#X?Faie|w?P8Wd~WFLzGZ`3C2a11L8Ay!N;vq}+f1x&bmVZTd7 zLP?fx3d?2-8s?95C~(YV`;X9Ldb~J~d+gkDm(riTH%wq`FG7=rK-WFcV*#@w1+v3i zFOque#7l^KAXuxfvBJ#I?H0Z~el(mbr^-3kqS z_MYGRZ&vD|Bv(TP1<{S3a)X?M# z-H-ef>wDO@KX*f{2C#nO&I_zP7FP8H^A`Rh6v)0`zSV!d5S`|Qex-AmVTd66+}%=8 zycf8hbcT|5#F`x$;(vHjuFADMLi1yldb3vvPo$H9okBzQ7 z$;vr(3Pm!#d_d|hy)yq`$9p%v$6;DnQOm6k=uY7qA~K-{9N0(dwT{d$QR{w5U})3Qfe<_!NzO6a+EEO_H>P#s^B}F*)8lDj z&ABXA?$k9CQBTQQ)k4!LJ3f;h&ytutS`4G%BIwxp(a7?i2K27Fcz5B6pt-ad{?GxlSy%#6DNoka6#Z#q(sYUx#xGN$Kf5%*N7QpqEE-7-lbgsR6`O|@TSt@n}{VMEM( zKJyoU>5qI|F^w`V4o|;6Bc{sn2TEKOx8q{tma|!w-Fu1Y|l{iBk%UIbiNkM_*{AVt?ae} zxx~26c69OGAW(IggmQmvS1#AH2{|RP=aDWumd?u}0L(X%rnU|pfw*;7c5D>nV*sM% zb}vCe`g|_eDeY-#>wQXbeMvmCyDeT{N7yx|v^!>Zgi%PbSLBD(t+7z~ePpEJ^lSx? z{ct=d(+6@LxFjD0@KI3v%K9Fff52AVK}Zrit(RVQc9i0;*BBwwfh$pHn00N2NqKu~ zU@Uko6XPdHyxwCLfU9MjbsE9ZV2(|$Ol2UGJ<0WA3h^x|?U7n=R5M)$Dgs{_WoziJi73=BmxNBhCDNU$dGa^o z&cJ->SL-r`*>-4KkhU8+C-}3`9cSy__CZGln3pT_0gbzdMdBLqjmT{F84QJngu=3l ze~&M4f^MUntV7OiIlRt0k9cK5dcP$w)pcI)RCpLh7FRbpw)OwiJLhJTd1+3XUr6uk z?}lV8tYc1!b9DTuzFS>$M~vI}Zg1E3EVR{TufB~p1t#_uCoY-{U{o+!$rd*a78LA*H6XI}}j68bil&QwK;KJX8 z8SbvQ=lEDwg&PqtXc*wh06XU9cp&#nugsnaP4e=Sup*i~(Rh1pHEkN-0g*3(^{}Ie ziRNL+DvZ6-C}B0$INn1+Sc$vC!^x7@AU0sj&}X&^jqVxAbqheukbtP0nhl+foG8$`AuJ`c8RLS2Nwe54JuFdGUi{oXx17*9P(C>XM+)<8boyZ)fAA94Wv`aO)%J zwba05W3$!R#}?sfqwUYFm`v$7{MNQku@;Qtn(t&&qLLN>;?|U6#sb;}i7^Nxi#U>{ z8m;%vs{0dzuf)&@pa_RF6euw;ee1kdZyioJqZe)fP=8(iS37w6@gT zR^mi~%5I?_GDKufX-`_VJXxT_>eAB|Tc3$B4$mB>Ty@5=Ed+w}M)Tz$5c_tiS9`#w z)VmdVeDH?e7(9oiE4xUz*GnGqD6#dKM&qeqHvF-*&#rzbcV#ez23)Eg6Kq)0iv%k! zB$8Aeag4#zw>tpZs&&BUmbf^}(fZ`TgSV2CvBjt7>m>D=%z}$jXpz#tB;83>GelvH zgIi9JP1K0J_-;yZ@Ul`u8$hfBkN;56)am*{v4*Gp6RU^9?6Tw-|V zs_8!Kq_GtKxy4S{JNhZ+l~FN%&Vu2>X}2sbDGouIWQXw6Mr{9 zoSe`*Vr0B;`0(n9KPx#|yVPg<*v ztXqz@w)NsJ-yrTol&|}!hY;SW!!&ZSIUWrNv=~~B*zuOVN1~@C1+{X~4S}`fiZ1C( ziZ1U%q1sU@wz;TziDXmIh@fT~r)Dl{E3Jz$1L-vvLJDJW>9o#Z_dAxP)OZK`lrT5R z-fN;2-~x@3jV;U_L;cSRYnS=VG#3C;PHGv32=>tlAk=HadP0RfESBBSvpvoL=%K*B zf~R@7TWDBaz`a}|)zV6?$Yyb$jT7CJeDOt$l%}@P+^FrUsq9Es6Jb3dItFcar#Ca- z_mZW`LO)AfyEnA|bu?oOjj~>AuzZn4PQxWZj1MinfXnf41k2LKiyrsr;*4Ckb5d9C zUa6GI%D1I5TL(2gL6jccs_mwv1DgK|)(D2l(_7qvA3WUf%uh@}dh_U+eQusu?xYM#d-IDaF3D)^|SO zMV1QY#DG_pJzEAv)KWZUyP%3{5rq7P*2eF!SY6yZB9H6irbI}>4w=QZ6IllSgIxL< z4{ACdUbY)|Fno=DjN~x@|Jt(l-FwyhZkU6&gD!?8=$TRT{E7C}>Y>vH!R@1Dyk>2f z6TK&zz&$uKfW;H6L?W;0UZ3v?4+yIZ}jzBtzTuyK?E zBM@RgNPO2D4bSURV#CgKxBB!E^Hfgui&MqZyRAmKeaiyK7nH)I&X0t33gL)<*_cVe za#?~DrGrJdk$WCG+6vYb%gZ4HUBG%m>Tb#vH%jYXU(>*9>4c-=ujT3LAmD>)Hc{8d zA)Re)Jhx!-NJf}nEmo+>7vBp*=ITwx@k*Q(tx_R7vKl7TKBqf>vV@U)dC$D#FV16W z&Cr=_DpDrlGN{;e^ZBxvf^Gu2rUb}{3hI9a0gl>68xy0szOodqfF~;{@g;ZLgcpac znG|q2x7$7=t)zf-)b%g}Xy(vHLopKOBa*mDX^W9HEoq~Sn=u&?n-y@WqQdz97=ji9 zwg{70$&77zjpeN!`9VjnfbPskz*`66-%zaEXiVj zVX)bBWCJ6I$ZgjNIph;*aRU*Of_09|W778Dd0b=E!)^xv9LF9?c|^BEs!*E^mf+s* zNl_K93lJ2mN_kK_x`$o_8*(p*xDN`q+6i`~WhN_rt&ocN_xY-ICttgxsmtll??)`8 z@7L?6tD;*lOK7oKh72EoU{0xbU9C^c$#wqs2K#9ZlDe!b*m;QQVNU?;O`}D3u(e)@ zIF~ImgH&+_rj2KdvX#7wlw6uPnR3O*Vn65Hk30Q%bv?6ySg75FI8H0CiAh34FtEV# z9+>shu3PX_xL`23Vy>%1t z0V3Q>$+04c10NC&KkA|hhf1^Mff7(dV?1xKAS*GJGF*#fw~wBj66ie_;{5G>m>tqM znL;mbk(#aA$U|S8ZXp$#<&Go3x?$4i~AL=dHzPHZU=Q?~$I8S1nw?B|g zJ+~9lW3@z|6UlIH(MbOkKo1$IkvGuzr%ZiL9bW{K!3o{kPD%3_@+Xqk@NPo-P(030 zSEykCWD&Miw459!bFwHn{e-$e`(p#&*HOS2L!Evzi-7|5bsdPpICIlnf7nf8mee>w z*a+s$hsXKMb!uNETW-r$S_-x(Rw+wz*wmw?y~E*Zb5t6<(MBobuvj{5D!+r>$+8?W zej9oCcxA2K)e85ShgfWACy&BKoo7Vh_a)tp$>J4!0HDjM%?m3-nJ$v7-cdHYgX-SB zubi(hM!Zf6P3+wf^J}`iTv_1dJ@!3A#14Nw4@4jM5rNTT^)7xD@ZV7=71J(u@R5YB z>*hD8Hn9I~l@rVzAT*ng7>r$fZ6WgO+Ry#FV`GM&|JGLb=le6@a;bz2Elp zN<#e(#9aJX*|XbOD~NfR$nB0%KOocMaB;}HIsn3Sev7xnTOIk+@Ei;BSM2sN;CP2v zvi$_oB2Tg*bJeK`^X+e&@%dv*ikTpp;C%vQjxRI{`%Pe=#8mi8uiirVkib~5frPLS zV*ywvmS7Mh{S|=&{r-X>SN(n z+#V&LSRJO#ExmEge|r0Y*4+GShymLlCvLyLpmcgq^je_ERwG03%b0;)HX6*7x)#DF zZU2phPwZ)@R1asw@ZldC&pzf6ZS5>&~F znqZ{n_pc6`pPupe4Rll%`MC^P@0;M9Y^6We32ePnq*^l|=iH2WUaT9ZGJiU)S%g{{ z4C*Y`?%T8(ATRd46cfjuX(JUieJ2ic3mfTT#i9)U{GMpx>vuYk+B&RFhtgS2fT#Ej ztv=kE$l%qN66FiZvSlmVdKoMc>z=6M8ETpjXr{XwZa70RD89>^RX8|}n&nhV$a{H4 z(wZQI{J~pu5h{$>QK~h@WZL&fff%S45mU7q3y))+x+Y?}W+PaQ8~1)--lmUj*&T~P zxLdO&K->y8%%N335e-9uIA|!Od71-`>e|a36j2h3^q*Thnw09^rU~Fl>nNpjb!D}R zu*;{n8oC7YX`GL>SE89PshiptSh({bq(;<(fI7ljkOnE*+}nEll$u()X|w_JGJj>A zF{WLC3|AcWI~yfrivBpC1bKK@K{_=VPJS$vj*B6ZH?Z@q50P&uG}dOkZXlYLKCcs) zle&fnBzKTk)pOB`CeW4G3+-Xpze)nvT`AJZbUgCPb9S?hZ1F5^~0B^8_`^Z^GVb- zpoUa+jIAQH)WFwlN9=G1n}%wMC>r_?E#T9wv}BUS%ahEA65luWA3Xowb)3N;jsVF9v{IHzpYuvb#+&K8Dv zsdPwUhj$n|uZC!>K{cAdE&TDtag%A!7|hgUj%bPK?IhSNff3onOvS=E(M9WY3OB5d zsAqlGD$Ua)A&;yrE2yuX2vp^nq8vKXi;Mg35R!8HDYMDn5jq;5b+}-ep?>pg%o|Xk z$+o;7Y}&G#LT%WQc$FBu?N-!%!@8e^^YK3xIuNx?{Ya<>5cUnh&Ul(XT7AXo+|F3t zk#qB8ugs?qoV0>S7fDTz3B3L`-~%F~Jt7b`8fkwEFaOM9gQhf|CEjvFm`Q~q)RIaa z=7NHb)wr)FGr*!FT-gjh6H}Cu?hx3_>dCmuw%DNchZ$P)>n!e!I>3T{S|23eGr4KbiLs^{5W9r_SpPv3PZ&yDVX&B zR(uh27-A<|GO|mkIqIi~AZreyjjIc|QzKP@{qFA|^HEbl+-jcsIL~60(@DdXaET*& z#8^iJD9*7?Bhe6*nU-sbl zH0kcI=|*9W2~J9g!tD+k+u&OKZi!Zm2 zC^P!>)$($5x*aNeNM$2%lFrRNT+@8AcYeNHJWw=v&*p`_oup$IHeGGG9p@mU+81}t zrq#4q%l86H5?zCz${A|ai~HuBC>0!%_JWFrZ1{+0re5=PMTmn2yv((`$`co9>}Ef$ z!Y(jz$(3X5D7A={udMMipNz1z>V6l}Ss@dOqg@jwK>d__yQxZ_Q-TAo>n$|WGoMnS z?wz}G}T>l6}Tx4JMypl+6wKs(uU3V>sz6}oX9hx$1} zQF6M)&@nzAsGP5>CUtN?G=TI{+4$QAD)X%=~7! z?8OB~iM7o1LbN|kNb5lx=mulbMfYu=(=28RvgNE^hehNZ#w*1s#D6yzy;g3_eP$_} zZ@l=O3V?C2ouBDK=o+1mVo9y8`5(QupWfSp*FO#qSRsXiekf zp~xXYw&`ekuC3VkXZ3f#Z?9|Z(Wpn8=XalW0jVxVg1L1%b8oC&Mz2L$u31tOwcT4~ z4yRL|VNt?*+Jk44SJPzk13SJt>jrIYXN;B97L*JCYChTRyFrGp8(7Z8?%41Yx{>qX z9Q6{r&hMvhieJ{eNK+cvecYpZs`TtEwJ&WAj?2>_3^@fj*LU{v&@@<)%f1Iley7s(+XUr)lJ5X;`<|8Ob=!>~=vq^H-ktk}? zi%&5>--bOWammLifiaVG^&Lrl=BZ&NOe!k7GCof#mwt>pS|lvEXe*^-^~I%45-`Lu z<2E{_ska!S!c!;&ASn@K446)xmtjcuXuK5*mVs7}$4oGSipd)KGebNAPcTo6PHEL9 z!^;warxMs;^XX?VT6f;cOubqov0biIqy^UT*fMm5#!~MInCzbteDrCRZ<7l2#Mz5Q5JgciNYQHS+f_X zIv3%fuXOZvi>(QTJqIgD#B)XcZ%IZw8OP>bfpr$i{j!Ink(++u?wh&Fb&gin)IheuQod&CWQ3229YtNyVkXy$Eo1Edr0Ld} z0B#z*UBcY&cm>@RX<9}o z#&R12q{XQi6Q>c#JF=f4y;`z-w&F5B@6doqrc<7MyqfVE^yaiQ=;nh9A6(-2e-b}N zUbX24q9NhQfdI)DI5+Z&B=E`%ZTpx@%^2SVOsjiiN+FEU`5qt`jVitKV?$NR8ui!= z`f`OlsxE;gMLIMJFeG}Uyoo$(LIKKr4{56%rHj*%aC}ZV@D`N*bh7z`i^F>mtCv{@;F8z3 z^OC~&$D#v$YLR8zt@Q`fY3V0;?H>0)qSZFOsOJE`+yzGCr8iC{ZnQFskfl&v5eba zPklls^*Sdd7XY$_Ky*R-_uFw1vMraS0P*VefE7BfYVip^>|p#i4V~cRWliMzjs58r*rH3cQZAI$+etyvn#kn^s7?_!JRo9f%(VYW6UCUMAa8C@&Z;yj9bB`^1spVzbG;Rzea z48Tjn$q#=bt}O!*(v_yM6aNLHZ#CI6lL)l-=GRGyL&$YSooCnET1LtC%Lp13GD`G) z&HP&U{W6m{Xr);97uLf45;_o`oDMhZ#?UcKZr1FWe!l>4lxymoZM|;H%uC(+An|J+ zJH#f(9O<@O0}^%O0d>~dayok3c(M#(U&%Y0bL!2nQa!(?gCfgrb;g7(mj6D#y zrg%kDo*bhMdQdD7tety+>c!&y;JOiNe&CM%g|F68uBoTs*Hc*$9Gvz|6gL!zCerkV zvkuDc5x*OZ)T9SM{ToieGri@216uj}YwN z@-vgvh2?ls(BLJcax|_0bw-0@pADjw(9_aDbVdS5ooqg9RJYy?z4y`sVZ93nMSlM5 z21gZ{v;alDYzMdEE7O3hET@mfC28aZxCwkSd97eeeU_f{_ocmjv8?S0V1m95WK!Dq zx6<=eIJ|)qyB5VgZj&5-nfEq-&DPN{Frxfx95kNQZ^F7;$BCAPuL#&%4U^;J29(Cq zqFuA}=6vN9s%cJIjHwCl>GT5}Cn-%(#pEy$WH^u(d?$VH8W}T{s?AkNG8&uBTaV8Tq%Z1tJ8% z2|x~?_d6A%NujCE_c{dRvKgQa(SZ2{Sfk2l3)DFx(*n6g2G?Dt!LzaALio{JX&8fJ z4s*v?>dhQAP^B0X9e`I^wY}HjOM@BVdaxn`JX61|3wG@1*iJX=PJ8o}J4tHp1_S|i zS#f zd8fbz+7WjD89mv{vG$g?Va(4^(DYb`%FS)?IVJw>Vj0ef9s2hQUg^sa{M6|7;QFqF zHkgO)7Jxt*WE@LS8hGwr;4KPyYD_yXeRH>lc-wya)*KrS+=|G-W4+@_?eMSKh2FpU zD-^N1Ilub2w~8*LsiybR6;uQ8F-xflBeWf3rrX8xh2e2VkRdDF(!I6Om~zd46Y*gW zziwg(FFQ;=C>)79pg14={22a47c=+P>U;SPf8CL$y2VUiYyn%=f100tp6@Y)Y%tL@ zjj?7nHXdV6-z6gkB#r~^U3mRRGtkz(!?M^6K%OpS@?rJH2Kp?#>yb^6%*m4>hTtSe z190I2ku^RpMi}RoqtVZY8Q@d1-t2FM{^z|DW~`Vv93jk5g2{V&qMqwb*0Mp#|NM7; zS`hl0xWy8}zt5yLbK36m(iB~%eFz1QoSC0#35y~+JVMp9Cr4Sck zuGsS@MD&`Y(S_KGU)PJ$0||6h#++&A&e~R*%jAr(=`Oxh5CNRDxm4pM-!Kk!9?Jx< z0G*9OkO8^ZrV)40wI+e53Fn(Yk#9QRAK&VECEI8>aa}{^G=MXY<`1UEYEVN%EcI|t z&O$usdn=~KN%N1QL4RZ%-UJWv{qU@Lwd=KN+fv_0<0mX^z5l=Q?>Ywjo#S98DIyc| z4@Y9;6GIBbxwv|tr2%m_*)1gdSlS~saW!!bn&sd4Ros8etG*>UTWG#kVP}M*03of} z53WXUsOc+*hH+L-G7uR)_0Y)E)s7P3TsJia7_%}%6P?_GbqqbhQPp6AA2~un<1vb8 zxSAu3VXEp3H+%LOoCsrpJxo+PV6MKloP?q1qoH}C^N%T$Bs*qB7KA42bx@Ja{rBK% z3s|j`;!S{KU81=vrdgCz+yh4&Yl7| zvvSe_{aBIl530IlW{e4x!HCKYe>ch>m9}eGoUF>S4NRYi+~Z>yW50SSUPl3+x-=Mp zE_r`=u)JvB^59o)>8e;`m=Ij*H#=^4KFxU*Jn#=}3sF6tJ-f-~bDGYQU9_w@DZjT6 zoP(7XS%{N%m|>@1>*3nA*(hq8k1KcV03C{17=% z)lu=^F5J8@L}`;0<3xGuDeXQgd)Y#I_d6YEU8Ll()ukwC#e_4g&;R{R{(3EF!|O_)dZ;W2%0HL} zy9<9p%sg|wFmKeOri1AI1`;n-Qmh@GE!X3dFJNBNI?zU_scSyexNGM)Gq?e-qATe0 zcT14&UnOJCc$|NYIorCQ8>`S4pJ`l*A?0J6lai1!Z?l-PniR8SC0Bdnmc zYG}JFwf345c{F)hL>WFr&!0Qny%jw}0viYYF5sTt(CUv}QCKvP6M<>MIdM>mEUP3d z5-s6I-ynGdJa|!&<920nTNMbA%MTz0P$8j-V!2Qi^V#);o9<20>gtob1e~~7Q6^*9qiq<}#2}}Ynx7}db1mM1 zBwewC6hz+3usijS$VWqVcUVC!9d9v%t$#4kl@5MJLTZ6s^oUoif=RE_lL6wJul#v_+%yh@r}hbURVU527F&L z#;Dgsl5p~@_)}lcoOz!&r&aTp+vc5iXX~)zevB-}AC%1nuN0+cx^`S8h^+Og-ElH7 z-ERQymNb3AoSI}ZlvyQ&chN4CZdlnlSg5~|mzIkWB1{vgB2~VI=5uzgF zJNgnIfg`}tqQWNd0{0*^Sfk6tuAH))dHDiiWT5*UCCsrIR)J`rx$;qsHks@00blhW z24j+?wghIm3z1&sI$O|=*=-n}MM;~HA-yLrYl486- zVgA@Sxttb`6I#W@6<)oL8m*S6lk){XXLhqBr}{l|>N=9Bc8CN^feKd!B}8~udbqOF z(K@84c!(}+8qQLe$RlRf&kaZ`h)n?P9vm2TOJ83&UT5LyW`u`;tZ$&lpMd=gSUp0? zUds|w;Re(2CFk48zyeCORfT*+rT(Z+GgMa5Jvc3ErVi#!t=SxDtpQaN2zNI(VU%8? zsDFdNHyV%%mSyG}iX?(o@x6)Mc;eV`;q&Nzs;qxQPF($}c{dt1Jx^WRo)Ffif&TN} z6z7PPJk*^5-wWXA*dlYef`!+#d2&YbsXW?EBJS?qHMVRrJdP8h1Dy@QNk&R0KB4hx z{-ZJ`dA-5qHXwsflPUlLYE%jg*_rZ9F;c%@{)ywxbvRF`)&0vQY*mrk5SVSf!UG9D z&g$8+5~ezm7Gy+th9So*h&zuTDJt{!JwC!RwW@mKn6h42Sin z352{0{u)e@!aB*O^eO0AI9ELfC8p%BF*n65mKH0T{3-9CTPzf|USwbE{&)BXUbd%j z=VyL9SwW<5jB*YiDiO7zyws2cR-DXhwJ%J_wI0@Iq(9x>UuS_#v}ut6ckAwyKNb;> z>9!T+b=G4XnyD5Ca=2wyWkP|9n(z3Ky5 zHObz1fNMunb_s(yDRc;J4WW{gWNbsHR3L~1wlJz+m%$3Mi~7x^_9|CKeAAX~P}m)t_suO}Ad4_E^{o8lA|{kzlsG~!|Fk2beAEg+5$E6Anc zjpT;d5GB8HERg!PjAZ=DoMc>MPF(9G#ey^h9YMWRz&|Xfiu+Ol=-9?XmU0xFGDEUP zOBqBW~IB0I9XN1GOs!$)(f{W+bTr4|O`4!}6|BhWk0iU+aiva|L*L`cJVSu)RKKpYd^Yu1ZcsNy32(o)}9!`I^n( z&PvFH)p6UpPwl_YTBhc{v$#X4Jr5FopaO^w1$&SVZq#2-TX#*jA!In!E6)|DD@z|M zFR`n;qh7|47cMBxMTKM%;II0h-PZkVYMf}rZ}Gx$ZE;8Cr<)hZ5JR@>|#0&?Z*T5z&%8(Joe{@5;g585NAXhkLGI&*(2vHC6b{svdX6B$}jKBG-VxT5~|qHks}|53{0! zxoY0^BuXrY$a8f)-kFJ&RJvT!^#$u(oZIe{*F*!Pd_Zuii99?2iK7i7jO}&RV7Vp> zM_j(i6EjRWUkTl2B31=!$9^ z%g*$}8~Ml7Z=B+kC~e&vC#t@P^v8i=0$n0|`~~deYblGvl&->%X&9ZLpATB>UTBZL z-Tj|g^3}EH+2M3 z`*G85fyfLyo%t@4@US`bmVGDAy`U6uVDGzMg}%GaBOh*2>fne!7-y4Ar%C_aD!YI0 zm%pZ8rN7Z4elbq(kJCT$eeIG}`(phZFY^4E^QdU$Ex>|!Z4?aY}@5KAgQ9Zq`C89LU zwI2Fwm7!32DJUxws{)xVBa>{H9pL-@1WICvSRsne@;smwhloUP{K8?xe>Kq5ORl8X zeVbJ^O{x1p7Tvoo55^L;>~{z7defI#QBT#ZEVe<`Ue^uInb-{JDy-&(9AtkxcTLTQ zZY*!8q26qXSp21)9!lUILxr5CD-h&wN7>Ohz4vaM{&qB@f8FPQ&FNnc-o5JvKCZ^$ zp&g)$fqW0k5C6q&xWBj^zYL?%d03((q?nO8a4e|D30os#fun%KilrdwMDq`{&U ziO@Xef!N<+bgq=azI@6IT*8HZAS0s9QySVZd(E;{}PS zT$njq4&xy!Utq+Yq_M!wbrKnz{xp~Qh;Qkcx+)20MpEi~){qRQ?GNBsFl&IwTf)2`b=qkXfg^2Ub z5bp4bs3cz?rH+nxyyAv?|4QpL`Z&m+_~OTkURP{xNh3rpv*&<1i^ei21N$OJV;nP6 z$rnkt2B5?wZ~$6h5aZBTOGE*QGd6mDd0EU04$#ONHq^(?f<|MdG`0iJ;Dw2;Y;LE8 zKI8Fd=tjCIG;n^WW?=yOJQH~GmZMhAeT|LK(#rBuCw(Jz$Xa2MJPsn^0BHVK5Vl`> zd}T=oA(p_USD~cU*mzrok;*h<^^6_V;HZGrGzHnT>yD& zFTP8XpU-}L{`C2GCrbRzuHs|Z_;RF0ytYIkH8A)DDNV<=qF7;F7O1JKXjlN<0xs`z z8`QWMod}0j2?s+@xL!K!Kst6;0am%E#s|5?U&+W%*pz! ztWu!mgX|P?@v+jlZUn!X(Rw>ZY9Fm7feO5q)^lsaNJ8LTtcX@*Oc*$*WjpzkpgyM1 z+kckT4W0;Bs`L$_F%qp_lt6EP*B{V(?|=0L^o~YWGiy2;VVU67RrI`(ra!WciB-1a z4MK~46@!Mvi;g(cM@N3{A|iaA5ptm2+l`jNyYyu(9ICy~mX|d-N!-w)%pm@y3q198 z>R%QLXe0>s8gN6U0B$FH(Jo*{dYG?HEh3wZU#VnPddv&O(2&m)AzNwT;T`&T5)Y9N z2z!8SK;d+yPma=Qa@O^dF1!Yh$amPAxs1o+TL_90SPpOKba2%Nc&MWEj5G#B-eYlK z@!KvB(%2SIxQUQYYd?yC0TK$8PUvZd&dn^6WH!MukyoVot!0AZPZ~7ytez7g3LQ#;{e^Qk&vW-72R&!@Sx{$5PfhHGCd~}QJQD-Yw1ACXW}-G2P0YSU|V7! z47f4K4F?N(1tjuV_+)fur8<0xyh*hoZW;+5F(IllF_r{J-de=j4h1NOLl`7dwN-2# zqb>!2sb-QZqxFBbJSb2pU&Sdm3EpxOq*=KlBK8ohXy{!PESs^2?hTnoKa~a#%Yt|m zZvnbHa(SJCL$;6vrC6G>_@+*x*EAHfj8e5m>hofrLvoxZ#vEF~J7!>75FK-3mz`=g z1p^_GC3p7;OVv75yzKC_tk?-?dBON7(~b*xXqBbP?Q<5G7-xq><^&?M>j7d7@wp{2 z=A~<^o7<*=-h#A^;<$P;vA2l=6l9EP5N?$kO`cwra*@Tm!gZOVZG@x}!}_W&)Gy*P z6O+`MCfg=XUy~?2c$A+im<<@ROZ*LrKA5`WA*jLo`8KWURao&p4JzKl@Z$L|1}RyKQE;RSk+VVB!|SfMTW4T#~644&kWShv%m!C!|)v7&tI! zgM|aa311y@S;C-}Fzw7sViFAxFSiR>ku@~Wn|DAqL)=SVag26k@TSO;P7>2lbav?S zb6=>lP{mg?Z#Mn}8p1?OlSSi027ET8dBwfQOEzA;_8ms3*$$E;%B8eS)3CCRRwk@y zcsqqUopalhW=wn{a9IYPj7$nBjiVaxaCuaR-KGcPSueV^;qC?i$YL_Hl4b!tYh5zf z1bq+zZ=O=29vH-K$n{68#k=#-;z8I>Wg-Xt=e^U}SB@RezH0?4A)ar@vA(nl9V{*& zEinw|wZOob6bt}-A4N3D9&%t~F56Oe+0~n7heFcdKHG%v9KUIfH}0KxNivF>7+K{; zD60NF_j4WA1x2AKcA0u(#OTkYT8{iX6SpkWx0AmJk7iYH6pad2kV~zM?>L{T#a$fsghvy^Ch7snz;KD3m71xcVqjFKY@VqU z$Np>K=ZWLz2j=S*(@&NcbcFLVN;@-5Y=#Y{D95Gr<}@>yHBL^Qq%T`GtDQ@D_I*l{qcb zh=$!b7=kMv1T{ob<&q&P$|^8!n6TvKLNTfg_&mXWdtEH6rdnTbU7S7<9=g-I8i@si zcwd8Welmn@M0TQRz03_9p}Lg74j$cTg_@b81n`~$KEaXUOMtnvvhUU=+Yq(T?aDPa zS;QiexvCTw&e^ZBV3I5emnJ%R0aOf(uTWdBl^=Fou&-S#vc$+9A(P<<$yY}We|IF- z9~XITcHiBt5vJCm8yIrV=yY;|1p1-4Vrgg4WF1GM4PIu+x)wMHlIK)(`| zzO1U(sf6n9WalujHOF)!K-H+~A^zVt73BLL^D7c0>g_3y{G!%B`yyW4Lxyvg&tKe> zbiE%5*wloSbzcyd1%ZD2-=k+4z$#vnHgptMIE?xM6YiQ))j4)6ei35JJ0E%1z!(`b zVm|sl2G7@DhA7gRj^(~G*dBS{u)v zC+SEm#}N@LXHEjbXu!S-m*3H8c`{;4&^7Y_m!=Z{Nc1d#a+%Pg&mt?I&=`^OhFbet zphC=j6;=EOFI}Kg%F*1Qh>zmk*;jwxO2mS$|&WE}Ebo=s!*F zA4u#G#)Pi_#nc!c(Z^yQcmUHlt6ycQNg9-nE-sTD3JgcsAwl7iAOsWLBt*F*x!|mP z2_a0JlyR=zZlQynmJ=5$o$fX~>7o(2$P#9AH`R`Du7QcGs)@iPE`saU5+!!TEw)|J z%{0#!42%KYo6~WY3&D_7Bm*&H^+_kRpzf%tmpNeV^a}vYl3$KM@8G8*zR3mcozl;< ztE=r1a+K&5dB{Hv58F~aaM5p{y)>^h?#|HN>WZ+`Jwms`Ukkn3gF^j%a|R#s?}!Hu zMN{1d@EQ!eCTIz|PpehYX`J=Y@ccSpmedqHX4pg8RV=H*SZzZ{>wcxu>|XcX1);^j z9pJ5a2hGZ7b&Hwq*y+OJpv561Q7zXCePhho8sAn`gjnw@yWV<)SQL6rM1!T+9Y7v&de<*FVlEVQ4J(39t%)! z%}&l2f8-2y#R|mY%!k}8jy3>po2#Bwn;?^#1LHJwN&(XnNPAqs3;1vb$f^RB=2{V{ zOIcH&e$@<92V0MqbFGq<7}}gUEiDv~^^>NG()(j$5hy%3FCsLG!C+Zk6>|WhG$^&0 zSs^BkO7im)S76wzm{K;SS2HZ+`W3xOM^X)Zd};jB*ykFC3TrN7d_^i8mP0=NGpm2> zE=s~8z3zaicgL~R0u+u@Xf8!pU*2ji`b-ZAzF`NDePIw+{`C+%9=zv?)yPd>NZh!y zg6QA;=R2hKN|wxy896ki$s&{g0HJ@+lc-ne>2JO;ywcf~8d|*x3Dm+`V-JJOa z)2XF>dL$+*bnvu%#Z`9a`Js}reK{rmOXlg4)8~Io8~*uVQRXjqUSLEftJ1qG6W;In zBy98Fq|J9ON;-+#kCSwCmbZoXdB@d;s?MPfCs zbKYF3`t4dz`UmlE8f&XhnKp2+HK&WoBXo@*CK8Ewi0ujNrk*prgl&l#XqQLm6aM*K zm}4joMGjBlu+3}DI&*|7$omi)R?IMjXq6|!mXXYGFqgSSICLtfh&JqnoaxzAXNsPr zWT}?se8hH>WcpZ7rB-0wweQvWQeyet3DR#<`nKbEN}PR112*dXa>+^FG(W@*slznF z+LKr;zH_(U=mZhouvfKM3!^5mBe&`TrhaqwT{>74wU)@3Z|BH%zN)kJ^-x2Q5~et* zZmaOu>i*$rq6N{!EOqafGXU4oHO2pZ%ynaiRzC)ymQhR_-38ueD)rwpv5)%08`Pf} z2p3d@B2}3~wjtTvE&%2x??B)FjaTMAtVg%ic;pf?C2EU@ZCuv{Rw>}ScRVxG#3fCUKS zgjqaI`%RJG9K5a|G%j-G(Y)oNWUxj}H{}8jWm>WXucc=gF#qe3@EQojXJXBebEwDU zkt-3*FbE(J(kXLS9}$N%J!*8nj`+&XL6oVZLz3FAU6~R7-by*$Fg#c#l#JGx{7RNq zrNM@~XFrz31!!?+j)$_hG*lv9o@AC|L&X!R!GW5rVQ`#v?(zQRdMvJhX~n|?&l-30 zo7TeBj182#n|hPGp+bbasU#GMwo-3+mtV_vlBuJ0!!&csVJT3;JyT=NKQ7*1-r^_p_x8PU+T7o%ipSUN*}(e+18yOo z?6?&9GJmx1lm6Eq?|FTf@CE^G%?92KlYM2b>4=SjP3Z z=Y?-HGXHi%tb-lQFj8=WzcUZ$X=p8O9zQl#UIs`5btOuNRO~CmsPOd19O$9%E$1hf zpjam=#@4Bu_~f~;r?8|SO!$!m4dqdb{W(~;Tyaxo;6}_u^_4;PI!i{ijBqqGO>}zNelo$T3q@akoEZGE=ZJLMar&&f8fbn7=cXQg%a!I)Cz*uFd~#$}T<_dT zKfAZz6aV37vA^4IvNmJ01El2Dy4`Be==T1Ho!b6}e`;uzAvs*a_z=(M!NCKY!S^aP z?6hX;XZH~)^VtIlOyvBHF|CRTzu0#bnAIVZPThJYx}JQLX{aGQbJ2K1XB>Cn?U@~O zjG5=8SNH}i6gQ9@1SY&f>%weM{$TN;%(yrBq<3X6I#o#B{}`ow3ax$VTDad+pRe|n z78HJi<8E!SorS_;;(AtpVkwS_pkd!?)?j1ydugBrXQy4~Ue&sQ_~t|^0t*B)^QaA~ zJRi?MW5?=nUbtP<&?Ph0-Gn)8-ei+Cue-Y}Ao;w(o*0WZG1lX@_hZ9}{^xcy4R%yd zoAU4%tRx-*<@e%&_I! zYAP{ugtf0|J@j#<&^XmmB+0N8Vpe`8^fM-+g(otoY%2;-NKtx16_O zeYjjjzX{K9J^xuvtGl}ZuZykMTc8(+$f9)_e7%IX)4+V}gAfCuAkk151HpFEv!wnx zcLFnK55ONo<^{+>ZbywKkf*k!*^GQ?5)8}o-5dSc!l#gZVM9**kVn?_Xfm9zi(GHG zh@3bqRDKAc3q?6Cnqv5Y7qr4kYH+ttEM0|6w<-b;bWHQ z2BY$_3&!y|sFK3dy22Cj+>0HA{6x~pJG0`Lqi|*!Y{`WIUTzx8bZ~`o&{?e(GOh^C z_d#==Daz%d;v6Tokq1>FT8Kp;GfivcAxou!;f}?$zr?~$t>;fV;av8d&g7q^oY?*& zjwq|Q=~wC9FL%#--y!D)2k$HMEK`2#Dwh8Ycf=p)8+7%@`$6MR{%i2Z`+_JOv~JKG zs0Y<y1pTt|GGN3emx36NtghZKCJ*TmkAp|^Zq)coyRtbd#NJK9N ztRfw-j_5pzC@wX}nJAsb$_K)8{_>@EW`m~oIK1uc))IlcxB_hE0I64Oq%`FAVVpoW zH6oZMj9kELqrh?kbZKamgRnx0;(&lKZ%v1O9RiVyeSNw5+^1cVo2DTYyDs`&;IzbS zQehQ_Qh-Z6lalUHE#KrCX{lj;VRZ&C-Qlqj&jVzIMr%n`xyQE5*3`hCTl0tytuayvs9no-}hWPJ@94exIBZ# zv#*?!iWE#F42X#w>hHXh)G#Q6yu@tB(Bx3UebBUX!D*I-U?`A~2=JjI6QmU$246a= z=fDGi282Qd;doOt*GMYA$@4Nn^j4uUAqoWEq=OH0=u0BJ&rg5&Q?ILHwo;lp{)D-p+HtQjsgh4Q4!E-bdIKc_dsZ0o_F*sK^PU-2t0 zK58oZm?;y1cS&5eIs-S#Al4F_ZFM@6>8rdY0tpnqK;v~j(T|MOh}w*k-gHt7#ooHwtHu#8rAKM5Z2L3{<{;SE##~NW-W(WXuz?jY$rnV9ZHup9OcCq&?nG}2T zb~PbyClKoB^7NS2{<|NmU8G%+{e&)`f;SBIAE{42Ow{rL zF)=<*cX6KfNrbw7|#eZ_Kw4g46d1G9bHTF?sGo3mIRcwby zTnJFJCTfiWrYnuFb_OL*qi_V<;m2$;Q{>sPA2D}GKbZ{s@cHS0?b%}{Dd;7pMQB#i z(^jzkM4@ybi#VG!nzqTXL#raP;Mi22D5 zB}c!0=q=%?nD5^fLh^M@}3!r>JE@`a)O-e;I!l7qh3#rf^rC_xpSFZNw4 z;fB*muo);texCZPhBag6cUl~$8}F=irPOASsGo9?@7u2*t7WwyHOp<4{qUY$A}#-U z#yI)|My^GX-3ub)y!Ozo4;ArS5N%IScUZ!E_Rxk>%YX4o+@geF;dlPWWW8ywFEEn9 z(RX=OBi*L=Aqpn$d31hVt+M85$6>8w@DuN4hJE`lT_{@ZSbJp9+DM3gY&cVyI6S06 z&+R6CWG1{vnK;-q-Gs=|X}~-2sX=DgUJ$#epja~P4bq*4VNyQy&Dv}%mV|G3D}>9u z@&J*BF~EB-PNf405RM{*^S?_tZ+uX<7m@_}wE3ps5`{q);vVa?TtSB#`*ul`F*y9r zM|5~eXFa!I<22PKCfv)@OKm3P4I=AJ?M2ts)YW6h9HzDl)2PKrMpZAke8l6>%EdQX zy=eT!=BPy}s8GNkX9qEwX<9=hH!RVj3}VF-0}|@Q{UF#7dR}B#Q~as`vh`zGoM_00 z$m#6y`O_EAFJ8uG&T+aProY)}M(Z!rcY$%$oLF+}n5DIs3WzPdq_+j6<--iDaqGL- z8m{f1)~Kve%U014vKq^V5QS;MO z1*p#g2vH79*31rZ$XqhmsVr1_4!7NJ5&q4)T`ZSA=cQ@JDXK~G&%hgZ)f|03iRI&( zdqBM@hFmK(ShSsc_k_*C$29IDOmV_TI1T|bcX=y;HWYT~-Z*w|5RX?&$2QT2lDovA z6{fs71OaDvC^T@zx|BvjM_FCFb^2u|6CCep!*JPmS`*8ilzX#qQmoCA*1hbh~=6~57TBkir^LUwaN5Z;xaIhli&Rz1% zWaUADd{MD?h#~H-=}rWU-NvB^acDe(%2%sgt6#ZP3gm(28N(L-ZL=um;Jxq;M!99( za}!sNohtg5q@BpDrU9Bz%{U?g(kZGQ`?xh~K|)a^AM*f*RqvY4J&3Ad!}o2ZNl?eg z%R!<-EJVhu$C9Mv-eL)Zhz$-lu^@;FsS_ChWtH&|50*HT6V%qZMp=z0JS^a-K156a z9YfX{7ea&`p0fbo*d;v@_%Yu$k=;Kznl(CmPAaf71~B&^X$UE%>e1V>D|I1=ZzioDXPsutoc zOtjQSbQ}=ey%FQE!ms+2^fJ~WZ#R)}Q`J66PQhGnbCkw0wYR>`8ZG65yD0-+yR-j> z=Z)j-qmXLJ>e~;xu1v&2_>LrEKggrPVkdsFkJ5SrTKj7h+*|o@J}qBI8^zW8%Mk z=H5SR^v8Ezi!=GxVjC1(b5n2#U0h0>zbnFbTmoh$BAu&D% z<*+U%{Yd}!|JaB0zn_t&J;npb=KoAM+^fw>qa@ynU2(f>PTaMxYdpfAs+oP>*ar~ZAuL^gA)aFI_*!%yD@HxbSKi*fpIL99Jp9@1|UZ#2I)3BH3> zx&J%fZ?!wSPlCDLlWQvcM5fqzspnI=^}C;f9~31Q^^|iu@u7^YQikPBLdTxy&6m-g z!nM|Y;TEou)*>l)lz60Tx@kom?u%|5bKaVZxfOE(&_4h?>@F<$Cx89G&r+xVjVj(JcHNG-P%KhLV@^HD;lR3XmC{WWH&Bxh4fc zv$-=AT?x9Dis;DAx3~xHQDMw&D-dQU;F9#JID;)DGj||1jFhe3!V)Mgz&C;hn;7A9q2M#U=bc#8>a&_GK@OTb)6btMPyAw$? z@%I&KNKLN|%j7`#C(r_GR>NLg_DCj4Shcm;pzx#!DT%KxkDuv^9Hw8Vw?Ds4!{c8b z>MzIm<@Vj%T+3XlCk$xd0L>bw44uWjbWK>K|w zzLVX$pfK&wfk`q{8{QGuoSh<-(M?2G3H^=@hQaxeL+zqhlO#AZfX_gzvBF$&-6>8( zaWGS1od=I#^|X}&k6KNjlfvT;Nsf=voDtD}aqBrD{-foJ0Ig5e=ZiG|)E$+=WR< zaUu9>4uZt3SWg_!*(ah*LjI$uFCIR_fcmH>vvvP%Ru)d)~Y zlPI%cV+C&1CdzU!(3RqK9-~XIv|)PUrrGewFLf)SPhJFpdv;v6oR|#9V*-c6NIh zTJO6WNWdOt<~<6>{hl}P547=#l@$K}#nn$1S0gh2rzO{rIQ|JC_Wf zegs(ZfDV3^itn5Y=Vo_&`s1eL>bQct6CPSS`uw$m0k~KM?Rsb%-Y7SE{^I<}iGWq- z8nK@vIgBytud+Ez!Sju;e#aa^?`?zuTxSb4qyWT=Xz}_wPW9&uNv%&D=XHkZM$!~l zB9PXS!8UJ)44V+v^y|+un4~AigY*UDMyX84MJvBflAk#`T6C4`&>-s*8b@l87)6)9 z-)%X~VazHG{NmmiBe}BaKJIBu19Z>+f*%#>z~Vj-n+HYcqWl;d*w~32ix)L5-IR zRsz#i&nt3^)c?8MGV|H)iTqA{ay_^BAxA`@W-ZBTFuEKLnI=6{KDj&AX$+3OFOG)$xgsyb?)%0ZFRl7QS0?n$8HTTCi)k8{ zFwh8p>ctfeu#RBN@lE+{#d`}TC?+FnB*KFXa*$A#yt(FH|B|=9t-{jX+1RP|4yDGA zOoTn*W0VM+=fMf~1NLpf;`ACizVc?g6R*1S?s~!8>KH&UH`QNQawv*BktPsG1WrQm z6GqO7G7_h}lc?MWN%X-Kc?i>V5C#&NSgSVWU09f?&qSJFp}<-xTAzAmkXGO@mN&*5 z#!GGhw+sfL_0j+%KZNy&?N_o0_-KjPwgCElPa^flpakq5yP(fQanR5#Ue*<~EM*Ko zYys$ZD_zk4r}HCZn+B1>h_L%4rAAUk&SrCBM?HOgfY<%Mx4-TQy4=H7cELwy^MIQW zk?&ZObu}X1aqhrm*l~Kp;S*AYfgO0ZfMm0h-w zEm34;+c~PJ(uMIMVTwz8YhB*WmDYJEP?kbVYFQxUQUT3F{uF^q*c&ihAVZz>W6!NR z{9{U_=IT|7^wLNT#$890G>}MWVKlptSE=44Nygf`%i17`q2_CwBazrrAGOB*d$oCA z*Lh%R{v(hA_vYeA@h3#`(1TuT8dqynC-R{#|#NomhDz zy>$x#B44F<@vkla%jeT}OGojF?e$;v4aXc(KV6SwcEhT^hHTIcFG0>4nI{DQUA2fU z5LUUNOpmffwkFN@DD|MW>ZVP6oCf`BqzB^F+6Cw$qBa-dA>qis2d(iQ{ILCi{rPD6 zivDLGtr=yVI#N5>%q|)3(p^Y9z4LNYLN?X#Q)#Gw(L838hniPm?a{^xy^3^r^BSpN zUt19ZE6Ib%ZU9}--9FNNR~i~Q+Z4O%)*1+33#8Sm;6NM!;&+w0=t`vRmm&lxEmRlG zi@h~Vn)dE;rp|5IW^X-J!59PP{P6j`ar)dWP|shVDmsyxp#&DK>0Tw?WBMMqpGA3d zV7t`#1a6PBVyQM)lqJ9yr3*PQDt0$qs$9Y?rZ#BEmz&zFhAQ=$3s3Ra)9h1E(arZJK`!G_S&h<2rT0xCKkoUdZ)s3g>9o-_$aG4NL!7z3=6TUZRhj!fCc6RS zu*DX?B4WJ9PDoYgi6J(-9g^mKLi|g9*<<-ma z1YST;YS_lU+FtBZe3nk-mV;g1PSPJw2kvDvuwl;K@`hg2E=&OTv1k%-_Df?T_;FSq zXDXy0yJ@48S}3Fs4OAA0vpEX2DYW=D>6AnEti22j2_nc8rH@{X$rbjLmYTZC;Q*8b zq6M)uwuxBW2}gcdij@Zg^b|;hcWQN1sink%H7?oQP~i@+>(GKU8ejN}YsiD6O5Bl~ z$N+E_{qgr>Z{7~f7ZR7N$9lxjH({jQzCfKz&eD#wnj~8?;1JhOfS22I7J;i;qb{(?!FHsRL;VT| zQGgXVbNI?38mPTIO|Q&DY|bR8O~=Q!&Lx2+LK_ot!5L=zEg^D#M2}LDaS%(i%WRe} zojCc{{cHO^<7{6y9te`enEY*jvvEUwOMCP7rwJp8w*F0ltjT$PUcF$s2bA&*6a3&w zhf;L&_qrXt9dS6~NF?S1{XE5t-!u33w0=Nv8XRS_`H?~J?-S1V&c7$ipIe4!=ZjBi zm1pbruj8xyog_**ulsj*ATRtMvC_Zm0!IKXudXw>(Cq5^6C^kelC$cNa5bwytM(ZI zPUf;Ujojavc@`u>pw2IkX~zKAune&YUn|kRtE%|L|`d!5lOsY zIK!V!pbb%LyGYI~RP^*?@xlVg36UFKk;3n;j4QsV4Q=7N*!`b<6jPy zAc;g&RO01eafD;BIU4iAFKuq>_1r@iO$i>lQ z3SMGq=tV>b*O_38LMv?qTr9xqZ#MP1E?8R<%5APyh)JSTJV{?|)?Co8$CqX0rb*74 zODff4KGgL95)G@Z#r%4oiK4KNB$U@&3UJnOBbryl!jXBG5oJBaFVnFBXWUedGblv7 zPeNsi)`E~G5Ni;#On8wv;h5c~jLF)cQ2%5X0eD|P%U-bYoprjq$KPRY*N<%|2=-T7 z#gDqIE+xGG@%`{IdhUFk9;c6%*)`D}BQIorjdrP?zOyZ4`xoP4+%}6Gk!rJP-ha5G zvsfUY;nb51ox`3bI24SxcPU+)pSBb6=l`npe?aRmDzdCA=kbGn1E2J{ivMTLwwzzr zRSCVzaMY3nB~q))_L%NIX#}+_LtJXP!%frkMiAhFu!;_ph11e>kYcnLGtVPDax_H8O{XcUiE~B?(apm#1&oNtZ&qyt2~pFyvVQ*HyOAtbe*43zT?rFzK32#bPO} zUWvd2rqgDb=j(2{(-QC_>)chTnDM$unmz*^yf(NK-USC4P*$Z?7Dg`ne3G7-!BH#L zs;ChPXpIyJeqOb%Zo99xiKMU!n48>NwB0h%O17O1*7k_5?gN-a`+WDik>2|q_}&rU zAqel3?>_jgKT=3v;I~Cxd~meD~<5PKWFm#z<1Ahc09qdW@ zcl^OW$Eji6v4esym;^5t?pNkduE|s$bBlvpy&p)HgG+FGa6grfo-T-gKDd7m4Te;} zf$n{p#7@hdbsSi`Jz9n?%Pk3l=Me=XpM-1To53LP!Q|(xXh|pxM=2}pQLA(3T~Ls+ z8y2OwJat*sE0P_A`r`ueih)sTN#TV4!&Vr2-Nz2|4jY_o&w1hEzgAM1joT24g z(mM$U#JkG)AGNymZ!$>?6T5Fl6%@VFgjvln)$BTTnxnlHs=pt{5tc^?8 zINc=S5R9IU0RI6h4~=B7YIs+Cg}VNYlbU)z6wRFOXP9L9nh*~dQ(9agK!HsJTLqQO zejqA6=2|Pj`Xf>3@#ml4yN456SBuS@E}_v1uW+0L+xbS|>+ZK>{APH0dP(D<2)+rd z!dANoY8WSU{6Eco>vG#xw&s641zM?&Nrs{&CF#t_j&o#NPF%;gwv_aAWl{n}LK0dO z$tFNcOyaJ7jj5V>x$`8m*S9WvZvd3!IXzV;b?USQ0vj9qvi7=s>svgy3`n8-!M8ja z3C+oBR=QnyvZ$AjkDtJ?N#p0NvvtDm^Qx9i#Oa!2EO7_ji0IemzRZV#Mcn*7oG(qo zZ+sjP#8fy2$#ABGT{o3(-er$c|2c=#*(_J2x&)}wz$GqdJ1KZ$mD@&13|Fj3Q(5v3 z^BqwZcF!F|Rc~h~i)ORp^cB&OX6b>mo~G&E&h9slP>mbhMMO{Ltt_`qCs8VE@-u}B zawrny-hYL}3tA1d82aeal(6b^AvF|&H8;AiiuynP`M-!CVNH7(+1{=#8W(6NXI#VB z$u2i>zHAjBc(fiCG=qR=lGd11vvRR0YAX`+AOHN{r>kFoEvo;Gcb07UT~vZrt%K+^70H zuo>hL;!j_l)a*5>op80r&(r9@S zrN;!*6W$}=^a2%grz$5YuitBCqz*>4)rC(yv%McwR$!-d@v|5v&mAte;TiZ}IWSvjE6yZ#K zEV{$Ih?Jz9kov9;D!x30{vlACv~x-%mQq&Xf(zG<)`#SRBSDL-$)k}|B{OZ8G21km zPQjT@wl>yO)~?e7KcY9hJ3}R6f8W%Rz9#+4tKS^nIo;ZU7P>o=S2L!Gh%#qzQ6s5l z+m`%tPAPvwaokM+sK+KyjBAqoc~$-j>HUWksbZ4YN*eDa?^;?_1$eIW^tMSO&$uA+ zib+J%>9%?gI3c*+C_?I_k5fW6R|;bl)whsV5&lb!XmeMRAjRKY@LGXcbRcs>O_|BI9yUmUZa6wuaeP9aNYg?OdRH zbQ~y&R#cNKT4$v5g0Y))G^OaHiEBvj>JbcK(q~+w*M(;zQrhT*wdD9&GiJZz#GYAo z9TzcMb3^PSBQH-rtx?oFK?GZ!#rR_SBFzNiLbNj^)LAux0PM6Zd@nF0Nn>TpXk?O^ z{)t0&Q#s#h zvqo>~?@6Pd(vsVcx7i0gC;{0gT~7b-Z7SP^X+Nz8FAiQEZTw2xVLP^yUeh9IvF`Rl z6nKd1&4$@?044}@?0%B+9ZYx7PdHXm61%WF6;R4moi!bc+8nr%N2iulV=DM+#xaTO zq86Y8|9&bIFU$)p=_O}Kb4$siNT&Ij69D#2475ckBkOZIX-#y&OEf_l)|WZ6ceYvO;O_D}I);-zW{7NeyonyVZVcIG8BQ ztJC?_MV;O0{z_x_S3>SD=IZWne_5Q7^#n5&eYY*zB~Gs-sw&VcnHp!VUSPvgI~D7? zcmP7N@pJ{Su)7xrE*UsK%(r z6JX)6Lo9Hdcp{3LEnNlxA%(YL<^Ctnt|1O9U;H?~R0#JoXa($%c#&7c9*{gOrlo5E zF?b5Xi4ipTkRu=MZ*ymb7#RhtVw71`(ij z4Msc>2*0o_rInN4F;bsKi4tqZ$WA6Usj*)R-sJ$BtbufwLZgX)-Gf^ulYksCR^xO& zVHyc{K9S_gM&ogooRtK%Lhiz~2+;ymUr;fxF}-wSl4&it_N>l=*TZ_EDcv#OL`Vrnr5*aqXu`1}X{N>`<*4lrs!z zaMpQF%}nPat^f%mUR-BXH}^#>@ikEmE+J||;nBRFm36a-3FTxMMv2VH{=Q8PMLzB7 zKcdTaiocjI$9&NK6dZ!YT19fRMr|7U9UYyo3r@ISN;;(i?Ltg^zN+U}u9Y#y14rvR z5pIiVOW!L6rVcc@2aBLK1m_*VjJp$@*rlMtE# zAm+621N~jfl!i{&U4eGMdz@6$yeRSob0A;OLhWEuSkJ{dV(`oaPSXcmEApK2NAN#Q z3ZeM1^Z}upwUs8FUM#7M{gg~Fl!L%mQcC=4!DE~w^BltqB#>2)dJyarwXuH`C^kN2 zd{H=ccgb{yZoVgc2r@OpEW-C-AB~-2s*s_onMEStq}`pJKf04|S~6sWs#sJJITQKQ zBq3t}*yBJDJnjOo-nj0QQCY(_?Ga{^Xv5e2kaxGqqc6#b)b9R1cG~)2HbKF=!(c}U zh>u?sG6Moj_I2&E!*Fr`|T1Rw*Pncgium){9i4T;Wwj^tD1LxdeQ5q4$G zcXX?iZ+}pQ=NNY18P&Y5)y%EQ*DyB~qZI$8OlDKLCpV^374@*Yb$YnpAHz>ozGd37 zQbe_OYnN1P)>x}Cp?di|6;|luaJFFrUrI(#qQP>Oz?@#Yps z4RXBP_Y)(=*=mUn8MQ#vD+)G~ATK6SHLzzS15#wwkpBu7ag8s1Y;voGtiD@>oT;}O z`&Ftd13rny7uw2t(skau7=OO|%q`TPtG1+CZ&m(Uu#X;J?Cit*ynuM* z6akb-sK&*NM$Kmf%sl$sb%-i={E8g5RC*MxtS3?+-669K2v zk_Y2DO5Y-2I8&1XnEfEV$?EyiR_atbYAGTy45~p$dl}d7$k@Cz&Xk<+>0v zAzU*FEp$5PkbcVU3nYaI_Y`f2$?EEAoo+!AZ9@`mMO;0CwHPOhX+AE*yJ}qv<1j|x~#$uX8fd( zaPT7;*Sr*dILyh2^2fIFEpiDvbuY>IHJRzETJ=Q9T1@}Ci@F-hj||Qu$=R^lJyP1i zz5E&Rk`Tp-Zd6PzRayN4- z5cw{t`oasd!nIvu1ndc6A=bzV*2oDp)PKU4s8<|5csVCwPf?r{p@C{Eg4kpkVQrAU3=LNQ&NV#2mRefEELPVLXp-#e-D+Y*; z)D_UXIAgHLt2O815%CNH1wq%0L6NLM#fNath%nua;?#ua-UHE8t=c8K8=6H}Y9x{* z@aGQ`IM;<`>NH<&KRM{dU0j(p#lJsokU;*WFha~rXHz5*PDXKr>`=)|$!j^pnVYe)u;#QaA%9P3m)S1hDi-hFhGxehkz(8%z zT6GhV^G*^_{}Pfi{=x4z80bzftxQFXitEZ4Slz14$K{BTyF*UHY7&n=FAGs&nofJA zY*b+Kh4^43`eVVjt{8Ba`&5W^-6tPRCXJ9a?NnmKwVF=8A5G#=9!S@19>Y$*Y5H4= z?|KwOYbnQNheQ5V2Qfync8Gwbuq0`lXC@Hym-Np}ob(cIz z`oHs=<)1t7)k#MPP8T6LBMrHRlXS6Xf`ld}^#dK$zpDqoiFn%0fSK>%zD8sdN-V8mWTCZO%%J+m~bL&5W^ab z>(6tWTG52b=L`n4SS^v0&Z_)-54R-7=VHNkDjNjtXt#cMoo4n7c6Q^q%iL;kr{|vg z{iuM;v1L%vXGIpGR1FO*4zgHiC54bfoXTHvlwY#0X2@fu^{cjhX z@ilcu*+%egLFe$SLtWFmiZwlGkye7 z6|Q*6_wC_xKl^$ZC|R?)_*f+&7!?i3d55LMlb`zc)8dx;$n=WOzT_sq(zH-iE-Om3 zScZFs=G|Su)}*P>LEjdSC|;s^pl&eE<{am~$hCZ+c@a4hY*n1*fQfFSF^Q^3-EF9- zeu$^@^K$GLjr+E#y85w5(%xBzVcM0}Biq(#ztbYogV7Hrty4vh$hHy!Bl02B;%AVy zr?xm|fli1*rO$p-QHJ8QaI%+vGu?oD3A^Rl^tKEATG_zAGp^Hn9B=M%?Qkz$Jy>;agsjG z;W}gLD1T)G8M}>+*G+v;yRW`bdJ~MzHt`3LTWng*3E>hZFl3Uq^b;Z0HH$n?&!_X# ze2SuwNCaVW>Uqr>Gt+gF!wPWo=KdOxyk`)*oxJ9%SDj*%z9EPepL>u{*o|VZCRZe6 znCetjhNg_0FN3(Glf^j41X+OBY0??gw`X&Lz_Qe!$nI;>c&LQ<@`^{37vH;OiGs(F z@_eZxVc^x8h>PBafR+LuOr+o=Glg+!;`fd!`O@*w;9%fA<&>(?D~rN{QVAe~6I9c&BEL;H zM~?LT*;zSZ5ulNJB)ZD4@cxM&yylW%iv>C4-A+#sMDTzJ84IrJu17h&Z5R;Tw$x}^ zlLqst0+jvrM?TJ8#yz!x6k2^ zcl|$glKk6Ohd&*@$`T@>a2?r3eH!A*(^6I$-yrT3_K!+1i7JG+(}3$)@b@X#dg-=t zwjZ29yuecqdfFCuyVNgoS@vQXaoH6dl|5KK(qT6=2U2rD(9Ype#{`y63`0LM?|&^y zwweqNqs%0@bSlrKqG+Z(oD$LqsEMt%6xgz^vp$;1pIrk0C%oPsd?>-ftI9s|k;06ewNnw1{nrCt4#-TF=l&5Gl<34i=m@aV}^7VJ@`oWP-mEn><@gBexEb3_tA=!5~{BN_Hg$! zo`Rp2rG-=>g6gsI?h~wif(=yrE!lxkdJOGwTHS*>vG{vH1t%hu#1yQq>x=b%`mz#@ zAgAEV94)eN5&xnR-hP)pFQuw5ZH5(UGsYDCQBI+I;O$ZuxHqyBHnK(8H0OuY)6Tzx zra?1lD@TunF;N0g$y;bW3^1FOV@0R&(EX3?r8}uUlty|vW)1>|U(q26%?<*C(8EMo z74?`;yC5BeWt3v-p)KW;;yboRatSmH1=C8L9JLBoggu)JK_3Wg#NF=>pM(!s(YjEPb8drTv{|80 zReXpYq~G~d&DpimRcBeuDaDeid9G%&*imN4hSt%BLny&^>)=@TI=JY+UJ`jcD;j)= z{|_kZ$`E*E#CvU5e#on%)u}rtTfcNL?%ku>-3x>8D#>}P;O1J1^)$?ikf5i)qqk^G zwZkS2Ga%bZ>zfF$Ur=Ohm~NeJ-Es%;;m7Fm>6Q;f$`+)Q z@ls~Id$z@Jp(V`gt^{Iiv6ApiMNAXP&*}Rg-$<(HFJzTdBs@vZ=JOMpuF-hBzx&nx zErTVI@kw&z*YZ9C_M%3If^y-EHUiaF^XZ3>x;}@Z6V^oWkxrP7I0-dZq^ah6qD6Or zo|1LeE&04u+@OK(WE#f@+FuMlgkN1>AOB%{JN^Fc+wWf;0;~7z_0G=T*Xi@O>6^F5 z>GMOnoNjMFVTJR(oWjS@^;e$-als(RLChQFnz(SPHn=ZIiA4bhFq)^?<3pOT zCm1r&K0^DvQbOeioSOjFCyj*6&&~=iu!JE6d{E5>HjfB+ls((N$>0b4+v;ke&k_p@ z_f6>97?r|#b{qr@t*vGl-9qRX>g*p6M+J>?hEd^zkHV8lkDZ3w&T!toblT?D|9riD zwUwq1;_>gN>7(?D_7~FGU0+&H{``8IxJ-XZA5hn~(e-}UU8}_}uKk`6QS|!Y1um8> zj@)1V@pPN&z!?z2L+^OpTu&KsS?9|di4L^JdZHO9sD{>?>2->yOqeppLP42Hbay+5 z_Oc}<)Vmd$NjfY`L3)Gk6Nso4W&R~X(z8arCUmTia9>8Bn?1~UY%-(GA(m?dpy&C566tNmu_ z;}$+)*X+Dmc!J!a!i}scH=;iTr9y_OKY(2yfYdtmen&|81rchdN5r@#-WmM%OYgIH z?icN8UnmmbuB*x795L=Cdwp>H?1#hm1Gj34WROWv;F-~wo91gtX+WtaYQ18P@)25V z)_j!4dtB&qQdHw*i74+0YtbjZmI0wiJb?9)LJ%-GS_w56GC9!Lq?qN(%qJlit%I!1 zDG44%(6c{k+Cge*2f_=?3Ix&&iV64ut&)1sXrfyM3=Jw&*cHRZSa48gIha8>qAjkOZrI1)5sthadk^ex*Id`c5c!B_H>Ab zSX?dYb=u3ewn!kAGp!Pm8%;eHvHF>O1n-Ox9upIM`hi%@?3qY{mr4g))ns&!y{w*> zQk3@T`WvUUZ3R3zJ-52jKc?UG({G8kRd-h-=_0B&6#vwo}_vr~yRXtR-pp%{s&akgTu+NrU(d}KL(*)Q(IwCL=9Ort~e0c8VGv z=M-W0pnc&9Ga?))w36DSk~|4yxKK$@%Hf@x+$_@kw3_bkAJxledEGN%_g%V$TG3nS zKK+YKx#sxyquOo_F`<5-5Se9w<=TDbRT@+o2)z58`f*WCCPh$GmXiZAW|BCe8l5!c znFeX|P!0;;M8kuaYcUX?)K0R#Ip1jrlf6|wCaAO8i@&=cQWeqR0O#4D(eL!}<8+I| zid6An!s(M+blIAFO*npJW?sYLp1q?Jx;NZ?-R&w}&iuO%97J#QI^{xV4F4q@p zuiu!yW_3kDBqGV8X-@!KK%k1Fp^q{|rP6FrLMbT-NhncNQ<9`nDuqE1N7m9MQB(ml zJOCkBfX|}DX?j2>x?^2yWpgHg01%`^hTB{eqI!FLxNmiiRsZSID|=pR>~jVK*UmBD zOd=3jQ%fW+T|`1t6hhcpC4UM02{AzrLB$deiqmfnI0uA-LkP@zGt#Fx=F^X}JVTw7 zRf)xXx_0Kt;(}`aM0-AKo~v2YFhNTROe-2MfBINdG>bR5wcsl_$JLwjg!NWs2Ir)d z)&ZY2E47qLM8psDGb`OT`3qaqTCQ)1rCLBS9jk zhV=}odMpeyQhHV2!LY@{i?pxNE0e?bLv={R@W}Em$=8VafI6iqNMj_fb*<>JY zvI@Ht4AshIZUrSuYB|$#>S5b7n3AA`W?&gWFY&$0?$E#82mO#&2dCA1>I~4I7-J$( zlSmbJM>VZRtVH}C+q!IUgc^AV-7Qp6)UTsNDR{J_H}`zeQ!VVZCi)P;4+F`^_FWIW z_VB2%HMG0a-*m9p3!@_iJnQmu*>Sr&(Xq1q-t*&HvR-u1Trh~6#fiS*|`R>Sm<)i2KG*ldo3tu_CPy4G{= z?++W-F3Nsvy^!F1{4J?o>F1y0f81XerB&>ty+<= z3F>ClD-iT`E~7NPd!fjg7nVATPp^O343K)earm7ffLF*A@Jpn?itzYpS{3b7#1_0P z{!kXzUD6IyibQJ8`-W!QOlj)Frd4Qtx!AVTQS-L7(}U zH0L20j-OCzd6?;B-W^bJveKEF`EqJ;K(>6Cohj)N6)YP;eZP~vmY%am@ow1yvz9F;{D(z9^41y?hrj9$jbwY65%;=3oyIe z%QK++4B?qDM$q_(kTo6*WS~E|k#IAYU*{?@xEiyKG_qeoe%A` zBq1#T_=sqp1=SoDd#K~6sl-aLJ=o4b{_V`29Hx1OSxls(6OgckdrevXIHb+@ztm!P zuv>-yh;5hZ2?i9GO%QLuf)Pd9T1`*#UkwlkM#hOxn z$UFxOO!6Ihu~LTeFhK+ZE=suAxk4lZwiWsk91@+5EOGrMZH3ozeUvPF3PV=ILOQTNkPC7VX-+0{F}CWcijxPA;GhdNX57 zu%zP^-S2SAyq?eIGN~p?sak`M1lgYIOJqpKaTeA|%tHR3#sWgx8i_=}5-2jp6t4U5 zGyxi#Uw?@e7K%EA;GLV2xPe9AvT?s}gSVkLak~VMawL7<50a5{0S5)7KL;1SEZXWSQ z6t{k`;m$wlQ;CdO z?$0>>&=DE5ua$DC9TK(8Ke_em_% zIt2)Y@@5--RGpILp%*Uc;Gu5)?ix6~Sr}<2&K=s~_m(G(Mh8v@rGRuBVbR_8eZ` zKBsFr5}~kfgfWm-nt7~(>0;zRXotX?%Eo_{h1opv8Z*lmsa+rX|2D+}WvVCwN%)`s zKp+V#lQ_5sBEqh4b05Qv5WLd1LR?n-7zLNI(0zC_Oq)n8uI(N840Wa(f{WdRKCE?< z+>Vbhbi|h(=!m_(FFz1PTZ043tMzVOKKMYS{W+Ca1SD9ad;vmyx? z_;htEslISEg?o(ZGLsVKX{E#wBe9c2<4Q(!V2(N*nRz-0j^RNZ4(3J~)})V9+^nKw zR~~z!+W+q zd~BdNU`p6l1vf5$Wtkj456QB7$h(rW61UC&b&-L@6&`~;JuR8ORZ>yhnOv`CsA)80 zBC)VURO^rqwHzH?hF4=`;SL3EhJt?^Jpxu%=RyL>!80K`^KoQps@WjvQHk#Ff%g6gyr6G|GHADQ8rwP~a`ja7RI;+cH3@)bn&myyds5bLFX2k;-(R`Y%%5+s@IGhV@ZRhRchHOS!kmUU2T&V^;=VM zqCRXr`h+e}F4+CL5iH4jb;r6wdK+&sE9tXoi?QQ*W^z2LWJZk;0m261G)fiEXM{Pl z97aj|=Et!#coJ-rh7#HFqWD?hxJ8lNq)A%q$`pGXqWCoRCP%eX8a3T@RtJN=iwa@< z72Hl8lAL86lX`*GYhW(ea^`Ljey60{4~+W6wY4)en2eGsIy1M~>}ipR&w%Q(k$mFX zZGp=%@=>GA=>{Zjq%SA8>dWc<_2mwS=(8NMX6mjK@Pv--!a4wBrWutQtt2c2{%A(Q zH1e$IyV!S_=83XL&&T7{66_nAGOSv{X~7)l4PcK29rJaP9n`Ogp{4hApR?GWa%Nd? zZ#oc3ANqpQhh{yWzs#z5#i4!_;lj;mD(r--LqI-`Tj zL-R~^JYB~jh3Gi)o(#$c1Sp_d&|j+NWUT_TK_Bn(26o+gKaU_y$_XcMGb;xNo{&c^ zOj*GaX!-qKR!5q0{d7&7E6=DY7)ie64lmsQQJ__U7s^MKrA_xC;C z>UmUCDq7W~6DI+e=HB5FvM z=ArA^8+0uA)!Wv0uiQ^xJRAHt!D9KNvj<~`&Zn=0?zc$#zy>$b#1+eo@r*PI64 zn{YV&Ah%E5;6Au-Iw#~#2hNwCmy_jr_{y+CZ+Ju;2v?;~%EiCjPx8x0lfkWO?ranq zfxL-TlI~(_HKppDQuSeUd%rK2GM6)5vUz&K%CBpEF zWlxDF_Hs5}vf1<7Evodfy{FeF6&fhxXcc|&MQ=b?Wwt&2J@{HR${QNG!-}`} zL>ZwEW6%W`)Rn_SyZoA2D%VffpU`LNvO%Sn=jlNCE=y-9^6D>Vb$F3h80%|rRqxXu z;aWr0HzR%Z{rc^jkHG@7GV}=OZ*weHmJ=0#2J`x}FTU8_6;vLNhuo;E>$i6iW;H*d(T z;~Jxk8rZXA5?h?x2AC~{c9nW+#%K_?66D)$dGl8SJ-h)D429LJDqMfASB{Di<4v@Z z8*fCnG&K^_4>*Z*+s=|a;2y2-pFhq~Y&OPtZ2~frWd0VP&jAHhz?>l|sM<-g$AhHu zB+OLrOe+8PZP(%64zISp*Q&d!caUR;U}*myqto}Bqi#awV0pe9>^cz=yZw8m2@`h4 zHdoZ7m){=v-%cND!}z+t$$XN@dnTEvP?gLxoN}1}PN)a5Z^~>l`-;~l*k0ZQi1$QFHcixv`JClA z-n7?uh6f37q+{S;=s+rJhnJl`fs;1?tajM}2B~9o7)nF=W%b!!+ROdmi>WLAsjr7z zY9=Ua!d=ORB)+NuHn!|8+;AnTjORgnTCRm=-rB<46K-7D5jw zj>!|WESAN#5TGYqV#KqIaEgWsS_E!r&j@yt{`u!%eqH`)ZSkC0Yur|_sJllb(|^f>?E#MOkByaUKHr5|TIY?s zRn@E0kexni$L}Xn9G=gQG{GJA86S@;jD8?~@T4vO>jBgBP&TeF&77`V4)9&r9xv!J^HaAAYkhRvDzlo+l z&3Zg$G+bG0VKrKWX@ch-bBT0%#gnYHhT0v;S_`IqPtUj6zeSH*M7fWq)oo094DSzw zCQdIbg&^NiR*KbTz20 z%P?PnwU$wGOTM8BMZa1$Wf$s(QYs76W@a0+3AJe?6Y3vd3X4xskD<$Trw+;_RU6WY ztYslTeO_{0;n*1|H?Hff`%LC5QmH04>9@S}x6_+P!Syv?-=#|Kff`i(eOdP=Hv{+F z7w)FPWbNrqEd%csjkejP-q$0ix9t6C^mPO_(QKi{xil#}!akNkYKT})qB&&3qye|^ zcEU6efFvU)g;l?mXxr@oCq2Jfdsej28y4Ujyz2n$B7shjy&HHlez zV0zKgXPqPT;C@5vqTl5=<<;scJtcrct<|1ZRj%qCH1LKcEL%ITE=9^E&E0*M1z|Er z<{-#oPhK*Z9zxESkqWb(g4b}pt*`_`kg#!GMAf5D1u<{sFnv)3G^TtK#CBtt2|^-N z0%1e}wp;BvGZPRlCVigET+(I{ghfPhP;x*RXd>BE!m9*{HnYqEhJ@^}VGmqR;@8j9 zeCdz1*2_cTg562Ze7GjZ7x{9)IA!zo9udBKd;snfT2F_6e;nLAOig!r;v);e%g~F? zPbDp3q~2IiynoAgn=Fv33+)~V%c?AbZ2&hsI}2qcc#cf434Aa*D#F`ip@hJbj))iQ zBk8fY$To2@*ji#X7}H8@Ntur=kRZyp!VulW&K2NWD10b}TEOI>(*5}G^}AOG$A>5_ z&5~W(QwDa#7mI6lcK}OL7qdzNfznJ*>mlok8F1L|_@Yf0*nBY$%p202T3~=54vtQ) z?ADWa2k#GFAN42?VRwkrTC?Hk(#aKHJGtt&TRM32{A70W)4{7Btr?$6cQWg5P}kZv zwT(aLu47>it_HVH5RJ`XHb|QDp!w?50A~^Z>^il(^NT*AS9fsLO&dP2%!HUffm2H) z;h-Fl>Dqq3Bxhob+@n&AyYP7-jB83V_1faVN3z8^i70GOw=9QDv7s+;y;=CKr0uRW zKi4gY!=_lHP}qt_&Nb+cl*gCD^!Q1SX~p}xzxf51+X3z@6#vvnh|Pv9I_3pDUzD7x z;;s+4*->i=hCOI69oM?S8NgU-ETgEp;@)z(-??)4S}V7tLA>$;_X;*z2`;!`0@!+j#T}i#DZ_5tG?`km zI`fjyR$}{9&OQY9@iGaVf5)whfsEa#HFuwztyts9BMDXEOx##ZE{G;X3)FqR5%SQ9 z^`!UtEF=L8Wq6RN9C|>zKFw?IqUnU_i}pa?IZv*a`q%2@@|Ic4R>2;2MgYnjdh!wX zBL%7&J0_C$*+Vb(4d!`^s@fq1HM6v()piI|W;z$WDp{(AszeG@y$(rIXAM6gp-N_B zf`EoxJ8!L@JdlsEMLARaMyK_FvLFj9yQ&pxrEdX!N~G`$D=KWkDl`VcW_OdRIK7_V z*;K5dQc06bRqsF<6IypS*>_4_-REnF4IQ99ntZ5#OFI2m}T z-V`l*OV!Se>vrUwev`t9x{1{}=Mvuyw&6fe*BsGCDke8bRW<4Jm&H`-BuP1C& z-y_WP+|vLxd|QV;l|H!oL(b#TxI4MSyVvdg+vF2Ods(2uXKC}l-_2X!zRF88{3U45 zA7jK=k;PAXnb2-8{O$K-Kh3(eEsCtVX7^e8H~Pm{+h4O!?a?{56Q5&!dw#$5%;u}q z-tU3qBQQt8?wqG;D2KL_S~2L%G@T4J?#p<_gA=DxsMnMzAE3lC(hlJzxVe4_Tjp1d~Ukm z{?u0gg8BHhF(1F)Iv;!f*Za*!<6~_;GM3%Jyx4r~wQUGDhW%{g_immKvcWh1*ZupZ zr+yE8qvEWFQU(9=+h7d)Y7%j~{c&8;oHiqeJ^l7tby~ zns|1$%3G?pI>U?@4vRTEX~1a``aO*Ztykzs=|d|o*dd@E++)Q1 zbTsfsm>))eyx^n~=|vo!aKEybLgRE%1vRcDGt)kT@{3zJ1)W1zSFW{EkQldNU@>a^ zNr;q{H^>kPokG+w=;Eq=jFr8`Ol)1_dD-~GT?kiw9BFAzAi@GQG|g*3{CkLU8UQxL z+TcUPjc5?q<{ED_*T^)b7sdk=4Kbp&I!XcfeAA?VWU#i|=?d?>_aQe@(sTA_>2e>CfMO z#Kb?+zpvT%bOAa#xTO9xx;uk3I?d<@f0`Y)j})9Y1=r4z6w@Z8RRx5WswMmf@jMKZ z;)c@7d?Zz4s4(K1LNSnsX{S6)OdcKur>GtzMNr7PB|1WHi9}cxzUSViZx+R4V4BB3 zQ%zBH97%bZ7FA?2ob0HeDSQWPl9QlWpHnux=PS%dMfOIR!%FpW!n1(!j}>K`I|Dk2 za%9;yZKi6<`gGm#5?Bug=6s+URC%=~<5^}7Wx1_~{zUQ6NRcOQGjyCXFWr?VNvjW! zalM&DCH-S5KzDqOQdTCz8(0PEM2=ifti9#)$z=Hs? zK)FRct}IKGNF!jXp7~QBc}XlWo5?M_Dvt2_h764)W5;mvff8^tMu!REn(u$)gh+kP zz&n?~W7!Qi8)7?nS<8Yp5~YD4-c>=Yl2tI@wC|%qit^JakE}C0jk8ld-!2{+Ih{HO z<&#FOm9HPEB*F%m>0r2p-^dyjLBv=6`mK!sWz%Y?0$3U+w+#mDgBuJIKVTeL_G`|Q zC`N!>6HCe+j=4dSmm82FSnf0v5RjJKP@YH{6K=znPu5iL@a+kE!(PrLtq;ttl82|+ zhEmHHIRrX*}#>a4}$rZ$w%X4yq*H*iSp zOwg{~$Az(B0EJvWa#R#pY`zx!X#o7h3BYS8xn4TM%MBKTgYKlFX?6Vee00;o+JbVk zuz1obNN&wil|kIxW-o};pkTR10Qew8W#-l(YJ?ey24R^8%Yku=^R^K?X;n!!UGmnF z$ zekiGe&(n3W)$suR8fcQoRNvbQ8>0NW+eIMI<_u-VpklBxIN%5ka2HM%KYr|!5m;g7 zqeEIR>m-<#WqzHWuIs`e?-E;_5$}xggK|~gg6r^*gpq>t?(CjZJpAWqO!CQx9JH_J zE4R;n>5WDY-T(Pp9!}=t>Y?66Spv04O7g;h%`x zj7OT$P*w}+Z}U^CW{+P>DNvsT`iTxDOsxrOzmi0xap4l6KQg^BEsiREChR#JACsD( zRHN5Q(^F~JZ@1*H>f!m9Cn7#iUcLRka$mef)q3xE1aScI^mC#!mj;TRH2Q7h>KMiU6EMB8TRc zZaY0B7y}L^n?R8?o4lrQba>z6_q}6v`ybExPckl6!fKKh>Y;pG(q}AL$FefRVDS4C z_l3=AV83Ru#7$=h)logs4tP~pznDQ6QpGcxMP~@#tP`i$TqAuJw8QkyuouxI&96%v zuYP1m4_4&D0aT(K!GJVIm*coxO~~0It3?vAuaX5$%(K)x{k{?BUxFJ1U*Z~pT$>1~ zMQdC{8${Zc2AgFsZSbB_g=~ssQu*s46~nHc$wH;DKLzvTBr+tTTkOw_jgcmuzs!^Z z9ZB*~3T^)rsdXtose5&gYV6i&a~yc_=ooYWMov7`9rtdX=F6>qOI_&g_RW*~}ZEs_1 zFJy0Hb1!CZa$jV1ZEa~~b1rRURa6B40UryNUA2ANk{d^o<$HWZsA#qXAQZ@=S`Slf zHH{)EHfKmttD;sTqqPwMAONHa$b>R73q;GbwjZ%yxL>k<+&v;AQ7DRQ+cP%ZEg>`G z>X+lkJ)-X2v#U4N{Ms(7+CFc$+rkI?`@NU=?YpYhU;Z%WuV0*>+m~wyR;8)E+t_OMtDiT) z`m!nTU}B%z(P)dw$fME77Tev%Z|RL-o3*#WZM`kZ#@9tp;1_tOD*bS5XKiCQo*Ke5!p_f&<-yV{>$bE_LG7-qJwDzSn~h0dmkYbcTF`^A zuG-DQE-E|NuZ#KGZhf<^7JpH?+^s{f*yLJB;28-aUUlq_J$bZCNyjOB%1Ww3q0Lh8#C~?QXo?SM@cu+3l=r zimD8MelI2A^M-wE1B*EqR)^96Xhh;%;ghOcjmd1_Er(LE+@*f>W zPZG}!I*Uc0=%k@BfoARMv=7vSKc`++wcBnt>;;X}5XKqy%FU#qU6edh?)cG?cdwJzuy(9&ByKd`cD^?Aji^$s8;})s_o0 zud2mtV5Nn_n@c2QNsQ*@(yI|L$%a zSsB0CjH%6lF_i|b;a#2e3;k8OcbZH zqiooDzblqJOk>RBXF+4DM3TloRPt?4dm)_EMxD+7v3W#;D*ZiD{@YS^^WPwe*<84(&cnNnXt z;#QSiVZ%wENf)7()RnubiUl;C$ALb6qqfOkh;6H&t8wsv89);5L88>I=|3fz z(?v0713t08RILcDJHXh9hyfH(GrMY2gf*E*8m77!tUO+2O;7K$gzU-ka8qkHzow7c z9Tw5qbqfQDC1(!?>k!C528`R$kJX&|BimZAxeML=uFGmqh+riewsJ*DtuE_ot2>5$ z*hamFDJJ_|1~PzAiJ))v+N{6ZqFhWAvax|&)&(iJEtW7d>eJ1#f)~ZCXdooh zTbB4)MbB#dN?)q-lB~1a4^7KPi+Xj0WoGBJbj6l1wTwuYHLO|g)()VR#X#jdf_F4N z^Gi6GLS_w|KvvI-uH^4^=7bictQai@Zk)Yi&oEpNt#{kDZQHhO+qP}nw(;DyZQHi3 zzCBG(nl?>(IzM0~``ezGHP^bSaqBX2WQ!!ODc%?qurz8&ycQqs)NHMAC~F2f3^lwN z9~!VHeIAuf=1}xD!M*91S3}Oa9!%Wq+7Bo1${w(>>DDl31Ag$v1K{enw#Bq9Z;jS9 zu#m_IW+}1e=@h*UCI;CRd!@40I)VM>$vie%TIGXHawHBeoVVk4t`wArN!Rxs`F5WiG?m|oQ)G97q_VxjX{s5K??0(1NAo8702ji1^#z4gx~_v zb(}0>nv|sAMVI*wq+loKHZwzorKc+H@SHRXw$K42@)m88Zm6bJk-WL6s#`5+@?JwRefV_ z$;1HNAbS6Kr{CxM!S*4db?57-dkx{yE~#3Nx4(ziU8lAZe$HEQ0FSL+r-c-8@KHw4 z|N0!R&T}k!W3V^jod}vJkwgk6R;uXrA5q|J6~T+Qk>44nA7V2VOh=UPJU-`ecBQBj ztxtZ{IrG^_dbY*j!1&T z32CjB@h)E+lw)0;)POtkGe1J;Z6ch=kLkD+7>Z|CV|Y3G5{aTXa5bqz6T0C*uxrN- z8TfD1wvHH2g$~H5g}{Nyp5d35mPH8o7c-z``g)9@|6X2Hw@i3zWH(hx&nJ~&)P*be z&Mgd>V};?1yYkzFi4h{gib3?%e=>Ps{`Yt6=-NH(jsN|z9GCZVl#l1-+OviJ&O^!@ zXpEr%u(aXeIeXckvfeX_$%o@-b?Q=g#NHRjIO)~liuGIS^_(Akzs`dA*5gt- zbs_^0qvJTlz&5)xH@R}iY!no{P*REs2pnk(*LfZzWfrm6OpG{5!;3Zv96`z^He_2A zl44!r+JUZDk7GrfcSu5+MC`IFVU(m5bXNj}l+Y_S8PfABjFZ+>VFFR@2FeVCV(OYI z4W1DAJosyQd6K;u&vl1N2mMPDTdaz#Oyq)DiRv*$*w_#8iF5$^1Mf0#0jepjTfrm+ z0j3(eMDAQWL@OfVRBx!X5^604v&0gq{6b?yODp_JGWH@}vHkuwSbW>%hIN`Utd-P!e%`+wf1xyt*v+vER9QB}M(~Nc4|a&dOtlan18i1; z>@pZJof(BQSQ^KW%{UVo0#iSp=u6l+emx^`l9__g`5$704TT3WqjU%~e?$cSlX@1Q zGH1f-zqzGcvj{5>8`2;XLLCXYG~*C*5JxLSRH$!FV{3&v#~?|a%HoU(!{O;PBN(X( zUlL&A0vOB)g6#EnhgjAcgq`_sb-SxR0*3zcVOs%g;e|Ux&;ZBtk+ZyxaP?S5eo?gM zrsy7$I3czyz?%x$3bA!*t!-WVNEW@-gm=y@F03?+E=n;xZbN6xE)^{>K-56PmJ#A< zGrUy#SU5<$5Dft7X0xQR#rrefYCX-=vjzEKo`j^Hyf9ep_xOPvg^O^^pEZ-N_BSz# z#JlQ8|8aNw7Y_>539k!S8(uC<}86H4br<=HP}U z17iY$_7F_71-P~X-c5Cx&H2?l<_Xkd5HZ1=jej}ZDp8t7_DGa0gn>4{pn1dU$$&)i z$i(7`wO=jr&B@B)wA{?6f}CIIOhzoaRxv7k)aZS=Ive$JUpf8WLl^g&4$@2%9TVWZ`0o&jNi9izhAo*AqcZ3^%a4ua*1` zlD;7vmyXwa$B@e*8#TpyqO9?n4?}a@3Pz znAhvL9tLokF+^nd$gENvIgV1{K6Z<3cbY@u=F}{H0RP@he9dlx z!C$wyPK7pjl6uk$UD3w$v=rxIc&bOqP;#wF9WFHpp4Q>UdtADheSFrs`g!s{T8r?! zn!v00kE8`k-ZO))=iZ?dr23=^zLN77sExz+xeAQ~d!K^!Z+{66ode_u!-}kRBgBnr z(Gp{Yz&+QSo*uBh$U5e?1LR<{IRu@k^@E%v&$F>;MMzm1qxzqFPbEhpeGBUz%x{Ck z9)T%Ac#h_95zZPrXhPX;4}wDTgDtnl(A;DyLTmma1?|Yo430ZU7|QT7Bs1r@bJK?b z#sGhG_NT{mlJqfR@%pN%pl~mUk$4Zrl^927*8uGx0$aD_uD39qm>U=!<| zPNJN9kLX0mtH%O)90)KGVlgb9Sdxh+*fA%668duudQBe|yy|q$F;L~+9R`E8sV7?4w`Pwm(1}|N6V5cZ1x&Xx#a$BK3U%f0~hj+ zcH&Eo$Yyq}xyuAR#k158OJkq@jBgBmvh!7|BoO4~7B!n{Gp*zh6ZRC$uv=!NQ-xxpYGQ|eSKg)~KGD0Yn(LwS>V{@XlW}Flsf8r5b;FhzO zDTRyZJ9q-@ruPT#q1c6$=bV6H%UC?-)$_S?CoC6V!eCY5idZ*~o zk~|$G+!92qjh-7QE5f7fz+@Im2u1Yz`d?_Ah48R39*AlK)TUHYO^It`s{;^jAG=^~ z7W;Qq!^i@KvnPSjk#@42+HQkKCVP=7Gk7FMm5^k{;-G;x{Tq}%E|EAYwL3&b@4Ejc zy#(BZk$h#=Jpt#gd9#(ZWmWF?T1v}V*Fz&|wwcgaPhCNgOw~eV%FCh7LfBpW#40N! z#yQ;u@ef+99fzUq&UUaIY2t>WBGZ9zEJa17LFgF-U1+GqC6KwQS{!cTTxqY#iUogq zs*GYa3qn<8^q*O=LKYhLFGTE)K*iu0)D&EghCt=O^(r*^tE(Oh;%S7`K{e z9wO-2P8DArjBbtwC?le*6R}wZlD3xc7Be@wM(Y(Ej2pbA)zG^iMt)+QiTZIh(HAP( zLY_{WZip;#~_jruh;RX$^_RC3zbbM*&-wb#V}cFFTT(5UJ) z23k0$^U>}0RSnS^E<?E`=iY#SvRk-&EQIXuh>Nl3+mSr|f4)-?WnZ=B<0f$Uv9#a6 z!vlua5cobee+UL&s#e#j4S?Mz)hU)`jSjRh;T&GH)QOB)nO@v~oGjSD%7a-1Fo7`U zSdcrSjQ}xOFDTxZkBz?IPIQX zcO#LDjDcPMBvt9O>zWP+Otc&-^X=f$k25gz??v#l(X0B>$CS;fr5f5C8L(N&84*k$ znBv9mqH=rovor(UbS|bs{|Q#QC{>|@TqpW~WUqfbuvQ-F>l+aMm7y)!1Uyfw)wqZr zJiDb+DTJ^Uq81F8DrXHV@?453;-~hl==}$-`4-y0K+<7}a_j<9Ad{Neym1@<>6M1` zny7NW4Gaek6K!1H?8=Qmo@Ae*p*B;(0?>KDxfOXIzm~46H!7wu&F7seOVET)m`SM} z2QLV)tg2VRN=`pirJ|v2$y7g4a(r2D5Na(9^!WEH@oSicoolENLqXcE3jVdEVUczxGKK?N z^Y_B?Ihm=R#5K#lKqS{3`qG#+2dNW_l0~aM??6mg{^XvhbfRwUgr?&)uG7Iq+>fhj zw8q0Iv}V;}8j`$`Wz9IBRSYVLPk{`hm+P2xbx9=K2bLsF&{P5cjfDxr4Uy|5C5qV^ zoCA$>0($|I{&3Ohc(Xbv5 zLyA^Go2XnM%WMgTT9rDIV(QAO)1V%Q>)6YHl8?@kyxmZ;dY}F02HK?;N)_CTHKCun z5#{}>R5YQUi4i>HBLN60CP9gj8501Xpp~ORzvXb0Ye;q72;K|S6s&QyWOLxd3bAZ4 zTf5&wv$g{vuxZ#J7hQokZa@Q}b_M3BB-J}3Bnq=ArSrMq zwFDvomf@bD1Vo2D-ij;Xir6-Ej}42h7K@VhiU5d6jADcY8Iy&rX-y}pt?FZ0@VPlg z+`)m&Y)Zf9#PZyzp5p?ex=B^lhXt5@We0?zYWzNIswIBZEA`Il;izJ;bwS;%IW#Iy9x zeedP`Q)x=RI~rr0l%{th1k^$c&v;3_qCighVyR`m1$>!KjtR=O0aqT}2pkuP0%!|I zhFlqn8;rqk(d7M>ya%VH``g9>D6Q-DtN+9`s+1BUagr?@!-;TlLRB=)JY~hGY-mur zWBO;pIzH-%W}NPflTjqSh41M ziwlr6RZ3tf6_bJ`WUMD)2N0iHamPQqF#&Q%I!5~MC6DE}Q*4srA&C+(+wg^J94r*n z)1*S*jj5Ijx9Fy!kq z{S<1IZfPRQGF4fT7K$Tcd+&q*;r1|!l(xfOd`|hd48WJlb?GP)uf>m-Mj0vW;OKDp zaChF%&Nqr=P2U5=Uey8ETLdmPuk?4ph5}$yfN(#8@EU;KaDZf#dS5*b+pl zTQg?0|B}~)k@L2Ydo|AECkhtYiOyu;KexLC>ZqVQg`5$3IjeGgXKgkmYNYH)Ew$Kkv@WQHvu4Sl=HmddrS$P5EKI;~q1-j|MAyGV9JL`TA z!5C?WY?bD`qty!=^u1s+A(cx~X+LnHuL~%930Xfd5$32hYP7l_S_*8d_(7eFdlEzS zF3pHo5&G|}2@f$^NxA|onpj}sbsu?GAq%u8dM>( zZdj}dR5zxRUy&L&JtLND^~3Kp`ETy;bI)|76-_U3u9q~Tl5`8FOi^6-V>WiHxyHm{ zw9~v2>u_k9B4!5ff>E!(kJ-sK2}$hq^ZLyRyU1hn*_rLWAf5}f-;1eYl<=tVE3X3o&ElnCMYgiR#gk8^lBAXxor3t#A=-1HAQke6@ALH%`q;QN*xw+?4VqESz2fHxX@n|}z z`X8qpj%5pgo9OF{%q;%{*ldAVm1{|p@*+I#>KE3Z!WHLiJ5_v#kJLS6FdLo3)ggbl z!Vmi@lWo{>TnZJ`7OC~qAVJm}Xa93&{_yQ=2kyYH4 z_|rat(B7ENb>0Ytrw`K81{t1Pw2QWYt!B;kGQ87@35yTbIDJ>UY+RUxXAWLP2);*t zf?plg7?9@)`|^tRjSoi8M-$3EN1QcobPL4YM7qTAb-vB8_7O4#%c%V~zxdlHXrIO-AZ_$yd=timB6#}r{U36>CXNZM!c@0aGJ zXAIwrcLvI09V_H=c*ARNpr31$i@_ZuqO9a1UW;gGF_M+5&|uwY2CbP_Px@ZTefoBv zgcrG4<7Xtxajx3>c_0z*83ujg{G{%sISUo(dVzfzB@52sx`<{eep7*h3LE#1N6EY~ zsv;Kt?Ct5$mCBD1hiquEtkYoeKmM?EnZ26SWZZVKJ{le1T- zYA!6*(!Xsxe7~wKIlKja(bT^lS_^!C>u7(X)|6s^R6H9BsU1T}=1BXA6aGGXlT%e- zid_-PPntG0#$&U`wE7-J;6D`!xY*S?5>lbn2TxJ^=i*epJ6ua&T8O31_@%W80wOSq zpdYBp$D##_%rlyUC%xdoV?IT9-y3w@TpVb7#Vn1dkKFAhMVcE&M(37pRK3X&P{sHo zSILmE7me79jda#Ma~3Sx@5RDT!FqYjLKSnUESt@qsV)*9PWZs-?9BhJp>g_(iF4>C z_`P{4iBpwz!D#&-4ieyV3)D2_ZZ8M!qM<2?fM4<>*bOJr21ix%-KWSV83({ zX?a7;g?(;s`{*~QZVsx|0^ zjWDi>%gd*&X36Z8?I817)FLh}ozL9Q0%aH_yIrD!C~;I53fHQ0_}~`#nTF*c15IQX z8QcXd;mFp<2ch1H(rxMGmt#MjweE4r6+PT(eXU>)Q5Q~N9}|n*&rrU~gh%b}qXaY{ z^_v#JHrv?Twd;V6%3X6_AhzH|TTNWDjdDg z8Y16JMo_5ue<>O&G*Pmseeh;vFdRSq!a z4ZA|uSbnzT=M=fK&`G+!+p?m2P%kiqjS)Sb-hLlmtmC8EG{(@Jwxa6@kT?MtJAda4 z-YG3RDv9y(5esVjSgn@CPi7BQ>j+rr=MhN^1@2#6RhY6Mrq@^IQIb<-xSC4#q^TSO z@-OiyG!c0x0y3f+mmi@3)0~JX010K_FD$LkRic3R@1TTIwg0RLd=W)HhG1NRsQ0WD z8;l|glsCL=!+eN~@Zdz382%33<7okkSP&;2?YX$gV<<+qp3dU4DbjR*vVUwn5214# zj`?)&w4DPi7UV$VRTnDG4qPDF>lWKi?m#k=*PaEP-Huw^(ewdNABWV*eu}6aysSxI z5j2^jy&$WjS>WH8mq=RUAh9H_cFYtU)Va?o!REcw?R|prhC`V&{#Z(`)>3e0$I5-_z zy4I)sS&-s2Ui4w|gI7waQrSkA=ZFUy4B-&rB>O|Fg6a3<)i!6nBAb#ZVm^7c$NdgpeC8ji61E*wB@pt{siP#iQrDpy^ zC%%&&$v>DuWpsQ+_?Rm&UuU`4+tv13Qq=N@JG$RYT-lsbn4obVu2xr`u=U7H)o5TF zUnuJk@h$aoI21^niCMIgq>x+{aZC=Ho;a>MzEkRn?uO_EEc;QQNUaNhpc{5cguzW( zqN&8)Skx5NO4m>)6Fne29YLzlkDbuXYZqgumPPE47a`g@LSA<#NIN9YRP?+?9f{%) zYtQ#QVwNCuWo`qbo^yQGMP~_0=g6|Au@NR}Lu@M4juq{u^*F*~3hg6HBf$8a@5-W-6j^?O3<9xKkve`~y>24mNAv zZNfJvMF`XSgt2!>_3@(7zj7goyVm*Wh6tEqnXvC6gczJl&a?I$9odRO7!xV{R_Q(sG9hdtw@{B zX87xO^6%a1$H~7{qF*%dar0q{@5CoV4n|ZxWQX=g>hS}HE}Lt2H@lrTlXJf#W^I2r zgzJagI~-MI-y%vKrV;yZ!N0--IEUJRcJ-tvmo0a9Ycw2Si91Vn1BDyk=mF~RWv2{v zZbI|-gx>8cW~k4DiY`lzn+U#?;DKTf6wRuInv_aq1!{GuXb97|;5iYT9mFsNHTv&G zCZYNc?AeMK*wKl%x(4mEB|cVHp+@_SVWk|Ru1@p2rlB`wy=F^y?H;3e5=Y(JLh?nr z9o$lJZephOB+B8Rl(Ut`9DUrkz^I(H633TY@@Xnb63yUXYWCiz(;d}(NRUA_M@P=t zeF?@1jKfa@aDK)avwEGzb2>wU*iLeK98tD*aEaR>9f5a0X-+{v zs>d;g*N4$2jn5TFvO>%Bsau;h-8C&UQHJRkJ!yyTs-mwd1vd>d6W*s`vjpG>Bh|su zr_c!-s^|G)AbEBIcRow$AYse4*j zM!LSpWw_OZTshdmi2n}IgrcNz8x9=Soj7nhLmf?D--O=PQfn5CasK#%cHwCwRsshY zt=tTiLfQ9)vo5swhXGT6W%1aQOV9q@&%&IW>XY@Y=LvOvLCa#@XNrH-?ozhDB}!X_ z@{iL+sc*+~l^S$rGaIcS{}INA$a3;Kj=X@$*KG5_WTK}#|B?ON0R9BUpRlDj&J*o+ zr$xwY#{k&8Wa^L^u;@3atlQgsWc;4lzY_k;eRLF*^UqA?9kPp$GzfFlGx;UWq4?O1 zx@yU#>Tr}*({mhfw(9eCCr95|$i2(=fb)YbdwnhnjE#{q&`icx=~D>nS~7wceP34&N7KMCbDxWA34#TnJ&d_-ocVR~7Rq(5r8_*rQjWxDKr}n67?Pay8T* zz7{L07}un*Fx`0Y0U~e`%wkPx(v5wr$8v+5y}M_Wv14k*sNANf@J9UOQk?X6Hzh*S z^f4=Vo!}khJ66OTGwF%#>L2}4WxJoE567DL`Plv0xZUaTk67xwhnX7lzadzV070Vo zx4=a@8;!5NgQs$AzK}8Oq&hS!-pVxl!Gr#q(ZWU69uHBDaatmVq`vt$fR3^?nwm@rX3Ga3;$ULa=e0x>#zY{aPk<5aHlf2tV4jGNqyGz74jv zp53iQv6D(Y7W52&x;Zge@0aRw7iOAlr*RrxYAkEZqnW!tHm>n9_tQSi>BP8wQ$^pi zs2ksJErMzPuJjs%+S&yKal4%eBUwgSEP@!QG*0LL9Xeq_E9j=HMQ}*u8f9LpT^lgd ze0lBYhlr(qH@N4kKivayor*UU&)ISJ@bRDt=cT=SRNnmbe>c(cS~YeVp#uOwa{~ad z{V$nl&Hr~lt-hI|5SI_VDAJ9lIL)$gHrCacnNm5opLGmC$fjrO_2aiINi zc5f5s4>nfz3A0r$`>4NOtwkTj?a4ApCuMZ4qt-M1wtqA`^aR+JkF}05n~mjp<#={Q zHXALu(sF7r%)qUe)wZG8_VH)4c9lG}Hl3_3mDX81h`z3bniFB+Kc{PFzSh^!IV0nE zYBhWBw_2;ujClBi48{WyDIdd3WrwtN`Y9drRO@lA!_%FELt0v?{q9#9W=Cf3f#jQL z@?zmAT4*&;220kQS*!qoBRVWUpLTS<0F0zN=qce*h>_f|Tetl;!_>U}vvCL%qglpJx;b@U)= z!9wc>H_fkD&w+Ae_3_sJo#pQLrTpo|GFfRHaDIsxHp{65I$GUGnLxCYULL#Y)wMRW ztE`uO9JM@GFYve{JJ}tx*!svNNxQE2?za0Z6X4iqY#Q?)iMwv&JR1q{3n5E@dP%qe z6+RGfUR7!@-Q~MVU9Nkz7B${L9lbgz z+*)NHdut~$?ngZ7R)3v3C(sW7hh|upVe9l2zIRjOURS`?nYZuviDdrl>Uusd>7);z zJXO^}D@#33dq26DK-xonSH`djpS)FKP8=@F?e*^+9?z`rN0x=sYxBnMX_cFzfPw3~ zm(Rx$boTnWdj38i&Z3{P=7Z&H+sOD57S?8Sp3@#j&Ifwz^Nq(n%5+C zaP17`KV#0Of|jT2cJaX1_ru=(_*2#s-P~S$E;wt#l6JTTau(-%vYQe)>lv*Quq$IYs|IP%gy9~peVe~z=)kK6$rd2J^T$DL3 z8_a6S#q(BsQw>roN=YZM_cR{PwWknEB%wPVh`?GTkE)XgcQ=d{cY2hO7hziYHd~fj z@-z@C`vJ6cJQ<=1R{ znG8xnBn@)RnC4gX6vHPu7*{Z|D*l3ndK=>mk}3-VTQXH#Fnd>NI_@r9S<@c8O>Vwz zpnBQ=d60R1A$0#9PkimO5?Vt|1MfHLil4{btL}mYZNBP)rZ5#`(jnY)3Rppv7F!WG zc!d^Y_v_na{QJr3q@BnB&_P%mp*kfer;e&)zt@4rzuwdBKv4xwoFdZA9AqO*yi#G^ zaInha3MK7_6biSJ1?Eyc5E(!en4k&$$n@+Dj@j}l$4b0+V!JZ#?vyHgl7KufJEq9= zLHfj-I0gp7@g>2XF@#e8=pP*#g=cZ(CRN2?dUA0S%+V zT*mE%Yq6s3;pH|89oBxK`{0{#egOU2`eg{R?wQz{84diF{e3Ux`Au`foSU9X3)Gxk zM{f?F-=svyMu3?jLSv$i2RIO}r6@u!oOkXNPacdtf&5_3FzCmF-m}sOB*bWrzCjM62LwwX6wH@O=o}@?)eoPK zcnBrWL`A7jhrICaktF3Th80RqI*E)E`xRJZ{dktux;aQ`42hSZE#<|L9;a6>qyC&& z&tk4IgWb-HmY^ga>GRRckj(S#j|@54EWtpvOiXIBpP6+1I{(3Y@vap~OHp)u5L zqT$8@F5Zh7iyThcXbIL4+esA*+2lk^fb@-uUQb zza#%7OJePQSoD@75__Y2Ceb?@NO<0jnhT|{nQRq71&Bk_QJ8NqncxSU)$i-^aKyU^ z9J16|C1Qa`B?Oxitm%X(Da*+Mj2%=$$m3H@P6OT_Yv4Oa)f%jn7 z@zWPX90TCC=CE+RdYcJ`nPl6@KtZ1n9*M573D{z27HW_bgd_|*HxUTbNsUr+a&=?r zSeBtU8JL->vC!8_rV{`Hi04$Z(aM{a8%Gra77?ye&+z`nVqxu?ao&s4P=W{ zOhRTn=Fq&Mn(#^k24mGuhlPSvK`*4J$EZ$TW04Hzzy)(1Zk7ajh&A97>?bfFl1u9E zrjfiFkR_v&8J>$wgCF6FhLYselM>CR($+@$2Nm!{!-Zo=D&H8%Q+41r47l^XJu`Jb6tF! zH=Px#dPW8EQ`I#*Hh(jW^9$dVd+sU$01?r4uXm^bXt{BHKI+VCDJM4nV7r^ocz3sN zO?xtFtKpyQNfNk3_%&-r%bfzjCvgLN6_q+8_4-e0OEcEp`XA-a2iTX z0tjl}IPU_rqvNwHP1oAC)qI)~gaE3ioPWKsATF+}89zT`P)-1Xza%aGZml`TtA|PqzM(H08}t@0a;7Wms@J9nLJn_Q9Y69!@I`ie zn3`D#A-l>Mn+U&#qT);so0y~LR%I#Muvptqm%|jAhVV65>v1O@kJm%5@z(fBOX3wd z>`7u0&v%P|fDPW}p{b|nn|{ZD#s71p?f0CmZFNy+O(oM+7epWp$(njpf+FYrFQ9=e zS>p{X83TWb8R^K;AYD%>2~2xo+O%^{Ca^m3XnB|LcoLR~8Bi-5hA`CW!zk0?B%WD| zYKCE&q+goLf@z<6QOr-9O1!kC(Klr2AW*0HqIRhp4bWA@>ao}d136?|IS38{du0=q z@7=10J6L_RnhjRQDa(|B)~kG-)Wnh;u({);PQFoiZ88Fr!`nk##5r1;3v6IaE=**U zR=2gV6RI8iwI#6;1DAz4W_bh42v_)$d!ld@>`PfXHPfFs`b&)1xqDOPi}$XvO9VP% z)16Y&6?z4d=R33ItEhYNM#f`u&u3kR&w>K~U+>?@DE?nvtUn?*&apbxQk>#;)MVJK zgu-%w_8*(kFaJj+|1ByhgYzTZ{ni>BAeI-&cX}bOU zsk0Mg$SPVVC!fN{XUB|^C5v)bumPGWO%BsOX_Z<_>Y&p5P-tkmbC!$so59cvlTDyC z07}fY4eQnA=wT)pEoU*bWX{B5PjMPPDR3+2fZz%icC021CX-E{uVl+?8oxpV)>#{oc8HwVpjEaQvg(@lu$%u8(ju1v-1gZ9d@cAwdj*Z(pgfS z2$Jg~{5A|vw+T!sg><)3eY`O4!tiNt)pWhhlPu^vq&BQiwuZpG5fW+DtVPjGpNs!25Pp6+596Y6yV9-S+4jptl0Cp zUpYClrjt*!CLTFFiQ1IeXjYloWzXM(jOg~KK)V@kg<9Lpz`8~mm1uX}*cez7Xt|T5i#>IzZszNm5Q=DNeOO?lw(ZTTrUxG&1aceP=o&dE+$Rn}1TX zK==fYkI}vOqgoGt3N%FOUoEu-2W<3i#57U6D&(#ea-Umc6)1b&!%w-Z1L5Qh2+3Yb zHl6`ya>+eXF5`fBe&^S1@tW7>8QF7D``%~+Bw3s2Oap_saBJ5U_vIR~Pi;eJ5L3Q< z%sH0iIe<`4XWKZ5oh`eDc-$*GF{uqpY&b1FW4gHgMC6`2B1JxqR(>UvD6h;a4EuV8 zc((1-?A$fjR(>A!!>-%%(G1_Ts8}w}2rq)@B?ry)H=k}hRTNdyqrl5NfUI|wM~gg}_3YF4UI$q13%WLxA53aRcnM1U z1%sPHNKmaBPH{yaj@#K#2aa=Mr^oFvn`)``*miwZ+i^#RAuDWYXQ^DoMPF9Cz zw~QFcNB8MYdo+=s!oS4k4daoNJX*rF96>O>wG`6(!NvARg=c}z5d;Zf{SVLncjP}H7=VBM3AS5m)K1{2*mc-KY@a)XxBiO~-HYSFv` zA$1#HQjVSg7+_bOFum<>^{6KTu zYDurpLc>h~rCIo6R%Mk#o0gPUrZ=MWb@yX2nF5rvEVz6h)0Gio0epyzI47XITz71s zOw3%GtrJ$wBa-ilI99v&nc7)&ztnCV3KB)|ng{z;xxV729Xe3{b-__cIB%avpFrE9 zIHMDlNvf=Pf$$~=Dx&u&ZkDR`s>1JBgpfWO8z20$V-Jqu=mGtgsRy z+<0E$6pmY)H;lAyR3k<56X?*@d4ymTyM$IN{v%18)bE%^f zznekztIy+DjbY;mV9R+PzHmqk5e%vhe0ytxj48eN?lgqnX(7oJE5v1Jn9JSL=LONR zpQDiRNDFc{w33yC)i6W$-YOcc1J>G_EOy>u1`2O)Ttw^fo@8C(KR}Z&M~xdB@CT{& zm?42fCZ3yY zzQrYRNbJsmDPSr=A)(-Yfw@OLuPaNW5rSO81l&=NRe~Geh>(HAplhn_(@F*h6#I@f zR6P-Oo~3c=bGVthrpcY+a_&fSEVN2^_9t>DlB$X%#0KkH#S)aUz&CW`TM(vAy$=D` zKa@4Llx8YQThbj#F`2YkQg)o>*w24mHbsYb+ig2WzB64xxgaHw$jh~>46w%cr!k`T zy3GP?kY|DxORJ$Zo&Z)Uil?~zib9g9*5abKmt+m5Nn|of>%9`vFE8~kD;H??x&)Jf z-#c&e79MAsSHOu0BV8`Cn>EijGUH6j5~YRUEaoDd)f2ra)uKBLnX*?%j=|2fxLR$y z-l(~9yTtqT=kYFb#2LRte$aHF<$HgCwohahvJfMnd!GymThZYP1&b$YTdDK>i2(GE zij0BQZ9_Kl7Tt%_{)c5dWKt>`$#_d)>spBZC_lZ~Y&1_?WFrO4TH^lMfCjC@^0#sq zVK%@Jn#UGk9*(pijEy7+qJ@W$Db0JGhsjy4f-=ARMw`c}KnglN{I#xa$q-d-d_X{d}Vtd#7k6vCm4P*&9f7Qynov$*wtU1gTm za}>48n7N*jOfue`bI^1aiCm3Q35zNz+a~Y$d;+RWuL_;@nj+CaY(k1^j>|zmn-WPP z_>G3kcI!uO^`XPXgp%fRDCoqVTYb*I0{t&v3r`$A1bV$Hnw0s_HmQTln%#g%UV?lN zf-2UaFK%`O^e1z!z;X5Jx$f{l2Xu|`N$PXhT0sGklaH520Ja_0=*`hS%1=`N;%IMV z*y@#_Xr%Z|Ybl>0EHmcp$ntR)CfPN}PFQrPnsg67U(jZv}D6X{6B;E!d zLa`osWXhcf;f}{qP`Y{hSKAXewO48AO0C?nf-FgrC1pZq=#3KeNf|SY<79A2GA8V* zBclG=4-8Q?jpbpIZSHbKok>m<0R4idOroDb#|)gHr z=&vk3PJ-G8w0xRadC|`6bw!kD2T+#&ps-eK;Z9PL`fG^d>G#zv(BFbiLp)qAViLJ9 zNlO;yze56xEcJc`EwXT~!U4aXx@MXRWs&F4V1BnMZKmbc#19=D!cxhfhv4^+0iBe% z#J-j>cbun6omyL%)T+#UGg00HsO;ckOs3zDwLTKA`7(ZZ?{~C|0G#dc zr~`nlAls92GbcNzhB_Hc=Os@V4D*RUfd7+$0q{Q<82`aA{%6tte;waj+8NupnwZl6 zPw>V6yC(Dhs^|DjK7XzXHXZ|6*B@jst% z4W;G&T5)=8c8&EVNK}c(eeSiW|yZW~_ z{ocz!bbP0|-P;`wvNFm7D(e4AKULG?XOmN2J)5Spi#|txxBKHx_e?lzcchS6>a?eL ztv*)}hx?h!{T~B-ll=iu{!z7Md&DDAwB4F$3YlC2O^z!bm*U~^1y^?X^D&!Lkj)Xz z(ly~7SG=O*T?yt7yDmD!38AjYlm#9^OdYaGVG~qScm>5^Xw&4P{Q{65%9|kIA39JD zha7(K@oZ-K1ks=zryG%k;e(vQkbgZD#Hn1TO2*8R=s8c#6A+myNC4v?oZXWByVQB0 zLsE0ZsUfV&qA+M50GAFzsqM0JXS=fEE!95b-x^n{=I~?(4Y=81Tp-3|g8Bq5O zw^ne)xThIpuyhkn*e*vK;Ul~Zk?WudpuDgNs=x^$tx$L+uuVGvP9StHX}17}NIZ`& zTKqWApr%|e)Y-WDJiSoZR6;S*X)RAWrh)t2k;UmWS^94JfXjLRo&3_o*}};EpywZU zHxAcXvV5PcI6j}(?AXN0hy#~1*b%e`*K1kv8~d&amoNi881wme&@Sv~ALkIie-@lM zvpJKi*jj#_7yvw22Hfbb1;-Uv@x#Z;%!tKz;S~UkInM*a_{zE0v7og5Vrk(OZ|+2? zGjC3we+WPLowz#j9Xr;e({Ze0`_x2=TkVr2!;9D%yLxct(}mfmB@;FmM_=^9^|uv6 zC!XFj064}PrXOA$ulcK^gR5#D-C(8z9;eBC^i>9Su!-ymkq}c4;TKdTyFJ541_x~HWCv$u)V+#FbV-qbHLu6y%{ml zfyFg!`BJw0t_9O=f0jQW6kr+fxvyYzUX0`HH22WNGdoD^bHU0vmp&id!3WBOv zrK}6|Fqa3pGfahywK0?0-{h7tWWN29~ZeCKsKz~opF}0 zXryQtBf#1q4sH&oj(6A-|{5EY!__CA`gz{Tf%0@*{DyB7ob!padL zc{04Zusz4q_tO=-{qFanj*P=aZZshuAJ-?R7Fjex$kfa6H@v?1o!&FkU`yT%%=CM-q@ad&0!d|IB z%vX5ti$jN;g^{2Qzb^#-qKz@XpkvndhJ4fv)pIlr0HP&7SR%GK=rik_-ZtTZzBpur z4aPa^k7v;@&j6n1-S7WK+Br1|0yJ2*Y}>YNyUVt1+qP}nRb94i+qRAEnT?IziP*RA zALQfB%zMrqu7#^&p{~bN^oOwL<$ev=HTbBaY4d`>iLZpzKd)VR_bL0qNEWik4!iyN zxz1w8l_5xct^!EWNJp;vlC`?}#}f;@LI885S!}qt_wO_qdTauh64wr-0o#hH`VT9V ztGq2km^BaG6FpZ&b;JaG2lnk@nq$qiHFCh%e5CgsewvH6$i;)W39WSTq-vPGe94cFzTU=bg%!LQIFf8e^gUgDw9E zZ!V8Ycn3~X0X!=)!m|^!@k@1>O|4zHnVw1T(M`M^!A5||$k4pW5|ici68GlzN#pMv zn^cs*8usUr#25X8BX^V2r3c@K-v-B>-M*N6vCJWz*mw&-VCu4SL8JvL zYb~7N@xln?MihuAm(XcIH+Z@MU?K<*yZ z*Ics6#z04)a-x=_AH8)A1>_8RxNWL(D2f9|8YAQ2o-cEk*zpjXAw9gE=Zo3Cac^Fu zLV&uau+?rHo`7qR**^1SBVM-YXntwyl&y16KFwb>-Wmbs6Dkr#=)IHJfGvyrNyv;xWhl5B;cXh( z;RaZH@Io2`W0L0Yq67m>o`B)0XYV*(-*NzHq@y0e8>uAHBVwD9;bO}+_1p%j|4w&3 zh*w+%#_!S&5e;upHNa?GH`!Xp?}Q``JX>K0-Z*;^>x2U%N&!tzBJ1e%0b+=TnI|~? zNrv-Pnp$(lo0fzqvKp@_kZS-TkI;7M29r>dyyR6GC6U^UA|*I%Z=EM9w)f#XBv!;PGkd4w z2+o@z@pHMbooVMQuU;Rl54uT7tkT0TGvQ{jcynK>u=TY9r-CQZ=&cnrYKI9PKhSvBDh^i zu1n9hd}bSWSOyObU4cc;by>e9l+s9s=)|AhakQ=SFQA? z_~1&rkK)XJJa=MwVLt{-D-b>Hl#kVpAGxFa@4OVhTyv-Pi9jLo*=E3hA*bAVp)qg1 zuWV4u+Ddk}w7)qtK$e!{5{|*VuYO-%XVVv)K4}kG+~FY6DJ4GQx$(ZcT7<+t0Xeun zWJM}J2T6>2@=fsa<52hlT7-!;H!~gqsx{W?_QuMru7XYLa3zJE&;y1H0!G@+6Y>p( z3RFDhz|_QCE6kS>V*dG>NP=xSjgB}Z#4jD9bf_bxvL53QG2BQ+7LQE!y@$*Di6x1| zV7h2R92@mFzxno@pxl@BN3sb13^yUw;MzNr?6m{I?6uXN@=)%A2I+rvkxhBS0i5yY=m`?@aiz^GwdH$wC$irtiF1qkFOl;F zPGAeWiO6i(cxyYOlNp4PR89AowFki)IONeuQsemsO;>yCJwV|1Iq*@w%OS-Qm`W)+ zKpvhEQn}k36lISH2^IC-|L|9sVONIfj88_n@Er-N;d`&F{=NmgX`A_z7mm!`)K{`HV1RBm>zpf z-ZMpXS75Abkp>dVW6e;~OhZO1DX59(za8|&stB2Fnd?tSU@4g9U>t5x632$YF&QUF5@M^CRMSq9TZ`JjUA=?WP4QYYFp zsH$ol9e+0cyZ>zff6BB7-e|YxaJ3?#K(K{32tfv^QRW2?vnO7>$Li>T&v;>*OG{#z z>8q#MDm_7zXI-Xbwa&V|Tim$Hwj|)p91g%_AIaD#5ZtdbNc&jFbBlkgkkhtFG9}nbO+%gF=1fLEss6gnP_qgI0WlLAERLmuOe5t7L)`%TB&!yC$I^=1 zt46n2)G4jvN17~>p=4g{J(I&UoLVP6R^}~{sEkKiqse}_O-GhX%x`>(eZFF*wD++;;j!baAIpR*fTfU*}MFNU|IiRDF`w#v> z;zK1Tq(6o{DVbaJfZCylM^ZPdK(PtkmOx-Sd$gx+&v=RU6!sP01H zI^526q^bX7ovx%Czi$bLg3_;M|9CFJyXVb1d=4Tq<4=zW8A~ZqEnbGzfDjxSST7Fo z3tf5*cB1~nH#QIwrKS$l*C|E!<9Gb$oKwB6XBV=^>nmA5; z;9#>32=!FZo*M?X2&kb6>Y0W_VMZe5wT(Qa^H0F^UIe%A%fEYaBB6sZSD09qu>tjTSpo=B{e80h?_cVvk@D_ z!~F}x7@B|V8|bw|%hy+|tsMj#>|8=@*6rBvi#+k8t|41couzINL zd_se#9O;+{afkUfa$zwDLg~s=GjGjO2;TS@4vId@oi`HMn35X?vJ<-*9I6D$i`KvO zM6~N1h(<=7f`ga{7L79H^FSBMMh*06=B1zZgk8OGpGT&DZN zySyXZwnofM>RgU}SSg)e1uPq;lxN4@A;UcN znw3(Dv$kZDN>j-4fgYLZ`P6Wj941UJfa>vMljZUQVTrVIwu>%?(ZdA$Q$3N8^P~wy zMXf5p!1_C4<3y|a#=)HFaBhYNKs|JKt`8~Jv`=eAB~ZxQp~FTJp_qg-49Zxf8RTRY ziq(~PH{Frrnkz8X;3k+BML^VTC8BJW3zAwf^H32oRh}EwC0|$%y5LnRU4jNjm(@Hx za)#UMDB`wAU2W{C8YqTfIVPHvpyFE?2`oV~Aud#|4413J41)a4N&S2!_a}tYs;~3f z!DVaCP>_DKDAO5kb40R2ocC~E zZoKQ?_4yx7>+Y?vL2fD-PM9WrxYSM);knQs*viyuEng-R;bh=5D4Q-zx++HuqXWwa zA-g510vS?@8gqSsQyV%(=2BDJYP_#*8%tvH!!V9rk%Cm?YAlg}oDyaCM&slKjWZ>R zg0JK=fbh@OG^K=jgN^YRL17ndcCxm>>eI2IwUP+q6HBPUyUXwlbnmCHN=Y2?=@7Y< z%lQ~uIaMsNt9=QqEiM{Lu5+*;)Dll*wPf6WmN^2d(?T=mdvk`#A`_p;s)K7vVGyj) z(4zK{cfo{-!ZQjaM6ryFT-2zqJ)C5*4OqvL%dOg!ErrjfKCxYM5SQsODDv6HKYwco zss66VI5kNbB!_9C6%yS}S@Aga$R;V*_XXTD!nW6S6%}|Kpvs>(m-X-0;NJ6WzP}xA z!CTo-DXlx1z^yNx)K~OxUs?!37c+y=c&Sh}Yy_YrY`>^d&*P#lRY=cr*;NXdpX(Xv zAfs{BsTen_Uy>@IMkt7I#}d#`f$E$WfxK0*`7z630YeRs)0z3B6}0dYkxjoobY&W= zWeF2Gh}Yr+f?_vd4%Hg;H8zM%G9!_hhyziIyvtjp8@>JU2+DGnd0vs*h#cLJl`WnR zR(Qx_tzEI7c1%r5ueT&RHFf#o$$vD4Bx>EweHa2_lr&U6vQe@g$?sXMUbX-hCe+XqIQCK&(~|mO(9QeoMi>@N(!w?9pP;Osp4s323#E|lMM#FnqK!MDRh== zneSH3XI5TiI-f3wYvbdfD6zg)bWmQbnQ4JPkq`@Z!0WPqkIV6$FYa_KL-EoiNu4e_ zkL)F`N`qftT`%F$Kf`2XI{cG-8)?_zl(gV(>;+O|$JjofG!uat-3LHA@k$87!hDW` zqFRP3WfILY2_`Np^Os1Unlf)t(o`W+siago%u&5AY-e3jZo(rz&p#90)St0K}^u^ zZ5GF}Y(u3*a#FvO%K*>ojuWEV0*4N|0%KU<1vhX(XBmPDAvB+-w)h*XauDK(Ay}^i z&sfmb9ghYO><#PPv-zM)4MVR6`;N1Mh%<&TAMQjDQ#><>!t~2)E8LkK0vFW)*(&8N zS#W}^v$9L_Sw>}tJ}fk)#Ik|35i+llptuu78!aBoiPIS*`$}79PMMKmXQ8@b;~zpz znY2W~FDdDq>@D?9gwCnfPTd#Gr52!EPewUf+yQBEM#e9JIYhdzIgLmO>McckEqNmZ z4akRNxIX}C25>~$?Pam=)~NvgE9Sf_S-fm0uvVp9gAy;rTQVY<%%@le5f%6w3^4ROSe!1iNAYF^qgllqTKXI zzdCUuxh8UN69G82U0630GAK)a#3tO_0X#nO{bZjl2C^0^KA?OokR)z>Plr7H)y|&wje`(e&^ZZ30VY1j25Ca@GT09y0O1 z#Hq$r#XzZU9e(q;t-;NKul*<3fXkjPRB4u-T${gQ5xiS31)D@1_9PmZ?DVlVJyc5X zr7Mr_xInL%?-q!kVQwhyAQ>eO^6)~CQF@Lm_x<$%$0NABN=UhaMpVD5MS&sTtM zSGk}|Q$HDA=#DT<#y%}_@x8HeG+{tD_QhFoV8DGj2haRG{U)Iksp}tv@(KL(6Rq&u z8U4H$&K?$(e2$AXsuk4tcUb_P_&Hj$7b<=2O=6~4DSTntho-RbX8s7KRobb=l0f3M zB1z!(HKSd8NLRS0hXlK(HI+VSmlp`=5ppm#5*Iggov^@F?|_RXs)YeU@gQp%^o5dp zcDiH6#H)R_4lVKFQu4p(!vQCMlNr zJ%FP6zu?d99Yida4zdz0@=N|3UxYekD~1LbzK3Gbi^{5!M(Hau;FPsts>FFNRac`; zsz5p)AmBQc3X;(e0g~5E&9=I~r!nd_E>)Bv2so4nyeEMeDyBGY#Gx>pm88g)`R1z( z{5=YE+tnebwz=iLR`~Qjl_{&ze6O|q*^(g{920xz0Ab(y9)~e6JIKx9qz7yK`lyyE zp;b^mWn*a@K)w^v%Z35~Mp~p{>LD3Yyc+?OSK>aGVkqS;mO9-8V`{Y`t|?uAxwA7N zZxZ_3q6SUkMee*oB)MhY6>D_)w%`hTuM*|OQO}D9*iV=L;KuMkB0fbfZJtawF?L=c zRubj1WWn1>WFYhrgCn{qr3j+T+mlp04!JuqI3AV%R<9w?cXD#3TBzcP$lLU;-Z=y2 z68NP1&po#DHi` zHsX$bd?BcC$J{a^8n>2X85gB`pnuFjxq8qfD)~w|Gp~Mw@5UHYRgi{MnsO&a3Q-uK zj|=}a$N=#*>UQp?6uIhTh%fXVG=Ps9_-oE`*Ki@WESL|_6XCPa1Zy8CDr-SUi;`rYu9ewblq%`cRfNdB}N_^#ye%*@M+B|*Cb)t zERQw(X&m8J)e8AeEOqj=i~bOODOlLEWRlg#pLli(S7A4Z9C{bK8I}CYz^k8nZnvQy z#>PYAjEoaOEjIK?jM@) zh4dzjzi~xKDPXtYW=E?x|0%j!Js&RP+`QYiv#AEh`Mg7~nkt>}PWPo(rgeCjiZi(_ zdns$T?C~Ah_?xX(HyL?|T6p+nx!taSD9ZtU<4-FGtM=OnuC=*@U^`+3>UVIGgt?RH z$N0|lSVw*<=*&)gLqikl9`!?@Az>TXJTpI-X1r(Qhy>vR9jJKn&s%>T8~tf>*;Ya6Y~;Bo*`Y1S~p=TTrY zCD;bKnLN)ExcZ7&P}14xs~*u9}q8d4bPbv7b_1PRWhAl%_1TBV5;{kLvG8)>20 zz?x~Xs7qVVu$tqqq{mZTfgXpEmq+z(??THmrke{+&BR(jhg)3&>=ld z)f3Gh0Lqj2WbY3h5p7Q)l`Kgv>nO#TM7#40)EzyzNN!3SViF(}%%YuN`-EA=T_(#Faah~J#298r!q#OO;X zAo6cD)2`UgW}FrrQ6I42ZR&>*c(I1O&Z~4q<~mBLRaxDmuDH@JvuiOr>IU)mOeOh_ zQXLyaCasc%Ot>uU`l_9BiOo4$c3;>bN;l6LW9NSdtcG8=8poueEivs8PxDs43nFAVYT z=T@)B4IZb{O+HG~#7)xirfCu0l1XOR!Q%!lMXjzdkcK@wje^jNbTq(vADNp(7HEyp z&dQT!SJkH7&dr$oiHD z^qJ5Cok^;|Mv9V)U(2i>q7mi+y&%QimRwd^VmLje0JX&6bpbfBwNasO?gcOqELha2 z{tM!>?29#iBqqVZ6urwxN}ugk5!s%0T*#%KbO9Fs6EdBj zVm2#{gKzrpA3y3VGt{T<+ixJORRy}6r*sG#Lu8UTd?F;|)G$c&ws^PA~^aRt! zC}(*|+zqn7%atl?%ao+I6BGH-%+Twj#4N=T+>&Vfi!@)8nQ#nZZ3Ho@N4IP;?lR^r zyUnf*wz4c%G>DA;l|41ul?4ShM??~HQu)g)JGfRN7)s2Ym}@`}+mVn9K!-~$F7LK)8m}4E zzUX`lo$I2k3Z_)XGtQ9oCEA#76_04CbxJaMb37|6qKvuCH7&l_M)Cdy6Qq^icw6p& z;(y+7c751?WJGV4Ex^9u>2s4$fSrjF5;z0l6h z`;(co9wvI7-lK}2ND*_wBHzzO>+SdO%iYxDse0LPRkSsLp78h;Nc@SYZi1UFZ)Y_0 zDi5R&$zte;7%U88x|3D7E61pZ%t*{T$iq*es!T-Qc8nT8+fQ zU`y+M%hAgQEZgV+(kGwLG{Oz-RSb8X+?k?WA|)UA$`vef(2ue#*$%t>4Zn=<27BXW#-Y1#P+^Hpr|L~ zIjFHs>Ua9Zn(`TYKCC_4QaQ;1Estq&RiXoMFQWFTKVenY++3c6)fde4_FWFD08gfm z3P03bU3+p-Ue|i}$?zGyCIeG%@*ipIq!(r?ma=Tm`sgtZaXntj`*Cn7KSnGJ&FD+K z7m?9tjF5pI0cu4_+`LnYxz3MCgiynmSHIp_+jqu^gmeo6t9qQH6!J#l!aN>i63Mc{ zLY4CCRHqgn#H?j0K51j7^k0o*|NXUpiZ3iS>*C|z8iymXH2*9&&(4nYy&Da`9|Efj zZigg?F|HD3P8Pl#0CAP5*>)ZT@=W#Y`}2@BiezSV?iv3z#L1zfou6l##%0_=*y-XM z;rPw`eO8735eG}xZ2E%NV@1s+UtOS4dCzQ`@ELL32Grq=CnNV3)Q&K3<7vc-h1JLb zLUsNY6jIYKkJVNkYX#;jT_-A|hqhZEJHC<8!lbc8Za!Df@(?fI3rmYdm!5x#)BcP0 zTr`mAI1Dh?_}v)L_^j4xy*Ko+Bd`ez?0gb~uHX0A$sHY*ejx=Hxj3qRj6yors6WV_ zUbQh+?EqQIwttQ6L-UBJ{nQPL_N~diY{$Ho6#KS)t@}AFunZ_;5kH_5=}$wFRflL9 zc61X{tqmcKD3_$x%>GbXEQb7!8IDcyNvun~0r7NAcl{;!w=%XisSLJEKk=*SoS2qY z+9)W$Ziv?n>OvOX0h#vwWc%@Z*BOQOHH^1%6C4;9sHIy?!N!3kQaZ;{E3F?-nv&bD zUW9&}z$Aj8X;ZQuiX_T<^&E)4EEQ+S|Cwrb4i+Yh(!l&2x_zorw(sLx^+*Iby=M=Y7_xq7+WceGWDFRgE2b$-*@ z%NND0Zd^-rIrG{6GpT{(PWr7x>Qfy}h-$O$IrTA>D*Wf8;hO~)55D_g6hDse=X0*P ztyWY%XNk&!4!nfPcB$yq&@}TEByM((ajWX1Cj0`8OuP5j;8Vh8jv!5)InuYvwkVqvj(S@NM%@S6!=O>K<2d7qc^Wl^1X+qHtwlw{ z_H#A4K_xZO5}>M|&YSIs(`g7na4lg*)4_Nc1Qy{NQ@xT;D{IB=*(Z|!5ClgxTtr7C-2 zemc#4)D(}4{$8=%ZvUXf8$eL!nnv%gW3N@G{%w9Zc?1V3fjC1S6gkm#G@9|?4Ws^> z6gEBmwjYj9wN@rA3X(zVhId;;WVdffuPX}xoR>#OLu8cy#0emHAp>x$b$*cSaOV@R zRcKA4O`RNiD3Y!5sF{wm2)K#P?^2LAtt!RXN8;628eg~`BD@SA=qoWrJ4&)(kW_ri zX>M%JX|RYwyk@!_sV7-7Xrta-fbqE7i2Ox`p?rRL7iciXh4bX~!^5fH%*0sdpgrF2 zUl)cSzD%5-`@h>T`n2b8h;AvhT!tdJDb*G5&H~(6d3xL0Fg`y~zkc>NF=U4szw`Vb z{Qswz_`mCemz-LkpjXxc`mZg%Epr$nm6)=|(m_Tmd7|IW$YScC0`8*^0|ds5;hCGMs%FMYQcxJ@U{sS-l&IbNDT)QRE#H^~OR66K|)k!vUAK_sGvZA7jQIcfsJKQ@UFj+8jEd?f9A`(tn z{gcHA)&Jf`^Iv^uhXhtOG*vY@R4l@G=7j8j`XEFLr|PLVRPrSYECpA%B?e)*h@dSZ zU`H5#<}5XKogP>+L_J9rXQ;Q5vh7jLlr5a3E=PcR@bumhMf*j+b|85N9$8>^-i7TX zf~>4PkH8i$=X$#$qAyBUbgn1(J$;J*85;0D4CbU6{}dYQatjxxLWOAF9NQG$=+ z%82pZ5fHeN)?N$g-jUr{us@O}=>UVs1g8jy{jNqiFu`?*KQ6OSwCC2Kx2e5dz<$Q! z>SD&A`E%>rq6k=2q?E{`ecad_g)(ObED$_~USPk+a5;b0uwU|lj}l*JvW8G}IE&^B z+M|)X^4tkG=h)J~@K{{Hh~tJat-^fI+8MK&{T%m2C^#>eBi)IyU>n zc6v=Y!ep?xj82i*@OZCrLB?}JcG6wKqzcywBEQ|yyqqyXgb!cFpm*PE(Yp&25HLrl ziDoI7oef9B!J%-%klpd7h<4lN@`iLVW=b3IrDG8vU+)lDTX@2OtZLk5p7~y4_U*u5&OMtxA?#k>`NJ~?dWB?CKLS5WwhhqL13PC;<}7LX5-%c z?ShGk30zIBPxA%Yk!zy{oo_PF68!{c?s8^7*iRGS6LyQ^9P+%D-FsKh85EWJj8c5_ zl_ce@%Xhp~eDp_{mWMzNe?F++u*C(KHKDt!DCx#aK>TS`+x0v4k!aI(qJ&c3M^rsC zl`-8Jz_I9%hcw9e)kj+s+X<1SG!7OFjm|&-mhp0%EzBpjb#~rJA#5^=w~}4uq^Lxx zn!vtas%r%8IUfw^BTsMMuCA_FVS#5ju{^uB&cA5VNQ)PbIqZKqTl*hQUb4O~xd;bN z`|`@?-p`59c3~Lc#FhYt+Y<=HU zVZ%x9uECl;O|LGdR9@^{SG_c7o^{y$JcykxyaBTGKl9>?-{3^B2%d;Op3`(>;(tFs z@A?+`xqXnco#kgLhD$SB?UJ44Y2@bJbjK{y))3oT(8*BQA2OwZJ1_9xI7?fpXFSdY z8NH8-kg0w`5JSFNG!#IWbjV0%Z|Xj2#l>N$Temd!$->u2TO$p7_vFy(*v7wHS%r>b zZJ=(vbV$qmvdmEq01P+mrdFc)MK-b7L?-6&IP*H+2!qPKxB$a%RV`|7Mc}L)AB?n| zOPhNrvDN5kRoEYJR46s=*e=%Xx0NbuvX)7`$PJ2u6ea3v|MDlxd1P=&JF+4Rs`X|6*+#~EvR`r={{G1;imzS$lE{_{m36@UVUjy|aJ|SC?XCuB589|$( z^2ZaDe@>`|kxh`8xu7}41o*a*QZB^pT z&fKY;c1{CYoVFL%`yJD8s8AUOW5SN+ zkrWwmv5jz+4WXN)Y3E=A7Z?Aki>vQWHcx*F@ZGE(m+P3NTIkWosRggb(aZ8EewW0XsB*PssQ?KVRYuf)IwMvh1L$^i_1p_uN(h$7ma&2RFv~jbxj^z;_+T?;DrV>; zLaadM0x{}qNTuHcwYboT^grzxXI7o%Vfd1zjd`UyvBDx}Cp71h0pt+83kk+or2y*qSV~f{PY#rc_oohL_LXPidI^8(l zTA+vAS{`ZSQ4!6`Fke_}gjIsp3b_C8K3=|_@45Wr`?+7_Z)+y>YpU66vYb|pR$0U6 z3E-crF>DmoKNuqIP7Sukz)vb}i_*I11w^s!Eq`GX*DBDgd)S*gAE%Y_z^4vwIx9&i z1hTPN;XJ2qkF2i+#T-=;oK8{)P)&w!+I8RnHCv4Do7d)~(hfbrLkME)Ppr2`; z8az2UK0bReauMWh$xhDZ|L&s~_Ml573vJ|?D)`AkV6I`0z-(P$y^J=SMWNs)ND#!9 zZ5^*W&EBmReXFN(_WpymN5{eMw|27eus6&l4)@TW1h;+ILSC1>&Rcimg3fVl66le7 zNe^RmlQGqk)pYNK`}_d^XSB(}68vnOn@v%3KR8E5wyY3L6SA#!Jpg$Y@Ac2M+A`0U zKEqM-f<_S}+qRyH&$G)j@XTxkk}W>*?+YCvJ{_HJ!WapR-D-4s05=CGKly{F%-eOk z2#x7H@8g|YmkGmcT+-NYi_{kbf$Uy_&Qv&lJja$O-C?iyBQUuqNfpD!5R%7T5;v0A zmtC6_f(f$c&x9N9P<%KtW24FZh#b;Mf(^>Ql&VeQCJXe-*r!o92+rR|YK!5{=Nj37 zEN(c?-~`LhuZ$D@r)`4QNjNTHnogFWd$z2sKx!M-{eODqw#2rfP875?C0FdBcAEhR;klh+-KEs-Mtz~-Hy z1x+usoAXObq_&<6Kq#v3dx%x$Z&y_XV0tko+Uv&X?SXktQa z6$9^Ml$A2ZFS297_JG$&pCT>M7|R~4RpHPbo~&Z9FoH1X+Kcxpyg7@^W5u}@VJp=! zR(>P_k^09of(1?jsi?Gp=}`g`W3VZMSkL*>=HP4-6L`|d5sd0`a3vBOSj4YzRlszMXa5Vj=}On~+iim8M?q%7M5{_rz1R};W-?-2()w}@L#FyjV@Cnk zhoo3JQ%jJ`D3P$vARVeQ8(~KkWNh;74)P%BIuC1%7JJxot8Fx95oT%SMnrM7%1``O z@SY6I(tO!`CYcTV9D@1QUo*n5+#Yf`7*-7K_ycF$Xf%B3^*t1~JA&__Wb!5l>BGbE z1BmSpfPK5xt1wkE(kC4cRlMMqPYR~OtK`g<3X6>?@595x;7kjQ%f=%2r%6f7eyHx& zA%vL3*q}Z}&^ZfIa9I!H*MDAMk;=#aUR}CZP^L>^_bLqLZUp;#$m9tQCNbCVfnV9g z2v7uc?(}Cnc}4~2JpS(PHu{UoJ9WQS>FgP5_{8=8rNG8N@lXDDZG68f$x~>9u^r&+eKgQMbDtW5m${ zxu}^Z*TsrAPPW7YEed1eASttaRdVA;a-A3Jz7>$RuQSfBDl0v_fX8!~xG4Y7xy+y5;0d%l8?H7*BYTWXe2rxH2M6`9(t4AFVKdWf309Y) z5iS`Au<1W>kW5wslp4_xy1Q}PPjJq8gYnY*%S!}6;06*yIk zZ!?pxe94MZ*eW%3heZX;;=VMj&%Fcntn%N&5b83LP@Sy}FOB%+h>;Z%MQ#9HnM)6I zhXdF!U+dG$4!Hq=Zzh}_?#u0aLHXjXCp%#Bbb_NBCn&*QjTcwRmH8bVl-8O6X`?8uuekW2>vX3Zwiv&5xl@-B)*&sBr zC194Ze%9Z)q6xQzOKV|GgL<^az3tXn5aDtF%KkP{@Ti>_vd^OVMITU+uxnVl^Idbx z0FIwtMft)(!<{Y*%dfzFl3Zu2A=NRSqT#sYua#k+U;hRu(3D#$4+7*(B=}iHm>7k> z`6$Uv_(`L^3dyv)k|lb#^z-)f+b-};+n3Dflk3|oiSuRINav&-tDfZYzFLv>p%QF< z78wbHY3??2^Si@}+L|T|J*C#Q2a8w9GP9)+rkQebpt>RafAJgl*Q@iCYZt-M zoX8z+)lq)0-*(EYtT)u;Q2UU~oznT6R_Ywba4o%CfwUF~_b3U{Hwa8_`RnEBC>r43 zt#vt@8aCv@{xI)-(z`H~Lv_atM20ONYfX=pS5$!e*YPQ`bq>9^(AA_khD^URx|TU8 zLAHApSZEiTS`qauBENuq6%4NRnjKAOeCodJVZv`_`3DEF7({7N_DEJGCF4Xelo(cW!CBf&UfmUnL9+a%t`6H~x|u8=rP@s`nnyIMq+$ zY#`s&j{xhmgLtIXnSCi>|1z>_Iah;puX*gAShtb+uo4$qZ|CzMH)NHn_|qC@FE=`Y z@=fJ?jkw!DH+a#e!F)5|h~3G1ke~-`mBz%Uopk2ItSW;N=?~)%X)X^^R!Lb1@0; zhMVT+6nKyx-G`K3(1y3>xm_Cnalgzu*7b^ffYO0dz;e2upUA#)kT_cZWL*PwZMA`= zr|+n~0Q6@=tN1a*CFx;hGJ<1F|F7H|LU8ZwylEmx^gg#q7J}oH??M1+c?1p9C`2y5(*Bq!AI) zr|h{kV3djkjpl{h9pqGrF0PMtAZ=`Am9(8xewfW~q`Os(st=8ZFy37b>u4EQ&g@HL#1K)mtwPlshpO~$(qAj}I zbo>-Ws{GRC14P3&pzzzY@3I_T{)qkRi*DB8W2`j+HHVh82hy9aPokN>l$Bo0!|7|D z^nP4~2nCi<1Ck{(&3P}~?p$<>z%Zv*Q!m(*2s2J`@pBj}&?ZXxuwh@EmsHVs*<+ti z)-xUa(iZ{;Y2Ouj0>=s9mdnJ4U}AdGdfU*F8Q18NRm99W$11$Ll9&NH@!thpZqCOA zRp*0)&8?E+&-EI<9lo6vElH+vIJEZcS0w&p-&fxeO^`e5yJs({N`!4pd%4qHqQnf) z`uyX1u|Cggu5v%%|1;aGyXb-skpTcy$N&OJ|0mhr%*58j(ZJcn`2WX0^I9owO0?|0 zqjo1%#$+Js?}XNGJ@_ZJp~0-Ojms?8Tq3o=Xj+d`k0ZER{(SPDI=3!)N{zS@94aHm zcYHp1JbSowb~g`qyp~Reo{Z_sbxiWHYR0&BZ*rKm&Q{ySjdrkd=x%NpzS%M1%CV8p zUfEi|;EAw5uXJ2Aj(Gf?^!**-Th%)C``p}JsXw2} z<>5Zr?jCimTo#V;X}so6@3MGiZ)oSk`X^V;Flq~ZG>5t4WowQJIQNY8;2u85&>tzS z?U#;fe_1-memYrcaz4#~wK2Q0yc&PH$+(`g^SU5RZs27IGu0Evz*@u&l7TU^_7s4~ z;&>_I^ylyL+79}K@n^zjjf2=^1mlxFc$%!f`xLR9W0)Q z*jg9`D=eWv+{0~3fRUa(PS(K5zHVc9X6|H__w$Fy!dwB^!78WnpICc=8EFT$G+b4Hnc} zx2dL=d0Ky@+j2}9OPHf z;(3W}^)>6#Ie%VX#b%|etH%O}Cp}l&+A%FAZZy5JK0NL5_xX}0S+;w^@{D3hj-Z%d7 zGqxKsQbV}v3+?aSi#D!y9k4Iw7Z=%UI~Gm7EVEcS@K* z7k3b@DOmbqhMpO#XR!XHvGO;5yr+>J(0>H+IcEy_g!`D~fxfb@j!}n$dPByB*f8Lt zVOQ^vZ+ZwsiB>_vPOaPZGCuLbOhsQ})%KQp%W9Qi3UNvgg+(^8-?DVZ#S=~+*url;bXzS*D{~gU(J-a8r?{&`N z-Qyc;Sp3}5@&Y%Ko}}Q0DgFCVM9C4I)WF!1bEI+NSiPb5Gv@ z_fNIHvLIe~I^@c8)gtEVSXe~Npl$ewKf%ojrTY-VxAGY)GZJ4-BmSkvwlqps-#%c0 zSC6>idIKD6y)s^^#LV??XZptS^NwbkF?zl|IZP?)!aDiu#e52+m-l*?T0#=l(W1*L zA6o1}96=%E2S8u;x8GG6fX)jjZ^WnJm4}g}(wnLm8(23`Qm!v!CpKE( z+km1P*>NS2zF%=KH!b^z_Jh?3sEepItPLQRCmT{8kcXCJj43)GY6?6*=GF)JYpqDZ z?S>=NKhi#r18WcxAu_}u33hZY`&475sXb7F5ljHfG$Y~K70da5K0#w|BP*r(_H89|p=ysBi9%JSM z-2BZ6_D4$Jr`wZ@n%UsY`YJdeumI$G=1z7fD=(xB3mUIQuTLK~Y<9vJD|^|*c+2c(cNJq;?ve@ctNckw21 zb>7>!i0_|{M?R4VfCE0k0>T{9@KNs?HRb3sAzOshy_uihfNBo#tP7-)upXaS`FHsz zyXMOAsImorN@)y23+h9^HgE-DuL`+k*O{T{_y_Po6(0_r%o{dfRtpel1o&?0?Fp44 z;P;|FU-!$LS03LIS_KN0JiXJ9U{8S4(oTl+ORX8l@1gQZ#D_z(ZNZ#lTnGg`0DQvf z37Il(mn1y#BdEEJA9K)VP5qsFg+MaOs_+M^CTLSwAwMdu1sKD2Hy5MOm&!8hyW(=) zsJF@Hj7|WVRQ+}R;pw(Nl{v35@J`^R*v$L#5Ex;Qn>V8<0R&h1?=cy5XAr9Ky^M0D z4EAo!&(fiaEe@VP3I)$aQ3W9j%vrn7iKt~ScAk7y&k?K9)#EH|UytH;+pbv_D2`mg+7cO#g%RVIuP90)T!NKs>DBZ$3J{aaI0r>n>HV;bVt+yy1ca z_%>-I;6M94)0YSP|6=VNq6CSyESk1$Ta~tL+qP}nwry8BD{b4hZFLTMt?u9Bp2aL? z@$S24$JuObJwQrz)&CH4voG;(o?@DycH3OjHPqQ%1F^V?F9f~iN7HB=ca)&N#xf8M zG_rd@1pE&Yi3ENAjmP5PfX{qD*g`{TwjIfGhD&3tE_?m^@^8AYc{1~}8k8-f@hw~;k?%dpWMAg#%xQtDHtYNg;m2(>}nYBa)%@XO0C+=LC``zj{k}*1jT_x zZ*VR{-jpN`_Wghj8z^*jo^fR!{;2ZeEC=MYh?OV`n#!J?3qvru(MhSnvVn$pO1`{U zH5y>L>k8`ql4vzQF)Ta~rNV1^jYHIRDL&#IQSj2Ay6=Yf-~_%@Q~vQ0zKY>@v3qRvmWOp9gSH`O+6LK1*V^M%u7?@DRaPa2^Gz zS%~K!?Q2GZslvyr1rHj_oB~uLCcws5J--i zh^qGSmU?Fo=KYrZu(W3)Y$qV^qu~F9>;tG*HCliSOtfpQYQ|{qNJVBH z_>8DgG7IDi96dULe4X_77h7hFPU9S2gqeGkyhyLX@`+`;VhWru{1|EiY~VXi2TKxaV7LbC)J^jS!_1_23EmLr<5 zDQDIx_TC{UZnE=45a-?s3S+Gi`v7DEK!k>{b>^H0g(oM*e)F)}C|ZCTv=u_A>FbW- z?VlR&^ip3|+GKxmu!o73tDaq^eiO2ykX1=YD1miEAcR{eLrB&~iSp;S^YH^_c+DZ@ z<_>8kFy`N8I2}b^0Xobgl7wfIIU@kW;;BUu?EpatMF9dOEX7iUEhC;LBpGx~5J9Ac zX%|)JnI2sR_w^QGb<>BlkO>M&kG1=~bwt%I+Xmis;K>m3qpPjNNkf*>zN)x9`N z4gqJy-k)@K^d`(DeM^6wL3(v%3r6nK?+dR5a(E&M+aCo!(c{9hr=-iKw~gVga~)sW z7;YQ5}dl68{ zR)go>AD?bBtcx17K(VYwp8AP68JIUon%P;*>4 zvVyRRcY3rRfVBlk%0Ka(>vYC*K;?Ynf&AibbpdDH|LBU0VsH^FTN0s{erK~4d%025 z05{Q(Sa)W<)O+2j<+I^?8bIm0iUa>z0Y}ZwI}|5Vf_r&;^cRzZh0I#A`>P^sM1r&1 z^P+2|Qm=829^axGqn84Xhz7EA>iejN_X1|6>% z8D^c5+nf!fS<8J^m)^YYHvdb1)^|?;ye~hfKL{>JAS?uYDNx{Ve^6|ofS5(lvY|w9 zodug z*pE-Go2OBa-%ZDMt)43t!Za)aji3-s5wZ6Y_JdpZohKAKGl1%i)YtxS80w%Jj};Fs zt`xh+8F+qQ`=En%FG|4MK9Q=1gd$0^%w)w<(%Wlm``%WP?Vxh#3VOJ`5?%ot#clyg z@;=E{+&T-LI%B2VX^+H+3%4&Mn99o@Fk_OnG|{P)2V3D872b9(5g))Wg3skKtNzjq zL}$wQwCvz%?}C?i3^<`EF+_o{D9_yBF}rc3X(<hx2UOSXbET@DF6h_du+hDC{@tNwp_}|b}5H4lg6pc#W-MpuO6f|=3Gz|irH|8rI;|5zSn&p7K zOyzRqkd%>JN^~=01`1ZM3AU~I!->@m_*_JO1U|7EbP~%?bvy1w*_Occ?eKwKqPHg; zrDCJzYgk+-mS4CyPMi>ho6Y8l!4y{A{pesK!$S}{wd`rfC#KeD*f{)D)$G;E*jgOM zCjmPN=MQWVC&Vtz!e=~eGhce@Hu>oO8 zpm6rcvwHC!J~av^7Y!eO@d*^Al7kU7}C1V99`@?><6KE*dSAA=j~*;5W!#4K(OM^TQ%1{$KB1s9Id) zD|Z9>;?(S)%w`be_gi9H!UZ!SF%$`ZENNI!H^)(i$1f;DHGzmq#oW1`)=59P3P*uF zz7%R$zLwx?vwSY#e;WIYFlG%vp{S;K_4hpalri@zOy?Ea4T5!4H7@G|vxAb>fbt6B zfQCI;2WRYkkv1Z$mJj(Mgz=}$PR{GqA2Dqj_J-FeSBhQOS_|Ui* zh+SgD<7Zb4zW0ki+?VMiai2kICtWSOp}3`nCPw%L<7!yZq*dIZwY5sd8b|Q$_4^7* zP*Gtg8;qTWZ9E`)&bzejNmpoD(#7E3vfix&J6FYWQ~0j#t=inry5ZnA4HJ2;(1s;I z>qo>+h+BEog`XC2d{-s~HT+P3P_Bh4wVLY;7Ean~nqUvF3y6N4n!$4leI!iE1||GqMnZ_g zA!nXP15r_?Wm*(nqcAky6ipy#g_KO`x8&{~^aZkICSh>j)emsENcOXhLBRMaLtx-% z;T3{XE0}-7$a;X(EGE%GT*vmTc#hZ<~}{IiI#b0QyzGy)9%?%7lZ0XwoO4GrVOZl&1}^ zI_wTS}FR+LPb7oI&&%GM`aFtS?;%kvan;h~F*7V39 zOgazK2B3VpLqKTP{Y;@>n+DHTfSm!YrKum2{Z{5sxk+50yl`vG;`5LtA}ig9DpbG# z9CDU^zMrFvAB0GLJ_$~QpYdzWi!(htf9RK2fw?*)z`sM9t9oRV64JecPa5!6G==Rk zB@?R!O)2j`q=>auoFKmz+3U5+m+!yFeLXxCI@DJ*_!0bAH~Ea>Bbe(sjFohudgXF+ zEo60c)^U7+`bv((O6E1zpG{#r= zD4?ClME^LfOF+-e!mV2{na-S+>Ss>GZ4)7cJXE%PFUKF;K;Z#oNG9Fz7kt1ed&s3S0hS*H;-*fiMjxP5-`h9GG95^MXhy64Liqy0KWl7O zr;Kh2;C9mWZir&E z2R-lal;e>IL-8+$Zg9Ux1y{=b!dpJvDVj#P>|*2iA{*%E?iyavppKxP)A*~RCh|Mn ztGcM%euyOTJN{sWaFM1@uNIxTEBO=`Ui)Q;?q8){@M>lF0s0Y1oTnA$QtYyTsu8eO zuQ*zMqG`m;oGhFlWam?T+hmPH+Wat1-FD{4-(x~ZwA_$IuSvPL<^i7&7)%=UcWT1n z_|6?xSgV4femo}_CxjS~>&jJ<>hWhXDt6l{OZ}5)HYxV>DNpqlFdr9x;*_U->z_$Z zIDg93ya&y_`21UEDZyp7M@k|SWyBju_O3aZGvU#s)YI1Xz77n%_6hP$I_q9B?dLm6 z@Adu555eMKgh%$Ws)yg1U^uI41h!g&mg`$7s!;5oc}ItQ&m0F(*Q4ofhvJqcTk*FqK=!v|omFobGO{R9;Zt-@i~LM`lLex|nX!EHWKA ztpW1%kt6u8l5b&VgEUd+iK&NxJ=A6&NtSk5t2PXOMlW~4sDB2}U}Ac1@LrM!Lilm1_ErvUI{?UzEGH==#P#Lgx(w~MJw$9j zlaie-k3xPV1NVTXB!wDng~aD8CyR>#R3o(@c9up&ME7&;S`sIARLGcmq)UT!LtUKK zB&K`~6^q7htTmeVNqzE^H5;4qvMw)YDAy!9m~}7{9#oj@m;j-aFt8iZaT{C5Gqwe% zQ7rP(&j0miQ%PEIpz4wu28`DsHK-7^^a|5>lfKC% ze)f;y7i3B73}mO0;~gGHfJ09r>pjP0_+@M|OeU|!f1SpEsdT)t&QDo?{faVmf;-(#xjFyVKUUp49>Pn>< z;%sDMO7tFbGZ1D(#h^$n#$Syd4wTz#9gp9RCXXH|o|jk=v$`H1-{_fqhCkNyRG@M| z4)|5Bf*;@M*}8eXMb2ExS)OT^e`gc(e#B!V>rnyc(LO3Yzs@($XU5C}!FQ>XTZP@a=W&;+n83&taeoOoQc-P#n=PoLWf&zY-+z zVjo>AClw+EcU{k%RK1F-4$1mPHJ20>ouj8^6~P^*?+0`(3JSjv&@>Q+hN$lK08LDQg^xp&+0Mahk$bl`)B>W)&AR-=!SKca6f| zEg>pR_oJ($R{3_^;(;#M{)1fDveh4sybLY8xc ze^q48>Qt1*b$6Y#_p3OQh{A@JG79IZTMyNSC;=Vd7%WhxE7?=%9aXY3%^V~fmXp@? ziVQ_Chc?PJNyW>&2`^5~D2z)?6(ojgia^m@lNosF9(t~bHE$&AoJewCHwyA^hiSg<5(LfF> z$THY;W@^a*w|rY4HOpTp6hE1(SbIGTwbc6?3B?u)#i~BFtN74u$WG2FR$ID8TI*^| z(NWzywiv0LA|sq2Xo>ArL-{}wtA+dvL4QZ-@4pgPgICF!>W^ESTCKSsJ(-o^Bbi;8OJytqMa*Yr!=QGe<}&iO zgez6~Q5`Y@vKMMITxb<9-pm!ioCj&zz_+}-+|r`{qKii62in8)o4Q>w&M@3u!-NTt z85ry|bzfPgsFbD}!N88xzYqHp>b^q=NIQe)1D~w);WSN5r!hSnd%jp7Tx^pWv7tRa zmZF^=oo0Bv3^QF^q?&kLF6#?DaQQRRf&j~S`-(m(A|C-)_)Eb8A)_Y)^y>}u-vW#B zZegp^BNU|5G5wQswgRZR?eQ0{(*~e80c&yR)c>&EKXo(0y#)~kaA`3jNG1r?+m343wd1Dp#I-2qLj zDNXf%_qK?`C0!0w-D3JU=_r5-0P&~3d9dYl5+kSaSe?O-n6U`Av6{lNC-RdZ1XBZ; z>C7R)i;)F{3%42tu40FPjW)7`!x`a6Nu0)hF5c`JdC0*N3)r|GSPOebi}@(?rMILoQLMI)yqY2#9;W+kOPRwkBE{ zb)^J9KBJgqPF%ZMOfv50+?AJKE9+H*)wnZ`r9ZgAJ}wf74{FGTHN4qKGNZJL{R0j} z^9bWZkY!B|PnNE+9pVUt1{l4@sg@c)nNT#Vv-@kwrF5?x`8cz=a^b z0iKlril_K0-&Ty&c;|cK)T`3{G2EC0Cb+Dmkt97p2n7e^xiXQ&3%E4$03wmW`6Xld zU+lbNea|Y(JS`ldbi4Mh&F z4EiR%aqW3hL;)9F<{LfdQ{QPfcDRReAVEN|ml3nUdy&ojp=S>~G~(rT`0K7AJdvtp zAa(m$p`MsA>k7ZDQarTu>{6e_*INKW#MCsaztfAdlO%mX*1U7z9@9tUU((Kl)i|;a z=;k}-^iSwV;x6lvl07v-WE*!oglaYu)&gP++-eVsM`J^zoYe>VQk}4-?A`%J79s-|gAOGC820gi7(z zi1Y?x>-<5_g=`o;{n=PbSD>0i2Bzy`SQH4vppQ^LIStlFhWCp&)KL%V@uzRjnhEy&f7{JhZ*i z;n$%nyNn{?fyOpX>T#8ryQ+~wPt%|#vB2~%I$^AiIW zKES|B*)1^}WJB76vtsNuLD;{=*SU`U_V5;l$O7JJlZ?6U3Oi5E?SDX;n`+sO!?DqZ z{nxzFFSlpOy|WhW25s=#pCqt}2|=m>udm3>^Hrfh}b0AL+LSh zBBCsE<;)aHl8%65T%?W$?kN)P20Ky?Rq6q>=N)GdSS>WRfo{jf?}^w;PL!Z~ssH3j z_R{h=X#n_&Fs7m4EI0*&?rJcLjrOweVCez;Gby~o$zC|v2Hn+Ry{7f|@(gYV_%w^4 zhn|neo1pcN)i7#DYAzO&iMmDq6Ok#2ggQw6RyKSoVNXS)d5L!NG}sXKZO+-tL^!j5 z378}XDLe_(H?H3+r(obs-&l|%Mpcv$i+f5lpca((#0bj$xfsJ9(CZv03dD+WwF`)P zEQ`x2Iln^7T~8>-0u%i$?&i!(%NHJKA9@@fI}W+pGb=G%bBYMz*}0c@2rVo4*+`}? z;Jpiun^n^kmGvMR#~1N~T_cKJ>_-A2F2%_ffGjhF$>dOW6tIr7E|j&hv&$nT8KbwQ6EHyojNT6}#IR(I!e$HeaIM zA8m((8aAScMt8!Yd3a+rZIF4H;?dooGZU-`5tQw5c2r*|zrD{3muB@V-3j?&TdHmy zw}f|vbZ5Jc+m^X57bC>T)_r|F2u+#DzaLY2W>$N{zMg-si^UtK$Rd@pZ@;*Rn^P;G zt!h>nr2#YSkPs&4%~#-g-1qm9`r$(!Kba$wY>n*X9*d@YF7#c8v-SRys?a6Nxj!vu zCycV-S41O1(W~iq_6MRB4uO0~bl8dyv@~1>XX_pBQ`}BlABWxm6I8(YBy43=As@&i zGzlV6Iu6D1^+pA3&lLvI0ph}f5f z!Az6Va04bW?T&=eB@Dm{i{?OlwqOl{*I^Z5t|1BHesUuY=9@`xLKp-r6I^mLgldBc z-x>wO<4&cZ0+8a8EZMgS$nppvHY?Z=j1Cd@njk#!2$v#ekt)vW7~l!|;H}(-!9r!c zC5a>gD4XYlAwA^m&HAyJ#SY}FCq0Z0UN&9f{(`B?S;+VAl^e6`haMS!ctFXF5w&}c zk{fr5EXXab>CQM(U-z+;{tdMIB8C_Gqz)a~j1%=B0wY@w1{?q$E&WlnDS+uJysw7 zO4DI3YZB~h!oZG*j*cAtpn^F5-$GwA-zDsH&H~*ozy;Jv5mRQwS=hF{Itlt-G+#_M zFk|<2-*Me+ziiJfyl2;^GXK z5llH=V)H|Ai6UZNAN$=mkTogo3qr2a-tO;7JTNIBril7%T?WT(c<`GXg`GY?BalZ6 zdY5&Au09lS7;}eN2=(VgbFl(ITawzQLQXgF4nun~&oX@Q@E$DqcY0ikC&K3^K8kBM zY}nvp)>{sC$_8jzTg-v$?x=lKO`3HXbN%-^J?KXxph@Y((ZNf~&BRmake+Q2q$yb2 zxxXYkC?S13H_o??|1SE-mbT+o@Zxshb26B6ran$SK0dgol4P!h7YJK8xyBse5Pyv4;RNI__S(3CnVk{GIwL8oqjs~xOW<5#I1cr6Zty~ku zj$$OHm<;Mglyp7^OwpFEAp@?vJ_Aa!+BBX$V&#M-0(P#0e%4GeOgdV&N>|aEy2=e^mcEf>wV47q-?d3eU zdqF$XXl!VSnjuJ;dE(AN5CTEh`uQqkL|uOp3ksp!K=oy}BZaW}iLQIg8ve-MuqhUe zOJx{f00v6h^=9Y_9GWfSm-h1#n$^4|+JQcI9X{60){Vj5MsDKm1F<`@Clvv?hlXzhRPs9h@IbYX#4*r)Wdk3H{#XBn+X5J z5l+EDVHslukn+7Fyka(E12A5oLVy6v*X8^(B59lZv0RSYh$Tuc5W(NR<`R|-`S*mJ z$qAWN9b)7v#mU@3@C=^c0%5R+S@VVUj)+Rku`nESK0I+TNfA%6ZVAv%(v%#r%`wJE z64e3H@0AB;w!lD`5aduW-!@*@EVZ^q0SrM|tq0ws+5J&PBgMAeJvn#*c1!7y#fcrMDd)d*W=A$;T_u13o@t9W~E?yq!QmY$quzJtUDST_rw%}VA5r-SS zXvk7*Y*HISg&-xF!5XMoXAm+a2%95=0-MTn17>d|d>SG1B5ZMus%<*$BPb z`s`LmF!ZwCPG0Y=acxk0?eGl;^KMcmq&nGqKUZJ01x97wi}SNi`Th^8m9QuhQfL(u zyxgA(78n2=#J`2(65jh(v`6K!$9Ky!q;BIp1T85F(nt^m*brk=qRF;(;|oL@Hw;=s zyK9Mzp8cHZmvQq4rK5+wGS2SA5zq>M)laC?NWPrKejl5pXs9073(W6rC=Qn&P~(a3 zV{peSYOA5ZFbI|SMci%+?ZdihYsWJVyCFdnH5JggU9Xqx&4Cc*6O9|_jC!FM&v@UTaTB~_||l0DQR9c3kfi)Io8PsS@yOuER0EpNsQrN|JsRE1`vOAKN; z_zM^ru`qkJgs|(NzET za>vR%R-yIi>g(d--R7^YZ2Kgk<9qTJ(>pL={X<3)+C3N9-kLu*RFw^uIU2>dYUR1g!QX^w&j1hYd) zFIhq@As`-?U$Mgx>x7Q>C_{k>f$tlNq42E$@28MVA~}GTaA!{&6i2U+_%SpgP=a4w z#s5wM9U~wik&YH7qM>OMU*@uh6QIuDp{{Aq=*{PXK_}GI8B2c;mAfb!b^V@0KqxC{ z9Z&D_J>Y%GPx}k7s3wZ_XB2+2hW^BTIbL#SMlzBED2gayh~(pFlXE#lfho|>LTK*N zq{EZE$H^he5o=t%?yeO`Lh-hu++1PJFGNt+gb!Pruh4kwmKT!^#3XO}io`wo@QBgF znj&en5QQkhL&cTjgJ8@%I=y!C$vtKmiTbIu_4y^x7%wQXNcNs$M`skXmG8ncc9pkK zS=zDj48S&QZBDO?A*=d z^W&zJCHd(ptLBs)n)M|`uiq zLz&=C2y6_;;VtOF0Q3P5NaD#xnPLi@9GwI}QoU=;IYQcGZC3iaVwa3NZ*mF|+oqVU6k1 z0S`z^*bE3V2DGGqs!dpXGqHMz?Ywgm&efGpkj!XpM?QqtigK{ZPhYg%4OMvU^D>=v zlsZqTVj((hVz&rN&9Q!@+ScC{3N-}h?HE4+NjX8N2SXxs#MTs!X!gz$tV%|X?y(OJ zG_}%)?Nevo^PGXY3B=`z6TjaN;DR~wiqkvIwo*hZ+d&YhnB1P@2o&Q>EQO3+ZT)D% zfO%~TV1RdrLWH!8x+E8mocQ0K2_M7SJ!{-Hl5xwiTq;#^`Q%Z1!wk9eOz)Z)us*m_ zdnJ4Bbg^q&OR`BbXKqF(eT-wx+&b2t+CWO$p;?hL%Kf}?`T}nXDjMrLOH}gK;`_IC z>i{tfiwl&-*Bc=_PQ9$Vhp6phH(nco=-q(2p{*JnI^N8>w>9srZ6LTMvTVOg*gvq< zn-((z&n*}|rJgp0nO!ZNwNUAs9f;@+RMkmD1y@Ferg^sec7AN#gj?n1FyuADZFO;k zq#g?6R-MM?xFZVkb(oxLo#fEiN*>B+Mz_paj{2zdS`qwxMv5ubOJ z#HQr5^;%gpHW#9xx~3t2V>_V20+P-45ycdlmgmibn3YKMLauu_;+OeE-hcW)Hr0 z?AC-;oG3xlT!!1W8>>g{Mgmy*&l=$dw3pXIG1z&{-zdi(r0!WFGzwedCh`hsmnhU+ z`AV{C4>CU4=Tj-uE95m=Un{iMEIFUYW%!GF3euRBd($?&k&pG-aKCY#2W>bJe6|Tp zCDrK}K{$IglDEQK&~3e>7q%Xz0;n?w{yZ}lQ+{R<9($k zF_Vi{Cq29AdDD99=Uj%Z^}`GQX<=gs0{HRqW#~dbUaX2?yC+oyBU6|BLdHtwXO(EV z58aM*0COh&b!h~sT%HhUm|#b=SlEA)lSb?H+0?#FSX%@1+LiHRsIPha*OoBUXWjeP zaDi)koRCf`~o8$(SzyB*Bq#c^40 z;#S|5x)-F)90`v#8VGn74 zq!5yIOf3vM{@S0Vw{>ybXrc@X4Ar50LiSrxgBq=K=y~D%9SP8Cll5snkOLct2^;*0 zZ2`fyBp7gFIM=`(Q-aUiwpe`+xE^sb zile@b=(R_ip!$_=`=`L8F=m=5H(gdB{S_LiQOJTi!2OFX2B2(mQu@(gIrKc9Dkru) zKOuvK4rPzZCqlY)CoY5dM{e8jFPiGlj!<~!iUL~YGN)YXEgX;}N)e0eO-61%%Sha2 zm*Y63m7;TcYKqO_Nfr39{Y#aLapy3}6*Y;)k#9<)CUcJ=>tgvShJf|~2NhU>45|;? zir&9wk+&R=rFrsMA@1Si)JeMq zvo2^rW8dZOz9jpQGc`%A2Tr?(i;1-4x^;JWK?s4(-k&hRuee@!daOwrWBlQih4X!* zkTTBJV~0g8`@kB|eR1zMMT|P5LzY2OTBeGvZ7PD%K%h7rRE$`Pvm7WUpQiZB*QeQmpVH~4(sxMyBlcm4n7ThW6->;63k6V@Hd%StTuNQ%xTINpwcm}~`@I_BESE`i> z+*w8biv0VoXUmyZ*;IvCSk1I2tmVUd^2(Pz(91@I_kC+DOAOZ}>+;rsd8;fL$B!WR zQ9bqYR0J7YJoVH15=6W~&K~miC0ZD?YmT>k-4~I`IM;}-6G+MyKoq*$aKqDe68CT| zJg*i8*l?UQ?>%Mm-9H^|zD|L2jGd81p(Hf~(IBy2;6V;yjb=M~0fVm@#wNyrIH4g zqm^)l-)jKS9fOC(w@!*rWOh}Xvpz1?GL$Us*FJiWNq&9rnb}C zPe35wx{#;MY)uqsq~Yv2=0_`k%pQnV_3ze!4JVdw${-DPJ7{jay;S4=YYJFvVP)02%`hEszyNx65p{KRAL!f?*z8lkvlEkEb-piP!oQ~wL(QNl>`|S%W+mk6eI-A8HSisVKUV7E{Vkv^&I$ucGIdx{id`%| zmijJU+`*+CZOeEfKQ~5+1-)|dw995;n45)0>r=xDld`tckaJ{W=t+bT(?|e}R)c%M z5&cIIf^1;s@^HhLvHJ#=6WES=HN5nIT_dq|J%Xbgh`ik6m883fpTO zi9W81QRUhr*_Ng1Oop$UcsuBnr2WeXm{WPLOrPF3&j~9E_$ROrOjab<<)jcrU_J@k z9IkI@K9=p24Xrb4xZe1RPnFI$8N9Pf&Rki8pAW4OAR@Gj;-equ>JEAh4YQt${KL^Y zEL0BWDg^Cx8UDxSpMM``CA()>-OFTBw(CnHxp}(|4~UJ3x)ZYxX@g&JwwGcWhMK0Y zix&QQ4B}T7v0~&yrK9IoF8~-W<(%G|ZqZZwrka|_H+Kc zVgmaKbsv4WxyZ#XnWzX3ep^pjYI2?;5iWCg$$;CL<}Xw6h6dpGTBEyK9bFKG1|pZ| zNwX>S!4&1MsvO(CCfQkz`nvHYNa>UO4WI|uf;N1@Om_F;*Nf8kLlnOQbss12oV%t_ zpP;a8ozfQML*#oP-yOmXrLb*R7BcwvUM_#=?graCK&L2kLL>=SDdUViwkTFIstgMm z_+DABlud_~ZyTjfN791obd&rhNnL37%KDdOo4d&_O5qMs74Y<|5WTE3s5}U zW%H{SWZ#OFGxig@%PPFX-*&|8jzOcQ1Y2o*71X&i4?tGvi@D?kU`Thi0DC*)yqhj{ z8t;2Ez`FoXn{f3S$m6CI5FZXABRW2RP*YpqD*+Rijt>!?5P6mY9UIQRTLIHVEv-hb zcPL8BqrS02J^k!&q@dC`XtGScufw`ox4+6#x84h%=C<;CkY4P2s>KK4sXgX025Nd7hV3(h4$KWal(QuuJelJJOJ4yD~!sEk0EN6kQ9_#y7Ktp(hv~|U0k^-hVlJbHGAO50iy26 zi1(MKg72AsXVIo<-_H4A-Mqg!&@ZE5M=*~`|4wS|1fU`ITGHKS^DP0J?Nd zl9~`adr+&Mc!L=^=Dp{JV+9_@x3`;Jh0BFgvhVqA`XG12EfJB2m+ZdDG(pU!Hc@Se zXvI(u2dZ(E6yDC*k_Ii3mum_aANkW$gHBiSkKLh#fpiZJPeq3%RSPGVr}nv$7SnHp zU7M+T)*c*JsP4x94xACLBSDsyHx@H{^ZmSG$I-RKpt~)7b+$&9l9Xhcpp89@tWJ2g zfV7Qv>?CNXHK~x^A zkVioEE-gd|9YT?4nb%Rew=x0?Ol!#fJ3Pc>NTNwifR$N;(ui6g^}R;6Zn_i1+ODoE z)Arl2=WzHFipn?fZqP$B%brBG$WJMD5$4k)pwA%Oy0(BEcxxf_vYGwSLKu5;G?h++ zR%u1OnT_4!hG{cO1T9XepmefAb@$Y_M+OY!109S0#w(yU zr+75^?YD|pym=hfsqoVw@ede^AmBMu?JrCN7pdf=kpNRWRK;=44>Z|RJeRmPtGt&? z{3yS+q%T&Hx(+U&aT(?@5WgNC=RO=6Wy|q>hk|h@BLM4_#+9 z;q``r8=Or-tqrxdZ{+j&w3pCjSm+MTCM-UBIE`2%aimfF_YYJ$*bi|W-$c&+)96Pq zVyw11@#0};P>uX^Ku{oXx!#M3JMluo_*nm@W3ayz zV`V{G{p}1AJrlXx{_hZ1ZkBY z3A&c}*8KaSubr^_x{&8PgAQe81#gI+G!Um$V^Cmc_Rn|n&fB15nHm>bbk#c)SYa;0 zGBXr%5@LGnTb~dXpi^bYx%-KGNXdEsn4TF5LJ6Ydt{8ZVCoTizak`;azGLP1A%Iuq zL1;-g^IhI&(of}B%EhG2>Np1KPFXrE?bVveT~y2p((npF?@}dq%Y-lWb`yes<||%@ z9mj1SE2e;`L@^>0t-m5!Tn#ja4C5qpTfGD){uJF@T%0Fh&eN9P8(5xs9zm4?VZ(c1 zFz^v{*=jNXowxkCD$?!NKi=vspiY1cOrE!T!}|syQLB~zK7?p4?cpuT28}n_)osfQ zsR!qV)!*+0>H1d{4pACRlchh4=f?s({}XMGtCkQ#cyZaz#Feh{eJ= z$4rp0#uk<`WrMU<*WCs+6Z`nF{p-0&cf za9}g=cNZ3(!e(&B#ZTyIv=4G&ro{gwRsofwlsC<~J)&W~Il?9Q7YU!AEhu>IRUS5? ztq_$>7*!I9sF>D^(Co^q#&Ob4iYuwmECv;w zrX=RU%4dR1L&1@=snGiAxLG&{Xo{gH@m@-_q0KLe@tZ<@c5$8h#XCUuJ^_694^>j{ z%egOC*wXXQNv$P(0AdKa*~SmqK!m-^Zr^igy{38Kg3MBKv>^%|BJS73hpHQwhbn>ZQHhO+qQn0*tTuk zp4iF6HYc{7lXKtxr|#Q5x2qpk?}x9ux~r?cT6^uaI($ZM5mCOpI)BrQ;jMlZZn}1A z^r^U8=7a^IIJP_9c3opl^@epEpaIyV0p5Pu(^;t`u1=YUPNQBfWz>K@;*Jt)-n!bH z7>C(w$U9N|52_~$5AJ7p1fPsSkx1v?oLs!F#d~C)Ye8Fhx_?Vd8%6%*P=dqeuIJ7L z-1q6%%2BifWdXi|Kh6zmMS`iYz&P5tXJv$9Ae;~xPyYOvkMg4 z=YzO_=-crReb7QuqWT&(2Q_&*lgdqKVpP3upn0`tEs|3?H|O}$1~Q@!;TQFQ$UduX z!A{}OKE-<>nl=vr{e7?coT%e6QM`33B9Br{yXEB;@SpoPzs5<62ymX>eM2IBQlyL~ zI>|+ScKE;q64B~W!i&?&VP)dg9OYNxg?R_@uMrltec@3W> zl`mnF2R*!d2Jfkq~#Upya1liDpzVu7FqWVxXHR% z$sRi`s+medq6$2z)jl-XAy0HW$<=;#rv|{PM8qA-DwXl}ZBe!U&nE!1TziezQ9#%J zQBcahcB&|pT5Fmc*(JKxt3F-h341tc_JldxOTgLLuiFLQiOKx_hL_=YZT<4WI`m^VgH?`bagQ-s6dWGQN%8ii9jVu|qOC_aGF7aXd z`6bNLGX*Y7O~%SO%+1#!?&?A%<50C(rkz<^|IcvHXc%(UP^y{!lh{Xmm--PF2%9zB zO?C(puO;r~P(?cJ^49MDrFs1H76T*0D`LHgH$k*%V=}FwK+;ylCE}UE}ZS} z-MuL=lruOg7ylFT4}9GG=|SK#EQl9hT*6@e9eZUTudJFfIovZWr&V!WKtk=P*~Iy}bhB;N)@)CjZs+^ySvrDV+V1v z`0fezBa$2}XC0s;aq@gxjPqAC)emggWNdHRx?IUfYtdt0x}vE+&$zB~G&r~L&G+IM z6^78p%>N;CzlZ2)(Ipdjr8pK7*IcQVr&_M^1nR4@J3ePtMksS*B0IK>RGF7l25by&Qp?|>Ie^(GC z=E>1iXmtOdaI@q@_%+kP-bVB0fo;UO~JwR+K9(1U)W!-)Vfyb-CsDMkG&sld z-z9{fQcmzsNoDV+WY9j5RJKG)8M(HiLCY+d1ORl#Ik z;bc|8VqM{4WyNT1=M|wFo@NzPbzZIRtdAYEfNV&)% z92*D4Z_!PulG5JmAJ$rS#&Vgk?G|6+TgGt}iE^Ctu6Ge7B81+RROQqg^c~mwZu2^K zXrB1~KLTW0{Lqd1p@D#62!MdJ|9{Z~|EVqQ*7Q@@m_Ys%$TNnXvzrf1e$qeX1B*1p z1znc2&Asds@li9)CTn-Q7z5;&pSky10PIGk@&%*t?W`KNb241a0lw{P#W@^2tTN<< z68#%(ULP%Uwu$a|=E1%EIrQc(6NzHjke$#Zb7b5x!Ff>HyLsN36sV-PF_JF)*hhaD zbIAHvaw@{b&W?>6U0T9}cxCtT^f9cKyRVF0iaZX=P!}XTdu2!;p)+512G)$leX)<+ zU1=zF{vJzZy5n4LC*=OUo_F-jSqR(O@^d@klqyXiWPv|4p^KE{pQc31kaQRdUU^L* zAva1b+xr)INhpvj`O8SR@E~Q9@o9mlQ+i%&xnP5_x0E#Hn<6T^#J}=}8rC~?E+8WC zh&U&Ni*cS;&VB%j|8Rw05-7QfG%|66F_&2=DIUShTT&X?qmD7gZ@U^RUCCKZ8@*3} zRmYS|@E<>|`P!G+Paq*QzovZlp%EeXZ`c(v#1ZDR%!BbvtyxS_UrrROXCsmP`Vko` z$XR)G#@faZFx8`vR65!UK`yDlVcDS$1MW+_kAz*RNX~IF>^G%WQhjb%1T8^45x8tJ zVUNs^(J$G0tro(-tx1b{2%}so(+1?UVl362xspG?DDXd1S3hAks)iG^<6u+(#88yg zaLQsDUPG?LINFX02d>|dV}-W#Ah9&rFkHLJvE`b>>ZxduFYWHeormiZ+Z{)k!82vC zKITs`{CN7i1wx%Zo_pz|6!zBh8E@R zRsk&GWv_)Rd71g5mhjeM|FpPPa^+UUfoF=8ksL1q;EcU}7M36~xme%yR)M-rv$0Yo zt|Hhms|U=uo;u7pqYL2E;NdhYe|(75DdwK!MrZj#TRw_|L@~Ke>It70XXU)X8Ndat zrp3w-&#}L;j0o_R4REYS`&K=(@i?UjxJKgbAjqyxW*=o84zXNqH+-bJY&b1S?c2Rr z>-D5I$JmOQe5MwPJtcviRs&|jNLG?jGgB=%r%x7H?5g1M@`8voEB9Otob7a?wT5Gj zcra))U*oq=W?v%$+`>*%s;y+hV4hs-df=#qN`JKu$)q~*GRDElaQqIM3Y?Z(u^jX$ zoy3u?z(oRXA&JPz0pBR@id7%%AnBGlLbCc~NxEcsBEi>ff+Ud2^Hr|jv18R#b_xh9 zr)v%>bW7QP+9p5MnAW^wcM6=_=^>*R2xd((Bd)qaHIS;cL!CZK*mVuM7V9r8G<2dC zY=BM@Bd1XrJ1()`;K#?z-Saf@Y47TK4|roA1$ugPEq(tM$y+*QAaE?TG1N8ny1b5 z)3>aWlcFqVQVdhhbZ>io6@6rE2vPfjq4%oZ&?BFy>2&khnTYu``nsj%4hS7*YB8=% zvvA9vL*30QbU$&tm{*KiOkMUcfG96r_UnpR-qvtR|sD z<~uHtW}N8ADKA1Tmd=k!l;mGu+V}K~?-ZPPRoW=-MqlXwf}(*2M@xegb&Xs}$a;Yo zWX3*}C!uSlz)RQM}*jh6gr40nEa$c=%vV*LdxsD4gQ`E`ym49W|W(i45OhYZL z?_D(}2|A3mBD!z~rvxLQ6*(%-uF}X=XTWC!xECSWuX~D00q- zS#tfz5A_=q0Aiay+N~cEvW>ES-MV+}TauBJkoG0~a1>?cvDLfV^Xcql&PUN~4b)c= zYu=py$YCiYSDTZ*VT-+6|)9bF?9m-5nTR_4Ki^?y6JNOp81G z@}`(JA|=hCOIG|#%lx--AH@QY~js< z)QUF}QK){IMijyqWtOvBD$9p<>#s?xz7_OW#U;~{?k__nri-iw!62gQ5v_~xUzUx7 zKPjIg0&~MMv1pb&jDnQyOWBN2->T5%JVV!$F-n-Y!>!zGctiP{ z!XhAv(n`0h!6D(C{kTV_J>=*}4^xNjV!@Ja+b|tX!i?rS;@OV6RhhXQkWggYOgw1`)qgKGRgw10P_-eT-|efwp7(J-6oIdY?bx3 zvP+w|@^baap0Q03H`Cm3gxhs+D^zzZNn9n#0QI;~;XNaW?x&;wjaFy?32CcDS-k_S zY=%IWbEU&`?E%HEJ{HMagy`J&EkFd%rZD=GPa&JqZ7ms9*wQN{59j#48wZ^c-8(5+ zuwPA{l>;3&@rMCSbXw^k)f-DoRc(3z4_lgztkQ%HXg#&o!(`@bqke==>$$b9ie+O% zdE)8mx0g=Nh=e#-A0*)1Rk1?e1lI{n_ccJ|F&7mc_rTtF$fV<11|n}+)5ce; zq~-+o<0x(Bh3c?+!VoBr|It&6|MamQa9)<=W>Fo*XQ}4AA=5857IV#{+R%Kfvfhi# zpwO>ap?!S7|K}DjQHd8Xt>oD%bxBy&D;q&N+;8rrq&->ZV6$#ZAn9#~5~gKjMN~?c6}O>Perd@+2&mbS~Ne66C6vsLZKSoV_p6MaDn*(3sbF86{Ex9 zomsJ+JSj~WDUt%h97l6@Q7T3&;jTW@xt%K z7wji{JewX(+7)mN1JKpxgZv>6&Gr7GrBkQxCeX6x#Rpw|Z)q3qU7k%J^-OQ^pR4mU z!d>^8-_ene;~nkKF(a+v6zR|v*vGlwxnBhT*&js6AiFy>djDA?dmJCOvBt&j04&>f`U*D|$jB8gv6l3r-sPy* zLCvjg5gB=vQ{FaEfRnJIs_Oh-MVWN&+N$AH4_lDitu5ont+}uTH-X+6vD5lbwL+MpjlBHjm4e&gzyU_xbNGUQEVLJjNYp+VAbNeYZbq zZJhwbH-H!FdhMVf8#^?uIS;L)gzsn}jok**C)0Vy7vt<|5Z+V9`9kj%r6`q1o6Yk@ zYy>l_`5XE@t)FF>Bl6MfRrgj1g3%7_UK*G)IOuafz`h?_eq}@qn4VZlT@$%-Z{|HY z5ZJ{_xhZy|Wz`Wi*s*-}SBz5Y8sPdiwH{)^X>;~U6MGZ94ptCzLeU-2N!4OFI^EYC zmfD+J2WeZrDn<=bb{Q+!A&G&CSaDCQr1XwqT8Vl`aCaq#OwO5PO|~aKX4s;nL2zf?#;gWTS&A;0T$fC67_7 zjY*w9F$+gGQUhwV3Wi4nt%YEpkJ~7*`!oOni;tv5ds7WRf>zzcwCf#B88)hp7>=@g zchoUw7_)A5FVj)W^5U&m=fhqZ?;KA#<&vXjy<%`avgVPLvqE3#+1*d*wR@)4WS_ms zYV!ylsYSKo&E{3JdRevE%0JJA@=e|3 z^NY7qUp<=>*clBr?3AcRrwWY~A&Awq)4azja+~Zl2KvNNF|HN{e}UiNkL?$t5OR|g z7~J*}Wi{At-Sa~x!+F$(qKbFIB0@1X-Nt(W6ELp2Ddx_Nfu~T~|#%1@|HPBGgd zDEB$u{PO1Su);JIKB%l%Ip7cgqt^)>ttigl*#a@Lzi!|rxhK!$`EnS} ztd*MH_u7{i!VYIK=2gxeKL_2UhT7;P4bAmM?m`QY8NE%4Uu*mA1Nt|)?_}p%CoKn! z;gIL$~^Z1+3_NQ}1RG+Q!;%sSb1?TJ0l7C#d+T4z)TUYxoPtYW>bO zZYilM)p3sBd~sDTXV4tfFF`bqxsQJf;M9LH;$`CPz-f-U5`X;4=iplRBu`EPl7>V@ zOC!w2$p-}+#S=HTNX7E!JncbwSvKMb@Q|thmiRz<#VC#~2=|Nio4vI| zfDwzzDjfSV242L)haJ6eXh@{_H7rAoqJ|5Ap}f9{6#lpKX6`0V#2dw7qLn;{;M27b z2mLlC0n@DK?%y&L3JvuD64)RiV?}}<&5bvC27V4(sS4B*o0b@C$_|h))!I2T3UE0M z@N!{n>|0F-);* z$wi$1mI{@UR^~PvrYuv29}8Xp$0aX|yeoJ^;|+b93l{qFJoeO~eI_Mj7Os(`#(%?7 zqYG4p?s&<0lONrn8P4chmn%wi+yma4wD(E0LL$-NlMQlto?#aL$ zFdWcn;FdPE0A>C7$%4QE&sxI*O$~k`D72vmTCw5S-(TM zH81v=$tmG8DMDaposOzGm2~!H*u2015ad6Y!cRdP{*7EjmoS^~^G1d{RN~*Xs5B*P zD9{O?)%H@<)EU+tD8ia)s{!#tcImN`Y7N$CX<35uM4}h)C7>Ty(cr7bNYBariQz=P z##pRo->G-$Y(%Fjn%D)WDLC2 zS0*7NEu{IB7k@}EH3(=c-OG-k+u29HS#*32Wjgo*(U71J+;Le8S#+5<7U-=dQ}|kG zB1xHxSiC|Ny<_~s_+Vv#@>YJOV52(9X%jWt0a3M)TtB5-SF*Vnh{-)X3^r*biZ%4n z{p!e8&J89;U`e5cgkq5WTo~v|M+tRe1LN&1QwO3qipgS21S_0Z`?rXKZsZ+5(r*-^ z)jrjx20qX@B1iso#AZV?hSYROf<3ZGZOs9rl>$N*yfs-6rVRgy<(7O%(vC;fPDZ#8 zp@$BvBtq!@r0vx7KORh4h*=un*r9TVxwrAb;j3Sr2_UGy5`I zX)M)6X;BeL9sRLUI}BnqAv0=f!KV0{0g6`C2+2MB;xzy|2mX4TbTUs9)E}q0fG;ErH zGODRk7&Frto;HsOK}i(YxEkImP8u?BAL}O5MCPdW2H0Q)tS)7=+d@Z35Qw)`wSx^ZIOgw49cm|cG-98xq%ruuM{1fqiN3L& zHEQ#iIOo;x>c$-tBq%!QdN4k?S?F)l>qooJM+)OwU50#&fX4#@Ow|j5?|i>qogMz8 zxX-EY0NeCmI%A1LR4`rG8^?q^ucUpt^WJg8z|;0u4a7(fAY=mT!LCAtblSuiLz?Z(JDz$2E3 z^!{9-=URw0^@OTxIIpur_W+{{p|fGL^X*oA@+}t)&f(bE4P>&>u1OMuc_q;ZP*ENN zTJZ8smrqIhSr&wMq9>$;jQxp?LTIYP(X{K6JBl9oWJHPHp7(TJrdvayO^pK;ekB3rW5JL+ z6(fbHGkkVKvzvS?krrm3lLv3P(_?!&>Ps-rRLjdqsz4CK;aX_r zcWSsenhX!jR6JBm8D0F&T-VjQK!xQW_vLN)C~}1mDR$5fBwj_p1kpyK?LwQTqseD7 z1Z8^jDh)WaX8KrUz;N_vJ&`?&ob})VuGz?1hTJn^!H-1&8}aKxt1}o5lzQ@AK9;yQ ze^K51%ltQ==VJtsk>PX@Nl%y%N+s!HO6?y?qY)MT4La*Z8In@o2oYqVLcPG%E4PlO zQF+`lHoh?YiEZM9^*>&01e!L)2xL$|o#BB3i+od-sIW_k_e58Inumh&g7aXQC#eUq z_U{kQ2@X)x1Qd{1kII%%i(6?Z#*yoyIzmDwNc%b)3 z_a?i5aUGNb+PwIF(|Xsxq)RiZQj;|gRW38Y(qCUZ2NT4)S$$YjF4+0?YWGu?0^FstF;Jnl*cQ2Se*|Z_-LbW4+DROAupu<;^Gge2l4=IC)Tl zbcK|WCCGjCEvWsDuR=nVgu{i$ElZ~{su)nYRe{^&ah$p`38gcR2o}(wjoIl(^p?ya zG7%qS*AH!uWFnbN=EMR@X@Y)Lk94MDrPE%T)^5+Ktwy`wW=4^!NY&k5G^rMb^N5!~ zz8QKah4wB-<{W!ISP3+~VTiUcv28t8X*Te8MMG=>1m!@M z$DX+~;FaIlV65XYxnC1Cf z_?fq`oA5v=LNd){oulDQv@{!}lYqI+_>MzmY}LsTY)}el&~Q<2Bhr!;Ud0{X4 z)B2=KEGOcp`{TUnzOv`KUOIg%S8f?lw5POTz8#C!A`Qg7kuytNO(tqXjA@a4zut6w zyW4!I?H&eF7b$u4`eC5YG9^v|BvuyLPEp8h7T#S`XpkjCMy<9^+=|odwdC6T7n1EO z4)37f^>G*AhTg`oHS-Vos@cj=JC;@#z~twP;3%pSS6`+7+V@m}YbsHo0i`-4D4}sF zUr=a{7o*ZRl78+@Ipu!HLiz%2%= z$U&u=5k*X!-xC$*rpPKlhRqW8=i?*u!u zlfJ3=a`>P~mT)b+7B$9EMcwv-KKGL0D2)?tzR*jL!@aUqGTH zVq@5(h&q++o2hJFiIn;MFNQ-@tW0(9Jei|x`LLK=fnoj3JW92%Ed@HZ>8?!G>G9v+ zn-(neZ;O#D!bSOSkmL_DWDHIWQEKw(=+FFDSl8QwrU{^(qWQglJ2g^wC z#f}~3TEIIeDO&FTB*Fd$CA&l!_#NpU%)yQ`8 zWqX?TsQo>PdDJu@@`CjG`oq#Z!YIMb#zKnQk8i$WsHnZA>98njK!Ob{1!g=T{S8GU z3XG`cgK{DK{K}oERvSIDmo!7JdIsVa!}w2!<}I`8Z}Rc6;_S~!|uCF{`B zBG&g`M~_bNvYDUs`Tk{h?2}k`D@Rqynn5e;MFU+7`i6@BhF6gtJU-d^@^&MrHb5}$ z+&|eAvF#~!YOZb-m#RK}*z@Ko@KO3ha^bDy6XPPS5ju(3tWmW42%oyb(_YGxEk>RG ztUDH-HtpREVD>&^@?^d57xyfpT_~ioh7Nw)46y47;zb(twSP`MU*qELEX$BlGAevv zP<3%<{aSU&>`l)8T>ShTwt;UNy0GBu>a`_Ji#cqP_ zs`)gFdyRTd&s1J@F4wMY{{*uYW#e9MHhu~W0Breq1Y=F#G&Fi<{v?wNQSQ%Gl9;NE|ge}f$Y3(+?S;$@LOvdqmhU$dHO zvR)B8D?%WclkkFYXi8Jh6G&e&AfSIg7tMLw{%k>i7u4r@Y4NgemRzn0GUMs79W`jg z(_mKG8V!`QglhNDIv% zfm!R_@AWmDy{435|Ae&7kak*@tPO5Fy9u}ZCRgU1XHn>{ zH@jzMit|}~BvD5E=hHEB$1V40^^sMs=R>u*H7mpXs=3WQlnc(aWrGEW7IUomlv^u% zT2PK?%(qrhPI7k9;%Cvn-D4hDU&LRH_IPv_!jl=Z=UGrxjD$Z|qhgazbFRXPP}rihN@mR%WIn+IT^lvgsM^ zTO0bP{|_A%T{ST*r{-|$u;1oevN9=$NJMTHv+QB>?;H3(>2yrW(O@BDARr26ARy)c zZ94rwg(yqfHZJS3sbAA|CvK}uq<3U%8Qq2yDwvZ@E$qL6D6*t=ll@01(XGXi0jq6y zJI`EYT_ve~9g7#fnrA*H@tq2J=PvZh-SqJK_~9j)NhENt0pOA@20rq!u!gv-e2V zw@xn#Va}LlgK3o;7aS3T=5$07KcbF2?^=_KVZ!)f$u118&n29cFOfrCV`Thx@&35Z z{av@{Ln_9Rdv^&yh3d(P6fI@;NM`AjZv%HmFV#YpU-ni6whAL96>c+ zZKhc?GYK6;Wi{wHVy#)b04r<;%t^l9FUmJhSAv|9!NO|NiAnO8>5L{AEbF-tD4$83Vr6w4vn3 zNXqPWNyL7A+YPu*y7@jg-$e*36hPcM&#Iz7+4C3b;y8N~QE>IjsoJ==zwV|G6nS_f zA$DHszKX4PUVMHzxy&i_BdYxrIz|@Qu-K})Izb`un8SNKX^;ByFH+xZhA6T>eyZd{ zLxNoOvK)Zif0!Z>9LnKa7Ii%vg;1~_q>xL*^Y9Iba%-oW-dMSOj&Hbi zx$Kk7*$D8H`y)a&xY4v%&eMtay6@BLH*HPu7KE@BE5M7S@kvB;1vp`0IsO@nii1F- zgr~Xrya244p#i)|{21H2vE1If$!))outCb~F8D3 z6bZJkdwcIBz8qPvbO{IudXbKO?tq=H7XE2pig8NBf==i@^L%qHPu!2brM<3%?X>RE z9-KdwgOb6IrX8%q*cO_;cD*|q^2RJnVwD+*uj!CoXWLL2DuGYVlM(88U+V)~i%afb zl}K>WsjMF$?@3}ni+R**EJ%m&v8pf(^J<3968E8c@G4cLgFD6M0lf(pT~Z5jOC<=$ ztD=gutM{QoNzl2pz@Rb^T1>fz8mKsBfj`5(J47ki8z^oOhImgd)a+FYje2sD=aBD3 zA`fd;6;gd6QaQ&0LQ!tFE*4>xl+4n{Sz_BECPul79N*G*4qbDM=(cDrokRub22P0; zPR@f_8I`CDbpt)aCtx^>=tEx!Rh1VilA9hB31v#g+_+PcDWhVvo6J$T%6^so?l(cK zAxoA+%Fhr_X+nAza_*h^t4KWUPPi6f3ksS}X7bkHcVaoOlsY>x;o=J2FS}>5#G-;6 zJ%<#|#LRIYb2h)2()kN=z%s@Z5`&N?Fftl%?UWsgKlq?vkq~;>S56LqC+f&xhkKw1 zgGG3MRxghs*+Tp1jAuq=hSj5PhnNfswWmhHDVm%>C7TME-P{j!#N3wFKRsD*H);wOmkD_|2)2Fe`+37z*87M;nUu|eo<9*z@G;Y7qNn_frP}zs=sVDnbsi~P$hsH~>MWzBad9Dak zI4%IDiWe)e?3q(X5nM84xn5@wsA~7|L6e->02lg*W?b7o$P<<+7{ zhH))rfMfX*IW7_-3&XI7as^LlBlculr;+2rRuN9oy`Z88gwO`{6qZ56bA@T`R3)8? z)-tTkPO`5l#d+@Pw|}{7Eu%H~kt*$yoc|pAdKcV8yKz=>m$jt%i^*E$7v!(FVuvAx z4EpDB<-DkqLe{ZpWH(x2tgz8VD3x34%vBdgxbdxU(3bCXQX#;)GU31`Ys3+W1^LWS z&pNZzk5p4>M4k49ro4Sh_kCQ6l3w#2I+%Pzj%7HPv42Qr|K2Y;lmqpv1`3yI= z{{`q}0_s$owJJ@)>>D<b8d#`R z1U@oMOf;xhxcLm^x5?yd37#3&qTkH<5zRGVT(I#e@nQPsnB-Q-&F+dz7Ia1m@~&=f z0>Rd%nKFbfuZ&LVDW>JAfpvg2svE|#$9})HLwi7cH-xaEm`zmwsdp5N?+50h5MmA zu>m&Pw->EzIfC6L4i@G78Oprgx#We-nsvn$()TLRM(+sBa+4P&9UHyRO+LZ1P-k}Hhu zWIl5VC>n#b?C5vcFiBQge6zuSI!`u{DP1&c)8;^RC1EqQ%Uf(Uyp}7%aVHKL;)LAy zf`op#8zO$7g@x3#UbeP!VRQEVniz)P^;Bp+p<%pBSuHA;3XgsHL!pmGDy_@v_^S@Q zd0*jmoA^-2J-7qV8=w!eywG;2y0753FYwX=sqoNv{f1Czgky_DMn;9>_cYXN9lxay zl}>YB9N_=nr1Ht%a2uI>Dz%n7uG*(6vev@DKraKlN`IwEw#4DB-*0=)9Yo8o(%~K448^Cih zqc>-2Sbp@KlMA4 z3c5g}xMoz5-!AL8z)1*i@2o|Nt19d`lEH?OK0-yf>lZdC^^98Lf|y5Zp|4~%GINtb zjlN4L>qFEeg7<6AHUxR}2?s*iKRg{6oTHw}=8hXhv*fuv*8C`_^-oK8K7Q72WdqQ` zX{x2whaB#g3)8}EAgJ&1<2=ql>|c1T53>Q$J&@{Ea0+#_Xzf_at#Y7$S@NXjv@|C| zefmdDO`OXvl?E_d9J51&%x&naJmR839fHcsHn|)Ny;okM(vJD8`_}6X5s7ucpt!q- zT;4jo#w)sk8)R)(nrYQK;{_q$C`R&Hv*C9Uu~@1=X!4?0%RT2NRUZybE$rSl4?CNb zfeLv)ZR*l`_vK0x#H1dbgcj&+Dh6QZGc=Bb`hsN2^vQHQ zu{9SKv8Qio%k4`bjgq`~TMq$<$7DxPCG%$Pfg=H?=5?UCARPoXSW2YH*sZK|DWmHd z&aJ$;owrHM;)0;QOGAkQC4jpiv~qC`imBjCZ!pTpaqfk21%W3RbC$*i zHKuqLkYC52m6-J$ABa$Goy!*Qm_xq;>B%J08nky9UiJ$4kwDjT!d^hKkHOgDsEZ0= zEOXP2J``vC2{Aj$pEW0oeupgc}<%)$mpe>m&AB^5=u{86D_?#CWRFXXtE3W^;~-V zU$WI}?RagBLuEz_3hzWdYO?*rk{sVFwewgK+IU~mRnqEh0-0re9%>xe)b0*toy-+$ znT0wvliVyD;%#X=|XCMgSZX@IgoWQrO51jFl(U8MeCBkf{*9i|D^1Da=kR31{zV=>0EgZ zfB;sWweN!#@v1`Uw&M!4R5Y@GK{2oi?)iNe2U&6@<$z^j>0T2|bL|6+x(cV%*CH2V z#>|rL^4Hmy4>>zZUidg65x-taN}VwTjvR!r}d?? z;K%$pb>AOz$3*V*@Qr8;u5RU&Pf8m2>gnR|Y;G+90yk?BCVGhb;bcHf6;&DKU^H0=B6*lj6#W?=AV zxA5lbYAY?1#Hlo~0blyQOU+xnr+2l~-~i`9xFK!V_5%SWzr*qkbWKzy`Gn1~kj17Y z74ltNzIm;g+H~L>f>mq8Ri|envOzrKc!qzg1W(h9B8Q0)P`yLwrQX2vJ3Wj!GX_d; z(}(Sn^1-Q91u$_k5OI#7nZGUJ7iSYu=q4k!5hUoZtj9T2#(s z^g4>c{ktVMU&{9OS?{v_a(nv}Ei<~+1|!PIS5Bx|`?b9xGg_hd5a~15U;^s}H%bT&qU`FCdVDCfFZQEe!Q#ihp!8Nmia^f>Pn^-f5>xMe zKS=XIh7}$5)ssQIfAUd>S7j$vS{p-Eh_gyppHvEmZ&5$&=|9OeMU_rTKdZlm%1r_* zB>W7QeAF5YoUb_;wezz+zP`Ju>e3X?e_x*cQb4IE^uW(_j7+?Vp$PU0I#e*>WviOx z(k`tamU&jGuUB|G;dXWA98J!OSEaUw1?=oN51*y5r%Jsfw?S>`+)sQMdNP+{HyrbV zpQ@JTi8B#h$Uc>&v(!x${>;WnPPVxx_QWU+ky|0g+|(_Scwn#V$0I58)t@phZYTg8u&U<{(uVlW*$(>muj}1IcMpxzH95eA_Waa_AY4G0} z9h~5K1sm3v^K}iA@Q`16FQ0NJY!4eGpS6twJ(qJjT?fkGMrD;s#y{q`Ox*Uqz-R6| zP@n%p2x=U-$7c`-1e6mF0wnVP!d(4d?k}* zLk(C;jMK*0&##eY%`6zXvP|}xi@ccm=KS6Bqw2$oyWg<&M1#9KWgL_T0}xA|dh3*i zez*RCLRaEfX2CfeWX+_F|1;&@46*iSH$@Ihm!HP)@7g-P>CCFpo}UJTGlLaW+A)*)RZ%r3j|G^376UIY@cr-N=Acaf z;q>9e=lOznUBCk&FZW>@en;;?er6i!@7oubtA5$_lfoCW+xPvw*7FB1H(wNdoB#nH z2ruTY?RT;JDxZTy7zKm`#x;The=CVUQcm_0;@I5Ytr3Full%s&YlnsF8xi+aE}nOw z!1E3sKHk%pu!t|`Mb54xf&9$LqIll(jAs}GhQzzY+;LRXOxf`k&HA*XM1qSEx;W8cz55fb7qrZcd!qm+ym3S3(GBX1+W? zqywaJ>yRfOF3-D&z7T(0jg;Ok{H$PB@2|eQ{Q);-55C{Oze%c@^keZ>i-V$?u9&9r z6rFuf z59-gZJ1rR6H|r7TI@>Q?iH8vsem)D}?thf<%?`d6#3K}3?n(t)&nT3H@hQELjAaIjm$M(CYQ*6!L^-TYlH$kP zxtCHf*BFY5zlZe?L(PE72c@CDhFYu1az;~#HX-u61mKy5cN7~%Z1JCAr+;=1eQc72_o zaSjzciXT4@|D$83c>eO<;N$z?a~l|O!sA=T?-C)pEVKrgvyOc|giPPP_PJUi@m38U z$A_;$pqP!~;G%ayiy$Qa9*>q87+~+mJ}sDv@kEj2nmBWHso)$>W5v7{Mcg+!eu|VW zc)lUr(;@)U&(z&0kg>B<{P{|II|8D`Hhna0Xs{5#GyF(Hx|b$OvS9j=_~l*j@)Ra!oA7B0J|B2wFOw-#aA<_85`I}d- z|1J6o)PaQc`j4GIb&voQ^~e3=^MgL{qgJ%B5vf0-y|>Zpe}DZ)Z}X4$|MITe$3glL z{(tQc>9|O%8^QOWOpMmnJ`y#8s6ZZ1g8(x*0q%3&|9o-&sUNSQE)J? z{ywZL9Tq6guM<$LhU4)Ia}eQECGRiq310QT!8juhqRv_LF4}rYePFQj`^jZKh9mwp zAAco20HnZri`pU3mZo2ls}xlz%}2Igw$|22C%K{dz%F6$pJ|_Zx#2Cq{p9#ZAM%{f zKMnz0ondXWF7&zsEqQ*>P91!J!rH6F358S9zgl)h+=83FLFn)q&@O0=i|K$k4?!Nl z@qp>W_W}%IigicCQl<3jiiESBv4G6f+UyReQ=@?cuPOn%!9HvEfHHGzm0r=TG zy2(Lzx*XH?C8%b?pvZ|y56ej|0O5aKhb0vAG#TQSt#^NlzqZz+TNpJplSIN#??6if zMIQ`<>uhjMT55rqQo{h{--7CgIMwn11i(#BC_-^@2>UZGKx0fm{vd$-b_(BIXE)Ge z3Y*Sbs5!A9hQ-Ph7H~-_e+CpW&c4vT+>Fs8_?nCtsqpB19vv;9#duE2cRD4N7tmk8 zmZY?)xSlZ#N~i-6NyLn*v&Lj`PJhuv&Ir3E2AZ#g5w`$J z=<|)D=(nPue_2~2{(6?q7qe-3zR3XWg2gyNy9@9+O2B}LU;)GJZC(W~1_lAO9ZZj( z(QpDd5diPd7dw#};b5F5v!(-l&9fo*0N6ikaO>*=5Y+dt&;^%{6VbC_p@8joa9G2# zj*d=$?4uIf2VJed4|>kWlYU%@w${$tFFU-+(|a%_V4Xm_VEfSgHx&!nj0~$d6dmyd zR94i`NekUabrHd!d_TT8C#@AVWl|eKYlEMt@4oLod-lxYJDNucnh?tGg7mH|hw7Yas({FU%W8q!1Ndrh|kW zU-M0Xj!T$aW><@RQK0t)_hq^A4f5r(M7SKV{)C`009&{jpksI z={=E7%f|wU%G(^VKz1DN*i^fZXg~%%@59c{0}C!;2w_;{X7C{60MEU;0_8wJv8wPw zDPR_X$npVP4^f7vD!l^+T|_bL_hN!)6ZgSD;vM1@iX>8}qIOf;K~=pc%%keD zd)&6xw)gWdEA{L_2aqh0FT%`0zsx~tJ-nKN?yy&RcxgF}4sdvO?lgf)z(zvV6?Jqo z;r={V@IWhG0tx5crzyd)-<1V8?1MEpqEVnJYaEwcMCXepX+qiv9CLOgI*@`)2)U|- zDeqv|Cqltu0z-8XcnnzI#JupNiQ~ZOtf=xfgX656vYG?P9Q?!8{R)RPbld~yylsvM z3K}?jXa(`<(Z?G3B+W>fVIJ#foV4eD>i23iM_#1PG#fcHv&85@#k;pN$#O#E9X(R%My5pf+So=A3qR9 zWyM_+m%nXq&JfM}bL4QAI#3}pwT8sE5?Mh9va=>93f(~H^CzwVDh88oVt|7}K{qGP zIZNgb@v1>_`VY0{wlcb+HN01s`EVUgjDr|?{p3!eE_M*L2Yzf_ML+(@6CRFnsbaB$| zdmTbb63>?m9M>=6xyfiOGv|oB4a5p;I;)T!Mr z6BXVf_sov6K-_}nvp*en@5s#*_oBOY$ZfNwy-dpGlEdE5&@u6|Oq{is4^hw&)s>dj zfx|8i;4D?Pqy{!iuNJ^TZN(E6GMYRv z!GZ$4sz*5ySN+qBW5BxW`lsm z?M@2i`7{?bu;1u|g408cBrGKxNXFj7Bx4VRjgcLS%;XdFYvZziq2pin1QS9IEe9=V zhD9>saH;`%%G+wu@YVb_1*{FT5uHzclTH^huu@VUhwM<%C**6E*o#K_JZUL=d`@>g ziFE}ZO=#$uTpT2>^X_nNG#Fxo;;w3-!C;(|a?_GJ1Ke}c#2YHAsI>{U2BsBEM=Oy{ zP*~pH4sAPd7y_Ys0)g^&n9I9!*b3LhE|+K@4*&DGyG=HETjUy62Kv4%Pq>d!q1*p64qLAh0g4m_ZNgNjx+Mhpg2ZL{2fzlVNlX!{C+% ztTzrdjUSe}(ytJ@U##bHY?sZK$kLR=G zYck7{>AbZa{TD_eeo50CqPm-V(Pw}cWmg&AQkfCjdR%QA>%&ZgGGMdEFJnebJb>E#t*AvC!o>1@fNGeoLRKGUYTEaKg3y_u zKQPONgHM-cUObXDS>3ve(4<+r{ocQD-l6|K7?MU zANny4(~91{wOH>LYFY+zQ3vFr2FQ{vH?xBcHltYfM{M980Xl(+7yEik4y+@At7#Js z0tdtF4Hz$dv!~>4D*AXt`j=^cEF%bAxV{ptk7)%Y5_Rz*T9L1-)QL<-OA6=@6*M2 zd^6XQWeYyt-Hq1U(K`OLItnqat=VBjvjv4|;R3I+ugZf-+lMw?QrzSE(E*C8UlLs} zCJ8?uAni$+b>xH@;BJC|r}IhpQ}=VqJW$s@6ZJv^WDdr(j22^!SH4;;&S1y{4lQ~P zPGCAA)Kb_e&XpH0p#nLP)l6M1(OPB#4cD5Xc2HdBp!@DM z($TcsK-5@WTSS!>f87~f;^8YeDjc3xqv)7t;*o zY%-<|QcVrYnEl0gw}7G3tQ~yXKkuLQdWU)%VLpJmM> zuvMN2vC}A4vX0oQ84!>6WTpVz;WyN~e+-=iR*;u|R0+9UzBjR8DoQ`}9 zFXkCcX`JUbc$ErVY;iMAH|g+?vUEHw>|<19|DE>d(TVah^sw<~IHlQL*}GuA+dbJ+ z_IIHaojwiJ=EKE*7%c*2jF?{|em{X$p$Hwm8$OZgkqgNNsdSDti6#qmum)`-zrvto zAhGd%m2-jz=y3;^nb3!peP`GSEY{%})N;d}Z58j}j%I)j7g3In!@+d)B6{5r+Z!9D zTY;-|E+E{VEzJ%5W;R6ERpRZx9CU*7A<4!IzSw4OA=b(fHQa zZ?&`_+i%Oh3NoOWa-ytR$~;vK*Jc>NPH8-f4no%~ojzu-dGQ1kLuz3KdTI!$SaSWn zgp`_guhKCIHy;qE?TVeUkq)$?`3d$7(d;S|vZJqOd*~iA6QDu4Ggx`ZJ??cFMoc5M zUVt$kzj}ceMZ=Z?Lz6RBwYd)?((b414d%JFoeh!eF>UymyS9oWr3^u3hBp|`q8l0Q z2NindY_RNY^tLoM<4#7dmf^Pa7S&{##MZL9rEi;*MG+xc(}NGx%A!AzAY@{|ueYOh zb%9%ns^Gnt8R7p;EmGYd%okwN8>p<_v%{Pyz_^z(v0HvnajiEqypA$@lK2uu^I%mu zm4H6SQW3AAW+=veC_p&CP3dXWEjLdZCpkatCZh*rF@=g)QxHsS7NtmnmI~BSerWPb zQjj*B2?N2NWLDS{QJ2id8xmHvEX4b|im#;v_h?;REGplIID7F3N+6iwp#kM$_my`k z_pN30%Pmi-s17zNvsdVBNyTz>9%?sQQhsOIVHQ>_51?AU#1(+}a^xk75=M@p3533? zqUh;}#dj_*9_{y|^NrL$R1fgmnudA(^Y~8^=)p@h;2Y1MBxrPAEb&lP(#V*fH%kmid@U< zXW^ub5DJ-sNsEf*AqDwT*vD&$NHj)vJwYte?`>@c9IFP}xF8sF@|)&8@$Q5lWz>-BAOxhqO_Nqt^Z_hnjxUaCAljJm71 z9)102t@+^!bCs@Kx9=eeu2zQE95VEEV&2EzESVMxaaTz8WoNY;{%2sCG=)RF(_Wh=6thF&c~^KS=o+K+zWdD zxVe=t=Fgvl8a|5WtxdV!wq2zox?I;+BAd{D6G4&s#(LZsnR_Hl(Hc`{VF84D_GY^P$U?)VgL-V5Jv6GCVK zUpV^+lrFF6ua6P^?Ev>G+HhG+^HBOCo*=;l_{H1|~;mr;nC5~#4!K1v|TZR-+o<^v8*{Fff=JZ(&f@E>D2Q2l+(XE&5Q9_Jyw)Nu#2+?#+Qvx+D(iR2>R>*e~beQOrUiBg8J6 zA0H*ZD|wDOMm!BQ`t~*+Qky(V(PeypS|7}{KfMa1V)$wQeQR5Fb;5Hd6C3InWeN!zM*t zQHT*;1LEz?=OU|CHaR&_M#ZIO>JL!)UVw92`uH zCt!*NoR~z?Zcr+lwuo+h?RdSI&D9J0S$dPqQt?|UG)-wZaf7d$fC88B`t3%S_3(!> zM${vgs#luyo=-g$vhG8%@0uIRVm}baTqC$XWE%s3^B( zK7t;yUOl!Mp`7J{kL6AfbN*AZ!{THy9-HT6`k||Z&slPdmR>PQW^+zX!0sf@6jR8R zs62!rcum*znIY}fpL1!o5#2n+Id_it4PHn~NP%{1G(YFg@kTT}_-MP)4D5AdfE7o; z-$*#RkKai=;P!3`(0`)seD+k^X*S@Ab~Lb^XXz-WaMnw7NZ1=?BF$xI?C{ZfPVot< z=ceLqiXmohAT%+53bMC77(D1HJW3C04R1XGIckpO8tXiDfg_X659M}^e0<>NzFCVg89Q3Zm?3fnlMPsUfmNhHt zw-d2}q|%$Xxk$<4r$nY{z9{J32F7nBED3Bkn#tjsp@VFPe^=a@p0Z9}gHn%koB~fa zQk$RD3$#wDALv1oH+Dze59g-4)u~=)$0{Q7$_;l#|H9GitcpZ|6bB9jWzs8hp!A|J z$lS(7JcI&50@uHb71_#&UN z!KoJq8U@Uabml15FRIUp)Gt%m-Ik6#w&~D35>Mpx@>!VC`!^>-M}ndpQ`_JV*snZE zLG9GaE2cEowmeDZJTxloThkOqy$}r>%BG&`eL!MIDUL$()96CIO209+W(f1T!|Yp} zTC9&J=jUJSWQJkhPB;vzAoR_KrH3ee@ZCKHMd3nZFpePuG|*|Khp+l652shd^)bM< z0&|nyq`pqE*I-@(hN%8G{A?78i+jGXAZjxa;wlw8+o5ElwKTo(B`#e&Y@gXFrsYxG!I_H)^bWp1{dmc+~MU;n9NB4A=nDG98j zutLA&JAKV<=K(YKASO#=)kn!BxCj)PYqb{h7is6LvlzhV%c?ZLz0G&6GB4{2_355} zs!5^^NgAqkke+n1fmfqK9~$lSRfCtJ=r?z}Rdh0p+2nHgY$y@rCrHyK2?&2cSwQSKdx_bt zg-B4aC;5w3oX9N>+@JGYn%@+8og2>kM?hWO+);60#L^AtEGzK6ltDjL2GH0qOg=uk zBt)nC5R=k_+D~dDOfDHv9?+03#v{?Y@wE`P0?0C5HlpHn19Sztz0voe`=Ux+gThio zDGu}>YZ66MyK}|s&Y&*=6vZ3$d&_g(Qz{cX#P0k{cEfKH5DX8CjM`{f9$v%&&goFV z#sl5>m5I|8&wYlvHp~b^&tqr=bIMSQhKcEqcGk>_@j2IArMW>3Le#+GHQC8;6bcaT zTW2yDxQ_Q34Yew%*&DDbuQu;k~ zZtbxB@Y}e{6^_5P(yh?stmUd6B$pAz#y%ShWARzkx1 zc;(dQJGCdV)PCiYSm%liNm+eNtVbp3PjHkxMic!9H0C!_grjI%PpeiSylJZ*?r}8q zgh11u9^w-vc%~^|85(YB)aWwc75t>70iIQiU@7U|BBY}yB7$)(0S~QN5o`jwYu7W7|HQ2EfD#%~tVLG-GOKA}G9+iU(^LHJ!kSY1I-8NRGrEPVLE={q5L|0OYHbTut$s}JI>DfMwu(!va<_{g-PQqD| zjJivml=C@$BN=x-2R>8$2xR}85^`o*^-`|XE+FP^DB2et`}|u!R-gRLxc^F~EF)6}HuC7RbNXts?+p7C#Js_`ek+iAZGv)_f;@4{?} zFcY@1M3~u~UX=Q9?koQA(Q*w=UaeGXamU^MYReAOwyDGuiNAm)g-T{@2DE&bE$slc+-*)@7P;E^irZDD_DAm2mF9 z7M93C6Hu$BtIDXTBrdjCj{Q=7Dt?it&Vp4%y_zS2Trh=_zU{T$Zy5b3sW;j%T@a_~ z9=&{m#kQQl%3Bij{$q&XO9;+ULQiO&8jL|X|K5J;bfaYb=Okk@{2jg`T>2Q|wVem; zO)xIeelxj?9iW{brRdfE2zSxZcic17Xk)LXUI{&Lwso+pCLIV6Y%oRVG|Ib7mj!HK zS}|l4vHv+mHrN4v)_j;tyx-oYo`&sIJ%DQ*kSI@GOYw-|5+(d@e|A+DK(vC)D21cR zYEN(Cmi zU@@(l!qI%$6if@6!qNO8Q=pNhKDEhGwaaoQg}y^~S|68A>!UlZk54$Qy~=4FE#0sq zcf*bzv|$z4dRvXIrStme&g8m;7jD*o48d zxt)?2K&o}SC7dNeJ?Bi2DwCXT$|Qy{k0~fd6*MUe96j18uIYKC%F9X$k!d3-n|b8= zM=frr)!!3qyTt`mQxip);+yP4VgXMTqUF!@8ce5)!VtB45)h{UJWiihUi zVhXXB-rY(#-){w9z=UwskUA2R|NMDo0>3D59DRhZS{h=DLZ=m6lMJc< z*X(Zusn<$m{(AlJb zQn8_XS-DcVt3T}y)s%>xc2Q|@c>mxg;M~!ze~Hp@kviRNJS_(xF`0Gq3C!sETP!4j z2XuXBX-l<5rqwTN{%@sqIL`trXYaq6F(6H4S1Jp0n-!@kaO~3C78dT=(j=z^wl|3~ z%~>pc@Il`&8z>QG*HY9E{)SkM%JDVAN-29h3+g^f>i(N{ zL}n6hDVS=dFUTx9$S0SS7Ry?MRp?`u4i+=XD>a~|EV*xH`PU2|c&X(gES)xge|A;y z2$nDniB*yL{v?dU5TFn=C4hbOII`9IQg|eG-#|E8Li#Q|SEQ=n2zNgVo3bm+BE!i? z@O6x!Td?P^+R^$kUObV{8}yZN$`#H{S>g3^HM+*ysVXAptxwUN$!h%uCbcIIF9XUe z*|D5m9n>lD_?LDvipy|?lAcKStvoxN5|Iz#0SNGU>Mt2!ZK%YFT>lFcuB%xx?$ZFE z3`(g3%*7VB0@u1m*$$AtrB6xP?WV8HdpdvK;hxe@f=j5>^R}8Lt6Z|`!#x+*4D-d_ z&7!#OUnYYuA&Wx0Y!6NTZe?E7>_o$jIK(%3YBMUG;!Ci$X01Miy!Kin^mu32AdBW@ z-5UrCYsk;N*$O)^FVnCyzIn6d07!Hn$G(_oE6%zXHq)5NKg3L{x6=slQ<`ZGz)CBv zOKRwY>@*AhW9>8#)c+1UZMg~a&u^wRutk5fcA9MvO!JW4)WnigzCE_#D0D`YX$8X3 zsX?FdRO(dhxZkpowvyGMbbi`s-+sYKc*qW0S6-uE-`MjfRB7u48a6WZ9%-MUOCVsL zl_=ZVDJQ4GQ=4ZV&o}0oBehZq9XliLCI|}8-=7QR^`iQ3_yLX z?X<8$c__IU%TtOeL-2?TAkptI_j${a*YYiY@pF~ZdJ(jDF6^wNo~bFxx02fn*i8+G zsCAeQl6xv)jGymRT1r&X))2BK7bQY>G0*k=oxLc-6g29LRbX2LG=jcUam1cyNnNld zWh-dhIi&AY-)D(BAPem^Jf-EGt<<}bLM@HkA<(x05(#MDy}f0S@hmogTspEnIjk3o zm*|sPn?nZbf+#ph0lW`87$rRw_Ji>PFd9sdI{iqqR^gEIXr0|AGo)U63zweo*}K z1!wokMlaBVMI_aZj?aHMpr~f7Sye>02@%sJHXi7r?h1^)_04$+F*ZlC{MSFdde!Pk zGd-wIl+78nH`RsxGmB2{T05I6szTo-U_wm=1#4hMP6w+=sc4CZcn@KYQRy2U7yh+Hn_tEcf8d#U2-4Gni+JDA0V-E+;T zspGshQ!u(wn169IT?nVd#FU^y7DhR0%^bo-W)$<1@%IZe`!EYDH;j)T6h&Yaa}Y+R z7gyqA+~05%$^EJs*@Pc2sMYJQ-8T*vpS!DKURIvf%X?MGE|D^tcF|?wY92$w(lUyn z#cAiNLn)KRv}Mgi4ctR3WVYD@*B)T+r0)X)yPt7p*DLz5rD z8DI6X1}l%_4Pds(!hJh3$o6qJ#;V zLyoSU4jgBLdv;0h9n?)x_!(oZf~k44o-fQ2Ism`<0QOzIrdituIkv;AEd!%f$*=(r zrMtBHaTtoZK}+CA;^^8hMygv>EV4NzUqz~7BLH6pt=S30d%$Qn3$+!W&${pXA5PDX z_j|9YSixYH*D=(6x^V>3W9_fZTRFm3azmzfb6pXqg6FDtb^4gmo|gDSv^C9dx9WIq z{SJrOug*uE6lMY`zbjWp02PS6ZX*Og00y9*q1d(iRXEl#lmMq|}G3B|W0<+`$ zs7O;?DE8$`Z9Uu(^9$&+%)9+Nv%q-|AghM$ww28>W>PA1LZ5erIIdu7e@eObV!djS`^N#@u3xfmzTx8@=5hw0BK&N^vFO624w7x^5{BS_Pl0gdQ=(=5jn^#}$pf6XOrd9@^_R7n6 z;d0Z3sReC63dBjILsE(<$9aZi7~x5o+{|~-(o>o+@gt2J`nNvgwdP#1fdVX;e#Xg^ zALcp9=d3yCGSv7<$l>m9x72q8R*rWIg=rcN+ioQEYdNdsiT1N&OZ_Wl!P`$l^RNKp zHx0&5Kvk{LTc2^IYbBb20Wcd;by7?{Dg6?&WcMvoN1Xd>c1aIYOb5IjZOX(q@r2Jn zcLNI+jh+|U7XhPzRGJA6yHRQu4j;hH9cWq`|GP?MRsCL6_Q zoF{}rN*$nc6juc1)8#w9%EeyFSI)}F#nER;Y@FQO%<{WzBCh{go0wicMdsdS$02V1 zivsvcHp-w!dQ)U$I4Z8zNY&O-s@{)DWIiZh|d&GbZA-9hpMflT<_ZE(|cSEWdP z5L|SBT6&+5^EF4QN5>e`imuSWy;;n4ZCm|fO+esWp#sag*xd+BV#ijtVgBpR#81czLc3<>6t zn;9ZvOW2Oh?khY>;%bAQR-{X6Py>~Inq1tbSwFVAw7s>&FJ9|}TqQc7Wl1p}RYA$3 zZ3mJSx#GP2aMx;kSt{_Q$>k0+N#x_jTpY-vl3a3eAGJ3R#$Gs%z;tw0XJS!8$kvdm zkggke$alvOaV~YgKXniO?6ttBeXm*?7>e7r@~=4UvVugf^PwF#X>rXZT++|bQ)gv0 zdxsr(gH7>3O}1>=_AK3?23xdrlSCN}UqwVq%BMfD5)6N==$wk*?HVR8W*G+(>V)*^ zP-8$F0dmA8tHntI98s=l9md<&oL72Lggy<@$qH-%y2wBNVOYHSuoTtr_1V~{@1u1B zYc5uhhyD#?Bc>!qp~Vh~{(LU61QdLiOgn2H$Ur1KPx4bz94B}CmqizM*qspDfS@0u zwil_l<0N9P)4>WQ{;d!}w>gBQlJxkIikO-1&aZxXfXZ&LiDSY1y}_fm6(>Q+I&#-y?WS~{ zE+$x}us_ZwFdd86Zf_4^X7l3ptLS<3MxzmR#hR(?@r)tA<~7`|1hBG_eY(|`mSAX=QTJvf(T<)m)~fqHY5pYDb^+xg_h!q6>% zb^~TGYDZV;+>oOl^nU@tQT5uUH0P8iUxnguly6RSdk>;Ha`-WeswRM@gy|H9BjwRw zi*wJQxx6>$J*ilw>D?EU9^&|GPmz}I$SrQ$4Yv74mK%#(%YGwAAxlrH3F+ z7yJ~xsi1mN{zW8q@t4FuUgK2+Ut?_+(ZTcQcwLIEiuwIG)uB7QBwe0XJhS3BxDQtk zz2y)qxr~|MwJTl4q6&sk|wkDPP9+j zc0nymMXHIQ_@$KMiU0)9$1I(C_eKmWvZ;= z-WBi~Eacnfv&5W#37P3H?8JX{+y5lVEj`ETGNLtw;%Z%>Oa0wTe54OfuDR4r%3%hM zzWnxWq^>ylUx^pnj?~d4oQ~6`n9^f6y8?F^=3YFSv`X*noRtTXeR>JlNZ6P zd2wV<$@tYUux9@MKOzBY$u6wcmhjtZU5!mBnl#CrDmb9AmCikWs1AsKc*@;*CiYdq zTMw3!40UTMuOXZ+Ock;NXwPcXq?{RvSgCed~tPM4#&ZM7T0O1r&%xu zh4HG;e!)dh9a7)bXE)TXJhewYw}bvdYK@BC$fvoAk?|h0@*RFY`%;wCUDyP&e1(nF z7S+D2xFE=3I*L5d>FLOfMvQotVq6d>DB0B_CD=y$P4u|@MAZGEMiSqZKE_sl*YM%h zgIkBV9GNN5H>`J|T3dPokw%+TaHN`*XVlNm5XzAHln!+J9Tgoe4la1qw1T>%;x9s+ z-$bDVnSGYr%1E({)N)F2ySH`<34wb-vp;(6_8Ir%KDX4mG=@rAQ9y|ZMGb4Zb7Lo) zI%ms--z)~xk$vLDaZ4qg^?HW^!T;lRI(>f+XE+<+>FMS4-p6PG9E>a?KC#3I!ZMG# zoMt4Z`U(R1s)jrSYp$HKExCacpAI`~TJET8dAD&+t$|J6CbJ>G>L|%Vj?NrKy<9zi z;%TDCh~CX$dNa!7*e-Wwf1AW@Mkg0XM?N^~@;oC7FV zT25&zWIM|>HZ-%W>*6QL&R5Bjz3RJBIJ-0fSQYo8a81KoY8cO>9+Iv+Za5|O%`BgD zg!)=3XLar!WpP^ASx;aVz5E1rGj6#G1%3fj!>@Z0F2T1ysd!NR0u8Q!3@FkJ;O|1Jd#O>`Znp#PL59zYHZ;P$E@wi05oc-@ep5D)F>do9Rv(fbS2UxgOP zOZ)qJ^xT>@{IULbv)+eh<)GLf^;nh8i9LgFt7$!I4i$w+R?0r39|}v#h}D?khr|Co z?rxKzG0ch^?2GU9IQ?qT*WOJ^CNZDo!^J>(@X${qH{PRMr%_1M>(^OyxwzuXY4pC~ zGv7;;eCP`qmS5nT6_KZ-!j)pCROg53xh|F1B27V3sk)4%c!scSGKLa|?USeG0I>tR%FV9{+b`hZUbwDKA_b zkl%03F_c8P*+cS8sl0T2g{c^)m=Zwz=(z?U@&mi{^AXec-#t*!oBEpQAKMyr z`Ej+GXG`76QaYb!=tIXGos}0u(t^AmwnvU-I3Wc_^~T(G{M#yOjOp!=vijI)FaGQU3Y&(-I$L>t0iO69 zSg~F!sc+6AzOe?U$NF`ZxMkCLNT+}$mC z4XdJC@Q~uAlj%qfoa75#CTgx3hiHP95@-aG(gW2e4^aiJ zrB-W$o>VsqA?eHWS%R+xC2s?QMqgGAdp$}M*p-yB%bF4zq^RKo666m|;HM*f)u*1w zYPq3u9a!M7qd*a=4f}~daGSj~CQD#f<1zZ!dOYKwEe%bYM(6Oq*#R$HUE-oI3p|F8IX1>da;K|Va7zVBMirD zc^63hVb}wo=qx%~EjFIp!0h&CSDu~=8^bQeAntbM>v*dbOW)R>gHUN88_f7DeH(9C z_%@L0F|YfMOpjpRh7p#@P%KfiTI7Cskz2xym6VinP%F}mTb=c~NNa0j)uLr@Lo;nh zJ>FkuFR4jsJ3V{LOsLA~`~a-# z6*eYrmE+s$L5oPh|vd9RSXyd+3p4=zlRdrX@qERNjeQD zVl9|D3%{`<#{wg4SY#>UJ{VJGh*FcHMTy5&pqatXHwrSNu#%e_PM~a3W2<@nW}?rY zZl2-#Mf9U04Gfw^4~#jh$S1LEDSGzHY@=Z|1NJ+M|W9ivqKI4>13T0Z1x)XnfAxsd(PSbdcZNBStp%T53KPzfjhh zW&5neH!SW68|+{HKE$RA2Jqp%kWy6h(Hui)(h;WMvoog`7Cs~h84Jcmn1}G{+Hzjs zNBGdeWNyV02AGtl6TQRSZKkjgVxFE66C68v>L%V&Z(1%;V?G^XT3(g)a1$M$#SOH` zE;GuKgJfvRVBrWf{%A4Q#9Q#~zR@sL&Jgu7`f8EP5{x5MV6O99z$cdDq|yr60sd28GrxMX*@98($jo`&T}iBCA|to zb%asKX)8!WJMSI6;MeH`wkInRRi8r_Pc_4j4vU~-rbAntHX<4=P#atV)E9!=&d2@O zX=HNPg|tewh@c{6zO7fNtahGarN03M%b8<+txjiJjWi+CqZ~5N$`PW`SB+dH$6BqF zlM_Z13Uyz;E2V9*RS`8C7cEb#jS$&t;pfbyrpV$Gsu@itu&M%~cgY;UCy#B{q(TdL zYaMl|GN{^Bmlwpf`XvUfM{1_(o`V#BvG^^P9kik8(X}>YEuZxwbVxDoDQhtP20umM zM*jgH^N7WIgsF&?G@%dIHGGoShoh5x-ldv<&MY_)u@TuX_Lwg8nbAzbuB^8-Bwrs3 z7cn~xI#gdT6DgJLg^_u~Z0H&L3~jsgO+PNRt#-A2Pf=5v==T&i%0WPC;4~SdA7HFI z{E(%$<~bJA-&yzg^oK6|_|QG;o*Z=h`zP=F2d5|SmEm`-y~qKw;|%8AqRkn-ef9ze zo_{%@_!ez@n-JMoohiT8NX!Xx(rYk^W|RXlEFv3IR+zSIacK`&-rlDboBG76^vH6e z>9&LqwU%k6S$`kF`ZQDgEs9>&)i~}M*R)gq9M-2kwaLP8+PC7DlD}g{j-E57fdv$q zzZ=MNjl>2r-9kwj_dZTl3y|`qG0KwOlJ8AOfb(o}yV6EIfksf8@i)>6oYP-M>SMG6 zk4J@pSAedRtYM8|T23LYo|p%$N_lB6wP+~`zsfxJ_H9RsUkVubb)0=kv1(O|)2-n} zniSfw>rxbWPx%$j8x``zi(RgWK$k0AwLw32=Gw#Pj?g7}%;Z#IV!DDZ(z(7URD({i z9M%>3l{iIuYOYMM4h)rBi}IL8gStb8z7%+!^x1qc_# z1!gfxE1d!8XoXv}ROH-6p?ou{_okFF(!#f`3bfGupH`RNzHP6O(~r)2+Z^`rosrRN zSgX+=R8%`?pt@L^kJ3U)I*8FJBD;T0TVA|zUfSKx)Th=3WIv$-De*HEG{kX1W^&ux z73s#;jTEB^Qmll;J`fOQcNN2!m-3Gs%6g)@-clh7KVoiP!Ipf1L$%hnnxn`vRo_j1}faN9F@29o3GC`>O7_Cj~IfOF(^X?tMY)uZy$41-{ zm(=l07t;(gdL&~KK6bJ{9nbbORZVGUI0sepp~LpX(RJaN6g5$GcGHb$d|jRSX@$t6 zRV@rnJhvKHx zjSNxB4U!wo`8rL8ga9Y!ITd2J5p5&Vx8aaKy!9!ngsG0mlO4My^n?YL+mg81iJm{t z=6>d6LvK`&eE$|$(}!$oRa@w2$z?twfbD1t;k|Vy>osyy8grp#8&&T2=6JV_HH7~H zxti^F*{BU%b5I+!T1+($R(yBc1s9b!%*~x|XR$AF6G)nBQk~-T}#2BWXipI-m=*<%lkp~j(tM>n! zg04o^6;arFtF&-R&#f%4>*Q-H6u2t=y?HtU7+1F|jl$}hs+J-7CAa+Ju z&df^WsKWWkepo04de=(xm8(RqRIN;%4GEMx0;A!;K>Il?xO-M~)kST+X_VBm=!=bL zc5M_3g(+wO(}Qnzf}vyh4E;REs<-d%W3$e-u?e(yt3tOoUCIi-=QFkk3o8DB23iqR z<7`;lQKhAL%A@xDl_SYCsJ^xO(5vKXkFu|3m7K~>gXOtXwL{tMXH7K}8rEcHjeN>Z zr^mUK8~By&(OP?tSLdqx__m$b-7@bG4*C&h$+SRkM8Qfari2wI|DV(Qc0`p-_c$EX zG_bx>fK&;h+ms&q(%wa|6Zs(H>UG9??}Qg|M*1-6otV}E#t3N6B^}I|?t2DhG&RvV z?ZCJ2`D%KS9(0zT#7!QPTc{wW(fZXQ*_zH`RbRJ#JZjCdhdR2ePQe2$AZ^F62WnRl z+@9dZfGZnHTEVJbWB6Z{iselSXW;00{*;V{SNcX2Jd4Cl!8TOho;9gN#ks*Kv88gP zOKQtZ_h?K0OsbK_VPAHC+C|bNOg1vR;ID40Ym?Xx|Fnqxm078KE4=)wT9#_)>1{s1 zTCckcJF*VVx<+U9?FXlatGW7M&id9{wH?UdPj*#OgMS5P@_yjVQ76yJ>SU-#m5N2sv~E>hMUe>0d)4uQW zkQOtM_{=CkH}^4i|5kQk?KxceBp%hB#MRDXREmXim!W}raZ%0&X3WXn6^B1@wXb}d_uZ323#B+v zD`~v0J;2rmm*bKi#zfc-!Hds9@3BMPyoGrux8+!C#3RWG`Gf}kKs}hJI3gTE!k?{y z$(mqStJ1yF1WW-#su+nf$Y=ccWvFj0P%u?kHu$*2-4I}$Z1dnG9A~vIYiTV1GHSn5 zOrCh|1#KAgL2t>LVlUTWb%lO>cNZmdu+uPWz;u}2McKOFn{j@pxkC10er;YFSJ{q_ z#N+>bX9|x);o@_7Al8@10A;6#`zXK^cjq3@-rBowyCs5IR-Hpf_pHjA)mEBpW~S&OAR#5Vj7Cx$->o`0v< ztO)t4ZVmj04@F7q^~DRzJ5-YLSu)GucuRg3d@)PR1a#_rF(1QmD_nqEgk(IYTeO-E z@ExN^(9M=pzXl-wU0pZ*9VNC4P6aZ+R8+Q&c9eFmxcnsh8}Kmhb*z5mF$^sP|%8ZX=gs2+)}Yi1$7S%6AEs?ryykmWnrk86>GKv3Hm1-;Oc` z)_9LXBene-S|2K{X=Si26bCE`{y_X8Q%7T@}R7s+&vzKod-uIV$LvbSrM=Q+_? zavOAFl^tbP!(StcHqgJ)DDAS(s47*7n}Ws)EDi2N?7Z7{iq05!kn?fhVG?r?@F2^# zw|!fQ$yMeG$JqsKRf;>{cX}WRFs@ume{Dtk<8gI}I5XBZ^0Q<-?yGkF;um^SAB(y6x3l2Sn)-|+USPSgeYTkv*F3Ak7$X`afCMCs>@H9G$b z@m)>h^s?sselkgc5CD4sPkTfL4+zOej&-+^+f?6y)$awCa><|YAZFZ2o)BimVu{Y%ZfCHRQF~UHdV)t$0 zuX%Fyl*s41@|mqj_Wj#DyJ#&x_UL+)89cT(rr2?{EDoN%;|k$fk!Ztf6(2{FR@t7J ze9sgadPDI}IKXlOsWaT^1~Xua4z+@|4(#ihlypWFgWPu0VMHn){JsfW*e3^PM`$cY z+J#RILF#B424@9ugiEapHX{xCNj0g}JW#&>X}R}F&(%Km+uO`C&61eS#F*wg9Em+B z6*I5`IzpKT;#X69E z*xGzE^CC1y%uUP6J_j2uoAXon6X;Fq0~b+NQydqZKG!QKFD~C%s#Bs&P+&n~_3^~l ztCVJd3XRe0wF0M;d-JzUFVNTk+IGO$aU<@y zs|{fAhMA1r1-Qz`cN8bK5VSe6i^yR3qseN3%F(st@xo;V;CYDqt;(qfAte;cXpjS} z=z+MY@Wn0DPLn?JIi;E^h18k5RB^@R^U|8V&|nDMtf3{6b*5;$8Wtyb-M!XX8pFdJHr zwX;pu)%*$OMrbmv=K8tLu0`|J5o-RuacGq0uQ#n2t!22C{i{T7aDOYYTd~h8yl~wJ zPG|{&9fs5p!@+SLfnq_(`C>3gi=uV|>xK?t%CjxK2s=+vB?;n9reuw7$eFU3M12+$ zr?1SvLFY!?QUq6EUoUgeY-v{uXE%{DOADyCl+}w2Q=KtvFPFgDdyM0j7r$&^O@fW4 z?e|BCs3DXhOG81urgd;aRK&wRFg^;(D>OK;%8|Q9tEF^$0%oV8hpk2WVx%^(($%$> z+PV$QtZ-?@M!J8=T5_!*>x-v13S8yhUsc~%%^z!gM-Q^Tz3nQS-|nJHtEjQYs}X7u zT^(kd(pfkJLVnqwrIKmd`h*g@HO)k8^=oEwR|YaXWvFi5>-K-rpk1zf%i1z~wv`z% zn&lI+Y<^m#QlLUzc1UWg~8{~`WJjV2d(JM<} zno4{r>SiLqMA&)#UYGl!Rr)#@A!4EDudn_Ve*5T(R2wEqL$!Bm4lV1g;s2ZJajG72 zNv|C@kk(4@>jt8F4-f76XW{uP)Mn9hK*DaMr)kErjCgCt<=lq9vg@J=fuP}Q(}3=zg0ZL zu!W3sWOPTQF8lgAV52S_HZ5?tauPUxG>I+jrIu*Y&F^~&^zx<57nOU}>z%RdxgBk) zIc+Llz^7fffT0!z3llb*5~EhwtSX{vy>$X*g0qRxvuFhYYk5*|7(IpuG|oFLSqC{V zRb-?E(Pb4QHD>~N6Z?dv04zi7*auu5loQ=jE^A)xP9y5~(^x-$Zi91Vul3@e$1;b- z@pShr*2)c?H#LB+L$9bvq}0QPyiRVF)`;zS1WUzCVS#wlR$4Uixq*!6UiS=y;T&d6d)sC%_E zNkUmswPCc}lMr@a>Wy;`$CCY$3l=U1!@`qk3bSsgrtYRT=V!~`Y-w)nqzZR^zGbg( zn2FUoe3xPlu+s%q=-x983%Zl%#NT`kLoC3j)7xvEoQQ(2^2@JTz9>-VDO9{(@g>8m z-g2UsqE9MtB}G2%OFHym?)w$Ym5>*hQ{vldlxvYZD>`(bLV4!h+0~~i;B@g`#`(3X z*1`9EOeC6O+0ALgD`CqODrHM)nH!$d;YG(%`bi&7!8spJ&ymJ$V=_wkjNv0hVcB5$ z(mO<18NWkR+-BWes@em@r9|w;TOf&AxRa~Qx_(;oB5==iuMMOQdOM5{4V2X>rH_>A zU$czFY^+)5f9i2sZPWO;DxKwnK z-pxPGlACM52An(Aj8n2+@V#UN44}v`;jHUh0hkZ7yj(Nq7 zknDLIhAxo)mfN|lOmmywFslxu$D=q0(hi*+>2g-r#ZVe`A(r+jDY}4W&9|uTfcnEO zJ7AwGwWPnEV>tIADs?gUq%MD>lf|b;d>H5Hympv2&*oAc-{m7jmvD4n!%n@jV;_2$ zRR=W`QFBU%f`Tn#joB@Yu-1#qjELcqZFnqmH5{T7Y%W>e`MVuKLcz=*Id3){%xE*z zz*l%QIO$O~XIR9wb)kD z=sC6b*`P~(?&mHuLn)5g+H}GKME>A9nXx1M2FB(Ze~1(+!beIStURAd@jr$#8e_S< zDSn2R0LZ{#zBcn}Q$oQ_Yx%8B+BwYikA7s?(#R$wMHGV^U}RHdK9ux7K~Keq$`1N` z9B03$$&>l7msyai1u#w&-uD#87v_!kAUl3P8KK-V)VpB5uVQ_$T=ZQwSxlnK>?WDb zfg|%Ik$6R|Ob(W++g8maWve|9@fMLTAll z$${Cfp=o!V+`Ut?JC^Zc>l%}p^+t5nG7p7x_ELd%mj1NJW^4+lKylHBadK6tNcP1I z&|Zqh*lU#YuiEnQrS;)!{;-Sb^Nz)g)*b&Ljj_!yTDo3LX{(}3%yi2V2yvRJiz~#N zo~R|NK|6hSj{t5Kb85uNX^@+2ay*4>$w1}U)DCyNX1S&en733+696x;7%NaIXvLS~ zJmFkl#CvF3`Q#=WvzrZ|Vm{rHtPIW3QYYRe>|<~e8t7o;2A$O{WyPj#Z}VoUo5B(P zWkjx+N%&zucH5ZeyZaU~YHzuCf5|yDO}PY`&37gyP)#|F5c&BnCr~l{!C0g`hl|2_ z*27L!sZzQYys{#`m0(&nvM9nw+qtq=K5KIaxwTjN?uT@+Q@TGOhel{S?1g%FN_06^ zd2J9HBXB*j(wN2<-(YN#ia(^YY;7{5cJNaQcxXq51(KLMh!1lR2Q61=Z;hqhUy1nh` z3%`ZO7Y~`fr+WPAxk{e!hPv*G+*gIThwUH}d)E{)-3RV@|KF(*`QgH-p`xgjCw`-> zliA_c=4ON@(=lEy3{b%v8~NhQ`NACEifpJRkDXQ^pkE~uGxnc>9Gum&x1|YrwZER= z-tB2_-j?3IHM)9R`SPtAakQPy(r7okhw}#sRF$pDS#D8^G$`8}0m>Df-8$m#a~)gd zFSQL^Vg#hJtWL>g`@s6=(`rgP(-%=%`W!{yGND|}OSV?BtLR@NzQ`M1g8gD|FisO4 z?-2614KpWGW55;ZCG^~}@IzIk6;@Coa4!O$KQ~QXX3&Im1FJE*0Ns`La`D`5S>u%M zLY?bFEUm;hi1^zxE6_tuh{Evt-86$DJct%*u|Sar|Ru1 zsk?fr^bsu8%-sp4a*#6CNEtIy?CB6f#x_D8k5J(@>hi*Pj@!|eyMpJ>IkF%WBxB51 z0Hzg@C%qnAq8%AK^n+BnM%DE*F!x4!hE1JCNMWPyP1ezHXGV)L`mI)3VR`O zBJ8=Di5^bnz+ee;4J_@7G!HdBY%h|Gvw>Lm-KKN_NuNJ?hOsBH*aJ3fQ{!FC^O}NN ztT>0PV7qzK11H~*=T);o$3rBFwfd`rmnE~Wsj_J}+dXoXU57qoiozq@V@GuYia2~O zN(O1m;=MI;S>}Uspr1{#h9D4>>ZrJN!vu0mI7}d+oHMTmYPeZbxL&aSmTLen&HU1{ zi(|3ZZ*}gu?3GeuuF#kntil7n!|8w8a)pLNsM8Sr;~&m0H#S|2HD?RDBVT8Vi3HPpM}b(+hFdXKPL zYyw#(eCr+r_X2|VK~!8tykTl{B=R>Urf)5nmy1_IN7GuuPsW5-B;-&8K~wr%N|qlv zgIx6Hg;R+&nosCH1m!ky{x^!~5_;9eDhxlHM=+`_KdWy?@9?F7^TvMH0i#kI?8Wm* zoAS(ZDqfDSv-33Q3E_PW|6v#Zbdy6-^1F#iQc6pT?^O1HRwu%+-O*xP3Vz}kDZk7# z5G+hku40EMl&8r8!mP#J3ona>;yZ!0I4r09y;A3T5l?|;JT@=Ob0JOK>^F>i>%A_Ix?<*SAn3%J64`v`+xrWVa%cN!JW zLQjQ)$+UEZY8}WBCUexq&f2jn;Rydcs1EWo&LlFSlmb#n#J~BZ`hr zKlbAf`@Q`megPiX27ju&ymZ)EZ+21AYg`__S5p(-DFEKn%oN>+v@sPWzMCIOw*t3y zGQ+7K)wmnT&)vjcb*K1AYH&M`fV?82&ftx!Ih*BHl*OhW!E5*)CYx_`k5pQZ^09}e z;SZzmZA6=5P%GqA)Bn6gVoNJ?`g*}07Ok($tmyTSqJj{@x=M3Jg>-^op!S0ll?Uhpjn%mTwk$em%7o}l$az>v zlT-kx2!)+TREJ34kO)CRW_FB)_b}q39N6}FzjyGdd$tv~)+o9CV3u2n;=r1iy(ktp zH)DK=V8fNCE+Ep@*W03xZmIwydO|Ll5^^2IFsqm%zc61TDRb;1tpYnXjXV6|Y;JukNm)=zK zU7Zy%G2nIUmX1(EI(#T3zOybiA{$Swl0EL7-2oRsHAS%TW)PGLTvIaM-D6AVYck7N zs|lPZavTbNls0`T0P20`UMrE_HoOg$ z3s4N)=~=y$@oU`Mb`!_VO?#!Xj$1oxDPs+`Gq9ny+NB5a z@Y;G()k?BIDhNqgP<1{4*Aw_Qibuz5#QJn^c(YdTZFTnKh?&DMHpKQ4BjJ6$ki*KbC zbwiB!KBlxEy7F%0y1Ras2X}JKlll_ahPtsim>$Y@nyb4d-=EDd0$?kEdZI*pex`&K zNib794oDQl;wjMaI8TP;H~=#|zlG7Moz}Z^z&Ady16dL6zdwq`dH!W_Q{}=YR&b5A z?fc1??iS~ug2%+CYIzfh3pw$?20t;5IaQjr#&Lyv1GHtK|c`jeSfN=eda<&@V^m7l% z&uf3klxF>D|Gam6Eh?)>8O=d?%th;~kY5(0(7nJSy-TsgJXD5dzAN%jR zD6z~HnM&oLqfo5z$d?b({6jh&f@y6vU-#dgYiF#!JX_AE#Yf~9di12EEkKj$eSeS? zwgjyZq5IQ&RNEgTLe*eRq@rqT3C4Qa=gluH``kwHa?Ebjh`{A`DGaBQkJrdOY4vU7 zUPBot3*L%u<`@UAu#fb*VG9CHuh@=azsF9>Cpp|@<}zl*(JMeO;q&6hYh^!|*VC@O!nC1FIW z!1v^dfLl=Cd!!j8gU%H;Wl%$UOMh*RNjT6QASr z9}afkzW!t9-#A+4i+-}ouRddBUM-xKdsk^KH7ewi78Hj;_>ZlrtZ}uZwz4yL zRpDe`)~;BetC6r>xtJp5OOm_W^_}vjXis#r8pcmnK&1sbGYKutU5hG}N5#J4b(`4up0G%7A}p1)vxF!7>EE041b|r{Xtj-B@Ob^SRdMMh{>2@Aj8GbQZvWUbv{nYgX8 z?@Wt_RH!#j&9Ha~zls#uxfZy4G~Zf@lyHYnPLB>xdiKHgqxn2}xNB)5Ur<21Qw$fA zTDk?k%A~Y6Qk6=97wX-xdhV|O<`Dl-mz$hGwk0iauni@X41YDy0nx#)e~!}E?I?ZI zjsPR@%QX6>B|)s14Wb-5qU%L-rZ`GGZ?%e1*a4ioL3%US0S9xH5K~H3N7q2&7+#3S zQrA@iOlU2Co_s;giOM@zS?aiOt*Th9UhPuGO#??I#@1OPvDXyAB%Fu}V~Yu?WbP1N z+a{WlUj?_qkABp~8&!#}paF(LRB#n!tg;M5X!7z2eLK+*$dF6!6Yk z$T7q(2eRoHgIbMMQV~tQOGi<67N)KVd_GIEd9h0{?VIwwwbH~ZUL>GMC|$re9VY7G z;VxNNRcq<(IgcJFk|^vtYmA=WUU`dLmySN^N-XQu|lTSVKQ~!nsHB z2D6~Qp8TzT!g2ynDko^YB56Fma_1!!=0DFcsb%VCubY{-8|EW^yYV!nQl7FRbiIiKZevK?%?jTLU^_Hx?wM%1qCy}okw$vO6n|PRlU5Z- z2+fj7{v<^p84+ZJ&I&SO*^9Ub3ybPa{Ekv%>FRp=y;q=-xk#&qQ7hZ}{E*PO6_pzu zlZejA_@kIN^rLw2jMzLzY~#X{Vq027(Q7t34xT?p$HsJ+%!U!zt`n^5V?xLYbA5iS zWo$&82tz>*!8dMHZeg5XCS$81uwOz_hg-klG52Na$}DBm9&^l1^JtjNVZ|v{c);#N zF_@|-XF0-tORRLVSwyFQrq^g#YC;dL!lcZzLxmaW_%EGk@S>RCk5d{BMB@xheX6*} zYo?|0V?_`+oi!#{Looi-`{+mkGa4Vk(KPDz%eoV~R;DC#>8g8eAy`X|-H#o@vKTgc z44jGDt^>J!VY2#8Go9j8)kODc3Y0B6%t}qtmc2C#idm86&*vqzq3QOv`rFp$kJUxG zc)0Oym*wHhEo=hX(j2Se^yj&bdf0l&ZvEvwdXai@rxezobflDz;N@?C0of-PM@LHP zbQC5(o1O|C1{a6L$zrTy@b@DA+b4}LX&Fdd0VGHsjb=a1r!U+UC=NtVh5>ccOk5u) z`8>v^EqxWOUXsR~m6P9ZvfCw_ekqjqCBY(|SPP>Nc7{z8y3;h;CtbTHtmj-&;rk}2 zggLpmln+)!rVHlb*wl&K6pz&jt_#iDqPr!h&`j$r9qGfgu@}Lgac?8KYxzFNl8Wed zjPF)q9>aWb$ya5(6k@Y?88k`9RD}aHN8r@Jx+#O7JW0CEqm%s;_R8Tg&PZT_s!y#u z<+Xjl+8aOu-JjGz4{~>c922a9!O8@5+eF27Px1N#pKC^aU^mp2jMCfdM>_Ij*+q zC*zH>Xq!l$1_7(`#k%$X)3ZgJw9M(#2yV--4?BA$vinA7@1LC^R+0KQ-H^xdLan^V zv*Z@-{bG{L<}GeT-|?&OT<0`!`a2ieL8aIYHY=f!QV*o+)_vD$9m$urWmy-D7RFuO z2wscGiWbAG^rpO|()7JtCB-sV1!VI9BskL9SZvq(OpL@z{r++W|;0W%>V4tdpRCkl^9FpU_! zJ1V%VOE8xSPzybNVDX?FNvsE5CX}#_ok9QdhDc`OI@2k2-gN$d{KrK{DP)vZ zbct#8$C$hea9B>MKSsUZ!&@`hoI~2$-w$72ljHA4Zaca?yKQ5~nJu zq*$x(gQ<2^a<%8RGTAoN3q$;jpSI2KZFW@8(mqQMAyPnWJ360(MpOKl&9CG2>uh~B z?nWWOctHao*ujY~8j+Nmi$_)J%`Z9GN3z-{Z|w#+G(lSM-+$}N#V8%>$;B> zZqHlo&E|0&(_dO>RaNo+`roou+l*JOFGR#PoZlS#^@w{Z2ac`0Vh>@&db}1`N%>cp z(h`=eFl%vTgl9A6)wuF+{|E)RxWa;;bLxNhX%q4Bz{AIcNkO_ooJ5gCkR#jVdV&4} z@e=SIwhlM`=cTx4;~{K2+W6-urH!ZH+=_T+Y5GFDov6&x|2oondUo|cm&%@kV>MQL z{iL3@*N4J4Z*Dl;G9mqgZlOWS-i7qyvRce9?@mYY=uztMD838n!qETkYEpkUi62!! zsCjSEHZL!9uphlq7;!PSPIL&EDEQW0bSYTmmo&Y>$RvFK1>i;_44#$vC`OWgHHOnD z@P!sCPn1FW3n#y%?9PkHjXXTL#GIA7vM2WNxOYP&*=6XU0X^lUMTk8Vdey7DEDXyTrW>pKuBS??u$2((o?k z4`WVC#*NATWcNJXRcS<&)=YW(zRkK%(qCuYa!<5m;r61z=DC{Y^f5>OJsA#wXQ#jJ z{_|yRa{~CbxcHT6!b3)bOGAdzwx>$6<3PUAF9mh>ViP!7EH1fGGbDaWsA|-FR)IqO zeKiWzfDb}s?f9{QT}?}b2wP5X-hh^y-EBrO($b4U-Ay(O(K9MTB~@viq6#NGg9lPp z-SDwMUV@HvI#kFg7NbWXqYHp)P@%rAA&yZ)L^K;S7J#AK%k$p*{*ULqv%`~*h?yVJ zObn zT?%VJZD+nBiEj;i`R3x-I$G88*r4+p2xNoO-;P9f=u3;_5JsL}9BX|17UZ!-9+d*w zqK>8#xrB?_!9B?wiubSu^s0{)bnzKoQUoE;15mjffBRNa>0mVz{wxs1*8NEr!vVf* zJsAo$ktak?KGnTOQ~hY__IymkQ#DP#*;E_NbZ%xkubAolThDa25mJu~QjaQ-di2ea zy4z@`2B}9CNIm-INPX4_sV4@hClyFNc~YceZyi-_rrXl(8%)}SnW~xj0qaZSQ@xJy zgPviPSEirRJmJzxkCmD)PCZ360KMd7c!s}+Iw-+pHwy7=1X zS*!2+6RzKchg%5nqq(2(5c5zEh&=acU|GER!-?S=V>_P96N>uSJF!DI^(8oo; z?s+u3@Lw`KArVzR==l{$=@FP);ZfXE65Q&~q1+7FJ!znxhU;tLhdk>z$yI`X?@0%~ zKzHvWE0$daA)b`VGA>Kd!NxZrv5*W+;)&pk+;o@?U~TdwNdK*GuK`huX)?Pvch~t$ zU05Ro4p^1>6DFl6*4o63nB#kuz<{r_F}rOLr=Qi>&0<7)v&C3@c}!oh{pp)ne?*H~ z&EZ@DJ0?g?H$ZO1IXMia>f!Vw<}YujkKZ>HWApS2}*FO-;6}H)M1>YFo6*>4ysVav$r{_qWhnp zy9d2~@6&$IAeC)4Kv;Z3@g1&F)xZuQkz92>3ryg zk>uwhV#35al-@^w+>Wvi&?NDGn2io1(Fu(>jfPBx-g7ebEDAWvNDXO1xodctEHf;! zEEY(!g`4J^YN`@BBfw!!9%o&bSExU9Q1n9w+KRqjTa3dZETHIY7mn6?FNrDp69DPwnkSm@20eRj%kn z@%sge6WB8g6a{BtVkR#jkYHf)0%(t=BwGuzl z7j1rLTI8gEP?jyeol*BOoXUs!p#q{o)V}RKuzHrss+y7f|Lq;oavL}9-CwbFXKX2P zl-N$M4{IF6I4?PP2n03P)HsloCyP)0@Gg7B8zY?+27*l4hBx-T6`)B2z zNqpX%i7W9-I*0STF8BOBUymWdx3*t_ki6|%*3HRmSYX_#)fr%qQbs$=EWFf86(uQ2 zYcUv#W-riRzn@iFgUvxO8OBqYdIU_D@e^fSm^9`}?y2va^r~EbX<>%*n|Q1!NN1jf z*z52+ueB|zU$0EvF)2DYK$~Nk&VaxdjUoGNd z4RoGJcN8=rkMLT21cvf3-XJtXk_b zD{>X7=AB1Wpds#TyrWEKQ95i`-b}WlFR`-r6btUu&RQstC0XFY>n)TVZVBp09jYk+ znHcv4HX@c?xm-%~qxva#Ea(sfgM_d|fL120s_hOE#-*$@u#K?P$#Lq-OHWv$TdrJQ zPH}x=KGoZK%&E4W!yP=ZEQ(JfSQ|)H^dprB)`9Sh1)|9Jk6O@V8I&ziX zU`Wv_GTV;z0jP@WT*AY;Vl);2MW0!0ImCI1apDk9?56WkUM0XArcoBhOpuNj=m&P1 z!hbFj(PFN$@OkA_tYnjw=p!3}-^Bi~7ltQK|II zQg|r!B8P0OVJvz9T~klh1c(jVLjH_3%)m|`<-kY%9@~neK{mu)JW_iobyuaD4iba_ zgp5S;NpU+Ce}}pqioxJaD%P2Y{yroAA_PZ&yi2XSzIq)BH_9dL0nlR@Vrda9c1 zsEXdHc`}D>y00v&tE4v`<}c_o|Ffe;PiFJhZoA~eHh+*|6>eml0=a5ev*Ga^0x;E$ zA-riiJlCzAc}?OQm=~9>(DO@^>D7GX%u)aJ`!>`H+I=_;2L<;K1*~KLVGX+AYT^TZ!x_CZ1D8vpV-u)%$#KC*t6I+hf6gwKtdoe=wfO= zO*_&1{wFBmnJ%`+~nClxgDJ{hB<dh<*sRp9|3LJMRr!$ydy@qbBoA(gQ)$rtze&kq=G>btQ#@PZm&ib zD2;)kc5IL2!Y&=1Z8FX&$v>_pjx5dX5@9+)7?hx)4JJ;Rwo{&F;(5LkS)(b@tinX| z=c9<$qTFvYD9z+e$dhSJ-Cw zW@WenRIgut%jsKLaqAsEwQFE~^($?!e#r9bm)TwY8dg`o#O4Bt5H9&xQtuHx*xJ^r zV{8>L^zAG({>G|ZNu>KbM+zz$ku zVh}xp6-+X)#t2YTlk9Kv3fe=3ut-`F7W zRq3}iNBS!pBmEkt$X9wsK@~eu>LxBxB>`I#Oe&lwlXyBGLw+@^jxtt#usmJnIve31 zlXhDvjQ4tA7>2X$;&mIN0ao+83cN%_UvYH4kWuwnauv^p3M#6Y&-A8b9J=Ff-KGc^ zkMB$TtK9I%A02mPsZ+QD3aZx{?p$vCylq=I^fenWC*(rDf3L9fZ3n*Xgum^=x83F5 zWQ+5Mcs#Q%;?jwlj@ap^WC0HrcH0l=RW=xwdzI_El>v}&DI?rv?qs)5!Ica&@XCsa zePcZG`T@}<>eS6*4G*`(j+Z0cY=0PxYIn4qM+!d`mVnx6tx`Qszff%+H3M9ZNGlQGLN{B0%+*xJLy2zcKtyv^cOcjvU%U~C zD|DdKjFC%L(HoVl`qk<)+E>UjwcIbWY~5oWig3fd$P*Jfy@|`l1PZ|`H4)?@t|elm zm>+2%eD{zO8bL0<0rC`stWHQYbiqx{kvZyu@OmOKWQ)jSvD3c5@NnU$nuFUa7gdX@ zcxBr@6+|w8uGVi1hf#mwJwN1yqmMD9{*BhJxvwx<2%H-h%foR zr$|NJ75S$-`1xQu)OfV?7zSK%G3(S!vjmDfE4ks^nRHic6#bkhm$xYfeTGRsn2m2Z zkVjy0$J?Ziv+xK>JCRNgx`%I%&U+sosTPA-#{RPbUKTW+==G%Za9T(4U<*@7n zZ66$P65(;_^5RM{oz%QLf56d%7G%$^hK&sesbxSGAs}d5-PKsw!m{!w%9YeM?7GJF z&(l?=9VMB=_3IdE>dz#eL^VDWi^G7S?=M3a$ubQ_FHp-;gQ->M;6e zx@|XWZR9!Ke^MG#>BHrHWgojK^PEZrl^kHiJ;QRY)(zXz7U}WA^Wp-={BCDd}W(SY2)qw^;m|I|~QK>&5M5vHE;65l8 zg4>XEOHq4x8seQjkg!yqekgKed{Pa|%2$L4eUPR$^?Q9}BkU)gUUkX0;($yXNsI>T z>0r88ZJN+;rD?7M78`{urWx{p!)ceki4ZZBma0wtamXq^YJs zUXuv_=iwT=(7rZ4BbIDMd?viNiwLZOLaR<#rHl?{v3)fi?6Pe{hcE&UMu$+`pva5v zz9;r{C~005Mv`I_8md2*hmUIUq`U7)pjzk%iB=n(%4k+iI+aGQeC1OWxmtorJrb2; z;;DdDV`xQ+EQyy%8VHMEY0xaBgqsJ=DyLE)>C&lKA~u>zK$qT6{BPO%Y#8tpJ<9`r z_q3;*qGo$m#v;Kq+&fcd$r+m^XV?3!IOOuCJb2n$mnSKfsR9`2!A7%UEK*DeANJwn z$L10XXXF|tm+@_ik35VU1|2^p8yXW%Dg8W)J|}dYXP!lwvU$=hhDUDl07B9Ltmf+) zMX+GvRhF~Uk4)#S=$g!R)s^@m8*PNk(cQ<0&Y4Z8d-9Xl>7gxS(-iTfU~ddBowDg- zf|eepq@(Ayx8!jfPfaXM2N(_yPEJ~vS+*6uif66fR@7^^JDBdAAw!lT8-%0FUJ7Co z=VQ8lHG?Ep^HJOYHo^?X)`EEforHgk7fBh1HG(tD7yS$8N3M|{%;a^0;(F+qjMKe+ zdQyrfbU-_m|haCqY*)y?nJvfrd<;dBcow=bG4cyw062$+a1+O*E;Lcp_^Tx7j09Q%!@=ZVNM5z%aBog zivLRfxKZa2oM&pk`DybqoxLWJByx z{r5{kQI%t~TnG(P;n}4g#r<5314n3Yp@;QaWu`9$r3a}97$sE5;C2-%5B0HMR)N2p zh{V^G{;YvVQJ^*>8`5byZz>;9G#tD>fxU7$*7*}gnNqL4I7Rg7T9Ep3m7wwzrDWkE zacIx#cbbIJN{rKeExkU{4-Vh-Zx777<){={*F^_{jtb#ZdoA;f>i|R(q`qXY!FU=S zXW5k^U^k)6Ll7y1IMKny#nHKrzw79inGUc;#^=57C_8Tlg9I}3H3@(!LxY;cIot}; zA+gJNoRUL?Ly~&Eh|n1a+IYEfDN+>v$*{BbJq6J!r=`DrI6r#bd-MMM^q{-l`lq%> zO#oGfgB2$^68t8cO;7;8nPn4ZDns5P#M=go3gYp%2gG9S4)3DDj>vD~LBi4DwKb}% z^7`Gy!K;&_-s#0*@0Ww~vv+657rhVfKlEB{>=-@Y`C&Wy;o0+l(2E1g!iet2!EHXz zCRjQZp45wQ4M5{SGT1alfq$HxlsoLWsWn6*7O{YMa>Ki%N z3B1w7+Opsd1AVELoiZ|0$Uug5YISj0NU|{osq{U=UcZ`TgX^bE$ESq&Q~dRbaiopb z-Lf;M?+<_Ky*oQR`T6xxkN!n}>JaKh?`?1Gzfem91PTBE00;nwK0{A<{A z7ytlA00{tRZ*OO8Wprh8bS-jaY-M3{Wi2r-F)%JLFK2IWXKZC{Z)0mOX>Ma|b!25P zXKim|YcFSQZ)0mMZEtdAEn#DHX>V?GE@)L$1pomb3zl8ISZi}KIfv{tNEEr_7^Zccm<=eo2kDaECk#?g;-t2lmOL`o`|VN`LbK$UfxD=N`J7|x(0 zqLAj8U^#+^PUrap2aky?(i=79xWc}e11{r;O3K*M+E~EbgGDzreyTPPQJ$HQLITx1!UAlw5?fGPl`WPJro^v({T+e4Q?<^mi-^rXcx*_}bv1j`} zxgI&g@xXyR9N<}_z_I-{IiucS(sxD|ZGsFMxd96qI727E%D`>Q(a(31drm{!>s{j2 zI&%h2a3e>aJHd#LJ9j?vw_XWiM4&lvwH!XwR`FTL?}6Evmk$L_Z&O}7aK-d z-c8$x_3eL7unv>dw}#dQY;67<9XP2s@$4b%4oLjTnIAa8B(Ukib^8LlZ+llx&-PDg z;Q9jG#J5G6z7<$H5;fxX17cY8J!c1HE2QUxp(ArWm%fmqzx*z`3wTJ)0M}Ea=+t?G~Kp z_`JZ8!x0fUqs zF*fb{Hih`{PpcF&myd%nY(t6MK91U@Wr`s200TMp*j8@=%A+{75%By ze26N#oW(Dc4ovY(=pV0=G=q<0i$RS=M-KA*LMS{awt1`M%OeXj9>i;r!;%k1S4pu8 zXGpo?fW==Z?zKfuNk3krBcDKC47y&QQb{Mu6jzVY@o4mI^7)M+s zWsuyTyA3%bhykZ*vtPEhgYB{5C*;`w^Owm8XPG%SO`Gu;Of2!Am1z{CJ8(Z_VY+1B zT~df;0z>2`-7KO-FZ)!Sg`QjYypJg!18;3wX6v!Or}^v7xP=8Gr#{pVO?k1jYvu9y zEXt6xyAdkM%C-t#1ue4Fk4|l-QdDs}v3+a(MDle)t5uquPq&y^gSBp*zcWS%MOP7l zo)MK@H$$wK(t)(tp-+VjuV_ImHy&4-c6A@C<`5$T#Dz<^&u|N z2lyM7{C6Ew&mV9FnlPtaHLL(>rhtLHXE>9=f^Ndb2y&zLMWPBVks7*xpmP9_%GwEF zfU2cV1gbk%Esc5^tI{zfmqz)7*~{^NF8~hzp|UQ0NRXgC3G@cZe?Y+{fqL*SO%l>g zJCy`)ywX)RH-9N4EcHqOMlC0it2VWmDK=+aV>QKvuELi2W@B!YeL)9l_X%CHQvxb~ z#AKLhCGZvY>9A056~%}_#_SAnbOt1O`qv}U-%1HCH+qTJkUMd;NlV5MM+|-)Gu}E*+uSa{sJiclajzEgdDCBPK;}j& zZK{ve9SXE36xrI82(R|Zltb)R+rj?1*Y^EPSzocurQkYJZa$9g64K=SqlP_~N*8&8 z?fs2!|K6&!d$TMF_J3{1opyt?5$fQlisLnkpB?I>HB(HbBK9QxJjXM$!Ppx09S=FB z&4|?Okj=BwAnL`JM<#K8E9jPe=t9ud;4KSQm;j%R%~qJ8wWuzE?1ZXF(W#?ndU*|& z6v!R`67BjQ;sUDQ--`d#?6@eHF44~|Z;y((*zSF`uvs~pEjIs^U;N!|Gcnt&Q?Nu@ zH^?YKl7F_X`G}?w&3yu z{*Qld!zSkW^-PA3&#*zMc&ek4ZQLUF%vm>4G09+`i(reGl>dJpX$$fW0}afcZ%`vm z=}O_>Co&F_IhMO0w)^!E8gO@w)H*BH#U3E_ijXUNvPNeJ26ra$lAjrQPfybz@$~ee zasfwEltKTTcfOPlcmEf(RXd4Cze0k55F>zqNd2Edo2{XXv4yGA|Bu?HH8$-wC6Ikr zHRXSh@I@cxQjx-tY{o|n73K`G=0IJX{h^NEQXx=<$lu2ntTQ#2+kv{;g?Yqf_E^`Bta55vx@bll#j_514S!hRSQ==nGATpe;fcBf1y2dHHx~we3RZDt z2gaCKL#FdfI=DOU#0Fl?R%bR6LqQWtUhr>D@s}_q+Zf59vUEkDT5D(OTxF1DIPZyPv0zn+Em6fEIfb1i$6rhkHNH7HWCsO^3P%K@bb&I8=w>hy@dP&I`u*dYz571@>u7z)VaO?LT`W zAj!vu%q={Xfdz)7_hd=2GW^gQ5C!JS$YCGgsj0q_AsKi9{!^fbvyU%(O6A!)t={6mRHMDg9PjQ<(`;Ni@ z<=x?oL66zwLhn6#O52{FfSHq`Eq6x`9Yy*>6b#k*#K}ieAB*Q$tZficqkb2&9g%Xt z*=z>Fm+!rm2aC)dr2*SfQhMk>W{3|k1W#djro9dsRogN7Uv{FXVTdlY*|>+omDXc; z;NN{%pFSOEJMtspsX`0pI8Q8irW4L`WENM4HuDxl@Q03Rd<=;;2zjqH3;2Dr2?stB z&l)SlabhKYP65483T3&=wWL1e`iNOdItOfeXqdB5IF9~3M`5^j_E_uyGt3otSRALO zeVjj;GorZqd&Umk)(T%;&*?~k?&rqG&Sg0tMS!^YPH?`(b8oH?2qfIxonQJrWs#d7jkm)^7_CSi}4`h<{j$Xi#5b48YZSiUfWD@`C4uI%nXN8St;F^os78k zUt%3fXpUa#CC*5uacvZQWgo95JDe~xug}UCW4J3fB!Ks=0RI!@RW$9H~*_|wDKBT??Z8E3#O$D$L65IVaEFAgQY9# zlr|~L!bOD6wQkryD>yi;$QI2}A(_G7#W^%1z_73No4va~*WdU0E%CpPb926loUQK$ zs_lzBVTYYoN6hS@hriuuJimqr7yy4l)^Q6#9D-rWGD3%zwH|eYe%WDF+ zQlE>iH9ge(M`GXU|I@ZVDTo%6OKPo-BKQ}}`;Nx@d2HJ9;O}0Vl+U41yOkr>1gDoj z!IOPw@t-?`x%NZnXNb|Aw%sm)1$AgFb-@zK^3_Y2HVxsN0C zI=|Rm?&t+J_&)hMgADs9EVED!PZ9)iOp!EBe*Z@eU=o3VNc>->jGd*iDZR6clcllC|HlkmYunmy za-n|T0GS;E0DA2TxO@IVx)4e>!ze2aPKjH30+7veqhhA>$R#GeQ7>(~ti?xZ9OBLh zoomB(0$hz;*{`0Vc!Y$DLUo)Wow}(m4=2-oooovq3`yummUXT^a)8tXeGWA#(kO54 z)7NhF@eUT#0yFgr7X^|$Ra3Hx?C9D^wGB?zlqe%nIQ?q5Gy=5_GX1rmPMVBKnb~EL zl0Z)vY4pUEMy-m*WM>`B55V-j5`%aI5{!U$DWRI5WW~&BBq#Qc3HNv-uxjK_U9Zwy zJb*2;#EZdFJp)xD1q_GPo_X=LTkSLG{isu|;>t)Hd!j$u^GbH+6j%-!VM(zhgVAG8 z3l`w*XNexr@(4R&>uLz4>zZ2v=UiEnec7xt-ihzdvCjS9poy9? z*bU`Bq)=Jkp5nu#9k;qBM|s+*S;s10;F@$ARltNQ5eR6+`Sx;gi|BVCRsB+ zz|3kYzY$}7i2g?k6e_gQPAD+McXVdq+pT{81TH1bY@Cu8eXAoa>5@Btidt-GeqJM zVt6O~k`}oS;Upl;ob>s789~^9@cADrfF$43)G&Kc-7-k@@C)WYRsg3zLdj{%RN_8G z5c&?j?~Q39%C3`rbM5C9-9@Xo!2LYN;Bfx6Cx{54G~v&9=OFq06P-e!N#+|H>|lYb z_mw1JU;trXkt3GwsJ!tm4eJx?Y~(LYE<|(>fvk}LS3@T0FRDxcxiHr`(aGu^GTU># zw}mgh!kSqcuOHSnll4njj6_;3qfd9-TF;6#K^JN0E7Z6Ew%Ff{mHM0>wtLA#gCj*K z0kq($GoJ8&h=G_xa>!cyW6^tV zpd)33)&ku=wJoA9=yp0%14=+_iE129Iz_X&F)yG!?=gL#9J}+DKgBP2NYOm;G#X9r zIl0UQ4mdh29u@xesyt8@4O+ICl3d(2U+Os!r|D1SzOlni&@@Qni1VxUPhVF&rU3H2 zupBDrv*ackBw07<@9@Cl#b%ml*V3Ad8o@j(zwsHis}TDRA*@7kP#aqjw(>|Y!x;|w zbRuGNUdvX{B?hsS6#f274W*hb(%y9G%RV_@7yc=bJ8v<}58<6ju<5*cY%`o1XEQ_p z}s=gYHn%>X;a`4-q@wyz;?d1vg4(ZD?yVis9~9%DX=yb~E_;Q}L2gs|!LQ z)-Rs;`_DQjcaFx0)+Q;`&z%@Z=GwRf%n6HI$%Rx%(uDHMBZG?Nm{wJI^lB-#mk2Hr zE;?+yH_=}EPSTZuiUv}{sOsXZ0WTI!ATQ)=beJ~Z5}M&IcAwjaR`~y#WNqhf>PK4x zk$v16CjEb%wC0V;4rsTPsq5QV(yWrFsmG!>OeQmk-@}%GnM!@rV2R@hdOR_&B5~t| zF6Qw1mh~Cv!_CQO@m`5>}C3d z!Pm?-gJJxrQILT#hboxa2`$bFoH?u1jXG7;0wz#gt3?0BJ(+^Jrmp_}NgfJXadl^3 z_Ns|WjC;lC9CToNK@)_60`z)5o&<*yCoRmKuGXx;wTu}u#Z*)3|9Z6F=6vNAe(iCM zxqUfkeg4~VdX7s(qSypW`TTlG!V9>;BKOU$Kn-weX(g*;0R+C7Y^^Yz^3V*=8Z@u>^Xa3biW~(&yKg zx^eqx)OYJxmw99SRXD|e@v+(uN-|^^ zFgx7S(8Mk)8cywr{tDwBN_WyeyReI>c4arho+h`5`T)GttNB}v+Uo-$td%-7C8pI% zC*8K|m%pj^DJIpn@F>I>-Rw%`PDEoeW}?+-_VxRK;H@gXWB6gkP|-gKdn78r%?O_)XC`G-}IyJTW7JimRo znWyJVnz?wBVn=0&e)6jkRFQ7oJk{-#x_lTP6z+Qq)=Q#ZAIK*Krf^heK7EO>6%Za@ zcg|7JzG^d`(!cFNft!q!U5q_|xb82PKB(@t85)~=g)LGJkN3$mxoG=RRqI#Vs$HF? z-NG!qUcrW2MV{>%->yE+tf1|xV9KYwkp{bmY3OVjp3L?;aL)`ib_y-Ac(cQSzI3|ql{_5jcX3zho z-MUq-*gMai9}6N?Yu;=4eX*f%uF|7(-fdi#+#lgZF&>m?=3zLhY_~NMxXm^f)5*cM z>V|GezE+`>IC} zyYdVd1=7s1T1HPcHGCWI?w7->mc0go21E3HAC9j7{4WBFo4ke_kOToKCI$V!?fK3Q zrpEL}u9h|?|GVd3`&v8WN+#~Pe@AlQ6N92duje{$L6SRy6;i=C`kX;8;Ec{d6~eHM z0|K_U?1b1>ir%l&>MAEHYoUbr`I>M?p(n|dW~-}x)CF<{Tu>o6Evl*cLB>&4k-LST_Xg>*MA9XZm(=r~dGu`S!rX&E@-gxqdgj`FM1FK3_H1q|CzQ37MChoreGf zWas^tnvi}y0L^2+=pK{=Od9O#<>keTNnC6)@%Xy2fIb|6Fb_(4+}|%xgI7e1WdI;3 z?mVGlk#ckMj|#_zjt)9oc=~M=Rb=reEv}B=@2?N&zB%7Hd9d;Qq?G#b^9c@|1M+g` zYvgwjW@f^EVM+!y9c>S$j-yQK`_u%8Y%TR z2AhDPzru>l$LG((LEM>niif*#vXLyjupmKx(eJ&cVHObwICwbudAPaV-}rcVErhWC zK|&5pLCk-p4SYU_xyf)my?eUS#KYMaE}NI#>EjQcoki}3XaNm0hM42!TAenK0im#+ zy5{8O_HkzOarSU>2uDzG%zqu6H^fA==lTmJnu*5*R@#%_b67C2an=s_JliT-ln<>- z8mIz>w)gsYO>g^pmJrJ+UtF+rVc;8N5fUD4T%1ap_=JJ7l zAjtbqExBrJ@`h+W(1d|LY<6jf9+gtyIC!xLfQVhXMCc6QgX%HoZIvcfHjBc?W2lXj z(T7*Oe1^xAb0bK z*fux&_O_VzKDzIORyrsVV!Exj<l#Lt15ES3iB5n?ge|?t7^Jp0I%iDp(jO{ zY4k)CnYCn=IgN@OxmgoEWR(@>J7^+d9?I2-L)NS7`Bc-`D7mpS)aRLeLc~xJt}|7k zvt!&34p5yzVesvZFDtW;MVv*Fbif)F{JI-d9IsL(iyp5M{qnHB{QRo)r;YFC7T|vq zG%lqIGyabH5y#>4^JFHY;PB(!`5@Rh6@Q6mV3KFfpcnG;@@t`@=wA1IKDYHc{g<(w zx~%d?#oYN;F`l~dY2_1oDDXh%4-0U|^w2XU@F-spN*W?T{Ld3ge17#3<>qR5tK#{t zzQ94}pQi1F{sM#C8VfTAt`!o-y?8@tORMj#;bFUl{o3ji;U-Uw*}R3mH^^Ld zYXdfcugd}A`^x#1*NDJkIr+I$g%!Y{9>)=A)vRuwwcv#)(Gg5(15gLD@!gyQ=`44Ac z_Rv~a(PJemNOL6C^*(;f#^V|ycq#|w%bGkja7TjB zy%~v-z($Ibk%B~p{uDVpUfgxv_NwA?qK(aj#d5=PbGTRbvCrDRbQ7n*%i5U$n1M6q8h|uZOWKZ0gy(na>q)l1oR{)fWbLQQAi&ORzFCAHS2)BYtoQ%tUk;`Qf9u}U|ltv zN_;s^jcTFZp$ycF9AA0W!_h&4n#xU6vwtd*dj_%)yJ~|SkBc5E9hu% FH0I#}06 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 z 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

    vUu1tZHe3*fLE`rB3Wyvr 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

    ZzGY7+$z+tbNeyp-VPDX~J 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 z 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�&Tk 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 z z2{a<9=31mFEMT5wAPe0G81Z_�$-FJ0~7)3%1S^zJ11y)J1ko@i3l5gfP!)l+AxH93Z|FYv>j$rM zIxvjR;!??pQbZ<+yHpK$@X1mFKamo0aA55p+N^l6(QQ*L-W`FrN@(z69YdnTEIPzH zvK4f$x*N6GVs9+5F%dglx;kk|{Vwj37{4%d5|Jn~P>*W{lG5WNqb*$+9E|MR8J9)# z-_1Qq9T#hHF>0oRHY{(BdQ65L|*FR-;iXPMM+)-iUTPPs^#(RmGsrA z%H?uCCy(};i$mWRr_bJA%jfUpbo66Ogh%Th!oXH`B{7&Y27n}M;3oTAI+LgL{K2r5|A)Wx#J;MDYtvpywXq!jw#t8la$ zk|$iZ3RBvO{F+Ajg{}5QmQV|uVyYPdMM~T|!4fV?NPX=y>x!o6YGF)|-wm$@rx(vB zoF0QbwSY^@G|GZImo#gHbCZostE6;d${w^~sMUXQ(zpQvZE`9=*wN32WCx>{$BzLy zssVCT1oESyBP{tlw-7~g38xF(%XI>|)EwvJ=6?o1Mf&__@Y0r%vGBfCE-8iJ%))x7 zFg7_X_f7=Gh6C%j4Fs^~-5>)-D4bEjmyk@UW{hx{j7@}`$tmgr0E)!Pw@=&yxCp}Y z_Eg3QZ=Z~B)j+5_`leE+UN?&r66DGvHV4^w2}l`OC6Dz${#??z(Nj%DJ7Fm4IwnXh zlp<7FEI_7diizL+IrfZcZy1TR%@y>Grf828$kBAn&YN@2E8Fo-jqT7q zi)dj^8hN4|h!r*d*b@!Ey>jd%fafoE3Wlp2jFOQNP^7)RQ{i}S0114dTQv1OM%u?| zGf!@Ryu%0esj%tHIg!+f@&?oYVg9EfRy<*&ocwM@)MUaF@H6~^H5<1o^mhJ&z1VK6S{b_^n&%0fQGSsj2d_%LM(OLHs<^ zVnAEXsI(bsYdoo{$)S4@eVA6=Lr*q_C*MN<^gHM`Tr|I72pg`MfBGf!_D%AZcZr+? z4o=X0V>Ph-rzK1j+7^J3Lt;x{(st{DUd4DE3{%43#p{P0;{z$u@P;l5w7cgEnxJQN z_>M8k8vQKn9TV^Dh-n%Nu^fpc6=qHXmSfywk2bPuD zrI*}nLn}z8P_cB3MMBxq(V(lr77tA?_CVrXL>zvaDe1`$mmrZ0KN7)#+-D|U8Q3J+ z?R7*S!Z_8}K=3^ea!W~ucRTVm0i+#BR5ogX=n_yd+P2@2#(Zv#uz{y=%%Tu4iY|sq z^4x2Qk2-9X&EU}Ip{Hg_tzvJ_!)u)f>faVeDWaj(TT-K6PzcgBRvXV))-%$|FBMfH z-3qeqf?NzI{j+|Ttc<=`ipiiYcbjB|>*|)0^{nkWTE1_~*SBJ(2W<|IeN z!iW;KEErVL8wesz9!&L#(uf@8ieXg{!@ap8k<7EaV4aR zxhq46`m(8gfp}}@ooZ5Ms4ouX`(FfuR_u%0D<-JpzdAV68s!!-FgD6m9E?|ao8)I? z=pWpwR5>!xHZllK{t&{px-PPo&XXD&<4l_*gNCQJ94}gSY-JL$$V=tw~hGydxJAiX_VyCju!N z<=8+~6Bw)9Fq$z8f>@VisdVuHE}Zq375a0TceU8-inoZHVa!$g$TNb}$-Ys%;-$p*aq%jpRtZp&`!v->bNAva zLG)7}ut@rT4!4wF%iQCMGBz?GblRZH&8?bB_I`2TXUcKQc~HuA+pbZvs?R2>&c_=B zH%E70DOW8?I6i~FKS0;rK@{Ji!`77bR#v{51kLdsZg@f9U)L}*34xLJT*Q#}A0-(| zvC%xzSwY+%_H~K&O$m!K!R%CK6i&3!8ps9@1lTmQ^%QqP;Zw4$qOL+7ha}!NBSll1 zY$@DIg%6#B3K+WR_8jUWE1|YVRiDnb_!y;V#`J!zXvs0CrVaC9oEV5#hni_A35Pid zykzG?X8BUd=4)zV;&H6+`|8qlU9f1Jb6`hJIf-nIKeqpH@S@pr;Rwl@GL{02-M@4@ zqV$rJ$Af~$2lDGNz=n9ONu&J;zF99XkZA6 z{L#W^!~8bkOR5ZUs`@E>vDChd-L8uzfjfY`Gz=}uS7mdF?V?^=T!r>d_z9g8-fnl- zv+MzTHCv{^FC`6818@<0Mi;($%NKa=pl-eIo^0 zCk34}D%ub@Q5xk|Azq?PGcOWT$^U?^v4cH4W=O{uYN1!&-hnF6>zo=2k3sB{#wIS( zc3UjC5*t%&X8Akt7+kTh@|d%!gP0^*IKVEh1_J?9KI1ibtx$j`_m5T>cF>3{sg)|v!=%xmo1y3PLW#6KVj*z z0Hfiy+9O5+CkU@x%b|k35@MAy_=-OB8~FdGNhl&1euIh5JT5}<8zs1=F_t69ZcAp5 zs;#GVUPQ}lV*advI>f1O0Te^9 z6i40EW&#b=v92if-##hLX!VdvL}5E`%OtaZQX`YnK!_Nb`m_PZ5><;d&vZjyv9Asr z>=Sc}C?10d$J7+lesH1is*eoklQX*lit^y1po2WHrL!Qf(GFv2H5*J$3`g6Y3R1nA zTnT~N*rHdBXHlgj-iInaOX7|TbD=AF%XV=Jj1cH;%j%;?bFBAfOz|xWF6*7`ZS;r2 zPAIDoCBYe`>9UCZx4-S!!+x|>WXb+s*A9T4qjifA%A>_p%mp)(-`OVr8%`A!B7z%1On5(GtvonM9_=Egl_Fw)=2T9ccxU* zLGlkZV$%?BehxFa20DKvJCs1lB@DEw)+x!TlB6gX5U4zL9_k(%1@>$KHBna&gfj_S z!?-8`sq6kCC^lF*39zTVGt7J&V_bMwsHZXaQBCw^!fx~Kpfh^3J$};Y5JPbWZ^{xL z=pl;@V@-GI+y@WM3ey39?Z_CExk}H`P6p@A-I#lNjn1*VQ;wg2zh1D93z-}ijX)VF zR*f0%b%;nilnAGYRJVJ@V^Hp=Vp-~>6@wwlI6hTS=5A^7q*+Ws{zZMo&-fNGUk6QD z$F;Wzeu`As7C=$Oxo*Ni@Y4g86QE3fnkElcm+(l^G3mmv@ISjVfw@yUf-p2nUAIb+ zm^eMWfJG_?-*O@1J|=H0&~qZ%o6mS*SUgF-8_}8sAnMR-grHkZB``1xa}NI}%Y_WC zDQsMgt2|X~%owpNqHvjyOb3`RvF>Y1hl@6A(!?9}7&_RSt(VJ(y#rF1cVt`h5&f(F zUC9Nw-R-}x*b|{Mc~32*=>$XBwQ_3QCX1QH7uw!Xsj@8~4GM^4Sj3oaqxr2wyGy|@ z>A6GMXrP?UN+vD}U)AKuCVVNE=0_m*AhOFuSSHmSM>%sBL{0b-XkT3qagE9G?PWHL z+e=mDx((X+0n9iK?+GafM~87e1VXE3Sma#{Clvrep}HD z@fq3~NIQ!JmEaJMS zDw>@}geJN-R~@ae2I1e0|5EV%1{BiI*P9qmRfYnm9siKA z3D|;;P||Q7q_ah+0(~=Em8_mcdFW`)Co4n7bvX(sRh~UWA}0e%k#RW-(1IEow<>La zt3QD7+?8;*vcV4qvzyUeX?>95g~@B10BS-R|@SXG&w*5ra&o7GB)} z?Ft2LYZ>cTaStnf(la>Cx(t9@>w0En+sAE^I?YTPRY2a6cff2pQ= z>TeU}D?dQVcrNC9d+M7_=sOl)P!{qX%S%#!-r0j~ntk|LMqrgfFLq2`@_k}Rm|T*g zPuVhS@|{gO@6s}ucrR?%BugahmRvMm93F~c5`I$>k1I>jz0AS%wh$p?cW@+b%S9W* zxnBH1!R&&*F&A5BNl8B<^Sqc$dp}%)UhDV%1HWz|q&WtPHIM73V|{Yyd?JU2>gNT% zf~A#zX!%#fK>Lp;*C#&Esl66|4KIRAN=;spTNv zKH_XCRq6o)n=GTttl>D;F3MUA(|yOCg4wP zDNhfq$N}tG6pDWqkpzqiNs)C8xz|`K(_^NjHEjeSYL1#X%-0^6vJPXYE*lcawiGxq z>>P$yIANU?A-PJ%COXhIhb+&(aKP56bJk1B1rSR0ZvrIJ2cOQnQ+{a4lxO@J_8s$m zZDFwC>7qQeqs_5e*@p_4tmuS4SH|97-68*6CAz~9M7s2}5tKMm93N z!njx3%2l7w8=iKK^}vz*JYHdq8N?}N~w|Gw?cjW{4Ly5uJ1aI{tDf$^7OlMDK_47?9nXp(ASMDtg~0FQfi$y)KFc*!X^Xa^HX;cr(N0k1n6S{g zMK+_8rzT6wE=ph-swsxHtC%pniApz6(P=8NZ=}LUD#oY$Br-y1%@NGxs6<~zr2Lu^ zgfe4AiTk2>LRA9@_o9m~8T(D{#E@Vgu&dPn^!!F5{HKGmoFPiiLbbC)x6!v8Ve3qR-Ke5AT^Yf8^**m{m)(eM1`;_lyn?VJ5_H|hGJ_c!oeP+r5#7g&dC=91QUT5%~Y9A?fX%B0fSL7IJ;4$-V2lu|?qfmB6W zRpL@bgyRCGHJfephBCZ>iX5B!uc~;?b!g1xr~n62`9~$ZQDd1f6=kN_0E)(3!iM2= zp#;%SsfVhMoKizMcB7^0Or{}~uVY}^Y9MwHYWsX543tM`D&N!-GX5C=VLYo@{MlugkM~fpTxO6H8_Hd}9 zwwD!p5c3j-59#YWIIJF1zc@k16aXyIZ6h!X*wj_#s)jgg>r_k0{wj2f_cH5EDW6nb6W6%VxL_Omd&hTmxsnSAQA%2*TvQ4_bKHxwAP>mL z$h9Rb{DKT6$HlZh8?_GKoQ%p=id!~k5<8P2lrvK+4TvWV2ZG8*-NIE`(Eqi^bd#^6 zI(TP;cSCPLB*g~XX1@>7htc|nxIN0a$wI1Kr z2h1kkgMcvKSD@QTz6CS>hT_7urTj!d6&-5I)bBbFcxqTyQ%!F>7uog*^Ckb>^s%*3 zG%Mh%WrHlNwgF$|Nc@*G?_bWme>wC1q0T(A&%>@Ym7+)k#vT_*az|I;uI#WZ4tzJ& z1WIQW9gzQ6A7Mr1t@;G`!p+rgyXnYc&g4Tfi0N<9l!A9zS|=gDqqNBUh={gNiK zjiO$C!aS;kY@-iWHLpc~seL6tye5Arx$&4iVLl3{ zS91VxnjmYW%digF!^l2No%D6DcjYXkKm)v0r1CxiUXO0FjyXf!kO8^h-kj_(2gSd9 zLIYM%e9ea!Vtbwj<^_G!g0Gy~{-zd5k^Nj^5&LoP()V`%{O8@`TRfvW1H07=<@&ge z=5u7`CXGFuOBN-w8FgWy@N=|f$sX{1X#LGg?+t_K$N90`_)$N&gDu8(sC%GTWBQ-f zhkLE6}S0DwkN$#i1N&!G` zc-H3YNx5PPIf=MUOYYMYzn_D;hPnADCC6FTRDLuaGN23h$!&7fC3?7>F-SN9s@PIC zMa`ty^1^)D*7t%-)!EKsbsIG3Tbw5fj~e zjrW;wPosI1*T9|8yU&9=Nbb>IQweuL?>-Oin2=u$mlx*q;9jj(wc}mWyU&CB!zKiO z`Yjk1$oJUL&oyvn_%0O#!hO7@g}C3QzO2HKAga86ZN7Z=%#2q(G$T_(quwS-{o>o* zbFX=_6*)951V}ISOIFp(R*TrQCu83&GlqXwlQbYfo@g*@*zYrCE3zKKDFa7(K*e_W z;7QxSu-GC3!r%h0&&d&o_~tsCQ?X}8G0Z&e1Dha=I zp|*8h9!II&r@>15-|%W2E|SF+fc3q6>^uW0SU11LGIH0E>WRJUnN501G|8z1R!hNA%} zvR&U-bcbgoF#O5nM>;NVW|s5_%s$T_8t@DSH|qm{+y%nuE>{h6LHC}Qy=ZyP-$#Xw z0`fb2g3aJnVUO)0)YEkVVmh_P0{~{w03YIjFrruV?=PIGed&1>nDWnuZ~B8?&BPD( zVD28(YEs=DawpWwHt6zQeBqb1@=L{FJ`bt>Z^o)$MynpSgI2rX-^Q8XjaV0neJ7Ub zEe(lJfGWv%7E>Z=!^c)}(xApP3XC!a8b--yv^#J#j@gFUV)JJs|Y(_vCy}Ad=6d5%oFH#~A3NVNnO!?jKXl z%(*tx_swD42p!Vjwh!CtS{XFYz8UoV^KsWd?Ol#~-Oi+EZfVtcvL*-vz38qU8ZzAw z@2f7LuBBA>xVRMY6u#tds9mh%Kf1TVX3j=o0?Ho!dODQfMwDRI@;+dRar}jD{1C3h z+$!y*X(GG{vllk8rZQjRgl2~|(Scua?*VPR-}(GAbGo^GbMHr>cAo$@{J+cQE< zd3V`Qn4MTFa6_2ohD=S!W;RUI?$g^-OY?ZIEg5Bo)%ch07}BsXik50-?M#^@69BWE z%DHK%GXjdO^fqzPMx2kyMmXQf{+{lXX}~l3atoBu_D8Z*qvP->U|cP?a^V!sR<$|{ z9l(@7c|+HL+_dBa8yg6QN#8}qZ|IVW^*`1pqpQU61y>HkFR%#SjQC}krtx~|a?_CB z%A4|1*|6S*c`yFxkQ|EU?w!8n?fJLAm0$7hta>w=?5IMqT#Vo18OoS1*Jp?E$0$u= z%1qPAAf{vyV;I-vq(S2p51=vMKVQde=$C>M&%OH~jp?$}@=XnVSFkXqhAj^^>CS2W zV!V!FK7a7Pt$F^Z=8jx9UNL-`;XN5`=V`E9>Y)EA-uJ1)Pq4-p=Xx--aJkAKnK$R?}R42{$2FmSW1vlo(l=}nzktI~QhRl}B$ntb5&H6gTvSZ0QZSVZo zf5i#o}MqodE){UoXR!^cu^YFwpE zQx93hGFXwBfhRk@xE%E_CTG4l@+223Si$-LNSG2rGs|vWOcYFSqwpi|3kHqjVlcFY zBd%_b*)rmuBwA79mK)QclUX#itQ|rS?+6jbOjZNc+dGN{lljHq< zb+FO=!QOIs*keJ$te(37XQ%&l&mEz)fyne6Jd|d(R3{nQ5Jit9SXQOVTy@jx!#VU zaBvpl@1l6=Ct*crb0I6DpiMUclIZlMJ&&rv1O1i8@6a2{G7O4{9xpeXPp4d_0S*q% z+m+xmE);YC|BI%4+1jmU3bNZQ$+~5^|JRwwlWXYn>!TL^`^`%>IfnUE?iw*@Aahhq z_mZkd&ak(}(6^6b=vxOvl|BG72*ph6#-`q1S^j*}%y{IBuJ{U2rt#HN9QUd)p%sci zRE7ndV#0|PgivBtea8FON5}PTXwP14YW1yw^v%l+Z8W5ft+3Gqn0P%jp6pDPgw~2LWwTC4rhbT z+h$SHz=y1pc=+qspQBID|ME+6YFTSp39PD{t8vdCez>3(XzHL}{8Go&&Ab;I`mBRo zH3}6CNHIB;v-ZawkmmgA5Izb5I|EdX1CaI&x_PZQHqXX(btocrF4(mqizE<{46(&k zr~^f;Nx}NF6}M|ctegt%g{}KxZTj(!Y?pKib_rc5dTziL#a9|+ti5GWBtf?=irc{8 z?(XjH?u|P%Zi71v?(XjH?(XjH41+s^`{R5s?!D*ydoSYF`q9z5A~LfwJGyFDuDw>e zDkoRyUaW~WbArr;KiFp^7&0b)qa4FG@T1E&Rj0QnH z5i$#^GJA*;P#gPLTL{F%n^@+=>W(rB;5-l3C7NJCWwH|@m(KgPr0KtNjrXm{GttB7 zgaJppEGCEPQtfax^A)w?Iyz`|3v;&25)%dL@r_Ddc|61Gq5l4fTfMi|hl^6)P1YY# zLVSl{A&RFI2%e9E@@mhc777zNK&>I&V7Hnrsrh>dqs3u!qHMSCYX*ewcC^40ZL`_k zcw@-jMpErxP5zf4Sg1~i-vvLD?r|mi?a2&@ER`M{NH-!Ca+x7w$YbpN5tnF|fb0nA zFqjNukhE%!BoX$51ZK9s>6W#X7EJ!Qg95qpB5#!P5D<05UxEY9PGK^k5pF1a{D(|^ z&p@xfhbx_X_%Gt4yV+&VmH#J#MO z@FoEKg{{9`)S?&8TWWc#pM5l6V-Sfk&r}KeN?i#5HjewCMW` z@M4Iu(}zI?-qdQW+GDnq2QEnCRW>S)vc)#Ku)C7Zc?$DPR13ATX0*Z+sGTs5n$${@ zqPupgu8XQEmDTxHsOtRIwL9d8Yd1f5=-vk;Q4;v@PstC5FL%#Q?S_@9{XZ<(DAk8033D)gDjviQtBwdxaS^>_Y7SF3X$darjvpq( z5k+0bvRXCEezxMxz=ow>Q@!}4=BXh-5$rftUD1Kf;AC?dO-{W$wVikf;xbM74Pj^& zU#gDsR-GzFdY)*+PfO`8Piy(Y+|(y{RXK+5a)NY+mKrt4(h3NS#0wK*JInEXVMjQv z@Fc`KI9ZMr4&l#A zd>(lB5e3QzqyPSlnXxowXXg*6-!xkMF-=u(ol{% z(!-0(OPo0~V2R`r^^W@z&+GawYsVIZFgMwSxI<<(AIwT{-6`uBP#KPyfT-uTUJfmr zy;v`K*3?QWc)yjlwc+CkN)m;KD5b>qpi7wR9|>KWb>nF`EU{x?z7{IZ;mDBf^t|@P z!2^@P`=eX70Y6TxagplruhvEV9TAr08Y$!ZUZ?(jOmv_WIA80j%RIdEYN1wOI}EXmQ(xe z%SDg8!pV2mqbPxAliqDa0kNLq*pS)ox|3E*|EOlIi_aVI$o7h|BBl8Dq*L=(Z*`Kw z)`s_~S69kQ9xF&9dJR6|j)vks;D~b6oTxK%Slp}X(4AQNL~~W-(h{>CxR^gcmCPfi z!CrEo2PY(|s&lbhWI58nU0ZotN<-SAkrt#x_vf^Fu%w5?Y?C`mTN|sMpD%NUl$gf2 z%CEiiAIe1@@`uPGzi2LgFR$_Ho=%)-=p|FxcuC4NlUrJ?EzUspzpO=eQ{{A~Qc_aZ zu2T`MG{#HDdUaz0wM_6_)UKJGZ;z%qZ(R1HE;WD~2j0J#ue>oWO~}ZL0-ym+Skn$aaW7yD3f~kSG`>@TK5pt>^$k` z4MdV#T4UfqUK8?p?XJ7#{So-JC%|!HXQG9m0o|Q*#he+GQAU1In{7T#&9}rpZhwRR z9Qyl*9&DHiR(pbngmuJ*iB-1wi8pr!z4){Z>mIj??+(mc^C-sy3Fhf0fw6WdhM~gF zd{{$5`dPX-XDZ}BVk630nlo8(5z$!dWg{#R($anyN6^fnHYM6uz)kfyC@ICTz>V|? ztZg6~N@UiE9}0DY|o)cj2_`eqMX(V$;+9a@dU`WZOo`OVjWiAhwA$|z1H1p zf+Xl1Bv=GYAjF50sZbKD5P7?LQpa0D3bNWS8>{{h&I$sWI+Lx^wSASFopqtk-?N}Y)uu@KRHzJ1!u|J2iu z5NGl*VI@2`cX9x3ZtT@zDilJ&IU;BEyFV@0lu8aDP`He93b)dmNVC|+Ol}dNiUQ)- zW9?6o{n+!%_5~wlB$PrG@o8MrmzZw_Vxz)BeB z+y5%W`W3jal>_((NMvBj`yl;D)^fbD)WP!cOX)AFsv_YMokIiumU{(vjN|2@O=>lJ ze=PpJ*hJjY*S!k0L9F-!jy;y$UBqGQ+1@_y!s&2|@mSOs!8~T#uiQ_C)SLn&(sb>n z-W!r_w zshYsl#7F>kPP}vt@cW_6HNtc@*{;N3?hS={X-BA-q#Z&@G`co;nJj>^-7Vp$26l68 zHtjq8ZE-B-EhnB|We%2Gq`o}^w!Lq8y5)KdX$g{Qa;QD*Y4FxOr!my3r=L-@#A85P z3%>0LzS7f)6(toV#8>g`V@YVC;Zj2;{S@b6`NfVUt|ikt7XqywQd05dEKjEob!?S=9GBUqyf|X4uX_&GxCFpeG?8(^( zPseO6NPN<9!|+&%D?Rr?C0?A|A}8R>}GCcredPzl65}ewX4}m+Nb0*HeD; zcXe6shH-9f`N1xZD{zc(_kOyz^q^r_Z#m!}LVD@iMlEsI{a)V`ue9!S+GB zuwiWZQMBwDS${#!+6$Y$+Z2enOT({OSDWYgh?B38`@nFO`#+x`?JdN{9>_sJ=2pP| zFIg2id)S-OyEt3g{I`e5OP@EVLaBzU>rYxMFOsV@bL?i1`^mqz+`n`dt6^F%tt-u4 z_p?w5=#uGyWPc!+2zIw$cJ0gp2#AD~R=^Lk!nQe-$kGkWeygdHSFF~GcOF0Q&z#EM zTDTVqxDYrzb*J zK(zwn(2KYZo1%{G?Jei+%k%rao$uS`PkkN-!W_Qi9!wZx->>fHgN~=0sg=6LzRJ;$ zp0Y{ zCa_<^u1qz10?^0Ud)Jedkp|kOaTalum$UK? zjt(!IYUhi`EzjN#t{Yt)7;${|k6k{?ug}ds4ldC^eSCw#>DrTx+ZVfnm)Ob5qlf0U zHk4|{RCD?`Xv8)i0lU_W)eMX5+$|Y|ODFHGSxk+j=KX)q727;7p03{H487kfnYx^i8*UpN0^Gd6 zd@OS~grMDPEIt?b>>|%+N6pP0oRnvVYx{UC2CLfljZxY7KiyY`M&p}Ht1FMBai=pr zUBHL}63lVnI(lq!n)dAaieV-24L(Z5fwh@mPqa;ek^A@0led(04sOgmdqs)08q_xW`HN?<7+y)^dZlLFoQwyyZN zJ$H#DvdM1E)X*?s+^mkgS^+U4ogm=qDS;0KEaKhr9j;!2OV%rzqnH#Fj&9wi7 z`$N7IgB)WmbX~;12~PlPm|&#hHSBS>sP&`mvnU*aL20hG`uvE1tJWnNLHpi5495LJ zqX9n~sw2MhcT8xb#149O?(pp?BmI(~72>V^cEmvF9`6fY{%)Q?K7w9Y9|J@iWP&Rd zc>-u$vON@{Px!k(L?FLBCmF$o6M+q)BOdp`*EmBlg|p;u(J5!so9k{onOOA5Wh83i+Y3c$vlXqKT}4 zd{_5W-XyKnKb8ta;g<|=3yOMA2?~bfHU0m;8%#L~6#zDO%cAydQTwh5~Fbw9Y_M2HD@IqX_T)4`F#&Ekeiug`K zDz>-0dA>XyodOjQbU7Vu41~;y`g5y682Q@zT3Yu!3|;W>x7>J8V+dZ5#Hi}7w_b%? z@1A-iw?}gpPya;6Qb{;}zAyH;;PB)9^NWnXd&1$}C9cay&W)|LQ~10^l%j3W539!x z{i_qZS9LLnK+LkeotZhC%K11xu3y!TaB0_pGNQKky^(dIa~&k)7M=Uxab(21RLH-! zW(qErhV+%e%?X910D#{Vb%XhvB`}2Hys}TgQ*X3p1fV>ZzGwg&g7um_2LY}_Y8GJH6m7y`iF1p`Q9@ro=Bj>vNnj zd3Sh%m5Q_dQM<{}Zy^$`1bACpC%xDHlCy&Z-e}KE974i#>592f@|Mp~q!sbdT#@rk zc$;2MrC({@2=y^rf4%l_2h9oXNyy}5!_4MK1LfE{voR9X}FU=kLO{F_!1^pGE%{c~# z1x2)DCv@-ZW`K{^B_p%>7XNG19JtwQ^p_aoQ3#I^d`Gkh+=G4NEQTil=ZDBAq~;rRFPV6 zy%4UUkRqiw3v&)3v#E9QHB@+qX&Bjpm$2ROE|&Kgojw>P4s2Uu?!$+d2@OE5vnN6@yQA1IR4|cx zEVv98oE;Z%-|HA7@U0w zvHU%v-Ed=Ra313G9uV(|J8nVB&zKLFtmgH&0^R+hNx80{M~;+uOR*s{f|APKN+s(? zeL`Ftg}*_9b_k_$O6GZs+!XCR?-w8$19}K!#tU=@ywl-lY`o3yg{dUcuHhw?Ab4Rq ze?;;2gp(=lBJKQ!5%w*b-+eBH@(=*q#S127!glt{93a5&tgoT<$pcMdCKz(TM+9^u z>fyRW>0b|V{~Y;zSdIO|#P-PJWsZoq2jv}!xVg_-AV>)Zz(nhoD1h;f4QPSRhQ&GyhI&2@wZ;ErW1F`S+Fcb8jDQug${K@tySTGBXvghDUbY&n1fL@+ zp>q7n#eYGHGd_`?BUF}TS`qMMkA=U;*C5nmjtkWBt{vgEs5oW~`W)(Xi#e8*5N}ls z?XlfFRmAaR$)X9{*{@eK4q)iR;FF)uXd_m2Itzn!rGn*2_o^eXfl8ddiSJW>R>+oF zepQyMQrIR@7KkF*L$G9WY3RN$Ot6pY9^?b*DpR1SPsI#z>X~#} zB$n-`GR#)x=h`|rZB3w>6g2CC@Zei&(db2gW*fi`j@opZsyIJNjjCkc&%$%xR(G*A zn9V0~PF0lKdfxT%th4Rx8m|14L)-g05a+BH-R6RHJHi@hNgIFaDj!AGtHVVRRsj`?CTPv38i_$6Q&Sh~j-tqMd;xithN#JfwgM|2nA3>yH@y({ANFV>E^Ib8Xq9* zs`t#IlZ*`*7gy^GhYtLe?W09Z{|WWq;aHAc8Dzg1ONNId6|RYebha12UfwnY87g0Wg+ zcJaO~$;h7c0#Atk6he5oPUG58b^Sv4=77J{N|b3j-yfYX3pp7U)WkWndT9%%hr~I! z+wypRyrNCaqWbf2SeM4NppNzuSeM|qv;s}iNv*zFrhjIJr;H)7^F-+~U2pxoh{Pwy_^Jj*eyQVQe90c}i$x8KgJ-2=Do%dS#VUU!I*VpAwFy;L zQP32bN;^mZYqM244zCQFsV1Z^Xsf4!3kT7;2@af4JHp7;3Qd z3JlSV<;`AiGHTV%B2Uj3vQ$OP`vexs#iQ>j7nf77C!whP6qkeJ%R|Vl!2Xi=A2uW;as^!Wo9poc!+LA3T$!V zx(TMZmU6DQ#>s_0S{F@&hPG9gq6TGx&e-0z$!6{#7V+Pka{$GNV-}9sfPq(M>3&fk|~*#e0^(?FME8L{{>w?O8$-3hh6QbzdDX|+u8pNXiEn+ zjT2q!!Qi+vU{QSpBH`Ve9~5E7F2qFs-NqPw$tSa8K*@ zLDBu7v|+CMipwWQEe+n}4%rM{7)f;`;bW{Q$lh{xVF*7gCHHp-+HSKe(D|X{<<7^+dbU*`u*pF(D8cp2@`Ja4tWVvwCvcp zj1fwCR#MpjzAz`Yum?+upHSMEIbkF~Q#Yz8KDMYHOPcgQ5eb2W5g=K#H`(;CRK|-` z2IK+{p|lfof|)?V5s+;9f5o*U5Cb`_;VZ^2T?Xh zR7hpwWmIIWIA!4MI&%5GrZXKa2ZM0trpZ|Szy$b%@T2c42Fq`OSTsi(Ob?FEIuk^@MN`zmpp{^Z}J|gQ{<8@{;xNDau?94+F(9%ksNLX#CY!74FRD>|G-) zni98kE3(7x*#Pd((}_lu%pR;NJBYfd%lP=*X^HkeikEibz*Bqe_5lrCE&PkkH3q{dx1B}8CkB+Gt_%yi_`kFZn_lL{U;!u3oXbxBa)ke~{> zcFS#ROXK9_>Xu1P)kj&4jm>^^fi*0&E8dPn#Jw|*p)Z1dfXT80qfJ#+Bm|)8Dr9MA zLD7=rAYOXmI)7^C5t>ycNn@Vv~ieHI6N@u*irBuVB=#NXalSY)%UOxnN67U^%X|TeRy@eV^Oq5jPn5crup8FZS zJe8lyK$qRpzsU@-!OuW7D=&mO9&?f7hbf2>^|EBmk0$|(lnS_}Y+rUCRU^y1{T zdF=`r*=uIKLYplL?3byAf>#AdvwR{W&vNkYp_mno%8HhJAO41>8J2(8X35EgaPXq> z{cI|N8R6|l(`t35QlXD@HTEqlY7(C{I?3BT8RaEcs)UlORpsV(KCof2r&VD&PJguXiJCeG3=1KGzTro?`l zcmh2qN=nxr&eYUXDQKAr7;GBfADYgVxKe>s|8N%37FCrqBJkB30iAr7{^V+=*@v^g zHLA=y&{X0p(`wRcmQH9~RsT#}|2u#@vSBnk{{C4MVujP0Yj0MX*g3U)Q?!{tE+I-5r|dm)b7f{q%av#JCZZA zCT?7N$WZG^E#RoDp?Oc4HD@mq*4Sfp1WCk6+<29ycU2wrdZ7do&nZt`mBR^ z5^)nZOUA!XZPI+OsD`?#1Iha;)VjOCdXbmp9OWFBN!r(xyRE+_l?ZS;(_I2z)%Iy` z@cvAijGAbeHe@C?K^mYZl?c|ow)gtS&$_W!Uu*2~MvH_=$4b|#7h!hx(C^YDl?XBU zw0CJ7*FvGW$0C{hGyYe}`Z65Ta`q!^K^5jvF!sypi#`DC3)x04KrUcYG@!ol@~x(T zjT{W-(A}Q5$6jeqc)%(I-i;~j9lDd05)0IxcNbP@8e8VJe7oz{Zd0ZK!)(mvG;X{^ zj%2}NtB}rGWT8Ln5(BH^-#!eFZTUSK^_k~nZ z3s?>I+chU1erBu}|F-0TpM-2aeTAs^5L}rT{cnUeh^k<`Y({T$1hbq&@5YEf1$YLp zjBr2uD9Xew>@kb`s)ZTRWITm<(G~*LU3;$u3MTUE>UjHM6!<`$e;Xo#L%Rg+&xd?tDJcel%iV}=W^ z(}KMJh=rI>y2e%fXbw4Hu~D@4;K#S)WVguXyby;EG>@F0Oxie+%y z7w(@?`SIVnD}XWAS7Y%TI4rcN>tXe1*fSy$_XyDyDTSTvm+_hQdC0PzwF@!1AhHLq=*{w(DtxIT}h^64UF4VaTkJDYkc1!RLKmU@p%i|H zj(C^nqXd5G^V8y)qRqC?bgTBd6rSL5ndqYq1mM~Jo4KuoZDmoyDngXqrx#{}E%~;A zSdllKMSEE-w9?Z^a4rdj*Ldc;=oJuh*|FcI$2s94T{zlU3D-$e?J}|XO^kaj$b|dM zoZ0zxpKMO6o9@bTXsV#$ow=A;>lFMh8zG;i+pf`fY44a4mc*&6cZ;r}=ru}z?i202 zkECf1Q`D^Bak`4W`}$C|`nlkcAOB7D!bOZ}N~C5b?$}oi%i+WX2msj@Vg^exj1tL7 zOcSIuvd9-O>Jj|#Ra!!NIX3_6_z8 zRcu-fVntOq*b%heBXH`^GN$ulQT?=mSxT8QWlby8=Q$z!9i{aZF0%t#5)ul4=v7(n zWtwCwOXlPT92=S%C|p`S1obh&=!?H(2V_;AC}v?yDl6mi!!C|a59bGP>*ewBSp``I z&GPf#tu2F>03ZC?OU^)pyOzfQ3i=8=mohs|iI#$+`I;(5HH{@A#D(lEsf!tluaHG9 z-)m-ts`6lNv!ZWX5OLM<6J$<-$M)b_7iJ6avkdyiffifB3Quvu zv}%ms1)v#CPoLo1@1Eg+aW@*9;2Ny)A(#W*W~ zs*q+HeFU9|Q3@bkO@XP5u}mduv1zzeIcf{qc~CXa5-jFX2en0jA#lL>8=GJQvewxx z&}G1fCbi5nOGu0*7}^q%Zw%NL4}AY#*$-3Bat0nMs5SN^qd|-lOupf*OqNbgQoOMP zsA_4o(zLDZ%fZPXL7VswB23~|cn)zPWN&dHDry7awMpn9E zM%F5A-}L;xHk?1BO_TqDPK;}#*!Q0+kotEcaQQ0}9a3NgMvTJrKR6_hcht@)^&Y>I zxRoWamhCxEHnfV4%gR5`UacLj1vqd2dGdE}3iXH4{idqN;3-DrQ4Wu#=EPDG@^=vl17zAECtHRK!3LUCV}?Pe#l2!Z0e1?>x)8T`Bs)EAX24j#ZWfS1T7 zh)8I;ma_Y&E58*3=D--bFnCmO?3v@VnF=KG+3g8sjpgSS`*S0NWLy{(!~1_S)*YWx z(yaXJXMe`6eD|9yqdoZR;2#Uc+o$0UPvS@JPlf(?P#JN%LTyfzSwixI9G zde%SU(K>|@lT#n(a+xa-XSqeB|4$Mt-W5zSvz>3F_z6l?&k!o)j_xrG_jZ;N~9VJ zTx#y`#v&f%Yp&+dW^`y|~}0N7!j3(c&G`BBp=I zalRRy$n;ory?7b6M;Ugc66-%DR*ZbJga0=!I;|U&ksg}S&cuGF#EO}3c9d_%ATmAm zzv9g>?6ipN*2q@s42AR}(-Wf8+Cdq~p&9>)H*=yc9fc;8gG*x>0(Og;G_#^mZ&QkG z4@>yH>bS5e_kF%a0$^nSZT}|dAABY%xezQ`yA$hTl9oJW?i75`*m0*E_QyIyZ?Nkm zH+5Gm0ffj#k3r6UJG+CBj4rQfsDZ}OCnfzcc7l2%f8(|; zYV7;sQZHwnQ~M5j(}KQdfDzdS=@3!bgXox3s>%Q)#JZ$~eFBx^Ia*bj05@u-`V8d- zMNv#1nV=rSBIMSu^i#MQ=Lo zC#p-(puv6*4L#eFI?cd2tYn3RkN20Qcr6?m(QRzI->RiUhSx zpnOKS3qo4UBd#Sug$0rAA1>wKzeHkLvGn0;M=cRG?}vzsdBh(S^>9zDK|35Km8|Rn{FXwK3Yr=w8WDS*`>qCr6wlI#c9(Hog(rM zhbqi~rr}C@8}!)@_wL&Oa#Jez>3LP2bdKr{C%^i9?sHc?`XQs0gcXOIA zqgGi_n{iQ=l)1e<20WstouhE3%V&3uTiQJ$zfsDvigYrIut}oG)wq*p^k1#oMZ#OZ zucWR*qX=SqNjw*ZkUI#)aXOV^-KZ0A{&k^VZ+zqQDl-_c0S!9g0 zv94jv&nZ@|LCwm#$+}sG%_RrAunQde29~ur#|?u|Rvc3!QY3;V`h#H?HS0V0sJs|Z zZxa00w4zt>ph_o8BTErSv7}s8{;ne)t!wq;OfeW$`#DyR6?op8CZaA&tVOb-{-@+o z^v%UI1zoK%InY6bQ5SObzJb_N+PZrOrqvElIc=4%yj{1 z1+ErT+#dFuyGJ`H=^?Ts`Qy~5gruaPLPa?Q#!2OykH8(_+FHgXT3wo>;-3#AP(oc& zzOkUHeIBjeo^r&nkzQIc)jVRQ4tYd!lh%{g(-PUUpzy0_q?N67{+BT>X$zf%jvIX~ zSRt~roVA=aqu)w{m}=2PJKOI3Rm8GUXS6CSZ5=-7XwqoXQvx+(wM(*9m+T$UC5sLy z#@2T|7T6CI8@b^B0xXRjuU0$U)55z{r@dVQKBw+@Oo8Kd*q~n-7GI3?3N$uUW5N#1fSFZKHU|q0Tbx}6`L|5#Nb)ijwZC+QWwr-~}5%{eR z^^Gn|8U;(+<#U}Jz&rd%bzFAk$F>4@*$9yCb0;)BBfKL+EZemq#DFy!Xjf;CzNHt) zm^uN!Ltap`>zoX9WpXO-(oel^MRU*Y13H?2V;9U((OU1kc4LA` zU_(3RvGKV_-Jp*8hF^HNX!aYu)kV3k4WGLY$ycy_C+7Fy4{srg`Gj*+EN!fNGk&~* zsY}=<;cE%CxUx?uhV3$h%8QKH=&vvVVZ3lxRBeTOF(gHkFNvG?KIW%8;8TptZc8sZ z3c)>rAp1Xqc#*Dz+Q7#zguYjF8?&a^3%xH-GZ*kytA+lG77)sdai!U2{3oVZcQk<< z$lH5Izx@{k>Bnp4<#UNfelM}T8Bg~29b3GUQXE$yi~BbbMfY6ar|9bd>`>tO+l;M2 zL?1e-0o*AB|0%4_^UMu_;$St^$gmUDsGtoSj$}dXepbH4m+LxTcfMx#=Y|!h+fxw# z#Xf%Z-TC9KM`!SSrj3hJd*|v}`YGBiv#1wHg+icrmGjhing8##9Cj9YxI8|7rti(K zb#UuPqKWUja%-c;?leJHF8?!=SKc*c@d>lueHx3W94>!Jj6i8Dfr?bDWzneWf-w)a z6A!k7H;@OLIXfy%VI)gILXMKOBoTRWJnYnD=G0`wndPrSQj-Y?c z7}UqJv!^RHB`KKmBvqx55W}*fjicn@$DZd41H}ixK%o#Pt@gimoUX6H_C#BAj|AWCWonxTWA#Z$ZUOIynqh;Y4u5^%)L&$RShP)K zk#{35jOfL&inM61irbzFx1$5BK0A(1H~ zN^Hf!*e>7)%5gqsmC1sqE;3Bj^Dq^d^#|SrdIwUVNcNW$=6+H2{a=rs1m&ajylx>r zU=Dn_D``sJ*AF8ipZU9>X6j^5gfPL+l}_Rx0bgMas7=ezahP!qq@z&CG1XD zw}tDdVG9-l1bo>zAO6kLN8ZQiWou#RG4vH$>pi&Rj>T)c3|a4xTIiKDo3adA20Dw4 z_7felnCi=QqoKUFv{P~u1jiK?! z`Hpa0M`FE;XvZM=%)x+zt=qo#z7^L+{U*Nk`^1&@O!)~SzU$Udy=J=p=w+R|z5ib! z|KrGTiSgEm&J%6JX;b)0Q#tmIiE_s3y%x8PU$@2&qtUZcaq2CYYJ$qs
    fkTt)M~dm!GyMEX2mxeLcqbRoG%+-8!&7Cw6|KKa}jXV zLiV_>{@WxFv(s#GuZnkQN}7O7#~7Fy3iGI+GKT=t9%Q}f7aKJu5ey5&&B^aRM-_de zVlFGM)65Eo&bIx@ep{3@Z;x_rATeMBt9cuH^2zN!gqit zSF56-9qFP=xXKP2pP}+HIv>SVj@A%=&LjQ%7t(ak;j>iNgAe43g||=XpgM^`NCb(ZWMCNAeOLOHJ*I8JMtY=BfzF^UV4T)EnlT4D* zTA?ZcnBhAGi*$*bds6Nmwy9n0`za_IrV{`@M~TbcI}3($5a=P54UaX9%f?V?Gs=S% zoIr*nvnD4=2%MgEGy5000PxXHBAmUL2Y>D3x^lt7%(735s32@m{Ca_G;^T&uWNb1ImCABN? z=k&b}HBM;$Wq2X)u?80e{7qnz(7=t>U^DX9Nci`Q6g1tLdf+ys&lU`4@?9318>KZhsHG(MUSlz&%Ibm01i&c?7lz4aXH}}GhE?i+XZn|CLwm`D%adz z+g87)A(r^%!1)*vOj+_e*iVDkPjqw;MU0w|Gau9i9y|J&%iHT-29_^oKrXCbzl zru2#9P+eYnzE1EshGKwa4gK4`IZaLA4OBNG!)#ULAY&#uNjG7YtuW}IY}NH8i*3Vo zyC?p1^b_5flzj+${F}=Q5<=W%|48}_j?*&1qq{OQfM}_m<(QveMZ9soQcl{ANzQSb za3xt.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

    aOx9|_^ho-PaF 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 diff --git a/cppbuild/googletest-release-1.11.0.zip b/cppbuild/googletest-release-1.11.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..faaf8ea404c3553631e58a44dc9d59a58e3c3ffd GIT binary patch literal 1121369 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�BgYwx47b_}Zyfy*e;xT}Z?g#ZJ0@EWa$X^& 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%0D>d*Cv%2wd|ARI7J-pD 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%0AyjqqA8Rm;|MBWW&Bdviz< ztWjaDjefq`>{3)737MJ!4rJhrVSiI7E@_#&c=^>*+9J?;|F{VFNPSd(di*{=|GozR z?&x^9;}H}R_VD5p6cP^Bwyb_$*8q{FN1R_&z*@qbla=DZN0Gu6P~&DXLcFplmOw3e zkZKGm(mb-1Obu5)*oKsg?%&MRELjSzQZZYtbkNL)b})4_%Ui86*y=W^ICge+4h{jC zX41%-&`BP>gI~+}BPzvC|-?2Yo0RZ$4dmH(~W}4C)b%Y7% zRH1z_$SresLB;J;Y2(LhHofph%k51?`wEXAy;%;vS4$su{lv+n>JKL)q({678yhX+?NoM+>Lc!i&E z%nna=htb#-IG@4I(!<}ur&byB@i)fpL~h@8=K16=XGZh+pUb!knw(b zk{58A58+ibl6Y47wWcKWJ6Gma{CRJ9OAyMG*O~*8Wffb3IO(Yiu84&xUk4i^hGw|6 zTO;Ck$rR9U`dS_2kXRaJvb904)DjJ;P>J-9EK4P}iFJW{4S-=T%3T4dE?FP6yeqcI z!X2>$`tAyhth`Fb5p^9%5?zMwzL%^*7bJjn9FLIk?2%ImhZ=1mkVNH(IZb%+7nns8 zWZvbo4UDMVX^Zg_#->yeT+$cHu7BLwG}u5Hlf~Z-rQ5q&KSKbELZ}$f<$f19F$IV) zD1ZqHLTJdiL<_teIP1z@Kz|OE9~O<^7|f{7V7$C;UIZrf=$>nK$%gO7;a@~*+*s>&~Q5D6xws!Dtn#?4D6j6lo2V7}CCEH=KhI6dg1 zf&^ai4kDrnU=kr3Acokzn}dKL%`_~(&>cFW79G_$z9^4U$`ze6ICZ0-O~Z)(*~Gqe zkc;;x$7fNtvfL|0^*XM#T}T{*YF{2$vR{Aoo^jxlg&>rxHe=U(ytVg;HR-J7@-~&* zDU3l72Q?yo{Ei-!*^LhZyJ(qpLai2`H*zHyx_YA8WSA^brG@sGIDGcA&S!|EIRaySL?&QX|_iyvQB0v%sevp!9E zQafh~9AVGr4C(m$Mc?40&X_Z?A>~aJSRy^@dTJZOF?EbvZl#XSCl@=CT%G5j@UQS^+yleVRaRGaZqp+6{oD7aZKfOv&i2nviyes^}-hvc{ zPApNbF;DW)-EiaBURfZ#V$KU4;u$>^|M;CA!+eR<3Q6bHLVI{S{>$R%^P_AZRQtD6 zRnaZR%|Z7dFSMKbdA0o-(E`*0DUtrWOZiqLK^z4ZCbmv8FXIv2{Eg!yIg|5H_{@Gt zwGXxs1=Wgj=_xjI^6RA)>cUIPp^i5!+)1%;iS#K$|BpuTrlNCl$tJNfeNezP^R4MG zYV^tQdq24ceSC7zzF#J!0tRbUSvTwbP7pynEuUY4lKOywp0bJA|Iuemvuce7f3msLe`dDP46(eR9b$U0yWec9 zaORggKSQFVuR*T>w>%%AA#+t)^=)KeF#!y8e~$O|>CWk_L_}{xi(S}ARZch&W_FZ#d7(*t&t#>so*cZwV-iYUP`@4TpbW`v~@v**HU% zH6La&#_HLw9VAko6#h=%U*xx-o?|@}^ANt+oHlOn)z?1+`uVb@^+wO^6t=-QuJ!Zz z0bk4P2ESV}yvOnxt-O=G6ZEvZ+x2b!(@m2Z;j19q6K_9%VJ&MXsw3pS6W~kF?4wV*2J$cRE55K)6IN&>vzsLjT0&k?w?4v!trZP6 zz$;cW2xDeyjcgdP5u&z5>Hq`qV^kUvT?u{O-;jBG0r_AdjGw+^@zE$Ut7{P_e8Aog z59K~xeGvSx+JsNyEV40Vx%(g|XqUh~Udkgce~?US zt}xfiw{Kg2oYUmg9<<$J@9W0^!-R$y(F{>rlKNre9euK@K{Oy*mYrs+`XDCj)0!p3 zvSy{QfTxsc-MN+3VxK;$t{Yc8C^1$k&>xw z1tRe=)g$^P20H@;jJJ}l0^{5bQ@{LghGVb@sCSarT&5DDxP_>YK+S~<3SU=yo^~U$ z>!}L7jr7t4(kGe91Y4dDzm$e1{k1Y%(8eI^8^;?v^j8q@0S{P~i`7_tJ&5h4*-udD z%}ZZo`2|SfGuss4!#90DLzYDRK?@3>a5tu@mN)-2Ka<+@1wspIY?rM>PpXWD76^X$9f(>WNZ^5H2i9Gp{=U& zGx25Hx)hc9ve#&PYt+}<(W@ZYpZcsMS;A-+LKgqs%TN z*5LKdkS1khYCgK5^d-b*{)>wqi205xdIQX3Rv`0Gn(R7CzzQUy=u@g&qfy7ajjMuN zmi~^Yt_hhT%gdwQ@3onMKm&SyGSI^r;f5ela5=z^7%3cSzo$oiKPXxTod#!AL0r+rq0fV9$gebG%t+ z96b3|Om1VN^u!n!V3E*QArcTNZ7D4jvH3*b;!-L5SO>R<+?h@8XrT&!)=%KyvnHBc zn4B-4d6=_*(_o?v@3wBVfOnLT#^lqfWl;gTJDkzxY22}-K)Vu?#}3OBx_afsNRMwy zHC*hj7)C{v(WNRD2#7vOEKa3_bC?We9g!+*LO>k<+^R8PlZ^WVOTa_WYkmLyGk{UI zwJ8yesQIpIiFFkq-xfRm6?!orRM{2z0`J&;LM>>^q{W7*G z_uU581x31^9IEA#bpnz4wE1CMnni>PKl>0SCuY$hqw9lIDkH$F(LCHH#U$f*f#WwB z5k6qgmQ>QrRi|Ul%j-@ht9eN??yNZ8*|S;Cqq|~RlW*3@&BW9vTYAM^*3&H8ww64y zmXKtlKNvt@5c6UqaY3FUO=^=n29ANW?tZW{&7=Xo`Bm|Up(K=aQA}@L4d>7*BqTo3 z(+a(mhRe?byV2QW9uEn3zYDsM`n+Dt(G?QF+SHvLDl!q>y;DRt)f%(VU*^tglCV5g z&7-{pUVU}~P`?f5aRxSn$C(jGE77+H2L?A5@YLzj0g+L|r(&zlaNC`Le{N80eZ212 zYsNrLf=ALZRafFC3DHgUxY%qN`v5{UWwSpuhK(f*@dpn}3TF&k5laduRY&^Qsc08v z3G+%+NrenUUK%CgE#40OLA9ga#HboT?<-#Bu#yI+>CnQk?x!m~K-wU|=jxMpXmFaW zM`25(ZVr}IyjD4q7F;N+fTo!fve7pe?kyKb!rkac`S9j)<8aea)kO0PW^y-vd`aed zN`8$p58*dOm}%;8midTb+C|VS$ zA;~RXRmtlt99#>DRN8t14UK;4NGbzHT#x-RYHhemTF=LgGquuI=szB>){Yjx8U0&- zKb7LYDo*IMNq}9E!Rta>H1(%oWns-vjd?BMWQj23s*|(^bgAV0`Bi-zH)B&igpaWx zpB_GkPPjtFkY{bP!^<>09JhEllcgmtps$1 zes6Mk^P7x?18t9IX@vU8dOP-g4NFIOhk26GPj0I z?fi~2iiSJ_bi__3Mxt&QL>k8-`^jUO7FM7{Ps}=i{~W1N4V#S0xVa(Cu#eU$&D#dE z&HRK@`r0i!Qn8%%J&}QgYP>JBX>M!5hr=9UDj!v#9AOyjHu{0W|5zBUjWqPtfApIB zNJJf&Vrr0;YH@GK?r^|IHOLQ?Q*I7YxENZKLC$y@0`^gKQU?z24MyG2QJ~nbsB$Y% zapO_9mhE+6@X8oe)l39bEy3O3VsxB1L{c-B!7p|m-P9dcsLX#g9NG%|q?3nz39$Rz zWKk*&EQ9Uj1^&77dDr_GeV)Gf%aX5Hu1W_$H4O)$$QbE(aBD~iT)zx5xMQYYu5~NW zc=3(8WiRsWZ|;kgJ=bLgP=7QxrO;1>t*%EP8pO67WTRv%LoP}47zMOar_q`6(v7-}ru4Dc`3EhtNqq$-J@MGnm< z5eEORQWj2zChv-(M2+Jsega9Wf)3Ac*%vmK%h%;tnZxvEMk^O(riH1Tp+(m^3&R3r z+9{GzHW{U)pm1WYAwr&jB$dY2_}_|b{i(_s#p7c&3*Z{&9HW{XJTIRLS3Nt>T||^_ z-iI?mhsX>%RNNT9`6S~p!{2wWeMN)iX$`KAEyubPG1VWrZ@5>&0p%98wXlNEHK*=L z-*oCYY1?$CNCT-tm zec2<0N&KL%g&e6?%p5zi6Jzh~7i=ylD#|mH?>@uD+Z=mv&-1HUe-(ph}2&QE?W zrtmc`>UP1GYJFl3``+AiRMA3Pf6qFYvkz|+u7cZcwKceZIO()-9*;esm`{$#Lh^{R zBKUk&X_F}&BQ&*M2r`=}G>g6jE*7pHA|cQ~2u}^84vr#pM&Qtm;z{P(VvgS7!Lhww zI8+;PZMG^$aS&av-KQ9tah42v2@XM1%l%{774iZx{QJ~N%qbLr`fq|uq zC+B}FZ^{$EuZ~BCK+tLGK$MzkGJ*~%=GftA)HU^28WIJFUF0m*w|a|hZrLkV)Sy<= zo|lELi?B46cv*!)_%m6#!H?o*!EZg<)plx%g|Fo?B*Ndct2mB6-xfj6HrbdeEQc$) zEC9*nxe6;}K&hgj6iNib#tl{P5zlP`v)hSzx1Ti5s8%~!{h z9#Ul`6yVi3tl&CH?8!GW;7CB7e#rc~k z*Dqof12?bX0Vy3%U*=xhyXV9WbuZuuZ&vBN1)Klf1WvF4rb|Gk34eUZo}jJ>hnj=a z&8@N+74nMbMNArm!5N5_&fNfEKDlZ-i&YMAgU^A5O4nHfqfh10l@$af3}U&8#(bS8 ze4Q7s)FdP>@`fg{_8dQ2X>9fY9E3lX*aWGioBQM!>#wd`JEDwT^@skQD$P6Z9YEvH zN#>SjOlGK0`8N7=e+ij|Jw8EI9c-dll5#&MqH5po++-Gkvf(ArXaNGIT#HR0Ge+^4 z>NW#jRYOu07ZKiRqdO&<(23lFy>{Bt>Qlg+93TE@YZ-F`z zFe%bZ*?rCV3t1}v8;M$A{jto!S`rT33id`8_$FgegTe+?pORGgNe(Xt)rwOLDmN5L z9JGg)gF9dd_eC5&*|$rhr6HG7mw+9G}Uabd<@a$5PP^R|5N5C zUpxWdU2kYiN9U$uHiccWi9YcBNO3<2h`xw9ef0o^36@8>)P>Hj4p+rB^8yK2`&JAr z?JqOid-sl-#H;gbWu=NbFED*gIqg!mkP$rpyfG++jHQl#k<%UE@a@i}{0VvUGw$~$ z`SD>WuGp%G9a?--(ZLkYU`b~fZTnA^86O7jx>H%A6kJ{keC00pvL%zzlqYtSWdYF^ zkp%aLn`ErwP#7cFe!5HELV7Rxw;+CQxKQkD%IBw***^8u;Es5*A+X(zJ5;<577woV z+3paI7^Es*C{baJVOi#r9z zn16hBa2I^P^-!J-GtqhdDtqW6cO6>dZfV&GC;XBNDaP0$9x@&{X9f=>{r%C``N79> zYUprFOX~6|=tK>sO<-`ewri`0X%0twLtv{UTl>l(Y8@T7qz0b-fjK&|WK)TR43{SQ zIf#31j6B!_oCw+DCXqe%Om(NJ+=%&^Lt~}`<;ix115qZ7%Z3^wXE+Xeu9+R?4_3*R zf(KHuTpXkZ9*^1UeTEI=`!#t~M3(cXdh4Wic*mn%&q$ccvb~=`=Z0Hj9mmyPz$KR! z$@pKtznx4;kjn*q+bgHtM%CA6dROXwS<=62a*wjW9u2%~SAxvw>O`#a)&4M(K)Y(v zM_4~IzXv(F8mQp%6wPMmtQI*S_{GP8dr9j z1j)!5W4Ckceft%gPfl)dZ$|RCa(Fr3P?CSz_7w<1kK>N;l7_9gh8PCB>Wf}=CaJ(i zT+Dbw#ceJZm9oHaTf8#F3{>TBSlotTUewvi=|vGUZ3J5ZoONX+yZp*) zruu5OLpqW8un?hSRoEs9JkZ)KE)p%3j{9# z3t20+>@)L{Kq({{O*0->gSSPjxt;|VrLH=wff3fYDdOJ_j=9iF2r;kk`a|8xeE&dP zN3>H$Of(v)et6b!VIXU^46wW5;mSzs0^ptHIpKO!`X_e4DRN7d<}*Sldr4d@+Z99R z(mjmU#1M#oZz=>lNK~kq-NmiDS?A^knPHd>nQWp&b-bBPGt%NXvfmi8| zP8dTJ6S%(ws3RCEvEdZO@0Z?u^|!++nRS{&4YngUI5FDZK~K)B4b1hwk1vtqkda3% zi{}U5i3riG<+kBJFK-8L#WXs(RtwoA_Tw^{TAU;oBdg6e{#}wfq6=0$)k6bc^b^I6 z_QhyZaR4oOLZGqtV}^(-vCYeCGMm>iFX$zA*CZ!;T;H{4j{)DVo&~)!)laek*(rJk zWEF|*hvs?6-A+U~%N5r1qAg{YO}Bx_5H}UF9_sP5uX^HR_NfjU!h4i>Yl2^Tk6Tjf*~oew52|BC5igxK zPc*O{O}s){4N0F@b5tZC6IqOe|~RtgLqod%eyo%g{`jK1vZu=k!M z$&rDFKe4&U4}nI`Ik@;Gp3fkGm*vBz4YgA}GM6}aTBA!qg9J-8_>fERozrS+m^|DO zF)vV#3qEy5b|X_$JW_4Y7F#{TZB8iWWfp``?!wP29ily*SHCz4&lkP3Gp@23u#plr zNg&CJDJNCieHPVOAglKo7zMKY>qL=%)oeF@pq;KQZD~C8)@-~AAZoV(s39@L4yOoV zwm3#dPnE$(Wz9V*kh*$-nzDwFY&j!1Zxz-Cro0_$d|+gJpC1OEx1;!J_RF#>T3{ez zT%f%sk>c&ZANaTlk7lZ4xXMFuiaroH$nJkf;zTaoXh=Zo<0@`Q-=wr=aV(IuP|m1b zW+xKLM1UTr$?`+d)E+d$P}q)7o3*zQ)vRsu3NPYt0l9TR!xFn=H*Y+^TZLzm;@Ufj zyB;w^_>^hNuKSus7B@U7@U{V6sK<3=)nli2J@Zy&a~uKXyIQ8=7QoQn(DJxZq=bs; zm++NG#oxsbFx-UMiz1?sYKWi@+ui6MPjuWCFn^mV~xsBFMS0Q)Ggspmr!>7;8&{@x@h)(aR4OZ4i5~MpoUtbcYHw z=$RF;Dy$|%)Ul{ftXqDe_|Xg$6;huj)tPubo z`RCL$uCW4(kAFG+Ws&pu3X1x{HnM)n)IZzj@gAHUe3PQ@(Ox%&lV?_0-W>t65=%r? zsSkt0E`@=)aaKP@;rR^c*SSAhi{H9-!{GJ0Sy{ZcDcdY=^Y^jt;ZPA zB5PFTsd?MpajJ3q;Knh26X+1qa@C8HgF9Ol9v?qOnGIj#>PYDf%B3>pem-*^+(!oY z$MfnPJNS4((_Y+oKrb@yQuq*y(u}er9$P-?c|GiTeFiPiJUqzMBy&onzoAe%7kCrwRKE8aG%Kl z0aDVM0o z!jb*kNky{-adWejtk`iCPRxjmu>vedF#qqwHQ-g94VVMZ{ii+f+20c^a8cdE*>7Vw z(4cdoBO$%^IK>`4D*Y75EZ*+ThNWRTw<8Ve1);1f1)O`d`-+-DK(rD&7Wsk?Qk2mL z{W@k4p&ga`SuELcxvNQ%3;~+JqE$QPxrMsCl~U6B`hr;$Cp}hpna}+9vY@{F}i z*LqXQlru8+(>&L*{01CMb^qgK%?Yxl$;gjj&qt6%b1uAOHCHu+$i4AVw1BhW16?4K zj>;Cm=P$+V_tK(H^0%dgQ(gPy@Ji0f<{^8M{pW88r8j*+?oJSgCCv>f*17b&_$`;Nz{jI?GtY?M;j6XMEMkSg#abR*;Bkx+S8AlU$8VXzblBfs#m6f z_IW9jo8-_8XBM^UYO?9#Lh`o`b8@RybJMVe!YCi?n-r3x6Nc>>Kqgu%M)>CI*U+dP zA58RFm;KK5mC>o#a?kF&Bb2%fRgV!U|4FqAEW^LxC%eZqFio1)wrA!J!ElUl9cqYl zqY%cO!K~zYXYd_Ls&;d0+Qvwi{;{);JmDgqMCQMm1M15V`_b31={D@}*N8DYlr1oXYPK@U$-;>qNKk^$d*0;>8{R>PoDxmHL}w zB~ch1u!_}SWzy^YaP$1Pz=lTXb9Xp>AxJ1~%?CO@#9R+)70}u!V>nvsV9IjPiE0a` zovjwE?h%Xd?4URgK?zN@XUhOZRikNVK!S)rH)2+x=KHM8r)Y{XU_s+-jlDrfOVusz z$x}&XkzAr>cU`8khH-xBSScdKG?J-O&z}V}?KQ2Q@aq8NW~5IP|DDAO@N`465S*s-i?1(Yl<*TA zZw>&>S}rpG5~aG(Ow3fjVG-ODgD~-~K(S)A9jDooSoF=Nk8m}wOt%S@W7e$d2N?y~ z$?oGk1X&NQRPhb|uE>R_HrGETmm@^Zaf2f6`tD`M0L zwH7VCT9;dQ7ArCH-y;qeop=N#u@(Y2Zq#J`$UdAQ?8rguo_x5~+~IQm@W?2v^vnM~ z=YQI$pCuu7Wd~H%=|HS{>F=Qx-HBrinZcJ3%*1ew!T1pU8H{X4p|U;F6}==(7PEK% ztHTWplL;w^z$4s#~nOznV5HDB6k6D<9O#i0x*tV1s~e zc?&-y@p~9$7hh*#xK=vHS-p%{S{gCt_HYc3I)d2GZ~(ih=x6d))tc@;gmC9uczX$& z6^7UM;p!nV=6+g#u`UJfl7)VTRfNLIJXQpzHMR002M57dB0OY~+o8S}KMnfwIxB_T;9-nUTrKXo zoxpB9+07dH6^^dI5AQSUuL2M9mj%CXvA&{LA-Pv4u3i#jNZZ22ER z^1urEt9iaBQu9n|UYlLQH?W0`_esIPf9Nv1wTvii@%C z>;PPwL-T5c0Y5~xuO?ShAKk#;yU_)<{)eCm+fP@fm7Hf?CPRh~`}U*rfee}t8U`gz z%%g=)s|lC3tk4dve+VP?(IVyFF|u!8#aI$^$8!1V%w)Hn;fI{(e_`#N zx@?V_b<4DE+qR9Bwr$(CZQHiF(zb2enJZaYwOc!Ff2VHhv|WE-UX2;=7*9m>9=h-r zWHo$zJ@}8C@P#VrQgg}`reFQgMZ1$G4>gqfiC@u;s{@*^0yLJF1a{BJyLMV(51&Dt zadZ>XE|G}zpB)3n*2t^c^T!&*u=4k~Z5S+9_`t~f0RNcmK`8{EBbU5jjx}OY(65*w z!!RF>PZ@TMz}d-vctm5~MuupGiQX1a&BR%gL0y@{rS38N(|&*}b|bl_mo9tIWc5MT z#%DnQXgOtP^9`SND&f3}4R__QZEyiHq73;K2N7He1g~f8uenw*Ic3VP;95I+`pbWH z)a;_MUJJo=0d)PzibD~<;k;?LB1UeWF0*rtvIuf9pumM|CGMHrD%W~q=m-P} zi&ML0Ug!aVbQ7edT!VcHiZ+?zB0=saW(%wy41WPsM|YUKxodpSQ{aQ3cZCr*lL|Fo zVwjl=(c7rVgX>1cmd&)y8u4L16B>;c#<@@MT0}yLB(F&lmeA}* zTSY#0P<0(2BfJ|&WIn*udEzJ&eW${16h#lL8J#<8`Ua29F(ru)O@g2!Dik9|HY^J}s&m~t#f!zNI+{FiH<|CH$Sj$pHd zaAd7|>>iGTN5U8qVq`M&B3J7h%P>Eim30lz&W?>H+#$MkaFcUcqqDvRltl8QBMNfl zV7T-+Wi!j`@!iDvRDO)8uVb#0=#WPHl~N3Ly@>UO4H47#UVmg(bbLW9(J6H5Lc-Gs z-7-K^!w;9>1><5Rkx9bK1n^<)EJG(D^;GmK+nGr-+uHIN-Fa`g>a=kQo#5Oc!!g>N%dWi^w{7DOj&ADJwH37e(_Q>90b* z0+@9dJT&Ia8>eO+mv%Y)t5ZPIR?+%?K9KSFaqr-BPeWU7Oa2u;cKsL2IU z(P10prVZFXZ>t*CkO+JO-7#u83fiVGZbygxm_+}%ZrGjB&^xrIgakEBf~uLjB?o3H zgszqV(OnpO<^jB|WYlKqax3QK+e$Fb9E#F?+09$4ZC4ZVSX!g)Q6b6;Q;_s z8^l~6PX>J5pPAH_)9}?C!kJakmZV{|)cqD@bomhU8Q>VGICp7b?6p`$)m^lI*BZSv z@)#xjFC$`>E>2F5-3J^hqNCxxs27#62rJbGlj9QYm@YRlBQ1K`SzkkTVG5^v=SmvN zdS~U_VMuS!9${JXYF=lm)_G6<^w08RR45M2eoc%^BwmK8P0)nqWyJYOUe!FbrQ_tCX;PykJ%eQ!J636#u4hjLy{Yh{ z<&%E~2Pw1bEgV1tQwGn33e@u)Y|wjQz=9@cqa2bK=tHR-wRzItR|W#{P*9E-JX^8R zSMecf*2+7E(H3#~p}P}g3(l}e*sXbkcfYsYWX3MoUgUXPYIg?yp+`J82~qL@4r?0Y zI;GgQAVGuTb*57&RWEek`J;6-8tD4?7B5#y2+cT7+>`?tCX;`;3a|>uq&o+J;f4NW z4X&QemfQ^&06^k@wzBkJd~zde1E>GslmC`HyG?Pp?^?ZnnfR6^4#%V~NBb-wi$vR) zR#^jXS~LrSv4ypHl~iZuqT-S5?^oheQLJ^zy7qhv8rZO-c<(nRzE2xvXg*ET;c(PA zd7EQl4fn7eLhaP$RI^KPNHco9Z{Tm5NtYRYMH0e3(cHo46_BZP{m+Dwf{iCeDRn}1 zD3=5#xQBp#QB?A`(Q24|=tClEXbxz-KsgX_({lp%5S&&M*erKwQOW`|7!6|}Rm@0J zek4_iF(~l~nG`dJ1P1qsqaY-s^n9$lGy?@XljtSJ1+}+k$8&;INrUG{0uxrenB3gl z0d))PRBzr1))EY#Y;9e+(^c~Fh7BjJBWZ}eD?OKy`|3&BAylg5At`0%xV-!$ggVYa zR*l2~Ii4hq2E0HDwFk-*n2zF%cpj~lMkCrPJiHB30k2_D9PKFsCVu}m^v7}UaGqXS zv|Bq{^t)$6wytzKvQ?+{jQ->4C(Fk4E$RDnTy5!}K=`EdWdw{3sNs5iRPrx{@#x>l ze{iP}E~skBn)q_{#F|EsS(WNb_i23{J|^8ghkQftB*=$SfoH{|M6)dE5yhT$Zsju% zaBy(H#=v`ZCTxYgi6d?j51P59`h#PzRK^K*JNwx{qWpv7%u(zo_E0=C2dIgrw9!%X z#Y`iTatuM*{Av>wDbh8>eO97QaN$Eu1%M>fksMz#coq`j@W<|b|3p+^HM-Hap&}`! zQa9>3StEG;9>MX14Rk{YzWkl&yt&vrz#F>rFP5G94~8Kfc1^p)UtM4Vv2kP=BMEQttoER)Ammre)PuAwYbIY6j{n;y z@e|4J0%u|Kj&-YjY^KEQUOdX*lkOuCeN+Rab>Oe%A)@RLL4 zEC8GVpy@aBhkyZcT)uq`Qc9BDG`a9Y!zkZyiE16Y6l&Xd>r^n)JAlND^O&GX`_p9ukzz%H%PsL5Q`& z=_IUWALBO-CJ{O5v*Mg`tP6BtgI4u0;}Gaxv?2JuM*J#dy(x4y?0G3sZllJN5W>}k zga*?UQq^}4<;BHc;s!H^h(MPT?s zjE^Vat%tOuNNU%*68$2Pb>9a@qI~HypGvzWwl$=wSj&J);FphJui;zDsAytElapNp zMSmHA`&kI?F^h~x$Q+~oFW_jcH)Jr+O3zr^7L-A{6G?az`vMv@MWB`QC*US9C^7CO zAfeS-*bzE3K8ETzO8b{&#EP-?3d~D6!pg}Ne>N)VkS;>3bDv_Qhuq$7Tsan-hy+Up&Cd-8?7kRq@ zlyG?uakv63o3kE+Cz-Z4g1=G>gd&0%c2Bt9H5}OA%Y8D_SGiKoBU<`sa{v0!D zQaUX4OV8sGuxN9YByj2FmRRefH7)nj>A>qF_hPV5xTRMp%8c>Y?t0~vH#;!9(=<7& zl?pFFo!x8>H)(ykdVmC^Y}2-I5l}^fwSYPVhv=}?1g#4$yj)J}gkX}LIBJJb{Npos zl}{Ly`MciK(%tN>73d}>fLX18vPdioq&Q2vWMRZEepYOqg_?0Gie5|jK^XCxL+oTv z!ndvM8_uV5DByC8Pgr`6&JXhbv$qTon+@9wHaFMuCa)Eal~=HcT5hWUYe>`F=UbDa za|hdBbkFx#YZm$v$W^E>mYy5K#MCEBnVILnGw?vzM%@nlAdy3dIaEg9PknwnwO1*M z3{sf@!&S$7sR%Vmj~s3uTIe=#5d8Y}1)7^tP7nkte266}8R-al;0qUZG%{A~n#GX; zHq+l9O|!LGi+61#ZXELkg*s%uUpvjE2%{}KX1*1}>0B3YSZ5(cs`4VWhPxu!2=5ve zVz&mR9wzwv8EFd@_;e;UVt0D6T7UHn&I(vF*aL_{xoz0<(y=GWGN-&+d`pAZg7suo zVgDUKqwolia$yL4#o$?MMlo?HOiZCxb`#%gvd87(p&7T@$p37`P=p6rWEVW+44$nL z8DxE-X4igBSHpzEtpqx&{d4v$x}vg!Hy>NEyPoQr^q6eTorDS4saDD!=b*dz71Oj! zzMnACd=3(Xu#?Ktwt?ER+ZwS}dPF%A6)0OZe#7$gDJZP0_SXMBlT6wn2@*6Csq9aI z$t|oRHuuHsu-JapK`B1YWF%h|3Ei!iQ_y*DaW70TJxTVbbHf5^q8uWTQTdr^76~{V z4kJ5{*nW=JnH4rrmrzXT5f>T4XIt{$OQ``%U=zU_VA{2abBSf4b=_a@-UjDNJ>AG} z=R()6x2$sW0~I77dybcp?la5p`H%HIg zf%`u#kvcjNX{r#^96Hqq3|*sZEzi4k*#sNY`Y|5ReJtZf+$14BE0zxj^yK=Dl7IU4 z(tFb7RL?dM`XIC6_C>zHY8_l-flzR4vC7`g58czYfAYdcn4eL^oVJD2T8B3@2<2_3FL6YNtTRLiEe|65;q6X9=3YBB=4Lb`h>XZS;}0bGs=d zCrKi=tQc@w?k#fCq@+n){f86>r?b~~+6@z4q^$LyhOf2-=wX!2vo??5tv9vFlwuGH zHN0kk+CtuYL9N)fMbZP%CL3J@s2R15u&qljqOE&`iJ3FsZ;~su_4e{EUr-B9nj37v zyMAm0+Al}gPw&F`ME`dA4RMksDiw7X*$r*;G+L%kF;yZt}(-`H-o~0(O zu6SwI;HDYA3`~jYiZwyK&w%8f2~n2ay0wN2cT&lm`$qMi8Ff-qfh9sUF^p#o1b&Sb z`&Ba1MB`rdJ@T7Xy<~qareJ$NnM6bK!7#!S>cCng3&)9YRft?1P)0%=C=`ckg}i{B z?f3!y=OujqEKZ;D*Sy5e1ppxX|Jx;8&)MWZAp+N0zuay%G~d%Y4y#%9#L0yWYuyzG zrm8X7N(-8@RNS^KQ}P=QI=k$=}-a1e@1w5=wUNi54jph$fk-lyE{6PrI9 zQq3Eep@wl$QsH&e;!t**o1vl6bt)VqkRQe8ffas2Paip3|T2CYRstQmJDe_8smZ zDwp&pRcw}X3xlmP`qFiR;=z!n6-3Gn5DHCwmk%2P;HCSaKJnpiP z3A;iKtU|Aiys=O=0hw3yKQJ+oZ*Q+<$dddutbi**y%aVSZ+mRnVl}Ue@aGLTPqjs~ zt>iyvNtDm5Ua{1p!JgI8r=!V&^ZG@Ktnga)k5I74YX(m=9*aZd z=nHnBywHb+3=AsV! zR$M$07rFXmbHhrB7zHn?i|ZZ@iG+;gtHaO;SdWJ+MH%DS=H`xHYJww_@%5PwfRqE% z3%B!OH)e<^=QOOO_6n{DOihEG!#mE@O1wUWLy7#(!X)b%>s+}+W@XDxgh?T&S~5>z zlX1|Witw85YWE6GJzlUOvcML*Gd)m@?JPg=0D$h1;}BfLv$7C{*T48Y3mBncqd84| zcL~An^kf>&O6=}CX2IwF$PU+WUK#<={~@Fj9C@@vfvT-Rsv2nxq_7EfH@OaK=y#y6k-%D~R0nhyVnhhV3H;yZNZaHifaM6Ik98ayU%FgGoQcZ?VRl&>%9 zqMKlICyHU^A)r@Md@^dGPm#GSB(64O-m0cW1|>@TD;+^AlVvMzCz-|K{{*nWb=Zno z8XcpLkBC4{QYmdW%Pr-~nOov^2fN+boUq{_0OBi42p6pOSV-eXnvZzo3l60+k5`2N ziXmkg!K4G)?8*v8H2GmJ^t~hU@r=N%--98OsVrA);%(r~EQEC}sjEyvF-}*uvgkSh zn9m66=p16kkK|&ey~XRPqdmPwLgW-1-(ic%ku5MOj*1k1#|#-w*eglC8xP_*Kfn>J zp%XTV*BIjmrcbXt7;<}D(h}`cvDgdvP>z+u;&+RUv!~;zE|ks-ewQBxtdKNnf%@oH z_0qh5#8VwsOyvxvbwKS1^~ip*4_a!#mGkfP;BRdrIf^ zo8hL{50}KB-fM?7V}VAQDwTlhnaCB4Ge+9~oZc>DH;9!Qjz)^oXdxjaVM$5cOtOAnK?JQm)R4P*A=1 zP*`|HDRAE7cSu~xx-8`|LGxiw+8!i(mBM_fIn|*g#t^Yqmy%E@{3#{|)~^J^uO`Bu zkX~#nzbt^pZG5%TyTS;;*4a5g)_i0g#xAw*w|d)fvYi2DSuu(l6!m~1NY>EcXzyTl z(@WduXV4Cf!?@9Fusg17bYNj}F)472jt}PGOOBJZjc>u`=J&V~{%(ZOyl=@_s2{DR z9$6D1Q9!|NnUl`?{^qk89<~QJFKc@~x=-b=8mPbNdR2d}cql$l!&9^U#OzWO{Dt(1 zBTmZqeIXgv_v@>c(wZJ#&&*iz5vQ-&|Qd%(;$5;}7V~xhcnj{uMq;x5N zw>?Hq$bAP6HAd#lG%ifac0Iap1EJ%V(Tq;cga@n5AXXI*F3kn1v56Pc16wGVRAA&h z^q1;qN@M})vS{|55NcKS(p<^@!x%mb#fj@+csCph2~t=^^($&0StTtczq;PI1h0Z~ zeJyoG=X2E_2wljXk;4|g-OMJ2Clwmpgjk^f?yQgY#I+1kFH3NLJJ|35@bXHxev#h* zEQju*!7GrmO=5kO2%CNW=wkiSW7$gWZnkTlX1#V%1+5^RPUNr=zC5}rrxNjuQ{N0T zHL;EhbSbo#;`X0YUI2cfgXPlUGfX4YA(wdT^N?oE^WbA%kuWUR%3_E#9dN-{Gy#_9dNIBlm?EiCU_GgW7LF*$RnQFgAUrS$ z?yL=cH?|*faEh9qtu^X>VItX_DoNFIfvSkL#87t5&!7+6ZY?wPy6c^-*d<4aPQYP zGM$I&?%k=|FYU2+7Hc6OsVk@L_SUH;Z@hiC#rK6e_;~dLt*!!n()P*6T%uo1`+{Eg zP|Fd?NR?UHSO!O`Y<7&~4Fof2Ik@6msXfEu&cW{|?FhARLv+cHeGJ4utXR9E8ZaBlh=khjlDBT9HR~{Tv;aYQpbWso-D7p@(0Erg&9sw9W=WQVsSqt zUJ`)5gZ8g-VmnVt&e(D=&oyPiQGz-!1BrL0;G-?4FW^mC&?7dTe;@L3B8;V3I^9q> zT%})qT4$r)f4tw0Kh@q3zjJ>gS=pgA9=GcVARW1PYvQ~#|G~dom}y8fiwgbmNW#E}~x#w2x?SBdX z)F6cFK_C7LDt>Y~T0^&)_7)_VrzO;~Cqc#}q)$mDGLd`^h!Nsau3wk3!Zv_F1tv}N zIv1f%`5|G23+&ft__zzuZLe*Pz^0$z07poXJt;@pBy*mc31TdSan+Uo*S zVS6ZvJ6t^hS{Ep7rZ$PS+{{OoUelh9nLo)n+%7qE-R!V!Be}wsMHnldHzKRHpNW1? z!^YBd9lXSIE$GK^GMX#|e2T~x^1)$OjhOceOuH_sUH@m^E|fq0i0t_m#vc>PUE>tV z6u?I**71kZ`b5W2$FqdA11%O#b41yriI(h-Mg|o`=@-l>8mw#4It96K)io(@G`NCt`x(fu&GhgmjBj%8y3-csanZ^{D>y8y(B|? zh{igFj1{i$Fb3bR*55~A-?Yz}MEii+rp_*=@9o-r&#EdXS(ul9s<;OahShKn=;+U6 z@OfL?9;zDyg!!XuVx4))Zow~*`T$ZWq&^@l(UUC`R82{ivPoXQq zHfU_nY5l!-=xNKwUyGF!$DIYQYx^PHS?RZ1dCY24`~}GT=lgf`@`~aU=2r_$`aiBP z&URKNwiccy{~ex}qv_*yz=rgbCs&YoVvRJQ^|FCSyIBOeerzG>8Q|=eClfo00l0y& z*>VNYv*YuUg*jfAZr$qZ3MpPRZ+^mFG(RS$$4ZRJVm4so_!{xA%l^0{rDy`N>+VyB zAhjyqMYG0kJzNV8+oS(au%Ezfoh|~@Y>H?jdv2RE2X?1xP`fsCR#)Pz#?g#N-vFwa z&u-&>+)YK(t~)^h>LrWjlt^IZP31~2I2<>K|(Vuy*eAN zC}q~_U{t?34+n6B#Z=CvJ*7sUUz`YlRnB$#agabOD=;Ij)nK>3#-zWn-dRCkmO$`; z&Pv7;+WrU>hkXV#CYT{w2&c{PL4RQrNIw0f$?|tP?5N6%k{=JwYQSjM{?YaHc5u(- z?#_!?(!Tzbt?l~o^qC_E=1%n9D(Yn%UwvL!(InSlK6QGi-50mILz z`g`x{;0fgk5maAvGwTuTNrlRw{!(?0%%2m8oZHU20?-%~p;3bbXRf5$oCBu90|7)= z9%F4BK3n#A?mSt8=~$`49H=7*KdMiQdGqy9L4g9NPy>NTEwy=of#Go8#Z(**tHu2y zp$(1BJvQ1KD^^o_h|>-MRR*xgm}fLSi~^CRUqq~$Kd-5-q2Ew0mH0$@sslR^Rv_zT z0xBIP-21%2#kfw~?ToUI&RV$?4qo_&5tWgkpL94f#bwM9jrP6{1g@o=Avqs)Az;guJ^|_e=nP5 zN?XwD;^cnTJ_(*}@t0)qw;Xy}5H$gAEZJh#=K1oojGv>ubQJuIYygG}Aclnv<~!g3 z?Os&Knj_>Sj+|}T-yOKx&|7du=*4!{KD>Fi3#G4o_;*h+{HNzkKHHeg%wUA^ftC@3##SKFm~mhKG>uIIY9GF%#uKlK@(Gbqav@zCAr17}2A9 zNpqQBHhbN-eb_0BAtV9d0jP69-?11L3~c>-W~4OJ~oq@SRNDe z4nk)SKv=L=GvB>+geLuGCx{MLirhKXCD^4sVNDc?3ls#8R);=42>%{OobAG98OePv zAVl(;nY?}A33p8FNTWB;99(eLAl$M>HMoT3^@gDz5nHmS=c$W}aYswZiE|V|i2ELNXlM$u`Q1Bv zX~7}oP{}8{CrOaX$WAP1hAs;U)JUsaY!iiq+5>24hfs+7`T&L1bdRPQjLtor?1AYuYq3fQ%CVN| zLHotYeUjM(iS)JNr3e*tZHy1GylRTjN#rOGX9$V;s|LHP>nlLHlZ`;D1uYq1Pb@8+ z0zLtgUUrG;LA8vHqZ$FLNS1|%Xf`Xs3qthh@yhiMUwB#8;F zN;!ZPlo2mEcHmQ)a;0EzN3i+h(UL@2PlEPlcrZ&|?^94qvl5_==ypR*?mH7etV^1q zxhi=y0`7<^n&@HvrNUk)abn-}>1#`8I>5|JFXGxn9;N%FkgKzp4!13GT0avml&mK$ zbYjc)=y%%lP)kQhK9mYC;YJgXN`EU`s1D9GJcMtz&%{QMzQMG!pUf%>cSAtLfEQ+4 zPT+Ml;#3TLQDWWqA;d$7f7~^ivP(XvDJs zS=lx)0Dt6KitV8AME3<@QPpWi|ume_1AXg&|t z(DuiZFxF{tCGPBEv;45)HB`viUXFNWjVS%p!ev}YF_py>MdRcivha&g^qRF+=XAX3 zdyrDoYpmbOF!S@#Bikylroa>^q#R?5$^M&jkyBR@Uwyx6ZKz=yL)fOjcVOywi{%wb zunSUZc1`E#UFBNSKfT$_vd;xNq7D$Be5_Fv2fF*^tNwCI0DT;aU~ZL^n&GGdunj>82j#LfuKYMU+GCe z-O=j>)%?umkMa~b$5qwxYF(9jCIovfQpu2%q{vwMp>zgu4$`RyW875z&S{v*lidm* z-{m_JaafC7@Vy=^vnp^sEehrVowar#@J33n}uScH4DX*q|rAESJ zV~~#|zCk7h1P6U4E)*h4-a_5%6&4(t7Mh8JhLsqyo07Y$!ZL=%C$d>1W9!nd4@r1&Q|v4xWREf%fm!jchE^NyivyEr;|B-NCiaRtVKU#dUqkH;&`3{8D-d?=*xhg6G( zB)X1=Zu?5OiYMm~nKXI$KX}JI9043xEeI{~?fd#z+&G+L8C0incnmSPu$=ZqH?^36 z>q=1Y4{%A8veeiH>{$;V+44T(m-HBVT48pWkV=pN!IqN}*DSVyDgr z{G8tXq*T%o^R%X~<+R{irXW=~JM$scUW+)*R5~HDWI@kbRafe}&z=S}Q6uKt2lk)2 z5~$;qzbk-NSO=4mh7Gc1Z@4fPyj_`Wom={zY=P$u1(Az~vj(-t#JgPh81k5wDc%~>pPh!8$Jp=N(z!Px@$cEFEM!I%yREf15{ z4hQ2Dqv;iRyZ++(n^c%BXN`4PYzV`p1Cglrl6FCo_Ddo>wO@F6Yyua&p7Hv!*&_p> z={wI}yc_lab;ag=sIj>J+HFzqZf_b%F{M2O>Bxd^^D;hxB9efsa~@em9Is)jtO~?4 zY*oBBX>0JUs`-H81&}Uf0YqfbjIQr{0lpOi4#=Z&o9!?urg?#a1@2&tDL))wbD*}I zFkGkKB(lE|g&dxdqIT%}c!sq_xwynY{0PJ_BN&b{ED&PTqd~Lk=;zyBfc6YB$U%*o zBhvoUwQK;7GxVi$Ln7b?-)6tthO))7huV1?UMh|BqY~JV|8k3N}g2YcDSTuq8@PMF1mK2oyHyHW1>Ct&N4V*@5Wrwl4Mp0p8A4|YECus8ZD8*tIx8*{*LON< z369Z}G{+uQx`11JHH}K$0&~z85ab@kpD=36KCs|3j{0;m~$Qk1W4Y(Xat2+8~1xvbfU5f z)#Sya)B%H85ZAyCBUBov{;@4a?yCH3Q$`YXz}d|gGVEO$4^;=y2*}nl%RcYyPno0A9G0ZnfWX4utX}gPSTmFv$NeN+KwQq5P?b~pS-$N z6hNPZgk4)mSg}QnWYKvyw(oIt+4m0ZOnVQfTRb;W;JCsr9!v!mhId}RsdHb(L{ko1 zi5{{)c?EC=4+_|ugz$mYO+;NGve+%iTy5SwjJNuOyzp;I%P(ZY(yv4~k^!R|p1sfN z9sh1E_wf-g)_@*0md7AOtb&RcFuJnEyp5cUhhBi1J;~aDCOT{jrc!1*8erY z`fCRI@8N+>qKw@p15D`cH)^(%IFPaH{Nh{zcpZLL10CRjv#4Ak(PAuv)&faK?avp* zDCR;<2M5x)8oZw43*mLP%&THaxo#iKcfJZsl&O8uw7!YYoxO*{J!G$?4m(5#5~Q&V z@Fs#|y=d4A=%jJAM?6r8(N;`CL(_O=BnmAbz3iPtTnisS_k>en2)CBZ~Z;7ZL4MZ_z z-mf-~?LlSMUDGRFpSAweXtr#Zo8D=5E6$x^)?YBYkI&ao@!f@Hcgt&ia`8-W95ZlG zL+k)4d_bH*LaK`LdX+csG4hw_&5;{`L9Hot(u;_?5>zqPC8xgK|LQ78A`duvTM{qC zd`^EMHUeg{m(RjcdIY~i`>a&WTUJ@}Dk!2LRW;z(vOimUXRSaZD0T^q?Y*I#MzpXw z4gXX?7=o&4#DWvaNX4x-fE!mKsV#EM1qf|9t`ipLh#?$3Jqv6h!(uof$LE72#EWSe z%O^r|V@dEJ(4s>`O{_bjDY_avK@Fz34T(2;ym<>P5W!^Ff|pMYXAbQ(>ljO%jJ*js zzzw6Rgja93$iOP!jCK0mXDI!71hDW#D!qiq~o6TV-@f6wnS+96uga2@lyu5#R=so=PdVRlG z15;Y$YQT0@o3j4l9JGcYyzDiv-iWd{%Mun~AA*~`9O_%ctL*ljv8Lm7&@8mN7F2@y)d4_@5tU*a05 zzn>$*Fwj=J$-*}`81Af*F5A8`B2vGbNMk1|Z^ca5a-##e%bEE(5E4(C7+EnY`zY|_ zZsyDl8x9Yu#cF0&xuhQn10Ey*)V69zO0z=juW|fUz3gogDD0bv&d1PKIuo%5D$zHmfZoW<>%Ax%^o3Xi9Ys0Z0eXJA*x!5VLeqO%NkvV z`yOP{Ut!fTeQin&f}{~DxMM`nm_e9N-Q+}YXph=-gk#lvqQ8U8ej;J<7SUacdoBq{ zCr-EZLRS!(pAcn;{fC+RodjM%R*dU}^F1OuWd;%~%n)5?A=x!dy@nnG6a@tNVsz`c zcz9{aeZme`5Hwm~*Usi+v^c8|KHOsa&H?mXH?d@>4=TRl1?onhcXRs0#fwxeKnULkd(DpbGB@r%i)jAfU# zeKY^f!FbNt8}oD2dlqmiEED;8ZTqJmUlyB3IESCepknUKREPx%g805dOPji&Y-ZM} zIS%#D@Y}V2f*uzL1}`u!%ZqoMhkM3?rW{3mxp#sK^qu74i%q4=c?v|Z73pKa7)49G#4p zcx6r>4p_2pSZ2?okSuJsL6bj;s4M?_W)Hilyc6=<5sXCv0O0>WuQEmkj>ZhX*fF%J=>^p!THGs%tb$QmrWi8qf5=RaS4 zt=7SS$4Q(#;T90QZe9MZ_%N208DE5@(e!rFpS3kL?Rv2+ywfQdmrW+EoKs>-2s!2` zl{%*IR))|1n^027M%U={p$ltpvEGNo@`Sm(N(SJK`}nmMZ5 zL7_3JDRM`p7fzioVo-X@Z*dJ62%d9D&;T|q2*DWlt0P6T3@ic9xItf%s=&sjltP;#-)HA5M|kUGDV{Rg~0 z-ytLTUeko!4me;SRL_#2o^1nQ3k@22ZQ!4py1Jr?NpV_Mi)2(i+y>=AfkVTjAcxrS!1TbPeGP^xafH8@8#!ZmRChBC?eIBG*af;K#SA`1fkX+S zENU54ezi+M`4ij%1JEC1!W#R2$07Uf3TL+7Tb6GoHFK67j7H&MvT)9x@p$cU8mtQt!?yTWP zDEvw57Um4ChMx@YqJSg!Oa+mT>^8ApK4Ki)=MCm!sLnR2ms!C372_y*nvV0kcG zIc0pOL@!a~N#?qHOPH$$+^xt7YHoY=?UYN2<%Oj?pv~+U*tk+=yNh?U1|Q)~_R&z@ zhEVc8fF5I?hHU>&D|K*ud3 z!S5v|8=gUWv}mU8O0tS z3fouO+bA2&Z_XGUJskE&T0mwNAmJrpC>(Go9(dDUTDs<(zK8C0mU^ACsPx@FVF62j zFN$7Q+}4gM+{tHK4VDk#!ug^sE9g_aF12pcdTwv`S(r>?c}TNJ18%SJhCfDL#+;?Y zAau~34L(&-d+U72YlS$NfGx}oIYD67NVQd8&NmXy6)mTev(WXOBEcogx=%zfpx_sjM83${stiu>iuyE#(q1SxW^36EA{h+U^vPxjUB z%X=O{+y(=va+4*wFY!vYL+x~BH4mmT`?j|0K`s^tO%w9#Sm`k?E0tArUbUV=gW+h3 zT%t9o;rE@|NMmpk9k_1yqUiV+F~9n6Ie0H$sGtlT<%4IX`q%6I9v zwL9}3KDBKRP$NE}A!@<}a~Fp}TY|iFaq(O_AQApxm`(`UF)SPN8FDdHds$DPeg+>Ul=1Kb-pRIU zG5Hav-02SP8C-$)+2P@R!@8?J`~b`*q=f$fe9FRF;Jde3sNK7sak+57t^KgKw!G;{ zN$w6o1z)2;)DJqKJ}?P)Zh3&rTP)I46E-GUuRv#?t56z85D;K>^WSGu@4b-3Y0UYP zI(K&W-66e{H^Ouw`5fywCY2~cp90;)`;0*Bn25#Xq`A^I%Z|Y z6h~v;dXLwQ9t;V?ia6hQ2+Hw)EqM>-l-J;PDs_+Vjs9pl2oE0zM2g{xu_*sT;?9S1 z4$}gA|Fb;nN0x&h$p?*L1q(z&9T3Cn~!`7f>_n%q6#xmQmc&2uBIYHKz-=}LF2H2)wcL9PU2phOG$(;3fGGCx72xOw`Y8ZBTvAZuazIT)8|pd#W|rn8|Y^I z`OUR3x+Cp4?&}}D7aN^LJvxPYf))(UiqB6gH}s!VlgKwg;mgd52(({4d+MayuS`Xe zvKmKXe={|I0RHoN-Sps_68zhq_xRlr75G2@)LYm(n>hY{>S_NgGWzdt3k@r!O>wlZ znYy!kWl(Gwk|zAtiC}9;Eq~XT=?x-jSJMg7Nt-V6M$M8`0%P(YpV^*mriY*@Wt&QX zF8ouz_boBEnHdo^v)K+!8tD7Q%{D)~D61Ou2oyoAJiP22NO}nnIqU=};zu#gB8N<@ z@eC%>+ESAOXR1PHGD+eP$&h&yJSn`4N|uSdVeM1uMKrleb*P+2Jsq^*#sy|pH3tz4 z8^mKpVPKWtz=&)juQv#L=Bc&aEYABqI{Vs!aSoI*1U} z|4I}=R%RqA+EzjURxUpEIuR0^97_)!Nf(JK;jUp$3mB84RFucGMI$^Mc5xw}7Dpla=e9GI_OKj+omgYf=Bal>=x<$n_1Elj zhrq>Cf5v?ipd4b??e4Oq*@wad`-!kEO{1pqu{_g#@I@F|dG(LohW=liokL(IT$rqr zFSc#lwr$&1$F^;!W81dfv2EMV{M(t`z3a0&%c{4k9@CYnGWu*tvQIkz_U`*OP~JWU zfw*Upf*l0U%dc;|YX&Oc?Mhcz>_355c=!r$fd_jj_jXese=hjoJN~DUXNNVDw)pS) zvHZ*USuuZ3^RexCU-i<{Q2b~JXxwnLHy=*{__fdh!Y7HM&n`wxcx}!{2oK0CueEIx z0|W@ursFsPTwh|#2Z%gz9p0@sOoBx3bsPK+6WCkVp%3PW5SI0N4DXTtz8i?upZv?k zAR=HsP?NsUA(+u-Lc@JS(BYk?{}jnwZ2YBl^2~n-FeF{5x>qK`?`^L;BV5jp`p-^| zna?r^h>#<|oBCMZNMr<}ZNv^mj(=&)$h;_2skcweS1g$%%cx{i92N9L2cTbeMva<^ zKM^y53)yy9WB9#W7E`9CQB+x&Sdb=-Q1YPyD9Puf&~WnnmYJTCYj}!MuUphB6(bg1 zFe-t~Ybc8O4rbk3=FgA?v2MKVmr{wNav?Y?dhu_jbmIF0CD&mc#qui3!df;xP7B`c z;Q?22*%U$xQS2~f(J}-Pp)=!EuyBjkWY+n?P@LkA+@61-T z8~e5NJx_i@#8`6? zTzh-e=>_r%7OIfJM)%XVM}6C~$b!Q|X{{=-V0@4kI_y*L(Hz{Cw8v{h3mcoBMJ=;a z%e&114*r>1c>*(i#cvGC^#~H6(^g~>P2vGkPA2B)hls4oN>{;T!bg+`yaB>iqZmZL z5Ee}_gQZGcr8zEw^Nvfpx!SLToG%LQ_m546r^~Z=1B)?XEonkXNq|SO%0z--chKii zdcK9rC{pVoh%& zAc~NWKw0N$k(=@Oy)vlxvHL&a&`0{(5j#Ts@^6cwoL|q^L~@Kc7lv5mczYe3lfwvq zu19Z*%)$LsK?4U6mLf~Sfrw1zZ&F(aVyAe+KR9zZg?~b5tW-;|PWH{(yp;|ZkyciC zEVB`3lnTwW6WcT$tW84La;Tiyy3nB|xtM&Upna*7#<0_hSS$wg15&V$w~g z$~)Lg$acC19{3%@({8J8D?+K=RyLKi{r&o<5-qYo`6)HfOQUeJ*3=OZ>B;vt#fw@f zGT=w{-{s#zylTpFzT6D`TZ1ORkum7#O_!o=pewx4vL&dg8iM17W5Xp|FC7`TN&Z{! z!VS;rT!0ALJlP;Ff|3xeOqCXl_B2gf3ek{CM`mNY-`KYuKb7azrg%#as@8jjOJwVj zN2nI$5hc-3pGVpZ!^2BVT?EB@SP>OGHkJHJ*Ki!hz(hyk0c~$Zg^Ijp$pfS@8x|sBX{?*Wg)m`ysz` z(0N0}$l^SgEZ&!L2AqKB_2m$(U2?9P&tOE0D(s_=$&Fd)N`-nTw$F`amy10uoL`eb z>QU+yQ@VeubIDir$0EZjAbUZVmmI8mxRBN!vwJLJgTK3BE-IK1T#F zMRW46O^2KBssM)~LuY{GR10zCInjXlPs_`)rXLYaw9PM(ty;1d5%ijhusmjuPU)6i zRP_jwXkvk^E(U!p>Jd5LhiuaH+J>+sa5-GxXx1@1P;r#${ugNQ(!}q`Ur%(|&j{*% z|ESQuP~}@d7fpq}t!66ahA-yu<6uhpYoS`1FgB+k_>Z}O)BsPxfFY}95yT?!SbVl` zaKxG!o=;bjqOHB?o7ak-JW^j)-HfQOx%KRCdQ!Id)uPqIbeWtEADb2)ya!Ns zFJW?VKaJ+RQ|{lmE3y(L(0lxbq}D&JTqZwiZDDka!;VI<|H zlMF85CSLSX|6<5)gPRPb^r>Cc=R~M3tWx-$sVGx?3AVb_GQAk!V_|FKlH`Y8vh!3F z@2x5h$b_b+SWk4txwZ+X6^TlhoXLHlyMl zcBy_oyTC5UUe-U6vjl8I?zvrb*yJ5Spi91&9C*f_0Yp}BLQ2z1KJ*Gx#Z ziSs0{i)|_GA1PzWCx2^nPrTOnrfWt@NdAy=7M=&%3)b;eQU1#Q%N{M8eIZ*Li9%v# zrY3q7sNBTG(SRI(9DDpRo=A7P}Vo1)Z+4mWWMA)riLJ@Ho# zgW;ileKmq&)x*IiL?k7mD2WGWn!Ty`$i^{L_*D`)VO>`c!JHl*K~Aq{CGVnb)nx1d zuOcUC_C;;7(^e0ov2O;nGkM8#PuT7+bbAS&n#sE=y=v3|op|?P%h0^m^>)UV zO8Pa(D-4TF6a=UB{BwGfPy$D5)OAZb2WXr%;)wuor{P2Wuwxqe8HVE7;S!?Q>Gxs0Sne6 zFG`DowL8hhKc*qVg^O`e3 z^;b(HPEE~%h&DVSi7mY|p;}?q2eYC+HO8yjG=wKuD9IZ%Kt2m8=!7Y>VN#jr?U#a* zCzfWuwp_WJ^@|)3Ef3wdEj>}LZX^XOP$u9M-}q78KA@>VC`PGZ&6ptXhDSyMFct6D z;{KDd9f)e0Lr`b_V{ZY9?($@e32b$W#c1Iv1W3!-9f46^P@Y+))tR7t{#VKu`mK0J zj!q+x>bMs!RqL_A=n)C3i-o)Y!JNM?$@`#zyzUeO`8KmVj}K}!m?S1EKLSPT%TS7Z z4H2R!Ebi<6DUzH+z@~v8UB=5F6I?JT0|#9YQrVc732wwts8@m z)?h~#nFdrAZ{SVBgx!tXcMb0i;5UGWuot^k z_AJkz3|l_eQ3v$6kKFqPdC?F5CI+2?bD==!y3BI z-^1_Ze{6HpVHRZd@_nV_453Q&g%yHy9Zp`BaXSweu>+>kjK_0i>XF$X!m( zZRv9pEhaeqpxS%h7mRtOuLf_ec(Kap7T^hy8dIwuGrIF;y@gT-9?YWrSZ0}OAAQrAzpV}4B*(PO&4?ivv31_TXL4$bD!YPhks>sWc5h& zoYT9qVSjr?NOs+iVeLkuJqTd|a@(VF4@Zpdi2|5DPo@aiWdt=Omohc>h1PRI0tz&2 zfhQZ3Bc}gy0q4BO{lc$@DIo3K;j`K}{Q|`YA}2!X&qPcEp6(|*bwUztKZyz-(&iBW zpQoJ$ny^_NA5r<}GJ~MCnL(86?csII1%u9&_CMyAp~h#j;Nbx^vLRs7CNB=0ooONj zyv2MW;yZcBHeots3TluyacZI*6|(js1s^A2awX!%^_;~i7;U~@!a-aA(5fH6hdCJn zg~aGcwd#ihPdlA6rvq3Gs@TNp``5h_yUFu+hfZMv+&qU3{V{;LM|Cto6IL?pPc9|G zu3HhkZ3t|Qoi4*OWnUow5hVy?Ha0|JNn;if`F(1G3La6~5lLc1-Uw|8Wigjr`?CGF z|CW4H!T~J(C@(SficDOZXI;cKm07Eh3QgDd5AQz5e~s2cMqq~nR?flRpQZ#!rjJIK zkFB3wR0vnHvXK#OEFoO1jaj~jixUQv9_!WUzQL>Nz*E^B%NiFr(vawae%}rGOJoJ- z;7Ajf9d@2#tPuQ{59zlcsQhmX%iYKzE%AtW!tIlR7@RVk(pY3zLOGjtVNoCcHE%*- zA8g@!=|E*Y1f%V?=mq^CT~3?6`99ng z4`cm(c8Y!A6M?7%| zt85ZP%0`Oo)H_?b^|^?AmYAU33CJYqdCz?DU-!h$S`+`C=5zEbHO5(>*lhQ+zzhpv zVgyYwN*V#CrhPtAP{X!`Jd-G@TPwy$z?S@Nq&Xtp_~)D~Va^swr8juJuOm!j#T!@q zD^xvB7^5?SE9*K4s0tA00w@SEys}U$RG7@goEPB~Du)KrNst{pS=y;+lMu>4JfRVr z_kQ>)^x%S%7!f~&tb|WKsmA3~ua)yLH5uLa@Lf{bLNgYgyq8WP&OAsfjU8h~%SRL0 z`f$iggA;3PK~JvbqM|9qCd4V|HTH~;sMipEumY@bO#|(m?GQQ$A;nA>7K~R{iY`jb z;pZQ>SRN3>!k(GDS)^$trh0J9CQ$6*sn0u-JvG@tS|u7QKEaUUHO*V>H`){ysg6H7 zABj~m4#IX9t}CW0A+e?9;c`eE9%UDf$u3KTO~9kj;KBY6*EU@)D6|p_X0-p1uYhRG zF2e1^74wm0fKG;;pkkPc#?7X;kkiMBnRA@2)=bQ+(1VgZu%^dZeJSgW9S9xhF@^2_ z`PlrH_s8%CTct1!+?212?x-~-7Qz>jz;(rM1PRIA6J-|eD9}S5TEOYq&j78Kmdm6P z$p+2_rY|v5E(YlSqsjvoT7gnC0<}iIWDMIDSx|;kT%XZ$^gWOBG8es9)|`u+Wl>5> zsSgOasF1Wcf_FpGyin&a@yneEF1G?qh6Jl^90|P<4z@a`ITPUUsY(2?2a8jU*N*`g zyFkV0{kUmtG8!nmWPL*?Yvo|neI=_D@&UPJp(84@p9W6 zyh;%a2E9HSGp`b|Uvt(u^}G-S@d&`a+BFEAAtk{UH6lKv2-}fprZkyv%2|*wS!f86 z++RfG9%3GD{kka>{OautC6Vp1IACZs|gzDJkkw zN|Iz{FwPUoL^_kpj}hXmfq?D4y`~f+c4e#?u^ZDc<%CpPl2c)0Nqh3kjfj{Pl%d#2 zqWl3#CENGCWS0a?W0a3BrdVF-0gYg#nvtTE>?TkjZS(^G!E6;W(Lz+crA`n-D4~&3 zIx&q_#6-Lz2`e30v)ewhGODOMIz1UNtM$Yxwqp&YypG|5C~s|sg>wZqMc3M(_fsuWxi8VD{5QKS>kxs^=y%7AarC`q97JFcXpf= zO2vYt;~9_JWpI@C^e60;dZL@QDr}7kD+KsBfd?own`@@@_0X?4?Ns&ZQpkdXAzGlA zq3^AkK%IXTM#U5yCb-@7$Q9Sar$D9uBjo-(>DuQ1OZ0dE-NlMuK?I1QwG9Uxu1v;T zX}ze_Djj;4eH(oW1fv4bYw&eE);#~SJC+q#Z!9ubmu;ec3XtRR`)iYlT_%(w#S)QeRo7(7 zmHE;1_k(;)o0D{z60%Ikvx672dPQ+f5cFE{5NXb=6elH1FIk4*vMo6?uXy(TSgOYr z62_swD}_mnv0UXCd)gJaQU(tF6p!5rWg#8JH$ll05ib)l(-Hn_lw-Sdrys|YWSV0H zswUu?oOqay<(i&-jK)(b1-zR$GNWs0=Ecx;&^@-}lgy-+Q z0$m1jWZ+@d(cXn5&wyK)JM0VBKfxR7QOK9JgRI6XR1Z zH|0HI*j(w!HdHrBp`_HoFusFx)fpe&p)qj6*)si6TXHt;1?hLxa|dm#hs=nZiX+|U zd(qV}IS_te3c}&SNaA|4Eufa=yOL6e?IQW|ccdo-Hq-eBUc`Dp&r~Fc_)beYT z53B^Ld==YyDtgcyBciimdQl?4@@wRQx6h*^ioe4+LfDdxz_}2(B2acLR%vptL=D34 z3WBh$D5qz7APA|UU{62zxZ_#E<&**yn+&8*KkZ5kUw5K2FChRTq1?77nEiVgpP_aN zj_rK*o<8u#aXLD~wCwn?1Bj9LI2L^D+HO=?)-Kv;{W+=~GIWg()jeCaq3XRN?p~NnF8PK*KsVmS~ zhgGxl5-U@|5EsHd7dgFSvh8Br#8NQ(9&Sb^`Eq_v3fV#Dt>n+3xsBEJk!M}08H+o- zrB9S)Kwm#`S_#XVZ)rgz>n?sHt%}<_dELz4cogj|y}(G&P$qNWtMCOZFh{vIzZ=(j zH+gx0oCz>nm>pSqyi&fUjR^{PP*MCVx~$hH%lZjXQGZ;8Gu9n$6N~isy#?wt?%l6P zgc`m>QTR>;ZAdu|c@&i#lkp7E$XyYt?ueZl1{k}Ukn!|m!rF(H1v6i={91%m!hkbV z)a9XYnS1Bt0&G#~Oz9E8G-{!>eQx%e1mjneY*d6l$v;K8al-pr_X{11R-8RYkGZC( zrY>`Beg>pCKQz0gQ)21da^0}q*)yN|aM#U6Z{6Iudfu<6gwJ)`a6wO<5QPsgKFomf{Z5;^(Z6~rSVpm|13 z8RW7XkTev^FPcEV6hnU(>B?3svA6=IL86<29;PkOEb@#6+iSaoImmYS51XVF?Oxb!tumgD^ z>lwa83#0DfS5@QC_^Z0`Y@#ix9aGb{zyw9^YRV^wpX!o3|3MmEn)cS~+fn}Jf-%vq zd>+kWg7U-}WL&B_|C7#^-EdJU)|X^`WuwmUCT(eaO!+p)vGdis%%HciTNndpE=X0< z!3*1m@wEpltOphh4~+`lA@H%yIr^xnD!!*nYkREMOK_^1)2)lV-bSh9y1Q{r+qevA z{Y^AontolJ2_K(i361UJ@*0kdYh>G*k>nu*&i9!H?F=TF90j*o0r zdp`__KOu%Z+r4DO+kX2b^A>q2(}1sY&78$Pd>|T;%(quUHz8_Em;M$CU(WI5osvcFM}Xe{XK-p`7g%?MUgMTV*Wt{{izzt~Q&?vvdy zrSt%Lox%(tlM++rR*7j zvlSxuAD1qTez&>V$MVczyrERtP2CKB>hA8qiD>UK?)~vWdPVF0qn3$@+WFNGzqW!# z)iyF}Z8DkVMS z-pMFUFtjm)6-+yjU0IHoP40VS1cq7ZH+}{(QS*e&UTU{|^_aCB`(uJCWa!f=XLwC} z&d7)XHHsO&uUfmDpBK57JMA6Srp@=#&JZjJlGj5kazx{xZdY}(OVT2Td^U#@cP}pqDA}b)A!r0S>+N7 zw=|Z`LH(0eN`elJKC|>6_t!BvrI}f+NAv!}6dk3xM18%RzC>wK9pwnRdEX-9MODUt zwsX}=?0TDa3-aB+8)uqA|LvdR<6X&6aOH16@Q>}j6?}}sd{@2X{DS}Q&`cqd6*374 z5YRx-|5rZN*}=?&&e+w;*7X0{$$VDMo04w3&omp^)PI|)Hg-r;MH|@)$R^EeNU2H9 z;%(evz>?&kXb|@R`K*(;eSEiPC=g=a<`xv;x@M7r|Lx|~8T57iWiW_3boovYTjdCS z8>-Uy-9WoteBw?s&Y1T0{_o8X7se|mTK0swD;dTou5Q!`=~xW?AG=rzIk7Cdak2~& z8LWA={3L`z251o5Cemm9HUBd22d{_G=iP={nXc9Umkf^o|POol2F zU=)%kyTtuXdLCq-)C%dJ8HT<@M+7kDpo4@wI$5*fuqUoKP3ChJQXnv1r=_T2Ycw38 zg@X_fc#c5`jIeT(Zt>$kX>zf0jBB!L321xf256W}F{5mq!Ns5f8PL6%fy}MYm~sw) z!eFXsGcGxx`ri*2saRB z1X-UDw@@ONKHA$9e?*JeV2bMj?I}88pZTaf#FJ)r8MglOX~=OjBKThPi9vqve8h#<$DIu?mICs>D7WA#de5bS z4|?z|{aEmXXw0awho2`qs0U+zyFU{iJh>iIHz$7=HIDk*14r@m%8rD*y8^EvX(zBecfn!(S+dM zmwZ_AVbjl@kHZ28uAwf|8)th))I|8tdZvJ02+M~H6XqfA)_IgWNPqM1jcvftysbjm z;lMp=nb|Kl_ef#_=Ao67b{~PN1QWOys$3L8rd=*soYL3SV&+EuOpFm7)NOzW$c9DvM)-^opgwzhdqYau?LE5q(Y%O3 z{)Kb9_08HY94_1r0i3*zz$EO>fey>&PHkOLZ6!@X0*O|+(kg8ok%BmAM6HuY8KFdf z0T<7`7V>pM#wC6Vq8nMParFy5m4mGLppZR!fE;wX#)|Y5|Gpy4^#W2}|7gp1adhdY8@>lT zOV42tkbb9NpQdyjDI1)*KWTV@Qhj2nZ-ttL+>xUf!_ERS0qXNk$`pUf^`2T_E1CQ7&BjlBq2@-+j?O(R)HI&>o-szK4*yb-O}`f z%^?=aXNPPm)R9j`x?m)ti$Gm2&HvlyKqIqM2&vA`5xQNl49w>bbmEm+U$Lf{#KpCA z!o?L#j_d~c*5-}S{hr@OiT`4>n6@9h;wo4c1EA=4y?~YSa_-SRtIoE7RFQ!4hq+Vr z9nsM~hirA zd-emHx<{cKXClr{Btj-PHcWrli+F)%lDDsW`r6BX%D-Nqg{55{H00=9MxuvZ>x2vN zje-y4%m;(o;1!h^8ezI4nim&v;XdTSNc+Q#z+%|T2z~%M*`E}hFW1%6s^op=%gJyM z{&E@j$R8K%*(qh1p>aaBwy&fP23}-g1VqCFfzsqD%a}`sSr<)MOxICE1fLACMo!C) zRU_GfboE3W@D0CWIoI1GiAPNJ7Q?>>y15fWwRCG<%E|_9SM>K>&mKBX7{2IX*xQ?wmD*AsGC16X zr}@C_6soZ>80YrLYX`|5%sO^R8N}l%aIVXKdP;)WEob6e_Qww8SZN?mEEEXN*^qK? zUEkcvmay4#s(uaE2LgTF^vw}5J2vhYGiE>%Z0Mz!w%E!%e{4eupA!C$`x{lonnJte zo_lDU@;enr{`BkVUVcbNJH$Y2qqrkkV{~v&7;rZF$l41z=&Ne1Fe;ElrD*6*uJMCh z8lhaEwRl)#;6tfs?5RX?JeIX`5XT z2wN}cAeQ3w)L5LqTMp96$0 z_iXiDC^Oyv7Lq zYrkzehklU%Uq8Nap^@|AMH%1suYy}05XMn+pMwi4`T}SO4eV;$KYI#V1aoEht%(PHpP3wLMmTd~x4Sd__fy1X_EsAWox z?Tw0jFZ6WV&I9#7dGo&vOr1mLEir#Wc^J@D2x$;7RZ&Uwu+;Azb}9EbvkeEmtNYIR$j%DdDggk=kIKA^sd}__KmR5mOXRxBzPdrCc4#D8*X2QcL90PtiPWVnS6zMhdxwe`4+aK z)MM8cNtOZ5Ad{tBpW7c6`P%s9r8PhUM%ak&SLk$$T@v4l&S_pHxwYO3V@%8Y4dU6PoXL_rZ?BffGZQ zjKcT2FYY8Ib4DTq_!5|=#e;DY&S+-9vep_PpGW&|sp+&%u{f9QAMq$t?k19IJaoPcs{6Zi&2zOfSv z%=nm11vP^-1yjxCFyd;_I^XN|%{LY7-QEwW&p6JcP3a*D*b69Zq+ z^4HLYl&TyO9WN&2m;fdiONvFN6F@s3GvZ``cRHHm z?xP$oo?wN15VTbk{~M#aLmLUkqDg;>HUl^VEa1Kb2OPo74dY;?W6`KMl;u-t1pmN`lEQcU^oa%8{hYR$=-*+GJ{$!=4&%Yidj)xvMrQ8@`y{2SkC*YCe zj8fz3(vHo#w8*P5mC^K&0XWw3#)K7wJ+x06sHYSUpn;l!vF^ZyqYBy!ao)s*zkT-d zm)HLD8dx`>6GitI)dg(3Hp32@*|Aa*Wf0ZxPVr?Gy38;&I9ew(Qy(Yab1E^atGaYB z&6y2td9e|Bj`g}CJOi)&d$<$y$~hT-&3}8pr}bC6+7uFI&Un!|78=qFDyo$>drEzl zi7MRB$z=@k3Jr$%Pq)q$8r30qOJYD9Xg|WCk;5yqjM3jgZIm(&b7F1uO-3OV{*Y}v z^HINYH_ZZH_#GkQg^(l%RQ$FHeM5SEDSLxu!jpeTv0397B-r!=bZbF>>>>RwcG;6O z8)&@J7?vT@tvYpp0&TA=+Mg*iGm3+AZgTS+5xwlj`D-HEK4Gfi>Zej{@zy%WWiU4- zVkw;1AeLx!4ML!R_dYp0MWV-NkORwyE&dLM_VZSnM|`18q69$d=!Q7JV_HB(3~>zzrp+}bM}hJZz8x4duwm8tpFI2K*e z(9*7;U=~22_<)}!K+ZMb;a^PRf&FLp{&1+%YB_!C9S&7`1CSIW#qd$B5_ZLHP~bfMX$P zCRmL?*2Kn-yHd)P_kpSORVBx!%;%Hyi(|IsjdBB3Am-@B^(nM*(9E9yq}!Jn80_OJ zubllrqm;dO)d)u_J7!=Y)y?kixM`o{>w0F1~A|~evQKh zL2d;(ZS{YI^l*l_Rk5&(#5EZy9z+f4(40!jK`u1~kByp-${LmpR%b+2AsslN1q>UW zAh)U!u0^^%{~dtAsSZVBDSC)UJbtyQV{%YTq9e389wUf`uR}w`w3ABmnW~AUkQW>b z&M2&eMmo@CK6gU{3TS|hc*OuT&)`Kx5Y>^~liiU|usDu*Gh0$6?tl7m!5&6x6#9Oi z4^qiY(J=2cY~hb_^U=aeNSbx_s*@QE6nIZe{_WGQHXgATdPA$9o$z{}X^zu2jAxk3 z&H`ZGv1T$W;1Tcy7U%^c<5?!_mZLU@CfNE}Bnq(=x$|x62<)+x_@d+4zNWOQJZr}hh3uA!^%ZCAtzogToBMN_fThh zzsYx+1RHgl1{6Xl;n?Se`pjZv&DdnQh6E|@lF#Z^(sFZ<79s8Z;4#%T)UX6%@U zyZt`X^0!ULlyp4#%m-lNZqoscw#VZdv0`j1=86>)xj&~emdcY5%a8( zH*2K$XAKv0C|P28{HYmjq~L~$?<>K$hpkM4plv^l6C;wX%&rh_itdCNMebki<4n3G zC2Qq5X0)!jRB=l^_-QF42)$b00OM))7R2-q7FvrGs=!d;Wenk{l(kTWVO=_FiBDNN zkuZV+dM;6EO@gmVKN@$ao>_cb+o>&w@r+Ht>C%C~RBUwAkSfs;c0aYQBms&UVGmAr z+$abyWbjIbzRU5;#SRPCm}bb|nE~F%i9K6JJXKqI({{A<_Dsk|zEDt9;n!%xfLGA? zxlHGw+ZOtE75M&>J#Vcu@uK2`u~Rz@nX~C`lpnXLyz;xa!))9F5^AFF++(-@2JWOl zin81{l$357_oStsbvo$JfVM=K%f2glh$qaEF@X?BfQQ({NVw_sC^ObSpNa;-gj9tgK#7b1U^Jx$ zo6Gom^W3hN4Dg~d-3}n`cItcFDi$oE?bcl4S?t;RwaH`65ju^W_#50D%G)dagV~(( zmMONtMK>+@qvr8v#^@N6QS}FV|Dl^a&O^e2vnTU8h)20Fuva$>@Rm(~BRXH5F>YH~ zKFO&phw9;_;hPveRQ6<@m?wqIigFO~1UlW<#%eUrDvewrsu2D1@p) z?)!NBDr_HCao3A@-WSMs8e2$8v#&_nb}bjEKz8FOp{L=_>CzdgW$o0j#cSzI+f>!4 z49dlW!8X~a76?2glvA|)tN+USo?Ieb`l$<-XQO(tuivxfM)u5*wiu;t7RCXiVjgMV zr}@^bjrQ!R2vfYJBLzKM#8^nwMrMgd2h5$6obBuRviht!)km@Gp9CuQ*F$w@C*QWxYP+R?Fw zT$^f^nc6elCxWi67o0ORbH*Q0v`<$%=LT zx-yLNVYkkNs`iNm@14e7$=c}+fOeku4;Z)>2sv5wRJ`lQDUKa9xu}T?6uBO=g)=zn zuAf()BAI^rqYl!X5RK;V-d}>&`in(8Yni9>9$Nl6S@9{i5&j?}zrTveIi8A|+?q%6 z_&(+F0;%ylcShkKt!&}AlHC0dixps~Q(^FNcW!X~r-}Y&=ChzW%O`b_^-(KK8f!pY z7&~0kX;ad<&)$}BX7cYU?`(L|V1qws??sYw4w1LlnPpXMcp2ogoKYrW1Mdr&tXT88 z2P^T+ix%dAOjBi#mmU9dy+t5zv_SM4gF;8^eN>l=iCt8r_K!^cvCxgGOQ=d9wlipz z5Ys^|OJ)}Aj4TF!3i4><1~A5T)wzpQS2PH8w*8hO<{sXx$zaN$A74jy4GtinnviVQ z4QpB}Rj<-%{@!;>WpGrg8Kz04loKOG^%y$C5XCUv-{;2wb=yJ(t70}NLx^@(LSker zQl;n@!$%wy5H6qQT2*MZST9qr)50y*@(ncOUA$02VJVsl-8aN6L}Jlj=oT}VA>$|~ z{;34xUNPQKUG%bqaxpqj+nqZnt+)j$!eKRLNWERZK#%CNK7%PlyyFNEzex@`eaDiO(NW(hdB3w4$yS_4ud(w_qFG^wH^AX*!@+~ zXgF-%$wy(Q?gLGE4P`J#3oxmzE9nTCCP#OnP5Gu?gC}&s%>Uva-q3;vUIU?k+Bpte zX>Q=pXbS*-P|FA``>R|YSw$*RGLVDRHCYZT^}Po$F)IaIMM+j2!N#P@P86TWME6?h zbVIHmRB?zJZ~;R+mboQEG6eQPCPAhIdQt5KVnaTSvzf9;Og++e=d4^o4~-Q17T7?;sEP(b2pX7p4dnpYzNI2xUJA2(4C{ zb-3|S4)m7GJZ=~k^`=h@Wg3S`DT%iuf4Jconpr2<7arW3j|MC`pDrS~awv(8H0j3t zL>xfjpwL~RN>7_!g$e4lk2sviDXV=2%L*B@tRgFkd`4XN3o==m&HA>&g^1&_Jmn*d>wo&pA-LXINk^`<&&8N>ywo%^vdol;axedj6 z5LP?-^agTt`_0*pUpypn$m1h_;JwGV7LhgPlS!)_zDFktT&8fYCFdA07tEE2G3=e* zv!n1DvqY-pJ7@Y&Qg$UY5r#&53f$lmX{a(nPy7C*lCOiuKDjpwMz*%9sk??zEV&{j z^I;dH@9;U*(t0$HJ~u#bbC)Gz1wBA?wPx#)`QsI!owOHl;2P~Yd92h4XrxzMDT(LnH9m~(=IMcNp~tJMJ?x-LmlH^PktP0q)1W`| z5T(BdZ04e);Gw`0b{-iu8v-{B%iL5)0QuE32l>xUMo$;Ajx94KbY+Ett zx0k`5d*pT@#BWt`P5P9aDIDESe#JWwIOynKRrShO%3hBMf*L2dcYisV07kqsn7l?vqa z-H{_dGj+J9(1U9Q!mt`g0!Z>XB3-?WK$^+8W9HZy*jbPoaIEAUIoyofYujQt-eXgb zC-44(TpVj;V6}Hb_M1X6Vsj~}HL=fxc8<}v)Gcp^#8Ow%S!ucYsjQNbQ^K2YyjTOD ziK5e(SAM1&LQ*L8E*x+R_S#(rcjdvpaY00oz+Qy7SjG(6V}b&~B^W(pu3Dt{m7hEe z$gW^xy$GXHP!_sY{bwihK0~ZNgP?gy(yeN_KoB5g^Opv)TQSJJ0Mj-oS4hUXy5n(n zqgXm83N34TU5HjxL^;=msW&E(Pq|@^OnpmNI$;LWpIDBz??~I;1r|8B@YBt;#=`7GcQi$O^~!y_U*MR@DWXKwc@@v@Lke3url;iewOm%Dy<8D z2%KAegURA{;V(OYjzN$rj_9E8aZ?-AR5_Z5uj)Z~yJ^t{kkGl4{;ne5G?cW4uhL@1 zfn^5Uwls}xsFtOqSEBy43N)m)J)Z{*3H3=R6Y6hL1rB~;GysRK`o*i1)$gWNa71GB zPl$K2_$s=OS1>FKqM7mf7ccZ8d4YLp#<^AjAn;3Sk?|z%53>8nOZ@DF7D38b)5H36 zIv+J#g7O9-Nndc}l|9NRt`Q7Aj|S^#lFC%1O41;V z!j6xEZv-8b79)JR>GBBDF7z(?fG%t4!74t}S}*8t?Z4U5s#*4a>aBpT0qWOSG1&Jo z>c46K0l~k29a+ovdmiSnseh?u9{X(nmP2tc=$cH-#mThy#6XJZ#E;j5FCXAHJ|z?2$f_$d*eUUIF?eS{w6lXQ`br{dZFjN(JlC@hDu%d6NA zMhhklaa}lw)4P{oB6K-q zY7$}8$?z?NoO6HmXuj-|R;fv@GX)^de8yyo!V3K4-_OAev$_ zlrO70C&gqt8q`m*7mxUKC$kv%uO3^lS5;4}`f(o&m+}LysSEs?r(?0qVVCYP+#DvA z3c#e`qDC>bqY#hWnR_afCAR_5koNpgqMud(vE8^m)S4ku^5bG}MaIl3!8!uslBHKQ z$?4v@9I2JGZ63~5M|=G!a!jfNyr#Iz>*i6<T4BTN!Ur_Mlsc1EuG2M6kJ5*Ko~Z$Y zNz=y%yhF=x%bwJ3?K`P2>eXS+R$Ubi^?=Rd{wBx4H`#s_8I-+W{#gkQ87*(bH2>a0 zw5PT#(X!%fv>i8yCQn{E2$8H${#*v8*v3`UaxT`!;=X>ujJn(jY~yj&R3&%R-Lkog|sNY`4K z8)Cjt1-TG;#OLajyW-?w(P0S4Od@*`fn$Q!I z<8jNkNPFphtIVBue96rI!u;=xI4LvKIGj)b0MB>;01W@-Naue>(`{?mIBm8e{M70N zD47|KC+InTFGL((jv?AO$);*2G+wq(n&TrTCde0u7GF7JeZBH_0_a&w$kuje$zEm* zF#~e1`MBQe1LERD=r(#vJ|FO+@!{hAmJrb<8Y58bkMtWHo{2jbiQ7AoDyCFC34}c5 zW{yxUY2;q4bFNBI8)HYhlm^F&q*gET-)CjSntTwSNOVkb9w?l?5=y+gHO@eoWCVNG z0!yId5GawTQtDiAs}-o1j0eHq$L~&J|5EG;D?F4RhJYusFENuB2}Bn^ysj{Rtos@0 zlO}o?Xv7CgQm<;jmN`O1L1@h+f>}0t!^>tLamwQ`UrG!Aqt<*(IlK)}PoWDd(y4g1 zZNf{dAC}OA?1WmOt8EAZlyLke&;%QILnrBXD?89e<>L_GLTD;BB)3bpL^npd!=htC zh&qKD#>~zU1_-$wJym!u(foUYjt(N0FGE5y`2dh~?$)py}sPNJ+8Bz2SzZ z{5kb_es9R)?XF)>ibeDYmhHm(KM4kyI|t@A8&7)qoVtAObfmAYmpKP<98K+8^yeh z=zV`112mnVuft}P%64rrj?+Hp(wk#o;ZC9*8?xquBsOLyRpdeQsD15?{-amK2;WhA zqZj3=Ifi;cP>$m%_|AKj*+W_Q=t6#~WIgCj%(cRsn zxKL7Mzx%g_GSB#o8PCjj$+x1|eLj zY;=LhiHs~@kVHjGWcZK&NEYwumVS=7HSL5~I`wVA+g9yB@ZPHTa`|2atvBv6XCmKW zsMvr=g15m5xwjycR=_BHAjlj&6MXdDqq=bNpxkpts=9wY3_I89wp29#i5cDuB;&-yC}^6UiXZmo zl(74EgDi#5px|5xi;7GfTiFFW#3r^h4jnUabrglc9YjZ$7IIqgcsl7{pM z=r9F&g(KMWi3z0~89^8I!9x^n-vjjSB*q-&@yGEiA+Y)N@?LjSSQ~i;StmTPZUxh= zXF0WSO{`x^K*0K#o9$0KAjSAzOA#BvY5Ds!qRe%JxoGZn&J6}Ra8o}O zhvq9(L4UkXe?{GeV9?sk35D4f6e@hC8(B=9RtpqiFyDn2UmYnC+)MT#S(WijW|K^H z^-8q8rVbe3%LwdT{~_!;!J3cnrolr@i+6m1KmVt{@npE{yk$7eEOEGe7yc)VJcWw& z7gP-AAlE_#OvDG9N!ZC6n{A4qQ^AAI&P3#O8r2y0BRmxt*Kv#XRB5#pTE$#Wf#9So zM4LqQ21r)sNEfPkIjFqS@hsz{dvFNlx)Tsf@!%Go=I3nRYwW8ypI%qCotHNa27zOK{J1CX>A#hN0WV621pW6H?Krd@fAybvAyY->D7bDPqrw>NYV9p& z^Ia`G_+L~+PYuz_3^alh8H3|h&X!KyA&w_17(Wvo|`}KNLFu2;`jR1IAEnIO6wbRfet+$L0!syLJ{39*+~pQiCGo&y8>A})pT3}33zf9nKu zD~WDt4;yHsN!EDAP`f5feBuC*pe+)6Pd1V^!3i#;*c^T7#EG!97`45A@@Kt`0f zeYdvRFIYyID2i;0FU(`y<|BB2g78&2|EZ94``8Ehd73At$Q}EMBWr!PDjK-0!e^01 zfxiEToO zMW6S1mKdmrZvY%;UTF8Bw1P&ObtN2LQn-ey#_>EXGW=sE^7;^hnNcCBGXV{^HQ?o| zF*)Hf(~5KG!lX@?CMRQiq?1Ko9?&TZ4E_pc`xfEOWt)a0Bj@ZrNThzFTk<_EwWBwY z@{PLqhW5XAd|!PgSWChmct>5U^|BPI$9@WvZkem{5SWe<&MUJUTi{;lxrbbGzJcQu_V z=(D}1v}>?9J9>ZBilMFSAZHq9JagrW`6|S3)>bUE)Y`htTy~*cZY{}}pxPK&OITzm zX<0FnEVtG$UaO*(N>_PlZdmHPp3N{*HKu&F+6@>pkOLi#g|_#QF(i9#VX5wck6Jo`z50KPhV;0Ibiq8{})82H;c z{~)1>ZkS|jR_k0gO5njx4|=FyDL2bv>0~sQwkz|S*kH+MxyXlduopsFM8J$VcrLlF zZ#mpwQAS41QE|WnbM}su=Hq8- zk3JkQ7EGEm!#5D}Ve7L<8~#ff7pgNzud3PKbnx(Xk=}0-qe?0uCt=HpBD#aae;N>m zTqHmT%{$`{M&SYm4UikeCty#4q)IF~75tt{%*T%q!qVPf*XoQFNDIQUMH{+V zSsaW;K$jBnm5wv#3QNMDvc*%PzdKTc`q=YpBdQTfi|c$8%`ZA*kY$Dto?yQ$mN)^H z{=AFZv!`A2j}VHp*Nm0{5C$HVkMdg*0!5ge5ymIu>AkwvOMY>N;ILZk#eG8^x!>Jh z?8OIKP>)REB$l7IOByrEfanO%_l?&Idy@bc@XnDd%C=P?#!mIgd86Ty!^5Jw^X5^W z6DJ!G9=LN#7$f5zOqt1pOZ&LPWv?iVaoAaj3E#5_HR0Ycdop(-tH){RmSxU5l9!_q zf0}|rFz6V@y(^N_iarPi2j~Zd2bd~G2w~?cTjT54D}xNk>fCsn@14Y2y)|ch-8f6Y zj^k-dob)z{@sPJu;gRXtw=4DTo;&NNGg4_fkHw7~Ok6sDpF7leHMOpr&HB8kZGXpz zuEw15dH{2ogG9)Wb1OO(klxDf^pw!)$R$w`w*UdmR12{Y90~V@4Aek za6S$=G-JL|iQE^6dI@F8!f4*<%!H-4ec1(e2*2-UT%UNpLC(qSMh|pWafs3>=$*-8 ziBlT1@wAXU3;3ICiOYsjjfNt}gR8PA4?5qMLR0OMA^6cHC&Wer{ktJf&y({q2ro@ zRz}7vv>0P*$s225AaeT0r?Xq8RkG^m0_nQlwbl1Wc*bDuN|#xap*pWZnwl&$R;YruRY~$|a zP1x^X%CALLc~T*|G%UsBMOzbKmVjB zhyOUm|KHM+|2R-kMM7Gb*3iJy#QJ|pPg?$!lz&e0?-@OY2Ok1A*eBUaSxJ?O5$bxx zwIx=GqBCR+FM^eI-6NgE#L8bUvy~J2BQup0asAt=E|13-k3+b^82k|FCY9775Cb7?h_&#_v1U{XYf6v268C~z!x%jvg9mM1 z<6}%jjZzF03Q9u!0y=1#4{vUQGXC0^YQzjk@>WS966a`Z2zK2GFGvINIL`2p|@uQpR=E!lirP zrjIr_L?RUA22>T)(~JDJb#iD!A20tw{oFBW8i6zif^elt4)G6orVBI8jEV_NX;sM2 z8-0o~W_EuNh0-?4F}$&&cujs9XiqwkKyw~-0|0|)WXakmV2)A;r1BW?F=_SGgmKD7 z1r038icDTqF(h2Uv$#SkGJXHm$G+YpA=co27Ep|~pD)h6LkSQhKTcx-@L0AX6*|Z_ zeS~*`aPm|n!x|I8ST~rfxPQuJ_%DDrYu;naDWgD``8<@+=nu}IN}|(KWRUBWWxvPU4Ru0fcMyJ+d50_dDfX3@Z|yUL({M|D7~MTZn(?HRy{aA^oZ zjdt-chlNnJ9n(U3`DbPF>JBmC<3xp%>P_<&<8EL5-@F)&o@NaG}ZKp?LpIVB-ky?gA>?U8x=c| z#oTqDRAUdt5r*}%PAYLGzRcEto+AkhT5!sUqVNvFHGb^a1R}F@>1AaJlJ0WlXpdN| ze$;H72yT-~^yU$xRj60&JTUyVu1`E_<$cM-iUD6)cUU(KlXFFvxX-OJmDh|n=^0F(6)W21t~j%C^^*0Xy>_sSllRQ)v5b|&S}FERKjKJi z56|kkCGjYy=Xwm(|NEy0h`Eww#Ixl)f)DcRw}+;B6{1-r(#4y4VHoPMC1@7HlsSBr zEHSN7mUhV}(9VhPZ@;Xep4_mXgDdkRS6&QilF)UUCdd}ZXZxL3q1&iaZ%0(!2Dly) ztCkP((|BzQlP=TDX08RnH`Ho#<<4Q28K@^kSE>i)MDCB$FCQ&u;(3MB?$bIK&B}!D zY0&ro;S9XSY;(t?1^_S_`!57p|Kn!;A3iA~XA3)9C%ymv=|8va*FN7$SR6@rw_hll zxs--Thijm$o$+_c45SV?YaE-wo13o`tNL*CvzZvSrchEg1+k@yaryz7(Z$sU5u{)t$@j&5rfP9Dk%0lDO_G!=tiOu#JJof3it5Xa} zf{e$&fmpuTafRp)1zJU{bE~&q*`f^3RjdI_s>GyOveXk`1y}*tT z`LhvpIvKJ(Wt$|!=Ym4(5(0F?X`Y7GinSoL-EOsqr;Z5wyFJ8?^hFWvFy#e74S;9* znyS%0z&R7@*Y^6C(KbTnJE9HI9xeg0Y6Hafgw9}HjIvfx|=(YT-f6M-kTvOrX2i~sT)uV+qsV08`kCTXqtl`qd^e^R<<7p767-o{uYib z*tbLwOlWsgR8s$)QV<|CE4B>6*!rF~eMsV>LQv++igA&W>ki&4?_l2cVgI`R2NsJ5 zXF6;{`{I1MDb42sjvQEbRMSnmPdmCFhRg@_ryFDX(@aOuw)`Ed2TGhjsrIiuf6y)yh0vqp$CLHv=vz1E7~mH(G#MQ%^X zRAMKo;{ky0M3C0V{!yc{!?^W_cRV4k%UqfPfqch*^z^z`japXqJ=5(Z;MI(`c22$8 z>2DQaT&}o&9ADiT+3mUv@tQV0P1=DLH9NF}K52JyI;DpP;>}m>)D!vZGU)_wIJ3OK z)Aw=#E(U0T$Jh8$SA$v@(#Wh>{vB98zY6Ge_|C8iy8h?kbsEr+Sxl0feG&yi0$x{5 zpx)T-!2Y;L0Py7mleqGev_H4yH46SS1RfaTOlOj=Z!wQft=`mT2furF{xr7u=-O2A zA1S2^Lf_r?HnuqoH+~jSpo*{4={E3A!!Ph)yLUcsX!iAn8WsnBUCfm@dSn<1KLP7w zMls(5FW8|Hy>Xc9W6GxiY1`|~F=!>m3rzH&E+$4Lc!`(25Ap7DPv14&XN9EWs0SV2 za}{7t6=)?COKbV?)JZ*|hHm7h<@i0q>$*DiUde5MJ{=wEB*s6ldwJ3Y_ zN9ZoBhUVuWu`YW1j~)R(qzQ83-VD9dVBQCjfzU;O^T~v zxpSW7qVb(1Fr^nAEZr zTL|%@Om6YVm=jCJG_AfbmX@sP5dr+R2W8q9{X+oFlM+-Q5*~R{@ZTRwLn@m26NQ5cWu{YYdYsN~PRLcjj zVx^K&qFAL;G!vStW$loLd`}6qG9U;(S#WQ#8B#!LbhtEo{bvydIDac%Z9=j3_qJt4 zWH54RLTn#4^G~86VR;hZ-2a$#IeZEa|^$l)1k>Ng0o5&hBNJcjwI z)!b(aKjjMTCFE2)n#1JAGbCm5ej7BulNU*g-k&1FW6JM0+Z+#{I9;%PPYiae#y&#z zep>!2C5^38)WUGp!dpV;WycgMXQ$P;<}n?sdk>Li>m0#xEm-=57|y9=ZECV0WC;j( zDyfu&qh)9Xr#Vh{fK#v@#c(d1h_iP2=G#vZ|nlww`NLhfFf zgn`=BCpd|TN;ax8l2KwTi};gnAIR#0?&GbE;<8$8#~j0;i!Je*s<5gm^N1PIE2roiIM|LfZq$)Z~vV>4%V4 zQ$N_Ae9rOH5H*VTLnwujXovD@PIr+B3XZR#IgtCeB7=p%NW@TFwf>~CUQ@Hmileh(MW z)8J;{oc>sy#2PK+!NN+1#?rZ_c^8dJS<7n5e)CAP%y;ICSs)qwo@Urw1G7ekxLryT zEAl}?MI-mb<*5b8!>WeF&Wh)lNrK3TTQ^LJ>!^bgGOCj0 zX8{oy@0DIY^PiZudmDg`AyC>=`EcR=_s235`(tW3HD18Ff|QPcx_I#gb1KYG*R=rp z#nOcL_)ur#Oy>rM00|kUqfx59?;y)3^M8&%8D+El?$Cn2_B4=tF<5@)ILq$sy=1c+ z59@$d2pHp>QrVdUDq47;5ZAE|+e8x(+#GtC-MwD94tN(Bh&Wmm1(qsue7~wo^qw;h zXkCAPHU;@%5mBp(K`S~rC9~5E(j7P%UdLfhb%{mw5V~kV@q#Rbt;)n;UdRPA|E-8| zz{8%Bh=S^sF5MzX?etU@c1*+C#Fs+dBl918d z#jMuxXuIWcGbk9r7hH9Wo+ZbsXsziLLE&U6qsb;Aw&Vt9;BXuyV&uijX6^W?PK7#< zo(;RkfhLEkc8am~IDS|YzXEHpcJ*!66F&XY1daKVi4#Fu(E9WPuMndR6sYd$Txdwm zMK{3MtBNVbe^2y8DdQe?z$gFKu$MbJ_2swWr?z2cN+8X{fdH6AgsT0$m@}FQ0=i9b zVo(4ZhowT5TFwSzTvMv-2{^$Rc!R=>wlA=E8mLZ?ZIKf))3t0arG7>QI)o%0jnfWYVCvooe-KK-pr4!*;dY=}K&pk4&6YxkzR*M~C6Os0efBQafguw! zg|fg>iidna1F6Gl)r&t2ea66>jJbf5kvW_w-odvGWP1WI0tg#g=u(I8vDK-bY^JPz zlEw`?v;T>$z5d)S;-rxAnHy!~!v7vXdS_69}+ zD1HEtVkm1gpC#QBpMriEkS9>GOW5)Oz2s=8kJqI5BTqW5Qiu`+EF{sWjUuBu=Pu)= z({OvZ0G_6G3b5o3FmaNo`V}6rO1gY8*j<1X99507{`00JnY+ zJ}92hPe9Y<&*)&SWcqef%LB=Hg382FbPym{WE&a9 z6UIZ%%;u$h5h~wqe?K@9`a}M4&NcVcQtxL~{a#1axDKHsmSq1joAGKc4IbX?} z@wA!k#fq@OoHuPh?Qjs13uLi#0 zB!gOA^SL}@M)GZe#bvY|_zO4GkZEcTZ8e567H8dgf=qA!*dKqL*SV-k?#ipV5Yn@j zyi81A49M(NZLG zB2V4|G!P*kUqX#Xf-myUU5u1f7k{W#IM2*}|3<=y^PWyh#|9NXhrw;Q&k!A8o)uTxtTGQZab5gGW#JcPAB9Bb z`UbbC*|aWP$xax9c{9M+@{dqAx~0RsK2%bK)q^(jZOxhoJ}Mn{UdYmp7M7=Zj{?AA2G*>O$LHisC+~;g>-GALq7_`ryeAcf%t*;k05H^UCB>LhP z#k1eF?rV9m{Z4Ks@7X^lO=@rxbtDVWvY#tT%VCAI^D!oOoiMzN&a>Q#h-sxHo3E`F z#$Z^;ZNekp%dARF83;Rf5`nhqJ)rL_CSQzR9o?q9nDsafcpYM?@;Q zv8F(rfFnMek^Y%$TT&)zDnqT^u;Wx*G_lJifNXrQPp!doY@2AF{FJ2zDPcq`Lv;}v z1*O`hO;7R|`5=_TAvM$5Y)N-SKDxfAH3#F3&}v3qHHnL15*BRnxR}{2R@QV@wU|1~ ztJN8+BQe%#`QMG;^gcgFGD?Hu7R^dnPS#_Rq<$Tp-PIy0N0zhHN~U6}dN;c*_4-ZuD4qU@NF z>%7h1rmS3NjIU=(!@g#Z=J{*-tHsJ!>A| z=2$Me%xi($Hmw4%myHxsGEqaU!7R*;>;{zmF7_e%fr@<>)qLKvk=IwhzRV%l*zo*F zK!>IEztNOx><{C{!=?*4sWJjmoIWa1Lr5tbQ_!I&nhb8<#Mrh7XUSmKgl9;})Fs7N zqKVTMBX+Fr$5eB#^`_04yO65+&lzdb84=tQPwnJo@S2yWOiRSiEhukG_-Q#x%!MWz zOawTLMkEWz_D+r76RG#het2jY=wH3vZXCNyH{m(|Crkrm2~5W9)!&&f8d#mL_Y z0s<z3sdDd~AL{rPF_OEA`Xy76zsAR|w%-I#pr#9j7sWIn_;!EQ~pA z5@y2n0tgak%||QW(izvQ>LC%R0cSm*ChO13M_Dr5Lm8oRU(52u$gVf~;vAHuM}M1P zj8>&iNt2LdsunAAKn05MkpRoW6oBDY=*;c5>qi$*S2#%9Gi$@-oTwaa*)oy8Y+-Vz z11(ldF=xcFwT7izVs&Y3I*Iazg?%LYHyV>d=`b=?GR)R^F{C@p%!(#4bORYKVdYG> zAxw93mY4ij;b_48IMXDcq8&~Hj@WD6AVP)kJ9b8ceCo5K#}f5pj2xw|mK&n)kr`+s zEfPvvJeGoXmhUwFjrVG%FI)uXPfGr3$MOeNT5OMh$jdMIX=G&qOP=U>V}Zui*SH@M z(6}F6M_75GTZad98n{6c?@PG9rO+mancav+1WBGf#7IFXxI~tYmxnaw^ogD#d%VN( zxl6~YRmsDWT22#htaXEp-59=S6XG0WlgxZ<G#6(GAoTBV%(?pp>rTRQsDLG)RUws?Tv8JrJK@yozus>5yN3{X z3>BS%3)LYS0wX%ywn|JiT)SzLqAvK_$CP~m_mXWc6P4@s_m0Rrr%ht^e&&-Z)R-NG z-OJ(ewp?RTYe&zGyix9J)OpY#3g|C~6P|`DUhs5Gnj|$u0JDeJ2@h%5u3Uc zPXvlk7ZhNA)duQAuz4auDC&}+EI>)*r%`!0DmRkfUuM2Kny*h}mL@NR=o9|X;o3nY ztmNq!||F{z(5PzYpvyLV>~= zUk4FJWF+&wCIsPoi6}VSo%96~sbmJ>&nz}%Reay+b9pm$IXhy~14CH

    L#rwBtZCXA`ErV-zJ)y`?Ca`O% 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℞jRzwey!cD9Xq{ zVpeOnHZhq{jXetl2avj{6$T;4dKN?Ry)nId^UR&p%K!aq$K$j@W}a2| zW6wJzv$+;n-9%z`J6P56oe*=0LUw_3Z`rJW!J~WBwVMXC{{}O=wcTGj9ict^=8dO$9#q z2lMc_1^RklnsAjHau-a}W%Gtp5Pj~b@r_n`SHP3^NnKItEhRMgVrm3RiwIDOYn?l&#(=toEIkb%+ovaHwOePr8hjVOIVXqB#dQLK5{ zPW!hhH?K&Bp>-rz-&+Qqpi?Z5sM`$Fa&dq)iWRUe*gk-a;**PA8AIKi_ik{MOC>1`ESKIQ0Ks;z`W8 ze3s)rDMPX5__{kRTiD*)&b0$_FPz~yTzUDos2qB9B%|y; z8r94&u+?2R1*Hf;?SwDD#Rkq(0izY@0Obcr?dXQ7E8-4RXGTE&(^N9qK>C#($p&kK z4yna}%>%}6v(iVJ%fONuqYRc|VuTsPO-n5M^JCO%5_U2tNHtM8AWnxzl64VSIl*hS)x$iE;qyxnJzS%_4e zYXcOkvB&~lAY~#ae(HYS88~s3R#^ks>^uiBHA=4m4O<@$%T0aS4ynH;9gwyN>GX*6 zw8+cfP=K-Ft0`eL9M}dFVtiJyc4oB~s+OS3avoQp-Znru8!+rs(+r_G!(=q%Fd-EX zb`Ay~m-~K&6rfKF8Trkba2sQ}p_?tRYSk!W03MBys^AP}%3LVdsCzRlAd0~e4a6E8 z(29YtkB++eu9M>ABW56!(+OznB`4bw%j22#1;6|`*Mr8rtphW&gO5+*BMQ|-H>Cqps^(({3_HD}Ty0Twj6~tI0o3TX z?7DJxO+=X)1`)7wyf3$WOO|4o`4Czp;>mgqW9mDBL5n*3LDq~iZlk*D&#rE?38=@! z=tU3Xw^Im)`1_lnW={;`(l_v^nJnS}+82P|>}Uv@W>DstcIL$b%&Nfey*5p2phr}% zXyg>y9fY0%445qH%$@;81#+cg4b#YkbVzX^{i1s!=vngDu9(&No=`!>tAPD@S`#ED z3+A%9CDanZk(EBWOaW98a_?XE@YooFKbNrNwscV7;%0ZE48dV1SOCK*2~f!!aocRO z{>;BzA8|fhN51~<{N#MObRqRgO>|%X4E7^!K)sj($yM~*BXML6REiIb&-5B;1WjP#A(D*ABzz148 zD+$)W6T!a>ySP;V?Zb*xV*iV(V>u?yc0!2oS;#B_spy0nKEkRSO$Ta8k}G z`I$Vqb{mR|rPhyO6O#%gE}8(-3AQPkflTAe97KIf-AJ%%E#=$=>g(>F97vfv@w@${ z3Dm4GO)Gr2yiv44?)5{!@aOdQ6(A1|?ku==ziRp5prc!-Vwc$jd{5O?$uIIBL#%eh zy#c##NMzTSJ36)W+~nmxcYI&ueLDWY>4bdWhHqOe-aPy8$`hQ*&IVYf2jV-8HvHz# zT-q{q^II4$IlE%X78fzF#;)JJ6|AyTr#JYX;Mx!gl*3;dQQPpTrhtu5S$N5Is@2DsW5CXo{Q zM<-MYqKojTe3^<=^{ja<+clm_Z5niG(hKEGu;6Xxy4&R3riP=HHc*q-KmJn+RWa2W zo2p;kAvk9{z0}}o1_%sTr}Q& z_ywx;L?0Vor1$c&-G^u;ztQyS5qNzC|J7 z1PUPzW7KF(-X=pVOlF&Cen%gm|5!+fsgWkARvOu1Jc@%tLRLr?=0+Lt_h6@=m5KF2 zNBrcE1$urq{dLskMKGD{A^rFX+zAkYAA~vsk5hT0odL@r_Xu{Qu{y9BE9f6)qClz$ zBt(m9VqU7XoKzF+!SX-T!g^fK+6}|Q#Hha*0dBnsyBQkDOzg)GvC5=G$fin4AuA?W z6KcI%MKX!PV&o*Ifu^>&*g&;Gv(Q`1rQSL!%C#L zAyz-#4HwMIoRztC>(wj@qXG&{hLinAseRfd>GSA>7~vMo8%;9#8i~Lf zHwbgX8ke1(OYRsaoS8aBdve*a34r-MQrAq8Fqg% zq_tezGK?7hHc2eqI0GtbFTiIn=h@%E&|(0|_Sn=TPf|e=a|X3E8h(tzL;solq(}$} zMh`a23@CFaOua`4zupLZd%2&E9rm?&0?)5Ht=DqC%chNN^7e~E2ngN zcOFj^3)~XA#vgJ~>JhJpRJW{Wxe{mttj4b3K2|j_>UZH8$L`QcB*jbzEWk~BLz;sC z=V4@yq%bf?)oGAGm$7$X5hAUJjjlHlZr0op#T-El;UvJ^bh>>Qj5RGgcnw}~s4zU? zoCaU8*nB$1z(L$*PK_4XXIi_r1@e}t^8`<;nk}2}%zr~=@=j^6C3naMn$)AkDsEg& zRA5MId5OLWR(F#}si`DAeK8e9&R~c0#4aVkqMrch4n;M!MiU;KNWzS5 zU>G3c4zM^+78HelLem~{8&Ljdj$DEx9DqiW+i~bo6vG%q=;cSXmqhs?QA^y;J9}gy z+l}N}vCHAEYWVxmfRF8`AV)x-O0cbs<_rP(;x$lgABsTKbqFlXjt?g0qUx<(@?+Fh|-NhVA{`>h{gsMDt&wWn5$9 zSr7qMnFJ^}(9t#Y)N1v%rBC%s6Ov-HTaDn{h(l}W3$#9+v_Hakp){O+)ApZZ+tz5* z+8kN__PP&tXIdJ+$*0rzKv1c?cF!oYu+ETX*4^@dhbEtVisAOc^m{VfjjZ7E>$;Vu z1$rTaOaa#RNf0&1#yC*@LmaGcfYRw}G;t=~^3M0<9sgFO#V_N(?m=kZ>KD8=v-)64 z^J5w5kJfl9N9yd zbTx(mTG#+E+@nY|8FK~333nk5qxUr2!Pse#vaLfoG-i-Q^cBePgQM7Xp`Li^ zz1?(-ZbuPeF?Cw|2Nr_pc9GkcAa$A?YMBhL;PZ+e{q5T$%o#}aIM&SH*JAS@!wQc<0rUs%m?|26`U7c)c zP*R&~QW!WBNWcrcha23yS}Wn#PAFM!4%l^#&8w@fvS@`ag~<^J2YlL60ent{T!JyVm50h_F+QG;)6V4KPOQlY6rMYBObgYIG7YO{+Zt~+X<5OhYvsc1zqxF+ zgRX}-Dy?D1CE3MzMIGOS7a}arhphTp)p9XihC>_yuHz{=y;}c`eh3CBp9~NNjnA3D zG|mso`_*h9sjL;6O(g|$4XcEi>Fj43BRhG`IdOBSV7{-)-3s`_Zv3?t0QA`bT4H!6HF}G|*Nu>P-?jHt^!bevyWV znjuMZ>IMr=&UOowi7&9_Hyrrwq}Z0Xo3ePSUX*z1pee)i3WblSXAu0L*Y48@g0ue` z?-NlIn>mGYJygr}O(~JGyK>t?O*G_ny53Y7o4G#5+gXH8d?_tzu|;noZMq+;cwOR{ zUfL%Qs={-KoiB5y(hqG``N>6)=0)DeWi8$CbzJqAZWj>p*#D>}ot6fbhq!Nx* zKMu$+^lH{XZ|bvOt$-m{6z)^W2~cKA9hN@w6+!v~CiI}!Zx4SS6CXO4T9!EI<+!h^ zyT?S7>g^4|jyqPAC^fu5D~24zoF+KM0qj$divN>KBbs<*>6pZLgwlZ7-#ld`GjTQt zXXa!!#yyarmPOk-e(YO-q}-L2d5`zkJXAI+kR61*QAy9c4FN!q*^?hBf&DLW($vtmPY6~ zTvHA>lA*;}T1J@kGa?dM9x_L4-JX8=fyVqFyobRq$*QgN(ig}W~?yzQr00lWooz5j{Hq7+CEF-c#9G` z!U!EAiK0V~{8W%3wgSR3HU6Lwy=SC(6KCk{2eS1Ql)kH$dL}hbFjBj zY)XMWMCzS}NgafP|Bdab&^U2Il(B07GRCFl-eiC~zq<>z05oHaH}Wg`O``z=ejymkS5B@8gbyG{#y-&Fis#4^*mQyuV1T16nmgDaO}kZX zghphpuplI`v^ADu?K$~HgofC4Cd`J|R?`~EK_uO`HWOCgv7>ix=Z5%b?kITpWR3spub5LR9fu>69Lq}|LS<{1_TKMZsV@AbhSvVG&GiYoat9qvBx3xZIQlrFk z&Sn91&Cxaa$N;o2w24uYgUlwesHSEdMw}`=(BgKmt2p(vVo6S59x;qwp@K6tclV zRF`yl;Iv!;FciC-2Obfe#y)-!RIvdzPZs`6lI_XFsp3$poL?_H0iuwA6GBD@ zchC||&#v5Lk*9Oh0S9}3RH40rqK?4Yfk1fb3Sp$I`}@2<#zl|lOM1LVbO4n_0U44@ zp-=*g?v_(AlZ+K72}Zd5v^8FRG1iyav7p82cF`mdHRIqx(QYt$l59ZA zrtq5U>=psQB5>CIZ|NTDC}iS796!k+1_X4B87k&&<^jU^n1Ld@br8&9B=oX*JB=~p zphI9kv7b0>Ns({?FcgfJ{~4|)^e8j24pA7NHJuo6OK4Qx?@{_2L8%U!Lnhij8P5Q?oNni^$vKTt> z5g=KCmdcKm0xD8za|)=2gEHi@0>#B{E)Bq-C(9DJV{3`Sb8i`tg{pqx_a9QkWK+1K zo-^)S4){n!|2R7u;uCCeG|XAFB2Y$^)9PC|^?apr|3ftZh2j7+(mYjT+QdwQ5sj&B zvTDW87p$g-4b8vk@vTDU9!g)wB|6#a0c-QfB?8ip`0H%^sI;|WagMWK`M~+e&gJok z!YQ~;Og>k~9@O}n%8w0IpazkAWDx3xDuVhFrG)`X+H&UkM3g8=hh8W^yUJ<+xmd_m zq`hJmf_Aib8 zYrHv4*O5_*Z<({vEDktSs)n*cYDX-?tR+z!bvU+nQnJ`OXZM?f`8TM`&S9-&0V}~V zesPllt0*S1);$UvKn-=uqEj63hUwbPdtP4^Uw*DCMb{_(82KPL;;#UM9QMTf-Yw+_uAJN1V7k}Z9vcL5W z-%0}YDW^G=Eaqrb8A&fXHMM?F=6{RQit9*S;l(ix4k?mAEO^op#f>}kTSKDm>emj9 zp($=;I(KC|Er%$WKi-RicYoq$f^Ql za&vewjAKJnaiEzO87MUZ=Nl0_>V=QeS3XG_T}gwpD2kgwK0?@)9L8P?s7H?u7123>IJ0ct{-wR zeNx*v^%iyW+x%EY9%R)i6KQJML`L#3UzHa_KD7jmp6lVV=OvqP{RiU*BGUc^*2jc)mg2jLSq?M274IE z(i4Q#wNX@ik$NB8R)othX-F%i#|+ju&6t^{E)T9ezHlp2$c4$<>{6Iihf=PDj7p3N zAa}uxQ*A3OKDF0Z@{%~K>1994BytVMU*>(hJfGY4)6NPO9SoM_g)>vk!U%*)9<6Ou zo90zkcPYr>u)Sx{Q~_qED4Y*wuW0T;Zrbfr_rR-Up)e#~376Zd@MoKY-F&^~zz1Tk z?#QnOegaCQm695#u4qM?z!{aQ$Tbkt8b#k&rI+d4D*JjLOXLS=2F_WvN`4|f7XZ|? z5ysj6yM<~~EJf3NB}LV4HOq+)sv0HF0J2rn!yiU=Cz7P0^7bHN2eWh&23Px$L6{C6 zCg3(_hAZLMhR6K2RsjF(dn4kE~1((CY!dGvx8%I>CS1OZshSFyG5N$y#tqm>k6W9r{d2A^ zRjmCTikCl^Ny&Tf4NPYlZzJQRkvV_gFiSE#T|(h^EFFWn_PekQJ9{W{F6}wTod9lx zKr~KcT;*>g)A;Uh1L8)-kmQ;3w)LgUl=EcMw2ncGYrqPA_A~g8-M-hPoA6ylWp=9Yp2T(UKw7Ov!|0aCD^k=!=rWAhEo*2P5$cJnVPPh5s;CXIXy zmp!7hl*hw{niV=(oDDN~Ez;XEV4&>7$ju<}GwBbuU`s%}ljCdCw+EErHjdAjLI|4E z3bkY@fR@Ui87k=E65>b3iF9Mf&ZqE~#-ny<#k2%=JH0m}j!UaE??J@}`25KR?D|Lz zASn-IsgL1a(Ds0hG-o;NY<=^#w(*HbnYJSf3hz;{vvv4kFylvj+lOJ1@%ScTN+CJg z&E6tes=1)c@{}GLjY=i*V_^sp(P`E36sdhjaSmWvC>6LsDD7*+M5SlJ!vSv1V80hj zQA$v{rD;4L7t-xv4smqEkkXs25eOM>W7#OT5$I{OcMgXHI{2-Zx~ENrSGoyn?(MJY zN+bxoG$Ewz7NUvR0F~nv%#V4XY18aDi2ea;IJp^9mjozn_J&|oQ<`~DtYS?KR_o|1 z5G^3yWR{|gF~#J922u(JA=cxVfw*j*U~fT~qs>v}#jgf8Z@!C#1iogvq(C~+K{Nl9 z^2B%F2yX?+!O_{mKo{62=OAbvdzhk_&!oKX+2Fn7imZ(sC@7&b2ohN5Rq`iK z$+|H|j_-sQd(Wf=k2n$Jgntx5F$)%4Zkuw^am;V^K*~OQ0nPS7f&A2DT3ktIu#m5( z<^;q3F;@l0s9{c<|6Ffc^Qs5e+0b9(9*ULk^Ej%2SG6Tb;@CZzUqv-+9!7UuJlqgxeZ)1jiXe@^U8-lGbPm~u6 zKx1?JAl3~r9T6#3yat34MMbH&R1XG5o)o%rY`Zq5icO+eFKrVh@SA;%Oo2Q=sa647Tz7orwr`2O6qP*+oQ~^J?BkR=7ADT6AK-CeLWl?-?$^s_I!i-umq$U7Xm_PpK#H* zhk?Rw%;!=!XzXZ-WpZUttt*`{M!~bLH;6iA4k|rbb9?jp(sz8e{tMA~ffhL$LgR#; zJx!j#n~lbSt2oAEd7mg*R3wajqh9aK{dUd9{bGhX1aQ4l72OH5`sizPiV z&sT=xzGB&`k*FWyq#hvM_4|B1mA-XfP#TUor($?k8Ctu#2|4~C!aE-3#RV92(Tqn! z&(s;dd@_2X1iK&DvlR_+==Sk*aF3}o*E{{Axt``bf7~5Jl72iY%@iFzPzD|`PU}5!zKK2H1dYzgvvzISGg4?lxEa4SAa&S8fb-c z3fo!fSxh?Ej2B2i8tDc^;26(FF5MKp46N;|2BMWWMO>(*X1#u&+vgW+6i;fCxF|h> zbY7B2b^OJXD*A;ng}x_di9~-wQjTBpfQb8i(b8lYZl#nvD9YAPzRXgj8w8gnB!-H1_TyoFIe_|sn2Tqdu>($joT?NwfE zbalj|@*(HvQ7*-+GRl0S;zZ#h%Sl`LG?L>8{})_a9RXQHsz0p4R8F-thzlr)^#wCP zj`p+l<*IFtzF?_*cB;^uvPLe;Q9z$}j`kg2OmO<7KN>e=&$R7i$E$r-x-{e1v|kxI zSO9Mkp(5f@O4U|Azc_+LR$Q z%KQ9S05n)6!bsM)TtnCcd?&g@1--UYec5R*oaI$dG61Byd$;;l6<>~p)kifz>`9;lpH>IkXsXUeVQ@hNRX3+abkZr zf`4$eh|<@i4ilSy;3qT&5n^dum=td^7 z3(IW@AM=f@{fUEPhkI0aHDG6b@_F<->&=cO5t5YJn7I09&@9N4Rqo%xQhZe)Fo7Zw z@c~j>`?rt%VVq|U9WTt^!smVU8urIn+0X+%KR@{~AA7># zi6$>*)~6-kSiUl>XPKu^UKB@(GR0uMqgVAb)NK3yNou$3m9}mppd2(2v=w^Guu@TT zojAca<4_B^d>o9j6>=`RcQTN5-Qv+OVFlQ>w#JLG`ABwvV6$DkAx?+2#Vx|5A~GIE zk}~-*xxtOp@B1k_xV(fM&9-SJSA9TJynfjei(m!Tn-?a znLR395p}H+4`=VqmB{RI8oS%Ry#a$$44)P2MJY=Qy`!}i1HG=IutE*^sF>Z;&+uK` zOP5hlE*8v4)M(JUw6RArUk6A505R0t6lMmPy3`k$Zjt9@W?y>7-|vLxQL-G#*yy!0 zGGymrmFAe~WYBFV>Q1=^jwWWFy#{mqDc$qsQ~=f4akAlmiHM^CPerPA_0{Xl*Km&% z&pnyahx3f&*A-M7s<;B8c<-QH3zI#=4xD0~BVPt&OZ8j-qS!sSIr%QW(E966(h+L8 zpKrvsS7Y*nYFksYg|qr>qS#f5Ew+;+ML85vZ^gmldq6Vq>DUBy2ic+*={;EMs`lqp zY!EvtxJ>_wf(x|<6%Luo-j?*%kGUM(x6MrpFL8XYJ@uBfW8&Dv0^5dv=5fS*?(YU5 ziT*}6hi+g*5slC41dFc%#f5So|84j^36vgs8h3;eeof-`u3$y8&?)q3VoVfR$yWOY znfRz_fXNB>v+H4gHh>2(w>D7&nc-}c=rO17k-ytc)|n!x z^(?4ZoYm&7GRavZbBdxR$t4>knnZ<>wKI~_tZVFy0W3gk2mQORqKCMFdLW{J76o z5Au)^M5s9oEZsB{iyD7sH0ejATA>P6R4)(JNhw?YVGaK19^1<=1ABOx>S0>2Y{>|d zW^FAKi!VI?tIjz2nL#H?yA@KXixqJ^`|P9J=B&LPh(a0;hdE`|kEaqZCyjtRw3;3A z1@Y`gzYD}h#S^+^)12XmsGzFS2~Uy4`>z+0!XQ%oVHp37jJ<$N^Ugt3GiNR0Or8 zZ$9~!Wn1bZKOe?Zpa+%rtO@PJ?J*RkOku|sb{d%?;4_9?cNy~mvV5RkU{9v)FGr_U zN)zAv0P*es7}D_@K4-~y?ZAB=I+HRpzK;YH+!8=?&EJcqix~KfD0BBKO%SXTF!S$0 z{yWys`eKkL`fB5T8ULB?dv>3^3h~cai^9&yldGE|3%*hFwur@y7hEaf&*wdJKiab_ zNAfQ$_vzqjw%tz#4gw^<^5mA!)-8>usJzU(f4~!0rcSn`A`Yu7PIfYA3|tL!I+Pic zo!T=iDh`Q1g|y2g0R4$lyYW zuuO&as!7cz+Prb{&u(wt+kNPz*~FMf%O^(f##D=zBS@3<5$ui za&|>}7*Htp2+9eUDo;uCQW9&JpV7D6Z2|7jWGGUknag`0Daeu+_9y%vQr__nEPLcx z^`2<5?udP>|Nt&W!}$+d4xDc^@nj|J$`ecR-LLs&j_uK(i*DR6#IX_#41VTk^%|$GK$me%ZN%u!*~04qAf|P&|`{ zVjXsV^T1jmLC*-X#IXE0^b}{FRfy>5PXI;B^W7P3$6BbBK&5Xi;kC7loJVj+lMPNu zw19y8)^?~l5l91s~Xp*DCY6zj&OqQ^@IEMJ43$NiNw zt_zs3pF!*@zta^xxYKk%T#s-V$dRF8;xwT7oA$^I^{Tp%34QwqN359$qqD=Xf7F8744^Pw9KjWd=Z#%6@K$1GaO5s>Fl~5L=D+5iz z^5mWWp0%;LwwJ*)J^3rdBkD8fadn(mjcLgwb76bIJqx*t2U%ULq8Z%cyzo1(+JCvWeWQv-8O*O1jb#wdk8OF2dMLQj@Wfr%+=9 z)A7Sl6^@mAkBEK()3lDEvKa6qw_{?NIAzLuRnJ*#Pjpt^g1SCGNB%?fM*to2rAo(dq^PDN4hoZF_pK?LO8WP0iGDL5TV~Q5MKR_C z)3i*0rhFMWG-?Lhhq3-d&_@s521oh;vO>)aoLp->IS1uy#Kq7tf>FbC$n%0Mmc>=t ztRl+pk>XCph{ajQiL#=C53?dvE?~ z9FtJ+p*B+N^f;W0u3OMlGw7kMv_lTf^a6KekK@CP;MZ*_QEyTK`zlCKi)F{5MnH&x z6 zU2=pOzu)Sb&!4;6D7`bvcVS*r0cQ1deMKnLc+JJn@6^-3E@u9Bf>RwT^yOPDz=}R@My6 z;TtSec${aGUN~)|)qCJ&Pzq%UrcgF*nt%dZieS81k-|Eqs?Hw^dhRfL39pn?)>Ze8 zV=GL*m6dtPuBmK>rdjV6L7zmiHH|uVw5qQ8Y{1pAG8ex{^#Nb1K2neu9SW#1E~LHg zH9B?N+8nSSX|1~i+op4+M-xY6$)+QOK&JZ_VCMOX7vWw`tEk0-5)&xACv(dvHdb|( zUC-d;55MhD%Gh)1nzbGO$U9(GEVUbQ+}gRgS!FdRK*Fmz_?`5eySGEp_wKC3+`MWu zNUWR>|AJ)@BD?MFZ4W)S@SKU2Zzfx30~VO$>{HbOMy!O$Pn=fl?>Hyr2AT zVJu@79=>MLFSYqawy`l>k<0TizvLNwUVl+LbI5;5R};hdNQR&nwsj#8;Zo=75V(lT zNRny#)m<>?b}{u~O$i^#L)Pp?7<|`31yI1ikmd?Sv_P~Nb|O30qMlQ6o9*dH%Z1U(Em4+NLDaykn>RT?It%F~CZsXSwBEv%&VAOYd=a69<$uTx(u4Xv11XneZvU1fUK{ub)EhyTNJ@&ZhBtCv z$Z#g&ONhf6Cel`7O*J^FYSBF1n!)C!+4{n5j_rC3eQO}K}g%-aXC2!*7usjMb~ zEuS0wbFm>@HIZRdhCetIEqLm4SJhQguo7H%Bj~sIH-`tdeUL=}x*Y zp=!VURw2A}1OUkvf@wruUA?u}5?+ffjBTBRVjGjoAe+vtKn(T~U4E zqTtzd1P9i;Xp@se5t}RUpCK#JldsH%J5w)2sF*npeo>g|)bLQa1r{VS)ht3Zct8rR z$%cxFn769{$(o}RdihUlOS;jVn^C7|<=JlZAx0yvNzXcfri9wU?uGat|B;BNMBE{O z(rsy=SQiFKs5vw)*lW_T--XJb-=&H~!V{(`nMorOMsVF+obbVSBV$82ZNgM204QCj zWCj{2mC_M*@n}s$qK8l`7c=D@!Sh3$*s*cI=SXjfRB-_oc^@&m$FJmS@Ttu0_4nzP zPDlp1=1I%o%l5E_=NFKc5krRRgrSl%2h<5IRn`{@+{kPHzd~}p_ZV>o7`ASSJ}_np zwrEsmn)lIz90K7y=(l2qh<@z1z3iA!@=IJKB^rt=12WCZYtFPzTnm6Cao_mAeCD}f z)^cnd{3o&5g-0?fGXQ$V#12Cg6FMsuI5Y%$Bb@WLkp{d<-&}1>0?Z_HDA>jG`%rZk z#c&}5JS2oX&^8PSEL}i7C&*-88tZY6lxCF`JZbE8Q+#P`hyyY81IL!$IJX{DaMpANC+!3eh=5P{OHB;)t|4%RZZxVO!PGac02|XR~1;7xZ|PPQg}x zp!tN905fv`3NW&>2k4)KdUHfsnsO4Wui}fZ<2!yTiP34@5v0xn2gvKBf0iIy6qT1t zfm|(v>h0|)%gT2p5%TVDwN9sQU_%4)ccEv-s<(>Y?*Dy-Lzj}Y?IgfXD9^Nni}??G zQ|Fqfpv88dFlk(PHlxMLR@Y2aJoaN;yhSPcEqeLaT?X(k)|nUm!sDKU$c&P#*h2z< zC;Jl{%6CUnBxunK-t%eMr3ShK6w*gw5O^wp2D61w9I?Vo#T_7lxAT&a8N>UYXaPc} zqC|zl{mzh%=u`n1Z{jN|cu;sUN6XM@=##2>RsxaE5hnFxkA(OZ^O{7{+oL|B(tZ)= z5kf{Rbb{n$4XK<7Miz?ZA?2lX$86oY=)H;F&D9K}me3ZX88y7!{CB^|@$h;s1?;e_ ztd;1p=e(}Ku~3i5#n>8NM0c^Dji!igR6mLqAj>Z`%YPIKxqWhKsodLqa7r2}nI}oA zS0O=f_OCK_ajaE zw+WV+D>g(~yuMygLOdSusMVE{^z4jyKAbqOG%+&w5t#RZgV&Q8RN&Yt50=vM=Dn3( zH+S5EHjX1~*$!-Vli(#}V=>;*fOY)r>uTvfeKctjc%73bC{9HgRn^y%R$3*$)bR;b zSN{+LsN_Y-$*z^qg~CvZmQ}(jXF(Mj7GU4kS^=njI&BK-fvsPfaG|;L)6j%#RI*dh zOm{AkI>WaBN3>E#sPE8fzSTv;!l=2vcfk#O?J?NKz-R^qitU%#;1bg#(j3tEr7wm| zWbF~H$~HEYq@3tMHVtR9{V|kC=3ZH}k-sf8rE<9mkNr|S-;t$wzXwF|@NN^K{dOCO zhJg(u{PcXn`Hx*dycdGtBpOv7pHpcNI<;?W?@H3Ayx^LWg3>Y`>Ed9L>l)v&WyOsSN~Gn1>r;aU2e;R~nyeqplGyjjv})!zD1bq& zd657xv-5IWc|7X?_Ed&NtqbF{99t$B1IqXl0j@zl{-HQ20Gk%Jyh^MmvxC9RL5z== z?An%(3-8Q)zjd74Me(l?u5km+KY4v7uV&Jp`f)6jNC8wJ>6#$m0G#8rjrw&v1nQ%L z`J6PQ3;C^Ji~UxUXGgxPZsq@8>v6i-^1TbM;fo@Lcsg+x11A_KHIp-5evbp3+_6lj|0+>NWqf1>v zTb1}k42+)e0X6e(d19t&%2cNfWb z?v=P^qJq70Zyy-eyUT#9S74w2UUygdB271Ly&5t(;HiPrXK`+qmprCrU5}deyFGIU zr1oB|Tf*^VDZYi1X|8i~#W;)RJw)cbIeY*uJ%^-~Iet*ooAVcSB}s{Hi~+O~wB)Lr zkiQ&vs_z>IJfMjt(FbT9DkoH7o*BCuu{Y$#XUcSNuiF#IX1i|UlWFAG7S@uFi`BBE zT4vN3nH>#Z8ik@5;W7PLwrag!1~<7AM^JYZbU}EmC1c|=Uq%DTm(GjUP>d~($WArk zXwUs*C}hF|V`}nKl0s*(-Az=TCPj@MU0ExEc;IGCYKkcO&08JztqXx)G9vbNFt%FW<9_ zxr(UZttTRyV+srfw?+7!?w5|J>IZPsNUO9B0xQ{-72iKa$hpjv~WjwMT z@2@l1f`U#wE(hQn7EooI zS=IZ^r9P{xo2&lKkjuK93l>dOm9jZ*+3;oV%%b75Oi9gid{m8Ku4h-po&fqE9;iS!Tu|MC;ycQg84hyVb9>;M2<|9|7g%+kix;Xi@mf8!G^+Ftfs z5{ZBMd4*!Y!%9Tbu4w6+>q#^y5v>u*BzY8L6S6=7MA~R;C>6w%{AApFKb4hPCQqi^ zO>IDj<3HuKwVy6MoxB+R6x+OFyE9|~ZQ|m7cLN?6yYE2L{TFRuz!;x=4sI|B;s2pl zI#y-19S%Jl5#1|%4}$>L{UJUy{m=w(ZwbWhrYE4T&k$D(o1?t#Z;7zMh=2IE$c2rt zy7o7mYzyZBxRC1+7FVPZ4u zt!=1^eHn;43Q5wF5Vxy4#7>y>A_T@~dxs$u6}p`TO?#094az033iyPtBK0lEh#sx@ zXMyG+hUAFzZ~3-%R6Mz|!@yqD;k2+K<8HfST=$6@w>0s`gA}7B_=cnq{Ou74BKt;F z1my(OTMUQUZt%n*n{-yME zGSJl<8;718>;QfGv*vlz4UD1i`t?ix3)hcR+dO?5{UbI^Y^P{2WyUr+bf>3bRUF{OHOZA=xa^gu<4V=7pfQ$YYHi9B# zr{Ycl#OO_U^tw5aP0a5W)8gpwSNB1jjOhCA6U)F^vptjV1Y(j)YNlAE!jdU>y5qpYsV0KmWpq|m4)sGP2Q!Dm|4zYD9F5a|j@_PCo-Yf{V*dxM|0?_j{A#D8m z`|xUc^{=l@miC%k8u~^euDq&#Pk)@A+zgZFw;vfcqS%O9?SqM8Q%wvtqE4o@^oU!{ z)>a>nU_RKi_=Q`UHo4fl<2)=6)}|N0yYxu1gU3!|^vcP`gzR5=pN0QfRugOQ0V7lk zH@hLzuk#Bm40ajafC9-M92$N6d&is?h~%sFU-g_}&U$^xezr*1FID6juh7zZEry{9 z@LQ~tl5kAlk`#B&Dl6TSVou95PaAdq00JsW$SBSVCFYr#`@9!xXwkY>b7lLGO@{C2 zxzp07;(MBG7jDNu1;pjz z9112AoFG@^1dVRO&Am%mCSF*J1UC&Bci0CYg2o4TuV*@i|-96rUdtY>QZ-07uL)`5c1lbX{gdU^Bcv9Xr&oR{*!# zdRJ$2)=DvypktL?TYUF^rM~U>Q;YIDb5V9MjPu`=sK2QLAug>UCFO6 zuUkwY!*mJhpzfZaqOg|Fc!Ljvp5!LJrdMVj`xM{Wc^@<=dAex|_e&Kg&wzSSWzRlD zO>d8&1pR*KbvU9Jxk^}?w8wu|BPa)4^@GGvW;zCKLpWTzEKnV??HF292O=4SQ|&sf z{)xaQfLw6hUh12U=)W&@%|&=GJIbW3(Q>dEDlj$t&|a$tUie~dOquG5$4)zTON5)? z4|udPICXEneWL3Gm+`)woSf*Awc&FA#!y+8QmJ&)(3>dViu3AdKQ%Gg^-)T(S5Nl# zejlYfZtU$VN<M~VhrxSx<~^3;$7t}AYq018>wP^WIsN4ifG!JMt)ydB;G7g=5t&wtepfT@LU*phlkN-6!9rOCJsgX2;%OETFq|Jg(D zx}HVx2#TUm*m)*yl69lI5gooL8Are3aEb^cGGv|Kj5DlYo1x9c+R*@o#Lgyc@?C3v?@$*3qM%ASvXq0;SImWaKUgL{B*9joD$H~`NkD67m2}l>RG#U2=kG( zXB4K@0SU||?O8ra>jb&ri_U@#1(IImZ&7!BE}0JogB@aAveV6DFxAUqglO9krjxxH zRk)TbmFMKPi%cxdVuwDb?jcMy8MNEK8kMG@SI-sz;j^C7EXj(jpe z@}o|oh&$ZHVK(s?h*OfxVKM+s5kM+Slh_KI4VAeEa>2ezH|e4nLRl71PPuKO=+NAh z;Oqj^FHE4e*29}{Vt3Fgt72x$#b1+aVa3fDnZYyGY~3b~Wm}ZR$eU04hUT zbIQ*sNg82}?PquoW~Yk24h}6jyvkKE2%x7=@L3O?mqgh$nAC^kV@X$=BvJ|shrvj) z#|Qc0&|FAy$`N3%n@O2LR#Hs20)c=Z0l!Gs1-ud6eipl^#hVGW*vU*WsR(J=9Th9C zfGj$se|qBN0~%Wyz+)(LiD3hN=7}eht@+{0fS%ommUX5OUlm6qyQXw|m^qt@wGR`J ze#8v!n?CmX3p>|YRX>(x%c7sN1&5Q~WmO=NyC^H@L->W&y7j>0XcCd+MZ}l<#N&Oa zjjsa8{lIJE5BfB2k^7K2&VJbQfjL=zgTC|(Dws@w17wwt2G|bxb|DSFAgcGg{C6F} zTOKf@2{<#C%G|>8vSPS<2H&~k)Ws%2s~7NyA@hhoS-$YGd#={yG;w=ULNN$KCPY;SXVkQ`(?Aua@*Y-X{byx`>}rP|7fdPR&t8!8 zApR%|6`Kn7|LHVt-BTXd)E3IgkpotoYP0}v6CKi-Q5a~isgF&f6c5$z=Vn_~`efqY z6fihh^0wOxj!)MF2*^9v6fA`tNZ|#m8T%Hc9>8_hpOQfMJSc}_qMAJTsUZh7GHC4j=Pb}*1M2PoaZO)3a^jMhD%U9Mt9+Vd7qq{>B5h1@Y9lP9+(sq)+ zH(h!zi=(P-i$UreG_`!VKOv37$e(S}E^md0DeRK-h4H&oo3^Xe6oXqo_aeFK0K?Thd<6c8aT&7&&3~Ti9KR)AV zX!5yFn472Vf!W9)7w&scjfRVht7Uu+#J`3i{?LY}#G?6?M0J~QYKq-_niHeojqj+` zE~<3|$EE6*kuu2{+Ptb$;*_U~)AWBU2Tuz0oKCbevb7Q^KB{U>h>+NA^cfFn{N zt0({3o`yl!3UPWV^b{Tl8b1h&J^943OALt<*FzEYrsjJJ_t#SP*Ll07A1Snl)HG zmthb1_U+j1gydF9ct&Q{``p1VB*?eEnY&)ZsXTYvliGIsX9L3#ELHK?F5vOz9y2W( z4aBzImJrX4XA}2d!PS2Jx6izky-)d85d~a0Y`typ8t1k$HLax#L?Ekn%2VBn$G!n_I!Rh~YmA{m6Y_(N5cC1$8)aut+wy#8paCd1v$nljE!}JkOUwTE(OY_Y zEa@CymGkg+)2qDG>-jVi>zQlpB2f%--sN%sP<%-gUN{pxQ9wL_UjXtOlS?v3L^r|P zvz=s@Qc0&K2rea9Se~Jz!-xxDdL7p8br!P zgW)9taD$sY7FCe$L3GEeB@&)8AnM=pEn*3u3N%Y)Y^R~uKPPv=Cj9FsVMHx~erFL> z1yokmz@#jNt3Lp;2cc7zdiS>v#}jF#!B6lAZc=WDJstm#Dk>T}l~AO3T2mPRA60ZC zY(QCNOsz?-M?!BPua5i(A1v)h>gAUFeO(Rx=qisa=ndcWa>(6%BTrhz&Ka^V)--9L zD{I4@QG_9^htiq1*sf9M z0YE5blnI0p#~Wul|HOK`px}yU-8(rXSV|IXk#p z=cNul!%YwNs{?!H&58bEU;07wbsn96xc_l|kbmjgPZZ!c=J{fn#0wdp3&?fzpPyYm zuD5bpPh8I%!`SN6a)3x@d&V;#(Jg=C#Z1?QHA7d%%gWcod*V3njhrur_H&t;C3`N? zfo-Xe;Atb<)xtdhCX-;e!$FJI@mQP4l2 zPv-R3t$Oz$N>+^d{r>-mqOdc#=>HK#PdXnrI)tjKz|<<;K864u(q8-FmjdeH6YdU! za6x>j3 zXH0TL8;|%_0zFobWbTVurt^285~A=tW@+VaP4a{U1)Y-GBnldFFrC;0>}9(Q!+If8 zVMG!D+Osc-J7VdBwg*NXVJYL#x1rx^z8uh{36cBUUtwtOOV|VWp?x9ydo6R!vIXB5 z*z^4*{pYW{AUX7(pgo|=Cu3l-$t;SwrD`uf-+L_tg9k;*{tq@=rKLs+bb!#z&OXuy z+HcXHT7KJrVOoLQKA3a(tYbMp_YNq5-Z?$GCyGl?A18v|EjQE}Rr^Q;4(BR{jwybW z-MVdqGX^?@y&uR=(~l(&*xs)xA!hImpId*vZXrDP3iL@)6EbOeO+^P72zfxTPq7))R==2j=$P3||OMzxUs`x|KaR zUA(7LAX(WWbA^3OclsqBBO}83Lv-66-z>q#?Wl;uNkvr7`*~aB%1O+KQg* zaliS}-spTx3WsV^k^`NBxqi8Fv|@V67mU(svjGea1A)s8Wc7lJ)GQ`<4#C_~E9RxT9yZ|&1ayDwrXcBLwcaabP%br(rZghaQ3eTp=NAMrY*o!dq=Y=4nxcWi zmC=GI2xl;5X7RfC3NB<3jCvy{`4fKWgnVKX5`l|W;Sn*_d>}2Oy)HZus?R|70(+30 zSgrE8))#^kz=t%ZLC<0q%BJ|r5bGdGL`!J{-T8DhIa|=7M}ns>2DLmdi3Aze3lr`A zPMUfh2hf|}&nC|*I04w{K<^|l=nq+ATDUoGjJrpQZ*JMTL3Y3dTd%#tJAqU%sb9ql zSH#q(uirF}=F+8+*Q}#30!F>cpGK0YoYnU=No3&@DjG@KfFWQw5e*wua(-uM3kknE zW~{(LtpcdaotR(@yUCZ*W>}_AuNX~-X6FbHzZ&KaFiNdiezUfj)psTNK|2{6J5x2k z+SZ-qDL%DL*?oXHRi%BTE%vfKApJ*?7MJGGoa5%=J~b?vJGLp4Ljuiv_!UzV_CM|^ zgEyVQ!dc))h*c6;z!8-Km6}7!adM8 zg+@5_?!fA40lWc;U@EoLK!OO5vb=14rqsdunIUBnzrA69lx!el@x&B0^Cj}ZU7{*A zYLL|agiR6;dDl*HhW{S5eN35$_9T;gL@^%BzM+!cFB?ApNy8mJ-VyXn>_b*?_T95m z3t*dGM%@I(aE$ayIWJ28yfNf8g`HN)Py)v$B5YVF(idO}JQLIoG5IKg0B`~!t&_Wf zyPjxq)UE!zRtA9}C#QjpBz{ZcHIn?*%&k}rh51D!gMAFFkfS z=jZu?Wk7539NXaWzyFE@Mt z&Q5}seHm+!U1cP+ITg--vKh_98QcenxY_8lMaVmcsV*rGXdQPPBwiT6Sw;})b;mUk$Zlr|&w$~d<-GnQ?}9BTZM_wRKeF5l1$2fV@L;gnRQ$PcPp?JQ zp2W~5-&WbB5!CXBY!5Fm!*r*L@+_QhMGo#1J9zh%nOS@AkXTPYUmw8<2hah)f5P0A z;pV@rWZEatT$pVH5xHz6hKr;A%It;)S0=OvAnAw@48ppqZuUTD`lKg2m!#dw{ zy>GF3&zjxt6TrCG_rLo$sF2`cyWR330nNM@Lf?bhd7#yjLP4C(-;@jeue`1>GhS+d zTTkTqzwZ-^jk_}y;T64QD;G<`^A=+2P}oTzX?d~vgc-oWE?W(P*MB&cPv`{L5|4x= z@rk0!wa!VPtbjA&VD51Q_HS|q#W;|?yW3*U117gH~=V z*FAPN7Aw5O7%EmJiyfaDo+>sel69A6JJ2pkmP+3;yLG0&4>6ioq+)=TGH<_ zy;@V1i{rlcnuR(m>qva!Qg7DxS)6*#T8vedGyh#dNTyN}@m;y4d{b_Db?LS=*H&b? z^F6m%WhtuSslumJrw4cKTl!PSG9Jc0hK$rA=6Ve$ivO83Agv=aiocQO^Y2=wto`q= zLj>TuVG3}>#_+Hjs;G6Nz)6O8*>i=J>$!3w%#(ieZ9O?y@W#ugNoXn4dwpf<+PSX? z5wWGWF{hy8`qdMf7_~kD5x2#4%a!AKlZ?!gA)6L{2WLXwigF82GeX&1U2XfVIh_K< zaxaG#J_cu^zJ%1qV=0kDsHUXrsGx!x>(a(!%ZMozss+t+?MQ*%uwb{eb*;fghM)Pl z%G&i(H37aww`B&d$MR7C8h~IKc)iK7S#LxE$dqo=DBmQ%MJUw=FX#lAs%eF7SfOV9 zd7~w!Lf}ZXgg$0#f#u%~nX{kGwjGH5R%l_|@2ou_C-&5j$66^tIO?n07biEp@H~yI zUkyXkQP~qua7l!U-*e)pB zB9H$TLB*KM4QkWt{K400HTvW9^#Rtco!sJxrPBZNU0^Ke2bDzRjHf%og&N|omG>x6 zZH8&}(4)^kVl8Btu=O+6#OOM4rBwP+8&^X3_pAY{fV3G!`?ec489v1r8u}(i-TF*o zQbIhwkiZ)t=vBH$q=rn^b=o z;KsH=p1+#>OVJfQeG+Od_yym z4VA8sceF48H_0J>tT+~Y6g-?UjO{E`e1(JA|!hXf&9GATX8NGji@U*KQ!Ge zefD^uHz8BAGb$`FJshYa>cmGk1H~FWvS1Q}&KVc*fPfdtGU&N*U{sy24pD6+s{|A* zIgf$IsD2{HzDbh>)PlCeNW(UQ3V=-`hC;W37!mbl{@c-SBa~qc+KLt$si?@ru#4vd zX`p7MLK>HNE+DukbBrolIa9xnBbGrtV;0nl^QeSM8fY%E(`6gB0O3DYNPmfgQdJFd z3KT6+cI&K?|_AprL}Qdp2MywGL}mcpEFVOd`tt_`|z1p@g4a;YX?Uy_=JE*lPVrXNyjx zexS5jmX}h)(a1x*)*|m-g8jOP4Bu+MV_O2DBMMf*=g%8?8wx&UQ5VJ82$70@(toI= z;8+-%LX+^$MPRInQrs#S-t^I){1QF)tdkOa?FDl7F+_glm!&WVUraH)2m>MpSKB~v zIzh&pH=N!MG9F1gaDe5Hy#27zS;fGiW6_LXV_k$UCt>-3Z!NC5wd{QR}AmChx zEJX=sVO+==)&33+c}ON^^CFwY_q(icLtP6HNBsCT6k(Adp1twtgYR7iHk|c0%;wSR};WOaJiYS<0(BcK|QFD`4un^iDG4JGA zhj0Sj)=l;?lHMNwyZ{A^d1fhnCbWFfLsnrtfGkoS0<*)(p@;bY63r4w#r5ZU1+hVA zmQyow25`ot9Ax-ALylJm@t$sNKn4-v(7(Uz?!n_7-q-GWqoi(Hfm&@dDq3R?g5Yqy z-*97QT$>zDrtGeZ?h=?sCC-OlNPhsCVuRgGYHWH__q+FibpJIw@ru+ncEdAZqswYi zVdj;ISp^6(7TRVK;L1eCTI{0yiH|^Z*r*SRfRBYRR6vZ9PNs2#Z0Z5hsg3IN zuG(=Ww>e#Bo8A~>kk13hIb)Q`1cv`A_46&pb4MP%9J3i*cyN-}sfFyg+2gbXZIxd`&`FLz=|DK->0YAt9@&3>3~ z5JM(2U=CyKav(-NX&>xbWoa`nd+IPxg*eJNeSRK8^O&#OfRkASh2@|7iGF_f@p$2L zaA}#X@q#TRd9S!Rr-BGPVGs}!mi*w~P0T#f^6_Erzrt9pdx!Xja5oasOM|kUP|*8{ z2|442@p#-`2*JI(DMz2rN0Ve%{G+)CtYEA4na8fQ_qH_KGk#91h1m-bezl)wo}VU={{n|a zv_R%%4{mJlalO2zYF|i#Y`-d-teyrt3}b6@TWr&unMn~(z6QS=xBh|`IwgGo%Clj; zu@BfB7xK%QM<38GSh)D~ncZX4Ah<1OVpq^db3~(-(W9ajC`b+>Z#0W9&(0%4c&PH$ zJX&KPA0wlsL)vnHSSFgo61}&No%!B_xX+NL%oIxDbZVMV1pJ`b?r!Pb-1u6ID3rac75|AY7D zrLaJZ$R2E~f{=j^8X-`rg0Y!GfH{c`kc$Z5?nl1C!NTWF@Jq8p54}(ogU;;Kjinxm z1}N}F|NTm~!SGeS3}(?(dysGs5;wPE$bKP*P(5pQ(8@kUTJ7#$YfTUs*zOr#W?JhL z>Kkk&dm95@KY0k$0pavxa&$C^?oihl-Yo6hY;`oQN1VJCHIY>I*ejmTgi-W&bQkYu zFNpGiOg|y7X#L!OScgwGmGB~GpiKfhi$&Q*(`Y38quTw^iF|^Iz8{3+r{fg_mJniS zCNN)cMst^8yYST@C4*G=%D*qg+;g3g=o})8N`oOD5ndPDm!Rd1XL50UewBCuIkD<@ zPn|#k6yO@*LF0d~asX_Fz~6=@XZ6w|Fz+a8!y2MuJr^aFIPp-rM>jJiDR^%j5(^FT zULj%P7>tky4sO^YHC;*Ngt?9hw(Jf$QHU$*%VN>}j}536vBIj@@OLDVM`r={ga3t& zf&V>^tpjIp#(I{p2b_~Q&WORqTKWS&87+ikesK6QGjLvtFa6asF#_I88dEz{D{EFk zA~FO-#}<(;5U_7|XU=scSP>SE%N0_a5d@I2dQ$dqyjX~$uM9Ze@#LyW?1pxVq#vewTQi3d;&M>@6lsZ}3#(PU zNRh)=^7~=E)v3QKY}e23f{uK*cbRYEaCvSI<$eV%_KB*_1cB@uu9lT@1xz;YOsc*I zl#HDO4LkBBR?KyX(HT!)(Lw7#bB+% zz^t0aPvWewbNH?O=*YFkGrvWjz|=F^*iSal&0D}Kc6P2Q9t!pyIGf@Xz3(}=tRa`C zZCt=Sy;1-YA;qSwC2tBu$AKNl;<|u%#`4L=$gxbFHu}?bs4Cmh820zwk*6;cMGf@( zZ<#B3;;9beT1ObR$DR9@B)141Wlgl*&)taX$;l15r$87DF&C#T*9-u2! zWVjBIM3n5Cif#>xR+DmTb+6Td!bT+szQSg;kT?e142YKjb4VU;JefxpN7aQN6_c^-?tu2rkZCr6MxnL}k%dZI%$2 zR$IhErH?cwFD=4TWSK0O@_BLdOc8MMYy%{0^GxIChV=zbAh7h#l`eRiVwZ0(B?ans zXtthXhrOkGRUeud_I7>I@MSrTf_CI z{~m>t8Rf8^#;rD6p(s@_0{o`NV6LZ57>VG#VDiGR9?#*J8XcbrPn8#nJu-w7-X*wW zUTnuR-+}w3DaNF@a3rA4ISB_{3on*5?jY4tc`+=*{7Puqh))Fd@=JH`a+{AY?KuJD zzlKxvW=jR8?e_prpn7R?MB`$!cBj?ugx$bZS@A_3jWA@F^6P(7H$!zK4cIdX)&L!Q*XzQ_OA~q<0W{rE6nD$6Y)*$6R<-q$uyC%=N%f{S&?6>^ ztV#cN@7J%C07vH;J1(>y1|Gldbbp~m?87fhYCvpH9%&Xq^=bs8=S7J0$T?5Ws zux;yl`xXtvQ4MO6l6db-k}Rj+8V=;CUZqArT$$UK2-ut2&S8BQl4vUlG-Kc%w>WaA zAeOigu;@??b?D_Z>kJu(nuk%o2hXps*$bqE%`0%QP)4+ z+!d+kd0J3ZfgQle;G<-qvhR&D&k=Ki@-tv{S11&Q!`J7KH{9qfFbx;ZK<@TQEFDFVv5!WtlcvP!Z?C7&2>3o}26 zpQn%PvtTIZf6vMSP%?aOEI4L}`+0?lP1bPZEeA=1tQVY>%9^9_}Naa82X^ z&IENMnyzYaElmirbmj)VW%U+0LWc<s$BCuLr2-I~Gs7{8*M<3@6svvPt&tsk4hK-dbVPiFBd~y{dh*)Q+5h~qg4a^L|gul0RM}F(zH^kXq`w%pjX2# zOAqCAfXGXlr9G#q?ufkZOhZ=I$G;;{jrHS=O-!ZFX+84o; zAxA1b8h)5Gf`s7bt9iqer&W|`dizH-@kcYz2ereSdgdtTk{f3mm$`CTZLhrg4Go&s zgkra5s?KuA1zzI7uE}o$@9PxSbOfCYH^;Z(rvP_X8qtZ ziy2{B|CB1z;WOT6)DRzI=O_|_%mY+*XJUrp95#$OfD-S^c1oxAf+>BHnwL_4Y1LH$8g67R`7ls z)PpXi1{=ny;Z7L+nx!SU;0*u+WM@!epJtkz`q>NqAlVFTfRGmFzvM(Q5#WyKr_^44 zl@6x2tg}$(cO<)3oro$9A=*u1%@~3AP+buSmPcBaDroNGx1^`Zj<8|3J}e0c{7WzM zEPG~Jx!IkNmaXZQrWRAbn@Uu$HAq^nd#EXdC%ok|3e6;{kBwr$#heYWo8T8N<&>f3 zVP#r{nczJCN$LlPDDI7ziG;_{c~L4qYn9myT$vdayamgm$C#qsT>PqcI?zyE5Lkxw z6b0Pt^9?)!&$psKryHI?jIqEL0OLb14nuCM z-KPSC2d!8vELLx}*!oTM=}oK422{7R`5k1JX3ODL=dgj9$U+oYu-=Z~+|TT0pd7pW z7@o@OF8z#H+oVotGp+#p>{On(q0cqZ%l$C0!~HqlqN`=#=U~=<6}40|Zhhk6x=Jl5 zyboean7pm4SuYwzS-UX%achQm2I%``GDxSKy8dLXbm)(bhk)s3)ZUkIQ};?(7-xIR zkq32*ysQo76WoP^i0)~(wm~QSB+-Kw+~0$$t&Bu7U7>1#$JNhp9*{iF`t?TRYFjzx z#Fo;#hNxj2kq{x76%|Yh7~7aYfEXqgb`OMETJ+TkiJj45Uc%1R?_4~j0I?*c zH0*A6HUbU~hT5~DhRXAsp-M^n`Eb7W)BlR5PfjFt^N(`T48$c{%BP>PLUt4FVSFe* zIGG7&cHxYU?nQ*@*Cw`szzj;IJT35w30+v2ow`_?eWHyZb0*y_(n6@$=n(@Z`&q5L zAB_&Ii#gQsJx9H^>B)2>7iXZN1`~M5N9Nu!8H(S-9?ZE9upELGzVgkhk2aNXT;eA?DCnvJmWvM=E8QnNvH$5Cau62N4=KQh8t(Qnuq<2Kw5hM@Fux^t zxx~HZLPC3Y#fAtES#mP{BRbxMl6u;%bYk5fyf`ZSXr$C@M!99W)ALD=b=-^l&qNi1 zot&>(T_&)@QA8!Cid$XL$;0V!?jBz$duh(HX_U(qfs2J2Ks zcN7*<{YZle5r^CETWX1Ex{V=#j+)n4vbR?d`W~1ICUdvGUeV{Aw^q@t$1$LN ztX@@d=mI(8LsnevlRH1^-==WpP9Bhj?)R41?p>dCJW6a*)&sNAb+}QAX7KBIt@@dY zw=yGdr!W%Dq|0WdoO^-9djgLVbVAUALs{sOF_z$Khki#(^6Z`)w~~sj(@P$Xlm0LL z@KvTzQgkSj`fqWa`~ENsO-+sW)opks6e_2fAyH zCiPp{7NyqtvwcCXg32jjhEMFI$@>RqQ;8>7M7NJ)YOIdV4#mpZU@9>Of_xj{I@rzVLR(A%L#dthq)u zC5?+@KSvvbPE|$uiRLG=GNhNt^2LGG3S*p#WX*9P_H&+oLdum%qgq`*B@m8PCr_+y z^C960FEb+G)Oe_db zG3V$HP)dKbDHmx7CsDzFv&G@hgL}rMgJMR(qqy38ZzQs|oy&s5+ee%gl(!RjAgizl z`L0gp{>RC`kyW{q{Gm-;`k;Q~&K%&=#Gte{Z9`K5^~N@93k@#2UOL2^ENbwWK23Sm z$jK<$XuD*3yizQF0UhrBO*zG#{kbF+yBS-eXynxbHDT|;msw}wE_78NDpl-Xf9CP3 z*R!J0(Omppg5sA_>siBm=#j`0gp&L%bS<^#nhmlsRR`Nr4=(AFitZ{vp9X>N`mYR< zh&ncte8ue`NS5Id6({_2wvQh}Avoxdu?1IVX}6w&OcJB7rbC~gthgMatm;ER;LUWI1Fu;R-H2c2Tz()>GW@AhkHxaOR=DX@ot=034STb+ zS4MgL55$#o+Ycfd1g`!lG65Q0vz1-ZtE6RRDbG2=K05{zkn72#)lnV!rSfwgcj+Wz zRKOVxAJkC#)rQw<|r`Qr?%Z3ze~Op0xQ|7vfapjr)TOx1&AfJMgpc6T;rJIfC8S0Ttb#XpAO1amhBD(e9=Bw&$? zH<1eY$C1GmuxJB21b5P@op<>@|Cq#5md~_(;Ke!8U9$(V>G1~Ok__nd z;vRN)m)zhSaPT@&nxsh)B-Fc9F*EOW&(nKOSYCi9STAgg>*{F!r%|&%!G1WMVy~xD zpZ$U(N`!R-hOwUs-CWUIs5dfiPgpxoDaSE-1)FR}N$uVP^q2;)ljIOvt2&h|<8UgI z<_s5Q@!t(Ee!Ib9-nu9G#YBk?*)M$hxht(le-U~qQy^w@=g|~#QlrrPWM1_TY|O4l z{EIl-fLf&*R9oJMr@W!cc$vKi6{EvQ1mQLhaps?8Y}1hNRyDxHT>LpAlek z*+qbRs&1%ri}`@0)I{98z}TvrP0(@=tHf+rJWQb)vwOW6XO6vZewnrahf$oC8=XSW2mEyVx9<(e zeWl|$!W~OLfWr3E%GM=X?Z%olA5=dl^yv)0x#1kMLXu|(Z8-$Wyt(lR?rm4BH$C)1 z7tX`}OClFSuo#Eb|8X{>n8N6rWkKipkXBcJ>z5p)KeFS(oOpBu~h44nlG(tc;DOWkmq*g8lF(NnN^((RmJBly2c}irw9zoSs=cVGCa#LH_X!AoQrO*CfA~%~eW`vy;vNhXFV6m3U+-tfPAwXzM5H)*tMIr~ zX>*e=r6VD-7y91L0B=HCzLCdDiU((36x5S3sh;Y|HJjmc5=)mox+buIVs7$A1Os}X zsf?KsoFgEK7$NE#f><_2nKPUIJsSSn@fxm#$LL=@BO?|(cu~fTxz#yM=arUjiA*BG z!|A&-g>C`IVA$aDm6{EFerQ>bi~hd&fAJukqW}m0?RAap>GtHGwWJqj7VowYdBkbH z*Vp771mCxmRqq@9mpAQFxpdTB0&NU52qf8lqON*bL$I%M z#m^z{u_C{28D}MP=z^#hAkkE!$k)kON@sIHrX1+ti%*YM&vcPfA2}C9W5HZS34rwD z6BOD|F)r>#n!Qq>>BMC|VRQVTt#yl7B$b5|LzM$2S-44U z6Z;QaR?Rd`U_m7fa{|R9pG_9iPq4JeO46|(7>r0P?KkVo5P7Ly%v^}LuCw%OUzzl4 z-8F?PIWf*}-hONGcj=yeI86mfJl?o&7Da*ya_*Iu)RY4}CFu!j@>YCOB9T?C;o4Z{ zwku`>b*prn-I>^bQ~kwRJPB|Ajc2W5hZRTtoHKldlUht>yrWL)AEAEabAjb>8thBsGqG(Z4~EaHs<7^U@$XmTfLzCF^O+1c27FX3*uXkS z!KR02{LA53H(On3QcXIu;b>|Gq)VscbQBQ#A>phT{cy>~ljw1=4AtQPOo~j%NiS}} zr5j|9uDPB1F2`y^oGTLA0*A{}R@Ev<)<$>-*cz`PIL?*ur915CP2ft&ju9(*x9jNy z(+Q{&PA7SzqJlJ2!jbCtqJDGk5xFl(vMvuRb&=_FM8kl5C7LaRZWqLhtn^IRyuhLg z+TkV(N#VDDLGd7fGl`enBa?KtPCtdS-tH7DxEP#iJ0ESnj9rxuB;_s;o9Vf)= zq3szo!<2yRgoVBz>S#Eu@9S~IXJKmOolNeNvX|nJ!)JJ?=#u=6Eow!nz=eN{8D7(# z=mRKgKpwvbx$HdA)tO2Osy9|`3DV&@t^*ad4;9auu{LRfPgaC_#2()74ATn!F~ReK zJ0U+-Z?!c%yCDpv)LRSGO}&G2A9kJ1aSP5Y&!`+uxWMU$top4!8KlA@$e}hvO?y?_ zW>uerjFw{&mr=BtCrI~Z8$QUzZ4TMgVR*z~4=?byzfQat*r~(hba7?Ga4S|naAIGo z07qd-;*Vxsebv+oZ$nQ_c>#NNhAINw)6=Ww(iS)rO54)ii@~4oHQ^%i*#X?pS1fIo zCTsE5a>KxN&XW9!Td5X`+-`Iuu4Km{XT)`Eqvy6<9j`-RipShw;C&kmi#=kB+z%H<|BR9T*VXvS z%BHB2SV~K#9PdEm`4xfOLf@rhdde3$l=Rb0dd+cLO}aI96HURO?6N+33g6|{!VnX> zbd(W~AqcH{wXEu@qg8J9jqHaB zyAAWxDQlevKhJBk>=LMAq2v<-)51NUQyVBz4I!LF`_hdoSjqT)cg+1wEP zP`N4&6N3e-h_ElIMyI;LpYJM5aN?*twy%6>EiAtYua^@A1Fj_7I*knUy<4!Y zN0HsK(}g9jXf>Y@ZTnpDJ48vYL4IJf+czUr;wGqF93GCQ_Ac~i|LB@Liw_LQju0%Q7r`&UGJ2vs9sc|pMcfd8j+tVSlEy5oTn zqgF3!s&LX?>$8n&ZMCKJJcfW1er`a#Fk5mo}<@qSd0# zz_S|gr*PC#VWAc`GPVTfaI%MTI1W<=bAUmNT^P)C?=IdmCxN=wFlJJ3ms#vnWtKa# zX|1y2&bx9P0ts`+GtnFP&n1!c?gK*S`$Y(V`EqwizuS`-po9TRfw(L9S0zZh`%xVU zBTOfd+dm~lc`T6D?~y|y1090AyCXRc4*^A>OUw#myB~)w`HKy)5`YOeki^Hwbqq^m zw&`4yaS`J6r<49d==JczcXT_Gf@_N^+ai$Pt_}`Mk-U`^r1cwTN*fONe?qt43&q80 z%nQJ&qpyQTk%T9phr(}>X1k*`1bebuqkqC=c>csIaID$%BcDoHTKydtg^M#c%cnUspu5c#`<$LyWOAjSdlv-Ku(F?%AvalbRPgE|CQmL4cec1XaD$CDDo{k!5aG7 z+&1{z;fkMJHKs8BXO!eqdL|I^=3!MiXTNByxO%ZuQz*r;)?TT0C75ua{vPBln_}9e zo(LaLnSWwzjMpiAl~H!=3#Q1(AUGfuJmieZAQ!9s;8C)GRV_8i*iuW_6DD32!o+&L zub!sSAP~i;xh!6JH9ysS-no`{r^_`}l%}{=TA3%cC6cw6%J@o&KS4G%Ql>hkvAgNA zLh-&baaE+Zmg3aJda6H;e?s{O2{uP1wb!QuU-H$R8`PSh6}s)n9Dqss<4IG|_V z;&{ z`#ScnB1#NM^A?!V+}lx2t~a`x_di?W-|jNh?SGK8qb>jd*8g`it-YP2^Z(rrcYOZ* zu-F#w?|!LKHk$@U*Co8(wl^Za5c(n2V0il-JSA-NSZH2z4brxBuG?)s+xnhlG;h$Y z%Pj6X&Q6v_>#1Wzix$jHnXzteDpda$XXmsf+7@lev~AnAZQHhO+qP}nw(ZQFwr$p_ zdaL_*zhcd{MvsV&p6KuCY7yRldwr`o#kDFC5?^kJ(PUo z>caMygpd-+ZcK2Y}rV2({3V0e3IBv4Hs_JIw)up^GuH`jpY}9^qYx zRP-1^%ki3^3Ys908|lO0s^~ zcy8juchb#|1|32SsAdsW>K3}q{=io~y}7Pq#H<)pc9NI%(Dwy_ht2%AZ(=U1{@K6G zZSDM4cL8Bk@naAt=)IM2hb0{e=4R2YsRSFlE@8Im4bPuW+tqXb24?Zx#(iyUKNv_f ztL3tVAK6{itm9NIHy>OWtSD~uyScAivUZc_x&b=`xT&7Wmh-C>ug~hy|I-a&=D2eY z+W_zGzBC1AuuyEP3bUol+C9`MJ@f!0P7Yx?1=zwd!*(q0C-8Ejd>9;KUUCMJmTtR&;d~Dr| zcFE4h#@6>3Jm~|9)Z~=u;n;KrPJj;N-Y3rQo^F`JQb(oMdFG5y;s|nIX^<@*}8a(3166}=M-GEQqBZ{$uONd9{IF`G(ffKbdzyczay__SK^uj4KF^W*IK;-O*LlhevPulF*ab5EOo*M5J>Q16ZV z$R~EtvK)RMs@NG_KB<%7Z?wWB3~F%r5?M2t)Mdi;%l@aGO-uQXOmvdriiCn^7|Z}R zd*;xUL~LTSEo(AsqvE5SmV=>-9lnkYpgJ1oabZIYl zex0pk5RC)^I?m&wc$>l>a!T-8&&w3l=~4X8M?{fU=Q_xdWfCxm9>gYCC8ac)3!_II z^^*K5lMW6(GK=BnXCPbc#ix$2JTrW5dawa}T6EgciXvNH%wDUcxYf-~ukM?(g0UdF zP_4X`_Qc6{=}bWpD^_p^gKK<8ul&Eb*8oJo61Yail_C>vO_H(yEoh-vVIJP8o?FpG zkB=KgkeRQq1q2$h00P7LEeYTY8r~rhFc~sM{Z~MN_!c)s2cOmFRCEyn zP0YsMqBGLVl(dJURcJLqCDSA5CFWrz`U-n#6*dxtk%(t@lSW6O-k{ea4YxUQ|% z%d-9o0U=m#?d2!^%3H4C9-t|7%TnSgLyG}T2h=gO1sZ|>!Y-LLtJ(5wi?Gu1e_C8) zV@oto6Bas{9)(W!LVi`}`QA9}XAHHs%5p>I$03kc@<)jY+QPfJk=W!jh1py=z+?>Y z6`>+EHQaEfoC_mK*qUJ=QJ6gf&2LEdV$L#!&t#!R(vqa8FCO^l>*rD|NkQ^SNM_IX zRVsnlcrfIfgxGqG^K$tm`}vt^Yn@Kq9K*GB^AoPH3kj&tm5aAI`ReuQtRR1^b!l>h zxXP2s`-a_SxQcjXb6ky`FV<9b&ZK(QbGK&&*J*qrBkY;ce?M%C}|Co3@X{wBQ#d zxdsnBk^g2!QsHW36U$v>5cf1pw^N8U0&GB9O1OUOD|s(hJHO#r^oE=rQ2mS8w;aEc z2m8}1_X%Aw3ztg-5fn6l{tZ65FY{go$#?5krOem6l~v>US|k^FN9eV~fBNPiFU>FB z&t49s|e}EyzK+_M&=vHr*vT0a5=W}v)O&92Ynm%9?uBvvpET2ejUgNKBEByaRgc4(Z$51%Y_kx#L`F66*zyF z+gD|)EGb0#m6is!g|t2e4$4VWJhO_SSM6wg&$|`7`KzzS!tWD!$dhL}HD=B9Olre# zW3T2P-s16b#g^3$4h%gW-|n zzdobMis)oEQWFrdC>t^^CWD`WkAC%>3ahbV$7?kLG2?%=(M2k|Kr>+u1x|e`X#ndW z6nVa#QORK>+Vv4gPLxK(G7@OLVn@Uis5Eqik53)NZSB%J1SWehXL;>C59bH*9vp~i z>WK6~w$Flry>wg2t-gF1Z17cq*VNgvs!4oc$5ytvIVAekHHGjis6Q`Mx_{Vb_1bTG z>|X!%#sTxsaV?B_0ep*Jo)u0m3;pQZz*K+>)4wKJA*uq}^LvGYic0;aEa_~KK!`AQ z#|5-!QQe&Trgj!E=^DWmx*zi{cZXAn)dQmovpJqk=oBDqgPqUc2V=Y6%40K8gIMd( z*-m^nVYe&D5dW#oX2loF#)tX=30}|2Ki7v<1)`CmF>7AAmcR5W`zG0rZ*-l*Nq(JC z3F*ASn2Q7r2`|Fkw6gaH6A`G=5xX}Ac#7&_t4?anq3*WpjvhmaK>w^|vr(CO>4zNf z2!Fzutz{gIrNs+Dh%|7W(Za9t+&rFA-Ofyl(azeP0~7T>8i`=D=O0K0^nrqr8WZVS zqj*4xi-%y(DO_1%q9Y=|43Att;q)baoIGc zX@LS<>~?AG0F0G(%@V-eq7lOIz2ID#Z6sVQ?qB38ZD*yBiu5K+<_3ZsE=XtOu_**e z@oGUoZNDTRF-*m&Hv%#vmVQH!O>AQ?7-d@`y@kbh|J-7PP}KOG&C*4@ru*NtjLq>8 zI|2!RJnRSjVyppZ2J-Q`Aq0jg@32#|aQ;-S-*gY?z9T<*0L=s*L0)};G?w8qntPs% z<>_`S)L?nESFv8lb=R8BV*(nrAkRcc#jw$|(N?k_TCD=*$e8;j?w(h26`4xX-dBnf z(j3Q}5PO)C;XCv7N*k?af# z{>vUl`pLjE_@GRsLyFo%!=oN97mGmDh9vbmIMzBJ$eM!ST5)tdU|j)FPuE@;y&OQcgOP^WOsfFa`AAon=!H)2 z-kFFIW{&Hn@Ql^wdy5wp+ei88vfF=ojE#Ql*g(wG+rY_ zXwew&s3meVVn#>JFva+4u@1ROSk4D7E+N&}5j+83baEUgG}s-zR1)-Vv|-7M31HM7 zX0!{Dty73rHw2Jq#FHO1X5Mxsnn8e$DkK7hSet=lj2zS!4|nD3iYBF?L85dMTEyDH zSW9%<5*-!9iNoh+09!*FeO9xXj6Go|b7qfQXK4k@Y1Pr4`I#IX<8lf3GbqiJ z$Bo-|aJYAg(tUBVPrl(D?J1%6y#z7iN6cvF<}Egks8fj;Ws4 ztwLG40vbi2HRxcGdt3c$u;Hlp3RZi!_*}%ugE^T1=m2XCg^VJK6km(!ky*X9qRq?& zK^*Q;Xq|nDzLRMNzu+jxMK1T%VfJm+Uqf2Bxd9~02}yjq!thA%yUj}XpwoE zjwlCpCy)d9;dC5m;<$Jl*HGyUPW%r?K`Qsu0>s6w>I7E+v%}1~+XkIo72>eyU38~! zVxZ3r|Kfz78g9BIfAQXvbp9N+Z_uDh*UtpCARK}{@@Wg88qX`k2w{QYto3({3y!95 zB7L_7l`d^T?Cc1H9LoEd^aK-`>;bQy(Ww=1;IYE z-aMTk-3CDuFz9v+wB%taaT>Gjt>K1uO(VF+hbH_7rfmuJc2Vc!niWyz##WZh0w{lAq9WBaI%*+!Bu$8WKm1tQFVT-Lp8d(rKss10%#phwON}EmrrZ`P(Cxb*lYw5w%hxVgFCYZ0= z92fh{kT%QB0nf$P0cEn7iKKQ2L{&GMXyX=O0+Cr%+HRb5H0Ik)9}f#C669I;F&dlc#X|5> z?@qdlJH<-&RPBVRFtYCP0Slj|ni|8FD0(00e0DLw9tx;2dfId(RjuNgq9>`FG*npv zq}2gvVwvG#rK_*RqJ2M}ICuEx?AD(N$V>e|@L$RUK$uUP^&-iFpHBA~; z6WJkNTqDj<6Oh{(hXV3ogJOzRt9g0|EdlqnN^wQ~=$ga*xurAEkqL7$-rsBx6pkwJ zkH|ucb^>LW(pzJ-=LY_9Dd+;_3y=b9>%T#M(tw2S^gFcLUDF~Q(|LfIo_f^GkfnOt#URxsSb*MLtbo-$QH|!k< zVQkT{PG}eZ=S-Z^eRh8QOhgBl)X-C%PxGn8z~1beK>1s=(7Zz&$H++oZXAmcNP&;l z9SasK_0b{$J`VI+gd$}pFoi{L%h!I)YU1J~tklGiW~AeV5g?bR)0xQLs?xxe>C`eO zt-Q5%tGL%q3c;|Zi3swoIPE@jm>$z*M^P%?=6Es5woERKU5e_7pfSrQ74!3odFG%4^;-SCTyiu`3y9J;}D>;PTp)9*If(i`Mj*o8a0I_!H80<(0tU}^gLa9G5n|!^i4t?B1O$l5CPSE**Fy8m4zrFk4KttpKQ1}=7g%xiB8ubYzSp` zt^&m))VjGcokA`O-_k|v-E1II&(|;ODfWUD*zN^14 z`{lrz-$act|7iJ|AAX?p`e8U`Ab=eXuG7H93hSsgYIupiC^s&jhB0*XSxqwLoPPn5 z<1J}67kbUQIi=t*y`_-Q0dVot+w4@UauragGyBo?43Oq&%#q~VuVw~`^V?mbJs9R8 zF=DA9w)FEyeAp*q=_6s=!sCryi9!M3qX6_v73toO6oxO|<==@wgLvB}=9)h+y|%e2 zDY}9#J>)WO#2YF}b6RO?@LeB`I}I(xeTsn!9o5aRIjcLH>)LA29%x(ZT+;`##`K?y z?AEk+kz(ue(X$gu?Q;Et#xo_;04-S3U<0BU`+VY-tI{O`~{Y}^|WN;~2wT0`maL zTz1>WKcqepI0m0C9etM6+Lg^rqsu!F54U`A?TbaJ^dB2H+r527Q#W-9wY7v7vN=)^ zDw`w)2v>XVFmZaRgC9Mu_}`v4^K8n$ma^!Zdf|L4yYJ-#3Y^5d+&)Z~2bIW8qn3AW zUH%t3d3jI?xZ;-?=})6NyG6|Ku5wn1@0L*1$AAZ!j^~$?li#5u+}lul5X!nwZO8Pj$l*hG8^{l z0X0=Kyxq@5rCGfh8nrF8NN-b1Mo=*w^}7i7x+x4xV%+p4TaY&?Y7%&n8{(K4UP0B# zHzh79v}2nD&K`~agHqoeipg0_R@Qlr*J!)zqQ_pn(lkN?(mq3QGW_4Uyi0I}F}i<- zFds;rzCsjv|0qW!^!7EFLLKY&gn@HF`AENIcumn%Cl3*kaQR^VnhDFNTZ^#=bH)8S z)l8fht40*05{Q467$Jl8+WGw;WC|a`3GHgs3EQW!h&?#(mlb*^(B&}sjzlg!zh7)tFgwYC7vE}|ZyaFg$MBDoR5oI{VKvw>BMR;j z;v-ur<6Vg{tUgQ-6F@py7;kWLyqj(;hNm$S3S1{NooG-%7z@8oa6q2o59EgRVaqFAY;5Y6=I6qz?lWBF_$h2LP@a}Ek6g~n`+F}WJv7@8vkloEfDJYub#PsNlV@H069z+0_Ic03Hb zY$>((O1dHoXt-23JIf1FmtbX_0Il!-(BHLHAFhU)fI^!?K>HbVLCqu!5@(1wrL~$N zo}`4|`v=o$-g+jmxT)~XR2qh_^6Ge({5zefwy+^NZ%9UQuy>EkI)<}c3ogZ&-yUdU zkScn$(mY`b7n3iP*(|UCJGew5yVV^!vsp|nDmU`;uxQ3JjhGflK+YiHNF>R|#(!+j z5Lp^0LG(eSS&8$KvO+GNXRVAXppOFS^GgSP3A}j#hzTahRK1aU(W!P-{SbeFcf7fh z(!JOnj<`w;W80?`vok++(=|1OY zWk!-fr8kWxiE}=dq05@)8@6|Q-;%e4K|JgT4h_pc@bS0xv5;geW1%oos#R@Jy(98) zu4k-EbS97Xn^#zIKlHNA$Gfm?_s)KG#U185U@;N)j_GtV-u?8A3v6h$_~{kpKTFMv zts%`NWd0HT%-|bpls(ag+T4#=Jg{^U>_o>+jB*1iX3C=Uppr{nF`R9I2 zd7u6p{m(E64*`9z9#CE1U!cTLxZ(bL-z$3U@Bw4D8|9ISs$3-+Qu?Tw9r8PBeczw( z*;*@G@ABOZZVsQ{!}IPxzqj8X@H2nE&yQt#)FmsB=Y?QHI$;{`>_P(N;4`bKTzm9<71K0%Zr5n#^nV|9y1MOP?wKm0o)wF@ zi9AqrcJkKq$N|cJY{?3MR!+@=%%sPVa^@k#K}2LJt{6P1A0EXmMq5_DVsQkvE>}2A zA$WKVDOh};7qY0APujL%eiOz&0~BYZ4{@o3{ujwmq_Iug$kWv=sym@6{2_BkbFl7m zO>iOh-;cL^a?x@m--=(y>>l?zG-DMdF(%A zEQDMKgCO6szUy;Q`k0?;mLbkky)%M+I0gI4hBpTS3#LK=r=50vXpjUO{ICXw> zrp5CFwBthdj6P^5GrPl?3%0q4SBk6HjB>z;q^Vm#1U$DBK2{4yQ%SZ&Ds9fXh6Dvq zY-bv`*s|^4oMZDpZsK+bHwa{o)79$M=LK@NCbJR-Ov4IQUKo6Uo>oaVy2P2i)m1iA z(QQK8y!m@7xlD>v;HkARuvmG)yAje%IHn$nf8`t?hj4S~k~{uq{uCx5EA$?(eg8$3 z08i9u43YDZMbg&AWw~PMDHhydjjhepx-TvH^p;L#M&!Q&H4apgia=WQc#%wt2c3q8 zJ|*3DR&y(U@;0pbwc=_Rig)|v&rp(*%2Rg;qa&Si5Bo*s4D^bbl2l@JM@R~cArl+xn#kml^t=a;%=We}-bk!XeP_uM6%A}~MTF($sV(y8%-eq(G@Bz9hRo*;4j}HT@xum!#kA5<=5E zDsk(pS`r{*a6V@fIlG}z6M?#ZQ&WEWgNuU8pAN6m%~?3ix{5seB&#C zGg$o&8P3CGFs2?sgk{NJ9g_ikQEqX)a~!S$m&T>7B&1S0?q6(O7`uyTrYr=y!JNL(#;^Je@To1r~xB)*~Oneju zZW5%gD!B~)l-uII8e8VvyW$*NHKh)A%2{>Jl*%h;#*dL<)u8EvuzbGI#3BnXr%`}m z%$)JtO=eO3a`H_-FCJ*fL!W;moh|}kov8cSDgdJ zP4uIbTi)5i8;7e5QHV7*^)!w_HA#hYJho@Wz=_>N5#2w- zME1WuyMR%$1ZvuBQa?{u#UMYVdqe>8oexY~GAhs-pS(2E%bn z3y`&!0yn)wP$gVDfi6=>@X)h4%QN{o4)M8%O#`)^f+Mx1UahTbvtm!$<|r@e#@evA zmDP~|!8{MCDOmP1E6tklvEVTCC~ziyTDiO~tQlT}Ns-PtAK-NY*9lyP6B>mgZFJfKpUbWqL}(SaH&zan0t z`ps+~^WFI`?B!kB6FlZE_RyLouV-^Hz%Sg%+GwTYqi*L9N0zil)=VCkwX*v4NFjS` z70WyEt|)JtxR#}3iB-kj$DqdpFO5tqlt|5(t@tB6TZ68)$^56b%+1aY(>aj_#zOP* z^q^7%$){}(>Ymx}|=QN>_Axqp8b$l78Tj#QIMIO@5+m!+i3)XBaA7Au(z!R24#RLUPsLr1TP4 z$7%>P>lKkT&)X@0zr8p7$pTAjx5QheV)WovK`lXY)of4XY^^!Zo(F{F3C z>O0^5nMG{iP(WAAj!tOBU0*c=B`L#ZI-`A?Xq>kThp05Dn%o9}ca+mdm0y-pGIEOArR zjwlKZcHYB#F?rL8^1Ga4-1AWC0W*7Be~oqMI)qYhcDa5*aTL`A2)--6BB;!A?I=nH zRZK}PB2sQ~JXYgQ-foCxCL&Q{#yM;WdANge2Q%$pk#`9{re!8K1gd}5A6+QDiHWJnai@Nd7g?@uOfTnka55P9tG22y zmJx^vo2t>ba(Bgf;9xMtrTQ~l7KwY-;ZSUilDZXItqpuQF&X^(0B{bRKgC^oz8)@h z`AD0>Zx8pi^Gh8Q??b+KN4tj!2QF*{u>S;46W#UTGM6OK;{uioCm}XK6bdV61Y60TO=Xlj|v-Ov~}ms+q>*Z`tq#pqV7h*C;Wg557XF*_IW zWH?s>1qnc)h+dj|sy*sRb;g-8IK7F8Lj{IBu6LM;kaJuimzVSIQM@wU^cnHmVNjgb!Z} z$rI*)5?>%LZQP(?$_?Fs)Fivp^Ab=Q1(y(ab;FWik+CiSCVJax{w{1VYCAlCqRmB`ss2AIUFA2XcK)nhU^EcA zyWK-R>Rqd2O>&Oflw>Tp`I`hgXj1%Qg?#tGr|0(Zk(HLmrzkx^-GL+v*5IZ4)F~Ou zE<7aU6*%x6H!BD7-9Rg_Wr$vg0=-#MEgiXb%}id-9TqF?j4!MwR2xiuKWO3Jz z^>U?N5foy1at^2VQH-de{=}PYLr@9lt1;>CB{OM5 zR0imlosU@mTKnhJW!hs%#&s0(uomsxXQ99~hJ5=~ETE~wgOmyHj9bh2q4&2W&`@G# zQ^u`u4h;HeIwT?Be_PSz$QbdoZexnOb=d5Wy3fvABza#cer&97iM{)^g`IhF%8{8G z`>(8adIhSNyAO3O(cpqQJOU$kvt)*0Z;Kjpt~T(qR4ef}n2Wd?&^R0IiN&GY+&cL< z8Wk3?NeoOXIzy9Cz8x6BOyqpzNdRL%iyHHa*(cQ%!y)Jx#6iL%k$cNE2&K&3WjexX z)g+o@;NITK`}3T6c~<*4FIWcGH?u#`H63SS$x#N1!$t{5rph64G z^{7SDPpeb;Uf!}Zcr0&+y@lL?=mzdhxo)X6r}{THipC8ivk32aD;wDPe%<~3f7kK; zzel&{-xq#y?Kx``mh9mLyandQ=P}&m+&;ahER^Oh@8)`=?-o5+8PPxT0#$h}x4qEU{gxn#r+N9@(Yz;j zoB99mXxc4)&sVP1{@401e$%QgN8%!v+nT-j#&D*SlxQ2;t}69mk`l(abWMSHe%d&2 zn$5ei#_<5$oA=L1=ZCGYl*y>GMo8A$kE5||#1v?|)HLQ#9%>E$|xZQaQ{ zZ_SFS{ppcd`EubJ*))ok;sgVC%_vbw$asa*b@#@fVSU-$sw8tt$|@oR$+nnck%lqs zx6r5(tXsUQC=*LGsy2K~`%}fLl0#dEc#qzZD^O-ZbD(uOlXsut34o)_bESLln7T`Z z&==i_Bw=%^JgNZyLCz!?S@Lm=R!|7Bp<4KSX`oBszp-TAullA`s-4pVuR;nTfPD9k zRBnq3h!9(0%VC;YiJ|ES`EJJ!o68tJh|qJ zNNEMt64;SYfVRR<88e zaJ`eAjqsrOj(Soqrjz{Sk6-g3W#{ZMjRx94TUSdufzZm9t)B`mOiklu!JF;KSIk8O z|FviH6OoiRCcGwL7N}n0`Zr&_9Gs)>Jd_`bOO*D-iL)Vs0v?W`A9OUU1i}+^BN3F# z1K%f#Ntjt^|2-BeZcvqCqBnFiQbNfQd7*7bi=^}+rLgwbJNBO7XoJgw>1N|VO~VKo zbjx%l)s>svlBM>}ocbm&72=fIEkJ60;K(HZG=sKdnLpK;z$ts=2m?&myou%n(++D7 zc8vu-0fbg2_Ih&=vqv#C}N>a zBI|9bARvAUrG9|CRPFeo@wxKGq<*_$06rui;5i2X@w@6tYML4<+*cIuomN}$>y_2Y zh0mSKr!99*&9%-j4Pa~*I{Dc2t&N@SG<&9OXfU1pH=Odo*ne%ISG!zD8;Rw;^UI`< zu)rkHgBe|?WM#1>Up=_~q1MAI3p9NJnR%f(tw+@VS>b;QnA5-q**(allmUPcvg_u>X7#P}Ip^qDtHvatpU zh}%+;j1t}w9htC?9`taV=|mXVP7?|0<~!^ur2YpXEDDF z_?6R2j*z;~4zNw7#UANs{YYKwA(RA{TlE}9fv|fBV zyOB-+_s~`*PTQx&QyzUs=tP|RU6kCfr^LQc?vor$tU0_)?83xulm+mMA}W5Ni4EM= zq>tDcyMZTu5CjBmh)7p6;L10jWvN|9yK0GRB7d!Fe%*ru<2Co--~hySk1fSk$$G&m zTD2{P=7SZbtMl=K^+i<8v9OdU<^AvcBueZ$+8d(-q`Nv@FIzEY({8;v*q3=@_sA+` z9|lzbxf@NJ@M|bR~(<_u{fvfKMmW(eIQ?$ zr5tM}a^c5jUzo4xJB1P!o`In5YoZQ>H9JawKCH9pFY<@N5>^VM;Vn>slI9UMViKp{ zf8%zqPiYF9wOJuXt}oL{&&?eBTqYQa5b60Tdx_SwVX}5xxNhq~zOv}fcO>kxVSFPl zSr}++I$+ER&6cL&k1Mq>C$CK8;2yqh?m+143FZ#TaeoF(vWmtOX)`kNvi1%4{?g7p zjZ*WY<>p4Xwn1O-czLgx;rlGBe%=d7O7Pw=ugwrF4rfmI8n27r^I1d0*E1I%t}+5F z$t>ciAsYC|=IBdbO71`2On-dzr{Jhm$e}TIcejwD@BRKz@{3w}9$Xx{Nht~g#xac< zj5}Up#b5@CyXn;MLTau9sLTM5vr>f^c_SyMzev8T5LJmiK(&@*y!Om1a-affE|GJ@ z9XnoUFa<9w{Ry@7A*RiS76t29D*8qL>aaXRhd2ZWX@@U>c>LjU2Rm(8qYVJc(`5hB^U)ND~N0P>#^Z%o(SGld7wa`w^Za@3?oaNl5X%RN^ChcZjOCu~?^ZD-7 z+3$86%>?8xsA0CNZ;ZhsucawuGUbw(T!1s{{rL}35g(h-hnvZ!Wq zCSEp(P9PCdHv$-k+Q=7i`;xu|I1E$XyK^jBfnU#lF@SzI`lV!-zqYE#nOw zLw8%h^fMp+jV@rsZWv6=JVob0-WvoPcH3u;RSeGfmAh}UewD+5F=+T35GLe#+G#N? zW3gCVt)|*I49&$Fp276B@n`cce@bcRWvJn|b7R6xT5XDYTV&==>v>Pm(S@T2Ck`g` z)p1@vZ=H57+5*8f&@=a8_(sRhZT0FU>Vzi=p5+DpLu}P`ws4^# zq4vK7Kn9%D0|tzxi;07rA3z6=u!8SrBiTrNh?mX)r`K%v-Q@$tvYvMa4_WEN!8(iJ zZZL8A@HEL>D>ZFc9xRZy!N(k?Hyg*mZQ3;uiRs3{43TNKZMF0c0E!95y#M}iGC_i# z?K6c5Pe)JVJYN?)RUi0|8icLx9{G>X)kYcdAe zzS8()*+9yW3^{pj>T}#;mXGxtAAke~aWRdH;ewdQIRHs!1CI@`rH^z&!P*x)@3C!L!Ma!tixwyVwp!h_8<~U1q z4xT4x%y{!f*`sI{s?Par7}DPc!}G#%P^5t!bThUCzn+6rYO&&%neYq6dK@biqod`szV$Biynygd^PgP z9(fUlT$EY(aClS^7pDOdHzYsjI6Y@2a==UmNF$mIDazpV1OX{A7o}J{cAu9F;qHCw zTsJX@0$?ZG8YmrS>`;9U*uOb_#r=;X0vy0_SjpKYLi9os1;EzXS%FXNUK*vUiHozU zMU&rFlTLbU3%o`7Z+@}22AQnU5CPF%r1jf17-ijlMa7a3-q%VAvWfBs0a$>r7HHJ- zAWSX+_%{Xf@f*kIUJBvqthZQ(Gl=H5l7oL`92dNTdqvDaD+49`Hn$!3f*5(uXdIyA zzW@wPYXbr?^Zd~<$q{L5@bo~nCZ&w>shC4>`N4w6{g|5t1rL~5?kKS}(Elv>p5%l> z>-3%=b1762JKMo7>?|<5_7XlTU@u%LG+V1YjiGteM!H?ccnd#P?6%i3^T#-LHpcm$ z`!L3NV}}mBa4Ko8PM>9#3mfa^-jiy*VlLoAa?UUeSeQepiRI*vCKMvZX-6z*T+}?+ z@z+m)F^0@7hoya;$rP%XHtn_&wZt#j!z{d^!s0KXY37ikxAfaA zzv15Icf#%_X|AyeGh$y59Zd ziu@Br2cr+9&ew)Cfy@oXVhmUtj^)YI?q@4-~a91pC$*gYuO_xFPWfr;G9tRs~{ z0LQEd1Ptqd0*$9CMIV6_f;(|VBnS$gVA74z4$z8V3ITYG7Fy_FF$Lf^hJqp}pa>c+ zAz+9`%t$eq)Ku$E>YP1;o2-I&?6#C-YMz9qJ~Z(-BXA02`B2s@S#<;>4WA)@dh;`y zXEQwr+aO~_RaP|^oQdEnbC>|!W5V<8rP7w+-PPS|`y0G|pc91eSpQ>r24k7l7Qnb8F2%yR3y>oqoIEe%O*roas|wwEMX!YijzU40tyj>;tfv` z!z68=F^b3{q>wGi4D_pF*;)V$$ew@|*y23ch#|8QmS%=vQPMt+mHch2=~X*RzK5-M}h@Y6ur^tZ)fl z)qW!|m2Zg}?s|#+g1%X|0)gHJ`>uwfV~Q=z2l20Zus(s>TB6E@YFEq*slsIE$01Rdo=V_$gW^1wKkZYvyy z9W+aP&2Cu0{czBr6oCdc4s6G5Z(fOypuf(6YGhOo79yFNa5t)$nz%mgXiOL?(PT;p zakBAzFJ2Q(eTy3wr+T8R&sO=G8x9@6rlosoyh0p z;DI~39P?v=h4jUNX)!lFkvZ=WYtvg=!1aipgqqeT=Wz2g1=A+!(q8>tyJlKV5cWjc z7eYjxb+=kV0J-PNHCj2BF=nnSYhEXf1R2zOE5hA&q0*#OO5tcHDvB6_Adx_0N-?DJ z-PpSO(m9UDn&Swl8WzP!?X4J_}CFpL$|kV?W+imAL!hWagB0C^zB*Yl&z zPy7h6$QCJ9!dG_t6NFemM7caKLjGxilhl`d`MbOnhW!yQ!6ni!0>v=?3<22mg(Kr% zjogEK9Hqbx%C%|+r}FYK*8=KVV9`G3aVq(t=^*yQLL+D+$HOVYhzP<`psV#Qi|ik} zaWwDci(YG+>cmZry80Iynzy_G1I~yr@a1IiWqH^-Sqwcx2OZ;#ng&k#%v8EeTOB5P zZKmxOB06m(dmW?MZ(!==3;k9o(TaKrkJK z{QGxYvV%%V7#`Zs@1ZuGMR6AROKdH0KmTCP?y*O`MWf>uJ~c3iM5(~d>HI}qsE|J) zi!mfDMKGpcA&0tS|bIf0-mXzhGxYmY$S(%@hpC~ydB^_bN>O^Z7%NFNORzVgm z#;Z^^oeQtH#ONuMUl%;TcmdhNKTyv z{UjrH?rxfw8wAVNG12!$_E!D~$x$6Ppeuv+*tVu4d^r(?)l|X##SMV5H9BZ?@!?Hp zzCb_3Hv(HMDuV=jfiF{9TxEh0Jw&NkMXExpgWA7mCu)kU5j|Cxfxl+7uq_SOSUNp2 z(+QkG1<1eOvdAHkZ4TzSM zI-7_RWUofP_TqQp54fxDLs#S)Jron$FiE2E&;+G#Pl}6`U$)6E%?T>gDXpQMToA}V4!u?jQ+ z1`q&4yBF}Ofw(bijb~Q&M3HYJ+kntr>Y5jEa|6+;RmpxZ z8YMjfj&2{wM`BMAAr!AupTL%WhI23+5UkC&gF*@xkq*Z%JS1Rs{w*gRt#sPwrD}Gc z9Rxsg*9OaUxWT<#y@_TZuTs<*8u|Wm(C{&=x$>WOR=NZiTeHXkUCo~Al^;ohPz(8k zYP?>Xt^~g}99q>9s!W?V*agKLCfY5sC9!PC(}{|qWKOGcW)uN3Ac$B8NJ||?^$Qyt z0jsi#4$smg)*W_7qwFuikt?2#w4-uUk*SMHHBdljkU}B)+g+#_fxZwlEugd;VITXryI-oJRFTT`AEW{?QGAGH*%{O zZW^ua=wQ1$ylb&G?BOC~9}x#uyq1Aq`7{#6GYAwyu|63M>XOvLtjyPBDZF=Zg|7nRSLu|aS!;V+Tcpl&(<_PFs4m6Ez>iU zWPiHg&9_oIM*90a@#=DJb${KytV{uC7-#4Wclx6a|Bhh~0(juC-|Z`_V97|o*YVYd z*uwfOQ&F-HDL8w&3QDs0;rb$lX(H2;8_zkUq4v?jovMkxxBP+x0_%A0U-Q_n;OY6< zH5uh)ag-w<{esPyC_!1_=H+>34MX7@rM*{hdtu1af6=D z60c;eWI;iQV&p!W=Sp%!40V&Cn%(_1Dmq5gyy1_8d>M{TTn$q@0g@kLa4;5cQ%<7Ml6CVl+YdEA(#Ma- zEkX1!h^D(##CitB6w0rzEc9n%F687ZDxKdk>gArNXi3)^#X`KF4~Wa5`aq~gh-Qi%g=>Yt-s86RkFk~`CD zQHD_^%ExXp);4$!^oyMJaV_zUAp?e7`a<~ve}<{mdQ08dlyT1lrP1tf502X6@n}T9 zQw{+TKlskywl)6oIM6?1sHz?GRjL?e!iAlrE9*xSCV-(LaFU?a;*1Skz>0TTT8#cZy+PS6zTlY<7ZzbuEmG9g0S=}gt2^$55saD|!m1=` zGA>$E@SAH$hW!OzyG}6@SmX#RmXir2%jvCCP*$hANBQA*v+7KcnfqN2yV5zx>c5=d z6AWPTqXwALci1LTA5==~$OZ^lc2?4m2dNgb-9J&C$+a7@Dpu=LMsf=w!j;+qq=;dt zq31LCss0tuLA$xGYnFj=7&7Tf#joAeB~^9~5rm69`=*4=aS!*qCss|mjXe7HPN8>) zV(7wh!JA7zKWX)qFzX7i4of1!FH@me{Hm-s@MoF$`yP6VYbz<tjg9FI8EW(QYw2f4g2%Z!I6UHv9B(@ZHqoT8B_YHPw5 zSzveT-CG6g_b<4MwT8bCQyw)L?jDh(d2R%yVm>TUJv!CmAQ_9)<2ud(OZcbb)n*xQ z+Moy{%7Jn01}$4;EBee_V7*bwwi)&Z6aJTGt!+KLN*t(o=wE22otuRWiG&l=Fqq>R z+08DQJ<}fU_bVV?ECswmvPv$;VY=|^doOx~r3eN7z@)e^ni0S3DjcVZ50!Lz*G8+g z-g?UKry!aHAIQW_?`1Cz2S5Vw0ODPxeXc4Uqi!0hCl#`@v35z_!^ji1kwM#7vrc3lPmvd`^tq4q(fteY$y9>^c3p zr@a|)G(c|8E`{J;ktz_S1AoAuuqHDdGja(HvW5vFfM|+cku^P{St{RLm$4&EZPIuQ z#NR+hcG=yw*Y8GlK4c&19NJz0SJ2}P)C1F;FZa_gF*!CkG6AI>J+=fY8ax>|i}^01 zIt@cC&QE-C2bL5tqeBG%fTGwR0&fGcNc;m2pL$zXzn~m?E|dqCGLW`{wLZW_gvA?= z{_yJASZqDv_lGZiLH7@&X+u!dB6;1lbA>2d+br_H_smjyBVZmjPAPe#WF32qCUP6 z0~+>2;f!&%ow{1?$(X=08%hp?qa%4!wOWG(dyPXPwE2F%vsOi$;`JPgMNs)uo8L|5 zg!+GHF@Z85k5bDab1Vbkx4jEQHebGGZ8-dY9ul^+ckhS4v*`sdf9B}_J&joSZ4yRF zt9ko|b`@U~*-h(+(&)#IzsFef;R^9ejtXKACAVlD4rl4wzW*Pe)3>UQH5dX2hyV!) zi1&YwOmj7Jaiw=O{-4~mQcYvU0|}(Bd_!iL6~`fgXukDxIgd0$E%z;{$4-ds|>l&PWp~U zW*av61i`v!Mt@<*H1&4wVpk^6?&&mjj$>p_ibH?@EmXm~M@g+Pot&N|VMKick|oxx zf_>@i116p}RJIb)j-oR>wi3b8mm-T`b3$sg2-?&ceY^h>e)1pK2&?h7#16Qi4@ zFH(r-z@e=A$;SEbTqCIwrNcL?nc``rEo7!DBr+RQ!a7M(R738iikwj26mx4T5n&nI zN-{L#>tHd{C;N_=-I$SJIm%{)Lz(BOOI;_y0`o1r5i^9EHvbjVsr9T(Ii5qf;{($n zt3jDI%SW>&?cru(Lm6;K(4BbW3 z1lXcG>DCqp$7(;w&5PBkI5HSVVIRjit&MFj}}^HV|*UYjQf|u9%@mW3!Vg#s-HLp z0yQJgXPCfwpaY=q=?^!*mM52ACd)NgdJ~p9?B3;gPOSRky06TYa+MgiLsZtnp$LkG zEUnP>Z+71cJZ!NvGW>h%w#vqs^yVK%wg@@=y3;3|o2R}yB!Vq7Y=_%PQo4BE3a!}_ z!^aT=OqA5;FbvZcATG%SO+vawcMq3UgxgKQS6t|L8Z=wp9ElB`Md)M9l`~3r%j3`S}{wOsf6smmk5~YU~aMyFHLxO0CM~Qn@kD==l@K+8%oo+W}gN_vbA-g8#lXYFxiI zS8+5ErcZ+2v?x_x>^Elp?olEXv(Q$&=&k$Xa*``s+3Q}Fu;^HIR-mU9WFHDNs#PB6 zUY|cK^kygZP{rGHFeOu|0L3he((2Xd@TR$n=8+U$%6nYGdTDwtT7_W-GGJC)Zpk~r z=~#<1D|#t@SN3 zcz37KMC$8A;hl=q?_{TdzUSIS|4Jz69*~sL(XT__;mVUo2{m2_f3;mo z(crITBB$cnb3!nZ4E|TD(2qk&2;sF^)!H{ATRjH9v1WLAiI*YM;1-~sH;La>xx>x$0gGy zBXvTw-i`9!c5Ikjw%-txt3IPvIQwNKtt*SMAG#OJg!N z0OI6pkYuo1xqNkl(3?>k&t7pA|FQt5(S$dl;#k)4oN4TqpwG9FS8|6HyyK^!rm%Ep8MJ5wI9K5SC3qzpFqDZa6oBLUx#_BEn7 z$C^hGwKO4WRblBCOq3Q_{^yP4|$BLraz%Q3OnQ5*Vg06*7L}g_P%gDRd&8#HVC85x zBkauygt1DanS~T!X3c)7;DJ59Dhc|e`%p)6x<80VJ)6Bc{e3X%(Vvc9&f%r-4lrdb zxhi@<5A2&4sGdH-@QJeig8ZLY(0EBlJ&%7H_vareneYEYuL7dTeOC)RAWPvgF8!lm2N|tK&GHPPak4gljT5i&d6S3D8$~?lLxtF| zll66+L&)2ln>X07#b@L8W3<=KXy_jyt-W)CB9`>bYheL6<_;xeN0K3ZD*0^q0hR@v_szBGFi~tHL4)!7&FY94bv+bE_
    kibsBs$T2Ss_WQk4Zq~4-1j72_Wo5~MDRN;`?4%?{0 zcI~i3cReU0$&-M8oaE7|8oBCLI@>1s4ea9*v8ZsjU!@w-_Rm2lp+$*68v-r452gEy zUETT`ef*r~g;tG^mL1 z;v=XvpQED7E9sbUvsCo=xW&QCD~qGM+G4Hv3J>nmB8gx|@8WR1124R=^kR}YgQs-S zyqVyR+lw;wMjX-QBn_~FE)pD96GWXlBSV--GV5^n_86x0elU6jPl_3YV2_Ylitl5Qyxh#+2t<%m?7QJJkrgNDlx6-AiBvoI0rZx?&fRFQX^CK@CC zSU3?x`dXPhhPB`@RXIc7NOB>QAP;w?#D*(r&37si@a7miSMv!)U5^yX>$k~s0i!P> z_eEC>dfwwpy}90|@xAy_bGW02EB@?%h)5YM^tdN`l7)fKM684u( zUSfj-MG$q2m`MO67{TWuN9F`^0HN_e17Bo(X=IT!-VKm4>vrWS>?u2khBy-r%Be|k z9f4*LpDnu=$>crUQ5#OdoO!vnV|d#;p(e){aGE3{B*aN_AJ61PLIOTG+DI~Y8SGd7 zo0wB!_0^4=H&-9Y#8GlJ_?7cr3o*%ZGGdss$GUj;#+9ePf@GTZGI867Hje*bxBS_Q zv{_Z>nXrqHsxg%DouWt~Tz4t*+v=(kBu6gkuwx?ZPTvkr-^*TK2G`nk#Huz&fGqnY zYT3`WxNTwUM5vDQIm;bduhz2lifZj|;{@6pD<3}|3+zt2FTX=XXc>q`ac zRxd)AZCo0LuN-I|8hT_GZhE2Q?SJJ};L&qpP%O-}>QxfP3{~}j54#&a1Ft{$?ztM8 zJQz^tg7VF`_KanbwEj(3qhW)voqPzFEyu>LDok;3%Q%UHcYzWmS1y%Ws;Sx1b|M#Fwmt7otlKM_`-) zKS^^88#$a~A0Rf6Isx43I-D=rUZJ#eYp@EqC(iED=l6nEi~1hPO}$$!S5GHP%b<|l z`=!%*UL|Fb=L`nE(IHDyYI!@Tfz_R7?;?+QH+3b)ek^8}?(^3CfVN}XhI7kZlS|d! z2{(*!F7!d1uyz;!L=Fd8{FT=J-BSI@OQ!PJk!b8eu5_d-3%N^K0Zd65=jh{i&eulw zts@x40O**nF>Vy%)-NkaS2y+{<0FAJY?GSnfHUkD$tVWX*I~i26MlgD6EWAd^l15~ zPYa{+@<-jZeXEkVD)?T+kTEasDrD-PL1Uf2rcr8-hQpP}Eik`Rbdm9Kk#ptc0IKuT zfJ&X*S3+qMmZ0fhSgh-te&KmDC0o8Xd&XZQ3BV)hdg91(BS3sQ54CSqPH%b_t- z?7z$9364p)chl7nd+cjrTYs&!_n_VaZaC*<=u;JAe?}3UpL#Dz;OF|~B%kZqwlp_o z?;&d+mH-&~*D6*R4Z1xGA&^rCYV!F)+Gt`6fAbXOFQe2;dZK>(EYWsP;aII6FIvL9 zaA_w~;tvPG@U&yViub&@XGh>E(*raYU;v324l4Z6b@~bWKb386-dw2s2ndMuFDMZ6 z|61ApyPRG6*=XWQC!c!wi?==3BsC-s^7Hf3+IpKJwawh$l32cMT?@FuR0iURrIpFB zFfHcq`X8j#drN^Vvbwx5oVemv(UAV1b8vT_wjo=NsO{^W1;QKTrgr)JY-sP?DczJ?C6XSSN!piL}BPs zSifxDZb!r8?oy`|`zvS00_unZe=OsUN({>m-8?BJgK?ab*H(gj53c>l~DU5w_&GNj(3PmFraFDUCJQ2pR^^gLEPpbbd ztFTNu@nr8xOwcW*Ji{E5hH++f!CNR}M5Jt?d#{GIdCA$$H|D=p&+l z96sWYiSm#5nnDLlwGs3MD`KGDAR&^fsIZ3@p|ru3I^`{rew_p1#sfkM;!PB5-K3Pe3XkW^X^2Hk6Dz5c$`>JmWzTdp28P7h3q`V|NMRz z^yj-mj5t43gO3*=Kma0eb==?;zvy0HEQ(j0K^or!SUN%&=I6Ck zUO3CTITyyim-`R`W_P*=_W+lQOGkr%ORR2QF78tGYJq2kSqPt#h+fsFyU)jiiH3Sd z-;a>J9b*T_rQI7Kgt_|jpE*GR)nUZmVbOpNsFTA*rysO20D@-k1!!5XM}*&HyhOJk z*VRqlUc;q>kC2$qeM4MeIN^s6=qvu|LWJ;>!p{;$!|-=N!LY}z%GFD}_lPfi1}Wg&Hj3J!jjp zT#o4H=^uSaUiFlSCtA3(ll6h^`j3Gf^v@h7Ak-k_J^f#VETgy zvBd2N=IWzhGA0eWW!Z(`>u$ezSv44Re)Yp7^m*h1h}aWaix_Wz5w6(PUc3NFuc15W z&0t*CPMuXMD@^5q^+5QdO_XPCBEQ|&^1T)oiDMbDr82lKlbdtByc zV*8ZmZ*+od!OXCub6Rj@XP;X?p1y@u@-+?kA)f#@*r>B%aLW@Q9%;h#SRi_FlPRkF zx1X2qfsWzY>p-wpM*6?5>)@TYuUes>}6={3ovT6OC3Lt@Wzp4y1WH{*1fLV3x zf~7bF3*cEB6BubQ**e0nhg>sAt`?`_JFK@48j9&hDyw+=l@Ih5b3jELv=mFh!2dHl z;TRTgsZ4oZU#}2;j?fa!?C`v2dS93f#Uacpu|#%Tube4avUvs*O7-gzI`n0t+}P0- zB)CY?&_7y=xcO1t=ilRV&O_v7|Mg^ot4pojNo7?Y-goV&yn=_nE#Va<05Lw?2UyCc z{fR0kjh!Dis`We0%k^- z0GTtcY!SMKW+^*4XNzXV-7X9@5$XVP`=$ea5}jpNKXO_HEO{)23Rs>!-!0#`b=>w9 zbnbpM@mSOW>oH*KVzKYCK5w0?i%?uOHQ3ugzPWeD2`I;*-vcdBz}?@I18%F$m;>Gz zGdenD-xq{&OqN0*0^SKZQs$I`SI1GM7Vav{%k4w_>MzuZXqkmZYEuM-ua)niff{okIWtQ z^Hyd!`%ZFf1^u=9&7@8N~AKqJVIUMd##mDoSOiK?9-Kn*DNSF~3FmqV(3yoAJEkJ5ffnv9Jk z&i~@W1c-hOVzY|62F3{E7BA+42TARWq(BqE0V}^kK680oc5Y5_#oe3c$-}G_ZR$T^ zHOk`cAsKfLZ!y((J+Eqp8BYpH1)d{I6qH;7lV7NtC7eLx={57^dgeiEEwvjzg*`yy zU7j>k=Niv*0mbUX@%ed)5E9IJz+Hd4g8g*T*qR&tpqVDe1IgO(lk20wFSBD# zkPLJ89!i+H=jA?JSX$t_1Sy9IGzZ<-vLG^2ZecWE>2f41HUT0Es7l%<=Zbdr`xemx zpp#)y(cdfyf)S{{=~(!)s-5kIqZ-)R@k%S|63{J~0*}SB6?zzUhdP93jrC?M8pa8h zj`*;XN@1xSS>jN_Qp=z}z)sk;D!rW($8jH_{efj=b~v+e3Qb+Rd%}7WpU?n@ZALJu zY@_}2&yN@#jx1R-LPNCYHztwhiknoKLm_3brRP&lx$H4llxe)SIa$#N#^y>$X(#C{=E z{k-^>{Wp*`A9#exe&yC9nl;Dp;G13JN*Gu2W#J#tKk?g!rgyJ2Fi@yE7!Fa6lgePG zB1*ba0-U(&uXnxxJ+-0FGB#$Bzg6|Hj|}!|Vy}{km>d^mlOSj!xBb56Q1VSxOzDdc z2M6C)j&rzpLqFjbF;NOOJ4GC>PC)!MayKN_3FUssyYF69PwKpsp7#BD4B$Xhj@|P^ z?Ct7$#B?u4*`9A#FNhFhUqF@UY+jAJMD7(gfG^?noxZW{NC_JOn-Kxskz8nY~k7AOe7>J z1VhvnsS?CxjDZoVWC@MUM5-76fD;OZ=0!(GBqFW&ZYN=&9YEB+pck}A(R5|LcNZjG z%V=W>%0c1eS;(UzZc16om7^}miM@kF6*1FRFqTWd1Vq$101s>iw5?`-o`Nx>%3weT zLi~m5&=t;V@av-SK9XOBO=$$=Po=hozL4QLgbJJVi6bTxJ-?QEN~dDu7NoP$v2CRc z(IBD-hsJUCeA77|(fqpNGpAI$ph^>B3lHt;N|q4!$OuAAbN-g}R1*~Uz~?TnxP+1l z72fXge0L-8=w%*?XJ#PCsii%_p;{c1BsdA1w=CYdbr=7#Y0$X_w5S$nj!>Z$`R_c%naDChJv_=b4kxocDu$ zuE55od8|;{Js?OFaF-rtGRAHfre-!*?-KwAU?K{ESoQaHDv-gcYo>K87Spcf3P`qX zmH{&Y1xn7N1(n%y3xX8gDd8UYRd5THNt4NNpP7QG5n-)GLK3*20nJKoGkMKT%XHAC zD>H9kQKS@ZkTvVAFxVTW8i&XVpaPIWQ}B-b^UcPS7Nxm{MTIso!Q7W^6preQ6*^SO z^H@saPudstu&0pVf)y93NN?(t!Qt;Zs2Z?9yih9WV)xM0WjS(P*P}cgmxHg6yg=to z6y{bJI!a+-cbqYuePxa2=hfZdBGTDJb!|PPARu_w<(gf=B)M^*a8!=HG8h4zob_5U zCei?c#0v5Na*W=G=7f{wcl3bggZUy~G07Ql!@7D#t;g6Ynwb24TT7UYgb@^A(9=Ql zJ`emj`@%s)VkuBRibjjoexJ(FnWzPO``r@8qC?`LdKNv+4i^F)djd^UqDZwh|r=zZM>0NSnCq5wrsF)Ug;c+dI~u4ueV0S z^3SIoP%hn((k<9o5#9tW)7~?wATVvp`{c;ZE|GKg!%n}Cr9Ux|V5M;8dIIS{jPVTj z@b^*ZY2z6(Dm8AU^900oBFf3Rc+gHGh~f#>Dnu|a)<-XtNQQj^Gl*i8n|8m_-;)aK zi>0~9XK_w%oJg}~8GafjrEa@-P07FnG*2ub0}4a*xj@vMS1zxs8zN@={pfp=ge}hO z5+w)j!JXI!WG|H%<_5~fZQ313mRa`gRLdiaahmvFc99;&3lG0<4x6R8cnF+VjWB?dpg+7e!MP8 zUEB1ib|pBRw8wYu=1>5Pvk~&^nV8FIT@*&&CMFumhMKkb($!%$$>=67=<*EptFLNn zIat9q6f*GL*U~5g@xfXWjneCifzdYsSxv@}(VSWpKmP*JC*ALAhEHcE_|^;I7!`og z4rf(i>4bc&l+Tz+Frg|-T7OqBXk9@D&;9Zxqz5L2pLaH_@`^^GJ5sPr9J`Gi4MB?r6zyyiJWZ+eQ1%gjL|-Hv19ps z?nnXrFQanb2@h=-FU0?pqharOGrV&2JM=_bT!$;5bog-EUF`b}fV2uWd z_Obs45R`n{#TZ+O;Kk9IuD?w-xWx9sTNY?&TJe|@xyJTJqb9TFv7c}RnLqAkF}&Z0 ziwzPHk}(H|)BA7PO2@qC=oqcb=|^yJEyf0Fdl(vykjB)sH7Z|hV%>HUH)F6w0f%bV z3y@s_fPIk97Ryh@gl}#W>-57NZ(nW#tHK{R<%3`5YcllxW{T7iZUE>Fm+`-3;LJ(v z9KV2$*7wkn*>;GSG&z;o%(P4FIJi%7pGWncm0^aELPg!cH%)_c8zv$Fi<_42dC4*f z@2(M~7NM6^#K-OCrWK8FC+(Dh8N%T3(%1NGCLg0cyK8<$b7!nV!)m1pr(Z^x@{1jt z+eVK%LL}#*;F8n*2|67ATx{bAK3y|QgG zE5YhvAiidi`~xN25=0yv9#Js8cWVWe6vRE9Q)r2TnMn6zB*`yjs!DRkHj`lF@Cr!Ht~DV_ zF$~w6(;D*C)7$)Q8@Y$ipBv?@quM-n_N%SKM3p(7*)}h9ewpYeENV-ww5ohlB@<@l z5J-{6Vb=6L#}R8%1lI zB+TE!*FgRrk`+;+lp^(#{pD=YdQ7ExF3eR|Vya9D3RYa%3UPR;={hiU(1B-g)-!Pf z&n;TCsp;>{raoFLZ#v9ua<&1&<>`CuLD z(Yg}VRxE)D@ziGeUvV4;+g`xT{yhL({v76{>a5q2o1Sg0(27SX;3HUv3z`IPvfK3& zNCknt6AnSK*r$*)-l_&2r4-{DhI7oyInW~*azht%Z0>FgP!%a;*l1*5=n|hEDDUk1 z0NE=F)JGLN%A|!%EYa~SvwMK*4WDdF5+`k^Bl@snVZ@WWe{YMT!h5WKRl~FE`4HI+ z=4d;=Zf_SyEZ)qCFs|<$fI9%pR;?vcqrlm#?;m9p7J#kAZ(!99*2XT--r`^UHN z%l#3YpEm>$N6^-j39V%A75s-6NLP!n-S>FFy%9c0jD38Z=^|2k(~eaewveN+UD{PxVsDSgljm;%Iy;HIX%A@ndliN+0Y8A+qhBC z8B~!UmH$&0mhb*fO^5I5Wwug6+HnE|v7Kb)22n*2CE z77t&o8S)cKhAiTxxeUAUtCRlP6=K5`q&OVT%o440eEfYx8KY%5q^36sR$FUoUM?B) zuf-i01kzESMu~kkyRPPR18)S|w3{jkYC*IGq|P(kwHb%wpFJ>jD@W|2 z+@Oser}dB|^w4Nej4t25uf6Km$RTtoHH>Nq!j9TzWcQWWN=2%RN#Z>Od#XVjS1XAY z^PvoRR4WA`3a+vrwu{<#(;y914>Ke@hGp{o!;}cCl=*|kgAHDm6{5uzzBUljID5s& zI{3-OtZ+_R7OBIBwl16rO!F#Zi^z|IeU61L`vvdi<&@<--)9ukH_5?E_nZu^24`Bu zr_WV^+`#%7LX~4kS-#YWDh1MWeJW|R zB`=n4Gi>ztRqD6a>U^75FcR|B*J(b#M(Pcoe3I|mtKQq2Ku+hR{v@=!EoXjVv{Tc> zz1wJ7)u`iQ1{>&S)GSiamd{(J)~HTuh`3wJ@k)JT5GnN(g5cjo^|^>@d0`^L+yJgp zc`%>GEuKd=*s-gsiT-?e0Vco+*L8ghiQc6rnyjKf#@}u)52-wNBgCEGzaxz2bXwK!3|=@5WcSD}lO0A1B++vU1GrNN;1&#%KZE@8&ig#PRymVU;{UZQ zz>D2imUQrf57;gXpKpnMUR+_Mk7~Tx9p(tnBFVv;m}6oyfR;!z%+2u~`x_Xz&*1jw z8x&CuHwy7^KY?*ASBvO(FXm53ombw%qvx5}_(jh=krLkgWL=Y`;bCMTy9e_r={$6| zRPw~mG>;0d*VTUMA}bUA9KKQ$T&87yo(vYA$3yylNqw_9w5e{b$LjXcVk!p5+y-Xm zZZ~W%T>Y(^$K5JySmTBFSUzia@RoTNTWym^c#2$_o$3C_ke*Ux9~IC$jh=c zUU79RCmnE;+XF9H<%(n4Js!%N6e-Xi;jTt)9=MX!ep_!jH6PY=^E>qLeTY-8*ngGT zcz=3nYXkKZE9_M zqOE`8 zaDNlnSqcB!oi{7H6vFsg-r4}va1#{SRD4d zEQ`6dqF-C5ST6Fh^d45d`Nim&Q4eAg;b{i6&fkBE*UZA@GfF$L_qFAqAyBG7iH|d)4^S4pmS( zM7_or=;$7`3@tM+;k* za>9hKTfm8G*msx{T!o)q1EtgQ_Zed>M)r&~jJ>5EG~$a?A)euHj8f+e>XQky6bUbz zx(vM8+F0(rvYuCNIEr0}wOgi-qysOIXp;wzX@{F{$asxR!iq8CP05vYjwe@mMaIS8O%*O^NsZ2cFHjd*J%CESQ)_B$syVmBW-!Qu7OFf}5tV+YlZB(R9@ zSD=*epghwloWz+TDVo$JmnPrN(JAL$jbyT0G-@QhtaNaGFD6PXjUhzyaWtL-I&;+v z9hCOt!}?tc!!SB-jKN}0mO5{nmrQG4uX+tj+2ZOaYH%vQf>511t_&N@IF!Ke5K%Q% zZ{{pb&E7CkB?2LAlL4?~A z7#%ec@r78Y#0q^B@}2PY&$txub?pgQ6D&>rRIn`8i*}Bt#s?WU7z0`uO-zxV5g7qt z3ORTXc--XO{wTCf^c;a^m(-39O2uN#tq@8+UB^+(V~=H}*}OcJiAVYzZ!;FE?EE=9 zbloMv06c{$%b!PJydMDbxOPUVY~tfCdr2zKxI!5KR3iu-q|<f+sv?`bv|Hqs_E8P^md^!x>16mV}$pdVtHyP ztElDA;Lh8b)z2#(*9VYotAlM)^4@Ri1}UVykw$i|Z&`(rX52@){8VQJT>tH9du)`dGKn*RzHENRseF&;6;z_#Fzwc-a% zFisbvV+M7DAR$<&YlWr!^rfc#bka3$)ObH==I@Nn$bxg>cc;a&RHvp=nujhMAD;T- zIt3#~c?`f}mH^8HN3J2?EO#Wqb+Y-ak)zvaIf*|weCw{}tpz-Ybl!`aP98IisoAVI z9YA7YCck%Zt{>L0uZ@+6wa2&yrzo}4lDwx#qcbSekjmtE+wF&0VCe;miyO}X%^7`` zL78D05~C^b9iC5Dlx~_T zSd#F-NS>Qk_^0|o<|K${rEybo>jd{&iWQFNNnn@jjiAk=w2+>uaQW0$w#)o>#vT)& z+aCo!I9&rHI@ML#Uw1)EH;A}~X+$o8f&!ka=Dy5eslksdzBDnjT zH@t<-8m~+$ElJ6P7%yQrp^o7at>=_cgC}kgXPl5(quRtP$k&{KE48E4fuJB!|iJbr#^=FZ)xxo7n>X>%(H+oLoM{COQ z-4Tis6ydG(+>TC9spqZat&uB^%18~}S0Q0;?$B^$qwa2hZ#ALgx>?GZWjsvQH1vCR zJ%+*{J{Qd_AWM4X@(#kRZ?R8-L{sg*vldU$2ZkCk^F;?E7)dcwtFYCv)}Wkb{COqP zke5>t`@^bmA82ixaf&1c5}zCmaM%3<7>x_m++8i6UrYa7=aDTqXL!fpFaEl*B3i(o}hmB5q z0Z?NlziSuSOFF;Sq;PslkbF%OnEh*sY+AMOSC?3T zOItWKF4b7Pn@%vI41Yq(c8jhs&4G*p^FpkDIrVx*LqCa!zLe`pY2{sVtg7lZJFoAu zmEj~P#0^aJl<$ZMea2<8oi_tk${8{VFNS$xL^J$f0B%5$zd@t|KR8BLJZ;vB+Koqw zTK@T3fy+PjVpoppdUMm#4EUF}DiXVfnS-Vg*3N-1S~`=TDP}?k+nAl4Ae0GZx9{ja z9L*?!tDPbOaV_Q*1IFkC?$%%0_m%dHSZB*E>!Uepf(WD}^G%w0opo_s#|nS1n z{U1N}_s)Wkr~Uol;NP z+&xL^09aCgj50n1QVGO8P^%OhOA(#~Yw)x&g>)w3Fhm%TK04v+TlcX?FyODF$TK&Hi} zn_E$4K`K%^f$q2s(gm?iiMj|gNua(2EB@*^Fk&ynMHuNKN(<1T(!VQV|U6cHEUWxZa|e3195Dr;1*gLbORA9LXI5eZ8$#(Y!ArGmom6e|>VijjX(Fds zEyK%bZK3$7txKt_$z%0e(!Wz0Wb(rUrEAU?98RITTxUu?gFiAqD>6N5wkX0I6?sk) zHM-8yB*lpVHUA+P;n}X+P0~B^$JH*gr*i#?!GpR#;E7w{lbDltU}+EX^T(qNb&k>4 zQeCkl-4Bu@YN7fJqgkp6?qD>QjMoxR?!I#S-E9{4(q-dPn?eB_`rZ+Nr)|(qrr`z9 zaGU}Ac``swA?!%EkY{BEYZb*=4ZUEy8C_$7Bh02jNqCUXn7HH5^INi2%YA)5XWuZq znjZgop3m45s?!4eR*!kN(?LNos_|znX z3v;vb_jq$n)g%MF{4we1%uMpqIoC;%=r3LzL)lF#(`N)nC+`M_eUg@v?LEX&jGNoP zr&>kY0pGYEu#LEPJRHcYHlLHA0|u1+%61Ao09QSq4!^OeHo#kyw&V#SkB|9BC~lD{ZC>xkKvaxo6As| z;fU4FQsld)X2v-_3+RT(vYhj95#Qm28IDqVO3zX=&+hCRm~FMWZJFsYcVh6f<*=c? zno$`MAy2S2$8Y9@Rfn#_|9oTZq%SYbOCi6SrJD~=zjPvfJ-BbTAO#rOl@hr3km z2{T~8%#!%I2X!5Owzc9|7sdp7Gp*sCCs^HrBCl?zsL%SvK(LsZxX%;Y=>%QPoQuul zLqgDrmZCHa;|S9`T6Z(tNRtP;wh3Mgb2%{RY(KzNH#mMT z^C^kGfV?4Hq=EuVvIcRd(@3Zic$3~~!p==jCfp+bfKZ|Y1R6^wR9UE^j_U-fRK$Y3qJyI1HDgpRw~PWee+hp z?kFs{=IG}L1g8d3_$mGczdT(3d28MJ%4~?U3=V_&gf`hfP!kXXal3pf5gDeq}re)&>-Z~W358Xx>x!?xdQSKsQ;5|>|ihA_0#OZFkj+>Da|&J1xr z>>}}P3(0b{S)L*C7+RDhM>XHMP#9870A&#!|EIGHvn%LrZSW8|b| z3@4LBVXBvaXe*tZ%Y(-xG6{lQ#!xgBo4fg4IBha?R9F81vA|U6h&+pJKp_|Frbp!U+#3%2r)RI&U4k>IQsTHV9)-g3SgIes-r9mA z(~Qk4GcI+@AFY#-#4SWMfisd62DqMIMZS>+grdXuU-Ev zOo9ta0n&SthCq3)M3bBPY9VhdW`}n1vA*YKV==pmq2CK-2&wC_0sf_}0Xhjrf$43el^GGnzSA4S zogs}!it7FT&hdk6Q_~J_fm$_meJzN__2H2Po#(y1kH4SEpxOD~4aUn;(6X{>i!>$t zqV3eleNiC(Q$y?84I*EV8w$pxlQB zO?ukVe;RA6DVN6Y^`AU2C&fyYiub)LNzvwp52vyiVb@c_d;lA}O|5bpzr`W!fPC&L zj5YTvMmm(DJ+p=|>_$Z^lKX{kDW3$k(e!Dn0=>)^dSvrMlt>R|VO7nYD<}ec~|X)lhJ$v zL&HQ7x8Vfe8u4bZvU zs-jJkz&l^HY%ZFLo-9#zK{?DZ-t=>{Qh%mpWsj^!eoUuCXRc~SDm{N(I6_YXIYi?x zZ+OrqrsU;IcxsPV@aiXc@XJqIztB0#%41Cd{G87tW<*Yl8%`*#^Ey>yNh2>HnGurP zJM@bn2_PLjvm%~bzx)Kx>hR1e@U$&%dgHMPc340xXOarEDkHz8k$0!8fVr5Q04fm; zPoVTQ;pL_}q$_5Q52bWA9Xi6n2|&e84nH$tWXnV#^b4IG%~T@j9n-{{wNkSiN^`U0 zbWqIYx8^QEImp1d&h64bHQjn&a~-x4j>a5Y(SY=}`cYBcRlwnmhW+A&(tlG^m$LOV z!zNyW!zHv59wNHfBqf5v8v^&@g))CX3Kwbh7J#2*-dKWSZot`WBAFvG z!Y0XMvI?X1aXfw{SWwW;U6i@7V1J7-DSV7sYado&N!=^_+1Y}h$Bc|xS|-&0w|C=4 zr)Hg>9eZc6Y+%e|D$f+-{)}0vB21;qc}J^-^#wcH&S)K!g@Yp#+OqWh6_20osx3?q zoAIwZdeU_#N|r!DhFYdJI5?&w{7z&VcCq=Ep?u@AVpe$J%VQd^P@!qNFtr`*BVFFX zs1FWNDr$RwaD5}NNH-sbjqN|d5?NyowpQb4JU0a!w70}SR1Q8x<-Xs9&>xd-kE=5A zkv9?B!H87oPm}o9-;Q3Dg z{}=kE!i@oKl;cQ>e%yvrx6X#Po$vAhur>WcP}!%Ux+?OD`j=xqt*i9mYGTX2tW&dO z3;jmViaS z+3w1=RbqC?W$th*S zFQP`saFHtAK#Zd^77}87CWLr!AFzoh4e*H($w)Br{4uvrOgVby6oxn71x@?Alc3*e z6*OHCPF;8yMc~$DlA(Lguxe47VAUU|Wc){9l*2fIa~fX5;5o|AqK=8-HG}EQ;P{ng zI!;cloaEFmUrJYY8$FmnKg>u@jU}Xc;N3uw__@K_l5y4qplwFLY2&5F=Ds(*zV*-x z-RQ>)y4zf>yO&;fMEXKs^lU*#FBf-Y^aq|HRSm-kigku-m1-18=YL55hcmvOn8lDBigEE$v(+qa1$ONZG~>`xuu< zlRtP<(-HLrN|-|F5syimk&JT!Qk>KpJ^RHij%ewUMG#_4bKLc#rh|6dXB!#flCKF3 z<0nXm%#55*(36LJKhe8Diy2oAO2S3Tkj;f$;(SeVIX3?IN45FJ%7)!G|G`%7UG?&f zBNgB!|E1sl@sAA#Bw_BDb{$&3qOT~%j7xT>x1e#Owf7Q`O(HaNVQv?X4Ta5oR?KtP zsz;YaG>d?B!zwg}kd_hTyG=?!;D|wb+NP(b8ED)hRJ=XXg)C>QsxDNc*r?{imz=V~ zk+?20%w^S>n6Cc#M`2%LfzoCWv_0@U_8WrUHXPhmjuc&W;W8V#+*sh_8ima`mpNJ4 znN^`N-DRG;3@n9m%>4#$o|OMdc-w@uqyMSHJ1V@u0|0qEhp?>252Sf>HlZYQ79e%GaEJ*O5d<;q_@<=^X%HY%@uBSRk{cHOSSQz^``J34@iMBY#@qck%478Q znI{Z)EFHhf=a=x0_Nk>$VZ^M1T#`+nNrFpeG)Z%Fv#OI1z}ZteWZ@Sw^TygmqjVPzlE`u0kdNPR?>dsPP#S=DApC;u1dH0De4)R8;@4y& zW3!YMBxH%(F@I$4AKXj}4G#~>5<<98O-VeHa&(2hE7W_0AvDv7nKqD_&^fnnVNV7$ z+Gd8hPtsQrP?HYn#l~dn&1&9wT7*55_#ff{1#JpybJIDM5b8$HWTj5bjOfJli^*YA zq|AV{5AlL07Mg=TKC$HmWaY_{)sfL8jO2H6G}Z88UXUI4+?)i`T9`_PxT7jrV8_g& zZ#FehcHjD|f`9l9p3IeAr2wjTKNiZxl;0^W>;s9RJiqTm%KXjx56yM&QG z#?47pq2fCT(=snAXttr4AKv<{e*M)G3RTtoFps~FXiFZTt*MeSTIt~w{~+awB-li; z)=6mz<$nDxd~l1z6pG~N`Z>lBY%E#??ybLebvrWA<&n-!NvBCFSS&SQ(6JPGO?T|@ z3xm~E#LH#<4%Q1C?6!8+92O~j4XUbn!j`bYqmo6|Uq+?Qai{EZ)dXY2FRUy}BM+h8 zc>K7&>HK0Z2P%58#O+Ci4-j&oGUsiZyb&`uQlGj+EdG#@RY?1dZ^+IHuUwu*CY}HY_dMn&QdVfR?HSoWNVfTavpn;>+H1FwKnf?MTRP`H}8(J zY&JPFzHL@j;frm_PAJJQGtkWA&*GKw7kgtGl7$1)F;DaxHP&*cu9|Q(Jl|EXQNW?&>lSU$>y35&0N-zt;hr9A#(4RXVDn6GZbr#iPb-}| zHOZW`@5Nn^+bg;jz#Ri1xQ02xjiFd(tN^RO6|Y^yGFf+*A*QeprQ-M zXG*W-H)bHZXc6u_-(#r(V$fAQ{GOmRWZkYi9mwfqI#Vt4E}lzK%v%&U3ks6*73$;a`ltpCa245teo2^;&K}& z0rcZq=nP)1w!!f=tIBRi#;w&Yk||In@;j8$2&G=5X&zHJnYLa)TdKF$6nwhGlO;f-kf)SqLF0BEZ6^5jfE#oXx)PA+6C9p8pmu!8X>!Sqz32~TjyN=mW7^CbZnnhmjpPaut?87%E?M$O!SF7c}C$pZ@o+wh{IwTbq^^3-N zVFv9ym$>sOjJYyTk{I;bJ(Bg9vm2zSIGPF;UpH>>o~CkulJBrDdAwLP!9P1|rp+5P z-cq68)9{Wi`${U!fymE~C_bV26SSEpC^CZ1iaLn%^=lJRtK*_1QV0buO(5{gBx2vT z#Aqxijd^+{gfYE>e;7EQuAo_Bf# zRB}*Y)`v$SD7mL(Tjd*kya|_TJDdywfX6;@Q6my}XS4T|ZvMTpS{n0%sQbX34<_A_GY zyv)@uLzfS7T6UJD-D9K~Ee)1o_V?Fb@SKhLEeP5-)L^$My>d?iOXS0se`N}q{pRaP z=p9DgbLNUv)KOcD$yi(T54Dr)3X{O!*bMM1>p)-lexgi-z1t~o)Aas{CT#k7njO2; z6w?MhvMZa=s5&K*$wajJo+Mvb+x`l~SYgm|wQCKltrb4Y>OS*Bb05J7d^@t38Tgy8 zVTg*E`kLmeFh)g}70eOl(ICk&;0q7=|9|j`7c%|`RynQ+zjxW>*cYGq_EXn={`$!+ zm+RktM@~A)YJrhsNb>6yS-`#AUbP|`>pUK@L?QYH6{01>!KSZEP1|C{>8@B&ZCk3T zp}GVu7^*yz^YN1e%QBAPZ@z+S$`krktyi-kFXx~|Qswy>%HaGo#;Rr^dpAiI*BX{u zoq6i@>YA7?&0l%hRxrqi^9z%i2JHod9FC1cT^tRq2BvZ=hiIjjCIeJ7c3|sjx)m-3 zNfeDIoI#Xxc<3s70P8w@piEkzfpWG{FRP>fF+q?LzyKOhqYHEz1b>9rFWw^Hu6@;0 zcWL>JzjE?0;{B-ptSUXDZJ@s@xtuD$*>iJgMODb_7G^jyR%>t9KJ8| zP}`pxLgn$(Q{0rCA!8u`zCmY?yqbZOue+J@e05p5a-CbvT25Fx>9}Z$e5KpkFVUa6 z2JzOiZO54Z*v}^qDF2&G-&=B#OfRL+pSFG>4~(5PpB4fD9kZon@RvCn_TCl&ey_9*na^}AA~RZ5ff8;|O7JMwQn zHjm~0`IAOglYh;TJpy0;?-tVF?tj*N zKj&bdI^)Z;&Q{+fRMnzcdQ7KN`XK*s+8>@Dp8ZYqNzvWD*o)M>GzZc|K4q|_dzhzr zA(EQ5V$(?q3d?m?$g2Nus=hD}9#u=P&VC5a24`57f@8qoOqSl|YOk;Bt$}(p#iD+S z9WI^3*A{tJg~)C7C(NUSiXEVW#vp-vn5H+mnolJN^)^g4F&qmM?@09}&&e3S5;`j^ z@}h6J$5Q+0E?S4v7wWCkFeiT*y8Xtp8aa1(xKd~c1+y_2ifH2~39NHJ4Yk)84`~0> z$?3kjIhcf3=#t1~&um;*X zx1B2ak*$s(1((B755}HFNL4nuJpz~|H6xVHXIRRIQ&~R(j-DsP4dDO)I>tT%gehL5 zN2d$Dh#AgHFphJ}wX>d;M+qc%7FFSO}-F$ne66z2Fs!e@CQo{Eqn>Et@PZ#K5>8|tMg zRl}tC5Zw=w8SA*cwi+p6ZK`J%fJxhPK+uWv$RrMbjJg~j9 z7@OH$`W)E2UWQHcI}mukZ>@yVbrwAfiN0Nm)bG%XZ(}vIFiQD3u=?FntiA=TzV)%% zyH2O*TrLSrDEls&m60zg8YRTvF~cn$UfgPL_&KdR+XBn6(LElncn$^O2;ek}uVOs< zIIwixVKRMQ$Coo*h$G@$6qsl#VX$j)LYj^lH)4I5-o3+w5c=VUhzKNV;zkddR)A@6 z!I_IT=-(HrxsYH95sCyUH`v{Ms}eW%T_8G)p#AHQPWbuT-R3*WyvsqE5Tu_)W9g4-tDQqd>>@<{!s0o@i?4fp8IM+xsYZwvC-r0;|-JRMS*G#TER1M%5)@!hG{!2w&d1$w#0 z7a;W7Md)=Iq3vpfw(kG1rGE96@(bHb8)Z6^&+L9nM!0pqhX9uh6afmvl}GrkJHl_v zBYgebBmBpatiLMB7^LGcL(dlw?RTd0-<2u$?Q;+C|KTY(Sa}KvrmxlK*4u(}jbi0B zitoBh9rc_XZYU!^x=cknorl;mUSS0`I3-KrYZOv$K{2y8sUC=Lv8};w&8>6ZYCyea z4cKf(O)<>1)!xGu;MBsXO5Clu8`l0Y>NLBh`~^D2h&lDs_8rgWGu;IGhRyQ|FETM> zrp?ka&q0Mq=aVsSF1Hsp86#>V$<-vP*~B<->3YBahb;{A1SOAC>lRKyvSKF`uEqd77o4aovX`B`5*A)SyH~m7>Ba zgqBSWlEf|ryftk!DFC7wTrBXFRK?>6DU!XOt#^- zuWK6qjv5}u$^4!^|7a9*K$91iu9-ZaOg34nQNmnjEFHgPGQSPD*fJ{aI?*jfhEsSL zAF?O_n7lhK%_4DfxKTaR9815dO$zm)j8Pd zN(z?d@|bryMo^od!kqFT!kWQ2Dnkl8HzaA_g?T(u$9R62sE?B{iTndisaABs4I#&> z%5}n#{nuE$F?+s(5omuKCd>*#D_2+P&n4X`$@I!l+^X-E;y zpnQ9j$z97?b#A=}v$c_wMt53Du**goGMXo3hq#}Pa7Q0iC)<5WyZgBc&FJuR*&#B zO)BH~%Jca@HF(bt^sHrwSSj-%~AiM02lp3t6BBJbsc9pgHp{(F&e2$$SO>v^n<1wsfMA zmELtZ^RNzx3blFC=>>y|FehBD@(Er90xkF@fjB{tE2no(h!w#pZOjJD0H_cH2_)gu zNKZsK8l~A-G}ObrVDIctAN!P6J^37GX@aQ0u`i3Msvh?7{`lM=QtrnRn^Qb5?@Xa% z=2e>M%)Dv@rwr_Ml8(Yjq=$ACj!uT^N6NB6J?!MS@eT;xac{HKq#v(!&Nku%uL0c*DifajTNhVS@rYK=az9kRUq74=(rnM(P zn5vQG6~QSinm%-h`Hl;Vr&R4!d!5tKuf|*s?#vEO$XSjGC`2EMMZdq`93}86rhst6b)*P zf8TmNt~vK}n?W-Bgf6eIo2H?6wc>wu+~m~B>hH6bBs#?zmW5{zz zy8`m!*-5|8r*Pz<`-0yVWAtlX!~}Lw)z&j^SH?tp)0&{Bvtfr zbgQ5A*R93GUDIa{Z*UqFvi91P?={3XraUTUPF~-Ne1trtOLo1sHrF9RKo_Js4i7p_ z<y#MsVYEP7fNviTJ?vz3Jre# zvLJ;0nN*xGovBKx)6qpQgWaI2iq>m5nl!!QDJ^4I_prFOm1p30Eb_&5XKXn-RERe4 zJIRf13q`ZF;pJPV{f^|jq`FTz&JW8oepzL4wg3RWHYWS$bUkQEGB=&l9*pw~>S(r! zZUGZ4D5--y#Fy`VnqEz!&9f+F&~%pliVgH?MuqJ2tJNwa3Zxf= zBsMeYK#Lc^T`V0TG&Y0NR(Wh{9@aD} zfG!yHO>6X0`#C|Ewo-#-IT^V;Hcla%wR{%?tvA{Coi+P=w`+fwz=AHQvf=DHAk3&v zThQEUwVC;YSqwPL!rLi7j3(hU$3y_|7@ttFYjhl02W`>s=W&jvA=)1Snyw$=jtN-Ff6bS1ZiQaHCwl|9{ran-!hB@}neg^T zLrfVx#K}_}X-=r6&>`rAvr4%Z+kLZ!#90a(6)Yd7WRZ+yxT4(~y)*LG}sl-%f!$T9fCA6>1!I11_H&~_Du#4HJ%-58o znF{S$Z~JK6E+*W;s#q>NkYvzXEIGMP#_~OT`2xd2*A*l@jnF`3_^@J=yT6?T5nISs z&8F@1y@#n|zW)IoA3$t-3&HKJ(9+*(%&ug3|7bpo?hn(^4Vs#6nlFkhe~a$}_ZaKc zF>;Z>;uN|#y;*QLj{()~1gZo$kGk*$fx%=602MA|<)?Vv)308zB!c+kiJ8L(=$C$ z2sYBBF^+RI!j2m_OAQJT%=vez>?D7os=~j)t}sq-gFMoW2vPYp)?XR5qCpkYpFH?y z8hgdiy}{d|y90N}Z3oJ~(@2#!QjAEvi9ydDH=a6XJZBb%{K)a5ovC`bq*wBQlo=Y} z3}ELpay_U9hP?z73!}$QtgIgajp7NlMfX)bSU5@GLDs)Sz+qs0V5&Na9)vJp33?`L zV2;JZqWhR)V`+irS`UOrpd%KfcZ2t;24!(;6kgh?Xstl36GG#eNcLEoQ4<+U+hrmo zrcL!GX2=_i_1>+o8r#dV@S&IgK(CtRF*jd?_(kg{0`!aT8eIdlNlifg!++oyLrqzf z32kf90o6|v*^>1j&HBvOwN_kbXSAEB^AII`!^*`*@$%cF!a@P)<|19#$z%I?To+UX zarGX2J}u`{u7W5mEQHV_cOU#qPHu6 z3W2rISsC4!^OUYgZ>PZAnY}!Lk0#I?`>=LaU^cr)p6s7A|2&3saTfix)m2APcEz`` zc)fdNIm?x!DaLQ2>?M!XTO3w2ehizkEcjn$eI{nD6RrOPS=MDTF-@_h`V;I-hp?|T z%bK_g=7qY04|BiXEItZQaWJM!r(CwU1yeI!!n;^6JC+({-d9-N+Zr)VA5tDkTPhtG zF!NsfO}8+q-=6A2xe)x<>oi#e4E>S$QNeU(T9oQS3XSQ8u0egQn+{2W0@^K~}Z=DOa z2VGWHg4A%dl(M?4M4R-yA|DWCigR`(Lxtau*aeMAfXJUszdRTI;z0VU|^A}id!k0#Y@{%g}J@exfJkP?s!td6C5H; z9x*0jh0Ab8L0@`+RormE-^frO%M;Q=poj8Ey8Gyr=>H+i2|eq~lvli*yKN;-+Xc>4bK$SydUZ!$anV*9cPYTFLd3JSSb1G#@v(el zHh>C@Dle>7MatP(3Mknd)1&y>OU!u4H=}IKHrK9v z7mV)%Y@7wnB)Ss?>EN*UJ{b0X=${7m?v!e=QfHW6FwGY9r|4t$t4GcG2E&a3#5l!> zd9DV{poG>XWYlFGO~!2-(hr9qgz!1$P-LuLpojH$9+yFMh|DXgI$37L_cK~f>?Ga8 zjOm+9WjtSDp^^-}m+@Z5(HUT;i)QCj2l5#y7-RIt{CeOBY#%^5@Ox;3%-I9M+)bf+ z$yZ4fdy1CH3sh}Ut;X6aKt(jiWyTWg^s)SQ37}W{COUpg=Se(ca3B^22^TDGwl;SQ z&^w;h=(06F8&hkrxIE^q}hDh!~a?Y;3 zhv|rX-<$r911y3Go>+1PXu(}gd9NUf;B5R|3MEPCP?N>zn8e}PG~cxNLaLE_&07@L z%AKX+G*i6&?JQ!J@?Ej#Zsd(mJiOadpqA>w<4yluYQIw|R)r>OsZ7r$P)5;|#*>c7 z=Y6bG6Krm`g){)}Q^X+@iGanhE%K(PWEYe|YwW|*V1$So$wou6y8wb*o?(`Sm?2hs zWH0liVQ(mw>ZTs9-ez-s^Fr6wBx%TshO32Z%sa0Tn#dvEJ@oc$qdvHrZ|uh#80Eta zH1z=KV!oV%guWNNJQ#!;mItNE6Aw{NK?|9q`|Q{3Op&@V?NU4qZwb=o zu8<+Huf#_Xvncp%yAln(&Jlp_n-gnLH^jGZ9c(st&2zF*HCsPz{bI-ATxY`~8;k{( zOmq;VuVVrH=B|EAYyjT`)t-`0JF5Cq0STYi62&D!{orx)^u}I6e0<~1UTM?>#2d5^ zcI7eKW-{a=9B0IMkSuom&D+up=yN9$sI=lZ*kdg5^QfVH?^p_HQ7}B{2H&bOe6*H& zJdYG+x-`Y1KzA*^EvxiO1GAl$2)wXQbI$g0|Mgc7tTpKZe($gjIemp&6RWCN(grjs zTv7#5sl%iw4+!k$8R^Xi*jXe_ex#jTr+11n3*C#RWe5+c zfshN3KT>Y(P;e9`l(z>*2^tX>T?lg*h!xL+{hVx^_9k2B6U3`1+CubT%N$HdGV?kr zg^%9%rM2BHaQ@C>_y@~-D6FJzvCADj4W6;t0fnocD^NZbWv_ti5{>BDFADi;S)##=F*%j;K29g zH4MYJn9r8NSpo%y^QUxPsC&*(KddYTmjj|2-WJq3p&R0b%bfYbw` zP{o8`@K&|6Ixgh9)K^-fyx{dmqp@-V7l>Il7LHNVaz}Dd>Qi{fkvNac2PASR?9RTEz(eP1;-&pGF;kRjzKWX9x%I}u6DQg`aiZ`w>lLU;~R3%IE=3Qni@Lv zgbR!qB2mhur-eaF{uep$`_>7^F5y@t8ZcST*_J3^QW85MVizDIo7=y~B}|z4*p|QC z;>9i#j`SmN8Z|EB;N?I<`=CRxW`!Z7rec8Mxn%{A@WcL(d;O1RgOlUo*Yjw-1H|6_ zeQBEADFP-NWih>eg;E}L z$$q0>~R8l zb|!+EVIivXyPMQ8cW6QzN3auN96ZkuUof1`E3FPM8FmJ0)3?&M}Jj3I>cd$tl%5ibq+Rr$;Zrkwjq0BTNA8#*6nWa1hvqur%nu&H322tq~|-= zWbm827A6akAmH)Qje5b*cEVW0S|igLDMKGQu_$!Z^efol4@d_ySj|G7-okl6QpftkF`Ea z_D9|(+_?AhkKEKYO5+i1#?d62MdjgoepT)js4#tVOOk)-R4GloAZh8by6G#bII&j6 z__9Q9jW9GO%B3vwl!6D5W#I2uFrNToGoL+7B41#%jjY5Y#EPPfub0cxtRTuBFCuZeM?*NMQhYF+0|!)~WEPFClXyg)9@8}EJ7O|FV2y1un@z$i zh7?}nxx<$zbd;Q9wj1ONzQ7UoP;}wFNxK@|llbFOs7;TxD8gRWbG|6-(wF?X7O$^f zu>|=TWs*!v4){DVlK1BebE#@}I-QnnM?OglDA&>->WF{D-XCX}Ti+7-*k&ri9~!1k z8Nh=Uk2+no$Ga9oWSwCeD+D<(&a-Kn+ki==4b4@`1{F8@86S?bbV`TbHDl`>M;G&} zE0_wK!P=cN)&~b8lt~v!rF|1oK}<;vvWszQ9PucJca@XB4pQTf8NFfuSQ}#+aE&^h>iL?;+mTq$sD;v(DknUkC0GMgeG~xv6 zAUw#uR9`FMa-An*v8RDzbD*nh!akV8iH6i0=0QtsUMx|VO&;2y8o?RjG9KylZQ%u1 zdBfRbA>gd}_2O!`3Xz~B61eKN)=s3HhZfw;ZSEGip8b()PmsjZMz^u`?^aW_v3i-g50l1X>F`AfXFF`2N%y=%^NxM&vUvF z*Q>-_+OTk{q712CW^gZ5R7r)EH77?mT3LyzH!DP)yX$b~X>vsdVnP2egR$|yC?ULx zR;M+(XIyQ|&dUYs#*#D4QqK&dKF+io%zQc~Zw2#EJU>0(qf>SXjXdL9m z72Wu4KZP8RC5Tx=9%b;%;BoT#R(A7NWXpXnyV5M18~Yh2LTXHAN|us`%agoD;9$;D^` zx$FoUEBj5CT$n;t=Q~~HlkWKEE><^O50gyN32p9{0DcA9i`>3z9KOF2dzp?Z&`%mi zb+|~k>#WbOMR{0^W3f)s=qIGp*Re52`%06mk@!pFL6Iv58=An{lwKfO&@9o>go^3+-a|_#YHI#c-o;*8=oBHvSGR2B z3NGWx3_bfx4dWyb{XEEllS%+&s_-$-nSLS8x=ovUEvjF0&ieVgSwN`giqTN_vZHFf zroH$FoQXmoV#m9Rb2`~mS=pIqkJ@qlNJ(@Nys<%2{PuOFL0vIi6&bXvJU=gcAJ1RQ zC(cjtYk_JwQGZ?ZAe+&Nnonrv!n}=pIVD<;FW1CaQ~a4pL=Knh#r9)t#lLPEP!zS! z*P{f;VP`>!YPFmESH^PgAgBHJHFk9ct5rBG}ymdoZkx|23I9fvj`_mdHC2n3^ zPF*$F_l3RdPr_~TXco+;!E9t^QTr&!&9X7mkS||ej52X}VFn6KfMFsA+CosXim(y~ znk*BCxr)&E0|quS%Y{{N!{wFpgC<^BR2ywfj1>7ZRKyu+E@F+PcUkpw?t5l%o-K;xrr!iGx$e#Io(5M)7Llxp zjaV#tb^6$`bAjR}G8v6jz7|-4P?p8~LW z=Co)Q_dq?1NikLiwFQQpM;qJ^baRgK(=F$ z(zPxrD4MQ3=+bgL&ooc!n?&(86JxWx0pq;@ga7D`2Vdu|E!rC`9kcVmjyBNN)ADEX z6&%t!uEv&Y!>QFY>YDALXaL#Av7oa!lxw@4njSsGFsR66)>vk>*9S#wewGV`Y)+nO zZHX~<{gZWsIlHRyxiqIMCu7*>18l*#?;OiLlfJ|i*()oFyC=Hi!WoLIr_)*_*lT2 zro2al=BOsoe`TiNnw7E-iz+C81bSILp z?6*y}F%~BkT=EaUsX`9XS1*j$Fq&Kj?Mi;JUXjk_mAeGpJXe(1HtY2HQM2_p;o!*z z)Q4y%#N$uKU}6Z)&sa7bH98O8>UC<6s(k4b)ZjSfDXJ_X+uFj%wewHVy+k6KiZTL$(R zM8~qa^ihROP`Pn_v!`d9VTmAt-f!ACx%QUkyE0i2OtLFj`{UMv)K*WzjhFh@Af|KQ zEx^pli?tF~{QcJ;CCR`R;G{2|1S?`SeU>q9Y;pw01o8Z=gepHqNcI}*EAT!w;PwUD zBgU`-WuF7bRWK8xQc9#L#uYu5n9o8(7sE;f%M_Da5e|Tb-K&Hnbva9EXL~$;983b* z7eZV_K$AeHi~wbjTTGwoWNj9aVy-qnIU5_M3Z+QN7+HVI80yPK`dM_t=-y&?D{l?? z>qp-mKK9;FFOiCCvuC<8d*XGOGuh_XrtdKE1dj_>_ga1jw4m|w>mltM@mo7Q7@Pxp zXJh+u5DJ;q=CpylY>3lwr}OW2K21b~K3?Ia2Unc44)7DKAS^)& zm^U~aU6*Bwof!u8Mr-A}ORAaqMdDc6EGTSNmOIO;nrVLpT(oX6Grk&h=pqUy-M*D- zm>I8e_-`EDgYu5yWo%SG$uvF2F(^Msjkem{cJJr75tcyvUNew(+p$#qsj`R}wru_K zFGa*U@*T}-$176tUx|Kh$ul{&x^h^lPpE#0Q;iXc^JywZO~Zc&jN&j>wA%iLXKPLg_ZuIs z_izJsn-MSn@QnNLA-9J%>{Bz%q7k`;P;CmTc@%zzBLXfN zjJg3v)sZ)+{iBl~`oUrUeQ)nid^NJy8}Q z`9CMulypGH|GmsRU$M4bi_SlMWxJg}ab4F)(kd&gn>AI!9+&J3{{lwW|J@jVvyI{T z#H5uxU!HL}5}^N~>(ME~qHkJUqfDi#t++Y~hEuy+sc;-zrz1BgB#oc-rKjeaU^@g|MMxv+ABt2A=}Aro;?sqFvzyf0^&vxCwH8Cu0a}LVo9UbNXDGR z=d(XuFWp@|(=!@joMg{g&Yl>g?&`Pd>gwvMU!A$>g!?y(tE-WCq^s9Ot_GiE;sN>$ z(~oWjl!lc0&PAK_nK}?0Emzz$1*kqY4RGi)G6iB}ELuVk6*eQ1#co|pGTE^WoBpJj zqRXdjJA1+@0Ew}7i{`P!MpUXXkc%7KRdA1CQnQKrOc$5l->S?%7vK#t zztecxFg(PdR%OtI1_2T{fNeTj%;4o2K4KrSb`ZC(wOx%vS#_f)>X+to$ZDxRSHv3T z*QBvw?uCu#f&RW-M&xg*=4G0`Yw*9BtpB%wKB|HlbEtt#!kMY<-e(O}!KRs-5W0Oo z5;T!Wpd==%KUaFy7$u>`u);2HC`}IB2cK}e^eOmmJy-Wzr)%n#E8E%0aR*sw77S`Y zrrOd8L##@0)8|v_&qOjh0T5ySzu*owK@Mxao48BOlupx+p5Nq%Ud1 z`Ac;AAf2c?unD*+5 zKLH`c2$>XVp_*y%w~dy@ibuDLMYcdR7VVfZfXWv3Tf5Q@aL-@H^V^saKEN3m;Xd9c z@vZiR!->#dQ-$QY!DenIU>*$jdM63YqqIKRZGs{A_LG3Hdh+$~EqI%`pI5cPZ+LGf z49QtilO7lgmFeRKqa6F|=9Xo9*<3J6^|~4@vKvUvsRWd2toilVEpvR zZBA_#)oFE9Z4E}r;2o)LK;xIic*?Za7+p!-3bJWR>K!L%al-Xv@{c*7s0~vv*x%qT zwAekpe)y()a@c#*N2kC1hv9MWMfa$)rtv0*sYZ_AF&)B8(SmIP_`xK2gX7DBsZcjLs8m0UQIi&+~{#4m$iqPq==+pWh|}bRyi| zE|A`Ddf3KW4&buQ_04gabL2 zO70wc**ojJI_q7W9I6}f;Z8|CJcY_@zB=o4PRi=i$yM2G@LLHrefA33&IF#BvzDg| zluPp?)n>c?sAK^I4-dV$!{R|ZOXB&bfS-*lyO+=?Sy}g07OHEnzF=Sq* z`aIkAyS+ViL7)*ld18oZaA9svd~Qdf7yTr@#rZ2NcZ-UoqhUx50yAaidH5)XK;>Di zqv&3|B4fPO9kDvRL|xC6`aR@%2wvzS;dW^uLfI+EzX1qid6+RidG9tpk5-ghAJaJEc%vCgE3aeU-Tcag;;R`D}Zf*>=`T&MOfX7#yd zn+k4a2gDVZMyoJpdywX`y$u%V?j%EIR19=LpLhPLG~KKzh_-@8w3w%j9HisYi9#I% zrd~}|&nkWB>Cibl4&Fzz1Z|OMIwZRU_=~8mMQF36%4(?4EFHzH?}7C~!~ODjF`V9;2nk8N?wbaIZxv$2}=X__S;@DZppdEab6)ds(e z%Dh~vaLC=xap z;=_u?@6*ie!~6NxVv>NIy=S%iG&@QrD-CaOcdagqn%8{nPqDoP#`AzT+P%BxrmMM! zz_kTrVm3FP^=RV7P6*VZO%16B%j%`sz%Q z5K~3K2s3+&Zi|pVd;Nxn@wQ6Y88UcKybI#7>P0q<2T3%tH^Lm8127cAPIDqLErWI3 zpVFG<091i^8I*8ZlXfnes$|5kOp(r01OZ#dC{AGvczj;QW`Jmj=4(7!55O#1N?o2 zubM$LyGDc(^*6c}HQ|F+pbEpu>pM2})&95N>{tJ{*LVKz(%*FTFS+^4^5WvJK4$Qx zW~YA|o*wO=E8X;XW6e2}lu}|;hkb;vdpNZW} z&Hs=3FEFN_q}uYf0RfuNL~_tVm)w?=C?ll?>iP6sA13Y63DhW7SGie4?FGP;mY!j5~TtU+3W9^)Nxyg03Ht|d&kbK(ynNX?Q}>>iJ*B|GQxXFS@!b-2xIP~J zFYs%ECz4%j1&>9|jof87f4$w6&9raL#Wl;-6L($5cEP(lZ>!Lwe*^v_U@1%kv>1~u z5np1tVTPd5G1{P_vRgnL4Q_}^-wgd+O`ho^nMgW^q;}ka>PTW0;-dv=rU%9eJ8{SE9XD~QD=xawz~Le`wkwK5Vqt9 zi2elrB@OeLx?6jyd=D+;>!@|XkD43sl3I8(dZ{krB*DkZZIDZBrQ zkegjwx@|v}>8E8y2`DOSiqB=bXxog16@aruk|_cXXl83M zp}ED8kaETm7YLViNmC>p)%1CQke;Ua2ze^A@)i@ zJ{>H3R`DT0RTbZ6WGGML4r){d4T4-XN|O5~3g}QJ2zfb_#5kMh8Rm2)UWlUX`JRzYX}B{b_10pH6NMz@Nq zrAGNGCKCCz@qth;U8W6oUyb!WVm>#m0WPQ(YC8bmjW&TDH9HkNOtzG69=~xE9z+vyuCpIBks^Dm`zux4i;Z zn40S>m40Xzj|JqPjyLk>8_q%Wc5;T_B|0t?JKVH`_+q#bwBi5WPSE4Ve)A-FF5zFK z@b zUY|XUO}#``mMD*2d6_$oeyusTTjnP}x35O&Wi(^~fY2{LI*S%ia1F4IfkZJpDg)YAw4qTHHaydUix@^30`xKL!QlZVKxFBHj9L z?RtrvJZAYTJzs}WrWbGM-X=G+t5tFBNgu7dtm1kgc)CPm{j}w!n5#d{`cij%3(Ot; zU01l+X5|vEa$l&;3d^o@bp;w^^(9`=tKwQTgpJM0ZuWr}W;C%h`N{T3JPzW7T$@*9 zxfJM-CIwgBxyVEJRbNx3Ka=Y~Z&5=X_i%9IMtHh-2rrP@>)5;&3?ZuFjy^0B8chhr19fxto?EhHz z2(EGC|5a{ZWF8A;KtO@bI{KL9VEXC(!*DQf@3KY;2)6ZF0a)GB&SAclr6e$N1_->| z?;ff8mcRpSwz4rAOo%nJ=A}k>yEZ!>6&bfP!Z~c@#c9w~vT~el&_%E+d{L^pzV13; zwmD_cE3Azq|2PVmq9@C+X5uNYUQY_!!&Qu^~?4A0tEoQ zkaFO(brhx*45~T!wF0cIQj+bx-UE8Ogl|hvMa#7<0#gQaD!6_lv*ryHg@z@st@&|C zggL?@l86{^z+iatBysI$UU8vlTFz-R5Fo(^CF1G#k=Pj)=B5b_i_R^^2OW$tJ@!>r zbw)7(rQ^`AxenUXGe&w6QpN+j^5n@c4o$zV2E!ACB+%h6&J*+_d#2~dC%&petjdqf zVocqKhoq)Zd|GW+YE-M~OKw|lC-R;BqjMSh;>)4#CtofL%Pj=0XS)%~Lj$B?BiN>2 z`i<3P1_~u&U%p_FZG8YwGO*k3OhB-Z6!(xW{N_^qT)`*qgu4`SmyC?TfVV&OF0S63 zIYUJeMW?yZE^dcUXZr12u0#lAE`XdN8~P0_@blz}XH8uGhT-`ZZqG&{dba>Duigiq z`i^bf%NV>HF!K{`2mGzCZv`vv37IvbKC9P!9?YGjMc8`hDD|P*>zkghs)+e?98>?~ zyC#43dBObuM;?9!^TRz)zY5dDr=EXh=h+HIpqhRKa-Y}#f%Sg6X`Y@}(b>x%$HX;h z7ERiJ!e_CSEi-)4bDtV3?{KzHl_nXFnYSLNp6>Vier><))$fH|^k*W;>HD8c%!>2u zzFTs&i%qc)?h*tZ4;9y&<)e*tFr&`fR}1$+mqeiet8~7GAR+8xY!Zn$lf5j_h@NFSGApfD@xb(`7I~$ zZ_pgs*ei^FPG9r|t3wyXu$t;@O?Mg*dPCWtM|aUH#8#O!&7g;or7|e_>mKf2hl> z2mijZ|8KgomkZcj`e3|0o^kRDzLJakyz0X(#8XhJW5k?6P}zJ6X?-&+hd zsTAkN=2q2UJD&O535+ri*+o25kUIUL=GjL>$qo8-Cn($ntBeiRfsQrI41dzdVlRo$ zn!sm?m4Pp&1{IcbstF4is$rX^0u8V};+eaxL}qe*+Xz5PChq`%)3kF-6}RXo&)+dwHg zI_kX%4|=CRhWjUnp;E%TuTDaHD(b_R!=ekHb0*>ZK@CcuP9kNSZUrJQu+zgm5f|ub zqsB3hO^OAvSy9Dt{!xs;p7)*xOSOZ1izT_BL`QTYDB*|!sPz{RRvv7zW%Qjfps~7S27vI!8pz4=7|DQ&0w0?EEy~DIBOvy z?l>CEQq&ujD!x#4F4JTb&j6P-wt#|!WCzJ8#xbUpM+P>^Cjwt#YO$@O3sp6e z@wBsl-Z=}8JLj)^hhg&s6OW%`mYKJuoFiU!pr|7re?{yzSPai5)L*Z%#FXoctI73K zOT4v*U9rvYaJi58FZ}o8Cr=v4oEc>F%@7|FBbJL3`F-cC->IHZ{CTTI>%Hc+a%M|^ z^xWkq-8b8aL8$)S+LE*G&O0Qv_RYPo&5z~Xs_gCR^{D1YjdNL8ilV;VG6&g4c_qJA zEUSJ-HK=kZMv-kZ8=}R12dX-v z7K=8+oW<}Onp0oEvtjVV@sT!dLMAnBCH!GLTH?La8BgbTODu-*hpGB4nU|7t9CfH0 zA#`IS4|w)aw@c_JRLYK{`2Zer2~Mafq6Wq73uVOSp7gM`*t86a#B-P}#^Xq-)|}KA zx}+V~J&sChKClt(^wEFL$#OrVqR5jp;}e0Zj+4_q^&X zc%6Uv5AfgS-}lAuhtfUkIJ$$uVTZ6k!EHPmZ9$F+H5BODFdZ!53@!HQdq~Zq7Uw{Z z(%+r(&Tmk!_Mlf^K9k+jxk_kyw&H9ML2v^&&M_!GrG#PZb@&JI?AZvBg?2&{%6QVU z5Wfi_;Zrt88hM0GnM!LG5}yF{Ct?JW5%7T{2E2O=JA$mJqi6sckfWQU0oeACE5$hWC=aG7WESndB|Nw3cE z+b&g+OP-Z-74XmIGT~OM)Rmo1e?$c&m1}~xI13Gc26)GPE z<9*sl#Ve5=?sC1>N9J&Zo0< z3eJ!*shK*BuaZlYc(KS7*fwsdEz4rt@l3QX_t@tb32cgxQ@Q;9(6W@591N! zwB8MR(|7`@kkoPiW|n}Qai$GbQo%wjCg~set{@#BYyHLz!@FX4Icm5SG%&n~d@*T5 z8qZ9oki+E}jM6OT>f&*=e16L;9BXzz)iN4<&RMgz4>N79z2dV>+$UVZoy+MO-p5zJ zf{WWXkhsqUJa_j7GV=OO&VhWVMJeyxj_Ivzi@9GFgr+#;~waMA&pu{zyhgz$s_{Ku{kDOgcKGwDpOM+u~MQWU7& zD>@~)VuG%XGx!s3hG>nNlF9(D*%_Q(&)d(1C9_4%qMtBLg_s7;RHyEv5u|1d78zoM zdCeK}5Gmhr_D-AMV@r%2xW$e+m4Y zpeat%Op-L2W<@C=TG?o0wKo5`Nasu2Y?L*bivgk*{ia6;jiT5!aP6+JqvirdxbuJc z(12ew+&(#}zqmu2hxI^NsC{}3+XI+uuShIFVsa7+)4(kbZfu#4z8T5;v5ec88V^N# zL2!SP9T2n^%AyA;qKl#dB;rshu8u&YcG|)I1QU3VFt!3Rf#MmEvUtX>}wjCsrwAYo(hRX5#)>ColMNM=*o#x=vmtBd9&vULAGlG5Pq}vuFPi9QJ~f-g$7?fsduTz53rxdh5glsOcHRQ_N{G)%M84 z^TTbf_6e`riGs{5oIs$!|F4Xz3*M!QO!Si_QE8OxrVRhEd zDB;UTlPM7Ol~ay4I!Xsh^g*N;{0CB&P|sSh_ZN^ibBwoDouOVQz73E22jTafvklwU zNRtY)CaU(2nHE7yVLm8Hfzqjd^<@}t$dtPL`PY9{pYy{X{H^#}k#67YfsUwFIkxGa zZNoFn{wz8|>FyVqT7NSCP=e-lTLxlCm6EQ+IOP3|)FMM#&@KF44W6@+l1;=+$b1|^ zio#t%#tfEXr%rlD-IH^^xa;BqDqjbQz&i=7*Ct)WHmRssLAZ?+r>=i~cn}_SUxb|> z&Yzo!x=`bkqo=1Iu*>&+WRmke``6E&!zrltVGGZ4 zm~Fh>C}RHwxvjx43|}je;oH3(XxiPv-7E#N{w-{HC7{W|KXnw}qvGb1JDN5k?C9WW z@LZi;ibEd@GJMGL+%_8Qj{c+i**ZSnIy^kTx!E3%w_)#R*_uo?Ux-PzRNIR4?%;C! zBzXQGs!jE8W2+H7;RD@OE4!2Vn`Ah@`7%#o%&DpFS$i1WVb$}MtEv^9Vb$%`TTLeS ztf{yUYqpowJZToZz}4!0p;z}SqYgjZQ{FOb-70T;_psIlLGeMbkYzTDukmqr7r#d_ z$j2RALcV$Q6OQkvhS6bnc8WJ-o%U=Jf0&1sq9Oz*AAisa8bANMCo{x4#eFGRsV7@| zw=;Oy5mR7D$~Dy@16EHd-g_?nEnUgF{>zc7uKoNo+`HW&i^kM|9D)#5FdM~_rW{rd z9YD0e)ilwlwZBrM&bpJfDJx&7h*>-eb5=rnm7B8?(Ui z>RNinb~zf7eSLu#8R}qDc639$HXOX}9Q-4s>y`J2$9q4N!q1JH2UW+7qrE7;!J={`g5X}efy0ulkfXi(wt*jb{8@Mvpw!z& zqae@j{q|p%2TLCM>2amfWx?|bh0FxdO`He(#tEL`Jm2cvNX8m>o<@dd0#GO5vvz(i z#Z3?Qx7R&|de*Qd)gO3!!-Rj<-}xooYiRG+ri6dMFV9!3sIO7?sjH*(;rC}N)@5vk z`&5l*vvii-rzRZpUIc<5sJzWF&*lI)%G!3$8DAIF9vM$fKb9(@+&bnv4NZOB0m+Gb z4gJhopTW_hpmQs#{W>aRa$$j}#pPH~FnPVT(zW0WUf?3n7L(Pg(tN>hgA}k6=Zei% zB7h#%_v`i_$6>Mu56EBzc8Uh`h2|aW$K`Wo(%s8>037h5Soa0OQ!YwXVZeDiF-K25 z?;gjGX_d3)lN_50KcD33R6@Kx*8s zIawC(-!n_5PRG1y7IWxT5ZIE#7OLAB@Fs9p20k$8W_78Il1ZuX47_Fz(;igS0yD>M zPf2)qxUz1)^jYNZneBuFT>mYdT!2}mwn&{r%xO~}Vym=SE>ONTfQkk;A3CU&FzBQ> zE6eGqa@k@E5;v=HsJi_6N1Tj>9z3Y(Rd?u8pU52oB)e*zo-5qj1(^r5{8Znn1S)2x zGtOw#x2!4!jYj&!91{TPxg>{%M5#dp&|OV}vr7nU8<|4`%5rij36BO}J$Yh#4uE5i zAM0+5ydd!7DBDJ?*mv^cc?u?S)J&u)zykj1+;-zBDCv+a9soC#Is;x?M_iY?4jx;D zTyiV_AT1D=;bZ|22O?obvG>{;dDo8PNdQQ4>K`P;1)5&-7kyHA4Sd^ZpUH{FXpUR**Z_zy&)T}wP=D!j{^3VlCYUK!nrzM-YQW5^rk{gaR?V#^w z9b(S(>tl{tdr5Pa$Ne1s(N#1H9__ia)W-ZN#?xeeZ6CG-zb}a&Drto!Z8m>>h`P7rnbE z1#7pz>_n*SLg{g^itQuwodtDAUU3lAo`O|g>~f2DPpeTWYW}?@?;e&Tfoos#tdg_7 zW;ctgt5Lj~!U3I|MU!C)K1(Yev|_a_1wBJKc~^ZfSV|@5!YV7S-`$Mob@7!GWkkuL zvSMmh7d$_ge|2lGL;_&)0iJ4~Do^7oPweUdXi!F*SsdI(#-Bo)Ow@6ZL2e!hzna8O z%r6UGrK`R}x5@*xK_bWGodv+qo-x zv*Pixs>rA{ITicbmiFp~%Xs(!5fmN-KcQZ1Q}q#$v(ft=2z1<}?c%Z*0iRu|>`{P= zJ+>n)JPYs_=21Y*m34{J)!S;Knq<-2wbnrPf-A8Hnz}f@)*#r>T*4090yrWcIk(CS zk1%j8m2zc^;*n{VEXXv=fsGP}fm1u-y7Zm(7pSxmep8-y-6Q@)$Ch0!ek&*7aMA!M&Qlze>X(z3?b5+UZDbc;|1(P`4+&yf zO7HhWv0Td`{NT`6gPw#@K!d2xd>RhXJ;5gh2m|!L9ty)+1@s&YX$ffG!y(I6VavgA z{IEFC#eb-cxcYQ|5~SR{(B#T|=U1+k;LBchHH6);d^Es?|JoA>+xPdKv9)pp zJrWV08$wS@mCuHuw*n#^4fzv5^z>jpeE<*D>7_7wy33#DZu)8NrS*~Yst3CaNzdW6 zPaUiwREecmIB4&Ir6<*gPds=(E1DjW;UNzb^bi2I1pf(~zsHHQxXAXaZ2D5^_?fZa zO0~Q)@VC+m?X}XcwzpSTCUNdQ5B^(TgDwYvLw2qh)*p)Q_KWJ*0|J#f8+Hl48#jG# zoHDNO11eiVN0y9Vu}I6c=06CT>g`(t#FPhSqQ9T!A*G;79%aafDs@@FqI&!GatRXE z+*4=1q|U@sXR@Tum8Z_tk~%X_omp8OFXEJ10X2QWx(hL-X)T^TyC+PP?L#ik*pPo1 zM5r2AK&4uS4-Dwu2rh*q(f5#exFCV`d5~Oi(a56a19W*Pm<$w5FAu)@>Z|`)2_>Us zhCI)mO#ROcma+D4pp4HBl<|KX5{M|7fcvh)KwZ=X^>K6y#E3^U``fZj{I-RnZl{(C z$fwcwv?*leas}r!%+5iu{^}-t9eCo0#s0MEvMOXuxY57Vc z8rlvVi#cjjd2jolDw(^$q2>s__$ei`+-yHbovZ9c7NEYkIa4hly}C?cdSBNE)6SP-oKCD zz3{a@!%Qzh+We%wUTSYQxUBkj+uv*NwgT>lS@!48mTs*g{KwhF$-O986p(}7@hM=# z9^Q*i)lxs?Lf@}vrJef3ZLxZ9T+kFb(=uyVg-0QKKuKCoYqcm5Fo~c< za3hA2lyFrdO_lr|MXS?%6}yPeK*xU!0zvb^3ic$O~mw9M$i2s^6nq4|Jrj+H?g-iRJS`&sIO# z9l==d$X?0h^6-u<^s}-bZP~Ho14{W5;-VBS5A?YQFQo*4LeGFOhS(deF^T;2zW}9z zQ61EZ2;1W_1PC8ugPhVJ06ir)ghH7hc&jH}m_T)hXc1a9>A)#YMBX-PRME$rA5y}E zPGdc zD0)-F3b;&@_v$pF315h#T>z&+d7|cHT|8%I4q?DC>^ZK*Cg;fS3bx?jREc*b`YF>Q z3a%#7KRT}tcbQpMp=AAw=D<2b807;51VRFiff2;?9nus|KVPc5GK zl&gCcEW@X-?0v59rAQSuZrwGm-PJ+(-V@5o>YBqY#9zA%R`+>+BzgXPy4V(Rn{4Z}yvb@GgTbpcY5_re(qU?s^N-j;sHCu@0G*As$1dVQ#|- zcBghT(BQny86|GMybBs%eE86SRG8{C`|ts?JKw~~EVzk3M8kN1DQ|zf9-simy~$0%Hjv zQ|%b_h6zHnI3Yh6p~VANb#Q~sE|d8znkA#V0OHu)^I4l{k^Vdyyi=NjYQ^0|}Idn_#lupJMgO#XzOpEt?%&1 zPo8Afjr0&gQ&UwY_ye zx_e4buhuF&i`7pD@8UT`yun|`(YyE{olF?yndZ#(m{sMkh9SJVY(1Brt%a(CXtIvs zfP-kHR4mFEOUfWJxa!LAENy)>O_D=Wo{a=x{)h}OTqmWYq5ikrb z7%jXxC~Ezl8a_#u9nnchH932a-4*#}*L2cca(#{Gy11GbrPrtr)WAo{zeIsT4M96%G!(RKpXHYF{?QO9Qp=u_@FsgslK11k?~8>8X9J zM`JGLmcCRRL{R9P{j-zq$t#X1LJng!IGm^3xxte;!*h7ZQ{)a2?;4?Cui%q zdmAdexqanp%57{9cVet39NCXrFsr2Iz*zE_2I-mhXY%wQ>Y{r6WbO`bwQuH zQh#o5zw3#}A>-CQn6P z@At#~7yY9WwS)P>wB~^W6DkVwpe?&gB-J`KMR(sFM<4894&g((Fv>eP9LAe_!7REB zQL(ZFa6>?J1?C+<$wkvSgG|gBfb1!~6E`rNs%qO!M~jU3{c16xW7IhxOd}zjnZ|n| zy39t~+o)-qnSX4`{`BnUmRtn80IZFz5lGc0cO%4J298*ySv-bSIZ_)B94Ov3AM+~F z4$oDVe}-npy;me>P=!mb9Y^vr>~^P}$B)gHedJi3)7wxpF%ze`-*ANJ{%{BhENMTm z+(f;Y^<;G}DH#P^Mz!0{gsZK+PfFusg~Ijeezm-w?w$WYy=z{(vuv>`*pg zqyzZEkc2;!!qEtVFQ(hU7nvGpD{y;2&1`5FMZD2J*+u$>D{{M22}m$*!U8?=Y<;VS z1J~~5_FM6LA#irqoEYDNAU5r2CEF+EE~e?^D2~*Db^Qw8(>CrU!R@ zP3CCdL5_zr9zsae<{QS4K90qvEvi1(#Wc=ee~?b&;i;zHQN+Pds|3Zbq_lIrH9ZZX zr-&IcjTC?J&e<+25H?G`2)-@VEX+??)on-`%S%f}_$a_HSYCOj6%bwH0pQ&Y)!A)? z#iO#0=W$}NDOx_7VGzMB@p_WZ)PYBaj9I*nL6SEh zS}$>5u|BW#K3x9W*pgAIpt^kCMrdJ1&CS{jFXKV9$oRn_F#?(ZVW!yaU8SXE$p>|r z2UwW0B~nuC)=KHCTew6w)fjPyssBwG(UHF=%~yVCG~53!V=*lX9u4EG1grHfPii4Wl`J#kM14fo z#mHea=V@(3==E@TIKZRX+FJ25GGM!(H8mR4ES|z1orO&Zy0advrpg%?5D(I9k1m-{dtg$%2bieka9AN}3^Z(o0dUs=W6puGcu$g7OU!| zI&ZV&azx>UP>Oqo3!07)mxSL5gWy2Pkjt2Pbg1;Ubc}U0!HjG)ijA|I#azjj+li*9 zk0C|U(mP4#{33}Y>A^zDS90|%(#Kzb5_0jG8Z%fNl~Os$uAp@|!&IB<*PCRjWw?@H zGxp^1%_wV`g|9YEs~Y`+r*>*mFP{! zOo}vx^~^3;GD_xmFg{*(IY({1=0N7;;^+tjku!-LLw}{TwxNCshA-Pij@$H38BhH3 zIRg=BnpM|}lHEZYuH;Ks%Q7h#ePrFuwaP-pg4U4M8iW z1uM)8@d07~j7C5wTU=&?S#k+4Cv~TNX2gx!@cBOL4d0Ks6aMKGn7T&AQ5$af3!ZtdqH;{))m`0i6GLiP_5- zq8Yzzr|vA-s=8f!hc-QtL5f8QYAt*P4tBO~9R`M{K|Ht~f`i@G{}(Xu5984*J>J#$ zHz#BN1niqT5q7GNga=^WgLE>VrK1cU@!&3|B|on6C2Co>N(HmlNqdl_8V1g4Q_kUx z4tBn!!@pk=VZ|by3A&)d!y@YBzj{x&D^osE#g4CZB7rSx}F%SZVu3^4b&f zqtMa~SRj1#N^g9+1kcln`CiB02Lw%sZ&diCFWDv`TL(U(wgeKPRwp6Dfi{G|ZP}<_ zuyJAKvUsqVE4@vV;br5=)0@a(0X%&Q1>eMchlUp>dNfiEDb-4?DVcu)^ymXMRI6T@ zn#wf8t*+amYL~H^IDm)+P^AF2*6z-&)DTX=*6bJ)}L`e)UQ-hmma;^5e zo`X#@8))+CPT(>yh?@rE=O7)%uK-f-;K`F0i)1uJyF-?MPLqPe5NCC;CL(=fp!)jS zkbu|5SjTXwd8M~qH8%Gf;P-cNJPoc>wRF9nrUGyOq~7!8(lJWm6`ybT%`kk?J3CUh z#)B{v$mw>-+O|()1)Wdb>`ZBuijLs6DDOp? z_i%Y9O8t#%_kk_1+Bry_x9Yr^qgyVNT0=(!^)bcS2eZYb&}-ZJJcU5~8r?3dqWc{j z#n;i`F4#Zqf`}P{2jC#WH!yT*0=W>qS1SOL81|5oPTFdI);aEd-wBU8ul5gq4Ef2l z-%+H(C2R;9%mZ*?IcwExppvsnIi?=%Du(eaD-wN>RTUzo#yZuLE=%Rg%4@lN`!FO~ zN&B9p(G`t*O4pNOmGUdsZWVVK*V58Pb^H%COQJxleiWz>8{se%3jwS%Yr4cwxjfLhIO+aCc-PoZZ6lW;(_+WxBe}$46*qjo zaABc13=4O1$cZ#2vFR%W-VC`SpBbJWTqbwcEa3Y|@-={PDl1vXG49V;ZE?Dfk z4i_rxy8gbvj>#50znabj(HQ)#wdbN#2ZID3HD_?sA^v>E7phXta4UF@j_QfNiJ_2z z_Xi--GUj+N)wI`g;1Ibxl=+-|ZYtO(7yb3QwKm)B1Er66dJP}f?KG9Wr%obYpKLIK z1iTe!_IRrmZuMx}!rfs*S4QdeHL#`S#6zV;lo+xythTc^(ej6Od}#C+d=RK{O==kpVP-7n0^-% zM7l1kZ0&qmJl|SOMQ(?5Hbiq~d>7n;Xa9`5g|?^tD}0(ULNzg&fU)J9h-^|}r?bfxzQNjVY|g+u1X7`*Lu}asQ(NAKHjm!L@{N`C27c`n(^%U&)&ld`ZA|AB z8pdXGw1}a2z!fmM2iV2HnLUnFCp)$^$>{sTq4=ihlu{kER%`VKJRatN6Pcs(j$OcD zp;83IJU2H)oC#1C#v%2m=0DY+jB$)Cs+YF$YpcBwj>gituU1iP4SY#Z$Ndat>9&xvTFg|rJ>|l7p?FS z#JE%9v};n`p?!9J-rz`88QIPa>3C`BXpX>MSbv+Mg^IzjOPc~8;yrLB-r7p66O(b7 z*2*>1WB^(8@2#TzQv#>i&)TghH-J1$oP!BRL3Oa?Ee^0l7g^!O^o_|4PT!ja&>l<% z+ss{I?YkwOc_57CQLa?ZKaBfs`~1#&l5!Y;`r4&o1d0y~(8BBbc1PfB1;P3b%R{eZ zT&Uxg#>-Lw89XD?#7s>(hZ&rskcA_a+omG9eo3Ten?W2q2veEg&+qzVKeC?XODnuf zrsD08_zAtd!*mkr_)9vJKzojdFu6!tTUFcyS~ z@PUj1v8j~N8+9Lq5BU&HQ9KG^ZDnMpNsxmlJmW$QRmOO}-=?#78yuVpex>v<2zoIX z1)K*@M534sam8^v597@#k1&7d+7tkQ|`Hj-cabjtHaS?EO@m7QVf{lZ@uy6=G*ECh6fa&GE!RS%a z-zb>(1|oP%n1OOhGbLG4Ns+-#7=IYVQ(TzfY7|}5`?&Sz<*Iftph*5D9--r?ecYKu z@J<*~Y*-koc~!F{e%>OTX4BRfjFhUbN(R6ECLW1iom?E~>QpBXbw2$4>+tKp7AhrQ zsn1oV4KZWDT-e0Z>%l;~`$mJCL>>S3HssD#frUj)5E)3qMYS(~QFuqdK#sEhJ&~Rw`5a_3+hnk)C{cD4^ zxX{mqvxs)e4GiQ`$sQ%16~l+&(ij3`i6J%Jj&-hwgFPWY*B!m9ZW=NN1#! zz!5Rkl=ZrAx)BaM95tBDJ?opf8$9CkTds7K%(AO-^XdR~c0T;twi;1(iF3HJ6H%QD=>@8Y`_{v}@h;g&sxtb)UWvV9gSo*x=i z3y-=B1S@>O;ioK<8egYKugJ9|*R+Y9rYiPozL;eBTd%Os>eVLCEJX0LQ`VM-h-U~_ zVIHS&T@)*V0J%*dP0DA#jJg*3vxSBPpm{^vs1jMj7#!f~G`dMfLx@U7g-8b*id}An zhKaQUE50SM(H_N<>-i1c2y`gDR6>l$1-n=27--ZS@HnKaS~S<@4ichlc7UyGTvF&_ z3*`so;slH@8rxp8>FonBS3x9~enOC)(osth$GzO7N=!zVSvmrrK8O&|L|{Hdtc~`V z5_fRLP_qQBqqYjp+v!>7c>nz3tfRzfS50I0sMFSEzHF0)M|SE)ExWd^pcgslWG#@6 z`B1607^ka2qKc!IXkrz~vcB-75*4Td^BQrFwxCB_mr=Bu21q1B@O0yPI{2I69a8smiJrCsO@)fIHb%d{{s`G--g#~;v^Z?`gSbaO1w zHtVX*L;XS@X4AQ08q@29jwS>d!y4rj%FD@Wn}Q|ET-w=45zqQr+f11&4z!9n4Y;Rx=f@* zwSEs$dwZNr@TC(kuA#n#DG6>&2Q5uVe~YyNd;ks`WG5XodmE8v!sb4`oz=Ew3^Gj$ zDH*sfz!yr%D50e2Oq;Q3{X*Eu1gQg;pk~;+I1kTzVgLM4O|YF?p1$Jj)tI90gyS6G zss+z7inm+A_eln?nf>`3!Em!MthuEh;?A!CDjG!0Z2i3Ji6m2hNt}OaM;;De~liqsB3Cs zBw*lqONuKU?Vzn(C^$fWnB1wuOz(e9L)&!TClN1_2)C}ZbMfZERm3R>FJn05(pgjN zt7jjcwW{wu^aH2L2%MwIFb5hR9+zN1+7|S}H)?}-!u=OLH802gS88vDYP%nWXPr~^ z5$;=t;bFOWi_8v~h%-1}#?$ti;0}8UrwgC9svVr2<8D9^sx6D+T?Xu*aO;dliJ41+ zx1$Fm@Hau0ndnlah74l}N}JBp*#^G@X}4~r&J5uaWLAcbL{Qz0r8A&cC1w}1Nl|r+ zK+{om$P0eLu(Lc)dOeCVQfy&xz`|-W;7)fVTd@s4lwr`ND>)qE0AObSBm?3rj1jhJADCck(+>t*_{xqFZ&%#(8gckk;L?b`-mPAF4EE`%vukW z?!@?-)bru`Hszd|(80<2J3WYRlhYYcO#iUqv!&C=6(X1D=U|F1V)T{F2?GoMj&njS z`gRCq8-NSKkgiy4vXIWD#(b-1LZ321EOc|`s-FtoAsO|9<5<25^Arzvg1 zree!+lJYB6NldTVfi~8uD<3?5o7r!RZkgOC!WhiKR{k@j35up^<1jW6WoqGl4g7bm z1vVyOLng(`0xy#hyC7&37rUtRZ*a(@l$iA1fMX@Tp5o)lxcwj-}U>~tzd{d!Z}o;W0A7SfK$gTtt03Tc^YSFIXC?=)2W zU)2|+C;I=m_5e%=>h;;zMy;B*opSLNHY-YHp>=c&IVM?`9z}|ZFe#A}ZgcCoDN#J~ zi_kuWBd}P+^9X7C>^cmE*NEU%q%j4^RJeh{L}hUZTnKZBej|mUiE}V)LY{Yg7G|q6 zTo-4_a2RWwA>M4Yd7HHDMHaVRT0{na1TDC5#TegSQacybfn@Ysu?VxE&)uhSv^1bX zXf}#jtE&hv353guJy^1`Gn-RJYUl{LYKi zPXf;sZU61aHWRsh$S+i6n=uLmboFIA>qLVaks~e(TS6*RRh#K#&lu5Nq8;hjYstzB zo{z4m#+3Qw_OrOpWA=V70hkB}-KC68+v661dSzDX7a&QNcm+JYk4u1kmR{8hz;yx8 zJ^^*S0Qlza^8}F7%z18fqs24?0GScfn=%~Tb{RGUF>_?$5^EGqf#eKzVYv2~QO&SN zc#C0^e^GjRvfGPp=u|s!<74DjxrV#JV-HCP1w^S!*d5kY$0OhCHE&bEE@_{L`hrTF z&Qv#)`CIbPB!5$t1yyeM7!!BLGSqE9g{hE2-po1e0Rt z3imQdlw7!!clOrM_Ni6JtPnxNXF1Fz#K3ZP%E$qtmt<1}CXH3DJ^m0p~|%aR13R#OW-OiOzuqJwOk!huI1y z&%m+`p>$hFS+XnL4f6RBY^H1~oewKuvJ|GFw0uAjr-E0>WY}EaUKcqm;QL3rvJ>0e z6ZN5e?{IjNp{sxw3n^}z+zLPwDxP`<=}$6mD$wd5myDwEm-UG6AH=U%--|K31k?IgaLJocFyp(VVe({` z#B+~op`V~zlT(Xc^)2>RFeb042ts-Xaf_YI7~UZnDt=Grc$M(%xzm(}1fx`I4n4M4 zoz5g<&z@+W>x6MW;m4m`C$vY&qb1j7y>FHjGs!?5Kq}^=i~f1K)UV=wIm1_OC8t7>$=`a%wi zW$xTo<6=y_F24pq$>mB~2_(MMpK^1V1s+p;n_NN06d_dn-gt(XrzyU?87Jgfd^Mu1 zTlkm-_b^x-etj{WxHt*np&xqIr}feOD%kgNbh@HBW3t>CXLUYj3<;hI7P1*Ox^>`? zz{_*-d@mG8KK@MPho|R06_9&e2rx?GtBsPwrpom30xFhSK1fV2Q4^NUUx|*O6F3FC23|PuJ?!W`FTB|(3e$#fL!*&)R|x_1PF+LL$wJM5olnY9!EqjaEJY9cGu97- zl>XguDs+jyuU?ZYSm%P$%o8F=1N=OPAf6bmdq7Dd5xgcM_?SpMdq>w`z5uUsOsQfX z%WPyhIUySF${aQzKLDCNNMMmE9dd8tKrIPIe3(qe(IlPRjR6nUz7dGvqiH%CElfUC zwGm>>F=@)0e(4dMsBgL%Ax2K`KrZNn82KVjA`Ie33s)#oW8~`j!Z4sa8^JdI8#d{$ zUv(b0Wza5q8LW{(35@vw-oz-W-5RIphMPTJNH&@UZvtD{3(O;EJAtxN2UCL?jHkll zxU~oEL+U&yxgI7wd#1x-MIr%dZkkYjBY^x@Q}8kYH)j{c!Sb9jkP#LE=Kn(j8({OX znBVF>W82Z(*0m>Zn8I%n&Bd^PU$PkSf*?u+hG_xwj-uNc)4pEi;Zw`zsx z&FjudaQ?c3JO*+$*gxw8C%yBa|N7$P%cIVr=D_{g^#bjw+x$TwW*x(Qx9w8jWC3Uzj~g+siihi17Ezw zG@K8(Ycfm_E$({u2>%L@RTfkKDC1}r!Xc-LRZ@b|nLQH)F~Rz-7V04Oh+7$X66IE; z<$h^az+e(+A9}}j{8IJNPD#FO!LW?Q<+v?!t5R`q;f-Q4T(%*;HMiD$)^Htwgu4$& zg~^rkY|x%vDt%@G``G;$)K32`F)#9R)3#yb#$CbUp}%2}UhJ3psp2GU1C$cF&rnhw zwWmSc!5B3NtkO9`&u~E%u?t;TSFx62soZ7I-RN?Vl{9P;n|+%zH`+&PW8^s|QT;L* zfr6Cp$EsKGcR~pV) z2Yzyyb=R|XG0-HY*dQcw8OPw$y|}s>ArOuU-~o(^o@bU1o|HTdm#>V=Z$-<#=3BbA8MRb|Y*}n`r%Tq+!`H;x znsZ(NIM%?eB?FulL+&+w#R>gmL;82Qt?8$_*O-)y74CSBDwbNVr?^GXds9o@B0>;4 z7^49jLO=K}qZK;+#JC}nH8LnOC1?g&x&-G3{=r+w#gu%%Bmpg8Ythh!g$r4&(A8Ek zZndRR&1QLp&JaUH0u#(iN(}hNo9AXmI_EH-;bLY(#9DU8G2D4F1Xl+(zEFTy3;iz{ z&1V*8bEzCKeiQ>W#N>F#@w2d_z5Z?xyF)PVXzfv2Z)9~fzMd1%VX-njuB#cWx-g>( z0fGFo#sTq>MOU#BNJ?>Ej7d=|>qUeyuJHOwGlkG=8YLd4z`-{xctTqn z)wxGOcY<<-A<`!Wi)z{W?iHEX3Q8c>p6TGh`Ya zzP6A(pu2JZ_5RtRy7lj$U-ZfIUzPjkA|~&26RXE39{SgFN&{|qO^4E9NG49E(F!oP z{CV1kqJ1T*7N8Hr-K!IHsIi0bahMIyjl@$bN>zJyl6Tb>Y>KUHem64E{qoS%vFerz zyyu9sPcaobyX;h21FI?Uxw+~K?2a33MNM~pI6vDLjfV%XyGLq~I_DRsXmKUotGqkz z!&oJ`CLgmhux_Q^)G%s_jZWBWAu^Ae_CEfJ{Ly>|e18srk@$Dk3h)#BqdOVKAL?t3 zm2+dFYSS@zOL8FmLSxvX3B_JDu29va2($s9abVVpH4%aeLCA|qPN3aH89V0@Rk`}*V(y^*L^cj}!$B?u+9fNe1V-mDB!0z>|O28FTEf8jd30Oxy zV$@i6q@*1(~XC?e*}weoB#+eW>2tWLIOe zk6x#@>X3ocHo^RUDc845^KD>(O7u}=%P+MoWR;|5r#GP5e5pVqwyvkxOYn%dZ>fSN;EcpK!7OGlXS8_ ze4P&L(}sCI0q&XM($DM@P@i^A=3JC9uNU1du53N+SlxXop&WetOYULt?SdMY$P4)K2%f-+&wXa^YE5IT7cZY17JK0hW# zc*n%b(O_;soe^fwlHofdR@NT5Jc;Ig4L;ii0L8=c88Cl=)-*#!`<8?zV>$O)L5l*VJ?!olkB4l=#Y z5{UMV1@a%?irEL3;F$Fkz;wdWZEtt8K4le=5yEt17z6lE5?xQ!y&@T~Im;o(Il`a^ zEyhw4$^0a-SP^3(!!NRJ^R<-{k6nLGM?={Z$WUq$9Y^q7)SZPW*OiSF{e`6HFG{?M zqHV$*$9M~qB;v`FU*wGV0ZX;Nu#MEnb=z?~Z5MDyo4<%&3RAEk*ajPH6JLwmx;b=E zx0}wpnsJaV&}Jlvrqhdnj5b%z#uwS!Nu#9!$MX5TNx~F=Q(|b5-6-)oRKmlQ7QT6p zi1%Jc*-PMNex-Fe&@35U^+BPhwG)4TQwkXG4oB3nCnNp%aNcccI4c0jEWbwLoPnJf zUPW+;a^C^#5Z5^%@@weus~GT;;5jpI*|>vW@*^zk$S>fap!g?0Ss$Ih5Llvm!NtPX zSl6dd+2@}{T9lJ$EVe}WfRZ)z3WoX~yr-*wB|VU&N>#i@_$)d#j5#N32OWNaR>E`~ z&EDY=;h6iPOj0umn^JT*2{<1&B^%{~m)%nSbj+GxPqRegkU6)HfrY~|fee`lkI%rq zc$EUD?rhoVsV&4M2Pi$ODeXEg9HZi4E%$l(%bL%6z4Y+4b%yy4@&q~YSFrU!Pi=ST zQ|Yv{T%F2mQ}FH+`~o*s4YRjIo07eBbt#i_Lr2X3EZzv0HJJ+(5S<*yGLg9+>MN~O z5!I&^DM1-a$BjtnOF>(-@~m0~@uBz%Xu(BBwc-mGcm1qWPX z6Yxrk@L5+v3?Ot7Xy10_oLiB#XTmePaBXC?k zC2hpW0kr7jcS;31i-%T1G~Q0S#{e|6e{v4qCEbIL;*Y}~dYX{^YFlYEwmdQkvbe^W z94137jYjqc-zd8$-ShBOulMSx6WR;|mW)!*ayP;J<=C)e_vHKiqwZll=%)+LFkfOMrRE&Gskc83by*_k<6%5kyFF{+mG)*npKd>WdYimU zo*qZZ3RLgIv5IF8(5!>ljkq-YP)EiJe0|7pjMUS&a5HKI z{!pMs0kHRr%*%Vg^8W4=hF&_=@Z-O4A?`TAgQ_iman=#STh+k>5hu}2-%ft5`YlgB z7xMcy3@ZKrzQOt^p2eg1eKaBGLeDrkD5SvVWMa~cj!eA(>nuLngBCTX^n5Mq2J6v# zyR1m#huMZ^fApg$?f}dhR$=39$uR;AlLquM2Jl%>cIbrx%`s}*DV=4Ma6YfRro`#8 zD2h{n@!sNl`e>-%hth@gD?-F=uy0I;M3+si{N^rSy&Ok7F%6-bcn>eh;$jj@N-ur+ zl#!#$pA%V5^HYSA_Jysj&Jfi8@50CMQli95Z+4id>rH-)!PawRSeK4u5FeTR*olf3 zRZb^%)puY^c1Xg9rNgrK-{q7ZNlG*Zkvd8B{a9OMczGa(tIH6DzRi_w2Y2a$t``kk zC-)XgiGg-0HIV3!XoOB0q=O*L4MRpevJxGoy2f*mUORPEgg^<)Ms->qzYOzBu(IiX zv~=M<_jDKLiRW8(v(|*?*X_?T-*RTZ37)~bQq*s-he^&U5vG=1OPykT82Ge=&;pqCl4io9a}{oCKoPqF$>e4!$U8vWkLH zTuqs>%!r}|Gp)LHhW}VI78o_1*!ia6c;ta|X*lrCH1ZCN%%dQ37hAz&&Ud4GShnz{ z@4A1SyA@qhQO^Z_kXh^5rN($}1<3exTe1$8!{!MMFJCp3$%*S_7Vh;8r zRDEW+HcwvE{1Z7>=Xa*76g~Guf>h_hQ40pggaoy6oy=4F=@*j_wJ>0+h{H0~^f0A= z&c5;bH&^)NO1hhn5S>}SO&uU=X}n`NCm089>$cM^x*=zwX<^rc@LCeo)nja~q;G-7_>NkRN+oL$6h@*0G^eJdxF+T#7=w-tLZ@hkTX+_z-gD)>FWeUtN|SiK)oB3)E^nnS`7_ReMAW3Q~HjyKtGe zuG{P*uae^`IF52t6nP~aknbyVLjL0&??AQKq&jBKA)|QFz(G7R$^O;~>;;qnL8# zUg8t%C>mfSggQdk-%i#MvPMmz(pf+?L!FWdG~TLfss(6d>;J8!;U_Ll!s4{ zYS9Hi1b@+ct+%kg^)=e63T&Rcr_(jOE zw(^`?;!Y_fgCiI|7GyvWpqa2-H!g4rZmgx#@16Ybp=!zO=jT4Re@iFd`2H9&D^0y` z;yvT6n)u?R%1M_})Ms%09dJQGPgnxMNzduc5Fs@PmE2P z5HV1Km|~%ZUoR6 z&{;kLI;WV0nG^IY0zDrPtk-$Uj|ohz@TOp$12m6o{h_aY4|{#elfgMN2*F&($saNn z;f=sSru1vteykzLy=1^BBNKk_Sjg~}laDwZ4NVnAm;mBzV;tbG+tPjXC@-L{dokH* zL3>#rzQNQVukiCOtoD`qbCbzh-P4cl4q{f8TnYsbMM_9%N^)VO4YPW36ZsSaXh%B^ zD7!_5iYA_cw=4{wXbLD?^Y=M0skO?#Fkw$hAl1nzi!SS`toE$BoWloMI=I}XD)FDp2(~mOwMw9S zAef{TJQkm5^cxeZ>on@33oUQBqSd_Bu>z9EV)3lfSDJAS3(l=nTV4?#FTWy6Mc!E( zJ=6_X3=1cEF;OC%mHft%8GF^69O~Le!j9cu=E%E-V;|+slr0;Hb2BxQm=6s$gt;D= zT;a(vow|MCV5AnoNJtb%qN;I5T{7Nb=<$PhHu!H&!LL+F-j^vRMZ`$X7tsv1E;R;k zupl(?t2K%{IiSgw2ODKpJx{02cDvmQo~!yqQYU1w^ElB{M@s~c`q(0Fj%CypK|llm z`=EUqT2{&CKYO|fkvb@fHlMBrD2FfnW+jbChPy5RqKZXU!VQC^F(elZT(>ibaG42Q zOmzny4ior&O(PcH>PR7sF;U9bXmrPk?wMHI9$}u~*UA}iduP((U1Zihnf>K2PEXG| z{eF0Ha@N^Dc#Zkf4j`E?Bh!a3I!C=Xq1rryS;`IuI)OH(Oi()<&GeZ3mQ#|e6T$-0 z{>l)t2k_qubmurv_c1I65ifrIh}}b@To*rT;_vE$O;fgE(_5O)5ReRuSxQaT0|mqk zC6({?PWo#$Jjf6s;CGDAL7N|d`Z?q#2(&;U`J+2R9>eUv+G}|(ZXbhmJXLomaJWb& z??@HE0$fqUoA4OvDV8pN_9Rfo6-y1rL_c2~-s15zP77kpA$`gqBS8{8LHvLWd z2MTgags+cx744g&xcU^oblwE?K*VR8NY%+#!HFfXELisOyqT$An)I1;1)BhtFZW1O zw>1gFS0AV}+9$iBz>d^fEsjjyiP&+zi}Vu=M#m~%8pBke!Au@4RE9lMz=2Tl7rxN>Sh!Y0Ct2aiO5F>sx`PIPcDk!yyd24oyGEf$}62!s#*MvHSTc3UQK>VP>pTJO{rYnhH`20yj z3ze>|iXb>V5iDR}zSY?}0f9&p4*_;0AOWL9Da8n8pE_G^{n>geSif4w`Cfmyo@;9q zp)qV(Te?aeRSt8I}?b9 z1=*sQwePU#7(01yV4Im4X&m#EITDD{=i85ihr?feQ?9+3 zPPTYPtA(!64gM9FY#ytND!|fz0}tWoPC)NZdqv4cU)1G8D*eBc4UK#=q)SBAAy}Qp z>iS^AdJPNRM3iF}uUU9cl}ODC;62PvL*cd1G(}del%=tN7{Re*bl-qXlG3 zL)FKD_WJf*da$E_BFbIGD>uGiQ2>h0mDe&DWaNebRS?ISfv(yCW{acF!vsM0*UVkI zdve}6JJ~-nqmU|l!(jC`P~j8U;$kQmzrqD+!f+!ENnK@}He5)jU(QZ=9c6BMJI__u zTxxZ6iMSHO?VuGr#v+chuv2Dvk*B(d>#X`nl<};*m?zzWtlg}vy{u0qJf-`YbBr{6 z&IzUI*I~RBPv9T0$bVoQeqL%Q5od#Fir483U?(R^Z0gJKfH(<*ImIv8&_4k5 zCq(g?1UBD&2cwvpK9LK|`giO0zQ7q`zB_}G5?%&L5d!K^7kX7%=z12%6J6}b(qeZp zj8&IAbjqdt#6)@1NOWLyyB-&wDFr7@3|#EcwE7v<#y4_Dc3mVFPL;M}ZqnMa&#fBm z4@{eAhQqk}Y&zn%XkHN28OSMkO^{Z@Ac?8|Lz;YFXV^urbm^a z7N7mX)3;z}3*N~M3Rz27Y5nPEjv^o|Bn^Ya0#k?U0Vv8`?UDtmHbvB;MmzX1U7(cY zqyZXcsbS@6;Z)D0@JtY_^(K0sr~#YW<`+~G`Y~ssv;{yMf__~*80dS88~)v)s02UY zQ000;%X}u;JdQ9IjZPn+N{%U1m7_6p#B^XvaMdOHCeWs_>tsL!%sAi&Zb+vY|{_VPH0DQdp$TP>?j;6f6xt^o!RKpa? zs_ss(zP+x5B)p=c^Ve-^TdO^_C9yf)i33(JQC|AtK5dsUW(NUVR$@%TPE+gr(?Rdz z$zuUn2EYzycLGhW z{;(~a9E|MqW{`|-E$UQJT`2YgVz`*EW%{0@dI zJ!J-@Bf;dNCn2OYG$m)4&SCvkz_hiy&kODLOw$sO$Ow0)gT15hhM z+nQH8Q8qBz&!S^dmXn5%ITF;v79rlEYMAe*(rjl@cEcVMq*cT18y!3%rE5(ALBFXc zjp+&P;tZw}qHSpo>Q%oI}tOlw8jgr#AGu!J(p#x@-zAFq3Q3q8E$? zQ>maGt_gb42;Gm-Q*Z(9O??2Va6<(Yjh3fM|1W|%%;zYM<<077Mk-8z)q!e$M7ERTh z1%UdE?pX|jfbfaByL60!CMkOJji!It`9AC%?{}dydo&w6YefUTYq)F{E$q?k+A&t})G-pK zc2jvN=4(nkp>SicJ+KLv7JOWbfX${02U=xk-R|ZO)*3To+PcUfbnRWOX%X$H0|WxM z-qmOd*7;=w5TKHlP3TZ(YADFLIJs9k23Kl_rX(y~_@gexQSF@+nM&3QX7C+J5f7$Kv_=;NDZwles+M+Wl}?Lb(uKztKtmgLCUbQe#z7mB*ke7Y0}3|P-|c8(@9_rxjUc>-rsE7s z^x@TqqgZuwEdYF$R_H=k~7cc7kRoQY?16y0NSZsoHh|RwehKGZ_YX~Nk7ArW)0lxJ z3IiMx$VINU>Y!z+ZQ=*-Mf8&fb$L$fy9wo;V5g#Ittt}oue)r_Kxiu+8x1X}W#q>u zuO6!^S}JOn;Qo(*j=!N_@Hw_O6 zTfWe@zN$~Z^;Io%_;6Q94d;d0w}DMe4!a*BZ?yYMQ33=_by*lKIP*4BG5#qj$Vuar zf^^lTN$u9VcBRlVPsA{7Vg=lkj5o>EoZ&>r5d;Fx^otSfEzFce$k&&5&=U*dqbBES4hl0y9k{WkzUGA-9(Jebj-^bDbWfF5^r z!!!pQTU#<~Y?1&gKj(FdAv+I*gD5v}qKJ#O;~{ zGCkVb866HS9O#N?%!OFC=&w@tIPL_Ue*TlU`ZSa$A%`~EQ?T*~r8-zxdl|k&e?Q?` zxEY@G0iZ+`ZEnD8*f<*W`UH{gVmcE6TmC&Irv&o!6+R+imW+W`G`YW!S`O@8U{8eN z_I&B}!{hw}_+a9IH*|Y_<~?tNCiKebz21ztcyt)(e?HcqV^(19InBf~=QpvHwh0(U zt@1b4j}S#oDku4HONI^V?)#0#?wq zrJHqa9x%vKr(KZrf}_0uMuZySSJxqQB5PyDyQbCh1+HHr5ldhYume!u=h!GS8HX%V;B7&|a<-l$8gd{t_&4On2aDVz9ewz zfyw56(r7yATFi-xI-_c^FR3|U!PVoLpdeW*m-H+Bd@BVHPF?YW>o9s=wz;1Ije(%!IPzr-@GlZ37&%smz8u& zKEq%w^LlcXf*%&69AyfO2evx?$FLEu$AMMNkN4)Fq^ z(Vq)-Zi644NE+}JQP+v=0JeQu6z!}sJ2)CYltw~8+daWCw0^-p?Vw~Eh>rGr$_qx` z5^Q0sqk(>wXFE93Sh9FGo>VwCJ~g_%1F+0+?hkyiFlctNa+ka+e6+(%=7qsy^QJ`E zXPggEO9KQ70000808LfPQX74Srt$*-0I&xD05$*#0B3J+XKZD3Wpi{ba%F5~VRL0I zF)lGNE-)`=Z*OO8Wprh8bT4yqV=rfPWpi|2ZDDC{E@NX=R0RM5f}q1-rBz{T<2Vrg zo?kI!xuY$nS$a^8?s4GQN+NJzI0&w-v;xN}ww!Lc-T!_wO1epVyWEG%2S?G2 z-n{o_tV|{l*{7GzJUlwM`uOoWfVs5~jRxLUm!ru9!lnTq?xEAY?smGSeF_O(o8EQi zesIRNP_{J;y#~`lZ-=hZe&^n_W%mLb+im**o{f71+xc%hI6~Rl+H6c!5=H=Jr{PI= zTjQLr;ioN1X?Js=MxTp!1beWXS7w#1HEf68 zp(s}(W5O=)?T$hRKM1F_&QvZCM9G7_%cs8;$Z<1 zriwEe08gW&h05KrV6oDjs$rWa*EbyiOeG;-6ESZQF_%odHgsYV=IpZp&a|9_C?GFHo=FCzFXl2zLcV12C33*Jz;0QpKrX^0c`KK2vb&TC(r_vlrVN>e z(}YnuuQuj_MT%ssy;FE-QP-sz+qP}nwv!Xvwr$(CZJ*e-d1Bj1r>dU%yT9t2?&{tb z`*K~5HP)PSyc72iVrDo=lE1(43{kArV@N@{LUkZ;wXq*cdYEANpb3X~jM>i>92+GS zh!&Dtvk01UMLQKrkVoq9j_ddkZCv^%h$LB$Lx^#%3{K@-nm7sz9J4(yEy)Yoy$T~? zr1l*R?`ZCBf$$j1&|*EHjyxB=Rv_Q%&U026`jl+kP z=>E$3TiN{TJYP@4idhiF0&DDDCY0oqf88#5I63^$ZP(e8dGjoUQ}2k?!oH312D4`J zwlJ!|le(+DLjb?4my&x~v#k>wn(*d==*7eAR}2XMlV8grz{&-t{F-MBj~~s!32!fW zDbFV})?C61SFHCB;Qy2pfd4Khzq;~YAJzX;Ir(o&LjPY9@;?v!ANu5qI#_%JS5>A~7p3o{^DPe#X+`m<-3=7=~qE~RixeA#6_3|Yu`V2#Ql!keLh z4~}m>5eQmW=tBqOL#~9+e8HrHsxO&WU!556GB1 zx>La~4ELZzmCeZ?;yvOpT#QkJbAr^YZWjPV#Ar?lybG>5QV0eKzstyn zs~Ds>8Uxl)67g2s-ByMqbLNpjCowOr1Y8_OST6?*?W9(?QbykUSvn$-6;LoPn9N=d zdm$a}pGU;AIH`L@3JNv!>cH84{Tfeof?H zO81YMAb>W;cry@iz^jCxS_!fxa&kB0b%TNJKS^NpUhvX{-|p?p5A7VBk1E*ZS3fma zyRit3;0nUy!Br3SxUzC&GO?6rZ>}Y^+3-CF^3ON?3+FhMu(G^QtX~))ihEdsC&}947ZU&j zrdao|)&UMo@0bAi;yfDqOo0l{F?CmCaklaso&2(2Qx4C{yeoENeYh#-XF)YLQckLT zRftv2aktIc#Y zJx*VzCeAwAFzAf_Md)AS+A-Ps>A!r@rn!HE`+O93H7|*9H>ijBlK~Dne-fBv=phl+oS?OD^J$=*8sCn-F7v-N;0%o##s(c}gvAuqNq z@XCOU+%kN5fq42&qxf|=L&k?{-A9;J)X-=aI;FBoP|mMHu-89ex~Xsf*7~?Xl0xuX zfj=AK@!gxuPpBcLs`OCgauYGc`}|hbDR*W*^4N;CFS`lQpCsWrKV59j9un;#w2+j)N%9Cx(i_QGIfc2XVW=Jm%RnKSz!p6} zbYV1u9l)hgWz)ml1P=Z|T_HIB^A`m#zvdpPpJCH zN#+_#@wsk0e^s3*IKd{t2l(TY{IdVJ(MR)UZ+G~nDovAx5G#-wvY;s%E-8(GxES?Ns^fK|ASaYufGL(5<|J&VVFg8< zy47UaLS|mJ#TRO$Cbf&*ToZ*%jW31D0=(7RQ0B;6QSL4Cc&}Vj2dv$miqA9JyiinH z^zTwcIc7^X>E|2|sEFU$^U>fRV8v;uUU9(bNH$XF{p)ooT=M6|F}CM^yj!I!E}Tfq zM~Qv@0Uvuca(2q;g+~^3e6F2Jpi85L$5(d@lUhF{9_Jw2VMbDM-J}+sMn-53PMt-0 z9Vd~Rwnl-fk+6fST~WI``Ma@6jfa>6)-O=6Wpl`dQY&hYd!rvl2ZRM_oWpUCZjB&c zqwX4F`!+L%18{?Iy_ZCf1>v$gsvClZSFEQq&XV#OTmGf=y-vnwU$3p0xoPmNP2PNY z??dkCO;KAo(;E2)nq+P6a(m_6Q3Ako8YdsjKv!oiigq$R=&*Wl9?!$`JKSb=k2w&L zjt4;t{af1NaYj}sM>yzlN^%4s$LY+5x~Uyo*t>2#5$dw@ap^O~WlRC$ys17H>0=&B z1LYT1$t7l*ubiPgD|0K+PV|9rFBDb^N!tQbKKl1Y1YC@iD?#ngctV2k{BQ7^$Cyq7 zzD$zB-^VwY1Rp0gGWM})6q%S<(SE#KA~^vakuqPUjV=kUQQ9Ea70K5de0tY>UF<5U zB=C@$H0s@zhIr##%X`Je%TLa%_?;BC4lTyYV5CTKFO8j{&*qNqcu9!HCAg+$L+?K&ju) zaNX=)osk@%(k=nIOoR#Qmr?Upx42ggYpGTva-+%2mI*v(qVd0fX$Kg`%s67B6$RxG zestZk12oDI#rL^tz^^n)e;+O0`A+8FNT(a`=`|CJ$NVeE=WTjgN#B@ra&wE!JX+kQ zcM3NZ!NVu1v#pTk&cZrh-@Y2+gbt0Ec1}pTV=6IH0kc5e3+O@y43Edm_5moW>Db1w zvl^BYP>CE8qtk00r^nb&R*!b9aU63qOJ9atpc5Y35wWuq<~1egp+G$P=UHnq*NhGuM1b0B=9B2 zgE+$>q!^38?ULkQM<+{*et3%xx;uG^`ACxR=%u=)uA&sxNRZgkKU5dDu={jeP%(}~ zi@gJ6RCZ4IIUTdJt=|`Sp@k(PJ=BtXAd~MDx{tGWn#}Al6GlOELpA?3&3Tb`;&_Ed z_dGe3+z^WRv_&h1yDYyEZ?O1e%YBbrZbhed;*{TMQti=JQloT`ruWrr(;tMH3tgqL z+HX;`A^1CNLS2{0*01MV%NzG5=1a{Xch*^sb*)9dzxL~A@Y?S`4eg#G zoG}h006+*10D$8ED?|H#KEP=W9Zd|ZXzgriO${upT^vnlU2H9!|C^1bv-kKfv)iMt z#&T9$xNE5X_(ojaUuIRa;Ao3KOh4W=;WX9PY;4{})}d^P zCvhN>95)(Ek;GjkO2jgwd)y){jnfh9oCQ*^kwv8e;-F%z8O4C6c_K05AG z8>wyyDlCxv;OH`U>Iy!8qXH#LM?(bGJ4JNeWM09yN-dDkDa9bbf8({QQu}yQ~51Eqd62Eug6Pux0l@ZHgMiWhY-fg z{i`{r>dgi-Zo2AhOuCiayLd)#wBxn}qt4oTTm#-{Ftn-uULzRZNoTDAELZTuT-I(Y z$aDnZ&7hcoCw-6f({)~d#dSi$8*TnJ&YLEqfpGxi*wEt{+8tjDrmIEiZ1Oq?5aB^+m+iz&R{MzA>EUDcxmqErtDmbFiwqQ=BS8*f0N8$GFbj*g z+{eIx;JDYXD^E0bml+2$tzJ{@R$OsvtImHT1Fo1Xj8;h~cn6u+IHUcUW%?ej)>_he ztxhvynejYQd98`o<@LciU}>%yr=R12jx!l;PBLJS(X+!+-8aZLOu!+f}vmLJv?3 zvIVI~(=eM4k{Kcih(5lY6KxD>&NL82DcyZjNt!W0E^0WBA;1O52p3tReziZytUlP` zF20u8!GHA{z{cC1_G_h=r;A8;gCdltg%1Z9S8V4ZTjvSBQ$0(^H&LX!1>dR@kV&>r z9S+7>-&2`t@DNf6qLfx`OhO&Jmi8tY&v3$IZtTEz=M0mO+>&7dN-pp~qFK2R-c_hd zm>+LMDBF-B2kJr+ubxL}(wzQKL_2kN3U`z*4-6}jD!A$J9WmbX$L~t4zShUOVD+IX z8FYLjvlV>(i^Qh6s7Kh{3ir%jv8V-igm08sPi4eId%taS_u1`nyIGUR7yHY7xCk)^C9Au6KPp1^aL6k@ z$J%|}W9NI3S*>=>7r2cXt&cLtS-W;`L8`mtRt9$WEFS6x58vgo){#WH-1#Of*O*L1 z#227uK0<-X}T*r3)lKf10ppE=3E&PVJNV~fJw<`FX`RB#IgrFMN% zx5RG-sjCwa|IU4fXMV>UO{5Tw04zudrWnQY!DPp}D@@B>?eaVIS<2!CD2rU-a@H-% zeOg)`Mz+$w+SnvFzvQR!)=^|t`xhs>=d^>JMD5MlNPSk>g*W># zRx<KZd*%y{2QPRLBUekjq2!O6<03e;#J+1kM%gOB8ixJ#c5OI!OFsZ-&Wlq1m(W zB1sW|wYrDy=^ehtgHpQhR^CR}zvG*=cE{LJ()gQ66-}MhH#0VEvrp3|I@wV{vJ-e4 z=beXD?vCr6+u?p`Wp{p+g2`l29y$6QL!_O8!l;dI)Wzz_X(@F`dEub>pTm4T;$%vE z=N)OQ0(O^1Vo#SGJ?fE*VWlUW)=O`24z;rmR%>07#@?TiO-??cl&4vzhsvq~0=6yH z^0dlS`Dj$NJ8yMR><-PXtz&59(`0c8rLK&FXLb-*zp(SaTMx@<6+Y^3z*79Z*gxk$Z~hmviSCsrhuV1pg)t)}kn>@F3Z+>$ zGsWwb+WmFk_^9vL?Y#4Mc}348qvTi7yNGudvHUtRo2#KN8Xk|N24C;)9=PjOS%%ct z_{OzN1y1?!+|R%1$8}X+a%x$%3!^V`*ZqnmT>3OjTRX*OFefR5i*Eqg>Ep>iwgtbW zyx!dOi#T##ZTe8E7Q-#{Gbe3U*f8Y&JiX6}6ZFo4p{L|)jgA=D2i3LF-dUCQUBjQU z^XFNTJ$I<*M0-u1BXJ<({+F|;q8lf(%a166XrDane?8IB+$GZu^wM z007Ei005N!fA?g1|Ir{(+qB&jL-1MsBcn`^0=zD#l@Bke=wGO|P>53DNJ;IBMBzwE zE93yGdx>H5(_@yJTth|~S?FP3o|D6DcJ1XQ-OJ0XYU*cx8rEj#hc!R7;Zq=)x<0-4 zoZ4MTKwew1&{B)%Jaa-5>0*0c%CyWw#ls7|X`aom3LdSlGPays$ja5;JqAvJRefSj1Tj`)$6565_*hl*^=b9GYUO z<|xtWv8sINXU9jZp0u5lVZyfRY<&SH$4ZI8?AqA^Pji0Q&rxC{Q!0*-l?mm~I8t)N z^b?InV=8JH+u8YMM#SKbn8u9gp4CS1G8F=td-mHPiC*%`*sSI~Z=NapAwk7m z6#GL)d!E+U6)ZRgkjAIYfo^%&jM*&{muaDcg6RHtOdC!{*)2B(H@n6%-M6sj_&oqQ z)j8u(#i_!7VxBFt^E4mE$zB9?0S;)y;ja9u*5lv78Fkco(oB18zFGSoRc(1=RZZtL zul|!U9cqPnW_6D`LT{RbGda1T(4iLu=-d1~Uuu(w&;vz!xOxJ*oIMs<15RBcg&NGm zgtCI~k+H73{J|g-nv^0+k~R%6Bo9V-4?}{`@9ev8edd@w8!D8(_H7O1zWcs^ok9-3A_JEr^DM@r8OfsU_Ka(P2`>2k+V!?e&LC-_OTu|#L zwXPy4yUZ-3gC<5I7ae^bQ~NH84;(m9^AAarRtypPT%)?5B??nOoX7?AuR=otRux02 ziR7qy@iQD$K&F3Y+~ly@JDg>IbZ3aubP|>C$=nj(US1U8rJj!t2To=`PIqCzqMNB; z!D>h1`-8dKoC0@umz!&x-|se3SG$%_Xg%SGwevQ|5AkX#q#3o&R$F$2t7x%2 zdCYV9+Ji4_Q5dn*M6`^Y85f4tGf0IlTQ`;9UQuqVEQMt-+H?S-b^HswjEIlF&?mm1f)JG2~|2t}s%Mk+pupY30*0 z;xk%Ok3p|tds|IZn>WI7gT^ac}y&l~+ z+ujdYZxfbQufu}bGUO>)=k9{*Kj>GDmVt(Hr9nBSE1;S1$G+BSWwdjxSOWFN>gvq~>QF9*!%yxQUAA6rC@|n*u>d62AwvtO3_L-peVJ)&w zSaUj!{pqehs3%(=q-c*l+kgd)s`aL#?`7EFSd~p&UIjIrZIt!9_J({&E-k|*gZ(8< zSkj_ST8D6e;z-QQ2iwsLZoWcC4^ykXY+xBSIoTEjn4TkBiiXXAMN6(nwU3xNa zJ?J%CYblOYEgqdCL5QIp=0{rAnFiUn`7~Bd%M~?VZwZ78LvCLuNZ($vc-ZJ&r7PP7 z;DmiDB-ZPvWV_^gw8hHzi;_3joq$D7g?k(BsHW>yi8VKFyO7O|35ti${-*ARzw4h^ zYE>QFkh7$ed|9F2{r%*~@bpKe~g8Cgx8|c9*xy$gV1fu=f9F^Er@RT(7LWd zx8?8Lq?k5$trV0xgl&Q~hD5ARvUlkJyvsr~FANQS>kF{tza6>%-Mh@lz}d*0*2LY& z#NOG$&enD&oVEa^iLK^CcV=0 z*XHiu258C?Mzh%TW=!V8^p57z^hs3t>(}NQ_zrKZ3YLhG3zo#d5W|U;$R-H}($(?c z3;BE+88&OOq!P=<4+g%VKpH4U)oYRhbt8!F>|AB2xJc`2qjVMDbPz{ZnUHb5Nvg`ua~&5`<(e zj+CUQ#3+_6unXz~f`-I;lk|HMD5I8#b~qF?hhFQxnR>psM-3#}0a9`qlMRRtt;L-< zrIH$?42BGf)9rdj@`XNt@%HosWw}p)*b*7eNgUu~SwMs#BW4dhIf7(1Oa!zHtH z;61Tdo>P}@w-&o@IS&c^_Pi1mS$H!mPl@Y)O`hWlti15B+ow9Po^is1yjL$jVy{>; z7TY|FVi*6KGllDa1;AtSo=n^|%;U4P9E^gm=TFvJuXYaQ9d|4`eQMP-T)g@$tl+lC z8#NZ3y~nbiXV78CZteFqVPdX2@Kl*`{c$aW1(}<;wCcKHzFD|@s%#aS+AFo|G8R}@ zakT|5^Vn&U%wTIdY;QeElIfBd9r%Tq}?r~1i+XabnBvx;%PrN^i&UVy)q{?0ZCpsOvKSK^2yEpgGR|;M-qu zu0&g4M;TijKfwDo`{y3%0S$MpuAp-hH?P3?G|HTV`&cZOK%Tr9i*i z!0C-a`AbVE1ch+s;^~)payJgHxn$sMsL;kyHD=Cgqg8~GIi*)l$2_oF&3jnkT$G21 zCz*v7bNTa!3Gd7W22kPB>+adffL-q1w>hT{-(Jv|pn{cBtd%FKI1cpez6(RLw_nIsBkF zPUP@y7zIr5V|9h}0Q{iHnO<4%TX!II6Qzws%bhE%{^}!0G(-?5e5zO8$1r91DhZkBnMYWz`LQsBvDZ6Osj z)uGE~)U*J`lV8X;=&M%(UQ(|A?!CR*_k!3VIt|2p8=r_vh+F3}F`EZA8TFf&C0}wt znyP2w{N2ToqVR>KAaSl20O=UNSCj%b$|dD-_^;>bjYo#d{X2xJCF1W);ed>b@ED3- z5}mvhd8;E-P%8<988a4hIK{XG-Mp)2M7A9;RSV&?kx{}{VU_+YMlngFaYTFkkZu48j)zX!RazM(rS6y z_H}q-SA?qz5#)yxE#b+(y*K+7Ayg$9Q#_@|9dOw^uI}o;Ik2kWtK)|){d@YjOtxQug77b%g6x=B_Gkz7c3)8P9>7v%!0h zj{?9ofiu83l|<{CVFq{rFNU}jBcPRec1l3GP!g28dDwqqTP{JPXG^xF`F^DF{9tP< z@7}YtDvo^+M7sXHV))C+KfK)(^{r1w-~-RwCVNx!(5odl@_m&GIi7lrZK{p$s^ace zP@oOHxgXsYEoJM)Z{iy>(8~CpBs{h=-D6LVa+7Lt4)V$LrWkY!Pv9cjrsNjMeudiq z*=_HRb7DT^Qy+56_jO9(z07NKnlyTTD!E;-2niZxv?K9_I*?5Xs3Tfrwxf~~5H|#b z8~g_);Y0&y(I2+nqJsHAzOw9=8hLG`@nlofE0Ry;gB(HGd(@^u*xRXmR7ghnWmb5p zPL-iK=GB^5wc;6Ky+|~+5Zw0kU3>UqomM^PhP-^Sxj=h?ZkpY~=jDC3KK7Koh`UOo zJ!;Y9Xu+DI4M{vr*WaS-hQOR-mC$2Dt#f|BI7UbR;8rxMJv=A>##Oqco7bsJXXCMO z&+nQAw{v~j08`_Kp1^B+v>N@`%hbiZRKPzME7)q(?f7rYA)CTy84ctSKPJ#WCx?+3 z;xxwu0YhX`{QB>J=3((O|9_ggrsj>x(ccNp0RjL3x&L2H-G3A(dNge84kVDiXX+>z zJ5e)8ja_f}7>kl{79mq{vL2)x6Xb+OYy(|JVmhz7%~?M->nd&fNV-V~HBdkguPZ%s zE6*J}J}zNo8r&1lwyXVj|9(B!K&J_9nc!6OT(`{3^o=pi4MLIp(cXCozFv$UO;SN+ z%1IWbatyx*ks2nP7K~6D(caA{_8`gAr~0SuvQJ2BN>KcbW+JG0Oe9%mfs+tRCz3cA zIO(B@!V?gJ@?sH)K1@S(i!aWrL58>R31^r48mHRK#Yg9aJq zQ2|AwDiWUVERO6TFWkZ}Ax{^{a;$?RhiY6N?aV@ZGR~}S&Nx%(JY!9;u;Qfvi+;MxJgzflor{e*(F4luQL-LI(wx;>G}rJQS`0 zp^QVoyMZqy69q1n%he=6>n`IF;z&uFT^v18wWU;PDsa$0ci-J6#%Q=)c(qW?2 zU&H2M01B7UWzXAVX<+OgU=rH8-%s%lqGs1=M9K2k<>teDwyq`^|bhu?|EZ2mqj>imK*wV{19|5s&ok-+2Bm-SHPY)xBxnt9&cG2_` z%mEK>ps$UYHrC*@#*IP3{J4f{AfEQR-+`|#h{4eAydB`$HQQ}9Y5eV0ucOCJ_m~03 z%m5^uB~E+FksYvlQebC+t|`~YLyrTRdXcR^Wj7}rz9euK@Z55Na6;vlezBcsc^?)l zhHe`QbK~_-_lh-WYrp7aDxVWpwvd^%fmP3bt;9x$Y1EjdpH!4RbykkSJyjl=#s-HO zXgV~L8x*$T%wEU3)aj2ndNniy*ecq7-H8$3t6C1Rvu|CCHoEq{;oy6-_LOtb z3f*jJkEco+inh-pOHm`~FmU?cZ>g#kGhw9xe52mEql&Id`F1Y!b^*mpyg&CW!zDZ( zh2w4;asiq0cMb@%a;pnv&TVb(Le6>%JTp=>yZkB%#f9u2>;O>QwJ`ykIMWN`j;}zB zccaax*(|EfHxf4)-@92Y79duC`abn}SUwpOUV*4%)RmF%@)b-jpwY^m-@W-h293FF zK1*o&@Rz0v-|S)L@N%eICK2Ic0%mlXCZAq{&9a=e~B1l zEs2`danaZ((_4PPG(S0U=K%WAX8nDJ#G5o#-b7=%fb8mc?S?=nxkK{VQEzt@J#+cpWOH4zB_3)7{eEOG>d#_5#$J;7A`kINs7|}2j;f*)nx{IG z6VmNk^!EDNo7wrNUYT&!-}Zb&m0#gRkp@(IagYV=0hH}-X;0p~dx|vfK!aucd^P=j z8lu9$sb@*d?VzP0w^tAGaWKJFcC_G-5tv)j`rk+?x4w}zCe9_}$jOwe-AK+6RYl(A ztN!_mNe23>5aY2D)Vjq7DBm)1#_8zyx!@|Fpd0XUzm-~BYoM&Bt_=5;U-`48!$Mil z>Mx$fyP~0|fFQOJhC5nU$T{Z)>Pv=@E3Jf>gY+d!R-t&rpO za1^lp^|ns zm!@4D)sqPW;`k!ko|pd5magW`3NlWj&jrw?VUMEdPHQt93r)?7YU(T{4ZVk-qs=;2 zrJ2>~7vrX?Ib5i5U<{NKTr(I#Ijwr`!MqgR)Q{pEkWnD>;Z`wvk4x$I4UoH49c{jBXA_O5Q6 zn0hPrl9GBWKDXB!_KOdd{M<@?En|3I4SRUmRUBd?p4m@EHcrcae@loR^Y#m7M)s|aDJ1D-817ygSQf0K3k`iz2axu>Y9 zX0_W3E8#&`E zm<#=Y|EG5_SKuGB`E71MBLe^k{cn2*J8L_~|63KPMBTG*pQuWp> zej`ud?=#ifncRBS_Xg0iZ58e8q~D)Bne}_pr#PZQ?t5sDQ=^^~&_YEKiZ~D?@wqyV zAW=0*psQp`;S})zNQxOPbq!{kH!sDTcL>Apdp%Yd3V~Uwx zJ3Lkk1CpttzTrfA`lCH5uNoMD6&w*=)iO3|zFIB61|E?Lw4z8E$uhB&>#$A1Qs{@> zhnG&QbR}KzU`|_Jnrd5r+9TVPmnu~>aiQO+knRQzEm$ZBfFzQ;S4rTbk87m?RURRD zM5;~z1)pl($B+p{ns!7?S*nO!9uqDpbDEks29>C&3oTXA>Fo?>+X3I}g}kMK2kf2e zejN?J22guqZmi#x)G->?2DsH(1o+@xpAA^c6);*?7I5)~aWrs0|00w{V+MDb7cuIM zuMPj|&UAnQcj%RhY=8XX&;4x9wKr1_jsb+j-iJZVcMNC?vz06Nxq-Najln$IJFHh@ z#dpxJZPvXXAiQp?9VdoDmWpog#ns4@F4Gfn!AxKee7#8=6}O%rhpMlp&wLEBx2st+ zPpAfSxWhR`3}91kKV2_(;W|sj!L3*nJP0gaa)GE@g?8*@10kb# z!t=IwnY3RcHf1tKmER_Ca+})?MoW+sY#4!t!HRp2;bbLjmvFdkndw+#zgPgTRwzQH zyHo}!chxglE=?DNdv(_I+4W&faiH#6ixa+fC&ZM_^xA~qV2=zB55tUFW*qpRBe!Pk z3hW^wPZlCLWY{=7N@3;Wxbf~pd7hT=of&29_dPSl8Wdl|(A*j;b(N_`7zlj<$HmHE zg1roKCr5jo45HdzUKkyoLrrzFzz({K*P=6-q0J}^wR6Fw;|F`LTUWCaTS=61waUqt z-lcoGJW-kWQAhy|=89;i%o8Cem3QByQ^zDd>zrexZ46&xg(ifPz7`t44bo6?xyy&b zE6xXnQB;Y%Q~~*>*Do4s>r+a3-!B%R|=Qfj!+;4O3WgLxZF9ib@Pjb=K z9AehlBm;%xMCYI}{p=*)0`H$qo1Ov$M6_X;Ug4?3as3qL+X^rB zR^vvou9T}&79W4WPe*w+SnBHfs{FxEfy6IpN}B_ey5GVOPEez<&Ev`XX2JJ zp0xd4X-pcY8N~R$OjR_FLMBzwk)icaWOq0@xw3ZoUNlY$^RZu@1fVd&mr5VWbUByW z<2Y5UNnf9~6!vb`<`tNxF5bYkdlfz zV#hhOiP~F{b6B9kv00G2^03|ed3T~Xn<^lgYMW~_8-E-C0=Ns*@~A1aJ$Y~ZltB?? z6dxOTil99Cq@!$KZpJ*&woz2ly*`|z4L5Ha!o@6pIDf9~Q=h%w_3Y4iv4t%@0olWx z7xs3!)8qJ+fn0sv$9;STGpa*nIpoEJ``Tk!ltO-@jqr}_74S=%fi3a+#GU3@NpCy8 zqlL|`K27s*ZCW%Onots{+B(vv_&1y&u2F&FLoEKJ`*i~KwcTE_tSsT~#5M`Edq0zT z%=s|u1TnMu?Ik=1X|u)s3xJi^;zR89?isv!;P!TP;}T@He;thPB^glglMdeJl6qiZ zsW_|KX&y1ZaE|$3TlQEj_X-Oj0085^tq$S;@3-22JcCPAW$g~x5PClTz$oRn0M{gK zD<{xGjUgE!+mrk$OvE}BO)$?Yr@lT{G?%KMIml-7NFvf1T<9&M!M&#qp zYT4ym|{iEj=tMJ^ZhOL?sj3{71f>XRsePRp?UZkfI1KmcA z`zoV3d~#$4GV-g+G*D2D;CYOI#cPYB;%VK(b>IpG6F(O%T3~%8Xf3W>cr21u$XW{ z^UtBn#7SEvb)wb={y%T(Z4U#2Tp~V z=Y$sCY&JBVzXMIh@BIWUW33}Pk|lvE&l{4b%l%Bh`9(EC>p1}qUHB^YYl&fI6|}XW z>hjv#+`>R+6-668tra-LIhTe#&VOe;?oiBN?Ybss#BmxhO{`d$B4?I4cW**{L^>lh zlY}ycTe2b}W+4(y+4{8uIP`iRTItmRU%eCRxx$%%e(JQG2L(YiG9YFi06YYy(IXy=PLYNm1A2y` zA+zY;vPlt(fGGia@3LhXJb220x41_m1=>R5auR=&jGfo?lbpBfpuX@1pJNd}_IMYB zC&F*;Z-vA8-_9)O(B|aW)@YVpHIy$b<$aPD=CzlPcT4*~ZS};sEvivhK3n6y80P0k zz0=s1w+8R}R(M?OpnI`gO~byun#`BjnYtWN+(Ai~#O2c+!2I6zIabbd!0_b(e_aP8 z7o^iSeXDU(QZSa`D{C_0M!)G-mZjv~{^nlk*ig1&|8Q^Xw3djJ1*1nx{N8B6$AwYWZUyfuX3RwxQOx46aWk?|!FRY!<>Mrs zP-6=^#~=F%J6Vu7N(9-9(2ad22RAwDY$T*veBwl>5UenP?pa@D_K_qROwpK)>|Bf#tmeb<+PkvCd$8y`||KZFafPhy6a-dIr~=} z1}Ko47V-`+>a3B;Kv#41oUCyqhoQBtM(&N|sMRc$cH|DOO?S?|+3f|3{{hstkPVj1~Z(xElaK{C`(FjZF-k&Hww0 z;D0;|{x2c$E1wUy&DO-*n{R6S<)(_uv3p{R7cK5-Jke6zoEB0&-puD_UY=%=@hyeo z)VMWUyBE7%4*-(BG!yb3FR#BY${J(={rU{);0zczIN`qS9^u`~Hbk-T@PE(3qZqW` zYB4|_u4noKPTzX-R~y2&)?)ZNpuJ=3My>~*&P4`l^@)yRqo zv8VwZHe4ycQqoD#8A28}evHLR$cN4(kPM0)vR?$u_?1-9QW4SrK30xYbmGWFTh@k%OlCb6ahc#00vr^8ySvk5z(o7{94#Y< z>rc)MSl0vTegIH_rM%@nV$FE44YO0+E9RfXfnuI>=FUT5FK9gY#2yirydHMT zk8=6cEU`)yAT~e?SX#)GKYZ*A^E7(Sys&?Q*@?VZGuQC_gT(R4ZdE8`c47 z{`jBAjb2am(BI9cBuxocrQ~%vT>g@suVKo7W^!#Nvbmk+{NQ0lXAPvZh0lIT*S3yl zLlLN=g6_v74`ZA8v9`60(A^-67}e~)!sCMR`x}3sK1GG+t-w{D=Oh=#?!wOA!79pP z5~>M(7jr8nZsV6%YA%8z(ezt~8rr*H=fT?FD2MACkJ|& zNyWInzIEnBWN1RhPH5vL=-sA^7V~mL-wer{(<|R#vv(`l`PL!==2sl5 zn7ge2$)4KPpyP4zRSj*6mo&RJJFYf-G5o~(V26A_co#?!e0DB`a}3Sy-f2GCjYpcWI#OPtajY6fW% ztkFQfQD2Tv+7TP@wVj&8J=Ebu(1iXK#h2uU1W4NK4Ah?wZR0QOVBG1-j^~5cy#ZQ* zI!FIR%m9liz+Ns$RXVRa!7CDp#DHyz!5;&SS_a6~(~w$rg4cfLOm4vNUXOODZap2a zA_^pcL-Eu8(uBvKz81-dVwm#_7Jt5JyBzF1pPjmXsc@id5(>I;=$UO%$Kq5A2D3jr zu-+KRV9hYX_+giT6x~CL)1PufI4a)UZLR)<=84Ry;(fS(PcGRZ3~#BcIOSQVtN-jR zqbW}oy%&<|nhx(-5=YZ5$4? z6WIp5m_bO7ie0E}&poiyrY$MMa%x^ypl{VwLEPNS(6d8}2`CmKFm}0`v@PN=LAIy?Pw;=NMB5U2Ruw4;3fj zbb(vV4=Z^$C;kES4lX{EvmO9okr;WJcV_6^+$D$$*@D|J`8;(c8c!MZb$UpYZcsc_ z=;kBf^co@V4d?M?1_^8=M;Uu=R=o6UNr9U{`NZE*}YwpiT-rNQ<|9_nB?w(<;Sl z$2rmi()c()zMIP2xcsrjrvlE?M*WS|6WC+`L+hqRkD0m+Lq zSL1H_l-4_PldijF?_Pj>4DRwiH`>B)Z#d=n6nt z9FJPfPUbYat_j#fk!Jqup^n83VRRBWlnamHA*1YqJN}yl&5@a=`FIPjR&{`icJ6pd zsQizFmul1O_T7ziL2R>}XO7eIfW}4;2(8Qzh)#f2&=cQ19Y7@F{e&ySU(wPo%}G&G zRS#GS#+P_i!5I_hL8z%9=f?S?lDd~Ku{Zu;gl;+doB~}3Vceg_!Vj2_Bvpu!%iZ2r z$vth8GOq#znL(kS(Dt>i>xTpX*y)%JHx4_B70b+bB+HeNAifpjuyenNruzc%3;w=( zTf{K9e&O=NIVA03E6q^`s{aff_l!?WvcWKi$b&L}v#4Xx9Az3$HHD{|=Ig7Yigv81 z*DhAC@Cyfvk|l+Q3Bi);<6FI%{&?eMlZ)F@(GjQcTu$eZg33`zcmLU*{L)P$+#wAm z@Zv2XU#OtFU!KdVpcUgl+ScctabLZgB{}W2B4admdx;!lZYd@UhK_u7_$38b&wse7 z=34TLp`)i3t0hWaeiIdjb!D(5#$ED2RFB)^&w7HOB7Udzvd@s^)sW>BlC^77Dr7xV z<;7iz(Ac=|x&;7A4ymn|<@67k6p(m5V1n`>oWSv>yWJ?VwA)G_*3@fz=hG6Iv$BbZ z{=*01YmOSi2(>7SwYS;>927oJy0G~hP?f|-&=4OcU>yy0>y^xNy%!Q4ZY$*+*iITd zAC#@W-l)m_L_xBarDiHjCes^%CH4%hf;ZTqNOBA+(enKFR92ksl52cfNUU%gw}NN^ z<#}Ma*wtLk^h#C)D}9v&r$uqu|0Ah=Y@{3`FXq*=t6gjj5t)ilk<^)AbSqBHI-lhk zua>jOH@+7k&E;;#6H4eVC0$E0`%#D<{0PAjfiuYPJ-<4j|H`J}M8D_Q%A-r_Y(gqX zRsfe9%V>cp4uL%p8Q|yOVbfJWOaVnMr{>_I02P5nCa4aXHKBil(94L{eq)j{OZ0dj z+l;ST?>tnnr!y~_-M;?@%r<@$VV$>zj6f{@3Nn}>{{9GqU++L=&+RZ2d*r6moi$qn z`Kyz^b($C5+V_YK?bayc^Cqh&^^MNqqi=ex|AP|Zw2R>peJ4LyP2A__>0nK@i-tQ? z)y;YJBDb`{sJeCEiDQ~Gom~h(2g4Box27#x8@$7rqYLB-I;YfgFq=$o31;E*A4Kfg zmn8VFDoWrj_D`)w&_=6PN%g8&iCuVsBF%zbcJS7`I~`jXn-fg_llG>Q+B6>f1U!{q z0)D&nsbSLr(*&EZ2v*r2T!}El7@$#LBL(ch`K&1*N=T#$zP%2>*1N-3%^W+2VCh$t zy$`|c{28hYQn^cV za;KhkjG9Ff>qKOsXdD%3z%EcD;e1azbgTk6T&nk(WR75ZLjzr~&E>v@mYrQ%dE7EP zZBhN=kXD=pEiT8P!`p!~f{B>?ER8}V=@XoN83ZV1F*9Dq*R%AV=+;(gJm-l!ldqBq zrJjc5I<3n)YWLZkQr%oEs(TfH;nw0o^xM8xZ-6<^fsTF_)aQNJky|}abKx7US9?cc zcdWRfgtvz%Zv=UmkoQtwv`iCt{@k-dBPf>i?# zzQxh0PwVXa)cLKXymlj_SE$rSvdDJyb}*3?&{!}qk87iE0dUvqp+Bj`K$liG2@#s@ zy>An-cogHra_ZFk%n599Dz0skjgj(jaJRR&omB)kVGEZ6BLVpDyEESgHy{Nf@OH^9 z_Tc@A;0!+F6<>1odr!F*J0t2J?Vce7F`ULx8cXT5>FZIrofG5^kY@trLz{1u=p0N? z{awqV6)M$=rPbLCWVW%ift}CO1(n-ok47=K5!CG&Hcn0pPOa+EF^eoEohvfBCgyRH zOq?obU-UA4L;N{@zZT4DSVA1o;OMXWM(;VA>UhPrgGTG{3Oq#!gwz?FkYpq-XNb5a z_lVQ2XH<_~oZ3p~r1)(te@KHAx^4zMiICc9^QWI?X4-&zG^xH{D^m?CTURY;9 zUa@2hPYkl)oQO`~bh zTR>C6aO_e)p5o)n8LlJU=MF*utFjZis@YOMTub+G>|J|U>t7O^_k^sC+>!lu!j0vLW?o#k)w|8{RtG3Q{m_-rHA zHFA0JJmMqx=xog(3UizVG4XU$Nqiul=@_*XSRzUM@nLYm-aNhE+s3M8vg!-er`M-K z-4mGkDUQ3R8kZEi!JU>sA2>~`QK=U78;h-GfJNJEy?=TyqX$H7U5LT^9vzq=c7Q7D zj!gmW-N!sQS{fVz_wb0qAQ7Q>ATJL|E$L$b*pII*#5p)Q5f)ZXZCapUGLdMyjJFcHVGng%)=uQ?kF z?K!eJT303nbg?P2Y{RIU&^@H4*Ei+*ha8$oT8;meepp9J2t5VVb1W zii!$J2_K-q?tB=-0n|$Tnv=~SMWG&bM=VW_I;Kw{r7-5Uw$6?Q1%_*$!lYEYs1+h0 z*8Ya#Cn+xUs=`X99VQX`r8|RB*1$ksr4{302cLBq1Ee~fe&qA1PzPu z7M)YN*_%o(OxmMIp~P!TgaR~-k}%c`8G6lE_Qr)WG`$>YP_V)wIH^JnuF8{4?y{e0 z9j;uS7uI~bCLk0XuEX+V=;d(#r}2Q1XDE}Lp+bn^8!vXX5ktZZixT&~(#)w@zqfl& z)b~}ZOw10YIJ0l;m1grzXTSNf1(!SDVT|bT8Yx!lRW*FGxTqlYg*3CTmDQr4$my#` zq=y3bHJ6)bt^^aI-3h+~8;{~XngpC}q#|YsU;yUOneGc@WvJU~E|ue;}=lUSRI;zJC zQ^I!gfS>2Kp=mzzVQ;psg`xKG0aed(B4Pp~29=?d8EQLeZPRHJmJ}_prJ|-|PM+I5 zM4r(iOU%RFf{J*4Or)$hVqDi@Pp}^{?gEkzi1f+qC1bNgGD3A6Sd5jWs?lQQh9Vdm zHSAGfzEl!$?K4^a(5Pj-@QI>c8I7H%Uy|ZQxO2fLIr$?_heG{q64G{}A*_|viIa;F zRsrj#kpY#C)Rlgl9Nc*7`(hxsP&H4)%_3kw`lcp3>j)`*;ek`Ac{Yw#a=|{dhZ^My)TChL>Ryb~;%H)6T zPkBvGS#ud`7{h;mRdi$K(~`?&s>WFUO{RYE@7m5|jVgK$wW$p~^PF+vw;mdTx>_mC z5edSfaKfhAy{H!{^(|mFTsbgrrL2XMwH@I0V1e?6P`JZ?cmN*tuabE?us3@Kr3?;n zN5Dzy$V^9x3f#0fakqwY)BTI67i6a88G~16%#)Kv?0gk<&)2XAlH|RAe zY-PDpCyGdqCOVVso__Ae(OtKNc{jQB9mDLLJe+`0n%L+=nj|O>A!zO>f~+~kRNfG< zkId#~)v#-DQ7x>L(IZ4?7$7LHY<;4RE*A1ZVyC-NsjgDtE?NQBo8mY*Nhde*{XP@< zTFFPgS@V}`?)z{q`nmbH@&Ea^`2Cw>@w@eJS3Km8(CrGos20|qNMaaYgaDY>5^nu1 z?Mcx@yhxL)eB1%qGs#3Ttf_{`6yk9)FI`(+nF&#iaI}tbT;5q+wDMS47ms~Nd|_IZ z8oHh$t2!IfjFOR_GL(Nby#fPlTu3S1xO7l69HLA_M&X2)Zy(LPys>)QVwN;83U zhKh>3HX}D(eIz=sTg6|bBq&MTLL(!RtQiR^-4vrW zia1L!TXuA8X5J*S+Wg-TG%If-y1H5M(CH~fzF3Jb&5YcR+~|;sVQ>78M1#?^5^6l3 zEBfxAQjy*`VYs&2^&?*;Z*o|=Y$Pxm=qMngtxe_>!7~h;E?EyJG|8$CO?hk2e#)CX zX%AyC3a>9YXb$3*LC`yMJbWr^`V-cw6%f-TL+#y)9m#8x zIZ7>IX{pvPr;?ZNM!0oy1-)LM$q3g9P!G}L0rrwHngyFjGZTIIntn@O`cldRe%vgz zX@QMNCC4b2;Z?`-9*X3}xPCD^7|M_l;_Onamrf9h#52(2cA{_YaHPUQoG)(#oD(xd z#D~|y!QpIKMI9WK#*<*EI*OfrNnb z1<1Q4=4iSUYerssAskgyrkBLf_k76CJ?g5aueDAf9>KKQ z`i3(jyN$q^rKGkkbsuPXq5ZTO&D?Q~mQw0ftAvDgDM}F7O1!<6$MWF!Y#x_vLmp?8 z7ufb39UP7tgOfaxVt-(#x+@KoxEdtkKgty%oyrIVp&CVC8 z25>>`cR~GWE-bt>UW**4`*WvlP!Z@0BYDZ!>T+t-+bW7Fj)V>EXPu9RJWEdukAtbm zs3@OF%aBdAzK5GilXd8Vniq=YgM649{-$yIkFB7Tr>kdHahVxxy8%@CailB>>LI4> zVMu67IQ#Dm|0)ZF{dACdOW<~;z*-YOA3Xj;Ik;R_KwDOz_a!oJXa7XXOZ+Y;gCr!o zP?_@~ZemSTuGi6E?buSe#=>^&J#4{Mz z&swIhCaVPV>07Pp>_FQ$h?2!*-E%d9vy!JEM_5rVgk}c8{OJfXEw+a9>YOhu2nf|9 zFfm)73<~d#=_PdrZnK#(*q|GLwD$ z8eN$I0_Z?so}-MdE`GuYhf_$iPf<{n(g-%RY8M9U4Q0cZe&0 z8w^J1^<)Z0>4jwuMU?E&rDY4Ep5YF9BGXp5=03-~IQY?bO6Xur2^!N!Sl-x8^=mZK z-v+%BTh`ntA^Y^kBg$~z)m)_S5_?tEaksX5q#kxeeZ5;-mw2;$nI|>m1wHK9)R9RNc+21Z520Ode$l zyMGdMBgESwG1Z*O8Lig$tKl-rZ4Le-v59eYHTU%t7j%Fn6z+iuneGB=?j3sr_T)kFBENY+F+OI3^G#R$G-v)y?sXl5 zAYFdD5S4thfJ_zNVgf0?Z~j3}ZFkm4(36=`-EV(4wOwDAN-`RGv;BxsvtklPSN=h? zu;L^jN1gb9H#^(JRj?ED??bw&wN`_uAC&cvsMzd+)(O-YZ_A7>K|t5du2% z$N=6~{JZL!w^9{AH`v5GI;B0os|K#%cH!J7{12Ulii`>ss&45a)5@q&Vh~hx0EcP_ z(l}~5!pn3_nzU!Dx*j6cw*#n@eja{0q)3x=ufT6-<&14|B0dUzyx(xLIg(H{go8>TSiBD)ARfoqmnc zV>IPc(&S3MZT&gOo!2;>+fpq9ZLEVEAYGMmWDrdU@8``RZXxJ!DFNc_U{^s5wsZN$ z2M`e_z3GTE6v|f_Gv3z95eo(0w`f>f%TBNrv!b3( z@4tiHjOwMtXSQiWW}}7D-Hy>@V1U5{{l;(jc>@B|0RH%YIlZ8MaabSZ^E@vtxc^c% ziW=s=-g{1q6)JAsYw3*9wBwDwiCv5pi$Y&)5}hhC-eCRmO!A0tG0o9L{3^V1ev%vJ z4+{L=Im#oWCs@Tp6G`vR%QD|f9F&CD}1#K5dhM=Q(U-F``vCR~knCF1Z15s`N^O1l} zudN#ZL-8FT4or`eg1Kv?QpZi4kQ{RoO1Twx!!OUJVyK-l<{C>{{)X7G79w2N?zxwt zQ9d0omj>wcG%zs4(u7MHBcJ}%J!e4tX)7yXixwd`$8FC5Ro<;dJ&<@=E ziN#4>FXpWEIcY;T(Lh6*bs^2{GGp>7EAjw*;*Ej7$|*4QF$invWKh;DFrA=$!0V{Z z{cUe@ii1Oiw8(+NCnqHGXe%O(7haiQ&JK@sDQ|v3%OLlf#7hU2{t3ei#Wd4Q(4Q)) zF$dA>N=u*Wxe1A*^SA`Pl($uu=Na9yY1p5kFR%nhsz@CLqm?hoSfpQ>3XF`%ov$ck1m*jQlQV_2BmYCE0myP-J!Iw+U3*E~^@F}oYG=OHhes%{E6 zd%u{YYM+GT!r>k{`(qmXcu)>9YA24E2YB2OwUx19w|@@WwM$O_WV+J^E9*~&|Nrz#l=wrm=q~>mc=aY z{eWsrq`S>htp-4t!tsplp0>B-x7p|GvB}MLoBM~77Zk@(w?Jp`;GLyAg!ppu1DpNr zv19dC+Yauo67{o$4-HSd6T=uR!=r_Vq5g{>2kTYl&y-bmJZ2b}kXd5D+ATtzrjt)x zixDB8o1;8)TAAGJ!fG0uG@@o}^fQS-Bi+SdfWhThtA}anwp~|hdU_P<@)9&yzI+7? z2e4Vx-i{Z8BHL`vZJeIhn|2F%T%0~D+d=JnXF{2a(Jx~G(j5oj7h|-g`|zl|@!@`r zmZzrG$ox~EJ$ol{LYFjuH}t!1_X+@i)K;JBZ%PDF8MUeO7`(QIG#Tgtc*;F8DU#F)IwClBJ)vqmMckrj3xy>oL06?4xL)&}SGt z^b8*&!(SUnpDD$RAdEhehe>0C;J*(sz(C>p=g=zSVnThE!!mO%Mce?`D+eLSU3aT) zRYi`;5m>WhNEgPqS4lFfj`ZV>dH5?$MTNv;p?Mevms~1?RmN=kmpjxOUFz%H_lJMv z4m1egeZ$gD=w@b|z?Ry~Tj*f7CKf4f5wApl!Rzlrg-r_xT)$S*v zg(eY4S&Wn4w}p#IA<6gGWn-xkAUHjh@wG>~4rkmyc6>e146&Wt`D7b-IoimZuC5k5 zta5SBrLjh_yZ3>}bpM>dBn<$3Y+{gKx$+HICxJ2{3w$Gx-)hy;J`49F`MQpknUeB} z+u*2;jv)Fy0`8xQXL><7cw$Zpq$XdYi|(_ zR@vl7M*xaa8cNeW9RCZ_MZk~(+DuFjtYd7*!%<{7Y9vwEGL>ZG_M8+ql-AC4#SF)` zqK0H17tdwqc6!Bd?)LesR}%}v_xsm$$b~rLj$dsCT&PbYjxlQyQ?;tT$C+%eJBGy@oXHhNa+eY#2AvqX zgGT596g$%~t#reF!jc2!sUeirjmkXQdM-4UP*K!D&cL=j`uUXOk1NOT_&rA;6Z~JzhIqz)x8eJ8+ zZZ5iMo+rUG7q`g0V6!t5=V*vE%&Xb@1*fuX>Y=GTsw(dNlr-(7ZTTM4}O0v(Lu zgeW`T{p2T*<_V@`DSpc+@wy76{sYqx7qJ<&p)gZlM@D_&%*2f&BW-ls-+^|~>+?Br zrcwsB1mt}8^NYGW5x~@Fl>ZsC&5$nfu61)9I7O6vEeBESAk7uIbcsXg!lhwc)EJyd zJ_ol#trTcQAH{vb5kOz2T0Bh6EhVG1P@r_t=qWNNiTG6q@Q`o*4g{XY5|d;ZD+} zQe&#?+KQE?0!}-((P!8|^63N2)$E$#vM4N_0h${B5_aJwRNqsxWGXx5gTEYnS{r_fvR zPKUwxqaeb2&fe*8eE#^iN>BfH`(iQDtdyABgH&-!2$`&{Q%nvv&IuBj)i)+mBuGZC zz$=}YZGl_C(5484t3LvMQ!2WCK_>a!Jseq&dwSacXhJhK)R`y0xqZDHwC!Cl_JX(V z@f|Ou1#(hBit}<~23KQ>;Y^>C`cwb_D%(0}#7z@vTcm$_mS_0_*_*~n20%n;TNDkP zZ`$3djXX>$m$?wZI#(4a4bLE9hAm8j^^wxQ3zEmlv07_JM260nENYO#N9Im{`a*Xq z)s+9QgQnQxxQ$@{22Ba!005-^-)-gkrXKqLi5>f&oaH0xclL*32tTv>j3r8-`hJCP0Wqa zH_DkiHB_JP2WRlWSm+}=T8Y!ihG*9?)h}7o&813~s=HMwW1dtBmZeop+SirU3F)IOB^)oUZdX?u!F$CjhfEc8qgm0b4a4`(~jL0M5Jd74UpqS&}~3CpR# zj7Q_pM|kB~y%^;5R5XjgGG`D3*veY*q9|zW(GA;)9w=Z4ReWHF?y;4`zoLCIN0THU~Yan5i*);Mt=r zS)n3&;GfCBHA<}|p0MgDTDAKXg&uwiB7j!#jFcZL0jA0-QdX`AVwUblQ2ik#!x%d+ zj5dAgA6ZgCyQqd54lR)vWuT>5)I+cqAM3!Zkii6px-rJPK!8JI|HBDQ zin#EZ2oa>olEk+zK4(vWkfEi1lTqsnZ%k(`?mk#M%#2rt4a|iZ5d&UBuQ+SODMVo| zZqv*Gl2O)R%wq!CSUoP(9GdMO^IR;fDE@dN0rrn$TvWhTW@K(Mm>rpJ@sbl>#&r@- z;)#y*>E3!Vp3p{0eBxXl%OyPbmv12pTefBQ+q&ZvISWE_I0vII@RkNInU%KOGagcgD$tS2)>L&ru=s)6edD_u1G%ANez9rzZnU+Dv0WjJnB-7a!EIS{YXxoT&f%YuQ`t&@*~%j>sq(X4Ys%U=2ySCP*&Vvi6WNUGX>#No#o zNy@_?i}VEB5mQLzOeMm!r)ov&!K*!Dui{r9axe855~F9`k@;vFGGA1CfKsv4Dl9@L zIK`D}J@?F|@ay!&Z)4d9H@?1V_ouX+`z)eRFFdQma{W~}$tzzzU2$8GUk;zl-pNqy zll1SbL2^F8LdJeWUw!zJYBS~ro;~+MU{35`GSq4BnqxDfj=%CO=f6M-g@>AVh&J6j z)Uk~^;v5ZW3eejSgPT=md@o7og$A-ayizGBcau6dlB3I(ocosz%GGYLmR%t?r}s5n z;B>r2N#EkGh!+4Q*^ZzT~;0Aal?dzZHa3BBxi2UEmj;Wm+t()QhPB^Gh-*PIJ zK>CMkK5jP$vJ|8BezWW%{|+cgk_iFP5^&?@B7*=46=eaURegVa^KKMKv)SNoYPbT2 zNo{jxYHF0q_v5lx@$H?Ra@ORVztyy_Y<#PDiyU3K?U=n|&-&}<_z+JxQ+e5&aGWv$ zq0~h&E`hqDH1R1|N^E>O#iHIhyB0fJm2}8dA|^R0t)!|1doW|3zqIYSqQvX=D5q-Uljjq>L5l2HDkh`nJ{cu-bRCEn9hUQ)G`6PuFF zNLQK5vN6F zPe7>uPsCGAwK)EuKznh_wPAq8Ccq{%(t4l4M}9)T;uu3sk{Pu$?p?HN9G6PMa&v4; z^;5e-cucmCAjFq35V%q8bS!Nb-BFE+jJPlGJb31WUu~+PYU^yJ7U3;(4JkV;gbK+N zN>$PqFh^@@+AK?;j&+B+X}H{8V*_IwC_f~{PG6tXCOftyF-wpjvJa` z6A+LHsY9`LLeRBWpTAku+a7JT_nG~Ss+~yvmijZG;LIxIarC4A`sUrSi2?#S@CW1? zQ4PWB$07lVH+!($b%F0^P*wvq3kNW^3nms(_<9;Lc5vK95*_>Y}bo+0zXF^&y%f3OC`>(cGr zRbwmuyxPBE(GflMuT!YhtvLssqx~H2fVn`(y;$r?J1n_$``z39`|7r zTP;|-(r6Xvj7N+=&`f=Hi)DYlF zk=kh!A^$7YM-lB;7@R+_uMt0P7yIT_Q`e)0dxnupiy_0NxTd;82=fQ+WJp%$O^^Vn zhY(7QWf4GRfI!`h?TOVuUka~3O|i+ZtW>2s+1hK{Ai(V^B=btG#3tIV9SgATD2Ayq z%__b9PS*#edL={wEvLvWH@;M^rA6A*(P%4Ch_+1BXK(I)9r+dr^6d3>;!s~V`?)_n;*MkqswZH9YhDLlj<(= z&N-fz1zHqA4DH8^CpHULZj!HUjT^TaeEcw-)k_W$iKctt5zsT#baBT=yj4~?| z*M{do`}WudW%F1vrh_bqo9VIX+TYvZx7q%k3%8FB3;uR$qGsJ z6a{XSWsNoFZ$u^2Iz-i;(56xl`Bt0c^_5i|tRX zPQ@Q;knFaY*$Mi+KA!rb_Lr9rb*K!Xb+TJgQvB#*sHaSFsyUhT$>+(PV_X{|kCchr z&i?+PYv)D?H}b=+hWrsx(as_Hi2QO4cvsZ83mtgjeQ{{E?=xs7Kn#ds61`ehQ+`!uKLhe`HL zh6Tf4e8w};Jz}5p7eps+v#L>&F@)L4kC*>_vae{goOpgziZPVo^hRV5N$h#-)mC zeFwx5Mf-;(sD>VQ!1>1huPW=X$hX@C`cGm16?dZlKUDU=5*O4B|9f3mm!VWaN{&CV zQx>(Y%2eMkWuUx861xe7=^dzQL$6ggA-eMOHd~z=a#R~tC#u+ZJ=^X1NPqcLM2hkiE3hk2$I>NeBo>ca{y`iHBz%k3D8p&OJ;I-Jfr?7mTOV5 z82kWba$JPNgGPEBA%;PY82tj1HYUTQVLJ5omm3krqi6~lahk0rVVfBp$fNYBuN^@t z*|ai=3OzJ3pY8_fPWT`)jE7BVii27|qzyeR9K<1ONYW`UVKuuyngdQ6+%+f-%` zu;nCIQ&E_5=kR=dJ)#PKMhKANpLXhUl?18Um;fzYnjsWUBh*1Oc!;q}#mXAbfvvNDp@i>%_ajcTi15H5wdjs$T>U)@ zKCGv^%YefGbMX)+v*JRpqO3FRKa@vf^1PG`{q zwGrG_Ombj_A;zmA0#n|@*WM6D+rCGHt~0z1S8G=tr^#%r^Wy5LDW!#3B(5uRlb_yxqrQl*6 zN}wo}y(ZPaUw4@;o5p5jx`#YZ3%>@Uj}JHLw{@t7faz-NSSlf8_ts6OpW0|>gZ2Ts zeGfza9sS2%IF|j;_z-In`|&GNMxWO+d9R;0Zd-Dci-n4zfPF#Tip>`18RX>{ey>k^ zr9>Z5v{F?FC(JSaXWvOaFf3|Di=4n?9E@+2XoS+f2d}6vi{SWuF=^^57D#_}_uu2? zq;OTT?@I-3tt6UtNKBM1ql(-xP{?v&kf;aNap!71!ZEU{fPLz-bwYgPQTZ&8+N!nz z9>Blm_Vm$z(|77$2!RFNP;45JYxEqxo|Gb1*m2LwY^M6tz=RMggJDw@kyb!FQy;sI zB=e8z<1PpuRKBK+VpoBW&W{~|tUSVDS=A{iP7_luA7!(3H=n+nLR5d~fo!eC$x!?F z{Q$)LxqX3?Dq|QqJWUeq&U;-wPPQ@j32WmRTn%uH=0)L_gzwdSA>ba2a<^8gVQ-wN zs^vnzesIRhvm`hE{sDq_H!*|oIWF*efDGEAs-5wt3Cs-5W2P5#yLo)Qs^t5zq@ z^=5%9X)4tgK;G1vLAiVECrjEuH)FgiROTH2ivTHpfJJ@ww=0O3vn5u1Ey7(hYps|k zyLB`T6U__Sz&=;(?_@9S#( zKW;1zPyB3JTxVXPftoFmbHSe+L!8XmesAo z^P8-Kw>P-GKvVUI^6FMBz4=w%)EvAdr!<4}`-HrmIk~Evb|V9?YXWdn zJCgK`aDK14LELYHYJVYDStJi8huq(44x2O4D~CdSKitw&dl~zSYW@QMSD8RY9T#Bw zm!d<*1ppxVe=8IJ5o%~==z|>4d~xal9G$XhbZrQGrd`V;{aJE*kSbQekK-=0Ai$15T`Ivlfkj9);KwmYn?Ed z6WZJkr2%q!$lyTkUiR5Q{C#jf<_vUC=NIoEM6;bGVu^rhxCj~%?dPWz2`AhjOY{T; z8LTNo9HDW1)MBFE7oDb@QWS9JUGSKzIT{5U>{? zD;T?{rsd#~naye*3x*%t>uoZqO0cd5ldSxQjqgS~%#X7XEG$xORt0%1FOsa~7qeMj zSeRKB1EWA6-kU2+_$zF)&1I%Kc-Q_#%(iE*1~@C=Z@&;W?~hhneKBh}^w<@!;e4R= zjD_xj_>0or#j5#1L$S8+<0>YGg?MP8m4=t~vN9}2T+BiLazK*xm04BU<(gJkAYy^~ zyj^oI=xOTa742D+85sUomLTMK#b8O8V`VyTY)+)gR%c-g&18kgnh*fvupaJBhHy>E zk@m32P>jlvGjEHP)h~`AyG=-|SB)Fvz-808fu|O+a93$RBAl~}rB)|vBg;7)m~CKt z1tzyPqvf-f6av>ak9gB}0LL(4kY5@acM;fWSa6ANwsp>J5Z_U1n4stQlxSR0~3{sdFHUIqS`!nL94wB6yHsp2*XPX8&Kz} zDwI#L5+^q|_6HplwXmch=j3S}Dc@Etd)_9`U>ud~0s_vKeAzm3yK;T{=aEbg{0*i< zPUNo0wDVfLrcn+rllZy#NM6zM{yfDK;?cKmd+U5uZAs>8d+{Z&4JUd^zyN;?>%liE+*tr1D&^eSoOaSgG6f0tP+WAjvXfwkTA&GvGwrlfl=UjZ%kq zkn~sIH1a{fzv#`3pe~kYH+Af2j#x$fGHFCQAX7+9Cn5K|f+&2WGr-b@JB8QQGqG}y zh`c_C-Xw)RXpo94>qog+{V~1?v{JQ-P0s4fG)UbvhdNSu2iV-kguzrHc{MQdjG6nr zsIyNS#M-S0!Xdk={iz>l$-#IrP-nbispQ^P^=c%=F%GkwSj3itE^)h|ik7gob&~%w9G)#*G(}KWhL6iY!rYz}YUck6ZdmD7*oHD1 zwG*edfaf1P^2aCh8np^bkrhaLci7X#^$%mE=EaQ=lVxyXWG2mXKpNt{skhUP%uKa` zleKa+O5@F0&d!exm*y%d$vCs%6fI^SwU%nBN8&pg(Z<;`p)lhJdIcT}5n zB5IZz`bxiT7}e*IvC~6_7tTTyH(4>+1((%vvdK(F`Y+^Q(TDT+5C)Y%YIt3U)=5`h z4QVC$C!8zS`z%w00@jcqiQT1$z`_TCPG^)GjV?F$dB#Ngb`L*C)7W#72t`oOwGVgw zFI6Yb#%%UohAnF7oN2$5v2=;0!I&-#fLe7I&cL__G?KY}LU)|8$@^LB2SS1Bo+53M zhEXR@H5}`gPU_=5LzSLmT>GzmZi%B5U)~eh^c_I-g`L&WNc$~Ye{S=xJGap=wOW&7 zPpWM~@NKY;$ej5L1(;lDuSe}A_e1GcO9We%V`Ng8giVZP`z>vrDWDWfqZVc6$UbOS zBVpDek7rWOKX}5QmwC+nSgXunZRn(;vGPhY5Lljc=KdRP@7SFQ_;mTkx?|f;$LZL1 zI<{@wwr$(CZFX$i=INQUX07=@XI{;-&b#XqRMoX>*Kcd$5H(T=f+9;qH`3}B2AB%Z z%%t04YLHc<)`@6fJex9xn@tO2iKR;B6C{`3fqHSU4$%NVp;?^ryaBNXW3v{g zUD@u-lMDFx4AQr)x~V}c$x+0Z71*}PTikCN0@wp_fRm}nG0h?x3=$o$pGHZKt6hmg^B>qt=d30W@wn0>nv56w5)C`UWG<>tnm zb$1u__29KfdM(E3`82GlCGD!BJPbxSy|T=sPsMt;9UAij5VnTAoKN^%03?3|%}rw| zFOf2%vI(CVbs+6K8?$Sj96lAiBhm0*QPU;rGve_Ko?7r4i+ay*hEIhcExr%q^o5*E z8Denuw!~@=skwJ_svhJ%a>>N9=#_WA1c8-N- zK%r0&U(bl%0yJ*ZNYyKBsC5($K%dKvSvI?*ynUe%c3|+ob3-yke}0>b8>A0?nIDtI zH3?fK$>YUtJ{G~319RJ#Vs~)t6w0Y9y=IladR-$4~gff-P;QpDC}$@(}dfR)nAH&q6mN0;TI}#3x{ykceH_Q zlzZk&c0T1QW?_A}z*EAn@d~k99C-23J2gjltueR2xmFl3mqi5hm0sxFYl1&x8e=^7 z|4TV#_=&MQx`vSY*rX;r`@TQ2q3vAN5`_PTKOtKX&WL46#DFZiVmc1~ESy))YuT8- zhH{*=WT(eT1+)&|FHi^DBwQh<>sEN3QMWR^pasdg*Q_&H?)`!158Iha6Od7x6<@TRmOR`v6=ssaaTU9rCo=f!(GA0mN zQi(9Epy|Euk{chL$wZ*tdUR6QZnno<^^_oD?Dn-6n@+6pmu5SOVdV^eq5P#yJ zr)p#yZv3@NSkUhyweI70*`9P2zW6P*D!cR$$TQAHCKS<@+LubzGgk6*|2SE5FybbD z(H7h05*eA4ZDRu|)25!w-b4RBs6{Z3*k59C>>Y>e{2PR|tC9v#8|GP?W zft&v0`XDsuLtnA&WMhz)O7ow$Nbhe^|%6w1!$H5a&<$g!?)PHEp?w9fd)2xGK$ASyic4{{AmGY~96juBm_Pq7AhFhD+i9^F#R$HLLj_ z7W%*f0HHyRKjZ9Yv4Jqj7<;lk zN^sy*Fb!HQ+=?nvaHwu#p*iXZdaiV_0P4Eizpa4kO z=pVoglEN&x9U2|@d<7cP{dVjb?ilfoa0#oOc}n4hSR0BGAEq#j;P9*RpK`)vV-2X) zvOr@@60s`5v;&|$GoE`V9qvDOO3C1FlEO-=?Eh3PVYDe14`2dm>&3wFrOY;7(1_Xn?>^Qyv__9H;IIETLu0k+ z%A_smV4Hoa5c7O*fJ~_5xOjRjJ7#$w9|sI|`Pw(`GZL7LTrYEbhzuJQ{s-hb{B|^tyS|JqAqX1UaEh0+Tu) z%-pfJdznbQKFkB9D@02yFGmi^R%8@Lg?D%2J*6SDbJyi(rcf_SkIYJ*7VmEf>P)2~ zm;_-eKc7WbGN7B$W;pdGKLY)Rs-_lhuy!R8qd-3bVo2x!kMe#SzANyeMX>7%=E(GZ zw~lzbT`KfGQ~-HQM%K-26g?;ttJjT z1EKEz!7$cOV&ywaYtL*kFv*Pg-4Y>e~v+cdreuL zp0Y{5qLsT(zO7_zHIsQSzQ|M|OQE~2;V`dFAmJcxMB>LD1{)0wdu;48JJWw~a&ZOn z?iwFvc}`f#b3G@lrG1W`?+}2#wroAQESni{>R^kRPKl9?e_lKL@nNcTQiUeX zGaW@>t&uYEaj)e1;>CivXr1%+h#4FHc=5f7zaVtGr=0iJh7P48y^MPUHhb6`LblFd$r4QDWa zdqPhJj0K$%ZsfB2r(wMgieCg>JgTXBbQhp9{LatmgV@e`CD1$>200Wbn$vibGz1dU zV%koFP5l%AG?=A>EC5v92)w7D9>-5TBhWxtj9HAbnu+#ALc^#*aEZh(Bd($%EVOd3 zR^n#EP$mrG4$EPOa(=%pzS*jRIy}LFG?x9>9;XcnWz0)}4hpNzha?vD3z8o!=p8;u z!3hn~7)>|{>dFs?laS;eQ%n$iVeeh9pUFeuB%CL*?sxNiZC-99JVt@o+dwO3B$A%% zgD6`VV>i>y-*nO4hb^o3M&1R{!+R7Z3nTXK50=GRTWJSoyx696fu(UMNs43X-mJ{U zbblkx3gB$6F4=4^;&pmg=4pm8C(*}^&U*MqzkccLv<{QUFkY;f6B2KSEfW4f=@N2e ztc%tTXxeG>*v6V?(nT7F%IOfc+ggwESmy^6Q}^Ob6eHK)*>`1RuIE!rp%3+(B(4u@ zTT63L`#5JKc2(!C>*Byze)RJ`%jD#YHcNMHP#9;@Hx%ozjE8#(QgEco^rP4f2WDdL z(l{AVG#@NrWC3vp_{dDxP5JP-0`%B^3Z}UpjOs!kqqyq=WLV{`=fCwXub1I5&DnF! zTPeB9hSGGgOKfIjqP65oNorh#GQX-2ejk8h$-&jMwddRGi&m67JoAI2LelO&9Bt0E z!#stTPn$e&Ddx(~^c}zC5ydG5Z>u&Cha95VS)2GCZz&x4nn3)jucJg^{cl#hIqmh^?TLfXuSBOX3n;U#4L}0!M${(siV={(2kH_O zbrbS}sB#$Gc`RnoXSUA=2T?Jr#hfNK`S5dgzf6!p@ybL2(MQWr+>PrVsT1 zOBlhp4T`^-VLS}dJtt8S2t>}s@cSOUY$VqFP47?M>e2lmCctodUlI>TgKbBCKD|Xl z%odk|MGJDu8xJ;Qc2)WHG}~hP7wnZyKUH#2oo<$P7l0Jd#SCZ2pkf&C`R%E~`kU?# zKQ0kpr{#!u8S^P+x%7bg{w)0r@k|H+l0txx^tK_lzfmVE$UZg;Uba1|0@yIGox#+x zTJ!2-ON=Q!cGO)apwj$@lBSGe?*o(r<27hp5#)C_+Q=8HJdB*cfT0To$+c`f4W?F*Z}9O!ck>|`(}`xh4=&#dV$yUVoijh`_~{8a)Mv!V}$8_awZ0n*(IG4 zb2)e<7W#kwpvW&!DQE9HQr{3Y6i{33UiT)QJC!N-shWU-g-tiROgG2ENj_=>Q&reW{#>rSwha+vOu-UOX{F- z?Hxd+(al~Q)E*f%t86YW21h9brh`bMIC!!~2y+eBH``CKPHkBm=J$p!PC~4q1AkV> zUE&OChOC1IyaFY0k#xSLZHfZGPZ8h>Tacz`g>)6&6VE^~&X?b{(8J$R)f6`+(yUZs zS(esnSzsl(a#HZDf7RBlq?9IaoT@@0Yq=Y&AK~qe*#qTef zzWbhMr4u71l@Q0dd*0hldkLE!luiw0gf8F%8-Lq5&;K>^(}FV1aBEE?IPgoS?BEeR z-fy$ej~H>MC}ow|&N8&dLaANvDBKqx}J7LT29mDhu` zn1fS9VBOjl-d z9t$^Gb!W)DtYi%YDk>jKQnH*i2ybO|JZAWlWRJH~`$si6hUU?*$rHc@zCb;VHMGTA z$|4o!!`g{*O=7!1^7cbId%u^*iL*tmNjvvGta9Vh48PDcS=ipm_Q1*!+oF=N3xw%q zINRymOYsV~3@(O-XMcQ#Zjt!vuQ5_3SMJ^k(@WA$`&4cbvd;k}MUn5Tx<3U_;vczm8<)EEp&y{XUp1(i-y za}QVzD7OmDZBSq7CR_@lg7!6FT$$PIi|G5LG}dhNwb%6~hz4}~dcX&LKg{K(t^KYA z^X)ahiwnc-HdOH$)HgMBPi{HN6Z7XaUm?{s*FdJk?XgK0vp${uDYN&N`=(BS#nnnfvsF5h7qY@XZ@D~bVbnw)z>u}Wrq86S16U;I5?4G?oO7sv{? zI8W;*y*+4H$Vn%W#ITg&j**~w-DFf{%vaH!Ybn7acs6B& zcmrX!OO21F$6x1=?5L_*6oueb4Aa8d;9sezDhg+cMi!KNiY#k7v`hoDV6Lj3dSwG$^i>|QAxJ>34|Z>csOlual?b5T+v4q z;5vu(Bhr<|X3414?^+zscty4z@8%iW$?;HqsDGRU)!XL zdssC(;f;DPwBFb#Zh8mcN>NKN{S%SVeUcUCh9DZImf&$g7wu*z+UL9JYfDLS-via; zbgxC4vm=d4djE0ZmW1Cenk~GHoA^-3$T7>f7ko!Em0)m>0KLd6vecQ8m6|yedu~F* z;wy3SmZB?%%*R}g788Kcdv4)tQtr;uANMt(i;bESObp4_?Fcgtv^@C-W)H8iJ>c-b zHPJ+`GFA51r~@1@5^bjx3*ns4?IQLD0P~8Dnen!tD3)NP*DZi4jDc5s{0dLaiv*fu zSa%b6B3Py6=x(%9IxfGKRa?xf6RMO)9v8hGCk<*U;1Y3UL!PdO>icEHc$TFk{v@Id z*CE1#8*R2d7&aIt*sONh0xz{efY%b8mJr#ql%RU~%fjLGL3IPq-1V9Pt^>mZL#rIx zc3z<0uQK0pJ78vC>(BeUK$Lo9WerR4ivfl-wf2NboQ@DgB-D*e!=0kT#d!(H+uf*x ziyX3(dtkwmRVHb|RdjYjQRe||--Bl2pHnC%dySvPGvF>gGk1KBqn6UrA&&+vU3t`j z*EjHAoLXfjI2$GGjvP_Cp1&)4m`{A%l*bIpRUhK^nbWPZBr9sY=i0aHe_- z-P(>ZhgMR%c3q486on0TbPvNmS1Xi=Y|`;16hqBa5Sr<voL{meAVh5@{M`6rVpGO@V`j#s`m76YT#l|sAFo4hJhHD3HIsevG+P1Vx z6;uT@tSnQ8uyJQAZnVnn7Ubb+76?mfDjG|;#95orAFAqg)s(HPK6-grg4cnl)~JV= z7-rQ?G5-5H2mKlZ;Ft>x`a0aG3&L%^*Dy^a#Glw2P{*5n&#^T3*v7JrSMl}R-p;)Y zf$y3>>fLD!obXG&HLpRGXwV*PIQ0R`Iwa=@s`bjcd;d=N*t#y74K~h(GnzU0~C%Qt*St}lhCwyP)%5UJIG?*8bq-TEh;nwTd<)HzyTCUCgvV+&h zP}^uYoCmOU*Z+JmHC7ZYL>do1Zf=U;BEhv(P}AtQa zlSVR_b=!8Ej_#e4-Q#0GZ|rP*1ZRir70#yPO-V05c(V?aq(!?;6;klBnNNkycC&|f zeX!gO__g(^iq zb3P{jHZCUEZat(K5K~bEyO($l5+kzAFP%HA0O$~Rs0Ju~R4D%8dOZS&SiTK-#}JBx z%Iz_O+cyK2uBH!_Ts&=|!r_=uj1`iP$A>g;{G6xi_(6|AUT(Z7vFCXsZd?xjBkfuL z`kS(HwlxI@41GB(VOltts`-B+uHR>)Fq2+~zOb_i_K=XRcu zm;?P(@)~%fK@=C8=or4imF;+Mlh|7G5fo4EzBSnplDtJjjPChW-khu_(MtoS4opsT zp}qGON3Z3^+3Fr>+`g)*jwT4hW3TJ%Y&2tVrol@8--7=VL)PNKy`E!ceq}`oUu}?F zxJ5A?<;Dp3_wB1=oU&sq*TWGAP@s!1;b^;(DUZH?fOQCvT)fP9mJ;fD7Mk>Nk0!=D z$3z8kW{t-)w~Qv%56gxQ@|thfi>5x;AAL^Dguqi-@2ibT_Oe~iAM%4aLE!B^%n#K| zcs}b{MT;gz*7M*x^{uMr;q5j;27VMB?*W06PpJ*g|3((oj>GG?JZ}V_6)RI;P(x7O z^E-|i^X`xKzQXO}o?u$|!=O>McV<#~g#q%>AJd zL3ACjn&Q>({w|K5n!E-A8%?Pr`itkA62Ycf?Rv8<1A>4{1DOhPEndCD=!1d4L%=Nr z>+RVlNy6#~+CHJP`Y@15Tc*o(otJ740Mk3;6}?8ra7lu=9Cu8&!=iNplp0QA$;n+Z zGXVYiq@afZeU!Z%2bXiYNyO-j>FkVUA6BXx!1sEYw~97@ncjh zXSFFE6q1COw30N7QRNY>sy3ESX zfcFE&iyI1~=YA^)ga`x>&eWsje|3(CM3Q6zn9T*nt6Pm4WsH>>sbQA@L1ic(2LkK9 zLz*9if`||UAd&Mssy`R{2}8v!dP-oA3gH4nZ#PxKlxYu z5{Lr%+Is|=w4$uV1C1C6DNDv-3RNg!&xwihZKCEF1RBByPWUMS57d`eMB9Fjs1!+7 z{%IrZlI;TWE9}5Zc7s-UFA$57IS11H(EpYo%ex79Ocqwa5)7H+y?5#vdE918T46Xs zuP{*+tqkD^LmHZj@#HKc(B;TuYs?sDY_xkhBM?B&cBqw z9NeTGN%LmK%?il;RVLQ(Y7un=g>tx}_bcvfi&IO6Fez3Sl8TWua0z2*DeL3n{Zl_| z^0-Z;J%Q<*v>(>1qe!NWq!a?5Geilsja*Ddp2SgbptMj75`0z&9}?oqZ?hJv8Hjm@ zP{{fhEX1k^eq@dOpv}hwz-Rl0a0$rOauncZF=!B50I!ONeEpH6`tWN);Dbjlhr_MG z^(O3759Hg%H5D&7K6d9W7v-J*x5>}A4}+&2Cj2)xWH+$2(hi1B;T_7$_XQb>U$V(8uB5tLNZ$v#BFivpE_zyO%u5Oo}qM!UGMP z$9Tpl^R4)9ZEs%tv~?S{J|F}<^g>%)ZJZ!n#oksvw91m;Y}nVi+`B&ysR)3wbUPKz<-r6NXVNrfrJDi4{YwWjYL3|y$dQu6FKBG# zJ;AQ6f7`bonE4C!K6`u^{PH-ijXQfU&Aww}P3p$GV#O1v0l%jZW@*c&pc&!_To zA^)ZCjGPw-ozK6M;K7fD@R?~LX!+D=d7v$0>cz%|)uT^*`n@n}yAZ4F2#<#(`_6H%oxyPfb;_6makM;bE~afRx?EQEE8C z#JlSB@ePorkacu^MQQnlPK17kQnv3&-g;PuhG|lz;L&Dz#fK1s#k5xyT~@>+#G*Ji zTA%Gzgl9f1B!8_FCwaBfeq7boipg_B9Q{2=`J{o<5axZKhy7F`*uk!C`9-VYHJ?*@ zFA#}Xq?!j7CSAw4h1flA1Si|otX)=yz$@+b16d6eVIey2!f$P2ChN*)s8U9sg1--n zR&}|Uzr)M9ls)DlJia+SdJ0mdV9TupAv;~X&fd4RB;gIhS^QcU_6AXpvl{WXQG&YPXsjY zf%Tz#(axNfqXHS%**{gVN}V`=Oe4&_o$_z?p<5K{2V^LeO6MLW4q&2{C`3c)kxQJ7 zfs@~kBfKApEML@RJjw*~DDRXrk{yor#kvzu!Bf`gsQ4#^x&FRVQk{Y(hXjqbfpOsL z6iGh9%yWW|XPCM$3vFA3&5h3tQ0_Mdou8y%2xGQWtAtCMmE;FxAOv@3{!-PGi1UkX zz{syeX)La<2>y%qA^rOphTHKK)+d{OkfKJiN<#(_KwwOrBxfjsUV4ixA&ConYw8@K z$0UEM?U2gEr4^qTv}jL&iO0c9XMWb6bz?G|I+bwDtAt;pa8%)^x!>=nJhPl zN8%R#b}xaxk5GxndkkegduW0LHYbK$=(U`rt3toKmIw;|wq^Y3=JvVrv-+XF*U^Is z%TI~;129Q}DSsO&Rhyz^Dne%Faju>nHwt&C!kHH5v(nPlt)@x%1eT{ zu7jD9bV@1%>rQsk9aB0Q5#%)Wj;};FbbTp({WF49{i><3m)-N6p(K8msc=xaqZ9c3*bn%8+#?w3(+B{B!%EYr7g@#Fr=wz@^6w`%T$ zj?iXa$kDxNLTveHAhg$ zxOZ*Q1dPiF<6}1X**(6ffe$eYjF7n_)n*#hpoAIvaxWrqI4a9!9ylaEyo zd?`8p(Bw1$F7UdXy5g#D>P;-Zy7+OHVkM|oF1pT=ImX=eoFjQOiBsAA3;e2wy-8NR z?g-kh?+TLH7YJq(kk2MlTV^e0mekO&_2AGGB*b^qUm)QIZkUG$t<% zpaZ$Yig)m0?y=G-v{uU^C6&2V&e*SG+}>U3B*}nduQ64&2AZmcD!5BD;z+$G#q2Y0FP3zHBi*9}~ z$H^KI_2Ie>w4Vo+rHXg@M*n|s7E(P=NwjzivokkRT7vGfhm`5IDUhe<-AyXLh- zNHsta8W~TVRJswCJ%}rLeXW$XfZC45N;q>7`*W|e_I2T|v3>%P3NKGTBMuxDz(W$0YTM_=5_t0}+{!2c}OP?+$%h+W# z!c|+3OT1zY;BJdM!vo&0*ysq`KyVsNwu`tio3gH4d0a-Cb`gB~EfV1ZmMsU+N%eZ_nCwV?HJ@^6~2dZ)^-Yy{{0T^D>0ED^}&_v}}v)we##>(90jVExR3FeEiy!^_P2bnrg)2MXAakwnq0*Vu@{M4Bbi9bRS%v zuv^;-uq*sEBFo(P(%;mb&=*$-I2Ck^!f5A?D>)#BCu1m+u}Vo9#a?~|OWYlf3i=VdaCG#@&JDsr#Z=} zACcjNUxVLf=KvM1DQDGlM-?|BSJt}E4AhO7$(dz~toZBy?09Uk6AVZ8=a~QaC~nh$ zK1k)eZ(5*yo3lpiTEB}><$#xgtB(Xq%`hTS0WtgVqLNwGRsJ5NKCp;ZATq9VpVZ#T zH(9ORk4DCZpI%7Pd*!vkXtOohW$L09TsKAc#%B14n_)EKe5S6W0njd1viiKW}&CYfB2Oty*H z$uhz8<2tg*9y%W>mmSaE-ZTv|Ax$!pZ8G@HG8*FaFp&sh=pYDw-{hVGIZZU&hFM*& zpNN)N*W4}yZSuX8%Q0Sl-L3YiJII#2Jv7_p@9mmQlP#m*!JfUZzAIr;R-tT^=h`PS zQ=j)@jDfXQa;0f@a;2AucAVLC+Vp9%XBm2A;@Lu)or~|b|7r0P`zaP``v-c6fCB;& z|G&QA{ZC2vKiu)fs@Ap}tcd?KUHeoSD36m9 zy;3SnN9bT`<$6UL4GP6Fm5wTy?kbvWQ^H2HrDBk5f%FxTf~g4w(*`#`XB{gkz;nks zzfRhYyEf7UtL|B|EUCU4AprcPV)eX2fu@cAK3iu`s5u_(`%hS6$(xR;Yuw?QtHVbSt*xYn}VpeI>n#^wcCUwDIEaJm2GiIJSaQ;78q(W;J%XCH^#K1q~)G z6AjaTEn<#z{I83rBk)+ej)?CooBHrkw)10p`;e_fxzi+RA2ox5z%3`c6&S%@xMDt( zP$jm2%}qAejZW}qMyPbe-O#>TkW>KWt4B+r(UBxN(1FAK zWY~EPwK2(!Lt9kGqy4?AkeMvuLM|ek^`yl3kzr!?Lwd&_F;ty; zd%trT?%=g_(*}kEu$W@-*2uXF^!DaJb4TlUOM*5d)i6f{hP-XVczXL`h!k;Lxk{FM z#5mX*2S0C9^2+f`aL_lWuxdh;bQFJQP7u|3B$i!-5Y?xV*N=Mj8#1TPrm^WC?xM`W zVOWJt9|YjGLC2u@>l-F={f28#caf1BU1Qn;=LO$rKOX9R8g)nP!Xr@Z8Skq8E?Xff zVqc_egAsv1JGaXs@vudAj!=-tpNW%!Z1od1xoY?H`x2$VIpC%YE#kQc1DAWyCTewB zj^qr?P6=9+Pf#BcZc1~&$n*7QiGlSOG%+PZ2d#TR6^rGdy$QFc6xTcWak3wcULOqi>^$+j52a~2HUiwNB?#VC<)z`DGLhL-nR6DEqk{jgi4wC5rWO+VvB@7HgQNPuV3ZWK2_mTE(s= z-;@U_1~=<2rYHK+a$om^ci+6_HLKj??fR(P=By%ScV#+9bxuhY91ZimPAQqkRydYz z{jwuK=-Rwje<=V75?B)55#qeD2EsNJ{ZY*HYmaCGPUjwG@Ss(rg4BGNcl1I-B^oiw zX}$G6aR5cFY}A%B9J2aAMBFWLF?}LaE~S|cv1)S+q?gB+|83tnNiJrq0V}iR*Qf!X zhHS+{BAhS!aZx-*t%VV2tCi@%o7yBr<1@27_Frhyh+RO3W1xby*Y-u#du63y|884r z_-B2kuv}GZb+RXMfh{hV0pNhjpzCU0x2zWwz}XqYU1O|K>2SLo5J}|nNEU=ZPrRGU zGrjk~~l71e%?g$HKn2rV+yCDhc?2#W8HP0g0X9^Q+(MJ>w3rk||`Z zKnG(4)+f6x+M>QO2IaDRuIPvSA>{TE4>H$$D0}2t5@m}Bzy(K&dpz;~M|5~b;ea$@ zuB(tC(cj=eQ1S4$f>zs1=SlZKLlniSwcrq_beJPX7r-_BJ1v*QpuYvvob2*W2Pf@X zG{z4Ku;wg!9soPgZTqArhgwoyP3zc@yc(XX+Nno?pha&Pkg62E&_P3p79<%Vz_`^= zqgD>$#^>Dn`&7;hg$_bxjC?05A|b2ilTNL*B1q)9(?&%IXAy z+285~LIgo8us7btvM_$J_-~A7gg_6X!lf58E`<6!T=NqIPD<(U$7?6C+0Ovws=B*O zpIE^+YO*kiH~h7p!AK?3GMVI<1cWVe^vFzR%~mi?0)#oj0Z}~ACG6ec&o9)bBEahK zpBBxBP@%8xSt(g)D7)qjRma@g(m+In(~?7K_cS^MhUqeb`>p;4ae($Ptrn?Vt53 zLE|gBgk+GDIC68_hzUgkW64Zj1mNc8Pw+fS6PZ z?k&+7iAHz4+J{l(SNG8q=IA;S?{ppzqIMBv5^6iF0r;Y2Wo4 zF8^A>UJRgSPpD+Bj5iz z#TBvWWL_ThhJqz%lhecyktbn`bLCu?q4PF%UVhU)88tmY0tzV@2PX>16XMi(V{PNo zsL~UhV<`&Qz9(O6I=x2BOPPu871fXJeNq=E@VF==!X!6CH~_H^Tno z-@Q|9Uf;;@4qWnUNR7ralm$>tP*B7i*O)|pV_g|_i= z&N(Gq8xx}dk?UWJBiR<`>6(G~dOzB672QcG=mJOZy;%fnp5b`GP(hOSKI;sFS2H|* zyRp~uA<>5}{yETkynGrXK-1&;3X!w`@hLt+X-OPgX=BsLBWd=3%J8YKTDd&}L@i&? zezR-Uim?#dj@-joua5ctms0K!E*6ys1_X2s1q7t@|3fMN&*@)T#`b{qf7Wt^JZF%8 zb=1@0HGHG+7HG-@DM<-On19dkiK2XjQqj1dZLA52rVVr+7Rbi*xw?vy zPUnFbQ=d(j9BZ;A7_Aq?7-Lm&W2QgUK=&x{d(oF709dS}3#H$x5`Wy=j>r#z^CuEO zq}@)jW0i5Agv}BOt*$f zt=N7jD2OoJj%^$)_e7nVv|kGx89|prGmabh!<#lODGp}$2TU{CJ7D}i}} zB$vWV2tjHtO32uIg5_aSek1tvMOp-CGbPsAGyQ)^d#4~#qHasKYL{)>wr$(CZQHhO z+x9No#xC3Dt-s^mh(3MK)9IId%!iB>IoBL>jQP=@FwEv^kAci0Lbi#AbhXsO3XcqN z!va@3HOP_xP0;N#Mg#fI7E(C&xA)_!CkAMPIDFc41}E{7O3T9@I2+8wThPa0ggC8> zYS+^jHS?+wM1~U^<@q0GhG4IjLk$)GxjWR;C;6Ze<6{;?-U5@Fa=70;*H0MKuJ_uH zO&s&4Wy(Fm2r|hOm31Be3j~+Z9mJj@+pf(hMhe;3A0mc~49jEBGfU!zcu#C3cz6+A zHqNs0iGU(l3YZ(4y<#EA0oOC6cqcqp999(y7e^KP5qRiQ2|^qu{4{8N8A_laowjDy z8((iSl|~JL!BGtSI7ZSnvhN@Py9F{D+h5-?nG+ehrQLzL+uC$f3FQqa@Yo;mGmQ5k za4+@2{x-NQ@>L3mAgl4(L0j)?>}};s z_C+oC1azXIKjQ6N9L#je+?^@%y@b83p2qoVgmwluzH&0|QS*|f*Myy56BYH;pC~D2 z#?C=-l|IO*ufidA$`l#h$F!+owaU#Q-2;HEstVB85r(}#3p9+pdysIC;oAEPQq8~s zT9Scuqq3Io59j9bIqXh%8<(BCt{b~OU69Km-xFkZ1{*V91@0`-BGc#jygaT0Or_dWoo5TvX0);Q^o}I6C-I;L^GI3J1?qy3zSt|pA0M8 zxm@!{=7P+r+p;yZStSRW>5;*i`= z_H6rFaokgp8!R9~xm<@*9wY@0fyJyBwEud`)xPaI z+@llC|3Vtrd#EUb000K&59wd2D>!9|BmRaS)154(7H|~|d325_;nXoFFUJMJ$a&Q$ zMGP1k*MUSQpZ-drXsF%>0_xv?sch>B)AZ30fADF)9p0 zX$)Jb4uud81a`$R{eblslzB*27*QM@VEvjNZVwTu`r-gQzVIS za0oR2#M&MKMOYF7BuV912ZLA?szXu-ntM$j$co#yOB4|!4ZoVB+piiHLjXmLkO+Fk z0zc0-e99#Nl+VzoW-%gl#AX`y2;mSDgG>_AL=sCbLmiaL!w>f6^h+5^C7^2s&J;<@ zOV|9)L+BWXd<#>?DeL-;3-(?jwjnJsiSaYWjH)5e;r=E_(5Q<*bJB_Wn{&5@0MLg* zlC-@iaF$+^mbw}WO#?RtXIAI4PE>^|Rzl*943r!&?e>7z+Qcz&*KxljF&!|u`T`M{ zDY>~Ea6C-<>vTq8ym*_^nW^i5<~sGlYR`gAR9p=`FNI$o!5sW(dThO9Triwiw%7xJ zdC%&C!oJWPQroCF`aY2!_GvLx? z>r3p=YR8Et*I3ipmtKTiH7svvb?}-cZ%y5mL2Y*IH!%?UtBvs8ne=~3c{QxfqR?MI zC3+?EbE&w_Ae8y^?j24Qb2@SJ!jPAxl~I5TheJWJe@DvUa0epAMqA&ER4Vv<&$2Ax z8#8@OUT&ZLjJ(K#FxbyVG?TUDh`&JwO{Qb(BB_i8ZcZ< z!@j^}utIN&fW(`U32MdU4iuj_CsAuXdTbFo1z zb0lD-TpIR8(kiW<>d=3_OcEMcJvRs5t=JrqXX~ksz{|_d&dsfT0LH57Pi?F@d5Y}~ z;iJk3L$AOoh2(P1h-7G%lTEZHgPIoK;+9(GZjqiwa*b{#vaZRS0=fnxaMY>^f)^2? zYlyR+Yu_QQkPq^yX^QVnPz8Bmk-}PTg6uM)=dh)>fR?52FgN6dn$3T`fVi?d@(;GW z9q|4&kE%emDkP@5BeWXdU}3aQoU)=g^Ov#Ue)^uLpD|T`VfJl&6o6cB7rO(JeE5{nW7NCh?6{6|lG` z`^B#Q_;u@M6{wBW`E@^AsassftsZ`iRLRva=_VZKq8;9xaE+pqXoTCPMGP=+-)fs}FfOZPTw3R*ZCs@5cG1LeK_=mx?YDvH;Yqoi^4} z0Nc{Ek1`{SND#2Lt8xQMTObTOpM|Ff(oCJk=m9AfvV$$T8Z}AY#Z`sC^AosMx^jnc z&xF7Vw`P$H+c)d=80F<2#14Z7%}4!Yh=-t-y1U|Horap|unA|K+O1;S7IIfEsZ&z=*04?q7&rp31Yca>*PRg`s{Keae2r_i1P^&Oble z6rWgh1h-B1*AD>9@)1NGzU>*NOo{i^WJJ+_x<*tKfe~w!IMW)Xkd1kA=s zccvlj+r26ds{kcbC}y=jVJXaWiJc_#={n8z5wU9Y0Xei@lD2x{I*>igK_?t;r87%4 zFH+zymMuXqV~h;j^h6R*aYwPb|5D!$#b6yWd)iGO?Vx7tHv1t8MIrY@WV4HI{>Sro z5+Vg=h+6WVo>`23qxwFqIR5QKphe&{fagn0oKND`enf5HXbHldb^Z%7=dzb%Sjk?nIQrZ+p{MpSjOsz@2s{)U{81qw%XK?aENqZ~(%h_-5~d>KJzDB3 zVBHE0MQFjneVs8uXU8Q%ZIT$Ha6td3dn#An4iu#EohZ%YH-qAM0nD`jw%>*Z+HZWl zKC_geJ|;+zDmNbZ?nDM&E`!?ZcCcoTFjWokUDQ9~(xVlolMpd#4aVhg860hHPyTl> z?*!x@`(0^+GSY0RG44IU5(ITTDu!0t4h*XZKLFM-$V@Qh+`0Y!A3Ea%oRoEt1pWR9 zD-NggHq}VLArttBVE~aUcws5xfbR(EJYop?Nap4q3HCDTdPAcg0512r{iF^Q`P~NX zTtZrCkeE5XD*j6KJkCP8M$?t-LTQXXz=B2AfLjdD9`C z$ZtT$sUCks2x#|Qm_LCB2^7o#Sb!ier2{mc(uXp^bf>^M5S<*S#=M;fNwC8m$atJs zWtp;%0}XezJcY-*4#}E3=YH_`=Qepmv2%0lXgnD*%w& zb0fnPpnyUCZ~sxOvAy)nlEMk{w{_pVXXc%5w0kv%5B8Ni{UC*8=v6|2%Sg|2IP_@I zKYld`%GKpZ*}9sXifvSJfFi`Fnhmya-;L|1`_4aE16{qGf*_5RiENZ(>%NOh4)g_< zYFHIGKrWJXoB;UYYfAocyvkgd+J8tX&6jX{)Cg-k-$&8M@)Mjl&90E->l+X-=;h3~ z6=&t`{e|%Q=3%DMu_!q(pgaFK=-~7$b5?%CEnuDgX>O=3B;RhGM-2i(>W2p3d!JTc z1@_e3l@}|zo0|juB1Qke$p><5EpSrn=RPeO95h=RIOSm!r4GhHzQ0xu`5+Qj#a|I6 zcjm7(GXDKi0EjJ;E+jrr#br6=U$K!_K!*>qi_4_xGK&fPNJ2qW{pCgl?3qx+LP9tv zIqC?eBpVDCZo8J`-omi4`Bn*=;HR8r2)8wwHfCmKQ`q3u$bu8Uxj41gv^TqJ2BgxZ zKc*UePV-XIwC?t>LfnH@j`MvmS_ zroJ{J3eH14s-OC;j~(iK1Y^a0+|&?danJ_Uc?i!fZt--_NCcq^0%_tR0Qdf_kt0X~ z7#7xgZsEQt8p4b2w~BBE)6W1|IpVyo1V<8wMfl&^2kgmrt>C41&R>7V`j%zByR!q6O`i61Gnwd% ze(6_-E2j0x%L$b%=g#pP5mtt{zZOS7l2cQQUmBg1~CgGPt z2HCscDc>feZ&ycEN~pBGFGyDB@FIx{g+qupkc+x;r$)3ECqc(wZx@fd%zm^P1dYUroK-L zn2KKy)ZVZae?K(M-A}%m;dn6@e1V9N~CYw5r3HuY=X|sQg9=xQ*XS~jy7Gzjhqjj0-s_2k$aW?b?*RI}rAgiT42rHV#6QdM9->3_ zM+XbG&%AUxorcA0WoMbQ$0=|fquBf+k{9QR@{j4?e4dc2Wrt+I-il}qo;s7wm*k9| zEmFx`4!0#-2(Z`6gx~D_^k@SOh2~8W;RIXzx$f0d<5yNJk;tk?JtbcL1RbB#sdm%C zSWPkBH>9VF{TeUNCx_b)IFI-D+tsr?+>rVs`Lh;Cgx^yfOn#jd(x_SWuFPDSYd($Vb-fD zP;DJWFTM6`NVZ@5=4O~57@FVaw!$qyjtA%QJieh-5;0bqi$+=I*Qo@ ztfl*|9U86eAhus zDQ`@#Kq0)>+VAgP`DIu94Oq%wi)(9|mZ94P1m6B=F5JVJTPL>DgcoXB?Nf6-_iMS0 z;x3o#^&jwsyeo{2q1fw95WR@EgK+LDYI2JKzH20#-(yorKZyed%ezHysyf%8ohHSP zt0BD;9?kLOeJ6un?z!9EjZ49EYcRsAQ{O&U7rgrHFsd$UC#ZYr)AF(n$8(;oiEV%} z7;CTtd-yVaL>v<3?G(UVh}3x%<{o)55bZ-;d+#715|)0rfCj;g zJWKSc)`;xYbTe=q0hVRMy*KH;^0N2%H)xTS_7z}GL86-iZPWzr z?wRF4{+A>Q=|-9EQ&lqxDLnzF6q(*l$*1H&nckei9u$saPxZWQ!;4y2b|a!--dp~a z!huQ*7gVv$QWjYFse@sgbijjRz-po8M^5h4=Z?NKmY=F|GCG=0g>wLLs-OCFFU z35`$3e)DGsXfts<QP4f7LjB63q=tXX*jb<Fr~WtZU7lfA^GYZnn*Et^Vz9{`lCH$vzs*^&-^KqFD?12KHZccj8guV) zW_q05c;^cqAf0_ULNqX5RLbd_rhq8`M@OJ%7;O!HH!~SXQG6f#8X`!#@&~Uti@V+c z78gg0wro1}Grw513W6+PhJK^3ee@8`-8~TZhFP+3Z#xzQd#*&%?5ao;Ll8;!y9Dli z9?aMnvk_ut1OC}|yqD!QfkxxoscO1ar}DY+$eU*IPTZX+HpPUZR?q`eV}{Q z4B7xANaa8Um(9o`l(Q!kkQ|PtJZ^qN=Ut{EzYHBJnmr=vC+>b}^cPnS@nyTR{C|RciTdgw`ug=#aBY zW4f>cM6h3mcnbY>OhriPG;K_o$aNBmAPxIH%G!)&_9k^O2z~(PVx%t8JleR3Fr)g@4_ZC#Tv|ryT`W->ASm9(6+vSmSLcu}XPWWwfCoLOs4A`VDhLe1w-J*l)_Y#Ho%k!0pIu$8GhS1vtEHLWKn z36h&DvDME7(0UXV>qmLC?a_9r_%jo=iJt_j@593?cCn&H8UjS#rjdUktY+zJ4@oks zs7{YPaDrg{AhBU768Jt&?&vmkLn4mM)&t=Ajm-C+^=R*%EmVL+X>y#!;d;GslOg`FKEsNG1BE@vl;Y7ow#72lnTq7@N$&4~zt ziYRwSr4dd&b>z&Qg;8^Y2lOq5bbQbr3q8AI2B1T92TMe&PD@J5dXs9Lj(!yCy_FVrd9m3 z2jnqImbt>}$&!1}kHyveTF)6n%o0I=wbmEtIbt z1fW{%{nSi<>MreHMKLC(+SC?IN8kwyajX4h!(F&jvy-~kImEP=2gwk2^^Xkn!;O_z5(9JQHF$R%7)z(CdsDrCzEIWv#e}8e zMKPDhxQvvcRyA^~;V@Na9 z(REGXf%@|ax=h<0h9)}aO=-_@?R-_?NEcv=B_?dKca2V5G6Wmz<~q;k*lYCmyeRHq z3@AjhAu=rgPjWMY7u8MP@ATIb0{}qkf2x~UTl^AR{xjWh`fsEBJ-yAPdNR;cO{hf_>U zv(RD1e4j`3YG?n*C1FJzXH6e2Wl2-uQsAmd%pRCKdnVV$=jUf(R#NU+QKw`DftpOQ znRu$yDU-!-hS%mSYth9hrHT}CMHmgZF`Bd?P)Vf6xnV+Z12}SL)`d%zmi6HjTt|&7 z^B89V7*h_+5ks=^F{8@@r-eCV8l|JxsZ(Bl$rS52v$uHw(%6$>Su!y4C;?Ft2uKq?A{mv%gJpSY}4mLnPRERV7ivI#s@fngDDQ1N+ z@6>D1S0e_AA6J3YK~~TbR!B~RGb7?7AuJJ4G$c)ukwHq7|M4b& zIc*x{F5cBiuNu1Jwa=7nw{BE>#7IQ7WDm4hxy|~xUO#T6UNAK6j+pPdT^-N4X~U6w zm4a>a@R&T;WjtNt2IQL7o5s>%TWq>iC(F`R?P%b^ z(Y#>x+<~f04p6ey!^fQKut+M+zO29*q#Ij33|tZPuS87ab64hCXvZAp{=sDB+I-42#VtI6!eXVN7MXxH`Kh4=&V zvR@8q!bYZPvCQ9PT0PcFrvGoqj8KqHjuyIGgvNBbgtEJS?NMFS0AYA>xoSgW@AB2U zPStLs`3^xg)n?PVc-B>de~nBLvc5|>P?_@plccg)Q#cl9&D1r0laEExLkTZ*Ch6`V+;MRI4+2S=Tm3MK_956E-|J-UnEO%@szHTSo%GWW#A*Fy*7S!w|2Bro?+ z1KXC1#Gd@-V47$6a_0YlvX|Lg;y07!(zg9GMNFoTI&GB-vSlmcMidB}*(UIPDO1cj zlPI1}hqeB7eZ$c(sG{@)kWwBBQ@N1-0q*MC3Z-;Vuz8X1k=&>KlVyO)O#)p8EC zw){?LeuolK8iO_M9_ssP57xWLEuou4nUe+=r;MX5$|t}CUJnZ@#COUiFnVop1bS+3 zCLROWYNkMKNujus&`7h#CgNzMoGyFs05bGmHNJST?+^&~PUO<+>VG4L;)HCOp?Bgp zmz^GuYAQL*cj^S?3KIw_I}ss=;>U|*;*qwIAZz04hxx8QB@?*MfZPfB3 zX|F21NC2T!y@uT?3_dP%QfWgE)eP`^t_IPDq1s-@`&N!7I($nqw2C8 z0ThLI6`BMgrM=O((wO3;-WD)qq5Yu@e_sI`jVk1It2-T@0TpSZ1HUVD@*DPc(3WOC9$dF?)^h9S36<|tz8Hp>H;)V>hJ!{Nt~j zLkdkUD#OercU)6x`@u_sv`d+u%Z(u!L7r$ye_>WE6wf=0BKjmqHN?gmhbq)Ww#DmJhZE{QCk|v8lhjw(B#KrBL+kcO-Vtubi{-uVeoSw`hY?Q~gyCx9AvQ5RTurexFd{N;``x zpe~lmCmSoD%J3?gnq(R)^cHo@sD+5gNpukBWc_$5F-}O1j&o;-L>nk1Q)yOtrzDp| zTI5{VARd%xi;{ek?-f`0N;ZN_JEM|WE7vCoD4Mjn#^f~-fk7=i^q4W>P-)skA_}A+ zaGPG5SGG}CzUgO6r;ST%z>|TL02oCd&uDlbqPk|6C^Ra1ocM^<8w92G5QVeu^mhc& zLEGD(;JposyCgT{+Ne@e75Oa8B*4K)$X1mrdmxq!Gu@FIz%%kQg^JqON=CB;naxW! zXvGi)?#?nM1r<|Qjx|Eco`AIO%qu&5;e*RiMm1EnEALH6rbSY^%7-#|3!^Mx{~2NM zM)uU@b+}tf5gFE;Zm-o(vmZFpR?tw<5>XKAKmJz(O@3QDFep>=vpg(usp*?ea{}5>J zRj48`sze(fI@dx^133DjCqWSOp?v5ZG|!~<*G6Ku6((e#UsRr}9IWxHertDX!Q`fn zS1(5kbK{r%^C-|}+58%wM*x28Y=VHF{$znY=PlqzVmp$p_&^O0dN*{ML${aOE4C1m z_Bn*RXS`}mR`|Zy0x$xO=eb^i z=$g27fy8$sJ?M2edBkWh0rDXS^3#zAY#}fFPp);e0T7t(et0(6V264w%=eeNw&#c3ocZ`$Q<)U@sFTse64ftX#=s$Madp3$~?FD zR5~3NrFq_O>Jh1#aIwsazTfI=jMj}@c(NijhO?854gFGZ9$S9|As=r8zzyLsT?Ds= zGKwOuvBtMr3x*Z%YEEl!ITvdY7$?U^4^z8(M55Nzq!TD=mt>uKTYoAWvvp>AcjkU+ z4y(Loq6qo@p<`k`hN{*~q2OH9_b+U=L72yDC?UAks^)>U@LQbCyX*bQ_~bBM9je3S zTQ?_?xSyru)!9_xuB%_Srqj|VI7n%9uiCIN1>|7oxOLh}mPMrNWNgri?JBj#n0z`EaK1C*%*(Q$k9DZFU6QhEt?fC&nEeH`RoO_gev#Nw>-;o zjt~EkPP-P>+6thHT=>!|%TD}`?c-DRQhCBd4NZ>alWIv zwbL?nxcmvRXd-u8`g4=AM^mIzV615#cKB~On2|IDdd}^WaeGoY!^A{!uRg8-MoCbc zsCx4`bKZHhoKC6iX3EZ8(<)Wo;|&HCDxQUCuv1@9qj8?@`Wc*^wvR= zW?=OX~hB#CXc^*MW@q!a^<2qZC3a238GF0A9W)Lkn}R+MrId&9I6w2 z<(Z*8EKflboei<&tzFX74G&bB#n;LdeBQcZ%?br0f7(=L0dIFD#sOj+UoNPffcjsX za|V8)UQT91uGu>kc`Sz3Og4Z9dF}7KVw7HREDq1Aw>`ivvz6S1$%>T<5k9|;!m3Ut zl&x4iQEpc_nr4@=vX)iLK6xw3Zu5;B%f}t;iR?``(|fU_=lRohxy+(DdK_K#zUT|} zcU@<@iz}nY;TY&!5{5VP2TWf(9|z_IT`f2_R2%~4`ynt36cUX|=x^_Ut}SbfBWKr8 zyiLnOw=S?$V%nzVo`3|+JW8k{&w-cJcg6j9H~l_s{oTLAwfApGx4h%0TI|JWnHYxU+!mP+G`Qjm7bl5(^Sf^95KB%sJO zR(Db%hr~+*(NXX{e6-$fR(XIBJqH>Ry6GTj(_n_C7UfI*nfm{(9qf zNGET-7a;NUr;9DNL%jGpf^j4Mym1pGQ@ngO+;9fZ1Ctrj8_h4tA^s9n_Mvu%q7G*y zZsCNo@%LVQ*#XnSa^+$SEs5jR7i25uXXil&&|le&jveC$oN>v@mG|+D23>960&z=P z@w4N}dM7hq*Ww8H=?BN8V0&OR$>(9P{U!=k84!@uo1{d6Tb_=^ZO20ZQk|do1;r~; zaotXoP)TK1EJoMxu=9lJT@X>1C>j;4e)D%Y)=Wq9tF`4fCdqs!{69D$bO;0 zQ2Q88<8}2pagh`B1IppuRcmdn#Z7puCOWm{J*?Y~F9C+8&R zu_~w&PDYj4F3t#~4OeKTRcl2nmy!a61miXd{uTaJ=x))j)AD4?9cCqUsUMH>8BAKqqY1HmG*i&75kHPOD+e%_y8RKZfp)@yLB7q8-`N1PtJ9eCz-p+`|9 zUY#>_+eD9$Wo5>&kd?(tZx-Z;5#-34$BYjicGj-(w_`!K1 z`Ahjz*__ZVVK<%XE+?f&T6DC0S6TKe#a4$&dhh3ms6 z?6oEwqD{n5T#WA|=p%;2FB5Rv`mysL)&ttmICzdCPZEJ+qx*IjwY^XMa16a6vi6sT z{YQ%`!yDYBJ{woUmg}}vxo#M@T4eaOp6$0pxQa{M+qLhnN<@!H6|4kT<+tJuEH6l^ zx6))xE=m_DOALbybneXdg@29jxYtO$!m~+e8h_#q@2`O74$=di{*n@_3A^w~a#gED zA=PcC<~WkpTC{?b;l=7RN^(8%1V7-XlZdyImIh@AJ?NZk`W;R*)(#G0&KNjA3mPPK zaQ`lhE#+u7VC{pUpRvOL$ts=QU;%jkfUf&21`r!q2hUmPaVjKYP-214_>M#Nco|L8 zj5*E+Mlr@Epl!bq;6q-Cegz&4OvzVKDxM0h`}b-dyGpchf7%YnUMGeyQzH!L$GG|V zYQP$IBia`Gq0wPH4zh8U`A_-yNxoZgH&w}wSr#F{{HOxmoQ=BKFlTXX#^9@T3zk@(T+kRndQ7JWJNNhRlbmfTXwxw z+V*!^E*08@c2&8(;Oe}lD#G*l&8$dnC2^L*2g?)ckyWGh41TiwE#|YdOs8^XN*u|& zys#X=py|ds9ig$4sDY6{+Dn9H_w4ds5|5%K4fn+W09sauq-)kao+@~lSQE$g(dc7s zT^nc{J5XsqZWJm~B%XYQ!;pFklC6sSLU=sJwa%;CD*GVfZEeGy{80ai-jspl^7^H; ze`^5xl-XYgoK=0DhivD#-^*&_lQM6Vv?3*^5%^OJadFF}YTM~IAgh^{c!8zOLYEz^ zkef7lAMr)uG{DD>;6)7K#S9|lRGzYl{x5J6iE~t2R}7%f|B+d_nYd(hXcmfLc~I(uBmm=9RY8Xw38Xik&h5JLJ`_AnU22=_1cbq2fY z2pA&u#Da$dH3eqULz|@><9!0L(@YPTg|1b(Mdyx!Jdps)JsA?`+*)?gFX1)L-0NCc zaTBfVR%B^?$8y&<(RS*F9d~@AI>*;qBmzeasw0$3O_d}wJ0A(6>{EPH8cuPMJtj;f z46$y&3DN8XIu)*X|2;f4h!8y*5^MPTXN_E=j=fNDy@CQmW85LB11Y@hR`=F?zJ;(8 zk*gowF8jc!-7vxav*7^D0ZE6~_{D!D9M>Kh7!W6is|f>Y*o>q-7@;3PjrwoxUj}$C zsMIu2Bfdzad(W@5fZBDUFEf)YKPEXe3`y%4Ifgis2K@8;GvtnGLe^(LI~z-^-8*nD zdL=ilKiNHcOyhovAJ^sUGitx!Q; z0jp-3zDOqHBx+~4qOEAG;b!!C5~8;og1hq@dY?c!!WQ%@7+>d({*nmKg|~ln9=5Zl zBGDkSn^-K3#iMloCydla!HpLiduvLNfgDrtczDB%)?AOLTPL|X%bT)_s0RQgHqlt_ zinWLV`mtDXx<6_ZN&sVTui(nrTWP}LXJWc<@ z)i!Apf|?Ch)okMEvrqd&Y&GZzd0i~R$8cUCdAG>N7eaZ)v158M5upd0pEfrQh+JJh z?LeNEFxjG`(fchmrA=+;yTL}sOE2Ogi<@A7pZK^?<3BVM78E` z9F z*z?MwPBKf?8qpPl%4P9do0L42w{<=$zN+q?`{$d{&8p=wq~%IgqG9o6hh-(^_YWL3 zo|~%smEDC@GL21c*4WNgs=2Nh?`rEME9@KEpQkIkn4`(bJoI2`-`RGr(XCl}m%$Ds z;Qh_DfxErfu6rxMQKjB1;U!1d2l1X#{;hSR6~H~aK+cgQ;caK6 zJD3*A=Qtg@<0PHrIK;>N@AN1nfJ@l3;>`=oKX*)hf%JP{0CMlqb?a_H*p`(xc0|HBR(Z1 zI?1Fld@K}1fmWa9UPTd^Fw}*%kCcHI8BQU9@6T0n#b>JVOMSdXc6=fsiOny96%y0O zcL%VXpB68H#+X`PrSeY@C84l%Yf;Ciq!J3AFD{lRFryr*^SI zBcjKL2mWdO$RrW`FM}0f3ls`tt^bXH+PET;F*VAOq><25dV}IvXkQw(svQ1TT04($ z&!NvI26{rb9OxjN-!SHmQVrB!js$n$n?A!P4q;3%8OfeP>HLOu5_k#{5Qo=@E((+c zDX2Ck=&%0|gH^OzP<p$AG{) zhcJx_1TF5s&>?qi<-)^6cNwxGZoDBWhm#qukxgw7=Na@$IpPr^=9utFWz%7#qA&CckqKX!2eHxa@{$GV3)_=u@;c zv*S>B?ahNb*LLI4E{6;`hNYnpK%wGi{i$CFtLvE0aWL}AVp0$>;aG!6Xds0XJ1-F( zbWr1$Ruv;w{jM2#SQ33R*)z(>ns)|{bRyHkdT>1v$$&L{Fn4wcbS<}CxdmMMPX-rt zdvF7q`MxROqJF5Wxz&p~NQ4lCH}2G*T8cy4F>gOsn2wWH`V+P>c)}J1ukwy(?a1{d z*oRLoMj7u@Yju04Y5OfQPZlfIc?5hfS#>m_H1Sf{OA1~4_2qOuhE)UNy@UcR+UMJ)-)sJdS^LhYh%YbW`F=XFF=w?DDv4p$hC9 zXsU*}5F|xj)^HZZDU#pB5@{9?v&;{A`3ID~K737zH{fE-h##YEfiJ+he$DZ+k|H^k zyJZ^Q=Py)pX=HNv;QiO#0*yq-Q6|czAT6lYDr+>vuK(ge44M`Q6`(>zr#uoZ36SY6 zv*gvzzY)P42#f@F8+Nl|LPdhEs1$(LIvPJrt6V(pS7AXd*XRKAd0tFz%%(?L`gM2A zb#ODUStUwag67T5^S6n_*#IKG%#Bh#DSJ6@QdGI3dlr<5kX@sFkOW}1P#=eGWAlZ; z2sJUxCzVBq3Gf3@6^SzIe$nIYyKJul19rFN%hm&ReS;cZAOE`D7z$57eedcvOB3RX zRB;ggiE;yNVGvNMIR#`T59W}>SmX`LkWk^ai6xBRe*=!%k1}vgk{WLTg}SW~lewAS3Mdg7Fb2oP8_05|9UqygA8g8Lz%)%}#+a&>T0k{epV)4D9w|DTxr@33iK1;^ z?K97Tk9Cf@We&ydJMF!-st9bHtFf#S{Yn_;18fctkN|(jQNj1`{lp|~mT>`FLd5D^ z6)S7psyERv-&r}8*+b>@PI~|8Vwm`cJ+b7hwiNHAp9+fVg3vyu(-Mr;cp`kk)cUGg z(o9vp&fZVe#K%A<1D<-`VH8r_zki<-pOVN`<|UnCMUXQXh?J`qua+!o}3Nz z#jGC#s;yAHVrs&w3Q!K9BKqXPS<8N)!3W+3ZgyX#nfcu3UK4oY0Hj{;yyYgLU7l6k6*(41 z0YM2&j2Hi^N)o5hbZ(jAIT_gWOY?nBuARNJ zg`MsH8)P;z`rm@gI(GYGh(0H3OYX%eTL${fa#hBrBw*5p5&A2vL&BI47+n(Ht7~I; z1oPM5FJ6^4(SS*_85%kk9^#qTwUtW0Rk!NQwF0f?+UVzl z!nvy$6ma|~*f1gdRn?t)R;u*&lQ`zfBlTTDT=rBU75rXEvXI&}Bs=4y0BLuTFfvUd zYsJ@7NP+rCOk+YbHQ|KLd({BP#?erK3W4s683ngy|8(VrUfeDl*$?;;SfKfN$jY&3 z?m>gxfS^L6m<)vZ`_l|gUvSoy2!zCFq zKgLD5CTtIndi^PAY#*}22|GM`^=%{IAG;ptJxS{7{NM*l>gtNyg{UoSiovCI;F>6R zVf6@$vtq*M9Q<`eI-pPyRr#la{VnlV#mtnj8AbYPNkqUGSDBH1xumTodNs6R2Wlf}=Q! z2D#f3i*Nmhub{RGC(+lGmY2W}8Z5l$KQ!}ZYU|4tX3_OB-rs)1mm~Fc8K@OSyryEU z6?rn&L(S?jg_^%a%uLQs!mEq5CF&^Xq{qoS`7mB|`sIWgE7hz=1v~b$i=qcs0k9b8 ztQ6=csqGQjO>?Qmuta0%Q$;2(wAaeqGokI?L{hL$9z!Rfq2#jEkxGk;o^g2=3vPzd z&=Q1?)zz9E`DMBmUodq2v}U@EG13b`99Xw)6P^+0;*3k7WgX5%e`OvlOKVxr%~hEi zvnH)g1vuhAhxOBu)eS3)44`zF*^1Lut_3R#zIpn1s1PbwKD_0RU^Bo3{Bv+}XzVlw0E|Nk+iGO9NWdhHtS}CW6pu&e>qi0D|X(^V(T1_*P z8fvhLPz`xOg!n53JLx)DMK7IlxiSrO8!V57M2ln=p2yxter)?69^AUt6335Q|0!VnHsHPQUx<8+ ze|(~WdS)FhVC!$;%T5pSnE*CSR?R>;Fmm*IeWdoXN^T4aNF*k#6^W#Ba)flR`9e4% zaS8ws{qmU=3C$DVoP5tUdia52J>uBiX4`vumOCM-bJWB7*?G^$HqwztKh2nT(rTU7 z$l4ftanRO6J4wfPBd5NfvHM22Q3t0~6jQ`^Hq8#4mE5PaQ*d{6F2k??T9DImRZDte z+xx=$01f|xXp0r?kV+WumRdMj#XEWe)D44s8rfN?_9l_o!rmxB^ zb;#y=<3rks9-^qQVY?QGbry#7dv;>eX>*i**;nTf8Rt1fvzAqa1tUQ zjNGQi9SKxDW7Y)=7{p-e;)GB+lH}WlDx=LTZYUGBH|gDkYAry1p9Vl=lADaIn_Nh8 z;Gn2IJNQ}$ZM2R1!)Mc~`9&$4<$DH~{Bw(wRbhKsrtRPPAvkEht=y5~ ziKucVt~CMA8ai|cP=8_R{igl#HRI+6;zxTAtX$zogPHK%R~uKzsP^GQG0KJEzn(Pp zb+?h4<4{iV?!-hK-f+$)A2;qP2UJFPK`$CFj>E!zD{*OIZN>N!%}1LZj_!@Ua0y`H z@VV=t%;Fg?1fsaj&3kC&2_K$+9rw`x+Hbr3vX*t&I8W+JHLw(lV_K*0EET7TFODy4 z$o9^ga8i#eOQh1MFQF0hq?FTl}Wn1*l>c5-+kv<^6nyoP`sT0QIig zM7~NKsIf8Jzl7bHwja=yT7ZPksJy?W@K0-d;gm1MB0JY2QKsgUyX6)Q8`4emcz5RIzg6f zp%z|b*IP%&&IF~2hUyo*6x$XO&cP~pga|$#!;=m|n@%T?6x7~Om=V(w&HBz zDQ~iKytsBV;$zd0HH;tnTp!3_B}OS@6x1tZ0K|I`sN!W*>ae#W*q*rwpkelkcMrC9 zK^mP=e*7!w1v|L~L1LeSOBJk8NxpG8#<6o0IdF^9cDl5deGtZ8Lam(B#WeC3^;-6+ zrgG`KkVM^_-7+T|h@4TLT#A@2`*GVR&e#qW1Oh;YK}lNd_I;Y*;MLdcZ}d@;6Le2$ zI-fN7hhCX_kxc?kyxBIGXnbOrpkNoZ0GCVMsCjx3t8Tt5@2(m(Uf#mB4=u&tJ=nd9 zzTQ(Q8{JO38*qR0r@mHozW+6SO`-MX96-UxE_~f^?&f-dcd@Op%-GJHB8JAA=6T*< zX?AFNe>?{vZz`R;`nDFf<~PCB2yF!4T_?uj{YDhYdo52{ocH@h)tiyVazPM#7%;%S zowjVm#nxI_@T8zXN0W|p7>5deLuuX?>M=)X07O zZ9d`uvlhAZ49x!cRmry$0RYJU-%bF2sVe^!)BdleA+@Qkm65RxwUxOIjgyW&9288@HM4*~Z|)>TQF*5Wb@h3ck6_~&;uhMiRG+H2QI(1Zk$|4{M>DDXe(dcAo8 zii9MHLF4i+XId&dNaFik@!RM#kc2S3(c|d^9C3ugq~$>1agUJ>gTuIH!;ulug<+)c zi1=}t`g3|A#LP68feqn#_L6t%g_(4Pfabcd*t&b4=lIZ?dmPDzf*iBIDf5uX8k!M~lM z5xM%JhB6Z2N+z?a672dY)WtF~n z8|j~oT0g=v;a{HZNesomh8l3BW&i?5!_Az>9C7=SGGgB|c0+ zL>Cc1by7rHT~)kdZ4M`yZ&hNe{27wS_CtAh|oIj(-3s=a`DM3A|VXr z?(720&e7kS(KlZ_DTk|6m-2gZ#=4|ZkMPKo^lHa{4tS6p{=DD!^cFRBfJO9?I}~VY z=jKCMPy{H&k|~ooFXSJAg%W^dF~mxv)+_F82p?M0)`IjFLiQF8-JljC$x}G{MxJ@}A-iZJbN%R;cfOtEXmgh2Al(T+&<1Q_X zt6g5vs3t95zypND*Pe%LQ@F!6wPEG(8Hh~oe9vgsTv-LW#7zD+?u~t7QLr; z`euFWT2?b6D1PH&oMkvA0bwD}d$+Kyu0*93QdOC3#qb^p4i~ICWhnnp48oQC9~;Vr z8Pn5%F_k22l^>`gs|?^{rx;v=-gu?u}v!Hj>1U28# zHqptaFLluCS*!z{zc5tV8h;&g7|y8z{N~1d#a$(Q zwOk~afd?2yNF!b?v9BE6Wq|{N$&~`7|&?KZ6IFYE!Ss;zm|X55m@s{!^F18DJquK z$bV44CWL0EP^(g7YKKoZg> zSm4km$+=AT4glV!`n@j6RojV4Pkey-*auunHzcXs5avvYVeSH-Z;L2Dpn!S}m^cqP zZ*z!Vfg+#__4b6Q$Q6SOoIT%oo(Qw)eCX2X;Ns}4kQ^x>1!i3R8tM_|5XBCRv7`0R zOw_R%UyA9qM1fYqc6Xz==Z_6cds;RftWjr6lv_nWP0J4`L^g{aO6`yZ*KL&kVV4kl zY5ql_v0PmfH4ny1S20^8Fw+i%J|9C_H5-#0kPD2$WyT7Fvi=q2S~UxL6J7dbi?jh3 zp0c3Vo~sG%I3GxSl}(}izI(kB&&TCB!w|nrYSz23ObaF*Y7;{wHRO@DxEPLMg@U`R zSBtqILUn0X2IfSf z`qy}0Y=E}EFx{E#bS!#RcHG9oaP)oP{!tEkSma`ta3bXJ6-aE0* zNTRQdG%AU6Z}b4TnL9G8q`=&UC_xT)D^*UEw4GR7=s&1Td&U(lvhb zK@kY`ew{F|-t%8AXiLEM_5(v&cM3FJV0j<7X_29}CxF-o^*;dsgtYy6iCI?RVf2Dz z_zOb}$BxWG*jywVfJ|Ge!%P*L{~)aHXHC_zDs5Yghgw9+^ORc@JaJL*b+CXWKl_zG z%PmUXo&BjAA}YH;N)vmh9|G_HXyf|`KKA0uP8kx6GNPtQe4M&KdOc`(*H&B482fN@ z;Ky8pzZf#;1Gc00a(T>xI?{Rw!@)tPDwQoY&lYiSg+~(<2*hKrfSLMnnEkn#(}kBC zo15}H<{=nIeID;c^M4YUeDJ>a^R8QqjEb$K^U@24%2YT^#0tNVB#X|CMVI%H2a=+_o9>X2)>9_$G>V}gh|nuvVAf)TBd~e3mpBc($?JxwrBMG{E?YpV zrfl){!Zh`_1&+a1RQ@k3Ry9jT)9^S%x_$c+X~E!8Tw4wJzrDf|v-jIab6m4kKPQ#N zI8CtC+GYR8dy)7?VYyB=3ugZs#ef=uEp+mV7E`}gSgfbW>IaJAhFO5E?j_bEMeSWa z1EE)S+*XhbvL;9}OC}KOIa@xILi4_y9v$(a!%9{iC04DI)S7Lpaxn2s()qF7g*zPN zpyWWs0-9d$_?vl&$1?z>0z1ZG?66Vk_F$SPXCVT{?LUdvQxbyh(gx(>-CI&>{HRY= zT&3~0O0BR>?=Do1UompOS8dXX)wKcwDQ)Qh$58^-|YjiwQ1t zG?SZ!f?+x2a;$Cc_Cwp==9budJHz0V=i6n{w~e8SB3vE{BGSekPDPxF4vWU4k5(ng(%HW`5tx&RxM0r!2f%{5cWYEO{9QT#w`ko}lMfNN9F`QT)@JVeq zscbg)fvbcxYUhOQb1f7?^$AcVqybx7Bm4ly^EaKdp*#QJ{EDZ_|B9;Kw8OQ5Xzz!& z_f?d6SE3)QdU!Xl$a)lKQT!DVJ}Ql*OQ`HvXhX6q6)uk^N#z>k1U(O(1YpZu0kj&AkOtdP$9aeL%cU|Gzx^^Y`BDNtN z>oat`*tp+6mB6C67pc9_SvZdcOhppvZHM70ID!ry@eg%PU_8dg^QJP5bi<%ML#4N6 zwz^=cQkJbJ=dO26TtV;>1@ouGwqoOJ1EXxqWRMx?hxzK`TMVZh(MJ-f))sOnfiIaj zu72MGvfoe8OA>A;VK7r1uDwQn*>t)uS(8=B_=sjiBb&M#7WpKQeEj9fWJRf1LA#A4 zdj0+WU)|n{7DF+~pCiX^u-8aCn$r@|R${H!+n+2@L<(+p(c&7e?QDEtAL*}DMfbzB zqEF|~Lh}Q1Zp^BVDkX#UHRxf+*>L#H`Uc*E&Pg`B`uu9K@-+>YPeml$5KF!n%{Mic z98%E$wVzJFJiR;{Xx#NB$K(oyTF=Gcys~{^^p1peCTi*&RR|X9d}1jh|HmU2G#&`E zp$UcC?TG&J#3F+EsMZ`kR_HQq`IJn*%hyTBox2uBK%0EQY>ydxo-^GQo)+oleQisM zdaIrM6tRPUt|b)U#LmfB57{vkJ7-;pJ7-Gw*)iTCKsSh+`X@DtUYGr($?c=DRayq_ zY5W6It-#PxZTj)fN><35AbdRJA)1I@VH7>L-tVgFC;ZhdT19W)bB`J$@Wd0jzYN44`-r?^w@sjT5{Ss{p! zWpnDaiFZC1o^hZ03i9Ij?<8SC5dZA5ZQIg%QiK=?akFG0F)o$wBrwecRHZ^!eF zfUU&iBKA{z>LbQo1khHE;vnJ(3;Cj3YM`4O+CD8@;Ld(wUwV;IzwQ)?RnGx}BKmD9 zr(m|%4?o9`KElI9aS&ozK;k-1Af?DRoNWQ0gYi@lz{5Gn*}~5g3EVF2KH4YbInt?@ zHDt1t6ZEEgqMLdQlXM_+Vlxuycw>{}tA9$+tA*T??|;UwbaixmyLvk%#y>8Q517^D20t!~O0gSCKYRs~w!<}#evONTIP71ch5N_uE^ozCWSuFY6$!wCT z>;y)2?ez4%KREzp-c}3QZru)|IdO&52@Wzqnw5SX1{x0}hHFXmUQ8i|5v}=dB z&)E(f*fS|b$nnqJNNW40Wk;EjaW1~yJ-_!1AST-JzkHA@O{wRt*{)1nHp@D;Y8QK2 zE54_Jb^ie)6Pb^}TC$1oKPX8lkNYsdZMS>*9f5$KRH9eLP%&BI((#J% zPtU%>U|5ELWn+>dY~S6>;zh-=WA2q@<7x8&g5hgBSJ=D{?kTKkt1~r4R_%qpo*x0z znfZtkyuxF+)t0$!Q^23(2l9V3R61~z@yRmS*MjX%WlDijwHZx*%gA44dFNJwXQrxP zbwq3p{W~JPp006|bWDc!tlR|A{BoG5TrpGWbgX?()?lU$v)ISOJ!oxS>M<V?bg%@D>eu#Qd8j;44 zH8@9r{seD8=N;v@mVG;Y*=S=#c0=>xcx~gVo4qB&>>81#VQ6b7-H<=rc)T3K(j+7A z8Lbf9WA@dLPxT4Xf$Las_DvGX7qKd7!bz_7Mc)q4U@l9do#!T(VJb!!qJKG zESo^+MFrYHi+Gm*INXms3x1fF5`FpZO}j<(vpo^jzez)$tSVkIqR+7=jF*mBTd-FX z_uG;`G!LYguSFx%G7@c^6a8@~a~aoPI5BE-k&@GNj&8Ykh%!A=#=s;}FoC)H0nZ4g zrmnY&y7+7lYMjZ*2%8wGayS|+(}Js}O#WA3(H_yUUvcgro@7^#64+2Xjzw;8n`S7Z zDn+|1E*w!6*9`XL@FHbLapS6adSciV%j@pjq>&OD6FZ;(X=bTmL<@Zhu%`z4KYK+e z?f=y)R#0e&CbUP;%&DeFw9d*KB?#CvAQ;}OOQpxZ4H_x&4BpFs%Xu}^ssHs;dTBqG zXre;kBOOgOy17Zz^3{ziTU?iwO7)eYdE;lh=p2P&z8U&3Pq9QA1V4>CBFxEJ-L{^2RQgg8v@|PBi};#CMv*(s5m) zVdo9i@nAh6Nsom6<0z$7ivrU~vl*jJY-l_qNg@x>l887)q+z;!?Z>CnQv@C%Zq(*V zr()l4X|eX~Wopg0n_B4E1&_qm{eFmL3#)Tf=_pv|0}noy&7SUwo33D@rIw_<=BXAqZ4_460u}i7p;(EnpG(54w?Ni&SIt zX~PM*uaUXPPpL4R*s?hWb)m2yc?Z=P+s3UG?h!lu8mVM%0YcAVEI*ttTVD9VBfEr( zRXnMFP$USAfDl*jpO)JPk68Bp1>^C5gs|+I=!D?*_W*6eL;YOd1F8~;ex%|LX8oPF zEJ##fT44p^%#bf?Kmn0#Var^Mu?>KSSXdNm0Q`eMYL#sMPpGs%C}e(O;us~72GfaL zP$x_EQCMCT#$Pdq8|V}%jPrbN-%0V5HJCI^(0*YOhr)fG!Ldt7{=04R72<2+Q)Hn^$ng_bwl8LKcov1Em@GCS9em9w`CCf)O|4@2$kPpemE zbFE}FjUnD{9FL?k|CX?&wfgQS9Q3dLdKkmYJ-ul+8qMM_&c7s0h~s62(@*`Mc1rlbDwPu$X-lfvTd6dxLvsk7P)X| zPfQk~3PXZ8Wg89$49p3=W8W5Ku>gEAF<^jHk{4*eC=Z=NMzux~Flu1%XQkwtet9~Le)ZuQpnkC7BhYh$aQ zY32wI0YaX_0PKGJTXGijoSADROFUb36cGew`M_%e_R^?pleNHumDg*)^kjOA3X?}~ zg4cHOwH$nav`Aqx$*0ts)0(vm02G!ZmQbFY2zj3FYp)OG#@>lVnC(7T2eZmNAoLR~ z>PPWAPXZae0-CWatZ|KQliZldvNU<(=paUV?ewB4o)>MskhKc><48opVd^M!5!kyYi2$KaSn&|$0G(LeRGqyDw% zvRBUMNSyT^k^*1Drnu^B5&u}Gm{Ck2LP?~S=~SH7q+ z*=)F$9?+{f1lAKjS%UOvfH&c+;Ij>$k@-mki$m@sp;;*)cAFWA-?sIgbllxuLwDl{ ziQg6MEqI1e6?(eb+6ROsTS(}`YxcD(ExY58n0yCJ_I=rsE@$($bZM%!_VORY&dyI= zq4$vA>)}1v$MK$v&V6L~uQxfMJpe4)2NVx_L>q8Bj_A6zgauJD$mPcNBde|{MIwo{ zh$DRLTQ=S0BSkha^$%SRI`Be#jXLpXLCz_*6l7VucocSWLWt!lt!i%SDaCyE{+u?1 zmY8WXpzR|n4X{-9lJE8K)k=bWvE0NRlOw@ z-u<&(=Ow-qB>V}0__&M(E}P1jpyk$brv&kXZ7cZg@FgAvZ7vj)cVZc~{AP+{;QY#w z?@1mO%#phJtoB$yx{ZpV4}jGCceg!Z5>Q3B&FroT2uo)7ue9s@kgz|~k?Bw`fg%^r z=H8kfMv5N$>cYtx02uP4VhJG5*Qqi|%H&=xnQ~KRQ4EoLLL_|SCbmUSqfwL`$oYvw z)3DX5^8BlfC5GvKT@cZfLjmrf=uru>*^lu1geb@f4I>51 za+!8PoZ8HIOQ%JX4#lLFB4s7pI-J0n&*wl6pkA5V+H1&l?M#-yvnHrb+kPwnn|c!C zbJjMM$;|hRe)Pox*w`udiYSiUi&HD`wx*4=9X`aXzC@LbQ^Nyurs$2g)2-=nzNR7c zz(ZH7iRO(jLX8_sPuDe_X^h-c>E4(8hWYqAZWFaq#;5pe4kRa-o?n0+`v8|+kE_We8CZ+%E zBmgCxE_Z)&D+0_#K_351XD7huBsLmZp0V)~Eb_P-C0S9&VSfdFI>Z%Ug>dpUFm)m8 zgIi?4zB;?;FfX%H*$n0UI31R+Qaq*Zwz9no!l9t?Cy>gWjGzQ!5$r~VJ5B$6lSpw5 z!3@&;i-cH>#0Q=ZcTO+QI}dl+59ibh=t+kHBWcpzq-um|G;NP_ICh>dU7iQJL0;#v zoBs-bl%o&|m~1}8m_R>97*ATfCnTwox~foZTD9r01fcB0X+g3Q2J)`~8wZF~?J-4s z@$&MDrpUS&$@=-;hbNQ!^yd5iMBU6w?XT|Ie8^$m)QF^drhg|CVilX`A%EB}Zb3Sn zTR2(#Sq5P?&qqEPkDcQCSUtt$YPD+=2qQSAeOvZd9cv1Ph0NR(9ZCjy@qYQXF~ziv z!HD~{kcNpq1XvWZmP@PgESIiua96W3@SvkX{8rB=9&g2uz>6%rUS)`qA8{p^8WNqR z?4HGgU)9hIkK}@%^e=*2YH!`4uB1ff7~@zw?WQ0}N^);<2LT8K9be|2M%Bx#?}wQF zi-7HCkmD!wXP8Zle507jvp298b@cBgBXYNJHFIpx1E-W)h2J*hu{M}9qsqxgiUPPc zDi597^5qvF_u1Z~vpO*}6kHk)D+5cBcvtcPCLFG^0$lVhGi_h*&42@M)ZYO z!4?6RLBWPo|H+RthNqnFo%1YGg_pOaAS)3Won#Wqd{s;fd{DZSiSgm-(qFnn@Xhl% zIKB3VxI*HH-?Uh=-ZtWAUN=2|SI@qno|nFxpwgg-rFfyMd1CHmz^t>ahF*1515=L{ zKjyUFhv|m`^t6*?DE@xykap87xKl;dt#9uIyQ%PxXyqG=S>vCof6d6Z^`+j2_M3^w zB*ieN)nCILRaxzQfw>mvAUVi%bFb{Lf0srOV(-d_Xl_r7_YC|SKDhA}L1@gx$m9Hx zIw9d6Hr#cr{*aI5Q^m5gyj|j=fdWDof?fgm`tQ4~C}R-;K7%+z%m|F>gUpg7lGMB) zrQVA_#%fD7FvRaq_-bYtN3<-eOH)k;WBqG-fRJQ5B}t$gBW|FBQW2-TuSi;_K--eO zg|Ps+!jXTBI8m5HRXDj4dmcLbyzz=xj0OpFlera`26kNn#$e@&Y=x-EnS2X<*WVA% zvstp0W_PBQKG@qr_iATn+IEU;H)sp+`6-SJqd{#jL2RIZfxS1ix(hqP#Y5HOj<^CL ziH9A|cwW3KdN1nQhg_XoeKe zn_s9%f$XM{E^6na0dL$D_bV=Hz^0S{@!iLKw0BdIxdO+SRV;q^QqS6MSbcuo(6hzL zbn^g&>+%Kb$r}5f%5YGUq^tyctwRiT-r|9$<2ZL3dHQGx)~Zwls-6w}M66_wz6MHa zvvj+8SiN4kWg~!)9oUhvs+6sJhF*$mKX171XY3kgKdRjVrtjhN_gues#f={d^@X4#U@(L&0V7Km-@4 z!&XY!RQ+7eaZr2!PbP1d)P9#uJkOF*`3V@E+?tROkvn~rPYgv-icxlfp1f&6gUw`s zOE4>YP!(S?G5ci1cxL}%W;y`q$h(1}p59vl;W6i%o;A3SH?}#S-_^ zxQF~*gZqvnHTps$znDKO^I0~>88*6k8VP1xyI81ZIG%p>PwmY|Jq~s`Xx(!k*`VGV zs>>E6n=bJr3(B2XyA`m;^z>afw5!OJP_@Jiu@{XRHw8$;UvyfD=M>Y6jAhl@??V3E zB5hL{0xl^6&fKMOW07+O{OH_*l%B}Zkf@R89bM}3>min*h5{!U)mzHO@w)5g4-r%B zZ&4#dH%8GeM!6yy4;;NFTX6JcBk^Wr&=P-QS_0?aqKG>u!bS{MugOj4vsC9ZA*-*z zG9J1W%CbgzS7$_Gh^3zM7{166gNf_JLi&xug6&4t=9z>}M6Ex9&Yo)QB6Vd?l(XB0 zX^Uue6@#^yu*3;|02G&VUC@#NIYdb@9yzEBXbVooV4=uCS7& zL@Otcz||(yCX@C_#vIKrh|gt6%fXfneB-XpYZi4_=frZ*<#yl zhMZdNqbh8(%sq#Ejkc-i+$Cz=3~ea?L&yo|cD$nHA9oVeIdYB*|&zLsgJ$rPXuus@}Q``%@f&;JNw!z#PNanU>^m}Mw7 zEv72G%jxAyaFaD`k*K7u?Ir@g`o#aw3z!e_S<_W~0D!2d|Cejr|Gt3v54g-Ux259- zTf)xQU%QNTObYp=`t0=T#zdugBxB3Tl&%6CU5kd|0+O-gV8Ui%W6{*{@8=5}0OD5^ zV@}2c_;6{U=xdQ)fM49YZevaFI>^kG_7I%U_gg9p=hK&FYNJ2v#bvk8G|Y zO)XJS!{f=!K>8X);q;|nBPx7~49Xq5Cg^uJW2kNcCue{!Tc5r5Pye0G+SJQ2oC{Pv zGXMU3yb!Ffju8S(daqpC^e4ONq%#Jfd^{`$k=4gY@2F}5KE&t)k?F|B?K)&SbRR+p zPXp_09w^a_)`t3ho?;9HOxc|<0npOSil0^#G*H;QI}#0qxB~l&=>^FPp{De@Wg0yG zHi(tED3_fTs}zPTG8iqQpG=_0W*p}dw!i0d0+B`r0^s&IX9h4C6sU0yzzH}3Ot(HO z&JlRnE#}MdZBk(w0Hq}FzLXvKkR2Rb07?UB7a!YD?3}I;JUN#_gIe1@W76N#le|7q za`~LNYPuv8y_fN|K7-{l-gcG|(!d?s(L(sZoHau-{JrAwj>5^^5C@(%45_>$qotDk2ky19S(+*P7npA*8L*SUaZ#)W-ZU8dwr?{j zjY*p5JEOU74%U&&dkZi22C0z8Coq+lO$@EHZn#~51BQn{_AI)KDK=iH}l6+y=+ zrqja)WMn#KnHg!En6fL_5fj&6qI<8if4JYFJ2s$ts);K=FR-rEp9u_KE6KW)x7ojD z;I!(qZFDmJBgZb+eZc9qjdTjKg2bGiKdQ4XRS-QZX0E)mKFJUW%1PfF~qd3vL zgl31}(;}JLx#_oFQI{k&m}79zZ7bQQ(|Tfhq=+eVlOe}vZ@Wu4F49(X0(>jLlUDtQ zuvAubdHwu^daHj6aLHip3eV0lI( zJuEJzFHgCPU|ToS5MPs#A5<2a4k1bT)<#uj7%y#4!}N;N#ylb ztr&bex=uauRGvrvx_r8r2%#n-bW$^nDFlHt?7)Ya?QQrNR>zfHHmugwGv==kN-g&6 zPLaFG$4I)gah@3PkmW}0*WqCn@xoSpCfDrDnJrJRHoZmYN>0$X4bJSeWh1EbNDon2 z{eaLvh|7=n6C9Z=JD2#M+1)<1KMg>o(aUh9u-ifLSHhRW7t7o5dIo?zf{b|Z z0)i3oV9QPpEG*GE#*fq8&SBpm_MtzqF;uq_UfZp_jz%BFxI%__HQKMPN8o(x_AP=P z>4+fD$8NM6V)jR;W)L+p!yxQx;*I0leOGVHYF>WUw6P@eo}PymDlD%Gak?kao})1_ zQ16S9eZa%nMF1jMTYGxYoIuaiR->To(43wFB_S7?073J2MTH$}MmRLnZ`<8BQ;>OY zH(#VtBRx&4E8HV6&{7LV7T=BSJ0Yf{o;yQx#IBaMB5>{|ox8r)K*g}DXl;<=GKJvZ zNhl)YKAOTncwnp-00O`^;MXDqXjTZUf5Em;Rsq9ma5P~q5c7)+u|qo@y%Mq7fV)xB z!TDl<6hg=fK<%Xw!czm(S4Ew&#!Tz`aB%$}j-k_d_2NcN%LWk`xc?ZBk(!ZvlPMwy^*?7EZ+8K!paD%oZ5(k0sW@L1LGm>ObjAvJ?1Ba7}#aK^d z0r`XAlW+;p0PlaZMQGH7<2SR>TE)MJBVe^Z6(NFu_>> zXhZX6h+k^1SqQvFo?@2KgK7c3y5KiJn*}$-=yU#w52n48HE;vKY(#S)3{vbNmaavk zkHz7MpbPh*-C^~S;^WH8&j?~<-wNl6&W&U z4$mz%KEQxYpp6|$u$`O^A$S4OELCrH=FT?v6@7oejMR%Hb88Lo!|S}$@mjr3?as#c z1D!2#q;!ORbwrl8@k=&Z7Vmoo4l5z$cFPJB(B%nB8)W`3qV&j6h*~)O&((p=~vqq(WI=~q7b2c45XF25A7 zX!y6$E(x6coS=*TycJV$y&P~jfmnMFxg%VNSMSrfCB!p2+p0FgOCBsnO7K{#+!mp@0OkWt}|R zhU6E-cc6+H(_G16;=*B0367v5=ndHRq$o8}vV*^k6x%q+WHQWTm*WJeNyM*L*e5CK zeanWJK%`TUD~*_=>2vG?^_`PfoC#n zXL>d0CFiLZ1^NMZdGQB*ZI4zL({V)(sWKNF)~i?UThUn>rrqBfNDvhYfsZ5{o# zP2gY=X4lKtK$^^*yuPWC|2mjBi>8{`Ms%W)YOXi-sYd2x&g_OVTj% zjnxRx(Lw4Fh#b0u(r1f?5la>V--+!SyBQeX+Z&#MEoYJf{sgaL$GwO5H2C+r4>%Z~ z-7@`@4I(=j`%TsK!9>Ot=q-gn^Q!`65O5Wz{U||C$Fg9r<43FXTz&8D?G&H$5!ujQ zVaNTLHSVX=^=WoqD-HSGoW?4n9OjWkgPe)fvIFU+PbM;$;7T3BT$JEhVa|Z>7NDe)e*-)^G zVDn@oK6s(+DGl7T!6pfh^Z#|c@kNvQGYed=rHaR?E*WOriZSv5`RVT+s}mj~paMXb zUt;b~XSh_aFIe$+f+zi*$-#P>Zu07LjRS%$jO|WFK3wyn<$yx&@CgFmJ!57|n6Q~vg#OC2OdCYt#X*X~NC;C&NK&8MS|v*yC%Xq!yl&0b*l$$dA08F6 z>GuYeb?6`SnHaOWVbA{a0VHFPzBom~rg~ZR&qA5la+Mc~k)TG)qZ!$bC6k4ng1&U; zgdfks2s2cRW}PDei?s_OhbyyV+DNHtUwElrBW`LAlcO=`oANaq_3z)=iRL;4PSda+ z?L)BbB?g>Q5JBHHu#k+u)nw*sSRky7ZDl;>)UE06nAZ)7IB2|0HQIW%kMomw3*zS` zqcF4osx_VMmK5sx@*kAzd6%1Y>LEbb10X`?F%rh|1jB>tzuh3_!Q`)9e~<8(n+ji_ zo%`=>KLI*H;bn0fxA}ABr`bvB8(m0pcoqjl+^AOFy5HJDgl61@enHVaM)&QZvt_s< z=sEN&Lz|mp%0FlO+fhMFD2^XYE2gskkk5(Y&;B1?0>~b4b%S%+jT=tc4Snq%{N=;W zI(RZGxF#;2l$}ei$>i3VFT9n%pliqb>m6%=*%X zSN#*#+>vVNsmiHl(}E7x@0jFeGxpc>{NM8gY2QZhnm8}RrbYX6DniujdbC3UHWD#H zG*uB=l_m_g#_^8m-xNCY#3?|9+iBk{>aS{C)+_BN)O-BuP^qdn-CuBsZRRady7*2t z{@vcZb8B--@^>`9QVcnzfJY)dw*ygE3Z~w0=i(CGrjJz3ic96_*ODv>5sN06=};`m z306XKjT;NRE~m@_MVFpjh|I$-5{7CYODg6-ZI6*5it;vGhk^rrRmGd7&DpI zt$udvrm?u1PYRb)j3q%8>WG0=9{ouIafO{M{Jw`q5-scAELTRT?FsljRQP8h?QQL3 zvbtM=z)ajZTYRN5H{24HCDJ6~Pun zPiE_+Foe>I&q&pc;o5}(gA#gK?n($3-p)~vB&4nT%&@Au&$RZLP|Km9`y^~|huh>w zM@HvSIT?A<`mWOGIM5rgc4HttNx=c-LBiK0UB(lbS|0lY$M_}SP#;KKh_nCcH?}hc(5X+KaA6TzP2dd2Mq|caz$fcIqfY z@9J|F$}A)r3v0w{ik9sx(OD~hQysUFPCQCQ>9D&jS545lbe>FzEhrA3!pG$g5@J^9 zTj$8S!Sw{*;#`w*#U^J_yU?a&CjELYAD0fpnOMDXEvHV9h=`CNCK~T**ifOV?Qddd zn~UG=y1Vw=7rB{9r$+`}h8I4k`9qS|h*^lGT4Zk7g&7bFMGJ^r_z?1`SCt9~ZDqCC zbYHckvVzCAiWHdO89AeD)q>wV741v78qcg^7Y^--KxKjG^KGxG(6a8O3|NKEVdJ=- z{dR>4REQfNmB83>ZOJeInARcn9IrW8o4{{umgH--u%Ta__?L<|Z(iXl{6yYPSuKP7 z)kT_86Z6n_KI2neB31=D6XxLXVUB)`tpqTfPyt3ug9PcT_*CLDM`!_s(y#{c2E=sc z7fF%i0@}tR^$A8ZweER;x?hV>tOV(8R-N<`F9#7q-7d z(5lpi@-5uRBgmJ(jp4X?EGubbFz5TDFAhcyyj$u)E{#Tob&m=~ZIiQowEPH|WX(!4 zr1xZlnYin+Ii55AHjdbi=k}z|mNurxUibvSpVltG&_fAkQ3Vz1gsyqr>fMsDUyMQQ)Q2`YMY6B7o%#s1ShVx-Ku6mTJ`qOu- zO}SKIMG&&`HPaAg=ATkag=&He&N{*l=+975djkP(S3MyVE42yT~<8c(gLcl_8}J`}P+Rqm0I*YNY}6vhYqls!0!71Twf_T--fx z$N|_>Zvk6=ncr0KFad9sufs4TV~BI{i?|85;JLLw5pd48x7|x*|-f1 z5vO*jl6w#=E=FI&`Ls#T+5)5Y?5c7~{Q$Ek*8l3OSM-vWm}lB9-eHy7q)xe#;f-^p zH@k4%Rda|cR5;we-V{ z4As_i+f!cu9PoFrW}>9_Jf(l>*_L@YP~5!Fq`I)v8wXGJRaI+MjlH8?_|8#09Coi? z?Nm{+=QmvwZH0x|n~!`o@!zS7;aC=ToJLC~p%%DWB`yCG03dnq$OV(juNeboO2llc z$ATgq>2q2P>=}C!6wgyU@9>J^OkzNJOFtv#(2GER>TAl`@84HWu&L>nA^?!*6(|PK zkEXOZ3~~y%b6F^fpuLHW5h6f0r!LBuQAf5~F{@AQ&`F@rd>u$(R=&$CkdF&x2J<&@ z9(ipM{xdM;wkC{m0OfmAZzeu+U`-ZW#B`NbjQ3EkF;q>K zNC8wRF;#6wwYJKEs|sh&QBgoD%!F~*swlFgb+Vyv6g9K_BrCs4{*25p!I8rQ{-==$ z-$w#kn5?=q$t$L)7&Njz)T45mc)n0w-L=yKUwh$DJrDlWqyaWEJBud+1q3bm1jry> zYawR>*Cr{{a*o*SS=rF)EBC5~gd#>Qx5S>L0;&ri6lS(ybOOV{)CfnJa(OntMaE9xsK+5&ZVu5kH7`?Rg4Z0!Nm5Byy{CtRZ!@20 zNME*kyvJd=>^Q;Qn{&M`ilO>wKVKDvq0IKQ8$;c^l=qoo-410;k|TGP41P0j6oqjk zTyD0DM4TWfJ@grMtqhGE&5&wb^(-BfKqgW^Hh)2-2Bk!yhTYj(9Ir0tV^~#1y zb4`cN;-x|GP(@=#_3Gw(Jo!i_PoyW5<9d}@aFI$DkCHQ5oG&JaWlg=IV?zClwEJ;f zllP}I%9gq~-cE911!BWLiZ#~x@y(G5DLGrs98!Vy#b-eRN?D7F;57IWGDt<((F%@r z(pNdeWJ>9XB2A<;Ovh}Ls|ZJLk!$|LNF|T%CbKcF=u4k=!w2qL(XbAG4U@{oW}l`K z35#41TdsKcZeh8aW2xl!X?QIQkJ@%}b0L+!`Z>o6pc?EZbwnuJa=Us=jFMuKf+cBX zyy}}if5wkH9e4SBSPRxemqJPK7Bj_)x*o;vRv#NlY!TxaltfB_BOFk&f7Ot~*jIyr z8o#IRpnO28fg6FI&5IQ}>H>eC?U&_RJ7VO-9^ZjWmb;QKl2ST4jsqB|6A-v7eimTT ze^?@x7i+u6#=Yl8c}Sw{OBD`6eAzO zM~gUJrTe`QV1c?K8QWt5Twep~b)425_*ZOS5A&3lA*&j7^agulw=l9#t%+qO5Djpn4tBMEvMVrw4p(2%M$5KH|-v+k>DeOoj>M?uU%Jj4g4R^ z3i+9yDtD#(VIh%a#+k0RQvpn%WwpQY@*jsg@Q!26e$a5KO=bZ~6@S&3ltA&so*%eAtmv;&&zkty z*-96M$4eF;`r&iycD_L$dpvUuW})-6b3Q#j1nxqxoN+vN=aM`R z=aD07iEWzPxnqj*=rM;(|9bcy~zaV8lg&h)-x!{p&wf#IX&p zhSKb<=cNF@eroqHQ$x7$swIw;9Z2WHt%K-TkD7?eY+Wv({zvtqR4C;{;i;zKl0?Fl z%=K2MJt5@BT6;XOdVhk*7UwkC^cIO+f~TfU^tX?gqt!tQx*)@4ObJwE7XkP8Veg`l z8XC3@ujpMGveR9#A+HeYDq^y%u;yOjl`is0_CBUlbN(knGC5&`!U>^fT0Wql3d#_zI}6~@?|+R};uaOfgdp*?*z$emyD zgh+PS_L{vC2mT7mmf7=T>7}lh&B#A=qTKJy@ff|Fc7(z0i>xH<6qFzy&v{kl(ZcnI zkE^oW6s8m(Q^||B`@yWC?S;$2o8rSd1TWWykQy+)8yPW3jvk3V=r>d#tKoS1dDqDac8J}oM)A{Iru zSWE@)7s{Le9yVVn2^Xk3E<;kb5~ms_wLX8sbL&2sQgw_)>R%?vsvKSQtut_^F0v9K z)qka>DY+rK~DbaID5_!*%+lifEv-u@R)!|KM#-vJN+04YcS z0G0p0o(6jZM+2Mx%FwW|bv3ZIFs89JurXoy&rSbdmqW3NjNJh%eD{T#bav3ez=bpP zW5Y16ae6)EYJyrqBA9w#9L+jG9-L57f{UNej=bdlmi4@llQ=T$+i^GB;NCwvw(8#_ zbaW{EL&~0cuCM8$x`_yUceZ`Jn_sx;_4y1scJZM`9=GHp=p`QuhGCf~JC-;?awAo3 zXKk79Tt4q8sG2BeiEtJvvCZsuq#8?RG2>j4u^4%*x+3}){h`&0if@vA5wvXv!%$MC z;H)T9Uai8Bo$)Sl@>&<0K1>IiR#2Af;!@-eT84X{Ktb>X8`F=0wK+#!HtDU3uA&02$_C~!+oZI~3@@Kp;aEj^4R=d!RawRamYo`ej~NRK z0WhLra317y9COwgJ|%J0o^CJgl*qCvs8$wAE_1p2STeVO4B|l7~ zuUI()>h`fzs((CdDLqOguA!v0762@8-w`Ium62D5py zo5-m8{w6zk0$F|sxcN9sZRDc~SE8iuJ#a0JYik@+^pyKpHR|Lqr~7pEh_l>t)2V^q z|9RcGSn=R^KSVeSLVD;Jvl5mmVest$R!5dmV&joamD&J^4b?kRu#%$*N+BUF5Bdx4 zu%YETR8>(H+wu1KXvjQ*PXXXE3mo^E_ys>LdLnPz&%8E6V6@iax#a_S~b}1l=%!u8;e_hWG*Y(Mf0st4b>6u z_Gje=`PMQH19UQACb^!kI!a;KU`gfar1(NBGCdEYrN*R1>pco=%T@|v-8R(w8z%_G zaE0jRe-U8yDVy_x{!Y)6-ymYu|0~n;e@L>5RdlQ_MB#l_YSFdHpGAgj^67et@ujT1 z1X7&c)Es0e1mam|0*hGQ?IBV>UuLSZhh9?V1iyBzT}@}RoJ?JLa)r!eXR|rDVQ(kp z_Z*CS9S+@oI6&wB-EPZ2=b{G;j-KDz>T!X*P%vqgDmn}jeeUi zob1*Myh6Y?Si0flOx-~?+IwBGA&TphJ?KpY(0P%wLkh1knP55sjm+dq28M6dVP1<7 zN^7nXE#TzWTNs_oN`+u0;3A<}-o4*r^x>ZOk~J)-{!FjJkz10-F&Ln|JPYSX;{9D* z?@wAEtvkyXr5|Xk*;L(`ABZr~NfUKr!$ay1RO{(N6lnezcDUUJ--ng`GaMX8OG%{_ z6Kxy1-)!M@89FQuF2is-gY5ES+hv6g2Dz&_nA|3e<(AR6Q7|ujVHp2LattZLhXihX1Rj#GJX_MOPg|D22zR=VzaZ-R6anW9CjB5Bx5Z z%An#lGvDRRD0}AC^6^vPAN?016?Z0i1=J6)k}huNF+`|-%`k>9-PpZ*5gjOlDJCrr zkpSU_MDoh0Rvrh!1WAmW)21GG8SoVkNlH=#^vW8^v2Or~Kpeqz1}rzg9_!xl49I{l zff6v}J&9skvE)|#<~Xb(c%)ix--_D6PmX)+fR8^Zk|GIK zM7Pfv1>9pY|HrYfqt8~OfZsNd{aclGuc-4c=2T9X|hWlI$~>_2No$oQAi5F zt2SdMYuwbNJ{^ZF2mB!; zmmrHt&mlBNM|5YtsjZjkgQ15_9A4B{ai6DKi!-mVkrEG8^iWXj(GN_!O+$gVR{$DR z-UiTTtKt1pM4MR_=sa(`O6uT32ZWe z2M;ewOQrd65Q;Zk??(@@Z}yXjTN{Pgj$Bz<(6EnGgxp+T#t%CH4YPFtjc_?FFZ+h@ zU1wIIdOCo|%=`2F69dW~?~?3=f>YRHKL_xYQobKTG=S|q537)eK}pXNz8pAt%0S?+ zglHXTLb>Z(TCUzhWTMl9o&PBTZMJ=Vsr{Wmxc?XUjq!iyH`V{M;1vtBQhdPwA9 zX?~gU5)*LpwS2lWJ{zR#{T6*F;Yj(tGjkL4QVyj^Pz0DkvTWZk$5W4w54W-J)XS+IEnGmp)l!~oN<-BK}OKm01lHg zQhMXM6H~v8Q)2U`sLPK0$m8Q)7LBo_g?HxGM>u}fii9_r5W>PGps0XAm#_Gtcl~f6vALf0ap(g1Oj5Srwl3) z!=5B31kk`MhJ(#X@G%N-pinpb=0PB-ggy^ntMc;fmFlm0zn2FL zw@U8}pz#N17h6p!G3b}-kG?VT=#wX4yNi+`GE5vDWZv8FtX7YwZ5o#^h^2j=-1ps< z79zSZH7eS{Qns?i_J%1XZ~@6%s?lR7p@d=FFz053$ISoj6cUY9n2@L-PVL4@>vT zRS0>j*Eubsco$vH`mYT3iXXkN0R^8^EF&8LxID9J5T+5WN8DF`s@QOGjLc^YtJ7KN zjP+K-E+%$rci@k<@Y$dkfwKR#@F{PU-P2!FJsmj0Tmg}m-7LHGyGrHGIc?Ykr}}o{ z)PGo@#u^;p*H?d)|&S*Y2F5@_Bli zj`!+AbNxQg(C|{0d6hBUm884QkOM1#%&znPW!vUDOU#ZFJ6m-0uzcjRwFGog7@RVv zfpKy*1-r^UmyB=xO7>c=z1>;Ah*p=s*7M1d)>Dr4BeLkd$F%;4Z7rAFxIm6B^QI%h zeHm>Zq>5%$G|ZNG_z$oa=jX))VkcainOQ!ze?{nnKi^JN)fI<$o_bPO%*HbqoOpc* zmo(!3U0mHpUKeXT%M<*CwVBN%z4?JCk>pIx*2Ej6{=aG+U5NdblYryh4g~&eoIjD! z1lg6;HVjK0XAdhSGWB?&L zF9Oawl}x4~XIgMdd;_{m-ueltPfLbMGekklms(cr6~RaAgk#u)?fHTC*m*d;PIE2X zXA(iT6wsK}(0^e~Go$R7Sxd*Q#(&^n#4oG~+5rFl)5411eh3qx-^q^`NV9bfq*H@Z zwZLW|AP^_?&LHnUNtX;JPE){Va6hybXaIix5T&OeKDbPvpHNj%o}e zlfr`sPEbY=pIXt*FO~F3eb0@Lqt%}lZX4+B&l=Uf(w+cSgDlo68rafY1rfZXj|2wH zl(tqJ_dkzpgE{c8)nFEYO+#DdkwP9*fgin@B*}8lq!(b(PK9;~kq+{hBG0b;Pg;C@QAwONZW>CJ0zCeA|xik!=Y$PN2{&uhVHDiM)vNo3)PE67`lqLO>Ln zx~Y>hVRj?fyuG`+#c8H*iAdmb3D7WG!k1x{~b7H6Njg2tCokv1lxl>n8Gqg7jbM^lLT5k22hFVKSNGd^0ri z$04^#2=M7=EJ}9+^DuEy_>H;mgA?FS&up^siwDc8E%$^NZ`AYSk?ip4vEF_!1x_*q zzg_)GjYp1!=Vo&W#v*|o9@Nh!95>(B-HAjS8*LZEmqjwt`RgEszc#{$jD9>xuDus~ z_~9#Y)eGDI99Pmaetm<)005+U003hD2i`6Jw_eO&e-9R0!p;*_opiR4rjce+awy5L z3bV*~S0Xu$#M+%{t2>b+xs3FTy;+E-^~B3YEgk?^8aQ4;_F>I(^6DYXoH=s`)>gFW z!;#cH)CpX?pHE`gR(3WXjss%Iijtgjpn}iE@2)Ia(C!$K!(mJL+Qv_lwv)A;$yK+f;D-lEvE@xSC;dm=Rvrh+mJ-eS%Lo=C?npt*C-UueOEM(ohS;VEcDHJWuP^;r0AVZ&om-NVjBb`owH z^e$n5W9+DL7oJ>CqT9Y~kFb<}VSl&xnB_h>!yJvi-2w8De7vFL&`;n*h+wp+z4Fj1 zpt7lfAtY%W{XvFZ2yJrGTcAC7o_+g-O@asU8N|CyECM|NK0FLs!5FBt)_wIEfKIq= zm-hlcU+&kr%VtpTp405!8|>!Tp^ezv1{%#1G(4~DL^t5O>(9rst&2$07l<5J@a~z7 z$$pR8SbfTAUgw&*PSck{^B?bdtCx@cE;3Ftw9?;pEa1nCErHT4H{sF^&Tj5=XE|&@ zdf^vue|}jmvuwa7>?|&3=bln_K2)$_v4fes$U&Uk7jesBkw&)D zCR({n9tVfDPWGEt(3zXEMZ0WPF0-pb&R?@n#Pf%%8~*!EMrrA@Gs4VUsBLGc6MZSw zb_?L*@x~%6tXLz@`Qv&upe)tb5)dI!LMbfJxn7eN&MSKW{M_x90np3`=9e}*3b6kv(WsgH0I@6CQzy4(6m zcPs?vnLy=U7~IYJZCB_aNd-$hwojg}l|E|_K|mUFy>m~&1~11|R#Rs+D=WJgKOX0o z>mStG#ZfREOl)?bknW=PgI}{mllCYp7gtk9ffIFx*bP@$uQlA~+>Q7%!F}_##Q92V zlD0bo1lB1T$0rDVS{~m%exIb{F zPtkZ$CD8I8$yU}c3Ewq4%Dd6>wXj=fE)W^}rq3hZ=b?G8+$+9en5&-fUgUMWgg4Od zWu;wV4t}dUv59xzyhir=d{Kks9O77pa<5IjJJ_*uC40$S!}A;c)p)^xwq)RMC3b`M znzwBzGx`q?P}^A^4wt%U-Dm9rdrrdpz*Q@tGxfV)UTz(?`wM8%VYTeixW~8{ut98E5g%dVq&$6^0C#xYMvBWrc3MC-ts=+}-Iz<>@XzH=$ym77 zJ|)HOcI6amm0-nreR*x3_?yim1#4|Y@_72m_)%Ir#i;y@wtbi~Gpr?U+dSyF5Hv7z zS^XO5Q~~nZ0B8t_$VmMN^*?lWX<^ry)f;noOy_VJe@G~-x4E&qJW>p=t-}lW5<&{z zr42ZU35T2YI)3yMESVj51J-_X-i1GtU{!nXYrgWJl2D5>DiD3}Ft4!t_(BW3@LO7a zZ~@)x;j|v~-8Z?fS}P$YLBLY6=6w z4ExaoC}m;1QZ6k?#hdt_)PB6=Ir3=hgz>nMVd>k(^W&+vzp3ci=~>WEx|XE5Ogb3# zxS)o%qWL-ijksP>t>=fmVb77_%NMOkn7SujSsD?0Uw`;LxnGbn!Q7bZ==4`iFxBmF z6aYk7SpJglRHOs|1EaZ2?H$C~dtZ?47&;|hW65K>6ZXsHwpwRYjUpLa`pZFWPod+0 zIo>2G`~5jyEeIxI8d?CtpZjL92{cDb|9vBRZcn2r0%tXY0C`?cqXbPHoDanT&0>Hr zsbApU$KJe#f<@!D)BQuEt6l;ggp4_LSTjvR7a%t?H6|jG*C44Y?uF$2(5E= z-Vdg0O^tjNlikLXNd{+SouFqts3jw?fF%dqhZ;2!{e`{20{571gE<@g2RtPxReZ!w z(a5v`LiCcVNEd@cvwXY&4Ka_tu|e=)`L|i{n$-NkQFz>bK--AA#cK{I;T1VgAcvj2 zXufn+HEe;0x^5Jmx-E}Fj)jgBL>w~*5R@WuRdr5{Hgo7TP8<*36Uj;&v>1ZqW&H{G zKB`zt8bs~Z2>K|nyZ~P@FV+FSlP~Ie(|mIt2z!A2p{R$&`~_U)2_4)ijp<(@YET5Y z0hn+k!Ec?6BOiGRTNrK~;hWMw95H6sFlcB^)H=V3)~@hXRu|ucefR?%bU+>hKSgg< zJ)=Gy^!TSF3jA3O!QI>~Op5rJda;s8fx9IS@olhL&k9edZ+!e_j6K(|Hp0Ylbq2sd zj*w)O2UcYDy{zQpWTyS@g{%cYiwKs|?V|bbK950G`n#Lvn(b|{hcuoBb?(tTYo2VN z)tOmu{Ub9KV!>#$xgZ0%j*M zgf6F2CCp*1mKYFQgtkP;N{4VIOw|W_d(;tnOt1KEde#X2=sw=2ZXK$4$9Cy5iU;CB zh`!fllH_#T&jrija&<7XiBn0&+np_wtlDQmA?QZRN(`-xqYx?_S{ABi)8=(Z#P^W9 zLL$3;Af`toyPkX?9}&gLX@~yCWnA@?eKzH$nANW+nZ|AIzDbP)&z!3}mX3mYH9a1a zP3+Pf*2-!h8WmydqO}t)gaKePljBMR`eWd)EenpdcjnCxX3WO#oJQ2~9_D)U5{hB& zCPbS>6ob4<-X|1;Iraiq;e1EUxbb!Z6!!y~dfoghMqRQ)(LCJ2^soRkk*AERvoITc z`YxE`)dbv=5W;!F+t|3Ul?&)$DlzZgH%>p6z&h*Q%5tny*mHIe-+ui$5EpfHax7SN zP%!$xrL^zw0E19el*|@lLgH++xz`f}hI6-Y`BB*!3vJhk**l)|Bn1zw+8_si(5&r( zKsUUbFRy~Yl8+H+)(M{r(2Q1<=8^==q*)Ke&OtVvO>nyRK9#GB^;+(rZKclp4VqPV zF#9D(_Q|_!V+;<2I;POnl>D0D76GF6kS=M@o1HPm*lZuQ+k`MIwoj`4)c?u(3hi(# zO8EGUn4O8Tz3ZOPJM{#>$ z5))-gxPLbLHcWsYjBs^v=fX6+r}OrJGxVPiZzbl7Xsnsv0EEAWq>Sf!N+^oxyP*cl z>r1TkDa7KCIi?g28%% zT>z+ign9oB6~#>qn<)Gvu8i6&0@}3YK@VNI&HYNlMdon#OjFU-bu5C!;^MVVOL^eB2M#>Xy&a9d-3Pc>R$gN$%pu~f8yv<_ht zjTUZFNHT97gq%V^Q2ZN5IHeNU2k zAoi6yP*XWIkiRIPKMV0J>+({1XTwTghil=O4?Xw4=4e&W$W#R%D?)Z%5=4W~i56(} zj2({s(OGa4XmfN?Ou2JCedMuJU;4i z58opjl8z~%SAN1ttlMn++wz2SE|Se!bQ__O-TqRlYoEQD^?sLO zHta~qh&&Ha<;s8<79b>y^!J({}1xTem|c2>;PN@SjVUFHrxvsEhR7 zv4i`(G3e{X%yiir`t@A*|E|_r%y3zakM&BJCR{>xLYw5MYej92D5cZRlN?i|%`h`Y z2RZTpRC^rs$_H5!(>3||W$Ucu0UxhwB`(tnyX?yvbTjdb>YBme#ql?Kz zj53f4Gvo|lU>xvTSl;LOJK{5d>d?7$9oLW>+-4o2X|ML{l&SqA1RVV)Gk{a%NGcP9pDD&1piBNUeoC4Tw_z4@eLNT z@Pe&C1>Q6Mem8#R26{m}t1N{UA@?Eac};V%Mvl{1Z#X4-miC9^IPn#%onVwJC+$@s z>(I#N5ML7uz$0>P62IOh-oN2`Cf&d1`LWP9c;52Y(p=dxR8%7eT;UGcsYLiC`rPRjMq_ta;C!4=Bo zLTS2>i*NnY&h~ZUTX57Q*}YVdK6kjDv!u9c{#e#dpgSlDaVd985dpnmTYQt!QeT)O zx656Wbx~H69cI&9(!}_}jc^4_sh@@BTGULEm9=2yzW!QRe-u28$v}eHPTL?@D66+ z2+Sf3)RYbi5li6aE<;1CHPXs3Wee41CN5PVPpxtZmD|I!;&FV$#(^Yws)Hb~_UDAb zY&Pd)`osmmMdo$pHW{Aj?t`pPnSh=xbn^o%{SL6XKMc)ur|A;37)%h-sa8Iq(pbzD z!V;dv)`2PW$>5Wn#W#-=6`}w^(2N%Rj##a0VZ)W>b~qS!UCHwj%2$=MXl~U`Q9S2; z`nN|JqrzUXb-fJ3$+lR>m6P`IXdQX>d~U$pT0>Pk<_Nni;2O{4ST~8|$nN(Ggxi7f zVm%GKQ=DwD<10$=^9&cxAHdW@OV~}JZG?m0Cg8lfOCsQ^zL=pT5Pnh=yhuN|OXX%{ zOfTJsjx~;{;5k@0!EWx35fuB}RPM5RHC+Wi6Poh(VCT+1W2#w>c+;h z`LYe~xqvzcpv=5wM+c!RCP29$X=;gp(8xjM@un~_#!Pb86U;PkS$&CQps_{nQT5G| ziUA}2ZJ-)0Bj2_eISs2KSSdrFv5&*lbj41q?4500(DYmZ9U!_o?^9GUOV5YOW7F{b z-LhlT12idqnr^!1fyx42$-gl%KS6WR1Q<8BkEf&q1+mRsqPmUS($Jb!Ce2yocK7UI z#y9LgZsuu5cjX-D`m1tKBr zmm<;s;-m`$&c`QGSZ<9kb-N0eWZ~<5h#;Z2^F9Zz9$4ZyF91S;)Na9+V^k62IK}}b zf&Qu@qt78&Gc}75p%zYE2z`QC6Izt5r}a0rK!V-2sZ?zPpmYqmk;?OZXSA)=F|4|2A8J zRfzW=bR~!ki*jj0KGcm=7z1pzd0&LOOWM-CbJ`v0lT4(@CmTpKge6ni4cy@cnX0Bu z(yIu*gA-X@#8Wpgb6+m%fj7=7VqnS2m$TLuFlo*-C;hQ?5O>Mmb$6|YkWL}LmDgq9 zFIJ8j46ruH&&M?tlg!-+iihPU&^rD7sFahF9YycL{Hoyq$I3;SSdnQ|W_U&s~)aBkd zWvpM5ayO9AihJh^N$y3crLr?9DHHn1s>A6yva}1RbTG0(-vGuzV|SF92~c0N>~zW--H4(4Q!XyVU4u zh&yMgfxdrD4Wd)P>QNFsL5GKWyQl&qtn8Gl1XQr znMMkH_1P$t<)F$mY_Uy2v@rp?G>RXdfLlRBli78rh<^1I?2M*RjPK^Y$cho?HWQM# zs_&GXuXTUf8t@@hby+O!8ju3v8k2_>ybmrTAE8n&HM*QT{O+uXeAZB__Rqc^l?1rO zFr*Cx>6Ws)y0&@f)kk-u2l8R9v8LKVdRgp2pL6spA^jXY*JC_g&W) zs0%YLBTf*@LoZL1-am3rf2hc-44j7U^D8>FN_Mkiy0=^uuwGP*Lw^A$=c3;S-_%8X z%LBAIWrNpFIo0z34&(u|GT8|sQWJS?IPBZ+Lyi;$8Z&op`7;dxz8D;5Kc#cJULRSe zF?7O@m+!x_W)6?lpd@P^f$A8|-!m`tDTp8!gmMT6=Wl4k-tkJ`EQ}T$Ag%3Jv0&qT zrK5sT5Or?Fh2Th`P>vxbBS42S!NlQzV0?@kK9jn}01UCGPW_np*1RiS1MwT+Fc?a* zxV1AIRi9YVop;%Q$Z$+1j++yBq!Y=rdtZ*+KShYT}JFTPTNYQ~5wXzkf;JEOJI$mD53zXvXMfmD z5RHL634I=LY9A|{Nq{_6{uOQTNV!E)^%sOGs|Bqet2hEr>BqiGS0q52v1gs+Mf{q< z6zDS|ii)_{aF|HeiS>X}vnLDtZ)%OT?#_nJ@P$|Bq)SRaVy1q*2{6#40n=- zD<$j{1@QtbwSJI!f3Hk%`_wDv-QyV@9tIW1#pH@46f0ADgr`y)H&%}>T@t?9evwXh z2_9*DfJIWVH8KgT*{-}c4I+wMIf@(!7Ib|OIrdP0uDd$1_kQ+0A7-YDLr7^DLj&0) zc2}K166Qxd0u#_fKl=noffe5P&B`Sic-;Sjf zR)h#nkr<4vJ=s`KEHsEjHmp-gILGqyvtm9cEE0=lc*Nj~?L6ZFnA<@--Tp!KO4aMUOavMB&c&Omr zD+@oM|2)R}>aH8rX#Cgs4v%X}M}qjKOVPqY7AlJ8%2jRu?S97&X6l2!8BE9ItV@I8 zA)e3Cn#z@IsH!uf4TVM4dAY_V4W{LAXSsO~%-aJwz^@}9H(l2DH@CyU-k^nMLYk;Y zs(JTrfn*jydJ+8lFsd$#R?alk(KHWRlZDfCn{%HThL7gBh&!D=>)$m=sHo=$);k6h zaP;aPnWnH&MoH(c4ScMJ+MHym(vY<Ero_YWkvJLM0ZQD^Oj18rJ=PV z?6UJa#O`8H+7$*hK?E>O-Z7|jb+a;=utpA@sAg^16i;2Qjo;86)p-iGQ%6RVP+cB- zTH@fNvPBRp4Fzr=-ks8_PY@jYQYQ``{-RO*6LB3S>i<0~9m56>xl z)eW8$L1sf!5`An)JsPl`@%4Rb;^x{|VfL2zGqu zq>#ptrZEa0FG?@teC~J-^em;o{g9-8TWWQ~bU*G*jC5~GMF&#f-Zf`Z70hOl zN#?u+-#j;%)CJ-x(6qPSIg5AT8p!&vwXV_5SGiec1|9ICl4Z0Ic$}L{R5d zx)(t8_RBGOD_BB~Qpx?>mDdDIiElVGdBc*I>+GfVxick2vGvwFzxs^`ir$~g@o8}( z2NP@;9l?CSAD;;4j1N_dTFOjTEVGHIbkL8>ipjVH_I13hRtww193*}gZtrezAt}Un zSp&P)%qD@lsf;=`^e;x;Qm=4Z3Kd)QRgGQ8dF4^Lm$MXEfbGkPh;<;=t*T?5qP*r$ z=-MXU)p)1aRK6bI-QV5yR4~-eTS>3qT%pcFeBhtq=4W5pb>JZ61nU_BtMkBa;I=B8FPlq;<6pj3KOYTB1xz<>OEca^_A5C>;N= zbQ1%KHluK3&bWLsg|ihzCbfb-OhWM_9=ajC2==%_q1tWv)CtQM^|geJw<)J#-J+

    {8dKD^e^TC!U83|3&x#O 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 z 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

    &k)#*nNYJxJrYOX__K_ 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 literal 0 HcmV?d00001 From b78099fedfc071814fd8e1bf299427331572bb65 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Wed, 21 Jul 2021 17:16:14 -0500 Subject: [PATCH 0723/1594] [Rust]: Initial checkin for a new Rust code generator - generates 100% pure safe rust code - no external rust lib dependencies - added gradle target `generateRustCodec` - created tests and benchmarks --- .gitignore | 4 + build.gradle | 48 + rust/Cargo.toml | 23 + rust/benches/car_benchmark.rs | 189 +++ rust/benches/md_benchmark.rs | 122 ++ rust/rust-toolchain | 1 + rust/tests/baseline_test.rs | 260 +++ rust/tests/extension_test.rs | 261 +++ .../generation/TargetCodeGeneratorLoader.java | 18 + .../sbe/generation/rust/LibRsDef.java | 287 ++++ .../sbe/generation/rust/MessageCoderDef.java | 231 +++ .../sbe/generation/rust/RustGenerator.java | 1455 +++++++++++++++++ .../generation/rust/RustOutputManager.java | 92 ++ .../sbe/generation/rust/RustUtil.java | 299 ++++ .../sbe/generation/rust/SubGroup.java | 240 +++ .../sbe/generation/rust/package-info.java | 19 + .../sbe/generation/rust/RustUtilTest.java | 150 ++ 17 files changed, 3699 insertions(+) create mode 100644 rust/Cargo.toml create mode 100644 rust/benches/car_benchmark.rs create mode 100644 rust/benches/md_benchmark.rs create mode 100644 rust/rust-toolchain create mode 100644 rust/tests/baseline_test.rs create mode 100644 rust/tests/extension_test.rs create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java diff --git a/.gitignore b/.gitignore index 2e20d39e2c..c7dcc86189 100644 --- a/.gitignore +++ b/.gitignore @@ -106,6 +106,10 @@ csharp/sbe-generated/uk_co_real_logic_sbe_benchmarks_fix csharp/sbe-tests/*.sbe csharp/nuget/ +# rust +rust/target +rust/Cargo.lock + # Mac .DS_Store /sbe-tool/src/main/golang/uk_co_real_logic_sbe_ir_generated/ diff --git a/build.gradle b/build.gradle index be022589a4..660ecbb846 100644 --- a/build.gradle +++ b/build.gradle @@ -531,6 +531,54 @@ project(':sbe-benchmarks') { javadoc.enabled = false } +/* + * Rust codec targets used for testing + */ +task generateRustExamples(type: JavaExec) { + main = 'uk.co.real_logic.sbe.SbeTool' + classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'generated/rust', + 'sbe.xinclude.aware': 'true', + 'sbe.target.language': 'Rust', + 'sbe.target.namespace': 'examples') + args = ['sbe-samples/src/main/resources/example-schema.xml', + 'sbe-samples/src/main/resources/example-extension-schema.xml', + 'sbe-benchmarks/src/main/resources/car.xml', + 'sbe-benchmarks/src/main/resources/fix-message-samples.xml' + ] +} + +task generateCarExampleDataFile(type: JavaExec) { + main = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub' + classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath + systemProperties('sbe.encoding.filename': 'rust/car_example_baseline_data.sbe') + args = [] + standardOutput = new ByteArrayOutputStream() +} + +task generateCarExampleExtensionDataFile(type: JavaExec) { + main = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension' + classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath + systemProperties('sbe.encoding.filename': 'rust/car_example_extension_data.sbe') + args = [] + standardOutput = new ByteArrayOutputStream() +} + +task runRustCarExample(type: Exec) { + workingDir = './rust' + executable = 'cargo' + args = ['run'] + standardOutput = new ByteArrayOutputStream() + errorOutput = new ByteArrayOutputStream() + dependsOn 'generateRustExamples', 'generateCarExampleDataFile', 'generateCarExampleExtensionDataFile' +} + +task generateRustCodecs { + description = 'Generate rust test codecs' + dependsOn 'generateRustExamples', 'generateCarExampleDataFile', 'generateCarExampleExtensionDataFile' +} + /* * Golang codec targets used for testing, benchmarking etc. We have * multiple targets as: diff --git a/rust/Cargo.toml b/rust/Cargo.toml new file mode 100644 index 0000000000..ed176caf0d --- /dev/null +++ b/rust/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "sbe_rust_example" +version = "0.1.0" +authors = [] +edition = "2018" +publish = false + +[dependencies] +examples_baseline = { path = "../generated/rust/baseline" } +examples_extension = { path = "../generated/rust/extension" } +examples_uk_co_real_logic_sbe_benchmarks = { path = "../generated/rust/uk_co_real_logic_sbe_benchmarks" } +examples_uk_co_real_logic_sbe_benchmarks_fix = { path = "../generated/rust/uk_co_real_logic_sbe_benchmarks_fix" } + +[dev-dependencies] +criterion = "0.3" + +[[bench]] +name = "car_benchmark" +harness = false + +[[bench]] +name = "md_benchmark" +harness = false \ No newline at end of file diff --git a/rust/benches/car_benchmark.rs b/rust/benches/car_benchmark.rs new file mode 100644 index 0000000000..f11269311f --- /dev/null +++ b/rust/benches/car_benchmark.rs @@ -0,0 +1,189 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use examples_uk_co_real_logic_sbe_benchmarks::*; + +const MANUFACTURER: &[u8] = b"MANUFACTURER"; +const MODEL: &[u8] = b"MODEL"; + +struct State { + buffer: Vec, +} + +pub fn car_encode_benchmark(c: &mut Criterion) { + let mut state = State { + buffer: vec![0u8; 1024], + }; + + c.bench_function("encode car", |b| { + b.iter(|| { + let _length = encode(black_box(&mut state)).unwrap(); + }) + }); +} + +fn encode(state: &mut State) -> SbeResult { + let buffer = state.buffer.as_mut_slice(); + let mut car = CarEncoder::default(); + let mut engine = EngineEncoder::default(); + let mut fuel_figures = FuelFiguresEncoder::default(); + let mut performance_figures = PerformanceFiguresEncoder::default(); + let mut acceleration = AccelerationEncoder::default(); + let mut extras = OptionalExtras::default(); + + car = car.wrap(WriteBuf::new(buffer), message_header::ENCODED_LENGTH); + car = car.header(0).parent()?; + + car.code(Model::A); + car.model_year(2005); + car.serial_number(12345); + car.available(BooleanType::T); + car.vehicle_code([97, 98, 99, 100, 101, 102]); // abcdef + car.some_numbers([0, 1, 2, 3, 4]); + + extras.set_sports_pack(true); + extras.set_sun_roof(true); + car.extras(extras); + + engine = car.engine_encoder(engine); + engine.capacity(4200); + engine.num_cylinders(8); + engine.manufacturer_code([97, 98, 99]); // abc + + car = engine.parent()?; + fuel_figures = car.fuel_figures_encoder(3, fuel_figures); + fuel_figures.advance()?; + fuel_figures.speed(30); + fuel_figures.mpg(35.9); + + fuel_figures.advance()?; + fuel_figures.speed(55); + fuel_figures.mpg(49.0); + + fuel_figures.advance()?; + fuel_figures.speed(75); + fuel_figures.mpg(40.0); + + car = fuel_figures.parent()?; + performance_figures = car.performance_figures_encoder(2, performance_figures); + performance_figures.advance()?; + performance_figures.octane_rating(95); + + acceleration = performance_figures.acceleration_encoder(3, acceleration); + acceleration.advance()?; + acceleration.mph(30); + acceleration.seconds(4.0); + + acceleration.advance()?; + acceleration.mph(60); + acceleration.seconds(7.5); + + acceleration.advance()?; + acceleration.mph(100); + acceleration.seconds(12.2); + + performance_figures = acceleration.parent()?; + performance_figures.advance()?; + performance_figures.octane_rating(99); + + acceleration = performance_figures.acceleration_encoder(3, acceleration); + acceleration.advance()?; + acceleration.mph(30); + acceleration.seconds(3.8); + + acceleration.advance()?; + acceleration.mph(60); + acceleration.seconds(7.1); + + acceleration.advance()?; + acceleration.mph(100); + acceleration.seconds(11.8); + + performance_figures = acceleration.parent()?; + car = performance_figures.parent()?; + + car.manufacturer(MANUFACTURER); + car.model(MODEL); + + Ok(car.encoded_length()) +} + +pub fn car_decode_benchmark(c: &mut Criterion) { + let mut state = State { + buffer: vec![0u8; 1024], + }; + let encoded_len = encode(&mut state).unwrap(); + + c.bench_function("decode car", |b| { + b.iter(|| { + let decoded_len = decode(black_box(&state)).unwrap(); + assert_eq!(encoded_len, decoded_len); + }) + }); +} + +fn decode(state: &State) -> SbeResult { + let mut car = CarDecoder::default(); + + let buf = ReadBuf::new(state.buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + car = car.header(header); + + // Car... + car.serial_number(); + car.model_year(); + car.available(); + car.code(); + + let len = car.some_numbers().len(); + for i in 0..len { + let _ = car.some_numbers()[i]; + } + + let len = car.vehicle_code().len(); + for i in 0..len { + let _ = car.vehicle_code()[i]; + } + + let extras = car.extras(); + extras.get_cruise_control(); + extras.get_sports_pack(); + extras.get_sun_roof(); + + let mut engine = car.engine_decoder(); + engine.capacity(); + engine.num_cylinders(); + engine.max_rpm(); + engine.manufacturer_code(); + engine.fuel(); + + car = engine.parent()?; + let mut fuel_figures = car.fuel_figures_decoder(); + + while let Ok(Some(_)) = fuel_figures.advance() { + fuel_figures.speed(); + fuel_figures.mpg(); + } + + car = fuel_figures.parent()?; + let mut performance_figures = car.performance_figures_decoder(); + + while let Ok(Some(_)) = performance_figures.advance() { + performance_figures.octane_rating(); + let mut acceleration = performance_figures.acceleration_decoder(); + while let Ok(Some(_)) = acceleration.advance() { + acceleration.mph(); + acceleration.seconds(); + } + performance_figures = acceleration.parent()?; + } + + car = performance_figures.parent()?; + let coord = car.manufacturer_decoder(); + car.manufacturer_slice(coord); + let coord = car.model_decoder(); + car.model_slice(coord); + + Ok(car.encoded_length()) +} + +criterion_group!(benches, car_encode_benchmark, car_decode_benchmark); +criterion_main!(benches); diff --git a/rust/benches/md_benchmark.rs b/rust/benches/md_benchmark.rs new file mode 100644 index 0000000000..2d1a23a892 --- /dev/null +++ b/rust/benches/md_benchmark.rs @@ -0,0 +1,122 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use examples_uk_co_real_logic_sbe_benchmarks_fix::*; + +struct State { + buffer: Vec, +} + +pub fn md_encode_benchmark(c: &mut Criterion) { + let mut state = State { + buffer: vec![0u8; 1024], + }; + + c.bench_function("encode md", |b| { + b.iter(|| { + let _length = encode_md(black_box(&mut state)).unwrap(); + }) + }); +} + +fn encode_md(state: &mut State) -> SbeResult { + let buffer = state.buffer.as_mut_slice(); + let mut market_data = MarketDataIncrementalRefreshTradesEncoder::default(); + let mut md_inc_grp = MdIncGrpEncoder::default(); + + let mut md_entry_px = Decimal64Encoder::default(); + let mut md_entry_size = IntQty32Encoder::default(); + + market_data = market_data.wrap(WriteBuf::new(buffer), message_header::ENCODED_LENGTH); + market_data = market_data.header(0).parent()?; + + market_data.transact_time(1234); + market_data.event_time_delta(987); + market_data.match_event_indicator(MatchEventIndicator::END_EVENT); + + md_inc_grp = market_data.md_inc_grp_encoder(2, md_inc_grp); + + // first + md_inc_grp.advance()?; + md_inc_grp.trade_id(1234); + md_inc_grp.security_id(56789); + md_entry_px = md_inc_grp.md_entry_px_encoder(md_entry_px); + md_entry_px.mantissa(50); + md_inc_grp = md_entry_px.parent()?; + md_entry_size = md_inc_grp.md_entry_size_encoder(md_entry_size); + md_entry_size.mantissa(10); + md_inc_grp = md_entry_size.parent()?; + md_inc_grp.number_of_orders(1); + md_inc_grp.md_update_action(MDUpdateAction::NEW); + md_inc_grp.rpt_seq(1); + md_inc_grp.aggressor_side(Side::BUY); + + // second + md_inc_grp.advance()?; + md_inc_grp.trade_id(1234); + md_inc_grp.security_id(56789); + md_entry_px = md_inc_grp.md_entry_px_encoder(md_entry_px); + md_entry_px.mantissa(50); + md_inc_grp = md_entry_px.parent()?; + md_entry_size = md_inc_grp.md_entry_size_encoder(md_entry_size); + md_entry_size.mantissa(10); + md_inc_grp = md_entry_size.parent()?; + md_inc_grp.number_of_orders(1); + md_inc_grp.md_update_action(MDUpdateAction::NEW); + md_inc_grp.rpt_seq(1); + md_inc_grp.aggressor_side(Side::SELL); + market_data = md_inc_grp.parent()?; + Ok(market_data.encoded_length()) +} + +pub fn md_decode_benchmark(c: &mut Criterion) { + let mut state = State { + buffer: vec![0u8; 1024], + }; + let encoded_len = encode_md(&mut state).unwrap(); + + c.bench_function("decode md", |b| { + b.iter(|| { + let decoded_len = decode_md(black_box(&state)).unwrap(); + assert_eq!(encoded_len, decoded_len); + }) + }); +} + +fn decode_md(state: &State) -> SbeResult { + let mut market_data = MarketDataIncrementalRefreshTradesDecoder::default(); + + let buf = ReadBuf::new(state.buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + market_data = market_data.header(header); + + market_data.transact_time(); + market_data.event_time_delta(); + market_data.match_event_indicator(); + + let mut md_inc_grp = market_data.md_inc_grp_decoder(); + let md_inc_grp_count = md_inc_grp.count(); + let mut count = 0; + + while let Ok(Some(_)) = md_inc_grp.advance() { + count += 1; + md_inc_grp.trade_id(); + md_inc_grp.security_id(); + let mut md_entry_px = md_inc_grp.md_entry_px_decoder(); + md_entry_px.mantissa(); + md_inc_grp = md_entry_px.parent()?; + let mut md_entry_size = md_inc_grp.md_entry_size_decoder(); + md_entry_size.mantissa(); + md_inc_grp = md_entry_size.parent()?; + md_inc_grp.number_of_orders(); + md_inc_grp.md_update_action(); + md_inc_grp.rpt_seq(); + md_inc_grp.aggressor_side(); + md_inc_grp.md_entry_type(); + } + assert_eq!(md_inc_grp_count, count); + market_data = md_inc_grp.parent()?; + + Ok(market_data.encoded_length()) +} + +criterion_group!(benches, md_encode_benchmark, md_decode_benchmark); +criterion_main!(benches); diff --git a/rust/rust-toolchain b/rust/rust-toolchain new file mode 100644 index 0000000000..bf867e0ae5 --- /dev/null +++ b/rust/rust-toolchain @@ -0,0 +1 @@ +nightly diff --git a/rust/tests/baseline_test.rs b/rust/tests/baseline_test.rs new file mode 100644 index 0000000000..2e578929d8 --- /dev/null +++ b/rust/tests/baseline_test.rs @@ -0,0 +1,260 @@ +use std::fs::File; +use std::io::prelude::*; + +use examples_baseline::*; + +fn read_sbe_file_generated_from_java_example() -> ::std::io::Result> { + // Generated by the generateCarExampleDataFile gradle task. + let mut f = File::open("car_example_baseline_data.sbe")?; + let mut buffer = Vec::new(); + f.read_to_end(&mut buffer)?; + Ok(buffer) +} + +#[test] +fn run_car_baseline_example() -> SbeResult<()> { + match read_sbe_file_generated_from_java_example() { + Ok(reference_example_bytes) => { + decode_car_and_assert_expected_content(&reference_example_bytes)?; + let (limit, mut bytes_encoded_from_rust) = encode_car_from_scratch()?; + decode_car_and_assert_expected_content(bytes_encoded_from_rust.as_slice())?; + bytes_encoded_from_rust.truncate(limit); + assert_eq!(reference_example_bytes, bytes_encoded_from_rust); + } + Err(e) => { + panic!("{:?}", e) + } + } + Ok(()) +} + +fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { + let mut car = CarDecoder::default(); + + let buf = ReadBuf::new(buffer); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + assert_eq!(car::SBE_TEMPLATE_ID, header.template_id()); + car = car.header(header); + + // Car... + assert_eq!(1234, car.serial_number()); + assert_eq!(2013, car.model_year()); + assert_eq!(BooleanType::T, car.available()); + assert_eq!(Model::A, car.code()); + + assert_eq!([1, 2, 3, 4], car.some_numbers()); + assert_eq!([97, 98, 99, 100, 101, 102], car.vehicle_code()); + + let extras = car.extras(); + assert_eq!(6, extras.0); + assert!(extras.get_cruise_control()); + assert!(extras.get_sports_pack()); + assert!(!extras.get_sun_roof()); + + assert_eq!(Model::C, car.discounted_model()); + + let engine = car.engine_decoder(); + assert_eq!(2000, engine.capacity()); + assert_eq!(4, engine.num_cylinders()); + assert_eq!(9000, engine.max_rpm()); + assert_eq!("123", String::from_utf8_lossy(&engine.manufacturer_code())); + + assert_eq!(b"Petrol", engine.fuel()); + assert_eq!(35, engine.efficiency()); + assert_eq!(BooleanType::T, engine.booster_enabled()); + + let mut booster = engine.booster_decoder(); + assert_eq!(BoostType::NITROUS, booster.boost_type()); + assert_eq!(200, booster.horse_power()); + + car = booster.parent()?.parent()?; + let mut fuel_figures = car.fuel_figures_decoder(); + assert_eq!(3, fuel_figures.count()); + + assert_eq!(Some(0), fuel_figures.advance()?); + assert_eq!(30, fuel_figures.speed()); + assert_eq!(35.9, fuel_figures.mpg()); + let coord = fuel_figures.usage_description_decoder(); + assert_eq!( + "Urban Cycle", + String::from_utf8_lossy(fuel_figures.usage_description_slice(coord)) + ); + + assert_eq!(Some(1), fuel_figures.advance()?); + assert_eq!(55, fuel_figures.speed()); + assert_eq!(49.0, fuel_figures.mpg()); + let coord = fuel_figures.usage_description_decoder(); + assert_eq!( + "Combined Cycle", + String::from_utf8_lossy(fuel_figures.usage_description_slice(coord)) + ); + + assert_eq!(Some(2), fuel_figures.advance()?); + assert_eq!(75, fuel_figures.speed()); + assert_eq!(40.0, fuel_figures.mpg()); + let coord = fuel_figures.usage_description_decoder(); + assert_eq!( + "Highway Cycle", + String::from_utf8_lossy(fuel_figures.usage_description_slice(coord)) + ); + assert_eq!(Ok(None), fuel_figures.advance()); + + car = fuel_figures.parent()?; + let mut performance_figures = car.performance_figures_decoder(); + assert_eq!(2, performance_figures.count()); + + // 95 octane + assert_eq!(Some(0), performance_figures.advance()?); + assert_eq!(95, performance_figures.octane_rating()); + let mut acceleration = performance_figures.acceleration_decoder(); + assert_eq!(3, acceleration.count()); + assert_eq!(Some(0), acceleration.advance()?); + assert_eq!(30, acceleration.mph()); + assert_eq!(4.0, acceleration.seconds()); + assert_eq!(Some(1), acceleration.advance()?); + assert_eq!(60, acceleration.mph()); + assert_eq!(7.5, acceleration.seconds()); + assert_eq!(Some(2), acceleration.advance()?); + assert_eq!(100, acceleration.mph()); + assert_eq!(12.2, acceleration.seconds()); + assert_eq!(Ok(None), acceleration.advance()); + + // 99 octane + performance_figures = acceleration.parent()?; + assert_eq!(Some(1), performance_figures.advance()?); + assert_eq!(99, performance_figures.octane_rating()); + acceleration = performance_figures.acceleration_decoder(); + assert_eq!(3, acceleration.count()); + assert_eq!(Some(0), acceleration.advance()?); + assert_eq!(30, acceleration.mph()); + assert_eq!(3.8, acceleration.seconds()); + assert_eq!(Some(1), acceleration.advance()?); + assert_eq!(60, acceleration.mph()); + assert_eq!(7.1, acceleration.seconds()); + assert_eq!(Some(2), acceleration.advance()?); + assert_eq!(100, acceleration.mph()); + assert_eq!(11.8, acceleration.seconds()); + assert_eq!(Ok(None), acceleration.advance()); + + performance_figures = acceleration.parent()?; + car = performance_figures.parent()?; + + let coord = car.manufacturer_decoder(); + assert_eq!( + "Honda", + String::from_utf8_lossy(car.manufacturer_slice(coord)) + ); + + let coord = car.model_decoder(); + assert_eq!("Civic VTi", String::from_utf8_lossy(car.model_slice(coord))); + + let coord = car.activation_code_decoder(); + assert_eq!( + "abcdef", + String::from_utf8_lossy(car.activation_code_slice(coord)) + ); + + Ok(()) +} + +fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { + let mut buffer = vec![0u8; 256]; + let mut car = CarEncoder::default(); + let mut engine = EngineEncoder::default(); + let mut booster = BoosterEncoder::default(); + let mut fuel_figures = FuelFiguresEncoder::default(); + let mut performance_figures = PerformanceFiguresEncoder::default(); + let mut acceleration = AccelerationEncoder::default(); + let mut extras = OptionalExtras::default(); + + car = car.wrap( + WriteBuf::new(buffer.as_mut_slice()), + message_header::ENCODED_LENGTH, + ); + car = car.header(0).parent()?; + + car.serial_number(1234); + car.model_year(2013); + car.available(BooleanType::T); + car.code(Model::A); + car.some_numbers([1, 2, 3, 4]); + car.vehicle_code([97, 98, 99, 100, 101, 102]); // abcdef + + extras.set_cruise_control(true); + extras.set_sports_pack(true); + extras.set_sun_roof(false); + car.extras(extras); + + engine = car.engine_encoder(engine); + engine.capacity(2000); + engine.num_cylinders(4); + engine.manufacturer_code([49, 50, 51]); // 123 + engine.efficiency(35); + engine.booster_enabled(BooleanType::T); + booster = engine.booster_encoder(booster); + booster.boost_type(BoostType::NITROUS); + booster.horse_power(200); + + engine = booster.parent()?; + car = engine.parent()?; + fuel_figures = car.fuel_figures_encoder(3, fuel_figures); + assert_eq!(Some(0), fuel_figures.advance()?); + fuel_figures.speed(30); + fuel_figures.mpg(35.9); + fuel_figures.usage_description(b"Urban Cycle"); + + assert_eq!(Some(1), fuel_figures.advance()?); + fuel_figures.speed(55); + fuel_figures.mpg(49.0); + fuel_figures.usage_description(b"Combined Cycle"); + + assert_eq!(Some(2), fuel_figures.advance()?); + fuel_figures.speed(75); + fuel_figures.mpg(40.0); + fuel_figures.usage_description(b"Highway Cycle"); + + car = fuel_figures.parent()?; + performance_figures = car.performance_figures_encoder(2, performance_figures); + assert_eq!(Some(0), performance_figures.advance()?); + performance_figures.octane_rating(95); + + acceleration = performance_figures.acceleration_encoder(3, acceleration); + assert_eq!(Some(0), acceleration.advance()?); + acceleration.mph(30); + acceleration.seconds(4.0); + + assert_eq!(Some(1), acceleration.advance()?); + acceleration.mph(60); + acceleration.seconds(7.5); + + assert_eq!(Some(2), acceleration.advance()?); + acceleration.mph(100); + acceleration.seconds(12.2); + + performance_figures = acceleration.parent()?; + assert_eq!(Some(1), performance_figures.advance()?); + performance_figures.octane_rating(99); + + acceleration = performance_figures.acceleration_encoder(3, acceleration); + assert_eq!(Some(0), acceleration.advance()?); + acceleration.mph(30); + acceleration.seconds(3.8); + + assert_eq!(Some(1), acceleration.advance()?); + acceleration.mph(60); + acceleration.seconds(7.1); + + assert_eq!(Some(2), acceleration.advance()?); + acceleration.mph(100); + acceleration.seconds(11.8); + + performance_figures = acceleration.parent()?; + car = performance_figures.parent()?; + + car.manufacturer("Honda"); + car.model("Civic VTi"); + car.activation_code(b"abcdef"); + + let limit = car.get_limit(); + Ok((limit, buffer)) +} diff --git a/rust/tests/extension_test.rs b/rust/tests/extension_test.rs new file mode 100644 index 0000000000..317b79651a --- /dev/null +++ b/rust/tests/extension_test.rs @@ -0,0 +1,261 @@ +use std::fs::File; +use std::io::prelude::*; + +use examples_extension::*; + +fn read_sbe_file_generated_from_java_example() -> ::std::io::Result> { + // Generated by the generateCarExampleDataFile gradle task. + let mut f = File::open("car_example_extension_data.sbe")?; + let mut buffer = Vec::new(); + f.read_to_end(&mut buffer)?; + Ok(buffer) +} + +#[test] +fn run_car_extension_example() -> SbeResult<()> { + match read_sbe_file_generated_from_java_example() { + Ok(reference_example_bytes) => { + decode_car_and_assert_expected_content(&reference_example_bytes)?; + let (limit, mut bytes_encoded_from_rust) = encode_car_from_scratch()?; + decode_car_and_assert_expected_content(bytes_encoded_from_rust.as_slice())?; + bytes_encoded_from_rust.truncate(limit); + } + Err(e) => { + panic!("{:?}", e) + } + } + Ok(()) +} + +fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { + let mut car = CarDecoder::default(); + + let buf = ReadBuf::new(buffer); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + assert_eq!(car::SBE_TEMPLATE_ID, header.template_id()); + car = car.header(header); + + // Car... + assert_eq!(1234, car.serial_number()); + assert_eq!(2013, car.model_year()); + assert_eq!(BooleanType::T, car.available()); + + assert_eq!(Model::A, car.code()); + + assert_eq!([0, 1, 2, 3], car.some_numbers()); + assert_eq!([97, 98, 99, 100, 101, 102], car.vehicle_code()); + + let extras = car.extras(); + assert_eq!(6, extras.0); + assert!(extras.get_cruise_control()); + assert!(extras.get_sports_pack()); + assert!(!extras.get_sun_roof()); + + assert_eq!(Model::C, car.discounted_model()); + + let mut engine = car.engine_decoder(); + assert_eq!(2000, engine.capacity()); + assert_eq!(4, engine.num_cylinders()); + assert_eq!(9000, engine.max_rpm()); + assert_eq!("123", String::from_utf8_lossy(&engine.manufacturer_code())); + + assert_eq!(b"Petrol", engine.fuel()); + assert_eq!(35, engine.efficiency()); + assert_eq!(BooleanType::T, engine.booster_enabled()); + + let mut booster = engine.booster_decoder(); + assert_eq!(BoostType::NITROUS, booster.boost_type()); + assert_eq!(200, booster.horse_power()); + + engine = booster.parent()?; + car = engine.parent()?; + let mut fuel_figures = car.fuel_figures_decoder(); + assert_eq!(3, fuel_figures.count()); + + assert_eq!(Some(0), fuel_figures.advance()?); + assert_eq!(30, fuel_figures.speed()); + assert_eq!(35.9, fuel_figures.mpg()); + let coord = fuel_figures.usage_description_decoder(); + assert_eq!( + "Urban Cycle", + String::from_utf8_lossy(fuel_figures.usage_description_slice(coord)) + ); + + assert_eq!(Some(1), fuel_figures.advance()?); + assert_eq!(55, fuel_figures.speed()); + assert_eq!(49.0, fuel_figures.mpg()); + let coord = fuel_figures.usage_description_decoder(); + assert_eq!( + "Combined Cycle", + String::from_utf8_lossy(fuel_figures.usage_description_slice(coord)) + ); + + assert_eq!(Some(2), fuel_figures.advance()?); + assert_eq!(75, fuel_figures.speed()); + assert_eq!(40.0, fuel_figures.mpg()); + let coord = fuel_figures.usage_description_decoder(); + assert_eq!( + "Highway Cycle", + String::from_utf8_lossy(fuel_figures.usage_description_slice(coord)) + ); + assert_eq!(Ok(None), fuel_figures.advance()); + + car = fuel_figures.parent()?; + let mut performance_figures = car.performance_figures_decoder(); + assert_eq!(2, performance_figures.count()); + + // 95 octane + assert_eq!(Some(0), performance_figures.advance()?); + assert_eq!(95, performance_figures.octane_rating()); + let mut acceleration = performance_figures.acceleration_decoder(); + assert_eq!(3, acceleration.count()); + assert_eq!(Some(0), acceleration.advance()?); + assert_eq!(30, acceleration.mph()); + assert_eq!(4.0, acceleration.seconds()); + assert_eq!(Some(1), acceleration.advance()?); + assert_eq!(60, acceleration.mph()); + assert_eq!(7.5, acceleration.seconds()); + assert_eq!(Some(2), acceleration.advance()?); + assert_eq!(100, acceleration.mph()); + assert_eq!(12.2, acceleration.seconds()); + assert_eq!(Ok(None), acceleration.advance()); + + // 99 octane + performance_figures = acceleration.parent()?; + assert_eq!(Some(1), performance_figures.advance()?); + assert_eq!(99, performance_figures.octane_rating()); + acceleration = performance_figures.acceleration_decoder(); + assert_eq!(3, acceleration.count()); + assert_eq!(Some(0), acceleration.advance()?); + assert_eq!(30, acceleration.mph()); + assert_eq!(3.8, acceleration.seconds()); + assert_eq!(Some(1), acceleration.advance()?); + assert_eq!(60, acceleration.mph()); + assert_eq!(7.1, acceleration.seconds()); + assert_eq!(Some(2), acceleration.advance()?); + assert_eq!(100, acceleration.mph()); + assert_eq!(11.8, acceleration.seconds()); + assert_eq!(Ok(None), acceleration.advance()); + + performance_figures = acceleration.parent()?; + car = performance_figures.parent()?; + + let coord = car.manufacturer_decoder(); + assert_eq!( + "Honda", + String::from_utf8_lossy(car.manufacturer_slice(coord)) + ); + + let coord = car.model_decoder(); + assert_eq!("Civic VTi", String::from_utf8_lossy(car.model_slice(coord))); + + let coord = car.activation_code_decoder(); + assert_eq!( + "abcdef", + String::from_utf8_lossy(car.activation_code_slice(coord)) + ); + + Ok(()) +} + +fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { + let mut buffer = vec![0u8; 256]; + let mut car = CarEncoder::default(); + let mut engine = EngineEncoder::default(); + let mut booster = BoosterEncoder::default(); + let mut fuel_figures = FuelFiguresEncoder::default(); + let mut performance_figures = PerformanceFiguresEncoder::default(); + let mut acceleration = AccelerationEncoder::default(); + let mut extras = OptionalExtras::default(); + + car = car.wrap( + WriteBuf::new(buffer.as_mut_slice()), + message_header::ENCODED_LENGTH, + ); + car = car.header(0).parent()?; + + car.serial_number(1234); + car.model_year(2013); + car.available(BooleanType::T); + car.code(Model::A); + car.some_numbers([0, 1, 2, 3]); + car.vehicle_code([97, 98, 99, 100, 101, 102]); // abcdef + + extras.set_cruise_control(true); + extras.set_sports_pack(true); + extras.set_sun_roof(false); + car.extras(extras); + + engine = car.engine_encoder(engine); + engine.capacity(2000); + engine.num_cylinders(4); + engine.manufacturer_code([49, 50, 51]); // 123 + engine.efficiency(35); + engine.booster_enabled(BooleanType::T); + booster = engine.booster_encoder(booster); + booster.boost_type(BoostType::NITROUS); + booster.horse_power(200); + + engine = booster.parent()?; + car = engine.parent()?; + fuel_figures = car.fuel_figures_encoder(3, fuel_figures); + assert_eq!(Some(0), fuel_figures.advance()?); + fuel_figures.speed(30); + fuel_figures.mpg(35.9); + fuel_figures.usage_description(b"Urban Cycle"); + + assert_eq!(Some(1), fuel_figures.advance()?); + fuel_figures.speed(55); + fuel_figures.mpg(49.0); + fuel_figures.usage_description(b"Combined Cycle"); + + assert_eq!(Some(2), fuel_figures.advance()?); + fuel_figures.speed(75); + fuel_figures.mpg(40.0); + fuel_figures.usage_description(b"Highway Cycle"); + + car = fuel_figures.parent()?; + performance_figures = car.performance_figures_encoder(2, performance_figures); + assert_eq!(Some(0), performance_figures.advance()?); + performance_figures.octane_rating(95); + + acceleration = performance_figures.acceleration_encoder(3, acceleration); + assert_eq!(Some(0), acceleration.advance()?); + acceleration.mph(30); + acceleration.seconds(4.0); + + assert_eq!(Some(1), acceleration.advance()?); + acceleration.mph(60); + acceleration.seconds(7.5); + + assert_eq!(Some(2), acceleration.advance()?); + acceleration.mph(100); + acceleration.seconds(12.2); + + performance_figures = acceleration.parent()?; + assert_eq!(Some(1), performance_figures.advance()?); + performance_figures.octane_rating(99); + + acceleration = performance_figures.acceleration_encoder(3, acceleration); + assert_eq!(Some(0), acceleration.advance()?); + acceleration.mph(30); + acceleration.seconds(3.8); + + assert_eq!(Some(1), acceleration.advance()?); + acceleration.mph(60); + acceleration.seconds(7.1); + + assert_eq!(Some(2), acceleration.advance()?); + acceleration.mph(100); + acceleration.seconds(11.8); + + performance_figures = acceleration.parent()?; + car = performance_figures.parent()?; + + car.manufacturer("Honda"); + car.model("Civic VTi"); + car.activation_code(b"abcdef"); + + let limit = car.get_limit(); + Ok((limit, buffer)) +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 1eb76f35d8..b87313662b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -23,6 +23,8 @@ import uk.co.real_logic.sbe.generation.golang.GolangGenerator; import uk.co.real_logic.sbe.generation.golang.GolangOutputManager; import uk.co.real_logic.sbe.generation.java.JavaGenerator; +import uk.co.real_logic.sbe.generation.rust.RustGenerator; +import uk.co.real_logic.sbe.generation.rust.RustOutputManager; import uk.co.real_logic.sbe.ir.Ir; import static uk.co.real_logic.sbe.SbeTool.*; @@ -97,6 +99,22 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) { return new GolangGenerator(ir, new GolangOutputManager(outputDir, ir.applicableNamespace())); } + }, + + /** + * Generates codecs for the Rust programming language. + */ + RUST() + { + /** + * {@inheritDoc} + */ + public CodeGenerator newInstance(final Ir ir, final String outputDir) + { + return new RustGenerator( + ir, + new RustOutputManager(outputDir, ir.packageName())); + } }; /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java new file mode 100644 index 0000000000..155ffe5536 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -0,0 +1,287 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.rust; + +import org.agrona.generation.OutputManager; +import uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType; + +import java.io.IOException; +import java.io.Writer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; + +import static java.nio.ByteOrder.LITTLE_ENDIAN; +import static uk.co.real_logic.sbe.generation.rust.RustGenerator.*; +import static uk.co.real_logic.sbe.generation.rust.RustUtil.*; + +/** + * Generates `lib.rs` specific code. + */ +class LibRsDef +{ + private final LinkedHashMap> modules = new LinkedHashMap<>(); + private final ArrayList enumDefs = new ArrayList<>(); + private final ArrayList bitSetDefs = new ArrayList<>(); + + private final OutputManager outputManager; + private final ByteOrder byteOrder; + + /** + * Create a new 'lib.rs' for the library being generated + * + * @param outputManager for generating the codecs to. + * @param byteOrder for the Encoding. + */ + LibRsDef( + final OutputManager outputManager, + final ByteOrder byteOrder) + { + this.outputManager = outputManager; + this.byteOrder = byteOrder; + } + + void addMod(final String modName, final CodecType codecType) + { + modules.computeIfAbsent(modName, __ -> new HashSet<>()).add(codecType); + } + + void addEnum(final String enumDef) + { + enumDefs.add(enumDef); + } + + void addBitSet(final String bitSetDef) + { + bitSetDefs.add(bitSetDef); + } + + void generate() throws IOException + { + try (Writer libRs = outputManager.createOutput("lib")) + { + indent(libRs, 0, "#![allow(clippy::upper_case_acronyms)]\n"); + indent(libRs, 0, "#![allow(non_camel_case_types)]\n"); + indent(libRs, 0, "use core::{convert::TryInto};\n\n"); + + // add modules + for (final String mod : modules.keySet()) + { + indent(libRs, 0, "pub mod %s;\n", toLowerSnakeCase(mod)); + } + indent(libRs, 0, "\n"); + + // add re-export of modules + for (final Map.Entry> entry : modules.entrySet()) + { + final String mod = entry.getKey(); + final HashSet codecTypes = entry.getValue(); + + if (codecTypes.size() == 1) + { + indent(libRs, 0, "pub use %s::%s::*;\n", + toLowerSnakeCase(mod), + toLowerSnakeCase(codecTypes.toArray()[0].toString())); + } + else + { + indent(libRs, 0, "pub use %s::{decoder::*, encoder::*};\n", toLowerSnakeCase(mod)); + } + } + indent(libRs, 0, "\n"); + + generateSbeErrorEnum(libRs); + generateEitherEnum(libRs); + + generateEncoderTraits(libRs); + generateDecoderTraits(libRs); + + generateReadBuf(libRs, byteOrder); + generateWriteBuf(libRs, byteOrder); + + // append generated enums + for (final String code : enumDefs) + { + libRs.append(code); + indent(libRs, 0, "\n"); + } + + // append generated bitSets + for (final String code : bitSetDefs) + { + libRs.append(code); + indent(libRs, 0, "\n"); + } + } + } + + static void generateEncoderTraits(final Writer writer) throws IOException + { + indent(writer, 0, "pub trait Writer<'a>: Sized {\n"); + indent(writer, 1, "fn get_buf_mut(&mut self) -> &mut WriteBuf<'a>;\n"); + indent(writer, 0, "}\n\n"); + + indent(writer, 0, "pub trait Encoder<'a>: Writer<'a> {\n"); + indent(writer, 1, "fn get_limit(&self) -> usize;\n"); + indent(writer, 1, "fn set_limit(&mut self, limit: usize);\n"); + indent(writer, 0, "}\n\n"); + } + + static void generateDecoderTraits(final Writer writer) throws IOException + { + indent(writer, 0, "pub trait Reader<'a>: Sized {\n"); + indent(writer, 1, "fn get_buf(&self) -> &ReadBuf<'a>;\n"); + indent(writer, 0, "}\n\n"); + + indent(writer, 0, "pub trait Decoder<'a>: Reader<'a> {\n"); + indent(writer, 1, "fn get_limit(&self) -> usize;\n"); + indent(writer, 1, "fn set_limit(&mut self, limit: usize);\n"); + indent(writer, 0, "}\n\n"); + } + + static void generateSbeErrorEnum(final Writer writer) throws IOException + { + indent(writer, 0, "pub type SbeResult = core::result::Result;\n\n"); + indent(writer, 0, "#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]\n"); + indent(writer, 0, "pub enum SbeErr {\n"); + indent(writer, 1, "ParentNotSet,\n"); + indent(writer, 0, "}\n"); + + indent(writer, 0, "impl core::fmt::Display for SbeErr {\n"); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n"); + indent(writer, 2, "write!(f, \"{:?}\", self)\n"); + indent(writer, 1, "}\n"); + indent(writer, 0, "}\n"); + + indent(writer, 0, "impl std::error::Error for SbeErr {}\n\n"); + } + + static void generateEitherEnum(final Writer writer) throws IOException + { + indent(writer, 0, "#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]\n"); + indent(writer, 0, "pub enum Either {\n"); + indent(writer, 1, "Left(L),\n"); + indent(writer, 1, "Right(R),\n"); + indent(writer, 0, "}\n\n"); + } + + static void generateReadBuf(final Appendable writer, final ByteOrder byteOrder) throws IOException + { + indent(writer, 0, "#[derive(Debug, Default)]\n"); + indent(writer, 0, "pub struct %s<%s> {\n", READ_BUF_TYPE, BUF_LIFETIME); + RustUtil.indent(writer, 1, "data: &%s [u8],\n", BUF_LIFETIME); + indent(writer, 0, "}\n"); + + // impl Reader... + indent(writer, 0, "impl<%s> Reader<%1$s> for %2$s<%1$s> {\n", BUF_LIFETIME, READ_BUF_TYPE); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn get_buf(&self) -> &ReadBuf<%s> {\n", BUF_LIFETIME); + indent(writer, 2, "self\n"); + indent(writer, 1, "}\n"); + indent(writer, 0, "}\n"); + + // impl ReadBuf ... + indent(writer, 0, "impl<%s> %s<%s> {\n", BUF_LIFETIME, READ_BUF_TYPE, BUF_LIFETIME); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "pub fn new(data: &%s [u8]) -> Self {\n", BUF_LIFETIME); + indent(writer, 2, "Self { data }\n"); + indent(writer, 1, "}\n\n"); + + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn get_bytes(slice: &[u8]) -> [u8; COUNT] {\n"); + indent(writer, 2, "slice.try_into().expect(\"slice with incorrect length\")\n"); + indent(writer, 1, "}\n\n"); + + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn get_bytes_at(slice: &[u8], index: usize) -> [u8; COUNT] {\n"); + indent(writer, 2, "Self::get_bytes(slice.split_at(index).1.split_at(COUNT).0)\n"); + indent(writer, 1, "}\n"); + + final LinkedHashSet uniquePrimitiveTypes + = new LinkedHashSet<>(TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.values()); + final String endianness = byteOrder == LITTLE_ENDIAN ? "le" : "be"; + + for (final String primitiveType : uniquePrimitiveTypes) + { + // get__at + indent(writer, 0, "\n"); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "pub fn get_%1$s_at(&self, index: usize) -> %1$s {\n", primitiveType); + indent(writer, 2, "%s::from_%s_bytes(Self::get_bytes_at(&self.data, index))\n", primitiveType, endianness); + indent(writer, 1, "}\n"); + } + + // get_slice_at + indent(writer, 0, "\n"); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "pub fn get_slice_at(&self, index: usize, len: usize) -> &[u8] {\n"); + indent(writer, 2, "self.data.split_at(index).1.split_at(len).0\n"); + indent(writer, 1, "}\n\n"); + + writer.append("}\n"); + } + + static void generateWriteBuf(final Writer writer, final ByteOrder byteOrder) throws IOException + { + indent(writer, 0, "\n"); + indent(writer, 0, "#[derive(Debug, Default)]\n"); + indent(writer, 0, "pub struct %s<%s> {\n", WRITE_BUF_TYPE, BUF_LIFETIME); + indent(writer, 1, "data: &%s mut [u8],\n", BUF_LIFETIME); + indent(writer, 0, "}\n"); + + indent(writer, 0, "impl<%s> %s<%s> {\n", BUF_LIFETIME, WRITE_BUF_TYPE, BUF_LIFETIME); + indent(writer, 1, "pub fn new(data: &%s mut [u8]) -> Self {\n", BUF_LIFETIME); + indent(writer, 2, "Self { data }\n"); + indent(writer, 1, "}\n\n"); + + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, + "pub fn put_bytes_at(&mut self, index: usize, bytes: [u8; COUNT]) -> usize {\n"); + indent(writer, 2, "for (i, byte) in bytes.iter().enumerate() {\n"); + indent(writer, 3, "self.data[index + i] = *byte;\n"); + indent(writer, 2, "}\n"); + indent(writer, 2, "COUNT\n"); + indent(writer, 1, "}\n\n"); + + final LinkedHashSet uniquePrimitiveTypes + = new LinkedHashSet<>(TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.values()); + final String endianness = byteOrder == LITTLE_ENDIAN ? "le" : "be"; + + for (final String primitiveType : uniquePrimitiveTypes) + { + // put__at + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "pub fn put_%1$s_at(&mut self, index: usize, value: %1$s) {\n", primitiveType); + indent(writer, 2, "self.put_bytes_at(index, %s::to_%s_bytes(value));\n", primitiveType, endianness); + indent(writer, 1, "}\n\n"); + } + + // put_slice_at + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "pub fn put_slice_at(&mut self, index: usize, src: &[u8]) -> usize {\n"); + indent(writer, 2, "let len = src.len();\n"); + indent(writer, 2, "let dest = self.data.split_at_mut(index).1.split_at_mut(len).0;\n"); + indent(writer, 2, "dest.clone_from_slice(src);\n"); + indent(writer, 2, "len\n"); + indent(writer, 1, "}\n"); + + indent(writer, 0, "}\n\n"); + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java new file mode 100644 index 0000000000..93339add2c --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -0,0 +1,231 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.rust; + +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.ir.Token; +import uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; + +import static uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType.Encoder; +import static uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType.Decoder; +import static uk.co.real_logic.sbe.generation.rust.RustGenerator.withLifetime; +import static uk.co.real_logic.sbe.generation.rust.RustUtil.*; + +class MessageCoderDef implements RustGenerator.ParentDef +{ + private final StringBuilder sb = new StringBuilder(); + private final ArrayList subGroups = new ArrayList<>(); + + private final Ir ir; + private final Token msgToken; + final String name; + final CodecType codecType; + + MessageCoderDef(final Ir ir, final Token msgToken, final CodecType codecType) + { + this.ir = ir; + this.msgToken = msgToken; + this.name = formatStructName(msgToken.name()); + this.codecType = codecType; + } + + String blockLengthType() + { + return rustTypeName(ir.headerStructure().blockLengthType()); + } + + String schemaVersionType() + { + return rustTypeName(ir.headerStructure().schemaVersionType()); + } + + void generate( + final List fields, + final List groups, + final List varData) throws IOException + { + indent(sb, 0, "pub mod %s {\n", codecType.toString().toLowerCase()); + indent(sb, 1, "use super::*;\n\n"); + + // i.e. Decoder or Encoder + final String msgTypeName = formatStructName(msgToken.name()) + codecType.name(); + appendMessageStruct(sb, msgTypeName); + + if (codecType == Encoder) + { + RustGenerator.appendImplEncoderTrait(sb, msgTypeName); + } + else + { + RustGenerator.appendImplDecoderTrait(sb, msgTypeName); + } + + RustGenerator.appendImplWithLifetimeHeader(sb, msgTypeName); // impl start + appendWrapFn(sb); + + indent(sb, 2, "#[inline]\n"); + indent(sb, 2, "pub fn encoded_length(&self) -> usize {\n"); + indent(sb, 3, "self.limit - self.offset\n"); + indent(sb, 2, "}\n\n"); + + if (codecType == Decoder) + { + appendMessageHeaderDecoderFn(sb); + + RustGenerator.generateDecoderFields(sb, fields, 2); + RustGenerator.generateDecoderGroups(sb, groups, 2, this); + RustGenerator.generateDecoderVarData(sb, varData, 2, false); + } + else + { + appendMessageHeaderEncoderFn(sb); + + RustGenerator.generateEncoderFields(sb, fields, 2); + RustGenerator.generateEncoderGroups(sb, groups, 2, this); + RustGenerator.generateEncoderVarData(sb, varData, 2); + } + + indent(sb, 1, "}\n\n"); // impl end + + // append all subGroup generated code + for (final SubGroup subGroup : subGroups) + { + subGroup.appendTo(sb); + } + + indent(sb, 0, "}\n"); // mod end + } + + void appendTo(final Appendable dest) throws IOException + { + dest.append(sb); + } + + @Override + public SubGroup addSubGroup(final String name, final int level, final Token groupToken) + { + final SubGroup subGroup = new SubGroup(name, level, groupToken); + subGroups.add(subGroup); + return subGroup; + } + + void appendMessageHeaderEncoderFn(final Appendable out) throws IOException + { + indent(out, 2, "pub fn header(self, offset: usize) -> MessageHeaderEncoder {\n"); + indent(out, 3, "let mut header = MessageHeaderEncoder::default().wrap(self, offset);\n"); + indent(out, 3, "header.block_length(SBE_BLOCK_LENGTH);\n"); + indent(out, 3, "header.template_id(SBE_TEMPLATE_ID);\n"); + indent(out, 3, "header.schema_id(SBE_SCHEMA_ID);\n"); + indent(out, 3, "header.version(SBE_SCHEMA_VERSION);\n"); + indent(out, 3, "header\n"); + indent(out, 2, "}\n\n"); + } + + void appendMessageHeaderDecoderFn(final Appendable out) throws IOException + { + indent(out, 2, "pub fn header(self, mut header: MessageHeaderDecoder>) -> Self {\n"); + indent(out, 3, "debug_assert_eq!(SBE_TEMPLATE_ID, header.template_id());\n"); + indent(out, 3, "let acting_block_length = header.block_length();\n"); + indent(out, 3, "let acting_version = header.version();\n\n"); + indent(out, 3, "self.wrap(\n"); + indent(out, 4, "header.parent().unwrap(),\n"); + indent(out, 4, "message_header::ENCODED_LENGTH,\n"); + indent(out, 4, "acting_block_length,\n"); + indent(out, 4, "acting_version,\n"); + indent(out, 3, ")\n"); + indent(out, 2, "}\n\n"); + } + + void appendMessageStruct(final Appendable out, final String structName) throws IOException + { + indent(out, 1, "#[derive(Debug, Default)]\n"); + indent(out, 1, "pub struct %s {\n", withLifetime(structName)); + indent(out, 2, "buf: %s,\n", withLifetime(this.codecType.bufType())); + indent(out, 2, "initial_offset: usize,\n"); + indent(out, 2, "offset: usize,\n"); + indent(out, 2, "limit: usize,\n"); + if (this.codecType == Decoder) + { + indent(out, 2, "pub acting_block_length: %s,\n", blockLengthType()); + indent(out, 2, "pub acting_version: %s,\n", schemaVersionType()); + } + indent(out, 1, "}\n\n"); + } + + void appendWrapFn(final Appendable out) throws IOException + { + if (this.codecType == Decoder) + { + indent(out, 2, "pub fn wrap(\n"); + indent(out, 3, "mut self,\n"); + indent(out, 3, "buf: %s,\n", withLifetime(this.codecType.bufType())); + indent(out, 3, "offset: usize,\n"); + indent(out, 3, "acting_block_length: %s,\n", blockLengthType()); + indent(out, 3, "acting_version: %s,\n", schemaVersionType()); + indent(out, 2, ") -> Self {\n"); + indent(out, 3, "let limit = offset + acting_block_length as usize;\n"); + } + else + { + indent(out, 2, "pub fn wrap(mut self, buf: %s, offset: usize) -> Self {\n", + withLifetime(this.codecType.bufType())); + indent(out, 3, "let limit = offset + SBE_BLOCK_LENGTH as usize;\n"); + } + + indent(out, 3, "self.buf = buf;\n"); + indent(out, 3, "self.initial_offset = offset;\n"); + indent(out, 3, "self.offset = offset;\n"); + indent(out, 3, "self.limit = limit;\n"); + if (this.codecType == Decoder) + { + indent(out, 3, "self.acting_block_length = acting_block_length;\n"); + indent(out, 3, "self.acting_version = acting_version;\n"); + } + indent(out, 3, "self\n"); + indent(out, 2, "}\n\n"); + } + + static void generateEncoder( + final Ir ir, + final Writer out, + final Token msgToken, + final List fields, + final List groups, + final List varData) throws IOException + { + final MessageCoderDef coderDef = new MessageCoderDef(ir, msgToken, Encoder); + coderDef.generate(fields, groups, varData); + coderDef.appendTo(out); + } + + static void generateDecoder( + final Ir ir, + final Writer out, + final Token msgToken, + final List fields, + final List groups, + final List varData) throws IOException + { + final MessageCoderDef coderDef = new MessageCoderDef(ir, msgToken, Decoder); + coderDef.generate(fields, groups, varData); + coderDef.appendTo(out); + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java new file mode 100644 index 0000000000..9bd5bb62bb --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -0,0 +1,1455 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.rust; + +import org.agrona.Verify; +import org.agrona.generation.OutputManager; +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.generation.CodeGenerator; +import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.ir.Encoding; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.ir.Signal; +import uk.co.real_logic.sbe.ir.Token; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static java.lang.String.format; +import static uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType.Decoder; +import static uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType.Encoder; +import static uk.co.real_logic.sbe.generation.rust.RustUtil.*; +import static uk.co.real_logic.sbe.ir.GenerationUtil.*; +import static uk.co.real_logic.sbe.ir.Signal.BEGIN_ENUM; +import static uk.co.real_logic.sbe.ir.Signal.BEGIN_SET; + +/** + * Generate codecs for the Rust programming language. + */ +public class RustGenerator implements CodeGenerator +{ + public static final String WRITE_BUF_TYPE = "WriteBuf"; + public static final String READ_BUF_TYPE = "ReadBuf"; + public static final String BUF_LIFETIME = "'a"; + + enum CodecType + { + Decoder + { + @Override String bufType() + { + return READ_BUF_TYPE; + } + }, + + Encoder + { + @Override String bufType() + { + return WRITE_BUF_TYPE; + } + }; + + abstract String bufType(); + } + + interface ParentDef + { + SubGroup addSubGroup(String name, int level, Token groupToken); + } + + private final Ir ir; + private final RustOutputManager outputManager; + + /** + * Create a new Rust language {@link CodeGenerator}. + * + * @param ir for the messages and types. + * @param outputManager for generating the codecs to. + */ + public RustGenerator( + final Ir ir, + final OutputManager outputManager) + { + Verify.notNull(ir, "ir"); + Verify.notNull(outputManager, "outputManager"); + + this.ir = ir; + this.outputManager = (RustOutputManager)outputManager; + } + + @Override + public void generate() throws IOException + { + // create Cargo.toml + try (Writer writer = outputManager.createCargoToml()) + { + final String packageName = ir.packageName().replaceAll("\\.", "_"); + final String namespace; + if (ir.namespaceName() == null || ir.namespaceName().equalsIgnoreCase(packageName)) + { + namespace = packageName.toLowerCase(); + } + else + { + namespace = (ir.namespaceName() + "_" + packageName).toLowerCase(); + } + + indent(writer, 0, "[package]\n"); + indent(writer, 0, "name = \"%s\"\n", namespace); + indent(writer, 0, "version = \"0.1.0\"\n"); + indent(writer, 0, "authors = [\"sbetool\"]\n"); + indent(writer, 0, "description = \"%s\"\n", ir.description()); + indent(writer, 0, "edition = \"2018\"\n\n"); + indent(writer, 0, "[lib]\n"); + indent(writer, 0, "name = \"%s\"\n", namespace); + indent(writer, 0, "path = \"src/lib.rs\"\n"); + } + + // lib.rs + final LibRsDef libRsDef = new LibRsDef(outputManager, ir.byteOrder()); + + generateEnums(ir, libRsDef); + generateBitSets(ir, libRsDef); + generateComposites(ir, libRsDef, outputManager); + + for (final List tokens : ir.messages()) + { + final Token msgToken = tokens.get(0); + + libRsDef.addMod(msgToken.name(), Encoder); + libRsDef.addMod(msgToken.name(), Decoder); + + final List messageBody = getMessageBody(tokens); + + int i = 0; + final List fields = new ArrayList<>(); + i = collectFields(messageBody, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(messageBody, i, groups); + + final List varData = new ArrayList<>(); + collectVarData(messageBody, i, varData); + + try (Writer out = outputManager.createOutput(msgToken.name())) + { + indent(out, 0, "use crate::*;\n\n"); + final String blockLengthType = blockLengthType(); + final String templateIdType = rustTypeName(ir.headerStructure().templateIdType()); + final String schemaIdType = rustTypeName(ir.headerStructure().schemaIdType()); + final String schemaVersionType = schemaVersionType(); + indent(out, 0, "pub const SBE_BLOCK_LENGTH: %s = %d;\n", blockLengthType, msgToken.encodedLength()); + indent(out, 0, "pub const SBE_TEMPLATE_ID: %s = %d;\n", templateIdType, msgToken.id()); + indent(out, 0, "pub const SBE_SCHEMA_ID: %s = %d;\n", schemaIdType, ir.id()); + indent(out, 0, "pub const SBE_SCHEMA_VERSION: %s = %d;\n\n", schemaVersionType, ir.version()); + + MessageCoderDef.generateEncoder(ir, out, msgToken, fields, groups, varData); + MessageCoderDef.generateDecoder(ir, out, msgToken, fields, groups, varData); + } + } + + libRsDef.generate(); + } + + String blockLengthType() + { + return rustTypeName(ir.headerStructure().blockLengthType()); + } + + String schemaVersionType() + { + return rustTypeName(ir.headerStructure().schemaVersionType()); + } + + + static String withLifetime(final String typeName) + { + return format("%s<%s>", typeName, BUF_LIFETIME); + } + + static void appendImplWithLifetimeHeader( + final Appendable appendable, + final String typeName) throws IOException + { + indent(appendable, 1, "impl<%s> %s<%s> {\n", BUF_LIFETIME, typeName, BUF_LIFETIME); + } + + static String getBufOffset(final Token token) + { + final int offset = token.offset(); + if (offset > 0) + { + return "offset + " + offset; + } + + return "offset"; + } + + static void generateEncoderFields( + final StringBuilder sb, + final List tokens, + final int level) + { + Generators.forEachField(tokens, (fieldToken, typeToken) -> + { + try + { + final String name = fieldToken.name(); + switch (typeToken.signal()) + { + case ENCODING: + generatePrimitiveEncoder(sb, level, typeToken, name); + break; + case BEGIN_ENUM: + generateEnumEncoder(sb, level, fieldToken, typeToken, name); + break; + case BEGIN_SET: + generateBitSetEncoder(sb, level, typeToken, name); + break; + case BEGIN_COMPOSITE: + generateCompositeEncoder(sb, level, typeToken, name); + break; + } + } + catch (final IOException e) + { + throw new RuntimeException(e); + } + }); + } + + static void generateEncoderGroups( + final StringBuilder sb, + final List tokens, + final int level, + final ParentDef parentDef) throws IOException + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + ++i; + final int index = i; + final int groupHeaderTokenCount = tokens.get(i).componentTokenCount(); + i += groupHeaderTokenCount; + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + + final String groupName = encoderName(formatStructName(groupToken.name())); + final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); + final PrimitiveType numInGroupPrimitiveType = numInGroupToken.encoding().primitiveType(); + + indent(sb, level, "/// GROUP ENCODER\n"); + assert 4 == groupHeaderTokenCount; + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(self, count: %s, %1$s: %3$s) -> %3$s {\n", + formatFunctionName(groupName), + rustTypeName(numInGroupPrimitiveType), + groupName); + + indent(sb, level + 1, "%s.wrap(self, count)\n", toLowerSnakeCase(groupName)); + indent(sb, level, "}\n\n"); + + final SubGroup subGroup = parentDef.addSubGroup(groupName, level, groupToken); + subGroup.generateEncoder(tokens, fields, groups, varData, index); + } + } + + static void generateEncoderVarData( + final StringBuilder sb, + final List tokens, + final int level) throws IOException + { + for (int i = 0, size = tokens.size(); i < size; ) + { + final Token varDataToken = tokens.get(i); + if (varDataToken.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); + } + + final String characterEncoding = tokens.get(i + 3).encoding().characterEncoding(); + final String propertyName = toLowerSnakeCase(varDataToken.name()); + final Token lengthToken = tokens.get(i + 2); + final Encoding lengthEncoding = lengthToken.encoding(); + final PrimitiveType lengthType = lengthEncoding.primitiveType(); + + final String varDataType; + final String toBytesFn; + switch (characterEncoding) + { + case "UTF-8": + { + varDataType = "&str"; + toBytesFn = ".as_bytes()"; + break; + } + default: + { + varDataType = "&[u8]"; + toBytesFn = ""; + break; + } + } + + // function to write slice ... todo - handle character encoding ? + indent(sb, level, "/// VAR_DATA ENCODER - character encoding %s\n", characterEncoding); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", propertyName, varDataType); + + indent(sb, level + 1, "let limit = self.get_limit();\n"); + indent(sb, level + 1, "let data_length = value.len();\n"); + indent(sb, level + 1, "self.set_limit(limit + %d + data_length);\n", lengthType.size()); + + indent(sb, level + 1, + "self.get_buf_mut().put_%s_at(limit, data_length as %1$s);\n", + rustTypeName(lengthType)); + + indent(sb, level + 1, "self.get_buf_mut().put_slice_at(limit + %d, value%s);\n", + lengthType.size(), + toBytesFn); + + indent(sb, level, "}\n\n"); + + i += varDataToken.componentTokenCount(); + } + } + + private static void generatePrimitiveEncoder( + final StringBuilder sb, + final int level, + final Token typeToken, + final String name) throws IOException + { + final Encoding encoding = typeToken.encoding(); + final PrimitiveType primitiveType = encoding.primitiveType(); + final String rustPrimitiveType = rustTypeName(primitiveType); + final int arrayLength = typeToken.arrayLength(); + if (arrayLength > 1) + { + indent(sb, level, "/// primitive array field %s\n", name); + indent(sb, level, "/// - min value: %s\n", encoding.applicableMinValue()); + indent(sb, level, "/// - max value: %s\n", encoding.applicableMaxValue()); + indent(sb, level, "/// - null value: %s\n", encoding.applicableNullValue()); + indent(sb, level, "/// - characterEncoding: %s\n", encoding.characterEncoding()); + indent(sb, level, "/// - semanticType: %s\n", encoding.semanticType()); + indent(sb, level, "/// - encodedOffset: %d\n", typeToken.offset()); + indent(sb, level, "/// - encodedLength: %d\n", typeToken.encodedLength()); + indent(sb, level, "/// - version: %d\n", typeToken.version()); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(&mut self, value: [%s; %d]) {\n", + formatFunctionName(name), + rustPrimitiveType, + arrayLength); + + // NB: must create variable 'offset' before calling mutable self.get_buf_mut() + indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); + indent(sb, level + 1, "let buf = self.get_buf_mut();\n"); + + for (int i = 0; i < arrayLength; i++) + { + if (i == 0) + { + indent(sb, level + 1, "buf.put_%s_at(offset, value[%d]);\n", rustPrimitiveType, i); + } + else + { + indent(sb, level + 1, "buf.put_%s_at(offset + %d, value[%d]);\n", + rustPrimitiveType, + i * primitiveType.size(), + i); + } + } + + indent(sb, level, "}\n\n"); + } + else + { + if (encoding.presence() == Encoding.Presence.CONSTANT) + { + indent(sb, level, "// skipping CONSTANT %s\n\n", name); + } + else + { + indent(sb, level, "/// primitive field %s\n", name); + indent(sb, level, "/// - min value: %s\n", encoding.applicableMinValue()); + indent(sb, level, "/// - max value: %s\n", encoding.applicableMaxValue()); + indent(sb, level, "/// - null value: %s\n", encoding.applicableNullValue()); + indent(sb, level, "/// - characterEncoding: %s\n", encoding.characterEncoding()); + indent(sb, level, "/// - semanticType: %s\n", encoding.semanticType()); + indent(sb, level, "/// - encodedOffset: %d\n", typeToken.offset()); + indent(sb, level, "/// - encodedLength: %d\n", typeToken.encodedLength()); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", + formatFunctionName(name), + rustPrimitiveType); + + // NB: must create variable 'offset' before calling mutable self.get_buf_mut() + indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); + indent(sb, level + 1, "self.get_buf_mut().put_%s_at(offset, value);\n", rustPrimitiveType); + indent(sb, level, "}\n\n"); + } + } + } + + private static void generateEnumEncoder( + final StringBuilder sb, + final int level, + final Token fieldToken, + final Token typeToken, + final String name) throws IOException + { + final String referencedName = typeToken.referencedName(); + final String enumType = formatStructName(referencedName == null ? typeToken.name() : referencedName); + + if (fieldToken.isConstantEncoding()) + { + indent(sb, level, "// skipping CONSTANT %s\n\n", name); + } + else + { + final Encoding encoding = typeToken.encoding(); + final String rustPrimitiveType = rustTypeName(encoding.primitiveType()); + + indent(sb, level, "/// REQUIRED\n"); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", formatFunctionName(name), enumType); + + // NB: must create variable 'offset' before calling mutable self.get_buf_mut() + indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); + indent(sb, level + 1, "self.get_buf_mut().put_%s_at(offset, value as %1$s)\n", rustPrimitiveType); + indent(sb, level, "}\n\n"); + } + } + + private static void generateBitSetEncoder( + final StringBuilder sb, + final int level, + final Token bitsetToken, + final String name) throws IOException + { + final Encoding encoding = bitsetToken.encoding(); + final String rustPrimitiveType = rustTypeName(encoding.primitiveType()); + final String structTypeName = formatStructName(bitsetToken.applicableTypeName()); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", formatFunctionName(name), structTypeName); + + // NB: must create variable 'offset' before calling mutable self.get_buf_mut() + indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(bitsetToken)); + indent(sb, level + 1, "self.get_buf_mut().put_%s_at(offset, value.0)\n", rustPrimitiveType); + indent(sb, level, "}\n\n"); + } + + private static void generateCompositeEncoder( + final StringBuilder sb, + final int level, + final Token typeToken, + final String name) throws IOException + { + final String encoderName = toLowerSnakeCase(encoderName(name)); + final String encoderTypeName = encoderName(formatStructName(typeToken.name())); + indent(sb, level, "/// COMPOSITE ENCODER\n"); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(self, %1$s: %2$s) -> %2$s {\n", + encoderName, + encoderTypeName); + + // NB: must create variable 'offset' before moving 'self' + indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); + indent(sb, level + 1, "%s.wrap(self, offset)\n", encoderName); + indent(sb, level, "}\n\n"); + } + + static void generateDecoderFields( + final StringBuilder sb, + final List tokens, + final int level) + { + Generators.forEachField(tokens, (fieldToken, typeToken) -> + { + try + { + final String name = fieldToken.name(); + final Encoding encoding = typeToken.encoding(); + + switch (typeToken.signal()) + { + case ENCODING: + generatePrimitiveDecoder(sb, level, typeToken, name, encoding); + break; + case BEGIN_ENUM: + generateEnumDecoder(sb, level, fieldToken, typeToken, name); + break; + case BEGIN_SET: + generateBitSetDecoder(sb, level, typeToken, name); + break; + case BEGIN_COMPOSITE: + generateCompositeDecoder(sb, level, typeToken, name); + break; + default: + throw new UnsupportedOperationException("Unable to handle: " + typeToken); + } + } + catch (final IOException e) + { + throw new RuntimeException(e); + } + }); + } + + private static void generateCompositeDecoder( + final StringBuilder sb, + final int level, + final Token typeToken, + final String name) throws IOException + { + final String decoderName = toLowerSnakeCase(decoderName(name)); + final String decoderTypeName = decoderName(formatStructName(typeToken.name())); + indent(sb, level, "/// COMPOSITE DECODER\n"); + indent(sb, level, "#[inline]\n"); + if (typeToken.version() > 0) + { + indent(sb, level, "pub fn %s(self) -> Either> {\n", + decoderName, + decoderTypeName); + + indent(sb, level + 1, "if self.acting_version < %d {\n", typeToken.version()); + indent(sb, level + 2, "return Either::Left(self);\n"); + indent(sb, level + 1, "}\n\n"); + + indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); + indent(sb, level + 1, "Either::Right(%s::default().wrap(self, offset))\n", + decoderTypeName); + } + else + { + indent(sb, level, "pub fn %s(self) -> %2$s {\n", + decoderName, + decoderTypeName); + + indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); + indent(sb, level + 1, "%s::default().wrap(self, offset)\n", decoderTypeName); + } + indent(sb, level, "}\n\n"); + } + + private static void generateBitSetDecoder( + final StringBuilder sb, + final int level, + final Token bitsetToken, + final String name) throws IOException + { + final Encoding encoding = bitsetToken.encoding(); + final String rustPrimitiveType = rustTypeName(encoding.primitiveType()); + final String structTypeName = formatStructName(bitsetToken.applicableTypeName()); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(&self) -> %s {\n", formatFunctionName(name), structTypeName); + indent(sb, level + 1, "%s::new(self.get_buf().get_%s_at(self.%s))\n", + structTypeName, + rustPrimitiveType, + getBufOffset(bitsetToken)); + indent(sb, level, "}\n\n"); + } + + private static void generatePrimitiveDecoder( + final StringBuilder sb, + final int level, + final Token typeToken, + final String name, + final Encoding encoding) throws IOException + { + if (typeToken.arrayLength() > 1) + { + generatePrimitiveArrayDecoder(sb, level, typeToken, name, encoding); + } + else if (encoding.presence() == Encoding.Presence.CONSTANT) + { + generatePrimitiveConstantDecoder(sb, level, name, encoding); + } + else if (encoding.presence() == Encoding.Presence.OPTIONAL) + { + generatePrimitiveOptionalDecoder(sb, level, typeToken, name, encoding); + } + else + { + generatePrimitiveRequiredDecoder(sb, level, typeToken, name, encoding); + } + } + + private static void generatePrimitiveArrayDecoder( + final StringBuilder sb, + final int level, + final Token typeToken, + final String name, + final Encoding encoding) throws IOException + { + final PrimitiveType primitiveType = encoding.primitiveType(); + final String rustPrimitiveType = rustTypeName(primitiveType); + + final int arrayLength = typeToken.arrayLength(); + assert arrayLength > 1; + + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(&self) -> [%s; %d] {\n", + formatFunctionName(name), + rustPrimitiveType, + arrayLength); + + if (typeToken.version() > 0) + { + indent(sb, level + 1, "if self.acting_version < %d {\n", typeToken.version()); + indent(sb, level + 2, "return [%s, %d];\n", encoding.applicableNullValue(), arrayLength); + indent(sb, level + 1, "}\n\n"); + } + + indent(sb, level + 1, "let buf = self.get_buf();\n"); + indent(sb, level + 1, "[\n"); + for (int i = 0; i < arrayLength; i++) + { + if (i == 0) + { + indent(sb, level + 2, "buf.get_%s_at(self.%s),\n", + rustPrimitiveType, + getBufOffset(typeToken)); + } + else + { + indent(sb, level + 2, "buf.get_%s_at(self.%s + %d),\n", + rustPrimitiveType, + getBufOffset(typeToken), + i * primitiveType.size()); + } + } + indent(sb, level + 1, "]\n"); + indent(sb, level, "}\n\n"); + } + + private static void generatePrimitiveConstantDecoder( + final StringBuilder sb, + final int level, + final String name, + final Encoding encoding) throws IOException + { + assert encoding.presence() == Encoding.Presence.CONSTANT; + final PrimitiveType primitiveType = encoding.primitiveType(); + final String rustPrimitiveType = rustTypeName(primitiveType); + final String characterEncoding = encoding.characterEncoding(); + + indent(sb, level, "/// CONSTANT \n"); + final String rawConstValue = encoding.constValue().toString(); + if (characterEncoding != null) + { + indent(sb, level, "/// characterEncoding: '%s'\n", characterEncoding); + indent(sb, level, "#[inline]\n"); + + switch (characterEncoding) + { + case "US-ASCII": + { + indent(sb, level, "pub fn %s(&self) -> &'static [u8] {\n", + formatFunctionName(name)); + indent(sb, level + 1, "b\"%s\"\n", rawConstValue); + break; + } + case "UTF-8": + { + indent(sb, level, "pub fn %s(&self) -> &'static str {\n", formatFunctionName(name)); + indent(sb, level + 1, "\"%s\"\n", rawConstValue); + break; + } + default: + throw new RuntimeException("Unable to handle " + characterEncoding); + } + + indent(sb, level, "}\n\n"); + } + else + { + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(&self) -> %s {\n", + formatFunctionName(name), + rustPrimitiveType); + indent(sb, level + 1, "%s\n", rawConstValue); + indent(sb, level, "}\n\n"); + } + } + + private static void generatePrimitiveOptionalDecoder( + final StringBuilder sb, + final int level, + final Token typeToken, + final String name, + final Encoding encoding) throws IOException + { + assert encoding.presence() == Encoding.Presence.OPTIONAL; + final PrimitiveType primitiveType = encoding.primitiveType(); + final String rustPrimitiveType = rustTypeName(primitiveType); + final String characterEncoding = encoding.characterEncoding(); + indent(sb, level, "/// primitive field - %s { null_value: '%s' }\n", + encoding.presence(), encoding.applicableNullValue()); + + if (characterEncoding != null) + { + // ASCII and UTF-8 + indent(sb, level, "/// characterEncoding: '%s'\n", characterEncoding); + } + + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(&self) -> Option<%s> {\n", + formatFunctionName(name), + rustPrimitiveType); + + if (typeToken.version() > 0) + { + indent(sb, level + 1, "if self.acting_version < %d {\n", typeToken.version()); + indent(sb, level + 2, "return None;\n"); + indent(sb, level + 1, "}\n\n"); + } + + indent(sb, level + 1, "let value = self.get_buf().get_%s_at(self.%s);\n", + rustPrimitiveType, + getBufOffset(typeToken)); + indent(sb, level + 1, "if value == %s {\n", + generateRustLiteral(primitiveType, encoding.applicableNullValue().toString())); + indent(sb, level + 2, "None\n"); + indent(sb, level + 1, "} else {\n"); + indent(sb, level + 2, "Some(value)\n"); + indent(sb, level + 1, "}\n"); + indent(sb, level, "}\n\n"); + } + + private static void generatePrimitiveRequiredDecoder( + final StringBuilder sb, + final int level, + final Token typeToken, + final String name, + final Encoding encoding) throws IOException + { + assert encoding.presence() == Encoding.Presence.REQUIRED; + final PrimitiveType primitiveType = encoding.primitiveType(); + final String rustPrimitiveType = rustTypeName(primitiveType); + final String characterEncoding = encoding.characterEncoding(); + indent(sb, level, "/// primitive field - %s\n", encoding.presence()); + + if (characterEncoding != null) + { + // ASCII and UTF-8 + indent(sb, level, "/// characterEncoding: '%s'\n", characterEncoding); + } + + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(&self) -> %s {\n", + formatFunctionName(name), + rustPrimitiveType); + + if (typeToken.version() > 0) + { + indent(sb, level + 1, "if self.acting_version < %d {\n", typeToken.version()); + indent(sb, level + 2, "return %s;\n", + generateRustLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString())); + indent(sb, level + 1, "}\n\n"); + } + + indent(sb, level + 1, "self.get_buf().get_%s_at(self.%s)\n", + rustPrimitiveType, + getBufOffset(typeToken)); + indent(sb, level, "}\n\n"); + + } + + private static void generateEnumDecoder( + final StringBuilder sb, + final int level, + final Token fieldToken, + final Token typeToken, + final String name) throws IOException + { + final String referencedName = typeToken.referencedName(); + final String enumType = formatStructName(referencedName == null ? typeToken.name() : referencedName); + + if (fieldToken.isConstantEncoding()) + { + indent(sb, level, "/// CONSTANT \n"); + final Encoding encoding = fieldToken.encoding(); + final String rawConstValueName = encoding.constValue().toString(); + final int indexOfDot = rawConstValueName.indexOf('.'); + final String constValueName = -1 == indexOfDot ? + rawConstValueName : + rawConstValueName.substring(indexOfDot + 1); + + final String constantRustExpression = enumType + "::" + constValueName; + appendConstAccessor(sb, name, enumType, constantRustExpression, level); + } + else + { + final Encoding encoding = typeToken.encoding(); + final String rustPrimitiveType = rustTypeName(encoding.primitiveType()); + + indent(sb, level, "/// REQUIRED\n"); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(&self) -> %s {\n", formatFunctionName(name), enumType); + indent(sb, level + 1, "self.get_buf().get_%s_at(self.%s).into()\n", + rustPrimitiveType, + getBufOffset(typeToken)); + indent(sb, level, "}\n\n"); + } + } + + static void generateDecoderGroups( + final StringBuilder sb, + final List tokens, + final int level, + final ParentDef parentDef) throws IOException + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + ++i; + final int index = i; + final int groupHeaderTokenCount = tokens.get(i).componentTokenCount(); + i += groupHeaderTokenCount; + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + + final String groupName = decoderName(formatStructName(groupToken.name())); + indent(sb, level, "/// GROUP DECODER\n"); + assert 4 == groupHeaderTokenCount; + + indent(sb, level, "#[inline]\n"); + if (groupToken.version() > 0) + { + indent(sb, level, "pub fn %s(self) -> Option<%2$s> {\n", + formatFunctionName(groupName), groupName); + + indent(sb, level + 1, "if self.acting_version < %d {\n", groupToken.version()); + indent(sb, level + 2, "return None;\n"); + indent(sb, level + 1, "}\n\n"); + + indent(sb, level + 1, "let acting_version = self.acting_version;\n"); + indent(sb, level + 1, "Some(%s::default().wrap(self, acting_version as usize))\n", + groupName); + } + else + { + indent(sb, level, "pub fn %s(self) -> %2$s {\n", + formatFunctionName(groupName), groupName); + + indent(sb, level + 1, "let acting_version = self.acting_version;\n"); + indent(sb, level + 1, "%s::default().wrap(self, acting_version as usize)\n", + groupName); + } + indent(sb, level, "}\n\n"); + + final SubGroup subGroup = parentDef.addSubGroup(groupName, level, groupToken); + subGroup.generateDecoder(tokens, fields, groups, varData, index); + } + } + + static void generateDecoderVarData( + final StringBuilder sb, + final List tokens, + final int level, + final boolean isSubGroup) throws IOException + { + for (int i = 0, size = tokens.size(); i < size; ) + { + final Token varDataToken = tokens.get(i); + if (varDataToken.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); + } + + final String characterEncoding = tokens.get(i + 3).encoding().characterEncoding(); + final String propertyName = toLowerSnakeCase(varDataToken.name()); + final Token lengthToken = tokens.get(i + 2); + final Encoding lengthEncoding = lengthToken.encoding(); + final PrimitiveType lengthType = lengthEncoding.primitiveType(); + + indent(sb, level, "/// VAR_DATA DECODER - character encoding %s\n", characterEncoding); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s_decoder(&mut self) -> (usize, usize) {\n", propertyName); + + if (isSubGroup) + { + if (varDataToken.version() > 0) + { + indent(sb, level + 1, "if self.acting_version < %d {\n", varDataToken.version()); + indent(sb, level + 2, "return (self.parent.as_ref().unwrap().get_limit(), 0);\n"); + indent(sb, level + 1, "}\n\n"); + } + + indent(sb, level + 1, "let offset = self.parent.as_ref().expect(\"parent missing\").get_limit();\n"); + indent(sb, level + 1, "let data_length = self.get_buf().get_%s_at(offset) as usize;\n", + rustTypeName(lengthType)); + indent(sb, level + 1, "self.parent.as_mut().unwrap().set_limit(offset + %d + data_length);\n", + lengthType.size()); + } + else + { + if (varDataToken.version() > 0) + { + indent(sb, level + 1, "if self.acting_version < %d {\n", varDataToken.version()); + indent(sb, level + 2, "return (self.get_limit(), 0);\n"); + indent(sb, level + 1, "}\n\n"); + } + + indent(sb, level + 1, "let offset = self.get_limit();\n"); + indent(sb, level + 1, "let data_length = self.get_buf().get_%s_at(offset) as usize;\n", + rustTypeName(lengthType)); + indent(sb, level + 1, "self.set_limit(offset + %d + data_length);\n", lengthType.size()); + } + indent(sb, level + 1, "(offset + %d, data_length)\n", lengthType.size()); + indent(sb, level, "}\n\n"); + + // function to return slice form given coord + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s_slice(&'a self, coordinates: (usize, usize)) -> &'a [u8] {\n", propertyName); + + if (varDataToken.version() > 0) + { + indent(sb, level + 1, "if self.acting_version < %d {\n", varDataToken.version()); + indent(sb, level + 2, "return &[] as &[u8];\n"); + indent(sb, level + 1, "}\n\n"); + } + + indent(sb, level + 1, "debug_assert!(self.get_limit() >= coordinates.0 + coordinates.1);\n"); + indent(sb, level + 1, "self.get_buf().get_slice_at(coordinates.0, coordinates.1)\n"); + indent(sb, level, "}\n\n"); + + i += varDataToken.componentTokenCount(); + } + } + + private static void generateBitSets( + final Ir ir, + final LibRsDef libRsDef) throws IOException + { + for (final List tokens : ir.types()) + { + if (!tokens.isEmpty() && tokens.get(0).signal() == BEGIN_SET) + { + final StringBuilder sb = new StringBuilder(); + generateSingleBitSet(tokens, sb); + libRsDef.addBitSet(sb.toString()); + } + } + } + + private static void generateSingleBitSet( + final List tokens, + final Appendable writer) throws IOException + { + final Token beginToken = tokens.get(0); + final String setType = formatStructName(beginToken.applicableTypeName()); + final String rustPrimitiveType = rustTypeName(beginToken.encoding().primitiveType()); + indent(writer, 0, "#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]\n"); + indent(writer, 0, "pub struct %s(pub %s);\n", setType, rustPrimitiveType); + indent(writer, 0, "impl %s {\n", setType); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "pub fn new(value: %s) -> Self {\n", rustPrimitiveType); + indent(writer, 2, "%s(value)\n", setType); + indent(writer, 1, "}\n\n"); + + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "pub fn clear(&mut self) -> &mut Self {\n"); + indent(writer, 2, "self.0 = 0;\n"); + indent(writer, 2, "self\n"); + indent(writer, 1, "}\n"); + + for (final Token token : tokens) + { + if (Signal.CHOICE != token.signal()) + { + continue; + } + + final String choiceName = formatFunctionName(token.name()); + final Encoding encoding = token.encoding(); + final String choiceBitIndex = encoding.constValue().toString(); + + indent(writer, 0, "\n"); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "pub fn get_%s(&self) -> bool {\n", choiceName); + indent(writer, 2, "0 != self.0 & (1 << %s)\n", choiceBitIndex); + indent(writer, 1, "}\n\n"); + + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "pub fn set_%s(&mut self, value: bool) -> &mut Self {\n", choiceName); + indent(writer, 2, "self.0 = if value {\n"); + indent(writer, 3, "self.0 | (1 << %s)\n", choiceBitIndex); + indent(writer, 2, "} else {\n"); + indent(writer, 3, "self.0 & !(1 << %s)\n", choiceBitIndex); + indent(writer, 2, "};\n"); + indent(writer, 2, "self\n"); + indent(writer, 1, "}\n"); + } + indent(writer, 0, "}\n"); + + indent(writer, 0, "impl core::fmt::Debug for %s {\n", setType); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {\n"); + indent(writer, 2, "write!(fmt, \"%s[", setType); + + final StringBuilder builder = new StringBuilder(); + final StringBuilder arguments = new StringBuilder(); + boolean comma = false; + for (final Token token : tokens) + { + if (Signal.CHOICE != token.signal()) + { + continue; + } + + final String choiceName = formatFunctionName(token.name()); + final String choiceBitIndex = token.encoding().constValue().toString(); + + if (comma) + { + builder.append(","); + } + + builder.append(choiceName).append("(").append(choiceBitIndex).append(")={}"); + arguments.append("self.get_").append(choiceName).append("(),"); + comma = true; + } + + writer.append(builder.toString()).append("]\",\n"); + indent(writer, 3, arguments + ")\n"); + indent(writer, 1, "}\n"); + indent(writer, 0, "}\n"); + } + + static void appendImplEncoderTrait( + final Appendable out, + final String typeName) throws IOException + { + indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withLifetime("Writer"), withLifetime(typeName)); + indent(out, 2, "#[inline]\n"); + indent(out, 2, "fn get_buf_mut(&mut self) -> &mut WriteBuf<'a> {\n"); + indent(out, 3, "&mut self.buf\n"); + indent(out, 2, "}\n"); + indent(out, 1, "}\n\n"); + + indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withLifetime("Encoder"), withLifetime(typeName)); + indent(out, 2, "#[inline]\n"); + indent(out, 2, "fn get_limit(&self) -> usize {\n"); + indent(out, 3, "self.limit\n"); + indent(out, 2, "}\n\n"); + + indent(out, 2, "#[inline]\n"); + indent(out, 2, "fn set_limit(&mut self, limit: usize) {\n"); + indent(out, 3, "self.limit = limit;\n"); + indent(out, 2, "}\n"); + indent(out, 1, "}\n\n"); + } + + static void appendImplDecoderTrait( + final Appendable out, + final String typeName) throws IOException + { + indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withLifetime("Reader"), withLifetime(typeName)); + indent(out, 2, "#[inline]\n"); + indent(out, 2, "fn get_buf(&self) -> &ReadBuf<'a> {\n"); + indent(out, 3, "&self.buf\n"); + indent(out, 2, "}\n"); + indent(out, 1, "}\n\n"); + + indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withLifetime("Decoder"), withLifetime(typeName)); + indent(out, 2, "#[inline]\n"); + indent(out, 2, "fn get_limit(&self) -> usize {\n"); + indent(out, 3, "self.limit\n"); + indent(out, 2, "}\n\n"); + + indent(out, 2, "#[inline]\n"); + indent(out, 2, "fn set_limit(&mut self, limit: usize) {\n"); + indent(out, 3, "self.limit = limit;\n"); + indent(out, 2, "}\n"); + indent(out, 1, "}\n\n"); + } + + private static void generateEnums( + final Ir ir, + final LibRsDef libRsDef) throws IOException + { + final Set enumTypeNames = new HashSet<>(); + for (final List tokens : ir.types()) + { + if (tokens.isEmpty()) + { + continue; + } + + final Token beginToken = tokens.get(0); + if (beginToken.signal() != BEGIN_ENUM) + { + continue; + } + + final String typeName = beginToken.applicableTypeName(); + if (enumTypeNames.contains(typeName)) + { + continue; + } + + final StringBuilder sb = new StringBuilder(); + generateEnum(tokens, sb); + enumTypeNames.add(typeName); + + libRsDef.addEnum(sb.toString()); + } + } + + private static void generateEnum( + final List enumTokens, + final Appendable writer) throws IOException + { + final String originalEnumName = enumTokens.get(0).applicableTypeName(); + final String enumRustName = formatStructName(originalEnumName); + final List messageBody = getMessageBody(enumTokens); + if (messageBody.isEmpty()) + { + throw new IllegalArgumentException("No valid values provided for enum " + originalEnumName); + } + + indent(writer, 0, "#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]\n"); + final String primitiveType = rustTypeName(messageBody.get(0).encoding().primitiveType()); + indent(writer, 0, "#[repr(%s)]\n", primitiveType); + indent(writer, 0, "pub enum %s {\n", enumRustName); + + for (final Token token : messageBody) + { + final Encoding encoding = token.encoding(); + final String literal = generateRustLiteral(encoding.primitiveType(), encoding.constValue().toString()); + indent(writer, 1, "%s = %s, \n", token.name(), literal); + } + + // null value + { + final Encoding encoding = messageBody.get(0).encoding(); + final CharSequence nullVal = generateRustLiteral(encoding.primitiveType(), + encoding.applicableNullValue().toString()); + indent(writer, 1, "NullVal = %s, \n", nullVal); + } + indent(writer, 0, "}\n"); + + // Default implementation to support Default in other structs + indent(writer, 0, "impl Default for %s {\n", enumRustName); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn default() -> Self { %s::%s }\n", enumRustName, "NullVal"); + indent(writer, 0, "}\n"); + + // From impl + indent(writer, 0, "impl From<%s> for %s {\n", primitiveType, enumRustName); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn from(v: %s) -> Self {\n", primitiveType); + indent(writer, 2, "match v {\n"); + + for (final Token token : messageBody) + { + final Encoding encoding = token.encoding(); + final String literal = generateRustLiteral(encoding.primitiveType(), encoding.constValue().toString()); + indent(writer, 3, "%s => Self::%s, \n", literal, token.name()); + } + + // default => NullVal + indent(writer, 3, "_ => Self::NullVal,\n"); + indent(writer, 2, "}\n"); + indent(writer, 1, "}\n"); + indent(writer, 0, "}\n"); + } + + private static void generateComposites( + final Ir ir, + final LibRsDef libRsDef, + final OutputManager outputManager) throws IOException + { + for (final List tokens : ir.types()) + { + if (!tokens.isEmpty() && tokens.get(0).signal() == Signal.BEGIN_COMPOSITE) + { + generateComposite(tokens, libRsDef, outputManager); + } + } + } + + private static void generateComposite( + final List tokens, + final LibRsDef libRsDef, + final OutputManager outputManager) throws IOException + { + final Token token = tokens.get(0); + final String compositeName = token.applicableTypeName(); + + try (Writer out = outputManager.createOutput(compositeName)) + { + indent(out, 0, "use crate::*;\n\n"); + + final int encodedLength = tokens.get(0).encodedLength(); + if (encodedLength > 0) + { + indent(out, 0, "pub const ENCODED_LENGTH: usize = %d;\n\n", encodedLength); + } + + generateCompositeEncoder(tokens, libRsDef, compositeName, encoderName(compositeName), out); + indent(out, 0, "\n"); + generateCompositeDecoder(tokens, libRsDef, compositeName, decoderName(compositeName), out); + } + } + + static void appendImplWriterForComposite( + final Appendable out, + final int level, + final String name) throws IOException + { + // impl Decoder... + indent(out, level, "impl<'a, P> Writer<'a> for %s

    where P: Writer<'a> {\n", name); + indent(out, level + 1, "#[inline]\n"); + indent(out, level + 1, "fn get_buf_mut(&mut self) -> &mut WriteBuf<'a> {\n"); + indent(out, level + 2, "if let Some(parent) = self.parent.as_mut() {\n"); + indent(out, level + 3, "parent.get_buf_mut()\n"); + indent(out, level + 2, "} else {\n"); + indent(out, level + 3, "panic!(\"parent was None\")\n"); + indent(out, level + 2, "}\n"); + indent(out, level + 1, "}\n"); + indent(out, level, "}\n\n"); + } + + static void appendImplEncoderForComposite( + final Appendable out, + final int level, + final String name) throws IOException + { + appendImplWriterForComposite(out, level, name); + + // impl Encoder... + indent(out, level, "impl<'a, P> Encoder<'a> for %s

    where P: Encoder<'a> {\n", name); + indent(out, level + 1, "#[inline]\n"); + indent(out, level + 1, "fn get_limit(&self) -> usize {\n"); + indent(out, level + 2, "self.parent.as_ref().expect(\"parent missing\").get_limit()\n"); + indent(out, level + 1, "}\n\n"); + + indent(out, level + 1, "#[inline]\n"); + indent(out, level + 1, "fn set_limit(&mut self, limit: usize) {\n"); + indent(out, level + 2, "self.parent.as_mut().expect(\"parent missing\").set_limit(limit);\n"); + indent(out, level + 1, "}\n"); + indent(out, level, "}\n\n"); + } + + static void appendImplReaderForComposite( + final Appendable out, + final int level, + final String name) throws IOException + { + // impl Reader... + indent(out, level, "impl<'a, P> Reader<'a> for %s

    where P: Reader<'a> + Default {\n", name); + indent(out, level + 1, "#[inline]\n"); + indent(out, level + 1, "fn get_buf(&self) -> &ReadBuf<'a> {\n"); + indent(out, level + 2, "self.parent.as_ref().expect(\"parent missing\").get_buf()\n"); + indent(out, level + 1, "}\n"); + indent(out, level, "}\n\n"); + } + + static void appendImplDecoderForComposite( + final Appendable out, + final int level, + final String name) throws IOException + { + appendImplReaderForComposite(out, level, name); + + // impl Decoder... + indent(out, level, "impl<'a, P> Decoder<'a> for %s

    where P: Decoder<'a> + Default {\n", name); + indent(out, level + 1, "#[inline]\n"); + indent(out, level + 1, "fn get_limit(&self) -> usize {\n"); + indent(out, level + 2, "self.parent.as_ref().expect(\"parent missing\").get_limit()\n"); + indent(out, level + 1, "}\n\n"); + + indent(out, level + 1, "#[inline]\n"); + indent(out, level + 1, "fn set_limit(&mut self, limit: usize) {\n"); + indent(out, level + 2, "self.parent.as_mut().expect(\"parent missing\").set_limit(limit);\n"); + indent(out, level + 1, "}\n"); + indent(out, level, "}\n\n"); + } + + private static void generateCompositeEncoder( + final List tokens, + final LibRsDef libRsDef, + final String compositeName, + final String encoderName, + final Writer out) throws IOException + { + libRsDef.addMod(compositeName, Encoder); + + indent(out, 0, "pub mod encoder {\n"); + indent(out, 1, "use super::*;\n\n"); + + // define struct... + indent(out, 1, "#[derive(Debug, Default)]\n"); + indent(out, 1, "pub struct %s

    {\n", encoderName); + indent(out, 2, "parent: Option

    ,\n"); + indent(out, 2, "offset: usize,\n"); + indent(out, 1, "}\n\n"); + + appendImplWriterForComposite(out, 1, encoderName); + + // impl<'a> start + indent(out, 1, "impl<'a, P> %s

    where P: Writer<'a> {\n", encoderName); + indent(out, 2, "pub fn wrap(mut self, parent: P, offset: usize) -> Self {\n"); + indent(out, 3, "self.parent = Some(parent);\n"); + indent(out, 3, "self.offset = offset;\n"); + indent(out, 3, "self\n"); + indent(out, 2, "}\n\n"); + + // parent fn... + indent(out, 2, "#[inline]\n"); + indent(out, 2, "pub fn parent(&mut self) -> SbeResult

    {\n"); + indent(out, 3, "self.parent.take().ok_or(SbeErr::ParentNotSet)\n"); + indent(out, 2, "}\n\n"); + + for (int i = 1, end = tokens.size() - 1; i < end; ) + { + final Token encodingToken = tokens.get(i); + final StringBuilder sb = new StringBuilder(); + + switch (encodingToken.signal()) + { + case ENCODING: + generatePrimitiveEncoder(sb, 2, encodingToken, encodingToken.name()); + break; + case BEGIN_ENUM: + generateEnumEncoder(sb, 2, encodingToken, encodingToken, encodingToken.name()); + break; + case BEGIN_SET: + generateBitSetEncoder(sb, 2, encodingToken, encodingToken.name()); + break; + case BEGIN_COMPOSITE: + generateCompositeEncoder(sb, 2, encodingToken, encodingToken.name()); + break; + } + + out.append(sb); + i += encodingToken.componentTokenCount(); + } + + indent(out, 1, "}\n"); // end impl + indent(out, 0, "} // end encoder mod \n"); + } + + private static void generateCompositeDecoder( + final List tokens, + final LibRsDef libRsDef, + final String compositeName, + final String decoderName, + final Writer out) throws IOException + { + indent(out, 0, "pub mod decoder {\n"); + indent(out, 1, "use super::*;\n\n"); + + libRsDef.addMod(compositeName, Decoder); + + indent(out, 1, "#[derive(Debug, Default)]\n"); + indent(out, 1, "pub struct %s

    {\n", decoderName); + indent(out, 2, "parent: Option

    ,\n"); + indent(out, 2, "offset: usize,\n"); + indent(out, 1, "}\n\n"); + + appendImplReaderForComposite(out, 1, decoderName); + + // impl<'a, P> start + indent(out, 1, "impl<'a, P> %s

    where P: Reader<'a> + Default {\n", decoderName); + indent(out, 2, "pub fn wrap(mut self, parent: P, offset: usize) -> Self {\n"); + indent(out, 3, "self.parent = Some(parent);\n"); + indent(out, 3, "self.offset = offset;\n"); + indent(out, 3, "self\n"); + indent(out, 2, "}\n\n"); + + // parent fn... + indent(out, 2, "#[inline]\n"); + indent(out, 2, "pub fn parent(&mut self) -> SbeResult

    {\n"); + indent(out, 3, "self.parent.take().ok_or(SbeErr::ParentNotSet)\n"); + indent(out, 2, "}\n\n"); + + for (int i = 1, end = tokens.size() - 1; i < end; ) + { + final Token encodingToken = tokens.get(i); + final StringBuilder sb = new StringBuilder(); + + switch (encodingToken.signal()) + { + case ENCODING: + generatePrimitiveDecoder(sb, 2, encodingToken, encodingToken.name(), encodingToken.encoding()); + break; + case BEGIN_ENUM: + generateEnumDecoder(sb, 2, encodingToken, encodingToken, encodingToken.name()); + break; + case BEGIN_SET: + generateBitSetDecoder(sb, 2, encodingToken, encodingToken.name()); + break; + case BEGIN_COMPOSITE: + generateCompositeDecoder(sb, 2, encodingToken, encodingToken.name()); + break; + } + + out.append(sb); + i += encodingToken.componentTokenCount(); + } + + indent(out, 1, "}\n"); // end impl + indent(out, 0, "} // end decoder mod \n"); + } + + private static void appendConstAccessor( + final Appendable writer, + final String name, + final String rustTypeName, + final String rustExpression, + final int level) throws IOException + { + indent(writer, level, "#[inline]\n"); + indent(writer, level, "pub fn %s(&self) -> %s {\n", formatFunctionName(name), rustTypeName); + indent(writer, level + 1, rustExpression + "\n"); + indent(writer, level, "}\n\n"); + } + + +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java new file mode 100644 index 0000000000..e1cd8d9941 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java @@ -0,0 +1,92 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.rust; + +import org.agrona.Verify; +import org.agrona.generation.OutputManager; + +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; + +import static java.io.File.separatorChar; +import static uk.co.real_logic.sbe.generation.rust.RustUtil.toLowerSnakeCase; + +/** + * {@link OutputManager} for managing the creation of Rust source files as the target of code generation. + * The character encoding for the {@link java.io.Writer} is UTF-8. + */ +public class RustOutputManager implements OutputManager +{ + private final File rootDir; + private final File srcDir; + + /** + * Create a new {@link OutputManager} for generating rust source files into a given module. + * @param baseDirName for the generated source code. + * @param packageName for the generated source code relative to the baseDirName. + */ + public RustOutputManager(final String baseDirName, final String packageName) + { + Verify.notNull(baseDirName, "baseDirName"); + Verify.notNull(packageName, "packageName"); + + String dirName = baseDirName.endsWith("" + separatorChar) ? baseDirName : baseDirName + separatorChar; + dirName += packageName.replaceAll("\\.", "_").toLowerCase() + separatorChar; + final String libDirName = dirName; + rootDir = new File(libDirName); + + final String srcDirName = libDirName + separatorChar + "src"; + + srcDir = new File(srcDirName); + if (!srcDir.exists() && !srcDir.mkdirs()) + { + throw new IllegalStateException("Unable to create directory: " + srcDirName); + } + } + + /** + * Create a new output which will be a rust source file in the given module. + *

    + * The {@link java.io.Writer} should be closed once the caller has finished with it. The Writer is + * buffered for efficient IO operations. + * + * @param name the name of the rust struct. + * @return a {@link java.io.Writer} to which the source code should be written. + * @throws IOException if an issue occurs when creating the file. + */ + @Override public Writer createOutput(final String name) throws IOException + { + final String fileName = toLowerSnakeCase(name) + ".rs"; + final File targetFile = new File(srcDir, fileName); + return Files.newBufferedWriter(targetFile.toPath(), StandardCharsets.UTF_8); + } + + /** + * + * @return a {@link java.io.Writer} to which the crate definition should be written. + * @throws IOException if an issue occurs when creating the file. + */ + public Writer createCargoToml() throws IOException + { + final String fileName = "Cargo.toml"; + final File targetFile = new File(rootDir, fileName); + return Files.newBufferedWriter(targetFile.toPath(), StandardCharsets.UTF_8); + } + +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java new file mode 100644 index 0000000000..c9c077a21e --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -0,0 +1,299 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.rust; + +import org.agrona.Verify; +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.*; + +import static java.lang.Long.parseLong; +import static java.lang.String.format; +import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; +import static uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType.Decoder; +import static uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType.Encoder; + +/** + * + */ +public class RustUtil +{ + static final String INDENT = " "; + public static final Map TYPE_NAME_BY_PRIMITIVE_TYPE_MAP = + new EnumMap<>(PrimitiveType.class); + + static + { + TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.CHAR, "u8"); + TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.INT8, "i8"); + TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.INT16, "i16"); + TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.INT32, "i32"); + TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.INT64, "i64"); + TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.UINT8, "u8"); + TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.UINT16, "u16"); + TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.UINT32, "u32"); + TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.UINT64, "u64"); + TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.FLOAT, "f32"); + TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.DOUBLE, "f64"); + } + + /** + * Map the name of a {@link PrimitiveType} to a Rust primitive type name. + * + * @param primitiveType to map. + * @return the name of the Rust primitive that most closely maps. + */ + static String rustTypeName(final PrimitiveType primitiveType) + { + return TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.get(primitiveType); + } + + static String generateRustLiteral(final PrimitiveType type, final String value) + { + Verify.notNull(type, "type"); + Verify.notNull(value, "value"); + final String typeName = rustTypeName(type); + if (typeName == null) + { + throw new IllegalArgumentException("Unknown Rust type name found for primitive " + type.primitiveName()); + } + + switch (type) + { + case CHAR: + case INT8: + case INT16: + case INT32: + case INT64: + return value + '_' + typeName; + case UINT8: + case UINT16: + case UINT32: + case UINT64: + return "0x" + Long.toHexString(parseLong(value)) + '_' + typeName; + case FLOAT: + case DOUBLE: + return value.endsWith("NaN") ? typeName + "::NAN" : value + '_' + typeName; + + default: + throw new IllegalArgumentException("Unsupported literal generation for type: " + type.primitiveName()); + } + } + + static byte eightBitCharacter(final String asciiCharacter) + { + Verify.notNull(asciiCharacter, "asciiCharacter"); + final byte[] bytes = asciiCharacter.getBytes(StandardCharsets.US_ASCII); + if (bytes.length != 1) + { + throw new IllegalArgumentException( + format("String value %s did not fit into a single 8-bit character", asciiCharacter)); + } + + return bytes[0]; + } + + /** + * Format a struct name for the generated code. + * + * @param structName to be formatted. + * @return the formatted struct name. + */ + static String formatStructName(final String structName) + { + return Generators.toUpperFirstChar(structName); + } + + static String codecName(final String structName, final CodecType codecType) + { + return formatStructName(structName + codecType.name()); + } + + static String encoderName(final String structName) + { + return codecName(structName, Encoder); + } + + static String decoderName(final String structName) + { + return codecName(structName, Decoder); + } + + static String formatFunctionName(final String value) + { + if (value.isEmpty()) + { + return value; + } + return sanitizeMethodOrProperty(toLowerSnakeCase(value)); + } + + static String cleanUpperAcronyms(final String value) + { + final int length = value.length(); + for (int i = 0; i < length; i++) + { + final char c = value.charAt(i); + if (!isUpperAlpha(c) && !isNumeric(c)) + { + if (c != '_' && i > 2) + { + final int index = i - 1; + return value.substring(0, index).toLowerCase() + value.substring(index); + } + return value; + } + } + + return value; + } + + /** + * Converts to 'snake_case' but will also handle when there are multiple + * upper case characters in a row 'UPPERCase' => 'upper_case' + * + * @param value to be formatted + * @return the string formatted to 'lower_snake_case' + */ + static String toLowerSnakeCase(final String value) + { + if (value.isEmpty()) + { + return value; + } + + final String cleaned = cleanUpperAcronyms(value); + final String s = toLowerFirstChar(cleaned); + final int length = s.length(); + + final StringBuilder out = new StringBuilder(length + 4); + char lastChar = '\0'; + + for (int i = 0, j = 0; j < length; j++) + { + final char c = s.charAt(j); + final boolean upper = isUpperAlpha(lastChar); + + if (c == '_') + { + out.append(c); + i = j + 1; + } + else if (isUpperAlpha(c)) + { + if (!upper && j - i > 1 && lastChar != '_') + { + out.append('_'); + out.append(toLowerSnakeCase(s.substring(j))); + return out.toString(); + } + out.append(Character.toLowerCase(c)); + } + else + { + if (upper && j - i > 1 && lastChar != '_') + { + out.append('_'); + out.append(toLowerSnakeCase(s.substring(j))); + return out.toString(); + } + out.append(c); + } + + lastChar = c; + } + + return out.toString(); + } + + private static boolean isUpperAlpha(final char c) + { + return 'A' <= c && c <= 'Z'; + } + + private static boolean isNumeric(final char c) + { + return '0' <= c && c <= '9'; + } + + private static String sanitizeMethodOrProperty(final String name) + { + if (shadowsKeyword(name)) + { + return name + "_"; + } + else + { + return name; + } + } + + private static boolean shadowsKeyword(final String name) + { + return ReservedKeyword.anyMatch(name); + } + + static Appendable indent(final Appendable appendable) throws IOException + { + return indent(appendable, 1); + } + + static Appendable indent(final Appendable appendable, final int level) throws IOException + { + Appendable out = appendable; + for (int i = 0; i < level; i++) + { + out = out.append(INDENT); + } + + return out; + } + + static Appendable indent(final Appendable appendable, final int level, final String f, final Object... args) + throws IOException + { + return indent(appendable, level).append(format(f, args)); + } + + private enum ReservedKeyword + { + Abstract, AlignOf, As, Async, Become, Box, Break, Const, Continue, + Crate, Do, Else, Enum, Extern, False, Final, Fn, For, If, Impl, In, + Let, Loop, Macro, Match, Mod, Move, Mut, OffsetOf, Override, Priv, + Proc, Pub, Pure, Ref, Return, Self, Sizeof, Static, Struct, Super, + Trait, True, Type, Typeof, Unsafe, Unsized, Use, Virtual, Where, + While, Yield; + + private static final Set LOWER_CASE_NAMES = new HashSet<>(); + + static + { + Arrays.stream(ReservedKeyword.values()) + .map(java.lang.Enum::name) + .map(String::toLowerCase) + .forEach(LOWER_CASE_NAMES::add); + } + + private static boolean anyMatch(final String v) + { + return LOWER_CASE_NAMES.contains(v.toLowerCase()); + } + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java new file mode 100644 index 0000000000..d291c86426 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -0,0 +1,240 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.rust; + +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.ir.Token; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import static uk.co.real_logic.sbe.generation.rust.RustUtil.indent; +import static uk.co.real_logic.sbe.generation.rust.RustUtil.rustTypeName; + +class SubGroup implements RustGenerator.ParentDef +{ + private final StringBuilder sb = new StringBuilder(); + private final ArrayList subGroups = new ArrayList<>(); + private final String name; + private final int level; + private final Token groupToken; + + SubGroup(final String name, final int level, final Token groupToken) + { + this.name = name; + this.level = level; + this.groupToken = groupToken; + } + + @Override + public SubGroup addSubGroup(final String name, final int level, final Token groupToken) + { + final SubGroup subGroup = new SubGroup(name, level, groupToken); + subGroups.add(subGroup); + return subGroup; + } + + void generateEncoder( + final List tokens, + final List fields, + final List groups, + final List varData, + final int index) throws IOException + { + final Token blockLengthToken = Generators.findFirst("blockLength", tokens, index); + final PrimitiveType blockLengthPrimitiveType = blockLengthToken.encoding().primitiveType(); + + final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); + final PrimitiveType numInGroupPrimitiveType = numInGroupToken.encoding().primitiveType(); + + // define struct... + indent(sb, level - 1, "#[derive(Debug, Default)]\n"); + indent(sb, level - 1, "pub struct %s

    {\n", name); + indent(sb, level, "parent: Option

    ,\n"); + indent(sb, level, "count: %s,\n", rustTypeName(numInGroupPrimitiveType)); + indent(sb, level, "index: usize,\n"); + indent(sb, level, "offset: usize,\n"); + indent(sb, level, "initial_limit: usize,\n"); + indent(sb, level - 1, "}\n\n"); + + RustGenerator.appendImplEncoderForComposite(sb, level - 1, name); + + // define impl... + indent(sb, level - 1, "impl<'a, P> %s

    where P: Encoder<'a> {\n", name); + + final int headerSize = blockLengthPrimitiveType.size() + numInGroupPrimitiveType.size(); + + // define wrap... + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn wrap(\n"); + indent(sb, level + 1, "mut self,\n"); + indent(sb, level + 1, "mut parent: P,\n"); + indent(sb, level + 1, "count: %s,\n", rustTypeName(numInGroupPrimitiveType)); + indent(sb, level, ") -> Self {\n"); + indent(sb, level + 1, "let initial_limit = parent.get_limit();\n"); + indent(sb, level + 1, "parent.set_limit(initial_limit + %d);\n", headerSize); + indent(sb, level + 1, "parent.get_buf_mut().put_%s_at(initial_limit, %d);\n", + rustTypeName(blockLengthPrimitiveType), this.groupToken.encodedLength()); + indent(sb, level + 1, "parent.get_buf_mut().put_%s_at(initial_limit + %d, count);\n", + rustTypeName(numInGroupPrimitiveType), blockLengthPrimitiveType.size()); + + indent(sb, level + 1, "self.parent = Some(parent);\n"); + indent(sb, level + 1, "self.count = count;\n"); + indent(sb, level + 1, "self.index = usize::MAX;\n"); + indent(sb, level + 1, "self.offset = usize::MAX;\n"); + indent(sb, level + 1, "self.initial_limit = initial_limit;\n"); + indent(sb, level + 1, "self\n"); + indent(sb, level, "}\n\n"); + + // block_length function + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn block_length() -> %s {\n", rustTypeName(blockLengthPrimitiveType)); + indent(sb, level + 1, "%d\n", this.groupToken.encodedLength()); + indent(sb, level, "}\n\n"); + + // parent function + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn parent(&mut self) -> SbeResult

    {\n"); + indent(sb, level + 1, "self.parent.take().ok_or(SbeErr::ParentNotSet)\n"); + indent(sb, level, "}\n\n"); + + // advance function... + indent(sb, level, "/// will return Some(current index) when successful otherwise None\n"); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn advance(&mut self) -> SbeResult> {\n"); + indent(sb, level + 1, "let index = self.index.wrapping_add(1);\n"); + indent(sb, level + 1, "if index >= self.count as usize {\n"); + indent(sb, level + 2, "return Ok(None);\n"); + indent(sb, level + 1, "}\n"); + + indent(sb, level + 1, "if let Some(parent) = self.parent.as_mut() {\n"); + indent(sb, level + 2, "self.offset = parent.get_limit();\n"); + indent(sb, level + 2, "parent.set_limit(self.offset + Self::block_length() as usize);\n"); + indent(sb, level + 2, "self.index = index;\n"); + indent(sb, level + 2, "Ok(Some(index))\n"); + indent(sb, level + 1, "} else {\n"); + indent(sb, level + 2, "Err(SbeErr::ParentNotSet)\n"); + indent(sb, level + 1, "}\n"); + indent(sb, level, "}\n\n"); + + RustGenerator.generateEncoderFields(sb, fields, level); + RustGenerator.generateEncoderGroups(sb, groups, level, this); + RustGenerator.generateEncoderVarData(sb, varData, level); + + indent(sb, level - 1, "}\n\n"); // close impl + } + + void generateDecoder( + final List tokens, + final List fields, + final List groups, + final List varData, + final int index) throws IOException + { + final Token blockLengthToken = Generators.findFirst("blockLength", tokens, index); + final PrimitiveType blockLengthPrimitiveType = blockLengthToken.encoding().primitiveType(); + + final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); + final PrimitiveType numInGroupPrimitiveType = numInGroupToken.encoding().primitiveType(); + + // define struct... + indent(sb, level - 1, "#[derive(Debug, Default)]\n"); + indent(sb, level - 1, "pub struct %s

    {\n", name); + indent(sb, level, "parent: Option

    ,\n"); + indent(sb, level, "block_length: usize,\n"); + indent(sb, level, "acting_version: usize,\n"); + indent(sb, level, "count: %s,\n", rustTypeName(numInGroupPrimitiveType)); + indent(sb, level, "index: usize,\n"); + indent(sb, level, "offset: usize,\n"); + indent(sb, level - 1, "}\n\n"); + + RustGenerator.appendImplDecoderForComposite(sb, level - 1, name); + + // define impl... + indent(sb, level - 1, "impl<'a, P> %s

    where P: Decoder<'a> + Default {\n", name); + + // define wrap... + indent(sb, level, "pub fn wrap(\n"); + indent(sb, level + 1, "mut self,\n"); + indent(sb, level + 1, "mut parent: P,\n"); + indent(sb, level + 1, "acting_version: usize,\n"); + indent(sb, level, ") -> Self {\n"); + indent(sb, level + 1, "let initial_offset = parent.get_limit();\n"); + indent(sb, level + 1, "let block_length = parent.get_buf().get_%s_at(initial_offset) as usize;\n", + rustTypeName(blockLengthPrimitiveType)); + indent(sb, level + 1, "let count = parent.get_buf().get_%s_at(initial_offset + %d);\n", + rustTypeName(numInGroupPrimitiveType), blockLengthPrimitiveType.size()); + indent(sb, level + 1, "parent.set_limit(initial_offset + %d);\n", + blockLengthPrimitiveType.size() + numInGroupPrimitiveType.size()); + + indent(sb, level + 1, "self.parent = Some(parent);\n"); + indent(sb, level + 1, "self.block_length = block_length;\n"); + indent(sb, level + 1, "self.acting_version = acting_version;\n"); + indent(sb, level + 1, "self.count = count;\n"); + indent(sb, level + 1, "self.index = usize::MAX;\n"); + indent(sb, level + 1, "self.offset = 0;\n"); + indent(sb, level + 1, "self\n"); + indent(sb, level, "}\n\n"); + + // parent function + indent(sb, level, "/// group token - %s\n", groupToken); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn parent(&mut self) -> SbeResult

    {\n"); + indent(sb, level + 1, "self.parent.take().ok_or(SbeErr::ParentNotSet)\n"); + indent(sb, level, "}\n\n"); + + // count function + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn count(&self) -> %s {\n", rustTypeName(numInGroupPrimitiveType)); + indent(sb, level + 1, "self.count\n"); + indent(sb, level, "}\n\n"); + + // advance function... + indent(sb, level, "/// will return Some(current index) when successful otherwise None\n"); + indent(sb, level, "pub fn advance(&mut self) -> SbeResult> {\n"); + indent(sb, level + 1, "let index = self.index.wrapping_add(1);\n"); + indent(sb, level + 1, "if index >= self.count as usize {\n"); + indent(sb, level + 2, " return Ok(None);\n"); + indent(sb, level + 1, "}\n"); + indent(sb, level + 1, "if let Some(parent) = self.parent.as_mut() {\n"); + indent(sb, level + 2, "self.offset = parent.get_limit();\n"); + indent(sb, level + 2, "parent.set_limit(self.offset + self.block_length as usize);\n"); + indent(sb, level + 2, "self.index = index;\n"); + indent(sb, level + 2, "Ok(Some(index))\n"); + indent(sb, level + 1, "} else {\n"); + indent(sb, level + 2, "Err(SbeErr::ParentNotSet)\n"); + indent(sb, level + 1, "}\n"); + indent(sb, level, "}\n\n"); + + RustGenerator.generateDecoderFields(sb, fields, level); + RustGenerator.generateDecoderGroups(sb, groups, level, this); + RustGenerator.generateDecoderVarData(sb, varData, level, true); + + indent(sb, level - 1, "}\n\n"); // close impl + } + + void appendTo(final Appendable dest) throws IOException + { + dest.append(sb); + + for (final SubGroup subGroup : subGroups) + { + subGroup.appendTo(dest); + } + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java new file mode 100644 index 0000000000..052fc27bae --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Generation of codecs for the Rust programming language. + */ +package uk.co.real_logic.sbe.generation.rust; \ No newline at end of file diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java new file mode 100644 index 0000000000..78be04c409 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java @@ -0,0 +1,150 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.rust; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static uk.co.real_logic.sbe.PrimitiveType.CHAR; +import static uk.co.real_logic.sbe.PrimitiveType.DOUBLE; +import static uk.co.real_logic.sbe.PrimitiveType.FLOAT; +import static uk.co.real_logic.sbe.PrimitiveType.INT16; +import static uk.co.real_logic.sbe.PrimitiveType.INT32; +import static uk.co.real_logic.sbe.PrimitiveType.INT64; +import static uk.co.real_logic.sbe.PrimitiveType.INT8; +import static uk.co.real_logic.sbe.PrimitiveType.UINT16; +import static uk.co.real_logic.sbe.PrimitiveType.UINT32; +import static uk.co.real_logic.sbe.PrimitiveType.UINT64; +import static uk.co.real_logic.sbe.PrimitiveType.UINT8; +import static uk.co.real_logic.sbe.generation.rust.RustUtil.cleanUpperAcronyms; +import static uk.co.real_logic.sbe.generation.rust.RustUtil.formatFunctionName; +import static uk.co.real_logic.sbe.generation.rust.RustUtil.generateRustLiteral; + +public class RustUtilTest +{ + @Test + public void nullParamToEightBitCharacterThrowsNPE() + { + assertThrows(NullPointerException.class, () -> + RustUtil.eightBitCharacter(null)); + } + + @Test + public void emptyParamToEightBitCharacterThrowsIAE() + { + assertThrows(IllegalArgumentException.class, () -> + RustUtil.eightBitCharacter("")); + } + + @Test + public void tooManyCharactersParamToEightBitCharacterThrowsIAE() + { + assertThrows(IllegalArgumentException.class, () -> + RustUtil.eightBitCharacter("ABC")); + } + + @Test + public void happyPathEightBitCharacter() + { + final byte aByte = RustUtil.eightBitCharacter("a"); + assertEquals('a', (char)aByte); + assertEquals("97", Byte.toString(aByte)); + } + + @Test + public void generateRustLiteralsHappyPaths() + { + assertEquals("65_u8", generateRustLiteral(CHAR, "65")); + assertEquals("64.1_f64", generateRustLiteral(DOUBLE, "64.1")); + assertEquals("f64::NAN", generateRustLiteral(DOUBLE, "NaN")); + assertEquals("64.1_f32", generateRustLiteral(FLOAT, "64.1")); + assertEquals("f32::NAN", generateRustLiteral(FLOAT, "NaN")); + + assertEquals("65_i8", generateRustLiteral(INT8, "65")); + assertEquals("65_i16", generateRustLiteral(INT16, "65")); + assertEquals("65_i32", generateRustLiteral(INT32, "65")); + assertEquals("65_i64", generateRustLiteral(INT64, "65")); + + assertEquals("0x41_u8", generateRustLiteral(UINT8, "65")); + assertEquals("0x41_u16", generateRustLiteral(UINT16, "65")); + assertEquals("0x41_u32", generateRustLiteral(UINT32, "65")); + assertEquals("0x41_u64", generateRustLiteral(UINT64, "65")); + } + + @Test + public void generateRustLiteralsForUnsignedPrimitiveNulls() + { + assertEquals("0xff_u8", generateRustLiteral(UINT8, UINT8.nullValue().toString())); + assertEquals("0xffff_u16", generateRustLiteral(UINT16, UINT16.nullValue().toString())); + assertEquals("0xffffffff_u32", generateRustLiteral(UINT32, UINT32.nullValue().toString())); + assertEquals("0xffffffffffffffff_u64", generateRustLiteral(UINT64, UINT64.nullValue().toString())); + } + + @Test + public void generateRustLiteralNullPrimitiveTypeParam() + { + assertThrows(NullPointerException.class, () -> generateRustLiteral(null, "65")); + } + + @Test + public void generateRustLiteralNullValueParam() + { + assertThrows(NullPointerException.class, () -> generateRustLiteral(INT8, null)); + } + + @Test + public void testCleanUpperAcronyms() + { + assertEquals("ABee", cleanUpperAcronyms("ABee")); + assertEquals("mdEntryTypeBook", cleanUpperAcronyms("MDEntryTypeBook")); + assertEquals("MD_EntryTypeBook", cleanUpperAcronyms("MD_EntryTypeBook")); + assertEquals("price9Book", cleanUpperAcronyms("PRICE9Book")); + } + + @Test + public void functionNameCasing() + { + assertEquals("", formatFunctionName("")); + assertEquals("a", formatFunctionName("a")); + assertEquals("a", formatFunctionName("A")); + assertEquals("car", formatFunctionName("Car")); + assertEquals("car", formatFunctionName("car")); + assertEquals("decode_car", formatFunctionName("DecodeCar")); + assertEquals("decode_car", formatFunctionName("decodeCar")); + assertEquals("decode_car", formatFunctionName("decode_car")); + assertEquals("decode_car", formatFunctionName("Decode_car")); + assertEquals("decode_car", formatFunctionName("decode_Car")); + assertEquals("decode_car", formatFunctionName("Decode_Car")); + assertEquals("decode_car", formatFunctionName("DECODE_Car")); + assertEquals("decode_car", formatFunctionName("DECODE_car")); + assertEquals("decode_car", formatFunctionName("DECODECar")); + assertEquals("decode_car", formatFunctionName("DECODE_CAR")); + assertEquals("decode_ca_r", formatFunctionName("DECODE_caR")); + + // special cases + assertEquals("pricenull_9", formatFunctionName("PRICENULL9")); + assertEquals("price9_book", formatFunctionName("PRICE9Book")); + assertEquals("upper_case", formatFunctionName("UPPERCase")); + assertEquals("no_md_entries", formatFunctionName("NoMDEntries")); + assertEquals("md_entry_type_book", formatFunctionName("MD_EntryTYPEBook")); + assertEquals("cl_ord_id", formatFunctionName("ClOrdID")); + assertEquals("ab_c", formatFunctionName("aBc")); + assertEquals("ab_cd", formatFunctionName("aBcD")); + assertEquals("ab_cd", formatFunctionName("aB_cD")); + assertEquals("ab_cd", formatFunctionName("AbCd")); + } +} From 4a5a23ad19ea0241a2f85154697e9c4e207d684a Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Wed, 21 Jul 2021 17:24:26 -0500 Subject: [PATCH 0724/1594] removed rust-toolchain file --- rust/rust-toolchain | 1 - 1 file changed, 1 deletion(-) delete mode 100644 rust/rust-toolchain diff --git a/rust/rust-toolchain b/rust/rust-toolchain deleted file mode 100644 index bf867e0ae5..0000000000 --- a/rust/rust-toolchain +++ /dev/null @@ -1 +0,0 @@ -nightly From d1d5ec13367a8ec0228b9824da508827896da1c8 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Thu, 22 Jul 2021 15:51:08 -0500 Subject: [PATCH 0725/1594] no change --- .../main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 155ffe5536..a63ddd35de 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -283,5 +283,6 @@ static void generateWriteBuf(final Writer writer, final ByteOrder byteOrder) thr indent(writer, 1, "}\n"); indent(writer, 0, "}\n\n"); + } } From 6331eea2e38dd6a9d361d61dae4edde08c93a502 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Thu, 22 Jul 2021 18:22:53 -0500 Subject: [PATCH 0726/1594] Revert "no change" This reverts commit d1d5ec13367a8ec0228b9824da508827896da1c8. --- .../main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 1 - 1 file changed, 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index a63ddd35de..155ffe5536 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -283,6 +283,5 @@ static void generateWriteBuf(final Writer writer, final ByteOrder byteOrder) thr indent(writer, 1, "}\n"); indent(writer, 0, "}\n\n"); - } } From 537f89501b02edbcecca3f8d90dfb6e8b2abdfde Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Thu, 22 Jul 2021 18:28:01 -0500 Subject: [PATCH 0727/1594] updated build.gradle to fix CI errors on github --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 660ecbb846..d29bbb21d6 100644 --- a/build.gradle +++ b/build.gradle @@ -535,7 +535,7 @@ project(':sbe-benchmarks') { * Rust codec targets used for testing */ task generateRustExamples(type: JavaExec) { - main = 'uk.co.real_logic.sbe.SbeTool' + mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'generated/rust', @@ -550,7 +550,7 @@ task generateRustExamples(type: JavaExec) { } task generateCarExampleDataFile(type: JavaExec) { - main = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub' + mainClass = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub' classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath systemProperties('sbe.encoding.filename': 'rust/car_example_baseline_data.sbe') args = [] @@ -558,7 +558,7 @@ task generateCarExampleDataFile(type: JavaExec) { } task generateCarExampleExtensionDataFile(type: JavaExec) { - main = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension' + mainClass = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension' classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath systemProperties('sbe.encoding.filename': 'rust/car_example_extension_data.sbe') args = [] From 5a15068bd007538c5ee6156c65d41621f0a077e3 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 27 Jul 2021 22:08:14 +0200 Subject: [PATCH 0728/1594] [Gradle] Remove enforcing of the ByteBuddy dependency. --- build.gradle | 3 --- 1 file changed, 3 deletions(-) diff --git a/build.gradle b/build.gradle index be022589a4..c6e22d07b0 100644 --- a/build.gradle +++ b/build.gradle @@ -41,7 +41,6 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' def mockitoVersion = '3.11.2' -def byteBuddyVersion = '1.11.3' def junitVersion = '5.7.2' def jmhVersion = '1.32' def agronaVersion = '1.11.0' @@ -138,8 +137,6 @@ allprojects { configurations.all { resolutionStrategy { failOnVersionConflict() - - force "net.bytebuddy:byte-buddy:${byteBuddyVersion}", "net.bytebuddy:byte-buddy-agent:${byteBuddyVersion}" } } From 08b1b21ff163245b5443f480cf45d7044d3ebcb0 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 28 Jul 2021 12:08:50 +0100 Subject: [PATCH 0729/1594] Grammar. --- .../java/uk/co/real_logic/sbe/CarBenchmark.java | 2 +- .../uk/co/real_logic/sbe/examples/OtfExample.java | 4 ++-- .../java/uk/co/real_logic/sbe/ValidationUtil.java | 14 +++++++------- .../co/real_logic/sbe/generation/Generators.java | 4 ++-- .../sbe/generation/TargetCodeGenerator.java | 2 +- .../sbe/generation/TargetCodeGeneratorLoader.java | 4 ++-- .../co/real_logic/sbe/generation/c/CGenerator.java | 2 +- .../sbe/generation/cpp/CppGenerator.java | 2 +- .../sbe/generation/csharp/CSharpUtil.java | 4 ++-- .../sbe/generation/golang/GolangGenerator.java | 5 ++--- .../sbe/generation/java/JavaGenerator.java | 4 ++-- .../java/uk/co/real_logic/sbe/ir/Encoding.java | 6 +++--- .../uk/co/real_logic/sbe/ir/GenerationUtil.java | 4 ++-- .../main/java/uk/co/real_logic/sbe/ir/Token.java | 4 ++-- .../real_logic/sbe/ir/generated/MetaAttribute.java | 2 +- .../real_logic/sbe/otf/AbstractTokenListener.java | 2 +- .../uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java | 2 +- .../uk/co/real_logic/sbe/otf/TokenListener.java | 4 ++-- .../main/java/uk/co/real_logic/sbe/otf/Types.java | 8 ++++---- .../uk/co/real_logic/sbe/xml/CompositeType.java | 6 +++--- .../java/uk/co/real_logic/sbe/xml/EnumType.java | 2 +- .../uk/co/real_logic/sbe/xml/ErrorHandler.java | 4 ++-- .../uk/co/real_logic/sbe/xml/MessageSchema.java | 2 +- .../java/uk/co/real_logic/sbe/xml/SetType.java | 2 +- 24 files changed, 47 insertions(+), 48 deletions(-) diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java index 43bfc15a5f..46a579427d 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java @@ -210,7 +210,7 @@ private static void decode( } /* - * Benchmarks to allow execution outside of JMH. + * Benchmarks to allow execution outside JMH. */ public static void main(final String[] args) diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java index 564297abb8..2b838b3806 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java @@ -63,7 +63,7 @@ public static void main(final String[] args) throws Exception final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); encodeTestMessage(encodedMsgBuffer); - // Now lets decode the schema IR so we have IR objects. + // Now let's decode the schema IR, so we have IR objects. encodedSchemaBuffer.flip(); final Ir ir = decodeIr(encodedSchemaBuffer); @@ -81,7 +81,7 @@ public static void main(final String[] args) throws Exception bufferOffset += headerDecoder.encodedLength(); - // Given the header information we can select the appropriate message template to do the decode. + // Given the header information we can select the appropriate message template to do the decode operation. // The OTF Java classes are thread safe so the same instances can be reused across multiple threads. final List msgTokens = ir.getMessage(templateId); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index 34d04f252c..ad8b8ffcc4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -80,7 +80,7 @@ public static boolean isCKeyword(final String token) * Is the value a possible C language keyword? * * @param value to be checked. - * @return true if the value a possible C language keyword. + * @return true if the value is a possible C language keyword. */ private static boolean possibleCKeyword(final String value) { @@ -178,7 +178,7 @@ public static boolean isCppKeyword(final String token) * Is the value a possible C++ language keyword? * * @param value to be checked. - * @return true if the value a possible C++ language keyword. + * @return true if the value is a possible C++ language keyword. */ private static boolean possibleCppKeyword(final String value) { @@ -319,7 +319,7 @@ private static boolean isJavaIdentifier(final String token) * identifier = letter { letter | unicode_digit } * letter = unicode_letter | "_" . *

    - * unicode_letter and unicode_digit are defined in section 4.5 of the the unicode + * unicode_letter and unicode_digit are defined in section 4.5 of the unicode * standard at http://www.unicode.org/versions/Unicode8.0.0/ and * the Java Character and Digit functions are unicode friendly * @@ -358,7 +358,7 @@ public static boolean isGolangKeyword(final String token) * Is the value a possible Go language keyword? * * @param value to be checked. - * @return true if the value a possible Go language keyword. + * @return true if the value is a possible Go language keyword. */ private static boolean possibleGolangKeyword(final String value) { @@ -418,11 +418,11 @@ private static boolean isSbeGolangIdentifierPart(final char c) /** * "Check" value for validity of usage as a csharp identifier. * https://msdn.microsoft.com/en-us/library/aa664670(v=vs.71).aspx - * ( Which basically boils down to + * Which basically boils down to *

    * first subsequent* * first is { @ | letter | underscore } - * subsequent is { first | digit | connecing | combining | formatting }* + * subsequent is { first | digit | connecting | combining | formatting }* *

    * letter is Lu, Ll, Lt, Lm, Lo, or Nl (possibly escaped) * digit is Nd (possibly escaped) @@ -468,7 +468,7 @@ public static boolean isCSharpKeyword(final String token) * Is the value a possible C# language keyword? * * @param value to be checked. - * @return true if the value a possible C# language keyword. + * @return true if the value is a possible C# language keyword. */ public static boolean possibleCSharpKeyword(final String value) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java index 3c2e2216b7..e5a5912efe 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java @@ -54,7 +54,7 @@ public static void forEachField(final List tokens, final BiConsumer> imports; + private final Stack> imports = new Stack<>(); /** * Create a new Go language {@link CodeGenerator}. @@ -65,7 +65,6 @@ public GolangGenerator(final Ir ir, final OutputManager outputManager) this.ir = ir; this.outputManager = outputManager; - this.imports = new Stack>(); this.imports.push(new TreeSet<>()); // ensure at least one } @@ -151,7 +150,7 @@ public void generate() throws IOException // Add the Marshalling from the big or little endian // template kept inside the jar. // - // The MessageHeader structure along with it's en/decoding is + // The MessageHeader structure along with its en/decoding is // also in the templated SbeMarshalling.go // // final Token token = ir.messages().iterator().next().get(0); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 4281368419..2b72abd40c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1488,7 +1488,7 @@ private CharSequence generateEnumValues(final List tokens) if (shouldDecodeUnknownEnumValues) { sb.append(INDENT).append("/**\n"); - sb.append(INDENT).append(" * To be used to represent a unknown value from a later version.\n"); + sb.append(INDENT).append(" * To be used to represent an unknown value from a later version.\n"); sb.append(INDENT).append(" */\n"); sb.append(INDENT).append("SBE_UNKNOWN").append('(').append(nullVal).append("),\n\n"); } @@ -1693,7 +1693,7 @@ private void generateMetaAttributeEnum() throws IOException "public enum MetaAttribute\n" + "{\n" + " /**\n" + - " * The epoch or start of time. Default is 'UNIX' which is midnight January 1, 1970 UTC\n" + + " * The epoch or start of time. Default is 'UNIX' which is midnight 1st January 1970 UTC.\n" + " */\n" + " EPOCH,\n\n" + " /**\n" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java index cf6cedf16b..733111dd31 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java @@ -259,9 +259,9 @@ public String timeUnit() } /** - * The semantic type of an encoding which can have relevance to the application layer. + * The semantic type of encoding value which can have relevance to the application layer. * - * @return semantic type of an encoding which can have relevance to the application layer. + * @return semantic type of encoding value which can have relevance to the application layer. */ public String semanticType() { @@ -379,7 +379,7 @@ public Builder nullValue(final PrimitiveValue nullValue) } /** - * Const value for the Encoding. + * Constant value to be used for the Encoding. * * @param constValue for the Encoding. * @return this for a fluent API. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java index d2f63750d9..f7e2eee19a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java @@ -133,10 +133,10 @@ public static int findEndSignal( } /** - * Find a list of sub group names. + * Find a list of sub-group names. * * @param tokens to search. - * @return list of names for the sub groups. + * @return list of names for the sub-groups. */ public static List findSubGroupNames(final List tokens) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index c03b4553a3..05c16f8468 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -276,7 +276,7 @@ else if (arrayLength > 1) * The offset for this token in the message. * * @return the offset of this Token. A value of 0 means the node has no relevant offset. A value of - * {@link Token#VARIABLE_LENGTH} means this nodes true offset is dependent on variable length + * {@link Token#VARIABLE_LENGTH} means this node's true offset is dependent on variable length * fields ahead of it in the encoding. */ public int offset() @@ -432,7 +432,7 @@ public Builder id(final int id) } /** - * Version attribute for the Token. + * Version attribute value for the Token. * * @param version for the Token. * @return this for a fluent API. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MetaAttribute.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MetaAttribute.java index af22473d99..7bac3df062 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MetaAttribute.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MetaAttribute.java @@ -7,7 +7,7 @@ public enum MetaAttribute { /** - * The epoch or start of time. Default is 'UNIX' which is midnight January 1, 1970 UTC + * The epoch or start of time. Default is 'UNIX' which is midnight 1st January 1970 UTC. */ EPOCH, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java index 8323b0d3f4..30ae2f87c3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java @@ -23,7 +23,7 @@ /** * Abstract {@link TokenListener} that can be extended when not all callback methods are required. *

    - * By extending this class their is a possibility for the optimizer to elide unused methods otherwise + * By extending this class there is a possibility for the optimizer to elide unused methods otherwise * requiring polymorphic dispatch. */ public abstract class AbstractTokenListener implements TokenListener diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java index 60f3f2a9ff..21e967497a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java @@ -25,7 +25,7 @@ /** * Used to decode a message header while doing on-the-fly decoding of a message stream. *

    - * Meta data is cached to improve the performance of decoding headers. + * Metadata is cached to improve the performance of decoding headers. *

    * This class is thread safe. */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java index 943f5bb40b..7b37cc80f3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java @@ -30,14 +30,14 @@ public interface TokenListener /** * Called on beginning the decoding of a message. * - * @param token representing the IR for message including meta data. + * @param token representing the IR for message including metadata. */ void onBeginMessage(Token token); /** * Called on end of decoding of a message. * - * @param token representing the IR for message including meta data. + * @param token representing the IR for message including metadata. */ void onEndMessage(Token token); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java index 677801179f..2d20b6ab56 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java @@ -23,7 +23,7 @@ import java.nio.ByteOrder; /** - * Utility functions for applying to types to help with on-the-fly (OTF) decoding. + * Utility functions for applying over encoded types to help with on-the-fly (OTF) decoding. */ public class Types { @@ -31,7 +31,7 @@ public class Types * Get an integer value from a buffer at a given index for a {@link PrimitiveType}. * * @param buffer from which to read. - * @param index at which he integer should be read. + * @param index at which the integer should be read. * @param type of the integer encoded in the buffer. * @param byteOrder of the integer in the buffer. * @return the value of the encoded integer. @@ -74,7 +74,7 @@ public static int getInt( * Get a long value from a buffer at a given index for a given {@link Encoding}. * * @param buffer from which to read. - * @param index at which he integer should be read. + * @param index at which the integer should be read. * @param encoding of the value. * @return the value of the encoded long. */ @@ -269,7 +269,7 @@ else if (value == Double.NEGATIVE_INFINITY) } /** - * Append an value as a Json String to a {@link StringBuilder}. + * Append a value as a Json String to a {@link StringBuilder}. * * @param sb to append the value to. * @param value to append. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index 5ec25a6c2d..3b6330ed19 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -152,7 +152,7 @@ public void makeDataFieldCompositeType() } /** - * Check the composite for being a well formed group encodedLength encoding. This means + * Check the composite for being a well-formed group encodedLength encoding. This means * that there are the fields "blockLength" and "numInGroup" present. * * @param node of the XML for this composite @@ -226,7 +226,7 @@ else if (numInGroupMinValue.longValue() < 0) } /** - * Check the composite for being a well formed variable length data encoding. This means + * Check the composite for being a well-formed variable length data encoding. This means * that there are the fields "length" and "varData" present. * * @param node of the XML for this composite @@ -295,7 +295,7 @@ else if (primitiveType == UINT32) } /** - * Check the composite for being a well formed message headerStructure encoding. This means + * Check the composite for being a well-formed message headerStructure encoding. This means * that there are the fields "blockLength", "templateId" and "version" present. * * @param node of the XML for this composite diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index 95da6fcf05..1135c39b0b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -81,7 +81,7 @@ public class EnumType extends Type break; default: - // might not have ran into this type yet, so look for it + // might not have run into this type yet, so look for it final Node encodingTypeNode = (Node)xPath.compile( String.format("%s[@name='%s']", XmlSchemaParser.TYPE_XPATH_EXPR, encodingTypeStr)) .evaluate(node.getOwnerDocument(), XPathConstants.NODE); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java index 29b06481c5..4dbc5ff4e4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java @@ -74,9 +74,9 @@ public void error(final String msg) } /** - * Record a message signifying an warning condition. + * Record a message signifying a warning condition. * - * @param msg signifying an warning. + * @param msg signifying a warning. */ public void warning(final String msg) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index c649ae6f20..285c2fd092 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -114,7 +114,7 @@ public int version() } /** - * The semantic version number of the schema. Typically use to reference a third party standard such as FIX. + * The semantic version number of the schema. Typically, used to reference a third party standard such as FIX. * * @return the semantic version number of the schema. */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index 148da894a2..6f9931c8b4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -76,7 +76,7 @@ public SetType(final Node node, final String givenName, final String referencedN break; default: - // might not have ran into this type yet, so look for it + // might not have run into this type yet, so look for it final String expression = TYPE_XPATH_EXPR + "[@name='" + encodingTypeStr + "']"; final Node encodingTypeNode = (Node)xPath .compile(expression) From 693769ce9fb1524b075a49be44cdb5b6e7efd4f5 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Fri, 30 Jul 2021 22:48:59 +1200 Subject: [PATCH 0730/1594] Add sbeRewind to message decoders. (#862) * [Java] Add sbeRewind to message decoders. * [Java] Checkstyle. --- .../sbe/generation/java/JavaGenerator.java | 5 + .../sbe/generation/java/RewindTest.java | 162 ++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 2b72abd40c..79cee171dc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2574,6 +2574,11 @@ private CharSequence generateDecoderFlyweightCode(final String className, final " offset + " + headerClassName + "Decoder.ENCODED_LENGTH,\n" + " headerDecoder.blockLength(),\n" + " headerDecoder.version());\n" + + " }\n\n" + + + " public void sbeRewind()\n" + + " {\n" + + " wrap(buffer, initialOffset, actingBlockLength, actingVersion);\n" + " }\n\n"; return generateFlyweightCode(DECODER, className, token, methods, readOnlyBuffer); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java new file mode 100644 index 0000000000..487dd441f1 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java @@ -0,0 +1,162 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import baseline.CarDecoder; +import baseline.EngineDecoder; +import baseline.MessageHeaderDecoder; +import baseline.OptionalExtrasDecoder; +import org.agrona.concurrent.UnsafeBuffer; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.EncodedCarTestBase; + +import java.nio.ByteBuffer; +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +public class RewindTest extends EncodedCarTestBase +{ + private static final int MSG_BUFFER_CAPACITY = 4 * 1024; + + @Test + void shouldRewindAfterReadingFullMessage() + { + final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); + encodeTestMessage(encodedMsgBuffer); + + final MessageHeaderDecoder header = new MessageHeaderDecoder(); + final CarDecoder carDecoder = new CarDecoder(); + carDecoder.wrapAndApplyHeader(new UnsafeBuffer(encodedMsgBuffer), 0, header); + + final ArrayList passOne = getValues(carDecoder); + carDecoder.sbeRewind(); + final ArrayList passTwo = getValues(carDecoder); + assertEquals(passOne, passTwo); + + carDecoder.sbeRewind(); + final ArrayList partialPassOne = getPartialValues(carDecoder); + carDecoder.sbeRewind(); + final ArrayList partialPassTwo = getPartialValues(carDecoder); + assertNotEquals(passOne, partialPassOne); + assertEquals(partialPassOne, partialPassTwo); + + carDecoder.sbeRewind(); + final ArrayList passThree = getValues(carDecoder); + assertEquals(passOne, passThree); + } + + private ArrayList getValues(final CarDecoder carDecoder) + { + final ArrayList values = new ArrayList<>(); + + values.add(carDecoder.serialNumber()); + values.add(carDecoder.modelYear()); + values.add(carDecoder.available()); + values.add(carDecoder.code()); + values.add(CarDecoder.someNumbersLength()); + for (int i = 0, n = CarDecoder.someNumbersLength(); i < n; i++) + { + values.add(carDecoder.someNumbers(i)); + } + values.add(carDecoder.vehicleCode()); + final OptionalExtrasDecoder extras = carDecoder.extras(); + values.add(extras.sunRoof()); + values.add(extras.sportsPack()); + values.add(extras.cruiseControl()); + final EngineDecoder engine = carDecoder.engine(); + values.add(engine.capacity()); + values.add(engine.numCylinders()); + values.add(engine.maxRpm()); + values.add(engine.manufacturerCode()); + values.add(engine.fuel()); + final CarDecoder.FuelFiguresDecoder fuelFigures = carDecoder.fuelFigures(); + while (fuelFigures.hasNext()) + { + fuelFigures.next(); + values.add(fuelFigures.speed()); + values.add(fuelFigures.mpg()); + } + final CarDecoder.PerformanceFiguresDecoder performanceFigures = carDecoder.performanceFigures(); + while (performanceFigures.hasNext()) + { + performanceFigures.next(); + values.add(performanceFigures.octaneRating()); + final CarDecoder.PerformanceFiguresDecoder.AccelerationDecoder acceleration = + performanceFigures.acceleration(); + while (acceleration.hasNext()) + { + acceleration.next(); + values.add(acceleration.mph()); + values.add(acceleration.seconds()); + } + } + values.add(carDecoder.manufacturer()); + values.add(carDecoder.model()); + return values; + } + + private ArrayList getPartialValues(final CarDecoder carDecoder) + { + final ArrayList values = new ArrayList<>(); + + values.add(carDecoder.serialNumber()); + values.add(carDecoder.modelYear()); + values.add(carDecoder.available()); + values.add(carDecoder.code()); + values.add(CarDecoder.someNumbersLength()); + for (int i = 0, n = CarDecoder.someNumbersLength(); i < n; i++) + { + values.add(carDecoder.someNumbers(i)); + } + values.add(carDecoder.vehicleCode()); + final OptionalExtrasDecoder extras = carDecoder.extras(); + values.add(extras.sunRoof()); + values.add(extras.sportsPack()); + values.add(extras.cruiseControl()); + final EngineDecoder engine = carDecoder.engine(); + values.add(engine.capacity()); + values.add(engine.numCylinders()); + values.add(engine.maxRpm()); + values.add(engine.manufacturerCode()); + values.add(engine.fuel()); + final CarDecoder.FuelFiguresDecoder fuelFigures = carDecoder.fuelFigures(); + while (fuelFigures.hasNext()) + { + fuelFigures.next(); + values.add(fuelFigures.speed()); + values.add(fuelFigures.mpg()); + } + final CarDecoder.PerformanceFiguresDecoder performanceFigures = carDecoder.performanceFigures(); + + // Stop decoding part way through the message. + if (performanceFigures.hasNext()) + { + performanceFigures.next(); + values.add(performanceFigures.octaneRating()); + final CarDecoder.PerformanceFiguresDecoder.AccelerationDecoder acceleration = + performanceFigures.acceleration(); + if (acceleration.hasNext()) + { + acceleration.next(); + values.add(acceleration.mph()); + } + } + + return values; + } +} From f99b6b552c23e048118fd3622495c905463a0969 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 2 Aug 2021 10:40:45 +0200 Subject: [PATCH 0731/1594] [Java] Regenerate IR codecs with `sbeRewind` added. --- .../uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java | 5 +++++ .../uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index f14c56220f..233fc7e20f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -104,6 +104,11 @@ public FrameCodecDecoder wrapAndApplyHeader( headerDecoder.version()); } + public void sbeRewind() + { + wrap(buffer, initialOffset, actingBlockLength, actingVersion); + } + public int encodedLength() { return limit - offset; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index a8d049642a..cf1e48205b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -104,6 +104,11 @@ public TokenCodecDecoder wrapAndApplyHeader( headerDecoder.version()); } + public void sbeRewind() + { + wrap(buffer, initialOffset, actingBlockLength, actingVersion); + } + public int encodedLength() { return limit - offset; From 2e8fbb038fe85c4d16dbb8aa023fc5039a860f3c Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Mon, 2 Aug 2021 16:39:28 -0500 Subject: [PATCH 0732/1594] [Rust] added null check for characterEncoding when generating encoder for VarData --- .../co/real_logic/sbe/generation/rust/RustGenerator.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 9bd5bb62bb..9304c7625a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -297,7 +297,12 @@ static void generateEncoderVarData( throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); } - final String characterEncoding = tokens.get(i + 3).encoding().characterEncoding(); + String characterEncoding = tokens.get(i + 3).encoding().characterEncoding(); + if (characterEncoding == null) + { + characterEncoding = ""; + } + final String propertyName = toLowerSnakeCase(varDataToken.name()); final Token lengthToken = tokens.get(i + 2); final Encoding lengthEncoding = lengthToken.encoding(); From 079999db64d9f4c4b7348b2872394c5602da81c7 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Tue, 3 Aug 2021 10:17:01 +1200 Subject: [PATCH 0733/1594] C/C++ sbe rewind (#863) * [C++] Partial test for rewind. * [C++] Implement SBE rewind for C++ codecs. * [C] Implement SBE rewind for C codecs. * [C] Use template params correctly in C code generator. --- CMakeLists.txt | 2 +- .../sbe/generation/c/CGenerator.java | 15 ++ .../sbe/generation/cpp/CppGenerator.java | 6 + sbe-tool/src/test/c/CodeGenTest.cpp | 212 ++++++++++++++++++ sbe-tool/src/test/cpp/CodeGenTest.cpp | 147 ++++++++++++ 5 files changed, 381 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a6df0e561..e52939e27a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,7 +153,7 @@ file(GLOB_RECURSE SBE_SOURCES ) add_custom_command(OUTPUT ${SBE_JAR} - COMMAND ./gradlew assemble -x javadoc + COMMAND ./gradlew assemble -x javadoc --console=plain DEPENDS ${SBE_SOURCES} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating SBE jar" diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 61940f9bdc..34779499e2 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1868,6 +1868,7 @@ private CharSequence generateMessageFlyweightStruct(final String structName) " uint64_t buffer_length;\n" + " uint64_t offset;\n" + " uint64_t position;\n" + + " uint64_t acting_block_length;\n" + " uint64_t acting_version;\n" + "};\n", structName); @@ -1920,6 +1921,7 @@ private CharSequence generateMessageFlyweightFunctions( " codec->buffer = buffer;\n" + " codec->offset = offset;\n" + " codec->buffer_length = buffer_length;\n" + + " codec->acting_block_length = acting_block_length;\n" + " codec->acting_version = acting_version;\n" + " if (!%10$s_set_sbe_position(codec, offset + acting_block_length))\n" + " {\n" + @@ -1935,6 +1937,7 @@ private CharSequence generateMessageFlyweightFunctions( " codec->buffer = other->buffer;\n" + " codec->offset = other->offset;\n" + " codec->buffer_length = other->buffer_length;\n" + + " codec->acting_block_length = other->acting_block_length;\n" + " codec->acting_version = other->acting_version;\n" + " codec->position = other->position;\n\n" + " return codec;\n" + @@ -2028,6 +2031,18 @@ private CharSequence generateMessageFlyweightFunctions( " acting_version);\n" + "}\n\n" + + "SBE_ONE_DEF struct %10$s *%10$s_sbe_rewind(\n" + + " struct %10$s *const codec)\n" + + "{\n" + + " return %10$s_wrap_for_decode(\n" + + " codec,\n" + + " codec->buffer,\n" + + " codec->offset,\n" + + " codec->acting_block_length,\n" + + " codec->acting_version,\n" + + " codec->buffer_length);\n" + + "}\n\n" + + "SBE_ONE_DEF uint64_t %10$s_encoded_length(\n" + " const struct %10$s *const codec)\n" + "{\n" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 53932ad2a6..219beb8377 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2050,6 +2050,12 @@ private CharSequence generateMessageFlyweightCode(final String className, final " return *this = %10$s(buffer, offset, bufferLength, actingBlockLength, actingVersion);\n" + " }\n\n" + + " %10$s &sbeRewind()\n" + + " {\n" + + " return wrapForDecode(" + + "m_buffer, m_offset, m_actingBlockLength, m_actingVersion, m_bufferLength);\n" + + " }\n\n" + + " SBE_NODISCARD std::uint64_t sbePosition() const SBE_NOEXCEPT\n" + " {\n" + " return m_position;\n" + diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index f9198e35ae..8b86a10eb5 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -220,6 +220,178 @@ class CodeGenTest : public testing::Test return CGT(car_encoded_length)(&car); } + static std::string walkCar(CGT(car)& car) + { + std::stringstream output; + + output << + CGT(car_serialNumber)(&car) << ';' << + CGT(car_modelYear) << ';' << + CGT(car_available) << ';' << + CGT(car_code) << ';'; + + for (std::uint64_t i = 0; i < CGT(car_someNumbers_length()); i++) + { + output << (int)CGT(car_someNumbers_buffer(&car))[i] << ';'; + } + + output << std::string(CGT(car_vehicleCode_buffer(&car)), CGT(car_vehicleCode_length())) << ';'; + + CGT(optionalExtras) extras = {}; + if (!CGT(car_extras)(&car, &extras)) + { + output << + CGT(optionalExtras_sunRoof)(&extras) << ';' << + CGT(optionalExtras_sportsPack)(&extras) << ';' << + CGT(optionalExtras_cruiseControl)(&extras) << ';'; + } + + char code_buf[4]; + CGT(engine) engine = {}; + if (CGT(car_engine)(&car, &engine)) + { + output << + CGT(engine_capacity(&engine)) << ';' << + (int)CGT(engine_numCylinders(&engine)) << ';' << + CGT(engine_maxRpm()) << ';' << + CGT(engine_get_manufacturerCode(&engine, code_buf, 3)) << ';' << + std::string(CGT(engine_fuel()), CGT(engine_fuel_length())) << ';'; + } + + CGT(car_fuelFigures) fuelFigures = {}; + if (CGT(car_get_fuelFigures)(&car, &fuelFigures)) + { + while (CGT(car_fuelFigures_has_next)(&fuelFigures)) + { + CGT(car_fuelFigures_next)(&fuelFigures); + output << + CGT(car_fuelFigures_speed(&fuelFigures)) << ';' << + CGT(car_fuelFigures_mpg(&fuelFigures)) << ';' << + std::string( + CGT(car_fuelFigures_usageDescription(&fuelFigures)), + CGT(car_fuelFigures_usageDescription_length(&fuelFigures))) << ';'; + } + } + + CGT(car_performanceFigures) perfFigures = {}; + if (CGT(car_get_performanceFigures(&car, &perfFigures))) + { + output << CGT(car_performanceFigures_count)(&perfFigures) << ';'; + + while (CGT(car_performanceFigures_has_next)(&perfFigures)) + { + CGT(car_performanceFigures_next(&perfFigures)); + output << CGT(car_performanceFigures_octaneRating(&perfFigures)) << ';'; + + CGT(car_performanceFigures_acceleration) acceleration = {}; + if (CGT(car_performanceFigures_get_acceleration(&perfFigures, &acceleration))) + { + while (CGT(car_performanceFigures_acceleration_has_next)(&acceleration)) + { + CGT(car_performanceFigures_acceleration_next(&acceleration)); + output << + CGT(car_performanceFigures_acceleration_mph(&acceleration)) << ';' << + CGT(car_performanceFigures_acceleration_seconds(&acceleration)) << ';'; + } + } + } + } + + CGT(car_string_view) manufacturer = CGT(car_get_manufacturer_as_string_view(&car)); + if (nullptr != manufacturer.data) + { + output << std::string(manufacturer.data, manufacturer.length) << ';'; + } + CGT(car_string_view) model = CGT(car_get_model_as_string_view(&car)); + if (nullptr != model.data) + { + output << std::string(model.data, model.length) << ';'; + } + + return output.str(); + } + + static std::string partialWalkCar(CGT(car)& car) + { + std::stringstream output; + + output << + CGT(car_serialNumber)(&car) << ';' << + CGT(car_modelYear) << ';' << + CGT(car_available) << ';' << + CGT(car_code) << ';'; + + for (std::uint64_t i = 0; i < CGT(car_someNumbers_length()); i++) + { + output << (int)CGT(car_someNumbers_buffer(&car))[i] << ';'; + } + + output << std::string(CGT(car_vehicleCode_buffer(&car)), CGT(car_vehicleCode_length())) << ';'; + + CGT(optionalExtras) extras = {}; + if (!CGT(car_extras)(&car, &extras)) + { + output << + CGT(optionalExtras_sunRoof)(&extras) << ';' << + CGT(optionalExtras_sportsPack)(&extras) << ';' << + CGT(optionalExtras_cruiseControl)(&extras) << ';'; + } + + char code_buf[4]; + CGT(engine) engine = {}; + if (CGT(car_engine)(&car, &engine)) + { + output << + CGT(engine_capacity(&engine)) << ';' << + (int)CGT(engine_numCylinders(&engine)) << ';' << + CGT(engine_maxRpm()) << ';' << + CGT(engine_get_manufacturerCode(&engine, code_buf, 3)) << ';' << + std::string(CGT(engine_fuel()), CGT(engine_fuel_length())) << ';'; + } + + CGT(car_fuelFigures) fuelFigures = {}; + if (CGT(car_get_fuelFigures)(&car, &fuelFigures)) + { + while (CGT(car_fuelFigures_has_next)(&fuelFigures)) + { + CGT(car_fuelFigures_next)(&fuelFigures); + output << + CGT(car_fuelFigures_speed(&fuelFigures)) << ';' << + CGT(car_fuelFigures_mpg(&fuelFigures)) << ';' << + std::string( + CGT(car_fuelFigures_usageDescription(&fuelFigures)), + CGT(car_fuelFigures_usageDescription_length(&fuelFigures))) << ';'; + } + } + + CGT(car_performanceFigures) perfFigures = {}; + if (CGT(car_get_performanceFigures(&car, &perfFigures))) + { + output << CGT(car_performanceFigures_count)(&perfFigures) << ';'; + + if (CGT(car_performanceFigures_has_next)(&perfFigures)) + { + CGT(car_performanceFigures_next(&perfFigures)); + output << CGT(car_performanceFigures_octaneRating(&perfFigures)) << ';'; + + CGT(car_performanceFigures_acceleration) acceleration = {}; + if (CGT(car_performanceFigures_get_acceleration(&perfFigures, &acceleration))) + { + if (CGT(car_performanceFigures_acceleration_has_next)(&acceleration)) + { + CGT(car_performanceFigures_acceleration_next(&acceleration)); + output << + CGT(car_performanceFigures_acceleration_mph(&acceleration)) << ';' << + CGT(car_performanceFigures_acceleration_seconds(&acceleration)) << ';'; + } + } + } + } + + return output.str(); + } + + std::uint64_t encodeHdr(char *buffer, std::uint64_t offset, std::uint64_t bufferLength) { if (!CGT(messageHeader_wrap)(&m_hdr, buffer, offset, 0, bufferLength)) @@ -1009,3 +1181,43 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) EXPECT_EQ(CGT(car_encoded_length)(&carDecoder), expectedCarEncodedLength); } + +TEST_F(CodeGenTest, shouldAllowForMultipleIterations2) +{ + char buffer[2048] = {}; + + std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer)); + std::uint64_t carEncodedLength = encodeCar( + buffer, CGT(messageHeader_encoded_length)(), sizeof(buffer) - CGT(messageHeader_encoded_length)()); + + if (!CGT(messageHeader_wrap)(&m_hdrDecoder, buffer, 0, 0, hdrSz)) + { + throw std::runtime_error(sbe_strerror(errno)); + } + + if (!CGT(car_wrap_for_decode)( + &m_carDecoder, + buffer, + CGT(messageHeader_encoded_length)(), + CGT(car_sbe_block_length)(), + CGT(car_sbe_schema_version)(), + hdrSz + carEncodedLength)) + { + throw std::runtime_error(sbe_strerror(errno)); + } + + std::string passOne = walkCar(m_carDecoder); + CGT(car_sbe_rewind(&m_carDecoder)); + std::string passTwo = walkCar(m_carDecoder); + EXPECT_EQ(passOne, passTwo); + + CGT(car_sbe_rewind(&m_carDecoder)); + std::string passThree = partialWalkCar(m_carDecoder); + CGT(car_sbe_rewind(&m_carDecoder)); + std::string passFour = partialWalkCar(m_carDecoder); + EXPECT_EQ(passThree, passFour); + + CGT(car_sbe_rewind(&m_carDecoder)); + std::string passFive = walkCar(m_carDecoder); + EXPECT_EQ(passOne, passFive); +} diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index e738e28363..dfea4cc0be 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -186,6 +186,129 @@ class CodeGenTest : public testing::Test displayStream.clear(); } + std::string walkCar(Car& carDecoder) + { + std::stringstream output; + + output << + carDecoder.serialNumber() << ';' << + carDecoder.modelYear() << ';' << + carDecoder.available() << ';' << + carDecoder.code() << ';'; + + for (std::uint64_t i = 0; i < Car::someNumbersLength(); i++) + { + output << carDecoder.someNumbers(i) << ';'; + } + + output << carDecoder.getVehicleCodeAsString() << ';'; + + OptionalExtras &extras = carDecoder.extras(); + output << + extras.sunRoof() << ';' << + extras.sportsPack() << ';' << + extras.cruiseControl() << ';'; + + Engine &engine = carDecoder.engine(); + output << + engine.capacity() << ';' << + static_cast(engine.numCylinders()) << ';' << + Engine::maxRpm() << ';' << + engine.getManufacturerCodeAsString() << ';' << + engine.getFuelAsString() << ';'; + + Car::FuelFigures &fuelFigures = carDecoder.fuelFigures(); + while (fuelFigures.hasNext()) + { + fuelFigures.next(); + output << + fuelFigures.speed() << ';' << + fuelFigures.mpg() << ';' << + fuelFigures.getUsageDescriptionAsString() << ';'; + } + + Car::PerformanceFigures &performanceFigures = carDecoder.performanceFigures(); + output << performanceFigures.count() << ';'; + while (performanceFigures.hasNext()) + { + performanceFigures.next(); + output << performanceFigures.octaneRating() << ';'; + Car::PerformanceFigures::Acceleration &acceleration = performanceFigures.acceleration(); + while (acceleration.hasNext()) + { + acceleration.next(); + output << + acceleration.mph() << ';' << + acceleration.seconds() << ';'; + } + } + + output << carDecoder.getManufacturerAsString() << ';'; + output << carDecoder.getModelAsString() << ';'; + + return output.str(); + } + + std::string partialWalkCar(Car& carDecoder) + { + std::stringstream output; + + output << + carDecoder.serialNumber() << ';' << + carDecoder.modelYear() << ';' << + carDecoder.available() << ';' << + carDecoder.code() << ';'; + + for (std::uint64_t i = 0; i < Car::someNumbersLength(); i++) + { + output << carDecoder.someNumbers(i) << ';'; + } + + output << carDecoder.getVehicleCodeAsString() << ';'; + + OptionalExtras &extras = carDecoder.extras(); + output << + extras.sunRoof() << ';' << + extras.sportsPack() << ';' << + extras.cruiseControl() << ';'; + + Engine &engine = carDecoder.engine(); + output << + engine.capacity() << ';' << + static_cast(engine.numCylinders()) << ';' << + Engine::maxRpm() << ';' << + engine.getManufacturerCodeAsString() << ';' << + engine.getFuelAsString() << ';'; + + Car::FuelFigures &fuelFigures = carDecoder.fuelFigures(); + while (fuelFigures.hasNext()) + { + fuelFigures.next(); + output << + fuelFigures.speed() << ';' << + fuelFigures.mpg() << ';' << + fuelFigures.getUsageDescriptionAsString() << ';'; + } + + Car::PerformanceFigures &performanceFigures = carDecoder.performanceFigures(); + output << performanceFigures.count() << ';'; + if (performanceFigures.hasNext()) + { + performanceFigures.next(); + output << performanceFigures.octaneRating() << ';'; + Car::PerformanceFigures::Acceleration &acceleration = performanceFigures.acceleration(); + if (acceleration.hasNext()) + { + acceleration.next(); + output << + acceleration.mph() << ';' << + acceleration.seconds() << ';'; + } + } + + return output.str(); + } + MessageHeader m_hdr = {}; MessageHeader m_hdrDecoder = {}; Car m_car = {}; @@ -935,3 +1058,27 @@ TEST_F(CodeGenTest, shouldPrintFullDecodedFlyweightRegardlessOfReadPosition) EXPECT_EQ(carDecoder.encodedLength(), expectedCarEncodedLength); } + +TEST_F(CodeGenTest, shouldAllowForMultipleIterations) +{ + char buffer[BUFFER_LEN] = {}; + + Car carEncoder(buffer, sizeof(buffer)); + uint64_t encodedLength = encodeCar(carEncoder); + Car carDecoder(buffer, encodedLength, Car::sbeBlockLength(), Car::sbeSchemaVersion()); + + std::string passOne = walkCar(carDecoder); + carDecoder.sbeRewind(); + std::string passTwo = walkCar(carDecoder); + EXPECT_EQ(passOne, passTwo); + + carDecoder.sbeRewind(); + std::string passThree = partialWalkCar(carDecoder); + carDecoder.sbeRewind(); + std::string passFour = partialWalkCar(carDecoder); + EXPECT_EQ(passThree, passFour); + + carDecoder.sbeRewind(); + std::string passFive = walkCar(carDecoder); + EXPECT_EQ(passOne, passFive); +} From 24249faa57387ee186510ec5e9c03ca1af38e79f Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Tue, 3 Aug 2021 10:58:23 +1200 Subject: [PATCH 0734/1594] [Java] Make sbeRewind use a fluent API to match C++ style. --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 79cee171dc..1bcd4798c0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2576,9 +2576,9 @@ private CharSequence generateDecoderFlyweightCode(final String className, final " headerDecoder.version());\n" + " }\n\n" + - " public void sbeRewind()\n" + + " public " + className + " sbeRewind()\n" + " {\n" + - " wrap(buffer, initialOffset, actingBlockLength, actingVersion);\n" + + " return wrap(buffer, initialOffset, actingBlockLength, actingVersion);\n" + " }\n\n"; return generateFlyweightCode(DECODER, className, token, methods, readOnlyBuffer); From 08d2f21e06294cd4ffd508d486d51f5d64796f1b Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 3 Aug 2021 09:30:06 +0200 Subject: [PATCH 0735/1594] [Java] Regenerate Java IR codecs to update `sbeRewind`. --- .../uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java | 4 ++-- .../uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 233fc7e20f..efb7c33192 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -104,9 +104,9 @@ public FrameCodecDecoder wrapAndApplyHeader( headerDecoder.version()); } - public void sbeRewind() + public FrameCodecDecoder sbeRewind() { - wrap(buffer, initialOffset, actingBlockLength, actingVersion); + return wrap(buffer, initialOffset, actingBlockLength, actingVersion); } public int encodedLength() diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index cf1e48205b..98a58e85d4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -104,9 +104,9 @@ public TokenCodecDecoder wrapAndApplyHeader( headerDecoder.version()); } - public void sbeRewind() + public TokenCodecDecoder sbeRewind() { - wrap(buffer, initialOffset, actingBlockLength, actingVersion); + return wrap(buffer, initialOffset, actingBlockLength, actingVersion); } public int encodedLength() From 3ec9f7fdf526ae04f320b5fb39d8393ed1c329c7 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Tue, 3 Aug 2021 07:55:14 -0500 Subject: [PATCH 0736/1594] [Rust] updated generator for composite encoder to create via `default()` --- rust/Cargo.toml | 2 ++ rust/benches/car_benchmark.rs | 3 +-- rust/benches/md_benchmark.rs | 11 ++++------- rust/tests/baseline_test.rs | 6 ++---- rust/tests/extension_test.rs | 6 ++---- .../real_logic/sbe/generation/rust/RustGenerator.java | 10 +++++----- .../co/real_logic/sbe/generation/rust/SubGroup.java | 2 +- 7 files changed, 17 insertions(+), 23 deletions(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index ed176caf0d..e9ca000c40 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -11,6 +11,8 @@ examples_extension = { path = "../generated/rust/extension" } examples_uk_co_real_logic_sbe_benchmarks = { path = "../generated/rust/uk_co_real_logic_sbe_benchmarks" } examples_uk_co_real_logic_sbe_benchmarks_fix = { path = "../generated/rust/uk_co_real_logic_sbe_benchmarks_fix" } +issue435 = { path = "../generated/rust/issue435" } + [dev-dependencies] criterion = "0.3" diff --git a/rust/benches/car_benchmark.rs b/rust/benches/car_benchmark.rs index f11269311f..c6425ad379 100644 --- a/rust/benches/car_benchmark.rs +++ b/rust/benches/car_benchmark.rs @@ -23,7 +23,6 @@ pub fn car_encode_benchmark(c: &mut Criterion) { fn encode(state: &mut State) -> SbeResult { let buffer = state.buffer.as_mut_slice(); let mut car = CarEncoder::default(); - let mut engine = EngineEncoder::default(); let mut fuel_figures = FuelFiguresEncoder::default(); let mut performance_figures = PerformanceFiguresEncoder::default(); let mut acceleration = AccelerationEncoder::default(); @@ -43,7 +42,7 @@ fn encode(state: &mut State) -> SbeResult { extras.set_sun_roof(true); car.extras(extras); - engine = car.engine_encoder(engine); + let mut engine = car.engine_encoder(); engine.capacity(4200); engine.num_cylinders(8); engine.manufacturer_code([97, 98, 99]); // abc diff --git a/rust/benches/md_benchmark.rs b/rust/benches/md_benchmark.rs index 2d1a23a892..3b59709a06 100644 --- a/rust/benches/md_benchmark.rs +++ b/rust/benches/md_benchmark.rs @@ -22,9 +22,6 @@ fn encode_md(state: &mut State) -> SbeResult { let mut market_data = MarketDataIncrementalRefreshTradesEncoder::default(); let mut md_inc_grp = MdIncGrpEncoder::default(); - let mut md_entry_px = Decimal64Encoder::default(); - let mut md_entry_size = IntQty32Encoder::default(); - market_data = market_data.wrap(WriteBuf::new(buffer), message_header::ENCODED_LENGTH); market_data = market_data.header(0).parent()?; @@ -38,10 +35,10 @@ fn encode_md(state: &mut State) -> SbeResult { md_inc_grp.advance()?; md_inc_grp.trade_id(1234); md_inc_grp.security_id(56789); - md_entry_px = md_inc_grp.md_entry_px_encoder(md_entry_px); + let mut md_entry_px = md_inc_grp.md_entry_px_encoder(); md_entry_px.mantissa(50); md_inc_grp = md_entry_px.parent()?; - md_entry_size = md_inc_grp.md_entry_size_encoder(md_entry_size); + let mut md_entry_size = md_inc_grp.md_entry_size_encoder(); md_entry_size.mantissa(10); md_inc_grp = md_entry_size.parent()?; md_inc_grp.number_of_orders(1); @@ -53,10 +50,10 @@ fn encode_md(state: &mut State) -> SbeResult { md_inc_grp.advance()?; md_inc_grp.trade_id(1234); md_inc_grp.security_id(56789); - md_entry_px = md_inc_grp.md_entry_px_encoder(md_entry_px); + let mut md_entry_px = md_inc_grp.md_entry_px_encoder(); md_entry_px.mantissa(50); md_inc_grp = md_entry_px.parent()?; - md_entry_size = md_inc_grp.md_entry_size_encoder(md_entry_size); + let mut md_entry_size = md_inc_grp.md_entry_size_encoder(); md_entry_size.mantissa(10); md_inc_grp = md_entry_size.parent()?; md_inc_grp.number_of_orders(1); diff --git a/rust/tests/baseline_test.rs b/rust/tests/baseline_test.rs index 2e578929d8..8156b71e53 100644 --- a/rust/tests/baseline_test.rs +++ b/rust/tests/baseline_test.rs @@ -160,8 +160,6 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { let mut buffer = vec![0u8; 256]; let mut car = CarEncoder::default(); - let mut engine = EngineEncoder::default(); - let mut booster = BoosterEncoder::default(); let mut fuel_figures = FuelFiguresEncoder::default(); let mut performance_figures = PerformanceFiguresEncoder::default(); let mut acceleration = AccelerationEncoder::default(); @@ -185,13 +183,13 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { extras.set_sun_roof(false); car.extras(extras); - engine = car.engine_encoder(engine); + let mut engine = car.engine_encoder(); engine.capacity(2000); engine.num_cylinders(4); engine.manufacturer_code([49, 50, 51]); // 123 engine.efficiency(35); engine.booster_enabled(BooleanType::T); - booster = engine.booster_encoder(booster); + let mut booster = engine.booster_encoder(); booster.boost_type(BoostType::NITROUS); booster.horse_power(200); diff --git a/rust/tests/extension_test.rs b/rust/tests/extension_test.rs index 317b79651a..56496d271c 100644 --- a/rust/tests/extension_test.rs +++ b/rust/tests/extension_test.rs @@ -161,8 +161,6 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { let mut buffer = vec![0u8; 256]; let mut car = CarEncoder::default(); - let mut engine = EngineEncoder::default(); - let mut booster = BoosterEncoder::default(); let mut fuel_figures = FuelFiguresEncoder::default(); let mut performance_figures = PerformanceFiguresEncoder::default(); let mut acceleration = AccelerationEncoder::default(); @@ -186,13 +184,13 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { extras.set_sun_roof(false); car.extras(extras); - engine = car.engine_encoder(engine); + let mut engine = car.engine_encoder(); engine.capacity(2000); engine.num_cylinders(4); engine.manufacturer_code([49, 50, 51]); // 123 engine.efficiency(35); engine.booster_enabled(BooleanType::T); - booster = engine.booster_encoder(booster); + let mut booster = engine.booster_encoder(); booster.boost_type(BoostType::NITROUS); booster.horse_power(200); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 9304c7625a..8969c71c7d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -484,13 +484,13 @@ private static void generateCompositeEncoder( final String encoderTypeName = encoderName(formatStructName(typeToken.name())); indent(sb, level, "/// COMPOSITE ENCODER\n"); indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn %s(self, %1$s: %2$s) -> %2$s {\n", + indent(sb, level, "pub fn %s(self) -> %2$s {\n", encoderName, encoderTypeName); // NB: must create variable 'offset' before moving 'self' indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); - indent(sb, level + 1, "%s.wrap(self, offset)\n", encoderName); + indent(sb, level + 1, "%s::default().wrap(self, offset)\n", encoderTypeName); indent(sb, level, "}\n\n"); } @@ -1248,7 +1248,7 @@ static void appendImplWriterForComposite( final String name) throws IOException { // impl Decoder... - indent(out, level, "impl<'a, P> Writer<'a> for %s

    where P: Writer<'a> {\n", name); + indent(out, level, "impl<'a, P> Writer<'a> for %s

    where P: Writer<'a> + Default {\n", name); indent(out, level + 1, "#[inline]\n"); indent(out, level + 1, "fn get_buf_mut(&mut self) -> &mut WriteBuf<'a> {\n"); indent(out, level + 2, "if let Some(parent) = self.parent.as_mut() {\n"); @@ -1268,7 +1268,7 @@ static void appendImplEncoderForComposite( appendImplWriterForComposite(out, level, name); // impl Encoder... - indent(out, level, "impl<'a, P> Encoder<'a> for %s

    where P: Encoder<'a> {\n", name); + indent(out, level, "impl<'a, P> Encoder<'a> for %s

    where P: Encoder<'a> + Default {\n", name); indent(out, level + 1, "#[inline]\n"); indent(out, level + 1, "fn get_limit(&self) -> usize {\n"); indent(out, level + 2, "self.parent.as_ref().expect(\"parent missing\").get_limit()\n"); @@ -1338,7 +1338,7 @@ private static void generateCompositeEncoder( appendImplWriterForComposite(out, 1, encoderName); // impl<'a> start - indent(out, 1, "impl<'a, P> %s

    where P: Writer<'a> {\n", encoderName); + indent(out, 1, "impl<'a, P> %s

    where P: Writer<'a> + Default {\n", encoderName); indent(out, 2, "pub fn wrap(mut self, parent: P, offset: usize) -> Self {\n"); indent(out, 3, "self.parent = Some(parent);\n"); indent(out, 3, "self.offset = offset;\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index d291c86426..8e10af00b1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -75,7 +75,7 @@ void generateEncoder( RustGenerator.appendImplEncoderForComposite(sb, level - 1, name); // define impl... - indent(sb, level - 1, "impl<'a, P> %s

    where P: Encoder<'a> {\n", name); + indent(sb, level - 1, "impl<'a, P> %s

    where P: Encoder<'a> + Default {\n", name); final int headerSize = blockLengthPrimitiveType.size() + numInGroupPrimitiveType.size(); From 35b121be7c39a5120d4c9a8292fe1ce477393395 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Tue, 3 Aug 2021 09:03:45 -0500 Subject: [PATCH 0737/1594] [Rust] created issue_435_test.rs --- rust/tests/issue_435_test.rs | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 rust/tests/issue_435_test.rs diff --git a/rust/tests/issue_435_test.rs b/rust/tests/issue_435_test.rs new file mode 100644 index 0000000000..a057211f18 --- /dev/null +++ b/rust/tests/issue_435_test.rs @@ -0,0 +1,37 @@ +use ::issue435::*; + +fn create_encoder(buffer: &mut Vec) -> Issue435Encoder { + let issue_435 = Issue435Encoder::default().wrap( + WriteBuf::new(buffer.as_mut_slice()), + message_header::ENCODED_LENGTH, + ); + let mut header = issue_435.header(0); + header.s(*SetRef::default().set_one(true)); + header.parent().unwrap() +} + +#[test] +fn issue_435_ref_test() -> SbeResult<()> { + assert_eq!(9, message_header::ENCODED_LENGTH); + assert_eq!(1, issue435::SBE_BLOCK_LENGTH); + assert_eq!(0, issue435::SBE_SCHEMA_VERSION); + + // encode... + let mut buffer = vec![0u8; 256]; + let encoder = create_encoder(&mut buffer); + encoder.example_encoder().e(EnumRef::Two); + + // decode... + let buf = ReadBuf::new(buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + assert_eq!(issue435::SBE_BLOCK_LENGTH, header.block_length()); + assert_eq!(issue435::SBE_SCHEMA_VERSION, header.version()); + assert_eq!(issue435::SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(issue435::SBE_SCHEMA_ID, header.schema_id()); + assert_eq!(*SetRef::default().set_one(true), header.s()); + + let decoder = Issue435Decoder::default().header(header); + assert_eq!(EnumRef::Two, decoder.example_decoder().e()); + + Ok(()) +} From a6b196393858946f64166b9fc7df5cfe322f6019 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Tue, 3 Aug 2021 14:00:01 -0500 Subject: [PATCH 0738/1594] [Rust] RustUtil.toLowerSnakeCase() will now separate numerics from alphas with a '_' (i.e. 'issue435' => 'issue_435') --- .../sbe/generation/rust/RustGenerator.java | 2 +- .../sbe/generation/rust/RustUtil.java | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 8969c71c7d..80c04ce910 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -101,7 +101,7 @@ public void generate() throws IOException // create Cargo.toml try (Writer writer = outputManager.createCargoToml()) { - final String packageName = ir.packageName().replaceAll("\\.", "_"); + final String packageName = toLowerSnakeCase(ir.packageName()).replaceAll("[.-]", "_"); final String namespace; if (ir.namespaceName() == null || ir.namespaceName().equalsIgnoreCase(packageName)) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index c9c077a21e..33c0edab54 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -188,8 +188,10 @@ static String toLowerSnakeCase(final String value) for (int i = 0, j = 0; j < length; j++) { + final boolean wasUpper = isUpperAlpha(lastChar); + final boolean wasNumeric = isNumeric(lastChar); + final boolean wasUnderscore = lastChar == '_'; final char c = s.charAt(j); - final boolean upper = isUpperAlpha(lastChar); if (c == '_') { @@ -198,7 +200,7 @@ static String toLowerSnakeCase(final String value) } else if (isUpperAlpha(c)) { - if (!upper && j - i > 1 && lastChar != '_') + if (wasNumeric || (!wasUpper && j - i > 1 && !wasUnderscore)) { out.append('_'); out.append(toLowerSnakeCase(s.substring(j))); @@ -206,9 +208,19 @@ else if (isUpperAlpha(c)) } out.append(Character.toLowerCase(c)); } + else if (isNumeric(c)) + { + if (!wasNumeric && j - i > 1 && !wasUnderscore) + { + out.append('_'); + out.append(toLowerSnakeCase(s.substring(j))); + return out.toString(); + } + out.append(c); + } else { - if (upper && j - i > 1 && lastChar != '_') + if ((wasUpper || wasNumeric) && j - i > 1 && !wasUnderscore) { out.append('_'); out.append(toLowerSnakeCase(s.substring(j))); From 33a43d5cc0e2cf544370ae7438c1b6dd15decf7b Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Tue, 3 Aug 2021 14:14:12 -0500 Subject: [PATCH 0739/1594] [Rust] updated RustUtilTest --- .../uk/co/real_logic/sbe/generation/rust/RustUtilTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java index 78be04c409..a1f36f4d98 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java @@ -137,7 +137,8 @@ public void functionNameCasing() // special cases assertEquals("pricenull_9", formatFunctionName("PRICENULL9")); - assertEquals("price9_book", formatFunctionName("PRICE9Book")); + assertEquals("price_9_book", formatFunctionName("PRICE9Book")); + assertEquals("issue_435", formatFunctionName("issue435")); assertEquals("upper_case", formatFunctionName("UPPERCase")); assertEquals("no_md_entries", formatFunctionName("NoMDEntries")); assertEquals("md_entry_type_book", formatFunctionName("MD_EntryTYPEBook")); From 5102355e69a68fdbece73d83f80494ae73ef746a Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Tue, 3 Aug 2021 14:15:02 -0500 Subject: [PATCH 0740/1594] [Rust] added tests for big-endian and issue435 --- build.gradle | 28 +++- rust/Cargo.toml | 3 +- rust/tests/big_endian_test.rs | 255 ++++++++++++++++++++++++++++++++++ rust/tests/issue_435_test.rs | 14 +- 4 files changed, 285 insertions(+), 15 deletions(-) create mode 100644 rust/tests/big_endian_test.rs diff --git a/build.gradle b/build.gradle index d29bbb21d6..22df73d07d 100644 --- a/build.gradle +++ b/build.gradle @@ -549,6 +549,19 @@ task generateRustExamples(type: JavaExec) { ] } +task generateRustTestCodecs(type: JavaExec) { + mainClass = 'uk.co.real_logic.sbe.SbeTool' + classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'generated/rust', + 'sbe.xinclude.aware': 'true', + 'sbe.target.language': 'Rust', + 'sbe.validation.xsd': validationXsdPath) + args = ['sbe-tool/src/test/resources/issue435.xml', + 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', + ] +} + task generateCarExampleDataFile(type: JavaExec) { mainClass = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub' classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath @@ -565,18 +578,19 @@ task generateCarExampleExtensionDataFile(type: JavaExec) { standardOutput = new ByteArrayOutputStream() } -task runRustCarExample(type: Exec) { +task generateRustCodecs { + description = 'Generate rust test codecs' + dependsOn 'generateRustExamples', 'generateRustTestCodecs', + 'generateCarExampleDataFile', 'generateCarExampleExtensionDataFile' +} + +task runRustExamples(type: Exec) { workingDir = './rust' executable = 'cargo' args = ['run'] standardOutput = new ByteArrayOutputStream() errorOutput = new ByteArrayOutputStream() - dependsOn 'generateRustExamples', 'generateCarExampleDataFile', 'generateCarExampleExtensionDataFile' -} - -task generateRustCodecs { - description = 'Generate rust test codecs' - dependsOn 'generateRustExamples', 'generateCarExampleDataFile', 'generateCarExampleExtensionDataFile' + dependsOn 'generateRustCodecs' } /* diff --git a/rust/Cargo.toml b/rust/Cargo.toml index e9ca000c40..8aef7aa48c 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -11,7 +11,8 @@ examples_extension = { path = "../generated/rust/extension" } examples_uk_co_real_logic_sbe_benchmarks = { path = "../generated/rust/uk_co_real_logic_sbe_benchmarks" } examples_uk_co_real_logic_sbe_benchmarks_fix = { path = "../generated/rust/uk_co_real_logic_sbe_benchmarks_fix" } -issue435 = { path = "../generated/rust/issue435" } +issue_435 = { path = "../generated/rust/issue435" } +baseline_bigendian = { path = "../generated/rust/baseline-bigendian" } [dev-dependencies] criterion = "0.3" diff --git a/rust/tests/big_endian_test.rs b/rust/tests/big_endian_test.rs new file mode 100644 index 0000000000..8670d14e53 --- /dev/null +++ b/rust/tests/big_endian_test.rs @@ -0,0 +1,255 @@ +use baseline_bigendian::*; + +#[test] +fn big_endian_baseline_example() -> SbeResult<()> { + // The byte array is from the java example made by running + // with -Dsbe.encoding.filename and then decoded using od -tu1 + let big_endian_bytes: Vec = vec![ + 0, 49, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 210, 7, 221, 1, 65, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 97, 98, 99, 100, 101, 102, 6, 7, 208, 4, 49, 50, 51, + 35, 1, 78, 200, 0, 6, 0, 3, 0, 30, 66, 15, 153, 154, 0, 0, 0, 11, 85, 114, 98, 97, 110, 32, + 67, 121, 99, 108, 101, 0, 55, 66, 68, 0, 0, 0, 0, 0, 14, 67, 111, 109, 98, 105, 110, 101, + 100, 32, 67, 121, 99, 108, 101, 0, 75, 66, 32, 0, 0, 0, 0, 0, 13, 72, 105, 103, 104, 119, + 97, 121, 32, 67, 121, 99, 108, 101, 0, 1, 0, 2, 95, 0, 6, 0, 3, 0, 30, 64, 128, 0, 0, 0, + 60, 64, 240, 0, 0, 0, 100, 65, 67, 51, 51, 99, 0, 6, 0, 3, 0, 30, 64, 115, 51, 51, 0, 60, + 64, 227, 51, 51, 0, 100, 65, 60, 204, 205, 0, 0, 0, 5, 72, 111, 110, 100, 97, 0, 0, 0, 9, + 67, 105, 118, 105, 99, 32, 86, 84, 105, 0, 0, 0, 6, 97, 98, 99, 100, 101, 102, + ]; + + decode_car_and_assert_expected_content(&big_endian_bytes)?; + let (limit, mut bytes_encoded_from_rust) = encode_car_from_scratch()?; + decode_car_and_assert_expected_content(bytes_encoded_from_rust.as_slice())?; + bytes_encoded_from_rust.truncate(limit); + assert_eq!(big_endian_bytes, bytes_encoded_from_rust); + + Ok(()) +} + +fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { + let mut car = CarDecoder::default(); + + let buf = ReadBuf::new(buffer); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + assert_eq!(car::SBE_TEMPLATE_ID, header.template_id()); + car = car.header(header); + + // Car... + assert_eq!(1234, car.serial_number()); + assert_eq!(2013, car.model_year()); + assert_eq!(BooleanType::T, car.available()); + assert_eq!(Model::A, car.code()); + + assert_eq!([0, 1, 2, 3, 4], car.some_numbers()); + assert_eq!([97, 98, 99, 100, 101, 102], car.vehicle_code()); + + let extras = car.extras(); + assert_eq!(6, extras.0); + assert!(extras.get_cruise_control()); + assert!(extras.get_sports_pack()); + assert!(!extras.get_sun_roof()); + + assert_eq!(Model::C, car.discounted_model()); + + let engine = car.engine_decoder(); + assert_eq!(2000, engine.capacity()); + assert_eq!(4, engine.num_cylinders()); + assert_eq!(9000, engine.max_rpm()); + assert_eq!("123", String::from_utf8_lossy(&engine.manufacturer_code())); + + assert_eq!(b"Petrol", engine.fuel()); + assert_eq!(35, engine.efficiency()); + assert_eq!(BooleanType::T, engine.booster_enabled()); + + let mut booster = engine.booster_decoder(); + assert_eq!(BoostType::NITROUS, booster.boost_type()); + assert_eq!(200, booster.horse_power()); + + car = booster.parent()?.parent()?; + let mut fuel_figures = car.fuel_figures_decoder(); + assert_eq!(3, fuel_figures.count()); + + assert_eq!(Some(0), fuel_figures.advance()?); + assert_eq!(30, fuel_figures.speed()); + assert_eq!(35.9, fuel_figures.mpg()); + let coord = fuel_figures.usage_description_decoder(); + assert_eq!( + "Urban Cycle", + String::from_utf8_lossy(fuel_figures.usage_description_slice(coord)) + ); + + assert_eq!(Some(1), fuel_figures.advance()?); + assert_eq!(55, fuel_figures.speed()); + assert_eq!(49.0, fuel_figures.mpg()); + let coord = fuel_figures.usage_description_decoder(); + assert_eq!( + "Combined Cycle", + String::from_utf8_lossy(fuel_figures.usage_description_slice(coord)) + ); + + assert_eq!(Some(2), fuel_figures.advance()?); + assert_eq!(75, fuel_figures.speed()); + assert_eq!(40.0, fuel_figures.mpg()); + let coord = fuel_figures.usage_description_decoder(); + assert_eq!( + "Highway Cycle", + String::from_utf8_lossy(fuel_figures.usage_description_slice(coord)) + ); + assert_eq!(Ok(None), fuel_figures.advance()); + + car = fuel_figures.parent()?; + let mut performance_figures = car.performance_figures_decoder(); + assert_eq!(2, performance_figures.count()); + + // 95 octane + assert_eq!(Some(0), performance_figures.advance()?); + assert_eq!(95, performance_figures.octane_rating()); + let mut acceleration = performance_figures.acceleration_decoder(); + assert_eq!(3, acceleration.count()); + assert_eq!(Some(0), acceleration.advance()?); + assert_eq!(30, acceleration.mph()); + assert_eq!(4.0, acceleration.seconds()); + assert_eq!(Some(1), acceleration.advance()?); + assert_eq!(60, acceleration.mph()); + assert_eq!(7.5, acceleration.seconds()); + assert_eq!(Some(2), acceleration.advance()?); + assert_eq!(100, acceleration.mph()); + assert_eq!(12.2, acceleration.seconds()); + assert_eq!(Ok(None), acceleration.advance()); + + // 99 octane + performance_figures = acceleration.parent()?; + assert_eq!(Some(1), performance_figures.advance()?); + assert_eq!(99, performance_figures.octane_rating()); + acceleration = performance_figures.acceleration_decoder(); + assert_eq!(3, acceleration.count()); + assert_eq!(Some(0), acceleration.advance()?); + assert_eq!(30, acceleration.mph()); + assert_eq!(3.8, acceleration.seconds()); + assert_eq!(Some(1), acceleration.advance()?); + assert_eq!(60, acceleration.mph()); + assert_eq!(7.1, acceleration.seconds()); + assert_eq!(Some(2), acceleration.advance()?); + assert_eq!(100, acceleration.mph()); + assert_eq!(11.8, acceleration.seconds()); + assert_eq!(Ok(None), acceleration.advance()); + + performance_figures = acceleration.parent()?; + car = performance_figures.parent()?; + + let coord = car.manufacturer_decoder(); + assert_eq!( + "Honda", + String::from_utf8_lossy(car.manufacturer_slice(coord)) + ); + + let coord = car.model_decoder(); + assert_eq!("Civic VTi", String::from_utf8_lossy(car.model_slice(coord))); + + let coord = car.activation_code_decoder(); + assert_eq!( + "abcdef", + String::from_utf8_lossy(car.activation_code_slice(coord)) + ); + + Ok(()) +} + +fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { + let mut buffer = vec![0u8; 256]; + let mut car = CarEncoder::default(); + let mut fuel_figures = FuelFiguresEncoder::default(); + let mut performance_figures = PerformanceFiguresEncoder::default(); + let mut acceleration = AccelerationEncoder::default(); + let mut extras = OptionalExtras::default(); + + car = car.wrap( + WriteBuf::new(buffer.as_mut_slice()), + message_header::ENCODED_LENGTH, + ); + car = car.header(0).parent()?; + + car.serial_number(1234); + car.model_year(2013); + car.available(BooleanType::T); + car.code(Model::A); + car.some_numbers([0, 1, 2, 3, 4]); + car.vehicle_code(*b"abcdef"); + + extras.set_cruise_control(true); + extras.set_sports_pack(true); + extras.set_sun_roof(false); + car.extras(extras); + + let mut engine = car.engine_encoder(); + engine.capacity(2000); + engine.num_cylinders(4); + engine.manufacturer_code([49, 50, 51]); // 123 + engine.efficiency(35); + engine.booster_enabled(BooleanType::T); + let mut booster = engine.booster_encoder(); + booster.boost_type(BoostType::NITROUS); + booster.horse_power(200); + + engine = booster.parent()?; + car = engine.parent()?; + fuel_figures = car.fuel_figures_encoder(3, fuel_figures); + assert_eq!(Some(0), fuel_figures.advance()?); + fuel_figures.speed(30); + fuel_figures.mpg(35.9); + fuel_figures.usage_description("Urban Cycle"); + + assert_eq!(Some(1), fuel_figures.advance()?); + fuel_figures.speed(55); + fuel_figures.mpg(49.0); + fuel_figures.usage_description("Combined Cycle"); + + assert_eq!(Some(2), fuel_figures.advance()?); + fuel_figures.speed(75); + fuel_figures.mpg(40.0); + fuel_figures.usage_description("Highway Cycle"); + + car = fuel_figures.parent()?; + performance_figures = car.performance_figures_encoder(2, performance_figures); + assert_eq!(Some(0), performance_figures.advance()?); + performance_figures.octane_rating(95); + + acceleration = performance_figures.acceleration_encoder(3, acceleration); + assert_eq!(Some(0), acceleration.advance()?); + acceleration.mph(30); + acceleration.seconds(4.0); + + assert_eq!(Some(1), acceleration.advance()?); + acceleration.mph(60); + acceleration.seconds(7.5); + + assert_eq!(Some(2), acceleration.advance()?); + acceleration.mph(100); + acceleration.seconds(12.2); + + performance_figures = acceleration.parent()?; + assert_eq!(Some(1), performance_figures.advance()?); + performance_figures.octane_rating(99); + + acceleration = performance_figures.acceleration_encoder(3, acceleration); + assert_eq!(Some(0), acceleration.advance()?); + acceleration.mph(30); + acceleration.seconds(3.8); + + assert_eq!(Some(1), acceleration.advance()?); + acceleration.mph(60); + acceleration.seconds(7.1); + + assert_eq!(Some(2), acceleration.advance()?); + acceleration.mph(100); + acceleration.seconds(11.8); + + performance_figures = acceleration.parent()?; + car = performance_figures.parent()?; + + car.manufacturer("Honda"); + car.model("Civic VTi"); + car.activation_code("abcdef"); + + let limit = car.get_limit(); + Ok((limit, buffer)) +} diff --git a/rust/tests/issue_435_test.rs b/rust/tests/issue_435_test.rs index a057211f18..e4e6c1e3c5 100644 --- a/rust/tests/issue_435_test.rs +++ b/rust/tests/issue_435_test.rs @@ -1,4 +1,4 @@ -use ::issue435::*; +use ::issue_435::*; fn create_encoder(buffer: &mut Vec) -> Issue435Encoder { let issue_435 = Issue435Encoder::default().wrap( @@ -13,8 +13,8 @@ fn create_encoder(buffer: &mut Vec) -> Issue435Encoder { #[test] fn issue_435_ref_test() -> SbeResult<()> { assert_eq!(9, message_header::ENCODED_LENGTH); - assert_eq!(1, issue435::SBE_BLOCK_LENGTH); - assert_eq!(0, issue435::SBE_SCHEMA_VERSION); + assert_eq!(1, issue_435::SBE_BLOCK_LENGTH); + assert_eq!(0, issue_435::SBE_SCHEMA_VERSION); // encode... let mut buffer = vec![0u8; 256]; @@ -24,10 +24,10 @@ fn issue_435_ref_test() -> SbeResult<()> { // decode... let buf = ReadBuf::new(buffer.as_slice()); let header = MessageHeaderDecoder::default().wrap(buf, 0); - assert_eq!(issue435::SBE_BLOCK_LENGTH, header.block_length()); - assert_eq!(issue435::SBE_SCHEMA_VERSION, header.version()); - assert_eq!(issue435::SBE_TEMPLATE_ID, header.template_id()); - assert_eq!(issue435::SBE_SCHEMA_ID, header.schema_id()); + assert_eq!(issue_435::SBE_BLOCK_LENGTH, header.block_length()); + assert_eq!(issue_435::SBE_SCHEMA_VERSION, header.version()); + assert_eq!(issue_435::SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(issue_435::SBE_SCHEMA_ID, header.schema_id()); assert_eq!(*SetRef::default().set_one(true), header.s()); let decoder = Issue435Decoder::default().header(header); From eb1bfa587445754e660eebf9f521cac31c3a7fd9 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Tue, 3 Aug 2021 14:59:01 -0500 Subject: [PATCH 0741/1594] [Rust] gradle task "runRustTests" will run `cargo test` --- build.gradle | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 22df73d07d..ef2078e4c4 100644 --- a/build.gradle +++ b/build.gradle @@ -584,12 +584,10 @@ task generateRustCodecs { 'generateCarExampleDataFile', 'generateCarExampleExtensionDataFile' } -task runRustExamples(type: Exec) { +task runRustTests(type: Exec) { workingDir = './rust' executable = 'cargo' - args = ['run'] - standardOutput = new ByteArrayOutputStream() - errorOutput = new ByteArrayOutputStream() + args = ['test'] dependsOn 'generateRustCodecs' } From 743d9bb03b90cdea93718d0d49bf5217249ad164 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 4 Aug 2021 12:09:35 +0200 Subject: [PATCH 0742/1594] [Java] Add a task to verify the generated Ir codecs are in sync with the current version of the generator. If the generator changed then the build will fail unless codecs are updated first. --- build.gradle | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index c6e22d07b0..b9df22e111 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,8 @@ +import java.nio.file.Files +import java.nio.file.Paths +import java.nio.file.StandardOpenOption +import java.security.MessageDigest + /* * Copyright 2013-2021 Real Logic Limited. * @@ -20,7 +25,7 @@ plugins { id "com.github.ben-manes.versions" version "0.39.0" } -defaultTasks 'clean', 'build' +defaultTasks 'clean', 'verifyJavaIrCodecsInSync', 'build' static def getBuildJavaVersion() { def buildJavaVersion = System.getenv('BUILD_JAVA_VERSION') ?: JavaVersion.current().getMajorVersion() @@ -660,7 +665,7 @@ task generateCSharpCodecs { 'generateCSharpCodecsWithXIncludes' } -task generateJavaIrCodecs(type: JavaExec) { +task generateJavaIrCodecs(type: JavaExec, dependsOn: 'computeOriginalIrHash') { mainClass = 'uk.co.real_logic.sbe.SbeTool' classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( @@ -708,6 +713,32 @@ task testReport(type: TestReport) { reportOn subprojects*.test } +final codecsDir = Paths.get('sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated').toFile() +final outputDir = Paths.get('sbe-tool/build') +final originalHashFile = outputDir.resolve('original.sha256').toFile() +final newHashFile = outputDir.resolve('new.sha256').toFile() + +task computeOriginalIrHash(type: ChecksumTask) { + inputDirectory = codecsDir + outputFile = originalHashFile +} + +task computeUpdatedIrHash(type: ChecksumTask, dependsOn: 'generateJavaIrCodecs') { + inputDirectory = codecsDir + outputFile = newHashFile +} + +task verifyJavaIrCodecsInSync(dependsOn: 'computeUpdatedIrHash') { + doLast { + final byte[] oldHash = Files.readAllBytes(originalHashFile.toPath()) + final byte[] newHash = Files.readAllBytes(newHashFile.toPath()) + if (!Arrays.equals(oldHash, newHash)) + { + throw new GradleException("Java Ir codecs are out of sync!") + } + } +} + def isNonStable = { String version -> def stableKeyword = ['RELEASE', 'FINAL', 'GA'].any { it -> version.toUpperCase().contains(it) } def regex = /^[0-9,.v-]+(-r)?$/ @@ -725,3 +756,34 @@ wrapper { gradleVersion = '7.1.1' distributionType = 'ALL' } + +class ChecksumTask extends DefaultTask +{ + private static final MessageDigest SHA_256 = MessageDigest.getInstance("SHA-256"); + + @InputDirectory + File inputDirectory + + @OutputFile + File outputFile + + @TaskAction + def checksum() { + SHA_256.reset() + + final File[] files = inputDirectory.listFiles(); + for (final File f : files) + { + SHA_256.update(Files.readAllBytes(f.toPath())) + } + + final byte[] hash = SHA_256.digest() + + Files.write( + outputFile.toPath(), + hash, + StandardOpenOption.CREATE, + StandardOpenOption.WRITE, + StandardOpenOption.TRUNCATE_EXISTING) + } +} \ No newline at end of file From 551e8d1724f436f35bd21512a1df75250456a43a Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 4 Aug 2021 12:11:30 +0200 Subject: [PATCH 0743/1594] [Build] Add missing empty line. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b9df22e111..d417866748 100644 --- a/build.gradle +++ b/build.gradle @@ -786,4 +786,4 @@ class ChecksumTask extends DefaultTask StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING) } -} \ No newline at end of file +} From bae7ac299d341be29756c6851a5646559e7ce53e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 4 Aug 2021 12:16:11 +0200 Subject: [PATCH 0744/1594] [Build] Clarify codecs out of sync. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d417866748..37c24819e0 100644 --- a/build.gradle +++ b/build.gradle @@ -734,7 +734,7 @@ task verifyJavaIrCodecsInSync(dependsOn: 'computeUpdatedIrHash') { final byte[] newHash = Files.readAllBytes(newHashFile.toPath()) if (!Arrays.equals(oldHash, newHash)) { - throw new GradleException("Java Ir codecs are out of sync!") + throw new GradleException("Java Ir codecs are out of sync! Please execute the `generateJavaIrCodecs` task and commit the changes.") } } } From fd92b2756d9227d920e217b987d28d3502a710be Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Wed, 4 Aug 2021 08:01:05 -0500 Subject: [PATCH 0745/1594] [Rust] added 'fieldToken' arg to RustGenerator.generatePrimitiveDecoder() so that 'sinceVersion' is correctly handled --- .../sbe/generation/rust/RustGenerator.java | 70 ++++++++++--------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 80c04ce910..19fe835ca4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -401,7 +401,7 @@ private static void generatePrimitiveEncoder( { if (encoding.presence() == Encoding.Presence.CONSTANT) { - indent(sb, level, "// skipping CONSTANT %s\n\n", name); + indent(sb, level, "// skipping CONSTANT %s\n\n", name); } else { @@ -509,7 +509,7 @@ static void generateDecoderFields( switch (typeToken.signal()) { case ENCODING: - generatePrimitiveDecoder(sb, level, typeToken, name, encoding); + generatePrimitiveDecoder(sb, level, fieldToken, typeToken, name, encoding); break; case BEGIN_ENUM: generateEnumDecoder(sb, level, fieldToken, typeToken, name); @@ -586,15 +586,16 @@ private static void generateBitSetDecoder( } private static void generatePrimitiveDecoder( - final StringBuilder sb, - final int level, - final Token typeToken, - final String name, - final Encoding encoding) throws IOException + final StringBuilder sb, + final int level, + final Token fieldToken, + final Token typeToken, + final String name, + final Encoding encoding) throws IOException { if (typeToken.arrayLength() > 1) { - generatePrimitiveArrayDecoder(sb, level, typeToken, name, encoding); + generatePrimitiveArrayDecoder(sb, level, fieldToken, typeToken, name, encoding); } else if (encoding.presence() == Encoding.Presence.CONSTANT) { @@ -602,20 +603,21 @@ else if (encoding.presence() == Encoding.Presence.CONSTANT) } else if (encoding.presence() == Encoding.Presence.OPTIONAL) { - generatePrimitiveOptionalDecoder(sb, level, typeToken, name, encoding); + generatePrimitiveOptionalDecoder(sb, level, fieldToken, name, encoding); } else { - generatePrimitiveRequiredDecoder(sb, level, typeToken, name, encoding); + generatePrimitiveRequiredDecoder(sb, level, fieldToken, name, encoding); } } private static void generatePrimitiveArrayDecoder( - final StringBuilder sb, - final int level, - final Token typeToken, - final String name, - final Encoding encoding) throws IOException + final StringBuilder sb, + final int level, + final Token fieldToken, + final Token typeToken, + final String name, + final Encoding encoding) throws IOException { final PrimitiveType primitiveType = encoding.primitiveType(); final String rustPrimitiveType = rustTypeName(primitiveType); @@ -629,9 +631,9 @@ private static void generatePrimitiveArrayDecoder( rustPrimitiveType, arrayLength); - if (typeToken.version() > 0) + if (fieldToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", typeToken.version()); + indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); indent(sb, level + 2, "return [%s, %d];\n", encoding.applicableNullValue(), arrayLength); indent(sb, level + 1, "}\n\n"); } @@ -709,11 +711,11 @@ private static void generatePrimitiveConstantDecoder( } private static void generatePrimitiveOptionalDecoder( - final StringBuilder sb, - final int level, - final Token typeToken, - final String name, - final Encoding encoding) throws IOException + final StringBuilder sb, + final int level, + final Token fieldToken, + final String name, + final Encoding encoding) throws IOException { assert encoding.presence() == Encoding.Presence.OPTIONAL; final PrimitiveType primitiveType = encoding.primitiveType(); @@ -733,16 +735,16 @@ private static void generatePrimitiveOptionalDecoder( formatFunctionName(name), rustPrimitiveType); - if (typeToken.version() > 0) + if (fieldToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", typeToken.version()); + indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); indent(sb, level + 2, "return None;\n"); indent(sb, level + 1, "}\n\n"); } indent(sb, level + 1, "let value = self.get_buf().get_%s_at(self.%s);\n", rustPrimitiveType, - getBufOffset(typeToken)); + getBufOffset(fieldToken)); indent(sb, level + 1, "if value == %s {\n", generateRustLiteral(primitiveType, encoding.applicableNullValue().toString())); indent(sb, level + 2, "None\n"); @@ -753,11 +755,11 @@ private static void generatePrimitiveOptionalDecoder( } private static void generatePrimitiveRequiredDecoder( - final StringBuilder sb, - final int level, - final Token typeToken, - final String name, - final Encoding encoding) throws IOException + final StringBuilder sb, + final int level, + final Token fieldToken, + final String name, + final Encoding encoding) throws IOException { assert encoding.presence() == Encoding.Presence.REQUIRED; final PrimitiveType primitiveType = encoding.primitiveType(); @@ -776,9 +778,9 @@ private static void generatePrimitiveRequiredDecoder( formatFunctionName(name), rustPrimitiveType); - if (typeToken.version() > 0) + if (fieldToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", typeToken.version()); + indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); indent(sb, level + 2, "return %s;\n", generateRustLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString())); indent(sb, level + 1, "}\n\n"); @@ -786,7 +788,7 @@ private static void generatePrimitiveRequiredDecoder( indent(sb, level + 1, "self.get_buf().get_%s_at(self.%s)\n", rustPrimitiveType, - getBufOffset(typeToken)); + getBufOffset(fieldToken)); indent(sb, level, "}\n\n"); } @@ -1422,7 +1424,7 @@ private static void generateCompositeDecoder( switch (encodingToken.signal()) { case ENCODING: - generatePrimitiveDecoder(sb, 2, encodingToken, encodingToken.name(), encodingToken.encoding()); + generatePrimitiveDecoder(sb, 2, encodingToken, encodingToken, encodingToken.name(), encodingToken.encoding()); break; case BEGIN_ENUM: generateEnumDecoder(sb, 2, encodingToken, encodingToken, encodingToken.name()); From d66c6e4bfd071daaa9aa6795c00e0824c871a0fc Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Wed, 4 Aug 2021 08:08:19 -0500 Subject: [PATCH 0746/1594] [Rust] fixed whitespace issues --- .../sbe/generation/rust/RustGenerator.java | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 19fe835ca4..f28146d589 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -586,12 +586,12 @@ private static void generateBitSetDecoder( } private static void generatePrimitiveDecoder( - final StringBuilder sb, - final int level, - final Token fieldToken, - final Token typeToken, - final String name, - final Encoding encoding) throws IOException + final StringBuilder sb, + final int level, + final Token fieldToken, + final Token typeToken, + final String name, + final Encoding encoding) throws IOException { if (typeToken.arrayLength() > 1) { @@ -612,12 +612,12 @@ else if (encoding.presence() == Encoding.Presence.OPTIONAL) } private static void generatePrimitiveArrayDecoder( - final StringBuilder sb, - final int level, - final Token fieldToken, - final Token typeToken, - final String name, - final Encoding encoding) throws IOException + final StringBuilder sb, + final int level, + final Token fieldToken, + final Token typeToken, + final String name, + final Encoding encoding) throws IOException { final PrimitiveType primitiveType = encoding.primitiveType(); final String rustPrimitiveType = rustTypeName(primitiveType); @@ -711,11 +711,11 @@ private static void generatePrimitiveConstantDecoder( } private static void generatePrimitiveOptionalDecoder( - final StringBuilder sb, - final int level, - final Token fieldToken, - final String name, - final Encoding encoding) throws IOException + final StringBuilder sb, + final int level, + final Token fieldToken, + final String name, + final Encoding encoding) throws IOException { assert encoding.presence() == Encoding.Presence.OPTIONAL; final PrimitiveType primitiveType = encoding.primitiveType(); @@ -755,11 +755,11 @@ private static void generatePrimitiveOptionalDecoder( } private static void generatePrimitiveRequiredDecoder( - final StringBuilder sb, - final int level, - final Token fieldToken, - final String name, - final Encoding encoding) throws IOException + final StringBuilder sb, + final int level, + final Token fieldToken, + final String name, + final Encoding encoding) throws IOException { assert encoding.presence() == Encoding.Presence.REQUIRED; final PrimitiveType primitiveType = encoding.primitiveType(); @@ -1424,7 +1424,8 @@ private static void generateCompositeDecoder( switch (encodingToken.signal()) { case ENCODING: - generatePrimitiveDecoder(sb, 2, encodingToken, encodingToken, encodingToken.name(), encodingToken.encoding()); + generatePrimitiveDecoder(sb, 2, encodingToken, encodingToken, encodingToken.name(), + encodingToken.encoding()); break; case BEGIN_ENUM: generateEnumDecoder(sb, 2, encodingToken, encodingToken, encodingToken.name()); From 4c9e0c41d78fdd14b1c704a634b2f000398b9d65 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 5 Aug 2021 13:11:27 +0200 Subject: [PATCH 0747/1594] [Java] Upgrade to Agrona 1.12.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 37c24819e0..a0ed8ed545 100644 --- a/build.gradle +++ b/build.gradle @@ -48,8 +48,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '3.11.2' def junitVersion = '5.7.2' def jmhVersion = '1.32' -def agronaVersion = '1.11.0' -def agronaVersionRange = '[1.11,1.12[' // allow any patch release of 1.11.x +def agronaVersion = '1.12.0' +def agronaVersionRange = '[1.12,1.13[' // allow any patch release of 1.12.x def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 75f1400005ce53c8e5f8abd0fc49e1197f2f08c9 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 5 Aug 2021 15:45:15 +0200 Subject: [PATCH 0748/1594] [Build] Fix file path issues to make it work on Windows. --- build.gradle | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 91e1e7f85d..4f42342e38 100644 --- a/build.gradle +++ b/build.gradle @@ -713,14 +713,14 @@ task testReport(type: TestReport) { reportOn subprojects*.test } -final codecsDir = Paths.get('sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated').toFile() -final outputDir = Paths.get('sbe-tool/build') -final originalHashFile = outputDir.resolve('original.sha256').toFile() -final newHashFile = outputDir.resolve('new.sha256').toFile() +final codecsDir = project.file('sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated') +final outputDir = project.file('sbe-tool/build') +final oldHashFile = new File(outputDir, 'old.sha256') +final newHashFile = new File(outputDir, 'new.sha256') task computeOriginalIrHash(type: ChecksumTask) { inputDirectory = codecsDir - outputFile = originalHashFile + outputFile = oldHashFile } task computeUpdatedIrHash(type: ChecksumTask, dependsOn: 'generateJavaIrCodecs') { @@ -730,7 +730,7 @@ task computeUpdatedIrHash(type: ChecksumTask, dependsOn: 'generateJavaIrCodecs') task verifyJavaIrCodecsInSync(dependsOn: 'computeUpdatedIrHash') { doLast { - final byte[] oldHash = Files.readAllBytes(originalHashFile.toPath()) + final byte[] oldHash = Files.readAllBytes(oldHashFile.toPath()) final byte[] newHash = Files.readAllBytes(newHashFile.toPath()) if (!Arrays.equals(oldHash, newHash)) { From f42677374b101ff247a12ad79353730f3d3ac6be Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 5 Aug 2021 16:30:24 +0100 Subject: [PATCH 0749/1594] Formatting. --- build.gradle | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index a0ed8ed545..91e1e7f85d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,3 @@ -import java.nio.file.Files -import java.nio.file.Paths -import java.nio.file.StandardOpenOption -import java.security.MessageDigest - /* * Copyright 2013-2021 Real Logic Limited. * @@ -19,6 +14,11 @@ import java.security.MessageDigest * limitations under the License. */ +import java.nio.file.Files +import java.nio.file.Paths +import java.nio.file.StandardOpenOption +import java.security.MessageDigest + plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '7.0.0' apply false From 183fdd71c1b462146082b4cfd1c6fb7fdff92b5d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 5 Aug 2021 16:46:28 +0100 Subject: [PATCH 0750/1594] [Java] Make use of MutableDirectBuffer.putStringWithoutLengthAscii for CharSequence to minimise bounds checks. --- .../co/real_logic/sbe/generation/java/JavaGenerator.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 1bcd4798c0..c7f4b9b517 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1081,12 +1081,7 @@ private void generateCharArrayEncodeMethods( indent + " final int limit = parentMessage.limit();\n" + indent + " parentMessage.limit(limit + headerLength + length);\n" + indent + " %5$s;\n" + - indent + " for (int i = 0; i < length; ++i)\n" + - indent + " {\n" + - indent + " final char charValue = value.charAt(i);\n" + - indent + " final byte byteValue = charValue > 127 ? (byte)'?' : (byte)charValue;\n" + - indent + " buffer.putByte(limit + headerLength + i, byteValue);\n" + - indent + " }\n\n" + + indent + " buffer.putStringWithoutLengthAscii(limit + headerLength, value);\n\n" + indent + " return this;\n" + indent + " }\n", className, From 229226647e07e154c90880d80e3f8016008547c3 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 5 Aug 2021 16:49:15 +0100 Subject: [PATCH 0751/1594] [Java] Remove unused import. --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4f42342e38..198080313f 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,6 @@ */ import java.nio.file.Files -import java.nio.file.Paths import java.nio.file.StandardOpenOption import java.security.MessageDigest From 6e319fa787061c4236caaefc044ddc0ff3cd91e6 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 5 Aug 2021 18:35:57 +0200 Subject: [PATCH 0752/1594] [Build] Normalize EOL of the generated files when computing checksums to avoid false positives. --- build.gradle | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 198080313f..7d6fdb575c 100644 --- a/build.gradle +++ b/build.gradle @@ -759,6 +759,8 @@ wrapper { class ChecksumTask extends DefaultTask { private static final MessageDigest SHA_256 = MessageDigest.getInstance("SHA-256"); + private static final byte CR = (byte) ('\r' as char) + private static final byte LF = (byte) ('\n' as char) @InputDirectory File inputDirectory @@ -773,7 +775,9 @@ class ChecksumTask extends DefaultTask final File[] files = inputDirectory.listFiles(); for (final File f : files) { - SHA_256.update(Files.readAllBytes(f.toPath())) + final byte[] raw = Files.readAllBytes(f.toPath()) + final byte[] normalized = normalizeEOL(raw); + SHA_256.update(normalized) } final byte[] hash = SHA_256.digest() @@ -785,4 +789,19 @@ class ChecksumTask extends DefaultTask StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING) } + + private byte[] normalizeEOL(final byte[] raw) + { + final byte[] result = new byte[raw.length] + int i = 0 + for (int j = 0, size = raw.length; j < size; j++) + { + if (CR == raw[j] && (j == size - 1 || LF == raw[j + 1])) + { + continue; + } + result[i++] = raw[j] + } + return raw.length == i ? result : Arrays.copyOf(result, i); + } } From 145b0d45ed2367b7167d651139fe5ad58d3bb908 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 5 Aug 2021 18:40:34 +0200 Subject: [PATCH 0753/1594] [Build] Make `build` depend on `verifyJavaIrCodecsInSync` so that the check is always executed. --- build.gradle | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 7d6fdb575c..e2283458e8 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ plugins { id "com.github.ben-manes.versions" version "0.39.0" } -defaultTasks 'clean', 'verifyJavaIrCodecsInSync', 'build' +defaultTasks 'clean', 'build' static def getBuildJavaVersion() { def buildJavaVersion = System.getenv('BUILD_JAVA_VERSION') ?: JavaVersion.current().getMajorVersion() @@ -744,13 +744,15 @@ def isNonStable = { String version -> return !stableKeyword && !(version ==~ regex) } -tasks.named("dependencyUpdates").configure { +tasks.named('dependencyUpdates').configure { // Reject all non stable versions rejectVersionIf { isNonStable(it.candidate.version) } } +tasks.findByName('build').dependsOn verifyJavaIrCodecsInSync + wrapper { gradleVersion = '7.1.1' distributionType = 'ALL' From 17c03c3036c10603ab235e933fb08a8d7c697e3d Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 5 Aug 2021 18:44:02 +0200 Subject: [PATCH 0754/1594] [CI] Add Windows to the Java build + fix schema validation warnings. --- .github/workflows/ci.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 801519bcf7..5ca3e3b8c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,12 +14,13 @@ env: jobs: java-build: - name: Java ${{ matrix.java }} - runs-on: ubuntu-20.04 + name: Java ${{ matrix.java }} (${{ matrix.os }}) + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: java: [ '8', '11', '16', '17-ea' ] + os: [ 'ubuntu-20.04', 'windows-latest' ] steps: - name: Checkout code uses: actions/checkout@v2 @@ -170,9 +171,11 @@ jobs: cpp-clang-macos-build: name: C++ Xcode ${{ matrix.version }} (macOS) - runs-on: macos-latest + runs-on: ${{ matrix.os }} strategy: fail-fast: false + matrix: + os: [ 'macos-latest' ] env: CC: clang CXX: clang++ @@ -189,9 +192,11 @@ jobs: cpp-msvc-build: name: C++ MSVC (Windows) - runs-on: windows-latest + runs-on: ${{ matrix.os }} strategy: fail-fast: false + matrix: + os: [ 'windows-latest' ] env: CC: cl CXX: cl From a51aa31fae22e1b6d6f71963fd67a4157ac058b0 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Thu, 5 Aug 2021 16:53:49 -0500 Subject: [PATCH 0755/1594] [Rust] updated RustGenerator.generateEnumDecoder() to support version --- .../sbe/generation/rust/RustGenerator.java | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index f28146d589..221b378926 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -179,7 +179,6 @@ String schemaVersionType() return rustTypeName(ir.headerStructure().schemaVersionType()); } - static String withLifetime(final String typeName) { return format("%s<%s>", typeName, BUF_LIFETIME); @@ -518,7 +517,7 @@ static void generateDecoderFields( generateBitSetDecoder(sb, level, typeToken, name); break; case BEGIN_COMPOSITE: - generateCompositeDecoder(sb, level, typeToken, name); + generateCompositeDecoder(sb, level, fieldToken, typeToken, name); break; default: throw new UnsupportedOperationException("Unable to handle: " + typeToken); @@ -534,6 +533,7 @@ static void generateDecoderFields( private static void generateCompositeDecoder( final StringBuilder sb, final int level, + final Token fieldToken, final Token typeToken, final String name) throws IOException { @@ -541,17 +541,17 @@ private static void generateCompositeDecoder( final String decoderTypeName = decoderName(formatStructName(typeToken.name())); indent(sb, level, "/// COMPOSITE DECODER\n"); indent(sb, level, "#[inline]\n"); - if (typeToken.version() > 0) + if (fieldToken.version() > 0) { indent(sb, level, "pub fn %s(self) -> Either> {\n", decoderName, decoderTypeName); - indent(sb, level + 1, "if self.acting_version < %d {\n", typeToken.version()); + indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); indent(sb, level + 2, "return Either::Left(self);\n"); indent(sb, level + 1, "}\n\n"); - indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); + indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(fieldToken)); indent(sb, level + 1, "Either::Right(%s::default().wrap(self, offset))\n", decoderTypeName); } @@ -561,7 +561,7 @@ private static void generateCompositeDecoder( decoderName, decoderTypeName); - indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); + indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(fieldToken)); indent(sb, level + 1, "%s::default().wrap(self, offset)\n", decoderTypeName); } indent(sb, level, "}\n\n"); @@ -824,6 +824,14 @@ private static void generateEnumDecoder( indent(sb, level, "/// REQUIRED\n"); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&self) -> %s {\n", formatFunctionName(name), enumType); + + if (fieldToken.version() > 0) + { + indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); + indent(sb, level + 2, "return %s::default();\n", enumType); + indent(sb, level + 1, "}\n\n"); + } + indent(sb, level + 1, "self.get_buf().get_%s_at(self.%s).into()\n", rustPrimitiveType, getBufOffset(typeToken)); @@ -1434,7 +1442,7 @@ private static void generateCompositeDecoder( generateBitSetDecoder(sb, 2, encodingToken, encodingToken.name()); break; case BEGIN_COMPOSITE: - generateCompositeDecoder(sb, 2, encodingToken, encodingToken.name()); + generateCompositeDecoder(sb, 2, encodingToken, encodingToken, encodingToken.name()); break; } From d43f987ae2d2e1a094e87cfb85a72c3fb3374105 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Thu, 5 Aug 2021 17:05:46 -0500 Subject: [PATCH 0756/1594] [Rust] added method RustUtil.characterEncoding(Encoding) --- .../sbe/generation/rust/RustGenerator.java | 13 ++++--------- .../co/real_logic/sbe/generation/rust/RustUtil.java | 12 ++++++++++++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 221b378926..4605b44f8d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -296,12 +296,7 @@ static void generateEncoderVarData( throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); } - String characterEncoding = tokens.get(i + 3).encoding().characterEncoding(); - if (characterEncoding == null) - { - characterEncoding = ""; - } - + final String characterEncoding = characterEncoding(tokens.get(i + 3).encoding()); final String propertyName = toLowerSnakeCase(varDataToken.name()); final Token lengthToken = tokens.get(i + 2); final Encoding lengthEncoding = lengthToken.encoding(); @@ -326,7 +321,7 @@ static void generateEncoderVarData( } // function to write slice ... todo - handle character encoding ? - indent(sb, level, "/// VAR_DATA ENCODER - character encoding %s\n", characterEncoding); + indent(sb, level, "/// VAR_DATA ENCODER - character encoding: '%s'\n", characterEncoding); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", propertyName, varDataType); @@ -915,13 +910,13 @@ static void generateDecoderVarData( throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); } - final String characterEncoding = tokens.get(i + 3).encoding().characterEncoding(); + final String characterEncoding = characterEncoding(tokens.get(i + 3).encoding()); final String propertyName = toLowerSnakeCase(varDataToken.name()); final Token lengthToken = tokens.get(i + 2); final Encoding lengthEncoding = lengthToken.encoding(); final PrimitiveType lengthType = lengthEncoding.primitiveType(); - indent(sb, level, "/// VAR_DATA DECODER - character encoding %s\n", characterEncoding); + indent(sb, level, "/// VAR_DATA DECODER - character encoding: '%s'\n", characterEncoding); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s_decoder(&mut self) -> (usize, usize) {\n", propertyName); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index 33c0edab54..9ee5bd204c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -19,6 +19,7 @@ import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.generation.Generators; import uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType; +import uk.co.real_logic.sbe.ir.Encoding; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -165,6 +166,17 @@ static String cleanUpperAcronyms(final String value) return value; } + static String characterEncoding(final Encoding encoding) + { + final String characterEncoding = encoding.characterEncoding(); + if (characterEncoding == null) + { + return "None"; + } + + return characterEncoding; + } + /** * Converts to 'snake_case' but will also handle when there are multiple * upper case characters in a row 'UPPERCase' => 'upper_case' From e6134ff1b4883b03cf67133cf298f79ba5100887 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Thu, 5 Aug 2021 17:23:21 -0500 Subject: [PATCH 0757/1594] [Rust] updated RustGenerator.generateBitSetDecoder() to support version --- rust/tests/big_endian_test.rs | 9 +++------ .../co/real_logic/sbe/generation/rust/RustGenerator.java | 8 ++++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/rust/tests/big_endian_test.rs b/rust/tests/big_endian_test.rs index 8670d14e53..ae677dce21 100644 --- a/rust/tests/big_endian_test.rs +++ b/rust/tests/big_endian_test.rs @@ -40,7 +40,7 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { assert_eq!(Model::A, car.code()); assert_eq!([0, 1, 2, 3, 4], car.some_numbers()); - assert_eq!([97, 98, 99, 100, 101, 102], car.vehicle_code()); + assert_eq!(*b"abcdef", car.vehicle_code()); let extras = car.extras(); assert_eq!(6, extras.0); @@ -146,10 +146,7 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { assert_eq!("Civic VTi", String::from_utf8_lossy(car.model_slice(coord))); let coord = car.activation_code_decoder(); - assert_eq!( - "abcdef", - String::from_utf8_lossy(car.activation_code_slice(coord)) - ); + assert_eq!(b"abcdef", car.activation_code_slice(coord)); Ok(()) } @@ -183,7 +180,7 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { let mut engine = car.engine_encoder(); engine.capacity(2000); engine.num_cylinders(4); - engine.manufacturer_code([49, 50, 51]); // 123 + engine.manufacturer_code(*b"123"); engine.efficiency(35); engine.booster_enabled(BooleanType::T); let mut booster = engine.booster_encoder(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 4605b44f8d..16840c6da7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -573,6 +573,14 @@ private static void generateBitSetDecoder( final String structTypeName = formatStructName(bitsetToken.applicableTypeName()); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&self) -> %s {\n", formatFunctionName(name), structTypeName); + + if (bitsetToken.version() > 0) + { + indent(sb, level + 1, "if self.acting_version < %d {\n", bitsetToken.version()); + indent(sb, level + 2, "return %s::default();\n", structTypeName); + indent(sb, level + 1, "}\n\n"); + } + indent(sb, level + 1, "%s::new(self.get_buf().get_%s_at(self.%s))\n", structTypeName, rustPrimitiveType, From 264935df63e3dfd77cdb1b6f8fcb67afccd6f3b2 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Fri, 6 Aug 2021 06:17:48 -0500 Subject: [PATCH 0758/1594] [Rust] lib.rs will be generated with "#![forbid(unsafe_code)]" --- .../main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 155ffe5536..83690976e5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -76,6 +76,7 @@ void generate() throws IOException { try (Writer libRs = outputManager.createOutput("lib")) { + indent(libRs, 0, "#![forbid(unsafe_code)]\n"); indent(libRs, 0, "#![allow(clippy::upper_case_acronyms)]\n"); indent(libRs, 0, "#![allow(non_camel_case_types)]\n"); indent(libRs, 0, "use core::{convert::TryInto};\n\n"); From b7e393c4737622aea3a9774e55ea762b43ea25d6 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Fri, 6 Aug 2021 07:26:52 -0500 Subject: [PATCH 0759/1594] [Rust] minor edits to rust docs generated by RustGenerator --- .../sbe/generation/rust/MessageCoderDef.java | 2 +- .../sbe/generation/rust/RustGenerator.java | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index 93339add2c..1a7f7a2315 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -111,7 +111,7 @@ void generate( subGroup.appendTo(sb); } - indent(sb, 0, "}\n"); // mod end + indent(sb, 0, "} // end %s\n\n", codecType.toString().toLowerCase()); // mod end } void appendTo(final Appendable dest) throws IOException diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 16840c6da7..a1f253b8ce 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -355,7 +355,7 @@ private static void generatePrimitiveEncoder( final int arrayLength = typeToken.arrayLength(); if (arrayLength > 1) { - indent(sb, level, "/// primitive array field %s\n", name); + indent(sb, level, "/// primitive array field '%s'\n", name); indent(sb, level, "/// - min value: %s\n", encoding.applicableMinValue()); indent(sb, level, "/// - max value: %s\n", encoding.applicableMaxValue()); indent(sb, level, "/// - null value: %s\n", encoding.applicableNullValue()); @@ -399,7 +399,7 @@ private static void generatePrimitiveEncoder( } else { - indent(sb, level, "/// primitive field %s\n", name); + indent(sb, level, "/// primitive field '%s'\n", name); indent(sb, level, "/// - min value: %s\n", encoding.applicableMinValue()); indent(sb, level, "/// - max value: %s\n", encoding.applicableMaxValue()); indent(sb, level, "/// - null value: %s\n", encoding.applicableNullValue()); @@ -432,14 +432,14 @@ private static void generateEnumEncoder( if (fieldToken.isConstantEncoding()) { - indent(sb, level, "// skipping CONSTANT %s\n\n", name); + indent(sb, level, "// skipping CONSTANT enum '%s'\n\n", name); } else { final Encoding encoding = typeToken.encoding(); final String rustPrimitiveType = rustTypeName(encoding.primitiveType()); - indent(sb, level, "/// REQUIRED\n"); + indent(sb, level, "/// REQUIRED enum\n"); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", formatFunctionName(name), enumType); @@ -724,7 +724,7 @@ private static void generatePrimitiveOptionalDecoder( final PrimitiveType primitiveType = encoding.primitiveType(); final String rustPrimitiveType = rustTypeName(primitiveType); final String characterEncoding = encoding.characterEncoding(); - indent(sb, level, "/// primitive field - %s { null_value: '%s' }\n", + indent(sb, level, "/// primitive field - '%s' { null_value: '%s' }\n", encoding.presence(), encoding.applicableNullValue()); if (characterEncoding != null) @@ -768,7 +768,7 @@ private static void generatePrimitiveRequiredDecoder( final PrimitiveType primitiveType = encoding.primitiveType(); final String rustPrimitiveType = rustTypeName(primitiveType); final String characterEncoding = encoding.characterEncoding(); - indent(sb, level, "/// primitive field - %s\n", encoding.presence()); + indent(sb, level, "/// primitive field - '%s'\n", encoding.presence()); if (characterEncoding != null) { @@ -808,7 +808,7 @@ private static void generateEnumDecoder( if (fieldToken.isConstantEncoding()) { - indent(sb, level, "/// CONSTANT \n"); + indent(sb, level, "/// CONSTANT enum\n"); final Encoding encoding = fieldToken.encoding(); final String rawConstValueName = encoding.constValue().toString(); final int indexOfDot = rawConstValueName.indexOf('.'); @@ -824,7 +824,7 @@ private static void generateEnumDecoder( final Encoding encoding = typeToken.encoding(); final String rustPrimitiveType = rustTypeName(encoding.primitiveType()); - indent(sb, level, "/// REQUIRED\n"); + indent(sb, level, "/// REQUIRED enum\n"); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&self) -> %s {\n", formatFunctionName(name), enumType); From 7283ddd6f46134ee4442eff51f6fe72e6a682771 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 6 Aug 2021 12:16:50 -0700 Subject: [PATCH 0760/1594] 1.24.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 2f18f2d7ee..d437046834 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.23.1-SNAPSHOT \ No newline at end of file +1.24.0 \ No newline at end of file From c776ca11d6ac4f3a1bd2565ee3c3be1c0f1893e7 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 6 Aug 2021 12:18:02 -0700 Subject: [PATCH 0761/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index d437046834..d07d97c65b 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.24.0 \ No newline at end of file +1.24.1-SNAPSHOT \ No newline at end of file From 8125ed9997a179a43c5ff8f8d65adb0a96085b0e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 9 Aug 2021 12:19:41 +0100 Subject: [PATCH 0762/1594] [Java] Upgrade to JMH 1.33. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e2283458e8..6abfa0d2b4 100644 --- a/build.gradle +++ b/build.gradle @@ -46,7 +46,7 @@ def checkstyleVersion = '8.39' def hamcrestVersion = '2.2' def mockitoVersion = '3.11.2' def junitVersion = '5.7.2' -def jmhVersion = '1.32' +def jmhVersion = '1.33' def agronaVersion = '1.12.0' def agronaVersionRange = '[1.12,1.13[' // allow any patch release of 1.12.x From e6106f9e3143ce6629bd1caa5f12d1dd92a2949a Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Mon, 9 Aug 2021 14:18:57 -0500 Subject: [PATCH 0763/1594] [Rust] added `rust-build` job to ci.yml --- .github/workflows/ci.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 801519bcf7..4d48662137 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -206,3 +206,33 @@ jobs: echo "cmake-$Env:CMAKE_VERSION-win64-x64/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 - name: Build run: cppbuild/cppbuild.cmd + + rust-build: + name: Rust ${{ matrix.rust }} + runs-on: ubuntu-20.04 + strategy: + fail-fast: false + matrix: + rust: [ stable, beta, nightly ] + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Cache Gradle dependencies + uses: actions/cache@v2 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v2 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + - name: Rust setup + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + override: true + - run: ./gradlew runRustTests \ No newline at end of file From 561ef2c310be8f9d9d8c7f09b09b430bd4d01605 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Wed, 11 Aug 2021 22:57:58 -0500 Subject: [PATCH 0764/1594] [Rust] updated README.md to include info on Rust --- README.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5e18d745cd..c937712816 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Simple Binary Encoding (SBE) [SBE](https://github.com/FIXTradingCommunity/fix-simple-binary-encoding) is an OSI layer 6 presentation for encoding and decoding binary application messages for low-latency financial applications. This repository contains -the reference implementations in Java, C++, Golang, and C#. +the reference implementations in Java, C++, Golang, C#, and Rust. More details on the design and usage of SBE can be found on the [Wiki](https://github.com/real-logic/simple-binary-encoding/wiki). @@ -110,6 +110,25 @@ Users of CSharp generated code should see the [user documentation](https://githu Developers wishing to enhance the CSharp generator should see the [developer documentation](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/README.md) +Rust Build +------------ +The SBE Rust generator will produce 100% safe rust crates (no `unsafe` code will be generated). Generated crates do +not have any dependencies on any libraries (including no SBE libraries). If you don't yet have Rust installed +see [Rust: Getting Started](https://www.rust-lang.org/learn/get-started) + +Generate the Rust codecs + + $ ./gradlew generateRustCodecs + +Run the Rust test from Gradle + + $ ./gradlew runRustTests + +Or run test directly with `Cargo` + + $ cd rust + $ cargo test + License (See LICENSE file for full license) ------------------------------------------- Copyright 2013-2021 Real Logic Limited. From 1d8a46528711aafe14c3cad5744edaa44229d062 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 12 Aug 2021 12:33:22 +0200 Subject: [PATCH 0765/1594] [Gradle] Enable all warnings. --- gradle.properties | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gradle.properties b/gradle.properties index b46e828b0d..65930afd28 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,9 @@ org.gradle.java.installations.auto-download=false org.gradle.java.installations.fromEnv=BUILD_JAVA_HOME +org.gradle.logging.level=warn +org.gradle.warning.mode=all + # HTTP timeouts for Gradle systemProp.org.gradle.internal.http.connectionTimeout=300000 systemProp.org.gradle.internal.http.socketTimeout=300000 From 5e0d46239b89f962b8a25d68c5c03fa37f657c98 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 14 Aug 2021 12:51:26 +0100 Subject: [PATCH 0766/1594] [Java] Upgrade to Checkstyle 8.45.1. --- build.gradle | 2 +- .../uk/co/real_logic/sbe/PrimitiveValue.java | 27 +++++++++---------- .../generation/java/JavaGeneratorTest.java | 22 ++++++++------- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/build.gradle b/build.gradle index 6abfa0d2b4..9f20c3caed 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ def toolchainLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } -def checkstyleVersion = '8.39' +def checkstyleVersion = '8.45.1' def hamcrestVersion = '2.2' def mockitoVersion = '3.11.2' def junitVersion = '5.7.2' diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index b46c9babb9..e987de53b9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -98,7 +98,7 @@ public enum Representation private final Representation representation; private final long longValue; private final double doubleValue; - private final byte[] byteArrayValue; + private final byte[] bytesValue; private final String characterEncoding; private final int size; private final byte[] byteArrayValueForLong = new byte[1]; @@ -114,7 +114,7 @@ public PrimitiveValue(final long value, final int size) representation = Representation.LONG; longValue = value; doubleValue = 0.0; - byteArrayValue = null; + bytesValue = null; characterEncoding = null; this.size = size; } @@ -130,7 +130,7 @@ public PrimitiveValue(final byte value, final String characterEncoding) representation = Representation.LONG; longValue = value; doubleValue = 0.0; - byteArrayValue = null; + bytesValue = null; this.characterEncoding = characterEncoding; this.size = 1; } @@ -146,7 +146,7 @@ public PrimitiveValue(final double value, final int size) representation = Representation.DOUBLE; longValue = 0; doubleValue = value; - byteArrayValue = null; + bytesValue = null; characterEncoding = null; this.size = size; } @@ -163,7 +163,7 @@ public PrimitiveValue(final byte[] value, final String characterEncoding, final representation = Representation.BYTE_ARRAY; longValue = 0; doubleValue = 0.0; - byteArrayValue = value; + bytesValue = value; this.characterEncoding = characterEncoding; this.size = size; } @@ -299,7 +299,7 @@ public long longValue() if (representation != Representation.LONG) { throw new IllegalStateException( - "Not a long representation: representation=" + representation + " value=" + toString()); + "Not a long representation: representation=" + representation + " value=" + this); } return longValue; @@ -316,7 +316,7 @@ public double doubleValue() if (representation != Representation.DOUBLE) { throw new IllegalStateException( - "Not a double representation: representation=" + representation + " value=" + toString()); + "Not a double representation: representation=" + representation + " value=" + this); } return doubleValue; @@ -333,10 +333,10 @@ public byte[] byteArrayValue() if (representation != Representation.BYTE_ARRAY) { throw new IllegalStateException( - "Not a byte[] representation: representation=" + representation + " value=" + toString()); + "Not a byte[] representation: representation=" + representation + " value=" + this); } - return byteArrayValue; + return bytesValue; } /** @@ -350,7 +350,7 @@ public byte[] byteArrayValue(final PrimitiveType type) { if (representation == Representation.BYTE_ARRAY) { - return byteArrayValue; + return bytesValue; } else if (representation == Representation.LONG && size == 1 && type == PrimitiveType.CHAR) { @@ -400,8 +400,7 @@ else if (Representation.BYTE_ARRAY == representation) { try { - return null == characterEncoding ? - new String(byteArrayValue) : new String(byteArrayValue, characterEncoding); + return null == characterEncoding ? new String(bytesValue) : new String(bytesValue, characterEncoding); } catch (final UnsupportedEncodingException ex) { @@ -437,7 +436,7 @@ public boolean equals(final Object value) return doubleToLongBits(doubleValue) == doubleToLongBits(rhs.doubleValue); case BYTE_ARRAY: - return Arrays.equals(byteArrayValue, rhs.byteArrayValue); + return Arrays.equals(bytesValue, rhs.bytesValue); } } } @@ -464,7 +463,7 @@ public int hashCode() break; case BYTE_ARRAY: - return Arrays.hashCode(byteArrayValue); + return Arrays.hashCode(bytesValue); default: throw new IllegalStateException("Unrecognised representation: " + representation); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index e5101effd6..5ffc034cd8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -497,29 +497,33 @@ private static Object wrap( @Test public void shouldValidateMissingMutableBufferClass() { - assertThrows(IllegalArgumentException.class, () -> - new JavaGenerator(ir, "dasdsads", BUFFER_NAME, false, false, false, outputManager)); + assertThrows( + IllegalArgumentException.class, + () -> new JavaGenerator(ir, "dasdsads", BUFFER_NAME, false, false, false, outputManager)); } @Test public void shouldValidateNotImplementedMutableBufferClass() { - assertThrows(IllegalArgumentException.class, () -> - new JavaGenerator(ir, "java.nio.ByteBuffer", BUFFER_NAME, false, false, false, outputManager)); + assertThrows( + IllegalArgumentException.class, + () -> new JavaGenerator(ir, "java.nio.ByteBuffer", BUFFER_NAME, false, false, false, outputManager)); } @Test public void shouldValidateMissingReadOnlyBufferClass() { - assertThrows(IllegalArgumentException.class, () -> - new JavaGenerator(ir, BUFFER_NAME, "dasdsads", false, false, false, outputManager)); + assertThrows( + IllegalArgumentException.class, + () -> new JavaGenerator(ir, BUFFER_NAME, "dasdsads", false, false, false, outputManager)); } @Test public void shouldValidateNotImplementedReadOnlyBufferClass() { - assertThrows(IllegalArgumentException.class, () -> - new JavaGenerator(ir, BUFFER_NAME, "java.nio.ByteBuffer", false, false, false, outputManager)); + assertThrows( + IllegalArgumentException.class, + () -> new JavaGenerator(ir, BUFFER_NAME, "java.nio.ByteBuffer", false, false, false, outputManager)); } private Class compileCarEncoder() throws Exception @@ -570,7 +574,7 @@ private Class compile(final String fqClassName) throws Exception { final Map sources = outputManager.getSources(); final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); - if (aClass == null) + if (null == aClass) { System.out.println(sources); } From a2a067f32f57048aa1b7781b7bf6d3cb08a1659b Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Wed, 18 Aug 2021 21:16:30 +1200 Subject: [PATCH 0767/1594] Implementation of sbeSkip and sbeDecodedLength for the Java Generator. (#865) * [Java] Partial implementation of sbeSkip. * [Java] Complete implementation of sbeSkip and sbeDecodedLength. Pull out common test utility methods. * [Java] Regenerate IR codecs. --- .../sbe/generation/java/JavaGenerator.java | 71 ++++++++++ .../sbe/ir/generated/FrameCodecDecoder.java | 18 +++ .../sbe/ir/generated/TokenCodecDecoder.java | 26 ++++ .../generation/java/CarDecodeTestUtil.java | 126 ++++++++++++++++++ .../sbe/generation/java/RewindTest.java | 111 +-------------- .../java/SkipAndDecodedLengthTest.java | 67 ++++++++++ 6 files changed, 313 insertions(+), 106 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index c7f4b9b517..2c5852b15f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -31,6 +31,8 @@ import java.util.function.Function; import static uk.co.real_logic.sbe.SbeTool.JAVA_INTERFACE_PACKAGE; +import static uk.co.real_logic.sbe.generation.cpp.CppUtil.formatClassName; +import static uk.co.real_logic.sbe.generation.cpp.CppUtil.formatPropertyName; import static uk.co.real_logic.sbe.generation.java.JavaGenerator.CodecType.DECODER; import static uk.co.real_logic.sbe.generation.java.JavaGenerator.CodecType.ENCODER; import static uk.co.real_logic.sbe.generation.java.JavaUtil.*; @@ -233,6 +235,7 @@ private void generateDecoder( generateDecoderVarData(sb, varData, BASE_INDENT); generateDecoderDisplay(sb, msgToken.name(), fields, groups, varData); + generateMessageLength(sb, className, true, groups, varData, BASE_INDENT); out.append(sb); out.append("}\n"); @@ -284,6 +287,7 @@ private void generateDecoderGroups( generateDecoderVarData(sb, varData, indent + INDENT); appendGroupInstanceDecoderDisplay(sb, fields, groups, varData, indent + INDENT); + generateMessageLength(sb, groupName, false, groups, varData, indent + INDENT); sb.append(indent).append(" }\n"); } @@ -2574,6 +2578,15 @@ private CharSequence generateDecoderFlyweightCode(final String className, final " public " + className + " sbeRewind()\n" + " {\n" + " return wrap(buffer, initialOffset, actingBlockLength, actingVersion);\n" + + " }\n\n" + + + " public int sbeDecodedLength()\n" + + " {\n" + + " final int currentLimit = limit();\n" + + " sbeSkip();\n" + + " final int decodedLength = encodedLength();\n" + + " limit(currentLimit);\n" + + " return decodedLength;\n" + " }\n\n"; return generateFlyweightCode(DECODER, className, token, methods, readOnlyBuffer); @@ -3650,6 +3663,64 @@ private void appendMessageToString(final StringBuilder sb, final String decoderN append(sb, INDENT, "}"); } + private void generateMessageLength( + final StringBuilder sb, + final String className, + final boolean isParent, + final List groups, + final List varData, + final String baseIndent) + { + final String methodIndent = baseIndent + INDENT; + final String bodyIndent = methodIndent + INDENT; + append(sb, methodIndent, ""); + append(sb, methodIndent, "public " + className + " sbeSkip()"); + append(sb, methodIndent, "{"); + if (isParent) + { + append(sb, bodyIndent, "sbeRewind();"); + } + for (int i = 0, size = groups.size(); i < size; i++) + { + final Token groupToken = groups.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + final String groupName = formatPropertyName(groupToken.name()); + final String groupDecoderName = decoderName(groupToken.name()); + + append(sb, bodyIndent, groupDecoderName + " " + groupName + " = " + groupName + "();"); + append(sb, bodyIndent, "if (" + groupName + ".count() > 0)"); + append(sb, bodyIndent, "{"); + append(sb, bodyIndent, " while (" + groupName + ".hasNext())"); + append(sb, bodyIndent, " {"); + append(sb, bodyIndent, " " + groupName + ".next();"); + append(sb, bodyIndent, " " + groupName + ".sbeSkip();"); + append(sb, bodyIndent, " }"); + append(sb, bodyIndent, "}"); + i = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); + } + + for (int i = 0, size = varData.size(); i < size;) + { + final Token varDataToken = varData.get(i); + if (varDataToken.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); + } + + final String varDataName = formatPropertyName(varDataToken.name()); + append(sb, bodyIndent, "skip" + Generators.toUpperFirstChar(varDataName) + "();"); + + i += varDataToken.componentTokenCount(); + } + + append(sb, bodyIndent, "return this;"); + append(sb, methodIndent, "}"); + } + private static String validateBufferImplementation( final String fullyQualifiedBufferImplementation, final Class bufferClass) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index efb7c33192..ce7cd2a13c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -109,6 +109,15 @@ public FrameCodecDecoder sbeRewind() return wrap(buffer, initialOffset, actingBlockLength, actingVersion); } + public int sbeDecodedLength() + { + final int currentLimit = limit(); + sbeSkip(); + final int decodedLength = encodedLength(); + limit(currentLimit); + return decodedLength; + } + public int encodedLength() { return limit - offset; @@ -664,4 +673,13 @@ public StringBuilder appendTo(final StringBuilder builder) return builder; } + + public FrameCodecDecoder sbeSkip() + { + sbeRewind(); + skipPackageName(); + skipNamespaceName(); + skipSemanticVersion(); + return this; + } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 98a58e85d4..bc1953b583 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -109,6 +109,15 @@ public TokenCodecDecoder sbeRewind() return wrap(buffer, initialOffset, actingBlockLength, actingVersion); } + public int sbeDecodedLength() + { + final int currentLimit = limit(); + sbeSkip(); + final int decodedLength = encodedLength(); + limit(currentLimit); + return decodedLength; + } + public int encodedLength() { return limit - offset; @@ -1890,4 +1899,21 @@ public StringBuilder appendTo(final StringBuilder builder) return builder; } + + public TokenCodecDecoder sbeSkip() + { + sbeRewind(); + skipName(); + skipConstValue(); + skipMinValue(); + skipMaxValue(); + skipNullValue(); + skipCharacterEncoding(); + skipEpoch(); + skipTimeUnit(); + skipSemanticType(); + skipDescription(); + skipReferencedName(); + return this; + } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java new file mode 100644 index 0000000000..87dd7279cc --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java @@ -0,0 +1,126 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import baseline.CarDecoder; +import baseline.EngineDecoder; +import baseline.OptionalExtrasDecoder; + +import java.util.ArrayList; + +public class CarDecodeTestUtil +{ + static ArrayList getValues(final CarDecoder carDecoder) + { + final ArrayList values = new ArrayList<>(); + + values.add(carDecoder.serialNumber()); + values.add(carDecoder.modelYear()); + values.add(carDecoder.available()); + values.add(carDecoder.code()); + values.add(CarDecoder.someNumbersLength()); + for (int i = 0, n = CarDecoder.someNumbersLength(); i < n; i++) + { + values.add(carDecoder.someNumbers(i)); + } + values.add(carDecoder.vehicleCode()); + final OptionalExtrasDecoder extras = carDecoder.extras(); + values.add(extras.sunRoof()); + values.add(extras.sportsPack()); + values.add(extras.cruiseControl()); + final EngineDecoder engine = carDecoder.engine(); + values.add(engine.capacity()); + values.add(engine.numCylinders()); + values.add(engine.maxRpm()); + values.add(engine.manufacturerCode()); + values.add(engine.fuel()); + final CarDecoder.FuelFiguresDecoder fuelFigures = carDecoder.fuelFigures(); + while (fuelFigures.hasNext()) + { + fuelFigures.next(); + values.add(fuelFigures.speed()); + values.add(fuelFigures.mpg()); + } + final CarDecoder.PerformanceFiguresDecoder performanceFigures = carDecoder.performanceFigures(); + while (performanceFigures.hasNext()) + { + performanceFigures.next(); + values.add(performanceFigures.octaneRating()); + final CarDecoder.PerformanceFiguresDecoder.AccelerationDecoder acceleration = + performanceFigures.acceleration(); + while (acceleration.hasNext()) + { + acceleration.next(); + values.add(acceleration.mph()); + values.add(acceleration.seconds()); + } + } + values.add(carDecoder.manufacturer()); + values.add(carDecoder.model()); + values.add(carDecoder.activationCode()); + return values; + } + + static ArrayList getPartialValues(final CarDecoder carDecoder) + { + final ArrayList values = new ArrayList<>(); + + values.add(carDecoder.serialNumber()); + values.add(carDecoder.modelYear()); + values.add(carDecoder.available()); + values.add(carDecoder.code()); + values.add(CarDecoder.someNumbersLength()); + for (int i = 0, n = CarDecoder.someNumbersLength(); i < n; i++) + { + values.add(carDecoder.someNumbers(i)); + } + values.add(carDecoder.vehicleCode()); + final OptionalExtrasDecoder extras = carDecoder.extras(); + values.add(extras.sunRoof()); + values.add(extras.sportsPack()); + values.add(extras.cruiseControl()); + final EngineDecoder engine = carDecoder.engine(); + values.add(engine.capacity()); + values.add(engine.numCylinders()); + values.add(engine.maxRpm()); + values.add(engine.manufacturerCode()); + values.add(engine.fuel()); + final CarDecoder.FuelFiguresDecoder fuelFigures = carDecoder.fuelFigures(); + while (fuelFigures.hasNext()) + { + fuelFigures.next(); + values.add(fuelFigures.speed()); + values.add(fuelFigures.mpg()); + } + final CarDecoder.PerformanceFiguresDecoder performanceFigures = carDecoder.performanceFigures(); + + // Stop decoding part way through the message. + if (performanceFigures.hasNext()) + { + performanceFigures.next(); + values.add(performanceFigures.octaneRating()); + final CarDecoder.PerformanceFiguresDecoder.AccelerationDecoder acceleration = + performanceFigures.acceleration(); + if (acceleration.hasNext()) + { + acceleration.next(); + values.add(acceleration.mph()); + } + } + + return values; + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java index 487dd441f1..9385da574c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java @@ -16,9 +16,7 @@ package uk.co.real_logic.sbe.generation.java; import baseline.CarDecoder; -import baseline.EngineDecoder; import baseline.MessageHeaderDecoder; -import baseline.OptionalExtrasDecoder; import org.agrona.concurrent.UnsafeBuffer; import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.EncodedCarTestBase; @@ -43,120 +41,21 @@ void shouldRewindAfterReadingFullMessage() final CarDecoder carDecoder = new CarDecoder(); carDecoder.wrapAndApplyHeader(new UnsafeBuffer(encodedMsgBuffer), 0, header); - final ArrayList passOne = getValues(carDecoder); + final ArrayList passOne = CarDecodeTestUtil.getValues(carDecoder); carDecoder.sbeRewind(); - final ArrayList passTwo = getValues(carDecoder); + final ArrayList passTwo = CarDecodeTestUtil.getValues(carDecoder); assertEquals(passOne, passTwo); carDecoder.sbeRewind(); - final ArrayList partialPassOne = getPartialValues(carDecoder); + final ArrayList partialPassOne = CarDecodeTestUtil.getPartialValues(carDecoder); carDecoder.sbeRewind(); - final ArrayList partialPassTwo = getPartialValues(carDecoder); + final ArrayList partialPassTwo = CarDecodeTestUtil.getPartialValues(carDecoder); assertNotEquals(passOne, partialPassOne); assertEquals(partialPassOne, partialPassTwo); carDecoder.sbeRewind(); - final ArrayList passThree = getValues(carDecoder); + final ArrayList passThree = CarDecodeTestUtil.getValues(carDecoder); assertEquals(passOne, passThree); } - private ArrayList getValues(final CarDecoder carDecoder) - { - final ArrayList values = new ArrayList<>(); - - values.add(carDecoder.serialNumber()); - values.add(carDecoder.modelYear()); - values.add(carDecoder.available()); - values.add(carDecoder.code()); - values.add(CarDecoder.someNumbersLength()); - for (int i = 0, n = CarDecoder.someNumbersLength(); i < n; i++) - { - values.add(carDecoder.someNumbers(i)); - } - values.add(carDecoder.vehicleCode()); - final OptionalExtrasDecoder extras = carDecoder.extras(); - values.add(extras.sunRoof()); - values.add(extras.sportsPack()); - values.add(extras.cruiseControl()); - final EngineDecoder engine = carDecoder.engine(); - values.add(engine.capacity()); - values.add(engine.numCylinders()); - values.add(engine.maxRpm()); - values.add(engine.manufacturerCode()); - values.add(engine.fuel()); - final CarDecoder.FuelFiguresDecoder fuelFigures = carDecoder.fuelFigures(); - while (fuelFigures.hasNext()) - { - fuelFigures.next(); - values.add(fuelFigures.speed()); - values.add(fuelFigures.mpg()); - } - final CarDecoder.PerformanceFiguresDecoder performanceFigures = carDecoder.performanceFigures(); - while (performanceFigures.hasNext()) - { - performanceFigures.next(); - values.add(performanceFigures.octaneRating()); - final CarDecoder.PerformanceFiguresDecoder.AccelerationDecoder acceleration = - performanceFigures.acceleration(); - while (acceleration.hasNext()) - { - acceleration.next(); - values.add(acceleration.mph()); - values.add(acceleration.seconds()); - } - } - values.add(carDecoder.manufacturer()); - values.add(carDecoder.model()); - return values; - } - - private ArrayList getPartialValues(final CarDecoder carDecoder) - { - final ArrayList values = new ArrayList<>(); - - values.add(carDecoder.serialNumber()); - values.add(carDecoder.modelYear()); - values.add(carDecoder.available()); - values.add(carDecoder.code()); - values.add(CarDecoder.someNumbersLength()); - for (int i = 0, n = CarDecoder.someNumbersLength(); i < n; i++) - { - values.add(carDecoder.someNumbers(i)); - } - values.add(carDecoder.vehicleCode()); - final OptionalExtrasDecoder extras = carDecoder.extras(); - values.add(extras.sunRoof()); - values.add(extras.sportsPack()); - values.add(extras.cruiseControl()); - final EngineDecoder engine = carDecoder.engine(); - values.add(engine.capacity()); - values.add(engine.numCylinders()); - values.add(engine.maxRpm()); - values.add(engine.manufacturerCode()); - values.add(engine.fuel()); - final CarDecoder.FuelFiguresDecoder fuelFigures = carDecoder.fuelFigures(); - while (fuelFigures.hasNext()) - { - fuelFigures.next(); - values.add(fuelFigures.speed()); - values.add(fuelFigures.mpg()); - } - final CarDecoder.PerformanceFiguresDecoder performanceFigures = carDecoder.performanceFigures(); - - // Stop decoding part way through the message. - if (performanceFigures.hasNext()) - { - performanceFigures.next(); - values.add(performanceFigures.octaneRating()); - final CarDecoder.PerformanceFiguresDecoder.AccelerationDecoder acceleration = - performanceFigures.acceleration(); - if (acceleration.hasNext()) - { - acceleration.next(); - values.add(acceleration.mph()); - } - } - - return values; - } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java new file mode 100644 index 0000000000..8f69440b8c --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import baseline.CarDecoder; +import baseline.MessageHeaderDecoder; +import org.agrona.concurrent.UnsafeBuffer; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.EncodedCarTestBase; + +import java.nio.ByteBuffer; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class SkipAndDecodedLengthTest extends EncodedCarTestBase +{ + private static final int MSG_BUFFER_CAPACITY = 4 * 1024; + + @Test + void shouldRewindAfterReadingFullMessage() + { + final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); + encodeTestMessage(encodedMsgBuffer); + + final int encodedLength = CAR.encodedLength(); + + final MessageHeaderDecoder header = new MessageHeaderDecoder(); + final CarDecoder carDecoder = new CarDecoder(); + carDecoder.wrapAndApplyHeader(new UnsafeBuffer(encodedMsgBuffer), 0, header); + final int decodedLengthNoRead = carDecoder.sbeDecodedLength(); + + final int initialLimit = carDecoder.limit(); + CarDecodeTestUtil.getValues(carDecoder); + final int readLimit = carDecoder.limit(); + + carDecoder.sbeRewind(); + final int rewindLimit = carDecoder.limit(); + carDecoder.sbeSkip(); + + final int skipLimit = carDecoder.limit(); + final int decodedLengthFullSkip = carDecoder.sbeDecodedLength(); + carDecoder.sbeRewind(); + final int decodedLengthAfterRewind = carDecoder.sbeDecodedLength(); + CarDecodeTestUtil.getPartialValues(carDecoder); + final int decodedLengthPartialRead = carDecoder.sbeDecodedLength(); + + assertEquals(initialLimit, rewindLimit); + assertEquals(readLimit, skipLimit); + assertEquals(encodedLength, decodedLengthNoRead); + assertEquals(encodedLength, decodedLengthFullSkip); + assertEquals(encodedLength, decodedLengthAfterRewind); + assertEquals(encodedLength, decodedLengthPartialRead); + } +} From afb6889f6b5c6d0a9fd7ac848b6e67a6dfa61527 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 18 Aug 2021 10:24:12 +0100 Subject: [PATCH 0768/1594] [Java] Formatting. --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 6 +++++- .../co/real_logic/sbe/ir/generated/FrameCodecDecoder.java | 2 ++ .../co/real_logic/sbe/ir/generated/TokenCodecDecoder.java | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 2c5852b15f..f9dd57a178 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2585,7 +2585,7 @@ private CharSequence generateDecoderFlyweightCode(final String className, final " final int currentLimit = limit();\n" + " sbeSkip();\n" + " final int decodedLength = encodedLength();\n" + - " limit(currentLimit);\n" + + " limit(currentLimit);\n\n" + " return decodedLength;\n" + " }\n\n"; @@ -3673,13 +3673,16 @@ private void generateMessageLength( { final String methodIndent = baseIndent + INDENT; final String bodyIndent = methodIndent + INDENT; + append(sb, methodIndent, ""); append(sb, methodIndent, "public " + className + " sbeSkip()"); append(sb, methodIndent, "{"); + if (isParent) { append(sb, bodyIndent, "sbeRewind();"); } + for (int i = 0, size = groups.size(); i < size; i++) { final Token groupToken = groups.get(i); @@ -3717,6 +3720,7 @@ private void generateMessageLength( i += varDataToken.componentTokenCount(); } + sb.append('\n'); append(sb, bodyIndent, "return this;"); append(sb, methodIndent, "}"); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index ce7cd2a13c..2c0f88f97a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -115,6 +115,7 @@ public int sbeDecodedLength() sbeSkip(); final int decodedLength = encodedLength(); limit(currentLimit); + return decodedLength; } @@ -680,6 +681,7 @@ public FrameCodecDecoder sbeSkip() skipPackageName(); skipNamespaceName(); skipSemanticVersion(); + return this; } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index bc1953b583..9e8b467ae5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -115,6 +115,7 @@ public int sbeDecodedLength() sbeSkip(); final int decodedLength = encodedLength(); limit(currentLimit); + return decodedLength; } @@ -1914,6 +1915,7 @@ public TokenCodecDecoder sbeSkip() skipSemanticType(); skipDescription(); skipReferencedName(); + return this; } } From 297c9be59624db8b2b37a5ccfc68bb1ec966553e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Aug 2021 15:44:16 +0200 Subject: [PATCH 0769/1594] [Java] Upgrade to Mockito 3.12.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9f20c3caed..280b7f6930 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.45.1' def hamcrestVersion = '2.2' -def mockitoVersion = '3.11.2' +def mockitoVersion = '3.12.1' def junitVersion = '5.7.2' def jmhVersion = '1.33' def agronaVersion = '1.12.0' From b03ed05b5e18c3bd4bd10e2e0d93f029b0180fb2 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Aug 2021 15:53:50 +0200 Subject: [PATCH 0770/1594] [Gradle] Configure test logging for all log levels and capture all relevant test events. --- build.gradle | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 280b7f6930..84f2c65e5d 100644 --- a/build.gradle +++ b/build.gradle @@ -208,8 +208,12 @@ subprojects { useJUnitPlatform() testLogging { - showStandardStreams = true - exceptionFormat = 'full' + for (def level : LogLevel.values()) + { + def testLogging = get(level) + testLogging.exceptionFormat = 'full' + testLogging.events = ["FAILED", "STANDARD_OUT", "STANDARD_ERROR"] + } } } } From 05d9ea294f4e13d27a420a7e592b2a9955735c50 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Aug 2021 15:57:10 +0200 Subject: [PATCH 0771/1594] [Gradle] Explicitly assign JavaLauncher for tests. --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index 84f2c65e5d..146923542c 100644 --- a/build.gradle +++ b/build.gradle @@ -215,6 +215,8 @@ subprojects { testLogging.events = ["FAILED", "STANDARD_OUT", "STANDARD_ERROR"] } } + + javaLauncher.set(toolchainLauncher) } } From e6a8cc61983919f55016877e2dbb9a1978fe7df9 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:52:33 +0200 Subject: [PATCH 0772/1594] Revert "[Java] Upgrade to Mockito 3.12.1." This reverts commit 297c9be59624db8b2b37a5ccfc68bb1ec966553e. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 146923542c..54ff5c9dff 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.45.1' def hamcrestVersion = '2.2' -def mockitoVersion = '3.12.1' +def mockitoVersion = '3.11.2' def junitVersion = '5.7.2' def jmhVersion = '1.33' def agronaVersion = '1.12.0' From 8110eab5ab8a03076d5fcdc195c315991ad0d08e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 25 Aug 2021 10:54:15 +0200 Subject: [PATCH 0773/1594] [Java] Upgrade to Mockito 3.12.3. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 54ff5c9dff..5997c6076e 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.45.1' def hamcrestVersion = '2.2' -def mockitoVersion = '3.11.2' +def mockitoVersion = '3.12.3' def junitVersion = '5.7.2' def jmhVersion = '1.33' def agronaVersion = '1.12.0' From 6c412321afb43c1c358d5da45df22835597f15b5 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 25 Aug 2021 16:15:06 +0200 Subject: [PATCH 0774/1594] [CI] Add GCC 11 to the build matrix. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ca3e3b8c1..2c5fc93522 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -103,7 +103,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '6', '7', '8', '9', '10' ] + version: [ '6', '7', '8', '9', '10', '11' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} From 632c5f4953f102852d4a6312b50f0072471735ee Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 27 Aug 2021 10:41:39 +0100 Subject: [PATCH 0775/1594] [Java] Upgrade to Mockito 3.12.4. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5997c6076e..62b1ab8a67 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.45.1' def hamcrestVersion = '2.2' -def mockitoVersion = '3.12.3' +def mockitoVersion = '3.12.4' def junitVersion = '5.7.2' def jmhVersion = '1.33' def agronaVersion = '1.12.0' From b58dacacd59d7b5dd88c1096221b18b7d6f6f665 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Fri, 27 Aug 2021 08:12:23 -0500 Subject: [PATCH 0776/1594] [Rust] fixed SubGroup's generateEncoder() and generateDecoder() --- .../real_logic/sbe/generation/rust/SubGroup.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index 8e10af00b1..2fc4098335 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -77,7 +77,7 @@ void generateEncoder( // define impl... indent(sb, level - 1, "impl<'a, P> %s

    where P: Encoder<'a> + Default {\n", name); - final int headerSize = blockLengthPrimitiveType.size() + numInGroupPrimitiveType.size(); + final int dimensionHeaderSize = tokens.get(index).encodedLength(); // define wrap... indent(sb, level, "#[inline]\n"); @@ -87,11 +87,11 @@ void generateEncoder( indent(sb, level + 1, "count: %s,\n", rustTypeName(numInGroupPrimitiveType)); indent(sb, level, ") -> Self {\n"); indent(sb, level + 1, "let initial_limit = parent.get_limit();\n"); - indent(sb, level + 1, "parent.set_limit(initial_limit + %d);\n", headerSize); - indent(sb, level + 1, "parent.get_buf_mut().put_%s_at(initial_limit, %d);\n", - rustTypeName(blockLengthPrimitiveType), this.groupToken.encodedLength()); + indent(sb, level + 1, "parent.set_limit(initial_limit + %d);\n", dimensionHeaderSize); + indent(sb, level + 1, "parent.get_buf_mut().put_%s_at(initial_limit, Self::block_length());\n", + rustTypeName(blockLengthPrimitiveType)); indent(sb, level + 1, "parent.get_buf_mut().put_%s_at(initial_limit + %d, count);\n", - rustTypeName(numInGroupPrimitiveType), blockLengthPrimitiveType.size()); + rustTypeName(numInGroupPrimitiveType), numInGroupToken.offset()); indent(sb, level + 1, "self.parent = Some(parent);\n"); indent(sb, level + 1, "self.count = count;\n"); @@ -168,6 +168,8 @@ void generateDecoder( // define impl... indent(sb, level - 1, "impl<'a, P> %s

    where P: Decoder<'a> + Default {\n", name); + final int dimensionHeaderSize = tokens.get(index).encodedLength(); + // define wrap... indent(sb, level, "pub fn wrap(\n"); indent(sb, level + 1, "mut self,\n"); @@ -178,9 +180,9 @@ void generateDecoder( indent(sb, level + 1, "let block_length = parent.get_buf().get_%s_at(initial_offset) as usize;\n", rustTypeName(blockLengthPrimitiveType)); indent(sb, level + 1, "let count = parent.get_buf().get_%s_at(initial_offset + %d);\n", - rustTypeName(numInGroupPrimitiveType), blockLengthPrimitiveType.size()); + rustTypeName(numInGroupPrimitiveType), numInGroupToken.offset()); indent(sb, level + 1, "parent.set_limit(initial_offset + %d);\n", - blockLengthPrimitiveType.size() + numInGroupPrimitiveType.size()); + dimensionHeaderSize); indent(sb, level + 1, "self.parent = Some(parent);\n"); indent(sb, level + 1, "self.block_length = block_length;\n"); From d175586e238c0747fde9381b5a68569a23290b39 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 14 Sep 2021 10:56:47 +0200 Subject: [PATCH 0777/1594] [Java] Upgrade to JUnit 5.8.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 62b1ab8a67..025ea2d5bc 100644 --- a/build.gradle +++ b/build.gradle @@ -45,7 +45,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.45.1' def hamcrestVersion = '2.2' def mockitoVersion = '3.12.4' -def junitVersion = '5.7.2' +def junitVersion = '5.8.0' def jmhVersion = '1.33' def agronaVersion = '1.12.0' def agronaVersionRange = '[1.12,1.13[' // allow any patch release of 1.12.x From 86e769267ed745c0f4d699864a134b144dfb0330 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 15 Sep 2021 22:28:27 +0200 Subject: [PATCH 0778/1594] [Java] Use JDK 17 GA. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c5fc93522..65cb945dc2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '11', '16', '17-ea' ] + java: [ '8', '11', '17' ] os: [ 'ubuntu-20.04', 'windows-latest' ] steps: - name: Checkout code From 74e367d89adf0821cc824b0ae64992c31c4555ff Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 15 Sep 2021 22:40:42 +0200 Subject: [PATCH 0779/1594] [Java] Fix JavaDoc URI for JDK 17 GA. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 025ea2d5bc..cc33f38cc6 100644 --- a/build.gradle +++ b/build.gradle @@ -190,7 +190,7 @@ subprojects { options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' options.links("https://www.javadoc.io/doc/org.agrona/agrona/${agronaVersion}/") - if (buildJavaVersion >= 17) { // early access JavaDoc location is different + if (buildJavaVersion >= 18) { // early access JavaDoc location is different options.links("https://download.java.net/java/early_access/jdk${buildJavaVersion}/docs/api/") } else if (buildJavaVersion >= 11) { From 1eccb89255ef05504cd093ed303890a0bf6c496d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 19 Sep 2021 16:13:11 +0100 Subject: [PATCH 0780/1594] [Doc] Add works with OpenJDK badge. --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 5e18d745cd..892ca8bf58 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ Simple Binary Encoding (SBE) ============================ + + + + [![Javadocs](https://www.javadoc.io/badge/uk.co.real-logic/sbe-tool.svg)](https://www.javadoc.io/doc/uk.co.real-logic/sbe-tool) [![GitHub](https://img.shields.io/github/license/real-logic/simple-binary-encoding.svg)](https://github.com/real-logic/simple-binary-encoding/blob/master/LICENSE) From 08b3c68b2ed4fad200581476e1430ccc1bb64fcf Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 20 Sep 2021 15:58:33 +0100 Subject: [PATCH 0781/1594] [Doc] Update link. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 892ca8bf58..d0ed2b72fd 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Simple Binary Encoding (SBE) ============================ - + From dbe5d92cf2094baec1066a28d8813fe2691d3ff5 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 22 Sep 2021 21:38:07 +0200 Subject: [PATCH 0782/1594] [Java] Upgrade to JUnit 5.8.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e3e54080d2..a0fcef9ed5 100644 --- a/build.gradle +++ b/build.gradle @@ -45,7 +45,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '8.45.1' def hamcrestVersion = '2.2' def mockitoVersion = '3.12.4' -def junitVersion = '5.8.0' +def junitVersion = '5.8.1' def jmhVersion = '1.33' def agronaVersion = '1.12.0' def agronaVersionRange = '[1.12,1.13[' // allow any patch release of 1.12.x From c756afc1a56a3d648be91fc2e4ee61dac77a430b Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 23 Sep 2021 09:46:47 +0200 Subject: [PATCH 0783/1594] [Java] Upgrade to Checkstyle 9.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a0fcef9ed5..079828e4e1 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ def toolchainLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } -def checkstyleVersion = '8.45.1' +def checkstyleVersion = '9.0' def hamcrestVersion = '2.2' def mockitoVersion = '3.12.4' def junitVersion = '5.8.1' From d19ca929d5cc1fb3f78247f030e41e9239f2dc76 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 5 Oct 2021 08:05:45 +0200 Subject: [PATCH 0784/1594] [Gradle] Upgrade to Shadow 7.1.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 079828e4e1..bbb7175da0 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ import java.security.MessageDigest plugins { id 'java-library' - id 'com.github.johnrengelman.shadow' version '7.0.0' apply false + id 'com.github.johnrengelman.shadow' version '7.1.0' apply false id "com.github.ben-manes.versions" version "0.39.0" } From 62d2def4ee81aca18374aac43d4c2a9c14968c99 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 5 Oct 2021 10:34:57 +0200 Subject: [PATCH 0785/1594] [CI] Add JDK 18-ea to the build matrix. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e188fa470b..b1ee7ed43e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '11', '17' ] + java: [ '8', '11', '17', '18-ea' ] os: [ 'ubuntu-20.04', 'windows-latest' ] steps: - name: Checkout code From c30fa955bf01f83fdf723f650503227fa4fd3a79 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 5 Oct 2021 19:12:36 +0100 Subject: [PATCH 0786/1594] [Java] Upgrade to Checkstyle 9.0.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bbb7175da0..a10e6f310a 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ def toolchainLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } -def checkstyleVersion = '9.0' +def checkstyleVersion = '9.0.1' def hamcrestVersion = '2.2' def mockitoVersion = '3.12.4' def junitVersion = '5.8.1' From 9df2a073f206e5bf7fdc7bc30d75c01ad9d912f4 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 7 Oct 2021 17:04:14 +0100 Subject: [PATCH 0787/1594] [Java]Upgrade to Mockito 4.0.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a10e6f310a..c2df950528 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.0.1' def hamcrestVersion = '2.2' -def mockitoVersion = '3.12.4' +def mockitoVersion = '4.0.0' def junitVersion = '5.8.1' def jmhVersion = '1.33' def agronaVersion = '1.12.0' From 5d1a8e255ce8ab8d6f20fd077706f9a9e2ec4092 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Fri, 8 Oct 2021 14:17:28 -0500 Subject: [PATCH 0788/1594] [Rust] fixed `needless_borrow` when generating primitive accessor (#871) Co-authored-by: Michael Ward --- .../java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 83690976e5..aab9f6a592 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -225,7 +225,7 @@ static void generateReadBuf(final Appendable writer, final ByteOrder byteOrder) indent(writer, 0, "\n"); indent(writer, 1, "#[inline]\n"); indent(writer, 1, "pub fn get_%1$s_at(&self, index: usize) -> %1$s {\n", primitiveType); - indent(writer, 2, "%s::from_%s_bytes(Self::get_bytes_at(&self.data, index))\n", primitiveType, endianness); + indent(writer, 2, "%s::from_%s_bytes(Self::get_bytes_at(self.data, index))\n", primitiveType, endianness); indent(writer, 1, "}\n"); } From 7a70ae5522cc8604fb05acfd39f5349b9a7a51a1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 14 Oct 2021 11:55:33 +0100 Subject: [PATCH 0789/1594] [Java] Upgrade to Gradle 7.2. --- build.gradle | 62 +++--- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 257 ++++++++++++++--------- 3 files changed, 187 insertions(+), 134 deletions(-) diff --git a/build.gradle b/build.gradle index c2df950528..2d1fcb6d27 100644 --- a/build.gradle +++ b/build.gradle @@ -406,7 +406,7 @@ project(':sbe-samples') { compileGeneratedJava.dependsOn 'generateCodecs' task generateCodecs(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': generatedDir, @@ -420,19 +420,19 @@ project(':sbe-samples') { } task runExampleUsingGeneratedStub(dependsOn: 'compileJava', type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub' + mainClass.set('uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub') classpath = sourceSets.main.runtimeClasspath systemProperties System.getProperties() } task runExampleUsingGeneratedStubExtension(dependsOn: 'compileJava', type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension' + mainClass.set('uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension') classpath = sourceSets.main.runtimeClasspath systemProperties System.getProperties() } task runOtfExample(dependsOn: 'compileJava', type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.examples.OtfExample' + mainClass.set('uk.co.real_logic.sbe.examples.OtfExample') classpath = sourceSets.main.runtimeClasspath workingDir = 'src/main/resources' } @@ -516,7 +516,7 @@ project(':sbe-benchmarks') { compileJava.dependsOn 'compileGeneratedJava' task generateCodecs(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'build/generated-src', @@ -542,7 +542,7 @@ project(':sbe-benchmarks') { * Rust codec targets used for testing */ task generateRustExamples(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'generated/rust', @@ -557,7 +557,7 @@ task generateRustExamples(type: JavaExec) { } task generateRustTestCodecs(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'generated/rust', @@ -570,7 +570,7 @@ task generateRustTestCodecs(type: JavaExec) { } task generateCarExampleDataFile(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub' + mainClass.set('uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub') classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath systemProperties('sbe.encoding.filename': 'rust/car_example_baseline_data.sbe') args = [] @@ -578,7 +578,7 @@ task generateCarExampleDataFile(type: JavaExec) { } task generateCarExampleExtensionDataFile(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension' + mainClass.set('uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension') classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath systemProperties('sbe.encoding.filename': 'rust/car_example_extension_data.sbe') args = [] @@ -608,7 +608,7 @@ task runRustTests(type: Exec) { * *) Some examples need to fiddle with WorkingDir to deal with XInclude */ task generateGolangCodecTestComposite(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src', @@ -617,7 +617,7 @@ task generateGolangCodecTestComposite(type: JavaExec) { } task generateGolangCodecTestBasic(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src/basic', @@ -626,7 +626,7 @@ task generateGolangCodecTestBasic(type: JavaExec) { } task generateGolangCodecTestGroup(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src/group', @@ -635,7 +635,7 @@ task generateGolangCodecTestGroup(type: JavaExec) { } task generateGolangCodecTestVarData(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src/vardata', @@ -644,7 +644,7 @@ task generateGolangCodecTestVarData(type: JavaExec) { } task generateGolangCodecsWithXIncludes(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src', @@ -656,7 +656,7 @@ task generateGolangCodecsWithXIncludes(type: JavaExec) { } task generateGolangCodecsWithXSD(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/src', @@ -696,7 +696,7 @@ task generateGolangCodecs { * multiple targets as XInclude forces us to change working dir */ task generateCSharpCodecsWithXIncludes(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'csharp/sbe-generated', @@ -708,7 +708,7 @@ task generateCSharpCodecsWithXIncludes(type: JavaExec) { } task generateCSharpCodecsTests(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'csharp/sbe-generated', @@ -731,7 +731,7 @@ task generateCSharpCodecs { } task generateJavaIrCodecs(type: JavaExec, dependsOn: 'computeOriginalIrHash') { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/java', @@ -741,7 +741,7 @@ task generateJavaIrCodecs(type: JavaExec, dependsOn: 'computeOriginalIrHash') { } task generateCppIrCodecs(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/cpp', @@ -751,7 +751,7 @@ task generateCppIrCodecs(type: JavaExec) { } task generateGolangIrCodecs(type: JavaExec) { - mainClass = 'uk.co.real_logic.sbe.SbeTool' + mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/golang', @@ -820,15 +820,15 @@ tasks.named('dependencyUpdates').configure { tasks.findByName('build').dependsOn verifyJavaIrCodecsInSync wrapper { - gradleVersion = '7.1.1' + gradleVersion = '7.2' distributionType = 'ALL' } class ChecksumTask extends DefaultTask { - private static final MessageDigest SHA_256 = MessageDigest.getInstance("SHA-256"); - private static final byte CR = (byte) ('\r' as char) - private static final byte LF = (byte) ('\n' as char) + private static final MessageDigest SHA_256 = MessageDigest.getInstance("SHA-256") + private static final byte CR = (byte)('\r' as char) + private static final byte LF = (byte)('\n' as char) @InputDirectory File inputDirectory @@ -837,14 +837,15 @@ class ChecksumTask extends DefaultTask File outputFile @TaskAction - def checksum() { + def checksum() + { SHA_256.reset() - final File[] files = inputDirectory.listFiles(); + final File[] files = inputDirectory.listFiles() for (final File f : files) { final byte[] raw = Files.readAllBytes(f.toPath()) - final byte[] normalized = normalizeEOL(raw); + final byte[] normalized = normaliseEol(raw) SHA_256.update(normalized) } @@ -858,18 +859,21 @@ class ChecksumTask extends DefaultTask StandardOpenOption.TRUNCATE_EXISTING) } - private byte[] normalizeEOL(final byte[] raw) + private static byte[] normaliseEol(final byte[] raw) { final byte[] result = new byte[raw.length] int i = 0 + for (int j = 0, size = raw.length; j < size; j++) { if (CR == raw[j] && (j == size - 1 || LF == raw[j + 1])) { continue; } + result[i++] = raw[j] } - return raw.length == i ? result : Arrays.copyOf(result, i); + + return raw.length == i ? result : Arrays.copyOf(result, i) } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index af7be50b10..a0f7639f7d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 744e882ed5..c53aefaa5f 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MSYS* | MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" From 7f4af10bce63da68b4aad4980b222df0edc935d5 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 20 Oct 2021 15:55:51 +0200 Subject: [PATCH 0790/1594] [CI] Add Clang 13.0 to the build matrix. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b1ee7ed43e..6b3b0a7901 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -138,7 +138,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '6.0', '7', '8', '9', '10', '11', '12' ] + version: [ '6.0', '7', '8', '9', '10', '11', '12', '13' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} From 3d9f086be205d1c5e1120d9fc17fa163b62321ee Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 6 Nov 2021 12:36:25 +0000 Subject: [PATCH 0791/1594] [Java] Style. --- build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 2d1fcb6d27..543e398d9a 100644 --- a/build.gradle +++ b/build.gradle @@ -841,8 +841,7 @@ class ChecksumTask extends DefaultTask { SHA_256.reset() - final File[] files = inputDirectory.listFiles() - for (final File f : files) + for (final File f : inputDirectory.listFiles()) { final byte[] raw = Files.readAllBytes(f.toPath()) final byte[] normalized = normaliseEol(raw) From 9b9786c5500a560d0d395e3686ea6e7ead95e2dd Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 6 Nov 2021 14:26:12 +0000 Subject: [PATCH 0792/1594] [C++] Only generate the macros and includes required for enum types. --- .../sbe/generation/cpp/CppGenerator.java | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 219beb8377..913b75f426 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -778,7 +778,7 @@ private void generateEnum(final List tokens) throws IOException try (Writer out = outputManager.createOutput(enumName)) { - out.append(generateFileHeader(ir.namespaces(), enumName, null)); + out.append(generateEnumFileHeader(ir.namespaces(), enumName)); out.append(generateEnumDeclaration(enumName)); out.append(generateEnumValues(tokens.subList(1, tokens.size() - 1), enumToken)); @@ -1168,6 +1168,47 @@ private static CharSequence generateFileHeader( return sb; } + private static CharSequence generateEnumFileHeader(final CharSequence[] namespaces, final String className) + { + final StringBuilder sb = new StringBuilder(); + + sb.append("/* Generated SBE (Simple Binary Encoding) message codec */\n"); + + sb.append(String.format( + "#ifndef _%1$s_%2$s_H_\n" + + "#define _%1$s_%2$s_H_\n\n" + + + "#if !defined(__STDC_LIMIT_MACROS)\n" + + "# define __STDC_LIMIT_MACROS 1\n" + + "#endif\n\n" + + + "#include \n" + + "#include \n" + + "#include \n" + + "#include \n" + + "#include \n" + + "#include \n" + + "#include \n" + + "\n" + + + "#define SBE_NULLVALUE_INT8 (std::numeric_limits::min)()\n" + + "#define SBE_NULLVALUE_INT16 (std::numeric_limits::min)()\n" + + "#define SBE_NULLVALUE_INT32 (std::numeric_limits::min)()\n" + + "#define SBE_NULLVALUE_INT64 (std::numeric_limits::min)()\n" + + "#define SBE_NULLVALUE_UINT8 (std::numeric_limits::max)()\n" + + "#define SBE_NULLVALUE_UINT16 (std::numeric_limits::max)()\n" + + "#define SBE_NULLVALUE_UINT32 (std::numeric_limits::max)()\n" + + "#define SBE_NULLVALUE_UINT64 (std::numeric_limits::max)()\n", + String.join("_", namespaces).toUpperCase(), + className.toUpperCase())); + + sb.append("\nnamespace "); + sb.append(String.join(" {\nnamespace ", namespaces)); + sb.append(" {\n\n"); + + return sb; + } + private static CharSequence generateClassDeclaration(final String className) { return From 2697b8eebf3b64317a9c37cf6c2536a04fb6194b Mon Sep 17 00:00:00 2001 From: ratcash Date: Thu, 11 Nov 2021 12:21:59 +0100 Subject: [PATCH 0793/1594] Mark classes of deprecated messages with @Deprecated. (#876) * Mark classes of deprecated messages with @Deprecated * Revert breaking changes * Create a dedicated xml for java test --- .../sbe/generation/java/JavaGenerator.java | 4 ++++ .../generation/java/JavaGeneratorTest.java | 23 +++++++++++++++++++ .../resources/deprecated-msg-test-schema.xml | 20 ++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 sbe-tool/src/test/resources/deprecated-msg-test-schema.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index f9dd57a178..a96f018116 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1657,6 +1657,10 @@ private static CharSequence generateDeclaration( final StringBuilder sb = new StringBuilder(); generateTypeJavadoc(sb, BASE_INDENT, typeToken); + if (typeToken.deprecated() > 0) + { + sb.append("@Deprecated\n"); + } sb.append("@SuppressWarnings(\"all\")\n") .append("public final class ").append(className).append(implementsString).append('\n') .append("{\n"); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 5ffc034cd8..3a9064b810 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -458,6 +458,29 @@ public void shouldGenerateRepeatingGroupCountLimits() throws Exception assertEquals(65534, maxValue.invoke(null)); } + @Test + public void shouldMarkDeprecatedClasses() throws Exception + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(Tests.getLocalResource("deprecated-msg-test-schema.xml"), options); + final IrGenerator irg = new IrGenerator(); + ir = irg.generate(schema); + + outputManager.clear(); + outputManager.setPackageName(ir.applicableNamespace()); + + generator().generate(); + final String encoderFqcn = ir.applicableNamespace() + ".DeprecatedMessageEncoder"; + final Class encoderClazz = compile(encoderFqcn); + assertNotNull(encoderClazz); + assertTrue(encoderClazz.isAnnotationPresent(Deprecated.class)); + + final String decoderFqcn = ir.applicableNamespace() + ".DeprecatedMessageDecoder"; + final Class decoderClazz = compile(decoderFqcn); + assertNotNull(decoderClazz); + assertTrue(decoderClazz.isAnnotationPresent(Deprecated.class)); + } + private Class getModelClass(final Object encoder) throws ClassNotFoundException { final String className = "Model"; diff --git a/sbe-tool/src/test/resources/deprecated-msg-test-schema.xml b/sbe-tool/src/test/resources/deprecated-msg-test-schema.xml new file mode 100644 index 0000000000..e7ed27e445 --- /dev/null +++ b/sbe-tool/src/test/resources/deprecated-msg-test-schema.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + From 0bfe5d705bde401a012d7b14e60acf4c63f0118e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 11 Nov 2021 17:47:22 +0000 Subject: [PATCH 0794/1594] [Java] Upgrade to Checkstyle 9.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 543e398d9a..c0a572bd37 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ def toolchainLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } -def checkstyleVersion = '9.0.1' +def checkstyleVersion = '9.1' def hamcrestVersion = '2.2' def mockitoVersion = '4.0.0' def junitVersion = '5.8.1' From 680e28ff08151d4c2ca74b9b7c407be28aa91c15 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Tue, 16 Nov 2021 05:55:26 -0600 Subject: [PATCH 0795/1594] [Rust] fixed rust codegen to support multiple schema file with same package (#877) Co-authored-by: Michael Ward --- rust/benches/car_benchmark.rs | 2 +- rust/benches/md_benchmark.rs | 2 +- rust/tests/baseline_test.rs | 4 +- rust/tests/big_endian_test.rs | 4 +- rust/tests/extension_test.rs | 4 +- rust/tests/issue_435_test.rs | 16 ++-- .../java/uk/co/real_logic/sbe/SbeTool.java | 2 +- .../sbe/generation/rust/LibRsDef.java | 73 ++++------------- .../sbe/generation/rust/MessageCoderDef.java | 2 +- .../sbe/generation/rust/RustGenerator.java | 78 +++++++++---------- .../generation/rust/RustOutputManager.java | 36 ++++++--- .../sbe/generation/rust/RustUtil.java | 5 ++ 12 files changed, 101 insertions(+), 127 deletions(-) diff --git a/rust/benches/car_benchmark.rs b/rust/benches/car_benchmark.rs index c6425ad379..7ca9c2e5c8 100644 --- a/rust/benches/car_benchmark.rs +++ b/rust/benches/car_benchmark.rs @@ -28,7 +28,7 @@ fn encode(state: &mut State) -> SbeResult { let mut acceleration = AccelerationEncoder::default(); let mut extras = OptionalExtras::default(); - car = car.wrap(WriteBuf::new(buffer), message_header::ENCODED_LENGTH); + car = car.wrap(WriteBuf::new(buffer), message_header_codec::ENCODED_LENGTH); car = car.header(0).parent()?; car.code(Model::A); diff --git a/rust/benches/md_benchmark.rs b/rust/benches/md_benchmark.rs index 3b59709a06..b429622f92 100644 --- a/rust/benches/md_benchmark.rs +++ b/rust/benches/md_benchmark.rs @@ -22,7 +22,7 @@ fn encode_md(state: &mut State) -> SbeResult { let mut market_data = MarketDataIncrementalRefreshTradesEncoder::default(); let mut md_inc_grp = MdIncGrpEncoder::default(); - market_data = market_data.wrap(WriteBuf::new(buffer), message_header::ENCODED_LENGTH); + market_data = market_data.wrap(WriteBuf::new(buffer), message_header_codec::ENCODED_LENGTH); market_data = market_data.header(0).parent()?; market_data.transact_time(1234); diff --git a/rust/tests/baseline_test.rs b/rust/tests/baseline_test.rs index 8156b71e53..a19b39a96e 100644 --- a/rust/tests/baseline_test.rs +++ b/rust/tests/baseline_test.rs @@ -33,7 +33,7 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { let buf = ReadBuf::new(buffer); let header = MessageHeaderDecoder::default().wrap(buf, 0); - assert_eq!(car::SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(car_codec::SBE_TEMPLATE_ID, header.template_id()); car = car.header(header); // Car... @@ -167,7 +167,7 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { car = car.wrap( WriteBuf::new(buffer.as_mut_slice()), - message_header::ENCODED_LENGTH, + message_header_codec::ENCODED_LENGTH, ); car = car.header(0).parent()?; diff --git a/rust/tests/big_endian_test.rs b/rust/tests/big_endian_test.rs index ae677dce21..40b652c1be 100644 --- a/rust/tests/big_endian_test.rs +++ b/rust/tests/big_endian_test.rs @@ -30,7 +30,7 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { let buf = ReadBuf::new(buffer); let header = MessageHeaderDecoder::default().wrap(buf, 0); - assert_eq!(car::SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(car_codec::SBE_TEMPLATE_ID, header.template_id()); car = car.header(header); // Car... @@ -161,7 +161,7 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { car = car.wrap( WriteBuf::new(buffer.as_mut_slice()), - message_header::ENCODED_LENGTH, + message_header_codec::ENCODED_LENGTH, ); car = car.header(0).parent()?; diff --git a/rust/tests/extension_test.rs b/rust/tests/extension_test.rs index 56496d271c..5e993f7701 100644 --- a/rust/tests/extension_test.rs +++ b/rust/tests/extension_test.rs @@ -32,7 +32,7 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { let buf = ReadBuf::new(buffer); let header = MessageHeaderDecoder::default().wrap(buf, 0); - assert_eq!(car::SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(car_codec::SBE_TEMPLATE_ID, header.template_id()); car = car.header(header); // Car... @@ -168,7 +168,7 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { car = car.wrap( WriteBuf::new(buffer.as_mut_slice()), - message_header::ENCODED_LENGTH, + message_header_codec::ENCODED_LENGTH, ); car = car.header(0).parent()?; diff --git a/rust/tests/issue_435_test.rs b/rust/tests/issue_435_test.rs index e4e6c1e3c5..3c9b43b0da 100644 --- a/rust/tests/issue_435_test.rs +++ b/rust/tests/issue_435_test.rs @@ -3,7 +3,7 @@ use ::issue_435::*; fn create_encoder(buffer: &mut Vec) -> Issue435Encoder { let issue_435 = Issue435Encoder::default().wrap( WriteBuf::new(buffer.as_mut_slice()), - message_header::ENCODED_LENGTH, + message_header_codec::ENCODED_LENGTH, ); let mut header = issue_435.header(0); header.s(*SetRef::default().set_one(true)); @@ -12,9 +12,9 @@ fn create_encoder(buffer: &mut Vec) -> Issue435Encoder { #[test] fn issue_435_ref_test() -> SbeResult<()> { - assert_eq!(9, message_header::ENCODED_LENGTH); - assert_eq!(1, issue_435::SBE_BLOCK_LENGTH); - assert_eq!(0, issue_435::SBE_SCHEMA_VERSION); + assert_eq!(9, message_header_codec::ENCODED_LENGTH); + assert_eq!(1, issue_435_codec::SBE_BLOCK_LENGTH); + assert_eq!(0, issue_435_codec::SBE_SCHEMA_VERSION); // encode... let mut buffer = vec![0u8; 256]; @@ -24,10 +24,10 @@ fn issue_435_ref_test() -> SbeResult<()> { // decode... let buf = ReadBuf::new(buffer.as_slice()); let header = MessageHeaderDecoder::default().wrap(buf, 0); - assert_eq!(issue_435::SBE_BLOCK_LENGTH, header.block_length()); - assert_eq!(issue_435::SBE_SCHEMA_VERSION, header.version()); - assert_eq!(issue_435::SBE_TEMPLATE_ID, header.template_id()); - assert_eq!(issue_435::SBE_SCHEMA_ID, header.schema_id()); + assert_eq!(issue_435_codec::SBE_BLOCK_LENGTH, header.block_length()); + assert_eq!(issue_435_codec::SBE_SCHEMA_VERSION, header.version()); + assert_eq!(issue_435_codec::SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(issue_435_codec::SBE_SCHEMA_ID, header.schema_id()); assert_eq!(*SetRef::default().set_one(true), header.s()); let decoder = Issue435Decoder::default().header(header); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index 565aea2145..ba8fb99784 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -164,7 +164,7 @@ public class SbeTool * Specifies token that should be appended to keywords to avoid compilation errors. *

    * If none is supplied then use of keywords results in an error during schema parsing. The - * underscore character is a good example fo a token to use. + * underscore character is a good example of a token to use. */ public static final String KEYWORD_APPEND_TOKEN = "sbe.keyword.append.token"; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index aab9f6a592..6799c64a27 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -15,17 +15,12 @@ */ package uk.co.real_logic.sbe.generation.rust; -import org.agrona.generation.OutputManager; -import uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType; - import java.io.IOException; import java.io.Writer; import java.nio.ByteOrder; +import java.nio.file.Files; import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.LinkedHashSet; -import java.util.Map; import static java.nio.ByteOrder.LITTLE_ENDIAN; import static uk.co.real_logic.sbe.generation.rust.RustGenerator.*; @@ -36,11 +31,7 @@ */ class LibRsDef { - private final LinkedHashMap> modules = new LinkedHashMap<>(); - private final ArrayList enumDefs = new ArrayList<>(); - private final ArrayList bitSetDefs = new ArrayList<>(); - - private final OutputManager outputManager; + private final RustOutputManager outputManager; private final ByteOrder byteOrder; /** @@ -50,28 +41,13 @@ class LibRsDef * @param byteOrder for the Encoding. */ LibRsDef( - final OutputManager outputManager, + final RustOutputManager outputManager, final ByteOrder byteOrder) { this.outputManager = outputManager; this.byteOrder = byteOrder; } - void addMod(final String modName, final CodecType codecType) - { - modules.computeIfAbsent(modName, __ -> new HashSet<>()).add(codecType); - } - - void addEnum(final String enumDef) - { - enumDefs.add(enumDef); - } - - void addBitSet(final String bitSetDef) - { - bitSetDefs.add(bitSetDef); - } - void generate() throws IOException { try (Writer libRs = outputManager.createOutput("lib")) @@ -79,31 +55,28 @@ void generate() throws IOException indent(libRs, 0, "#![forbid(unsafe_code)]\n"); indent(libRs, 0, "#![allow(clippy::upper_case_acronyms)]\n"); indent(libRs, 0, "#![allow(non_camel_case_types)]\n"); - indent(libRs, 0, "use core::{convert::TryInto};\n\n"); + indent(libRs, 0, "use ::core::{convert::TryInto};\n\n"); + + final ArrayList modules = new ArrayList<>(); + Files.walk(outputManager.getSrcDirPath()) + .filter(Files::isRegularFile) + .map(path -> path.getFileName().toString()) + .filter(fileName -> fileName.endsWith(".rs")) + .filter(fileName -> !fileName.equals("lib.rs")) + .map(fileName -> fileName.substring(0, fileName.length() - 3)) + .forEach(modules::add); // add modules - for (final String mod : modules.keySet()) + for (final String mod : modules) { indent(libRs, 0, "pub mod %s;\n", toLowerSnakeCase(mod)); } indent(libRs, 0, "\n"); // add re-export of modules - for (final Map.Entry> entry : modules.entrySet()) + for (final String module : modules) { - final String mod = entry.getKey(); - final HashSet codecTypes = entry.getValue(); - - if (codecTypes.size() == 1) - { - indent(libRs, 0, "pub use %s::%s::*;\n", - toLowerSnakeCase(mod), - toLowerSnakeCase(codecTypes.toArray()[0].toString())); - } - else - { - indent(libRs, 0, "pub use %s::{decoder::*, encoder::*};\n", toLowerSnakeCase(mod)); - } + indent(libRs, 0, "pub use %s::*;\n", toLowerSnakeCase(module)); } indent(libRs, 0, "\n"); @@ -115,20 +88,6 @@ void generate() throws IOException generateReadBuf(libRs, byteOrder); generateWriteBuf(libRs, byteOrder); - - // append generated enums - for (final String code : enumDefs) - { - libRs.append(code); - indent(libRs, 0, "\n"); - } - - // append generated bitSets - for (final String code : bitSetDefs) - { - libRs.append(code); - indent(libRs, 0, "\n"); - } } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index 1a7f7a2315..e885735663 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -147,7 +147,7 @@ void appendMessageHeaderDecoderFn(final Appendable out) throws IOException indent(out, 3, "let acting_version = header.version();\n\n"); indent(out, 3, "self.wrap(\n"); indent(out, 4, "header.parent().unwrap(),\n"); - indent(out, 4, "message_header::ENCODED_LENGTH,\n"); + indent(out, 4, "message_header_codec::ENCODED_LENGTH,\n"); indent(out, 4, "acting_block_length,\n"); indent(out, 4, "acting_version,\n"); indent(out, 3, ")\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index a1f253b8ce..c58a38dc27 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -126,17 +126,14 @@ public void generate() throws IOException // lib.rs final LibRsDef libRsDef = new LibRsDef(outputManager, ir.byteOrder()); - generateEnums(ir, libRsDef); - generateBitSets(ir, libRsDef); - generateComposites(ir, libRsDef, outputManager); + generateEnums(ir, outputManager); + generateBitSets(ir, outputManager); + generateComposites(ir, outputManager); for (final List tokens : ir.messages()) { final Token msgToken = tokens.get(0); - - libRsDef.addMod(msgToken.name(), Encoder); - libRsDef.addMod(msgToken.name(), Decoder); - + final String codecModName = codecModName(msgToken.name()); final List messageBody = getMessageBody(tokens); int i = 0; @@ -149,9 +146,11 @@ public void generate() throws IOException final List varData = new ArrayList<>(); collectVarData(messageBody, i, varData); - try (Writer out = outputManager.createOutput(msgToken.name())) + try (Writer out = outputManager.createOutput(codecModName)) { indent(out, 0, "use crate::*;\n\n"); + indent(out, 0, "pub use encoder::*;\n"); + indent(out, 0, "pub use decoder::*;\n\n"); final String blockLengthType = blockLengthType(); final String templateIdType = rustTypeName(ir.headerStructure().templateIdType()); final String schemaIdType = rustTypeName(ir.headerStructure().schemaIdType()); @@ -981,32 +980,36 @@ static void generateDecoderVarData( private static void generateBitSets( final Ir ir, - final LibRsDef libRsDef) throws IOException + final RustOutputManager outputManager) throws IOException { for (final List tokens : ir.types()) { if (!tokens.isEmpty() && tokens.get(0).signal() == BEGIN_SET) { - final StringBuilder sb = new StringBuilder(); - generateSingleBitSet(tokens, sb); - libRsDef.addBitSet(sb.toString()); + final Token beginToken = tokens.get(0); + final String bitSetType = formatStructName(beginToken.applicableTypeName()); + + try (Writer out = outputManager.createOutput(bitSetType)) + { + generateSingleBitSet(bitSetType, tokens, out); + } } } } private static void generateSingleBitSet( + final String bitSetType, final List tokens, final Appendable writer) throws IOException { final Token beginToken = tokens.get(0); - final String setType = formatStructName(beginToken.applicableTypeName()); final String rustPrimitiveType = rustTypeName(beginToken.encoding().primitiveType()); indent(writer, 0, "#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]\n"); - indent(writer, 0, "pub struct %s(pub %s);\n", setType, rustPrimitiveType); - indent(writer, 0, "impl %s {\n", setType); + indent(writer, 0, "pub struct %s(pub %s);\n", bitSetType, rustPrimitiveType); + indent(writer, 0, "impl %s {\n", bitSetType); indent(writer, 1, "#[inline]\n"); indent(writer, 1, "pub fn new(value: %s) -> Self {\n", rustPrimitiveType); - indent(writer, 2, "%s(value)\n", setType); + indent(writer, 2, "%s(value)\n", bitSetType); indent(writer, 1, "}\n\n"); indent(writer, 1, "#[inline]\n"); @@ -1044,10 +1047,10 @@ private static void generateSingleBitSet( } indent(writer, 0, "}\n"); - indent(writer, 0, "impl core::fmt::Debug for %s {\n", setType); + indent(writer, 0, "impl core::fmt::Debug for %s {\n", bitSetType); indent(writer, 1, "#[inline]\n"); indent(writer, 1, "fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {\n"); - indent(writer, 2, "write!(fmt, \"%s[", setType); + indent(writer, 2, "write!(fmt, \"%s[", bitSetType); final StringBuilder builder = new StringBuilder(); final StringBuilder arguments = new StringBuilder(); @@ -1128,7 +1131,7 @@ static void appendImplDecoderTrait( private static void generateEnums( final Ir ir, - final LibRsDef libRsDef) throws IOException + final RustOutputManager outputManager) throws IOException { final Set enumTypeNames = new HashSet<>(); for (final List tokens : ir.types()) @@ -1145,16 +1148,15 @@ private static void generateEnums( } final String typeName = beginToken.applicableTypeName(); - if (enumTypeNames.contains(typeName)) + if (!enumTypeNames.add(typeName)) { continue; } - final StringBuilder sb = new StringBuilder(); - generateEnum(tokens, sb); - enumTypeNames.add(typeName); - - libRsDef.addEnum(sb.toString()); + try (Writer out = outputManager.createOutput(typeName)) + { + generateEnum(tokens, out); + } } } @@ -1219,39 +1221,41 @@ private static void generateEnum( private static void generateComposites( final Ir ir, - final LibRsDef libRsDef, - final OutputManager outputManager) throws IOException + final RustOutputManager outputManager) throws IOException { for (final List tokens : ir.types()) { if (!tokens.isEmpty() && tokens.get(0).signal() == Signal.BEGIN_COMPOSITE) { - generateComposite(tokens, libRsDef, outputManager); + generateComposite(tokens, outputManager); } } } private static void generateComposite( final List tokens, - final LibRsDef libRsDef, - final OutputManager outputManager) throws IOException + final RustOutputManager outputManager) throws IOException { final Token token = tokens.get(0); final String compositeName = token.applicableTypeName(); + final String compositeModName = codecModName(compositeName); - try (Writer out = outputManager.createOutput(compositeName)) + try (Writer out = outputManager.createOutput(compositeModName)) { indent(out, 0, "use crate::*;\n\n"); + indent(out, 0, "pub use encoder::*;\n"); + indent(out, 0, "pub use decoder::*;\n\n"); + final int encodedLength = tokens.get(0).encodedLength(); if (encodedLength > 0) { indent(out, 0, "pub const ENCODED_LENGTH: usize = %d;\n\n", encodedLength); } - generateCompositeEncoder(tokens, libRsDef, compositeName, encoderName(compositeName), out); + generateCompositeEncoder(tokens, encoderName(compositeName), out); indent(out, 0, "\n"); - generateCompositeDecoder(tokens, libRsDef, compositeName, decoderName(compositeName), out); + generateCompositeDecoder(tokens, decoderName(compositeName), out); } } @@ -1331,13 +1335,9 @@ static void appendImplDecoderForComposite( private static void generateCompositeEncoder( final List tokens, - final LibRsDef libRsDef, - final String compositeName, final String encoderName, final Writer out) throws IOException { - libRsDef.addMod(compositeName, Encoder); - indent(out, 0, "pub mod encoder {\n"); indent(out, 1, "use super::*;\n\n"); @@ -1395,16 +1395,12 @@ private static void generateCompositeEncoder( private static void generateCompositeDecoder( final List tokens, - final LibRsDef libRsDef, - final String compositeName, final String decoderName, final Writer out) throws IOException { indent(out, 0, "pub mod decoder {\n"); indent(out, 1, "use super::*;\n\n"); - libRsDef.addMod(compositeName, Decoder); - indent(out, 1, "#[derive(Debug, Default)]\n"); indent(out, 1, "pub struct %s

    {\n", decoderName); indent(out, 2, "parent: Option

    ,\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java index e1cd8d9941..5fa9c4bf93 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java @@ -21,10 +21,11 @@ import java.io.File; import java.io.IOException; import java.io.Writer; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.Path; import static java.io.File.separatorChar; +import static java.nio.charset.StandardCharsets.UTF_8; import static uk.co.real_logic.sbe.generation.rust.RustUtil.toLowerSnakeCase; /** @@ -36,8 +37,19 @@ public class RustOutputManager implements OutputManager private final File rootDir; private final File srcDir; + static File createDir(final String dirName) + { + final File dir = new File(dirName); + if (!dir.exists() && !dir.mkdirs()) + { + throw new IllegalStateException("Unable to create directory: " + dirName); + } + return dir; + } + /** * Create a new {@link OutputManager} for generating rust source files into a given module. + * * @param baseDirName for the generated source code. * @param packageName for the generated source code relative to the baseDirName. */ @@ -52,12 +64,7 @@ public RustOutputManager(final String baseDirName, final String packageName) rootDir = new File(libDirName); final String srcDirName = libDirName + separatorChar + "src"; - - srcDir = new File(srcDirName); - if (!srcDir.exists() && !srcDir.mkdirs()) - { - throw new IllegalStateException("Unable to create directory: " + srcDirName); - } + srcDir = createDir(srcDirName); } /** @@ -70,15 +77,17 @@ public RustOutputManager(final String baseDirName, final String packageName) * @return a {@link java.io.Writer} to which the source code should be written. * @throws IOException if an issue occurs when creating the file. */ - @Override public Writer createOutput(final String name) throws IOException + @Override + public Writer createOutput(final String name) throws IOException { final String fileName = toLowerSnakeCase(name) + ".rs"; final File targetFile = new File(srcDir, fileName); - return Files.newBufferedWriter(targetFile.toPath(), StandardCharsets.UTF_8); + return Files.newBufferedWriter(targetFile.toPath(), UTF_8); } /** - * + * Creates a new Cargo.toml file + *

    * @return a {@link java.io.Writer} to which the crate definition should be written. * @throws IOException if an issue occurs when creating the file. */ @@ -86,7 +95,12 @@ public Writer createCargoToml() throws IOException { final String fileName = "Cargo.toml"; final File targetFile = new File(rootDir, fileName); - return Files.newBufferedWriter(targetFile.toPath(), StandardCharsets.UTF_8); + return Files.newBufferedWriter(targetFile.toPath(), UTF_8); + } + + Path getSrcDirPath() + { + return srcDir.toPath(); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index 9ee5bd204c..19aff8c97d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -122,6 +122,11 @@ static String formatStructName(final String structName) return Generators.toUpperFirstChar(structName); } + static String codecModName(final String prefix) + { + return toLowerSnakeCase(prefix + "Codec"); + } + static String codecName(final String structName, final CodecType codecType) { return formatStructName(structName + codecType.name()); From 67a5cf17c3f7b00bb1b2a640c5a37bb341f4309c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 16 Nov 2021 12:05:16 +0000 Subject: [PATCH 0796/1594] [Java] Tidy up after merge of PR #877. --- .../sbe/generation/rust/LibRsDef.java | 8 +++---- .../sbe/generation/rust/MessageCoderDef.java | 1 - .../sbe/generation/rust/RustGenerator.java | 21 +++++++++---------- .../generation/rust/RustOutputManager.java | 3 +-- .../sbe/generation/rust/RustUtil.java | 5 ++--- .../sbe/generation/rust/SubGroup.java | 1 - 6 files changed, 17 insertions(+), 22 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 6799c64a27..1baf03f047 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -60,10 +60,10 @@ void generate() throws IOException final ArrayList modules = new ArrayList<>(); Files.walk(outputManager.getSrcDirPath()) .filter(Files::isRegularFile) - .map(path -> path.getFileName().toString()) - .filter(fileName -> fileName.endsWith(".rs")) - .filter(fileName -> !fileName.equals("lib.rs")) - .map(fileName -> fileName.substring(0, fileName.length() - 3)) + .map((path) -> path.getFileName().toString()) + .filter((fileName) -> fileName.endsWith(".rs")) + .filter((fileName) -> !fileName.equals("lib.rs")) + .map((fileName) -> fileName.substring(0, fileName.length() - 3)) .forEach(modules::add); // add modules diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index e885735663..8eef8ecd77 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -119,7 +119,6 @@ void appendTo(final Appendable dest) throws IOException dest.append(sb); } - @Override public SubGroup addSubGroup(final String name, final int level, final Token groupToken) { final SubGroup subGroup = new SubGroup(name, level, groupToken); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index c58a38dc27..27ccaea108 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -33,10 +33,11 @@ import java.util.Set; import static java.lang.String.format; -import static uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType.Decoder; -import static uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType.Encoder; import static uk.co.real_logic.sbe.generation.rust.RustUtil.*; -import static uk.co.real_logic.sbe.ir.GenerationUtil.*; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData; +import static uk.co.real_logic.sbe.ir.GenerationUtil.getMessageBody; import static uk.co.real_logic.sbe.ir.Signal.BEGIN_ENUM; import static uk.co.real_logic.sbe.ir.Signal.BEGIN_SET; @@ -53,7 +54,7 @@ enum CodecType { Decoder { - @Override String bufType() + String bufType() { return READ_BUF_TYPE; } @@ -61,7 +62,7 @@ enum CodecType Encoder { - @Override String bufType() + String bufType() { return WRITE_BUF_TYPE; } @@ -81,8 +82,8 @@ interface ParentDef /** * Create a new Rust language {@link CodeGenerator}. * - * @param ir for the messages and types. - * @param outputManager for generating the codecs to. + * @param ir for the messages and types. + * @param outputManager for generating the codecs to. */ public RustGenerator( final Ir ir, @@ -227,9 +228,9 @@ static void generateEncoderFields( break; } } - catch (final IOException e) + catch (final IOException ex) { - throw new RuntimeException(e); + throw new RuntimeException(ex); } }); } @@ -1465,6 +1466,4 @@ private static void appendConstAccessor( indent(writer, level + 1, rustExpression + "\n"); indent(writer, level, "}\n\n"); } - - } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java index 5fa9c4bf93..864b8b1dd2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java @@ -44,6 +44,7 @@ static File createDir(final String dirName) { throw new IllegalStateException("Unable to create directory: " + dirName); } + return dir; } @@ -77,7 +78,6 @@ public RustOutputManager(final String baseDirName, final String packageName) * @return a {@link java.io.Writer} to which the source code should be written. * @throws IOException if an issue occurs when creating the file. */ - @Override public Writer createOutput(final String name) throws IOException { final String fileName = toLowerSnakeCase(name) + ".rs"; @@ -102,5 +102,4 @@ Path getSrcDirPath() { return srcDir.toPath(); } - } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index 19aff8c97d..5e65a327f4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -32,13 +32,12 @@ import static uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType.Encoder; /** - * + * Utility method for Rust codec generation. */ public class RustUtil { static final String INDENT = " "; - public static final Map TYPE_NAME_BY_PRIMITIVE_TYPE_MAP = - new EnumMap<>(PrimitiveType.class); + static final Map TYPE_NAME_BY_PRIMITIVE_TYPE_MAP = new EnumMap<>(PrimitiveType.class); static { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index 2fc4098335..2d2af72993 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -41,7 +41,6 @@ class SubGroup implements RustGenerator.ParentDef this.groupToken = groupToken; } - @Override public SubGroup addSubGroup(final String name, final int level, final Token groupToken) { final SubGroup subGroup = new SubGroup(name, level, groupToken); From 245dd30ecb3c6987d7d0020700cac4636f97dd9f Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 16 Nov 2021 20:03:28 +0100 Subject: [PATCH 0797/1594] Version bump for release. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index d07d97c65b..63610187e2 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.24.1-SNAPSHOT \ No newline at end of file +1.25.0-SNAPSHOT From 57979f81aca34adf47c1b5c9ee9c8144f9fce1b8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 16 Nov 2021 20:29:03 +0000 Subject: [PATCH 0798/1594] [Java] Upgrade to Agrona 1.13.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index c0a572bd37..99b17ba7b8 100644 --- a/build.gradle +++ b/build.gradle @@ -47,8 +47,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.0.0' def junitVersion = '5.8.1' def jmhVersion = '1.33' -def agronaVersion = '1.12.0' -def agronaVersionRange = '[1.12,1.13[' // allow any patch release of 1.12.x +def agronaVersion = '1.13.0' +def agronaVersionRange = '[1.13,1.14[' // allow any patch release of 1.13.x def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From afb62b59e2310630914fca0f0ad39490777e8133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Ram=C3=A9?= Date: Wed, 17 Nov 2021 09:31:23 +0000 Subject: [PATCH 0799/1594] DirectBuffer - Support ArraySegment for underlying array (#878) * DirectBuffer - Support ArraySegment for backing storage * fix comments --- csharp/sbe-dll/DirectBuffer.cs | 37 +++++++++++++++++++++++++++ csharp/sbe-tests/DirectBufferTests.cs | 34 ++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/csharp/sbe-dll/DirectBuffer.cs b/csharp/sbe-dll/DirectBuffer.cs index 52b78ea4af..09eb64ec7e 100644 --- a/csharp/sbe-dll/DirectBuffer.cs +++ b/csharp/sbe-dll/DirectBuffer.cs @@ -64,6 +64,25 @@ public DirectBuffer(byte* pBuffer, int bufferLength, BufferOverflowDelegate buff Wrap(pBuffer, bufferLength); } + ///

    + /// Attach a view to a buffer owned by external code + /// + /// byte buffer + public DirectBuffer(ArraySegment buffer) : this(buffer, null) + { + } + + /// + /// Attach a view to a buffer owned by external code + /// + /// byte buffer + /// delegate to allow reallocation of buffer + public DirectBuffer(ArraySegment buffer, BufferOverflowDelegate bufferOverflow) + { + this.bufferOverflow = bufferOverflow; + Wrap(buffer); + } + /// /// Creates a DirectBuffer that can later be wrapped /// @@ -114,6 +133,24 @@ public void Wrap(byte* pBuffer, int bufferLength) _needToFreeGCHandle = false; } + /// + /// Recycles an existing from a byte buffer owned by external code + /// + /// buffer of bytes + public void Wrap(ArraySegment buffer) + { + if (buffer == null) throw new ArgumentNullException(nameof(buffer)); + + FreeGCHandle(); + + // pin the buffer so it does not get moved around by GC, this is required since we use pointers + _pinnedGCHandle = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned); + _needToFreeGCHandle = true; + + _pBuffer = ((byte*)_pinnedGCHandle.AddrOfPinnedObject().ToPointer()) + buffer.Offset; + _capacity = buffer.Count; + } + /// /// Capacity of the underlying buffer /// diff --git a/csharp/sbe-tests/DirectBufferTests.cs b/csharp/sbe-tests/DirectBufferTests.cs index 2ac82e4e07..4c37ebe1f0 100644 --- a/csharp/sbe-tests/DirectBufferTests.cs +++ b/csharp/sbe-tests/DirectBufferTests.cs @@ -66,6 +66,40 @@ public void ConstructFromNativeBuffer() } } + [TestMethod] + public void ConstructFromByteArray() + { + var buffer = new byte[16]; + + const int value = 5; + const int index = 0; + + using (var directBuffer = new DirectBuffer(buffer)) + { + directBuffer.Int64PutLittleEndian(index, value); + Assert.AreEqual(value, buffer[index]); + } + } + + [TestMethod] + public void ConstructFromArraySegment() + { + const int value = 5; + const int index = 0; + const int offset = 512; + const int size = 1024; + + var bigBuffer = new byte[size]; + var buffer = new ArraySegment(bigBuffer, offset, size - offset); + + using (var directBuffer = new DirectBuffer(buffer)) + { + directBuffer.Int64PutLittleEndian(index, value); + Assert.AreEqual(value, bigBuffer[offset + index]); + Assert.AreEqual(value, buffer.AsSpan()[index]); + } + } + [TestMethod] public void Recycle() { From 6434c28ccf248f5f94d8f67c654c57c978664546 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Wed, 17 Nov 2021 08:34:32 -0800 Subject: [PATCH 0800/1594] 1.25.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 63610187e2..ad2191947f 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.25.0-SNAPSHOT +1.25.0 From f611518bec16d2c9ef3df2f6b3ec2dcfb6e256a5 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Wed, 17 Nov 2021 08:36:29 -0800 Subject: [PATCH 0801/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index ad2191947f..b1d7655df2 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.25.0 +1.25.1-SNAPSHOT From d20adc38e5ce8007813717dbc7974f54111c938f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 21 Nov 2021 13:43:31 +0000 Subject: [PATCH 0802/1594] [Java] Upgrade to Mockito 4.1.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 99b17ba7b8..ce4fd4e7b1 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.1' def hamcrestVersion = '2.2' -def mockitoVersion = '4.0.0' +def mockitoVersion = '4.1.0' def junitVersion = '5.8.1' def jmhVersion = '1.33' def agronaVersion = '1.13.0' From a2f348a3113cc8eea2e1c73378829f068e18acf1 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 21 Nov 2021 15:06:59 +0100 Subject: [PATCH 0803/1594] [Java] Upgrade to Agrona 1.13.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ce4fd4e7b1..f7389425a5 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.1.0' def junitVersion = '5.8.1' def jmhVersion = '1.33' -def agronaVersion = '1.13.0' +def agronaVersion = '1.13.1' def agronaVersionRange = '[1.13,1.14[' // allow any patch release of 1.13.x def sbeGroup = 'uk.co.real-logic' From 8d1b6a0591f24bef98b8ccc37ed3dab960487d75 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 23 Nov 2021 17:52:00 +0100 Subject: [PATCH 0804/1594] [Java] Upgrade to Agrona 1.14.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index f7389425a5..2b4c4748bb 100644 --- a/build.gradle +++ b/build.gradle @@ -47,8 +47,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.1.0' def junitVersion = '5.8.1' def jmhVersion = '1.33' -def agronaVersion = '1.13.1' -def agronaVersionRange = '[1.13,1.14[' // allow any patch release of 1.13.x +def agronaVersion = '1.14.0' +def agronaVersionRange = '[1.14,1.15[' // allow any patch release of 1.14.x def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 60d1b2fede2f1995cbf53da04f9dcf24e6a57806 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Wed, 24 Nov 2021 08:25:44 -0800 Subject: [PATCH 0805/1594] 1.25.1 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index b1d7655df2..d905a6d1d6 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.25.1-SNAPSHOT +1.25.1 From 0aca497ea66ec954bda2bfeb6ca9f00366e50267 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Wed, 24 Nov 2021 08:27:17 -0800 Subject: [PATCH 0806/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index d905a6d1d6..6fb671d7e9 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.25.1 +1.25.2-SNAPSHOT From 0ee9e55ada49fec533eb826ae485d51241b76f5e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Nov 2021 13:36:39 +0100 Subject: [PATCH 0807/1594] [Java] Upgrade to JUnit 5.8.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2b4c4748bb..7c2bad88a9 100644 --- a/build.gradle +++ b/build.gradle @@ -45,7 +45,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.1' def hamcrestVersion = '2.2' def mockitoVersion = '4.1.0' -def junitVersion = '5.8.1' +def junitVersion = '5.8.2' def jmhVersion = '1.33' def agronaVersion = '1.14.0' def agronaVersionRange = '[1.14,1.15[' // allow any patch release of 1.14.x From 44ca92f152cbfaaaf0b72bc9ee08e2f2c345b303 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 30 Nov 2021 15:38:13 +0000 Subject: [PATCH 0808/1594] [Java] Upgrade to Checkstyle 9.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7c2bad88a9..f506c48c66 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ def toolchainLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } -def checkstyleVersion = '9.1' +def checkstyleVersion = '9.2' def hamcrestVersion = '2.2' def mockitoVersion = '4.1.0' def junitVersion = '5.8.2' From b7b2e0ccba80a3b00ea53b7d53586f0c6a1359e0 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 2 Dec 2021 13:19:39 +0000 Subject: [PATCH 0809/1594] [Java] Upgrade to Gradle 7.3.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index f506c48c66..da5da5feb5 100644 --- a/build.gradle +++ b/build.gradle @@ -820,7 +820,7 @@ tasks.named('dependencyUpdates').configure { tasks.findByName('build').dependsOn verifyJavaIrCodecsInSync wrapper { - gradleVersion = '7.2' + gradleVersion = '7.3.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a0f7639f7d..3cd8500c13 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 15391b4f53219f6074b7d4a3a774638a1691e2b8 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 15 Dec 2021 11:18:16 +0100 Subject: [PATCH 0810/1594] [Java] Upgrade to Shadow 7.1.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index da5da5feb5..d93b8b5ea4 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ import java.security.MessageDigest plugins { id 'java-library' - id 'com.github.johnrengelman.shadow' version '7.1.0' apply false + id 'com.github.johnrengelman.shadow' version '7.1.1' apply false id "com.github.ben-manes.versions" version "0.39.0" } From 470db5384d7fb60de7dd89adc4968afaf7ccfd48 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 15 Dec 2021 22:57:00 +0000 Subject: [PATCH 0811/1594] [Java] Upgrade to Gradle 7.3.2. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index d93b8b5ea4..b58aff0ca0 100644 --- a/build.gradle +++ b/build.gradle @@ -820,7 +820,7 @@ tasks.named('dependencyUpdates').configure { tasks.findByName('build').dependsOn verifyJavaIrCodecsInSync wrapper { - gradleVersion = '7.3.1' + gradleVersion = '7.3.2' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3cd8500c13..ac0b842f19 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From c36cef0c6f0ed438e630c379978096d9a6483b9b Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 16 Dec 2021 11:00:48 +0100 Subject: [PATCH 0812/1594] [Java] Regenerate Gradle wrapper scripts. --- gradlew | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gradlew b/gradlew index c53aefaa5f..1b6c787337 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,10 +32,10 @@ # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # From c02b4247cd30534e6e328c06a8712694b44745c3 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 16 Dec 2021 13:51:01 +0000 Subject: [PATCH 0813/1594] [Java] Upgrade to Mockito 4.2.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b58aff0ca0..ae8126b1d9 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.2' def hamcrestVersion = '2.2' -def mockitoVersion = '4.1.0' +def mockitoVersion = '4.2.0' def junitVersion = '5.8.2' def jmhVersion = '1.33' def agronaVersion = '1.14.0' From 0bc4268e609ffcbab108a52295c08f8b977f08fb Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 22 Dec 2021 15:47:04 +0000 Subject: [PATCH 0814/1594] [Java] Upgrade to Gradle 7.3.3. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index ae8126b1d9..e080a8a410 100644 --- a/build.gradle +++ b/build.gradle @@ -820,7 +820,7 @@ tasks.named('dependencyUpdates').configure { tasks.findByName('build').dependsOn verifyJavaIrCodecsInSync wrapper { - gradleVersion = '7.3.2' + gradleVersion = '7.3.3' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ac0b842f19..669386b870 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787337..c53aefaa5f 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,10 +32,10 @@ # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # From 0b1e282d66f154f5a9de4adbf45ae7c260241355 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 22 Dec 2021 17:27:54 +0000 Subject: [PATCH 0815/1594] [Java] Add missing Javadoc. --- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java index a4f2b6235a..2696d1eee1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java @@ -27,6 +27,9 @@ */ public class Field { + /** + * Value to indicate a {@link Field} is invalid or not yet set. + */ public static final int INVALID_ID = Integer.MAX_VALUE; // schemaId must be a short, so this is way out of range. private final String name; // required for field/data & group From 4bcd9429ac452d4c417e1ea34f3a72ff05558c5b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 22 Dec 2021 17:48:22 +0000 Subject: [PATCH 0816/1594] [Java] Restrict JVM version range for test. --- .../sbe/generation/csharp/Issue567GroupSizeTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index b59caa3f4a..fb916d5f40 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -19,6 +19,8 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledForJreRange; +import org.junit.jupiter.api.condition.JRE; import uk.co.real_logic.sbe.Tests; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; @@ -32,6 +34,7 @@ import static org.mockito.Mockito.verify; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; +@EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_17) public class Issue567GroupSizeTest { public static final String ERR_MSG = From 24061c25e7e949c7fc41507dc55ea9a66c5012b4 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 23 Dec 2021 16:39:37 +0000 Subject: [PATCH 0817/1594] [Java] Upgrade to JMH 1.34. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e080a8a410..5c15c8c467 100644 --- a/build.gradle +++ b/build.gradle @@ -46,7 +46,7 @@ def checkstyleVersion = '9.2' def hamcrestVersion = '2.2' def mockitoVersion = '4.2.0' def junitVersion = '5.8.2' -def jmhVersion = '1.33' +def jmhVersion = '1.34' def agronaVersion = '1.14.0' def agronaVersionRange = '[1.14,1.15[' // allow any patch release of 1.14.x From 1e2187013a3ee529668182879b3045a56cbb5b70 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 24 Dec 2021 16:43:44 +0000 Subject: [PATCH 0818/1594] [Java] Set encoding type for test to see if it works for charset changes in Java 18. --- .../csharp/Issue567GroupSizeTest.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index fb916d5f40..9092e8f3fe 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -19,14 +19,15 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledForJreRange; -import org.junit.jupiter.api.condition.JRE; +import org.xml.sax.InputSource; import uk.co.real_logic.sbe.Tests; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import java.io.IOException; +import java.io.InputStream; import java.io.PrintStream; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -34,7 +35,6 @@ import static org.mockito.Mockito.verify; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -@EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_17) public class Issue567GroupSizeTest { public static final String ERR_MSG = @@ -58,18 +58,25 @@ public void after() } @Test - public void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupSize() + public void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupSize() throws IOException { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - assertThrows(IllegalArgumentException.class, - () -> parse(Tests.getLocalResource("issue567-invalid.xml"), options)); + final InputStream in = Tests.getLocalResource("issue567-invalid.xml"); + final InputSource is = new InputSource(in); + is.setEncoding("UTF-8"); + + assertThrows(IllegalArgumentException.class, () -> parse(is, options)); } @Test public void shouldGenerateWhenUsingATypeThatIsConstrainedToFitInAnIntAsTheGroupSize() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("issue567-valid.xml"), options); + final InputStream in = Tests.getLocalResource("issue567-valid.xml"); + final InputSource is = new InputSource(in); + is.setEncoding("UTF-8"); + + final MessageSchema schema = parse(is, options); final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); From d332e5c26e2a2dd22e09fbeab5f7af48370e91c9 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 24 Dec 2021 18:16:02 +0000 Subject: [PATCH 0819/1594] [Java] Disable test for Java 18. --- .../sbe/generation/csharp/Issue567GroupSizeTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index 9092e8f3fe..c1af4c495a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -19,6 +19,8 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledForJreRange; +import org.junit.jupiter.api.condition.JRE; import org.xml.sax.InputSource; import uk.co.real_logic.sbe.Tests; import uk.co.real_logic.sbe.ir.Ir; @@ -35,6 +37,7 @@ import static org.mockito.Mockito.verify; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; +@EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_17) public class Issue567GroupSizeTest { public static final String ERR_MSG = From 4ace22a7af1d6ce313f60b652540fe0457403e2e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 28 Dec 2021 17:40:55 +0000 Subject: [PATCH 0820/1594] [Java] Remove unnecessary checks. --- .../uk/co/real_logic/sbe/xml/XmlSchemaParser.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index e20562b4f5..c1f4e26333 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -289,12 +289,6 @@ public static String getAttributeValue(final Node elementNode, final String attr } final NamedNodeMap attributes = elementNode.getAttributes(); - if (null == attributes) - { - throw new IllegalStateException( - "element '" + elementNode.getNodeName() + "' has empty or missing attribute: " + attrName); - } - final Node attrNode = attributes.getNamedItemNS(null, attrName); if (null == attrNode || "".equals(attrNode.getNodeValue())) { @@ -322,11 +316,6 @@ public static String getAttributeValue(final Node elementNode, final String attr } final NamedNodeMap attributes = elementNode.getAttributes(); - if (null == attributes) - { - return defValue; - } - final Node attrNode = attributes.getNamedItemNS(null, attrName); if (null == attrNode) { @@ -345,7 +334,7 @@ public static String getAttributeValue(final Node elementNode, final String attr */ public static String getAttributeValueOrNull(final Node elementNode, final String attrName) { - if (null == elementNode || null == elementNode.getAttributes()) + if (null == elementNode) { return null; } From ca83fd753c19295722f3ec86654fb0cc20d243f6 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 28 Dec 2021 17:50:09 +0000 Subject: [PATCH 0821/1594] [Java] Don't create xpath factory until needed and set character encoding for test. --- .../java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java | 3 +-- .../sbe/generation/csharp/Issue567GroupSizeTest.java | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index c1f4e26333..49cdcd0fd1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -129,11 +129,10 @@ public static MessageSchema parse(final InputSource is, final ParserOptions opti } final Document document = factory.newDocumentBuilder().parse(is); - final XPath xPath = XPathFactory.newInstance().newXPath(); - final ErrorHandler errorHandler = new ErrorHandler(options); document.setUserData(ERROR_HANDLER_KEY, errorHandler, null); + final XPath xPath = XPathFactory.newInstance().newXPath(); final Map typeByNameMap = findTypes(document, xPath); errorHandler.checkIfShouldExit(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index c1af4c495a..6b0eadc6d3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -30,14 +30,16 @@ import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.PrintStream; +import java.nio.charset.StandardCharsets; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -@EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_17) +@EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_18) public class Issue567GroupSizeTest { public static final String ERR_MSG = @@ -65,8 +67,7 @@ public void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupS { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); final InputStream in = Tests.getLocalResource("issue567-invalid.xml"); - final InputSource is = new InputSource(in); - is.setEncoding("UTF-8"); + final InputSource is = new InputSource(new InputStreamReader(in, StandardCharsets.UTF_8)); assertThrows(IllegalArgumentException.class, () -> parse(is, options)); } @@ -76,8 +77,7 @@ public void shouldGenerateWhenUsingATypeThatIsConstrainedToFitInAnIntAsTheGroupS { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); final InputStream in = Tests.getLocalResource("issue567-valid.xml"); - final InputSource is = new InputSource(in); - is.setEncoding("UTF-8"); + final InputSource is = new InputSource(new InputStreamReader(in, StandardCharsets.UTF_8)); final MessageSchema schema = parse(is, options); final IrGenerator irg = new IrGenerator(); From b35ab85f22892643e8efe0657a8c1111a274f648 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 28 Dec 2021 17:53:53 +0000 Subject: [PATCH 0822/1594] [Java] Revert testing on Java 18. --- .../real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index 6b0eadc6d3..363b3d4149 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -39,7 +39,7 @@ import static org.mockito.Mockito.verify; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -@EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_18) +@EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_17) public class Issue567GroupSizeTest { public static final String ERR_MSG = From a8c21ed77ffab65c7a7dce986551cc4d182d7d23 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 28 Dec 2021 17:58:46 +0000 Subject: [PATCH 0823/1594] [Java] Formatting. --- sbe-tool/src/test/resources/issue435.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/test/resources/issue435.xml b/sbe-tool/src/test/resources/issue435.xml index ddebd2fad1..8cf1a3794b 100644 --- a/sbe-tool/src/test/resources/issue435.xml +++ b/sbe-tool/src/test/resources/issue435.xml @@ -27,6 +27,6 @@ - + From 23c67a31de34366da2be5a7fdac034982c9ab348 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 28 Dec 2021 18:00:06 +0000 Subject: [PATCH 0824/1594] [Java] Formatting. --- sbe-tool/src/test/resources/issue567-valid.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/test/resources/issue567-valid.xml b/sbe-tool/src/test/resources/issue567-valid.xml index a7a52c19bf..c9cd88b933 100644 --- a/sbe-tool/src/test/resources/issue567-valid.xml +++ b/sbe-tool/src/test/resources/issue567-valid.xml @@ -15,7 +15,7 @@ - + @@ -33,7 +33,7 @@ - + From 369ef4c409348a69f18e4d5f2c46626da74e4ca4 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 28 Dec 2021 18:01:24 +0000 Subject: [PATCH 0825/1594] [Java] Formatting. --- sbe-tool/src/test/resources/issue567-invalid.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/test/resources/issue567-invalid.xml b/sbe-tool/src/test/resources/issue567-invalid.xml index 445b1c69f2..b5cb41b1c6 100644 --- a/sbe-tool/src/test/resources/issue567-invalid.xml +++ b/sbe-tool/src/test/resources/issue567-invalid.xml @@ -28,12 +28,12 @@ - + - + From 814b2a5fa9353f231fd300a8bdc3b66bf9a69c19 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 28 Dec 2021 18:34:04 +0000 Subject: [PATCH 0826/1594] [Java] Formatting. --- sbe-tool/src/test/resources/issue827.xml | 2 +- sbe-tool/src/test/resources/issue847.xml | 12 ++++++------ sbe-tool/src/test/resources/issue848.xml | 12 ++++++------ sbe-tool/src/test/resources/issue849.xml | 12 ++++++------ 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/sbe-tool/src/test/resources/issue827.xml b/sbe-tool/src/test/resources/issue827.xml index 08430a6e73..cfc0f7fefd 100644 --- a/sbe-tool/src/test/resources/issue827.xml +++ b/sbe-tool/src/test/resources/issue827.xml @@ -19,6 +19,6 @@ - + diff --git a/sbe-tool/src/test/resources/issue847.xml b/sbe-tool/src/test/resources/issue847.xml index ce015bbb1c..784608ac9e 100644 --- a/sbe-tool/src/test/resources/issue847.xml +++ b/sbe-tool/src/test/resources/issue847.xml @@ -1,11 +1,11 @@ + package="issue847" + id="1" + version="0" + semanticVersion="1.0" + description="test case 847 20210511" + byteOrder="littleEndian"> diff --git a/sbe-tool/src/test/resources/issue848.xml b/sbe-tool/src/test/resources/issue848.xml index cf31b53740..e30b4b9589 100644 --- a/sbe-tool/src/test/resources/issue848.xml +++ b/sbe-tool/src/test/resources/issue848.xml @@ -1,11 +1,11 @@ + package="issue848" + id="1" + version="0" + semanticVersion="1.0" + description="test case 848 20210511" + byteOrder="littleEndian"> diff --git a/sbe-tool/src/test/resources/issue849.xml b/sbe-tool/src/test/resources/issue849.xml index 4eb45ce8ee..6533a270c6 100644 --- a/sbe-tool/src/test/resources/issue849.xml +++ b/sbe-tool/src/test/resources/issue849.xml @@ -1,11 +1,11 @@ + package="issue849" + id="1" + version="0" + semanticVersion="1.0" + description="test case 849 20210512" + byteOrder="littleEndian"> From 60cdde5fc76afb41065da176546199c7e11916c4 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 28 Dec 2021 18:59:48 +0000 Subject: [PATCH 0827/1594] [Java] Improve test for Issue #567. --- .../generation/csharp/Issue567GroupSizeTest.java | 13 +++++++++++-- sbe-tool/src/test/resources/issue567-invalid.xml | 11 +++-------- sbe-tool/src/test/resources/issue567-valid.xml | 11 +++-------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index 363b3d4149..615ce24fc4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -35,6 +35,7 @@ import java.nio.charset.StandardCharsets; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -42,9 +43,15 @@ @EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_17) public class Issue567GroupSizeTest { - public static final String ERR_MSG = + private static final String ERR_MSG = "WARNING: at \"numInGroup\" should be UINT8 or UINT16"; + private static final String EXPECTED_COUNT_CHECK = + " if ((uint) count > 2147483647)\n" + + " {\n" + + " ThrowHelper.ThrowCountOutOfRangeException(count);\n" + + " }"; + private final PrintStream mockErr = mock(PrintStream.class); private PrintStream err; @@ -87,7 +94,9 @@ public void shouldGenerateWhenUsingATypeThatIsConstrainedToFitInAnIntAsTheGroupS outputManager.setPackageName(ir.applicableNamespace()); final CSharpGenerator generator = new CSharpGenerator(ir, outputManager); - // Act + Assert (no exception) generator.generate(); + + final String source = outputManager.getSource("tests.Issue567").toString(); + assertTrue(source.contains(EXPECTED_COUNT_CHECK)); } } diff --git a/sbe-tool/src/test/resources/issue567-invalid.xml b/sbe-tool/src/test/resources/issue567-invalid.xml index b5cb41b1c6..d31d1eff64 100644 --- a/sbe-tool/src/test/resources/issue567-invalid.xml +++ b/sbe-tool/src/test/resources/issue567-invalid.xml @@ -1,7 +1,7 @@ - - - - - - + diff --git a/sbe-tool/src/test/resources/issue567-valid.xml b/sbe-tool/src/test/resources/issue567-valid.xml index c9cd88b933..e5f56d82bf 100644 --- a/sbe-tool/src/test/resources/issue567-valid.xml +++ b/sbe-tool/src/test/resources/issue567-valid.xml @@ -1,7 +1,7 @@ - - - - - - + From 7b0c022d81ec33d13038193fb8d5c9aadbe2a973 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 28 Dec 2021 19:26:59 +0000 Subject: [PATCH 0828/1594] [Java] Add the ability to ParserOptions for setting which stream errors gets printed to and improve test for Issue #567. --- .../co/real_logic/sbe/xml/ErrorHandler.java | 8 +-- .../co/real_logic/sbe/xml/ParserOptions.java | 49 ++++++++++++++++--- .../csharp/Issue567GroupSizeTest.java | 20 +++----- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java index 4dbc5ff4e4..4afaf0e092 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java @@ -30,7 +30,8 @@ public class ErrorHandler private int warnings = 0; /** - * Construct a new {@link ErrorHandler} that outputs to a provided {@link PrintStream}. + * Construct a new {@link ErrorHandler} that outputs to a provided {@link PrintStream} which overrides the value + * set in {@link ParserOptions#errorPrintStream()}. * * @param stream to which output should be sent. * @param options the parsing options. @@ -44,13 +45,14 @@ public ErrorHandler(final PrintStream stream, final ParserOptions options) } /** - * Default {@link ErrorHandler} that outputs to {@link System#err}. + * Default {@link ErrorHandler} that outputs to {@link System#err} if {@link ParserOptions#errorPrintStream()} is + * not set. * * @param options the parsing options. */ public ErrorHandler(final ParserOptions options) { - this(System.err, options); + this(options.errorPrintStream() != null ? options.errorPrintStream() : System.err, options); } /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java index 9ff509d56d..3743f860ce 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java @@ -15,40 +15,49 @@ */ package uk.co.real_logic.sbe.xml; +import java.io.PrintStream; + /** * Class to hold the values of the parsing options. */ public final class ParserOptions { - public static final ParserOptions DEFAULT = new ParserOptions(false, false, false, true, null); + /** + * Default parser options which can be used for convenience. + */ + public static final ParserOptions DEFAULT = new ParserOptions(false, false, false, true, null, null); private final boolean stopOnError; private final boolean warningsFatal; private final boolean suppressOutput; private final boolean xIncludeAware; private final String xsdFilename; + private final PrintStream errorPrintStream; /** * Sets up the parsing options. * - * @param stopOnError specifies whether the parsing should stop on error. - * @param warningsFatal specifies whether the warnings should be handled as fatal errors. - * @param suppressOutput specifies whether to suppress the output of errors and warnings. - * @param xIncludeAware should parse expect XInclude references. - * @param xsdFilename the name of the schema file. + * @param stopOnError specifies whether the parsing should stop on error. + * @param warningsFatal specifies whether the warnings should be handled as fatal errors. + * @param suppressOutput specifies whether to suppress the output of errors and warnings. + * @param xIncludeAware should parse expect XInclude references. + * @param xsdFilename the name of the schema file. + * @param errorPrintStream the {@link PrintStream} to which parsing errors and warnings are printed. */ private ParserOptions( final boolean stopOnError, final boolean warningsFatal, final boolean suppressOutput, final boolean xIncludeAware, - final String xsdFilename) + final String xsdFilename, + final PrintStream errorPrintStream) { this.stopOnError = stopOnError; this.warningsFatal = warningsFatal; this.suppressOutput = suppressOutput; this.xIncludeAware = xIncludeAware; this.xsdFilename = xsdFilename; + this.errorPrintStream = errorPrintStream; } /** @@ -101,6 +110,16 @@ public String xsdFilename() return xsdFilename; } + /** + * The {@link PrintStream} to which errors and warnings are printed when parsing. + * + * @return the {@link PrintStream} to which errors and warnings are printed when parsing. + */ + public PrintStream errorPrintStream() + { + return errorPrintStream; + } + /** * Creates a builder. * @@ -121,6 +140,7 @@ public static class Builder private boolean suppressOutput; private boolean xIncludeAware; private String xsdFilename; + private PrintStream errorPrintStream; /** * The value of the stopOnError parameter. @@ -232,6 +252,18 @@ public Builder xsdFilename(final String xsdFilename) return this; } + /** + * Set the {@link PrintStream} to which parsing errors and warnings are printed. + * + * @param errorPrintStream to which parsing errors and warnings are printed. + * @return this instance + */ + public Builder errorPrintStream(final PrintStream errorPrintStream) + { + this.errorPrintStream = errorPrintStream; + return this; + } + /** * Creates an instance of {@link ParserOptions} with all the values set. * @@ -239,7 +271,8 @@ public Builder xsdFilename(final String xsdFilename) */ public ParserOptions build() { - return new ParserOptions(stopOnError, warningsFatal, suppressOutput, xIncludeAware, xsdFilename); + return new ParserOptions( + stopOnError, warningsFatal, suppressOutput, xIncludeAware, xsdFilename, errorPrintStream); } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index 615ce24fc4..01b75ec135 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -17,7 +17,6 @@ import org.agrona.generation.StringWriterOutputManager; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledForJreRange; import org.junit.jupiter.api.condition.JRE; @@ -53,26 +52,20 @@ public class Issue567GroupSizeTest " }"; private final PrintStream mockErr = mock(PrintStream.class); - private PrintStream err; - - @BeforeEach - public void before() - { - err = System.err; - System.setErr(mockErr); - } @AfterEach public void after() { - System.setErr(err); verify(mockErr).println(ERR_MSG); } @Test public void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupSize() throws IOException { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final ParserOptions options = ParserOptions.builder() + .errorPrintStream(mockErr) + .stopOnError(true) + .build(); final InputStream in = Tests.getLocalResource("issue567-invalid.xml"); final InputSource is = new InputSource(new InputStreamReader(in, StandardCharsets.UTF_8)); @@ -82,7 +75,10 @@ public void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupS @Test public void shouldGenerateWhenUsingATypeThatIsConstrainedToFitInAnIntAsTheGroupSize() throws Exception { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final ParserOptions options = ParserOptions.builder() + .errorPrintStream(mockErr) + .stopOnError(true) + .build(); final InputStream in = Tests.getLocalResource("issue567-valid.xml"); final InputSource is = new InputSource(new InputStreamReader(in, StandardCharsets.UTF_8)); From 7c943f6c2eeb4d94697ed2315e042bf6d2e5fea9 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 28 Dec 2021 19:32:43 +0000 Subject: [PATCH 0829/1594] [Java] Test again with Java 18. --- .../real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index 01b75ec135..0f60a83d3f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -39,7 +39,7 @@ import static org.mockito.Mockito.verify; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -@EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_17) +@EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_18) public class Issue567GroupSizeTest { private static final String ERR_MSG = From fb22bcd8b6712957565f1d1c8ab5f24ac3f4f5ba Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 28 Dec 2021 19:35:53 +0000 Subject: [PATCH 0830/1594] [Java] Remove range check for Java 18. --- .../sbe/generation/csharp/Issue567GroupSizeTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index 0f60a83d3f..96d7f84fb6 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -18,8 +18,6 @@ import org.agrona.generation.StringWriterOutputManager; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledForJreRange; -import org.junit.jupiter.api.condition.JRE; import org.xml.sax.InputSource; import uk.co.real_logic.sbe.Tests; import uk.co.real_logic.sbe.ir.Ir; @@ -39,7 +37,6 @@ import static org.mockito.Mockito.verify; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -@EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_18) public class Issue567GroupSizeTest { private static final String ERR_MSG = From 1c8856e59bdcc442e5c2ab8be3eba47e288ad12d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 29 Dec 2021 09:43:39 +0000 Subject: [PATCH 0831/1594] [Java] Simplify and clarify test. --- .../generation/csharp/Issue567GroupSizeTest.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index 96d7f84fb6..4f6b99bf71 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -16,7 +16,6 @@ package uk.co.real_logic.sbe.generation.csharp; import org.agrona.generation.StringWriterOutputManager; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.xml.sax.InputSource; import uk.co.real_logic.sbe.Tests; @@ -24,6 +23,7 @@ import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import uk.co.real_logic.sbe.xml.XmlSchemaParser; import java.io.IOException; import java.io.InputStream; @@ -35,7 +35,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class Issue567GroupSizeTest { @@ -50,12 +49,6 @@ public class Issue567GroupSizeTest private final PrintStream mockErr = mock(PrintStream.class); - @AfterEach - public void after() - { - verify(mockErr).println(ERR_MSG); - } - @Test public void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupSize() throws IOException { @@ -66,7 +59,8 @@ public void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupS final InputStream in = Tests.getLocalResource("issue567-invalid.xml"); final InputSource is = new InputSource(new InputStreamReader(in, StandardCharsets.UTF_8)); - assertThrows(IllegalArgumentException.class, () -> parse(is, options)); + assertThrows(IllegalArgumentException.class, () -> XmlSchemaParser.parse(is, options)); + verify(mockErr).println(ERR_MSG); } @Test @@ -79,7 +73,9 @@ public void shouldGenerateWhenUsingATypeThatIsConstrainedToFitInAnIntAsTheGroupS final InputStream in = Tests.getLocalResource("issue567-valid.xml"); final InputSource is = new InputSource(new InputStreamReader(in, StandardCharsets.UTF_8)); - final MessageSchema schema = parse(is, options); + final MessageSchema schema = XmlSchemaParser.parse(is, options); + verify(mockErr).println(ERR_MSG); + final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); From 1ddd6b3e7298373ed95d978f8d2a4108a8de73fc Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 29 Dec 2021 09:52:40 +0000 Subject: [PATCH 0832/1594] [Java] Improve tests so failures are easier to debug. --- .../real_logic/sbe/generation/cpp/CppGeneratorTest.java | 9 +++++---- .../sbe/generation/csharp/Issue567GroupSizeTest.java | 5 +++-- .../co/real_logic/sbe/generation/rust/RustUtilTest.java | 9 +++------ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index 5106c1a7bf..f59ffbfb89 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -23,8 +23,9 @@ import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class CppGeneratorTest @@ -43,7 +44,7 @@ public void shouldUseGeneratedLiteralForConstantOneWhenGeneratingBitsetCode() th generator.generate(); final String source = outputManager.getSource("issue827.FlagsSet").toString(); - assertFalse(source.contains("1u << ")); - assertTrue(source.contains("UINT64_C(0x1) << ")); + assertThat(source, not(containsString("1u << "))); + assertThat(source, containsString("UINT64_C(0x1) << ")); } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index 4f6b99bf71..832f94cdce 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -31,8 +31,9 @@ import java.io.PrintStream; import java.nio.charset.StandardCharsets; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -86,6 +87,6 @@ public void shouldGenerateWhenUsingATypeThatIsConstrainedToFitInAnIntAsTheGroupS generator.generate(); final String source = outputManager.getSource("tests.Issue567").toString(); - assertTrue(source.contains(EXPECTED_COUNT_CHECK)); + assertThat(source, containsString(EXPECTED_COUNT_CHECK)); } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java index a1f36f4d98..b409cb103e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java @@ -39,22 +39,19 @@ public class RustUtilTest @Test public void nullParamToEightBitCharacterThrowsNPE() { - assertThrows(NullPointerException.class, () -> - RustUtil.eightBitCharacter(null)); + assertThrows(NullPointerException.class, () -> RustUtil.eightBitCharacter(null)); } @Test public void emptyParamToEightBitCharacterThrowsIAE() { - assertThrows(IllegalArgumentException.class, () -> - RustUtil.eightBitCharacter("")); + assertThrows(IllegalArgumentException.class, () -> RustUtil.eightBitCharacter("")); } @Test public void tooManyCharactersParamToEightBitCharacterThrowsIAE() { - assertThrows(IllegalArgumentException.class, () -> - RustUtil.eightBitCharacter("ABC")); + assertThrows(IllegalArgumentException.class, () -> RustUtil.eightBitCharacter("ABC")); } @Test From 778c61cf94c8cf2a5689f4d70ed59ca698b3e985 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 29 Dec 2021 10:05:54 +0000 Subject: [PATCH 0833/1594] [Java] Enable warnings as errors. --- build.gradle | 1 + .../sbe/generation/rust/RustUtil.java | 20 +++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/build.gradle b/build.gradle index 5c15c8c467..b7979e11b1 100644 --- a/build.gradle +++ b/build.gradle @@ -180,6 +180,7 @@ subprojects { tasks.withType(JavaCompile) { options.encoding = 'UTF-8' options.deprecation = true + options.compilerArgs.addAll(['-Xlint:all', '-Werror']) // Enable all warnings and treat them as errors } javadoc { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index 5e65a327f4..d4326bd179 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -104,18 +104,12 @@ static byte eightBitCharacter(final String asciiCharacter) if (bytes.length != 1) { throw new IllegalArgumentException( - format("String value %s did not fit into a single 8-bit character", asciiCharacter)); + "String value `" + asciiCharacter + "` did not fit into a single 8-bit character"); } return bytes[0]; } - /** - * Format a struct name for the generated code. - * - * @param structName to be formatted. - * @return the formatted struct name. - */ static String formatStructName(final String structName) { return Generators.toUpperFirstChar(structName); @@ -300,7 +294,7 @@ static Appendable indent(final Appendable appendable, final int level, final Str return indent(appendable, level).append(format(f, args)); } - private enum ReservedKeyword + enum ReservedKeyword { Abstract, AlignOf, As, Async, Become, Box, Break, Const, Continue, Crate, Do, Else, Enum, Extern, False, Final, Fn, For, If, Impl, In, @@ -313,13 +307,13 @@ private enum ReservedKeyword static { - Arrays.stream(ReservedKeyword.values()) - .map(java.lang.Enum::name) - .map(String::toLowerCase) - .forEach(LOWER_CASE_NAMES::add); + for (final ReservedKeyword value : ReservedKeyword.values()) + { + LOWER_CASE_NAMES.add(value.name()); + } } - private static boolean anyMatch(final String v) + static boolean anyMatch(final String v) { return LOWER_CASE_NAMES.contains(v.toLowerCase()); } From 08ef8e412165e595d0512b630f4ed7949e7ca340 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 29 Dec 2021 10:38:22 +0000 Subject: [PATCH 0834/1594] [Java] Fix javadoc and scope issues. --- .../uk/co/real_logic/sbe/PrimitiveType.java | 43 ++++ .../uk/co/real_logic/sbe/PrimitiveValue.java | 189 +++++++++++++++--- .../sbe/generation/rust/RustGenerator.java | 6 +- .../co/real_logic/sbe/ir/HeaderStructure.java | 15 ++ .../co/real_logic/sbe/TestTargetLanguage.java | 6 +- 5 files changed, 223 insertions(+), 36 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java index 7fe416e754..7453d4f57e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java @@ -22,16 +22,59 @@ */ public enum PrimitiveType { + /** + * One byte character type which is a flavour of ASCII. + */ CHAR("char", 1, MIN_VALUE_CHAR, MAX_VALUE_CHAR, NULL_VALUE_CHAR), + + /** + * A raw byte or signed 8-bit integer. + */ INT8("int8", 1, MIN_VALUE_INT8, MAX_VALUE_INT8, NULL_VALUE_INT8), + + /** + * A 16-bit signed integer. + */ INT16("int16", 2, MIN_VALUE_INT16, MAX_VALUE_INT16, NULL_VALUE_INT16), + + /** + * A 32-bit signed integer. + */ INT32("int32", 4, MIN_VALUE_INT32, MAX_VALUE_INT32, NULL_VALUE_INT32), + + /** + * A 64-bit signed integer. + */ INT64("int64", 8, MIN_VALUE_INT64, MAX_VALUE_INT64, NULL_VALUE_INT64), + + /** + * A 8-bit unsigned integer. + */ UINT8("uint8", 1, MIN_VALUE_UINT8, MAX_VALUE_UINT8, NULL_VALUE_UINT8), + + /** + * A 16-bit unsigned integer. + */ UINT16("uint16", 2, MIN_VALUE_UINT16, MAX_VALUE_UINT16, NULL_VALUE_UINT16), + + /** + * A 32-bit unsigned integer. + */ UINT32("uint32", 4, MIN_VALUE_UINT32, MAX_VALUE_UINT32, NULL_VALUE_UINT32), + + /** + * A 64-bit unsigned integer. + */ UINT64("uint64", 8, MIN_VALUE_UINT64, MAX_VALUE_UINT64, NULL_VALUE_UINT64), + + /** + * A 32-bit single precision floating point number. + */ FLOAT("float", 4, MIN_VALUE_FLOAT, MAX_VALUE_FLOAT, NULL_VALUE_FLOAT), + + /** + * A 64-bit double precision floating point number. + */ DOUBLE("double", 8, MIN_VALUE_DOUBLE, MAX_VALUE_DOUBLE, NULL_VALUE_DOUBLE); private static final PrimitiveType[] VALUES = PrimitiveType.values(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index e987de53b9..0336953859 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -49,50 +49,179 @@ public enum Representation BYTE_ARRAY } + /** + * Minimum value representation for a char type. + */ public static final long MIN_VALUE_CHAR = 0x20; + + /** + * Maximum value representation for a char type. + */ public static final long MAX_VALUE_CHAR = 0x7E; + + /** + * Null value representation for a char type. + */ public static final long NULL_VALUE_CHAR = 0; + /** + * Minimum value representation for a signed 8-bit type. + */ public static final long MIN_VALUE_INT8 = -127; + + /** + * Maximum value representation for a signed 8-bit type. + */ public static final long MAX_VALUE_INT8 = 127; + + /** + * Null value representation for a signed 8-bit type. + */ public static final long NULL_VALUE_INT8 = -128; + /** + * Minimum value representation for an unsigned 8-bit type. + */ public static final long MIN_VALUE_UINT8 = 0; + + /** + * Maximum value representation for an unsigned 8-bit type. + */ public static final long MAX_VALUE_UINT8 = 254; + + /** + * Null value representation for an unsigned 8-bit type. + */ public static final long NULL_VALUE_UINT8 = 255; + /** + * Minimum value representation for a signed 16-bit type. + */ public static final long MIN_VALUE_INT16 = -32767; + + /** + * Maximum value representation for a signed 16-bit type. + */ public static final long MAX_VALUE_INT16 = 32767; + + /** + * Null value representation for a signed 16-bit type. + */ public static final long NULL_VALUE_INT16 = -32768; + /** + * Minimum value representation for an unsigned 16-bit type. + */ public static final long MIN_VALUE_UINT16 = 0; + + /** + * Maximum value representation for an unsigned 16-bit type. + */ public static final long MAX_VALUE_UINT16 = 65534; + + /** + * Null value representation for an unsigned 16-bit type. + */ public static final long NULL_VALUE_UINT16 = 65535; + /** + * Minimum value representation for a signed 32-bit type. + */ public static final long MIN_VALUE_INT32 = -2147483647; + + /** + * Maximum value representation for a signed 32-bit type. + */ public static final long MAX_VALUE_INT32 = 2147483647; + + /** + * Null value representation for a signed 32-bit type. + */ public static final long NULL_VALUE_INT32 = -2147483648; + /** + * Minimum value representation for an unsigned 32-bit type. + */ public static final long MIN_VALUE_UINT32 = 0; + + /** + * Maximum value representation for an unsigned 32-bit type. + */ public static final long MAX_VALUE_UINT32 = 0xFFFF_FFFFL - 1; + + /** + * Null value representation for an unsigned 32-bit type. + */ public static final long NULL_VALUE_UINT32 = 0xFFFF_FFFFL; + /** + * Minimum value representation for a signed 64-bit type. + */ public static final long MIN_VALUE_INT64 = Long.MIN_VALUE + 1; // (-2 ^ 63) + 1 + + /** + * Maximum value representation for a signed 64-bit type. + */ public static final long MAX_VALUE_INT64 = Long.MAX_VALUE; // ( 2 ^ 63) - 1 + + /** + * Null value representation for a signed 64-bit type. + */ public static final long NULL_VALUE_INT64 = Long.MIN_VALUE; // (-2 ^ 63) + /** + * Minimum value representation for an unsigned 64-bit type. + */ public static final long MIN_VALUE_UINT64 = 0; + + /** + * Maximum value representation for an unsigned 64-bit type. + */ public static final BigInteger BI_MAX_VALUE_UINT64 = new BigInteger("18446744073709551614"); + + /** + * Maximum value representation for an unsigned 64-bit type. + */ public static final long MAX_VALUE_UINT64 = BI_MAX_VALUE_UINT64.longValue(); // (2 ^ 64) - 2 + + /** + * Null value representation for an unsigned 64-bit type. + */ public static final BigInteger BI_NULL_VALUE_UINT64 = new BigInteger("18446744073709551615"); + + /** + * Null value representation for an unsigned 64-bit type. + */ public static final long NULL_VALUE_UINT64 = BI_NULL_VALUE_UINT64.longValue(); // (2 ^ 64) - 1 + /** + * Maximum value representation for a single precision 32-bit floating point type. + */ public static final float MIN_VALUE_FLOAT = Float.MIN_VALUE; + + /** + * Maximum value representation for a single precision 32-bit floating point type. + */ public static final float MAX_VALUE_FLOAT = Float.MAX_VALUE; + + /** + * Null value representation for a single precision 32-bit floating point type. + */ public static final float NULL_VALUE_FLOAT = Float.NaN; + /** + * Minimum value representation for a double precision 64-bit floating point type. + */ public static final double MIN_VALUE_DOUBLE = Double.MIN_VALUE; + + /** + * Maximum value representation for a double precision 64-bit floating point type. + */ public static final double MAX_VALUE_DOUBLE = Double.MAX_VALUE; + + /** + * Null value representation for a double precision 64-bit floating point type. + */ public static final double NULL_VALUE_DOUBLE = Double.NaN; private final Representation representation; @@ -106,8 +235,8 @@ public enum Representation /** * Construct and fill in value as a long. * - * @param value in long format - * @param size of the type in bytes + * @param value in long format. + * @param size of the type in bytes. */ public PrimitiveValue(final long value, final int size) { @@ -138,8 +267,8 @@ public PrimitiveValue(final byte value, final String characterEncoding) /** * Construct and fill in value as a double. * - * @param value in double format - * @param size of the type in bytes + * @param value in double format. + * @param size of the type in bytes. */ public PrimitiveValue(final double value, final int size) { @@ -154,9 +283,9 @@ public PrimitiveValue(final double value, final int size) /** * Construct and fill in value as a byte array. * - * @param value as a byte array - * @param characterEncoding of the characters - * @param size of string in characters + * @param value as a byte array. + * @param characterEncoding of the characters. + * @param size of string in characters. */ public PrimitiveValue(final byte[] value, final String characterEncoding, final int size) { @@ -181,8 +310,8 @@ public Representation representation() /** * Parse constant value string and set representation based on type * - * @param value expressed as a String - * @param primitiveType that this is supposed to be + * @param value expressed as a String. + * @param primitiveType that this is supposed to be. * @return a new {@link PrimitiveValue} for the value. * @throws IllegalArgumentException if parsing malformed type */ @@ -240,8 +369,8 @@ public static PrimitiveValue parse(final String value, final PrimitiveType primi /** * Parse constant value string and set representation based on type * - * @param value expressed as a String - * @param primitiveType that this is supposed to be + * @param value expressed as a String. + * @param primitiveType that this is supposed to be. * @param characterEncoding of the constant value. * @return a new {@link PrimitiveValue} for the value. * @throws IllegalArgumentException if parsing malformed type @@ -265,11 +394,11 @@ public static PrimitiveValue parse( /** * Parse constant value string and set representation based on type, length, and characterEncoding * - * @param value expressed as a String - * @param length of the type - * @param characterEncoding of the String + * @param value expressed as a String. + * @param length of the type. + * @param characterEncoding of the String. * @return a new {@link PrimitiveValue} for the value. - * @throws IllegalArgumentException if parsing malformed type + * @throws IllegalArgumentException if parsing malformed type. */ public static PrimitiveValue parse( final String value, final int length, final String characterEncoding) @@ -289,10 +418,10 @@ public static PrimitiveValue parse( } /** - * Return long value for this PrimitiveValue + * Return long value for this PrimitiveValue. * - * @return value expressed as a long - * @throws IllegalStateException if not a long value representation + * @return value expressed as a long. + * @throws IllegalStateException if not a long value representation. */ public long longValue() { @@ -308,8 +437,8 @@ public long longValue() /** * Return double value for this PrimitiveValue. * - * @return value expressed as a double - * @throws IllegalStateException if not a double value representation + * @return value expressed as a double. + * @throws IllegalStateException if not a double value representation. */ public double doubleValue() { @@ -325,8 +454,8 @@ public double doubleValue() /** * Return byte array value for this PrimitiveValue. * - * @return value expressed as a byte array - * @throws IllegalStateException if not a byte array value representation + * @return value expressed as a byte array. + * @throws IllegalStateException if not a byte array value representation. */ public byte[] byteArrayValue() { @@ -342,9 +471,9 @@ public byte[] byteArrayValue() /** * Return byte array value for this PrimitiveValue given a particular type * - * @param type of this value - * @return value expressed as a byte array - * @throws IllegalStateException if not a byte array value representation + * @param type of this value. + * @return value expressed as a byte array. + * @throws IllegalStateException if not a byte array value representation. */ public byte[] byteArrayValue(final PrimitiveType type) { @@ -364,7 +493,7 @@ else if (representation == Representation.LONG && size == 1 && type == Primitive /** * Return encodedLength for this PrimitiveValue for serialization purposes. * - * @return encodedLength for serialization + * @return encodedLength for serialization. */ public int size() { @@ -416,8 +545,8 @@ else if (Representation.BYTE_ARRAY == representation) /** * Determine if two values are equivalent. * - * @param value to compare this value with - * @return equivalence of values + * @param value to compare this value with. + * @return equivalence of values. */ public boolean equals(final Object value) { @@ -445,9 +574,9 @@ public boolean equals(final Object value) } /** - * Return hashCode for value. This is the underlying representations hashCode for the value + * Return hashCode for value. This is the underlying representations hashCode for the value. * - * @return int value of the hashCode + * @return int value of the hashCode. */ public int hashCode() { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 27ccaea108..8cfdbd888d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -46,9 +46,9 @@ */ public class RustGenerator implements CodeGenerator { - public static final String WRITE_BUF_TYPE = "WriteBuf"; - public static final String READ_BUF_TYPE = "ReadBuf"; - public static final String BUF_LIFETIME = "'a"; + static final String WRITE_BUF_TYPE = "WriteBuf"; + static final String READ_BUF_TYPE = "ReadBuf"; + static final String BUF_LIFETIME = "'a"; enum CodecType { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java index 8bc3144538..4906f10915 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java @@ -26,9 +26,24 @@ */ public class HeaderStructure { + /** + * The field containing the length of the root block in bytes. + */ public static final String BLOCK_LENGTH = "blockLength"; + + /** + * The field containing the template id of the following message. + */ public static final String TEMPLATE_ID = "templateId"; + + /** + * The field containing the schema id to which the following message belongs. + */ public static final String SCHEMA_ID = "schemaId"; + + /** + * The field containing the version of the following message. + */ public static final String SCHEMA_VERSION = "version"; private final List tokens; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java index 54f1fc0adb..550499ce41 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java @@ -23,9 +23,9 @@ public class TestTargetLanguage implements TargetCodeGenerator { - public static final CodeGenerator SINGLETON = mock(CodeGenerator.class); - public static Ir ir = null; - public static String outputDir = ""; + static final CodeGenerator SINGLETON = mock(CodeGenerator.class); + static Ir ir = null; + static String outputDir = ""; public CodeGenerator newInstance(final Ir ir, final String outputDir) { From 838771942bbbdf2ba8df28a4e37c2c9eebc88959 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 29 Dec 2021 10:55:39 +0000 Subject: [PATCH 0835/1594] [Java] Add descriptions to IR. --- .../sbe/ir/generated/ByteOrderCodec.java | 10 ++- .../sbe/ir/generated/FrameCodecDecoder.java | 2 +- .../sbe/ir/generated/FrameCodecEncoder.java | 2 +- .../ir/generated/MessageHeaderDecoder.java | 2 +- .../ir/generated/MessageHeaderEncoder.java | 2 +- .../sbe/ir/generated/PresenceCodec.java | 14 ++- .../sbe/ir/generated/PrimitiveTypeCodec.java | 50 ++++++++++- .../sbe/ir/generated/SignalCodec.java | 70 ++++++++++++++- .../sbe/ir/generated/TokenCodecDecoder.java | 2 +- .../sbe/ir/generated/TokenCodecEncoder.java | 2 +- .../ir/generated/VarDataEncodingDecoder.java | 2 +- .../ir/generated/VarDataEncodingEncoder.java | 2 +- sbe-tool/src/main/resources/sbe-ir.xml | 86 +++++++++---------- 13 files changed, 191 insertions(+), 55 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java index cec61c4eed..fc8fd3463b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java @@ -3,12 +3,20 @@ /** - * Number encoding byte order + * Number encoding byte order. */ public enum ByteOrderCodec { + + /** + * Little Endian byte encoding. + */ SBE_LITTLE_ENDIAN((short)0), + + /** + * Big Endian byte encoding. + */ SBE_BIG_ENDIAN((short)1), /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 2c0f88f97a..1fc4a81cdd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -6,7 +6,7 @@ /** - * Frame Header for start of encoding IR + * Frame Header for start of encoding IR. */ @SuppressWarnings("all") public final class FrameCodecDecoder diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index e2534e99b9..3fca868e13 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -6,7 +6,7 @@ /** - * Frame Header for start of encoding IR + * Frame Header for start of encoding IR. */ @SuppressWarnings("all") public final class FrameCodecEncoder diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java index 04223e1e06..d83fa30430 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java @@ -5,7 +5,7 @@ /** - * Message identifiers and length of message root + * Message identifiers and length of message root. */ @SuppressWarnings("all") public final class MessageHeaderDecoder diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java index 6aa30f16eb..f295379b98 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java @@ -5,7 +5,7 @@ /** - * Message identifiers and length of message root + * Message identifiers and length of message root. */ @SuppressWarnings("all") public final class MessageHeaderEncoder diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java index 638926218e..ceea18d898 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java @@ -3,14 +3,26 @@ /** - * Field presence declaration + * Field presence declaration. */ public enum PresenceCodec { + + /** + * A field is required. + */ SBE_REQUIRED((short)0), + + /** + * A field is optional. + */ SBE_OPTIONAL((short)1), + + /** + * A field is a constant value. + */ SBE_CONSTANT((short)2), /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java index 4dca2be18d..bc2f89cde3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java @@ -3,32 +3,80 @@ /** - * Primitive types in type system + * Primitive types in type system. */ public enum PrimitiveTypeCodec { + + /** + * No type is provided. + */ NONE((short)0), + + /** + * Single byte character encoding in ASCII. + */ CHAR((short)1), + + /** + * 8-bit signed integer. + */ INT8((short)2), + + /** + * 16-bit signed integer. + */ INT16((short)3), + + /** + * 32-bit signed integer. + */ INT32((short)4), + + /** + * 64-bit signed integer. + */ INT64((short)5), + + /** + * 8-bit unsigned integer. + */ UINT8((short)6), + + /** + * 16-bit unsigned integer. + */ UINT16((short)7), + + /** + * 32-bit unsigned integer. + */ UINT32((short)8), + + /** + * 64-bit unsigned integer. + */ UINT64((short)9), + + /** + * 32-bit single precision floating point. + */ FLOAT((short)10), + + /** + * 64-bit double precision floating point. + */ DOUBLE((short)11), /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java index 3a932483bc..59940ef860 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java @@ -3,42 +3,110 @@ /** - * Token signal type in IR + * Token signal type in IR. */ public enum SignalCodec { + + /** + * Signal the beginning of a message. + */ BEGIN_MESSAGE((short)1), + + /** + * Signal the end of a message. + */ END_MESSAGE((short)2), + + /** + * Signal the beginning of a composite. + */ BEGIN_COMPOSITE((short)3), + + /** + * Signal the end of a composite. + */ END_COMPOSITE((short)4), + + /** + * Signal the beginning of a field. + */ BEGIN_FIELD((short)5), + + /** + * Signal end beginning of a field. + */ END_FIELD((short)6), + + /** + * Signal the beginning of a group. + */ BEGIN_GROUP((short)7), + + /** + * Signal the end of a group. + */ END_GROUP((short)8), + + /** + * Signal the beginning of a enum. + */ BEGIN_ENUM((short)9), + + /** + * Signal a value of an enum. + */ VALID_VALUE((short)10), + + /** + * Signal the end of a enum. + */ END_ENUM((short)11), + + /** + * Signal the beginning of a set. + */ BEGIN_SET((short)12), + + /** + * Signal the a choice in a set. + */ CHOICE((short)13), + + /** + * Signal the end of a set. + */ END_SET((short)14), + + /** + * Signal the beginning of variable data. + */ BEGIN_VAR_DATA((short)15), + + /** + * Signal the end of variable data. + */ END_VAR_DATA((short)16), + + /** + * Signal the encoding of a field. + */ ENCODING((short)17), /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 9e8b467ae5..674a2cd566 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -6,7 +6,7 @@ /** - * Codec for an IR Token + * Codec for an IR Token. */ @SuppressWarnings("all") public final class TokenCodecDecoder diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index 1af7ed2f53..1790f6f10b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -6,7 +6,7 @@ /** - * Codec for an IR Token + * Codec for an IR Token. */ @SuppressWarnings("all") public final class TokenCodecEncoder diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java index b227f42d29..9b067585e4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java @@ -5,7 +5,7 @@ /** - * Header for var data fields + * Header for var data fields. */ @SuppressWarnings("all") public final class VarDataEncodingDecoder diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java index 1909b37f7d..d86d2879a2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java @@ -5,7 +5,7 @@ /** - * Header for var data fields + * Header for var data fields. */ @SuppressWarnings("all") public final class VarDataEncodingEncoder diff --git a/sbe-tool/src/main/resources/sbe-ir.xml b/sbe-tool/src/main/resources/sbe-ir.xml index 4aa581e49c..9d70ef93db 100644 --- a/sbe-tool/src/main/resources/sbe-ir.xml +++ b/sbe-tool/src/main/resources/sbe-ir.xml @@ -6,66 +6,66 @@ byteOrder="littleEndian" description="SBE IR Serialization Codecs."> - + - + - + - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 - - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 15 - 16 - 17 + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 - - 0 - 1 + + 0 + 1 - - 0 - 1 - 2 + + 0 + 1 + 2 - + @@ -74,7 +74,7 @@ - + From a0b19fa6bac54661cee04a4778316cf5de350a22 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 29 Dec 2021 11:08:32 +0000 Subject: [PATCH 0836/1594] [Java] Simplify use of display builders for Java and C Sharp. --- .../generation/csharp/CSharpGenerator.java | 22 +++++++------- .../sbe/generation/csharp/CSharpUtil.java | 20 +++---------- .../sbe/generation/java/JavaGenerator.java | 30 +++++++++---------- .../sbe/generation/java/JavaUtil.java | 11 ++----- 4 files changed, 32 insertions(+), 51 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 6d9f9d7a38..cef39009bb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1572,9 +1572,9 @@ private void appendGroupInstanceDisplay( append(sb, indent, " return;"); append(sb, indent, " }"); sb.append('\n'); - Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT); appendDisplay(sb, fields, groups, varData, indent + INDENT); - Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT); sb.append('\n'); append(sb, indent, "}"); } @@ -1635,7 +1635,7 @@ private void appendDisplay( append(sb, indent, "builder.Append(\"" + Separators.END_GROUP + "\");"); lengthBeforeLastGeneratedSeparator = sb.length(); - Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + Separators.FIELD.appendToGeneratedBuilder(sb, indent); i = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); } @@ -1667,7 +1667,7 @@ private void appendDisplay( } lengthBeforeLastGeneratedSeparator = sb.length(); - Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + Separators.FIELD.appendToGeneratedBuilder(sb, indent); i += varDataToken.componentTokenCount(); } @@ -1712,7 +1712,7 @@ private int writeTokenDisplay( } else { - Separators.BEGIN_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); + Separators.BEGIN_ARRAY.appendToGeneratedBuilder(sb, indent); append(sb, indent, "for (int i = 0; i < " + fieldName + "Length; ++i)"); append(sb, indent, "{"); append(sb, indent, " if (i > 0)"); @@ -1721,7 +1721,7 @@ private int writeTokenDisplay( append(sb, indent, " }"); append(sb, indent, " builder.Append(Get" + fieldName + "(i));"); append(sb, indent, "}"); - Separators.END_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); + Separators.END_ARRAY.appendToGeneratedBuilder(sb, indent); } } else @@ -1754,7 +1754,7 @@ private int writeTokenDisplay( } final int lengthBeforeFieldSeparator = sb.length(); - Separators.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + Separators.FIELD.appendToGeneratedBuilder(sb, indent); return lengthBeforeFieldSeparator; } @@ -1779,9 +1779,9 @@ private CharSequence generateChoiceDisplay(final String enumName) append(sb, INDENT, "{"); append(sb, TWO_INDENT, "internal static void BuildString(this " + enumName + " val, StringBuilder builder)"); append(sb, TWO_INDENT, "{"); - Separators.BEGIN_SET.appendToGeneratedBuilder(sb, THREE_INDENT, "builder"); + Separators.BEGIN_SET.appendToGeneratedBuilder(sb, THREE_INDENT); append(sb, THREE_INDENT, "builder.Append(val.ToString());"); - Separators.END_SET.appendToGeneratedBuilder(sb, THREE_INDENT, "builder"); + Separators.END_SET.appendToGeneratedBuilder(sb, THREE_INDENT); append(sb, TWO_INDENT, "}"); append(sb, INDENT, "}"); return sb; @@ -1847,7 +1847,7 @@ private CharSequence generateCompositeDisplay(final List tokens) append(sb, TWO_INDENT, " return;"); append(sb, TWO_INDENT, " }"); sb.append('\n'); - Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, THREE_INDENT, "builder"); + Separators.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, THREE_INDENT); int lengthBeforeLastGeneratedSeparator = -1; @@ -1864,7 +1864,7 @@ private CharSequence generateCompositeDisplay(final List tokens) sb.setLength(lengthBeforeLastGeneratedSeparator); } - Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, THREE_INDENT, "builder"); + Separators.END_COMPOSITE.appendToGeneratedBuilder(sb, THREE_INDENT); sb.append('\n'); append(sb, TWO_INDENT, "}"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index 82f9114ae3..3a6a10d0f6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -21,17 +21,12 @@ import java.util.EnumMap; import java.util.Map; - /** * Utilities for mapping between IR and the C# language. */ public class CSharpUtil { - - /** - * Useful separator constants for code generation - */ - public enum Separators + enum Separators { BEGIN_GROUP('['), END_GROUP(']'), @@ -52,20 +47,14 @@ public enum Separators this.symbol = symbol; } - /** - * Add separator to a generated append to a {@link StringBuilder}. - * - * @param builder the code generation builder to which information should be added - * @param indent the current generated code indentation - * @param builderName the generated StringBuilder to which separator should be added - */ - public void appendToGeneratedBuilder(final StringBuilder builder, final String indent, final String builderName) + void appendToGeneratedBuilder(final StringBuilder builder, final String indent) { - builder.append(indent).append(builderName).append(".Append('").append(symbol).append("');").append('\n'); + builder.append(indent).append("builder.Append('").append(symbol).append("');").append('\n'); } /** * Returns the string value of this separator. + * * @return the string value of this separator */ public String toString() @@ -182,5 +171,4 @@ public static void append(final StringBuilder builder, final String indent, fina { builder.append(indent).append(line).append('\n'); } - } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index a96f018116..e2d96b4927 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3331,7 +3331,7 @@ private CharSequence generateCompositeDecoderDisplay(final List tokens) append(sb, INDENT, " return builder;"); append(sb, INDENT, " }"); sb.append('\n'); - Separator.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, INDENT + INDENT, "builder"); + Separator.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, INDENT + INDENT); int lengthBeforeLastGeneratedSeparator = -1; @@ -3348,7 +3348,7 @@ private CharSequence generateCompositeDecoderDisplay(final List tokens) sb.setLength(lengthBeforeLastGeneratedSeparator); } - Separator.END_COMPOSITE.appendToGeneratedBuilder(sb, INDENT + INDENT, "builder"); + Separator.END_COMPOSITE.appendToGeneratedBuilder(sb, INDENT + INDENT); sb.append('\n'); append(sb, INDENT, " return builder;"); append(sb, INDENT, "}"); @@ -3364,7 +3364,7 @@ private CharSequence generateChoiceDisplay(final List tokens) sb.append('\n'); append(sb, INDENT, "public StringBuilder appendTo(final StringBuilder builder)"); append(sb, INDENT, "{"); - Separator.BEGIN_SET.appendToGeneratedBuilder(sb, INDENT + INDENT, "builder"); + Separator.BEGIN_SET.appendToGeneratedBuilder(sb, INDENT + INDENT); append(sb, INDENT, " boolean atLeastOne = false;"); for (final Token token : tokens) @@ -3376,7 +3376,7 @@ private CharSequence generateChoiceDisplay(final List tokens) append(sb, INDENT, " {"); append(sb, INDENT, " if (atLeastOne)"); append(sb, INDENT, " {"); - Separator.ENTRY.appendToGeneratedBuilder(sb, INDENT + INDENT + INDENT + INDENT, "builder"); + Separator.ENTRY.appendToGeneratedBuilder(sb, INDENT + INDENT + INDENT + INDENT); append(sb, INDENT, " }"); append(sb, INDENT, " builder.append(\"" + choiceName + "\");"); append(sb, INDENT, " atLeastOne = true;"); @@ -3384,7 +3384,7 @@ private CharSequence generateChoiceDisplay(final List tokens) } } - Separator.END_SET.appendToGeneratedBuilder(sb, INDENT + INDENT, "builder"); + Separator.END_SET.appendToGeneratedBuilder(sb, INDENT + INDENT); sb.append('\n'); append(sb, INDENT, " return builder;"); append(sb, INDENT, "}"); @@ -3454,9 +3454,9 @@ private void appendGroupInstanceDecoderDisplay( append(sb, indent, " return builder;"); append(sb, indent, " }"); sb.append('\n'); - Separator.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + Separator.BEGIN_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT); appendDecoderDisplay(sb, fields, groups, varData, indent + INDENT); - Separator.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT, "builder"); + Separator.END_COMPOSITE.appendToGeneratedBuilder(sb, indent + INDENT); sb.append('\n'); append(sb, indent, " return builder;"); append(sb, indent, "}"); @@ -3507,14 +3507,14 @@ private void appendDecoderDisplay( append(sb, indent, " while (" + groupName + ".hasNext())"); append(sb, indent, " {"); append(sb, indent, " " + groupName + ".next().appendTo(builder);"); - Separator.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT, "builder"); + Separator.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT); append(sb, indent, " }"); append(sb, indent, " builder.setLength(builder.length() - 1);"); append(sb, indent, "}"); - Separator.END_GROUP.appendToGeneratedBuilder(sb, indent, "builder"); + Separator.END_GROUP.appendToGeneratedBuilder(sb, indent); lengthBeforeLastGeneratedSeparator = sb.length(); - Separator.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + Separator.FIELD.appendToGeneratedBuilder(sb, indent); i = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); } @@ -3550,7 +3550,7 @@ private void appendDecoderDisplay( } lengthBeforeLastGeneratedSeparator = sb.length(); - Separator.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + Separator.FIELD.appendToGeneratedBuilder(sb, indent); i += varDataToken.componentTokenCount(); } @@ -3586,17 +3586,17 @@ private int writeTokenDisplay( } else { - Separator.BEGIN_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); + Separator.BEGIN_ARRAY.appendToGeneratedBuilder(sb, indent); append(sb, indent, "if (" + fieldName + "Length() > 0)"); append(sb, indent, "{"); append(sb, indent, " for (int i = 0; i < " + fieldName + "Length(); i++)"); append(sb, indent, " {"); append(sb, indent, " builder.append(" + fieldName + "(i));"); - Separator.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT, "builder"); + Separator.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT); append(sb, indent, " }"); append(sb, indent, " builder.setLength(builder.length() - 1);"); append(sb, indent, "}"); - Separator.END_ARRAY.appendToGeneratedBuilder(sb, indent, "builder"); + Separator.END_ARRAY.appendToGeneratedBuilder(sb, indent); } } else @@ -3631,7 +3631,7 @@ private int writeTokenDisplay( } final int lengthBeforeFieldSeparator = sb.length(); - Separator.FIELD.appendToGeneratedBuilder(sb, indent, "builder"); + Separator.FIELD.appendToGeneratedBuilder(sb, indent); return lengthBeforeFieldSeparator; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 4da409b6d8..839923d2e1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -61,16 +61,9 @@ enum Separator this.symbol = symbol; } - /** - * Add separator to a generated append to a {@link StringBuilder}. - * - * @param builder the code generation builder to which information should be added - * @param indent the current generated code indentation - * @param builderName of the generated StringBuilder to which separator should be added - */ - void appendToGeneratedBuilder(final StringBuilder builder, final String indent, final String builderName) + void appendToGeneratedBuilder(final StringBuilder builder, final String indent) { - builder.append(indent).append(builderName).append(".append('").append(symbol).append("');").append('\n'); + builder.append(indent).append("builder.append('").append(symbol).append("');").append('\n'); } /** From e4da8fa2a268695ef92118d65337c5f708c3eacd Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 29 Dec 2021 19:46:17 +0000 Subject: [PATCH 0837/1594] [Java] Upgrade to Shadow 7.1.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b7979e11b1..bf23f7754c 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ import java.security.MessageDigest plugins { id 'java-library' - id 'com.github.johnrengelman.shadow' version '7.1.1' apply false + id 'com.github.johnrengelman.shadow' version '7.1.2' apply false id "com.github.ben-manes.versions" version "0.39.0" } From 2b91e1bd100ada4faed30cb288ec6f1f2986f872 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 29 Dec 2021 19:57:05 +0000 Subject: [PATCH 0838/1594] [Java] Upgrade to Checkstyle 9.2.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bf23f7754c..c31bcc58e0 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ def toolchainLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } -def checkstyleVersion = '9.2' +def checkstyleVersion = '9.2.1' def hamcrestVersion = '2.2' def mockitoVersion = '4.2.0' def junitVersion = '5.8.2' From 43b458ce7ab782f866185fb42f4a29b49e6cb46a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 1 Jan 2022 09:08:45 +0000 Subject: [PATCH 0839/1594] [Java] Upgrade to version 0.40.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c31bcc58e0..dccbca6ad5 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ import java.security.MessageDigest plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '7.1.2' apply false - id "com.github.ben-manes.versions" version "0.39.0" + id "com.github.ben-manes.versions" version "0.40.0" } defaultTasks 'clean', 'build' From 248299d84dc4203766e955945d633f030c6a6b7b Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 3 Jan 2022 10:06:16 +0100 Subject: [PATCH 0840/1594] [Java] Regenerate Gradle wrapper scripts. --- gradlew | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gradlew b/gradlew index c53aefaa5f..1b6c787337 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,10 +32,10 @@ # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # From 796a44887c2aaa6c570dc46f7c55e302dcc1161d Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 6 Jan 2022 20:34:36 +0000 Subject: [PATCH 0841/1594] [Java] Upgrade to Versions 0.41.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index dccbca6ad5..e4d41d6416 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ import java.security.MessageDigest plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '7.1.2' apply false - id "com.github.ben-manes.versions" version "0.40.0" + id "com.github.ben-manes.versions" version "0.41.0" } defaultTasks 'clean', 'build' From ff8d2c9ab2773b0051cd9e701981ef72232c26c5 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 8 Jan 2022 10:57:29 +0100 Subject: [PATCH 0842/1594] [Java] Charset encoding handling improvements. (#887) * [Java] Use StandardCharsets when generating `CharacterEncoding` methods and make alias names case-insensitive. * [Java] Use `putStringWithoutLengthAscii` for ASCII-encoded property when input is a `CharSequence`. * [Java] Replace use an actual CharSet instance when invoking String constructor and getBytes. * [Java] Use `ArrayUtil.EMPTY_BYTE_ARRAY` instead of creating `byte[0]` when input string is null or empty. * [Java] Add assertions around Charset usage. * [Java] Add an explicit test for case-insensitive alias and remove extra output. * [Java] Resolve canonical charset name when not a standard charset. * [Java] Do not convert character encoding to upper case, i.e. treat character encoding as case-sensitive. --- .../generation/golang/GolangGenerator.java | 49 ++--- .../sbe/generation/java/JavaGenerator.java | 53 ++--- .../sbe/generation/java/JavaUtil.java | 71 ++++++- .../sbe/generation/rust/RustGenerator.java | 51 ++--- .../sbe/ir/generated/FrameCodecDecoder.java | 42 +--- .../sbe/ir/generated/FrameCodecEncoder.java | 36 +--- .../sbe/ir/generated/TokenCodecDecoder.java | 154 ++------------ .../sbe/ir/generated/TokenCodecEncoder.java | 132 ++---------- .../real_logic/sbe/xml/EncodedDataType.java | 4 +- .../java/CharacterEncodingTest.java | 195 ++++++++++++++++++ .../sbe/xml/EncodedDataTypeTest.java | 43 ++++ 11 files changed, 423 insertions(+), 407 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index 4118130c4d..0e5d8438ba 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -20,6 +20,7 @@ import uk.co.real_logic.sbe.generation.CodeGenerator; import org.agrona.generation.OutputManager; import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.generation.java.JavaUtil; import uk.co.real_logic.sbe.ir.*; import org.agrona.Verify; @@ -244,29 +245,31 @@ private void generateCharacterEncodingRangeCheck( if (null != characterEncoding) { - switch (token.encoding().characterEncoding()) + if (JavaUtil.isAsciiEncoding(characterEncoding)) { - case "ASCII": - imports.peek().add("fmt"); - sb.append(String.format( - "\tfor idx, ch := range %1$s {\n" + - "\t\tif ch > 127 {\n" + - "\t\t\treturn fmt.Errorf(\"%1$s[%%d]=%%d" + - " failed ASCII validation\", idx, ch)\n" + - "\t\t}\n" + - "\t}\n", - varName)); - break; - - case "UTF-8": - imports.peek().add("errors"); - imports.peek().add("unicode/utf8"); - sb.append(String.format( - "\tif !utf8.Valid(%1$s[:]) {\n" + - "\t\treturn errors.New(\"%1$s failed UTF-8 validation\")\n" + - "\t}\n", - varName)); - break; + imports.peek().add("fmt"); + sb.append(String.format( + "\tfor idx, ch := range %1$s {\n" + + "\t\tif ch > 127 {\n" + + "\t\t\treturn fmt.Errorf(\"%1$s[%%d]=%%d" + + " failed ASCII validation\", idx, ch)\n" + + "\t\t}\n" + + "\t}\n", + varName)); + } + else if (JavaUtil.isUtf8Encoding(characterEncoding)) + { + imports.peek().add("errors"); + imports.peek().add("unicode/utf8"); + sb.append(String.format( + "\tif !utf8.Valid(%1$s[:]) {\n" + + "\t\treturn errors.New(\"%1$s failed UTF-8 validation\")\n" + + "\t}\n", + varName)); + } + else + { + throw new IllegalArgumentException("Unsupported encoding: " + characterEncoding); } } } @@ -1836,7 +1839,7 @@ private void generateCompositePropertyElements( final String containingTypeName, final List tokens) { - for (int i = 0; i < tokens.size();) + for (int i = 0; i < tokens.size(); ) { final Token token = tokens.get(i); final String propertyName = formatPropertyName(token.name()); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index e2d96b4927..4272a8f436 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -921,25 +921,16 @@ private void generateDataDecodeMethods( indent + " }\n\n" + indent + " final byte[] tmp = new byte[dataLength];\n" + indent + " buffer.getBytes(limit + headerLength, tmp, 0, dataLength);\n\n" + - indent + " final String value;\n" + - indent + " try\n" + - indent + " {\n" + - indent + " value = new String(tmp, \"%6$s\");\n" + - indent + " }\n" + - indent + " catch (final java.io.UnsupportedEncodingException ex)\n" + - indent + " {\n" + - indent + " throw new RuntimeException(ex);\n" + - indent + " }\n\n" + - indent + " return value;\n" + + indent + " return new String(tmp, %6$s);\n" + indent + " }\n", formatPropertyName(propertyName), generateStringNotPresentCondition(token.version(), indent), sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", generateGet(lengthType, "limit", byteOrderStr), - characterEncoding); + charset(characterEncoding)); - if (characterEncoding.contains("ASCII")) + if (isAsciiEncoding(characterEncoding)) { new Formatter(sb).format("\n" + indent + " public int get%1$s(final Appendable appendable)\n" + @@ -1050,7 +1041,7 @@ private void generateCharArrayEncodeMethods( { final PrimitiveType lengthPutType = PrimitiveType.UINT32 == lengthType ? PrimitiveType.INT32 : lengthType; - if (characterEncoding.contains("ASCII")) + if (isAsciiEncoding(characterEncoding)) { new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final String value)\n" + @@ -1099,16 +1090,8 @@ private void generateCharArrayEncodeMethods( new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final String value)\n" + indent + " {\n" + - indent + " final byte[] bytes;\n" + - indent + " try\n" + - indent + " {\n" + - indent + " bytes = null == value || value.isEmpty() ?" + - " org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(\"%3$s\");\n" + - indent + " }\n" + - indent + " catch (final java.io.UnsupportedEncodingException ex)\n" + - indent + " {\n" + - indent + " throw new RuntimeException(ex);\n" + - indent + " }\n\n" + + indent + " final byte[] bytes = (null == value || value.isEmpty()) ?" + + " org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(%3$s);\n\n" + indent + " final int length = bytes.length;\n" + indent + " if (length > %4$d)\n" + indent + " {\n" + @@ -1123,7 +1106,7 @@ private void generateCharArrayEncodeMethods( indent + " }\n", className, formatPropertyName(propertyName), - characterEncoding, + charset(characterEncoding), maxLengthValue, sizeOfLengthField, generatePut(lengthPutType, "limit", "length", byteOrderStr)); @@ -2042,7 +2025,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( fieldLength, charset(encoding.characterEncoding())); - if (encoding.characterEncoding().contains("ASCII")) + if (isAsciiEncoding(encoding.characterEncoding())) { new Formatter(sb).format("\n" + indent + " public int get%1$s(final Appendable value)\n" + @@ -2240,7 +2223,7 @@ private void generateCharArrayEncodeMethods( fieldLength, offset); - if (encoding.characterEncoding().contains("ASCII")) + if (isAsciiEncoding(encoding.characterEncoding())) { new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final String src)\n" + @@ -2274,15 +2257,10 @@ private void generateCharArrayEncodeMethods( indent + " throw new IndexOutOfBoundsException(" + "\"CharSequence too large for copy: byte length=\" + srcLength);\n" + indent + " }\n\n" + - indent + " for (int i = 0; i < srcLength; ++i)\n" + - indent + " {\n" + - indent + " final char charValue = src.charAt(i);\n" + - indent + " final byte byteValue = charValue > 127 ? (byte)'?' : (byte)charValue;\n" + - indent + " buffer.putByte(offset + %4$d + i, byteValue);\n" + - indent + " }\n\n" + - indent + " for (int i = srcLength; i < length; ++i)\n" + + indent + " buffer.putStringWithoutLengthAscii(offset + %4$d, src);\n\n" + + indent + " for (int start = srcLength; start < length; ++start)\n" + indent + " {\n" + - indent + " buffer.putByte(offset + %4$d + i, (byte)0);\n" + + indent + " buffer.putByte(offset + %4$d + start, (byte)0);\n" + indent + " }\n\n" + indent + " return this;\n" + indent + " }\n", @@ -2297,7 +2275,8 @@ private void generateCharArrayEncodeMethods( indent + " public %s %s(final String src)\n" + indent + " {\n" + indent + " final int length = %d;\n" + - indent + " final byte[] bytes = null == src ? new byte[0] : src.getBytes(%s);\n" + + indent + " final byte[] bytes = (null == src || src.isEmpty()) ?" + + " org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : src.getBytes(%s);\n" + indent + " if (bytes.length > length)\n" + indent + " {\n" + indent + " throw new IndexOutOfBoundsException(" + @@ -2387,7 +2366,7 @@ private static void generateCharacterEncodingMethod( sb.append("\n") .append(indent).append(" public static String ").append(propName).append("CharacterEncoding()\n") .append(indent).append(" {\n") - .append(indent).append(" return \"").append(characterEncoding).append("\";\n") + .append(indent).append(" return ").append(charsetName(characterEncoding)).append(";\n") .append(indent).append(" }\n"); } } @@ -3537,7 +3516,7 @@ private void appendDecoderDisplay( } else { - if (characterEncoding.contains("ASCII") || characterEncoding.contains("ascii")) + if (isAsciiEncoding(characterEncoding)) { append(sb, indent, "builder.append('\\'');"); append(sb, indent, formatGetterName(varDataToken.name()) + "(builder);"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 839923d2e1..f6969c111e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -18,20 +18,19 @@ import org.agrona.Strings; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.SbeTool; +import uk.co.real_logic.sbe.ValidationUtil; import uk.co.real_logic.sbe.generation.Generators; import uk.co.real_logic.sbe.ir.Token; -import uk.co.real_logic.sbe.ValidationUtil; import java.io.IOException; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.EnumMap; import java.util.HashMap; import java.util.Map; -import static java.lang.reflect.Modifier.STATIC; - /** * Utilities for mapping between {@link uk.co.real_logic.sbe.ir.Ir} and the Java language. */ @@ -96,7 +95,7 @@ public String toString() /** * Indexes known charset aliases to the name of the instance in {@link StandardCharsets}. */ - private static final Map STD_CHARSETS = new HashMap<>(); + static final HashMap STD_CHARSETS = new HashMap<>(); static { @@ -104,11 +103,25 @@ public String toString() { for (final Field field : StandardCharsets.class.getDeclaredFields()) { - if (Charset.class.isAssignableFrom(field.getType()) && ((field.getModifiers() & STATIC) == STATIC)) + if (Charset.class.isAssignableFrom(field.getType()) && Modifier.isStatic(field.getModifiers()) && + Modifier.isPublic(field.getModifiers())) { final Charset charset = (Charset)field.get(null); - STD_CHARSETS.put(charset.name(), field.getName()); - charset.aliases().forEach((alias) -> STD_CHARSETS.put(alias, field.getName())); + final String name = field.getName(); + String oldName = STD_CHARSETS.put(charset.name(), name); + if (null != oldName) + { + throw new IllegalStateException("Duplicate charset alias: old=" + oldName + ", new=" + name); + } + for (final String alias : charset.aliases()) + { + oldName = STD_CHARSETS.put(alias, name); + if (null != oldName) + { + throw new IllegalStateException("Duplicate charset alias: old=" + oldName + ", new=" + + alias); + } + } } } } @@ -207,10 +220,52 @@ public static String charset(final String encoding) } else { - return "java.nio.charset.Charset.forName(\"" + encoding + "\")"; + final String canonicalName = Charset.isSupported(encoding) ? Charset.forName(encoding).name() : encoding; + return "java.nio.charset.Charset.forName(\"" + canonicalName + "\")"; } } + /** + * Code to fetch the name of the {@link Charset} given the encoding. + * + * @param encoding as a string name (eg. UTF-8). + * @return the code to fetch the associated Charset name. + */ + public static String charsetName(final String encoding) + { + final String charsetName = STD_CHARSETS.get(encoding); + if (charsetName != null) + { + return "java.nio.charset.StandardCharsets." + charsetName + ".name()"; + } + else + { + return "\"" + (Charset.isSupported(encoding) ? Charset.forName(encoding).name() : encoding) + "\""; + } + } + + /** + * Checks if the given encoding represents an ASCII charset. + * + * @param encoding as a string name (e.g. ASCII). + * @return {@code true} if the encoding denotes an ASCII charset. + */ + public static boolean isAsciiEncoding(final String encoding) + { + return "US_ASCII".equals(STD_CHARSETS.get(encoding)); + } + + /** + * Checks if the given encoding represents a UTF-8 charset. + * + * @param encoding as a string name (e.g. unicode-1-1-utf-8). + * @return {@code true} if the encoding denotes a UTF-8 charset. + */ + public static boolean isUtf8Encoding(final String encoding) + { + return "UTF_8".equals(STD_CHARSETS.get(encoding)); + } + /** * Generate a literal value to be used in code generation. * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 8cfdbd888d..b3abad386c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -20,6 +20,7 @@ import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.generation.CodeGenerator; import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.generation.java.JavaUtil; import uk.co.real_logic.sbe.ir.Encoding; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.ir.Signal; @@ -304,20 +305,15 @@ static void generateEncoderVarData( final String varDataType; final String toBytesFn; - switch (characterEncoding) + if (JavaUtil.isUtf8Encoding(characterEncoding)) { - case "UTF-8": - { - varDataType = "&str"; - toBytesFn = ".as_bytes()"; - break; - } - default: - { - varDataType = "&[u8]"; - toBytesFn = ""; - break; - } + varDataType = "&str"; + toBytesFn = ".as_bytes()"; + } + else + { + varDataType = "&[u8]"; + toBytesFn = ""; } // function to write slice ... todo - handle character encoding ? @@ -681,23 +677,20 @@ private static void generatePrimitiveConstantDecoder( indent(sb, level, "/// characterEncoding: '%s'\n", characterEncoding); indent(sb, level, "#[inline]\n"); - switch (characterEncoding) + if (JavaUtil.isAsciiEncoding(characterEncoding)) { - case "US-ASCII": - { - indent(sb, level, "pub fn %s(&self) -> &'static [u8] {\n", - formatFunctionName(name)); - indent(sb, level + 1, "b\"%s\"\n", rawConstValue); - break; - } - case "UTF-8": - { - indent(sb, level, "pub fn %s(&self) -> &'static str {\n", formatFunctionName(name)); - indent(sb, level + 1, "\"%s\"\n", rawConstValue); - break; - } - default: - throw new RuntimeException("Unable to handle " + characterEncoding); + indent(sb, level, "pub fn %s(&self) -> &'static [u8] {\n", + formatFunctionName(name)); + indent(sb, level + 1, "b\"%s\"\n", rawConstValue); + } + else if (JavaUtil.isUtf8Encoding(characterEncoding)) + { + indent(sb, level, "pub fn %s(&self) -> &'static str {\n", formatFunctionName(name)); + indent(sb, level + 1, "\"%s\"\n", rawConstValue); + } + else + { + throw new IllegalArgumentException("Unsupported encoding: " + characterEncoding); } indent(sb, level, "}\n\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 1fc4a81cdd..d958498953 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -299,7 +299,7 @@ public static int packageNameSinceVersion() public static String packageNameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String packageNameMetaAttribute(final MetaAttribute metaAttribute) @@ -382,17 +382,7 @@ public String packageName() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int namespaceNameId() @@ -407,7 +397,7 @@ public static int namespaceNameSinceVersion() public static String namespaceNameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String namespaceNameMetaAttribute(final MetaAttribute metaAttribute) @@ -490,17 +480,7 @@ public String namespaceName() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int semanticVersionId() @@ -515,7 +495,7 @@ public static int semanticVersionSinceVersion() public static String semanticVersionCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String semanticVersionMetaAttribute(final MetaAttribute metaAttribute) @@ -598,17 +578,7 @@ public String semanticVersion() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public String toString() diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index 3fca868e13..4bcc266652 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -267,7 +267,7 @@ public static int packageNameId() public static String packageNameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String packageNameMetaAttribute(final MetaAttribute metaAttribute) @@ -319,15 +319,7 @@ public FrameCodecEncoder putPackageName(final byte[] src, final int srcOffset, f public FrameCodecEncoder packageName(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -351,7 +343,7 @@ public static int namespaceNameId() public static String namespaceNameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String namespaceNameMetaAttribute(final MetaAttribute metaAttribute) @@ -403,15 +395,7 @@ public FrameCodecEncoder putNamespaceName(final byte[] src, final int srcOffset, public FrameCodecEncoder namespaceName(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -435,7 +419,7 @@ public static int semanticVersionId() public static String semanticVersionCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String semanticVersionMetaAttribute(final MetaAttribute metaAttribute) @@ -487,15 +471,7 @@ public FrameCodecEncoder putSemanticVersion(final byte[] src, final int srcOffse public FrameCodecEncoder semanticVersion(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 674a2cd566..cfac525b67 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -616,7 +616,7 @@ public static int nameSinceVersion() public static String nameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String nameMetaAttribute(final MetaAttribute metaAttribute) @@ -699,17 +699,7 @@ public String name() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int constValueId() @@ -724,7 +714,7 @@ public static int constValueSinceVersion() public static String constValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String constValueMetaAttribute(final MetaAttribute metaAttribute) @@ -807,17 +797,7 @@ public String constValue() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int minValueId() @@ -832,7 +812,7 @@ public static int minValueSinceVersion() public static String minValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String minValueMetaAttribute(final MetaAttribute metaAttribute) @@ -915,17 +895,7 @@ public String minValue() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int maxValueId() @@ -940,7 +910,7 @@ public static int maxValueSinceVersion() public static String maxValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String maxValueMetaAttribute(final MetaAttribute metaAttribute) @@ -1023,17 +993,7 @@ public String maxValue() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int nullValueId() @@ -1048,7 +1008,7 @@ public static int nullValueSinceVersion() public static String nullValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String nullValueMetaAttribute(final MetaAttribute metaAttribute) @@ -1131,17 +1091,7 @@ public String nullValue() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int characterEncodingId() @@ -1156,7 +1106,7 @@ public static int characterEncodingSinceVersion() public static String characterEncodingCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String characterEncodingMetaAttribute(final MetaAttribute metaAttribute) @@ -1239,17 +1189,7 @@ public String characterEncoding() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int epochId() @@ -1264,7 +1204,7 @@ public static int epochSinceVersion() public static String epochCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String epochMetaAttribute(final MetaAttribute metaAttribute) @@ -1347,17 +1287,7 @@ public String epoch() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int timeUnitId() @@ -1372,7 +1302,7 @@ public static int timeUnitSinceVersion() public static String timeUnitCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String timeUnitMetaAttribute(final MetaAttribute metaAttribute) @@ -1455,17 +1385,7 @@ public String timeUnit() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int semanticTypeId() @@ -1480,7 +1400,7 @@ public static int semanticTypeSinceVersion() public static String semanticTypeCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String semanticTypeMetaAttribute(final MetaAttribute metaAttribute) @@ -1563,17 +1483,7 @@ public String semanticType() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int descriptionId() @@ -1588,7 +1498,7 @@ public static int descriptionSinceVersion() public static String descriptionCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String descriptionMetaAttribute(final MetaAttribute metaAttribute) @@ -1671,17 +1581,7 @@ public String description() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public static int referencedNameId() @@ -1696,7 +1596,7 @@ public static int referencedNameSinceVersion() public static String referencedNameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String referencedNameMetaAttribute(final MetaAttribute metaAttribute) @@ -1779,17 +1679,7 @@ public String referencedName() final byte[] tmp = new byte[dataLength]; buffer.getBytes(limit + headerLength, tmp, 0, dataLength); - final String value; - try - { - value = new String(tmp, "UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } - - return value; + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } public String toString() diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index 1790f6f10b..1f429e09b5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -567,7 +567,7 @@ public static int nameId() public static String nameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String nameMetaAttribute(final MetaAttribute metaAttribute) @@ -619,15 +619,7 @@ public TokenCodecEncoder putName(final byte[] src, final int srcOffset, final in public TokenCodecEncoder name(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -651,7 +643,7 @@ public static int constValueId() public static String constValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String constValueMetaAttribute(final MetaAttribute metaAttribute) @@ -703,15 +695,7 @@ public TokenCodecEncoder putConstValue(final byte[] src, final int srcOffset, fi public TokenCodecEncoder constValue(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -735,7 +719,7 @@ public static int minValueId() public static String minValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String minValueMetaAttribute(final MetaAttribute metaAttribute) @@ -787,15 +771,7 @@ public TokenCodecEncoder putMinValue(final byte[] src, final int srcOffset, fina public TokenCodecEncoder minValue(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -819,7 +795,7 @@ public static int maxValueId() public static String maxValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String maxValueMetaAttribute(final MetaAttribute metaAttribute) @@ -871,15 +847,7 @@ public TokenCodecEncoder putMaxValue(final byte[] src, final int srcOffset, fina public TokenCodecEncoder maxValue(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -903,7 +871,7 @@ public static int nullValueId() public static String nullValueCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String nullValueMetaAttribute(final MetaAttribute metaAttribute) @@ -955,15 +923,7 @@ public TokenCodecEncoder putNullValue(final byte[] src, final int srcOffset, fin public TokenCodecEncoder nullValue(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -987,7 +947,7 @@ public static int characterEncodingId() public static String characterEncodingCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String characterEncodingMetaAttribute(final MetaAttribute metaAttribute) @@ -1039,15 +999,7 @@ public TokenCodecEncoder putCharacterEncoding(final byte[] src, final int srcOff public TokenCodecEncoder characterEncoding(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -1071,7 +1023,7 @@ public static int epochId() public static String epochCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String epochMetaAttribute(final MetaAttribute metaAttribute) @@ -1123,15 +1075,7 @@ public TokenCodecEncoder putEpoch(final byte[] src, final int srcOffset, final i public TokenCodecEncoder epoch(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -1155,7 +1099,7 @@ public static int timeUnitId() public static String timeUnitCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String timeUnitMetaAttribute(final MetaAttribute metaAttribute) @@ -1207,15 +1151,7 @@ public TokenCodecEncoder putTimeUnit(final byte[] src, final int srcOffset, fina public TokenCodecEncoder timeUnit(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -1239,7 +1175,7 @@ public static int semanticTypeId() public static String semanticTypeCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String semanticTypeMetaAttribute(final MetaAttribute metaAttribute) @@ -1291,15 +1227,7 @@ public TokenCodecEncoder putSemanticType(final byte[] src, final int srcOffset, public TokenCodecEncoder semanticType(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -1323,7 +1251,7 @@ public static int descriptionId() public static String descriptionCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String descriptionMetaAttribute(final MetaAttribute metaAttribute) @@ -1375,15 +1303,7 @@ public TokenCodecEncoder putDescription(final byte[] src, final int srcOffset, f public TokenCodecEncoder description(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) @@ -1407,7 +1327,7 @@ public static int referencedNameId() public static String referencedNameCharacterEncoding() { - return "UTF-8"; + return java.nio.charset.StandardCharsets.UTF_8.name(); } public static String referencedNameMetaAttribute(final MetaAttribute metaAttribute) @@ -1459,15 +1379,7 @@ public TokenCodecEncoder putReferencedName(final byte[] src, final int srcOffset public TokenCodecEncoder referencedName(final String value) { - final byte[] bytes; - try - { - bytes = null == value || value.isEmpty() ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes("UTF-8"); - } - catch (final java.io.UnsupportedEncodingException ex) - { - throw new RuntimeException(ex); - } + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); final int length = bytes.length; if (length > 65534) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index 4c76c27184..f8b6728851 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -94,12 +94,12 @@ public EncodedDataType(final Node node, final String givenName, final String ref if (PrimitiveType.CHAR == primitiveType) { - characterEncoding = getAttributeValue(node, "characterEncoding", "US-ASCII").trim().toUpperCase(); + characterEncoding = getAttributeValue(node, "characterEncoding", "US-ASCII").trim(); } else { final String characterEncoding = getAttributeValueOrNull(node, "characterEncoding"); - this.characterEncoding = characterEncoding == null ? null : characterEncoding.trim().toUpperCase(); + this.characterEncoding = characterEncoding == null ? null : characterEncoding.trim(); } if (presence() == CONSTANT) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java new file mode 100644 index 0000000000..80125fdcf8 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java @@ -0,0 +1,195 @@ +/* + * Copyright 2013-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.io.ByteArrayInputStream; +import java.util.Map; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.hamcrest.CoreMatchers.allOf; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.StringContains.containsString; +import static uk.co.real_logic.sbe.generation.java.JavaUtil.*; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +public class CharacterEncodingTest +{ + private static final String XML_SCHEMA; + + static + { + final StringBuilder buffer = + new StringBuilder("\n") + .append("\n") + .append(" \n") + .append(" \n") + .append(" \n") + .append(" \n") + .append(" \n") + .append(" \n") + .append(" \n"); + + int i = 0; + for (final String alias : STD_CHARSETS.keySet()) + { + buffer.append(" \n"); + buffer.append(" \n") + .append(" \n") + .append(" \n") + .append(" \n"); + i++; + } + buffer.append(" \n"); + buffer.append(" \n") + .append(" \n") + .append(" \n \n"); + buffer.append(" \n"); + buffer.append(" \n"); + + buffer.append(" \n") + .append(" \n"); + i = 0; + for (int j = 0, size = STD_CHARSETS.size(); j < size; j++) + { + buffer.append(" \n"); + i++; + } + buffer.append(""); + buffer.append(""); + buffer.append(""); + + for (int j = 0, size = STD_CHARSETS.size(); j < size; j++) + { + buffer.append(" \n"); + i++; + } + buffer.append(""); + + buffer.append(" \n") + .append(""); + XML_SCHEMA = buffer.toString(); + } + + @Test + public void shouldUseStandardCharsetsForWellKnowEncodings() throws Exception + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = + parse(new ByteArrayInputStream(XML_SCHEMA.getBytes(UTF_8)), options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + final JavaGenerator generator = new JavaGenerator( + ir, MutableDirectBuffer.class.getName(), DirectBuffer.class.getName(), false, false, false, outputManager); + + generator.generate(); + final Map sources = outputManager.getSources(); + final String encoderSources = sources.get("code.generation.test.EncodingTestEncoder").toString(); + final String decoderSources = sources.get("code.generation.test.EncodingTestDecoder").toString(); + + verifyCharacterEncodingMethods(encoderSources); + verifyCharacterEncodingMethods(decoderSources); + + assertThat(encoderSources, not(containsString("java.io.UnsupportedEncodingException"))); + assertThat(encoderSources, not(containsString("new byte[0]"))); + for (final String charset : STD_CHARSETS.values()) + { + if (!"US_ASCII".equals(charset)) + { + assertThat( + encoderSources, containsString("getBytes(java.nio.charset.StandardCharsets." + charset + ")")); + } + } + assertThat(encoderSources, containsString("getBytes(java.nio.charset.Charset.forName(\"custom-encoding\"))")); + assertThat(encoderSources, containsString("getBytes(java.nio.charset.Charset.forName(\"ISO-8859-2\"))")); + assertThat(encoderSources, allOf(not(containsString("\"cp912\"")), not(containsString("\"CP912\"")))); + final int encodeFromStringStartIndex = encoderSources.indexOf("f_std_alias(final String src)"); + final int encodeFromStringEndIndex = encoderSources.indexOf("return this", encodeFromStringStartIndex); + assertThat( + encoderSources.substring(encodeFromStringStartIndex, encodeFromStringEndIndex), + containsString("final byte[] bytes = (null == src || src.isEmpty()) ?" + + " org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY :" + + " src.getBytes(java.nio.charset.StandardCharsets.ISO_8859_1);")); + assertThat(decoderSources, not(containsString("java.io.UnsupportedEncodingException"))); + assertThat(decoderSources, not(containsString("new byte[0]"))); + for (final String charset : STD_CHARSETS.values()) + { + assertThat(decoderSources, containsString("end, java.nio.charset.StandardCharsets." + charset + ")")); + } + assertThat(decoderSources, containsString("end, java.nio.charset.Charset.forName(\"custom-encoding\"))")); + assertThat(decoderSources, containsString("end, java.nio.charset.Charset.forName(\"ISO-8859-2\"))")); + assertThat(decoderSources, allOf(not(containsString("\"cp912\"")), not(containsString("\"CP912\"")))); + } + + private void verifyCharacterEncodingMethods(final String code) + { + int i = 0; + for (final String charset : STD_CHARSETS.values()) + { + assertContainsCharacterEncodingMethod( + "f_" + (i++), "java.nio.charset.StandardCharsets." + charset + ".name()", code); + } + assertContainsCharacterEncodingMethod("f_custom", "\"custom-encoding\"", code); + assertContainsCharacterEncodingMethod( + "f_std_alias", "java.nio.charset.StandardCharsets.ISO_8859_1.name()", code); + assertContainsCharacterEncodingMethod("f_non_std_alias", "\"ISO-8859-2\"", code); + } + + private static void assertContainsCharacterEncodingMethod( + final String fieldName, final String expectedEncoding, final String sources) + { + final String expectedOne = + " public static String " + fieldName + "CharacterEncoding()\n" + + " {\n return " + expectedEncoding + ";\n }"; + assertThat(sources, containsString(expectedOne)); + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index 4e31d104be..a73173bb16 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -414,6 +414,49 @@ public void shouldReturnCorrectNullValueWhenSpecified() throws Exception is(parse(nullVal, PrimitiveType.INT8))); } + @Test + public void shouldReturnCharacterEncodingWhenSpecified() throws Exception + { + final String testXmlString = + "" + + " " + + ""; + + final Map map = parseTestXmlWithMap("/types/type", testXmlString); + + assertThat((((EncodedDataType)map.get("testTypeCharacterEncoding")).characterEncoding()), is("cp912")); + } + + @Test + public void shouldReturnCharacterEncodingWhenSpecifiedNonCharType() throws Exception + { + final String testXmlString = + "" + + " " + + ""; + + final Map map = parseTestXmlWithMap("/types/type", testXmlString); + + assertThat( + (((EncodedDataType)map.get("testTypeCharacterEncodingNonChar")).characterEncoding()), is("windows-1251")); + } + + @Test + public void shouldReturnUsAsciiWhenCharacterEncodingNotSpecifiedForTypeChar() throws Exception + { + final String testXmlString = + "" + + " " + + ""; + + final Map map = parseTestXmlWithMap("/types/type", testXmlString); + + assertThat( + (((EncodedDataType)map.get("testCharDefaultCharacterEncoding")).characterEncoding()), is("US-ASCII")); + } + private static Map parseTestXmlWithMap(final String xPathExpr, final String xml) throws ParserConfigurationException, XPathExpressionException, IOException, SAXException { From c08dd7ceb2632b8627fa407241531734848d8b05 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 8 Jan 2022 10:37:45 +0000 Subject: [PATCH 0843/1594] [Java] Formatting and import tidyup. --- .../sbe/generation/java/JavaGenerator.java | 7 ++++--- .../sbe/generation/java/JavaUtil.java | 19 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 4272a8f436..9254c3c5c6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -15,7 +15,10 @@ */ package uk.co.real_logic.sbe.generation.java; -import org.agrona.*; +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.Strings; +import org.agrona.Verify; import org.agrona.generation.OutputManager; import org.agrona.sbe.*; import uk.co.real_logic.sbe.PrimitiveType; @@ -31,8 +34,6 @@ import java.util.function.Function; import static uk.co.real_logic.sbe.SbeTool.JAVA_INTERFACE_PACKAGE; -import static uk.co.real_logic.sbe.generation.cpp.CppUtil.formatClassName; -import static uk.co.real_logic.sbe.generation.cpp.CppUtil.formatPropertyName; import static uk.co.real_logic.sbe.generation.java.JavaGenerator.CodecType.DECODER; import static uk.co.real_logic.sbe.generation.java.JavaGenerator.CodecType.ENCODER; import static uk.co.real_logic.sbe.generation.java.JavaUtil.*; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index f6969c111e..483318936e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -109,17 +109,19 @@ public String toString() final Charset charset = (Charset)field.get(null); final String name = field.getName(); String oldName = STD_CHARSETS.put(charset.name(), name); + if (null != oldName) { throw new IllegalStateException("Duplicate charset alias: old=" + oldName + ", new=" + name); } + for (final String alias : charset.aliases()) { oldName = STD_CHARSETS.put(alias, name); if (null != oldName) { - throw new IllegalStateException("Duplicate charset alias: old=" + oldName + ", new=" + - alias); + throw new IllegalStateException( + "Duplicate charset alias: old=" + oldName + ", new=" + alias); } } } @@ -214,7 +216,7 @@ public static void append(final StringBuilder builder, final String indent, fina public static String charset(final String encoding) { final String charsetName = STD_CHARSETS.get(encoding); - if (charsetName != null) + if (null != charsetName) { return "java.nio.charset.StandardCharsets." + charsetName; } @@ -234,7 +236,7 @@ public static String charset(final String encoding) public static String charsetName(final String encoding) { final String charsetName = STD_CHARSETS.get(encoding); - if (charsetName != null) + if (null != charsetName) { return "java.nio.charset.StandardCharsets." + charsetName + ".name()"; } @@ -323,8 +325,7 @@ public static String generateLiteral(final PrimitiveType type, final String valu * @param indent level for the comment. * @param typeToken for the type. */ - public static void generateTypeJavadoc( - final StringBuilder sb, final String indent, final Token typeToken) + public static void generateTypeJavadoc(final StringBuilder sb, final String indent, final Token typeToken) { final String description = typeToken.description(); if (Strings.isEmpty(description)) @@ -350,8 +351,7 @@ public static void generateTypeJavadoc( * @param optionToken for the type. * @throws IOException on failing to write to output. */ - public static void generateOptionDecodeJavadoc( - final Appendable out, final String indent, final Token optionToken) + public static void generateOptionDecodeJavadoc(final Appendable out, final String indent, final Token optionToken) throws IOException { final String description = optionToken.description(); @@ -379,8 +379,7 @@ public static void generateOptionDecodeJavadoc( * @param optionToken for the type. * @throws IOException on failing to write to output. */ - public static void generateOptionEncodeJavadoc( - final Appendable out, final String indent, final Token optionToken) + public static void generateOptionEncodeJavadoc(final Appendable out, final String indent, final Token optionToken) throws IOException { final String description = optionToken.description(); From 71639dca07b22c98d4529b1014cd9c2e1ba272db Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 8 Jan 2022 10:41:21 +0000 Subject: [PATCH 0844/1594] Update copyright. --- CMakeLists.txt | 2 +- CONTRIBUTING.md | 2 +- README.md | 2 +- build.gradle | 4 ++-- config/checkstyle/checkstyle.xml | 2 +- sbe-benchmarks/src/main/cpp/CMakeLists.txt | 2 +- sbe-benchmarks/src/main/cpp/CarBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/CodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/MarketDataBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/benchlet-main.cpp | 2 +- sbe-benchmarks/src/main/cpp/benchlet.h | 2 +- .../src/main/java/uk/co/real_logic/sbe/CarBenchmark.java | 2 +- .../main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/package-info.java | 2 +- sbe-samples/src/main/cpp/CMakeLists.txt | 2 +- sbe-samples/src/main/cpp/GeneratedStubExample.cpp | 2 +- sbe-samples/src/main/cpp/OtfExample.cpp | 2 +- .../uk/co/real_logic/sbe/examples/ExampleTokenListener.java | 2 +- .../co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java | 2 +- .../sbe/examples/ExampleUsingGeneratedStubExtension.java | 2 +- .../main/java/uk/co/real_logic/sbe/examples/OtfExample.java | 2 +- .../main/java/uk/co/real_logic/sbe/examples/package-info.java | 2 +- sbe-tool/src/main/cpp/CMakeLists.txt | 2 +- sbe-tool/src/main/cpp/otf/Encoding.h | 2 +- sbe-tool/src/main/cpp/otf/IrDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/Token.h | 2 +- .../src/main/java/uk/co/real_logic/sbe/PrimitiveType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ValidationUtil.java | 2 +- .../main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java | 2 +- .../java/uk/co/real_logic/sbe/codec/java/MethodSelector.java | 2 +- .../java/uk/co/real_logic/sbe/codec/java/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/CodeGenerator.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/Generators.java | 2 +- .../uk/co/real_logic/sbe/generation/TargetCodeGenerator.java | 2 +- .../real_logic/sbe/generation/TargetCodeGeneratorLoader.java | 2 +- .../java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 2 +- .../uk/co/real_logic/sbe/generation/c/COutputManager.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/c/CUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/c/package-info.java | 2 +- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java | 2 +- .../real_logic/sbe/generation/cpp/NamespaceOutputManager.java | 2 +- .../uk/co/real_logic/sbe/generation/cpp/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/csharp/CSharp.java | 2 +- .../co/real_logic/sbe/generation/csharp/CSharpGenerator.java | 2 +- .../sbe/generation/csharp/CSharpNamespaceOutputManager.java | 2 +- .../uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/csharp/package-info.java | 2 +- .../co/real_logic/sbe/generation/golang/GolangGenerator.java | 2 +- .../real_logic/sbe/generation/golang/GolangOutputManager.java | 2 +- .../uk/co/real_logic/sbe/generation/golang/GolangUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/golang/package-info.java | 2 +- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/JavaUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/java/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 2 +- .../co/real_logic/sbe/generation/rust/RustOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/RustUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/SubGroup.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/package-info.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java | 2 +- .../main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/package-info.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java | 2 +- .../java/uk/co/real_logic/sbe/json/JsonTokenListener.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/json/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java | 2 +- .../main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java | 2 +- .../main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/otf/package-info.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/package-info.java | 2 +- sbe-tool/src/test/c/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/c/CComplianceTest.c | 2 +- sbe-tool/src/test/c/CMakeLists.txt | 2 +- sbe-tool/src/test/c/CodeGenTest.cpp | 2 +- sbe-tool/src/test/c/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/cpp/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/cpp/CMakeLists.txt | 2 +- sbe-tool/src/test/cpp/CodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeElementsTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp | 2 +- sbe-tool/src/test/cpp/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/cpp/Issue835Test.cpp | 2 +- sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp | 2 +- sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp | 2 +- .../test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java | 2 +- .../java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/TestTargetLanguage.java | 2 +- sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java | 2 +- .../test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java | 2 +- .../uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java | 2 +- .../sbe/generation/csharp/Issue567GroupSizeTest.java | 2 +- .../co/real_logic/sbe/generation/java/CarDecodeTestUtil.java | 2 +- .../real_logic/sbe/generation/java/CharacterEncodingTest.java | 2 +- .../sbe/generation/java/CompositeElementsGenerationTest.java | 2 +- .../real_logic/sbe/generation/java/ConstantCharArrayTest.java | 2 +- .../sbe/generation/java/FixedSizeDataGeneratorTest.java | 2 +- .../real_logic/sbe/generation/java/GenerateFixBinaryTest.java | 2 +- .../sbe/generation/java/GenerateIlinkBinaryTest.java | 2 +- .../co/real_logic/sbe/generation/java/JavaGeneratorTest.java | 2 +- .../sbe/generation/java/PackageOutputManagerTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/ReflectionUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/RewindTest.java | 2 +- .../real_logic/sbe/generation/java/SchemaExtensionTest.java | 2 +- .../sbe/generation/java/SkipAndDecodedLengthTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/ToStringTest.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/RustUtilTest.java | 2 +- .../uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java | 2 +- .../co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java | 2 +- 160 files changed, 161 insertions(+), 161 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e52939e27a..d98335b346 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2021 Real Logic Limited. +# Copyright 2013-2022 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 882484f46e..656cc2e855 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ If you are adding a new file it should have the following header: ``` /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index e9a0ab9b8c..98f247b51d 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ Or run test directly with `Cargo` License (See LICENSE file for full license) ------------------------------------------- -Copyright 2013-2021 Real Logic Limited. +Copyright 2013-2022 Real Logic Limited. Copyright 2017 MarketFactory Inc. Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/build.gradle b/build.gradle index e4d41d6416..b28d4d95d0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -186,7 +186,7 @@ subprojects { javadoc { failOnError false title = '

    Simple Binary Encoding (SBE)

    ' - options.bottom = 'Copyright © 2013-2021 Real Logic Limited. All Rights Reserved.' + options.bottom = 'Copyright © 2013-2022 Real Logic Limited. All Rights Reserved.' options.encoding = 'UTF-8' options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 5197f7bb3e..28aab05fd6 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -23,7 +23,7 @@ - + diff --git a/sbe-benchmarks/src/main/cpp/CMakeLists.txt b/sbe-benchmarks/src/main/cpp/CMakeLists.txt index 51aa80dca9..3e0da195d9 100644 --- a/sbe-benchmarks/src/main/cpp/CMakeLists.txt +++ b/sbe-benchmarks/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2021 Real Logic Limited. +# Copyright 2013-2022 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/CarBench.cpp b/sbe-benchmarks/src/main/cpp/CarBench.cpp index 5e8c42c8e4..7f938c3fc9 100644 --- a/sbe-benchmarks/src/main/cpp/CarBench.cpp +++ b/sbe-benchmarks/src/main/cpp/CarBench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/CodecBench.h b/sbe-benchmarks/src/main/cpp/CodecBench.h index f704b3352c..8028ef0bed 100644 --- a/sbe-benchmarks/src/main/cpp/CodecBench.h +++ b/sbe-benchmarks/src/main/cpp/CodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp index 75cd518b9c..4a01b81049 100644 --- a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp +++ b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h index 615c6ba108..217f4eb39a 100644 --- a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h index 18723e9714..e67807adb1 100644 --- a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp index 0fcddad03c..dd6136b932 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp +++ b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/benchlet.h b/sbe-benchmarks/src/main/cpp/benchlet.h index 948b025e96..68e00b2427 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet.h +++ b/sbe-benchmarks/src/main/cpp/benchlet.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java index 46a579427d..c15ebafeea 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java index 125af11b69..f459ae1dc9 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java index c23c5cbf62..568d9b0fad 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/CMakeLists.txt b/sbe-samples/src/main/cpp/CMakeLists.txt index 5c5eba141a..5c8664ca92 100644 --- a/sbe-samples/src/main/cpp/CMakeLists.txt +++ b/sbe-samples/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2021 Real Logic Limited. +# Copyright 2013-2022 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index 7e59b8cfab..e2187c87ee 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/OtfExample.cpp b/sbe-samples/src/main/cpp/OtfExample.cpp index ef2df6d891..c108bbf9ba 100644 --- a/sbe-samples/src/main/cpp/OtfExample.cpp +++ b/sbe-samples/src/main/cpp/OtfExample.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java index 27ff7e745d..820131c543 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java index d77a8aab29..640458f767 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java index fcacc3e4fb..06bf499719 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java index 2b838b3806..847df95550 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java index 4365a35946..1cafaea915 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/CMakeLists.txt b/sbe-tool/src/main/cpp/CMakeLists.txt index 5306731b2d..3100de1e6b 100644 --- a/sbe-tool/src/main/cpp/CMakeLists.txt +++ b/sbe-tool/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2021 Real Logic Limited. +# Copyright 2013-2022 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/Encoding.h b/sbe-tool/src/main/cpp/otf/Encoding.h index 4607508c0e..33aa3cf1cd 100644 --- a/sbe-tool/src/main/cpp/otf/Encoding.h +++ b/sbe-tool/src/main/cpp/otf/Encoding.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index 6f116f4eef..381a7e9638 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h index b68d6b9d67..3fdd955a45 100644 --- a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h index 9d646637a2..f0a225b5f5 100644 --- a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/Token.h b/sbe-tool/src/main/cpp/otf/Token.h index 6cf5bb5b17..9e2a3f0f18 100644 --- a/sbe-tool/src/main/cpp/otf/Token.h +++ b/sbe-tool/src/main/cpp/otf/Token.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java index 7453d4f57e..ba6887f411 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index 0336953859..804b38bb21 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index ba8fb99784..f954685139 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index ad8b8ffcc4..1c87c1cb40 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java index 8ab31806a3..5407cf1237 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java index 437d984943..fef09f50f0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java index 7f1c6eaa83..ed53dc625a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java index a74a8ee417..9216ed5548 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java index e5a5912efe..775d972e09 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java index 738af3bfda..4f4c31c125 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 344249bac4..07065da1ac 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 34779499e2..39e521a360 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java index 29c7530b15..2158196b40 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java index 40e8b9ce80..2b0346fb0e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java index 055906cf21..86782b9872 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 913b75f426..46e88b39cd 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index ccb4898421..ec19a53102 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java index e6692adc28..59b0bccfc1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java index 211ee9b813..e9158a3558 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java index 46b13bc35a..9c8643c277 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index cef39009bb..ec0b458d12 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java index 9dca1481b2..b48c50611f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index 3a6a10d0f6..0da828d02f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java index fd0fb30ac8..148b19f141 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index 0e5d8438ba..cdefc9f7c0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java index 29fba30b4a..874b7769ec 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java index 44362a06cb..0858cede34 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java index e52fa637bd..7cffab4c59 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 9254c3c5c6..1c0fc182ff 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 483318936e..49bdbfdaa9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java index 5207eb5f1c..dfd94ec902 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java index a5562a22b6..d23c989d0b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 1baf03f047..796ef98d16 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index 8eef8ecd77..75aa4c49fc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index b3abad386c..2df4ce440f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java index 864b8b1dd2..45458df2de 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index d4326bd179..fe49709908 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index 2d2af72993..e56049205c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java index 052fc27bae..265a1f3e82 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java index 733111dd31..78a8b60935 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java index f7e2eee19a..aa2929c08e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java index 4906f10915..98d0592e22 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java index 32a0a8ebee..534827134e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index 420b955864..f5af22d62b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java index da10d93de8..1107511407 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java index febe9c4df0..f791c1b02b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java index cf361733d4..bcdc380a4b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index 05c16f8468..d9a09966f2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java index fdb8989cf5..8562868ba9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java index d89dab0b9a..99ef90556a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index a0cc32cebc..3337db04d2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java index 3887d90370..1c58dc66a6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java index 30ae2f87c3..9ea3194669 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java index 21e967497a..6f09a7f85b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java index 56c4d6ef7f..3e4a7266a7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java index 7b37cc80f3..ef991ae99c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java index 2d20b6ab56..2fb3ca07a2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java index 796ac53ce8..cc994a9775 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java index 9689cfd029..7445a48574 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index 3b6330ed19..98863144b9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index f8b6728851..fc26d9cbdc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index 1135c39b0b..967a84063f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java index 4afaf0e092..361d2b1e77 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java index 2696d1eee1..2bead68c2a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index 5f9850e983..9a61439426 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java index cb35a143f5..cdb1715179 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index 285c2fd092..3f0bab5ff4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java index 3743f860ce..8ae645180a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java index 8c3697f311..7609e46a0e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index 6f9931c8b4..92019acec8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java index 886141634f..b9db2c5138 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 49cdcd0fd1..022777ae8f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java index e1d75032cf..6f79c9b6fa 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/BoundsCheckTest.cpp b/sbe-tool/src/test/c/BoundsCheckTest.cpp index ed809cfd11..8cb984e0c7 100644 --- a/sbe-tool/src/test/c/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/c/BoundsCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CComplianceTest.c b/sbe-tool/src/test/c/CComplianceTest.c index 8cead8201b..61763dbb29 100644 --- a/sbe-tool/src/test/c/CComplianceTest.c +++ b/sbe-tool/src/test/c/CComplianceTest.c @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index 97043728fa..32147f3c73 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2021 Real Logic Limited. +# Copyright 2013-2022 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index 8b86a10eb5..d1c0c0fcae 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/GroupWithDataTest.cpp b/sbe-tool/src/test/c/GroupWithDataTest.cpp index 404158839c..7d2b0efa2f 100644 --- a/sbe-tool/src/test/c/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/c/GroupWithDataTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp index 6924088137..ee33ebd0cd 100644 --- a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index 9d4bcd4b3a..bef2c99280 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2021 Real Logic Limited. +# Copyright 2013-2022 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index dfea4cc0be..1bd387f46e 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp index c3b383de15..d7b6fd6038 100644 --- a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp index 12361521bd..632827a0fc 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp index 3e4ad3abc4..8ddb1101b9 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp index f1f80496f2..c9bc42621d 100644 --- a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/Issue835Test.cpp b/sbe-tool/src/test/cpp/Issue835Test.cpp index 820fd42f32..dfac7a7115 100644 --- a/sbe-tool/src/test/cpp/Issue835Test.cpp +++ b/sbe-tool/src/test/cpp/Issue835Test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp index d7cd2e536e..9767023f54 100644 --- a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp +++ b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp index f6ae957bec..f3ad271857 100644 --- a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp +++ b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java index 14679eb22c..f9ee2695ef 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java index b49797e788..7b63c47573 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java index 550499ce41..1911940443 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java index ea148677fc..7a5c92481e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java index bcfe7b5fc0..c9c6bb2aac 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index f59ffbfb89..8187e18813 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index 832f94cdce..ef04946d0b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java index 87dd7279cc..b4772e7271 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java index 80125fdcf8..45175be330 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java index 462546a9d3..6f1d4f6fbc 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java index db15186444..91af57d373 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java index be2c9556f7..2ea2738687 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java index d0351dfc76..fb7c599db8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java index 93925c5206..530b9b530d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 3a9064b810..42dc85f09f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java index 465e9c6738..4c72144043 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java index 03fdf60176..56f7ccbc8d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java index 9385da574c..37130e8d40 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index e3afb850f0..1620bbf740 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java index 8f69440b8c..f1c0cd9824 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java index 1576ec9ea9..36d762fd83 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java index b409cb103e..366d8663cd 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index a543f737ca..bdd33c0535 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java index ea79e33f30..ecdae485ef 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java index 298468d454..91f5736a20 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java index f76f153f34..6edf89a346 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index f63b7aef35..5bb0750cfd 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java index 2e1a7861b5..2ec78f51db 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java index 33dcac5396..9ff34d4d5d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java index 7792413a94..6fa1006086 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java index 350515db92..4278f91f60 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java index d60d49c838..6c00ca511f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java index 6ea423f870..ee59e45644 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java index c3657df172..7e10355e49 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java index 2262665723..8b3b1dc9ed 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index a73173bb16..008a3d8199 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index 0fdd149c40..0a13521102 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index 8e187211b0..2707138cb6 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * Copyright 2017 MarketFactory Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java index f9c1f8da5e..dd25ca3caf 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java index 9e37f61749..8ddc6f620d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java index 68b7915d3a..1fa997c138 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index ed49028ff5..0911c8f9d1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 Real Logic Limited. + * Copyright 2013-2022 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 9dd7cbb3f658ad8f9c1a074fcb14fc12d4f119e7 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 25 Jan 2022 18:26:09 +0000 Subject: [PATCH 0845/1594] Upgrade to Mockito 4.3.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b28d4d95d0..ce044cf449 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.2.1' def hamcrestVersion = '2.2' -def mockitoVersion = '4.2.0' +def mockitoVersion = '4.3.1' def junitVersion = '5.8.2' def jmhVersion = '1.34' def agronaVersion = '1.14.0' From e43fb200ec94ef9d9b731fc46c37aefd7db66b9d Mon Sep 17 00:00:00 2001 From: Adam Greenstein <63319780+greenstein@users.noreply.github.com> Date: Mon, 31 Jan 2022 11:15:05 -0600 Subject: [PATCH 0846/1594] C++ code generation: check composite and bitset version (#888) --- .../sbe/generation/cpp/CppGenerator.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 46e88b39cd..17bbcebd4d 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2793,7 +2793,24 @@ private void writeTokenDisplay( case BEGIN_SET: case BEGIN_COMPOSITE: - sb.append(indent).append("builder << ").append(fieldName).append("();\n"); + if (0 == typeToken.version()) + { + sb.append(indent).append("builder << ").append(fieldName).append("();\n"); + } + else + { + new Formatter(sb).format( + indent + "if (%1$sInActingVersion())\n" + + indent + "{\n" + + indent + " builder << %1$s();\n" + + indent + "}\n" + + indent + "else\n" + + indent + "{\n" + + indent + " builder << %2$s;\n" + + indent + "}\n", + fieldName, + typeToken.signal() == Signal.BEGIN_SET ? "\"[]\"" : "\"{}\""); + } break; } From 9bf5acb66b5438d44a3419bb67ff4c39b8ded3e7 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 7 Feb 2022 11:56:14 +0000 Subject: [PATCH 0847/1594] Upgrade to Versions 0.42.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ce044cf449..fab902027d 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ import java.security.MessageDigest plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '7.1.2' apply false - id "com.github.ben-manes.versions" version "0.41.0" + id "com.github.ben-manes.versions" version "0.42.0" } defaultTasks 'clean', 'build' From 26e58934c98ce3fcca95c7bc23f1150ac7ec73d9 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 7 Feb 2022 12:06:02 +0000 Subject: [PATCH 0848/1594] [Java] Upgrade to Checkstyle 9.3. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index fab902027d..84f4da1a82 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ def toolchainLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } -def checkstyleVersion = '9.2.1' +def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.3.1' def junitVersion = '5.8.2' From 975ce962c5c7e42820340b5139bebede5f0777e1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 11 Feb 2022 10:39:54 +0000 Subject: [PATCH 0849/1594] [Java] Reduce scope. --- .../generation/java/CarDecodeTestUtil.java | 2 +- .../java/CharacterEncodingTest.java | 4 +- .../java/CompositeElementsGenerationTest.java | 11 ++-- .../java/ConstantCharArrayTest.java | 4 +- .../java/FixedSizeDataGeneratorTest.java | 10 ++-- .../java/GenerateFixBinaryTest.java | 6 +-- .../java/GenerateIlinkBinaryTest.java | 6 +-- .../generation/java/JavaGeneratorTest.java | 52 +++++++++---------- .../java/PackageOutputManagerTest.java | 4 +- .../sbe/generation/java/RewindTest.java | 3 +- .../generation/java/SchemaExtensionTest.java | 8 +-- .../java/SkipAndDecodedLengthTest.java | 2 +- 12 files changed, 55 insertions(+), 57 deletions(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java index b4772e7271..62657132b1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java @@ -21,7 +21,7 @@ import java.util.ArrayList; -public class CarDecodeTestUtil +class CarDecodeTestUtil { static ArrayList getValues(final CarDecoder carDecoder) { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java index 45175be330..bc380a4665 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java @@ -35,7 +35,7 @@ import static uk.co.real_logic.sbe.generation.java.JavaUtil.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class CharacterEncodingTest +class CharacterEncodingTest { private static final String XML_SCHEMA; @@ -118,7 +118,7 @@ public class CharacterEncodingTest } @Test - public void shouldUseStandardCharsetsForWellKnowEncodings() throws Exception + void shouldUseStandardCharsetsForWellKnowEncodings() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); final MessageSchema schema = diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java index 6f1d4f6fbc..10eaedee62 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java @@ -49,7 +49,7 @@ import static org.hamcrest.Matchers.containsString; import static org.mockito.Mockito.*; -public class CompositeElementsGenerationTest +class CompositeElementsGenerationTest { private static final MessageHeaderEncoder MESSAGE_HEADER = new MessageHeaderEncoder(); private static final MsgEncoder MSG_ENCODER = new MsgEncoder(); @@ -57,7 +57,7 @@ public class CompositeElementsGenerationTest private static final int SCHEMA_BUFFER_CAPACITY = 16 * 1024; @Test - public void shouldEncode() + void shouldEncode() { final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); encodeTestMessage(encodedMsgBuffer); @@ -93,7 +93,7 @@ public void shouldEncode() } @Test - public void shouldDecode() + void shouldDecode() { final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); encodeTestMessage(encodedMsgBuffer); @@ -124,7 +124,7 @@ public void shouldDecode() } @Test - public void shouldDisplay() + void shouldDisplay() { final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); encodeTestMessage(encodedMsgBuffer); @@ -137,7 +137,7 @@ public void shouldDisplay() } @Test - public void shouldOtfDecode() throws Exception + void shouldOtfDecode() throws Exception { final ByteBuffer encodedSchemaBuffer = ByteBuffer.allocate(SCHEMA_BUFFER_CAPACITY); encodeSchema(encodedSchemaBuffer); @@ -145,7 +145,6 @@ public void shouldOtfDecode() throws Exception final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); encodeTestMessage(encodedMsgBuffer); - encodedSchemaBuffer.flip(); final Ir ir = decodeIr(encodedSchemaBuffer); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java index 91af57d373..1141e5c983 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java @@ -29,7 +29,7 @@ import static org.hamcrest.core.StringContains.containsString; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class ConstantCharArrayTest +class ConstantCharArrayTest { private static final Class BUFFER_CLASS = MutableDirectBuffer.class; private static final String BUFFER_NAME = BUFFER_CLASS.getName(); @@ -37,7 +37,7 @@ public class ConstantCharArrayTest private static final String READ_ONLY_BUFFER_NAME = READ_ONLY_BUFFER_CLASS.getName(); @Test - public void shouldGenerateConstCharArrayMethods() throws Exception + void shouldGenerateConstCharArrayMethods() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); final MessageSchema schema = parse(Tests.getLocalResource("issue505.xml"), options); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java index 2ea2738687..8edb42474c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java @@ -36,7 +36,7 @@ import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class FixedSizeDataGeneratorTest +class FixedSizeDataGeneratorTest { private static final Class BUFFER_CLASS = MutableDirectBuffer.class; private static final String BUFFER_NAME = BUFFER_CLASS.getName(); @@ -48,7 +48,7 @@ public class FixedSizeDataGeneratorTest private Ir ir; @BeforeEach - public void setUp() throws Exception + void setUp() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); final MessageSchema schema = parse(Tests.getLocalResource("extension-schema.xml"), options); @@ -62,7 +62,7 @@ public void setUp() throws Exception } @Test - public void shouldGeneratePutAndGetByteArrayForFixedLengthBlob() throws Exception + void shouldGeneratePutAndGetByteArrayForFixedLengthBlob() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); @@ -96,7 +96,7 @@ public void shouldGeneratePutAndGetByteArrayForFixedLengthBlob() throws Exceptio } @Test - public void shouldGeneratePutAndGetDirectBufferForFixedLengthBlob() throws Exception + void shouldGeneratePutAndGetDirectBufferForFixedLengthBlob() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); @@ -130,7 +130,7 @@ public void shouldGeneratePutAndGetDirectBufferForFixedLengthBlob() throws Excep } @Test - public void shouldGenerateWrapForFixedLengthBlob() throws Exception + void shouldGenerateWrapForFixedLengthBlob() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java index fb7c599db8..09274ec5f7 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java @@ -32,7 +32,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class GenerateFixBinaryTest +class GenerateFixBinaryTest { private static final Class BUFFER_CLASS = MutableDirectBuffer.class; private static final String BUFFER_NAME = BUFFER_CLASS.getName(); @@ -42,7 +42,7 @@ public class GenerateFixBinaryTest private final StringWriterOutputManager outputManager = new StringWriterOutputManager(); @Test - public void shouldGenerateValidJava() throws Exception + void shouldGenerateValidJava() throws Exception { System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); @@ -76,7 +76,7 @@ public void shouldGenerateValidJava() throws Exception } @Test - public void shouldGenerateAndEncodeIr() throws Exception + void shouldGenerateAndEncodeIr() throws Exception { System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java index 530b9b530d..a8c9e2676a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java @@ -32,7 +32,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class GenerateIlinkBinaryTest +class GenerateIlinkBinaryTest { private static final Class BUFFER_CLASS = MutableDirectBuffer.class; private static final String BUFFER_NAME = BUFFER_CLASS.getName(); @@ -42,7 +42,7 @@ public class GenerateIlinkBinaryTest private final StringWriterOutputManager outputManager = new StringWriterOutputManager(); @Test - public void shouldGenerateValidJava() throws Exception + void shouldGenerateValidJava() throws Exception { System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); @@ -76,7 +76,7 @@ public void shouldGenerateValidJava() throws Exception } @Test - public void shouldGenerateAndEncodeIr() throws Exception + void shouldGenerateAndEncodeIr() throws Exception { System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 42dc85f09f..6ad49097bd 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -42,7 +42,7 @@ import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class JavaGeneratorTest +class JavaGeneratorTest { private static final Class BUFFER_CLASS = MutableDirectBuffer.class; private static final String BUFFER_NAME = BUFFER_CLASS.getName(); @@ -56,7 +56,7 @@ public class JavaGeneratorTest private Ir ir; @BeforeEach - public void setUp() throws Exception + void setUp() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); final MessageSchema schema = parse(Tests.getLocalResource("code-generation-schema.xml"), options); @@ -68,7 +68,7 @@ public void setUp() throws Exception } @Test - public void shouldGenerateMessageHeaderStub() throws Exception + void shouldGenerateMessageHeaderStub() throws Exception { final int bufferOffset = 64; final int templateIdOffset = 2; @@ -95,7 +95,7 @@ public void shouldGenerateMessageHeaderStub() throws Exception } @Test - public void shouldGenerateMessageHeaderDecoderStub() throws Exception + void shouldGenerateMessageHeaderDecoderStub() throws Exception { final int bufferOffset = 64; final int templateIdOffset = 2; @@ -120,7 +120,7 @@ public void shouldGenerateMessageHeaderDecoderStub() throws Exception } @Test - public void shouldGenerateUint8EnumStub() throws Exception + void shouldGenerateUint8EnumStub() throws Exception { final String className = "BooleanType"; final String fqClassName = ir.applicableNamespace() + "." + className; @@ -136,7 +136,7 @@ public void shouldGenerateUint8EnumStub() throws Exception } @Test - public void shouldGenerateCharEnumStub() throws Exception + void shouldGenerateCharEnumStub() throws Exception { generateTypeStubs(); @@ -148,7 +148,7 @@ public void shouldGenerateCharEnumStub() throws Exception } @Test - public void shouldGenerateChoiceSetStub() throws Exception + void shouldGenerateChoiceSetStub() throws Exception { final int bufferOffset = 8; final byte bitset = (byte)0b0000_0100; @@ -172,7 +172,7 @@ public void shouldGenerateChoiceSetStub() throws Exception } @Test - public void shouldGenerateCompositeEncoder() throws Exception + void shouldGenerateCompositeEncoder() throws Exception { final int bufferOffset = 64; final int capacityFieldOffset = bufferOffset; @@ -205,7 +205,7 @@ public void shouldGenerateCompositeEncoder() throws Exception } @Test - public void shouldGenerateCompositeDecoder() throws Exception + void shouldGenerateCompositeDecoder() throws Exception { final int bufferOffset = 64; final int capacityFieldOffset = bufferOffset; @@ -233,7 +233,7 @@ public void shouldGenerateCompositeDecoder() throws Exception } @Test - public void shouldGenerateBasicMessage() throws Exception + void shouldGenerateBasicMessage() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); generator().generate(); @@ -248,7 +248,7 @@ public void shouldGenerateBasicMessage() throws Exception } @Test - public void shouldGenerateRepeatingGroupDecoder() throws Exception + void shouldGenerateRepeatingGroupDecoder() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); generator().generate(); @@ -269,7 +269,7 @@ public void shouldGenerateRepeatingGroupDecoder() throws Exception } @Test - public void shouldGenerateReadOnlyMessage() throws Exception + void shouldGenerateReadOnlyMessage() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); generator().generate(); @@ -284,7 +284,7 @@ public void shouldGenerateReadOnlyMessage() throws Exception } @Test - public void shouldGenerateVarDataCodecs() throws Exception + void shouldGenerateVarDataCodecs() throws Exception { final String expectedManufacturer = "Ford"; final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); @@ -302,7 +302,7 @@ public void shouldGenerateVarDataCodecs() throws Exception } @Test - public void shouldGenerateCompositeDecoding() throws Exception + void shouldGenerateCompositeDecoding() throws Exception { final int expectedEngineCapacity = 2000; final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); @@ -320,7 +320,7 @@ public void shouldGenerateCompositeDecoding() throws Exception } @Test - public void shouldGenerateBitSetCodecs() throws Exception + void shouldGenerateBitSetCodecs() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); @@ -338,7 +338,7 @@ public void shouldGenerateBitSetCodecs() throws Exception } @Test - public void shouldGenerateEnumCodecs() throws Exception + void shouldGenerateEnumCodecs() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); generator().generate(); @@ -355,7 +355,7 @@ public void shouldGenerateEnumCodecs() throws Exception } @Test - public void shouldGenerateGetString() throws Exception + void shouldGenerateGetString() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); generator().generate(); @@ -374,7 +374,7 @@ public void shouldGenerateGetString() throws Exception } @Test - public void shouldGenerateGetFixedLengthStringUsingAppendable() throws Exception + void shouldGenerateGetFixedLengthStringUsingAppendable() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); final StringBuilder result = new StringBuilder(); @@ -399,7 +399,7 @@ public void shouldGenerateGetFixedLengthStringUsingAppendable() throws Exception } @Test - public void shouldGenerateGetVariableStringUsingAppendable() throws Exception + void shouldGenerateGetVariableStringUsingAppendable() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); final StringBuilder result = new StringBuilder(); @@ -423,7 +423,7 @@ public void shouldGenerateGetVariableStringUsingAppendable() throws Exception } @Test - public void shouldGeneratePutCharSequence() throws Exception + void shouldGeneratePutCharSequence() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); generator().generate(); @@ -442,7 +442,7 @@ public void shouldGeneratePutCharSequence() throws Exception } @Test - public void shouldGenerateRepeatingGroupCountLimits() throws Exception + void shouldGenerateRepeatingGroupCountLimits() throws Exception { generator().generate(); @@ -459,7 +459,7 @@ public void shouldGenerateRepeatingGroupCountLimits() throws Exception } @Test - public void shouldMarkDeprecatedClasses() throws Exception + void shouldMarkDeprecatedClasses() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); final MessageSchema schema = parse(Tests.getLocalResource("deprecated-msg-test-schema.xml"), options); @@ -518,7 +518,7 @@ private static Object wrap( } @Test - public void shouldValidateMissingMutableBufferClass() + void shouldValidateMissingMutableBufferClass() { assertThrows( IllegalArgumentException.class, @@ -526,7 +526,7 @@ public void shouldValidateMissingMutableBufferClass() } @Test - public void shouldValidateNotImplementedMutableBufferClass() + void shouldValidateNotImplementedMutableBufferClass() { assertThrows( IllegalArgumentException.class, @@ -534,7 +534,7 @@ public void shouldValidateNotImplementedMutableBufferClass() } @Test - public void shouldValidateMissingReadOnlyBufferClass() + void shouldValidateMissingReadOnlyBufferClass() { assertThrows( IllegalArgumentException.class, @@ -542,7 +542,7 @@ public void shouldValidateMissingReadOnlyBufferClass() } @Test - public void shouldValidateNotImplementedReadOnlyBufferClass() + void shouldValidateNotImplementedReadOnlyBufferClass() { assertThrows( IllegalArgumentException.class, diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java index 4c72144043..5152196ed0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java @@ -26,12 +26,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue; -public class PackageOutputManagerTest +class PackageOutputManagerTest { private final String tempDirName = System.getProperty("java.io.tmpdir"); @Test - public void shouldCreateFileWithinPackage() throws Exception + void shouldCreateFileWithinPackage() throws Exception { final String packageName = "uk.co.real_logic.test"; final String exampleClassName = "ExampleClassName"; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java index 37130e8d40..9a4974ebf1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java @@ -27,7 +27,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; -public class RewindTest extends EncodedCarTestBase +class RewindTest extends EncodedCarTestBase { private static final int MSG_BUFFER_CAPACITY = 4 * 1024; @@ -57,5 +57,4 @@ void shouldRewindAfterReadingFullMessage() final ArrayList passThree = CarDecodeTestUtil.getValues(carDecoder); assertEquals(passOne, passThree); } - } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index 1620bbf740..78c6e2d5de 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -39,7 +39,7 @@ import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @SuppressWarnings("MethodLength") -public class SchemaExtensionTest +class SchemaExtensionTest { private static final Class BUFFER_CLASS = MutableDirectBuffer.class; private static final String BUFFER_NAME = BUFFER_CLASS.getName(); @@ -51,7 +51,7 @@ public class SchemaExtensionTest private Ir ir; @BeforeEach - public void setup() throws Exception + void setup() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); final MessageSchema schema = parse(Tests.getLocalResource("extension-schema.xml"), options); @@ -65,7 +65,7 @@ public void setup() throws Exception } @Test - public void testMessage1() throws Exception + void testMessage1() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); @@ -186,7 +186,7 @@ public void testMessage1() throws Exception } @Test - public void testMessage2() throws Exception + void testMessage2() throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java index f1c0cd9824..23d6246566 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java @@ -25,7 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class SkipAndDecodedLengthTest extends EncodedCarTestBase +class SkipAndDecodedLengthTest extends EncodedCarTestBase { private static final int MSG_BUFFER_CAPACITY = 4 * 1024; From 585cb9d90697269882d52f511178b0f0924e0fcd Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 11 Feb 2022 11:15:50 +0000 Subject: [PATCH 0850/1594] [Java] Avoid use of String.format. --- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index 967a84063f..39c8f4e02f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -82,8 +82,8 @@ public class EnumType extends Type default: // might not have run into this type yet, so look for it - final Node encodingTypeNode = (Node)xPath.compile( - String.format("%s[@name='%s']", XmlSchemaParser.TYPE_XPATH_EXPR, encodingTypeStr)) + final String expression = TYPE_XPATH_EXPR + "[@name='" + encodingTypeStr + "']"; + final Node encodingTypeNode = (Node)xPath.compile(expression) .evaluate(node.getOwnerDocument(), XPathConstants.NODE); if (null == encodingTypeNode) From 2f1b555c2d8e2185ac7c677cc3979fdfa9e857d1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 11 Feb 2022 14:30:11 +0000 Subject: [PATCH 0851/1594] [Java] Generate null value for enums based on specialised type when provided rather than default primitive type. PR #889. --- .../sbe/generation/java/JavaGenerator.java | 18 ++--- .../sbe/ir/generated/SignalCodec.java | 2 +- .../uk/co/real_logic/sbe/xml/EnumType.java | 36 ++++------ .../uk/co/real_logic/sbe/xml/IrGenerator.java | 6 +- sbe-tool/src/main/resources/sbe-ir.xml | 2 +- .../generation/java/NullEnumTypedTest.java | 66 +++++++++++++++++++ .../real_logic/sbe/xml/ErrorHandlerTest.java | 2 +- .../resources/error-handler-types-schema.xml | 1 + sbe-tool/src/test/resources/issue889.xml | 26 ++++++++ 9 files changed, 116 insertions(+), 43 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java create mode 100644 sbe-tool/src/test/resources/issue889.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 1c0fc182ff..e928bc90ba 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1236,16 +1236,18 @@ private void generateEnum(final List tokens) throws IOException { final Token enumToken = tokens.get(0); final String enumName = formatClassName(enumToken.applicableTypeName()); + final Encoding encoding = enumToken.encoding(); + final String nullVal = encoding.applicableNullValue().toString(); try (Writer out = outputManager.createOutput(enumName)) { out.append(generateEnumFileHeader(ir.applicableNamespace())); out.append(generateEnumDeclaration(enumName, enumToken)); - out.append(generateEnumValues(getMessageBody(tokens))); + out.append(generateEnumValues(getMessageBody(tokens), generateLiteral(encoding.primitiveType(), nullVal))); out.append(generateEnumBody(enumToken, enumName)); - out.append(generateEnumLookupMethod(getMessageBody(tokens), enumName)); + out.append(generateEnumLookupMethod(getMessageBody(tokens), enumName, nullVal)); out.append("}\n"); } @@ -1451,7 +1453,7 @@ private String bitsetArgType(final PrimitiveType primitiveType) } } - private CharSequence generateEnumValues(final List tokens) + private CharSequence generateEnumValues(final List tokens, final String nullVal) { final StringBuilder sb = new StringBuilder(); @@ -1463,11 +1465,6 @@ private CharSequence generateEnumValues(final List tokens) sb.append(INDENT).append(token.name()).append('(').append(constVal).append("),\n\n"); } - final Token token = tokens.get(0); - final Encoding encoding = token.encoding(); - final CharSequence nullVal = generateLiteral( - encoding.primitiveType(), encoding.applicableNullValue().toString()); - if (shouldDecodeUnknownEnumValues) { sb.append(INDENT).append("/**\n"); @@ -1505,7 +1502,7 @@ private CharSequence generateEnumBody(final Token token, final String enumName) " }\n"; } - private CharSequence generateEnumLookupMethod(final List tokens, final String enumName) + private CharSequence generateEnumLookupMethod(final List tokens, final String enumName, final String nullVal) { final StringBuilder sb = new StringBuilder(); final PrimitiveType primitiveType = tokens.get(0).encoding().primitiveType(); @@ -1528,8 +1525,7 @@ private CharSequence generateEnumLookupMethod(final List tokens, final St sb.append(" case ").append(constStr).append(": return ").append(name).append(";\n"); } - final String nullValue = tokens.get(0).encoding().applicableNullValue().toString(); - sb.append(" case ").append(nullValue).append(": return NULL_VAL").append(";\n"); + sb.append(" case ").append(nullVal).append(": return NULL_VAL").append(";\n"); final String handleUnknownLogic = shouldDecodeUnknownEnumValues ? INDENT + INDENT + "return SBE_UNKNOWN;\n" : diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java index 59940ef860..dd812e782e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java @@ -81,7 +81,7 @@ public enum SignalCodec /** - * Signal the a choice in a set. + * Signal the choice in a set. */ CHOICE((short)13), diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index 39c8f4e02f..3197c08c47 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -105,28 +105,20 @@ public class EnumType extends Type final String nullValueStr = getAttributeValueOrNull(node, "nullValue"); if (null != nullValueStr) { - if (presence() != OPTIONAL) - { - handleError(node, "nullValue set, but presence is not optional"); - } - nullValue = PrimitiveValue.parse(nullValueStr, encodingType); } - else if (presence() == OPTIONAL) + else if (null != encodedDataType && null != encodedDataType.nullValue()) { - if (null != encodedDataType && null != encodedDataType.nullValue()) - { - nullValue = encodedDataType.nullValue(); - } - else - { - handleError(node, "presence optional but no null value found"); - nullValue = null; - } + nullValue = encodedDataType.nullValue(); } else { - nullValue = null; + nullValue = encodingType.nullValue(); + } + + if (presence() == OPTIONAL && null == nullValue) + { + handleError(node, "presence optional but no null value found"); } final NodeList list = (NodeList)xPath.compile("validValue").evaluate(node, XPathConstants.NODESET); @@ -152,15 +144,11 @@ else if (presence() == OPTIONAL) encodedDataType.minValue().longValue() : encodingType.minValue().longValue(); final long maxValue = null != encodedDataType && null != encodedDataType.maxValue() ? encodedDataType.maxValue().longValue() : encodingType.maxValue().longValue(); - final long nullLongValue = null != nullValue ? nullValue.longValue() : - encodingType.nullValue().longValue(); + final long nullLongValue = nullValue.longValue(); if (nullLongValue == value) { - handleError( - node, - "validValue " + v.name() + " uses nullValue: " + - (null != nullValue ? nullValue : encodingType.nullValue())); + handleError(node, "validValue " + v.name() + " uses nullValue: " + nullLongValue); } else if (value < minValue || value > maxValue) { @@ -223,9 +211,9 @@ public ValidValue getValidValue(final String name) } /** - * The nullValue of the type + * The nullValue of the type. * - * @return value of the nullValue + * @return value of the nullValue. */ public PrimitiveValue nullValue() { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index 9a61439426..87e3e4717d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -263,13 +263,9 @@ private void add(final EnumType type, final int offset, final Field field) final Encoding.Builder encodingBuilder = new Encoding.Builder() .primitiveType(encodingType) .semanticType(semanticTypeOf(type, field)) + .nullValue(type.nullValue()) .byteOrder(schema.byteOrder()); - if (type.presence() == Presence.OPTIONAL) - { - encodingBuilder.nullValue(encodingType.nullValue()); - } - final Token.Builder builder = new Token.Builder() .signal(Signal.BEGIN_ENUM) .name(type.name()) diff --git a/sbe-tool/src/main/resources/sbe-ir.xml b/sbe-tool/src/main/resources/sbe-ir.xml index 9d70ef93db..4b55318f53 100644 --- a/sbe-tool/src/main/resources/sbe-ir.xml +++ b/sbe-tool/src/main/resources/sbe-ir.xml @@ -47,7 +47,7 @@ 10 11 12 - 13 + 13 14 15 16 diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java new file mode 100644 index 0000000000..9c930485cb --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.util.Map; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.StringContains.containsString; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +class NullEnumTypedTest +{ + private static final Class BUFFER_CLASS = MutableDirectBuffer.class; + private static final String BUFFER_NAME = BUFFER_CLASS.getName(); + private static final Class READ_ONLY_BUFFER_CLASS = DirectBuffer.class; + private static final String READ_ONLY_BUFFER_NAME = READ_ONLY_BUFFER_CLASS.getName(); + + @Test + void shouldGenerateEnumWithNonDefaultNullType() throws Exception + { + final ParserOptions options = ParserOptions.builder() + .stopOnError(true) + .build(); + final MessageSchema schema = parse(Tests.getLocalResource("issue889.xml"), options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, true, outputManager); + + outputManager.setPackageName(ir.applicableNamespace()); + generator.generateMessageHeaderStub(); + generator.generateTypeStubs(); + generator.generate(); + + final Map sources = outputManager.getSources(); + final String source = sources.get("issue889.LotType").toString(); + + assertThat(source, containsString("NULL_VAL((short)0);")); + assertThat(source, containsString("case 0: return NULL_VAL;")); + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index 2707138cb6..405a63e902 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -88,7 +88,7 @@ public void shouldNotExitOnTypeErrorsAndWarnings() throws Exception parseTestXmlAddToMap(map, "/types/enum", testXmlString, handler); parseTestXmlAddToMap(map, "/types/set", testXmlString, handler); - assertThat(handler.errorCount(), is(3)); + assertThat(handler.errorCount(), is(2)); assertThat(handler.warningCount(), is(33)); } diff --git a/sbe-tool/src/test/resources/error-handler-types-schema.xml b/sbe-tool/src/test/resources/error-handler-types-schema.xml index 02e6f6fe19..a21430c81a 100644 --- a/sbe-tool/src/test/resources/error-handler-types-schema.xml +++ b/sbe-tool/src/test/resources/error-handler-types-schema.xml @@ -8,6 +8,7 @@ 0 1 + 255 diff --git a/sbe-tool/src/test/resources/issue889.xml b/sbe-tool/src/test/resources/issue889.xml new file mode 100644 index 0000000000..286d472b57 --- /dev/null +++ b/sbe-tool/src/test/resources/issue889.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + 1 + 2 + 3 + + + + + + \ No newline at end of file From 71bb045085518d06c7a493c93f0873c0fd71203a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 11 Feb 2022 16:30:35 +0000 Subject: [PATCH 0852/1594] [C++] Check for specialised null value when generated enum. PR #889. --- sbe-tool/src/test/cpp/CMakeLists.txt | 13 ++++++++++-- sbe-tool/src/test/cpp/Issue889Test.cpp | 29 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 sbe-tool/src/test/cpp/Issue889Test.cpp diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index bef2c99280..438844b066 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -34,11 +34,12 @@ endfunction() find_package(Java REQUIRED) set(CODE_GENERATION_SCHEMA ${CODEC_SCHEMA_DIR}/code-generation-schema.xml) +set(COMPOSITE_ELEMENTS_SCHEMA ${CODEC_SCHEMA_DIR}/composite-elements-schema.xml) set(COMPOSITE_OFFSETS_SCHEMA ${CODEC_SCHEMA_DIR}/composite-offsets-schema.xml) set(MESSAGE_BLOCK_LENGTH_TEST ${CODEC_SCHEMA_DIR}/message-block-length-test.xml) set(GROUP_WITH_DATA_SCHEMA ${CODEC_SCHEMA_DIR}/group-with-data-schema.xml) -set(COMPOSITE_ELEMENTS_SCHEMA ${CODEC_SCHEMA_DIR}/composite-elements-schema.xml) set(ISSUE835_SCHEMA ${CODEC_SCHEMA_DIR}/issue835.xml) +set(ISSUE889_SCHEMA ${CODEC_SCHEMA_DIR}/issue889.xml) set(GENERATED_CODECS ${CXX_CODEC_TARGET_DIR} @@ -46,7 +47,13 @@ set(GENERATED_CODECS add_custom_command( OUTPUT ${GENERATED_CODECS} - DEPENDS ${CODE_GENERATION_SCHEMA} ${CODE_GENERATION_SCHEMA_CPP} ${COMPOSITE_OFFSETS_SCHEMA} ${MESSAGE_BLOCK_LENGTH_TEST} + DEPENDS ${CODE_GENERATION_SCHEMA} + ${COMPOSITE_ELEMENTS_SCHEMA} + ${COMPOSITE_OFFSETS_SCHEMA} + ${MESSAGE_BLOCK_LENGTH_TEST} + ${GROUP_WITH_DATA_SCHEMA} + ${ISSUE835_SCHEMA} + ${ISSUE889_SCHEMA} sbe-jar ${SBE_JAR} COMMAND ${Java_JAVA_EXECUTABLE} @@ -60,6 +67,7 @@ add_custom_command( ${GROUP_WITH_DATA_SCHEMA} ${COMPOSITE_ELEMENTS_SCHEMA} ${ISSUE835_SCHEMA} + ${ISSUE889_SCHEMA} ) add_custom_target(codecs DEPENDS ${GENERATED_CODECS}) @@ -74,3 +82,4 @@ sbe_test(GroupWithDataTest codecs) sbe_test(Rc3OtfFullIrTest codecs) sbe_test(CompositeElementsTest codecs) sbe_test(Issue835Test codecs) +sbe_test(Issue889Test codecs) diff --git a/sbe-tool/src/test/cpp/Issue889Test.cpp b/sbe-tool/src/test/cpp/Issue889Test.cpp new file mode 100644 index 0000000000..1804152646 --- /dev/null +++ b/sbe-tool/src/test/cpp/Issue889Test.cpp @@ -0,0 +1,29 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" +#include "issue889/LotType.h" + +using namespace issue889; + +class Issue889Test : public testing::Test +{ +}; + +TEST_F(Issue889Test, shouldGenerateSpecalisedNullValue) +{ + EXPECT_EQ(LotType::get(0), LotType::NULL_VALUE); +} From 595d73c4bed41108f101b0dc378b41971661f5a1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 11 Feb 2022 16:55:52 +0000 Subject: [PATCH 0853/1594] [C] Check for specialised null value when generated enum. PR #889. --- sbe-tool/src/test/c/CMakeLists.txt | 5 ++++- sbe-tool/src/test/c/Issue889Test.cpp | 31 ++++++++++++++++++++++++++ sbe-tool/src/test/cpp/Issue889Test.cpp | 3 ++- 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 sbe-tool/src/test/c/Issue889Test.cpp diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index 32147f3c73..9d3c2b03dd 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -35,6 +35,7 @@ find_package(Java REQUIRED) set(CODE_GENERATION_SCHEMA ${CODEC_SCHEMA_DIR}/code-generation-schema.xml) set(GROUP_WITH_DATA_SCHEMA ${CODEC_SCHEMA_DIR}/group-with-data-schema.xml) +set(ISSUE889_SCHEMA ${CODEC_SCHEMA_DIR}/issue889.xml) set(GENERATED_CODECS ${C_CODEC_TARGET_DIR} @@ -42,7 +43,7 @@ set(GENERATED_CODECS add_custom_command( OUTPUT ${GENERATED_CODECS} - DEPENDS sbe-jar ${SBE_JAR} ${CODE_GENERATION_SCHEMA} ${GROUP_WITH_DATA_SCHEMA} + DEPENDS sbe-jar ${SBE_JAR} ${CODE_GENERATION_SCHEMA} ${GROUP_WITH_DATA_SCHEMA} ${ISSUE889_SCHEMA} COMMAND ${Java_JAVA_EXECUTABLE} -Dsbe.output.dir=${C_CODEC_TARGET_DIR} @@ -50,6 +51,7 @@ add_custom_command( -jar ${SBE_JAR} ${CODE_GENERATION_SCHEMA} ${GROUP_WITH_DATA_SCHEMA} + ${ISSUE889_SCHEMA} ) add_custom_target(c_codecs DEPENDS ${GENERATED_CODECS}) @@ -58,6 +60,7 @@ add_custom_target(c_codecs DEPENDS ${GENERATED_CODECS}) sbe_test(BoundsCheckTest c_codecs) sbe_test(CodeGenTest c_codecs) sbe_test(GroupWithDataTest c_codecs) +sbe_test(Issue889Test c_codecs) # Compile a dummy C source to test C compliance of generated headers. add_executable(CComplianceTest CComplianceTest.c) diff --git a/sbe-tool/src/test/c/Issue889Test.cpp b/sbe-tool/src/test/c/Issue889Test.cpp new file mode 100644 index 0000000000..c0f5ec36a1 --- /dev/null +++ b/sbe-tool/src/test/c/Issue889Test.cpp @@ -0,0 +1,31 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "issue889/lotType.h" + +class Issue889Test : public testing::Test +{ +}; + +TEST_F(Issue889Test, shouldGenerateSpecalisedNullValue) +{ + issue889_lotType lot_type; + + EXPECT_TRUE(issue889_lotType_get(0, &lot_type)); + EXPECT_EQ(lot_type, issue889_lotType::issue889_lotType_NULL_VALUE); +} diff --git a/sbe-tool/src/test/cpp/Issue889Test.cpp b/sbe-tool/src/test/cpp/Issue889Test.cpp index 1804152646..1b0c67433d 100644 --- a/sbe-tool/src/test/cpp/Issue889Test.cpp +++ b/sbe-tool/src/test/cpp/Issue889Test.cpp @@ -14,7 +14,8 @@ * limitations under the License. */ -#include "gtest/gtest.h" +#include + #include "issue889/LotType.h" using namespace issue889; From 9b8c5db52e7b2c49bd2086e9beb080a83adcdbf6 Mon Sep 17 00:00:00 2001 From: spoerri Date: Mon, 7 Mar 2022 04:30:37 -0500 Subject: [PATCH 0854/1594] toString() shouldn't disturb repeating groups #890 (#892) * toString() shouldn't disturb repeating groups #890 * Remove trailing whitespace * Ugh, removed more whitespace --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index e928bc90ba..ab8e351395 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3475,6 +3475,9 @@ private void appendDecoderDisplay( final String groupName = formatPropertyName(groupToken.name()); final String groupDecoderName = decoderName(groupToken.name()); + append(sb, indent, "int " + groupName + "OriginalOffset = " + groupName + ".offset;"); + append(sb, indent, "int " + groupName + "OriginalIndex = " + groupName + ".index;"); + append( sb, indent, "builder.append(\"" + groupName + Separator.KEY_VALUE + Separator.BEGIN_GROUP + "\");"); append(sb, indent, groupDecoderName + " " + groupName + " = " + groupName + "();"); @@ -3489,6 +3492,9 @@ private void appendDecoderDisplay( append(sb, indent, "}"); Separator.END_GROUP.appendToGeneratedBuilder(sb, indent); + append(sb, indent, groupName + ".offset = " + groupName + "OriginalOffset;"); + append(sb, indent, groupName + ".index = " + groupName + "OriginalIndex;"); + lengthBeforeLastGeneratedSeparator = sb.length(); Separator.FIELD.appendToGeneratedBuilder(sb, indent); From c24b79336a6cd2fc45b5021de18dbfd2188320c5 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 7 Mar 2022 09:50:11 +0000 Subject: [PATCH 0855/1594] [Java] Tidy up generated code style. PR #892. --- .../real_logic/sbe/generation/java/JavaGenerator.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index ab8e351395..8778c06299 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3475,12 +3475,12 @@ private void appendDecoderDisplay( final String groupName = formatPropertyName(groupToken.name()); final String groupDecoderName = decoderName(groupToken.name()); - append(sb, indent, "int " + groupName + "OriginalOffset = " + groupName + ".offset;"); - append(sb, indent, "int " + groupName + "OriginalIndex = " + groupName + ".index;"); - append( sb, indent, "builder.append(\"" + groupName + Separator.KEY_VALUE + Separator.BEGIN_GROUP + "\");"); - append(sb, indent, groupDecoderName + " " + groupName + " = " + groupName + "();"); + append(sb, indent, "final int " + groupName + "OriginalOffset = " + groupName + ".offset;"); + append(sb, indent, "final int " + groupName + "OriginalIndex = " + groupName + ".index;"); + append(sb, indent, "final " + groupDecoderName + " " + groupName + " = " + groupName + "();"); + append(sb, indent, "if (" + groupName + ".count() > 0)"); append(sb, indent, "{"); append(sb, indent, " while (" + groupName + ".hasNext())"); @@ -3490,10 +3490,11 @@ private void appendDecoderDisplay( append(sb, indent, " }"); append(sb, indent, " builder.setLength(builder.length() - 1);"); append(sb, indent, "}"); - Separator.END_GROUP.appendToGeneratedBuilder(sb, indent); append(sb, indent, groupName + ".offset = " + groupName + "OriginalOffset;"); append(sb, indent, groupName + ".index = " + groupName + "OriginalIndex;"); + Separator.END_GROUP.appendToGeneratedBuilder(sb, indent); + lengthBeforeLastGeneratedSeparator = sb.length(); Separator.FIELD.appendToGeneratedBuilder(sb, indent); From 36ca5b4bcc044c802dcd64bb12601172c150ac5a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 8 Mar 2022 17:16:56 +0000 Subject: [PATCH 0856/1594] [Java] Upgrade to Mockito 4.4.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 84f4da1a82..d784a2681d 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' -def mockitoVersion = '4.3.1' +def mockitoVersion = '4.4.0' def junitVersion = '5.8.2' def jmhVersion = '1.34' def agronaVersion = '1.14.0' From 05d9c4557d8a68ca2178741886fbca4028d1ed7f Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 10 Mar 2022 18:25:50 +0100 Subject: [PATCH 0857/1594] [Java] Upgrade to Gradle 7.4.1. --- build.gradle | 6 +++--- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 59821 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index d784a2681d..0f1c101f79 100644 --- a/build.gradle +++ b/build.gradle @@ -774,9 +774,9 @@ task runJavaBenchmarks(type: Exec, dependsOn: 'sbe-benchmarks:jar') { } task testReport(type: TestReport) { - destinationDir = file("$buildDir/reports/allTests") + destinationDirectory = file("$buildDir/reports/allTests") // Include the results from the `test` task in all sub-projects - reportOn subprojects*.test + testResults.setFrom(subprojects*.test) } final codecsDir = project.file('sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated') @@ -821,7 +821,7 @@ tasks.named('dependencyUpdates').configure { tasks.findByName('build').dependsOn verifyJavaIrCodecsInSync wrapper { - gradleVersion = '7.3.3' + gradleVersion = '7.4.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..41d9927a4d4fb3f96a785543079b8df6723c946b 100644 GIT binary patch delta 8958 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 669386b870..d7e66b5c61 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 488167b321cef2af6958a446ab8f61c87c00a37f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 15 Mar 2022 18:24:40 +0000 Subject: [PATCH 0858/1594] [Java] Upgrade to Agrona 1.15.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0f1c101f79..b7614cafdb 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.4.0' def junitVersion = '5.8.2' def jmhVersion = '1.34' -def agronaVersion = '1.14.0' +def agronaVersion = '1.15.0' def agronaVersionRange = '[1.14,1.15[' // allow any patch release of 1.14.x def sbeGroup = 'uk.co.real-logic' From 2fc765979ab02a398e8aedc6dbf51ff3434533fd Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 18 Mar 2022 18:01:24 +0000 Subject: [PATCH 0859/1594] [Java] Increase minor version. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 6fb671d7e9..b4f8049e9c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.25.2-SNAPSHOT +1.26.0-SNAPSHOT From ce68063f21a803b451ccff1c616f0ef7ca24bb54 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Fri, 18 Mar 2022 11:11:17 -0700 Subject: [PATCH 0860/1594] 1.25.2 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 6fb671d7e9..61b813d5e6 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.25.2-SNAPSHOT +1.25.2 From 75f10ed0e23ee131548ac7e156bc6d425e3d30e8 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 21 Mar 2022 22:12:12 +0100 Subject: [PATCH 0861/1594] [CI] Allow only one concurrent build of the same workflow at a time. Every new attempt to build should cancel already running build. --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6b3b0a7901..d4bf19f1d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,10 @@ on: branches: - master +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + env: GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail" CMAKE_VERSION: "3.6.1" From 408976ae5a5b2106402f8264c22baeb3a03518de Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 21 Mar 2022 22:17:17 +0100 Subject: [PATCH 0862/1594] [Java] Fix Agrona version range to match the 1.15.x release. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b7614cafdb..28808b39da 100644 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,7 @@ def mockitoVersion = '4.4.0' def junitVersion = '5.8.2' def jmhVersion = '1.34' def agronaVersion = '1.15.0' -def agronaVersionRange = '[1.14,1.15[' // allow any patch release of 1.14.x +def agronaVersionRange = '[1.15,1.16[' // allow any patch release of 1.15.x def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From ebae848f74494dfe79b5afd9d427e0b7d8bf2844 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 22 Mar 2022 19:17:39 +0100 Subject: [PATCH 0863/1594] [Java] Update JavaDoc URL for JDK 18 GA. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 28808b39da..9648d5b0b6 100644 --- a/build.gradle +++ b/build.gradle @@ -191,7 +191,7 @@ subprojects { options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' options.links("https://www.javadoc.io/doc/org.agrona/agrona/${agronaVersion}/") - if (buildJavaVersion >= 18) { // early access JavaDoc location is different + if (buildJavaVersion >= 19) { // early access JavaDoc location is different options.links("https://download.java.net/java/early_access/jdk${buildJavaVersion}/docs/api/") } else if (buildJavaVersion >= 11) { From cd62d5a4512053728f02c96d48f7b2411e8b4061 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 28 Mar 2022 14:56:39 +0100 Subject: [PATCH 0864/1594] [Java] Upgrade to JMH 1.35. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9648d5b0b6..07f3c639de 100644 --- a/build.gradle +++ b/build.gradle @@ -46,7 +46,7 @@ def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.4.0' def junitVersion = '5.8.2' -def jmhVersion = '1.34' +def jmhVersion = '1.35' def agronaVersion = '1.15.0' def agronaVersionRange = '[1.15,1.16[' // allow any patch release of 1.15.x From 62b30616ad98147d801e4104082d0db1b7daf882 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 4 Apr 2022 13:02:34 +0200 Subject: [PATCH 0865/1594] [Java] Upgrade to Gradle 7.4.2. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 07f3c639de..d488148251 100644 --- a/build.gradle +++ b/build.gradle @@ -821,7 +821,7 @@ tasks.named('dependencyUpdates').configure { tasks.findByName('build').dependsOn verifyJavaIrCodecsInSync wrapper { - gradleVersion = '7.4.1' + gradleVersion = '7.4.2' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d7e66b5c61..92f06b50fd 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 227a6f9367b0423132d3bb72fab7dbd3415424c1 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 13 Apr 2022 09:45:54 +0200 Subject: [PATCH 0866/1594] [CI] Use JDK 18 GA release. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4bf19f1d4..421f93d3f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '11', '17', '18-ea' ] + java: [ '8', '11', '17', '18' ] os: [ 'ubuntu-20.04', 'windows-latest' ] steps: - name: Checkout code From 14467844eada59775d0b87d873e82b6b452c2ac6 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 14 Apr 2022 18:05:29 +0100 Subject: [PATCH 0867/1594] [Java] Upgrade to Agrona 1.15.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d488148251..1bf300ad28 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.4.0' def junitVersion = '5.8.2' def jmhVersion = '1.35' -def agronaVersion = '1.15.0' +def agronaVersion = '1.15.1' def agronaVersionRange = '[1.15,1.16[' // allow any patch release of 1.15.x def sbeGroup = 'uk.co.real-logic' From 388010963e96fa1a4c21cfb8fe241ec9b7f898a1 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 14 Apr 2022 18:08:46 +0100 Subject: [PATCH 0868/1594] Set version to 1.25.2. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index b4f8049e9c..6fb671d7e9 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.26.0-SNAPSHOT +1.25.2-SNAPSHOT From 58e9a4bb387b49028d0bb8ab64e3bba0d37055a7 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 14 Apr 2022 18:17:29 +0100 Subject: [PATCH 0869/1594] Correct version. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 6fb671d7e9..47bcf2880a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.25.2-SNAPSHOT +1.25.3-SNAPSHOT From 143cfd5df715f3a130e207e627f8b7ddaee758ee Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Thu, 14 Apr 2022 10:30:15 -0700 Subject: [PATCH 0870/1594] 1.25.3 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 47bcf2880a..5bb76b575e 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.25.3-SNAPSHOT +1.25.3 From 6524c5b10a04132a99309f8f776681d30d0b71ac Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Thu, 14 Apr 2022 10:31:26 -0700 Subject: [PATCH 0871/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 5bb76b575e..bda7b6dbcb 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.25.3 +1.25.4-SNAPSHOT From 48c722ec84d1c8066865907e607c5e965be2b4bb Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 20 Apr 2022 09:58:29 +0100 Subject: [PATCH 0872/1594] Upgrade to Mockito 4.5.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1bf300ad28..a18ad6c370 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' -def mockitoVersion = '4.4.0' +def mockitoVersion = '4.5.0' def junitVersion = '5.8.2' def jmhVersion = '1.35' def agronaVersion = '1.15.1' From 9af63a1ceb5c0f78e2929d7750db97f3fbde0265 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 28 Apr 2022 14:29:46 +0200 Subject: [PATCH 0873/1594] [Java] Upgrade to Mockito 4.5.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a18ad6c370..c76b35f4d7 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' -def mockitoVersion = '4.5.0' +def mockitoVersion = '4.5.1' def junitVersion = '5.8.2' def jmhVersion = '1.35' def agronaVersion = '1.15.1' From 0382cba6e6970b8616c59a5231d0b81ff3844a5e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 4 May 2022 15:23:34 +0100 Subject: [PATCH 0874/1594] [Java] Generate SuppressWarnings annotation for enum types. Issue #894. --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 3 ++- .../java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java | 1 + .../java/uk/co/real_logic/sbe/ir/generated/MetaAttribute.java | 1 + .../java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java | 1 + .../uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java | 1 + .../java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java | 1 + 6 files changed, 7 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 8778c06299..d9ed796c4c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1673,6 +1673,7 @@ private void generateMetaAttributeEnum() throws IOException "/**\n" + " * Meta attribute enum for selecting a particular meta attribute value.\n" + " */\n" + + " @SuppressWarnings(\"all\")\n" + "public enum MetaAttribute\n" + "{\n" + " /**\n" + @@ -1700,7 +1701,7 @@ private static CharSequence generateEnumDeclaration(final String name, final Tok final StringBuilder sb = new StringBuilder(); generateTypeJavadoc(sb, BASE_INDENT, typeToken); - sb.append("public enum ").append(name).append("\n{\n"); + sb.append("@SuppressWarnings(\"all\")\n").append("public enum ").append(name).append("\n{\n"); return sb; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java index fc8fd3463b..76fc614e8b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/ByteOrderCodec.java @@ -5,6 +5,7 @@ /** * Number encoding byte order. */ +@SuppressWarnings("all") public enum ByteOrderCodec { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MetaAttribute.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MetaAttribute.java index 7bac3df062..7e10779484 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MetaAttribute.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MetaAttribute.java @@ -4,6 +4,7 @@ /** * Meta attribute enum for selecting a particular meta attribute value. */ + @SuppressWarnings("all") public enum MetaAttribute { /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java index ceea18d898..8d135992f0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PresenceCodec.java @@ -5,6 +5,7 @@ /** * Field presence declaration. */ +@SuppressWarnings("all") public enum PresenceCodec { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java index bc2f89cde3..464d0af814 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/PrimitiveTypeCodec.java @@ -5,6 +5,7 @@ /** * Primitive types in type system. */ +@SuppressWarnings("all") public enum PrimitiveTypeCodec { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java index dd812e782e..e1ba77713e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/SignalCodec.java @@ -5,6 +5,7 @@ /** * Token signal type in IR. */ +@SuppressWarnings("all") public enum SignalCodec { From a61401114a6bc5cbd933f4196ddd99a53358b62c Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 11 May 2022 15:42:23 +0200 Subject: [PATCH 0875/1594] [CI] Add Clang 14 to the build matrix. --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 421f93d3f2..2068ac66da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,8 +13,8 @@ concurrency: cancel-in-progress: true env: - GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail" - CMAKE_VERSION: "3.6.1" + GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail' + CMAKE_VERSION: '3.14.7' jobs: java-build: @@ -142,7 +142,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '6.0', '7', '8', '9', '10', '11', '12', '13' ] + version: [ '6.0', '7', '8', '9', '10', '11', '12', '13', '14' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} @@ -244,4 +244,4 @@ jobs: profile: minimal toolchain: ${{ matrix.rust }} override: true - - run: ./gradlew runRustTests \ No newline at end of file + - run: ./gradlew runRustTests From 061be357ff7c1a2f387b57b79af27a8051403a36 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 16 May 2022 20:34:29 +0200 Subject: [PATCH 0876/1594] [Java] Allow any Agrona version >= 1.15.0 and < 2.0.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c76b35f4d7..0e40567df0 100644 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,7 @@ def mockitoVersion = '4.5.1' def junitVersion = '5.8.2' def jmhVersion = '1.35' def agronaVersion = '1.15.1' -def agronaVersionRange = '[1.15,1.16[' // allow any patch release of 1.15.x +def agronaVersionRange = '[1.15,2.0[' // allow any release >= 1.15.0 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 63069034c76c26b6e30fa09c17fc62f036bb457d Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 16 May 2022 20:35:34 +0200 Subject: [PATCH 0877/1594] [Java] Upgrade to Agrona 1.15.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0e40567df0..37aba2fb44 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.5.1' def junitVersion = '5.8.2' def jmhVersion = '1.35' -def agronaVersion = '1.15.1' +def agronaVersion = '1.15.2' def agronaVersionRange = '[1.15,2.0[' // allow any release >= 1.15.0 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' From 95824f3938a6630f9895e4886d181b9a7f05bb81 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 22 May 2022 18:08:08 +0200 Subject: [PATCH 0878/1594] [Java] Set min Agrona version to 1.15.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 37aba2fb44..ce1570debb 100644 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,7 @@ def mockitoVersion = '4.5.1' def junitVersion = '5.8.2' def jmhVersion = '1.35' def agronaVersion = '1.15.2' -def agronaVersionRange = '[1.15,2.0[' // allow any release >= 1.15.0 and < 2.0.0 +def agronaVersionRange = '[1.15.2,2.0[' // allow any release >= 1.15.2 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From e1c1278b23a0c6322dc95cae6b8aa3f2eb5aeb61 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 24 May 2022 11:07:00 +0100 Subject: [PATCH 0879/1594] [Rust] Tidy up and fix resource leak. --- .../sbe/generation/rust/LibRsDef.java | 19 ++-- .../sbe/generation/rust/RustGenerator.java | 105 +++++++++--------- .../generation/rust/RustOutputManager.java | 2 +- .../sbe/generation/rust/RustUtil.java | 1 + .../sbe/generation/rust/SubGroup.java | 1 + 5 files changed, 70 insertions(+), 58 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 796ef98d16..4913e30b9d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -19,8 +19,10 @@ import java.io.Writer; import java.nio.ByteOrder; import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.LinkedHashSet; +import java.util.stream.Stream; import static java.nio.ByteOrder.LITTLE_ENDIAN; import static uk.co.real_logic.sbe.generation.rust.RustGenerator.*; @@ -58,13 +60,16 @@ void generate() throws IOException indent(libRs, 0, "use ::core::{convert::TryInto};\n\n"); final ArrayList modules = new ArrayList<>(); - Files.walk(outputManager.getSrcDirPath()) - .filter(Files::isRegularFile) - .map((path) -> path.getFileName().toString()) - .filter((fileName) -> fileName.endsWith(".rs")) - .filter((fileName) -> !fileName.equals("lib.rs")) - .map((fileName) -> fileName.substring(0, fileName.length() - 3)) - .forEach(modules::add); + try (Stream walk = Files.walk(outputManager.getSrcDirPath())) + { + walk + .filter(Files::isRegularFile) + .map((path) -> path.getFileName().toString()) + .filter((fileName) -> fileName.endsWith(".rs")) + .filter((fileName) -> !fileName.equals("lib.rs")) + .map((fileName) -> fileName.substring(0, fileName.length() - 3)) + .forEach(modules::add); + } // add modules for (final String mod : modules) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 2df4ce440f..adb9e7b7ad 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -27,6 +27,7 @@ import uk.co.real_logic.sbe.ir.Token; import java.io.IOException; +import java.io.UncheckedIOException; import java.io.Writer; import java.util.ArrayList; import java.util.HashSet; @@ -208,32 +209,34 @@ static void generateEncoderFields( final List tokens, final int level) { - Generators.forEachField(tokens, (fieldToken, typeToken) -> - { - try + Generators.forEachField( + tokens, + (fieldToken, typeToken) -> { - final String name = fieldToken.name(); - switch (typeToken.signal()) + try { - case ENCODING: - generatePrimitiveEncoder(sb, level, typeToken, name); - break; - case BEGIN_ENUM: - generateEnumEncoder(sb, level, fieldToken, typeToken, name); - break; - case BEGIN_SET: - generateBitSetEncoder(sb, level, typeToken, name); - break; - case BEGIN_COMPOSITE: - generateCompositeEncoder(sb, level, typeToken, name); - break; + final String name = fieldToken.name(); + switch (typeToken.signal()) + { + case ENCODING: + generatePrimitiveEncoder(sb, level, typeToken, name); + break; + case BEGIN_ENUM: + generateEnumEncoder(sb, level, fieldToken, typeToken, name); + break; + case BEGIN_SET: + generateBitSetEncoder(sb, level, typeToken, name); + break; + case BEGIN_COMPOSITE: + generateCompositeEncoder(sb, level, typeToken, name); + break; + } } - } - catch (final IOException ex) - { - throw new RuntimeException(ex); - } - }); + catch (final IOException ex) + { + throw new UncheckedIOException(ex); + } + }); } static void generateEncoderGroups( @@ -489,36 +492,38 @@ static void generateDecoderFields( final List tokens, final int level) { - Generators.forEachField(tokens, (fieldToken, typeToken) -> - { - try + Generators.forEachField( + tokens, + (fieldToken, typeToken) -> { - final String name = fieldToken.name(); - final Encoding encoding = typeToken.encoding(); - - switch (typeToken.signal()) + try { - case ENCODING: - generatePrimitiveDecoder(sb, level, fieldToken, typeToken, name, encoding); - break; - case BEGIN_ENUM: - generateEnumDecoder(sb, level, fieldToken, typeToken, name); - break; - case BEGIN_SET: - generateBitSetDecoder(sb, level, typeToken, name); - break; - case BEGIN_COMPOSITE: - generateCompositeDecoder(sb, level, fieldToken, typeToken, name); - break; - default: - throw new UnsupportedOperationException("Unable to handle: " + typeToken); + final String name = fieldToken.name(); + final Encoding encoding = typeToken.encoding(); + + switch (typeToken.signal()) + { + case ENCODING: + generatePrimitiveDecoder(sb, level, fieldToken, typeToken, name, encoding); + break; + case BEGIN_ENUM: + generateEnumDecoder(sb, level, fieldToken, typeToken, name); + break; + case BEGIN_SET: + generateBitSetDecoder(sb, level, typeToken, name); + break; + case BEGIN_COMPOSITE: + generateCompositeDecoder(sb, level, fieldToken, typeToken, name); + break; + default: + throw new UnsupportedOperationException("Unable to handle: " + typeToken); + } } - } - catch (final IOException e) - { - throw new RuntimeException(e); - } - }); + catch (final IOException ex) + { + throw new UncheckedIOException(ex); + } + }); } private static void generateCompositeDecoder( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java index 45458df2de..4426638193 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java @@ -86,7 +86,7 @@ public Writer createOutput(final String name) throws IOException } /** - * Creates a new Cargo.toml file + * Creates a new Cargo.toml file. *

    * @return a {@link java.io.Writer} to which the crate definition should be written. * @throws IOException if an issue occurs when creating the file. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index fe49709908..731f57199d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -157,6 +157,7 @@ static String cleanUpperAcronyms(final String value) final int index = i - 1; return value.substring(0, index).toLowerCase() + value.substring(index); } + return value; } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index e56049205c..79fb608f79 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -45,6 +45,7 @@ public SubGroup addSubGroup(final String name, final int level, final Token grou { final SubGroup subGroup = new SubGroup(name, level, groupToken); subGroups.add(subGroup); + return subGroup; } From d9600d4656a291e375e8dd53c05079ca3075ca36 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Tue, 24 May 2022 09:25:16 -0500 Subject: [PATCH 0880/1594] [Rust] fix generated comparison when value is NAN (#895) (#896) Co-authored-by: Michael Ward --- .../sbe/generation/rust/RustGenerator.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index adb9e7b7ad..00417ec76d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -746,8 +746,18 @@ private static void generatePrimitiveOptionalDecoder( indent(sb, level + 1, "let value = self.get_buf().get_%s_at(self.%s);\n", rustPrimitiveType, getBufOffset(fieldToken)); - indent(sb, level + 1, "if value == %s {\n", - generateRustLiteral(primitiveType, encoding.applicableNullValue().toString())); + + + final String literal = generateRustLiteral(primitiveType, encoding.applicableNullValue().toString()); + if (literal.endsWith("::NAN")) + { + indent(sb, level + 1, "if value.is_nan() {\n"); + } + else + { + indent(sb, level + 1, "if value == %s {\n", literal); + } + indent(sb, level + 2, "None\n"); indent(sb, level + 1, "} else {\n"); indent(sb, level + 2, "Some(value)\n"); From 30bbb0065221ad946e0a2c4eae0a62d2b3f0768d Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Thu, 26 May 2022 02:54:07 -0500 Subject: [PATCH 0881/1594] [Rust] added tests for issue #895 (#897) * [Rust] fix generated comparison when value is NAN (#895) * [Rust] added test for issue #895 Co-authored-by: Michael Ward --- build.gradle | 1 + rust/Cargo.toml | 1 + rust/tests/baseline_test.rs | 4 +- rust/tests/big_endian_test.rs | 2 +- rust/tests/extension_test.rs | 4 +- rust/tests/issue_435_test.rs | 12 ++-- rust/tests/issue_895_test.rs | 75 ++++++++++++++++++++++++ sbe-tool/src/test/resources/issue895.xml | 21 +++++++ 8 files changed, 109 insertions(+), 11 deletions(-) create mode 100644 rust/tests/issue_895_test.rs create mode 100644 sbe-tool/src/test/resources/issue895.xml diff --git a/build.gradle b/build.gradle index ce1570debb..60e9d756ca 100644 --- a/build.gradle +++ b/build.gradle @@ -566,6 +566,7 @@ task generateRustTestCodecs(type: JavaExec) { 'sbe.target.language': 'Rust', 'sbe.validation.xsd': validationXsdPath) args = ['sbe-tool/src/test/resources/issue435.xml', + 'sbe-tool/src/test/resources/issue895.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', ] } diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 8aef7aa48c..eb57d8b01c 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -12,6 +12,7 @@ examples_uk_co_real_logic_sbe_benchmarks = { path = "../generated/rust/uk_co_rea examples_uk_co_real_logic_sbe_benchmarks_fix = { path = "../generated/rust/uk_co_real_logic_sbe_benchmarks_fix" } issue_435 = { path = "../generated/rust/issue435" } +issue_895 = { path = "../generated/rust/issue895" } baseline_bigendian = { path = "../generated/rust/baseline-bigendian" } [dev-dependencies] diff --git a/rust/tests/baseline_test.rs b/rust/tests/baseline_test.rs index a19b39a96e..ca45f14b43 100644 --- a/rust/tests/baseline_test.rs +++ b/rust/tests/baseline_test.rs @@ -3,7 +3,7 @@ use std::io::prelude::*; use examples_baseline::*; -fn read_sbe_file_generated_from_java_example() -> ::std::io::Result> { +fn read_sbe_file_generated_from_java_example() -> std::io::Result> { // Generated by the generateCarExampleDataFile gradle task. let mut f = File::open("car_example_baseline_data.sbe")?; let mut buffer = Vec::new(); @@ -33,7 +33,7 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { let buf = ReadBuf::new(buffer); let header = MessageHeaderDecoder::default().wrap(buf, 0); - assert_eq!(car_codec::SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(SBE_TEMPLATE_ID, header.template_id()); car = car.header(header); // Car... diff --git a/rust/tests/big_endian_test.rs b/rust/tests/big_endian_test.rs index 40b652c1be..d3a6952dec 100644 --- a/rust/tests/big_endian_test.rs +++ b/rust/tests/big_endian_test.rs @@ -30,7 +30,7 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { let buf = ReadBuf::new(buffer); let header = MessageHeaderDecoder::default().wrap(buf, 0); - assert_eq!(car_codec::SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(SBE_TEMPLATE_ID, header.template_id()); car = car.header(header); // Car... diff --git a/rust/tests/extension_test.rs b/rust/tests/extension_test.rs index 5e993f7701..c189763c6f 100644 --- a/rust/tests/extension_test.rs +++ b/rust/tests/extension_test.rs @@ -3,7 +3,7 @@ use std::io::prelude::*; use examples_extension::*; -fn read_sbe_file_generated_from_java_example() -> ::std::io::Result> { +fn read_sbe_file_generated_from_java_example() -> std::io::Result> { // Generated by the generateCarExampleDataFile gradle task. let mut f = File::open("car_example_extension_data.sbe")?; let mut buffer = Vec::new(); @@ -32,7 +32,7 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { let buf = ReadBuf::new(buffer); let header = MessageHeaderDecoder::default().wrap(buf, 0); - assert_eq!(car_codec::SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(SBE_TEMPLATE_ID, header.template_id()); car = car.header(header); // Car... diff --git a/rust/tests/issue_435_test.rs b/rust/tests/issue_435_test.rs index 3c9b43b0da..87bd9a075e 100644 --- a/rust/tests/issue_435_test.rs +++ b/rust/tests/issue_435_test.rs @@ -13,8 +13,8 @@ fn create_encoder(buffer: &mut Vec) -> Issue435Encoder { #[test] fn issue_435_ref_test() -> SbeResult<()> { assert_eq!(9, message_header_codec::ENCODED_LENGTH); - assert_eq!(1, issue_435_codec::SBE_BLOCK_LENGTH); - assert_eq!(0, issue_435_codec::SBE_SCHEMA_VERSION); + assert_eq!(1, SBE_BLOCK_LENGTH); + assert_eq!(0, SBE_SCHEMA_VERSION); // encode... let mut buffer = vec![0u8; 256]; @@ -24,10 +24,10 @@ fn issue_435_ref_test() -> SbeResult<()> { // decode... let buf = ReadBuf::new(buffer.as_slice()); let header = MessageHeaderDecoder::default().wrap(buf, 0); - assert_eq!(issue_435_codec::SBE_BLOCK_LENGTH, header.block_length()); - assert_eq!(issue_435_codec::SBE_SCHEMA_VERSION, header.version()); - assert_eq!(issue_435_codec::SBE_TEMPLATE_ID, header.template_id()); - assert_eq!(issue_435_codec::SBE_SCHEMA_ID, header.schema_id()); + assert_eq!(SBE_BLOCK_LENGTH, header.block_length()); + assert_eq!(SBE_SCHEMA_VERSION, header.version()); + assert_eq!(SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(SBE_SCHEMA_ID, header.schema_id()); assert_eq!(*SetRef::default().set_one(true), header.s()); let decoder = Issue435Decoder::default().header(header); diff --git a/rust/tests/issue_895_test.rs b/rust/tests/issue_895_test.rs new file mode 100644 index 0000000000..6c7090d2da --- /dev/null +++ b/rust/tests/issue_895_test.rs @@ -0,0 +1,75 @@ +use ::issue_895::*; + +fn create_encoder(buffer: &mut Vec) -> Issue895Encoder { + let issue_895 = Issue895Encoder::default().wrap( + WriteBuf::new(buffer.as_mut_slice()), + ENCODED_LENGTH, + ); + let mut header = issue_895.header(0); + header.parent().unwrap() +} + +#[test] +fn issue_895_both_some() -> SbeResult<()> { + assert_eq!(8, ENCODED_LENGTH); + assert_eq!(12, SBE_BLOCK_LENGTH); + assert_eq!(0, SBE_SCHEMA_VERSION); + + // encode... + let mut buf = vec![0u8; 256]; + let mut encoder = create_encoder(&mut buf); + encoder.optional_float(2.07); + encoder.optional_double(4.12); + + // decode... + let buf = ReadBuf::new(buf.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + assert_eq!(SBE_BLOCK_LENGTH, header.block_length()); + assert_eq!(SBE_SCHEMA_VERSION, header.version()); + assert_eq!(SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(SBE_SCHEMA_ID, header.schema_id()); + + let decoder = Issue895Decoder::default().header(header); + assert_eq!(Some(2.07), decoder.optional_float()); + assert_eq!(Some(4.12), decoder.optional_double()); + + Ok(()) +} + +#[test] +fn issue_895_float_none() -> SbeResult<()> { + // encode... + let mut buf = vec![0u8; 256]; + let mut encoder = create_encoder(&mut buf); + encoder.optional_float(f32::NAN); + encoder.optional_double(4.12); + + // decode... + let buf = ReadBuf::new(buf.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + + let decoder = Issue895Decoder::default().header(header); + assert_eq!(None, decoder.optional_float()); + assert_eq!(Some(4.12), decoder.optional_double()); + + Ok(()) +} + +#[test] +fn issue_895_double_none() -> SbeResult<()> { + // encode... + let mut buffer = vec![0u8; 256]; + let mut encoder = create_encoder(&mut buffer); + encoder.optional_float(2.07); + encoder.optional_double(f64::NAN); + + // decode... + let buf = ReadBuf::new(buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + + let decoder = Issue895Decoder::default().header(header); + assert_eq!(Some(2.07), decoder.optional_float()); + assert_eq!(None, decoder.optional_double()); + + Ok(()) +} \ No newline at end of file diff --git a/sbe-tool/src/test/resources/issue895.xml b/sbe-tool/src/test/resources/issue895.xml new file mode 100644 index 0000000000..5f14dd35a7 --- /dev/null +++ b/sbe-tool/src/test/resources/issue895.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + From cac83597a68f537ccc599fd918baf5a6ba0a8415 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 30 May 2022 09:43:32 +0100 Subject: [PATCH 0882/1594] [Rust] Upgrade to Mockito 4.6.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 60e9d756ca..290ec362b1 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' -def mockitoVersion = '4.5.1' +def mockitoVersion = '4.6.0' def junitVersion = '5.8.2' def jmhVersion = '1.35' def agronaVersion = '1.15.2' From e1f166b5427d0e18c169d230e8bb576e38f3366f Mon Sep 17 00:00:00 2001 From: Naveen <172697+naveensrinivasan@users.noreply.github.com> Date: Tue, 31 May 2022 03:19:57 -0500 Subject: [PATCH 0883/1594] chore: Set permissions for GitHub actions (#898) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restrict the GitHub token permissions only to the required ones; this way, even if the attackers will succeed in compromising your workflow, they won’t be able to do much. - Included permissions for the action. https://github.com/ossf/scorecard/blob/main/docs/checks.md#token-permissions https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs [Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/) Signed-off-by: naveen <172697+naveensrinivasan@users.noreply.github.com> --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2068ac66da..8f018aa915 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,9 @@ env: GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail' CMAKE_VERSION: '3.14.7' +permissions: + contents: read + jobs: java-build: name: Java ${{ matrix.java }} (${{ matrix.os }}) From b9c60ae28d57cd1bbeb58687d5b812b571909b85 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 6 Jun 2022 17:30:24 +0100 Subject: [PATCH 0884/1594] [Java] Upgrade to Mockito 4.6.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 290ec362b1..2358dcaae3 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' -def mockitoVersion = '4.6.0' +def mockitoVersion = '4.6.1' def junitVersion = '5.8.2' def jmhVersion = '1.35' def agronaVersion = '1.15.2' From 727281a26157a244947ec8c8afa92176c3f98a9b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 21 Jun 2022 11:28:53 +0100 Subject: [PATCH 0885/1594] [Java] Check sinceVersion on elements are valid in the context of message schema version. Issue #902. --- .../co/real_logic/sbe/xml/CompositeType.java | 49 ++++-- .../co/real_logic/sbe/xml/ErrorHandler.java | 4 +- .../co/real_logic/sbe/xml/MessageSchema.java | 161 +++++++++++++++++- .../java/uk/co/real_logic/sbe/xml/Type.java | 12 +- .../real_logic/sbe/xml/XmlSchemaParser.java | 2 + .../sbe/TargetCodeGeneratorTest.java | 6 +- .../real_logic/sbe/codec/java/TypesTest.java | 14 +- .../sbe/generation/cpp/CppGeneratorTest.java | 4 +- .../csharp/Issue567GroupSizeTest.java | 6 +- .../sbe/generation/java/ToStringTest.java | 6 +- .../sbe/generation/rust/RustUtilTest.java | 22 +-- .../sbe/ir/BasicXmlIrGenerationTest.java | 15 +- .../sbe/ir/CompositeElementsIrTest.java | 8 +- .../sbe/ir/CompositeOffsetsTest.java | 4 +- .../real_logic/sbe/ir/CompositeRefsTest.java | 4 +- .../co/real_logic/sbe/ir/EncodedIrTest.java | 14 +- .../sbe/ir/GroupWithDataIrTest.java | 10 +- .../sbe/ir/SinceVersionValidationTest.java | 44 +++++ .../co/real_logic/sbe/ir/ValueRefsTest.java | 4 +- .../real_logic/sbe/json/JsonPrinterTest.java | 4 +- .../sbe/xml/BasicSchemaFileTest.java | 21 +-- .../sbe/xml/CompositeElementsTest.java | 4 +- .../real_logic/sbe/xml/CompositeTypeTest.java | 14 +- .../sbe/xml/CyclicReferencesTest.java | 4 +- .../xml/EmbeddedLengthAndCountFileTest.java | 6 +- .../sbe/xml/EncodedDataTypeTest.java | 54 +++--- .../co/real_logic/sbe/xml/EnumTypeTest.java | 28 +-- .../real_logic/sbe/xml/ErrorHandlerTest.java | 26 +-- .../real_logic/sbe/xml/GroupWithDataTest.java | 4 +- .../co/real_logic/sbe/xml/OffsetFileTest.java | 18 +- .../sbe/xml/RelativeXIncludeTest.java | 4 +- .../uk/co/real_logic/sbe/xml/SetTypeTest.java | 16 +- .../resources/error-handler-since-version.xml | 38 +++++ 33 files changed, 447 insertions(+), 183 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java create mode 100644 sbe-tool/src/test/resources/error-handler-since-version.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index 98863144b9..667da499dc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -58,7 +58,7 @@ public class CompositeType extends Type /** * Construct a new compositeType from XML Schema. * - * @param node from the XML Schema Parsing + * @param node from the XML Schema parsing. * @param givenName for this node. * @param referencedName of the type when created from a ref in a composite. * @param compositesPath with the path of composites that represents the levels of composition. @@ -88,10 +88,10 @@ public class CompositeType extends Type } /** - * Return the EncodedDataType within this composite with the given name + * Return the EncodedDataType within this composite with the given name. * - * @param name of the EncodedDataType to return - * @return type requested + * @param name of the type to return. + * @return type requested. */ public Type getType(final String name) { @@ -99,9 +99,9 @@ public Type getType(final String name) } /** - * The encodedLength (in octets) of the list of EncodedDataTypes + * The encodedLength (in octets) of the list of encoded types. * - * @return encodedLength of the compositeType + * @return encodedLength of the compositeType. */ public int encodedLength() { @@ -129,9 +129,9 @@ public int encodedLength() } /** - * Return list of the {@link Type}s that compose this composite + * Return list of the {@link Type}s that compose this composite. * - * @return {@link List} that holds the {@link Type}s in this composite + * @return {@link List} that holds the {@link Type}s in this composite. */ public List getTypeList() { @@ -140,7 +140,7 @@ public List getTypeList() /** * Make this composite type, if it has a varData member, variable length - * by making the EncodedDataType with the name "varData" be variable length. + * by making the type with the name "varData" be variable length. */ public void makeDataFieldCompositeType() { @@ -155,7 +155,7 @@ public void makeDataFieldCompositeType() * Check the composite for being a well-formed group encodedLength encoding. This means * that there are the fields "blockLength" and "numInGroup" present. * - * @param node of the XML for this composite + * @param node of the XML for this composite. */ public void checkForWellFormedGroupSizeEncoding(final Node node) { @@ -433,10 +433,7 @@ private Type processType( case "ref": { final XPath xPath = XPathFactory.newInstance().newXPath(); - - final String refName = XmlSchemaParser.getAttributeValue(subTypeNode, "name"); final String refTypeName = XmlSchemaParser.getAttributeValue(subTypeNode, "type"); - final int refOffset = Integer.parseInt(XmlSchemaParser.getAttributeValue(subTypeNode, "offset", "-1")); final Node refTypeNode = (Node)xPath.compile( "/*[local-name() = 'messageSchema']/types/*[@name='" + refTypeName + "']") .evaluate(subTypeNode.getOwnerDocument(), XPathConstants.NODE); @@ -453,11 +450,33 @@ private Type processType( throw new IllegalStateException("ref types cannot create circular dependencies"); } + final String refName = XmlSchemaParser.getAttributeValue(subTypeNode, "name"); type = processType(refTypeNode, refName, refName, refTypeName); - if (-1 != refOffset) + final String refOffset = XmlSchemaParser.getAttributeValueOrNull(subTypeNode, "offset"); + if (null != refOffset) + { + try + { + type.offsetAttribute(Integer.parseInt(refOffset)); + } + catch (final NumberFormatException ex) + { + XmlSchemaParser.handleError(subTypeNode, "invalid number type: " + refOffset); + } + } + + final String refVersion = XmlSchemaParser.getAttributeValueOrNull(subTypeNode, "sinceVersion"); + if (null != refVersion) { - type.offsetAttribute(refOffset); + try + { + type.sinceVersion(Integer.parseInt(refVersion)); + } + catch (final NumberFormatException ex) + { + XmlSchemaParser.handleError(subTypeNode, "invalid number type: " + refVersion); + } } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java index 361d2b1e77..12fe0663a3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java @@ -104,11 +104,11 @@ public void checkIfShouldExit() { if (errors > 0) { - throw new IllegalStateException("had " + errors + " errors"); + throw new IllegalStateException("had " + errors + (errors > 1 ? " errors" : " error")); } else if (warnings > 0 && warningsFatal) { - throw new IllegalStateException("had " + warnings + " warnings"); + throw new IllegalStateException("had " + warnings + (warnings > 1 ? " warnings" : " warning")); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index 3f0bab5ff4..b62495f537 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -19,8 +19,7 @@ import org.agrona.Verify; import java.nio.ByteOrder; -import java.util.Collection; -import java.util.Map; +import java.util.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.*; @@ -164,4 +163,162 @@ public ByteOrder byteOrder() { return byteOrder; } + + /** + * Validate the message schema and delegate warnings and errors to the supplied {@link ErrorHandler}. + * + * @param errorHandler for delegating warnings and errors. + */ + public void validate(final ErrorHandler errorHandler) + { + final Deque path = new ArrayDeque<>(); + + for (final Type type : typeByNameMap.values()) + { + validateType(errorHandler, path, type); + } + + for (final Message message : messageByIdMap.values()) + { + if (message.sinceVersion() > version) + { + errorHandler.error(message.name() + ".sinceVersion=" + message.sinceVersion() + + " > messageSchema.version=" + version); + } + + path.addLast(message.name()); + + for (final Field field : message.fields()) + { + validateField(errorHandler, path, field); + } + + path.removeLast(); + } + } + + private void validateType(final ErrorHandler errorHandler, final Deque path, final Type type) + { + if (type instanceof EncodedDataType) + { + validateEncodedType(errorHandler, path, (EncodedDataType)type); + } + else if (type instanceof EnumType) + { + validateEnumType(errorHandler, path, (EnumType)type); + } + else if (type instanceof SetType) + { + validateSetType(errorHandler, path, (SetType)type); + } + else if (type instanceof CompositeType) + { + validateCompositeType(errorHandler, path, (CompositeType)type); + } + } + + private void validateEncodedType( + final ErrorHandler errorHandler, final Deque path, final EncodedDataType type) + { + if (type.sinceVersion() > version) + { + reportError(errorHandler, path, type.name(), type.sinceVersion()); + } + } + + private void validateEnumType(final ErrorHandler errorHandler, final Deque path, final EnumType type) + { + if (type.sinceVersion() > version) + { + reportError(errorHandler, path, type.name(), type.sinceVersion()); + } + + path.addLast(type.name()); + + for (final EnumType.ValidValue validValue : type.validValues()) + { + if (validValue.sinceVersion() > version) + { + reportError(errorHandler, path, validValue.name(), validValue.sinceVersion()); + } + } + + path.removeLast(); + } + + private void validateSetType(final ErrorHandler errorHandler, final Deque path, final SetType type) + { + if (type.sinceVersion() > version) + { + reportError(errorHandler, path, type.name(), type.sinceVersion()); + } + + path.addLast(type.name()); + + for (final SetType.Choice choice : type.choices()) + { + if (choice.sinceVersion() > version) + { + reportError(errorHandler, path, choice.name(), choice.sinceVersion()); + } + } + + path.removeLast(); + } + + private void validateCompositeType( + final ErrorHandler errorHandler, final Deque path, final CompositeType type) + { + if (type.sinceVersion() > version) + { + reportError(errorHandler, path, type.name(), type.sinceVersion()); + } + + path.addLast(type.name()); + + for (final Type subType : type.getTypeList()) + { + validateType(errorHandler, path, subType); + } + + path.removeLast(); + } + + private void validateField(final ErrorHandler errorHandler, final Deque path, final Field field) + { + if (field.sinceVersion() > version) + { + reportError(errorHandler, path, field.name(), field.sinceVersion()); + } + + final List groupFields = field.groupFields(); + if (null != groupFields) + { + path.addLast(field.name()); + + for (final Field groupField : groupFields) + { + validateField(errorHandler, path, groupField); + } + + path.removeLast(); + } + } + + private void reportError( + final ErrorHandler errorHandler, final Deque path, final String name, final int sinceVersion) + { + final StringBuilder sb = new StringBuilder(); + + for (final String step : path) + { + sb.append(step).append('.'); + } + + sb.append(name) + .append(".sinceVersion=").append(sinceVersion) + .append(" > messageSchema.version=").append(version); + + errorHandler.error(sb.toString()); + } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java index b9db2c5138..8a1e491ff4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java @@ -28,12 +28,12 @@ public abstract class Type private final String name; private final Presence presence; private final String description; - private final int sinceVersion; private final int deprecated; private final String semanticType; private final String referencedName; private int offsetAttribute; + private int sinceVersion; /** * Construct a new Type from XML Schema. Called by subclasses to mostly set common fields @@ -150,6 +150,16 @@ public int sinceVersion() return sinceVersion; } + /** + * Set the sinceVersion for the type. + * + * @param version to be set. + */ + public void sinceVersion(final int version) + { + sinceVersion = version; + } + /** * Version in which type was deprecated. Only valid if greater than zero. * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 022777ae8f..fbc66f9888 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -146,6 +146,8 @@ public static MessageSchema parse(final InputSource is, final ParserOptions opti } final MessageSchema messageSchema = new MessageSchema(schemaNode, typeByNameMap, messageByIdMap); + + messageSchema.validate(errorHandler); errorHandler.checkIfShouldExit(); return messageSchema; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java index 7b63c47573..83b71ac815 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java @@ -23,17 +23,17 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -public class TargetCodeGeneratorTest +class TargetCodeGeneratorTest { @Test - public void shouldThrowOnNoTargetLanguage() + void shouldThrowOnNoTargetLanguage() { assertThrows(IllegalArgumentException.class, () -> SbeTool.generate(mock(Ir.class), ".", "none")); } @Test - public void shouldLoadAndInstantiateNonStandardTargetLanguage() throws Exception + void shouldLoadAndInstantiateNonStandardTargetLanguage() throws Exception { final Ir ir = mock(Ir.class); final String outputDir = "."; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java index c9c6bb2aac..5ca540c2b6 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java @@ -23,7 +23,7 @@ import static org.junit.jupiter.api.Assertions.*; -public class TypesTest +class TypesTest { private static final ByteOrder BYTE_ORDER = ByteOrder.nativeOrder(); private static final int BUFFER_CAPACITY = 64; @@ -31,7 +31,7 @@ public class TypesTest private final MutableDirectBuffer buffer = new UnsafeBuffer(new byte[BUFFER_CAPACITY]); @Test - public void shouldTestBitInByte() + void shouldTestBitInByte() { final byte bits = (byte)0b1000_0000; final int bufferIndex = 8; @@ -53,7 +53,7 @@ public void shouldTestBitInByte() } @Test - public void shouldSetBitInByte() + void shouldSetBitInByte() { final int bufferIndex = 8; @@ -69,7 +69,7 @@ public void shouldSetBitInByte() } @Test - public void shouldTestBitInShort() + void shouldTestBitInShort() { final short bits = (short)0b0000_0000_0000_0100; final int bufferIndex = 8; @@ -91,7 +91,7 @@ public void shouldTestBitInShort() } @Test - public void shouldSetBitInShort() + void shouldSetBitInShort() { final int bufferIndex = 8; @@ -107,7 +107,7 @@ public void shouldSetBitInShort() } @Test - public void shouldTestBitInInt() + void shouldTestBitInInt() { final int bits = 0b0000_0000_0000_0000_0000_0000_0000_0100; final int bufferIndex = 8; @@ -129,7 +129,7 @@ public void shouldTestBitInInt() } @Test - public void shouldSetBitInInt() + void shouldSetBitInInt() { final int bufferIndex = 8; long total = 0; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index 8187e18813..b198de3073 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -28,10 +28,10 @@ import static org.hamcrest.Matchers.not; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class CppGeneratorTest +class CppGeneratorTest { @Test - public void shouldUseGeneratedLiteralForConstantOneWhenGeneratingBitsetCode() throws Exception + void shouldUseGeneratedLiteralForConstantOneWhenGeneratingBitsetCode() throws Exception { final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); final MessageSchema schema = parse(Tests.getLocalResource("issue827.xml"), options); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index ef04946d0b..3a7eeca34c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -37,7 +37,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -public class Issue567GroupSizeTest +class Issue567GroupSizeTest { private static final String ERR_MSG = "WARNING: at \"numInGroup\" should be UINT8 or UINT16"; @@ -51,7 +51,7 @@ public class Issue567GroupSizeTest private final PrintStream mockErr = mock(PrintStream.class); @Test - public void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupSize() throws IOException + void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupSize() throws IOException { final ParserOptions options = ParserOptions.builder() .errorPrintStream(mockErr) @@ -65,7 +65,7 @@ public void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupS } @Test - public void shouldGenerateWhenUsingATypeThatIsConstrainedToFitInAnIntAsTheGroupSize() throws Exception + void shouldGenerateWhenUsingATypeThatIsConstrainedToFitInAnIntAsTheGroupSize() throws Exception { final ParserOptions options = ParserOptions.builder() .errorPrintStream(mockErr) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java index 36d762fd83..3dde226e72 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java @@ -23,12 +23,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class ToStringTest extends EncodedCarTestBase +class ToStringTest extends EncodedCarTestBase { private static final int MSG_BUFFER_CAPACITY = 4 * 1024; @Test - public void shouldToStringMessage() + void shouldToStringMessage() { final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); encodeTestMessage(encodedMsgBuffer); @@ -56,7 +56,7 @@ public void shouldToStringMessage() } @Test - public void shouldToStringBlankMessage() + void shouldToStringBlankMessage() { final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); CAR.wrap(new UnsafeBuffer(encodedMsgBuffer), 0); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java index 366d8663cd..cab7fc9f10 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java @@ -34,28 +34,28 @@ import static uk.co.real_logic.sbe.generation.rust.RustUtil.formatFunctionName; import static uk.co.real_logic.sbe.generation.rust.RustUtil.generateRustLiteral; -public class RustUtilTest +class RustUtilTest { @Test - public void nullParamToEightBitCharacterThrowsNPE() + void nullParamToEightBitCharacterThrowsNPE() { assertThrows(NullPointerException.class, () -> RustUtil.eightBitCharacter(null)); } @Test - public void emptyParamToEightBitCharacterThrowsIAE() + void emptyParamToEightBitCharacterThrowsIAE() { assertThrows(IllegalArgumentException.class, () -> RustUtil.eightBitCharacter("")); } @Test - public void tooManyCharactersParamToEightBitCharacterThrowsIAE() + void tooManyCharactersParamToEightBitCharacterThrowsIAE() { assertThrows(IllegalArgumentException.class, () -> RustUtil.eightBitCharacter("ABC")); } @Test - public void happyPathEightBitCharacter() + void happyPathEightBitCharacter() { final byte aByte = RustUtil.eightBitCharacter("a"); assertEquals('a', (char)aByte); @@ -63,7 +63,7 @@ public void happyPathEightBitCharacter() } @Test - public void generateRustLiteralsHappyPaths() + void generateRustLiteralsHappyPaths() { assertEquals("65_u8", generateRustLiteral(CHAR, "65")); assertEquals("64.1_f64", generateRustLiteral(DOUBLE, "64.1")); @@ -83,7 +83,7 @@ public void generateRustLiteralsHappyPaths() } @Test - public void generateRustLiteralsForUnsignedPrimitiveNulls() + void generateRustLiteralsForUnsignedPrimitiveNulls() { assertEquals("0xff_u8", generateRustLiteral(UINT8, UINT8.nullValue().toString())); assertEquals("0xffff_u16", generateRustLiteral(UINT16, UINT16.nullValue().toString())); @@ -92,19 +92,19 @@ public void generateRustLiteralsForUnsignedPrimitiveNulls() } @Test - public void generateRustLiteralNullPrimitiveTypeParam() + void generateRustLiteralNullPrimitiveTypeParam() { assertThrows(NullPointerException.class, () -> generateRustLiteral(null, "65")); } @Test - public void generateRustLiteralNullValueParam() + void generateRustLiteralNullValueParam() { assertThrows(NullPointerException.class, () -> generateRustLiteral(INT8, null)); } @Test - public void testCleanUpperAcronyms() + void testCleanUpperAcronyms() { assertEquals("ABee", cleanUpperAcronyms("ABee")); assertEquals("mdEntryTypeBook", cleanUpperAcronyms("MDEntryTypeBook")); @@ -113,7 +113,7 @@ public void testCleanUpperAcronyms() } @Test - public void functionNameCasing() + void functionNameCasing() { assertEquals("", formatFunctionName("")); assertEquals("a", formatFunctionName("a")); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index bdd33c0535..b7577f4100 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -29,10 +29,10 @@ import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class BasicXmlIrGenerationTest +class BasicXmlIrGenerationTest { @Test - public void shouldGenerateIrForMessageHeader() throws Exception + void shouldGenerateIrForMessageHeader() throws Exception { final MessageSchema schema = parse(getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -94,7 +94,7 @@ public void shouldGenerateIrForMessageHeader() throws Exception } @Test - public void shouldGenerateIrForBasicMessage() throws Exception + void shouldGenerateIrForBasicMessage() throws Exception { final MessageSchema schema = parse(getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -143,7 +143,7 @@ public void shouldGenerateIrForBasicMessage() throws Exception } @Test - public void shouldGenerateIrForMessageWithVariableLengthField() throws Exception + void shouldGenerateIrForMessageWithVariableLengthField() throws Exception { final MessageSchema schema = parse(getLocalResource( "basic-variable-length-schema.xml"), ParserOptions.DEFAULT); @@ -206,7 +206,7 @@ public void shouldGenerateIrForMessageWithVariableLengthField() throws Exception } @Test - public void shouldGenerateIrForMessageWithRepeatingGroupWithEmbeddedDimensions() throws Exception + void shouldGenerateIrForMessageWithRepeatingGroupWithEmbeddedDimensions() throws Exception { final MessageSchema schema = parse(getLocalResource( "basic-group-schema.xml"), ParserOptions.DEFAULT); @@ -240,8 +240,7 @@ public void shouldGenerateIrForMessageWithRepeatingGroupWithEmbeddedDimensions() } @Test - public void shouldGenerateIrForMessageWithRepeatingGroupWithEmbeddedDimensionsDefaultDimensionType() - throws Exception + void shouldGenerateIrForMessageWithRepeatingGroupWithEmbeddedDimensionsDefaultDimensionType() throws Exception { final MessageSchema schema = parse(getLocalResource( "embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); @@ -267,7 +266,7 @@ public void shouldGenerateIrForMessageWithRepeatingGroupWithEmbeddedDimensionsDe } @Test - public void shouldGenerateIrForMessageWithVariableLengthFieldWithEmbeddedLength() throws Exception + void shouldGenerateIrForMessageWithVariableLengthFieldWithEmbeddedLength() throws Exception { final MessageSchema schema = parse(getLocalResource( "embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java index ecdae485ef..60a2538922 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java @@ -28,10 +28,10 @@ import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class CompositeElementsIrTest +class CompositeElementsIrTest { @Test - public void shouldGenerateIrForCompositeElementsSchema() throws Exception + void shouldGenerateIrForCompositeElementsSchema() throws Exception { final MessageSchema schema = parse(getLocalResource( "composite-elements-schema.xml"), ParserOptions.DEFAULT); @@ -94,7 +94,7 @@ public void shouldGenerateIrForCompositeElementsSchema() throws Exception } @Test - public void shouldGenerateIrForCompositeElementsWithOffsetsSchemaRc4() throws Exception + void shouldGenerateIrForCompositeElementsWithOffsetsSchemaRc4() throws Exception { final MessageSchema schema = parse(getLocalResource( "composite-elements-schema-rc4.xml"), ParserOptions.DEFAULT); @@ -149,7 +149,7 @@ public void shouldGenerateIrForCompositeElementsWithOffsetsSchemaRc4() throws Ex } @Test - public void shouldGenerateIrForCompositeWithRefSchema() throws Exception + void shouldGenerateIrForCompositeWithRefSchema() throws Exception { final MessageSchema schema = parse(getLocalResource( "composite-elements-schema-rc4.xml"), ParserOptions.DEFAULT); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java index 91f5736a20..fa773de170 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java @@ -27,10 +27,10 @@ import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class CompositeOffsetsTest +class CompositeOffsetsTest { @Test - public void shouldGenerateOffsetsForFieldsWithEmbeddedComposite() throws Exception + void shouldGenerateOffsetsForFieldsWithEmbeddedComposite() throws Exception { final MessageSchema schema = parse(getLocalResource("composite-offsets-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java index 6edf89a346..aab8b540ab 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java @@ -24,10 +24,10 @@ import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class CompositeRefsTest +class CompositeRefsTest { @Test - public void shouldGenerateIrForCompositeRefs() throws Exception + void shouldGenerateIrForCompositeRefs() throws Exception { final MessageSchema schema = parse(getLocalResource("issue496.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index 5bb0750cfd..900ab99e38 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -28,12 +28,12 @@ import static org.hamcrest.core.Is.is; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class EncodedIrTest +class EncodedIrTest { private static final int CAPACITY = 1024 * 16; @Test - public void shouldEncodeIr() throws Exception + void shouldEncodeIr() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -45,7 +45,7 @@ public void shouldEncodeIr() throws Exception } @Test - public void shouldEncodeThenDecodeIr() throws Exception + void shouldEncodeThenDecodeIr() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -61,7 +61,7 @@ public void shouldEncodeThenDecodeIr() throws Exception } @Test - public void shouldHandleRightSizedBuffer() throws Exception + void shouldHandleRightSizedBuffer() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -81,7 +81,7 @@ public void shouldHandleRightSizedBuffer() throws Exception } @Test - public void shouldDecodeFrame() throws Exception + void shouldDecodeFrame() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "code-generation-schema.xml"), ParserOptions.DEFAULT); @@ -104,7 +104,7 @@ public void shouldDecodeFrame() throws Exception } @Test - public void shouldDecodeHeader() throws Exception + void shouldDecodeHeader() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "code-generation-schema.xml"), ParserOptions.DEFAULT); @@ -128,7 +128,7 @@ public void shouldDecodeHeader() throws Exception } @Test - public void shouldDecodeMessagesAndTypes() throws Exception + void shouldDecodeMessagesAndTypes() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "code-generation-schema.xml"), ParserOptions.DEFAULT); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java index 2ec78f51db..83a274dbd3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java @@ -28,10 +28,10 @@ import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class GroupWithDataIrTest +class GroupWithDataIrTest { @Test - public void shouldGenerateIrForSingleVarDataInRepeatingGroup() throws Exception + void shouldGenerateIrForSingleVarDataInRepeatingGroup() throws Exception { final MessageSchema schema = parse(getLocalResource("group-with-data-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -72,7 +72,7 @@ public void shouldGenerateIrForSingleVarDataInRepeatingGroup() throws Exception } @Test - public void shouldGenerateIrForMultipleVarDataInRepeatingGroup() throws Exception + void shouldGenerateIrForMultipleVarDataInRepeatingGroup() throws Exception { final MessageSchema schema = parse(getLocalResource("group-with-data-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -100,7 +100,7 @@ public void shouldGenerateIrForMultipleVarDataInRepeatingGroup() throws Exceptio } @Test - public void shouldGenerateIrForVarDataInNestedRepeatingGroup() throws Exception + void shouldGenerateIrForVarDataInNestedRepeatingGroup() throws Exception { final MessageSchema schema = parse(getLocalResource("group-with-data-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -132,7 +132,7 @@ public void shouldGenerateIrForVarDataInNestedRepeatingGroup() throws Exception } @Test - public void shouldGenerateIrForOnlyMultipleVarDataInRepeatingGroup() throws Exception + void shouldGenerateIrForOnlyMultipleVarDataInRepeatingGroup() throws Exception { final MessageSchema schema = parse(getLocalResource("group-with-data-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java new file mode 100644 index 0000000000..073ffca2f2 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.ir; + +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; +import static uk.co.real_logic.sbe.Tests.getLocalResource; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +class SinceVersionValidationTest +{ + @Test + void shouldErrorOnTypeWithGreaterSinceVersion() throws Exception + { + try + { + final ParserOptions options = ParserOptions.builder().suppressOutput(true).build(); + parse(getLocalResource("error-handler-since-version.xml"), options); + } + catch (final IllegalStateException ex) + { + assertEquals("had 5 errors", ex.getMessage()); + return; + } + + fail("expected IllegalStateException"); + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java index 9ff34d4d5d..eee71d141c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java @@ -25,10 +25,10 @@ import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class ValueRefsTest +class ValueRefsTest { @Test - public void shouldGenerateValueRefToEnum() throws Exception + void shouldGenerateValueRefToEnum() throws Exception { final MessageSchema schema = parse(getLocalResource("value-ref-schema.xml"), ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java index 6fa1006086..4d2c9e597f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java @@ -34,13 +34,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class JsonPrinterTest extends EncodedCarTestBase +class JsonPrinterTest extends EncodedCarTestBase { private static final int SCHEMA_BUFFER_CAPACITY = 16 * 1024; private static final int MSG_BUFFER_CAPACITY = 4 * 1024; @Test - public void exampleMessagePrintedAsJson() throws Exception + void exampleMessagePrintedAsJson() throws Exception { final ByteBuffer encodedSchemaBuffer = ByteBuffer.allocate(SCHEMA_BUFFER_CAPACITY); encodeSchema(encodedSchemaBuffer); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java index 4278f91f60..a0b7ef5ae4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java @@ -15,48 +15,43 @@ */ package uk.co.real_logic.sbe.xml; -import java.util.List; - import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.Tests; +import java.util.List; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class BasicSchemaFileTest +class BasicSchemaFileTest { @Test - public void shouldHandleBasicFile() - throws Exception + void shouldHandleBasicFile() throws Exception { parse(Tests.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); } @Test - public void shouldHandleConstantHeaderField() - throws Exception + void shouldHandleConstantHeaderField() throws Exception { parse(Tests.getLocalResource("basic-schema-constant-header-field.xml"), ParserOptions.DEFAULT); } @Test - public void shouldHandleBasicFileWithGroup() - throws Exception + void shouldHandleBasicFileWithGroup() throws Exception { parse(Tests.getLocalResource("basic-group-schema.xml"), ParserOptions.DEFAULT); } @Test - public void shouldHandleBasicFileWithVariableLengthData() - throws Exception + void shouldHandleBasicFileWithVariableLengthData() throws Exception { parse(Tests.getLocalResource("basic-variable-length-schema.xml"), ParserOptions.DEFAULT); } @Test - public void shouldHandleBasicAllTypes() - throws Exception + void shouldHandleBasicAllTypes() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource("basic-types-schema.xml"), ParserOptions.DEFAULT); final List fields = schema.getMessage(1).fields(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java index 6c00ca511f..0b29b1bcf2 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java @@ -24,10 +24,10 @@ import static org.hamcrest.core.Is.is; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class CompositeElementsTest +class CompositeElementsTest { @Test - public void shouldParseSchemaSuccessfully() throws Exception + void shouldParseSchemaSuccessfully() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "composite-elements-schema.xml"), ParserOptions.DEFAULT); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java index ee59e45644..f8c3a3aa8a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java @@ -37,10 +37,10 @@ import static org.hamcrest.core.Is.is; import static org.junit.jupiter.api.Assertions.*; -public class CompositeTypeTest +class CompositeTypeTest { @Test - public void shouldHandleDecimalCompositeType() throws Exception + void shouldHandleDecimalCompositeType() throws Exception { final String testXmlString = "" + @@ -64,7 +64,7 @@ public void shouldHandleDecimalCompositeType() throws Exception } @Test - public void shouldHandleDecimal32CompositeType() throws Exception + void shouldHandleDecimal32CompositeType() throws Exception { final String testXmlString = "" + @@ -90,7 +90,7 @@ public void shouldHandleDecimal32CompositeType() throws Exception } @Test - public void shouldHandleDecimal64CompositeType() throws Exception + void shouldHandleDecimal64CompositeType() throws Exception { final String testXmlString = "" + @@ -115,7 +115,7 @@ public void shouldHandleDecimal64CompositeType() throws Exception } @Test - public void shouldHandleCompositeTypeList() throws Exception + void shouldHandleCompositeTypeList() throws Exception { final String testXmlString = "" + @@ -134,7 +134,7 @@ public void shouldHandleCompositeTypeList() throws Exception } @Test - public void shouldHandleCompositeHasNullableType() throws Exception + void shouldHandleCompositeHasNullableType() throws Exception { final String nullValStr = "9223372036854775807"; final String testXmlString = @@ -155,7 +155,7 @@ public void shouldHandleCompositeHasNullableType() throws Exception } @Test - public void shouldThrowExceptionWhenCompositeTypeHasTypeNameDuplicates() + void shouldThrowExceptionWhenCompositeTypeHasTypeNameDuplicates() { final String testXmlString = "" + diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java index 7e10355e49..ca3a0d3dca 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java @@ -22,10 +22,10 @@ import static org.junit.jupiter.api.Assertions.fail; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class CyclicReferencesTest +class CyclicReferencesTest { @Test - public void shouldTestForCyclicRefs() throws Exception + void shouldTestForCyclicRefs() throws Exception { try { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java index 8b3b1dc9ed..a129c7ecc1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java @@ -25,10 +25,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class EmbeddedLengthAndCountFileTest +class EmbeddedLengthAndCountFileTest { @Test - public void shouldHandleEmbeddedCountForGroup() throws Exception + void shouldHandleEmbeddedCountForGroup() throws Exception { final MessageSchema schema = parse( Tests.getLocalResource("embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); @@ -43,7 +43,7 @@ public void shouldHandleEmbeddedCountForGroup() throws Exception } @Test - public void shouldHandleEmbeddedLengthForData() throws Exception + void shouldHandleEmbeddedLengthForData() throws Exception { parse(Tests.getLocalResource("embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index 008a3d8199..6763e2c50f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -39,10 +39,10 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static uk.co.real_logic.sbe.PrimitiveValue.parse; -public class EncodedDataTypeTest +class EncodedDataTypeTest { @Test - public void shouldHandleSettingAllAttributes() throws Exception + void shouldHandleSettingAllAttributes() throws Exception { final String testXmlString = "" + @@ -65,7 +65,7 @@ public void shouldHandleSettingAllAttributes() throws Exception } @Test - public void shouldHandleMultipleTypes() throws Exception + void shouldHandleMultipleTypes() throws Exception { final String testXmlString = "" + @@ -84,7 +84,7 @@ public void shouldHandleMultipleTypes() throws Exception } @Test - public void shouldSetAppropriateDefaultsWhenNoneSpecified() throws Exception + void shouldSetAppropriateDefaultsWhenNoneSpecified() throws Exception { final String testXmlString = "" + @@ -104,7 +104,7 @@ public void shouldSetAppropriateDefaultsWhenNoneSpecified() throws Exception } @Test - public void shouldUseAppropriatePresence() throws Exception + void shouldUseAppropriatePresence() throws Exception { final String testXmlString = "" + @@ -123,7 +123,7 @@ public void shouldUseAppropriatePresence() throws Exception } @Test - public void shouldThrowExceptionWhenUnknownPresenceSpecified() + void shouldThrowExceptionWhenUnknownPresenceSpecified() { final String testXmlString = "" + @@ -134,7 +134,7 @@ public void shouldThrowExceptionWhenUnknownPresenceSpecified() } @Test - public void shouldThrowExceptionWhenNoPrimitiveTypeSpecified() + void shouldThrowExceptionWhenNoPrimitiveTypeSpecified() { final String testXmlString = "" + @@ -145,7 +145,7 @@ public void shouldThrowExceptionWhenNoPrimitiveTypeSpecified() } @Test - public void shouldThrowExceptionWhenNoNameSpecified() + void shouldThrowExceptionWhenNoNameSpecified() { final String testXmlString = "" + @@ -156,7 +156,7 @@ public void shouldThrowExceptionWhenNoNameSpecified() } @Test - public void shouldUseAppropriatePrimitiveType() throws Exception + void shouldUseAppropriatePrimitiveType() throws Exception { final String testXmlString = "" + @@ -189,7 +189,7 @@ public void shouldUseAppropriatePrimitiveType() throws Exception } @Test - public void shouldThrowExceptionWhenUnknownPrimitiveTypeSpecified() + void shouldThrowExceptionWhenUnknownPrimitiveTypeSpecified() { final String testXmlString = "" + @@ -201,7 +201,7 @@ public void shouldThrowExceptionWhenUnknownPrimitiveTypeSpecified() } @Test - public void shouldReturnCorrectSizeForPrimitiveTypes() throws Exception + void shouldReturnCorrectSizeForPrimitiveTypes() throws Exception { final String testXmlString = "" + @@ -233,7 +233,7 @@ public void shouldReturnCorrectSizeForPrimitiveTypes() throws Exception } @Test - public void shouldReturnCorrectDescriptionForType() throws Exception + void shouldReturnCorrectDescriptionForType() throws Exception { final String desc = "basic description attribute of a type element"; final String testXmlString = @@ -247,7 +247,7 @@ public void shouldReturnCorrectDescriptionForType() throws Exception } @Test - public void shouldReturnNullOnNoDescriptionSet() throws Exception + void shouldReturnNullOnNoDescriptionSet() throws Exception { final String testXmlString = "" + @@ -261,7 +261,7 @@ public void shouldReturnNullOnNoDescriptionSet() throws Exception } @Test - public void shouldReturnCorrectSemanticTypeForType() throws Exception + void shouldReturnCorrectSemanticTypeForType() throws Exception { final String semanticType = "char"; final String testXmlString = @@ -275,7 +275,7 @@ public void shouldReturnCorrectSemanticTypeForType() throws Exception } @Test - public void shouldReturnNullWhenSemanticTypeNotSpecified() throws Exception + void shouldReturnNullWhenSemanticTypeNotSpecified() throws Exception { final String testXmlString = "" + @@ -288,7 +288,7 @@ public void shouldReturnNullWhenSemanticTypeNotSpecified() throws Exception } @Test - public void shouldThrowExceptionWhenConstantPresenceButNoDataSpecified() + void shouldThrowExceptionWhenConstantPresenceButNoDataSpecified() { final String testXmlString = "" + @@ -299,7 +299,7 @@ public void shouldThrowExceptionWhenConstantPresenceButNoDataSpecified() } @Test - public void shouldReturnCorrectPresenceConstantWhenSpecified() throws Exception + void shouldReturnCorrectPresenceConstantWhenSpecified() throws Exception { final String testXmlString = "" + @@ -314,7 +314,7 @@ public void shouldReturnCorrectPresenceConstantWhenSpecified() throws Exception } @Test - public void shouldReturnCorrectConstantStringWhenSpecified() throws Exception + void shouldReturnCorrectConstantStringWhenSpecified() throws Exception { final String strConst = "string constant"; final String testXmlString = @@ -331,7 +331,7 @@ public void shouldReturnCorrectConstantStringWhenSpecified() throws Exception } @Test - public void shouldReturnDefaultMinValueWhenSpecified() throws Exception + void shouldReturnDefaultMinValueWhenSpecified() throws Exception { final String testXmlString = "" + @@ -344,7 +344,7 @@ public void shouldReturnDefaultMinValueWhenSpecified() throws Exception } @Test - public void shouldReturnDefaultMaxValueWhenSpecified() throws Exception + void shouldReturnDefaultMaxValueWhenSpecified() throws Exception { final String testXmlString = "" + @@ -357,7 +357,7 @@ public void shouldReturnDefaultMaxValueWhenSpecified() throws Exception } @Test - public void shouldReturnDefaultNullValueWhenSpecified() throws Exception + void shouldReturnDefaultNullValueWhenSpecified() throws Exception { final String testXmlString = "" + @@ -370,7 +370,7 @@ public void shouldReturnDefaultNullValueWhenSpecified() throws Exception } @Test - public void shouldReturnCorrectMinValueWhenSpecified() throws Exception + void shouldReturnCorrectMinValueWhenSpecified() throws Exception { final String minVal = "10"; final String testXmlString = @@ -384,7 +384,7 @@ public void shouldReturnCorrectMinValueWhenSpecified() throws Exception } @Test - public void shouldReturnCorrectMaxValueWhenSpecified() throws Exception + void shouldReturnCorrectMaxValueWhenSpecified() throws Exception { final String maxVal = "10"; final String testXmlString = @@ -399,7 +399,7 @@ public void shouldReturnCorrectMaxValueWhenSpecified() throws Exception } @Test - public void shouldReturnCorrectNullValueWhenSpecified() throws Exception + void shouldReturnCorrectNullValueWhenSpecified() throws Exception { final String nullVal = "10"; final String testXmlString = @@ -415,7 +415,7 @@ public void shouldReturnCorrectNullValueWhenSpecified() throws Exception } @Test - public void shouldReturnCharacterEncodingWhenSpecified() throws Exception + void shouldReturnCharacterEncodingWhenSpecified() throws Exception { final String testXmlString = "" + @@ -429,7 +429,7 @@ public void shouldReturnCharacterEncodingWhenSpecified() throws Exception } @Test - public void shouldReturnCharacterEncodingWhenSpecifiedNonCharType() throws Exception + void shouldReturnCharacterEncodingWhenSpecifiedNonCharType() throws Exception { final String testXmlString = "" + @@ -444,7 +444,7 @@ public void shouldReturnCharacterEncodingWhenSpecifiedNonCharType() throws Excep } @Test - public void shouldReturnUsAsciiWhenCharacterEncodingNotSpecifiedForTypeChar() throws Exception + void shouldReturnUsAsciiWhenCharacterEncodingNotSpecifiedForTypeChar() throws Exception { final String testXmlString = "" + diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index 0a13521102..ec6162f05d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -43,10 +43,10 @@ import static org.junit.jupiter.api.Assertions.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class EnumTypeTest +class EnumTypeTest { @Test - public void shouldHandleBinaryEnumType() throws Exception + void shouldHandleBinaryEnumType() throws Exception { final String testXmlString = "" + @@ -67,7 +67,7 @@ public void shouldHandleBinaryEnumType() throws Exception } @Test - public void shouldHandleBooleanEnumType() throws Exception + void shouldHandleBooleanEnumType() throws Exception { final String testXmlString = "" + @@ -88,7 +88,7 @@ public void shouldHandleBooleanEnumType() throws Exception } @Test - public void shouldHandleOptionalBooleanEnumType() throws Exception + void shouldHandleOptionalBooleanEnumType() throws Exception { final String nullValueStr = "255"; final String testXmlString = @@ -112,7 +112,7 @@ public void shouldHandleOptionalBooleanEnumType() throws Exception } @Test - public void shouldHandleEnumTypeList() throws Exception + void shouldHandleEnumTypeList() throws Exception { final String testXmlString = "" + @@ -156,7 +156,7 @@ public void shouldHandleEnumTypeList() throws Exception } @Test - public void shouldHandleCharEnumEncodingType() throws Exception + void shouldHandleCharEnumEncodingType() throws Exception { final String testXmlString = "" + @@ -179,7 +179,7 @@ public void shouldHandleCharEnumEncodingType() throws Exception } @Test - public void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() + void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() { final String testXmlString = "" + @@ -194,7 +194,7 @@ public void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() } @Test - public void shouldThrowExceptionWhenDuplicateValueSpecified() + void shouldThrowExceptionWhenDuplicateValueSpecified() { final String testXmlString = "" + @@ -210,7 +210,7 @@ public void shouldThrowExceptionWhenDuplicateValueSpecified() } @Test - public void shouldThrowExceptionWhenDuplicateNameSpecified() + void shouldThrowExceptionWhenDuplicateNameSpecified() { final String testXmlString = "" + @@ -226,7 +226,7 @@ public void shouldThrowExceptionWhenDuplicateNameSpecified() } @Test - public void shouldThrowExceptionWhenImplicitNullValueIsUsed() + void shouldThrowExceptionWhenImplicitNullValueIsUsed() { final String testXmlString = "" + @@ -241,7 +241,7 @@ public void shouldThrowExceptionWhenImplicitNullValueIsUsed() } @Test - public void shouldThrowExceptionWhenExplicitNullValueIsUsed() + void shouldThrowExceptionWhenExplicitNullValueIsUsed() { final String testXmlString = "" + @@ -257,7 +257,7 @@ public void shouldThrowExceptionWhenExplicitNullValueIsUsed() @ParameterizedTest @ValueSource(longs = { (long)Integer.MIN_VALUE - 1, (long)Integer.MAX_VALUE + 1 }) - public void shouldThrowExceptionWhenIntValueIsOutOfRange(final long value) + void shouldThrowExceptionWhenIntValueIsOutOfRange(final long value) { final String testXmlString = "" + @@ -272,7 +272,7 @@ public void shouldThrowExceptionWhenIntValueIsOutOfRange(final long value) } @Test - public void shouldThrowExceptionIfEnumValueIsOutOfCustomValueRange() throws IOException + void shouldThrowExceptionIfEnumValueIsOutOfCustomValueRange() throws IOException { final InputStream file = Tests.getLocalResource("error-handler-enum-violates-min-max-value-range.xml"); final IllegalStateException exception = assertThrows(IllegalStateException.class, @@ -281,7 +281,7 @@ public void shouldThrowExceptionIfEnumValueIsOutOfCustomValueRange() throws IOEx } @Test - public void shouldHandleEncodingTypesWithNamedTypes() throws Exception + void shouldHandleEncodingTypesWithNamedTypes() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "encoding-types-schema.xml"), ParserOptions.DEFAULT); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index 405a63e902..0f75157955 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -41,10 +41,10 @@ import static org.junit.jupiter.api.Assertions.fail; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class ErrorHandlerTest +class ErrorHandlerTest { @Test - public void shouldNotExitOnTypeErrorsAndWarnings() throws Exception + void shouldNotExitOnTypeErrorsAndWarnings() throws Exception { final String testXmlString = "" + @@ -93,7 +93,7 @@ public void shouldNotExitOnTypeErrorsAndWarnings() throws Exception } @Test - public void shouldExitAfterTypes() throws Exception + void shouldExitAfterTypes() throws Exception { try { @@ -110,7 +110,7 @@ public void shouldExitAfterTypes() throws Exception } @Test - public void shouldExitAfterTypesWhenDupTypesDefined() throws Exception + void shouldExitAfterTypesWhenDupTypesDefined() throws Exception { try { @@ -119,7 +119,7 @@ public void shouldExitAfterTypesWhenDupTypesDefined() throws Exception } catch (final IllegalStateException ex) { - assertEquals("had 1 warnings", ex.getMessage()); + assertEquals("had 1 warning", ex.getMessage()); return; } @@ -127,7 +127,7 @@ public void shouldExitAfterTypesWhenDupTypesDefined() throws Exception } @Test - public void shouldExitAfterMessageWhenDupMessageIdsDefined() throws Exception + void shouldExitAfterMessageWhenDupMessageIdsDefined() throws Exception { try { @@ -136,7 +136,7 @@ public void shouldExitAfterMessageWhenDupMessageIdsDefined() throws Exception } catch (final IllegalStateException ex) { - assertEquals("had 1 errors", ex.getMessage()); + assertEquals("had 1 error", ex.getMessage()); return; } @@ -144,7 +144,7 @@ public void shouldExitAfterMessageWhenDupMessageIdsDefined() throws Exception } @Test - public void shouldExitAfterMessage() throws Exception + void shouldExitAfterMessage() throws Exception { try { @@ -161,7 +161,7 @@ public void shouldExitAfterMessage() throws Exception } @Test - public void shouldExitAfterMessageWhenGroupDimensionsNotComposite() throws Exception + void shouldExitAfterMessageWhenGroupDimensionsNotComposite() throws Exception { try { @@ -170,7 +170,7 @@ public void shouldExitAfterMessageWhenGroupDimensionsNotComposite() throws Excep } catch (final IllegalStateException ex) { - assertEquals("had 1 errors", ex.getMessage()); + assertEquals("had 1 error", ex.getMessage()); return; } @@ -178,7 +178,7 @@ public void shouldExitAfterMessageWhenGroupDimensionsNotComposite() throws Excep } @Test - public void shouldExitAfterTypesWhenCompositeOffsetsIncorrect() throws Exception + void shouldExitAfterTypesWhenCompositeOffsetsIncorrect() throws Exception { try { @@ -195,7 +195,7 @@ public void shouldExitAfterTypesWhenCompositeOffsetsIncorrect() throws Exception } @Test - public void shouldExitAfterTypesWhenCompositeHasInvalidTypes() throws Exception + void shouldExitAfterTypesWhenCompositeHasInvalidTypes() throws Exception { try { @@ -212,7 +212,7 @@ public void shouldExitAfterTypesWhenCompositeHasInvalidTypes() throws Exception } @Test - public void shouldExitInvalidFieldNames() throws Exception + void shouldExitInvalidFieldNames() throws Exception { try { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java index dd25ca3caf..ac203c3693 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java @@ -25,10 +25,10 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class GroupWithDataTest +class GroupWithDataTest { @Test - public void shouldParseSchemaSuccessfully() throws Exception + void shouldParseSchemaSuccessfully() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "group-with-data-schema.xml"), ParserOptions.DEFAULT); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java index 8ddc6f620d..18176fb7b4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java @@ -28,10 +28,10 @@ /* * Tests associated with offset and blockLength calculation and validation */ -public class OffsetFileTest +class OffsetFileTest { @Test - public void shouldHandleAllTypeOffsets() throws Exception + void shouldHandleAllTypeOffsets() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "basic-types-schema.xml"), ParserOptions.DEFAULT); @@ -50,7 +50,7 @@ public void shouldHandleAllTypeOffsets() throws Exception } @Test - public void shouldHandleAllTypeOffsetsSetByXml() throws Exception + void shouldHandleAllTypeOffsetsSetByXml() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "basic-types-schema.xml"), ParserOptions.DEFAULT); @@ -69,7 +69,7 @@ public void shouldHandleAllTypeOffsetsSetByXml() throws Exception } @Test - public void shouldCalculateGroupOffsetWithNoPaddingFromBlockLength() throws Exception + void shouldCalculateGroupOffsetWithNoPaddingFromBlockLength() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "block-length-schema.xml"), ParserOptions.DEFAULT); @@ -92,7 +92,7 @@ public void shouldCalculateGroupOffsetWithNoPaddingFromBlockLength() throws Exce } @Test - public void shouldCalculateGroupOffsetWithPaddingFromBlockLength() throws Exception + void shouldCalculateGroupOffsetWithPaddingFromBlockLength() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "block-length-schema.xml"), ParserOptions.DEFAULT); @@ -114,7 +114,7 @@ public void shouldCalculateGroupOffsetWithPaddingFromBlockLength() throws Except } @Test - public void shouldCalculateGroupOffsetWithPaddingFromBlockLengthAndGroupBlockLength() throws Exception + void shouldCalculateGroupOffsetWithPaddingFromBlockLengthAndGroupBlockLength() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "block-length-schema.xml"), ParserOptions.DEFAULT); @@ -136,7 +136,7 @@ public void shouldCalculateGroupOffsetWithPaddingFromBlockLengthAndGroupBlockLen } @Test - public void shouldCalculateDataOffsetWithPaddingFromBlockLength() throws Exception + void shouldCalculateDataOffsetWithPaddingFromBlockLength() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "block-length-schema.xml"), ParserOptions.DEFAULT); @@ -149,7 +149,7 @@ public void shouldCalculateDataOffsetWithPaddingFromBlockLength() throws Excepti } @Test - public void shouldCalculateCompositeSizeWithOffsetsSpecified() throws Exception + void shouldCalculateCompositeSizeWithOffsetsSpecified() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "composite-offsets-schema.xml"), ParserOptions.DEFAULT); @@ -159,7 +159,7 @@ public void shouldCalculateCompositeSizeWithOffsetsSpecified() throws Exception } @Test - public void shouldCalculateDimensionSizeWithOffsetsSpecified() throws Exception + void shouldCalculateDimensionSizeWithOffsetsSpecified() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "composite-offsets-schema.xml"), ParserOptions.DEFAULT); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java index 1fa997c138..bde5d84164 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java @@ -24,10 +24,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class RelativeXIncludeTest +class RelativeXIncludeTest { @Test - public void shouldParseFileInSubDir() throws Exception + void shouldParseFileInSubDir() throws Exception { final URL testResource = getClass().getClassLoader().getResource("sub/basic-schema.xml"); assertNotNull(testResource); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index 0911c8f9d1..c57bddddde 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -41,10 +41,10 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class SetTypeTest +class SetTypeTest { @Test - public void shouldHandleBinarySetType() throws Exception + void shouldHandleBinarySetType() throws Exception { final String testXmlString = "" + @@ -65,7 +65,7 @@ public void shouldHandleBinarySetType() throws Exception } @Test - public void shouldHandleSetTypeList() throws Exception + void shouldHandleSetTypeList() throws Exception { final String testXmlString = "" + @@ -115,7 +115,7 @@ public void shouldHandleSetTypeList() throws Exception } @Test - public void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() + void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() { final String testXmlString = "" + @@ -130,7 +130,7 @@ public void shouldThrowExceptionWhenIllegalEncodingTypeSpecified() } @Test - public void shouldThrowExceptionWhenDuplicateValueSpecified() + void shouldThrowExceptionWhenDuplicateValueSpecified() { final String testXmlString = "" + @@ -145,7 +145,7 @@ public void shouldThrowExceptionWhenDuplicateValueSpecified() } @Test - public void shouldThrowExceptionWhenDuplicateNameSpecified() + void shouldThrowExceptionWhenDuplicateNameSpecified() { final String testXmlString = "" + @@ -160,7 +160,7 @@ public void shouldThrowExceptionWhenDuplicateNameSpecified() } @Test - public void shouldThrowExceptionWhenValueOutOfBoundsSpecified() + void shouldThrowExceptionWhenValueOutOfBoundsSpecified() { final String testXmlString = "" + @@ -175,7 +175,7 @@ public void shouldThrowExceptionWhenValueOutOfBoundsSpecified() } @Test - public void shouldHandleEncodingTypesWithNamedTypes() throws Exception + void shouldHandleEncodingTypesWithNamedTypes() throws Exception { final MessageSchema schema = parse(Tests.getLocalResource( "encoding-types-schema.xml"), ParserOptions.DEFAULT); diff --git a/sbe-tool/src/test/resources/error-handler-since-version.xml b/sbe-tool/src/test/resources/error-handler-since-version.xml new file mode 100644 index 0000000000..3eac105f08 --- /dev/null +++ b/sbe-tool/src/test/resources/error-handler-since-version.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From c93cdea495abe280e5328b5a4156c6d4ba5791f7 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 21 Jun 2022 15:52:56 +0100 Subject: [PATCH 0886/1594] [Java] Formatting. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2358dcaae3..52b2c4861a 100644 --- a/build.gradle +++ b/build.gradle @@ -869,7 +869,7 @@ class ChecksumTask extends DefaultTask { if (CR == raw[j] && (j == size - 1 || LF == raw[j + 1])) { - continue; + continue } result[i++] = raw[j] From 6afe100b0d1cee2fe0972716231ee3683939c57f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 26 Jun 2022 16:03:17 +0100 Subject: [PATCH 0887/1594] [C++] Type. --- sbe-tool/src/test/cpp/Issue889Test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/test/cpp/Issue889Test.cpp b/sbe-tool/src/test/cpp/Issue889Test.cpp index 1b0c67433d..42c87b1720 100644 --- a/sbe-tool/src/test/cpp/Issue889Test.cpp +++ b/sbe-tool/src/test/cpp/Issue889Test.cpp @@ -24,7 +24,7 @@ class Issue889Test : public testing::Test { }; -TEST_F(Issue889Test, shouldGenerateSpecalisedNullValue) +TEST_F(Issue889Test, shouldGenerateSpecialisedNullValue) { EXPECT_EQ(LotType::get(0), LotType::NULL_VALUE); } From 57dd44d12b751d5d4c02d868faf85f719062df9c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 26 Jun 2022 16:25:36 +0100 Subject: [PATCH 0888/1594] [C++] Use universal ref in forEach and set min to C++11. Issue #903. --- .../sbe/generation/cpp/CppGenerator.java | 27 +++++-------------- sbe-tool/src/test/cpp/Issue835Test.cpp | 11 ++++++++ 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 17bbcebd4d..4f2d56a5cc 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -378,17 +378,6 @@ private static void generateGroupClassHeader( .append(indent).append(" }\n"); sb.append("\n") - .append(indent).append("#if __cplusplus < 201103L\n") - .append(indent).append(" template inline void forEach(Func &func)\n") - .append(indent).append(" {\n") - .append(indent).append(" while (hasNext())\n") - .append(indent).append(" {\n") - .append(indent).append(" next();\n") - .append(indent).append(" func(*this);\n") - .append(indent).append(" }\n") - .append(indent).append(" }\n\n") - - .append(indent).append("#else\n") .append(indent).append(" template inline void forEach(Func &&func)\n") .append(indent).append(" {\n") .append(indent).append(" while (hasNext())\n") @@ -396,9 +385,7 @@ private static void generateGroupClassHeader( .append(indent).append(" next();\n") .append(indent).append(" func(*this);\n") .append(indent).append(" }\n") - .append(indent).append(" }\n\n") - - .append(indent).append("#endif\n"); + .append(indent).append(" }\n\n"); } private static void generateGroupProperty( @@ -2655,20 +2642,19 @@ private CharSequence appendDisplay( new Formatter(sb).format( indent + "{\n" + indent + " bool atLeastOne = false;\n" + - indent + " builder << R\"(\"%3$s\": [)\";\n" + - indent + " writer.%2$s().forEach(\n" + - indent + " [&](%1$s &%2$s)\n" + + indent + " builder << R\"(\"%2$s\": [)\";\n" + + indent + " writer.%1$s().forEach(\n" + + indent + " [&](auto &&%1$s)\n" + indent + " {\n" + indent + " if (atLeastOne)\n" + indent + " {\n" + indent + " builder << \", \";\n" + indent + " }\n" + indent + " atLeastOne = true;\n" + - indent + " builder << %2$s;\n" + + indent + " builder << %1$s;\n" + indent + " });\n" + indent + " builder << ']';\n" + indent + "}\n\n", - formatClassName(groupToken.name()), formatPropertyName(groupToken.name()), groupToken.name()); @@ -3122,8 +3108,7 @@ private CharSequence generateMessageLength(final List groups, final List< } new Formatter(sbSkip).format( - indent + " %2$s().forEach([](%1$s &e){ e.skip(); });\n", - formatClassName(groupToken.name()), + indent + " %1$s().forEach([](auto &&e){ e.skip(); });\n", formatPropertyName(groupToken.name())); i = endSignal; diff --git a/sbe-tool/src/test/cpp/Issue835Test.cpp b/sbe-tool/src/test/cpp/Issue835Test.cpp index dfac7a7115..b22fdf9277 100644 --- a/sbe-tool/src/test/cpp/Issue835Test.cpp +++ b/sbe-tool/src/test/cpp/Issue835Test.cpp @@ -69,4 +69,15 @@ TEST_F(Issue835Test, shouldCompileWithSkipper) BUFFER_LEN); EXPECT_EQ(decoder.decodeLength(), encoder.encodedLength()); + + MDIncrementalRefreshOrderBook47 decoder2; + decoder2.wrapForDecode( + buffer, + offset, + MDIncrementalRefreshOrderBook47::sbeBlockLength(), + MDIncrementalRefreshOrderBook47::sbeSchemaVersion(), + BUFFER_LEN); + + decoder2.skip(); + EXPECT_EQ(decoder2.encodedLength(), encoder.encodedLength()); } From d5966bf97f5f88660de5440bf4ca823a401d732e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 26 Jun 2022 16:36:12 +0100 Subject: [PATCH 0889/1594] [C++] Revert use of auto in lambdas. Issue #903. --- .../real_logic/sbe/generation/cpp/CppGenerator.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 4f2d56a5cc..24c6b07038 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2642,19 +2642,20 @@ private CharSequence appendDisplay( new Formatter(sb).format( indent + "{\n" + indent + " bool atLeastOne = false;\n" + - indent + " builder << R\"(\"%2$s\": [)\";\n" + - indent + " writer.%1$s().forEach(\n" + - indent + " [&](auto &&%1$s)\n" + + indent + " builder << R\"(\"%3$s\": [)\";\n" + + indent + " writer.%2$s().forEach(\n" + + indent + " [&](%1$s &%2$s)\n" + indent + " {\n" + indent + " if (atLeastOne)\n" + indent + " {\n" + indent + " builder << \", \";\n" + indent + " }\n" + indent + " atLeastOne = true;\n" + - indent + " builder << %1$s;\n" + + indent + " builder << %2$s;\n" + indent + " });\n" + indent + " builder << ']';\n" + indent + "}\n\n", + formatClassName(groupToken.name()), formatPropertyName(groupToken.name()), groupToken.name()); @@ -3108,7 +3109,8 @@ private CharSequence generateMessageLength(final List groups, final List< } new Formatter(sbSkip).format( - indent + " %1$s().forEach([](auto &&e){ e.skip(); });\n", + indent + " %2$s().forEach([](%1$s &e){ e.skip(); });\n", + formatClassName(groupToken.name()), formatPropertyName(groupToken.name())); i = endSignal; From cc441b034a02b8efa4c75f6a2ef9ef33e6565115 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 26 Jun 2022 17:35:22 +0100 Subject: [PATCH 0890/1594] [C++] Generate skip function without use of lambdas or templates. Issue #903. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 24c6b07038..23ffeb642b 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -3109,8 +3109,11 @@ private CharSequence generateMessageLength(final List groups, final List< } new Formatter(sbSkip).format( - indent + " %2$s().forEach([](%1$s &e){ e.skip(); });\n", - formatClassName(groupToken.name()), + indent + (" auto &%1$sGroup { %1$s() };\n") + + indent + (" while (%1$sGroup.hasNext())\n") + + indent + (" {\n") + + indent + (" %1$sGroup.next().skip();\n") + + indent + (" }\n"), formatPropertyName(groupToken.name())); i = endSignal; From b0f91d55a3152a1b91dec107f47b56a4174e3263 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 27 Jun 2022 17:05:26 +0100 Subject: [PATCH 0891/1594] [Java] Upgrade to Agrona 1.16.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 52b2c4861a..a485cfb9c6 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.6.1' def junitVersion = '5.8.2' def jmhVersion = '1.35' -def agronaVersion = '1.15.2' +def agronaVersion = '1.16.0' def agronaVersionRange = '[1.15.2,2.0[' // allow any release >= 1.15.2 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' From 8aa6caea7c0cea0ccb5273f30b9ef6a87893e9ae Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sun, 10 Jul 2022 16:11:33 +0100 Subject: [PATCH 0892/1594] [Java] Provide raw access to field containing a bitset via a getRaw() method on the generated bitset decoder. Issue #893. --- .../sbe/generation/cpp/CppGenerator.java | 14 +++++----- .../sbe/generation/java/JavaGenerator.java | 26 ++++++++++++++----- .../sbe/generation/rust/RustGenerator.java | 5 ++-- version.txt | 2 +- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 23ffeb642b..95151c7106 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -706,14 +706,16 @@ private void generateVarDataDescriptors( private void generateChoiceSet(final List tokens) throws IOException { - final String bitSetName = formatClassName(tokens.get(0).applicableTypeName()); + final Token token = tokens.get(0); + final String bitSetName = formatClassName(token.applicableTypeName()); try (Writer out = outputManager.createOutput(bitSetName)) { out.append(generateFileHeader(ir.namespaces(), bitSetName, null)); out.append(generateClassDeclaration(bitSetName)); - out.append(generateFixedFlyweightCode(bitSetName, tokens.get(0).encodedLength())); + out.append(generateFixedFlyweightCode(bitSetName, token.encodedLength())); + final Encoding encoding = token.encoding(); new Formatter(out).format("\n" + " %1$s &clear()\n" + " {\n" + @@ -722,7 +724,7 @@ private void generateChoiceSet(final List tokens) throws IOException " return *this;\n" + " }\n", bitSetName, - cppTypeName(tokens.get(0).encoding().primitiveType())); + cppTypeName(encoding.primitiveType())); new Formatter(out).format("\n" + " SBE_NODISCARD bool isEmpty() const\n" + @@ -731,7 +733,7 @@ private void generateChoiceSet(final List tokens) throws IOException " std::memcpy(&val, m_buffer + m_offset, sizeof(%1$s));\n" + " return 0 == val;\n" + " }\n", - cppTypeName(tokens.get(0).encoding().primitiveType())); + cppTypeName(encoding.primitiveType())); new Formatter(out).format("\n" + " SBE_NODISCARD %1$s rawValue() const\n" + @@ -740,7 +742,7 @@ private void generateChoiceSet(final List tokens) throws IOException " std::memcpy(&val, m_buffer + m_offset, sizeof(%1$s));\n" + " return val;\n" + " }\n", - cppTypeName(tokens.get(0).encoding().primitiveType())); + cppTypeName(encoding.primitiveType())); new Formatter(out).format("\n" + " %1$s &rawValue(%2$s value)\n" + @@ -749,7 +751,7 @@ private void generateChoiceSet(final List tokens) throws IOException " return *this;\n" + " }\n", bitSetName, - cppTypeName(tokens.get(0).encoding().primitiveType())); + cppTypeName(encoding.primitiveType())); out.append(generateChoices(bitSetName, tokens.subList(1, tokens.size() - 1))); out.append(generateChoicesDisplay(bitSetName, tokens.subList(1, tokens.size() - 1))); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index d9ed796c4c..ef0ffe667c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1185,15 +1185,26 @@ private void generateBitSet(final List tokens) throws IOException final String bitSetName = token.applicableTypeName(); final String decoderName = decoderName(bitSetName); final String encoderName = encoderName(bitSetName); - final List messageBody = getMessageBody(tokens); + final List choiceList = tokens.subList(1, tokens.size() - 1); final String implementsString = implementsInterface(Flyweight.class.getSimpleName()); try (Writer out = outputManager.createOutput(decoderName)) { + final Encoding encoding = token.encoding(); generateFixedFlyweightHeader(out, token, decoderName, implementsString, readOnlyBuffer, fqReadOnlyBuffer); - out.append(generateChoiceIsEmpty(token.encoding().primitiveType())); - generateChoiceDecoders(out, messageBody); - out.append(generateChoiceDisplay(messageBody)); + out.append(generateChoiceIsEmpty(encoding.primitiveType())); + + new Formatter(out).format( + "\n" + + " public %s getRaw()\n" + + " {\n" + + " return %s;\n" + + " }\n", + primitiveTypeName(token), + generateGet(encoding.primitiveType(), "offset", byteOrderString(encoding))); + + generateChoiceDecoders(out, choiceList); + out.append(generateChoiceDisplay(choiceList)); out.append("}\n"); } @@ -1201,7 +1212,7 @@ private void generateBitSet(final List tokens) throws IOException { generateFixedFlyweightHeader(out, token, encoderName, implementsString, mutableBuffer, fqMutableBuffer); generateChoiceClear(out, encoderName, token); - generateChoiceEncoders(out, encoderName, messageBody); + generateChoiceEncoders(out, encoderName, choiceList); out.append("}\n"); } } @@ -1244,10 +1255,11 @@ private void generateEnum(final List tokens) throws IOException out.append(generateEnumFileHeader(ir.applicableNamespace())); out.append(generateEnumDeclaration(enumName, enumToken)); - out.append(generateEnumValues(getMessageBody(tokens), generateLiteral(encoding.primitiveType(), nullVal))); + final List valuesList = tokens.subList(1, tokens.size() - 1); + out.append(generateEnumValues(valuesList, generateLiteral(encoding.primitiveType(), nullVal))); out.append(generateEnumBody(enumToken, enumName)); - out.append(generateEnumLookupMethod(getMessageBody(tokens), enumName, nullVal)); + out.append(generateEnumLookupMethod(valuesList, enumName, nullVal)); out.append("}\n"); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 00417ec76d..e7e26bcc31 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -39,7 +39,6 @@ import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData; -import static uk.co.real_logic.sbe.ir.GenerationUtil.getMessageBody; import static uk.co.real_logic.sbe.ir.Signal.BEGIN_ENUM; import static uk.co.real_logic.sbe.ir.Signal.BEGIN_SET; @@ -137,7 +136,7 @@ public void generate() throws IOException { final Token msgToken = tokens.get(0); final String codecModName = codecModName(msgToken.name()); - final List messageBody = getMessageBody(tokens); + final List messageBody = tokens.subList(1, tokens.size() - 1); int i = 0; final List fields = new ArrayList<>(); @@ -1175,7 +1174,7 @@ private static void generateEnum( { final String originalEnumName = enumTokens.get(0).applicableTypeName(); final String enumRustName = formatStructName(originalEnumName); - final List messageBody = getMessageBody(enumTokens); + final List messageBody = enumTokens.subList(1, enumTokens.size() - 1); if (messageBody.isEmpty()) { throw new IllegalArgumentException("No valid values provided for enum " + originalEnumName); diff --git a/version.txt b/version.txt index bda7b6dbcb..b4f8049e9c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.25.4-SNAPSHOT +1.26.0-SNAPSHOT From 9100ce6fc755d3bcbc5e856cf86f384efea50ed3 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Mon, 11 Jul 2022 16:23:59 +0300 Subject: [PATCH 0893/1594] 1.26.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index b4f8049e9c..5ff8c4f5d2 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.26.0-SNAPSHOT +1.26.0 From 34d75191ee54decffcd6df38a90935f9416dd2bf Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Mon, 11 Jul 2022 16:25:15 +0300 Subject: [PATCH 0894/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 5ff8c4f5d2..28509b3918 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.26.0 +1.26.1-SNAPSHOT From 4ac18d08821869df38c3de04e32547c071d98b45 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 26 Jul 2022 17:41:28 +0100 Subject: [PATCH 0895/1594] [Java] Set size for constant type to zero. --- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index 87e3e4717d..9ae856ca3b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -404,6 +404,7 @@ private void add(final EncodedDataType type, final int offset) break; case CONSTANT: + tokenBuilder.size(0); encodingBuilder .presence(Encoding.Presence.CONSTANT) .constValue(type.constVal()); From bca88499a57f8301818c563ae0b4ad32bbb4321c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 26 Jul 2022 18:21:29 +0100 Subject: [PATCH 0896/1594] [Java] Carry down field sinceVersion into composite types to allow for more convenient OTF parsing. Issue #908. --- .../uk/co/real_logic/sbe/xml/IrGenerator.java | 50 ++++++++----------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index 9ae856ca3b..6ddf288605 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -208,22 +208,19 @@ private void add(final CompositeType type, final int currOffset, final Field fie .semanticType(semanticTypeOf(type, field)) .build(); + final int version = null != field ? Math.max(field.sinceVersion(), type.sinceVersion()) : type.sinceVersion(); + final Token.Builder builder = new Token.Builder() .signal(Signal.BEGIN_COMPOSITE) .name(type.name()) .referencedName(type.referencedName()) .offset(currOffset) .size(type.encodedLength()) - .version(type.sinceVersion()) + .version(version) .deprecated(type.deprecated()) .description(type.description()) .encoding(encoding); - if (null != field) - { - builder.version(Math.max(field.sinceVersion(), type.sinceVersion())); - } - tokenList.add(builder.build()); int offset = 0; @@ -236,19 +233,21 @@ private void add(final CompositeType type, final int currOffset, final Field fie if (elementType instanceof EncodedDataType) { - add((EncodedDataType)elementType, offset); + add((EncodedDataType)elementType, + offset, + null != field ? Math.max(field.sinceVersion(), type.sinceVersion()) : elementType.sinceVersion()); } else if (elementType instanceof EnumType) { - add((EnumType)elementType, offset, null); + add((EnumType)elementType, offset, field); } else if (elementType instanceof SetType) { - add((SetType)elementType, offset, null); + add((SetType)elementType, offset, field); } else if (elementType instanceof CompositeType) { - add((CompositeType)elementType, offset, null); + add((CompositeType)elementType, offset, field); } offset += elementType.encodedLength(); @@ -266,22 +265,19 @@ private void add(final EnumType type, final int offset, final Field field) .nullValue(type.nullValue()) .byteOrder(schema.byteOrder()); + final int version = null != field ? Math.max(field.sinceVersion(), type.sinceVersion()) : type.sinceVersion(); + final Token.Builder builder = new Token.Builder() .signal(Signal.BEGIN_ENUM) .name(type.name()) .referencedName(type.referencedName()) .size(encodingType.size()) .offset(offset) - .version(type.sinceVersion()) + .version(version) .deprecated(type.deprecated()) .description(type.description()) .encoding(encodingBuilder.build()); - if (null != field) - { - builder.version(Math.max(field.sinceVersion(), type.sinceVersion())); - } - tokenList.add(builder.build()); for (final EnumType.ValidValue validValue : type.validValues()) @@ -322,22 +318,19 @@ private void add(final SetType type, final int offset, final Field field) .primitiveType(encodingType) .build(); + final int version = null != field ? Math.max(field.sinceVersion(), type.sinceVersion()) : type.sinceVersion(); + final Token.Builder builder = new Token.Builder() .signal(Signal.BEGIN_SET) .name(type.name()) .referencedName(type.referencedName()) .size(encodingType.size()) .offset(offset) - .version(type.sinceVersion()) + .version(version) .deprecated(type.deprecated()) .description(type.description()) .encoding(encoding); - if (null != field) - { - builder.version(Math.max(field.sinceVersion(), type.sinceVersion())); - } - tokenList.add(builder.build()); for (final SetType.Choice choice : type.choices()) @@ -369,7 +362,7 @@ private void add(final SetType.Choice value, final PrimitiveType encodingType) tokenList.add(builder.build()); } - private void add(final EncodedDataType type, final int offset) + private void add(final EncodedDataType type, final int offset, final int sinceVersion) { final Encoding.Builder encodingBuilder = new Encoding.Builder() .primitiveType(type.primitiveType()) @@ -382,7 +375,7 @@ private void add(final EncodedDataType type, final int offset) .referencedName(type.referencedName()) .size(type.encodedLength()) .description(type.description()) - .version(type.sinceVersion()) + .version(sinceVersion) .deprecated(type.deprecated()) .offset(offset); @@ -426,21 +419,18 @@ private void add(final EncodedDataType type, final int offset, final Field field .timeUnit(field.timeUnit()) .epoch(field.epoch()); + final int version = Math.max(field.sinceVersion(), type.sinceVersion()); + final Token.Builder tokenBuilder = new Token.Builder() .signal(Signal.ENCODING) .name(type.name()) .referencedName(type.referencedName()) .size(type.encodedLength()) .description(type.description()) - .version(type.sinceVersion()) + .version(version) .deprecated(type.deprecated()) .offset(offset); - if (field.type() instanceof CompositeType) - { - tokenBuilder.version(Math.max(field.sinceVersion(), type.sinceVersion())); - } - switch (field.presence()) { case REQUIRED: From 7e6bcc75423324ec7575ed15cb2e3c5de7e25d37 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 28 Jul 2022 11:07:06 +0100 Subject: [PATCH 0897/1594] [Java] Upgrade to JUnit 5.9.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a485cfb9c6..3b1729a2df 100644 --- a/build.gradle +++ b/build.gradle @@ -45,7 +45,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.6.1' -def junitVersion = '5.8.2' +def junitVersion = '5.9.0' def jmhVersion = '1.35' def agronaVersion = '1.16.0' def agronaVersionRange = '[1.15.2,2.0[' // allow any release >= 1.15.2 and < 2.0.0 From c17d2bf7cbd6b3d15f56de5d0db190c9671a3bef Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 28 Jul 2022 14:24:09 +0100 Subject: [PATCH 0898/1594] [Java] Fix warnings. --- .../main/java/uk/co/real_logic/sbe/SbeTool.java | 5 ++++- .../java/uk/co/real_logic/sbe/ValidationUtil.java | 15 ++++++++------- .../java/uk/co/real_logic/sbe/xml/SetType.java | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index f954685139..340de63f8f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -205,7 +205,10 @@ public static void main(final String[] args) throws Exception } else if (fileName.endsWith(".sbeir")) { - ir = new IrDecoder(fileName).decode(); + try (IrDecoder irDecoder = new IrDecoder(fileName)) + { + ir = irDecoder.decode(); + } } else { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index 1c87c1cb40..ff01421e7f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -43,7 +43,7 @@ public class ValidationUtil * must have all elements be a letter or digit or '_'. The first character must not be a digit. * And must not be a C keyword. *

    - * http://en.cppreference.com/w/c/keyword + * C keywords * * @param value to check * @return true for validity as a C name. false if not. @@ -141,7 +141,7 @@ private static boolean isSbeCIdentifierPart(final char c) * must have all elements be a letter or digit or '_'. The first character must not be a digit. * And must not be a C++ keyword. *

    - * http://en.cppreference.com/w/cpp/keyword + * C++ keywords * * @param value to check * @return true for validity as a C++ name. false if not. @@ -228,7 +228,7 @@ private static boolean isSbeCppIdentifierPart(final char c) /** * Check string for validity of usage as a Java identifier. Avoiding keywords. *

    - * http://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.9 + * Java JLS * * @param value to check * @return true for validity as a Java name. false if not. @@ -314,13 +314,13 @@ private static boolean isJavaIdentifier(final String token) /** * "Check" value for validity of usage as a golang identifier. From: - * https://golang.org/ref/spec#Identifiers + * Golang identifiers *

    * identifier = letter { letter | unicode_digit } * letter = unicode_letter | "_" . *

    * unicode_letter and unicode_digit are defined in section 4.5 of the unicode - * standard at http://www.unicode.org/versions/Unicode8.0.0/ and + * standard at Unicode 8.0.0 and * the Java Character and Digit functions are unicode friendly * * @param value to check @@ -393,7 +393,8 @@ private static boolean isSbeGolangIdentifierPart(final char c) } /** - * https://docs.microsoft.com/en-gb/dotnet/articles/csharp/language-reference/keywords/index + * + * C# keywords * Note this does not include the contextual keywords * Note "virtual" is no longer but was in early versions of C# */ @@ -417,7 +418,7 @@ private static boolean isSbeGolangIdentifierPart(final char c) /** * "Check" value for validity of usage as a csharp identifier. - * https://msdn.microsoft.com/en-us/library/aa664670(v=vs.71).aspx + * C# identifiers * Which basically boils down to *

    * first subsequent* diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index 92019acec8..3288ff0e03 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -177,7 +177,7 @@ public Collection choices() /** * Always false. - * + *

    * {@inheritDoc} */ public boolean isVariableLength() From 61689959701a01e455affb4b9b676e9b4360ece2 Mon Sep 17 00:00:00 2001 From: Tom Johnson Date: Thu, 28 Jul 2022 15:50:59 +0100 Subject: [PATCH 0899/1594] Replicate compiler errors in decoders on JDK17 for "yield()" #910 (#911) * Test to replicate compiler errors in decoders on JDK17 when a field is called "yield" #910 * #910 Start fixing unqualified yield errors This now generates code that compiles in Java 17 for groups, composites and fields named "yield", and demonstrates the need for each of these. There are many paths through the JavaGenerator I have not yet tested (or implemented). * #910 Finish(?) fixing unqualified yield errors This now generates code that compiles in Java 17 for all the paths through writeTokenDisplay I can find, and I think that's all that's needed here? * #910 Add a test to ensure we handle both groups called yield and groups with a field called yield, ie that recursive rendering works the way I'd hope and expect. * #910 Use a unit test to highlight compilation errors rather than an entry in the build file. Note: this only fails when running with a Java 17 toolchain, not on Java 8 or 11. * #910 Restrict test to run only on JRE17, and generate updated IR codecs * #910 Fix checkstyle * #910 Remove unnecessary property from unit test * #910 Remove unused import Co-authored-by: tom.johnson --- .../sbe/generation/java/JavaGenerator.java | 18 ++--- .../sbe/ir/generated/FrameCodecDecoder.java | 6 +- .../ir/generated/MessageHeaderDecoder.java | 8 +-- .../sbe/ir/generated/TokenCodecDecoder.java | 20 +++--- .../ir/generated/VarDataEncodingDecoder.java | 2 +- .../generation/java/QualifiedYieldTest.java | 72 +++++++++++++++++++ sbe-tool/src/test/resources/issue910.xml | 65 +++++++++++++++++ 7 files changed, 164 insertions(+), 27 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java create mode 100644 sbe-tool/src/test/resources/issue910.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index ef0ffe667c..21ca6f5a15 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3492,7 +3492,7 @@ private void appendDecoderDisplay( sb, indent, "builder.append(\"" + groupName + Separator.KEY_VALUE + Separator.BEGIN_GROUP + "\");"); append(sb, indent, "final int " + groupName + "OriginalOffset = " + groupName + ".offset;"); append(sb, indent, "final int " + groupName + "OriginalIndex = " + groupName + ".index;"); - append(sb, indent, "final " + groupDecoderName + " " + groupName + " = " + groupName + "();"); + append(sb, indent, "final " + groupDecoderName + " " + groupName + " = this." + groupName + "();"); append(sb, indent, "if (" + groupName + ".count() > 0)"); append(sb, indent, "{"); @@ -3575,9 +3575,9 @@ private int writeTokenDisplay( if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { append(sb, indent, - "for (int i = 0; i < " + fieldName + "Length() && " + fieldName + "(i) > 0; i++)"); + "for (int i = 0; i < " + fieldName + "Length() && this." + fieldName + "(i) > 0; i++)"); append(sb, indent, "{"); - append(sb, indent, " builder.append((char)" + fieldName + "(i));"); + append(sb, indent, " builder.append((char)this." + fieldName + "(i));"); append(sb, indent, "}"); } else @@ -3587,7 +3587,7 @@ private int writeTokenDisplay( append(sb, indent, "{"); append(sb, indent, " for (int i = 0; i < " + fieldName + "Length(); i++)"); append(sb, indent, " {"); - append(sb, indent, " builder.append(" + fieldName + "(i));"); + append(sb, indent, " builder.append(this." + fieldName + "(i));"); Separator.ENTRY.appendToGeneratedBuilder(sb, indent + INDENT + INDENT); append(sb, indent, " }"); append(sb, indent, " builder.setLength(builder.length() - 1);"); @@ -3598,22 +3598,22 @@ private int writeTokenDisplay( else { // have to duplicate because of checkstyle :/ - append(sb, indent, "builder.append(" + fieldName + "());"); + append(sb, indent, "builder.append(this." + fieldName + "());"); } break; case BEGIN_ENUM: - append(sb, indent, "builder.append(" + fieldName + "());"); + append(sb, indent, "builder.append(this." + fieldName + "());"); break; case BEGIN_SET: - append(sb, indent, fieldName + "().appendTo(builder);"); + append(sb, indent, "this." + fieldName + "().appendTo(builder);"); break; case BEGIN_COMPOSITE: { final String typeName = formatClassName(decoderName(typeToken.applicableTypeName())); - append(sb, indent, "final " + typeName + " " + fieldName + " = " + fieldName + "();"); + append(sb, indent, "final " + typeName + " " + fieldName + " = this." + fieldName + "();"); append(sb, indent, "if (" + fieldName + " != null)"); append(sb, indent, "{"); append(sb, indent, " " + fieldName + ".appendTo(builder);"); @@ -3694,7 +3694,7 @@ private void generateMessageLength( final String groupName = formatPropertyName(groupToken.name()); final String groupDecoderName = decoderName(groupToken.name()); - append(sb, bodyIndent, groupDecoderName + " " + groupName + " = " + groupName + "();"); + append(sb, bodyIndent, groupDecoderName + " " + groupName + " = this." + groupName + "();"); append(sb, bodyIndent, "if (" + groupName + ".count() > 0)"); append(sb, bodyIndent, "{"); append(sb, bodyIndent, " while (" + groupName + ".hasNext())"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index d958498953..12fc62b74b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -623,13 +623,13 @@ public StringBuilder appendTo(final StringBuilder builder) builder.append(BLOCK_LENGTH); builder.append("):"); builder.append("irId="); - builder.append(irId()); + builder.append(this.irId()); builder.append('|'); builder.append("irVersion="); - builder.append(irVersion()); + builder.append(this.irVersion()); builder.append('|'); builder.append("schemaVersion="); - builder.append(schemaVersion()); + builder.append(this.schemaVersion()); builder.append('|'); builder.append("packageName="); builder.append('\'').append(packageName()).append('\''); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java index d83fa30430..b0f47e2bd5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java @@ -217,16 +217,16 @@ public StringBuilder appendTo(final StringBuilder builder) builder.append('('); builder.append("blockLength="); - builder.append(blockLength()); + builder.append(this.blockLength()); builder.append('|'); builder.append("templateId="); - builder.append(templateId()); + builder.append(this.templateId()); builder.append('|'); builder.append("schemaId="); - builder.append(schemaId()); + builder.append(this.schemaId()); builder.append('|'); builder.append("version="); - builder.append(version()); + builder.append(this.version()); builder.append(')'); return builder; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index cfac525b67..5f23d9ef9e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -1724,34 +1724,34 @@ public StringBuilder appendTo(final StringBuilder builder) builder.append(BLOCK_LENGTH); builder.append("):"); builder.append("tokenOffset="); - builder.append(tokenOffset()); + builder.append(this.tokenOffset()); builder.append('|'); builder.append("tokenSize="); - builder.append(tokenSize()); + builder.append(this.tokenSize()); builder.append('|'); builder.append("fieldId="); - builder.append(fieldId()); + builder.append(this.fieldId()); builder.append('|'); builder.append("tokenVersion="); - builder.append(tokenVersion()); + builder.append(this.tokenVersion()); builder.append('|'); builder.append("componentTokenCount="); - builder.append(componentTokenCount()); + builder.append(this.componentTokenCount()); builder.append('|'); builder.append("signal="); - builder.append(signal()); + builder.append(this.signal()); builder.append('|'); builder.append("primitiveType="); - builder.append(primitiveType()); + builder.append(this.primitiveType()); builder.append('|'); builder.append("byteOrder="); - builder.append(byteOrder()); + builder.append(this.byteOrder()); builder.append('|'); builder.append("presence="); - builder.append(presence()); + builder.append(this.presence()); builder.append('|'); builder.append("deprecated="); - builder.append(deprecated()); + builder.append(this.deprecated()); builder.append('|'); builder.append("name="); builder.append('\'').append(name()).append('\''); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java index 9b067585e4..aad78db9fe 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java @@ -139,7 +139,7 @@ public StringBuilder appendTo(final StringBuilder builder) builder.append('('); builder.append("length="); - builder.append(length()); + builder.append(this.length()); builder.append('|'); builder.append(')'); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java new file mode 100644 index 0000000000..8f895f6a5d --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import java.util.Map; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.generation.CompilerUtil; +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledForJreRange; +import org.junit.jupiter.api.condition.JRE; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + + +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +public class QualifiedYieldTest +{ + private static final Class BUFFER_CLASS = MutableDirectBuffer.class; + private static final String BUFFER_NAME = BUFFER_CLASS.getName(); + private static final Class READ_ONLY_BUFFER_CLASS = DirectBuffer.class; + private static final String READ_ONLY_BUFFER_NAME = READ_ONLY_BUFFER_CLASS.getName(); + + private final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + + @Test + @EnabledForJreRange(min = JRE.JAVA_17) + void shouldGenerateValidJava() throws Exception + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(Tests.getLocalResource("issue910.xml"), options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager); + + outputManager.setPackageName(ir.applicableNamespace()); + generator.generateMessageHeaderStub(); + generator.generateTypeStubs(); + generator.generate(); + + final Map sources = outputManager.getSources(); + + { + final String fqClassName = ir.applicableNamespace() + "." + "Issue910FieldDecoder"; + final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); + assertNotNull(aClass); + } + } +} diff --git a/sbe-tool/src/test/resources/issue910.xml b/sbe-tool/src/test/resources/issue910.xml new file mode 100644 index 0000000000..f15f7c83fb --- /dev/null +++ b/sbe-tool/src/test/resources/issue910.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + A + B + C + + + 0 + 1 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From d06ff4cd77e543d943935797486f05dfb8d80174 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 8 Aug 2022 10:26:01 +0100 Subject: [PATCH 0900/1594] [Java] Upgrade to Gradle 7.5.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 59821 -> 60756 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 6 ++++++ gradlew.bat | 14 ++++++++------ 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 3b1729a2df..290a273060 100644 --- a/build.gradle +++ b/build.gradle @@ -822,7 +822,7 @@ tasks.named('dependencyUpdates').configure { tasks.findByName('build').dependsOn verifyJavaIrCodecsInSync wrapper { - gradleVersion = '7.4.2' + gradleVersion = '7.5.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927a4d4fb3f96a785543079b8df6723c946b..249e5832f090a2944b7473328c07c9755baa3196 100644 GIT binary patch delta 10197 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 92f06b50fd..8fad3f5a98 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787337..a69d9cb6c2 100755 --- a/gradlew +++ b/gradlew @@ -205,6 +205,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index 107acd32c4..f127cfd49d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal From 8a5f760b992b4999a1e3a81cdac062d0b62ae03c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 9 Aug 2022 12:05:24 +0100 Subject: [PATCH 0901/1594] [Java] Upgrade github actions. --- .github/workflows/ci.yml | 42 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f018aa915..a532c476f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,21 +30,21 @@ jobs: os: [ 'ubuntu-20.04', 'windows-latest' ] steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Cache Gradle dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Setup java - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: 'zulu' java-version: ${{ matrix.java }} @@ -54,7 +54,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - name: Setup java 8 to run the Gradle script - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: 'zulu' java-version: 8 @@ -73,28 +73,28 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Cache Gradle dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Cache NuGet dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.nuget/packages key: ${{ runner.os }}-nuget-${{ hashFiles('csharp/**/*.sln') }} restore-keys: | ${{ runner.os }}-nuget- - name: Setup dotnet - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v2 with: dotnet-version: ${{ matrix.dotnet }} - name: Build @@ -116,16 +116,16 @@ jobs: CXX: g++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Cache Gradle dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} @@ -151,16 +151,16 @@ jobs: CXX: clang++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Cache Gradle dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} @@ -188,7 +188,7 @@ jobs: CXX: clang++ steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install CMake run: | curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz @@ -209,7 +209,7 @@ jobs: CXX: cl steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install CMake run: | $client = new-object System.Net.WebClient @@ -228,16 +228,16 @@ jobs: rust: [ stable, beta, nightly ] steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Cache Gradle dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} From 02c5b6a61eed1548d4afbb21d71434d09d2a8663 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 15 Aug 2022 11:26:56 +0200 Subject: [PATCH 0902/1594] [Java] Upgrade to Mockito 4.7.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 290a273060..478167dfeb 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' -def mockitoVersion = '4.6.1' +def mockitoVersion = '4.7.0' def junitVersion = '5.9.0' def jmhVersion = '1.35' def agronaVersion = '1.16.0' From 75f85d0b382d875c1ccf766bbab902e2d97f0423 Mon Sep 17 00:00:00 2001 From: vdaniloff Date: Fri, 19 Aug 2022 15:54:17 +0300 Subject: [PATCH 0903/1594] [Java] Support binary vardata in json printer (#914) --- .../sbe/json/JsonTokenListener.java | 6 +++- .../real_logic/sbe/json/JsonPrinterTest.java | 30 +++++++++++++++++++ .../resources/json-printer-test-schema.xml | 11 +++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index 3337db04d2..a618463229 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -16,6 +16,7 @@ package uk.co.real_logic.sbe.json; import org.agrona.DirectBuffer; +import org.agrona.PrintBufferUtil; import uk.co.real_logic.sbe.PrimitiveValue; import uk.co.real_logic.sbe.ir.Encoding; import uk.co.real_logic.sbe.ir.Token; @@ -230,7 +231,10 @@ public void onVarData( final byte[] tempBuffer = new byte[length]; buffer.getBytes(bufferIndex, tempBuffer, 0, length); - final String str = new String(tempBuffer, 0, length, typeToken.encoding().characterEncoding()); + + final String charsetName = typeToken.encoding().characterEncoding(); + final String str = charsetName != null ? new String(tempBuffer, 0, length, charsetName) : + PrintBufferUtil.hexDump(tempBuffer); escape(str); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java index 4d2c9e597f..1134876d22 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java @@ -15,6 +15,9 @@ */ package uk.co.real_logic.sbe.json; +import baseline.CredentialsEncoder; +import baseline.MessageHeaderEncoder; +import org.agrona.concurrent.UnsafeBuffer; import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.EncodedCarTestBase; import uk.co.real_logic.sbe.ir.Ir; @@ -125,6 +128,33 @@ void exampleMessagePrintedAsJson() throws Exception result); } + @Test + public void exampleVarData() throws Exception + { + final ByteBuffer encodedSchemaBuffer = ByteBuffer.allocate(SCHEMA_BUFFER_CAPACITY); + encodeSchema(encodedSchemaBuffer); + + final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); + final UnsafeBuffer buffer = new UnsafeBuffer(encodedMsgBuffer); + final CredentialsEncoder encoder = new CredentialsEncoder(); + encoder.wrapAndApplyHeader(buffer, 0, new MessageHeaderEncoder()); + encoder.login("example"); + encoder.putEncryptedPassword(new byte[] {11, 0, 64, 97}, 0, 4); + encodedMsgBuffer.position(encoder.encodedLength()); + + encodedSchemaBuffer.flip(); + final Ir ir = decodeIr(encodedSchemaBuffer); + + final JsonPrinter printer = new JsonPrinter(ir); + final String result = printer.print(encodedMsgBuffer); + assertEquals( + "{\n" + + " \"login\": \"example\",\n" + + " \"encryptedPassword\": \"0b004061\"\n" + + "}", + result); + } + private static void encodeSchema(final ByteBuffer buffer) throws Exception { final Path path = Paths.get("src/test/resources/json-printer-test-schema.xml"); diff --git a/sbe-tool/src/test/resources/json-printer-test-schema.xml b/sbe-tool/src/test/resources/json-printer-test-schema.xml index 94044b19f7..da01a58fd1 100644 --- a/sbe-tool/src/test/resources/json-printer-test-schema.xml +++ b/sbe-tool/src/test/resources/json-printer-test-schema.xml @@ -23,6 +23,10 @@ + + + + @@ -77,4 +81,11 @@ + + + + + + + From 43f4a7d6ec13748b04a0fd54742b70c906f43f69 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 22 Aug 2022 15:00:17 +0100 Subject: [PATCH 0904/1594] [CI] Remove deprecated Ubuntu 18.04 builds. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a532c476f2..d37d09af37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -141,11 +141,11 @@ jobs: cpp-clang-build: name: C++ Clang ${{ matrix.version }} - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: - version: [ '6.0', '7', '8', '9', '10', '11', '12', '13', '14' ] + version: [ '8', '9', '10', '11', '12', '13', '14' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} From 3757794b64ce8d5446bc839a2e1c7fca8d5d06af Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 22 Aug 2022 15:04:17 +0100 Subject: [PATCH 0905/1594] [CI] Remove deprecated Ubuntu 18.04 builds. --- .github/workflows/ci.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d37d09af37..79e547e0b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -166,11 +166,12 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | - curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-${{ matrix.version }} main" + curl --retry ${INSTALL_COMPILER_RETRIES} -L https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + echo 'Acquire::Retries "${INSTALL_COMPILER_RETRIES}";' | sudo tee -a /etc/apt/apt.conf.d/99retries + sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${{ matrix.version }} main" sudo apt-get update - sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev libidn11 - curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz + sudo apt-get install -y clang-${{ matrix.version }} libstdc++-7-dev libbsd-dev uuid-dev libidn11 + curl --retry ${INSTALL_COMPILER_RETRIES} -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH - name: Build From f1b45ef9d25b1b58ca70040256c88283cb385d6c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 22 Aug 2022 15:08:40 +0100 Subject: [PATCH 0906/1594] [CI] Remove deprecated Ubuntu 18.04 builds. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79e547e0b3..8c7f10e57e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -170,7 +170,7 @@ jobs: echo 'Acquire::Retries "${INSTALL_COMPILER_RETRIES}";' | sudo tee -a /etc/apt/apt.conf.d/99retries sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${{ matrix.version }} main" sudo apt-get update - sudo apt-get install -y clang-${{ matrix.version }} libstdc++-7-dev libbsd-dev uuid-dev libidn11 + sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev libidn11 curl --retry ${INSTALL_COMPILER_RETRIES} -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH From 863b874ab381572c66b2b0be4e4e612b75c49929 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 22 Aug 2022 15:13:36 +0100 Subject: [PATCH 0907/1594] [CI] Remove deprecated Ubuntu 18.04 builds. --- .github/workflows/ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c7f10e57e..46d5ca6c2b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -166,12 +166,11 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | - curl --retry ${INSTALL_COMPILER_RETRIES} -L https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - echo 'Acquire::Retries "${INSTALL_COMPILER_RETRIES}";' | sudo tee -a /etc/apt/apt.conf.d/99retries + curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${{ matrix.version }} main" sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev libidn11 - curl --retry ${INSTALL_COMPILER_RETRIES} -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz + curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH - name: Build From dfbe41f4f2fdcf2549462c799504c3de9331966a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 22 Aug 2022 15:16:33 +0100 Subject: [PATCH 0908/1594] [CI] Remove clang 8. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 46d5ca6c2b..6867faae94 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -145,7 +145,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '8', '9', '10', '11', '12', '13', '14' ] + version: [ '9', '10', '11', '12', '13', '14' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} From 303881f4bc2fc02f9361be8954ee01948d3f6a52 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Aug 2022 12:23:27 +0200 Subject: [PATCH 0909/1594] [CI] Add Ubuntu 22.04 to the build matrix. --- .github/workflows/ci.yml | 88 +++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6867faae94..6bc49bdcf0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: fail-fast: false matrix: java: [ '8', '11', '17', '18' ] - os: [ 'ubuntu-20.04', 'windows-latest' ] + os: [ 'ubuntu-22.04', 'windows-latest' ] steps: - name: Checkout code uses: actions/checkout@v3 @@ -63,7 +63,7 @@ jobs: csharp-build: name: C# ${{ matrix.dotnet }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: @@ -104,8 +104,8 @@ jobs: - name: Pack run: ./csharp/pack.sh - cpp-gcc-build: - name: C++ GCC ${{ matrix.version }} + cpp-gcc-2004-build: + name: C++ GCC ${{ matrix.version }} (Ubuntu 20.04) runs-on: ubuntu-20.04 strategy: fail-fast: false @@ -131,16 +131,50 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | - sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic main universe" + sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ bionic main universe" sudo apt-get install -y g++-${{ matrix.version }} libsparsehash-dev libidn11 curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH - name: Build - run: cmake --version && ./cppbuild/cppbuild + run: ./cppbuild/cppbuild + + cpp-gcc-2204-build: + name: C++ GCC ${{ matrix.version }} (Ubuntu 22.04) + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + version: [ '9', '10', '11', '12' ] + env: + CC: gcc-${{ matrix.version }} + CXX: g++-${{ matrix.version }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + - name: Cache Gradle dependencies + uses: actions/cache@v3 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v3 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + - name: Install compiler + run: | + sudo apt-get install -y g++-${{ matrix.version }} libsparsehash-dev libidn11 + curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz + tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz + echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH + - name: Build + run: ./cppbuild/cppbuild - cpp-clang-build: - name: C++ Clang ${{ matrix.version }} + cpp-clang-2004-build: + name: C++ Clang ${{ matrix.version }} (Ubuntu 20.04) runs-on: ubuntu-20.04 strategy: fail-fast: false @@ -174,7 +208,41 @@ jobs: tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH - name: Build - run: cmake --version && ./cppbuild/cppbuild + run: ./cppbuild/cppbuild + + cpp-clang-2204-build: + name: C++ Clang ${{ matrix.version }} (Ubuntu 22.04) + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + version: [ '9', '10', '11', '12', '13', '14' ] + env: + CC: clang-${{ matrix.version }} + CXX: clang++-${{ matrix.version }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + - name: Cache Gradle dependencies + uses: actions/cache@v3 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v3 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + - name: Install compiler + run: | + sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev libidn11 + curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz + tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz + echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH + - name: Build + run: ./cppbuild/cppbuild cpp-clang-macos-build: name: C++ Xcode ${{ matrix.version }} (macOS) @@ -221,7 +289,7 @@ jobs: rust-build: name: Rust ${{ matrix.rust }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: From a1a2e05554858b02043a5b458df81010c5957373 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Aug 2022 12:25:58 +0200 Subject: [PATCH 0910/1594] [CI] Remove some dependencies from Ubuntu 22.04 builds. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6bc49bdcf0..5c4b58f8a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -166,7 +166,7 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | - sudo apt-get install -y g++-${{ matrix.version }} libsparsehash-dev libidn11 + sudo apt-get install -y g++-${{ matrix.version }} curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH @@ -237,7 +237,7 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | - sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev libidn11 + sudo apt-get install -y clang-${{ matrix.version }} curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH From d8599bc5d21214dc0833b3a9ca735e0a403b199d Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Aug 2022 12:27:58 +0200 Subject: [PATCH 0911/1594] [CI] Remove Clang 9 and 10 from Ubuntu 22.04. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c4b58f8a4..a88bfb8a8f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -216,7 +216,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '9', '10', '11', '12', '13', '14' ] + version: [ '11', '12', '13', '14' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} From f58e0073fb7630a35c050aa4e1ddc1d8da9dfd96 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 30 Aug 2022 15:07:49 +0100 Subject: [PATCH 0912/1594] [C/C++] Upgrade to Google Test 1.12.1. --- CMakeLists.txt | 4 ++-- cppbuild/googletest-release-1.11.0.zip | Bin 1121369 -> 0 bytes cppbuild/googletest-release-1.12.1.zip | Bin 0 -> 1081236 bytes 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 cppbuild/googletest-release-1.11.0.zip create mode 100644 cppbuild/googletest-release-1.12.1.zip diff --git a/CMakeLists.txt b/CMakeLists.txt index d98335b346..a8e7b0010c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,8 +67,8 @@ if (SBE_TESTS) ExternalProject_Add( gtest - URL ${CMAKE_CURRENT_SOURCE_DIR}/cppbuild/googletest-release-1.11.0.zip - URL_MD5 52943a59cefce0ae0491d4d2412c120b + URL ${CMAKE_CURRENT_SOURCE_DIR}/cppbuild/googletest-release-1.12.1.zip + URL_MD5 2648d4138129812611cf6b6b4b497a3b PREFIX "${SBE_THIRDPARTY_BINARY_DIR}/gtest" CMAKE_ARGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER};-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} BUILD_BYPRODUCTS "${SBE_THIRDPARTY_BINARY_DIR}/gtest/src/gtest-build/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX};${SBE_THIRDPARTY_BINARY_DIR}/gtest/src/gtest-build/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock_main${CMAKE_STATIC_LIBRARY_SUFFIX}" diff --git a/cppbuild/googletest-release-1.11.0.zip b/cppbuild/googletest-release-1.11.0.zip deleted file mode 100644 index faaf8ea404c3553631e58a44dc9d59a58e3c3ffd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1121369 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�BgYwx47b_}Zyfy*e;xT}Z?g#ZJ0@EWa$X^& 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%0D>d*Cv%2wd|ARI7J-pD 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%0AyjqqA8Rm;|MBWW&Bdviz< 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

    L#rwBtZCXA`ErV-zJ)y`?Ca`O% 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

    4-SGy}j^6Si(%tW01` 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�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℞jRzwey!cD9Xq{ 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

    {8dKD^e^TC!U83|3&x#O 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 z zmC?i|CO)@fJ5PC_WNvI}a0YlZ1B&nPRlXN=39@dBZhraldqrE+jLH`MUlo(Br$c0u z1fU!dO#KvGi;fwS&DCI1i6s(~9G+;HM2VI-RiSJ(=U8>}3Nh_WvP@w3RRUo{tV1V} zvw-Vs09s~x2Vs?FipiqMCM$~@NM=P8G9%(h8!nD^;4gFc1_SET!goFkwM#d0(l+v; zM4iGP_L6BDV_ftod5Hr3p_VUUTAqv?cO-K-Y9M);eTk{Q+1Il~en>s@9ri+$DRNi7 zMlx&wfwxUUiFbR&Y{pV)l#Pm3hCjqv@3R40NVklr)y^iqR~n$fS+z zdR7SP3U2IUN{H6PF>RVWN7OCw|8q%`eyZd2tas3^XUBO%lopQrN-z9OB@d8Jx*KN# zWEEnkap+Yi^YxF#I^GnjiZZ9K%{=&n(RL?dW(6_wl~7N8`9o0tUSSLn$|skI)rp%K z2RvEg5_7qc@P~KKYDNOOp#Kc9vKADo%y{_Y1PhRUFZ0vf(OGff&3)nBxl+w5NBxz$ zr%t9IxpeOB2_-vj&{1+u41P7Ypjv3#acmRs$KsA=jUm=#-taqTI>iGnm^7(bB;oQ) z&~rn_w|~*5Gxhf%pi>$-$(V%BwTV0i1i&LtPRJX^QMVF2raCVw0supEp;)+Vo zYvqA#1b9s*vWa1Yd_ICrQ19|`IMikBGdIF>8E#6acywsX}_TrttZ zOLj39-mIt0v8ZIK!Q6_55tTqRGJ)k!;limZdwcF=QRa$QqO)6|g*4XYDWFyG*~qSH zoHlgPQ}g)~%{!G?UA!QEB{nNEzw`15rTodbpFn%D<|+Nl6Za!;7+M!9R>8Dh=|p>E zS=Wia5J_yyaZSyEltI_gmTj`b)z%#D2Cwaw&tD5y>ntHI6$?wy3-U?ZPm~i2ZYWBK z@LBF5^4UNKJvMn8h!kr^Ml8pj@nwPXD%eD9hW>`7L4N`QePd0hv4QLfi?*xiT2C}n z##6_R!j91(ntFWAv!yOG<++#=#$k#^8KT{gMi9kc_}*OtWgP`=!p6HHpoDj6+J)Ea zz|<@YQdWud&K$?S;B}}I3Sq#T-TQ8Uw-?aHsoKtwF*3xJoU)0y(&5>8uU-ZmuM5AR zyXR}~yJyLC!wUewc(fYASr!0cuuSc!UfK*St$7%=o5=%S5kidl;gS&a)>$U@*Vo_A zo$18(Uj&#C0!&DGnK%rvi}}^n0}RrTu4=;$lv14-l>&4_!7 z7Z?S$&+mGesx`<8eOZls=`X7pr#MRFd@}ZBDJ-JBA&zQA5>X0;jzAKqmEa;p^>G+Q z@}9+OF?MU9%&0vA+~LVdu_mhkPQplG_g%ldEKVb8knO>>cc;NMs_;}9Sejnh2H489Mew1l{#O|*~=6H zSek-G+pn4E)Yg8oG?g2ASSc#4cK7pekU5*)TY)pymk^vW)Pjz0}JtS zgKE;ti9H2aAeBS@qJ$otU2vTc8r#RCBhsWHF19yBglNdA@1Rm>3wMWk@ zbKum1X$upfEXalC&X+IZOYP-9`BWwB-_UMkVc4(2|3sh#wAYzRsy$>zDv^im2>PCWo-noXXpz>ucl$ zgr~=zdzpNpqAVyS^oBLXm4vpA2t?g!+D%+OIKFmASfCac6rh0_`65R%URy-xLBS3S zV5tE1R%`=;!G-C|R4NrdZ#uD?$zZ(<`pD(OZvUvxYqXv^WkkdXdF6bwwwu1W%t$f< z>mD485a9V)FAWnDE1BTRYrRUYlP}EcPvh#7W2#Z~O?vt)*J;xzL`hbaly<45EpvA36O zE8btv^qLHnNG7&6^@twr@_jdbaHovpe8U~yAs&!3pTw6z%M*E{!+Mo&!@SQ55`LHX z1==8w>QTh9y7K|?XZlKU_2mZ@IZ$3@XQzKW?49lRPC*$TAN_5#e|~n>J08lbW@B6G zxx_}YQ|sEaBxFluUw=9HL;`c-+wGEy0 zJ^zB@iW&{q`Fv$DjS6TnQg4-%;Wu;qT}uD--4on&;)aTpQR?>Ow_4G6&?!{?c?`Fq z>c>lAW-S+O{;%h_dcxU?B9&rFGz!fcr0;g8Q(64qN1Jqyj+8hwR;)clZqJrNO9?`m zV%qxmQ%qHBcOKjPW}aTmSn;WWA5E~4<3!`~x5mk_E*syQLVN;&3PiL?jLPqUcG^M5 z@vTA*d%~5Ofa&|>5goeh$%<~XjB6HX|l? zGNkU* zPP6)gPP+q)GbR9MF)9RWIH5WR6sVoJmoNx%mlQ|Qp+>irYOU+&&06OECNfewM6QM%C4IF;1n48&9h+i1H})D}9%n0c7INxcSW~`q3rEn8eBpq! z3C;(-(fRS|*~t*l?;VWxPdjy5;>sx#RqBw+}2^%(!5cOK)pk7#1wfE2kI zF(S?1-|xMkUG3Oyl&9$HY$z8Iq}i8gpTl=4=t{b(jggf!`8{idr7h#E9k!G`l=8Ni zOd>;(Xu40mOI{_P!nkg7?i5Y6g-$nvQDQ{2g8lSpMDq+O6WUerHZyqDCKUt7;91qI zN^{O&SuMoK#RVW&;bzCnpQUpv%V;&tm@l>qs2-z}^?N+CSM1+awOHhas;bnojwlhW z`KZZMf$Yl9RH|WEH)aQ6u7Z;&) zRJawH>^vUO+;#jKlj7lQcIn)Q=s3dgEE#^N)lj!;$4@F8^j3OB&tZ_%Ebqkd^o*lL z)#-`PIDdYXhfgj=C*`RX9$6PbBjdvrFQN5zgZ^~1BRI6dx2aPvK{O?ZsJh?6+6+U2 zD7pe0z(a%RPC%Z~*_A-VwBry@DJo?9JFm|23he=yk>-99JJA>G&(7!b9&`_=XC5}ET% z4NANcgztmu4DHMS(L_XmTxirw%B9;p(a)(@9pfw2uzm>;4Zye<#SXiewF=(dcoQ@( zosjSN!C+tof()ug`ZSSJ)A7LIp@-fjytYLWg)UzxHo~eS>EZ?%XLnD)8EF73-@dec zbfyuW$bWenSpoS>cV~wPo%YOeqT#B{LlHE?CV95lJ4W<4_JsG6)aZYyHW84Y+70A! zfp_s9%k!93-7&|q?(AfVdFi*+oz&TOI;(7_v!-<{NQbul)xJDe4exj62LkJUTb>3tJ%un?$PrPiKU$T1`k<{Mip>`;HBo{R2Mw!FnmA2s}kHH95mFv$n$WRf#fpw-Y<+G}+3e!w(2Q^nm<#BgP zgQX-&;g(2~8L!fb#1y2$$mn$0`~YdKYj5C#Gn?8OX|2++pJZi&s4m~Xqqez+vjsa` z5S9Vnq z>DhSg5y<4o9<*5AXYTNVGD}2`vUj$;}TwbF0J&b($HrNyo zYH#eu4zE3VMHXhErH!=u9j!7cwZas)Zy)gTEMy37yhZmqVyzFJhyGz|{Nh30Lg>Ve zIbmQ=FMn7=oG|HoIL9k`rVq4@Frnjq6ubiECmy*_8<>0HPA+q0>j+BTw5DG*Y4Ozz zD$z>J0a$8=c;fvQT8h!qaAne9Ev$GIrPXaPBLbVlH0kD+$ajs)Z^R{Y>+}cwd^okP z20)B2uZ@cDmnTp6Cu`hP$7+)03Gw3XN(>x^qTJOw(=P!C2H%gb855b_4#WrJEh%bJ zU~YY%-0ja)0yh^ZWWl-N%@cWo)1o~YGBzpMup_hIUDz^4pCMdu3gS4A9Cx_Jg?-szaAh1bH!%8&gRRN#{HV0URE6Kh&*h;Ee$GXyOFc1t2!U zR>30Pi*xiQDp1y(k>`%0BSU#5DL86m-(yq`o@UK2IYBoTH9VRJ_6T_LwE(O)#Uo{V zqGruQuaHr!gOz`I6Y#!zSxbPkOGQaN3cU)+|xgplY zd6KmvGRqU@fLc=*LL>`NmMeVM&b*U}xAGAH5gLCTg}ybmM-%9qYb=Tv{|xZO5T765 zV?#yg`x~iJN1>NPe|YVCcX<+`HhZE#X7fOd;?SrgShuNNMSVc2VWdvJa5OZjR%_AW zq;|WqBT8;p@xaoTgSA`>&ZX>Fk?(WtFWGorDeX+ks?jHWo(Fu~=_mPSa4$OV4Y<--3zJ2qif$ny0SR#F(A@w285moi??p(TIX^W;D#Org?Dc!4!1u z1>p{6ZLBscDkN~?0P=6azLZAlAx4{7w<&X5&K;Av&kG2BQqyL$q|Ns-nzwL+I{hwd zLGSEj=QcFcbv)GBEIs?PEn}TfMPPO$puAA{q^3gilqxfb6Gtw*$wRaWoTahBupXi}(gkduPSql@%DgU-!1mR8 zDmt4*nBCdDB9tqONxW?EeCNu6#h6+*6rsjqG9mbtV%=ifc;KV&b^qDTco6hpD=6tp>5U8Z*u38c44RLjDO9}>AY(D44(Q;!0 z>i`o4HIVtSLrN!@%wPlb^xWIJo?HsiZY0u8-KuzBQxZ0nk%@*}&%l~ag zse>|-Ryv*(mGQ1}+{p@c=p8%-X=7N;+zp+nTrN21;Nc8aOs0mXc!^*TOVEcXgQ%}D zS5Jg}6S{9wN6A~mn{wjkwmXThebS&rC4R$7zw-nj(vRi(T|W{I$!OCur?$pf)o$N7qJLYIH`4K@r~_V=mkbej-`y=dGqOnX9e8tBc(v2 z(&Yd^M!BwqcTyAY>M1sEyic25(@WN-dwX4{Xy$Z5+G;vFga3?Fpkdx~0;a?c zxS0>V;i!K+-0X}F&rUv#ddI(v)}EMcxFvr%C6_GO z6a;>84nkWe3KH{=Rsomwnhe84De6Rr-PgXjGOoWeo9Q0z*FU}a`OQzSx3@Ms?KIyz zg?#U{))s7VqqN1%!WK7M>Fv*_=sz^zN$@dOG);+|m=TPCi9L31zzW4NdxffQiB9bY z^5V&->C|q9r(17r7u^kW4Sn;lCoPt>w*u43ncR6=8FEVmFnk2!| z`Z>t!X!xr(hWN@TOn_f$WS zX4Kp%Gww}d3d4kDm|-GI7l`_nZ}`OCR?BQKZLmXRKeM|fHPUJMNpXaCKAP}gG~HMs zcU!Wh#K1kowhldC4p)57edb{Ck!od6KtE_qW4~I8g4)K0wbyR7D64-Buc#mqFm))u z$)?{=LyX{A)!=2+=2I}aXznXu^=c-*CHv)KyqBGq8tn30Nl$SbhRJV{M*fiQE1&uh zKyvn5pj(%l`j+q3?o;$5PJgTII5~%<=Pm9M+)*c&n4H}FOsB16`ZD!m+1yp!F|_}Z zWnoQZCnDnJ9t@5$#zGNOcP-r128_b8L$`&9Ab^4{j^<04Do^|a$1dn)%#P&wi9V*J z)O1&~vR#{xSa24uW0SUvLbqD~Yi9eVZiz%h=bIeoxOo4CE|`G2%-vEuMXOY94*d~G zY#6ZESOFS~+EckQN14L{c3`7-+xI;@G)_Jl(&Ui{CRY4VRF3VmajRf!hpQ-uS#aVe z5;T>v@fW%cq;`LQUlyt+N9iIQW#G^eQL>X-^QAGJ&nlP}C!&uuF$}_shvnEvWt9E1 z7&9XSBk|!+-Cn44XQ9%Y3zgoI>uZ@$ zn+ir8ilhD_m!mQKuPD_A%qI3dCgH=K&wRN6{nYzaZtwE3+0rV*lVSI$7DWh^9Icll zAx0;17Dn&lcB6OSZ*5?(E1Aq}00< z2*bPT!Te&zciugz6=~`vN_>UgL(f=@gRXD?5-$QxeYBO|N1bH4C`~gyeIMmu`z9aT zpa1QUEfD`d5!s~--a9<*?U1~)jV2AVXynKfkxH~_X{_fkP0f?qcSB+U(_3Y=MG}rz z-bF&5@O3OG=A~9!^`2=c<7{y(HadSC8r#M5*B^sKJ`USYfJ7y0nUX1Sf-5>LLcX7E z$|uT`0E#!JTwlsi1~EN!ZrN0h)4lFrdmhKJSpJ0*`j-EoGLESTHu5hr2F+*sb>L8r zLn6^3^wVzUoy2-iY^&Id{cC&tHKq_PR1WCo*^B7G)fHwmzqiKW^dVjw$UB%3I0bz= z6TXI7eR&(>6FrPCWX5U~?!fC2d&1a_sLueu3(HtMDU_oC7rfCLWhI%M4jyMq z`8LP0C_ot0++_AmGry?BX-2TVh@p+A&m@sfX zw!DT0csbfg%B)Xe$XCNJ!#ir6e(oFf5iz#fM!UBl5xod3`Tp z=yI~T`z-DRsUko0>e-eWntFJpF+wiWSRrD3FLeus3;DJcpw^4cTl*ff6F8^_>0nGloV$+9sH8rr!`Bq*qmBa(oEv9q`FKuoG4%LmYOQHd`whWn3M`Dy zWzt;uK9Jd76&{S$zU6+f!xI@%izYfiJ#hSNQYuxCj+Xab43Hb!^|g(6Djauo$F)Zj z$FEa}pMJ+xd`RJVVOa4AR09Qa@pn44=79sla_HQ^bL(c7@b(-H@mxo4yYR{9n0l(3 zJf(Y7fN-WFpQMNHefN_yojQSbO8+xusfqOl2Y*=@;%xi3po6~J52$Hy-8FSo$TOxQ zl?PD4f(YZ#a559DY&K(3Rv6vaNZ;uZ`E=rq)ygDEnc+4?=y{^Y^g1n zS&F8hQ(e1b$Go6f2R;>V6&ZgJ;ERZ#V(zNkRMQ7}q37}(1{Jx_x4j@|bbhB88h1k9 zz4Ts6g$*BJ&d3#Td6CR0DqPn&N}3^tlOFR+3Czm~-o`s$CV*QYi+}0|sb49B`NU%x zmlN()sv`Lv;Af%c*lKJK_>iTM?+kAxjF&jYU^m`blhL&|9%(}cHQWk#dNL0KXJVgR zR$=L*$jN1K32n*MSfm<#)vR_aG1wWZ6%43A!lJcN^8RAp$%R2LIN37m|7ezXBzjmo zg2*Ql0;&3)fPH$D?^pzEH>ikzRp&(@6X}MY3!g9S@XoefdE7|u48-<`u1I;4fLNE_ zD2QW|^Q+3#wBMpjhM!eBiND%mi9a>vl2*`jD`WBfCnG!Q8G1=rfw=K>xI=d)vKbh^@3U^#{wl>kZLP^AUMN->|9#fS~jzg zmdwVGm}fOj=vUF_rVU;o-RJ1Ap0Bz}lYW}3rZZkWOLgQNYB8nFh5GSXnyWdTR|dbZ z=Sur+3Fs@!;aSpK)iQZj>$Ku>ah9@YsoZz}S)Kd1-ZbLec|6YTe4IN=;M^{kz{h0H zEK?y>@@KAACab`!P*BT^`JXK1D-g&(UFuf@K6B4gvFNH6^$WFdAwz=)mFhXJC?W$% zv(SP^EYeKAi-c9WN~nB66rKHEJ#gGeek$0wf|>_UfV1-yY^LR<>cK^2kKd*m3O=Yy ziuXAZTGc*sf|9#6C1~@~fRL1KLxuf|2>llg@k0IO9>7n?Gx{6#H-6JZ>qSHDZq>vK zyqn|&XR3OEmyNt2$G-CS*7QideE#S`I#K+d{xGrJE{U33skeru=+SGuLhvhD1Q)ij z5?4WC3oGyx6vBV>D!#ab)$YdAHt}@OwQNW#2vjX5qlA+v#U?MG=FhWS-enZ>RzR6f zNcy+50r^takBuVC8o`lF-Qn=8|NeZ4x0jv|dIuxvUI5+qfv&esjrckyx2U8W)-;l? zd~ZIB<1^%Kb~E3eutAG^nm)TE)h+F(XT5`$4Pl4lH98n}NdbYF76ks_@`}^ZJYWhF z+CvKQ)F)+Ly}-rywKWey=N7ZpoLRVuN&8E;4xmq2KVj7u+<0GYee+6QgJxTSGexFj zX-rNC>hhLz2u&zVu`6yc{U=^_#R&%OFeWaSG70?>mxX*(O1lp3&C6%X1tb2@-Wz{FmsgVN7gGEpfW+WA@~&VE!W-=X*+J^M?{D zHcwcgYBI~`NQQ7CiPg5hZurUxOG+MN>>7ZmksM%2loBU zZwQTd7$g%RsNBvH@d&EC46+^vip!KG;wHGlXYdEN@(?MpLqi~3(D3iS5Vs3KUE>o_-{6?L>h!dpcDcZsOhTH0J_p~KeorKm^UDX!r_-aYT zn~xYttw9e**lm{T;s|m1cQeJ;BnkLyGs)IPwRKDlA80Ayv{`dU#BF7Ff9-ZMF2wGn zzHg?!Z}A$=%nJE;OW&iX@H`-4Pv|VcUt7D$0ScuaKWVgiXs+`-VRw>WHpZh00k}y3ZW4g216VW6Q%LwKXR0cC#U%Z5Pdmp7Nr}mJMLi>FUxhfOplmlv1Wf+j zR^n1BYWQoLS3WrsS0Zy#>N0Y-tmGxXZb!=~DT?~{1w}IXH3@ks87-4irQ70NfVqqD z>!#&Gvr;J*YQ9K<(mRSVEPK2g5sAObp#YWJyeWW7RaizIQi&+8UiKjek2Yf$7OunE z^~AJ_aVZ^+N~6`C7R`5l%+-1aKh(7NARP!E302|sl0BJ5Gk&vgRQ&klsDC`vw|J9) zx6MdJH^cH-&PGv*KeqE@!fFXgqH`AM6BcD1yhztB(66Jzle16VVY{xI zIM}zTt}~X?h~Hv+v0NZ>dR;q(!G|yM1)&Uk4J)@WOt0o9NBFjJROgFBMk34jwJPz< z#DWzFk47P-Do#vu>cEOeX9UusG@yX39s>YisU!+C+Xk9!X-Q;NN49p&Y6QAweLbBZ z1N%#|Cu#9>XD}U;B+`*Ybt7&mR94exx-bVK9v{+;O?3ZOZg5* zQNP<0on~2`MW&R6W)zLvoqD{?0fmDqq|$t%Nz-OMvlby;)DW*5;!XY(qbZxVN)xX= z!<)xCMH;ARDoT=tR+*bKQLbiADiY`%{a$XIByQEyi?XP5DX%K9 zl}KJhW+dqCH0W*JvPm}cXgSiJ;Z<~7sb^d8?DewpR=_G2z6LD?+??)iZ?1mQE97lk zXYWeYsUbpoMf2hE(_thVG!aHpk)9UQN@IN;d(JpRwpp2U)eO-tpCi&BIw=sH%5y9f z!bBozDv83Fut?D3Z(E6P+v?k5vXf)V#q2^+r{7!jdt0Bc(?1JLHGeAS(;zleAT}2V zv6TX`wK$0F6o~ER&9qo}VwqV+5#~&G>+7rrm2^Cr1@|8=s^fqM{EpLIVw&SyE$r|uX!3Vhd1Qe!eCyE6 zzDYCt_V-<5!3!+dq9Sj;$2JgNBS#zQmT!;f2AVzb+wY>D0MJOn(>8hex+(F!NFL>w zPt3S_iw!1(|6IhOS9+OxqKL>E%?(Zw_r+zV#08@0D=7I*8bFd$;yV|=NW%LjB%8$d z*s>X51i&>PXNoud^gTm9y^G;hQ_q^%lUEoIfmfdL<5P&TI2-gVb$eZT23My4kZe4YLn;#x_kKfX656D{Zfz4c`N7;Z@1%{vvgoQ^w~} z*W?$QrOlal*d>_XG4kg;*;tpeZ)V7==P>fqyI67G^9nw(Xa0(}&Be=CiJfyf4qem_ z;=fHX8aq-cX7))Eckg`)MlD}^tq?o24$R`L#I6Kqqq2Nrbkiy~jePGPbC~M# z5pNUbh8G=tQQ(UgQ8Iw`b5iQ^Tj#k!x9{!2!xeI3*(pK}nwON}kR6~|mGvNRj8}>+ zt-qL=i_H|KEs*qBAT6J>iIXi$I(>OXt~jCCpdy}D#)(pWuF;kpUy)wVGNM!0<(Z7K z&9#(IUEU>U-j$Ug>6i?wT1g#bJICR8I`DKQyuiBO8P4xX# zKAJOwkuqyX9?Bydig%(LsyRmyKndxpgg{_%3`~RmqeLwe2QT8Imy?N4DL4}-%sRjQ zUeb6caU{vOUn)-#U04%5+CZ=hwn~Ngfjk;xA7~UnenGin=I5Cnm2FlE=Mj2p#v* zygu&LYu66S#YZQR8ArbR=+u&|PP~q}YOY?x5HEYc*zb*)+rXX+G2C`-KL8v4P55QWcm}*G{L1RsAd1BZZ8#>4n=ho<_jx^Ro~3Qhg_IP$jl>^nH({YDiFsgUuRqzpQ0d@ z>r{ymnj$(zDLB*{N3w^x%DHRjR4PM?FONB@b>VMuj0}}f4RVJCWKviT=0fFeMTT2r zJbtnm4qxuywA()uCh}XSRf3PD$=493Ky zYaDcCEM&qi-nra~{)$naKV=cw}+<_f$xpCTLj4!&jW-~gV zqmLGJbnWa&SJ%!?KN!p}0(A>>=8_!!t?`yBPD&8pOXj#UUZO^ER=6I;?G(+_QJ3Px z(0N$OlOFQiH~U5K+&TAG%GAb8^E!TP6-7cx*CQH|)0?W$#f(arD^|g?fKxh9er-L# zSRa3_B~wUH4k%OA1?)c^mt1%nD&d_c_*+mjUzoe{4pmBR!9GRZyI8+|#q}0RebsI~ zqJE`%m1{)2JSyy0Ikc;FZ;{@w)WZq17VP6Il}#bh%komI6^+|;#s=vS%o)0JLHvun z3U5bJGeTeH7q^zynl(^@;}Ep`4lLogC^|5*<&>SUg9#HAf_MZ)b!2V}pXF{hwx9~b zG?P)_iN4XW*0q3qP~?v_>W-$gZbmoCn_AMhj~u-_JG|>luofA-=+Ya66GO)qXuPN; zSoPV{sYf0fi#}dd*3w)v1@6xCrxO6d+`_wR_~`w|?f@k1VDuTpt$+OCsrh)fI3t;l zpMwP$nQW{c>4i0uVpvSyWk74{?+?&2)!3M?XiRKeUeO#qy{0*;u4+uWWC`_CC_Lqg zNV})UJi-cW%wsPsHZzk2p1{)78(7%bl;bghWSJqD8GU87E6nRpz@?1&R+&+G7F-dt z^6jf?>{`?iN-=CjwonD06)374w*3LhiW0dzMqz0jH|wkfzgMKT^8381$)scTBvwff?#O&)VDXr)^t3dQZzJYZU|&PFbY^nX2rrFWlHLR069OdOmHA^ z5#y;B*rU)J&1AgH=%2Rl?V8KDGVa7s=5p?1*yiZc_iobV%)mU?E&xGq6R#cj(s7;e zAqO|}>jccWNTQ5ux$WKb6FS!Rol2_vDx-dkOzQZ0hD2Y!RUI95@vaGsdbzXn-T`64 zU%SyA%sCf9v*|OJ*P4qP>wYw!&M=@nhW7Q7b$<>IC7IH*ec>oQ5#5q5TFq8d150RN zmyM`!3={M7;-e_RejGuHVVp_~sV`6%Be=|;=?uWjf*7&w{kYcJM)?cDAI;DwzQH6GJd z#Je(Z5yK2{kzX1;>uPW(F;`C$&GhBNdIc7z;A)IkFEZRtx4jti&2(hcTs6KWaoniX zDXVD#KDNyiA9s&mU}DRGEmIWTczDgIbLBdh&e#H;11OcV=n{7VF%eeaal$wW&zt+= z*aAQlMgNbvV~4vU^f>_26Y{=ov=sraHO0qJT-?!JroQFS?WzhG-!X`-z`T!;^$XNk;`2{d@HOJ;zeHl&8mqml^C>UA`k~|vyx+$J z@Wk>psNGI=FHUEFHcp*ZE6&y>^Cbu2!1sgMyBG> zY#T}OE@dDpvcNKvaAbr0#Hhu31gMTaalS|(_JhdC}t+WwN#I+zCytku%(_q+}MsMZEmgSn}AOCJi9$ABeK zX*Y{98^POjtV_%XgXtsh1*Iqeb&nWzQry>3eoO9`D>u$;NgU;bnrQk#XWa>JJf8dV zvX*SqGX2R#;7#Ws>?Db}g2Ovm>6+>rYdSUcPiQ@khAy0Y-*H8qBBY$isgHY8ZV*qb@( zI#`%6&M6aztiZ^CW(N%Le}T7`T0Z6-ZgTa{v?AincL6e))OqmWhSoh^)i$Q$fC^q(t7Q>lb0X>!UFAF%x1h7}D$Y_pmjBdIXosN(j6)29h1LyM6toGW(c7sX1kQz)tNn6v! zsxhxtIRh>&Us!lUyou~1%fGTSWS0`sX>K>fW|=zQWOZIJ3&jR=p5k@Ag>)(T!;I=w zOp#O*57d&v-1F%bfk6zS#e#9fW&vzef>7EC1%M-Xh5eH$uE*2ymG5M0N_$7%8yBsw zEIx7tYCl?b&;$rpGy_5Np0fG2#lg|362iw2s9WmQ#tW7-9;8c2BCKp+nz*wbg2?$w z=jKfU1FMn$Kk5FbO}gdMMzVslVg>1n|*e7Dc#)V{}iFbo6jOuZ~vi=>t!Np`g5%M3xennlyZWvIhAxS5A!i22-1q_X5!Q`YDR8%k3V#X+0Mqj6aRA2e&ELW}ex@RW#YOj;F3p}WA z0K7|>58KW5C5lMrGBK2}NQX*n(r+wXWvo%fwyd(vkhd?_8m5yB1|rcPVxL~5hL3BZddGl~K597@RkHUr)#iIuoo4{dA(nq9QIM3{ZFshK}zOQ#4=d1!&0f}x%S`k*jS0Kal3H1Bq|Ew{Z{=5L@$jI$>2OGu7qrowh4&IdNTwUSZ zZ^;G7)VaFGMOmCJQ67kL(~e-9sdj8|1Bx%fl89vSYY3fbzNtO}@btBRu76FYBh0Tm*V+Qw2CHrwt<%OCB%y)3G zDC1$IiBW{~zYA3iFg}3^tHVi4 z%3=~)nfZpQnO-oISwb|Qycf#Rtkw%gIO*<4j-M!L2P_Q7z8Bx0o4!6bb$71pzx18C zIR*rM-QlCq^MIxRS%d>2!q~6(?MdRA4eT2RabZuryQUER@I{~yfhIAwKyYw@79Igb5EC*eRjdMqB`_=*DA7!r z9s7KY3-_-r|1|W2$N))QwlcyCF=w5Tx)Jl)()1qpSP*qO8Q9XqEUsM|`v!xP)Ij0AoO$zw)a!QWusAXh40|O+o#} zD*h~C<-hOby`SaQoOO76PQId~IC@!pa3POpXInHeU}q;F%4@B5XLAcQN#$z9AxzFa zu~XH|6^N<|#gIg#!~EJRe0wp<=pS0_B!(%f-Jl_yQ1f#;G>;cv2?GZx@v>cQTx`@Pd)|Kxa(eseY)_UReA7e=23`=eiaXU~3wZ;oq=-r3p7+327* z*cUZ6nkfYztPDcu#^w#)+Or?+X zm_Q8_sgaLoC!aMvf?uLFTFwE7emHT?r#k#pVg?@kv@<)f3j;y9IhQNskyl2V7{I-%rRn$p)L zly;B*mPRmov^XZowtp(%i=o{-#>Dt2JHQEP@6UY^rpbLHo6O6=s?R==R{X|u+`kyi zckGD-B5IH4*gLdBYbq~AuCU3&yE`(z1l9a^^^l?>j`7-M02r_G4-O*Y*^kEA{a}i@ z#DdA|)Do~v+c8wxR8iGD@c1sZBw;6R5~4DeQ(URbQfs?;xNH79Is||rB+U#8oR_&6 zg?NZ8h5{WsND;4X7iBxNL7hxrQ&IWp)j`y&i6E=OV&6*|W@*6e!)6qUW95vziA5}q ziOZ3x!srZHw@?%oYpa+Ud2$(li%;O4TE5H}-SvIzL0qBJZX}xukSZ3U!PuMGlSAvP zovd|6(TN}@T+x?b>(7&bq>z=288tE`r+AJ}0%`_yWH6<b; zoE7NJe`A4GI%tJ5z4~T4|9|K_qVeRMzBCG*MMkf@vjPyIn>}&g^3NKsxzl}Y_g#9P zyhQZoLEY$4TiwL;IN|>@hjJD1LgxJ`gG%eG6;4UfA_tAI^v(y~FrnQlB6<@i42B+G z$|BuO^!^s+2hV?t?^-kc< z6VTd+MItPTbz+&6=eSR#5tyo8Oej<}k%`#P=E3#o!Ww@~WWttU;h7JFtW_c;#xPLm=S7mqsgvu~r(QUAC% z8o>bX*3>USH_AlUgC`2T-#_Tp^bb@dSplPPotxPdk84c=Q(M1cg))2|){gy^6uNkqK>T1L3b*c}OZ8 zF>-)lz)!5#CA2MswiQ9su|>%17w~Tk|0XHyPp$A;Tsok-@KU85Av*l%*u-iMEE zmZXhWVnd)nq!4+7i2TH?14M+52(VK0;PWB;{Q&C)_;!JfEa8@=~CDTDP{O~L;GAZh^TpP9oo)zz;-Ot8(K>Opl|d{vTfpW z|9}5-6g379;OqbXg&SR8r&=4-e3tE7+2+?Z;t-8mqRMONr1hUvPstwHfF9ZC!{`5n ze}930M*spoum2^1`S#A0j5pqqG6h`6Dc2iqDZ=}t{uFzA8B--` zMC_}3rcP#|b7M{EZ9P5ta=V2A2l+o)V5Ixk;3tBI#_$m|A>P*TvuuzazY}LzJbvTz zS9(S0!Ydt66#~l9#RRM-YKWAenR{oa!FAKAe4^@2L(+CxEV@G$9jK#nJ|;dWa+90(xvl{ zgy$w>bpcp!bZbrPwQan0?!xl<+iP~UX3O6MSMA8F8zIRn5>bQt@JGUoz%@8UhN9Yd z{huCj1S>7&n^hMg@0-3xe*ooCo4K;_C_%1|zC*pSE4WO1=@^z#Hk=o{X zgx2C3ZxR_f(#hw@>;DjbBxvqbpn20k^Y*`k3@q8tn-yr@%A>icm;W$Q6Xa}FAZNQ| zAZHYD;&#t3wR_w-Z=|0-(9=v^SS&p$FN#E+P^~N$M1uA<8AYh^cw6JKS~BM8-_K5X z9p}-?b_dQE5$WwOU);{Gzy1n;HsRkk{Cf@meu95*;NQ>iuie65SgXc-lFi6Aw({EHCSv#tP7FvF3KX>rAMksF@%RG<2)35n&$X4YJJAHumfPr3JlCLo zreGEjBp_5Hk5U({LSn(%ZP`yzV-@w10p)$}3P!LR8 z!f7KQzyp45;bSB=XL?Me2q6d9IShtRs#o(289dWK#ta`zF&i=&cm)OxYcW=QvNWQa z5h}AEHH$eEYaoENq)vq=WWS-VG{XMk8r5jE2ENB(hNJfD)r}=Q4v0ecnAo`67>~#J z#~)uuVTb9QFKFH8^iW(Nk@SVu10C@WPp2EBJdJr>WUaTNAP-rM-sdEzApkQUmVje0 z)z?VuqOU4>8wyNB2K%RTh@-DV;3y8jRFy2b{JbCZZf&>T!R~~QxlgsDIL9IE#H| z2$l`vG7w8}BMsmw#WiPY26RHt*QRD+UE;1e2=1-p%>z;UF+20tL@=LWx>U4|z!S(K6cq+x4w1k_2u6mx${TXIVaVUk{jrEmM;9>$@E#o|pNI9^Hb(mCi z;z&b{V`u5?uH|~}!wphlyYm}5o9AGBYi!oZ_M?z}ITo3P2}RcX>xlCaMbY?O75LkH zrUw9QH(xgd{E9+!yDF@rY=}|iHdZdUKB@*qax@U;@-I-u>TIFbS_9PNy4Wn0eOdP9 zW&vJ{EOboby$ zgXKeL&nykv(OXxY3@+)12;_5jjdq`&yRg#Hsn4gq)xdy-QA9kQYaVlcdgw9Rx2B?n znexR2jk%DV#uH9%j}0rnse|1rZ+!ztAfEYFBbJ6Mfxr=)i-8=D(T&%9Wc-8YUBRHF z;BSjYZ45x)-p5eqm+z=Y*HV-f4dWJfsK)fd@r)=hHI`ef2J%OY5V&^5Lb>TG3+3}T zX;>Zi@La-ArGpvDy|7+11pKNnoOcA4=7W}0qaeAYC1)roC+a`{)DW%v*X=cN8>F7( zkb6{2?opE5qaMauZR&yI{HRmP0WMc`<%ULmhm*-cX`$%rAW4}VxeEBOn2KSNieXGe zA<9E0tuo5^JB4vxR@4v0eE*Q-`v+oPTj%?SihTbdyR0e^?||={X(~4Js3_+9ha}%W z3}Y$^QC^Vm?+W;ye`GU0nt04dtN2(;)LCLKW6!=(K+EcodJ;|vK{<$JL9!l25!^|ci&4l+-8OqV|t;~tR zWDBWQA6U@ zk3t&ri!v>e=aSxz<^HjKEe|I)^XAl(3ZqCBO3tq*M#9SH+moCDP)Vs|#)3SfCr>Er zY-;Au%qSfhRuzo`BkqMGpgJ{G2S6530qwf{XDe175ZS5~M~Fexq9c}tvKEy}2wQwS zGb1$>HCGBkEU!xq!Q4?NyF~Gz%K6Ywus{fSL5~Y}8&(~}WL#0eDqw6+D8V@l`nPY% zCxD&+JIY;#AmqZM$aQuaK}s)sF|jyI>a@R$%tWoizLF8&ud~PBl508gNIie97gYO! zar)O_e&Kub5R)6oJIRQuOAl}EqOBvquqo$z_}KeLyN(Ny`wWf^c$T_o$eKuuznmhn}9zXvUrDKC;?E4vf0uhS~)H!PvF@H_$uw!9VkDh#^Bd}PA9)KwGGX0wh zmgWk(6hBSf?#*D;8+!iUo{Zm%8+$JN>mY(abn8$6_}(5CY09rME_>!Xx3Fs7c@`%~ zi|%AYkCQ!hF0f5|`XH_??6r7vk-S+ATyNvRz&qa<%AMuPJ0+N9u*$}StrAhR!ZaRb z=t#QRbq2|FU$_+s=7bl}Ih^MaQ{KL7i_4)AROv2xIjK%Do&{uX@QN!uA-F; zoL@hG`#aq|-#fD(lEBIPBv)r(XQrp8r>Cc9rauZWWD?^};9>c}vy!ck2-d%nWcm55|GkqkJ8cwFVUo|t5pulcX;)RdN zy;-6L*c$z96q6}xwa-$LRGxG`1xHB?(cUd5wJ1eSkocfNa2d+ zJBm&F z>1<-@B1SS?ZE*4+Hen)$2jt~L41%B2+vqbq3cNl4_dYdcy~+H->Ih5uY~h#zxRUM- zxlJ)U5oKirw=aeSM<59>BDzSH1?rPfg}5~l19>k_2RsWewLMLO<2aeIrHPb(jeNi- z;X3@xDGBkP2@i~zD24~`8UzMZCmw_06CmWNJ!v3Tg@D^+wVsFA0WbDjPLh-6JC48X%lRMgZLZY@sX?eh!UF>*&G3T5pc zZnfisg@{vDIB;>-D?+DTn>Tf`JBxB;f0)-?ci#^-Wfix(N1wP{!22k?!E3z~4-aD3 z;JHd5heff(J{J(Gh-h@&nB@|{G)hELNy`e0xkktJninihuC{n7lJ6l0U%qnXN*>GV zVfkq17e+#=Br=u17>&uf#_c{Z<{+Ei@raOlhdCGK&2RSigJB$AC20n#BbYh+%3^S@WJovGKMcd<3LfRw;c(ul&>*@Q zPw&?+(&2rT+EgKvG1W~8g!esmilmDOZ!<` z>@~v4ju{+^QGPCHVV^grjYIo-h3|78N3gej&_(t@)`|y z^(f#!*fFDjkm85_HXR|k*)13m5NjQ(>J+o{s4rcJk z&VJbsr-SSLQ8>%Y32{)x%+t^mwr}!_(w6?W%4xrpm6;tDmbAviIBo69MPspTXnj#> z^SQ%zsSKqeE4w+-@mfNaV^d;=t*R8FUlp)>ZCZi&>1Z?O^7Ls--mw2#Z*#4&3hFavp2T}wN;Ap+9b8w`prxV2 zIkw_4Hwi*>Q-prQ$J_Qc=aLJi3VotzWNb7c1nD(TRj5fzQ$BVW+ zzl*FPOxxqIFi?zea(W#n;pAR_?uA4~@?n@Y@RMb<^;|>hv(W>M!h9|HJ{JIZq zt;8hyt|tazYQxAbPF2EJzlweES1f}>%-J{`L@O)uSMf~F@U&L4?l3r=go966z-7f6 zAOE>b(PQ7iQ9T;G6fiIKKaitN|E1rTQJn8L(e!;1qkrKMTO7^R_1(d20?VP#V~%6^ zX!d!UvOTH~wz>U5I!mUx;4`^lC<6;N97l$s(t%MuQ-?Q1i5kl0w;jrP@2uizR3=a} za!tcNM}5OV@#RxGBC3}U#PTPaAC-Q!;%L7|? z={9WBhhwKUjvdn*=}lLIKQEGRdfG_yU2fGza%;o94(I%haiH6c#gL`M#U`vg2G48b z{M;n0%1TUOxc3%E8{h%z2E05XFKVOy!Xo$K@#)@@*4V-6``5=^0c*p{BR|$g`bU%A zC*8d>>I3+Bqj=fnVlw7rj$_-XMh|7mRblZf>#Z74=6-(zRS$40ph+%6sR0%>R42b|2N;dK zgN4B^{nhpn3M&~-7g!&_PeuA7EHTT&R z>Bbdt@IWLY7w{MyD;8xjcZ^KM31#cltS+Xw$fzL4gBl-NugkiWq`ZpKXL$gz`=HfOU;+X?Oti{Hy4v{-|vzVKT4-5p|tQY}heTq(w zfch3;T5R1`UufPP_CrL

    &k)#*nNYJxJrYOX__K_ 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 diff --git a/cppbuild/googletest-release-1.12.1.zip b/cppbuild/googletest-release-1.12.1.zip new file mode 100644 index 0000000000000000000000000000000000000000..2eb158e76041f30a3c12a7264af16000cdce65d9 GIT binary patch literal 1081236 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%0AZqA34YUClF$j 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

    aP&%S&js%4*AEl1`F0Ww|nQVQN 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 z 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

      qH+f~o$;pW{e9MoD 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

      qGhIl>6Sut+Zra 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≠S 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

      %l{)rihaaG0Z!6$2oVbJWK+oIyd2#Xj++#s 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⪙g8}>o_Eh9(!k5 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

      SwY5tZV^nLW4ARwMF@LjJ5EAq#f9T`%Th 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

      + * This field can contain a list of ordered pairs in the form: + * ((<schema id> | '*') ':' <schema id>)(',' ((<schema id> | '*') ':' <schema id>))*. + * E.g. 123:5,*:6 which means transform schema with id = 123 to version 5, all others to version 6. + */ + public static final String SCHEMA_TRANSFORM_VERSION = "sbe.schema.transform.version"; + /** * Main entry point for the SBE Tool. * @@ -201,7 +220,10 @@ public static void main(final String[] args) throws Exception validateAgainstSchema(fileName, xsdFilename); } - ir = new IrGenerator().generate(parseSchema(fileName), System.getProperty(TARGET_NAMESPACE)); + final MessageSchema schema = parseSchema(fileName); + final SchemaTransformer transformer = new SchemaTransformerFactory( + System.getProperty(SCHEMA_TRANSFORM_VERSION)); + ir = new IrGenerator().generate(transformer.transform(schema), System.getProperty(TARGET_NAMESPACE)); } else if (fileName.endsWith(".sbeir")) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java new file mode 100644 index 0000000000..6f4e655fe7 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.xml; + +import java.util.Map; + +class IdKeyedSchemaTransformer implements SchemaTransformer +{ + private final Map transformerBySchemaId; + private final SchemaTransformer defaultTransformer; + + IdKeyedSchemaTransformer( + final Map transformerBySchemaId, + final SchemaTransformer defaultTransformer) + { + this.transformerBySchemaId = transformerBySchemaId; + this.defaultTransformer = defaultTransformer; + } + + public MessageSchema transform(final MessageSchema originalSchema) + { + return lookupTransformer(originalSchema.id()).transform(originalSchema); + } + + SchemaTransformer lookupTransformer(final int schemaId) + { + return transformerBySchemaId.getOrDefault(schemaId, defaultTransformer); + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index b62495f537..38a168f1c0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -15,8 +15,8 @@ */ package uk.co.real_logic.sbe.xml; -import org.w3c.dom.Node; import org.agrona.Verify; +import org.w3c.dom.Node; import java.nio.ByteOrder; import java.util.*; @@ -62,6 +62,28 @@ public class MessageSchema ((CompositeType)typeByNameMap.get(this.headerType)).checkForWellFormedMessageHeader(schemaNode); } + MessageSchema( + final String packageName, + final String description, + final int id, + final int version, + final String semanticVersion, + final ByteOrder byteOrder, + final String headerType, + final Map typeByNameMap, + final Map messageByIdMap) + { + this.packageName = packageName; + this.description = description; + this.id = id; + this.version = version; + this.semanticVersion = semanticVersion; + this.byteOrder = byteOrder; + this.headerType = headerType; + this.typeByNameMap = typeByNameMap; + this.messageByIdMap = messageByIdMap; + } + /** * The Schema headerType for message headers. This should be a {@link CompositeType}. * @@ -154,6 +176,16 @@ public Collection messages() return messageByIdMap.values(); } + /** + * Get the {@link Collection} of {@link Type}s for this Schema. + * + * @return the {@link Collection} of {@link Type}s for this Schema. + */ + public Collection types() + { + return typeByNameMap.values(); + } + /** * Return the byte order specified by the messageSchema * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java new file mode 100644 index 0000000000..58eb9ee5eb --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.xml; + +/** + * An abstraction that allows for general transformations of the IR. + */ +public interface SchemaTransformer +{ + /** + * Does an identity transform of the incoming schema. + */ + SchemaTransformer IDENTITY_TRANSFORMER = originalSchema -> originalSchema; + + /** + * Return a new MessageSchema that has been transformed from the original. + * + * @param originalSchema to be transformed + * @return resulting transformed schema. + */ + MessageSchema transform(final MessageSchema originalSchema); +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java new file mode 100644 index 0000000000..f158c5f75f --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java @@ -0,0 +1,88 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.xml; + +import java.util.HashMap; +import java.util.Map; + +/** + * Entry point for schema transformations, will check all incoming configuration/properties and create the appropriate + * transformers as required. + */ +public class SchemaTransformerFactory implements SchemaTransformer +{ + private final SchemaTransformer transformer; + + public SchemaTransformerFactory(final String schemaTransformConfig) + { + transformer = parse(schemaTransformConfig); + } + + /** + * {@inheritDoc} + */ + public MessageSchema transform(final MessageSchema originalSchema) + { + return transformer.transform(originalSchema); + } + + static SchemaTransformer parse(final String configuration) + { + if (null == configuration || configuration.isEmpty()) + { + return IDENTITY_TRANSFORMER; + } + + final String[] split = configuration.split(","); + if (0 == split.length) + { + return IDENTITY_TRANSFORMER; + } + + final HashMap transformerBySchemaId = new HashMap<>(); + parseComponents(split, transformerBySchemaId); + + SchemaTransformer defaultTransformer = transformerBySchemaId.remove(-1); + defaultTransformer = null != defaultTransformer ? defaultTransformer : IDENTITY_TRANSFORMER; + + return transformerBySchemaId.isEmpty() ? + defaultTransformer : new IdKeyedSchemaTransformer(transformerBySchemaId, defaultTransformer); + } + + private static void parseComponents( + final String[] configuration, + final Map transformerBySchemaId) + { + for (String field : configuration) + { + final String[] fieldParts = field.split(":"); + + if (2 != fieldParts.length) + { + throw new IllegalArgumentException("version transformation property part '" + field + "' is invalid"); + } + + final int schemaId = "*".equals(fieldParts[0]) ? -1 : Integer.parseInt(fieldParts[0].trim()); + final int sinceVersion = Integer.parseInt(fieldParts[1].trim()); + transformerBySchemaId.put(schemaId, new SinceVersionSchemaTransformer(sinceVersion)); + } + } + + SchemaTransformer delegate() + { + return transformer; + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java new file mode 100644 index 0000000000..92012a86e1 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java @@ -0,0 +1,70 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.xml; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +class SinceVersionSchemaTransformer implements SchemaTransformer +{ + private final int sinceVersion; + + public SinceVersionSchemaTransformer(final int sinceVersion) + { + this.sinceVersion = sinceVersion; + } + + public MessageSchema transform(final MessageSchema originalSchema) + { + final Collection types = originalSchema.types(); + final Map newTypes = new HashMap<>(); + + for (Type type : types) + { + if (type.sinceVersion() <= this.sinceVersion) + { + newTypes.put(type.name(), type); + } + } + + final Collection messages = originalSchema.messages(); + final Map newMessages = new HashMap<>(); + for (Message message : messages) + { + if (message.sinceVersion() <= this.sinceVersion) + { + newMessages.put((long)message.id(), message); + } + } + + return new MessageSchema( + originalSchema.packageName(), + originalSchema.description(), + originalSchema.id(), + sinceVersion, + originalSchema.semanticVersion(), + originalSchema.byteOrder(), + originalSchema.messageHeader().name(), + newTypes, + newMessages); + } + + int sinceVersion() + { + return sinceVersion; + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java new file mode 100644 index 0000000000..7a9a64c489 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.*; + +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static uk.co.real_logic.sbe.SbeTool.JAVA_DEFAULT_DECODING_BUFFER_TYPE; +import static uk.co.real_logic.sbe.SbeTool.JAVA_DEFAULT_ENCODING_BUFFER_TYPE; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +public class SinceVersionTransformedSchemaJavaGenerationTest +{ + @ParameterizedTest + @CsvSource({ "0,4", "4,5", "5,6" }) + void shouldGenerateCodeForOlderVersion(final int versionIncluded, final int versionExcluded) throws Exception + { + final MessageSchema schema = parse( + Tests.getLocalResource("since-version-filter-schema.xml"), ParserOptions.DEFAULT); + final SchemaTransformer transformer = new SchemaTransformerFactory("*:" + versionIncluded); + final MessageSchema transformedSchema = transformer.transform(schema); + final Ir ir = new IrGenerator().generate(transformedSchema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName("test"); + + final JavaGenerator javaGenerator = new JavaGenerator( + ir, + JAVA_DEFAULT_ENCODING_BUFFER_TYPE, + JAVA_DEFAULT_DECODING_BUFFER_TYPE, + false, + false, + false, + outputManager); + + javaGenerator.generate(); + + final Map sources = outputManager.getSources(); + assertTrue(containsCodeWithSinceVersion(sources, versionIncluded)); + assertTrue(doesNotContainsCodeWithSinceVersion(sources, versionExcluded)); + } + + private static boolean containsCodeWithSinceVersion(final Map sources, final int version) + { + final String nameFragment = "Since" + version; + return sources.keySet().stream().anyMatch(s -> s.contains(nameFragment)); + } + + private boolean doesNotContainsCodeWithSinceVersion(final Map sources, final int version) + { + final String nameFragment = "Since" + version; + return sources.keySet().stream().noneMatch(s -> s.contains(nameFragment)); + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java new file mode 100644 index 0000000000..13f8da4bca --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.xml; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class SchemaTransformerFactoryTest +{ + @Test + void shouldAcceptNullAsTransformConfiguration() + { + final SchemaTransformerFactory schemaTransformerFactory = new SchemaTransformerFactory(null); + assertSame(SchemaTransformer.IDENTITY_TRANSFORMER, schemaTransformerFactory.delegate()); + } + + @Test + void shouldAcceptEmptyStringAsTransformConfiguration() + { + final SchemaTransformerFactory schemaTransformerFactory = new SchemaTransformerFactory(""); + assertSame(SchemaTransformer.IDENTITY_TRANSFORMER, schemaTransformerFactory.delegate()); + } + + @Test + void shouldAllSchemasAsOnlyInput() + { + final SchemaTransformerFactory schemaTransformerFactory = new SchemaTransformerFactory("*:5"); + final SchemaTransformer delegate = schemaTransformerFactory.delegate(); + assertInstanceOf(SinceVersionSchemaTransformer.class, delegate); + + SinceVersionSchemaTransformer transformer = (SinceVersionSchemaTransformer)delegate; + assertEquals(5, transformer.sinceVersion()); + } + + @Test + void shouldHandleMultiSchemaTransformation() + { + final SchemaTransformerFactory schemaTransformerFactory = new SchemaTransformerFactory("1:20,4:32,*:5"); + final SchemaTransformer delegate = schemaTransformerFactory.delegate(); + assertInstanceOf(IdKeyedSchemaTransformer.class, delegate); + + IdKeyedSchemaTransformer transformer = (IdKeyedSchemaTransformer)delegate; + final SinceVersionSchemaTransformer schemaTransformer1 = + (SinceVersionSchemaTransformer)transformer.lookupTransformer(1); + assertEquals(20, schemaTransformer1.sinceVersion()); + final SinceVersionSchemaTransformer schemaTransformer4 = + (SinceVersionSchemaTransformer)transformer.lookupTransformer(4); + assertEquals(32, schemaTransformer4.sinceVersion()); + final SinceVersionSchemaTransformer schemaTransformerDefault = + (SinceVersionSchemaTransformer)transformer.lookupTransformer(89732465); + assertEquals(5, schemaTransformerDefault.sinceVersion()); + } +} \ No newline at end of file diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java new file mode 100644 index 0000000000..59dc2ce8ad --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java @@ -0,0 +1,132 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.xml; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import uk.co.real_logic.sbe.Tests; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; + +import static org.junit.jupiter.api.Assertions.*; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +public class SinceVersionSchemaTransformerTest +{ + @ParameterizedTest + @ValueSource(ints = { 0, 4, 5 }) + void shouldFilterAllVersionedFields(final int filteringVersion) throws Exception + { + final MessageSchema schema = parse( + Tests.getLocalResource("since-version-filter-schema.xml"), ParserOptions.DEFAULT); + + final SinceVersionSchemaTransformer sinceVersionSchemaTransformer = new SinceVersionSchemaTransformer( + filteringVersion); + final MessageSchema transformedSchema = sinceVersionSchemaTransformer.transform(schema); + + assertEquals(filteringVersion, transformedSchema.version()); + assertTypeSinceVersionLessOrEqualTo(filteringVersion, schema, transformedSchema); + assertMessageSinceVersionLessOrEqualTo(filteringVersion, schema, transformedSchema); + } + + private static void assertMessageSinceVersionLessOrEqualTo( + final int filteringVersion, + final MessageSchema originalSchema, + final MessageSchema transformedSchema) + { + final ArrayList transformedMessagesCopy = new ArrayList<>(transformedSchema.messages()); + + final Collection types = originalSchema.messages(); + for (Message message : types) + { + if (message.sinceVersion() <= filteringVersion) + { + assertNotNull( + findAndRemove(transformedMessagesCopy, message), + "Message (" + message.name() + ") should be retained"); + } + else + { + assertNull( + findAndRemove(transformedMessagesCopy, message), + "Message (" + message.name() + ") should be removed"); + } + } + + assertTrue(transformedMessagesCopy.isEmpty(), "Messages should have been removed: " + transformedMessagesCopy); + } + + private static void assertTypeSinceVersionLessOrEqualTo( + final int filteringVersion, + final MessageSchema originalSchema, + final MessageSchema transformedSchema) + { + final ArrayList transformedTypesCopy = new ArrayList<>(transformedSchema.types()); + + final Collection types = originalSchema.types(); + for (Type type : types) + { + if (type.sinceVersion() <= filteringVersion) + { + assertNotNull( + findAndRemove(transformedTypesCopy, type), + "Type (" + type.name() + ") should be retained"); + } + else + { + assertNull( + findAndRemove(transformedTypesCopy, type), + "Type (" + type.name() + ") should be removed"); + } + } + + assertTrue(transformedTypesCopy.isEmpty(), "Types should have been removed: " + transformedTypesCopy); + } + + private static Type findAndRemove(final ArrayList transformedTypesCopy, final Type type) + { + Type result = null; + for (final Iterator it = transformedTypesCopy.iterator(); it.hasNext();) + { + final Type transformedType = it.next(); + if (type.name().equals(transformedType.name())) + { + result = transformedType; + it.remove(); + } + } + + return result; + } + + private static Message findAndRemove(final ArrayList transformedMessagesCopy, final Message message) + { + Message result = null; + for (final Iterator it = transformedMessagesCopy.iterator(); it.hasNext();) + { + final Message transformedMessage = it.next(); + if (message.id() == transformedMessage.id()) + { + result = transformedMessage; + it.remove(); + } + } + + return result; + } +} diff --git a/sbe-tool/src/test/resources/since-version-filter-schema.xml b/sbe-tool/src/test/resources/since-version-filter-schema.xml new file mode 100644 index 0000000000..730a166e0c --- /dev/null +++ b/sbe-tool/src/test/resources/since-version-filter-schema.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A + + + + A + + + + A + + + + A + B + C + + + + 0 + + + + 0 + + + + 0 + + + + 0 + 1 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f3baca4155c004975275d047218e8d78f6d1daec Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Thu, 15 Sep 2022 15:33:02 +1200 Subject: [PATCH 0917/1594] [Java] Include removing fields from messages/groups when transforming to generate older versions. --- .../java/uk/co/real_logic/sbe/SbeTool.java | 3 +- .../java/uk/co/real_logic/sbe/xml/Field.java | 21 ++++ .../uk/co/real_logic/sbe/xml/Message.java | 14 +++ .../real_logic/sbe/xml/SchemaTransformer.java | 2 +- .../sbe/xml/SchemaTransformerFactory.java | 9 +- .../xml/SinceVersionSchemaTransformer.java | 44 +++++++-- .../sbe/xml/SchemaTransformerFactoryTest.java | 4 +- .../SinceVersionSchemaTransformerTest.java | 97 ++++++++++++------- 8 files changed, 145 insertions(+), 49 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index cacf53a187..fa0d1450aa 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -190,7 +190,8 @@ public class SbeTool * to generate older versions of a schema to do version compatibility testing. *

      * This field can contain a list of ordered pairs in the form: - * ((<schema id> | '*') ':' <schema id>)(',' ((<schema id> | '*') ':' <schema id>))*. + * ((<schema id> | '*') ':' <schema id>)(',' ((<schema id> | '*') ':' <schema id>))* + * . * E.g. 123:5,*:6 which means transform schema with id = 123 to version 5, all others to version 6. */ public static final String SCHEMA_TRANSFORM_VERSION = "sbe.schema.transform.version"; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java index 2bead68c2a..9170bbcdc5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java @@ -88,6 +88,27 @@ public class Field this.timeUnit = timeUnit; } + Field(final Field field, final List groupFieldList) + { + this( + field.name, + field.description, + field.id, + field.type, + field.offset, + field.semanticType, + field.presence, + field.valueRef, + field.blockLength, + field.dimensionType, + field.variableLength, + field.sinceVersion, + field.deprecated, + field.epoch, + field.timeUnit); + this.groupFieldList = groupFieldList; + } + /** * Validate the node is correct for the type. * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java index cdb1715179..93586bbd67 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java @@ -83,6 +83,20 @@ public Message(final Node messageNode, final Map typeByNameMap) th validateBlockLength(messageNode, blockLength, computedBlockLength); } + Message(final Message message, final List newFieldList) + { + id = message.id; + name = message.name; + description = message.description; + blockLength = message.blockLength; + sinceVersion = message.sinceVersion; + deprecated = message.deprecated; + semanticType = message.semanticType; + typeByNameMap = message.typeByNameMap; + fieldList = newFieldList; + computedBlockLength = computeMessageRootBlockLength(newFieldList); + } + /** * Return the template schemaId of the message * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java index 58eb9ee5eb..ea2e99b713 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java @@ -31,5 +31,5 @@ public interface SchemaTransformer * @param originalSchema to be transformed * @return resulting transformed schema. */ - MessageSchema transform(final MessageSchema originalSchema); + MessageSchema transform(MessageSchema originalSchema); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java index f158c5f75f..6c08d3706e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java @@ -26,6 +26,13 @@ public class SchemaTransformerFactory implements SchemaTransformer { private final SchemaTransformer transformer; + /** + * Construct the SchemaTransformerFactory with the specified configuration for filtering the messages and types by + * version. + * + * @param schemaTransformConfig configuration for the sinceVersion transformation + * @see uk.co.real_logic.sbe.SbeTool#SCHEMA_TRANSFORM_VERSION + */ public SchemaTransformerFactory(final String schemaTransformConfig) { transformer = parse(schemaTransformConfig); @@ -66,7 +73,7 @@ private static void parseComponents( final String[] configuration, final Map transformerBySchemaId) { - for (String field : configuration) + for (final String field : configuration) { final String[] fieldParts = field.split(":"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java index 92012a86e1..7b4f97d0cb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java @@ -15,25 +15,26 @@ */ package uk.co.real_logic.sbe.xml; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import java.util.*; class SinceVersionSchemaTransformer implements SchemaTransformer { private final int sinceVersion; - public SinceVersionSchemaTransformer(final int sinceVersion) + SinceVersionSchemaTransformer(final int sinceVersion) { this.sinceVersion = sinceVersion; } + /** + * {@inheritDoc} + */ public MessageSchema transform(final MessageSchema originalSchema) { final Collection types = originalSchema.types(); final Map newTypes = new HashMap<>(); - for (Type type : types) + for (final Type type : types) { if (type.sinceVersion() <= this.sinceVersion) { @@ -43,11 +44,14 @@ public MessageSchema transform(final MessageSchema originalSchema) final Collection messages = originalSchema.messages(); final Map newMessages = new HashMap<>(); - for (Message message : messages) + for (final Message message : messages) { - if (message.sinceVersion() <= this.sinceVersion) + final List newFields = removeFields(message.fields(), sinceVersion); + final Message newMessage = new Message(message, newFields); + + if (newMessage.sinceVersion() <= this.sinceVersion) { - newMessages.put((long)message.id(), message); + newMessages.put((long)newMessage.id(), newMessage); } } @@ -63,6 +67,30 @@ public MessageSchema transform(final MessageSchema originalSchema) newMessages); } + private List removeFields(final List fields, final int sinceVersion) + { + final ArrayList newFields = new ArrayList<>(); + for (final Field field : fields) + { + if (field.sinceVersion() > sinceVersion) + { + continue; + } + + Field newField = field; + List groupFields = field.groupFields(); + if (null != groupFields && !groupFields.isEmpty()) + { + groupFields = removeFields(groupFields, sinceVersion); + newField = new Field(field, groupFields); + } + + newFields.add(newField); + } + + return newFields; + } + int sinceVersion() { return sinceVersion; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java index 13f8da4bca..98d86e69d9 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java @@ -42,7 +42,7 @@ void shouldAllSchemasAsOnlyInput() final SchemaTransformer delegate = schemaTransformerFactory.delegate(); assertInstanceOf(SinceVersionSchemaTransformer.class, delegate); - SinceVersionSchemaTransformer transformer = (SinceVersionSchemaTransformer)delegate; + final SinceVersionSchemaTransformer transformer = (SinceVersionSchemaTransformer)delegate; assertEquals(5, transformer.sinceVersion()); } @@ -53,7 +53,7 @@ void shouldHandleMultiSchemaTransformation() final SchemaTransformer delegate = schemaTransformerFactory.delegate(); assertInstanceOf(IdKeyedSchemaTransformer.class, delegate); - IdKeyedSchemaTransformer transformer = (IdKeyedSchemaTransformer)delegate; + final IdKeyedSchemaTransformer transformer = (IdKeyedSchemaTransformer)delegate; final SinceVersionSchemaTransformer schemaTransformer1 = (SinceVersionSchemaTransformer)transformer.lookupTransformer(1); assertEquals(20, schemaTransformer1.sinceVersion()); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java index 59dc2ce8ad..eb2f9ad815 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java @@ -19,10 +19,9 @@ import org.junit.jupiter.params.provider.ValueSource; import uk.co.real_logic.sbe.Tests; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; +import java.util.*; +import static java.util.Comparator.comparing; import static org.junit.jupiter.api.Assertions.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -51,26 +50,65 @@ private static void assertMessageSinceVersionLessOrEqualTo( { final ArrayList transformedMessagesCopy = new ArrayList<>(transformedSchema.messages()); - final Collection types = originalSchema.messages(); - for (Message message : types) + final Collection messages = originalSchema.messages(); + for (final Message originalMessage : messages) { - if (message.sinceVersion() <= filteringVersion) + + if (originalMessage.sinceVersion() <= filteringVersion) { - assertNotNull( - findAndRemove(transformedMessagesCopy, message), - "Message (" + message.name() + ") should be retained"); + final Message transformedMessage = findAndRemove( + transformedMessagesCopy, originalMessage, comparing(Message::id)); + assertNotNull(transformedMessage, "Message (" + originalMessage.name() + ") should be retained"); + + assertFieldsSinceVersionLessOrEqualTo( + filteringVersion, originalMessage.fields(), transformedMessage.fields()); } else { assertNull( - findAndRemove(transformedMessagesCopy, message), - "Message (" + message.name() + ") should be removed"); + findAndRemove(transformedMessagesCopy, originalMessage, comparing(Message::id)), + "Message (" + originalMessage.name() + ") should be removed"); } } assertTrue(transformedMessagesCopy.isEmpty(), "Messages should have been removed: " + transformedMessagesCopy); } + private static void assertFieldsSinceVersionLessOrEqualTo( + final int filteringVersion, + final List originalFields, + final List transformedFields) + { + assertFalse(null == originalFields ^ null == transformedFields); + if (null == originalFields) + { + return; + } + + final ArrayList transformedFieldsCopy = new ArrayList<>(transformedFields); + + for (final Field originalField : originalFields) + { + if (originalField.sinceVersion() <= filteringVersion) + { + final Field transformedField = findAndRemove( + transformedFieldsCopy, originalField, comparing(Field::name)); + assertNotNull(transformedField, "Field (" + originalField.name() + ") should be retained"); + + assertFieldsSinceVersionLessOrEqualTo( + filteringVersion, originalField.groupFields(), transformedField.groupFields()); + } + else + { + assertNull( + findAndRemove(transformedFieldsCopy, originalField, comparing(Field::name)), + "Field (" + originalField.name() + ") should be removed"); + } + } + + assertTrue(transformedFieldsCopy.isEmpty(), "Fields should have been removed: " + transformedFields); + } + private static void assertTypeSinceVersionLessOrEqualTo( final int filteringVersion, final MessageSchema originalSchema, @@ -79,18 +117,18 @@ private static void assertTypeSinceVersionLessOrEqualTo( final ArrayList transformedTypesCopy = new ArrayList<>(transformedSchema.types()); final Collection types = originalSchema.types(); - for (Type type : types) + for (final Type type : types) { if (type.sinceVersion() <= filteringVersion) { assertNotNull( - findAndRemove(transformedTypesCopy, type), + findAndRemove(transformedTypesCopy, type, comparing(Type::name)), "Type (" + type.name() + ") should be retained"); } else { assertNull( - findAndRemove(transformedTypesCopy, type), + findAndRemove(transformedTypesCopy, type, comparing(Type::name)), "Type (" + type.name() + ") should be removed"); } } @@ -98,31 +136,18 @@ private static void assertTypeSinceVersionLessOrEqualTo( assertTrue(transformedTypesCopy.isEmpty(), "Types should have been removed: " + transformedTypesCopy); } - private static Type findAndRemove(final ArrayList transformedTypesCopy, final Type type) - { - Type result = null; - for (final Iterator it = transformedTypesCopy.iterator(); it.hasNext();) - { - final Type transformedType = it.next(); - if (type.name().equals(transformedType.name())) - { - result = transformedType; - it.remove(); - } - } - - return result; - } - - private static Message findAndRemove(final ArrayList transformedMessagesCopy, final Message message) + private static T findAndRemove( + final ArrayList transformedTsCopy, + final T original, + final Comparator comparator) { - Message result = null; - for (final Iterator it = transformedMessagesCopy.iterator(); it.hasNext();) + T result = null; + for (final Iterator it = transformedTsCopy.iterator(); it.hasNext();) { - final Message transformedMessage = it.next(); - if (message.id() == transformedMessage.id()) + final T transformedT = it.next(); + if (0 == comparator.compare(original, transformedT)) { - result = transformedMessage; + result = transformedT; it.remove(); } } From d088c5b666fb5a023558271df271e0223cee30ff Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 21 Sep 2022 15:49:04 +0100 Subject: [PATCH 0918/1594] [Java] Upgrade to JUnit 5.9.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 582bed2752..2e864a76b5 100644 --- a/build.gradle +++ b/build.gradle @@ -45,7 +45,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.8.0' -def junitVersion = '5.9.0' +def junitVersion = '5.9.1' def jmhVersion = '1.35' def agronaVersion = '1.17.1' def agronaVersionRange = '[1.17.1,2.0[' // allow any release >= 1.17.1 and < 2.0.0 From 742cd8a1fa1f0b5f6d29d4606f021719c2d8930a Mon Sep 17 00:00:00 2001 From: ratcash Date: Tue, 27 Sep 2022 10:49:46 +0200 Subject: [PATCH 0919/1594] Adding support for the package attribute on the types element. (#904) * Adding support for the package attribute on the types element. * checkstyle. * Revert accidental delete. * Change parameter order for Token. Add Javadoc. * Code style fixes. * Make QualifiedYieldTest use the new constructor. * Revert changes to test files (using custom version of StringWriterOutputManager). Should be replaced with a new version of Agrona. * Use agrone 1.17.1 * Remove @Override * make checkstyle happy. * Correct inherit directive. --- .../java/uk/co/real_logic/sbe/SbeTool.java | 8 ++ .../generation/TargetCodeGeneratorLoader.java | 5 +- .../sbe/generation/java/JavaGenerator.java | 83 +++++++++++++++++-- .../generation/java/JavaOutputManager.java | 81 ++++++++++++++++++ .../java/uk/co/real_logic/sbe/ir/Token.java | 31 +++++++ .../real_logic/sbe/xml/EncodedDataType.java | 27 +++++- .../uk/co/real_logic/sbe/xml/IrGenerator.java | 7 +- .../java/uk/co/real_logic/sbe/xml/Type.java | 38 ++++++++- .../real_logic/sbe/xml/XmlSchemaParser.java | 12 +++ .../generation/java/JavaGeneratorTest.java | 64 ++++++++++++++ .../java/JavaOutputManagerTest.java | 80 ++++++++++++++++++ .../generation/java/QualifiedYieldTest.java | 2 +- .../explicit-package-test-schema.xml | 45 ++++++++++ 13 files changed, 469 insertions(+), 14 deletions(-) create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java create mode 100644 sbe-tool/src/test/resources/explicit-package-test-schema.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index fa0d1450aa..2f2e53970b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -68,6 +68,8 @@ *

    1. sbe.keyword.append.token: Token to be appended to keywords.
    2. *
    3. sbe.decode.unknown.enum.values: Support unknown decoded enum values. Defaults to false.
    4. *
    5. sbe.xinclude.aware: Is XInclude supported for the schema. Defaults to false.
    6. + *
    7. sbe.type.package.override: Is a package attribute for types element supported (only for JAVA). Defaults to + * false.
    8. * */ public class SbeTool @@ -117,6 +119,12 @@ public class SbeTool */ public static final String XINCLUDE_AWARE = "sbe.xinclude.aware"; + /** + * Boolean system property to control the support of package names in {@code } elements. + * Part of SBE v2-rc2. Defaults to false. + */ + public static final String TYPE_PACKAGE_OVERRIDE = "sbe.type.package.override"; + /** * Target language for generated code. */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 07065da1ac..6f1e68f08c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -15,7 +15,7 @@ */ package uk.co.real_logic.sbe.generation; -import org.agrona.generation.PackageOutputManager; +import uk.co.real_logic.sbe.generation.java.JavaOutputManager; import uk.co.real_logic.sbe.generation.c.CGenerator; import uk.co.real_logic.sbe.generation.c.COutputManager; import uk.co.real_logic.sbe.generation.cpp.CppGenerator; @@ -52,7 +52,8 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) "true".equals(System.getProperty(JAVA_GROUP_ORDER_ANNOTATION)), "true".equals(System.getProperty(JAVA_GENERATE_INTERFACES)), "true".equals(System.getProperty(DECODE_UNKNOWN_ENUM_VALUES)), - new PackageOutputManager(outputDir, ir.applicableNamespace())); + "true".equals(System.getProperty(TYPE_PACKAGE_OVERRIDE)), + new JavaOutputManager(outputDir, ir.applicableNamespace())); } }, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 21ca6f5a15..f8fa753d7f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -19,7 +19,7 @@ import org.agrona.MutableDirectBuffer; import org.agrona.Strings; import org.agrona.Verify; -import org.agrona.generation.OutputManager; +import org.agrona.generation.DynamicPackageOutputManager; import org.agrona.sbe.*; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.generation.CodeGenerator; @@ -30,7 +30,9 @@ import java.io.Writer; import java.util.ArrayList; import java.util.Formatter; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.function.Function; import static uk.co.real_logic.sbe.SbeTool.JAVA_INTERFACE_PACKAGE; @@ -60,7 +62,7 @@ enum CodecType private static final String INDENT = " "; private final Ir ir; - private final OutputManager outputManager; + private final DynamicPackageOutputManager outputManager; private final String fqMutableBuffer; private final String mutableBuffer; private final String fqReadOnlyBuffer; @@ -68,6 +70,32 @@ enum CodecType private final boolean shouldGenerateGroupOrderAnnotation; private final boolean shouldGenerateInterfaces; private final boolean shouldDecodeUnknownEnumValues; + private final boolean shouldSupportTypePackages; + private final Set typePackages = new HashSet<>(); + + /** + * Create a new Java language {@link CodeGenerator}. Generator support for types in their own package is disabled. + * + * @param ir for the messages and types. + * @param mutableBuffer implementation used for mutating underlying buffers. + * @param readOnlyBuffer implementation used for reading underlying buffers. + * @param shouldGenerateGroupOrderAnnotation in the codecs. + * @param shouldGenerateInterfaces for common methods. + * @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding. + * @param outputManager for generating the codecs to. + */ + public JavaGenerator( + final Ir ir, + final String mutableBuffer, + final String readOnlyBuffer, + final boolean shouldGenerateGroupOrderAnnotation, + final boolean shouldGenerateInterfaces, + final boolean shouldDecodeUnknownEnumValues, + final DynamicPackageOutputManager outputManager) + { + this(ir, mutableBuffer, readOnlyBuffer, shouldGenerateGroupOrderAnnotation, shouldGenerateInterfaces, + shouldDecodeUnknownEnumValues, false, outputManager); + } /** * Create a new Java language {@link CodeGenerator}. @@ -78,6 +106,7 @@ enum CodecType * @param shouldGenerateGroupOrderAnnotation in the codecs. * @param shouldGenerateInterfaces for common methods. * @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding. + * @param shouldSupportTypePackages generator support for types in their own package * @param outputManager for generating the codecs to. */ public JavaGenerator( @@ -87,12 +116,14 @@ public JavaGenerator( final boolean shouldGenerateGroupOrderAnnotation, final boolean shouldGenerateInterfaces, final boolean shouldDecodeUnknownEnumValues, - final OutputManager outputManager) + final boolean shouldSupportTypePackages, + final DynamicPackageOutputManager outputManager) { Verify.notNull(ir, "ir"); Verify.notNull(outputManager, "outputManager"); this.ir = ir; + this.shouldSupportTypePackages = shouldSupportTypePackages; this.outputManager = outputManager; this.mutableBuffer = validateBufferImplementation(mutableBuffer, MutableDirectBuffer.class); @@ -144,11 +175,30 @@ public void generateTypeStubs() throws IOException } } + /** + * Register the the type's explicit package - if it's set and should be supported. + * + * @param token the 0-th token of the type + * @param ir the intermediate representation + * @return the overriden package name of the type if set and supported, or {@link Ir#applicableNamespace() } + */ + private String registerTypePackage(final Token token, final Ir ir) + { + if (shouldSupportTypePackages && token.packageName() != null) + { + typePackages.add(token.packageName()); + outputManager.setPackageName(token.packageName()); + return token.packageName(); + } + return ir.applicableNamespace(); + } + /** * {@inheritDoc} */ public void generate() throws IOException { + typePackages.clear(); generatePackageInfo(); generateTypeStubs(); generateMessageHeaderStub(); @@ -1188,6 +1238,7 @@ private void generateBitSet(final List tokens) throws IOException final List choiceList = tokens.subList(1, tokens.size() - 1); final String implementsString = implementsInterface(Flyweight.class.getSimpleName()); + registerTypePackage(token, ir); try (Writer out = outputManager.createOutput(decoderName)) { final Encoding encoding = token.encoding(); @@ -1208,6 +1259,7 @@ private void generateBitSet(final List tokens) throws IOException out.append("}\n"); } + registerTypePackage(token, ir); try (Writer out = outputManager.createOutput(encoderName)) { generateFixedFlyweightHeader(out, token, encoderName, implementsString, mutableBuffer, fqMutableBuffer); @@ -1225,7 +1277,8 @@ private void generateFixedFlyweightHeader( final String buffer, final String fqBuffer) throws IOException { - out.append(generateFileHeader(ir.applicableNamespace(), fqBuffer)); + final String packageName = registerTypePackage(token, ir); + out.append(generateFileHeader(packageName, fqBuffer)); out.append(generateDeclaration(typeName, implementsString, token)); out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer)); } @@ -1238,7 +1291,8 @@ private void generateCompositeFlyweightHeader( final String fqBuffer, final String implementsString) throws IOException { - out.append(generateFileHeader(ir.applicableNamespace(), fqBuffer)); + final String packageName = registerTypePackage(token, ir); + out.append(generateFileHeader(packageName, fqBuffer)); out.append(generateDeclaration(typeName, implementsString, token)); out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer)); } @@ -1250,9 +1304,10 @@ private void generateEnum(final List tokens) throws IOException final Encoding encoding = enumToken.encoding(); final String nullVal = encoding.applicableNullValue().toString(); + final String packageName = registerTypePackage(enumToken, ir); try (Writer out = outputManager.createOutput(enumName)) { - out.append(generateEnumFileHeader(ir.applicableNamespace())); + out.append(generateEnumFileHeader(packageName)); out.append(generateEnumDeclaration(enumName, enumToken)); final List valuesList = tokens.subList(1, tokens.size() - 1); @@ -1272,6 +1327,7 @@ private void generateComposite(final List tokens) throws IOException final String decoderName = decoderName(compositeName); final String encoderName = encoderName(compositeName); + registerTypePackage(token, ir); try (Writer out = outputManager.createOutput(decoderName)) { final String implementsString = implementsInterface(CompositeDecoderFlyweight.class.getSimpleName()); @@ -1320,6 +1376,7 @@ private void generateComposite(final List tokens) throws IOException out.append("}\n"); } + registerTypePackage(token, ir); try (Writer out = outputManager.createOutput(encoderName)) { final String implementsString = implementsInterface(CompositeEncoderFlyweight.class.getSimpleName()); @@ -1572,13 +1629,22 @@ private CharSequence generateFileHeader(final String packageName, final String f private CharSequence generateMainHeader( final String packageName, final CodecType codecType, final boolean hasVarData) { + final StringBuffer packageImports = new StringBuffer(); + for (final String typePackage : typePackages) + { + packageImports.append("import "); + packageImports.append(typePackage); + packageImports.append(".*;\n"); + } + if (fqMutableBuffer.equals(fqReadOnlyBuffer)) { return "/* Generated SBE (Simple Binary Encoding) message codec. */\n" + "package " + packageName + ";\n\n" + "import " + fqMutableBuffer + ";\n" + - interfaceImportLine(); + interfaceImportLine() + + packageImports.toString(); } else { @@ -1590,7 +1656,8 @@ private CharSequence generateMainHeader( "package " + packageName + ";\n\n" + (hasMutableBuffer ? "import " + fqMutableBuffer + ";\n" : "") + (hasReadOnlyBuffer ? "import " + fqReadOnlyBuffer + ";\n" : "") + - interfaceImportLine(); + interfaceImportLine() + + packageImports.toString(); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java new file mode 100644 index 0000000000..9dcd568c1f --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java @@ -0,0 +1,81 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import java.io.FilterWriter; +import java.io.IOException; +import java.io.Writer; +import org.agrona.collections.Object2NullableObjectHashMap; +import org.agrona.collections.Object2ObjectHashMap; +import org.agrona.generation.DynamicPackageOutputManager; +import org.agrona.generation.PackageOutputManager; + +/** + * Implementation of {@link DynamicPackageOutputManager} for Java. + */ +public class JavaOutputManager implements DynamicPackageOutputManager +{ + private final String baseDirName; + private final PackageOutputManager basePackageOutputManager; + private PackageOutputManager actingPackageOutputManager; + private final Object2ObjectHashMap outputManagerCache + = new Object2NullableObjectHashMap<>(); + + /** + * Constructor. + * @param baseDirName the target directory + * @param packageName the initial package name + */ + public JavaOutputManager(final String baseDirName, final String packageName) + { + basePackageOutputManager = new PackageOutputManager(baseDirName, packageName); + actingPackageOutputManager = basePackageOutputManager; + this.baseDirName = baseDirName; + } + + /** + * {@inheritDoc} + */ + public void setPackageName(final String packageName) + { + actingPackageOutputManager = outputManagerCache.get(packageName); + if (actingPackageOutputManager == null) + { + actingPackageOutputManager = new PackageOutputManager(baseDirName, packageName); + outputManagerCache.put(packageName, actingPackageOutputManager); + } + } + + private void resetPackage() + { + actingPackageOutputManager = basePackageOutputManager; + } + + /** + * {@inheritDoc} + */ + public Writer createOutput(final String name) throws IOException + { + return new FilterWriter(actingPackageOutputManager.createOutput(name)) + { + public void close() throws IOException + { + super.close(); + resetPackage(); + } + }; + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index d9a09966f2..3fdfb32674 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -79,6 +79,7 @@ public class Token private final String name; private final String referencedName; private final String description; + private final String packageName; private final int id; private final int version; private final int deprecated; @@ -94,6 +95,8 @@ public class Token * @param name of the token in the message. * @param referencedName of the type when created from a ref in a composite. * @param description of what the token is for. + * @param packageName of the token in the message. Use null, except for BEGIN_MESSAGE tokens for types that + * require an explicit package. * @param id as the identifier in the message declaration. * @param version application within the template. * @param deprecated as of this version. @@ -107,6 +110,7 @@ public Token( final String name, final String referencedName, final String description, + final String packageName, final int id, final int version, final int deprecated, @@ -123,6 +127,7 @@ public Token( this.name = name; this.referencedName = referencedName; this.description = description; + this.packageName = packageName; this.id = id; this.version = version; this.deprecated = deprecated; @@ -152,6 +157,16 @@ public String name() return name; } + /** + * Return the packageName of the token + * + * @return packageName of the token or null, if it was not set explicitly. + */ + public String packageName() + { + return packageName; + } + /** * Get the name of the type when this is from a reference. * @@ -344,6 +359,7 @@ public String toString() ", name='" + name + '\'' + ", referencedName='" + referencedName + '\'' + ", description='" + description + '\'' + + ", packageName='" + packageName + '\'' + ", id=" + id + ", version=" + version + ", deprecated=" + deprecated + @@ -361,6 +377,7 @@ public static class Builder { private Signal signal; private String name; + private String packageName = null; private String referencedName; private String description; private int id = INVALID_ID; @@ -395,6 +412,19 @@ public Builder name(final String name) return this; } + /** + * Package name for the Token. Default is null. Use for BEGIN_MESSAGE tokens for types that require an explicit + * package. + * + * @param packageName for the Token. + * @return this for a fluent API. + */ + public Builder packageName(final String packageName) + { + this.packageName = packageName; + return this; + } + /** * Referenced type name for the Token. * @@ -515,6 +545,7 @@ public Token build() name, referencedName, description, + packageName, id, version, deprecated, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index fc26d9cbdc..064b5358e6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -218,7 +218,32 @@ public EncodedDataType( final int length, final boolean varLen) { - super(name, presence, description, 0, 0, semanticType); + this(name, null, presence, description, semanticType, primitiveType, length, varLen); + } + + /** + * Construct a new EncodedDataType with direct values.Does not handle constant values. + * + * @param name of the type + * @param packageName of the type + * @param presence of the type + * @param description of the type or null + * @param semanticType of the type or null + * @param primitiveType of the EncodedDataType + * @param length of the EncodedDataType + * @param varLen of the EncodedDataType + */ + public EncodedDataType( + final String name, + final String packageName, + final Presence presence, + final String description, + final String semanticType, + final PrimitiveType primitiveType, + final int length, + final boolean varLen) + { + super(name, packageName, presence, description, 0, 0, semanticType); this.primitiveType = primitiveType; this.length = length; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index 6ddf288605..6349ce760b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -213,6 +213,7 @@ private void add(final CompositeType type, final int currOffset, final Field fie final Token.Builder builder = new Token.Builder() .signal(Signal.BEGIN_COMPOSITE) .name(type.name()) + .packageName(type.packageName()) .referencedName(type.referencedName()) .offset(currOffset) .size(type.encodedLength()) @@ -270,6 +271,7 @@ private void add(final EnumType type, final int offset, final Field field) final Token.Builder builder = new Token.Builder() .signal(Signal.BEGIN_ENUM) .name(type.name()) + .packageName(type.packageName()) .referencedName(type.referencedName()) .size(encodingType.size()) .offset(offset) @@ -323,6 +325,7 @@ private void add(final SetType type, final int offset, final Field field) final Token.Builder builder = new Token.Builder() .signal(Signal.BEGIN_SET) .name(type.name()) + .packageName(type.packageName()) .referencedName(type.referencedName()) .size(encodingType.size()) .offset(offset) @@ -372,6 +375,7 @@ private void add(final EncodedDataType type, final int offset, final int sinceVe final Token.Builder tokenBuilder = new Token.Builder() .signal(Signal.ENCODING) .name(type.name()) + .packageName(type.packageName()) .referencedName(type.referencedName()) .size(type.encodedLength()) .description(type.description()) @@ -424,6 +428,7 @@ private void add(final EncodedDataType type, final int offset, final Field field final Token.Builder tokenBuilder = new Token.Builder() .signal(Signal.ENCODING) .name(type.name()) + .packageName(type.packageName()) .referencedName(type.referencedName()) .size(type.encodedLength()) .description(type.description()) @@ -505,4 +510,4 @@ private Encoding.Presence mapPresence(final Presence presence) return encodingPresence; } -} \ No newline at end of file +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java index 8a1e491ff4..dba276f95f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java @@ -19,6 +19,7 @@ import static uk.co.real_logic.sbe.xml.XmlSchemaParser.getAttributeValue; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.getAttributeValueOrNull; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.getTypesPackageAttribute; /** * An SBE type. One of encodedDataType, compositeType, enumType, or setType per the SBE spec. @@ -26,6 +27,7 @@ public abstract class Type { private final String name; + private final String packageName; private final Presence presence; private final String description; private final int deprecated; @@ -54,7 +56,7 @@ public Type(final Node node, final String givenName, final String referencedName } this.referencedName = referencedName; - + packageName = getTypesPackageAttribute(node); presence = Presence.get(getAttributeValue(node, "presence", "required")); description = getAttributeValueOrNull(node, "description"); sinceVersion = Integer.parseInt(getAttributeValue(node, "sinceVersion", "0")); @@ -63,10 +65,32 @@ public Type(final Node node, final String givenName, final String referencedName offsetAttribute = Integer.parseInt(getAttributeValue(node, "offset", "-1")); } + /** + * Construct a new Type from direct values. + * + * @param name of the type + * @param presence of the type + * @param description of the type or null + * @param sinceVersion for the type + * @param deprecated version in which this was deprecated. + * @param semanticType of the type or null + */ + public Type( + final String name, + final Presence presence, + final String description, + final int sinceVersion, + final int deprecated, + final String semanticType) + { + this(name, null, presence, description, sinceVersion, deprecated, semanticType); + } + /** * Construct a new Type from direct values. * * @param name of the type + * @param packageName of the type * @param presence of the type * @param description of the type or null * @param sinceVersion for the type @@ -75,6 +99,7 @@ public Type(final Node node, final String givenName, final String referencedName */ public Type( final String name, + final String packageName, final Presence presence, final String description, final int sinceVersion, @@ -82,6 +107,7 @@ public Type( final String semanticType) { this.name = name; + this.packageName = packageName; this.presence = presence; this.description = description; this.sinceVersion = sinceVersion; @@ -206,4 +232,14 @@ public void offsetAttribute(final int offsetAttribute) { this.offsetAttribute = offsetAttribute; } + + /** + * Return the packageName attribute of the {@link Type} from the schema + * + * @return the packageName attribute value or null, if not explicitely defined by the schema + */ + public String packageName() + { + return packageName; + } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index fbc66f9888..455278d707 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -326,6 +326,18 @@ public static String getAttributeValue(final Node elementNode, final String attr return attrNode.getNodeValue(); } + /** + * To be used with child elements of {@code } elements. Returns the package attribute as + * defined on the parent {@code } element + * + * @param elementNode the node inside the types element + * @return the package name, or null if not defined + */ + public static String getTypesPackageAttribute(final Node elementNode) + { + return getAttributeValue(elementNode.getParentNode(), "package", null); + } + /** * Helper function that hides the null return from {@link org.w3c.dom.NamedNodeMap#getNamedItem(String)}. * diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 6ad49097bd..297fc02ec0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -481,6 +481,70 @@ void shouldMarkDeprecatedClasses() throws Exception assertTrue(decoderClazz.isAnnotationPresent(Deprecated.class)); } + @Test + void shouldCreateTypesInDifferentPackages() throws Exception + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(Tests.getLocalResource("explicit-package-test-schema.xml"), options); + final IrGenerator irg = new IrGenerator(); + ir = irg.generate(schema); + + outputManager.clear(); + outputManager.setPackageName(ir.applicableNamespace()); + + final JavaGenerator generator = new JavaGenerator(ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, + true, outputManager); + + generator.generate(); + final String encoderFqcn = ir.applicableNamespace() + ".TestMessageEncoder"; + final Class encoderClazz = compile(encoderFqcn); + assertNotNull(encoderClazz); + + final String decoderFqcn = ir.applicableNamespace() + ".TestMessageDecoder"; + final Class decoderClazz = compile(decoderFqcn); + assertNotNull(decoderClazz); + + final Map sources = outputManager.getSources(); + assertNotNull(sources.get("test.message.schema.common.CarEncoder")); + assertNotNull(sources.get("test.message.schema.common.CarDecoder")); + assertNotNull(sources.get("outside.schema.BooleanType")); + assertNotNull(sources.get("outside.schema.DaysEncoder")); + assertNotNull(sources.get("outside.schema.DaysDecoder")); + assertNotNull(sources.get(ir.applicableNamespace() + ".MessageHeaderEncoder")); + } + + @Test + void shouldCreateTypesInSamePackageIfSupportDisabled() throws Exception + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(Tests.getLocalResource("explicit-package-test-schema.xml"), options); + final IrGenerator irg = new IrGenerator(); + ir = irg.generate(schema); + + outputManager.clear(); + outputManager.setPackageName(ir.applicableNamespace()); + + final JavaGenerator generator = new JavaGenerator(ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, + false, outputManager); + + generator.generate(); + final String encoderFqcn = ir.applicableNamespace() + ".TestMessageEncoder"; + final Class encoderClazz = compile(encoderFqcn); + assertNotNull(encoderClazz); + + final String decoderFqcn = ir.applicableNamespace() + ".TestMessageDecoder"; + final Class decoderClazz = compile(decoderFqcn); + assertNotNull(decoderClazz); + + final Map sources = outputManager.getSources(); + assertNotNull(sources.get(ir.applicableNamespace() + ".CarEncoder")); + assertNotNull(sources.get(ir.applicableNamespace() + ".CarDecoder")); + assertNotNull(sources.get(ir.applicableNamespace() + ".BooleanType")); + assertNotNull(sources.get(ir.applicableNamespace() + ".DaysEncoder")); + assertNotNull(sources.get(ir.applicableNamespace() + ".DaysDecoder")); + assertNotNull(sources.get(ir.applicableNamespace() + ".MessageHeaderEncoder")); + } + private Class getModelClass(final Object encoder) throws ClassNotFoundException { final String className = "Model"; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java new file mode 100644 index 0000000000..3bbd7e4fb9 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java @@ -0,0 +1,80 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; + +public class JavaOutputManagerTest +{ + + private final String tempDirName = System.getProperty("java.io.tmpdir"); + + @Test + void shouldCreateFileWithinPackage() throws Exception + { + final String packageName = "uk.co.real_logic.test"; + final String exampleClassName = "ExampleClassName"; + + final JavaOutputManager cut = new JavaOutputManager(tempDirName, packageName); + final Writer out = cut.createOutput(exampleClassName); + out.close(); + + final String typePackageName = "uk.co.real_logic.common"; + final String typeClassName = "CompositeBigDecimal"; + cut.setPackageName(typePackageName); + final Writer typeOut = cut.createOutput(typeClassName); + typeOut.close(); + + final String typePackageName2 = "uk.co.real_logic.common2"; + final String typeClassName2 = "CompositeBigInteger"; + cut.setPackageName(typePackageName2); + final Writer typeOut2 = cut.createOutput(typeClassName2); + typeOut2.close(); + + final String exampleClassName2 = "ExampleClassName2"; + + final Writer out2 = cut.createOutput(exampleClassName2); + out2.close(); + + assertFileExists(packageName, exampleClassName); + assertFileExists(packageName, exampleClassName2); + assertFileExists(typePackageName, typeClassName); + assertFileExists(typePackageName2, typeClassName2); + } + + private void assertFileExists(final String packageName, final String exampleClassName) throws IOException + { + final String baseDirName = tempDirName.endsWith("" + File.separatorChar) ? tempDirName : tempDirName + + File.separatorChar; + + final String fullyQualifiedFilename = baseDirName + packageName.replace('.', File.separatorChar) + + File.separatorChar + exampleClassName + ".java"; + + final Path path = FileSystems.getDefault().getPath(fullyQualifiedFilename); + final boolean exists = Files.exists(path); + Files.delete(path); + + assertTrue(exists); + } + +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java index 8f895f6a5d..701d50057a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java @@ -54,7 +54,7 @@ void shouldGenerateValidJava() throws Exception final IrGenerator irg = new IrGenerator(); final Ir ir = irg.generate(schema); final JavaGenerator generator = new JavaGenerator( - ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager); + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, false, outputManager); outputManager.setPackageName(ir.applicableNamespace()); generator.generateMessageHeaderStub(); diff --git a/sbe-tool/src/test/resources/explicit-package-test-schema.xml b/sbe-tool/src/test/resources/explicit-package-test-schema.xml new file mode 100644 index 0000000000..a0e02791b1 --- /dev/null +++ b/sbe-tool/src/test/resources/explicit-package-test-schema.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + 0 + 1 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + + + + + + + + + + From a52aef5b3f4ae8871f03060a80ca367a806a09d5 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 27 Sep 2022 10:29:21 +0100 Subject: [PATCH 0920/1594] [Java] Clean up after merge of PR #904. --- .../java/uk/co/real_logic/sbe/SbeTool.java | 6 +-- .../generation/TargetCodeGeneratorLoader.java | 2 +- .../sbe/generation/java/JavaGenerator.java | 49 ++++++++--------- .../generation/java/JavaOutputManager.java | 22 ++++---- .../java/uk/co/real_logic/sbe/ir/Token.java | 4 +- .../real_logic/sbe/xml/EncodedDataType.java | 34 ++++++------ .../java/uk/co/real_logic/sbe/xml/Type.java | 54 +++++++++---------- .../java/JavaOutputManagerTest.java | 17 +++--- version.txt | 2 +- 9 files changed, 97 insertions(+), 93 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index 2f2e53970b..a0be516bf9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -68,7 +68,7 @@ *
    9. sbe.keyword.append.token: Token to be appended to keywords.
    10. *
    11. sbe.decode.unknown.enum.values: Support unknown decoded enum values. Defaults to false.
    12. *
    13. sbe.xinclude.aware: Is XInclude supported for the schema. Defaults to false.
    14. - *
    15. sbe.type.package.override: Is a package attribute for types element supported (only for JAVA). Defaults to + *
    16. sbe.type.package.override: Is package attribute for types element supported (only for JAVA). Defaults to * false.
    17. * */ @@ -121,9 +121,9 @@ public class SbeTool /** * Boolean system property to control the support of package names in {@code } elements. - * Part of SBE v2-rc2. Defaults to false. + * Part of SBE v2-rc3. Defaults to false. */ - public static final String TYPE_PACKAGE_OVERRIDE = "sbe.type.package.override"; + public static final String TYPES_PACKAGE_OVERRIDE = "sbe.types.package.override"; /** * Target language for generated code. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 6f1e68f08c..2dade346dd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -52,7 +52,7 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) "true".equals(System.getProperty(JAVA_GROUP_ORDER_ANNOTATION)), "true".equals(System.getProperty(JAVA_GENERATE_INTERFACES)), "true".equals(System.getProperty(DECODE_UNKNOWN_ENUM_VALUES)), - "true".equals(System.getProperty(TYPE_PACKAGE_OVERRIDE)), + "true".equals(System.getProperty(TYPES_PACKAGE_OVERRIDE)), new JavaOutputManager(outputDir, ir.applicableNamespace())); } }, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index f8fa753d7f..f02cfc419d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -70,8 +70,8 @@ enum CodecType private final boolean shouldGenerateGroupOrderAnnotation; private final boolean shouldGenerateInterfaces; private final boolean shouldDecodeUnknownEnumValues; - private final boolean shouldSupportTypePackages; - private final Set typePackages = new HashSet<>(); + private final boolean shouldSupportTypesPackageNames; + private final Set packageNameByTypes = new HashSet<>(); /** * Create a new Java language {@link CodeGenerator}. Generator support for types in their own package is disabled. @@ -106,7 +106,7 @@ public JavaGenerator( * @param shouldGenerateGroupOrderAnnotation in the codecs. * @param shouldGenerateInterfaces for common methods. * @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding. - * @param shouldSupportTypePackages generator support for types in their own package + * @param shouldSupportTypesPackageNames generator support for types in their own package. * @param outputManager for generating the codecs to. */ public JavaGenerator( @@ -116,14 +116,14 @@ public JavaGenerator( final boolean shouldGenerateGroupOrderAnnotation, final boolean shouldGenerateInterfaces, final boolean shouldDecodeUnknownEnumValues, - final boolean shouldSupportTypePackages, + final boolean shouldSupportTypesPackageNames, final DynamicPackageOutputManager outputManager) { Verify.notNull(ir, "ir"); Verify.notNull(outputManager, "outputManager"); this.ir = ir; - this.shouldSupportTypePackages = shouldSupportTypePackages; + this.shouldSupportTypesPackageNames = shouldSupportTypesPackageNames; this.outputManager = outputManager; this.mutableBuffer = validateBufferImplementation(mutableBuffer, MutableDirectBuffer.class); @@ -176,18 +176,19 @@ public void generateTypeStubs() throws IOException } /** - * Register the the type's explicit package - if it's set and should be supported. + * Register the types explicit package - if it's set and should be supported. * - * @param token the 0-th token of the type - * @param ir the intermediate representation - * @return the overriden package name of the type if set and supported, or {@link Ir#applicableNamespace() } + * @param token the 0-th token of the type. + * @param ir the intermediate representation. + * @return the overridden package name of the type if set and supported, or {@link Ir#applicableNamespace()}. */ - private String registerTypePackage(final Token token, final Ir ir) + private String registerTypesPackageName(final Token token, final Ir ir) { - if (shouldSupportTypePackages && token.packageName() != null) + if (shouldSupportTypesPackageNames && token.packageName() != null) { - typePackages.add(token.packageName()); + packageNameByTypes.add(token.packageName()); outputManager.setPackageName(token.packageName()); + return token.packageName(); } return ir.applicableNamespace(); @@ -198,7 +199,7 @@ private String registerTypePackage(final Token token, final Ir ir) */ public void generate() throws IOException { - typePackages.clear(); + packageNameByTypes.clear(); generatePackageInfo(); generateTypeStubs(); generateMessageHeaderStub(); @@ -1238,7 +1239,7 @@ private void generateBitSet(final List tokens) throws IOException final List choiceList = tokens.subList(1, tokens.size() - 1); final String implementsString = implementsInterface(Flyweight.class.getSimpleName()); - registerTypePackage(token, ir); + registerTypesPackageName(token, ir); try (Writer out = outputManager.createOutput(decoderName)) { final Encoding encoding = token.encoding(); @@ -1259,7 +1260,7 @@ private void generateBitSet(final List tokens) throws IOException out.append("}\n"); } - registerTypePackage(token, ir); + registerTypesPackageName(token, ir); try (Writer out = outputManager.createOutput(encoderName)) { generateFixedFlyweightHeader(out, token, encoderName, implementsString, mutableBuffer, fqMutableBuffer); @@ -1277,7 +1278,7 @@ private void generateFixedFlyweightHeader( final String buffer, final String fqBuffer) throws IOException { - final String packageName = registerTypePackage(token, ir); + final String packageName = registerTypesPackageName(token, ir); out.append(generateFileHeader(packageName, fqBuffer)); out.append(generateDeclaration(typeName, implementsString, token)); out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer)); @@ -1291,7 +1292,7 @@ private void generateCompositeFlyweightHeader( final String fqBuffer, final String implementsString) throws IOException { - final String packageName = registerTypePackage(token, ir); + final String packageName = registerTypesPackageName(token, ir); out.append(generateFileHeader(packageName, fqBuffer)); out.append(generateDeclaration(typeName, implementsString, token)); out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer)); @@ -1304,7 +1305,7 @@ private void generateEnum(final List tokens) throws IOException final Encoding encoding = enumToken.encoding(); final String nullVal = encoding.applicableNullValue().toString(); - final String packageName = registerTypePackage(enumToken, ir); + final String packageName = registerTypesPackageName(enumToken, ir); try (Writer out = outputManager.createOutput(enumName)) { out.append(generateEnumFileHeader(packageName)); @@ -1327,7 +1328,7 @@ private void generateComposite(final List tokens) throws IOException final String decoderName = decoderName(compositeName); final String encoderName = encoderName(compositeName); - registerTypePackage(token, ir); + registerTypesPackageName(token, ir); try (Writer out = outputManager.createOutput(decoderName)) { final String implementsString = implementsInterface(CompositeDecoderFlyweight.class.getSimpleName()); @@ -1376,7 +1377,7 @@ private void generateComposite(final List tokens) throws IOException out.append("}\n"); } - registerTypePackage(token, ir); + registerTypesPackageName(token, ir); try (Writer out = outputManager.createOutput(encoderName)) { final String implementsString = implementsInterface(CompositeEncoderFlyweight.class.getSimpleName()); @@ -1629,8 +1630,8 @@ private CharSequence generateFileHeader(final String packageName, final String f private CharSequence generateMainHeader( final String packageName, final CodecType codecType, final boolean hasVarData) { - final StringBuffer packageImports = new StringBuffer(); - for (final String typePackage : typePackages) + final StringBuilder packageImports = new StringBuilder(); + for (final String typePackage : packageNameByTypes) { packageImports.append("import "); packageImports.append(typePackage); @@ -1644,7 +1645,7 @@ private CharSequence generateMainHeader( "package " + packageName + ";\n\n" + "import " + fqMutableBuffer + ";\n" + interfaceImportLine() + - packageImports.toString(); + packageImports; } else { @@ -1657,7 +1658,7 @@ private CharSequence generateMainHeader( (hasMutableBuffer ? "import " + fqMutableBuffer + ";\n" : "") + (hasReadOnlyBuffer ? "import " + fqReadOnlyBuffer + ";\n" : "") + interfaceImportLine() + - packageImports.toString(); + packageImports; } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java index 9dcd568c1f..9d34d89a81 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java @@ -15,34 +15,36 @@ */ package uk.co.real_logic.sbe.generation.java; -import java.io.FilterWriter; -import java.io.IOException; -import java.io.Writer; import org.agrona.collections.Object2NullableObjectHashMap; import org.agrona.collections.Object2ObjectHashMap; import org.agrona.generation.DynamicPackageOutputManager; import org.agrona.generation.PackageOutputManager; +import java.io.FilterWriter; +import java.io.IOException; +import java.io.Writer; + /** * Implementation of {@link DynamicPackageOutputManager} for Java. */ public class JavaOutputManager implements DynamicPackageOutputManager { private final String baseDirName; - private final PackageOutputManager basePackageOutputManager; + private final PackageOutputManager initialPackageOutputManager; private PackageOutputManager actingPackageOutputManager; - private final Object2ObjectHashMap outputManagerCache + private final Object2ObjectHashMap outputManagerByPackageName = new Object2NullableObjectHashMap<>(); /** * Constructor. + * * @param baseDirName the target directory * @param packageName the initial package name */ public JavaOutputManager(final String baseDirName, final String packageName) { - basePackageOutputManager = new PackageOutputManager(baseDirName, packageName); - actingPackageOutputManager = basePackageOutputManager; + initialPackageOutputManager = new PackageOutputManager(baseDirName, packageName); + actingPackageOutputManager = initialPackageOutputManager; this.baseDirName = baseDirName; } @@ -51,17 +53,17 @@ public JavaOutputManager(final String baseDirName, final String packageName) */ public void setPackageName(final String packageName) { - actingPackageOutputManager = outputManagerCache.get(packageName); + actingPackageOutputManager = outputManagerByPackageName.get(packageName); if (actingPackageOutputManager == null) { actingPackageOutputManager = new PackageOutputManager(baseDirName, packageName); - outputManagerCache.put(packageName, actingPackageOutputManager); + outputManagerByPackageName.put(packageName, actingPackageOutputManager); } } private void resetPackage() { - actingPackageOutputManager = basePackageOutputManager; + actingPackageOutputManager = initialPackageOutputManager; } /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index 3fdfb32674..7d42b02599 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -377,7 +377,7 @@ public static class Builder { private Signal signal; private String name; - private String packageName = null; + private String packageName; private String referencedName; private String description; private int id = INVALID_ID; @@ -413,7 +413,7 @@ public Builder name(final String name) } /** - * Package name for the Token. Default is null. Use for BEGIN_MESSAGE tokens for types that require an explicit + * Package name for the Token, default is null. Use for BEGIN_MESSAGE tokens for types that require an explicit * package. * * @param packageName for the Token. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index 064b5358e6..ca81a4edc3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -65,7 +65,7 @@ public EncodedDataType(final Node node) /** * Construct a new encodedDataType from XML Schema. * - * @param node from the XML Schema Parsing + * @param node from the XML Schema Parsing. * @param givenName for this node. * @param referencedName of the type when created from a ref in a composite. */ @@ -201,13 +201,13 @@ private PrimitiveValue lookupValueRef(final Node node) /** * Construct a new EncodedDataType with direct values. Does not handle constant values. * - * @param name of the type - * @param presence of the type - * @param description of the type or null - * @param semanticType of the type or null - * @param primitiveType of the EncodedDataType - * @param length of the EncodedDataType - * @param varLen of the EncodedDataType + * @param name of the type. + * @param presence of the type. + * @param description of the type or null. + * @param semanticType of the type or null. + * @param primitiveType of the EncodedDataType. + * @param length of the EncodedDataType. + * @param varLen of the EncodedDataType. */ public EncodedDataType( final String name, @@ -222,16 +222,16 @@ public EncodedDataType( } /** - * Construct a new EncodedDataType with direct values.Does not handle constant values. + * Construct a new EncodedDataType with direct values. Does not handle constant values. * - * @param name of the type - * @param packageName of the type - * @param presence of the type - * @param description of the type or null - * @param semanticType of the type or null - * @param primitiveType of the EncodedDataType - * @param length of the EncodedDataType - * @param varLen of the EncodedDataType + * @param name of the type. + * @param packageName of the type. + * @param presence of the type. + * @param description of the type or null. + * @param semanticType of the type or null. + * @param primitiveType of the EncodedDataType. + * @param length of the EncodedDataType. + * @param varLen of the EncodedDataType. */ public EncodedDataType( final String name, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java index dba276f95f..67a09d3152 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java @@ -40,7 +40,7 @@ public abstract class Type /** * Construct a new Type from XML Schema. Called by subclasses to mostly set common fields * - * @param node from the XML Schema Parsing + * @param node from the XML Schema Parsing. * @param givenName of this node, if null then the attributed name will be used. * @param referencedName of the type when created from a ref in a composite. */ @@ -68,12 +68,12 @@ public Type(final Node node, final String givenName, final String referencedName /** * Construct a new Type from direct values. * - * @param name of the type - * @param presence of the type - * @param description of the type or null - * @param sinceVersion for the type - * @param deprecated version in which this was deprecated. - * @param semanticType of the type or null + * @param name of the type. + * @param presence of the type. + * @param description of the type or null. + * @param sinceVersion for the type. + * @param deprecated version in which this was deprecated. + * @param semanticType of the type or null. */ public Type( final String name, @@ -89,13 +89,13 @@ public Type( /** * Construct a new Type from direct values. * - * @param name of the type - * @param packageName of the type - * @param presence of the type - * @param description of the type or null + * @param name of the type. + * @param packageName of the type. + * @param presence of the type. + * @param description of the type or null. * @param sinceVersion for the type - * @param deprecated version in which this was deprecated. - * @param semanticType of the type or null + * @param deprecated version in which this wa.s deprecated. + * @param semanticType of the type or null. */ public Type( final String name, @@ -118,9 +118,9 @@ public Type( } /** - * Return the name of the type + * The name of the type. * - * @return name of the Type + * @return name of the Type. */ public String name() { @@ -138,9 +138,9 @@ public String referencedName() } /** - * Return the presence of the type + * The {@link Presence} of the type. * - * @return presence of the Type + * @return {@link Presence} of the type. */ public Presence presence() { @@ -157,9 +157,9 @@ public Presence presence() public abstract int encodedLength(); /** - * The description of the Type (if set) or null + * The description of the Type (if set) or null. * - * @return description set by the type or null + * @return description set by the type or null. */ public String description() { @@ -197,9 +197,9 @@ public int deprecated() } /** - * The semanticType of the Type + * The FIX semanticType of the Type. * - * @return semanticType of the Type if set or null if not set + * @return FIX semanticType of the Type if set or null if not set. */ public String semanticType() { @@ -214,9 +214,9 @@ public String semanticType() public abstract boolean isVariableLength(); /** - * Return the offset attribute of the {@link Type} from the schema + * The offset attribute of the {@link Type} from the schema. * - * @return the offset attribute value or -1 to indicate not set by the schema + * @return the offset attribute value or -1 to indicate not set by the schema. */ public int offsetAttribute() { @@ -224,9 +224,9 @@ public int offsetAttribute() } /** - * Set the offset attribute of the {@link Type} from the schema + * Set the offset attribute of the {@link Type} from the schema. * - * @param offsetAttribute to set + * @param offsetAttribute to set. */ public void offsetAttribute(final int offsetAttribute) { @@ -234,9 +234,9 @@ public void offsetAttribute(final int offsetAttribute) } /** - * Return the packageName attribute of the {@link Type} from the schema + * The packageName attribute of the {@link Type} from the schema. * - * @return the packageName attribute value or null, if not explicitely defined by the schema + * @return the packageName attribute value or null, if not explicitly defined by the schema. */ public String packageName() { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java index 3bbd7e4fb9..97bab7f9ff 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java @@ -15,26 +15,27 @@ */ package uk.co.real_logic.sbe.generation.java; +import org.agrona.SystemUtil; +import org.junit.jupiter.api.Test; + import java.io.File; import java.io.IOException; import java.io.Writer; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; + import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; -public class JavaOutputManagerTest +class JavaOutputManagerTest { - - private final String tempDirName = System.getProperty("java.io.tmpdir"); - @Test void shouldCreateFileWithinPackage() throws Exception { final String packageName = "uk.co.real_logic.test"; final String exampleClassName = "ExampleClassName"; + final String tempDirName = SystemUtil.tmpDirName(); final JavaOutputManager cut = new JavaOutputManager(tempDirName, packageName); final Writer out = cut.createOutput(exampleClassName); out.close(); @@ -64,8 +65,9 @@ void shouldCreateFileWithinPackage() throws Exception private void assertFileExists(final String packageName, final String exampleClassName) throws IOException { - final String baseDirName = tempDirName.endsWith("" + File.separatorChar) ? tempDirName : tempDirName + - File.separatorChar; + final String tempDirName = SystemUtil.tmpDirName(); + final String baseDirName = tempDirName.endsWith("" + File.separatorChar) ? + tempDirName : tempDirName + File.separatorChar; final String fullyQualifiedFilename = baseDirName + packageName.replace('.', File.separatorChar) + File.separatorChar + exampleClassName + ".java"; @@ -76,5 +78,4 @@ private void assertFileExists(final String packageName, final String exampleClas assertTrue(exists); } - } diff --git a/version.txt b/version.txt index 28509b3918..8503140e97 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.26.1-SNAPSHOT +1.27.0-SNAPSHOT From ff5158ea475976a5a0efa0dd48059bfd9c370eaa Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 28 Sep 2022 09:30:53 +0100 Subject: [PATCH 0921/1594] [Java] Fix lookup of types ancestor for PR #904. --- .../real_logic/sbe/xml/XmlSchemaParser.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 455278d707..0d55ab1262 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -327,15 +327,26 @@ public static String getAttributeValue(final Node elementNode, final String attr } /** - * To be used with child elements of {@code } elements. Returns the package attribute as - * defined on the parent {@code } element + * To be used with descendant elements of {@code } elements. Returns the package attribute value as + * defined on the ancestor {@code } element. * - * @param elementNode the node inside the types element - * @return the package name, or null if not defined + * @param elementNode the node inside the {@code } element. + * @return the package name, or null if not defined. */ public static String getTypesPackageAttribute(final Node elementNode) { - return getAttributeValue(elementNode.getParentNode(), "package", null); + Node parentNode = elementNode.getParentNode(); + while (null != parentNode) + { + if ("types".equals(parentNode.getLocalName()) || "types".equals(parentNode.getNodeName())) + { + return getAttributeValue(parentNode, "package", null); + } + + parentNode = parentNode.getParentNode(); + } + + return null; } /** From cd883801045eede5120ac8ffae3bffc5793627c2 Mon Sep 17 00:00:00 2001 From: ratcash Date: Wed, 5 Oct 2022 18:22:06 +0200 Subject: [PATCH 0922/1594] Fix package name support for embedded composites (#915) * enhanced test case. * Bugfix: embedded composites were missing import for required types. * polish * use Collections.emptySet() * chain append statements * renamed method argument additionalPackages -> importedTypesPackages --- .../sbe/generation/java/JavaGenerator.java | 97 ++++++++++++++----- .../explicit-package-test-schema.xml | 18 ++++ 2 files changed, 92 insertions(+), 23 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index f02cfc419d..5977951e69 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.io.Writer; import java.util.ArrayList; +import java.util.Collections; import java.util.Formatter; import java.util.HashSet; import java.util.List; @@ -60,6 +61,7 @@ enum CodecType private static final String PACKAGE_INFO = "package-info"; private static final String BASE_INDENT = ""; private static final String INDENT = " "; + private static final Set NO_PACKAGES = Collections.emptySet(); private final Ir ir; private final DynamicPackageOutputManager outputManager; @@ -184,11 +186,15 @@ public void generateTypeStubs() throws IOException */ private String registerTypesPackageName(final Token token, final Ir ir) { - if (shouldSupportTypesPackageNames && token.packageName() != null) + + if (!shouldSupportTypesPackageNames) + { + return ir.applicableNamespace(); + } + if (token.packageName() != null) { packageNameByTypes.add(token.packageName()); outputManager.setPackageName(token.packageName()); - return token.packageName(); } return ir.applicableNamespace(); @@ -1243,7 +1249,8 @@ private void generateBitSet(final List tokens) throws IOException try (Writer out = outputManager.createOutput(decoderName)) { final Encoding encoding = token.encoding(); - generateFixedFlyweightHeader(out, token, decoderName, implementsString, readOnlyBuffer, fqReadOnlyBuffer); + generateFixedFlyweightHeader(out, token, decoderName, implementsString, readOnlyBuffer, fqReadOnlyBuffer, + NO_PACKAGES); out.append(generateChoiceIsEmpty(encoding.primitiveType())); new Formatter(out).format( @@ -1263,7 +1270,8 @@ private void generateBitSet(final List tokens) throws IOException registerTypesPackageName(token, ir); try (Writer out = outputManager.createOutput(encoderName)) { - generateFixedFlyweightHeader(out, token, encoderName, implementsString, mutableBuffer, fqMutableBuffer); + generateFixedFlyweightHeader(out, token, encoderName, implementsString, mutableBuffer, fqMutableBuffer, + NO_PACKAGES); generateChoiceClear(out, encoderName, token); generateChoiceEncoders(out, encoderName, choiceList); out.append("}\n"); @@ -1276,10 +1284,11 @@ private void generateFixedFlyweightHeader( final String typeName, final String implementsString, final String buffer, - final String fqBuffer) throws IOException + final String fqBuffer, + final Set importedTypesPackages) throws IOException { final String packageName = registerTypesPackageName(token, ir); - out.append(generateFileHeader(packageName, fqBuffer)); + out.append(generateFileHeader(packageName, importedTypesPackages, fqBuffer)); out.append(generateDeclaration(typeName, implementsString, token)); out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer)); } @@ -1290,10 +1299,11 @@ private void generateCompositeFlyweightHeader( final Writer out, final String buffer, final String fqBuffer, - final String implementsString) throws IOException + final String implementsString, + final Set importedTypesPackages) throws IOException { final String packageName = registerTypesPackageName(token, ir); - out.append(generateFileHeader(packageName, fqBuffer)); + out.append(generateFileHeader(packageName, importedTypesPackages, fqBuffer)); out.append(generateDeclaration(typeName, implementsString, token)); out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer)); } @@ -1329,11 +1339,12 @@ private void generateComposite(final List tokens) throws IOException final String encoderName = encoderName(compositeName); registerTypesPackageName(token, ir); + final Set importedTypesPackages = scanPackagesToImport(tokens); try (Writer out = outputManager.createOutput(decoderName)) { final String implementsString = implementsInterface(CompositeDecoderFlyweight.class.getSimpleName()); generateCompositeFlyweightHeader( - token, decoderName, out, readOnlyBuffer, fqReadOnlyBuffer, implementsString); + token, decoderName, out, readOnlyBuffer, fqReadOnlyBuffer, implementsString, importedTypesPackages); for (int i = 1, end = tokens.size() - 1; i < end;) { @@ -1381,7 +1392,8 @@ private void generateComposite(final List tokens) throws IOException try (Writer out = outputManager.createOutput(encoderName)) { final String implementsString = implementsInterface(CompositeEncoderFlyweight.class.getSimpleName()); - generateCompositeFlyweightHeader(token, encoderName, out, mutableBuffer, fqMutableBuffer, implementsString); + generateCompositeFlyweightHeader(token, encoderName, out, mutableBuffer, fqMutableBuffer, implementsString, + importedTypesPackages); for (int i = 1, end = tokens.size() - 1; i < end;) { @@ -1423,6 +1435,30 @@ private void generateComposite(final List tokens) throws IOException } } + private Set scanPackagesToImport(final List tokens) + { + if (!shouldSupportTypesPackageNames) + { + return NO_PACKAGES; + } + + final Set packagesToImport = new HashSet<>(); + for (int i = 1; i < tokens.size() - 1; i++) + { + final Token typeToken = tokens.get(i); + if (typeToken.signal() == Signal.BEGIN_ENUM || + typeToken.signal() == Signal.BEGIN_SET || + typeToken.signal() == Signal.BEGIN_COMPOSITE) + { + if (typeToken.packageName() != null) + { + packagesToImport.add(typeToken.packageName()); + } + } + } + return packagesToImport; + } + private void generateChoiceClear(final Appendable out, final String bitSetClassName, final Token token) throws IOException { @@ -1608,6 +1644,23 @@ private CharSequence generateEnumLookupMethod(final List tokens, final St return sb; } + private StringBuilder generateImportStatements(final Set packages, final String currentPackage) + { + final StringBuilder importsStatements = new StringBuilder(); + for (final String candidatePackage : packages) + { + if (!candidatePackage.equalsIgnoreCase(currentPackage)) + { + importsStatements.append("import ").append(candidatePackage).append(".*;\n"); + } + } + if (importsStatements.length() > 0) + { + importsStatements.append("\n\n"); + } + return importsStatements; + } + private String interfaceImportLine() { if (!shouldGenerateInterfaces) @@ -1618,25 +1671,23 @@ private String interfaceImportLine() return "import " + JAVA_INTERFACE_PACKAGE + ".*;\n\n"; } - private CharSequence generateFileHeader(final String packageName, final String fqBuffer) + + private CharSequence generateFileHeader(final String packageName, final Set importedTypesPackages, + final String fqBuffer) { - return - "/* Generated SBE (Simple Binary Encoding) message codec. */\n" + + final StringBuilder importStatements = generateImportStatements(importedTypesPackages, packageName); + + return "/* Generated SBE (Simple Binary Encoding) message codec. */\n" + "package " + packageName + ";\n\n" + "import " + fqBuffer + ";\n" + - interfaceImportLine(); + interfaceImportLine() + + importStatements; } private CharSequence generateMainHeader( final String packageName, final CodecType codecType, final boolean hasVarData) { - final StringBuilder packageImports = new StringBuilder(); - for (final String typePackage : packageNameByTypes) - { - packageImports.append("import "); - packageImports.append(typePackage); - packageImports.append(".*;\n"); - } + final StringBuilder importStatements = generateImportStatements(packageNameByTypes, packageName); if (fqMutableBuffer.equals(fqReadOnlyBuffer)) { @@ -1645,7 +1696,7 @@ private CharSequence generateMainHeader( "package " + packageName + ";\n\n" + "import " + fqMutableBuffer + ";\n" + interfaceImportLine() + - packageImports; + importStatements; } else { @@ -1658,7 +1709,7 @@ private CharSequence generateMainHeader( (hasMutableBuffer ? "import " + fqMutableBuffer + ";\n" : "") + (hasReadOnlyBuffer ? "import " + fqReadOnlyBuffer + ";\n" : "") + interfaceImportLine() + - packageImports; + importStatements; } } diff --git a/sbe-tool/src/test/resources/explicit-package-test-schema.xml b/sbe-tool/src/test/resources/explicit-package-test-schema.xml index a0e02791b1..fc3aaf6929 100644 --- a/sbe-tool/src/test/resources/explicit-package-test-schema.xml +++ b/sbe-tool/src/test/resources/explicit-package-test-schema.xml @@ -18,6 +18,13 @@ + + + + + + + @@ -25,6 +32,10 @@ 0 1 + + + + 0 1 @@ -34,6 +45,13 @@ 5 6 + + 1 + 2 + 3 + 4 + 5 + From e46a5e78f889d7f2487d12371fb37ac0d8bfcaf8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 5 Oct 2022 17:34:35 +0100 Subject: [PATCH 0923/1594] [Java] Tidy up after merge of PR #915. --- .../sbe/generation/java/JavaGenerator.java | 58 +++++++++---------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 5977951e69..9a7cef4b48 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -61,7 +61,7 @@ enum CodecType private static final String PACKAGE_INFO = "package-info"; private static final String BASE_INDENT = ""; private static final String INDENT = " "; - private static final Set NO_PACKAGES = Collections.emptySet(); + private static final Set PACKAGES_EMPTY_SET = Collections.emptySet(); private final Ir ir; private final DynamicPackageOutputManager outputManager; @@ -178,7 +178,7 @@ public void generateTypeStubs() throws IOException } /** - * Register the types explicit package - if it's set and should be supported. + * Register the types explicit package - if set and should be supported. * * @param token the 0-th token of the type. * @param ir the intermediate representation. @@ -186,17 +186,18 @@ public void generateTypeStubs() throws IOException */ private String registerTypesPackageName(final Token token, final Ir ir) { - if (!shouldSupportTypesPackageNames) { return ir.applicableNamespace(); } + if (token.packageName() != null) { packageNameByTypes.add(token.packageName()); outputManager.setPackageName(token.packageName()); return token.packageName(); } + return ir.applicableNamespace(); } @@ -1249,8 +1250,8 @@ private void generateBitSet(final List tokens) throws IOException try (Writer out = outputManager.createOutput(decoderName)) { final Encoding encoding = token.encoding(); - generateFixedFlyweightHeader(out, token, decoderName, implementsString, readOnlyBuffer, fqReadOnlyBuffer, - NO_PACKAGES); + generateFixedFlyweightHeader( + out, token, decoderName, implementsString, readOnlyBuffer, fqReadOnlyBuffer, PACKAGES_EMPTY_SET); out.append(generateChoiceIsEmpty(encoding.primitiveType())); new Formatter(out).format( @@ -1270,8 +1271,8 @@ private void generateBitSet(final List tokens) throws IOException registerTypesPackageName(token, ir); try (Writer out = outputManager.createOutput(encoderName)) { - generateFixedFlyweightHeader(out, token, encoderName, implementsString, mutableBuffer, fqMutableBuffer, - NO_PACKAGES); + generateFixedFlyweightHeader( + out, token, encoderName, implementsString, mutableBuffer, fqMutableBuffer, PACKAGES_EMPTY_SET); generateChoiceClear(out, encoderName, token); generateChoiceEncoders(out, encoderName, choiceList); out.append("}\n"); @@ -1287,8 +1288,7 @@ private void generateFixedFlyweightHeader( final String fqBuffer, final Set importedTypesPackages) throws IOException { - final String packageName = registerTypesPackageName(token, ir); - out.append(generateFileHeader(packageName, importedTypesPackages, fqBuffer)); + out.append(generateFileHeader(registerTypesPackageName(token, ir), importedTypesPackages, fqBuffer)); out.append(generateDeclaration(typeName, implementsString, token)); out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer)); } @@ -1302,8 +1302,7 @@ private void generateCompositeFlyweightHeader( final String implementsString, final Set importedTypesPackages) throws IOException { - final String packageName = registerTypesPackageName(token, ir); - out.append(generateFileHeader(packageName, importedTypesPackages, fqBuffer)); + out.append(generateFileHeader(registerTypesPackageName(token, ir), importedTypesPackages, fqBuffer)); out.append(generateDeclaration(typeName, implementsString, token)); out.append(generateFixedFlyweightCode(typeName, token.encodedLength(), buffer)); } @@ -1314,8 +1313,8 @@ private void generateEnum(final List tokens) throws IOException final String enumName = formatClassName(enumToken.applicableTypeName()); final Encoding encoding = enumToken.encoding(); final String nullVal = encoding.applicableNullValue().toString(); - final String packageName = registerTypesPackageName(enumToken, ir); + try (Writer out = outputManager.createOutput(enumName)) { out.append(generateEnumFileHeader(packageName)); @@ -1340,6 +1339,7 @@ private void generateComposite(final List tokens) throws IOException registerTypesPackageName(token, ir); final Set importedTypesPackages = scanPackagesToImport(tokens); + try (Writer out = outputManager.createOutput(decoderName)) { final String implementsString = implementsInterface(CompositeDecoderFlyweight.class.getSimpleName()); @@ -1392,8 +1392,8 @@ private void generateComposite(final List tokens) throws IOException try (Writer out = outputManager.createOutput(encoderName)) { final String implementsString = implementsInterface(CompositeEncoderFlyweight.class.getSimpleName()); - generateCompositeFlyweightHeader(token, encoderName, out, mutableBuffer, fqMutableBuffer, implementsString, - importedTypesPackages); + generateCompositeFlyweightHeader( + token, encoderName, out, mutableBuffer, fqMutableBuffer, implementsString, importedTypesPackages); for (int i = 1, end = tokens.size() - 1; i < end;) { @@ -1439,11 +1439,12 @@ private Set scanPackagesToImport(final List tokens) { if (!shouldSupportTypesPackageNames) { - return NO_PACKAGES; + return PACKAGES_EMPTY_SET; } final Set packagesToImport = new HashSet<>(); - for (int i = 1; i < tokens.size() - 1; i++) + + for (int i = 1, limit = tokens.size() - 1; i < limit; i++) { final Token typeToken = tokens.get(i); if (typeToken.signal() == Signal.BEGIN_ENUM || @@ -1456,6 +1457,7 @@ private Set scanPackagesToImport(final List tokens) } } } + return packagesToImport; } @@ -1646,19 +1648,22 @@ private CharSequence generateEnumLookupMethod(final List tokens, final St private StringBuilder generateImportStatements(final Set packages, final String currentPackage) { - final StringBuilder importsStatements = new StringBuilder(); + final StringBuilder importStatements = new StringBuilder(); + for (final String candidatePackage : packages) { - if (!candidatePackage.equalsIgnoreCase(currentPackage)) + if (!candidatePackage.equals(currentPackage)) { - importsStatements.append("import ").append(candidatePackage).append(".*;\n"); + importStatements.append("import ").append(candidatePackage).append(".*;\n"); } } - if (importsStatements.length() > 0) + + if (importStatements.length() > 0) { - importsStatements.append("\n\n"); + importStatements.append("\n\n"); } - return importsStatements; + + return importStatements; } private String interfaceImportLine() @@ -3878,13 +3883,6 @@ private String decoderName(final String className) private String implementsInterface(final String interfaceName) { - if (!shouldGenerateInterfaces) - { - return ""; - } - else - { - return " implements " + interfaceName; - } + return shouldGenerateInterfaces ? " implements " + interfaceName : ""; } } From 4fc4462e52fbeb48410625e05197df1175fd9f76 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 6 Oct 2022 09:24:41 +0100 Subject: [PATCH 0924/1594] [Java] Remove broken works with OpenJDK link. --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index 98f247b51d..bc0984add5 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,6 @@ Simple Binary Encoding (SBE) ============================ -
      - - - [![Javadocs](https://www.javadoc.io/badge/uk.co.real-logic/sbe-tool.svg)](https://www.javadoc.io/doc/uk.co.real-logic/sbe-tool) [![GitHub](https://img.shields.io/github/license/real-logic/simple-binary-encoding.svg)](https://github.com/real-logic/simple-binary-encoding/blob/master/LICENSE) From 93dbe85643a11c51cf3d29fff951e7f3b5b478a6 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 11 Oct 2022 08:49:06 -0700 Subject: [PATCH 0925/1594] 1.27.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 8503140e97..5db08bf2dc 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.27.0-SNAPSHOT +1.27.0 From bb199949aab31e9b172950ab7666b980d8a3b947 Mon Sep 17 00:00:00 2001 From: "Todd L. Montgomery" Date: Tue, 11 Oct 2022 08:49:56 -0700 Subject: [PATCH 0926/1594] post release bump. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 5db08bf2dc..f9aacd1c13 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.27.0 +1.27.1-SNAPSHOT From 100cb64062557a2419268f04a6b8421f81eaf9a9 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 18 Oct 2022 09:26:27 +0100 Subject: [PATCH 0927/1594] [Java] Upgrade to Version 0.43.0 and Mockito 4.8.1. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 2e864a76b5..2c87d894bd 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ import java.security.MessageDigest plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '7.1.2' apply false - id "com.github.ben-manes.versions" version "0.42.0" + id "com.github.ben-manes.versions" version "0.43.0" } defaultTasks 'clean', 'build' @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' -def mockitoVersion = '4.8.0' +def mockitoVersion = '4.8.1' def junitVersion = '5.9.1' def jmhVersion = '1.35' def agronaVersion = '1.17.1' From 4a33a5d6e2c0a7eadda787130d7e12a6f71b65ea Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Thu, 3 Nov 2022 09:01:31 +1300 Subject: [PATCH 0928/1594] [Java] Correctly print warnings for undersize header fields. --- .../co/real_logic/sbe/xml/MessageSchema.java | 29 +++++++++-- .../real_logic/sbe/xml/XmlSchemaParser.java | 8 ++- .../java/WarningFormattingTest.java | 50 +++++++++++++++++++ .../src/test/resources/npe-small-header.xml | 23 +++++++++ 4 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java create mode 100644 sbe-tool/src/test/resources/npe-small-header.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index 38a168f1c0..f9757a1ed8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -18,10 +18,19 @@ import org.agrona.Verify; import org.w3c.dom.Node; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; import java.nio.ByteOrder; -import java.util.*; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Deque; +import java.util.List; +import java.util.Map; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.*; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.getAttributeValue; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.getAttributeValueOrNull; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.getByteOrder; /** * Message schema aggregate for schema attributes, messageHeader, and reference for multiple {@link Message} objects. @@ -59,7 +68,8 @@ public class MessageSchema this.headerType = null == headerType ? HEADER_TYPE_DEFAULT : headerType; Verify.present(typeByNameMap, this.headerType, "Message header"); - ((CompositeType)typeByNameMap.get(this.headerType)).checkForWellFormedMessageHeader(schemaNode); + final Node messageHeaderNode = findNode(schemaNode, "types/composite[@name='" + this.headerType + "']"); + ((CompositeType)typeByNameMap.get(this.headerType)).checkForWellFormedMessageHeader(messageHeaderNode); } MessageSchema( @@ -353,4 +363,17 @@ private void reportError( errorHandler.error(sb.toString()); } + + private static Node findNode(final Node contextNode, final String path) + { + try + { + return (Node)XPathFactory.newInstance().newXPath() + .evaluate(path, contextNode, XPathConstants.NODE); + } + catch (final XPathExpressionException e) + { + throw new IllegalArgumentException("Unable to locate node with path=" + path, e); + } + } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 0d55ab1262..3705fc491e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -363,7 +363,13 @@ public static String getAttributeValueOrNull(final Node elementNode, final Strin return null; } - final Node attrNode = elementNode.getAttributes().getNamedItemNS(null, attrName); + final NamedNodeMap attributes = elementNode.getAttributes(); +// if (null == attributes) +// { +// return null; +// } + + final Node attrNode = attributes.getNamedItemNS(null, attrName); if (null == attrNode) { return null; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java new file mode 100644 index 0000000000..38b0e83d31 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2022 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static uk.co.real_logic.sbe.Tests.getLocalResource; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +public class WarningFormattingTest +{ + @Test + void shouldGenerateCorrectWarning() throws Exception + { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final ParserOptions options = new ParserOptions.Builder().errorPrintStream(new PrintStream(out)).build(); + final MessageSchema schema = parse(getLocalResource("npe-small-header.xml"), options); + final IrGenerator irg = new IrGenerator(); + irg.generate(schema); + + final String warnings = out.toString(StandardCharsets.US_ASCII.name()); + assertTrue(warnings.contains( + "WARNING: at \"blockLength\" should be UINT16")); + assertTrue(warnings.contains( + "WARNING: at \"templateId\" should be UINT16")); + assertTrue(warnings.contains( + "WARNING: at \"version\" should be UINT16")); + } +} diff --git a/sbe-tool/src/test/resources/npe-small-header.xml b/sbe-tool/src/test/resources/npe-small-header.xml new file mode 100644 index 0000000000..96ade65735 --- /dev/null +++ b/sbe-tool/src/test/resources/npe-small-header.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + \ No newline at end of file From 224bce368ff5f51dfad5a23bd6605cefe60f0c8e Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Thu, 3 Nov 2022 14:51:26 +1300 Subject: [PATCH 0929/1594] [Java] Restore belt and braces null check. --- .../java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 3705fc491e..1ad8ac15f3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -364,10 +364,10 @@ public static String getAttributeValueOrNull(final Node elementNode, final Strin } final NamedNodeMap attributes = elementNode.getAttributes(); -// if (null == attributes) -// { -// return null; -// } + if (null == attributes) + { + return null; + } final Node attrNode = attributes.getNamedItemNS(null, attrName); if (null == attrNode) From 80c130f398e6f79c4ff1b33ee79955e86131d30a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 3 Nov 2022 17:35:39 +0000 Subject: [PATCH 0930/1594] [Java] Tidy up handling of reporting warnings on non-standard header and replace use of String.format. --- .../co/real_logic/sbe/xml/CompositeType.java | 53 ++++++++----------- .../co/real_logic/sbe/xml/MessageSchema.java | 7 ++- .../real_logic/sbe/xml/XmlSchemaParser.java | 10 ++-- .../java/WarningFormattingTest.java | 16 +++--- .../src/test/resources/npe-small-header.xml | 23 ++++---- 5 files changed, 54 insertions(+), 55 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index 667da499dc..037c01c8c8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -195,9 +195,9 @@ else if (!isUnsigned(numInGroupType.primitiveType())) } else if (numInGroupMinValue.longValue() < 0) { - XmlSchemaParser.handleError(node, String.format( - "\"numInGroup\" minValue=%s must be greater than zero " + - "for signed \"numInGroup\" types", numInGroupMinValue)); + XmlSchemaParser.handleError(node, + "\"numInGroup\" minValue=" + numInGroupMinValue + " must be greater than zero " + + "for signed \"numInGroup\" types"); } } else @@ -218,8 +218,8 @@ else if (numInGroupMinValue.longValue() < 0) if (numInGroupMinValue.longValue() > max) { - XmlSchemaParser.handleError(node, String.format( - "\"numInGroup\" minValue=%s greater than maxValue=%d", numInGroupMinValue, max)); + XmlSchemaParser.handleError( + node, "\"numInGroup\" minValue=" + numInGroupMinValue + " greater than maxValue=" + max); } } } @@ -275,22 +275,22 @@ private static void validateGroupMaxValue( final long allowedValue = primitiveType.maxValue().longValue(); if (longValue > allowedValue) { - XmlSchemaParser.handleError(node, String.format( - "maxValue greater than allowed for type: maxValue=%d allowed=%d", longValue, allowedValue)); + XmlSchemaParser.handleError( + node, "maxValue greater than allowed for type: maxValue=" + longValue + " allowed=" + allowedValue); } final long maxInt = INT32.maxValue().longValue(); if (primitiveType == UINT32 && longValue > maxInt) { - XmlSchemaParser.handleError(node, String.format( - "maxValue greater than allowed for type: maxValue=%d allowed=%d", longValue, maxInt)); + XmlSchemaParser.handleError( + node, "maxValue greater than allowed for type: maxValue=" + longValue + " allowed=" + maxInt); } } else if (primitiveType == UINT32) { final long maxInt = INT32.maxValue().longValue(); - XmlSchemaParser.handleError(node, String.format( - "maxValue must be set for varData UINT32 type: max value allowed=%d", maxInt)); + XmlSchemaParser.handleError( + node, "maxValue must be set for varData UINT32 type: max value allowed=" + maxInt); } } @@ -333,33 +333,25 @@ private void validateHeaderField( { if (actualType == null) { - XmlSchemaParser.handleError( - node, - String.format("composite for message header must have \"%s\"", fieldName)); + XmlSchemaParser.handleError(node, "composite for message header must have \"" + fieldName + "\""); } else if (actualType.primitiveType() != expectedType) { - XmlSchemaParser.handleWarning(node, String.format("\"%s\" should be %s", fieldName, expectedType.name())); + XmlSchemaParser.handleWarning(node, "\"" + fieldName + "\" should be " + expectedType.name()); if (shouldGenerateInterfaces) { if (actualType.primitiveType().size() > expectedType.size()) { - XmlSchemaParser.handleError( - node, - String.format("\"%s\" must be less than %s bytes to use %s", - fieldName, - expectedType.size(), - JAVA_GENERATE_INTERFACES)); + final String msg = "\"" + fieldName + "\" must be less than " + expectedType.size() + + " bytes to use " + JAVA_GENERATE_INTERFACES; + XmlSchemaParser.handleError(node, msg); } else { - XmlSchemaParser.handleWarning( - node, - String.format("\"%s\" will be cast to %s to use %s", - fieldName, - expectedType.name(), - JAVA_GENERATE_INTERFACES)); + final String msg = "\"" + fieldName + "\" will be cast to " + expectedType.name() + + " to use " + JAVA_GENERATE_INTERFACES; + XmlSchemaParser.handleWarning(node, msg); } } } @@ -383,8 +375,7 @@ public void checkForValidOffsets(final Node node) if (offsetAttribute < offset) { XmlSchemaParser.handleError( - node, - String.format("composite element \"%s\" has incorrect offset specified", edt.name())); + node, "composite element \"" + edt.name() + "\" has incorrect offset specified"); } offset = offsetAttribute; @@ -434,8 +425,8 @@ private Type processType( { final XPath xPath = XPathFactory.newInstance().newXPath(); final String refTypeName = XmlSchemaParser.getAttributeValue(subTypeNode, "type"); - final Node refTypeNode = (Node)xPath.compile( - "/*[local-name() = 'messageSchema']/types/*[@name='" + refTypeName + "']") + final String expression = "/*[local-name() = 'messageSchema']/types/*[@name='" + refTypeName + "']"; + final Node refTypeNode = (Node)xPath.compile(expression) .evaluate(subTypeNode.getOwnerDocument(), XPathConstants.NODE); if (refTypeNode == null) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index f9757a1ed8..77be002e95 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -52,8 +52,7 @@ public class MessageSchema private final Map typeByNameMap; private final Map messageByIdMap; - MessageSchema( - final Node schemaNode, final Map typeByNameMap, final Map messageByIdMap) + MessageSchema(final Node schemaNode, final Map typeByNameMap, final Map messageByIdMap) { this.packageName = getAttributeValue(schemaNode, "package"); this.description = getAttributeValueOrNull(schemaNode, "description"); @@ -371,9 +370,9 @@ private static Node findNode(final Node contextNode, final String path) return (Node)XPathFactory.newInstance().newXPath() .evaluate(path, contextNode, XPathConstants.NODE); } - catch (final XPathExpressionException e) + catch (final XPathExpressionException ex) { - throw new IllegalArgumentException("Unable to locate node with path=" + path, e); + throw new IllegalArgumentException("Unable to locate node with path=" + path, ex); } } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 1ad8ac15f3..c2d4312af1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -176,9 +176,10 @@ public static MessageSchema parse(final InputStream in, final ParserOptions opti * @param document for the XML parsing. * @param xPath for XPath expression reuse. * @return {@link java.util.Map} of name {@link java.lang.String} to {@link Type}. - * @throws Exception on parsing error. + * @throws XPathExpressionException on parsing error. */ - public static Map findTypes(final Document document, final XPath xPath) throws Exception + public static Map findTypes(final Document document, final XPath xPath) + throws XPathExpressionException { final Map typeByNameMap = new HashMap<>(); @@ -216,10 +217,11 @@ public static Map findTypes(final Document document, final XPath x * @param xPath for XPath expression reuse. * @param typeByNameMap to use for Type objects. * @return {@link java.util.Map} of schemaId to {@link Message}. - * @throws Exception on parsing error. + * @throws XPathExpressionException on parsing error. */ public static Map findMessages( - final Document document, final XPath xPath, final Map typeByNameMap) throws Exception + final Document document, final XPath xPath, final Map typeByNameMap) + throws XPathExpressionException { final Map messageByIdMap = new HashMap<>(); final ObjectHashSet distinctNames = new ObjectHashSet<>(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java index 38b0e83d31..def80db067 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java @@ -24,27 +24,31 @@ import java.io.PrintStream; import java.nio.charset.StandardCharsets; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class WarningFormattingTest +class WarningFormattingTest { @Test void shouldGenerateCorrectWarning() throws Exception { final ByteArrayOutputStream out = new ByteArrayOutputStream(); - final ParserOptions options = new ParserOptions.Builder().errorPrintStream(new PrintStream(out)).build(); + final ParserOptions options = new ParserOptions.Builder() + .stopOnError(true) + .errorPrintStream(new PrintStream(out)) + .build(); final MessageSchema schema = parse(getLocalResource("npe-small-header.xml"), options); final IrGenerator irg = new IrGenerator(); irg.generate(schema); final String warnings = out.toString(StandardCharsets.US_ASCII.name()); - assertTrue(warnings.contains( + assertThat(warnings, containsString( "WARNING: at \"blockLength\" should be UINT16")); - assertTrue(warnings.contains( + assertThat(warnings, containsString( "WARNING: at \"templateId\" should be UINT16")); - assertTrue(warnings.contains( + assertThat(warnings, containsString( "WARNING: at \"version\" should be UINT16")); } } diff --git a/sbe-tool/src/test/resources/npe-small-header.xml b/sbe-tool/src/test/resources/npe-small-header.xml index 96ade65735..07a4fb277e 100644 --- a/sbe-tool/src/test/resources/npe-small-header.xml +++ b/sbe-tool/src/test/resources/npe-small-header.xml @@ -7,16 +7,19 @@ description="Message format for XXXXXX" byteOrder="littleEndian"> - - - - - - - - + + + + + + + From afdac25369db273ec9ba3762f1039e0f8936c9b8 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Fri, 4 Nov 2022 09:53:38 +1300 Subject: [PATCH 0931/1594] [Java] Formatting fixes. --- .../uk/co/real_logic/sbe/xml/XmlSchemaParser.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index c2d4312af1..8b95df9ff2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -195,16 +195,20 @@ public static Map findTypes(final Document document, final XPath x typeByNameMap.put("float", new EncodedDataType("float", REQUIRED, null, null, FLOAT, 1, false)); typeByNameMap.put("double", new EncodedDataType("double", REQUIRED, null, null, DOUBLE, 1, false)); - forEach((NodeList)xPath.compile(TYPE_XPATH_EXPR).evaluate(document, XPathConstants.NODESET), + forEach( + (NodeList)xPath.compile(TYPE_XPATH_EXPR).evaluate(document, XPathConstants.NODESET), (node) -> addTypeWithNameCheck(typeByNameMap, new EncodedDataType(node), node)); - forEach((NodeList)xPath.compile(COMPOSITE_XPATH_EXPR).evaluate(document, XPathConstants.NODESET), + forEach( + (NodeList)xPath.compile(COMPOSITE_XPATH_EXPR).evaluate(document, XPathConstants.NODESET), (node) -> addTypeWithNameCheck(typeByNameMap, new CompositeType(node), node)); - forEach((NodeList)xPath.compile(ENUM_XPATH_EXPR).evaluate(document, XPathConstants.NODESET), + forEach( + (NodeList)xPath.compile(ENUM_XPATH_EXPR).evaluate(document, XPathConstants.NODESET), (node) -> addTypeWithNameCheck(typeByNameMap, new EnumType(node), node)); - forEach((NodeList)xPath.compile(SET_XPATH_EXPR).evaluate(document, XPathConstants.NODESET), + forEach( + (NodeList)xPath.compile(SET_XPATH_EXPR).evaluate(document, XPathConstants.NODESET), (node) -> addTypeWithNameCheck(typeByNameMap, new SetType(node), node)); return typeByNameMap; @@ -226,7 +230,8 @@ public static Map findMessages( final Map messageByIdMap = new HashMap<>(); final ObjectHashSet distinctNames = new ObjectHashSet<>(); - forEach((NodeList)xPath.compile(MESSAGE_XPATH_EXPR).evaluate(document, XPathConstants.NODESET), + forEach( + (NodeList)xPath.compile(MESSAGE_XPATH_EXPR).evaluate(document, XPathConstants.NODESET), (node) -> addMessageWithIdCheck(distinctNames, messageByIdMap, new Message(node, typeByNameMap), node)); if (messageByIdMap.isEmpty()) From cb98b5e828161000c73d715ce461eca21adb57f1 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Fri, 4 Nov 2022 10:03:57 +1300 Subject: [PATCH 0932/1594] [Java] Prevent clashing defines in C/C++ codecs when multiple generated schemas are used. #884. --- .../main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 39e521a360..de8d3519eb 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1131,7 +1131,7 @@ private static CharSequence generateFileHeader(final String structName, final Li " #define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)\n" + "#elif defined(_MSC_VER)\n" + " #define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)\n" + - "#else\n" + + "#elif !defined(SBE_BOUNDS_CHECK_EXPECT)\n" + " #define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))\n" + "#endif\n\n" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 95151c7106..1235fc1cc8 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1126,7 +1126,7 @@ private static CharSequence generateFileHeader( "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (false)\n" + "#elif defined(_MSC_VER)\n" + "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (exp)\n" + - "#else\n" + + "#elif !defined(SBE_BOUNDS_CHECK_EXPECT)\n" + "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (__builtin_expect(exp, c))\n" + "#endif\n\n" + From 953f137527d6f4db870d804e3fc4c28a8cee9857 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Thu, 3 Nov 2022 21:34:09 -1100 Subject: [PATCH 0933/1594] [Java] Move check for existing SBE_BOUNDS_CHECK_EXPECT define to outer condition to capture all platforms. --- .../co/real_logic/sbe/generation/c/CGenerator.java | 14 ++++++++------ .../sbe/generation/cpp/CppGenerator.java | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index de8d3519eb..f82eec476c 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1127,12 +1127,14 @@ private static CharSequence generateFileHeader(final String structName, final Li " Set __BYTE_ORDER__ manually before including this file.\"\n" + "#endif\n\n" + - "#if defined(SBE_NO_BOUNDS_CHECK)\n" + - " #define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)\n" + - "#elif defined(_MSC_VER)\n" + - " #define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)\n" + - "#elif !defined(SBE_BOUNDS_CHECK_EXPECT)\n" + - " #define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))\n" + + "#if !defined(SBE_BOUNDS_CHECK_EXPECT)\n" + + "# if defined(SBE_NO_BOUNDS_CHECK)\n" + + "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (false)\n" + + "# elif defined(_MSC_VER)\n" + + "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (exp)\n" + + "# else \n" + + "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (__builtin_expect(exp, c))\n" + + "# endif\n\n" + "#endif\n\n" + "#define SBE_NULLVALUE_INT8 INT8_MIN\n" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 1235fc1cc8..81b8da29d7 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1122,12 +1122,14 @@ private static CharSequence generateFileHeader( "Set __BYTE_ORDER__ manually before including this file.\"\n" + "#endif\n\n" + - "#if defined(SBE_NO_BOUNDS_CHECK)\n" + - "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (false)\n" + - "#elif defined(_MSC_VER)\n" + - "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (exp)\n" + - "#elif !defined(SBE_BOUNDS_CHECK_EXPECT)\n" + - "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (__builtin_expect(exp, c))\n" + + "#if !defined(SBE_BOUNDS_CHECK_EXPECT)\n" + + "# if defined(SBE_NO_BOUNDS_CHECK)\n" + + "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (false)\n" + + "# elif defined(_MSC_VER)\n" + + "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (exp)\n" + + "# else \n" + + "# define SBE_BOUNDS_CHECK_EXPECT(exp, c) (__builtin_expect(exp, c))\n" + + "# endif\n\n" + "#endif\n\n" + "#define SBE_NULLVALUE_INT8 (std::numeric_limits::min)()\n" + From fc609e2192bd539f5a5f0bf2d31444c73524dc5b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 18 Nov 2022 08:47:35 +0000 Subject: [PATCH 0934/1594] [Java] Upgrade to Version 0.44.0, Mockito 4.9.0, and JMH 1.36. --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 2c87d894bd..a0abfae24d 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ import java.security.MessageDigest plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '7.1.2' apply false - id "com.github.ben-manes.versions" version "0.43.0" + id "com.github.ben-manes.versions" version "0.44.0" } defaultTasks 'clean', 'build' @@ -44,9 +44,9 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' -def mockitoVersion = '4.8.1' +def mockitoVersion = '4.9.0' def junitVersion = '5.9.1' -def jmhVersion = '1.35' +def jmhVersion = '1.36' def agronaVersion = '1.17.1' def agronaVersionRange = '[1.17.1,2.0[' // allow any release >= 1.17.1 and < 2.0.0 From 9f679d4f6f2a0156369e2c80a5bcbf20d6df8135 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Wed, 30 Nov 2022 16:12:06 +1300 Subject: [PATCH 0935/1594] [Gradle] Upgrade to 7.6. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index a0abfae24d..abc3c3974d 100644 --- a/build.gradle +++ b/build.gradle @@ -822,7 +822,7 @@ tasks.named('dependencyUpdates').configure { tasks.findByName('build').dependsOn verifyJavaIrCodecsInSync wrapper { - gradleVersion = '7.5.1' + gradleVersion = '7.6' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8fad3f5a98..f42e62f372 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From c8d39eaa4475e59bfc6be54851b8c81ba41a9584 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 30 Nov 2022 10:23:20 +0100 Subject: [PATCH 0936/1594] [Gradle] Re-run `./gradlew wrapper` to regenerate scripts. --- gradle/wrapper/gradle-wrapper.jar | Bin 60756 -> 61574 bytes gradle/wrapper/gradle-wrapper.properties | 1 + gradlew | 12 ++++++++---- gradlew.bat | 1 + 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 249e5832f090a2944b7473328c07c9755baa3196..943f0cbfa754578e88a3dae77fce6e3dea56edbf 100644 GIT binary patch delta 36524 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%0DGK?7GHTj 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 VwlMN}`%er%aGR6olj~j${vQ;P=LY}) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f42e62f372..2b22d057a0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index a69d9cb6c2..65dcd68d65 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,10 +80,10 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' @@ -143,12 +143,16 @@ fi if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac diff --git a/gradlew.bat b/gradlew.bat index f127cfd49d..93e3f59f13 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% From 7cd146e65731734fd0cd037d6ae095078ca4a6b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mu=C3=B1oz?= Date: Fri, 2 Dec 2022 11:11:26 +0100 Subject: [PATCH 0937/1594] Add CodeQL workflow --- .github/workflows/codeql.yml | 181 +++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..0fdf5f35a4 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,181 @@ +name: "CodeQL" + +on: + push: + branches: [ 'master' ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ 'master' ] + schedule: + - cron: '16 7 * * 3' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail' + CMAKE_VERSION: '3.14.7' + +permissions: + contents: read + +jobs: + + java-analyze: + name: Java Analyze ${{ matrix.java }} + runs-on: ubuntu-22.04 + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + java: [ '8' ] + + steps: + - name: Checkout code + uses: actions/checkout@v3 + - name: Cache Gradle dependencies + uses: actions/cache@v3 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v3 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + - name: Setup java + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: ${{ matrix.java }} + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + + - name: Build with Gradle + run: ./gradlew + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" + + csharp-analyze: + name: C# Analyze ${{ matrix.dotnet }} + runs-on: ubuntu-22.04 + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: [ 'csharp' ] + dotnet: [ '3.1.301' ] + env: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + steps: + - name: Checkout code + uses: actions/checkout@v3 + - name: Cache Gradle dependencies + uses: actions/cache@v3 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v3 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + - name: Cache NuGet dependencies + uses: actions/cache@v3 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('csharp/**/*.sln') }} + restore-keys: | + ${{ runner.os }}-nuget- + - name: Setup dotnet + uses: actions/setup-dotnet@v2 + with: + dotnet-version: ${{ matrix.dotnet }} + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + + - name: Build + run: ./csharp/build.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" + + cpp-gcc-2204-analyze: + name: C++ GCC Analyze ${{ matrix.version }} + runs-on: ubuntu-22.04 + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: ['cpp'] + version: [ '12' ] + env: + CC: gcc-${{ matrix.version }} + CXX: g++-${{ matrix.version }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + - name: Cache Gradle dependencies + uses: actions/cache@v3 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v3 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + - name: Install compiler + run: | + sudo apt-get install -y g++-${{ matrix.version }} + curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz + tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz + echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + + - name: Build + run: ./cppbuild/cppbuild + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" + From 2c62ef9def3781f7ff18ad212866ff03d4f07e88 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 15 Dec 2022 08:52:49 +0000 Subject: [PATCH 0938/1594] [Java] Upgrade to Mockito 4.10.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index abc3c3974d..23957d007f 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' -def mockitoVersion = '4.9.0' +def mockitoVersion = '4.10.0' def junitVersion = '5.9.1' def jmhVersion = '1.36' def agronaVersion = '1.17.1' From 2b7f925532f913a02652961b819f03a669042d98 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 28 Dec 2022 15:19:04 +0100 Subject: [PATCH 0939/1594] [Java] Upgrade to Mockito 4.11.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 23957d007f..77ba3dcbbf 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' -def mockitoVersion = '4.10.0' +def mockitoVersion = '4.11.0' def junitVersion = '5.9.1' def jmhVersion = '1.36' def agronaVersion = '1.17.1' From 8390e48afd31085c303060c0bf474330500d4bdc Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 1 Jan 2023 15:38:29 +0100 Subject: [PATCH 0940/1594] Update copyright. --- CMakeLists.txt | 2 +- CONTRIBUTING.md | 2 +- README.md | 2 +- build.gradle | 2 +- config/checkstyle/checkstyle.xml | 2 +- sbe-benchmarks/src/main/cpp/CMakeLists.txt | 2 +- sbe-benchmarks/src/main/cpp/CarBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/CodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/MarketDataBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/benchlet-main.cpp | 2 +- sbe-benchmarks/src/main/cpp/benchlet.h | 2 +- .../src/main/java/uk/co/real_logic/sbe/CarBenchmark.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/package-info.java | 2 +- sbe-samples/src/main/cpp/CMakeLists.txt | 2 +- sbe-samples/src/main/cpp/GeneratedStubExample.cpp | 2 +- sbe-samples/src/main/cpp/OtfExample.cpp | 2 +- .../uk/co/real_logic/sbe/examples/ExampleTokenListener.java | 2 +- .../co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java | 2 +- .../sbe/examples/ExampleUsingGeneratedStubExtension.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java | 2 +- .../main/java/uk/co/real_logic/sbe/examples/package-info.java | 2 +- sbe-tool/src/main/cpp/CMakeLists.txt | 2 +- sbe-tool/src/main/cpp/otf/Encoding.h | 2 +- sbe-tool/src/main/cpp/otf/IrDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/Token.h | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java | 2 +- .../main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java | 2 +- .../java/uk/co/real_logic/sbe/codec/java/MethodSelector.java | 2 +- .../main/java/uk/co/real_logic/sbe/codec/java/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/CodeGenerator.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/Generators.java | 2 +- .../uk/co/real_logic/sbe/generation/TargetCodeGenerator.java | 2 +- .../co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/c/COutputManager.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/c/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java | 2 +- .../real_logic/sbe/generation/cpp/NamespaceOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/cpp/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/csharp/CSharp.java | 2 +- .../uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java | 2 +- .../sbe/generation/csharp/CSharpNamespaceOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/csharp/package-info.java | 2 +- .../uk/co/real_logic/sbe/generation/golang/GolangGenerator.java | 2 +- .../real_logic/sbe/generation/golang/GolangOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/golang/package-info.java | 2 +- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 2 +- .../uk/co/real_logic/sbe/generation/java/JavaOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/JavaUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/package-info.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/RustOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/RustUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/SubGroup.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/package-info.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/package-info.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java | 2 +- .../main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/json/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java | 2 +- .../main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java | 2 +- .../main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/otf/package-info.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java | 2 +- .../java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java | 2 +- .../java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java | 2 +- .../uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/package-info.java | 2 +- sbe-tool/src/test/c/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/c/CComplianceTest.c | 2 +- sbe-tool/src/test/c/CMakeLists.txt | 2 +- sbe-tool/src/test/c/CodeGenTest.cpp | 2 +- sbe-tool/src/test/c/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/c/Issue889Test.cpp | 2 +- sbe-tool/src/test/cpp/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/cpp/CMakeLists.txt | 2 +- sbe-tool/src/test/cpp/CodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeElementsTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp | 2 +- sbe-tool/src/test/cpp/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/cpp/Issue835Test.cpp | 2 +- sbe-tool/src/test/cpp/Issue889Test.cpp | 2 +- sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp | 2 +- sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp | 2 +- .../src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java | 2 +- .../test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java | 2 +- sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java | 2 +- .../test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java | 2 +- .../uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java | 2 +- .../real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java | 2 +- .../real_logic/sbe/generation/java/CharacterEncodingTest.java | 2 +- .../sbe/generation/java/CompositeElementsGenerationTest.java | 2 +- .../real_logic/sbe/generation/java/ConstantCharArrayTest.java | 2 +- .../sbe/generation/java/FixedSizeDataGeneratorTest.java | 2 +- .../real_logic/sbe/generation/java/GenerateFixBinaryTest.java | 2 +- .../real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java | 2 +- .../real_logic/sbe/generation/java/JavaOutputManagerTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java | 2 +- .../sbe/generation/java/PackageOutputManagerTest.java | 2 +- .../co/real_logic/sbe/generation/java/QualifiedYieldTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/ReflectionUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/RewindTest.java | 2 +- .../co/real_logic/sbe/generation/java/SchemaExtensionTest.java | 2 +- .../java/SinceVersionTransformedSchemaJavaGenerationTest.java | 2 +- .../sbe/generation/java/SkipAndDecodedLengthTest.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/ToStringTest.java | 2 +- .../real_logic/sbe/generation/java/WarningFormattingTest.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java | 2 +- .../uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java | 2 +- .../co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java | 2 +- .../uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java | 2 +- .../real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java | 2 +- 175 files changed, 175 insertions(+), 175 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a8e7b0010c..878df9b951 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2022 Real Logic Limited. +# Copyright 2013-2023 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 656cc2e855..ab34fb164c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ If you are adding a new file it should have the following header: ``` /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index bc0984add5..6248e6a4cf 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ Or run test directly with `Cargo` License (See LICENSE file for full license) ------------------------------------------- -Copyright 2013-2022 Real Logic Limited. +Copyright 2013-2023 Real Logic Limited. Copyright 2017 MarketFactory Inc. Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/build.gradle b/build.gradle index 77ba3dcbbf..b128e5c48f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 28aab05fd6..84cd75c377 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -23,7 +23,7 @@ - + diff --git a/sbe-benchmarks/src/main/cpp/CMakeLists.txt b/sbe-benchmarks/src/main/cpp/CMakeLists.txt index 3e0da195d9..d35adebb49 100644 --- a/sbe-benchmarks/src/main/cpp/CMakeLists.txt +++ b/sbe-benchmarks/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2022 Real Logic Limited. +# Copyright 2013-2023 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/CarBench.cpp b/sbe-benchmarks/src/main/cpp/CarBench.cpp index 7f938c3fc9..101974e8de 100644 --- a/sbe-benchmarks/src/main/cpp/CarBench.cpp +++ b/sbe-benchmarks/src/main/cpp/CarBench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/CodecBench.h b/sbe-benchmarks/src/main/cpp/CodecBench.h index 8028ef0bed..2cbb379e15 100644 --- a/sbe-benchmarks/src/main/cpp/CodecBench.h +++ b/sbe-benchmarks/src/main/cpp/CodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp index 4a01b81049..84cbee18ee 100644 --- a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp +++ b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h index 217f4eb39a..10f06ef65f 100644 --- a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h index e67807adb1..69cbf98890 100644 --- a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp index dd6136b932..e292d64255 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp +++ b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/benchlet.h b/sbe-benchmarks/src/main/cpp/benchlet.h index 68e00b2427..37c39222fa 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet.h +++ b/sbe-benchmarks/src/main/cpp/benchlet.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java index c15ebafeea..117dfefec0 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java index f459ae1dc9..a182c61331 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java index 568d9b0fad..974d94de21 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/CMakeLists.txt b/sbe-samples/src/main/cpp/CMakeLists.txt index 5c8664ca92..ea9213e665 100644 --- a/sbe-samples/src/main/cpp/CMakeLists.txt +++ b/sbe-samples/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2022 Real Logic Limited. +# Copyright 2013-2023 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index e2187c87ee..810c667be8 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/OtfExample.cpp b/sbe-samples/src/main/cpp/OtfExample.cpp index c108bbf9ba..fe9ceeb64a 100644 --- a/sbe-samples/src/main/cpp/OtfExample.cpp +++ b/sbe-samples/src/main/cpp/OtfExample.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java index 820131c543..a64d203640 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java index 640458f767..8af8d1094d 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java index 06bf499719..f9b1233468 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java index 847df95550..7512257b57 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java index 1cafaea915..fd12f685ba 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/CMakeLists.txt b/sbe-tool/src/main/cpp/CMakeLists.txt index 3100de1e6b..a2c4081141 100644 --- a/sbe-tool/src/main/cpp/CMakeLists.txt +++ b/sbe-tool/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2022 Real Logic Limited. +# Copyright 2013-2023 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/Encoding.h b/sbe-tool/src/main/cpp/otf/Encoding.h index 33aa3cf1cd..bad608a880 100644 --- a/sbe-tool/src/main/cpp/otf/Encoding.h +++ b/sbe-tool/src/main/cpp/otf/Encoding.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index 381a7e9638..2b4571b5b7 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h index 3fdd955a45..78a49c8eda 100644 --- a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h index f0a225b5f5..c61658aa35 100644 --- a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/Token.h b/sbe-tool/src/main/cpp/otf/Token.h index 9e2a3f0f18..b187a86198 100644 --- a/sbe-tool/src/main/cpp/otf/Token.h +++ b/sbe-tool/src/main/cpp/otf/Token.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java index ba6887f411..307e4a3b02 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index 804b38bb21..70553f642b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index a0be516bf9..1134e90c0e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index ff01421e7f..eac6dd4ba1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java index 5407cf1237..a69e280d0d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java index fef09f50f0..4ebebf2f83 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java index ed53dc625a..4ffba79157 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java index 9216ed5548..df4040e2bf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java index 775d972e09..be906f06e0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java index 4f4c31c125..83afb9928b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 2dade346dd..5d81eb691b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index f82eec476c..258104e5bf 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java index 2158196b40..5877162f56 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java index 2b0346fb0e..cadc1399fb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java index 86782b9872..d0e6656cc4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 81b8da29d7..3965763d21 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index ec19a53102..3e561bd207 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java index 59b0bccfc1..7616ad4b28 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java index e9158a3558..5c58a2d237 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java index 9c8643c277..5b4870a321 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index ec0b458d12..0550eb8bc0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java index b48c50611f..c2c500f5bc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index 0da828d02f..1140ae8b02 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java index 148b19f141..d1431f3343 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index cdefc9f7c0..24084e23ef 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java index 874b7769ec..c225f8b4a9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java index 0858cede34..d658a7e759 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java index 7cffab4c59..9bc17ee5fa 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 9a7cef4b48..b3ac5a63fb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java index 9d34d89a81..516093b5f8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 49bdbfdaa9..c29db9cbc2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java index dfd94ec902..e7ae8909e2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java index d23c989d0b..dd303f9a0e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 4913e30b9d..419f155e48 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index 75aa4c49fc..d61f888f01 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index e7e26bcc31..3fc3cccdec 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java index 4426638193..2e28bd67c8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index 731f57199d..4f71f0de84 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index 79fb608f79..756e019fdf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java index 265a1f3e82..e2e3f52525 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java index 78a8b60935..6f1c114103 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java index aa2929c08e..0e020cae75 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java index 98d0592e22..57e946b0df 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java index 534827134e..4fef0d5394 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index f5af22d62b..0551dcdf02 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java index 1107511407..4bbcfaef95 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java index f791c1b02b..aca56530b3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java index bcdc380a4b..e4b14a08f4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index 7d42b02599..a6845a15ae 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java index 8562868ba9..34a0ea2c56 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java index 99ef90556a..bd74f67e44 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index a618463229..92a38128b7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java index 1c58dc66a6..22e7595740 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java index 9ea3194669..947f6fb053 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java index 6f09a7f85b..c480a328bc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java index 3e4a7266a7..f189284b5c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java index ef991ae99c..0a7671a020 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java index 2fb3ca07a2..8cd16555fc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java index cc994a9775..efd0d150b8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java index 7445a48574..bc5d5ee6c2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index 037c01c8c8..966f5f0e2e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index ca81a4edc3..4e26bfded1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index 3197c08c47..e805dd8fc0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java index 12fe0663a3..7fad3ab7ea 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java index 9170bbcdc5..dd93a87fb7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java index 6f4e655fe7..7def2d9aed 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index 6349ce760b..f135d9e2fa 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java index 93586bbd67..1fbe750a2e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index 77be002e95..ee4ddffec0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java index 8ae645180a..9e38fd8c94 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java index 7609e46a0e..191f4e8279 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java index ea2e99b713..2c8b402f88 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java index 6c08d3706e..8f1ec8c23c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index 3288ff0e03..63618fdebf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java index 7b4f97d0cb..2d65a39044 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java index 67a09d3152..8b54fb6cfc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 8b95df9ff2..e407e675ff 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java index 6f79c9b6fa..3ffcf30830 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/BoundsCheckTest.cpp b/sbe-tool/src/test/c/BoundsCheckTest.cpp index 8cb984e0c7..f7656e2dd8 100644 --- a/sbe-tool/src/test/c/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/c/BoundsCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CComplianceTest.c b/sbe-tool/src/test/c/CComplianceTest.c index 61763dbb29..3ba67f78da 100644 --- a/sbe-tool/src/test/c/CComplianceTest.c +++ b/sbe-tool/src/test/c/CComplianceTest.c @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index 9d3c2b03dd..bb58cfc3cb 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2022 Real Logic Limited. +# Copyright 2013-2023 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index d1c0c0fcae..961db64b2d 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/GroupWithDataTest.cpp b/sbe-tool/src/test/c/GroupWithDataTest.cpp index 7d2b0efa2f..d8da323877 100644 --- a/sbe-tool/src/test/c/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/c/GroupWithDataTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/Issue889Test.cpp b/sbe-tool/src/test/c/Issue889Test.cpp index c0f5ec36a1..c621653028 100644 --- a/sbe-tool/src/test/c/Issue889Test.cpp +++ b/sbe-tool/src/test/c/Issue889Test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp index ee33ebd0cd..e3b81677dc 100644 --- a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index 438844b066..03d1ab1cfb 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2022 Real Logic Limited. +# Copyright 2013-2023 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index 1bd387f46e..5c7ad29b77 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp index d7b6fd6038..6b772b976e 100644 --- a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp index 632827a0fc..28bcbb1880 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp index 8ddb1101b9..2ef126a774 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp index c9bc42621d..2c0c242d8b 100644 --- a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/Issue835Test.cpp b/sbe-tool/src/test/cpp/Issue835Test.cpp index b22fdf9277..01aa455037 100644 --- a/sbe-tool/src/test/cpp/Issue835Test.cpp +++ b/sbe-tool/src/test/cpp/Issue835Test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/Issue889Test.cpp b/sbe-tool/src/test/cpp/Issue889Test.cpp index 42c87b1720..f730936a16 100644 --- a/sbe-tool/src/test/cpp/Issue889Test.cpp +++ b/sbe-tool/src/test/cpp/Issue889Test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp index 9767023f54..6ff568dd9d 100644 --- a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp +++ b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp index f3ad271857..ad46bab3a9 100644 --- a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp +++ b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java index f9ee2695ef..63bcc2e412 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java index 83b71ac815..a354a11d43 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java index 1911940443..eeea08ac0d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java index 7a5c92481e..4f5228f46f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java index 5ca540c2b6..9dcf95b8bb 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index b198de3073..dd7be3c505 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index 3a7eeca34c..cd5342f7d8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java index 62657132b1..59fe07b2f3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java index bc380a4665..8342f439e7 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java index 10eaedee62..124faba06c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java index 1141e5c983..75790252d2 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java index 8edb42474c..9e6a9f1706 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java index 09274ec5f7..0595da4469 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java index a8c9e2676a..e3facf38f6 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 297fc02ec0..c8d4d5870d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java index 97bab7f9ff..d953828de5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java index 9c930485cb..2b29b64451 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java index 5152196ed0..6122cdfd13 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java index 701d50057a..e9f3573272 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java index 56f7ccbc8d..a48074eb89 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java index 9a4974ebf1..c2c3e07f4b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index 78c6e2d5de..dcc8877b74 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java index 7a9a64c489..cdafc79fdb 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java index 23d6246566..8d8fcf3d4d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java index 3dde226e72..11b28123e1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java index def80db067..93a6a62183 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java index cab7fc9f10..33f3a876d4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index b7577f4100..b5932aa7f9 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java index 60a2538922..3e92466bbd 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java index fa773de170..0e527f43e2 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java index aab8b540ab..8986a43923 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index 900ab99e38..ca89103961 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java index 83a274dbd3..5abe33da26 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java index 073ffca2f2..612b4a4a4e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java index eee71d141c..4116bf0a78 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java index 1134876d22..dc4bd822f0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java index a0b7ef5ae4..94c9fe680d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java index 0b29b1bcf2..d5821fffcc 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java index f8c3a3aa8a..fdba65bc5b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java index ca3a0d3dca..30f75080fc 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java index a129c7ecc1..70b73af2d0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index 6763e2c50f..edd151623a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index ec6162f05d..fcdb5d8a66 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index 0f75157955..12292e4d65 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * Copyright 2017 MarketFactory Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java index ac203c3693..083e8dbd0d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java index 18176fb7b4..62b952f46b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java index bde5d84164..3e73957429 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java index 98d86e69d9..2b6dfa3607 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index c57bddddde..dcd51baff4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java index eb2f9ad815..28ca3b8c0c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 Real Logic Limited. + * Copyright 2013-2023 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 0150476aea588b189555a70abd128ac658aa327d Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 10 Jan 2023 17:25:06 +0100 Subject: [PATCH 0941/1594] [Java] Upgrade to JUnit 5.9.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b128e5c48f..63b9ef5357 100644 --- a/build.gradle +++ b/build.gradle @@ -45,7 +45,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' -def junitVersion = '5.9.1' +def junitVersion = '5.9.2' def jmhVersion = '1.36' def agronaVersion = '1.17.1' def agronaVersionRange = '[1.17.1,2.0[' // allow any release >= 1.17.1 and < 2.0.0 From 7630eef483de80abf6fd5ce593c904e4727522f3 Mon Sep 17 00:00:00 2001 From: Martin Thompson Date: Fri, 20 Jan 2023 17:04:13 +0000 Subject: [PATCH 0942/1594] Remove LGTM refs --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 6248e6a4cf..03c1eb03a3 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,6 @@ Simple Binary Encoding (SBE) [![GitHub](https://img.shields.io/github/license/real-logic/simple-binary-encoding.svg)](https://github.com/real-logic/simple-binary-encoding/blob/master/LICENSE) [![Actions Status](https://github.com/real-logic/simple-binary-encoding/workflows/Continuous%20Integration/badge.svg)](https://github.com/real-logic/simple-binary-encoding/actions) -[![Total Alerts](https://img.shields.io/lgtm/alerts/g/real-logic/simple-binary-encoding.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/real-logic/simple-binary-encoding/alerts) -[![Code Quality: Java](https://img.shields.io/lgtm/grade/java/g/real-logic/simple-binary-encoding.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/real-logic/simple-binary-encoding/context:java) [SBE](https://github.com/FIXTradingCommunity/fix-simple-binary-encoding) is an OSI layer 6 presentation for encoding and decoding binary application messages for low-latency financial applications. This repository contains From aa1a53e0c6b4e27ed531b3a655b8cb5d3513fb37 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Jan 2023 15:02:51 +0100 Subject: [PATCH 0943/1594] [Java] Use int for total. --- .../test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java index 9dcf95b8bb..11df1c5919 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java @@ -57,7 +57,7 @@ void shouldSetBitInByte() { final int bufferIndex = 8; - short total = 0; + int total = 0; for (int i = 0; i < 8; i++) { byte bits = buffer.getByte(bufferIndex); From 175ada06d9c8d1b721f1e273f4b7d0eb05250750 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Jan 2023 15:06:05 +0100 Subject: [PATCH 0944/1594] [CI] Run CodeQL when the `master` is being built. --- .github/workflows/ci.yml | 1 + .github/workflows/codeql.yml | 11 +++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a88bfb8a8f..1ae520d882 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,5 @@ name: Continuous Integration + on: push: branches: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0fdf5f35a4..3dc7cd836c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -2,12 +2,12 @@ name: "CodeQL" on: push: - branches: [ 'master' ] + branches: + - master pull_request: - # The branches below must be a subset of the branches above - branches: [ 'master' ] - schedule: - - cron: '16 7 * * 3' + types: [opened, synchronize] + branches: + - master concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -178,4 +178,3 @@ jobs: uses: github/codeql-action/analyze@v2 with: category: "/language:${{matrix.language}}" - From 6a30c05b8597cd6e6eb916c9d7f61a14754c819c Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Jan 2023 15:09:04 +0100 Subject: [PATCH 0945/1594] [CI] Remove duplicate GCC and Clang versions. --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ae520d882..fd2ea4cbb8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,7 +111,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '6', '7', '8', '9', '10', '11' ] + version: [ '6', '7', '8', '9', '10' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} @@ -146,7 +146,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '9', '10', '11', '12' ] + version: [ '11', '12' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} @@ -180,7 +180,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '9', '10', '11', '12', '13', '14' ] + version: [ '9', '10', '11', '12' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} @@ -217,7 +217,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '11', '12', '13', '14' ] + version: [ '13', '14', '15' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} From 6bbc1306e2603bd9eda91d64b5e16657df53ef7a Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Jan 2023 15:11:27 +0100 Subject: [PATCH 0946/1594] [CI] Add CodeQL badge. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 03c1eb03a3..0de28a3b78 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Simple Binary Encoding (SBE) [![GitHub](https://img.shields.io/github/license/real-logic/simple-binary-encoding.svg)](https://github.com/real-logic/simple-binary-encoding/blob/master/LICENSE) [![Actions Status](https://github.com/real-logic/simple-binary-encoding/workflows/Continuous%20Integration/badge.svg)](https://github.com/real-logic/simple-binary-encoding/actions) +[![CodeQL Status](https://github.com/real-logic/simple-binary-encoding/workflows/CodeQL/badge.svg)](https://github.com/real-logic/simple-binary-encoding/workflows/actions) [SBE](https://github.com/FIXTradingCommunity/fix-simple-binary-encoding) is an OSI layer 6 presentation for encoding and decoding binary application messages for low-latency financial applications. This repository contains From d8104d5553cfa6aa038b9134bf7db87e515ce2f7 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Jan 2023 15:13:28 +0100 Subject: [PATCH 0947/1594] [CI] Fix Clang 15 installation. --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd2ea4cbb8..5a5cffc7ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -238,6 +238,8 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | + sudo add-apt-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${{ matrix.version }} main" + sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz From 5033a408792a19d335ef7e238e5f4fd126ddd6a2 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Jan 2023 15:18:54 +0100 Subject: [PATCH 0948/1594] [CI] Add Clang GPG key. --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a5cffc7ce..679e21e7ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -238,6 +238,7 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | + curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - sudo add-apt-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${{ matrix.version }} main" sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} From 9ffc9a4f0a5905594b9bd245b47cd6a1c8320912 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Jan 2023 15:29:05 +0100 Subject: [PATCH 0949/1594] [CI] Update list of .NET versions tested against. --- .github/workflows/ci.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 679e21e7ac..7f05ab33d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,7 +68,7 @@ jobs: strategy: fail-fast: false matrix: - dotnet: [ '3.1.301' ] + dotnet: [ '3.1.301', '5.x', '6.x', '7.x' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -95,9 +95,10 @@ jobs: restore-keys: | ${{ runner.os }}-nuget- - name: Setup dotnet - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@v3 with: dotnet-version: ${{ matrix.dotnet }} + dotnet-quality: 'ga' - name: Build run: ./csharp/build.sh - name: Run tests @@ -267,7 +268,7 @@ jobs: tar xf cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Darwin-x86_64/CMake.app/Contents/bin" >> $GITHUB_PATH - name: Build - run: cmake --version && ./cppbuild/cppbuild + run: ./cppbuild/cppbuild cpp-msvc-build: name: C++ MSVC (Windows) From 3e41d5dc6704f8b94102e6769424839039da77a1 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Jan 2023 15:32:06 +0100 Subject: [PATCH 0950/1594] Revert "[CI] Update list of .NET versions tested against." This reverts commit 9ffc9a4f0a5905594b9bd245b47cd6a1c8320912. --- .github/workflows/ci.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7f05ab33d9..679e21e7ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,7 +68,7 @@ jobs: strategy: fail-fast: false matrix: - dotnet: [ '3.1.301', '5.x', '6.x', '7.x' ] + dotnet: [ '3.1.301' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -95,10 +95,9 @@ jobs: restore-keys: | ${{ runner.os }}-nuget- - name: Setup dotnet - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v2 with: dotnet-version: ${{ matrix.dotnet }} - dotnet-quality: 'ga' - name: Build run: ./csharp/build.sh - name: Run tests @@ -268,7 +267,7 @@ jobs: tar xf cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Darwin-x86_64/CMake.app/Contents/bin" >> $GITHUB_PATH - name: Build - run: ./cppbuild/cppbuild + run: cmake --version && ./cppbuild/cppbuild cpp-msvc-build: name: C++ MSVC (Windows) From f5fd9884c0c197c60069e5701bc97a227edcbfa1 Mon Sep 17 00:00:00 2001 From: Yong Jie Date: Fri, 27 Jan 2023 15:01:07 +0800 Subject: [PATCH 0951/1594] [Rust] bugfix: nested composite name should not be based on field name (#922) * [Rust] add failing test: nested composite should used composite name (instead of field name) as type name * [Rust] bugfix: nested composite should used composite name (instead of field name) as type name --- build.gradle | 1 + rust/Cargo.toml | 1 + .../sbe/generation/rust/RustGenerator.java | 4 +-- .../test/resources/nested-composite-name.xml | 29 +++++++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 sbe-tool/src/test/resources/nested-composite-name.xml diff --git a/build.gradle b/build.gradle index 63b9ef5357..abdc932a63 100644 --- a/build.gradle +++ b/build.gradle @@ -568,6 +568,7 @@ task generateRustTestCodecs(type: JavaExec) { args = ['sbe-tool/src/test/resources/issue435.xml', 'sbe-tool/src/test/resources/issue895.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', + 'sbe-tool/src/test/resources/nested-composite-name.xml', ] } diff --git a/rust/Cargo.toml b/rust/Cargo.toml index eb57d8b01c..8b7c1e774d 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -14,6 +14,7 @@ examples_uk_co_real_logic_sbe_benchmarks_fix = { path = "../generated/rust/uk_co issue_435 = { path = "../generated/rust/issue435" } issue_895 = { path = "../generated/rust/issue895" } baseline_bigendian = { path = "../generated/rust/baseline-bigendian" } +nested_composite_name = { path = "../generated/rust/nested-composite-name" } [dev-dependencies] criterion = "0.3" diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 3fc3cccdec..98ed1c2554 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -473,7 +473,7 @@ private static void generateCompositeEncoder( final String name) throws IOException { final String encoderName = toLowerSnakeCase(encoderName(name)); - final String encoderTypeName = encoderName(formatStructName(typeToken.name())); + final String encoderTypeName = encoderName(formatStructName(typeToken.applicableTypeName())); indent(sb, level, "/// COMPOSITE ENCODER\n"); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(self) -> %2$s {\n", @@ -533,7 +533,7 @@ private static void generateCompositeDecoder( final String name) throws IOException { final String decoderName = toLowerSnakeCase(decoderName(name)); - final String decoderTypeName = decoderName(formatStructName(typeToken.name())); + final String decoderTypeName = decoderName(formatStructName(typeToken.applicableTypeName())); indent(sb, level, "/// COMPOSITE DECODER\n"); indent(sb, level, "#[inline]\n"); if (fieldToken.version() > 0) diff --git a/sbe-tool/src/test/resources/nested-composite-name.xml b/sbe-tool/src/test/resources/nested-composite-name.xml new file mode 100644 index 0000000000..e7fb3a0566 --- /dev/null +++ b/sbe-tool/src/test/resources/nested-composite-name.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + From f2ee9e315971545bb42d3eeccc0bc176b8e023da Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 27 Jan 2023 17:24:31 +0100 Subject: [PATCH 0952/1594] [CI] Allow manual runs. --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 679e21e7ac..1959daf8ab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,7 @@ name: Continuous Integration on: + workflow_dispatch: push: branches: - master From 21aef3d0074d48d8641eff681f02035abd74cd27 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Feb 2023 16:08:31 +0100 Subject: [PATCH 0953/1594] [Java] Upgrade to versions plugin 0.45.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index abdc932a63..c7b707c1f4 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ import java.security.MessageDigest plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '7.1.2' apply false - id "com.github.ben-manes.versions" version "0.44.0" + id "com.github.ben-manes.versions" version "0.45.0" } defaultTasks 'clean', 'build' From 13d6092a010ad9529d3c53672075902ece187c4b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 3 Feb 2023 15:32:49 +0000 Subject: [PATCH 0954/1594] [Java] Fix CodeQL link. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0de28a3b78..8affd43e68 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Simple Binary Encoding (SBE) [![GitHub](https://img.shields.io/github/license/real-logic/simple-binary-encoding.svg)](https://github.com/real-logic/simple-binary-encoding/blob/master/LICENSE) [![Actions Status](https://github.com/real-logic/simple-binary-encoding/workflows/Continuous%20Integration/badge.svg)](https://github.com/real-logic/simple-binary-encoding/actions) -[![CodeQL Status](https://github.com/real-logic/simple-binary-encoding/workflows/CodeQL/badge.svg)](https://github.com/real-logic/simple-binary-encoding/workflows/actions) +[![CodeQL Status](https://github.com/real-logic/simple-binary-encoding/workflows/CodeQL/badge.svg)](https://github.com/real-logic/simple-binary-encoding/actions) [SBE](https://github.com/FIXTradingCommunity/fix-simple-binary-encoding) is an OSI layer 6 presentation for encoding and decoding binary application messages for low-latency financial applications. This repository contains From 060a95c9dcd7d21c1ce55f757162a292793e5ae5 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Feb 2023 16:41:43 +0100 Subject: [PATCH 0955/1594] [CI] Try autobuild for Java CodeQL. --- .github/workflows/codeql.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3dc7cd836c..063bb2ea9f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -64,15 +64,15 @@ jobs: - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: - languages: ${{ matrix.language }} - - - name: Build with Gradle - run: ./gradlew + languages: 'java' + + - name: Autobuild + uses: github/codeql-action/autobuild@v2 - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 with: - category: "/language:${{matrix.language}}" + category: '/language:java' csharp-analyze: name: C# Analyze ${{ matrix.dotnet }} From e5cf91eb5cc0ca22d8538328cc305bffe1dd76f7 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Feb 2023 16:53:02 +0100 Subject: [PATCH 0956/1594] Revert "[CI] Try autobuild for Java CodeQL." This reverts commit 060a95c9dcd7d21c1ce55f757162a292793e5ae5. --- .github/workflows/codeql.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 063bb2ea9f..3dc7cd836c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -64,15 +64,15 @@ jobs: - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: - languages: 'java' - - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + languages: ${{ matrix.language }} + + - name: Build with Gradle + run: ./gradlew - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 with: - category: '/language:java' + category: "/language:${{matrix.language}}" csharp-analyze: name: C# Analyze ${{ matrix.dotnet }} From 8efe53c0e9a3768f5a00039028ac0133090348db Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Feb 2023 16:54:35 +0100 Subject: [PATCH 0957/1594] [CI] Enable `security-and-quality` CodeQL checks. --- .github/workflows/codeql.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3dc7cd836c..044cc76de0 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -65,6 +65,7 @@ jobs: uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} + queries: +security-and-quality - name: Build with Gradle run: ./gradlew @@ -120,6 +121,7 @@ jobs: uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} + queries: +security-and-quality - name: Build run: ./csharp/build.sh @@ -170,6 +172,7 @@ jobs: uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} + queries: +security-and-quality - name: Build run: ./cppbuild/cppbuild From d734e60d78f8520c0615c0a7640ee9ba8ab772c3 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 3 Feb 2023 16:09:09 +0000 Subject: [PATCH 0958/1594] [C++] Ensure values are initialised for test. --- sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h index 10f06ef65f..f55c4bed4c 100644 --- a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h @@ -83,10 +83,10 @@ class SbeCarCodecBench : public CodecBench { car.wrapForDecode((char *)buffer, 0, Car::sbeBlockLength(), Car::sbeSchemaVersion(), bufferLength); - volatile int64_t tmpInt; - volatile const char *tmpChar; - volatile double tmpDouble; - volatile bool tmpBool; + volatile int64_t tmpInt = 0; + volatile const char *tmpChar = nullptr; + volatile double tmpDouble = 0; + volatile bool tmpBool = 0; tmpInt = car.serialNumber(); tmpInt = car.modelYear(); From 20cff02a4b53777598587f1161ef835503fe3963 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 3 Feb 2023 16:13:15 +0000 Subject: [PATCH 0959/1594] [Java] Validate IR file for decoding is not greater than Integer.MAX_VALUE. --- .../main/java/uk/co/real_logic/sbe/ir/IrDecoder.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index 0551dcdf02..d80ca04b46 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -46,7 +46,7 @@ public class IrDecoder implements AutoCloseable private final FrameCodecDecoder frameDecoder = new FrameCodecDecoder(); private final TokenCodecDecoder tokenDecoder = new TokenCodecDecoder(); private int offset; - private final long length; + private final int length; private String irPackageName = null; private String irNamespaceName = null; private String semanticVersion = null; @@ -67,9 +67,15 @@ public IrDecoder(final String fileName) { channel = FileChannel.open(Paths.get(fileName), READ); final long fileLength = channel.size(); + + if (fileLength > Integer.MAX_VALUE) + { + throw new IllegalStateException("Invalid IR file: length=" + fileLength + " > Integer.MAX_VALUE"); + } + final MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, fileLength); directBuffer = new UnsafeBuffer(buffer); - length = fileLength; + length = (int)fileLength; offset = 0; } catch (final IOException ex) From 702df4e1bfdcee2cae76502463d697bf94f00736 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Feb 2023 15:19:38 +0000 Subject: [PATCH 0960/1594] [Java] Add CodeQL config. --- .github/codeql/codeql-config.yml | 8 ++++++++ .github/workflows/codeql.yml | 3 +++ 2 files changed, 11 insertions(+) create mode 100644 .github/codeql/codeql-config.yml diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 0000000000..00f0562196 --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,8 @@ +name: "SBE CodeQL Scanning" + +queries: + - uses: security-and-quality + +query-filters: + - exclude: + id: java/iterator-implements-iterable diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 044cc76de0..54d4a46dc6 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -66,6 +66,7 @@ jobs: with: languages: ${{ matrix.language }} queries: +security-and-quality + config-file: ./.github/codeql/codeql-config.yml - name: Build with Gradle run: ./gradlew @@ -122,6 +123,7 @@ jobs: with: languages: ${{ matrix.language }} queries: +security-and-quality + config-file: ./.github/codeql/codeql-config.yml - name: Build run: ./csharp/build.sh @@ -173,6 +175,7 @@ jobs: with: languages: ${{ matrix.language }} queries: +security-and-quality + config-file: ./.github/codeql/codeql-config.yml - name: Build run: ./cppbuild/cppbuild From 826a101f718dde5af3ceeac8441bf398a77797fe Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Feb 2023 15:37:10 +0000 Subject: [PATCH 0961/1594] [C#] Remove useless assignment warnings. --- .github/codeql/codeql-config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index 00f0562196..afc903892e 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -6,3 +6,5 @@ queries: query-filters: - exclude: id: java/iterator-implements-iterable + - exclude: + id: cs/useless-assignment-to-local From 08309a4263c672d3cddcaf447e35b55564c630f7 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Feb 2023 16:19:49 +0000 Subject: [PATCH 0962/1594] [Java] Fix warnings in IrUtil. --- .../java/uk/co/real_logic/sbe/ir/IrUtil.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java index aca56530b3..9b57dee5bf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java @@ -48,14 +48,14 @@ static ByteOrder mapByteOrder(final ByteOrderCodec byteOrder) { switch (byteOrder) { - case SBE_LITTLE_ENDIAN: - return ByteOrder.LITTLE_ENDIAN; - case SBE_BIG_ENDIAN: return ByteOrder.BIG_ENDIAN; - } - return ByteOrder.LITTLE_ENDIAN; + default: + case SBE_LITTLE_ENDIAN: + case NULL_VAL: + return ByteOrder.LITTLE_ENDIAN; + } } static SignalCodec mapSignal(final Signal signal) @@ -414,9 +414,11 @@ static Encoding.Presence mapPresence(final PresenceCodec presence) case SBE_CONSTANT: return Encoding.Presence.CONSTANT; - } - return Encoding.Presence.REQUIRED; + default: + case SBE_REQUIRED: + return Encoding.Presence.REQUIRED; + } } static PresenceCodec mapPresence(final Encoding.Presence presence) @@ -428,8 +430,10 @@ static PresenceCodec mapPresence(final Encoding.Presence presence) case CONSTANT: return PresenceCodec.SBE_CONSTANT; - } - return PresenceCodec.SBE_REQUIRED; + default: + case REQUIRED: + return PresenceCodec.SBE_REQUIRED; + } } } From d1909acaade7b772539e42a492706c540f0d60a8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Feb 2023 16:28:09 +0000 Subject: [PATCH 0963/1594] [C#] Warnings cleanup. --- .github/codeql/codeql-config.yml | 2 ++ csharp/sbe-samples-car/CarExample.cs | 2 +- csharp/sbe-samples-extension/ExtensionExample.cs | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index afc903892e..da536ab06f 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -6,5 +6,7 @@ queries: query-filters: - exclude: id: java/iterator-implements-iterable + - exclude: + id: java/missing-override-annotation - exclude: id: cs/useless-assignment-to-local diff --git a/csharp/sbe-samples-car/CarExample.cs b/csharp/sbe-samples-car/CarExample.cs index 3a51103d8a..3706ab959a 100644 --- a/csharp/sbe-samples-car/CarExample.cs +++ b/csharp/sbe-samples-car/CarExample.cs @@ -261,7 +261,7 @@ public static void Decode(Car car, sb.Append("\ncar.size=").Append(car.Size); - Console.WriteLine(sb.ToString()); + Console.WriteLine(sb); } } } diff --git a/csharp/sbe-samples-extension/ExtensionExample.cs b/csharp/sbe-samples-extension/ExtensionExample.cs index 73b3956aa0..9e11ee3b35 100644 --- a/csharp/sbe-samples-extension/ExtensionExample.cs +++ b/csharp/sbe-samples-extension/ExtensionExample.cs @@ -74,7 +74,7 @@ public static void ExampleMain() // And now let's encode an extension and decode it as baseline Extension.ExtensionExample.Encode(extensionCar, directBuffer, Extension.MessageHeader.Size); - Baseline.ExtensionExample.Decode(baselineCar, directBuffer, (int)Baseline.MessageHeader.Size, (int)Extension.Car.BlockLength, (int)Baseline.Car.SchemaVersion); + Baseline.ExtensionExample.Decode(baselineCar, directBuffer, Baseline.MessageHeader.Size, (int)Extension.Car.BlockLength, (int)Baseline.Car.SchemaVersion); } } @@ -283,7 +283,7 @@ public static void Decode(Car car, sb.Append("\ncar.size=").Append(car.Size); - Console.WriteLine(sb.ToString()); + Console.WriteLine(sb); } } } @@ -539,7 +539,7 @@ public static void Decode(Car car, sb.Append("\ncar.size=").Append(car.Size); - Console.WriteLine(sb.ToString()); + Console.WriteLine(sb); } } } From 77666f96c15645e0abec05655195f4947f105487 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Feb 2023 16:38:08 +0000 Subject: [PATCH 0964/1594] [Java] More efficient attribute parsing in XML with more precise error message. --- .../uk/co/real_logic/sbe/xml/XmlSchemaParser.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index e407e675ff..da8c0e1483 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -16,6 +16,7 @@ */ package uk.co.real_logic.sbe.xml; +import org.agrona.Strings; import org.agrona.collections.ObjectHashSet; import org.w3c.dom.*; import org.xml.sax.InputSource; @@ -298,13 +299,20 @@ public static String getAttributeValue(final Node elementNode, final String attr final NamedNodeMap attributes = elementNode.getAttributes(); final Node attrNode = attributes.getNamedItemNS(null, attrName); - if (null == attrNode || "".equals(attrNode.getNodeValue())) + if (null == attrNode) { throw new IllegalStateException( - "element '" + elementNode.getNodeName() + "' has empty or missing attribute: " + attrName); + "element '" + elementNode.getNodeName() + "' has missing attribute: " + attrName); } - return attrNode.getNodeValue(); + final String nodeValue = attrNode.getNodeValue(); + if (Strings.isEmpty(nodeValue)) + { + throw new IllegalStateException( + "element '" + elementNode.getNodeName() + "' has empty attribute: " + attrName); + } + + return nodeValue; } /** From 76d01f7bef470dd7767f0f8d0be3a3841b24d311 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Feb 2023 16:43:04 +0000 Subject: [PATCH 0965/1594] [C++] Allow trivial switch statements. --- .github/codeql/codeql-config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index da536ab06f..889b4fe698 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -10,3 +10,5 @@ query-filters: id: java/missing-override-annotation - exclude: id: cs/useless-assignment-to-local + - exclude: + id: cpp/trivial-switch From 15f395e748686e5d5a90ac3afb0d52a7619bbc2c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Feb 2023 17:05:33 +0000 Subject: [PATCH 0966/1594] [Java] Close resources in test. --- .../csharp/Issue567GroupSizeTest.java | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index cd5342f7d8..48b436b289 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -58,10 +58,14 @@ void shouldThrowWhenUsingATypeThatIsNotConstrainedToFitInAnIntAsTheGroupSize() t .stopOnError(true) .build(); final InputStream in = Tests.getLocalResource("issue567-invalid.xml"); - final InputSource is = new InputSource(new InputStreamReader(in, StandardCharsets.UTF_8)); - assertThrows(IllegalArgumentException.class, () -> XmlSchemaParser.parse(is, options)); - verify(mockErr).println(ERR_MSG); + try (InputStreamReader characterStream = new InputStreamReader(in, StandardCharsets.UTF_8)) + { + final InputSource is = new InputSource(characterStream); + + assertThrows(IllegalArgumentException.class, () -> XmlSchemaParser.parse(is, options)); + verify(mockErr).println(ERR_MSG); + } } @Test @@ -72,21 +76,25 @@ void shouldGenerateWhenUsingATypeThatIsConstrainedToFitInAnIntAsTheGroupSize() t .stopOnError(true) .build(); final InputStream in = Tests.getLocalResource("issue567-valid.xml"); - final InputSource is = new InputSource(new InputStreamReader(in, StandardCharsets.UTF_8)); - final MessageSchema schema = XmlSchemaParser.parse(is, options); - verify(mockErr).println(ERR_MSG); + try (InputStreamReader characterStream = new InputStreamReader(in, StandardCharsets.UTF_8)) + { + final InputSource is = new InputSource(characterStream); + + final MessageSchema schema = XmlSchemaParser.parse(is, options); + verify(mockErr).println(ERR_MSG); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); - final StringWriterOutputManager outputManager = new StringWriterOutputManager(); - outputManager.setPackageName(ir.applicableNamespace()); - final CSharpGenerator generator = new CSharpGenerator(ir, outputManager); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + final CSharpGenerator generator = new CSharpGenerator(ir, outputManager); - generator.generate(); + generator.generate(); - final String source = outputManager.getSource("tests.Issue567").toString(); - assertThat(source, containsString(EXPECTED_COUNT_CHECK)); + final String source = outputManager.getSource("tests.Issue567").toString(); + assertThat(source, containsString(EXPECTED_COUNT_CHECK)); + } } } From f77d5e99a651b7b1edf90bfd668ed40c4fa72a1e Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Feb 2023 18:26:10 +0000 Subject: [PATCH 0967/1594] [Java] Fix resource leaks in tests. --- .../real_logic/sbe/xml/XmlSchemaParser.java | 2 +- .../sbe/generation/cpp/CppGeneratorTest.java | 27 +- .../java/ConstantCharArrayTest.java | 75 +-- .../java/FixedSizeDataGeneratorTest.java | 22 +- .../java/GenerateFixBinaryTest.java | 112 +++-- .../java/GenerateIlinkBinaryTest.java | 112 +++-- .../generation/java/JavaGeneratorTest.java | 169 ++++--- .../generation/java/NullEnumTypedTest.java | 40 +- .../generation/java/QualifiedYieldTest.java | 43 +- .../generation/java/SchemaExtensionTest.java | 18 +- ...onTransformedSchemaJavaGenerationTest.java | 41 +- .../java/WarningFormattingTest.java | 36 +- .../sbe/ir/BasicXmlIrGenerationTest.java | 471 +++++++++--------- .../sbe/ir/CompositeElementsIrTest.java | 289 +++++------ .../sbe/ir/CompositeOffsetsTest.java | 40 +- .../real_logic/sbe/ir/CompositeRefsTest.java | 17 +- .../co/real_logic/sbe/ir/EncodedIrTest.java | 227 +++++---- .../sbe/ir/GroupWithDataIrTest.java | 231 +++++---- .../sbe/ir/SinceVersionValidationTest.java | 8 +- .../co/real_logic/sbe/ir/ValueRefsTest.java | 21 +- .../sbe/xml/BasicSchemaFileTest.java | 38 +- .../sbe/xml/CompositeElementsTest.java | 49 +- .../sbe/xml/CyclicReferencesTest.java | 7 +- .../xml/EmbeddedLengthAndCountFileTest.java | 24 +- .../co/real_logic/sbe/xml/EnumTypeTest.java | 30 +- .../real_logic/sbe/xml/ErrorHandlerTest.java | 33 +- .../real_logic/sbe/xml/GroupWithDataTest.java | 25 +- .../co/real_logic/sbe/xml/OffsetFileTest.java | 209 ++++---- .../uk/co/real_logic/sbe/xml/SetTypeTest.java | 31 +- .../SinceVersionSchemaTransformerTest.java | 19 +- 30 files changed, 1344 insertions(+), 1122 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index da8c0e1483..d9ecb33df3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -172,7 +172,7 @@ public static MessageSchema parse(final InputStream in, final ParserOptions opti } /** - * Scan XML for all types (encodedDataType, compositeType, enumType, and setType) and save in map. + * Scan XML for all types (encodedDataType, compositeType, enumType, and setType) and save in a map. * * @param document for the XML parsing. * @param xPath for XPath expression reuse. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index dd7be3c505..73fa7664f2 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -23,6 +23,8 @@ import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import java.io.InputStream; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; @@ -33,18 +35,21 @@ class CppGeneratorTest @Test void shouldUseGeneratedLiteralForConstantOneWhenGeneratingBitsetCode() throws Exception { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("issue827.xml"), options); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final StringWriterOutputManager outputManager = new StringWriterOutputManager(); - outputManager.setPackageName(ir.applicableNamespace()); + try (InputStream in = Tests.getLocalResource("issue827.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); - final CppGenerator generator = new CppGenerator(ir, false, outputManager); - generator.generate(); + final CppGenerator generator = new CppGenerator(ir, false, outputManager); + generator.generate(); - final String source = outputManager.getSource("issue827.FlagsSet").toString(); - assertThat(source, not(containsString("1u << "))); - assertThat(source, containsString("UINT64_C(0x1) << ")); + final String source = outputManager.getSource("issue827.FlagsSet").toString(); + assertThat(source, not(containsString("1u << "))); + assertThat(source, containsString("UINT64_C(0x1) << ")); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java index 75790252d2..7b823d5a86 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java @@ -24,10 +24,12 @@ import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import uk.co.real_logic.sbe.xml.XmlSchemaParser; + +import java.io.InputStream; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.StringContains.containsString; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; class ConstantCharArrayTest { @@ -39,45 +41,48 @@ class ConstantCharArrayTest @Test void shouldGenerateConstCharArrayMethods() throws Exception { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("issue505.xml"), options); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); + try (InputStream in = Tests.getLocalResource("issue505.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = XmlSchemaParser.parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); - final StringWriterOutputManager outputManager = new StringWriterOutputManager(); - outputManager.setPackageName(ir.applicableNamespace()); - final JavaGenerator generator = new JavaGenerator( - ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager); - generator.generate(); - final String sources = outputManager.getSources().toString(); + generator.generate(); + final String sources = outputManager.getSources().toString(); - final String expectedOne = - " public byte sourceOne()\n" + - " {\n" + - " return (byte)67;\n" + - " }"; - assertThat(sources, containsString(expectedOne)); + final String expectedOne = + " public byte sourceOne()\n" + + " {\n" + + " return (byte)67;\n" + + " }"; + assertThat(sources, containsString(expectedOne)); - final String expectedTwo = - " public byte sourceTwo()\n" + - " {\n" + - " return (byte)68;\n" + - " }"; - assertThat(sources, containsString(expectedTwo)); + final String expectedTwo = + " public byte sourceTwo()\n" + + " {\n" + + " return (byte)68;\n" + + " }"; + assertThat(sources, containsString(expectedTwo)); - final String expectedThree = - " public String sourceThree()\n" + - " {\n" + - " return \"EF\";\n" + - " }"; - assertThat(sources, containsString(expectedThree)); + final String expectedThree = + " public String sourceThree()\n" + + " {\n" + + " return \"EF\";\n" + + " }"; + assertThat(sources, containsString(expectedThree)); - final String expectedFour = - " public String sourceFour()\n" + - " {\n" + - " return \"GH\";\n" + - " }"; - assertThat(sources, containsString(expectedFour)); + final String expectedFour = + " public String sourceFour()\n" + + " {\n" + + " return \"GH\";\n" + + " }"; + assertThat(sources, containsString(expectedFour)); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java index 9e6a9f1706..7827dac2b3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java @@ -27,14 +27,15 @@ import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import uk.co.real_logic.sbe.xml.XmlSchemaParser; +import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.*; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; class FixedSizeDataGeneratorTest { @@ -50,15 +51,18 @@ class FixedSizeDataGeneratorTest @BeforeEach void setUp() throws Exception { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("extension-schema.xml"), options); - final IrGenerator irg = new IrGenerator(); - ir = irg.generate(schema); + try (InputStream in = Tests.getLocalResource("extension-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = XmlSchemaParser.parse(in, options); + final IrGenerator irg = new IrGenerator(); + ir = irg.generate(schema); - outputManager.clear(); - outputManager.setPackageName(ir.applicableNamespace()); + outputManager.clear(); + outputManager.setPackageName(ir.applicableNamespace()); - generator().generate(); + generator().generate(); + } } @Test diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java index 0595da4469..82a280ed5e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java @@ -22,9 +22,14 @@ import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.SbeTool; import uk.co.real_logic.sbe.Tests; -import uk.co.real_logic.sbe.ir.*; -import uk.co.real_logic.sbe.xml.*; - +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.ir.IrDecoder; +import uk.co.real_logic.sbe.ir.IrEncoder; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.io.InputStream; import java.nio.ByteBuffer; import java.util.Map; @@ -46,32 +51,35 @@ void shouldGenerateValidJava() throws Exception { System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("FixBinary.xml"), options); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final JavaGenerator generator = new JavaGenerator( - ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager); - - outputManager.setPackageName(ir.applicableNamespace()); - generator.generateMessageHeaderStub(); - generator.generateTypeStubs(); - generator.generate(); - - final Map sources = outputManager.getSources(); - + try (InputStream in = Tests.getLocalResource("FixBinary.xml")) { - final String className = "MDIncrementalRefreshTradeSummary42Encoder"; - final String fqClassName = ir.applicableNamespace() + "." + className; - final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); - assertNotNull(aClass); - } - - { - final String className = "MDIncrementalRefreshTradeSummary42Decoder"; - final String fqClassName = ir.applicableNamespace() + "." + className; - final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); - assertNotNull(aClass); + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager); + + outputManager.setPackageName(ir.applicableNamespace()); + generator.generateMessageHeaderStub(); + generator.generateTypeStubs(); + generator.generate(); + + final Map sources = outputManager.getSources(); + + { + final String className = "MDIncrementalRefreshTradeSummary42Encoder"; + final String fqClassName = ir.applicableNamespace() + "." + className; + final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); + assertNotNull(aClass); + } + + { + final String className = "MDIncrementalRefreshTradeSummary42Decoder"; + final String fqClassName = ir.applicableNamespace() + "." + className; + final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); + assertNotNull(aClass); + } } } @@ -80,25 +88,33 @@ void shouldGenerateAndEncodeIr() throws Exception { System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("FixBinary.xml"), options); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); - - final IrEncoder irEncoder = new IrEncoder(buffer, ir); - irEncoder.encode(); - - buffer.flip(); - final IrDecoder irDecoder = new IrDecoder(buffer); - final Ir decodedIr = irDecoder.decode(); - - assertEquals(ir.id(), decodedIr.id()); - assertEquals(ir.version(), decodedIr.version()); - assertEquals(ir.byteOrder(), decodedIr.byteOrder()); - assertEquals(ir.applicableNamespace(), decodedIr.applicableNamespace()); - assertEquals(ir.packageName(), decodedIr.packageName()); - assertEquals(ir.types().size(), decodedIr.types().size()); - assertEquals(ir.messages().size(), decodedIr.messages().size()); + try (InputStream in = Tests.getLocalResource("FixBinary.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); + + try (IrEncoder irEncoder = new IrEncoder(buffer, ir)) + { + irEncoder.encode(); + } + + buffer.flip(); + + try (IrDecoder irDecoder = new IrDecoder(buffer)) + { + final Ir decodedIr = irDecoder.decode(); + + assertEquals(ir.id(), decodedIr.id()); + assertEquals(ir.version(), decodedIr.version()); + assertEquals(ir.byteOrder(), decodedIr.byteOrder()); + assertEquals(ir.applicableNamespace(), decodedIr.applicableNamespace()); + assertEquals(ir.packageName(), decodedIr.packageName()); + assertEquals(ir.types().size(), decodedIr.types().size()); + assertEquals(ir.messages().size(), decodedIr.messages().size()); + } + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java index e3facf38f6..6448428ff8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java @@ -22,9 +22,14 @@ import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.SbeTool; import uk.co.real_logic.sbe.Tests; -import uk.co.real_logic.sbe.ir.*; -import uk.co.real_logic.sbe.xml.*; - +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.ir.IrDecoder; +import uk.co.real_logic.sbe.ir.IrEncoder; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.io.InputStream; import java.nio.ByteBuffer; import java.util.Map; @@ -46,32 +51,35 @@ void shouldGenerateValidJava() throws Exception { System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("ilinkbinary.xml"), options); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final JavaGenerator generator = new JavaGenerator( - ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager); - - outputManager.setPackageName(ir.applicableNamespace()); - generator.generateMessageHeaderStub(); - generator.generateTypeStubs(); - generator.generate(); - - final Map sources = outputManager.getSources(); - + try (InputStream in = Tests.getLocalResource("ilinkbinary.xml")) { - final String className = "NewOrderSingle514Encoder"; - final String fqClassName = ir.applicableNamespace() + "." + className; - final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); - assertNotNull(aClass); - } - - { - final String className = "NewOrderSingle514Decoder"; - final String fqClassName = ir.applicableNamespace() + "." + className; - final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); - assertNotNull(aClass); + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager); + + outputManager.setPackageName(ir.applicableNamespace()); + generator.generateMessageHeaderStub(); + generator.generateTypeStubs(); + generator.generate(); + + final Map sources = outputManager.getSources(); + + { + final String className = "NewOrderSingle514Encoder"; + final String fqClassName = ir.applicableNamespace() + "." + className; + final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); + assertNotNull(aClass); + } + + { + final String className = "NewOrderSingle514Decoder"; + final String fqClassName = ir.applicableNamespace() + "." + className; + final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); + assertNotNull(aClass); + } } } @@ -80,25 +88,33 @@ void shouldGenerateAndEncodeIr() throws Exception { System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("ilinkbinary.xml"), options); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); - - final IrEncoder irEncoder = new IrEncoder(buffer, ir); - irEncoder.encode(); - - buffer.flip(); - final IrDecoder irDecoder = new IrDecoder(buffer); - final Ir decodedIr = irDecoder.decode(); - - assertEquals(ir.id(), decodedIr.id()); - assertEquals(ir.version(), decodedIr.version()); - assertEquals(ir.byteOrder(), decodedIr.byteOrder()); - assertEquals(ir.applicableNamespace(), decodedIr.applicableNamespace()); - assertEquals(ir.packageName(), decodedIr.packageName()); - assertEquals(ir.types().size(), decodedIr.types().size()); - assertEquals(ir.messages().size(), decodedIr.messages().size()); + try (InputStream in = Tests.getLocalResource("ilinkbinary.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); + + try (IrEncoder irEncoder = new IrEncoder(buffer, ir)) + { + irEncoder.encode(); + } + + buffer.flip(); + + try (IrDecoder irDecoder = new IrDecoder(buffer)) + { + final Ir decodedIr = irDecoder.decode(); + + assertEquals(ir.id(), decodedIr.id()); + assertEquals(ir.version(), decodedIr.version()); + assertEquals(ir.byteOrder(), decodedIr.byteOrder()); + assertEquals(ir.applicableNamespace(), decodedIr.applicableNamespace()); + assertEquals(ir.packageName(), decodedIr.packageName()); + assertEquals(ir.types().size(), decodedIr.types().size()); + assertEquals(ir.messages().size(), decodedIr.messages().size()); + } + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index c8d4d5870d..f12fef3751 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -29,6 +29,7 @@ import uk.co.real_logic.sbe.xml.ParserOptions; import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Method; import java.nio.ByteOrder; import java.util.Map; @@ -58,13 +59,16 @@ class JavaGeneratorTest @BeforeEach void setUp() throws Exception { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("code-generation-schema.xml"), options); - final IrGenerator irg = new IrGenerator(); - ir = irg.generate(schema); + try (InputStream in = Tests.getLocalResource("code-generation-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + ir = irg.generate(schema); - outputManager.clear(); - outputManager.setPackageName(ir.applicableNamespace()); + outputManager.clear(); + outputManager.setPackageName(ir.applicableNamespace()); + } } @Test @@ -461,88 +465,97 @@ void shouldGenerateRepeatingGroupCountLimits() throws Exception @Test void shouldMarkDeprecatedClasses() throws Exception { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("deprecated-msg-test-schema.xml"), options); - final IrGenerator irg = new IrGenerator(); - ir = irg.generate(schema); - - outputManager.clear(); - outputManager.setPackageName(ir.applicableNamespace()); - - generator().generate(); - final String encoderFqcn = ir.applicableNamespace() + ".DeprecatedMessageEncoder"; - final Class encoderClazz = compile(encoderFqcn); - assertNotNull(encoderClazz); - assertTrue(encoderClazz.isAnnotationPresent(Deprecated.class)); - - final String decoderFqcn = ir.applicableNamespace() + ".DeprecatedMessageDecoder"; - final Class decoderClazz = compile(decoderFqcn); - assertNotNull(decoderClazz); - assertTrue(decoderClazz.isAnnotationPresent(Deprecated.class)); + try (InputStream in = Tests.getLocalResource("deprecated-msg-test-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + ir = irg.generate(schema); + + outputManager.clear(); + outputManager.setPackageName(ir.applicableNamespace()); + + generator().generate(); + final String encoderFqcn = ir.applicableNamespace() + ".DeprecatedMessageEncoder"; + final Class encoderClazz = compile(encoderFqcn); + assertNotNull(encoderClazz); + assertTrue(encoderClazz.isAnnotationPresent(Deprecated.class)); + + final String decoderFqcn = ir.applicableNamespace() + ".DeprecatedMessageDecoder"; + final Class decoderClazz = compile(decoderFqcn); + assertNotNull(decoderClazz); + assertTrue(decoderClazz.isAnnotationPresent(Deprecated.class)); + } } @Test void shouldCreateTypesInDifferentPackages() throws Exception { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("explicit-package-test-schema.xml"), options); - final IrGenerator irg = new IrGenerator(); - ir = irg.generate(schema); - - outputManager.clear(); - outputManager.setPackageName(ir.applicableNamespace()); - - final JavaGenerator generator = new JavaGenerator(ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, - true, outputManager); - - generator.generate(); - final String encoderFqcn = ir.applicableNamespace() + ".TestMessageEncoder"; - final Class encoderClazz = compile(encoderFqcn); - assertNotNull(encoderClazz); - - final String decoderFqcn = ir.applicableNamespace() + ".TestMessageDecoder"; - final Class decoderClazz = compile(decoderFqcn); - assertNotNull(decoderClazz); - - final Map sources = outputManager.getSources(); - assertNotNull(sources.get("test.message.schema.common.CarEncoder")); - assertNotNull(sources.get("test.message.schema.common.CarDecoder")); - assertNotNull(sources.get("outside.schema.BooleanType")); - assertNotNull(sources.get("outside.schema.DaysEncoder")); - assertNotNull(sources.get("outside.schema.DaysDecoder")); - assertNotNull(sources.get(ir.applicableNamespace() + ".MessageHeaderEncoder")); + try (InputStream in = Tests.getLocalResource("explicit-package-test-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + ir = irg.generate(schema); + + outputManager.clear(); + outputManager.setPackageName(ir.applicableNamespace()); + + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, true, outputManager); + + generator.generate(); + final String encoderFqcn = ir.applicableNamespace() + ".TestMessageEncoder"; + final Class encoderClazz = compile(encoderFqcn); + assertNotNull(encoderClazz); + + final String decoderFqcn = ir.applicableNamespace() + ".TestMessageDecoder"; + final Class decoderClazz = compile(decoderFqcn); + assertNotNull(decoderClazz); + + final Map sources = outputManager.getSources(); + assertNotNull(sources.get("test.message.schema.common.CarEncoder")); + assertNotNull(sources.get("test.message.schema.common.CarDecoder")); + assertNotNull(sources.get("outside.schema.BooleanType")); + assertNotNull(sources.get("outside.schema.DaysEncoder")); + assertNotNull(sources.get("outside.schema.DaysDecoder")); + assertNotNull(sources.get(ir.applicableNamespace() + ".MessageHeaderEncoder")); + } } @Test void shouldCreateTypesInSamePackageIfSupportDisabled() throws Exception { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("explicit-package-test-schema.xml"), options); - final IrGenerator irg = new IrGenerator(); - ir = irg.generate(schema); - - outputManager.clear(); - outputManager.setPackageName(ir.applicableNamespace()); - - final JavaGenerator generator = new JavaGenerator(ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, - false, outputManager); - - generator.generate(); - final String encoderFqcn = ir.applicableNamespace() + ".TestMessageEncoder"; - final Class encoderClazz = compile(encoderFqcn); - assertNotNull(encoderClazz); - - final String decoderFqcn = ir.applicableNamespace() + ".TestMessageDecoder"; - final Class decoderClazz = compile(decoderFqcn); - assertNotNull(decoderClazz); - - final Map sources = outputManager.getSources(); - assertNotNull(sources.get(ir.applicableNamespace() + ".CarEncoder")); - assertNotNull(sources.get(ir.applicableNamespace() + ".CarDecoder")); - assertNotNull(sources.get(ir.applicableNamespace() + ".BooleanType")); - assertNotNull(sources.get(ir.applicableNamespace() + ".DaysEncoder")); - assertNotNull(sources.get(ir.applicableNamespace() + ".DaysDecoder")); - assertNotNull(sources.get(ir.applicableNamespace() + ".MessageHeaderEncoder")); + try (InputStream in = Tests.getLocalResource("explicit-package-test-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + ir = irg.generate(schema); + + outputManager.clear(); + outputManager.setPackageName(ir.applicableNamespace()); + + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, false, outputManager); + + generator.generate(); + final String encoderFqcn = ir.applicableNamespace() + ".TestMessageEncoder"; + final Class encoderClazz = compile(encoderFqcn); + assertNotNull(encoderClazz); + + final String decoderFqcn = ir.applicableNamespace() + ".TestMessageDecoder"; + final Class decoderClazz = compile(decoderFqcn); + assertNotNull(decoderClazz); + + final Map sources = outputManager.getSources(); + assertNotNull(sources.get(ir.applicableNamespace() + ".CarEncoder")); + assertNotNull(sources.get(ir.applicableNamespace() + ".CarDecoder")); + assertNotNull(sources.get(ir.applicableNamespace() + ".BooleanType")); + assertNotNull(sources.get(ir.applicableNamespace() + ".DaysEncoder")); + assertNotNull(sources.get(ir.applicableNamespace() + ".DaysDecoder")); + assertNotNull(sources.get(ir.applicableNamespace() + ".MessageHeaderEncoder")); + } } private Class getModelClass(final Object encoder) throws ClassNotFoundException diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java index 2b29b64451..09d6f5b00e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java @@ -24,12 +24,13 @@ import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import uk.co.real_logic.sbe.xml.XmlSchemaParser; +import java.io.InputStream; import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.StringContains.containsString; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; class NullEnumTypedTest { @@ -41,26 +42,29 @@ class NullEnumTypedTest @Test void shouldGenerateEnumWithNonDefaultNullType() throws Exception { - final ParserOptions options = ParserOptions.builder() - .stopOnError(true) - .build(); - final MessageSchema schema = parse(Tests.getLocalResource("issue889.xml"), options); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); + try (InputStream in = Tests.getLocalResource("issue889.xml")) + { + final ParserOptions options = ParserOptions.builder() + .stopOnError(true) + .build(); + final MessageSchema schema = XmlSchemaParser.parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); - final StringWriterOutputManager outputManager = new StringWriterOutputManager(); - final JavaGenerator generator = new JavaGenerator( - ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, true, outputManager); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, true, outputManager); - outputManager.setPackageName(ir.applicableNamespace()); - generator.generateMessageHeaderStub(); - generator.generateTypeStubs(); - generator.generate(); + outputManager.setPackageName(ir.applicableNamespace()); + generator.generateMessageHeaderStub(); + generator.generateTypeStubs(); + generator.generate(); - final Map sources = outputManager.getSources(); - final String source = sources.get("issue889.LotType").toString(); + final Map sources = outputManager.getSources(); + final String source = sources.get("issue889.LotType").toString(); - assertThat(source, containsString("NULL_VAL((short)0);")); - assertThat(source, containsString("case 0: return NULL_VAL;")); + assertThat(source, containsString("NULL_VAL((short)0);")); + assertThat(source, containsString("case 0: return NULL_VAL;")); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java index e9f3573272..36ef9bed42 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java @@ -15,8 +15,6 @@ */ package uk.co.real_logic.sbe.generation.java; -import java.util.Map; - import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; import org.agrona.generation.CompilerUtil; @@ -24,16 +22,16 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledForJreRange; import org.junit.jupiter.api.condition.JRE; - -import static org.junit.jupiter.api.Assertions.assertNotNull; - - import uk.co.real_logic.sbe.Tests; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import java.io.InputStream; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; public class QualifiedYieldTest @@ -49,24 +47,27 @@ public class QualifiedYieldTest @EnabledForJreRange(min = JRE.JAVA_17) void shouldGenerateValidJava() throws Exception { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("issue910.xml"), options); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final JavaGenerator generator = new JavaGenerator( - ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, false, outputManager); + try (InputStream in = Tests.getLocalResource("issue910.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, false, outputManager); - outputManager.setPackageName(ir.applicableNamespace()); - generator.generateMessageHeaderStub(); - generator.generateTypeStubs(); - generator.generate(); + outputManager.setPackageName(ir.applicableNamespace()); + generator.generateMessageHeaderStub(); + generator.generateTypeStubs(); + generator.generate(); - final Map sources = outputManager.getSources(); + final Map sources = outputManager.getSources(); - { - final String fqClassName = ir.applicableNamespace() + "." + "Issue910FieldDecoder"; - final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); - assertNotNull(aClass); + { + final String fqClassName = ir.applicableNamespace() + "." + "Issue910FieldDecoder"; + final Class aClass = CompilerUtil.compileInMemory(fqClassName, sources); + assertNotNull(aClass); + } } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index dcc8877b74..1774666139 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -27,16 +27,19 @@ import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import uk.co.real_logic.sbe.xml.XmlSchemaParser; +import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.*; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @SuppressWarnings("MethodLength") class SchemaExtensionTest @@ -53,10 +56,13 @@ class SchemaExtensionTest @BeforeEach void setup() throws Exception { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(Tests.getLocalResource("extension-schema.xml"), options); - final IrGenerator irg = new IrGenerator(); - ir = irg.generate(schema); + try (InputStream in = Tests.getLocalResource("extension-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = XmlSchemaParser.parse(in, options); + final IrGenerator irg = new IrGenerator(); + ir = irg.generate(schema); + } outputManager.clear(); outputManager.setPackageName(ir.applicableNamespace()); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java index cdafc79fdb..c626e044d4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java @@ -22,6 +22,7 @@ import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.*; +import java.io.InputStream; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -35,28 +36,30 @@ public class SinceVersionTransformedSchemaJavaGenerationTest @CsvSource({ "0,4", "4,5", "5,6" }) void shouldGenerateCodeForOlderVersion(final int versionIncluded, final int versionExcluded) throws Exception { - final MessageSchema schema = parse( - Tests.getLocalResource("since-version-filter-schema.xml"), ParserOptions.DEFAULT); - final SchemaTransformer transformer = new SchemaTransformerFactory("*:" + versionIncluded); - final MessageSchema transformedSchema = transformer.transform(schema); - final Ir ir = new IrGenerator().generate(transformedSchema); - final StringWriterOutputManager outputManager = new StringWriterOutputManager(); - outputManager.setPackageName("test"); + try (InputStream in = Tests.getLocalResource("since-version-filter-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final SchemaTransformer transformer = new SchemaTransformerFactory("*:" + versionIncluded); + final MessageSchema transformedSchema = transformer.transform(schema); + final Ir ir = new IrGenerator().generate(transformedSchema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName("test"); - final JavaGenerator javaGenerator = new JavaGenerator( - ir, - JAVA_DEFAULT_ENCODING_BUFFER_TYPE, - JAVA_DEFAULT_DECODING_BUFFER_TYPE, - false, - false, - false, - outputManager); + final JavaGenerator javaGenerator = new JavaGenerator( + ir, + JAVA_DEFAULT_ENCODING_BUFFER_TYPE, + JAVA_DEFAULT_DECODING_BUFFER_TYPE, + false, + false, + false, + outputManager); - javaGenerator.generate(); + javaGenerator.generate(); - final Map sources = outputManager.getSources(); - assertTrue(containsCodeWithSinceVersion(sources, versionIncluded)); - assertTrue(doesNotContainsCodeWithSinceVersion(sources, versionExcluded)); + final Map sources = outputManager.getSources(); + assertTrue(containsCodeWithSinceVersion(sources, versionIncluded)); + assertTrue(doesNotContainsCodeWithSinceVersion(sources, versionExcluded)); + } } private static boolean containsCodeWithSinceVersion(final Map sources, final int version) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java index 93a6a62183..f48ce8e830 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java @@ -19,36 +19,40 @@ import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import uk.co.real_logic.sbe.xml.XmlSchemaParser; import java.io.ByteArrayOutputStream; +import java.io.InputStream; import java.io.PrintStream; import java.nio.charset.StandardCharsets; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static uk.co.real_logic.sbe.Tests.getLocalResource; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; class WarningFormattingTest { @Test void shouldGenerateCorrectWarning() throws Exception { - final ByteArrayOutputStream out = new ByteArrayOutputStream(); - final ParserOptions options = new ParserOptions.Builder() - .stopOnError(true) - .errorPrintStream(new PrintStream(out)) - .build(); - final MessageSchema schema = parse(getLocalResource("npe-small-header.xml"), options); - final IrGenerator irg = new IrGenerator(); - irg.generate(schema); + try (InputStream in = getLocalResource("npe-small-header.xml")) + { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final ParserOptions options = new ParserOptions.Builder() + .stopOnError(true) + .errorPrintStream(new PrintStream(out)) + .build(); + final MessageSchema schema = XmlSchemaParser.parse(in, options); + final IrGenerator irg = new IrGenerator(); + irg.generate(schema); - final String warnings = out.toString(StandardCharsets.US_ASCII.name()); - assertThat(warnings, containsString( - "WARNING: at \"blockLength\" should be UINT16")); - assertThat(warnings, containsString( - "WARNING: at \"templateId\" should be UINT16")); - assertThat(warnings, containsString( - "WARNING: at \"version\" should be UINT16")); + final String warnings = out.toString(StandardCharsets.US_ASCII.name()); + assertThat(warnings, containsString( + "WARNING: at \"blockLength\" should be UINT16")); + assertThat(warnings, containsString( + "WARNING: at \"templateId\" should be UINT16")); + assertThat(warnings, containsString( + "WARNING: at \"version\" should be UINT16")); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index b5932aa7f9..e99a73f272 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -21,6 +21,7 @@ import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import java.io.InputStream; import java.nio.ByteOrder; import java.util.List; @@ -34,263 +35,277 @@ class BasicXmlIrGenerationTest @Test void shouldGenerateIrForMessageHeader() throws Exception { - final MessageSchema schema = parse(getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - - final Ir ir = irg.generate(schema); - final List tokens = ir.headerStructure().tokens(); - - assertThat(tokens.size(), is(6)); - - /* assert all elements of node 0 */ - assertThat(tokens.get(0).signal(), is(Signal.BEGIN_COMPOSITE)); - assertThat(tokens.get(0).name(), is("messageHeader")); - assertThat(tokens.get(0).id(), is(Token.INVALID_ID)); - assertThat(tokens.get(0).encodedLength(), is(8)); - assertThat(tokens.get(0).offset(), is(0)); - - /* assert all elements of node 1 */ - assertThat(tokens.get(1).signal(), is(Signal.ENCODING)); - assertThat(tokens.get(1).name(), is("blockLength")); - assertThat(tokens.get(1).encoding().primitiveType(), is(PrimitiveType.UINT16)); - assertThat(tokens.get(1).id(), is(Token.INVALID_ID)); - assertThat(tokens.get(1).encodedLength(), is(2)); - assertThat(tokens.get(1).offset(), is(0)); - assertThat(tokens.get(1).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); - - /* assert all elements of node 2 */ - assertThat(tokens.get(2).signal(), is(Signal.ENCODING)); - assertThat(tokens.get(2).name(), is("templateId")); - assertThat(tokens.get(2).encoding().primitiveType(), is(PrimitiveType.UINT16)); - assertThat(tokens.get(2).id(), is(Token.INVALID_ID)); - assertThat(tokens.get(2).encodedLength(), is(2)); - assertThat(tokens.get(2).offset(), is(2)); - assertThat(tokens.get(2).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); - - /* assert all elements of node 3 */ - assertThat(tokens.get(3).signal(), is(Signal.ENCODING)); - assertThat(tokens.get(3).name(), is("schemaId")); - assertThat(tokens.get(3).encoding().primitiveType(), is(PrimitiveType.UINT16)); - assertThat(tokens.get(3).id(), is(Token.INVALID_ID)); - assertThat(tokens.get(3).encodedLength(), is(2)); - assertThat(tokens.get(3).offset(), is(4)); - assertThat(tokens.get(3).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); - - /* assert all elements of node 4 */ - assertThat(tokens.get(4).signal(), is(Signal.ENCODING)); - assertThat(tokens.get(4).name(), is("version")); - assertThat(tokens.get(4).encoding().primitiveType(), is(PrimitiveType.UINT16)); - assertThat(tokens.get(4).id(), is(Token.INVALID_ID)); - assertThat(tokens.get(4).encodedLength(), is(2)); - assertThat(tokens.get(4).offset(), is(6)); - assertThat(tokens.get(4).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); - - /* assert all elements of node 6 */ - assertThat(tokens.get(5).signal(), is(Signal.END_COMPOSITE)); - assertThat(tokens.get(5).name(), is("messageHeader")); - assertThat(tokens.get(5).id(), is(Token.INVALID_ID)); - assertThat(tokens.get(5).encodedLength(), is(8)); - assertThat(tokens.get(5).offset(), is(0)); + try (InputStream in = getLocalResource("basic-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + + final Ir ir = irg.generate(schema); + final List tokens = ir.headerStructure().tokens(); + + assertThat(tokens.size(), is(6)); + + /* assert all elements of node 0 */ + assertThat(tokens.get(0).signal(), is(Signal.BEGIN_COMPOSITE)); + assertThat(tokens.get(0).name(), is("messageHeader")); + assertThat(tokens.get(0).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(0).encodedLength(), is(8)); + assertThat(tokens.get(0).offset(), is(0)); + + /* assert all elements of node 1 */ + assertThat(tokens.get(1).signal(), is(Signal.ENCODING)); + assertThat(tokens.get(1).name(), is("blockLength")); + assertThat(tokens.get(1).encoding().primitiveType(), is(PrimitiveType.UINT16)); + assertThat(tokens.get(1).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(1).encodedLength(), is(2)); + assertThat(tokens.get(1).offset(), is(0)); + assertThat(tokens.get(1).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); + + /* assert all elements of node 2 */ + assertThat(tokens.get(2).signal(), is(Signal.ENCODING)); + assertThat(tokens.get(2).name(), is("templateId")); + assertThat(tokens.get(2).encoding().primitiveType(), is(PrimitiveType.UINT16)); + assertThat(tokens.get(2).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(2).encodedLength(), is(2)); + assertThat(tokens.get(2).offset(), is(2)); + assertThat(tokens.get(2).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); + + /* assert all elements of node 3 */ + assertThat(tokens.get(3).signal(), is(Signal.ENCODING)); + assertThat(tokens.get(3).name(), is("schemaId")); + assertThat(tokens.get(3).encoding().primitiveType(), is(PrimitiveType.UINT16)); + assertThat(tokens.get(3).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(3).encodedLength(), is(2)); + assertThat(tokens.get(3).offset(), is(4)); + assertThat(tokens.get(3).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); + + /* assert all elements of node 4 */ + assertThat(tokens.get(4).signal(), is(Signal.ENCODING)); + assertThat(tokens.get(4).name(), is("version")); + assertThat(tokens.get(4).encoding().primitiveType(), is(PrimitiveType.UINT16)); + assertThat(tokens.get(4).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(4).encodedLength(), is(2)); + assertThat(tokens.get(4).offset(), is(6)); + assertThat(tokens.get(4).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); + + /* assert all elements of node 6 */ + assertThat(tokens.get(5).signal(), is(Signal.END_COMPOSITE)); + assertThat(tokens.get(5).name(), is("messageHeader")); + assertThat(tokens.get(5).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(5).encodedLength(), is(8)); + assertThat(tokens.get(5).offset(), is(0)); + } } @Test void shouldGenerateIrForBasicMessage() throws Exception { - final MessageSchema schema = parse(getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - - final List tokens = ir.getMessage(50001); - - assertThat(tokens.size(), is(5)); - - /* assert all elements of node 0 */ - assertThat(tokens.get(0).signal(), is(Signal.BEGIN_MESSAGE)); - assertThat(tokens.get(0).name(), is("TestMessage50001")); - assertThat(tokens.get(0).id(), is(50001)); - assertThat(tokens.get(0).encodedLength(), is(16)); - assertThat(tokens.get(0).offset(), is(0)); - - /* assert all elements of node 1 */ - assertThat(tokens.get(1).signal(), is(Signal.BEGIN_FIELD)); - assertThat(tokens.get(1).name(), is("Tag40001")); - assertThat(tokens.get(1).id(), is(40001)); - assertThat(tokens.get(1).encodedLength(), is(4)); - assertThat(tokens.get(1).offset(), is(0)); - - /* assert all elements of node 2 */ - assertThat(tokens.get(2).signal(), is(Signal.ENCODING)); - assertThat(tokens.get(2).name(), is("uint32")); - assertThat(tokens.get(2).encoding().primitiveType(), is(PrimitiveType.UINT32)); - assertThat(tokens.get(2).id(), is(Token.INVALID_ID)); - assertThat(tokens.get(2).encodedLength(), is(4)); - assertThat(tokens.get(2).offset(), is(0)); - assertThat(tokens.get(2).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); - - /* assert all elements of node 3 */ - assertThat(tokens.get(3).signal(), is(Signal.END_FIELD)); - assertThat(tokens.get(3).name(), is("Tag40001")); - assertThat(tokens.get(3).id(), is(40001)); - assertThat(tokens.get(3).encodedLength(), is(4)); - assertThat(tokens.get(3).offset(), is(0)); - - /* assert all elements of node 4 */ - assertThat(tokens.get(4).signal(), is(Signal.END_MESSAGE)); - assertThat(tokens.get(4).name(), is("TestMessage50001")); - assertThat(tokens.get(4).id(), is(50001)); - assertThat(tokens.get(4).encodedLength(), is(16)); - assertThat(tokens.get(4).offset(), is(0)); + try (InputStream in = getLocalResource("basic-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + final List tokens = ir.getMessage(50001); + + assertThat(tokens.size(), is(5)); + + /* assert all elements of node 0 */ + assertThat(tokens.get(0).signal(), is(Signal.BEGIN_MESSAGE)); + assertThat(tokens.get(0).name(), is("TestMessage50001")); + assertThat(tokens.get(0).id(), is(50001)); + assertThat(tokens.get(0).encodedLength(), is(16)); + assertThat(tokens.get(0).offset(), is(0)); + + /* assert all elements of node 1 */ + assertThat(tokens.get(1).signal(), is(Signal.BEGIN_FIELD)); + assertThat(tokens.get(1).name(), is("Tag40001")); + assertThat(tokens.get(1).id(), is(40001)); + assertThat(tokens.get(1).encodedLength(), is(4)); + assertThat(tokens.get(1).offset(), is(0)); + + /* assert all elements of node 2 */ + assertThat(tokens.get(2).signal(), is(Signal.ENCODING)); + assertThat(tokens.get(2).name(), is("uint32")); + assertThat(tokens.get(2).encoding().primitiveType(), is(PrimitiveType.UINT32)); + assertThat(tokens.get(2).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(2).encodedLength(), is(4)); + assertThat(tokens.get(2).offset(), is(0)); + assertThat(tokens.get(2).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); + + /* assert all elements of node 3 */ + assertThat(tokens.get(3).signal(), is(Signal.END_FIELD)); + assertThat(tokens.get(3).name(), is("Tag40001")); + assertThat(tokens.get(3).id(), is(40001)); + assertThat(tokens.get(3).encodedLength(), is(4)); + assertThat(tokens.get(3).offset(), is(0)); + + /* assert all elements of node 4 */ + assertThat(tokens.get(4).signal(), is(Signal.END_MESSAGE)); + assertThat(tokens.get(4).name(), is("TestMessage50001")); + assertThat(tokens.get(4).id(), is(50001)); + assertThat(tokens.get(4).encodedLength(), is(16)); + assertThat(tokens.get(4).offset(), is(0)); + } } @Test void shouldGenerateIrForMessageWithVariableLengthField() throws Exception { - final MessageSchema schema = parse(getLocalResource( - "basic-variable-length-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - - final List tokens = ir.getMessage(1); - - assertThat(tokens.size(), is(8)); - - assertThat(tokens.get(0).signal(), is(Signal.BEGIN_MESSAGE)); - assertThat(tokens.get(0).name(), is("TestMessage1")); - assertThat(tokens.get(0).id(), is(1)); - assertThat(tokens.get(0).encodedLength(), is(0)); - assertThat(tokens.get(0).offset(), is(0)); - - assertThat(tokens.get(1).signal(), is(Signal.BEGIN_VAR_DATA)); - assertThat(tokens.get(1).name(), is("encryptedNewPassword")); - assertThat(tokens.get(1).id(), is(1404)); - assertThat(tokens.get(1).encodedLength(), is(0)); - assertThat(tokens.get(1).offset(), is(0)); - - assertThat(tokens.get(2).signal(), is(Signal.BEGIN_COMPOSITE)); - assertThat(tokens.get(2).name(), is("varDataEncoding")); - assertThat(tokens.get(2).encodedLength(), is(-1)); - assertThat(tokens.get(2).offset(), is(0)); - - assertThat(tokens.get(3).signal(), is(Signal.ENCODING)); - assertThat(tokens.get(3).name(), is("length")); - assertThat(tokens.get(3).encoding().primitiveType(), is(PrimitiveType.UINT8)); - assertThat(tokens.get(3).id(), is(Token.INVALID_ID)); - assertThat(tokens.get(3).encodedLength(), is(1)); - assertThat(tokens.get(3).offset(), is(0)); - assertThat(tokens.get(3).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); - - assertThat(tokens.get(4).signal(), is(Signal.ENCODING)); - assertThat(tokens.get(4).name(), is("varData")); - assertThat(tokens.get(4).encoding().primitiveType(), is(PrimitiveType.CHAR)); - assertThat(tokens.get(4).id(), is(Token.INVALID_ID)); - assertThat(tokens.get(4).encodedLength(), is(-1)); - assertThat(tokens.get(4).offset(), is(1)); - assertThat(tokens.get(4).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); - - assertThat(tokens.get(5).signal(), is(Signal.END_COMPOSITE)); - assertThat(tokens.get(5).name(), is("varDataEncoding")); - assertThat(tokens.get(5).encodedLength(), is(-1)); - assertThat(tokens.get(5).offset(), is(0)); - - assertThat(tokens.get(6).signal(), is(Signal.END_VAR_DATA)); - assertThat(tokens.get(6).name(), is("encryptedNewPassword")); - assertThat(tokens.get(6).id(), is(1404)); - assertThat(tokens.get(6).encodedLength(), is(0)); - assertThat(tokens.get(6).offset(), is(0)); - - assertThat(tokens.get(7).signal(), is(Signal.END_MESSAGE)); - assertThat(tokens.get(7).name(), is("TestMessage1")); - assertThat(tokens.get(7).id(), is(1)); - assertThat(tokens.get(7).encodedLength(), is(0)); - assertThat(tokens.get(7).offset(), is(0)); + try (InputStream in = getLocalResource("basic-variable-length-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + final List tokens = ir.getMessage(1); + + assertThat(tokens.size(), is(8)); + + assertThat(tokens.get(0).signal(), is(Signal.BEGIN_MESSAGE)); + assertThat(tokens.get(0).name(), is("TestMessage1")); + assertThat(tokens.get(0).id(), is(1)); + assertThat(tokens.get(0).encodedLength(), is(0)); + assertThat(tokens.get(0).offset(), is(0)); + + assertThat(tokens.get(1).signal(), is(Signal.BEGIN_VAR_DATA)); + assertThat(tokens.get(1).name(), is("encryptedNewPassword")); + assertThat(tokens.get(1).id(), is(1404)); + assertThat(tokens.get(1).encodedLength(), is(0)); + assertThat(tokens.get(1).offset(), is(0)); + + assertThat(tokens.get(2).signal(), is(Signal.BEGIN_COMPOSITE)); + assertThat(tokens.get(2).name(), is("varDataEncoding")); + assertThat(tokens.get(2).encodedLength(), is(-1)); + assertThat(tokens.get(2).offset(), is(0)); + + assertThat(tokens.get(3).signal(), is(Signal.ENCODING)); + assertThat(tokens.get(3).name(), is("length")); + assertThat(tokens.get(3).encoding().primitiveType(), is(PrimitiveType.UINT8)); + assertThat(tokens.get(3).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(3).encodedLength(), is(1)); + assertThat(tokens.get(3).offset(), is(0)); + assertThat(tokens.get(3).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); + + assertThat(tokens.get(4).signal(), is(Signal.ENCODING)); + assertThat(tokens.get(4).name(), is("varData")); + assertThat(tokens.get(4).encoding().primitiveType(), is(PrimitiveType.CHAR)); + assertThat(tokens.get(4).id(), is(Token.INVALID_ID)); + assertThat(tokens.get(4).encodedLength(), is(-1)); + assertThat(tokens.get(4).offset(), is(1)); + assertThat(tokens.get(4).encoding().byteOrder(), is(ByteOrder.LITTLE_ENDIAN)); + + assertThat(tokens.get(5).signal(), is(Signal.END_COMPOSITE)); + assertThat(tokens.get(5).name(), is("varDataEncoding")); + assertThat(tokens.get(5).encodedLength(), is(-1)); + assertThat(tokens.get(5).offset(), is(0)); + + assertThat(tokens.get(6).signal(), is(Signal.END_VAR_DATA)); + assertThat(tokens.get(6).name(), is("encryptedNewPassword")); + assertThat(tokens.get(6).id(), is(1404)); + assertThat(tokens.get(6).encodedLength(), is(0)); + assertThat(tokens.get(6).offset(), is(0)); + + assertThat(tokens.get(7).signal(), is(Signal.END_MESSAGE)); + assertThat(tokens.get(7).name(), is("TestMessage1")); + assertThat(tokens.get(7).id(), is(1)); + assertThat(tokens.get(7).encodedLength(), is(0)); + assertThat(tokens.get(7).offset(), is(0)); + } } @Test void shouldGenerateIrForMessageWithRepeatingGroupWithEmbeddedDimensions() throws Exception { - final MessageSchema schema = parse(getLocalResource( - "basic-group-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - - /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=group, 5=comp, 6=enc, 7=enc, 8=compend, ... */ - final int groupIdx = 4; - final int dimensionsCompIdx = 5; - final int dimensionsBlEncIdx = 6; - final int dimensionsNigEncIdx = 7; - - final List tokens = ir.getMessage(1); - - /* assert on the group token */ - assertThat(tokens.get(groupIdx).signal(), is(Signal.BEGIN_GROUP)); - assertThat(tokens.get(groupIdx).name(), is("Entries")); - assertThat(tokens.get(groupIdx).id(), is(2)); - - /* assert on the comp token for dimensions */ - assertThat(tokens.get(dimensionsCompIdx).signal(), is(Signal.BEGIN_COMPOSITE)); - assertThat(tokens.get(dimensionsCompIdx).name(), is("groupSizeEncoding")); - - /* assert on the enc token for dimensions blockLength */ - assertThat(tokens.get(dimensionsBlEncIdx).signal(), is(Signal.ENCODING)); - assertThat(tokens.get(dimensionsBlEncIdx).name(), is("blockLength")); - - /* assert on the enc token for dimensions numInGroup */ - assertThat(tokens.get(dimensionsNigEncIdx).signal(), is(Signal.ENCODING)); - assertThat(tokens.get(dimensionsNigEncIdx).name(), is("numInGroup")); + try (InputStream in = getLocalResource("basic-group-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=group, 5=comp, 6=enc, 7=enc, 8=compend, ... */ + final int groupIdx = 4; + final int dimensionsCompIdx = 5; + final int dimensionsBlEncIdx = 6; + final int dimensionsNigEncIdx = 7; + + final List tokens = ir.getMessage(1); + + /* assert on the group token */ + assertThat(tokens.get(groupIdx).signal(), is(Signal.BEGIN_GROUP)); + assertThat(tokens.get(groupIdx).name(), is("Entries")); + assertThat(tokens.get(groupIdx).id(), is(2)); + + /* assert on the comp token for dimensions */ + assertThat(tokens.get(dimensionsCompIdx).signal(), is(Signal.BEGIN_COMPOSITE)); + assertThat(tokens.get(dimensionsCompIdx).name(), is("groupSizeEncoding")); + + /* assert on the enc token for dimensions blockLength */ + assertThat(tokens.get(dimensionsBlEncIdx).signal(), is(Signal.ENCODING)); + assertThat(tokens.get(dimensionsBlEncIdx).name(), is("blockLength")); + + /* assert on the enc token for dimensions numInGroup */ + assertThat(tokens.get(dimensionsNigEncIdx).signal(), is(Signal.ENCODING)); + assertThat(tokens.get(dimensionsNigEncIdx).name(), is("numInGroup")); + } } @Test void shouldGenerateIrForMessageWithRepeatingGroupWithEmbeddedDimensionsDefaultDimensionType() throws Exception { - final MessageSchema schema = parse(getLocalResource( - "embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); + try (InputStream in = getLocalResource("embedded-length-and-count-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); - /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=group, 5=comp, 6=enc, 7=enc, 8=compend, 9=field, ... */ - final int groupIdx = 4; - final int dimensionsCompIdx = 5; - final int fieldInGroupIdx = 9; + /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=group, 5=comp, 6=enc, 7=enc, 8=compend, 9=field, ... */ + final int groupIdx = 4; + final int dimensionsCompIdx = 5; + final int fieldInGroupIdx = 9; - final List tokens = ir.getMessage(1); + final List tokens = ir.getMessage(1); - assertThat(tokens.get(groupIdx).signal(), is(Signal.BEGIN_GROUP)); - assertThat(tokens.get(groupIdx).name(), is("ListOrdGrp")); - assertThat(tokens.get(groupIdx).id(), is(73)); + assertThat(tokens.get(groupIdx).signal(), is(Signal.BEGIN_GROUP)); + assertThat(tokens.get(groupIdx).name(), is("ListOrdGrp")); + assertThat(tokens.get(groupIdx).id(), is(73)); - assertThat(tokens.get(dimensionsCompIdx).signal(), is(Signal.BEGIN_COMPOSITE)); - assertThat(tokens.get(dimensionsCompIdx).name(), is("groupSizeEncoding")); + assertThat(tokens.get(dimensionsCompIdx).signal(), is(Signal.BEGIN_COMPOSITE)); + assertThat(tokens.get(dimensionsCompIdx).name(), is("groupSizeEncoding")); - assertThat(tokens.get(fieldInGroupIdx).signal(), is(Signal.BEGIN_FIELD)); - assertThat(tokens.get(fieldInGroupIdx).name(), is("ClOrdID")); + assertThat(tokens.get(fieldInGroupIdx).signal(), is(Signal.BEGIN_FIELD)); + assertThat(tokens.get(fieldInGroupIdx).name(), is("ClOrdID")); + } } @Test void shouldGenerateIrForMessageWithVariableLengthFieldWithEmbeddedLength() throws Exception { - final MessageSchema schema = parse(getLocalResource( - "embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - - /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=field, 5=comp, 6=enc, 7=enc, 8=compend, 9=fieldend */ - final int lengthFieldIdx = 4; - final int lengthEncIdx = 6; - final int dataEncIdx = 7; - - final List tokens = ir.getMessage(2); - - /* assert the varDataEncoding field node is formed correctly */ - assertThat(tokens.get(lengthFieldIdx).signal(), is(Signal.BEGIN_VAR_DATA)); - assertThat(tokens.get(lengthFieldIdx).name(), is("EncryptedPassword")); - assertThat(tokens.get(lengthFieldIdx).id(), is(1402)); - - /* assert the length node has correct values */ - assertThat(tokens.get(lengthEncIdx).signal(), is(Signal.ENCODING)); - assertThat(tokens.get(lengthEncIdx).encoding().primitiveType(), is(PrimitiveType.UINT8)); - - /* assert the group node has the right IrId and xRefIrId, etc. */ - assertThat(tokens.get(dataEncIdx).signal(), is(Signal.ENCODING)); - assertThat(tokens.get(dataEncIdx).encoding().primitiveType(), is(PrimitiveType.CHAR)); + try (InputStream in = getLocalResource("embedded-length-and-count-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=field, 5=comp, 6=enc, 7=enc, 8=compend, 9=fieldend */ + final int lengthFieldIdx = 4; + final int lengthEncIdx = 6; + final int dataEncIdx = 7; + + final List tokens = ir.getMessage(2); + + /* assert the varDataEncoding field node is formed correctly */ + assertThat(tokens.get(lengthFieldIdx).signal(), is(Signal.BEGIN_VAR_DATA)); + assertThat(tokens.get(lengthFieldIdx).name(), is("EncryptedPassword")); + assertThat(tokens.get(lengthFieldIdx).id(), is(1402)); + + /* assert the length node has correct values */ + assertThat(tokens.get(lengthEncIdx).signal(), is(Signal.ENCODING)); + assertThat(tokens.get(lengthEncIdx).encoding().primitiveType(), is(PrimitiveType.UINT8)); + + /* assert the group node has the right IrId and xRefIrId, etc. */ + assertThat(tokens.get(dataEncIdx).signal(), is(Signal.ENCODING)); + assertThat(tokens.get(dataEncIdx).encoding().primitiveType(), is(PrimitiveType.CHAR)); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java index 3e92466bbd..cf900c22d0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java @@ -21,6 +21,7 @@ import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import java.io.InputStream; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; @@ -33,156 +34,162 @@ class CompositeElementsIrTest @Test void shouldGenerateIrForCompositeElementsSchema() throws Exception { - final MessageSchema schema = parse(getLocalResource( - "composite-elements-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final List tokens = ir.getMessage(1); - - final Token fieldToken = tokens.get(1); - final Token outerCompositeToken = tokens.get(2); - final Token enumToken = tokens.get(3); - final Token zerothToken = tokens.get(7); - final Token setToken = tokens.get(8); - final Token innerCompositeToken = tokens.get(13); - final Token firstToken = tokens.get(14); - final Token secondToken = tokens.get(15); - final Token endOuterCompositeToken = tokens.get(17); - - assertThat(fieldToken.signal(), is(Signal.BEGIN_FIELD)); - assertThat(fieldToken.name(), is("structure")); - - assertThat(outerCompositeToken.signal(), is(Signal.BEGIN_COMPOSITE)); - assertThat(outerCompositeToken.name(), is("outer")); - assertThat(outerCompositeToken.componentTokenCount(), is(16)); - - assertThat(enumToken.signal(), is(Signal.BEGIN_ENUM)); - assertThat(enumToken.name(), is("enumOne")); - assertThat(enumToken.encodedLength(), is(1)); - assertThat(enumToken.encoding().primitiveType(), is(PrimitiveType.UINT8)); - assertThat(enumToken.offset(), is(0)); - assertThat(enumToken.componentTokenCount(), is(4)); - - assertThat(zerothToken.signal(), is(Signal.ENCODING)); - assertThat(zerothToken.offset(), is(1)); - assertThat(zerothToken.encoding().primitiveType(), is(PrimitiveType.UINT8)); - - assertThat(setToken.signal(), is(Signal.BEGIN_SET)); - assertThat(setToken.name(), is("setOne")); - assertThat(setToken.encodedLength(), is(4)); - assertThat(setToken.encoding().primitiveType(), is(PrimitiveType.UINT32)); - assertThat(setToken.offset(), is(2)); - assertThat(setToken.componentTokenCount(), is(5)); - - assertThat(innerCompositeToken.signal(), is(Signal.BEGIN_COMPOSITE)); - assertThat(innerCompositeToken.name(), is("inner")); - assertThat(innerCompositeToken.offset(), is(6)); - assertThat(innerCompositeToken.componentTokenCount(), is(4)); - - assertThat(firstToken.signal(), is(Signal.ENCODING)); - assertThat(firstToken.name(), is("first")); - assertThat(firstToken.offset(), is(0)); - assertThat(firstToken.encoding().primitiveType(), is(PrimitiveType.INT64)); - - assertThat(secondToken.signal(), is(Signal.ENCODING)); - assertThat(secondToken.name(), is("second")); - assertThat(secondToken.offset(), is(8)); - assertThat(secondToken.encoding().primitiveType(), is(PrimitiveType.INT64)); - - assertThat(endOuterCompositeToken.signal(), is(Signal.END_COMPOSITE)); - assertThat(endOuterCompositeToken.name(), is("outer")); + try (InputStream in = getLocalResource("composite-elements-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final List tokens = ir.getMessage(1); + + final Token fieldToken = tokens.get(1); + final Token outerCompositeToken = tokens.get(2); + final Token enumToken = tokens.get(3); + final Token zerothToken = tokens.get(7); + final Token setToken = tokens.get(8); + final Token innerCompositeToken = tokens.get(13); + final Token firstToken = tokens.get(14); + final Token secondToken = tokens.get(15); + final Token endOuterCompositeToken = tokens.get(17); + + assertThat(fieldToken.signal(), is(Signal.BEGIN_FIELD)); + assertThat(fieldToken.name(), is("structure")); + + assertThat(outerCompositeToken.signal(), is(Signal.BEGIN_COMPOSITE)); + assertThat(outerCompositeToken.name(), is("outer")); + assertThat(outerCompositeToken.componentTokenCount(), is(16)); + + assertThat(enumToken.signal(), is(Signal.BEGIN_ENUM)); + assertThat(enumToken.name(), is("enumOne")); + assertThat(enumToken.encodedLength(), is(1)); + assertThat(enumToken.encoding().primitiveType(), is(PrimitiveType.UINT8)); + assertThat(enumToken.offset(), is(0)); + assertThat(enumToken.componentTokenCount(), is(4)); + + assertThat(zerothToken.signal(), is(Signal.ENCODING)); + assertThat(zerothToken.offset(), is(1)); + assertThat(zerothToken.encoding().primitiveType(), is(PrimitiveType.UINT8)); + + assertThat(setToken.signal(), is(Signal.BEGIN_SET)); + assertThat(setToken.name(), is("setOne")); + assertThat(setToken.encodedLength(), is(4)); + assertThat(setToken.encoding().primitiveType(), is(PrimitiveType.UINT32)); + assertThat(setToken.offset(), is(2)); + assertThat(setToken.componentTokenCount(), is(5)); + + assertThat(innerCompositeToken.signal(), is(Signal.BEGIN_COMPOSITE)); + assertThat(innerCompositeToken.name(), is("inner")); + assertThat(innerCompositeToken.offset(), is(6)); + assertThat(innerCompositeToken.componentTokenCount(), is(4)); + + assertThat(firstToken.signal(), is(Signal.ENCODING)); + assertThat(firstToken.name(), is("first")); + assertThat(firstToken.offset(), is(0)); + assertThat(firstToken.encoding().primitiveType(), is(PrimitiveType.INT64)); + + assertThat(secondToken.signal(), is(Signal.ENCODING)); + assertThat(secondToken.name(), is("second")); + assertThat(secondToken.offset(), is(8)); + assertThat(secondToken.encoding().primitiveType(), is(PrimitiveType.INT64)); + + assertThat(endOuterCompositeToken.signal(), is(Signal.END_COMPOSITE)); + assertThat(endOuterCompositeToken.name(), is("outer")); + } } @Test void shouldGenerateIrForCompositeElementsWithOffsetsSchemaRc4() throws Exception { - final MessageSchema schema = parse(getLocalResource( - "composite-elements-schema-rc4.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final List tokens = ir.getMessage(2); - - final Token outerCompositeToken = tokens.get(2); - final Token enumToken = tokens.get(3); - final Token zerothToken = tokens.get(7); - final Token setToken = tokens.get(8); - final Token innerCompositeToken = tokens.get(13); - final Token firstToken = tokens.get(14); - final Token secondToken = tokens.get(15); - final Token endOuterCompositeToken = tokens.get(17); - - assertThat(outerCompositeToken.signal(), is(Signal.BEGIN_COMPOSITE)); - assertThat(outerCompositeToken.name(), is("outerWithOffsets")); - assertThat(outerCompositeToken.encodedLength(), is(32)); - - assertThat(enumToken.signal(), is(Signal.BEGIN_ENUM)); - assertThat(enumToken.encodedLength(), is(1)); - assertThat(enumToken.encoding().primitiveType(), is(PrimitiveType.UINT8)); - assertThat(enumToken.offset(), is(2)); - - assertThat(zerothToken.signal(), is(Signal.ENCODING)); - assertThat(zerothToken.offset(), is(3)); - assertThat(zerothToken.encoding().primitiveType(), is(PrimitiveType.UINT8)); - - assertThat(setToken.signal(), is(Signal.BEGIN_SET)); - assertThat(setToken.name(), is("setOne")); - assertThat(setToken.encodedLength(), is(4)); - assertThat(setToken.encoding().primitiveType(), is(PrimitiveType.UINT32)); - assertThat(setToken.offset(), is(8)); - - assertThat(innerCompositeToken.signal(), is(Signal.BEGIN_COMPOSITE)); - assertThat(innerCompositeToken.name(), is("inner")); - assertThat(innerCompositeToken.offset(), is(16)); - - assertThat(firstToken.signal(), is(Signal.ENCODING)); - assertThat(firstToken.name(), is("first")); - assertThat(firstToken.offset(), is(0)); - assertThat(firstToken.encoding().primitiveType(), is(PrimitiveType.INT64)); - - assertThat(secondToken.signal(), is(Signal.ENCODING)); - assertThat(secondToken.name(), is("second")); - assertThat(secondToken.offset(), is(8)); - assertThat(secondToken.encoding().primitiveType(), is(PrimitiveType.INT64)); - - assertThat(endOuterCompositeToken.signal(), is(Signal.END_COMPOSITE)); - assertThat(endOuterCompositeToken.name(), is("outerWithOffsets")); + try (InputStream in = getLocalResource("composite-elements-schema-rc4.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final List tokens = ir.getMessage(2); + + final Token outerCompositeToken = tokens.get(2); + final Token enumToken = tokens.get(3); + final Token zerothToken = tokens.get(7); + final Token setToken = tokens.get(8); + final Token innerCompositeToken = tokens.get(13); + final Token firstToken = tokens.get(14); + final Token secondToken = tokens.get(15); + final Token endOuterCompositeToken = tokens.get(17); + + assertThat(outerCompositeToken.signal(), is(Signal.BEGIN_COMPOSITE)); + assertThat(outerCompositeToken.name(), is("outerWithOffsets")); + assertThat(outerCompositeToken.encodedLength(), is(32)); + + assertThat(enumToken.signal(), is(Signal.BEGIN_ENUM)); + assertThat(enumToken.encodedLength(), is(1)); + assertThat(enumToken.encoding().primitiveType(), is(PrimitiveType.UINT8)); + assertThat(enumToken.offset(), is(2)); + + assertThat(zerothToken.signal(), is(Signal.ENCODING)); + assertThat(zerothToken.offset(), is(3)); + assertThat(zerothToken.encoding().primitiveType(), is(PrimitiveType.UINT8)); + + assertThat(setToken.signal(), is(Signal.BEGIN_SET)); + assertThat(setToken.name(), is("setOne")); + assertThat(setToken.encodedLength(), is(4)); + assertThat(setToken.encoding().primitiveType(), is(PrimitiveType.UINT32)); + assertThat(setToken.offset(), is(8)); + + assertThat(innerCompositeToken.signal(), is(Signal.BEGIN_COMPOSITE)); + assertThat(innerCompositeToken.name(), is("inner")); + assertThat(innerCompositeToken.offset(), is(16)); + + assertThat(firstToken.signal(), is(Signal.ENCODING)); + assertThat(firstToken.name(), is("first")); + assertThat(firstToken.offset(), is(0)); + assertThat(firstToken.encoding().primitiveType(), is(PrimitiveType.INT64)); + + assertThat(secondToken.signal(), is(Signal.ENCODING)); + assertThat(secondToken.name(), is("second")); + assertThat(secondToken.offset(), is(8)); + assertThat(secondToken.encoding().primitiveType(), is(PrimitiveType.INT64)); + + assertThat(endOuterCompositeToken.signal(), is(Signal.END_COMPOSITE)); + assertThat(endOuterCompositeToken.name(), is("outerWithOffsets")); + } } @Test void shouldGenerateIrForCompositeWithRefSchema() throws Exception { - final MessageSchema schema = parse(getLocalResource( - "composite-elements-schema-rc4.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final List tokens = ir.getMessage(3); - - final Token beginCompositeToken = tokens.get(2); - final Token mantissaToken = tokens.get(3); - final Token exponentToken = tokens.get(4); - final Token enumToken = tokens.get(5); - final Token endCompositeToken = tokens.get(9); - - assertThat(beginCompositeToken.signal(), is(Signal.BEGIN_COMPOSITE)); - assertThat(beginCompositeToken.name(), is("futuresPrice")); - assertThat(beginCompositeToken.encodedLength(), is(11)); - - assertThat(mantissaToken.signal(), is(Signal.ENCODING)); - assertThat(mantissaToken.name(), is("mantissa")); - assertThat(mantissaToken.offset(), is(0)); - assertThat(mantissaToken.encoding().primitiveType(), is(PrimitiveType.INT64)); - - assertThat(exponentToken.signal(), is(Signal.ENCODING)); - assertThat(exponentToken.name(), is("exponent")); - assertThat(exponentToken.offset(), is(8)); - assertThat(exponentToken.encoding().primitiveType(), is(PrimitiveType.INT8)); - - assertThat(enumToken.signal(), is(Signal.BEGIN_ENUM)); - assertThat(enumToken.encodedLength(), is(1)); - assertThat(enumToken.encoding().primitiveType(), is(PrimitiveType.UINT8)); - assertThat(enumToken.offset(), is(10)); - - assertThat(endCompositeToken.signal(), is(Signal.END_COMPOSITE)); - assertThat(endCompositeToken.name(), is("futuresPrice")); + try (InputStream in = getLocalResource("composite-elements-schema-rc4.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final List tokens = ir.getMessage(3); + + final Token beginCompositeToken = tokens.get(2); + final Token mantissaToken = tokens.get(3); + final Token exponentToken = tokens.get(4); + final Token enumToken = tokens.get(5); + final Token endCompositeToken = tokens.get(9); + + assertThat(beginCompositeToken.signal(), is(Signal.BEGIN_COMPOSITE)); + assertThat(beginCompositeToken.name(), is("futuresPrice")); + assertThat(beginCompositeToken.encodedLength(), is(11)); + + assertThat(mantissaToken.signal(), is(Signal.ENCODING)); + assertThat(mantissaToken.name(), is("mantissa")); + assertThat(mantissaToken.offset(), is(0)); + assertThat(mantissaToken.encoding().primitiveType(), is(PrimitiveType.INT64)); + + assertThat(exponentToken.signal(), is(Signal.ENCODING)); + assertThat(exponentToken.name(), is("exponent")); + assertThat(exponentToken.offset(), is(8)); + assertThat(exponentToken.encoding().primitiveType(), is(PrimitiveType.INT8)); + + assertThat(enumToken.signal(), is(Signal.BEGIN_ENUM)); + assertThat(enumToken.encodedLength(), is(1)); + assertThat(enumToken.encoding().primitiveType(), is(PrimitiveType.UINT8)); + assertThat(enumToken.offset(), is(10)); + + assertThat(endCompositeToken.signal(), is(Signal.END_COMPOSITE)); + assertThat(endCompositeToken.name(), is("futuresPrice")); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java index 0e527f43e2..0f20f59520 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java @@ -20,6 +20,7 @@ import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import java.io.InputStream; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; @@ -32,29 +33,32 @@ class CompositeOffsetsTest @Test void shouldGenerateOffsetsForFieldsWithEmbeddedComposite() throws Exception { - final MessageSchema schema = parse(getLocalResource("composite-offsets-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); + try (InputStream in = getLocalResource("composite-offsets-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final List message2 = ir.getMessage(2); + final Ir ir = irg.generate(schema); + final List message2 = ir.getMessage(2); - final int fieldOneIndex = 1; - assertThat(message2.get(fieldOneIndex).offset(), is(0)); - assertThat(message2.get(fieldOneIndex + 1).encodedLength(), is(4)); + final int fieldOneIndex = 1; + assertThat(message2.get(fieldOneIndex).offset(), is(0)); + assertThat(message2.get(fieldOneIndex + 1).encodedLength(), is(4)); - final int fieldTwoIndex = 4; - assertThat(message2.get(fieldTwoIndex).offset(), is(8)); - assertThat(message2.get(fieldTwoIndex + 1).encodedLength(), is(16)); + final int fieldTwoIndex = 4; + assertThat(message2.get(fieldTwoIndex).offset(), is(8)); + assertThat(message2.get(fieldTwoIndex + 1).encodedLength(), is(16)); - assertThat(message2.get(fieldTwoIndex + 2).offset(), is(0)); - assertThat(message2.get(fieldTwoIndex + 2).encodedLength(), is(1)); - assertThat(message2.get(fieldTwoIndex + 3).offset(), is(8)); - assertThat(message2.get(fieldTwoIndex + 3).encodedLength(), is(8)); + assertThat(message2.get(fieldTwoIndex + 2).offset(), is(0)); + assertThat(message2.get(fieldTwoIndex + 2).encodedLength(), is(1)); + assertThat(message2.get(fieldTwoIndex + 3).offset(), is(8)); + assertThat(message2.get(fieldTwoIndex + 3).encodedLength(), is(8)); - final int fieldThreeIndex = 10; - assertThat(message2.get(fieldThreeIndex).offset(), is(24)); - assertThat(message2.get(fieldThreeIndex + 1).encodedLength(), is(8)); + final int fieldThreeIndex = 10; + assertThat(message2.get(fieldThreeIndex).offset(), is(24)); + assertThat(message2.get(fieldThreeIndex + 1).encodedLength(), is(8)); - assertThat(message2.get(0).encodedLength(), is(32)); + assertThat(message2.get(0).encodedLength(), is(32)); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java index 8986a43923..1cab824202 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java @@ -20,6 +20,8 @@ import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import java.io.InputStream; + import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.Tests.getLocalResource; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -29,12 +31,15 @@ class CompositeRefsTest @Test void shouldGenerateIrForCompositeRefs() throws Exception { - final MessageSchema schema = parse(getLocalResource("issue496.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); + try (InputStream in = getLocalResource("issue496.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); - assertNotNull(ir.getType("compositeOne")); - assertNotNull(ir.getType("compositeTwo")); - assertNotNull(ir.getType("compositeThree")); + assertNotNull(ir.getType("compositeOne")); + assertNotNull(ir.getType("compositeTwo")); + assertNotNull(ir.getType("compositeThree")); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index ca89103961..824e3acd1f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -21,10 +21,12 @@ import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import java.io.InputStream; import java.nio.ByteBuffer; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.core.Is.is; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -35,137 +37,178 @@ class EncodedIrTest @Test void shouldEncodeIr() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final ByteBuffer buffer = ByteBuffer.allocateDirect(CAPACITY); - final IrEncoder irEncoder = new IrEncoder(buffer, ir); - - irEncoder.encode(); + try (InputStream in = Tests.getLocalResource("basic-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final ByteBuffer buffer = ByteBuffer.allocate(CAPACITY); + try (IrEncoder irEncoder = new IrEncoder(buffer, ir)) + { + irEncoder.encode(); + assertThat(buffer.position(), greaterThan(0)); + } + } } @Test void shouldEncodeThenDecodeIr() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final ByteBuffer buffer = ByteBuffer.allocateDirect(CAPACITY); - final IrEncoder irEncoder = new IrEncoder(buffer, ir); + try (InputStream in = Tests.getLocalResource("basic-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final ByteBuffer buffer = ByteBuffer.allocate(CAPACITY); + try (IrEncoder irEncoder = new IrEncoder(buffer, ir)) + { + irEncoder.encode(); + } - irEncoder.encode(); - buffer.flip(); + buffer.flip(); - final IrDecoder decoder = new IrDecoder(buffer); - decoder.decode(); + try (IrDecoder decoder = new IrDecoder(buffer)) + { + decoder.decode(); + } + } } @Test void shouldHandleRightSizedBuffer() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final ByteBuffer buffer = ByteBuffer.allocateDirect(CAPACITY); - final IrEncoder irEncoder = new IrEncoder(buffer, ir); + try (InputStream in = Tests.getLocalResource("basic-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final ByteBuffer buffer = ByteBuffer.allocate(CAPACITY); + + try (IrEncoder irEncoder = new IrEncoder(buffer, ir)) + { + irEncoder.encode(); + } - irEncoder.encode(); - buffer.flip(); + buffer.flip(); - final ByteBuffer readBuffer = ByteBuffer.allocateDirect(buffer.remaining()); - readBuffer.put(buffer); - readBuffer.flip(); + final ByteBuffer readBuffer = ByteBuffer.allocate(buffer.remaining()); + readBuffer.put(buffer); + readBuffer.flip(); - final IrDecoder irDecoder = new IrDecoder(readBuffer); - irDecoder.decode(); + try (IrDecoder irDecoder = new IrDecoder(readBuffer)) + { + irDecoder.decode(); + } + } } @Test void shouldDecodeFrame() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "code-generation-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final ByteBuffer buffer = ByteBuffer.allocateDirect(CAPACITY); - final IrEncoder irEncoder = new IrEncoder(buffer, ir); - - irEncoder.encode(); - buffer.flip(); - - final IrDecoder irDecoder = new IrDecoder(buffer); - final Ir decodedIr = irDecoder.decode(); - - assertThat(decodedIr.id(), is(ir.id())); - assertThat(decodedIr.version(), is(ir.version())); - assertThat(decodedIr.semanticVersion(), is(ir.semanticVersion())); - assertThat(decodedIr.packageName(), is(ir.packageName())); - assertThat(decodedIr.namespaceName(), is(ir.namespaceName())); + final InputStream in = Tests.getLocalResource("code-generation-schema.xml"); + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final ByteBuffer buffer = ByteBuffer.allocate(CAPACITY); + + try (IrEncoder irEncoder = new IrEncoder(buffer, ir)) + { + irEncoder.encode(); + } + + buffer.flip(); + + try (IrDecoder irDecoder = new IrDecoder(buffer)) + { + final Ir decodedIr = irDecoder.decode(); + + assertThat(decodedIr.id(), is(ir.id())); + assertThat(decodedIr.version(), is(ir.version())); + assertThat(decodedIr.semanticVersion(), is(ir.semanticVersion())); + assertThat(decodedIr.packageName(), is(ir.packageName())); + assertThat(decodedIr.namespaceName(), is(ir.namespaceName())); + } + } } @Test void shouldDecodeHeader() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "code-generation-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final ByteBuffer buffer = ByteBuffer.allocateDirect(CAPACITY); - final IrEncoder irEncoder = new IrEncoder(buffer, ir); - - irEncoder.encode(); - buffer.flip(); - - final IrDecoder irDecoder = new IrDecoder(buffer); - final Ir decodedIr = irDecoder.decode(); - final List tokens = decodedIr.headerStructure().tokens(); - - assertThat(tokens.size(), is(ir.headerStructure().tokens().size())); - for (int i = 0, size = tokens.size(); i < size; i++) + try (InputStream in = Tests.getLocalResource("code-generation-schema.xml")) { - assertEqual(tokens.get(i), ir.headerStructure().tokens().get(i)); + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final ByteBuffer buffer = ByteBuffer.allocate(CAPACITY); + + try (IrEncoder irEncoder = new IrEncoder(buffer, ir)) + { + irEncoder.encode(); + } + + buffer.flip(); + + try (IrDecoder irDecoder = new IrDecoder(buffer)) + { + final Ir decodedIr = irDecoder.decode(); + final List tokens = decodedIr.headerStructure().tokens(); + + assertThat(tokens.size(), is(ir.headerStructure().tokens().size())); + for (int i = 0, size = tokens.size(); i < size; i++) + { + assertEqual(tokens.get(i), ir.headerStructure().tokens().get(i)); + } + } } } @Test void shouldDecodeMessagesAndTypes() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "code-generation-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final ByteBuffer buffer = ByteBuffer.allocateDirect(CAPACITY); - final IrEncoder irEncoder = new IrEncoder(buffer, ir); - - irEncoder.encode(); - buffer.flip(); - - final IrDecoder irDecoder = new IrDecoder(buffer); - final Ir decodedIr = irDecoder.decode(); - - assertThat(decodedIr.messages().size(), is(ir.messages().size())); - for (final List decodedTokenList : decodedIr.messages()) + try (InputStream in = Tests.getLocalResource("code-generation-schema.xml")) { - final List tokens = ir.getMessage(decodedTokenList.get(0).id()); + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final ByteBuffer buffer = ByteBuffer.allocate(CAPACITY); - assertThat(decodedTokenList.size(), is(tokens.size())); - for (int i = 0, size = decodedTokenList.size(); i < size; i++) + try (IrEncoder irEncoder = new IrEncoder(buffer, ir)) { - assertEqual(decodedTokenList.get(i), tokens.get(i)); + irEncoder.encode(); } - } - assertThat(decodedIr.types().size(), is(ir.types().size())); - for (final List decodedTokenList : decodedIr.types()) - { - final Token t = decodedTokenList.get(0); - final String name = t.referencedName() != null ? t.referencedName() : t.name(); - final List tokens = ir.getType(name); + buffer.flip(); - assertThat(name + " token count", decodedTokenList.size(), is(tokens.size())); - for (int i = 0, size = decodedTokenList.size(); i < size; i++) + try (IrDecoder irDecoder = new IrDecoder(buffer)) { - assertEqual(decodedTokenList.get(i), tokens.get(i)); + final Ir decodedIr = irDecoder.decode(); + + assertThat(decodedIr.messages().size(), is(ir.messages().size())); + for (final List decodedTokenList : decodedIr.messages()) + { + final List tokens = ir.getMessage(decodedTokenList.get(0).id()); + + assertThat(decodedTokenList.size(), is(tokens.size())); + for (int i = 0, size = decodedTokenList.size(); i < size; i++) + { + assertEqual(decodedTokenList.get(i), tokens.get(i)); + } + } + + assertThat(decodedIr.types().size(), is(ir.types().size())); + for (final List decodedTokenList : decodedIr.types()) + { + final Token t = decodedTokenList.get(0); + final String name = t.referencedName() != null ? t.referencedName() : t.name(); + final List tokens = ir.getType(name); + + assertThat(name + " token count", decodedTokenList.size(), is(tokens.size())); + for (int i = 0, size = decodedTokenList.size(); i < size; i++) + { + assertEqual(decodedTokenList.get(i), tokens.get(i)); + } + } } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java index 5abe33da26..80ccc9f1a2 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java @@ -21,6 +21,7 @@ import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import java.io.InputStream; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; @@ -33,129 +34,141 @@ class GroupWithDataIrTest @Test void shouldGenerateIrForSingleVarDataInRepeatingGroup() throws Exception { - final MessageSchema schema = parse(getLocalResource("group-with-data-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final List tokens = ir.getMessage(1); - - /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=group, 5=comp, 6=enc, 7=enc, 8=compend, ... */ - - final Token groupToken = tokens.get(4); - final Token dimensionsCompToken = tokens.get(5); - final Token dimensionsBlEncToken = tokens.get(6); - final Token varDataFieldToken = tokens.get(15); - final Token lengthEncToken = tokens.get(17); - final Token dataEncToken = tokens.get(18); - - /* assert on the group token */ - assertThat(groupToken.signal(), is(Signal.BEGIN_GROUP)); - assertThat(groupToken.name(), is("Entries")); - assertThat(groupToken.id(), is(2)); - - /* assert on the comp token for dimensions */ - assertThat(dimensionsCompToken.signal(), is(Signal.BEGIN_COMPOSITE)); - assertThat(dimensionsCompToken.name(), is("groupSizeEncoding")); - - /* assert on the enc token for dimensions blockLength */ - assertThat(dimensionsBlEncToken.signal(), is(Signal.ENCODING)); - assertThat(dimensionsBlEncToken.name(), is("blockLength")); - - assertThat(varDataFieldToken.signal(), is(Signal.BEGIN_VAR_DATA)); - assertThat(varDataFieldToken.name(), is("varDataField")); - assertThat(varDataFieldToken.id(), is(5)); - - assertThat(lengthEncToken.signal(), is(Signal.ENCODING)); - assertThat(lengthEncToken.encoding().primitiveType(), is(PrimitiveType.UINT8)); - - assertThat(dataEncToken.signal(), is(Signal.ENCODING)); - assertThat(dataEncToken.encoding().primitiveType(), is(PrimitiveType.CHAR)); + try (InputStream in = getLocalResource("group-with-data-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final List tokens = ir.getMessage(1); + + /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=group, 5=comp, 6=enc, 7=enc, 8=compend, ... */ + + final Token groupToken = tokens.get(4); + final Token dimensionsCompToken = tokens.get(5); + final Token dimensionsBlEncToken = tokens.get(6); + final Token varDataFieldToken = tokens.get(15); + final Token lengthEncToken = tokens.get(17); + final Token dataEncToken = tokens.get(18); + + /* assert on the group token */ + assertThat(groupToken.signal(), is(Signal.BEGIN_GROUP)); + assertThat(groupToken.name(), is("Entries")); + assertThat(groupToken.id(), is(2)); + + /* assert on the comp token for dimensions */ + assertThat(dimensionsCompToken.signal(), is(Signal.BEGIN_COMPOSITE)); + assertThat(dimensionsCompToken.name(), is("groupSizeEncoding")); + + /* assert on the enc token for dimensions blockLength */ + assertThat(dimensionsBlEncToken.signal(), is(Signal.ENCODING)); + assertThat(dimensionsBlEncToken.name(), is("blockLength")); + + assertThat(varDataFieldToken.signal(), is(Signal.BEGIN_VAR_DATA)); + assertThat(varDataFieldToken.name(), is("varDataField")); + assertThat(varDataFieldToken.id(), is(5)); + + assertThat(lengthEncToken.signal(), is(Signal.ENCODING)); + assertThat(lengthEncToken.encoding().primitiveType(), is(PrimitiveType.UINT8)); + + assertThat(dataEncToken.signal(), is(Signal.ENCODING)); + assertThat(dataEncToken.encoding().primitiveType(), is(PrimitiveType.CHAR)); + } } @Test void shouldGenerateIrForMultipleVarDataInRepeatingGroup() throws Exception { - final MessageSchema schema = parse(getLocalResource("group-with-data-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final List tokens = ir.getMessage(2); - - /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=group, 5=comp, 6=enc, 7=enc, 8=compend, ... */ - - final Token groupToken = tokens.get(4); - final Token varDataField1Token = tokens.get(15); - final Token varDataField2Token = tokens.get(21); - - /* assert on the group token */ - assertThat(groupToken.signal(), is(Signal.BEGIN_GROUP)); - assertThat(groupToken.name(), is("Entries")); - assertThat(groupToken.id(), is(2)); - - assertThat(varDataField1Token.signal(), is(Signal.BEGIN_VAR_DATA)); - assertThat(varDataField1Token.name(), is("varDataField1")); - assertThat(varDataField1Token.id(), is(5)); - - assertThat(varDataField2Token.signal(), is(Signal.BEGIN_VAR_DATA)); - assertThat(varDataField2Token.name(), is("varDataField2")); - assertThat(varDataField2Token.id(), is(6)); + try (InputStream inputStream = getLocalResource("group-with-data-schema.xml")) + { + final MessageSchema schema = parse(inputStream, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final List tokens = ir.getMessage(2); + + /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=group, 5=comp, 6=enc, 7=enc, 8=compend, ... */ + + final Token groupToken = tokens.get(4); + final Token varDataField1Token = tokens.get(15); + final Token varDataField2Token = tokens.get(21); + + /* assert on the group token */ + assertThat(groupToken.signal(), is(Signal.BEGIN_GROUP)); + assertThat(groupToken.name(), is("Entries")); + assertThat(groupToken.id(), is(2)); + + assertThat(varDataField1Token.signal(), is(Signal.BEGIN_VAR_DATA)); + assertThat(varDataField1Token.name(), is("varDataField1")); + assertThat(varDataField1Token.id(), is(5)); + + assertThat(varDataField2Token.signal(), is(Signal.BEGIN_VAR_DATA)); + assertThat(varDataField2Token.name(), is("varDataField2")); + assertThat(varDataField2Token.id(), is(6)); + } } @Test void shouldGenerateIrForVarDataInNestedRepeatingGroup() throws Exception { - final MessageSchema schema = parse(getLocalResource("group-with-data-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final List tokens = ir.getMessage(3); - - /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=group, 5=comp, 6=enc, 7=enc, 8=compend, ... */ - - final Token groupToken = tokens.get(4); - final Token nestedGroupToken = tokens.get(12); - final Token varDataFieldNestedToken = tokens.get(20); - final Token varDataFieldToken = tokens.get(27); - - assertThat(groupToken.signal(), is(Signal.BEGIN_GROUP)); - assertThat(groupToken.name(), is("Entries")); - assertThat(groupToken.id(), is(2)); - - assertThat(nestedGroupToken.signal(), is(Signal.BEGIN_GROUP)); - assertThat(nestedGroupToken.name(), is("NestedEntries")); - assertThat(nestedGroupToken.id(), is(4)); - - assertThat(varDataFieldNestedToken.signal(), is(Signal.BEGIN_VAR_DATA)); - assertThat(varDataFieldNestedToken.name(), is("varDataFieldNested")); - assertThat(varDataFieldNestedToken.id(), is(6)); - - assertThat(varDataFieldToken.signal(), is(Signal.BEGIN_VAR_DATA)); - assertThat(varDataFieldToken.name(), is("varDataField")); - assertThat(varDataFieldToken.id(), is(7)); + try (InputStream in = getLocalResource("group-with-data-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final List tokens = ir.getMessage(3); + + /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=group, 5=comp, 6=enc, 7=enc, 8=compend, ... */ + + final Token groupToken = tokens.get(4); + final Token nestedGroupToken = tokens.get(12); + final Token varDataFieldNestedToken = tokens.get(20); + final Token varDataFieldToken = tokens.get(27); + + assertThat(groupToken.signal(), is(Signal.BEGIN_GROUP)); + assertThat(groupToken.name(), is("Entries")); + assertThat(groupToken.id(), is(2)); + + assertThat(nestedGroupToken.signal(), is(Signal.BEGIN_GROUP)); + assertThat(nestedGroupToken.name(), is("NestedEntries")); + assertThat(nestedGroupToken.id(), is(4)); + + assertThat(varDataFieldNestedToken.signal(), is(Signal.BEGIN_VAR_DATA)); + assertThat(varDataFieldNestedToken.name(), is("varDataFieldNested")); + assertThat(varDataFieldNestedToken.id(), is(6)); + + assertThat(varDataFieldToken.signal(), is(Signal.BEGIN_VAR_DATA)); + assertThat(varDataFieldToken.name(), is("varDataField")); + assertThat(varDataFieldToken.id(), is(7)); + } } @Test void shouldGenerateIrForOnlyMultipleVarDataInRepeatingGroup() throws Exception { - final MessageSchema schema = parse(getLocalResource("group-with-data-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final List tokens = ir.getMessage(4); - - /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=group, 5=comp, 6=enc, 7=enc, 8=compend, ... */ - - final Token groupToken = tokens.get(4); - final Token varDataField1Token = tokens.get(9); - final Token varDataField2Token = tokens.get(15); - - /* assert on the group token */ - assertThat(groupToken.signal(), is(Signal.BEGIN_GROUP)); - assertThat(groupToken.name(), is("Entries")); - assertThat(groupToken.id(), is(2)); - - assertThat(varDataField1Token.signal(), is(Signal.BEGIN_VAR_DATA)); - assertThat(varDataField1Token.name(), is("varDataField1")); - assertThat(varDataField1Token.id(), is(5)); - - assertThat(varDataField2Token.signal(), is(Signal.BEGIN_VAR_DATA)); - assertThat(varDataField2Token.name(), is("varDataField2")); - assertThat(varDataField2Token.id(), is(6)); + try (InputStream in = getLocalResource("group-with-data-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final List tokens = ir.getMessage(4); + + /* 0=msg, 1=field, 2=enc, 3=fieldend, 4=group, 5=comp, 6=enc, 7=enc, 8=compend, ... */ + + final Token groupToken = tokens.get(4); + final Token varDataField1Token = tokens.get(9); + final Token varDataField2Token = tokens.get(15); + + /* assert on the group token */ + assertThat(groupToken.signal(), is(Signal.BEGIN_GROUP)); + assertThat(groupToken.name(), is("Entries")); + assertThat(groupToken.id(), is(2)); + + assertThat(varDataField1Token.signal(), is(Signal.BEGIN_VAR_DATA)); + assertThat(varDataField1Token.name(), is("varDataField1")); + assertThat(varDataField1Token.id(), is(5)); + + assertThat(varDataField2Token.signal(), is(Signal.BEGIN_VAR_DATA)); + assertThat(varDataField2Token.name(), is("varDataField2")); + assertThat(varDataField2Token.id(), is(6)); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java index 612b4a4a4e..9306e75f95 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java @@ -18,6 +18,8 @@ import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.xml.ParserOptions; +import java.io.InputStream; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static uk.co.real_logic.sbe.Tests.getLocalResource; @@ -28,10 +30,10 @@ class SinceVersionValidationTest @Test void shouldErrorOnTypeWithGreaterSinceVersion() throws Exception { - try + final ParserOptions options = ParserOptions.builder().suppressOutput(true).build(); + try (InputStream in = getLocalResource("error-handler-since-version.xml")) { - final ParserOptions options = ParserOptions.builder().suppressOutput(true).build(); - parse(getLocalResource("error-handler-since-version.xml"), options); + parse(in, options); } catch (final IllegalStateException ex) { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java index 4116bf0a78..f6eea310f5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java @@ -20,6 +20,8 @@ import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import java.io.InputStream; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static uk.co.real_logic.sbe.Tests.getLocalResource; @@ -30,14 +32,17 @@ class ValueRefsTest @Test void shouldGenerateValueRefToEnum() throws Exception { - final MessageSchema schema = parse(getLocalResource("value-ref-schema.xml"), ParserOptions.DEFAULT); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); + try (InputStream in = getLocalResource("value-ref-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); - assertThat(ir.getMessage(1).get(1).encodedLength(), is(8)); - assertThat(ir.getMessage(2).get(1).encodedLength(), is(0)); - assertThat(ir.getMessage(3).get(1).encodedLength(), is(0)); - assertThat(ir.getMessage(4).get(1).encodedLength(), is(0)); - assertThat(ir.getMessage(5).get(1).encodedLength(), is(0)); + assertThat(ir.getMessage(1).get(1).encodedLength(), is(8)); + assertThat(ir.getMessage(2).get(1).encodedLength(), is(0)); + assertThat(ir.getMessage(3).get(1).encodedLength(), is(0)); + assertThat(ir.getMessage(4).get(1).encodedLength(), is(0)); + assertThat(ir.getMessage(5).get(1).encodedLength(), is(0)); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java index 94c9fe680d..73999d9fd4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java @@ -18,6 +18,7 @@ import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.Tests; +import java.io.InputStream; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; @@ -29,37 +30,52 @@ class BasicSchemaFileTest @Test void shouldHandleBasicFile() throws Exception { - parse(Tests.getLocalResource("basic-schema.xml"), ParserOptions.DEFAULT); + try (InputStream in = Tests.getLocalResource("basic-schema.xml")) + { + parse(in, ParserOptions.DEFAULT); + } } @Test void shouldHandleConstantHeaderField() throws Exception { - parse(Tests.getLocalResource("basic-schema-constant-header-field.xml"), ParserOptions.DEFAULT); + try (InputStream in = Tests.getLocalResource("basic-schema-constant-header-field.xml")) + { + parse(in, ParserOptions.DEFAULT); + } } @Test void shouldHandleBasicFileWithGroup() throws Exception { - parse(Tests.getLocalResource("basic-group-schema.xml"), ParserOptions.DEFAULT); + try (InputStream in = Tests.getLocalResource("basic-group-schema.xml")) + { + parse(in, ParserOptions.DEFAULT); + } } @Test void shouldHandleBasicFileWithVariableLengthData() throws Exception { - parse(Tests.getLocalResource("basic-variable-length-schema.xml"), ParserOptions.DEFAULT); + try (InputStream in = Tests.getLocalResource("basic-variable-length-schema.xml")) + { + parse(in, ParserOptions.DEFAULT); + } } @Test void shouldHandleBasicAllTypes() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource("basic-types-schema.xml"), ParserOptions.DEFAULT); - final List fields = schema.getMessage(1).fields(); + try (InputStream in = Tests.getLocalResource("basic-types-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final List fields = schema.getMessage(1).fields(); - assertThat(fields.get(0).name(), is("header")); - assertThat(fields.get(1).name(), is("EDTField")); - assertThat(fields.get(2).name(), is("ENUMField")); - assertThat(fields.get(3).name(), is("SETField")); - assertThat(fields.get(4).name(), is("int64Field")); + assertThat(fields.get(0).name(), is("header")); + assertThat(fields.get(1).name(), is("EDTField")); + assertThat(fields.get(2).name(), is("ENUMField")); + assertThat(fields.get(3).name(), is("SETField")); + assertThat(fields.get(4).name(), is("int64Field")); + } } } \ No newline at end of file diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java index d5821fffcc..b726352632 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java @@ -18,6 +18,7 @@ import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.Tests; +import java.io.InputStream; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; @@ -29,36 +30,38 @@ class CompositeElementsTest @Test void shouldParseSchemaSuccessfully() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "composite-elements-schema.xml"), ParserOptions.DEFAULT); - final List fields = schema.getMessage(1).fields(); - final Field composite = fields.get(0); + try (InputStream in = Tests.getLocalResource("composite-elements-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final List fields = schema.getMessage(1).fields(); + final Field composite = fields.get(0); - assertThat(composite.name(), is("structure")); - final CompositeType compositeType = (CompositeType)composite.type(); + assertThat(composite.name(), is("structure")); + final CompositeType compositeType = (CompositeType)composite.type(); - assertThat(compositeType.name(), is("outer")); - final List elements = compositeType.getTypeList(); + assertThat(compositeType.name(), is("outer")); + final List elements = compositeType.getTypeList(); - final EnumType enumType = (EnumType)elements.get(0); - final EncodedDataType encodedDataType = (EncodedDataType)elements.get(1); - final SetType setType = (SetType)elements.get(2); - final CompositeType nestedCompositeType = (CompositeType)elements.get(3); + final EnumType enumType = (EnumType)elements.get(0); + final EncodedDataType encodedDataType = (EncodedDataType)elements.get(1); + final SetType setType = (SetType)elements.get(2); + final CompositeType nestedCompositeType = (CompositeType)elements.get(3); - assertThat(enumType.name(), is("enumOne")); - assertThat(encodedDataType.name(), is("zeroth")); - assertThat(setType.name(), is("setOne")); - assertThat(nestedCompositeType.name(), is("inner")); + assertThat(enumType.name(), is("enumOne")); + assertThat(encodedDataType.name(), is("zeroth")); + assertThat(setType.name(), is("setOne")); + assertThat(nestedCompositeType.name(), is("inner")); - final List nestedElements = nestedCompositeType.getTypeList(); + final List nestedElements = nestedCompositeType.getTypeList(); - final EncodedDataType first = (EncodedDataType)nestedElements.get(0); - final EncodedDataType second = (EncodedDataType)nestedElements.get(1); + final EncodedDataType first = (EncodedDataType)nestedElements.get(0); + final EncodedDataType second = (EncodedDataType)nestedElements.get(1); - assertThat(first.name(), is("first")); - assertThat(second.name(), is("second")); + assertThat(first.name(), is("first")); + assertThat(second.name(), is("second")); - assertThat(nestedCompositeType.encodedLength(), is(16)); - assertThat(compositeType.encodedLength(), is(22)); + assertThat(nestedCompositeType.encodedLength(), is(16)); + assertThat(compositeType.encodedLength(), is(22)); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java index 30f75080fc..d982667e8a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java @@ -18,6 +18,8 @@ import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.Tests; +import java.io.InputStream; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -27,11 +29,10 @@ class CyclicReferencesTest @Test void shouldTestForCyclicRefs() throws Exception { - try + try (InputStream in = Tests.getLocalResource("cyclic-refs-schema.xml")) { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - - parse(Tests.getLocalResource("cyclic-refs-schema.xml"), options); + parse(in, options); } catch (final IllegalStateException ex) { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java index 70b73af2d0..cd32bde628 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java @@ -18,6 +18,7 @@ import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.Tests; +import java.io.InputStream; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; @@ -30,21 +31,26 @@ class EmbeddedLengthAndCountFileTest @Test void shouldHandleEmbeddedCountForGroup() throws Exception { - final MessageSchema schema = parse( - Tests.getLocalResource("embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); - final List fields = schema.getMessage(1).fields(); + try (InputStream in = Tests.getLocalResource("embedded-length-and-count-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final List fields = schema.getMessage(1).fields(); - assertThat(fields.get(1).name(), is("ListOrdGrp")); - assertThat(fields.get(1).id(), is(73)); - assertNotNull(fields.get(1).dimensionType()); + assertThat(fields.get(1).name(), is("ListOrdGrp")); + assertThat(fields.get(1).id(), is(73)); + assertNotNull(fields.get(1).dimensionType()); - final List groupFields = fields.get(1).groupFields(); - assertNotNull(groupFields); + final List groupFields = fields.get(1).groupFields(); + assertNotNull(groupFields); + } } @Test void shouldHandleEmbeddedLengthForData() throws Exception { - parse(Tests.getLocalResource("embedded-length-and-count-schema.xml"), ParserOptions.DEFAULT); + try (InputStream in = Tests.getLocalResource("embedded-length-and-count-schema.xml")) + { + parse(in, ParserOptions.DEFAULT); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index fcdb5d8a66..08c0132c6e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -274,28 +274,30 @@ void shouldThrowExceptionWhenIntValueIsOutOfRange(final long value) @Test void shouldThrowExceptionIfEnumValueIsOutOfCustomValueRange() throws IOException { - final InputStream file = Tests.getLocalResource("error-handler-enum-violates-min-max-value-range.xml"); - final IllegalStateException exception = assertThrows(IllegalStateException.class, - () -> parse(file, ParserOptions.builder().suppressOutput(true).build())); - assertEquals("had 4 errors", exception.getMessage()); + try (InputStream in = Tests.getLocalResource("error-handler-enum-violates-min-max-value-range.xml")) + { + final IllegalStateException exception = assertThrows(IllegalStateException.class, + () -> parse(in, ParserOptions.builder().suppressOutput(true).build())); + assertEquals("had 4 errors", exception.getMessage()); + } } @Test void shouldHandleEncodingTypesWithNamedTypes() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "encoding-types-schema.xml"), ParserOptions.DEFAULT); - final List fields = schema.getMessage(1).fields(); - - assertNotNull(fields); - - EnumType type = (EnumType)fields.get(1).type(); + try (InputStream in = Tests.getLocalResource("encoding-types-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final List fields = schema.getMessage(1).fields(); - assertThat(type.encodingType(), is(PrimitiveType.CHAR)); + assertNotNull(fields); - type = (EnumType)fields.get(2).type(); + EnumType type = (EnumType)fields.get(1).type(); + assertThat(type.encodingType(), is(PrimitiveType.CHAR)); - assertThat(type.encodingType(), is(PrimitiveType.UINT8)); + type = (EnumType)fields.get(2).type(); + assertThat(type.encodingType(), is(PrimitiveType.UINT8)); + } } private static Map parseTestXmlWithMap(final String xPathExpr, final String xml) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index 12292e4d65..fd36fc3de3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -32,6 +32,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.util.HashMap; import java.util.Map; @@ -95,10 +96,10 @@ void shouldNotExitOnTypeErrorsAndWarnings() throws Exception @Test void shouldExitAfterTypes() throws Exception { - try + try (InputStream in = Tests.getLocalResource("error-handler-types-schema.xml")) { final ParserOptions options = ParserOptions.builder().suppressOutput(true).build(); - parse(Tests.getLocalResource("error-handler-types-schema.xml"), options); + parse(in, options); } catch (final IllegalStateException ex) { @@ -112,10 +113,10 @@ void shouldExitAfterTypes() throws Exception @Test void shouldExitAfterTypesWhenDupTypesDefined() throws Exception { - try + try (InputStream in = Tests.getLocalResource("error-handler-types-dup-schema.xml")) { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(Tests.getLocalResource("error-handler-types-dup-schema.xml"), options); + parse(in, options); } catch (final IllegalStateException ex) { @@ -129,10 +130,10 @@ void shouldExitAfterTypesWhenDupTypesDefined() throws Exception @Test void shouldExitAfterMessageWhenDupMessageIdsDefined() throws Exception { - try + try (InputStream in = Tests.getLocalResource("error-handler-dup-message-schema.xml")) { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(Tests.getLocalResource("error-handler-dup-message-schema.xml"), options); + parse(in, options); } catch (final IllegalStateException ex) { @@ -146,10 +147,10 @@ void shouldExitAfterMessageWhenDupMessageIdsDefined() throws Exception @Test void shouldExitAfterMessage() throws Exception { - try + try (InputStream in = Tests.getLocalResource("error-handler-message-schema.xml")) { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(Tests.getLocalResource("error-handler-message-schema.xml"), options); + parse(in, options); } catch (final IllegalStateException ex) { @@ -163,10 +164,10 @@ void shouldExitAfterMessage() throws Exception @Test void shouldExitAfterMessageWhenGroupDimensionsNotComposite() throws Exception { - try + try (InputStream in = Tests.getLocalResource("error-handler-group-dimensions-schema.xml")) { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(Tests.getLocalResource("error-handler-group-dimensions-schema.xml"), options); + parse(in, options); } catch (final IllegalStateException ex) { @@ -180,10 +181,10 @@ void shouldExitAfterMessageWhenGroupDimensionsNotComposite() throws Exception @Test void shouldExitAfterTypesWhenCompositeOffsetsIncorrect() throws Exception { - try + try (InputStream in = Tests.getLocalResource("error-handler-invalid-composite-offsets-schema.xml")) { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(Tests.getLocalResource("error-handler-invalid-composite-offsets-schema.xml"), options); + parse(in, options); } catch (final IllegalStateException ex) { @@ -197,10 +198,10 @@ void shouldExitAfterTypesWhenCompositeOffsetsIncorrect() throws Exception @Test void shouldExitAfterTypesWhenCompositeHasInvalidTypes() throws Exception { - try + try (InputStream in = Tests.getLocalResource("error-handler-invalid-composite.xml");) { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(Tests.getLocalResource("error-handler-invalid-composite.xml"), options); + parse(in, options); } catch (final IllegalStateException ex) { @@ -214,10 +215,10 @@ void shouldExitAfterTypesWhenCompositeHasInvalidTypes() throws Exception @Test void shouldExitInvalidFieldNames() throws Exception { - try + try (InputStream in = Tests.getLocalResource("error-handler-invalid-name.xml")) { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); - parse(Tests.getLocalResource("error-handler-invalid-name.xml"), options); + parse(in, options); } catch (final IllegalStateException ex) { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java index 083e8dbd0d..3a45e114bd 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java @@ -18,6 +18,7 @@ import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.Tests; +import java.io.InputStream; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; @@ -30,18 +31,20 @@ class GroupWithDataTest @Test void shouldParseSchemaSuccessfully() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "group-with-data-schema.xml"), ParserOptions.DEFAULT); - final List fields = schema.getMessage(1).fields(); - final Field entriesGroup = fields.get(1); - final CompositeType dimensionType = entriesGroup.dimensionType(); - final List entriesFields = entriesGroup.groupFields(); + try (InputStream in = Tests.getLocalResource("group-with-data-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final List fields = schema.getMessage(1).fields(); + final Field entriesGroup = fields.get(1); + final CompositeType dimensionType = entriesGroup.dimensionType(); + final List entriesFields = entriesGroup.groupFields(); - assertThat(entriesGroup.name(), is("Entries")); - assertThat(dimensionType.name(), is("groupSizeEncoding")); + assertThat(entriesGroup.name(), is("Entries")); + assertThat(dimensionType.name(), is("groupSizeEncoding")); - final Field varDataField = entriesFields.get(2); - assertThat(varDataField.name(), is("varDataField")); - assertTrue(varDataField.isVariableLength()); + final Field varDataField = entriesFields.get(2); + assertThat(varDataField.name(), is("varDataField")); + assertTrue(varDataField.isVariableLength()); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java index 62b952f46b..1e784cffcc 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java @@ -18,6 +18,7 @@ import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.Tests; +import java.io.InputStream; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; @@ -33,138 +34,154 @@ class OffsetFileTest @Test void shouldHandleAllTypeOffsets() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "basic-types-schema.xml"), ParserOptions.DEFAULT); - final List fields = schema.getMessage(1).fields(); - - assertThat(fields.get(0).computedOffset(), is(0)); - assertThat(fields.get(0).type().encodedLength(), is(8)); - assertThat(fields.get(1).computedOffset(), is(8)); - assertThat(fields.get(1).type().encodedLength(), is(20)); - assertThat(fields.get(2).computedOffset(), is(28)); - assertThat(fields.get(2).type().encodedLength(), is(1)); - assertThat(fields.get(3).computedOffset(), is(29)); - assertThat(fields.get(3).type().encodedLength(), is(4)); - assertThat(fields.get(4).computedOffset(), is(33)); - assertThat(fields.get(4).type().encodedLength(), is(8)); + try (InputStream in = Tests.getLocalResource("basic-types-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final List fields = schema.getMessage(1).fields(); + + assertThat(fields.get(0).computedOffset(), is(0)); + assertThat(fields.get(0).type().encodedLength(), is(8)); + assertThat(fields.get(1).computedOffset(), is(8)); + assertThat(fields.get(1).type().encodedLength(), is(20)); + assertThat(fields.get(2).computedOffset(), is(28)); + assertThat(fields.get(2).type().encodedLength(), is(1)); + assertThat(fields.get(3).computedOffset(), is(29)); + assertThat(fields.get(3).type().encodedLength(), is(4)); + assertThat(fields.get(4).computedOffset(), is(33)); + assertThat(fields.get(4).type().encodedLength(), is(8)); + } } @Test void shouldHandleAllTypeOffsetsSetByXml() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "basic-types-schema.xml"), ParserOptions.DEFAULT); - final List fields = schema.getMessage(2).fields(); - - assertThat(fields.get(0).computedOffset(), is(0)); - assertThat(fields.get(0).type().encodedLength(), is(8)); - assertThat(fields.get(1).computedOffset(), is(8)); - assertThat(fields.get(1).type().encodedLength(), is(20)); - assertThat(fields.get(2).computedOffset(), is(32)); - assertThat(fields.get(2).type().encodedLength(), is(1)); - assertThat(fields.get(3).computedOffset(), is(128)); - assertThat(fields.get(3).type().encodedLength(), is(4)); - assertThat(fields.get(4).computedOffset(), is(136)); - assertThat(fields.get(4).type().encodedLength(), is(8)); + try (InputStream in = Tests.getLocalResource("basic-types-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final List fields = schema.getMessage(2).fields(); + + assertThat(fields.get(0).computedOffset(), is(0)); + assertThat(fields.get(0).type().encodedLength(), is(8)); + assertThat(fields.get(1).computedOffset(), is(8)); + assertThat(fields.get(1).type().encodedLength(), is(20)); + assertThat(fields.get(2).computedOffset(), is(32)); + assertThat(fields.get(2).type().encodedLength(), is(1)); + assertThat(fields.get(3).computedOffset(), is(128)); + assertThat(fields.get(3).type().encodedLength(), is(4)); + assertThat(fields.get(4).computedOffset(), is(136)); + assertThat(fields.get(4).type().encodedLength(), is(8)); + } } @Test void shouldCalculateGroupOffsetWithNoPaddingFromBlockLength() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "block-length-schema.xml"), ParserOptions.DEFAULT); - final Message msg = schema.getMessage(1); - - assertThat(msg.blockLength(), is(8)); - - final List fields = msg.fields(); - assertThat(fields.get(0).computedOffset(), is(0)); - assertThat(fields.get(0).type().encodedLength(), is(8)); - assertThat(fields.get(1).computedOffset(), is(8)); - assertNull(fields.get(1).type()); - - final List groupFields = fields.get(1).groupFields(); - assertThat(groupFields.size(), is(2)); - assertThat(groupFields.get(0).computedOffset(), is(0)); - assertThat(groupFields.get(0).type().encodedLength(), is(4)); - assertThat(groupFields.get(1).computedOffset(), is(4)); - assertThat(groupFields.get(1).type().encodedLength(), is(8)); + try (InputStream in = Tests.getLocalResource("block-length-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final Message msg = schema.getMessage(1); + + assertThat(msg.blockLength(), is(8)); + + final List fields = msg.fields(); + assertThat(fields.get(0).computedOffset(), is(0)); + assertThat(fields.get(0).type().encodedLength(), is(8)); + assertThat(fields.get(1).computedOffset(), is(8)); + assertNull(fields.get(1).type()); + + final List groupFields = fields.get(1).groupFields(); + assertThat(groupFields.size(), is(2)); + assertThat(groupFields.get(0).computedOffset(), is(0)); + assertThat(groupFields.get(0).type().encodedLength(), is(4)); + assertThat(groupFields.get(1).computedOffset(), is(4)); + assertThat(groupFields.get(1).type().encodedLength(), is(8)); + } } @Test void shouldCalculateGroupOffsetWithPaddingFromBlockLength() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "block-length-schema.xml"), ParserOptions.DEFAULT); - final List fields = schema.getMessage(2).fields(); - - assertThat(fields.get(0).computedOffset(), is(0)); - assertThat(fields.get(0).type().encodedLength(), is(8)); - assertThat(fields.get(1).computedOffset(), is(64)); - assertNull(fields.get(1).type()); - assertThat(fields.get(1).computedBlockLength(), is(12)); - - final List groupFields = fields.get(1).groupFields(); - - assertThat(groupFields.size(), is(2)); - assertThat(groupFields.get(0).computedOffset(), is(0)); - assertThat(groupFields.get(0).type().encodedLength(), is(4)); - assertThat(groupFields.get(1).computedOffset(), is(4)); - assertThat(groupFields.get(1).type().encodedLength(), is(8)); + try (InputStream in = Tests.getLocalResource("block-length-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final List fields = schema.getMessage(2).fields(); + + assertThat(fields.get(0).computedOffset(), is(0)); + assertThat(fields.get(0).type().encodedLength(), is(8)); + assertThat(fields.get(1).computedOffset(), is(64)); + assertNull(fields.get(1).type()); + assertThat(fields.get(1).computedBlockLength(), is(12)); + + final List groupFields = fields.get(1).groupFields(); + + assertThat(groupFields.size(), is(2)); + assertThat(groupFields.get(0).computedOffset(), is(0)); + assertThat(groupFields.get(0).type().encodedLength(), is(4)); + assertThat(groupFields.get(1).computedOffset(), is(4)); + assertThat(groupFields.get(1).type().encodedLength(), is(8)); + } } @Test void shouldCalculateGroupOffsetWithPaddingFromBlockLengthAndGroupBlockLength() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "block-length-schema.xml"), ParserOptions.DEFAULT); - final List fields = schema.getMessage(3).fields(); - - assertThat(fields.get(0).computedOffset(), is(0)); - assertThat(fields.get(0).type().encodedLength(), is(8)); - assertThat(fields.get(1).computedOffset(), is(64)); - assertNull(fields.get(1).type()); - assertThat(fields.get(1).computedBlockLength(), is(16)); - - final List groupFields = fields.get(1).groupFields(); - - assertThat(groupFields.size(), is(2)); - assertThat(groupFields.get(0).computedOffset(), is(0)); - assertThat(groupFields.get(0).type().encodedLength(), is(4)); - assertThat(groupFields.get(1).computedOffset(), is(4)); - assertThat(groupFields.get(1).type().encodedLength(), is(8)); + try (InputStream in = Tests.getLocalResource("block-length-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final List fields = schema.getMessage(3).fields(); + + assertThat(fields.get(0).computedOffset(), is(0)); + assertThat(fields.get(0).type().encodedLength(), is(8)); + assertThat(fields.get(1).computedOffset(), is(64)); + assertNull(fields.get(1).type()); + assertThat(fields.get(1).computedBlockLength(), is(16)); + + final List groupFields = fields.get(1).groupFields(); + + assertThat(groupFields.size(), is(2)); + assertThat(groupFields.get(0).computedOffset(), is(0)); + assertThat(groupFields.get(0).type().encodedLength(), is(4)); + assertThat(groupFields.get(1).computedOffset(), is(4)); + assertThat(groupFields.get(1).type().encodedLength(), is(8)); + } } @Test void shouldCalculateDataOffsetWithPaddingFromBlockLength() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "block-length-schema.xml"), ParserOptions.DEFAULT); - final List fields = schema.getMessage(4).fields(); - - assertThat(fields.get(0).computedOffset(), is(0)); - assertThat(fields.get(0).type().encodedLength(), is(8)); - assertThat(fields.get(1).computedOffset(), is(64)); - assertThat(fields.get(1).type().encodedLength(), is(-1)); + try (InputStream in = Tests.getLocalResource("block-length-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final List fields = schema.getMessage(4).fields(); + + assertThat(fields.get(0).computedOffset(), is(0)); + assertThat(fields.get(0).type().encodedLength(), is(8)); + assertThat(fields.get(1).computedOffset(), is(64)); + assertThat(fields.get(1).type().encodedLength(), is(-1)); + } } @Test void shouldCalculateCompositeSizeWithOffsetsSpecified() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "composite-offsets-schema.xml"), ParserOptions.DEFAULT); - final CompositeType header = schema.messageHeader(); + try (InputStream in = Tests.getLocalResource("composite-offsets-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final CompositeType header = schema.messageHeader(); - assertThat(header.encodedLength(), is(12)); + assertThat(header.encodedLength(), is(12)); + } } @Test void shouldCalculateDimensionSizeWithOffsetsSpecified() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "composite-offsets-schema.xml"), ParserOptions.DEFAULT); - final CompositeType dimensions = schema.getMessage(1).fields().get(0).dimensionType(); + try (InputStream in = Tests.getLocalResource("composite-offsets-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final CompositeType dimensions = schema.getMessage(1).fields().get(0).dimensionType(); - assertThat(dimensions.encodedLength(), is(8)); + assertThat(dimensions.encodedLength(), is(8)); + } } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index dcd51baff4..b04463d244 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -31,6 +31,7 @@ import javax.xml.xpath.XPathFactory; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -177,27 +178,25 @@ void shouldThrowExceptionWhenValueOutOfBoundsSpecified() @Test void shouldHandleEncodingTypesWithNamedTypes() throws Exception { - final MessageSchema schema = parse(Tests.getLocalResource( - "encoding-types-schema.xml"), ParserOptions.DEFAULT); - final List fields = schema.getMessage(1).fields(); - - assertNotNull(fields); - - SetType type = (SetType)fields.get(3).type(); - - assertThat(type.encodingType(), is(PrimitiveType.UINT8)); - - type = (SetType)fields.get(4).type(); + try (InputStream in = Tests.getLocalResource("encoding-types-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final List fields = schema.getMessage(1).fields(); - assertThat(type.encodingType(), is(PrimitiveType.UINT16)); + assertNotNull(fields); - type = (SetType)fields.get(5).type(); + SetType type = (SetType)fields.get(3).type(); + assertThat(type.encodingType(), is(PrimitiveType.UINT8)); - assertThat(type.encodingType(), is(PrimitiveType.UINT32)); + type = (SetType)fields.get(4).type(); + assertThat(type.encodingType(), is(PrimitiveType.UINT16)); - type = (SetType)fields.get(6).type(); + type = (SetType)fields.get(5).type(); + assertThat(type.encodingType(), is(PrimitiveType.UINT32)); - assertThat(type.encodingType(), is(PrimitiveType.UINT64)); + type = (SetType)fields.get(6).type(); + assertThat(type.encodingType(), is(PrimitiveType.UINT64)); + } } private static Map parseTestXmlWithMap(final String xPathExpr, final String xml) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java index 28ca3b8c0c..7a06142707 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java @@ -19,6 +19,7 @@ import org.junit.jupiter.params.provider.ValueSource; import uk.co.real_logic.sbe.Tests; +import java.io.InputStream; import java.util.*; import static java.util.Comparator.comparing; @@ -31,16 +32,18 @@ public class SinceVersionSchemaTransformerTest @ValueSource(ints = { 0, 4, 5 }) void shouldFilterAllVersionedFields(final int filteringVersion) throws Exception { - final MessageSchema schema = parse( - Tests.getLocalResource("since-version-filter-schema.xml"), ParserOptions.DEFAULT); + try (InputStream in = Tests.getLocalResource("since-version-filter-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); - final SinceVersionSchemaTransformer sinceVersionSchemaTransformer = new SinceVersionSchemaTransformer( - filteringVersion); - final MessageSchema transformedSchema = sinceVersionSchemaTransformer.transform(schema); + final SinceVersionSchemaTransformer sinceVersionSchemaTransformer = new SinceVersionSchemaTransformer( + filteringVersion); + final MessageSchema transformedSchema = sinceVersionSchemaTransformer.transform(schema); - assertEquals(filteringVersion, transformedSchema.version()); - assertTypeSinceVersionLessOrEqualTo(filteringVersion, schema, transformedSchema); - assertMessageSinceVersionLessOrEqualTo(filteringVersion, schema, transformedSchema); + assertEquals(filteringVersion, transformedSchema.version()); + assertTypeSinceVersionLessOrEqualTo(filteringVersion, schema, transformedSchema); + assertMessageSinceVersionLessOrEqualTo(filteringVersion, schema, transformedSchema); + } } private static void assertMessageSinceVersionLessOrEqualTo( From d5efe5ca6b3d19d0f2d84ccb486b3288b6d34782 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Feb 2023 18:47:06 +0000 Subject: [PATCH 0968/1594] [C#] Fix warning about using is in Equals method. --- csharp/sbe-dll/PrimitiveValue.cs | 2 +- csharp/sbe-tests/Issue435Tests.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/csharp/sbe-dll/PrimitiveValue.cs b/csharp/sbe-dll/PrimitiveValue.cs index 01d57bc1fd..c455ab2dcd 100644 --- a/csharp/sbe-dll/PrimitiveValue.cs +++ b/csharp/sbe-dll/PrimitiveValue.cs @@ -485,7 +485,7 @@ public override string ToString() /// equivalence of values public override bool Equals(object value) { - if (null != value && value is PrimitiveValue) + if (null != value && this.GetType().Equals(value.GetType())) { var rhs = (PrimitiveValue) value; diff --git a/csharp/sbe-tests/Issue435Tests.cs b/csharp/sbe-tests/Issue435Tests.cs index 9f67c3734d..a40e19f77f 100644 --- a/csharp/sbe-tests/Issue435Tests.cs +++ b/csharp/sbe-tests/Issue435Tests.cs @@ -75,6 +75,5 @@ public void Issue435RefTest() Assert.AreEqual(Issue435.EnumRef.Two, _issue435.Example.E, "Incorrect EnuRef"); } - } } From 42dd81d04b95e47f774e0cdcb0cdcec282e49599 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Feb 2023 18:53:00 +0000 Subject: [PATCH 0969/1594] [C++] Suppress large function documentation warning. --- .github/codeql/codeql-config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index 889b4fe698..aa139de9c0 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -12,3 +12,5 @@ query-filters: id: cs/useless-assignment-to-local - exclude: id: cpp/trivial-switch + - exclude: + id: cpp/poorly-documented-function From 56029aad5a47f3f2ca494682bd9d64e6725c0f22 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Feb 2023 18:56:16 +0000 Subject: [PATCH 0970/1594] [C#] Use DirectBuffer in using block for Dispose. --- csharp/sbe-tests/DirectBufferTests.cs | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/csharp/sbe-tests/DirectBufferTests.cs b/csharp/sbe-tests/DirectBufferTests.cs index 4c37ebe1f0..566588a39c 100644 --- a/csharp/sbe-tests/DirectBufferTests.cs +++ b/csharp/sbe-tests/DirectBufferTests.cs @@ -103,21 +103,21 @@ public void ConstructFromArraySegment() [TestMethod] public void Recycle() { - var directBuffer = new DirectBuffer(); - var firstBuffer = new Byte[16]; - directBuffer.Wrap(firstBuffer); - - directBuffer.Int64PutLittleEndian(0, 1); - Assert.AreEqual(1, BitConverter.ToInt64(firstBuffer, 0)); - - var secondBuffer = new byte[16]; - var secondBufferHandle = GCHandle.Alloc(secondBuffer, GCHandleType.Pinned); - var secondUnmanagedBuffer = (byte*)secondBufferHandle.AddrOfPinnedObject().ToPointer(); - directBuffer.Wrap(secondUnmanagedBuffer, 16); - directBuffer.Int64PutLittleEndian(0, 2); - Assert.AreEqual(2, BitConverter.ToInt64(secondBuffer, 0)); - - directBuffer.Dispose(); + using (var directBuffer = new DirectBuffer()) + { + var firstBuffer = new Byte[16]; + directBuffer.Wrap(firstBuffer); + + directBuffer.Int64PutLittleEndian(0, 1); + Assert.AreEqual(1, BitConverter.ToInt64(firstBuffer, 0)); + + var secondBuffer = new byte[16]; + var secondBufferHandle = GCHandle.Alloc(secondBuffer, GCHandleType.Pinned); + var secondUnmanagedBuffer = (byte*)secondBufferHandle.AddrOfPinnedObject().ToPointer(); + directBuffer.Wrap(secondUnmanagedBuffer, 16); + directBuffer.Int64PutLittleEndian(0, 2); + Assert.AreEqual(2, BitConverter.ToInt64(secondBuffer, 0)); + } } [TestMethod] From 9cf915f960bd74b6a2735eff3c60d74a1c9736a6 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 7 Feb 2023 19:06:11 +0000 Subject: [PATCH 0971/1594] [Java] Filter out uncaught NumberFormatException. --- .github/codeql/codeql-config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index aa139de9c0..5e1a52ef54 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -8,6 +8,8 @@ query-filters: id: java/iterator-implements-iterable - exclude: id: java/missing-override-annotation + - exclude: + id: java/uncaught-number-format-exception - exclude: id: cs/useless-assignment-to-local - exclude: From 31a2453dc90f9be9c1f6123adbe94c9e199c3941 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 10:02:13 +0000 Subject: [PATCH 0972/1594] [C++] Filter out third party code for CodeQL. --- .github/workflows/codeql.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 54d4a46dc6..5455fd9ed0 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -183,4 +183,19 @@ jobs: - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 with: - category: "/language:${{matrix.language}}" + category: "/language:${{ matrix.language }}" + upload: false + output: sarif-results + + - name: filter-sarif + uses: advanced-security/filter-sarif@v1 + with: + patterns: | + -**/thirdparty/** + input: sarif-results/${{ matrix.language }}.sarif + output: sarif-results/${{ matrix.language }}.sarif + + - name: Upload SARIF + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: sarif-results/${{ matrix.language }}.sarif From 232ab9a4a073bb5b7a65a84d953e0417194a74fc Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 10:32:27 +0000 Subject: [PATCH 0973/1594] [Java] Default some missing enum cases. --- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java | 3 +++ .../java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java | 6 ++++++ .../src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java | 3 +++ 3 files changed, 12 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java index 4fef0d5394..2f7a309a99 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java @@ -301,6 +301,9 @@ private void captureTypes(final List tokens, final int beginIndex, final case BEGIN_SET: i = captureType(tokens, i, Signal.END_SET, token.name(), token.referencedName()); break; + + default: + break; } } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java index f189284b5c..23910e4910 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java @@ -131,6 +131,9 @@ private static int decodeFields( case ENCODING: listener.onEncoding(fieldToken, buffer, bufferOffset + offset, typeToken, actingVersion); break; + + default: + break; } i = nextFieldIdx; @@ -257,6 +260,9 @@ private static void decodeComposite( case ENCODING: listener.onEncoding(typeToken, buffer, bufferOffset + offset, typeToken, actingVersion); break; + + default: + break; } i += typeToken.componentTokenCount(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index f135d9e2fa..de4ceff388 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -505,6 +505,9 @@ private Encoding.Presence mapPresence(final Presence presence) case CONSTANT: encodingPresence = Encoding.Presence.CONSTANT; break; + + default: + break; } } From 73ab905bfafd16849d1be09688c2e5281f0beeb7 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 11:46:06 +0000 Subject: [PATCH 0974/1594] [Java] Add missing cases for enums in switch statements. --- .../sbe/generation/c/CGenerator.java | 9 +++++ .../sbe/generation/cpp/CppGenerator.java | 15 ++++++++ .../generation/csharp/CSharpGenerator.java | 15 ++++++-- .../generation/golang/GolangGenerator.java | 19 +++++++++- .../sbe/generation/java/JavaGenerator.java | 36 +++++++++++++++++++ .../sbe/generation/rust/RustGenerator.java | 10 ++++-- 6 files changed, 98 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 258104e5bf..61f6cb87c7 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -89,6 +89,9 @@ List generateTypeStubs(final CharSequence[] scope) throws IOException case BEGIN_COMPOSITE: generateComposite(scope, tokens); break; + + default: + break; } typesToInclude.add(tokens.get(0).applicableTypeName()); @@ -110,6 +113,9 @@ List generateTypesToIncludes(final List tokens) case BEGIN_COMPOSITE: typesToInclude.add(token.applicableTypeName()); break; + + default: + break; } } @@ -1236,6 +1242,9 @@ private void generatePropertyFunctions( encodingToken, containingStructName); break; + + default: + break; } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 3965763d21..0dba1dfc6d 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -98,6 +98,9 @@ private List generateTypeStubs() throws IOException case BEGIN_COMPOSITE: generateComposite(tokens); break; + + default: + break; } typesToInclude.add(tokens.get(0).applicableTypeName()); @@ -119,6 +122,9 @@ private List generateTypesToIncludes(final List tokens) case BEGIN_COMPOSITE: typesToInclude.add(token.applicableTypeName()); break; + + default: + break; } } @@ -1242,6 +1248,9 @@ private CharSequence generateCompositePropertyElements( case BEGIN_COMPOSITE: generateCompositeProperty(sb, propertyName, fieldToken, indent); break; + + default: + break; } i += tokens.get(i).componentTokenCount(); @@ -2188,6 +2197,9 @@ private void generateFields( case BEGIN_COMPOSITE: generateCompositeProperty(sb, propertyName, encodingToken, indent); break; + + default: + break; } } } @@ -2803,6 +2815,9 @@ private void writeTokenDisplay( typeToken.signal() == Signal.BEGIN_SET ? "\"[]\"" : "\"{}\""); } break; + + default: + break; } sb.append('\n'); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 0550eb8bc0..f55bd11c9f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -104,6 +104,9 @@ public void generateTypeStubs() throws IOException case BEGIN_COMPOSITE: generateComposite(tokens); break; + + default: + break; } } } @@ -586,7 +589,6 @@ private CharSequence generateCompositePropertyElements(final List tokens, final Token token = tokens.get(i); final String propertyName = formatPropertyName(token.name()); - // FIXME: do I need to pass classname down here for disambiguation switch (token.signal()) { case ENCODING: @@ -604,6 +606,9 @@ private CharSequence generateCompositePropertyElements(final List tokens, case BEGIN_COMPOSITE: sb.append(generateCompositeProperty(propertyName, token, token, indent)); break; + + default: + break; } i += tokens.get(i).componentTokenCount(); @@ -1271,6 +1276,9 @@ private CharSequence generateFields(final List tokens, final String inden case BEGIN_COMPOSITE: sb.append(generateCompositeProperty(propertyName, signalToken, encodingToken, indent)); break; + + default: + break; } } } @@ -1739,7 +1747,6 @@ private int writeTokenDisplay( break; case BEGIN_COMPOSITE: - { append(sb, indent, "if (this." + fieldName + " != null)"); append(sb, indent, "{"); append(sb, indent, " this." + fieldName + ".BuildString(builder);"); @@ -1749,7 +1756,9 @@ private int writeTokenDisplay( append(sb, indent, " builder.Append(\"null\");"); append(sb, indent, "}"); break; - } + + default: + break; } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index 24084e23ef..e059524da8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -812,6 +812,9 @@ private int generateEncodeDecode( // And we can move over this group i += signalToken.componentTokenCount() - 1; break; + + default: + break; } } @@ -1114,6 +1117,9 @@ private int generateFieldEncodeDecode( generateDecodePrimitive(decode, primitive, encodingToken); generateRangeCheckPrimitive(rc, primitive, encodingToken, signalToken.isOptionalEncoding()); break; + + default: + break; } return encodingToken.encodedLength() + gap; @@ -1729,6 +1735,9 @@ private void generateTypeBody( case END_GROUP: i = tokens.size(); // terminate the loop break; + + default: + break; } } @@ -1974,7 +1983,7 @@ private void generateTypeBodyComposite( final String typeName, final List tokens) throws IOException { - // gofmt lines up the types and we don't want it to have to rewrite + // gofmt lines up the types, and we don't want it to have to rewrite // our generated files. To line things up we need to know the longest // string length and then fill with whitespace int longest = 0; @@ -2001,6 +2010,9 @@ private void generateTypeBodyComposite( case END_COMPOSITE: i = tokens.size(); // terminate the loop break; + + default: + break; } } @@ -2055,6 +2067,9 @@ private void generateTypeBodyComposite( .append((arrayLength > 1) ? ("[" + arrayLength + "]") : "") .append(typeName).append(propertyType).append("\n"); break; + + default: + break; } } sb.append("}\n"); @@ -2306,6 +2321,8 @@ private CharSequence generateNullValueLiteral(final PrimitiveType primitiveType, case UINT64: imports.peek().add("math"); return "math.MaxUint64"; + default: + break; } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index b3ac5a63fb..30aea38815 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -173,6 +173,9 @@ public void generateTypeStubs() throws IOException case BEGIN_COMPOSITE: generateComposite(tokens); break; + + default: + break; } } } @@ -1377,6 +1380,9 @@ private void generateComposite(final List tokens) throws IOException generateCompositeProperty( sb, true, DECODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName); break; + + default: + break; } out.append(sb); @@ -1424,6 +1430,9 @@ private void generateComposite(final List tokens) throws IOException generateCompositeProperty( sb, true, ENCODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName); break; + + default: + break; } out.append(sb); @@ -2941,6 +2950,9 @@ private void generateDecoderFields(final StringBuilder sb, final List tok generateCompositeProperty( sb, false, DECODER, propertyName, fieldToken, typeToken, indent, typeName); break; + + default: + break; } }); } @@ -3226,6 +3238,9 @@ private String generateGet(final PrimitiveType type, final String index, final S case DOUBLE: return "buffer.getDouble(" + index + byteOrder + ")"; + + default: + break; } throw new IllegalArgumentException("primitive type not supported: " + type); @@ -3264,6 +3279,9 @@ private String generatePut( case DOUBLE: return "buffer.putDouble(" + index + ", " + value + byteOrder + ")"; + + default: + break; } throw new IllegalArgumentException("primitive type not supported: " + type); @@ -3293,6 +3311,9 @@ private String generateChoiceIsEmptyInner(final PrimitiveType type) case UINT64: return "0 == buffer.getLong(offset)"; + + default: + break; } throw new IllegalArgumentException("primitive type not supported: " + type); @@ -3313,6 +3334,9 @@ private String generateChoiceGet(final PrimitiveType type, final String bitIndex case UINT64: return "0 != (buffer.getLong(offset" + byteOrder + ") & (1L << " + bitIndex + "))"; + + default: + break; } throw new IllegalArgumentException("primitive type not supported: " + type); @@ -3329,6 +3353,9 @@ private String generateStaticChoiceGet(final PrimitiveType type, final String bi case UINT64: return "0 != (value & (1L << " + bitIndex + "))"; + + default: + break; } throw new IllegalArgumentException("primitive type not supported: " + type); @@ -3361,6 +3388,9 @@ private String generateChoicePut(final PrimitiveType type, final String bitIdx, " long bits = buffer.getLong(offset" + byteOrder + ");\n" + " bits = value ? bits | (1L << " + bitIdx + ") : bits & ~(1L << " + bitIdx + ");\n" + " buffer.putLong(offset, bits" + byteOrder + ");"; + + default: + break; } throw new IllegalArgumentException("primitive type not supported: " + type); @@ -3385,6 +3415,9 @@ private String generateStaticChoicePut(final PrimitiveType type, final String bi case UINT64: return " return value ? bits | (1L << " + bitIdx + ") : bits & ~(1L << " + bitIdx + ");\n"; + + default: + break; } throw new IllegalArgumentException("primitive type not supported: " + type); @@ -3748,6 +3781,9 @@ private int writeTokenDisplay( append(sb, indent, "}"); break; } + + default: + break; } final int lengthBeforeFieldSeparator = sb.length(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 98ed1c2554..fe58ce4874 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -229,6 +229,8 @@ static void generateEncoderFields( case BEGIN_COMPOSITE: generateCompositeEncoder(sb, level, typeToken, name); break; + default: + break; } } catch (final IOException ex) @@ -1391,6 +1393,8 @@ private static void generateCompositeEncoder( case BEGIN_COMPOSITE: generateCompositeEncoder(sb, 2, encodingToken, encodingToken.name()); break; + default: + break; } out.append(sb); @@ -1439,8 +1443,8 @@ private static void generateCompositeDecoder( switch (encodingToken.signal()) { case ENCODING: - generatePrimitiveDecoder(sb, 2, encodingToken, encodingToken, encodingToken.name(), - encodingToken.encoding()); + generatePrimitiveDecoder( + sb, 2, encodingToken, encodingToken, encodingToken.name(), encodingToken.encoding()); break; case BEGIN_ENUM: generateEnumDecoder(sb, 2, encodingToken, encodingToken, encodingToken.name()); @@ -1451,6 +1455,8 @@ private static void generateCompositeDecoder( case BEGIN_COMPOSITE: generateCompositeDecoder(sb, 2, encodingToken, encodingToken, encodingToken.name()); break; + default: + break; } out.append(sb); From 8a3794bfbd8dfd38caf3f260211af3422ad392b4 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 11:53:01 +0000 Subject: [PATCH 0975/1594] [C#] Filter out complex block warning in CodeQL --- .github/codeql/codeql-config.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index 5e1a52ef54..a5ea05694f 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -12,7 +12,9 @@ query-filters: id: java/uncaught-number-format-exception - exclude: id: cs/useless-assignment-to-local + - exclude: + id: cs/complex-block - exclude: id: cpp/trivial-switch - exclude: - id: cpp/poorly-documented-function + id: cpp/poorly-documented-function \ No newline at end of file From 8b8a7200db10baa329dae9919ed03dfbf0d62d99 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 11:54:31 +0000 Subject: [PATCH 0976/1594] [C#] Remove redundant ToString() methods. --- .../co/real_logic/sbe/generation/csharp/CSharpGenerator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index f55bd11c9f..732b322e8d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1789,10 +1789,11 @@ private CharSequence generateChoiceDisplay(final String enumName) append(sb, TWO_INDENT, "internal static void BuildString(this " + enumName + " val, StringBuilder builder)"); append(sb, TWO_INDENT, "{"); Separators.BEGIN_SET.appendToGeneratedBuilder(sb, THREE_INDENT); - append(sb, THREE_INDENT, "builder.Append(val.ToString());"); + append(sb, THREE_INDENT, "builder.Append(val);"); Separators.END_SET.appendToGeneratedBuilder(sb, THREE_INDENT); append(sb, TWO_INDENT, "}"); append(sb, INDENT, "}"); + return sb; } From 882f9a37e4440c3b000bba2b9509f81b42fcb2e0 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 12:04:08 +0000 Subject: [PATCH 0977/1594] [Java] Make use of schema id to avoid warning. --- .../main/java/uk/co/real_logic/sbe/examples/OtfExample.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java index 7512257b57..86a754fa3c 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java @@ -79,6 +79,11 @@ public static void main(final String[] args) throws Exception final int actingVersion = headerDecoder.getSchemaVersion(buffer, bufferOffset); final int blockLength = headerDecoder.getBlockLength(buffer, bufferOffset); + if (schemaId != MessageHeaderEncoder.SCHEMA_ID) + { + throw new IllegalStateException("Invalid schema id: " + schemaId); + } + bufferOffset += headerDecoder.encodedLength(); // Given the header information we can select the appropriate message template to do the decode operation. From bd7db860d2d25cc03981bb2597d251b51b031838 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 12:13:09 +0000 Subject: [PATCH 0978/1594] [Java] Warnings cleanup. --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 3 +++ .../main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java | 4 ++-- .../src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 30aea38815..233c9aecbe 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2912,6 +2912,9 @@ private void generateEncoderFields( generateCompositeProperty( sb, false, ENCODER, propertyName, fieldToken, typeToken, indent, typeName); break; + + default: + break; } }); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index 4e26bfded1..f205802aae 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -98,8 +98,8 @@ public EncodedDataType(final Node node, final String givenName, final String ref } else { - final String characterEncoding = getAttributeValueOrNull(node, "characterEncoding"); - this.characterEncoding = characterEncoding == null ? null : characterEncoding.trim(); + final String configuredCharacterEncoding = getAttributeValueOrNull(node, "characterEncoding"); + characterEncoding = configuredCharacterEncoding == null ? null : configuredCharacterEncoding.trim(); } if (presence() == CONSTANT) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index ee4ddffec0..a196df56d0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -63,8 +63,8 @@ public class MessageSchema this.typeByNameMap = typeByNameMap; this.messageByIdMap = messageByIdMap; - final String headerType = getAttributeValueOrNull(schemaNode, "headerType"); - this.headerType = null == headerType ? HEADER_TYPE_DEFAULT : headerType; + final String configuredHeaderType = getAttributeValueOrNull(schemaNode, "headerType"); + headerType = null == configuredHeaderType ? HEADER_TYPE_DEFAULT : configuredHeaderType; Verify.present(typeByNameMap, this.headerType, "Message header"); final Node messageHeaderNode = findNode(schemaNode, "types/composite[@name='" + this.headerType + "']"); From 844678320357f661d45e5361ed8fa05cd7c3c4c0 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 12:23:23 +0000 Subject: [PATCH 0979/1594] [Java] Filter unused parameter warnings. --- .github/codeql/codeql-config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index a5ea05694f..30aba2fe02 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -10,6 +10,8 @@ query-filters: id: java/missing-override-annotation - exclude: id: java/uncaught-number-format-exception + - exclude: + id: java/unused-parameter - exclude: id: cs/useless-assignment-to-local - exclude: From df74daf054442e4a728b6e6f6e16e53990f4c0d1 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 8 Feb 2023 13:27:20 +0100 Subject: [PATCH 0980/1594] [CI] Remove `queries: +security-and-quality` as those are specified in the config file. --- .github/workflows/codeql.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 5455fd9ed0..fba15354c6 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -65,7 +65,6 @@ jobs: uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} - queries: +security-and-quality config-file: ./.github/codeql/codeql-config.yml - name: Build with Gradle @@ -122,7 +121,6 @@ jobs: uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} - queries: +security-and-quality config-file: ./.github/codeql/codeql-config.yml - name: Build @@ -174,7 +172,6 @@ jobs: uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} - queries: +security-and-quality config-file: ./.github/codeql/codeql-config.yml - name: Build From bc4d34d250c4ad9cca5e2d63704e24cb2a9ba7a9 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 16:03:39 +0000 Subject: [PATCH 0981/1594] [C++] Generate different body to *InActionVersion check if property version is 0 so avoid warnings. --- .../sbe/generation/cpp/CppGenerator.java | 44 +++++++------------ 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 0dba1dfc6d..f587b3eb7e 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -440,6 +440,9 @@ private static void generateGroupProperty( propertyName, cppTypeForNumInGroup); + final int version = token.version(); + final String versionCheck = 0 == version ? + " return true;\n" : " return m_actingVersion >= %1$sSinceVersion();\n"; new Formatter(sb).format("\n" + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + indent + " {\n" + @@ -448,17 +451,10 @@ private static void generateGroupProperty( indent + " SBE_NODISCARD bool %1$sInActingVersion() const SBE_NOEXCEPT\n" + indent + " {\n" + - indent + "#if defined(__clang__)\n" + - indent + "#pragma clang diagnostic push\n" + - indent + "#pragma clang diagnostic ignored \"-Wtautological-compare\"\n" + - indent + "#endif\n" + - indent + " return m_actingVersion >= %1$sSinceVersion();\n" + - indent + "#if defined(__clang__)\n" + - indent + "#pragma clang diagnostic pop\n" + - indent + "#endif\n" + + indent + versionCheck + indent + " }\n", propertyName, - token.version()); + version); } private void generateVarData( @@ -662,6 +658,9 @@ private void generateVarDataDescriptors( toLowerFirstChar(propertyName), characterEncoding); + final int version = token.version(); + final String versionCheck = 0 == version ? + " return true;\n" : " return m_actingVersion >= %1$sSinceVersion();\n"; new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + indent + " {\n" + @@ -670,14 +669,7 @@ private void generateVarDataDescriptors( indent + " bool %1$sInActingVersion() SBE_NOEXCEPT\n" + indent + " {\n" + - indent + "#if defined(__clang__)\n" + - indent + "#pragma clang diagnostic push\n" + - indent + "#pragma clang diagnostic ignored \"-Wtautological-compare\"\n" + - indent + "#endif\n" + - indent + " return m_actingVersion >= %1$sSinceVersion();\n" + - indent + "#if defined(__clang__)\n" + - indent + "#pragma clang diagnostic pop\n" + - indent + "#endif\n" + + indent + versionCheck + indent + " }\n\n" + indent + " static SBE_CONSTEXPR std::uint16_t %1$sId() SBE_NOEXCEPT\n" + @@ -685,7 +677,7 @@ private void generateVarDataDescriptors( indent + " return %3$d;\n" + indent + " }\n", toLowerFirstChar(propertyName), - token.version(), + version, token.id()); new Formatter(sb).format("\n" + @@ -705,7 +697,7 @@ private void generateVarDataDescriptors( indent + " return %3$s(length);\n" + indent + " }\n", toLowerFirstChar(propertyName), - generateArrayFieldNotPresentCondition(token.version(), BASE_INDENT), + generateArrayFieldNotPresentCondition(version, BASE_INDENT), formatByteOrderEncoding(lengthToken.encoding().byteOrder(), lengthToken.encoding().primitiveType()), lengthCppType); } @@ -2220,6 +2212,9 @@ private void generateFieldCommonMethods( propertyName, fieldToken.id()); + final int version = fieldToken.version(); + final String versionCheck = 0 == version ? + " return true;\n" : " return m_actingVersion >= %1$sSinceVersion();\n"; new Formatter(sb).format("\n" + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t %1$sSinceVersion() SBE_NOEXCEPT\n" + indent + " {\n" + @@ -2228,17 +2223,10 @@ private void generateFieldCommonMethods( indent + " SBE_NODISCARD bool %1$sInActingVersion() SBE_NOEXCEPT\n" + indent + " {\n" + - indent + "#if defined(__clang__)\n" + - indent + "#pragma clang diagnostic push\n" + - indent + "#pragma clang diagnostic ignored \"-Wtautological-compare\"\n" + - indent + "#endif\n" + - indent + " return m_actingVersion >= %1$sSinceVersion();\n" + - indent + "#if defined(__clang__)\n" + - indent + "#pragma clang diagnostic pop\n" + - indent + "#endif\n" + + indent + versionCheck + indent + " }\n", propertyName, - fieldToken.version()); + version); new Formatter(sb).format("\n" + indent + " SBE_NODISCARD static SBE_CONSTEXPR std::size_t %1$sEncodingOffset() SBE_NOEXCEPT\n" + From 2acfc424a386de1f8f9df4303f40bd367a5fc704 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 16:18:06 +0000 Subject: [PATCH 0982/1594] [Java] More filters for warnings about overloads in generated code. --- .github/codeql/codeql-config.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index 30aba2fe02..224ed0e44c 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -12,6 +12,10 @@ query-filters: id: java/uncaught-number-format-exception - exclude: id: java/unused-parameter + - exclude: + id: java/confusing-method-signature + - exclude: + id: java/local-shadows-field - exclude: id: cs/useless-assignment-to-local - exclude: From 4551cb7460811f24e778b036dfdded6d5e33e8ca Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 18:23:22 +0000 Subject: [PATCH 0983/1594] [C++] Address duplicate guard issues. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index f587b3eb7e..f06863b356 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1048,8 +1048,8 @@ private static CharSequence generateFileHeader( sb.append("/* Generated SBE (Simple Binary Encoding) message codec */\n"); sb.append(String.format( - "#ifndef _%1$s_%2$s_H_\n" + - "#define _%1$s_%2$s_H_\n\n" + + "#ifndef _%1$s_%2$s_CXX_H_\n" + + "#define _%1$s_%2$s_CXX_H_\n\n" + "#if defined(SBE_HAVE_CMATH)\n" + "/* cmath needed for std::numeric_limits::quiet_NaN() */\n" + @@ -1164,8 +1164,8 @@ private static CharSequence generateEnumFileHeader(final CharSequence[] namespac sb.append("/* Generated SBE (Simple Binary Encoding) message codec */\n"); sb.append(String.format( - "#ifndef _%1$s_%2$s_H_\n" + - "#define _%1$s_%2$s_H_\n\n" + + "#ifndef _%1$s_%2$s_CXX_H_\n" + + "#define _%1$s_%2$s_CXX_H_\n\n" + "#if !defined(__STDC_LIMIT_MACROS)\n" + "# define __STDC_LIMIT_MACROS 1\n" + From 1973c86f84b190d5b2507786e6445970c390ea62 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 18:43:10 +0000 Subject: [PATCH 0984/1594] [C++] Pass by reference rather than value when streaming to a string. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index f06863b356..54fa183222 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2556,7 +2556,7 @@ private void generateDisplay( new Formatter(sb).format("\n" + "template\n" + "friend std::basic_ostream & operator << (\n" + - " std::basic_ostream &builder, %1$s _writer)\n" + + " std::basic_ostream &builder, %1$s &_writer)\n" + "{\n" + " %1$s writer(\n" + " _writer.m_buffer,\n" + @@ -2587,7 +2587,7 @@ private CharSequence generateGroupDisplay( return String.format("\n" + indent + "template\n" + indent + "friend std::basic_ostream & operator << (\n" + - indent + " std::basic_ostream &builder, %1$s writer)\n" + + indent + " std::basic_ostream &builder, %1$s &writer)\n" + indent + "{\n" + indent + " builder << '{';\n" + "%2$s" + @@ -2603,7 +2603,7 @@ private CharSequence generateCompositeDisplay(final String name, final List\n" + "friend std::basic_ostream & operator << (\n" + - " std::basic_ostream &builder, %1$s writer)\n" + + " std::basic_ostream &builder, %1$s &writer)\n" + "{\n" + " builder << '{';\n" + "%2$s" + @@ -2822,7 +2822,7 @@ private CharSequence generateChoicesDisplay(final String name, final List new Formatter(sb).format("\n" + indent + "template\n" + indent + "friend std::basic_ostream & operator << (\n" + - indent + " std::basic_ostream &builder, %1$s writer)\n" + + indent + " std::basic_ostream &builder, %1$s &writer)\n" + indent + "{\n" + indent + " builder << '[';\n", name); From de5ab5646cd807b470dff53a22bbaac8c0999c09 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 18:58:26 +0000 Subject: [PATCH 0985/1594] [C#] Fix warnings. --- csharp/sbe-tests/BigEndianTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/csharp/sbe-tests/BigEndianTests.cs b/csharp/sbe-tests/BigEndianTests.cs index 8e1358800a..41adc1da4b 100644 --- a/csharp/sbe-tests/BigEndianTests.cs +++ b/csharp/sbe-tests/BigEndianTests.cs @@ -26,12 +26,11 @@ public unsafe class BigendianTests { // The byte array is from the java example made by running // with -Dsbe.encoding.filename and then decoded using od -tu1 - private byte[] _decodeBuffer = { 0, 49, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 210, 7, 221, 1, 65, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 97, 98, 99, 100, 101, 102, 6, 7, 208, 4, 49, 50, 51, 35, 1, 78, 200, 0, 6, 0, 3, 0, 30, 66, 15, 153, 154, 0, 0, 0, 11, 85, 114, 98, 97, 110, 32, 67, 121, 99, 108, 101, 0, 55, 66, 68, 0, 0, 0, 0, 0, 14, 67, 111, 109, 98, 105, 110, 101, 100, 32, 67, 121, 99, 108, 101, 0, 75, 66, 32, 0, 0, 0, 0, 0, 13, 72, 105, 103, 104, 119, 97, 121, 32, 67, 121, 99, 108, 101, 0, 1, 0, 2, 95, 0, 6, 0, 3, 0, 30, 64, 128, 0, 0, 0, 60, 64, 240, 0, 0, 0, 100, 65, 67, 51, 51, 99, 0, 6, 0, 3, 0, 30, 64, 115, 51, 51, 0, 60, 64, 227, 51, 51, 0, 100, 65, 60, 204, 205, 0, 0, 0, 5, 72, 111, 110, 100, 97, 0, 0, 0, 9, 67, 105, 118, 105, 99, 32, 86, 84, 105, 0, 0, 0, 6, 97, 98, 99, 100, 101, 102 }; + private readonly byte[] _decodeBuffer = { 0, 49, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 210, 7, 221, 1, 65, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 97, 98, 99, 100, 101, 102, 6, 7, 208, 4, 49, 50, 51, 35, 1, 78, 200, 0, 6, 0, 3, 0, 30, 66, 15, 153, 154, 0, 0, 0, 11, 85, 114, 98, 97, 110, 32, 67, 121, 99, 108, 101, 0, 55, 66, 68, 0, 0, 0, 0, 0, 14, 67, 111, 109, 98, 105, 110, 101, 100, 32, 67, 121, 99, 108, 101, 0, 75, 66, 32, 0, 0, 0, 0, 0, 13, 72, 105, 103, 104, 119, 97, 121, 32, 67, 121, 99, 108, 101, 0, 1, 0, 2, 95, 0, 6, 0, 3, 0, 30, 64, 128, 0, 0, 0, 60, 64, 240, 0, 0, 0, 100, 65, 67, 51, 51, 99, 0, 6, 0, 3, 0, 30, 64, 115, 51, 51, 0, 60, 64, 227, 51, 51, 0, 100, 65, 60, 204, 205, 0, 0, 0, 5, 72, 111, 110, 100, 97, 0, 0, 0, 9, 67, 105, 118, 105, 99, 32, 86, 84, 105, 0, 0, 0, 6, 97, 98, 99, 100, 101, 102 }; private byte[] _encodeBuffer; private DirectBuffer _directBuffer; private MessageHeader _messageHeader; - private Car Car; [TestInitialize] public void SetUp() From deed84d19c461b3c260d2f7c0d1c342946e14c86 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 19:06:29 +0000 Subject: [PATCH 0986/1594] [C#] Put back Car type. --- csharp/sbe-tests/BigEndianTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/csharp/sbe-tests/BigEndianTests.cs b/csharp/sbe-tests/BigEndianTests.cs index 41adc1da4b..e2369fb220 100644 --- a/csharp/sbe-tests/BigEndianTests.cs +++ b/csharp/sbe-tests/BigEndianTests.cs @@ -31,6 +31,7 @@ public unsafe class BigendianTests private DirectBuffer _directBuffer; private MessageHeader _messageHeader; + private Car Car; [TestInitialize] public void SetUp() From 2e02a195830fce4289bc183d86ff063a5dfd437b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 19:13:44 +0000 Subject: [PATCH 0987/1594] [C#] Address static field issues. --- csharp/sbe-tests/InteropTests.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/csharp/sbe-tests/InteropTests.cs b/csharp/sbe-tests/InteropTests.cs index 6d9e46fa84..57338e0bfb 100644 --- a/csharp/sbe-tests/InteropTests.cs +++ b/csharp/sbe-tests/InteropTests.cs @@ -30,19 +30,21 @@ public unsafe class InteropTests // The byte array is from the java example for interop test made by // running with -Dsbe.encoding.filename and then decoded using od -tu1 - static byte[] _decodeBuffer; - static byte[] _encodeBuffer; + private byte[] _decodeBuffer; + private byte[] _encodeBuffer; - static DirectBuffer _directBuffer; - static MessageHeader _messageHeader; - static Car Car; + private DirectBuffer _directBuffer; + private MessageHeader _messageHeader; + private Car Car; [TestInitialize] public void Setup() { const string interopFile = "../../../ExampleUsingGeneratedStub.sbe"; if (!File.Exists(interopFile)) + { Assert.Inconclusive($"Could not read interop file: {interopFile}"); + } _decodeBuffer = File.ReadAllBytes(interopFile); _encodeBuffer = new byte[_decodeBuffer.Length]; _messageHeader = new MessageHeader(); From da97c0303350f04edf38ec3d314802df3f63ac61 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 8 Feb 2023 19:29:08 +0000 Subject: [PATCH 0988/1594] [C#] Catch more specific exception when getting bytes from an encoding. --- csharp/sbe-samples-car/CarExample.cs | 4 ++-- csharp/sbe-samples-extension/ExtensionExample.cs | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/csharp/sbe-samples-car/CarExample.cs b/csharp/sbe-samples-car/CarExample.cs index 3706ab959a..0229cacc59 100644 --- a/csharp/sbe-samples-car/CarExample.cs +++ b/csharp/sbe-samples-car/CarExample.cs @@ -80,9 +80,9 @@ static CarExample() ManufacturerCode = Engine.ManufacturerCodeResolvedCharacterEncoding.GetBytes("123"); ActivationCode = Car.ActivationCodeResolvedCharacterEncoding.GetBytes("abcdef"); } - catch (Exception ex) + catch (EncoderFallbackException ex) { - throw new Exception("An error occured while reading encodings", ex); + throw new Exception("An error occurred while reading encodings", ex); } } diff --git a/csharp/sbe-samples-extension/ExtensionExample.cs b/csharp/sbe-samples-extension/ExtensionExample.cs index 9e11ee3b35..eb8c5b1802 100644 --- a/csharp/sbe-samples-extension/ExtensionExample.cs +++ b/csharp/sbe-samples-extension/ExtensionExample.cs @@ -100,14 +100,13 @@ static ExtensionExample() Model = Encoding.GetEncoding(Car.ModelCharacterEncoding).GetBytes("Civic VTi"); ActivationCode = Encoding.GetEncoding(Car.ActivationCodeCharacterEncoding).GetBytes("abcdef"); } - catch (Exception ex) + catch (EncoderFallbackException ex) { - throw new Exception("An error occured while reading encodings", ex); + throw new Exception("An error occurred while reading encodings", ex); } } - public static int Encode(Car car, DirectBuffer directBuffer, int bufferOffset) { const int srcOffset = 0; @@ -312,7 +311,7 @@ static ExtensionExample() Model = Encoding.GetEncoding(Car.ModelCharacterEncoding).GetBytes("Civic VTi"); ActivationCode = Encoding.GetEncoding(Car.ActivationCodeCharacterEncoding).GetBytes("abcdef"); } - catch (Exception ex) + catch (EncoderFallbackException ex) { throw new Exception("An error occurred while reading encodings", ex); } @@ -390,7 +389,7 @@ public static int Encode(Car car, DirectBuffer directBuffer, int bufferOffset) // we have written all the constant length fields, now we can write the repeatable groups - var fuelFigures = car.FuelFiguresCount(3); // we specify that we are going to write 3 FueldFigures (the API is not very .NET friendly yet, we will address that) + var fuelFigures = car.FuelFiguresCount(3); // we specify that we are going to write 3 FuelFigures (the API is not very .NET friendly yet, we will address that) fuelFigures.Next(); // move to the first element fuelFigures.Speed = 30; fuelFigures.Mpg = 35.9f; From 79eb75d5f672fed320fe23bce805eebcfec6d264 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 9 Feb 2023 09:21:27 +0000 Subject: [PATCH 0989/1594] [C#] Override ToString to give name of PrimitiveType. --- csharp/sbe-dll/PrimitiveType.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/csharp/sbe-dll/PrimitiveType.cs b/csharp/sbe-dll/PrimitiveType.cs index 5643f747ea..2d4b09689c 100644 --- a/csharp/sbe-dll/PrimitiveType.cs +++ b/csharp/sbe-dll/PrimitiveType.cs @@ -207,5 +207,7 @@ public SbePrimitiveType Type { get { return _sbePrimitiveType; } } + + public override string ToString() => PrimitiveName; } } From 21409b60e92893f471fc8a6ea9f86fa84613cc20 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 9 Feb 2023 09:39:47 +0000 Subject: [PATCH 0990/1594] [C#] Try fix shadowing issues in InteropTests. --- csharp/sbe-tests/InteropTests.cs | 85 ++++++++++++++++---------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/csharp/sbe-tests/InteropTests.cs b/csharp/sbe-tests/InteropTests.cs index 57338e0bfb..43ef7fd0c3 100644 --- a/csharp/sbe-tests/InteropTests.cs +++ b/csharp/sbe-tests/InteropTests.cs @@ -35,7 +35,6 @@ public unsafe class InteropTests private DirectBuffer _directBuffer; private MessageHeader _messageHeader; - private Car Car; [TestInitialize] public void Setup() @@ -56,36 +55,36 @@ public void InteropDecodeTest() _directBuffer = new DirectBuffer(_decodeBuffer); _messageHeader.Wrap(_directBuffer, 0, Baseline.MessageHeader.SbeSchemaVersion); - var Car = new Car(); - Car.WrapForDecode(_directBuffer, MessageHeader.Size, _messageHeader.BlockLength, _messageHeader.Version); + var car = new Car(); + car.WrapForDecode(_directBuffer, MessageHeader.Size, _messageHeader.BlockLength, _messageHeader.Version); Assert.AreEqual(1234UL, Car.SerialNumber); Assert.AreEqual((ushort)2013, Car.ModelYear); Assert.AreEqual(BooleanType.T, Car.Available); Assert.AreEqual(Model.A, Car.Code); - for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) + for (int i = 0, size = car.SomeNumbersLength; i < size; i++) { - Assert.AreEqual(Car.GetSomeNumbers(i), (uint)i+1); + Assert.AreEqual(car.GetSomeNumbers(i), (uint)i+1); } var btmp = new byte[6]; - Car.GetVehicleCode(btmp, 0); + car.GetVehicleCode(btmp, 0); var s = System.Text.Encoding.UTF8.GetString(btmp, 0, btmp.Length); Assert.AreEqual("abcdef", s); - Assert.AreEqual(OptionalExtras.CruiseControl | OptionalExtras.SportsPack, Car.Extras); - Assert.AreEqual((ushort)2000, Car.Engine.Capacity); - Assert.AreEqual((byte)4, Car.Engine.NumCylinders); + Assert.AreEqual(OptionalExtras.CruiseControl | OptionalExtras.SportsPack, car.Extras); + Assert.AreEqual((ushort)2000, car.Engine.Capacity); + Assert.AreEqual((byte)4, car.Engine.NumCylinders); btmp = new byte[3]; - Car.Engine.GetManufacturerCode(btmp, 0); + car.Engine.GetManufacturerCode(btmp, 0); s = System.Text.Encoding.UTF8.GetString(btmp, 0, btmp.Length); Assert.AreEqual("123", s); - Assert.AreEqual((sbyte)35, Car.Engine.Efficiency); - Assert.AreEqual(BooleanType.T, Car.Engine.BoosterEnabled); - Assert.AreEqual(BoostType.NITROUS, Car.Engine.Booster.BoostType); - Assert.AreEqual((byte)200, Car.Engine.Booster.HorsePower); + Assert.AreEqual((sbyte)35, car.Engine.Efficiency); + Assert.AreEqual(BooleanType.T, car.Engine.BoosterEnabled); + Assert.AreEqual(BoostType.NITROUS, car.Engine.Booster.BoostType); + Assert.AreEqual((byte)200, car.Engine.Booster.HorsePower); - var fuelFigures = Car.FuelFigures; + var fuelFigures = car.FuelFigures; Assert.AreEqual(3, fuelFigures.Count); fuelFigures.Next(); @@ -112,7 +111,7 @@ public void InteropDecodeTest() s = System.Text.Encoding.UTF8.GetString(btmp, 0, btmp.Length); Assert.AreEqual("Highway Cycle", s); - var perfFigures = Car.PerformanceFigures; + var perfFigures = car.PerformanceFigures; Assert.AreEqual(2, perfFigures.Count); perfFigures.Next(); @@ -144,15 +143,15 @@ public void InteropDecodeTest() Assert.AreEqual(11.8f, acceleration.Seconds); btmp = new byte[5]; - Car.GetManufacturer(btmp, 0, 5); + car.GetManufacturer(btmp, 0, 5); s = System.Text.Encoding.UTF8.GetString(btmp, 0, btmp.Length); Assert.AreEqual("Honda", s); btmp = new byte[9]; - Car.GetModel(btmp, 0, 9); + car.GetModel(btmp, 0, 9); s = System.Text.Encoding.UTF8.GetString(btmp, 0, btmp.Length); Assert.AreEqual("Civic VTi", s); btmp = new byte[6]; - Car.GetActivationCode(btmp, 0, 6); + car.GetActivationCode(btmp, 0, 6); s = System.Text.Encoding.UTF8.GetString(btmp, 0, btmp.Length); Assert.AreEqual("abcdef", s); } @@ -160,7 +159,7 @@ public void InteropDecodeTest() [TestMethod] public void InteropEncodeTest() { - Car = new Car(); + car = new Car(); _directBuffer = new DirectBuffer(_encodeBuffer); _messageHeader.Wrap(_directBuffer, 0, Baseline.MessageHeader.SbeSchemaVersion); _messageHeader.BlockLength = Car.BlockLength; @@ -169,27 +168,27 @@ public void InteropEncodeTest() _messageHeader.Version = Car.SchemaVersion; // Populate the car with the known interop values - Car.WrapForEncode(_directBuffer, Baseline.MessageHeader.Size); - Car.SerialNumber = 1234; - Car.ModelYear = 2013; - Car.Available = BooleanType.T; - Car.Code = Model.A; - for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) + car.WrapForEncode(_directBuffer, Baseline.MessageHeader.Size); + car.SerialNumber = 1234; + car.ModelYear = 2013; + car.Available = BooleanType.T; + car.Code = Model.A; + for (int i = 0, size = car.SomeNumbersLength; i < size; i++) { - Car.SetSomeNumbers(i, (uint)i+1); + car.SetSomeNumbers(i, (uint)i+1); } - Car.SetVehicleCode(System.Text.Encoding.ASCII.GetBytes("abcdef"), 0); - Car.Extras = OptionalExtras.CruiseControl | OptionalExtras.SportsPack; - - Car.Engine.Capacity = 2000; - Car.Engine.NumCylinders = 4; - Car.Engine.SetManufacturerCode(System.Text.Encoding.ASCII.GetBytes("123"), 0); - Car.Engine.Efficiency = 35; - Car.Engine.BoosterEnabled = BooleanType.T; - Car.Engine.Booster.BoostType = BoostType.NITROUS; - Car.Engine.Booster.HorsePower = 200; - - var fuelFigures = Car.FuelFiguresCount(3); + car.SetVehicleCode(System.Text.Encoding.ASCII.GetBytes("abcdef"), 0); + car.Extras = OptionalExtras.CruiseControl | OptionalExtras.SportsPack; + + car.Engine.Capacity = 2000; + car.Engine.NumCylinders = 4; + car.Engine.SetManufacturerCode(System.Text.Encoding.ASCII.GetBytes("123"), 0); + car.Engine.Efficiency = 35; + car.Engine.BoosterEnabled = BooleanType.T; + car.Engine.Booster.BoostType = BoostType.NITROUS; + car.Engine.Booster.HorsePower = 200; + + var fuelFigures = car.FuelFiguresCount(3); fuelFigures.Next(); fuelFigures.Speed = 30; fuelFigures.Mpg = 35.9f; @@ -205,7 +204,7 @@ public void InteropEncodeTest() fuelFigures.Mpg = 40.0f; fuelFigures.SetUsageDescription(System.Text.Encoding.ASCII.GetBytes("Highway Cycle"), 0, 13); - var perfFigures = Car.PerformanceFiguresCount(2); + var perfFigures = car.PerformanceFiguresCount(2); perfFigures.Next(); perfFigures.OctaneRating = 95; @@ -236,9 +235,9 @@ public void InteropEncodeTest() acceleration.Mph = 100; acceleration.Seconds = 11.8f; - Car.SetManufacturer(System.Text.Encoding.ASCII.GetBytes("Honda"), 0, 5); - Car.SetModel(System.Text.Encoding.ASCII.GetBytes("Civic VTi"), 0, 9); - Car.SetActivationCode(System.Text.Encoding.ASCII.GetBytes("abcdef"), 0, 6); + car.SetManufacturer(System.Text.Encoding.ASCII.GetBytes("Honda"), 0, 5); + car.SetModel(System.Text.Encoding.ASCII.GetBytes("Civic VTi"), 0, 9); + car.SetActivationCode(System.Text.Encoding.ASCII.GetBytes("abcdef"), 0, 6); for (int i = 0; i < _decodeBuffer.Length; i++) { From 553010e5c1d9e3551472a3a528677eec0455250a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 9 Feb 2023 09:44:21 +0000 Subject: [PATCH 0991/1594] [C#] Add ToString doc. --- csharp/sbe-dll/PrimitiveType.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/csharp/sbe-dll/PrimitiveType.cs b/csharp/sbe-dll/PrimitiveType.cs index 2d4b09689c..d0d183eabc 100644 --- a/csharp/sbe-dll/PrimitiveType.cs +++ b/csharp/sbe-dll/PrimitiveType.cs @@ -208,6 +208,9 @@ public SbePrimitiveType Type get { return _sbePrimitiveType; } } + /// + /// The PrimitiveName as a string. + /// public override string ToString() => PrimitiveName; } } From 2da83043fffb7b9ef5a25ec9f032b5468dcc9877 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 9 Feb 2023 09:44:38 +0000 Subject: [PATCH 0992/1594] [C#] Try fix compilation errors. --- csharp/sbe-tests/InteropTests.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/csharp/sbe-tests/InteropTests.cs b/csharp/sbe-tests/InteropTests.cs index 43ef7fd0c3..24638dbd42 100644 --- a/csharp/sbe-tests/InteropTests.cs +++ b/csharp/sbe-tests/InteropTests.cs @@ -58,10 +58,10 @@ public void InteropDecodeTest() var car = new Car(); car.WrapForDecode(_directBuffer, MessageHeader.Size, _messageHeader.BlockLength, _messageHeader.Version); - Assert.AreEqual(1234UL, Car.SerialNumber); - Assert.AreEqual((ushort)2013, Car.ModelYear); - Assert.AreEqual(BooleanType.T, Car.Available); - Assert.AreEqual(Model.A, Car.Code); + Assert.AreEqual(1234UL, car.SerialNumber); + Assert.AreEqual((ushort)2013, car.ModelYear); + Assert.AreEqual(BooleanType.T, car.Available); + Assert.AreEqual(Model.A, car.Code); for (int i = 0, size = car.SomeNumbersLength; i < size; i++) { Assert.AreEqual(car.GetSomeNumbers(i), (uint)i+1); @@ -159,7 +159,6 @@ public void InteropDecodeTest() [TestMethod] public void InteropEncodeTest() { - car = new Car(); _directBuffer = new DirectBuffer(_encodeBuffer); _messageHeader.Wrap(_directBuffer, 0, Baseline.MessageHeader.SbeSchemaVersion); _messageHeader.BlockLength = Car.BlockLength; @@ -167,6 +166,8 @@ public void InteropEncodeTest() _messageHeader.TemplateId = Car.TemplateId; _messageHeader.Version = Car.SchemaVersion; + var car = new Car(); + // Populate the car with the known interop values car.WrapForEncode(_directBuffer, Baseline.MessageHeader.Size); car.SerialNumber = 1234; From fd93ad690e95cdd63a1912e5e592804e0e2c58de Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 9 Feb 2023 09:47:38 +0000 Subject: [PATCH 0993/1594] [C#] Qualify static methods with type. --- csharp/sbe-tests/InteropTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/sbe-tests/InteropTests.cs b/csharp/sbe-tests/InteropTests.cs index 24638dbd42..74d9014f13 100644 --- a/csharp/sbe-tests/InteropTests.cs +++ b/csharp/sbe-tests/InteropTests.cs @@ -62,7 +62,7 @@ public void InteropDecodeTest() Assert.AreEqual((ushort)2013, car.ModelYear); Assert.AreEqual(BooleanType.T, car.Available); Assert.AreEqual(Model.A, car.Code); - for (int i = 0, size = car.SomeNumbersLength; i < size; i++) + for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) { Assert.AreEqual(car.GetSomeNumbers(i), (uint)i+1); } @@ -174,7 +174,7 @@ public void InteropEncodeTest() car.ModelYear = 2013; car.Available = BooleanType.T; car.Code = Model.A; - for (int i = 0, size = car.SomeNumbersLength; i < size; i++) + for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) { car.SetSomeNumbers(i, (uint)i+1); } From 1019f1df26626dd89b1eed248da369ceedd567c8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 9 Feb 2023 09:55:36 +0000 Subject: [PATCH 0994/1594] [C#] Fix shadowing for BigEndianTests. --- csharp/sbe-tests/BigEndianTests.cs | 90 +++++++++++++++--------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/csharp/sbe-tests/BigEndianTests.cs b/csharp/sbe-tests/BigEndianTests.cs index e2369fb220..66d24e5df8 100644 --- a/csharp/sbe-tests/BigEndianTests.cs +++ b/csharp/sbe-tests/BigEndianTests.cs @@ -31,7 +31,6 @@ public unsafe class BigendianTests private DirectBuffer _directBuffer; private MessageHeader _messageHeader; - private Car Car; [TestInitialize] public void SetUp() @@ -46,36 +45,36 @@ public void BigendianDecodeTest() _directBuffer = new DirectBuffer(_decodeBuffer); _messageHeader.Wrap(_directBuffer, 0, Baseline.MessageHeader.SbeSchemaVersion); - var Car = new Car(); - Car.WrapForDecode(_directBuffer, MessageHeader.Size, _messageHeader.BlockLength, _messageHeader.Version); + var car = new Car(); + car.WrapForDecode(_directBuffer, MessageHeader.Size, _messageHeader.BlockLength, _messageHeader.Version); - Assert.AreEqual(1234UL, Car.SerialNumber); - Assert.AreEqual((ushort)2013, Car.ModelYear); - Assert.AreEqual(BooleanType.T, Car.Available); - Assert.AreEqual(Model.A, Car.Code); + Assert.AreEqual(1234UL, car.SerialNumber); + Assert.AreEqual((ushort)2013, car.ModelYear); + Assert.AreEqual(BooleanType.T, car.Available); + Assert.AreEqual(Model.A, car.Code); for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) { - Assert.AreEqual(Car.GetSomeNumbers(i), (uint)i); + Assert.AreEqual(car.GetSomeNumbers(i), (uint)i); } var btmp = new byte[6]; - Car.GetVehicleCode(btmp, 0); + car.GetVehicleCode(btmp, 0); var s = System.Text.Encoding.UTF8.GetString(btmp, 0, btmp.Length); Assert.AreEqual("abcdef", s); - Assert.AreEqual(OptionalExtras.CruiseControl | OptionalExtras.SportsPack, Car.Extras); - Assert.AreEqual((ushort)2000, Car.Engine.Capacity); - Assert.AreEqual((byte)4, Car.Engine.NumCylinders); + Assert.AreEqual(OptionalExtras.CruiseControl | OptionalExtras.SportsPack, car.Extras); + Assert.AreEqual((ushort)2000, car.Engine.Capacity); + Assert.AreEqual((byte)4, car.Engine.NumCylinders); btmp = new byte[3]; - Car.Engine.GetManufacturerCode(btmp, 0); + car.Engine.GetManufacturerCode(btmp, 0); s = System.Text.Encoding.UTF8.GetString(btmp, 0, btmp.Length); Assert.AreEqual("123", s); - Assert.AreEqual((sbyte)35, Car.Engine.Efficiency); - Assert.AreEqual(BooleanType.T, Car.Engine.BoosterEnabled); - Assert.AreEqual(BoostType.NITROUS, Car.Engine.Booster.BoostType); - Assert.AreEqual((byte)200, Car.Engine.Booster.HorsePower); + Assert.AreEqual((sbyte)35, car.Engine.Efficiency); + Assert.AreEqual(BooleanType.T, car.Engine.BoosterEnabled); + Assert.AreEqual(BoostType.NITROUS, car.Engine.Booster.BoostType); + Assert.AreEqual((byte)200, car.Engine.Booster.HorsePower); - var fuelFigures = Car.FuelFigures; + var fuelFigures = car.FuelFigures; Assert.AreEqual(3, fuelFigures.Count); fuelFigures.Next(); @@ -102,7 +101,7 @@ public void BigendianDecodeTest() s = System.Text.Encoding.UTF8.GetString(btmp, 0, btmp.Length); Assert.AreEqual("Highway Cycle", s); - var perfFigures = Car.PerformanceFigures; + var perfFigures = car.PerformanceFigures; Assert.AreEqual(2, perfFigures.Count); perfFigures.Next(); @@ -134,15 +133,15 @@ public void BigendianDecodeTest() Assert.AreEqual(11.8f, acceleration.Seconds); btmp = new byte[5]; - Car.GetManufacturer(btmp, 0, 5); + car.GetManufacturer(btmp, 0, 5); s = System.Text.Encoding.UTF8.GetString(btmp, 0, btmp.Length); Assert.AreEqual("Honda", s); btmp = new byte[9]; - Car.GetModel(btmp, 0, 9); + car.GetModel(btmp, 0, 9); s = System.Text.Encoding.UTF8.GetString(btmp, 0, btmp.Length); Assert.AreEqual("Civic VTi", s); btmp = new byte[6]; - Car.GetActivationCode(btmp, 0, 6); + car.GetActivationCode(btmp, 0, 6); s = System.Text.Encoding.UTF8.GetString(btmp, 0, btmp.Length); Assert.AreEqual("abcdef", s); } @@ -150,7 +149,6 @@ public void BigendianDecodeTest() [TestMethod] public void BigendianEncodeTest() { - Car = new Car(); _directBuffer = new DirectBuffer(_encodeBuffer); _messageHeader.Wrap(_directBuffer, 0, Baseline.MessageHeader.SbeSchemaVersion); _messageHeader.BlockLength = Car.BlockLength; @@ -158,28 +156,30 @@ public void BigendianEncodeTest() _messageHeader.TemplateId = Car.TemplateId; _messageHeader.Version = Car.SchemaVersion; + var car = new Car(); + // Populate the car with the known values - Car.WrapForEncode(_directBuffer, Baseline.MessageHeader.Size); - Car.SerialNumber = 1234; - Car.ModelYear = 2013; - Car.Available = BooleanType.T; - Car.Code = Model.A; + car.WrapForEncode(_directBuffer, Baseline.MessageHeader.Size); + car.SerialNumber = 1234; + car.ModelYear = 2013; + car.Available = BooleanType.T; + car.Code = Model.A; for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) { - Car.SetSomeNumbers(i, (uint)i); + car.SetSomeNumbers(i, (uint)i); } - Car.SetVehicleCode(System.Text.Encoding.ASCII.GetBytes("abcdef"), 0); - Car.Extras = OptionalExtras.CruiseControl | OptionalExtras.SportsPack; - - Car.Engine.Capacity = 2000; - Car.Engine.NumCylinders = 4; - Car.Engine.SetManufacturerCode(System.Text.Encoding.ASCII.GetBytes("123"), 0); - Car.Engine.Efficiency = 35; - Car.Engine.BoosterEnabled = BooleanType.T; - Car.Engine.Booster.BoostType = BoostType.NITROUS; - Car.Engine.Booster.HorsePower = 200; - - var fuelFigures = Car.FuelFiguresCount(3); + car.SetVehicleCode(System.Text.Encoding.ASCII.GetBytes("abcdef"), 0); + car.Extras = OptionalExtras.CruiseControl | OptionalExtras.SportsPack; + + car.Engine.Capacity = 2000; + car.Engine.NumCylinders = 4; + car.Engine.SetManufacturerCode(System.Text.Encoding.ASCII.GetBytes("123"), 0); + car.Engine.Efficiency = 35; + car.Engine.BoosterEnabled = BooleanType.T; + car.Engine.Booster.BoostType = BoostType.NITROUS; + car.Engine.Booster.HorsePower = 200; + + var fuelFigures = car.FuelFiguresCount(3); fuelFigures.Next(); fuelFigures.Speed = 30; fuelFigures.Mpg = 35.9f; @@ -195,7 +195,7 @@ public void BigendianEncodeTest() fuelFigures.Mpg = 40.0f; fuelFigures.SetUsageDescription(System.Text.Encoding.ASCII.GetBytes("Highway Cycle"), 0, 13); - var perfFigures = Car.PerformanceFiguresCount(2); + var perfFigures = car.PerformanceFiguresCount(2); perfFigures.Next(); perfFigures.OctaneRating = 95; @@ -226,9 +226,9 @@ public void BigendianEncodeTest() acceleration.Mph = 100; acceleration.Seconds = 11.8f; - Car.SetManufacturer(System.Text.Encoding.ASCII.GetBytes("Honda"), 0, 5); - Car.SetModel(System.Text.Encoding.ASCII.GetBytes("Civic VTi"), 0, 9); - Car.SetActivationCode(System.Text.Encoding.ASCII.GetBytes("abcdef"), 0, 6); + car.SetManufacturer(System.Text.Encoding.ASCII.GetBytes("Honda"), 0, 5); + car.SetModel(System.Text.Encoding.ASCII.GetBytes("Civic VTi"), 0, 9); + car.SetActivationCode(System.Text.Encoding.ASCII.GetBytes("abcdef"), 0, 6); for (int i = 0; i < _decodeBuffer.Length; i++) { From d5057a42d572659bb4fdece7a70b7bb2d25a3161 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 9 Feb 2023 10:15:07 +0000 Subject: [PATCH 0995/1594] [C#] Filter constant comparison checks. --- .github/codeql/codeql-config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index 224ed0e44c..e7c7cc873b 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -20,6 +20,8 @@ query-filters: id: cs/useless-assignment-to-local - exclude: id: cs/complex-block + - exclude: + id: cs/constant-comparison - exclude: id: cpp/trivial-switch - exclude: From be8d12d9c3695c34ac7248e67e9d2371bdc0af4a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 9 Feb 2023 10:35:20 +0000 Subject: [PATCH 0996/1594] [C#] Compare doubles with a tolerance. --- csharp/sbe-dll/PrimitiveValue.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/csharp/sbe-dll/PrimitiveValue.cs b/csharp/sbe-dll/PrimitiveValue.cs index c455ab2dcd..49c5ba0aff 100644 --- a/csharp/sbe-dll/PrimitiveValue.cs +++ b/csharp/sbe-dll/PrimitiveValue.cs @@ -500,7 +500,11 @@ public override bool Equals(object value) return _unsignedLongValue == rhs._unsignedLongValue; case Representation.Double: - return _doubleValue == rhs._doubleValue; + { + const double EPSILON = 1e-10; + return (_doubleValue == rhs._doubleValue) || + (Math.Abs(_doubleValue - rhs._doubleValue) < EPSILON); + } case Representation.ByteArray: return _byteArrayValue.SequenceEqual(rhs._byteArrayValue); From a1ea4e8b40e9b75e01aa753eb3ab891932c62034 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 9 Feb 2023 10:59:45 +0000 Subject: [PATCH 0997/1594] [C#] Use Double.Equals to compare double values in PrimitiveValue. --- csharp/sbe-dll/PrimitiveValue.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/csharp/sbe-dll/PrimitiveValue.cs b/csharp/sbe-dll/PrimitiveValue.cs index 49c5ba0aff..00b9707bdf 100644 --- a/csharp/sbe-dll/PrimitiveValue.cs +++ b/csharp/sbe-dll/PrimitiveValue.cs @@ -501,9 +501,7 @@ public override bool Equals(object value) case Representation.Double: { - const double EPSILON = 1e-10; - return (_doubleValue == rhs._doubleValue) || - (Math.Abs(_doubleValue - rhs._doubleValue) < EPSILON); + return _doubleValue.Equals(rhs._doubleValue); } case Representation.ByteArray: From 8d6f29b76f6c5f4067d7c11a2aadc512e0fcbd42 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 9 Feb 2023 11:12:59 +0000 Subject: [PATCH 0998/1594] [C#] Compare PrimitiveValue with doubles in the same way as Java by the raw bits, so NaN and Infinity are correctly handled. --- csharp/sbe-dll/PrimitiveValue.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/sbe-dll/PrimitiveValue.cs b/csharp/sbe-dll/PrimitiveValue.cs index 00b9707bdf..14e1d191d9 100644 --- a/csharp/sbe-dll/PrimitiveValue.cs +++ b/csharp/sbe-dll/PrimitiveValue.cs @@ -501,7 +501,7 @@ public override bool Equals(object value) case Representation.Double: { - return _doubleValue.Equals(rhs._doubleValue); + return BitConverter.DoubleToInt64Bits(_doubleValue) == BitConverter.DoubleToInt64Bits(rhs._doubleValue); } case Representation.ByteArray: From 84bbf2eed852a56d403f206e9dc9683cd9fba8f7 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 9 Feb 2023 11:13:23 +0000 Subject: [PATCH 0999/1594] [C#] Formatting. --- csharp/sbe-dll/PrimitiveValue.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/csharp/sbe-dll/PrimitiveValue.cs b/csharp/sbe-dll/PrimitiveValue.cs index 14e1d191d9..a579baa158 100644 --- a/csharp/sbe-dll/PrimitiveValue.cs +++ b/csharp/sbe-dll/PrimitiveValue.cs @@ -500,9 +500,7 @@ public override bool Equals(object value) return _unsignedLongValue == rhs._unsignedLongValue; case Representation.Double: - { return BitConverter.DoubleToInt64Bits(_doubleValue) == BitConverter.DoubleToInt64Bits(rhs._doubleValue); - } case Representation.ByteArray: return _byteArrayValue.SequenceEqual(rhs._byteArrayValue); From a640a451c31256f5efb83a4b44b51c660176c512 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 15 Feb 2023 10:18:15 +0000 Subject: [PATCH 1000/1594] [Java] Warnings cleanup. --- build.gradle | 8 ++++---- .../main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java | 4 ++-- .../java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index c7b707c1f4..d5102e37f9 100644 --- a/build.gradle +++ b/build.gradle @@ -138,7 +138,7 @@ allprojects { mavenCentral() } - configurations.all { + configurations.configureEach { resolutionStrategy { failOnVersionConflict() } @@ -166,18 +166,18 @@ subprojects { checkstyle.toolVersion = "${checkstyleVersion}" - tasks.withType(Sign) { + tasks.withType(Sign).configureEach { onlyIf { isReleaseVersion && gradle.taskGraph.hasTask(tasks.publish) } } - tasks.withType(Jar) { + tasks.withType(Jar).configureEach { enabled = true includeEmptyDirs = false } - tasks.withType(JavaCompile) { + tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' options.deprecation = true options.compilerArgs.addAll(['-Xlint:all', '-Werror']) // Enable all warnings and treat them as errors diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java index 0e020cae75..744fb0c15c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java @@ -133,10 +133,10 @@ public static int findEndSignal( } /** - * Find a list of sub-group names. + * Find a list of subgroup names. * * @param tokens to search. - * @return list of names for the sub-groups. + * @return list of names for the subgroups. */ public static List findSubGroupNames(final List tokens) { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index fd36fc3de3..bda3393aa9 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -198,7 +198,7 @@ void shouldExitAfterTypesWhenCompositeOffsetsIncorrect() throws Exception @Test void shouldExitAfterTypesWhenCompositeHasInvalidTypes() throws Exception { - try (InputStream in = Tests.getLocalResource("error-handler-invalid-composite.xml");) + try (InputStream in = Tests.getLocalResource("error-handler-invalid-composite.xml")) { final ParserOptions options = ParserOptions.builder().suppressOutput(true).warningsFatal(true).build(); parse(in, options); From e208bb51f63c739a090cba5afd72bce34ea7e032 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 24 Feb 2023 15:39:44 +0100 Subject: [PATCH 1001/1594] [Java] Upgrade to versions plugin 0.46.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d5102e37f9..d7dbd02bdd 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ import java.security.MessageDigest plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '7.1.2' apply false - id "com.github.ben-manes.versions" version "0.45.0" + id 'com.github.ben-manes.versions' version '0.46.0' } defaultTasks 'clean', 'build' From d9bb75b8d401448095faec1884b367db3c88dc1a Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 24 Feb 2023 15:47:04 +0100 Subject: [PATCH 1002/1594] [Gradle] Use lazy task configuration. --- build.gradle | 215 ++++++++++++++++++++++++++------------------------- 1 file changed, 111 insertions(+), 104 deletions(-) diff --git a/build.gradle b/build.gradle index d7dbd02bdd..b58ba21e0f 100644 --- a/build.gradle +++ b/build.gradle @@ -260,14 +260,15 @@ project(':sbe-tool') { compileTestJava.dependsOn compileGeneratedJava - task generateTestCodecs(dependsOn: 'compileJava', type: JavaExec) { + tasks.register('generateTestCodecs', JavaExec) { + dependsOn 'compileJava' mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': generatedDir, - 'sbe.target.language': 'Java', - 'sbe.validation.stop.on.error': 'true', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.output.dir': generatedDir, + 'sbe.target.language': 'Java', + 'sbe.validation.stop.on.error': 'true', + 'sbe.validation.xsd': validationXsdPath) args = ['src/test/resources/json-printer-test-schema.xml', 'src/test/resources/composite-elements-schema.xml'] } @@ -283,10 +284,10 @@ project(':sbe-tool') { ) } - task sourcesJar(type: Jar) { + tasks.register('sourcesJar', Jar) { archiveClassifier.set('sources') from sourceSets.main.allSource - from ('src/main/cpp/otf') { + from('src/main/cpp/otf') { into 'cpp' } } @@ -344,10 +345,10 @@ project(':sbe-all') { jar.finalizedBy shadowJar - task sourcesJar(type: Jar) { + tasks.register('sourcesJar', Jar) { archiveClassifier.set('sources') from project(':sbe-tool').sourceSets.main.allSource - from (project(':sbe-tool').file('src/main/cpp/otf')) { + from(project(':sbe-tool').file('src/main/cpp/otf')) { into 'cpp' } } @@ -356,7 +357,8 @@ project(':sbe-all') { source += project(':sbe-tool').sourceSets.main.allJava } - task javadocJar(type: Jar, dependsOn: javadoc) { + tasks.register('javadocJar', Jar) { + dependsOn javadoc archiveClassifier.set('javadoc') from javadoc.destinationDir } @@ -406,39 +408,42 @@ project(':sbe-samples') { compileJava.dependsOn 'compileGeneratedJava' compileGeneratedJava.dependsOn 'generateCodecs' - task generateCodecs(type: JavaExec) { + tasks.register('generateCodecs', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': generatedDir, - 'sbe.target.language': 'Java', - 'sbe.java.generate.interfaces': 'true', - 'sbe.validation.stop.on.error': 'true', - 'sbe.decode.unknown.enum.values': 'true', - 'sbe.xinclude.aware': 'true', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.output.dir': generatedDir, + 'sbe.target.language': 'Java', + 'sbe.java.generate.interfaces': 'true', + 'sbe.validation.stop.on.error': 'true', + 'sbe.decode.unknown.enum.values': 'true', + 'sbe.xinclude.aware': 'true', + 'sbe.validation.xsd': validationXsdPath) args = ['src/main/resources/example-schema.xml', 'src/main/resources/example-extension-schema.xml'] } - task runExampleUsingGeneratedStub(dependsOn: 'compileJava', type: JavaExec) { + tasks.register('runExampleUsingGeneratedStub', JavaExec) { + dependsOn 'compileJava' mainClass.set('uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub') classpath = sourceSets.main.runtimeClasspath systemProperties System.getProperties() } - task runExampleUsingGeneratedStubExtension(dependsOn: 'compileJava', type: JavaExec) { + tasks.register('runExampleUsingGeneratedStubExtension', JavaExec) { + dependsOn 'compileJava' mainClass.set('uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension') classpath = sourceSets.main.runtimeClasspath systemProperties System.getProperties() } - task runOtfExample(dependsOn: 'compileJava', type: JavaExec) { + tasks.register('runOtfExample', JavaExec) { + dependsOn 'compileJava' mainClass.set('uk.co.real_logic.sbe.examples.OtfExample') classpath = sourceSets.main.runtimeClasspath workingDir = 'src/main/resources' } - task runJavaExamples { + tasks.register('runJavaExamples') { dependsOn 'runExampleUsingGeneratedStub', 'runExampleUsingGeneratedStubExtension', 'runOtfExample' } @@ -456,7 +461,7 @@ project(':sbe-samples') { ) } - task sourcesJar(type: Jar) { + tasks.register('sourcesJar', Jar) { archiveClassifier.set('sources') from sourceSets.main.allSource from sourceSets.generated.allSource @@ -516,16 +521,16 @@ project(':sbe-benchmarks') { compileGeneratedJava.dependsOn 'generateCodecs' compileJava.dependsOn 'compileGeneratedJava' - task generateCodecs(type: JavaExec) { + tasks.register('generateCodecs', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'build/generated-src', - 'sbe.target.language': 'Java', - 'sbe.validation.stop.on.error': 'true', - 'sbe.validation.xsd': validationXsdPath, - 'sbe.java.encoding.buffer.type': 'org.agrona.concurrent.UnsafeBuffer', - 'sbe.java.decoding.buffer.type': 'org.agrona.concurrent.UnsafeBuffer') + 'sbe.output.dir': 'build/generated-src', + 'sbe.target.language': 'Java', + 'sbe.validation.stop.on.error': 'true', + 'sbe.validation.xsd': validationXsdPath, + 'sbe.java.encoding.buffer.type': 'org.agrona.concurrent.UnsafeBuffer', + 'sbe.java.decoding.buffer.type': 'org.agrona.concurrent.UnsafeBuffer') args = ['src/main/resources/car.xml', 'src/main/resources/fix-message-samples.xml'] } @@ -539,10 +544,7 @@ project(':sbe-benchmarks') { javadoc.enabled = false } -/* - * Rust codec targets used for testing - */ -task generateRustExamples(type: JavaExec) { +tasks.register('generateRustExamples', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( @@ -557,7 +559,7 @@ task generateRustExamples(type: JavaExec) { ] } -task generateRustTestCodecs(type: JavaExec) { +tasks.register('generateRustTestCodecs', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( @@ -572,7 +574,7 @@ task generateRustTestCodecs(type: JavaExec) { ] } -task generateCarExampleDataFile(type: JavaExec) { +tasks.register('generateCarExampleDataFile', JavaExec) { mainClass.set('uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub') classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath systemProperties('sbe.encoding.filename': 'rust/car_example_baseline_data.sbe') @@ -580,7 +582,7 @@ task generateCarExampleDataFile(type: JavaExec) { standardOutput = new ByteArrayOutputStream() } -task generateCarExampleExtensionDataFile(type: JavaExec) { +tasks.register('generateCarExampleExtensionDataFile', JavaExec) { mainClass.set('uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension') classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath systemProperties('sbe.encoding.filename': 'rust/car_example_extension_data.sbe') @@ -588,13 +590,13 @@ task generateCarExampleExtensionDataFile(type: JavaExec) { standardOutput = new ByteArrayOutputStream() } -task generateRustCodecs { +tasks.register('generateRustCodecs') { description = 'Generate rust test codecs' dependsOn 'generateRustExamples', 'generateRustTestCodecs', 'generateCarExampleDataFile', 'generateCarExampleExtensionDataFile' } -task runRustTests(type: Exec) { +tasks.register('runRustTests', Exec) { workingDir = './rust' executable = 'cargo' args = ['test'] @@ -610,62 +612,62 @@ task runRustTests(type: Exec) { * as they generate into the same directory and golang won't allow that. * *) Some examples need to fiddle with WorkingDir to deal with XInclude */ -task generateGolangCodecTestComposite(type: JavaExec) { +tasks.register('generateGolangCodecTestComposite', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'gocode/src', - 'sbe.target.language': 'golang') + 'sbe.output.dir': 'gocode/src', + 'sbe.target.language': 'golang') args = ['sbe-tool/src/test/resources/composite-elements-schema-rc4.xml'] } -task generateGolangCodecTestBasic(type: JavaExec) { +tasks.register('generateGolangCodecTestBasic', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'gocode/src/basic', - 'sbe.target.language': 'golang') + 'sbe.output.dir': 'gocode/src/basic', + 'sbe.target.language': 'golang') args = ['sbe-tool/src/test/resources/basic-types-schema.xml'] } -task generateGolangCodecTestGroup(type: JavaExec) { +tasks.register('generateGolangCodecTestGroup', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'gocode/src/group', - 'sbe.target.language': 'golang') + 'sbe.output.dir': 'gocode/src/group', + 'sbe.target.language': 'golang') args = ['sbe-tool/src/test/resources/basic-group-schema.xml'] } -task generateGolangCodecTestVarData(type: JavaExec) { +tasks.register('generateGolangCodecTestVarData', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'gocode/src/vardata', - 'sbe.target.language': 'golang') + 'sbe.output.dir': 'gocode/src/vardata', + 'sbe.target.language': 'golang') args = ['sbe-tool/src/test/resources/basic-variable-length-schema.xml'] } -task generateGolangCodecsWithXIncludes(type: JavaExec) { +tasks.register('generateGolangCodecsWithXIncludes', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'gocode/src', - 'sbe.target.language': 'golang', - 'sbe.xinclude.aware': 'true', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.output.dir': 'gocode/src', + 'sbe.target.language': 'golang', + 'sbe.xinclude.aware': 'true', + 'sbe.validation.xsd': validationXsdPath) args = ['sbe-samples/src/main/resources/example-schema.xml', 'sbe-samples/src/main/resources/example-extension-schema.xml'] } -task generateGolangCodecsWithXSD(type: JavaExec) { +tasks.register('generateGolangCodecsWithXSD', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'gocode/src', - 'sbe.target.language': 'golang', - 'sbe.xinclude.aware': 'true', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.output.dir': 'gocode/src', + 'sbe.target.language': 'golang', + 'sbe.xinclude.aware': 'true', + 'sbe.validation.xsd': validationXsdPath) args = ['sbe-tool/src/test/resources/group-with-data-schema.xml', 'sbe-tool/src/test/resources/FixBinary.xml', 'sbe-tool/src/test/resources/issue435.xml', @@ -684,40 +686,40 @@ task generateGolangCodecsWithXSD(type: JavaExec) { 'gocode/resources/simple.xml'] } -task generateGolangCodecs { +tasks.register('generateGolangCodecs') { description = 'Generate golang test codecs' dependsOn 'generateGolangCodecTestVarData', - 'generateGolangCodecTestGroup', - 'generateGolangCodecTestBasic', - 'generateGolangCodecTestComposite', - 'generateGolangCodecsWithXIncludes', - 'generateGolangCodecsWithXSD' + 'generateGolangCodecTestGroup', + 'generateGolangCodecTestBasic', + 'generateGolangCodecTestComposite', + 'generateGolangCodecsWithXIncludes', + 'generateGolangCodecsWithXSD' } /* * CSharp codec targets used for testing, benchmarking etc. We have * multiple targets as XInclude forces us to change working dir */ -task generateCSharpCodecsWithXIncludes(type: JavaExec) { +tasks.register('generateCSharpCodecsWithXIncludes', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'csharp/sbe-generated', - 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharp', - 'sbe.xinclude.aware': 'true', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.output.dir': 'csharp/sbe-generated', + 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharp', + 'sbe.xinclude.aware': 'true', + 'sbe.validation.xsd': validationXsdPath) args = ['sbe-samples/src/main/resources/example-schema.xml', 'sbe-samples/src/main/resources/example-extension-schema.xml'] } -task generateCSharpCodecsTests(type: JavaExec) { +tasks.register('generateCSharpCodecsTests', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'csharp/sbe-generated', - 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharp', - 'sbe.xinclude.aware': 'true', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.output.dir': 'csharp/sbe-generated', + 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharp', + 'sbe.xinclude.aware': 'true', + 'sbe.validation.xsd': validationXsdPath) args = ['sbe-tool/src/test/resources/FixBinary.xml', 'sbe-tool/src/test/resources/issue435.xml', 'sbe-tool/src/test/resources/issue483.xml', @@ -727,55 +729,57 @@ task generateCSharpCodecsTests(type: JavaExec) { 'sbe-benchmarks/src/main/resources/fix-message-samples.xml'] } -task generateCSharpCodecs { +tasks.register('generateCSharpCodecs') { description = 'Generate csharp codecs' dependsOn 'generateCSharpCodecsTests', - 'generateCSharpCodecsWithXIncludes' + 'generateCSharpCodecsWithXIncludes' } -task generateJavaIrCodecs(type: JavaExec, dependsOn: 'computeOriginalIrHash') { +tasks.register('generateJavaIrCodecs', JavaExec) { + dependsOn 'computeOriginalIrHash' mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-all').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'sbe-tool/src/main/java', - 'sbe.target.language': 'Java', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.output.dir': 'sbe-tool/src/main/java', + 'sbe.target.language': 'Java', + 'sbe.validation.xsd': validationXsdPath) args = ['sbe-tool/src/main/resources/sbe-ir.xml'] } -task generateCppIrCodecs(type: JavaExec) { +tasks.register('generateCppIrCodecs', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'sbe-tool/src/main/cpp', - 'sbe.target.language': 'cpp', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.output.dir': 'sbe-tool/src/main/cpp', + 'sbe.target.language': 'cpp', + 'sbe.validation.xsd': validationXsdPath) args = ['sbe-tool/src/main/resources/sbe-ir.xml'] } -task generateGolangIrCodecs(type: JavaExec) { +tasks.register('generateGolangIrCodecs', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'sbe-tool/src/main/golang', - 'sbe.target.language': 'golang', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.output.dir': 'sbe-tool/src/main/golang', + 'sbe.target.language': 'golang', + 'sbe.validation.xsd': validationXsdPath) args = ['sbe-tool/src/main/resources/sbe-ir.xml'] } -task generateIrCodecs { +tasks.register('generateIrCodecs') { description = 'Generate Java, C++, and golang IR Codecs' dependsOn 'generateJavaIrCodecs', 'generateCppIrCodecs', 'generateGolangIrCodecs' } -task runJavaBenchmarks(type: Exec, dependsOn: 'sbe-benchmarks:jar') { +tasks.register('runJavaBenchmarks', Exec) { + dependsOn 'sbe-benchmarks:jar' commandLine toolchainLauncher.get().executablePath, - '-jar', 'sbe-benchmarks/build/libs/sbe-benchmarks.jar', - '-jvmArgs', '-Dagrona.disable.bounds.checks=true -XX:+UseParallelGC', - '-w', '1s', '-r', '1s','-wi', '3', '-i', '5', '-tu', 'ns', '-f', '5' + '-jar', 'sbe-benchmarks/build/libs/sbe-benchmarks.jar', + '-jvmArgs', '-Dagrona.disable.bounds.checks=true -XX:+UseParallelGC', + '-w', '1s', '-r', '1s', '-wi', '3', '-i', '5', '-tu', 'ns', '-f', '5' } -task testReport(type: TestReport) { +tasks.register('testReport', TestReport) { destinationDirectory = file("$buildDir/reports/allTests") // Include the results from the `test` task in all sub-projects testResults.setFrom(subprojects*.test) @@ -786,27 +790,32 @@ final outputDir = project.file('sbe-tool/build') final oldHashFile = new File(outputDir, 'old.sha256') final newHashFile = new File(outputDir, 'new.sha256') -task computeOriginalIrHash(type: ChecksumTask) { +tasks.register('computeOriginalIrHash', ChecksumTask) { inputDirectory = codecsDir outputFile = oldHashFile } -task computeUpdatedIrHash(type: ChecksumTask, dependsOn: 'generateJavaIrCodecs') { +tasks.register('computeUpdatedIrHash', ChecksumTask) { + dependsOn 'generateJavaIrCodecs' inputDirectory = codecsDir outputFile = newHashFile } -task verifyJavaIrCodecsInSync(dependsOn: 'computeUpdatedIrHash') { +tasks.register('verifyJavaIrCodecsInSync') { + dependsOn 'computeUpdatedIrHash' doLast { final byte[] oldHash = Files.readAllBytes(oldHashFile.toPath()) final byte[] newHash = Files.readAllBytes(newHashFile.toPath()) - if (!Arrays.equals(oldHash, newHash)) - { + if (!Arrays.equals(oldHash, newHash)) { throw new GradleException("Java Ir codecs are out of sync! Please execute the `generateJavaIrCodecs` task and commit the changes.") } } } +tasks.named('build').configure { + dependsOn 'verifyJavaIrCodecsInSync' +} + def isNonStable = { String version -> def stableKeyword = ['RELEASE', 'FINAL', 'GA'].any { it -> version.toUpperCase().contains(it) } def regex = /^[0-9,.v-]+(-r)?$/ @@ -820,8 +829,6 @@ tasks.named('dependencyUpdates').configure { } } -tasks.findByName('build').dependsOn verifyJavaIrCodecsInSync - wrapper { gradleVersion = '7.6' distributionType = 'ALL' From ef309b21ceed242f90010604a13c3e349608c7aa Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 28 Feb 2023 14:05:25 +0100 Subject: [PATCH 1003/1594] [Gradle] Upgrade to Gradle 8.0.1 and Shadow 8.1.0. --- build.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index b58ba21e0f..5d3bf9e3e9 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ import java.security.MessageDigest plugins { id 'java-library' - id 'com.github.johnrengelman.shadow' version '7.1.2' apply false + id 'com.github.johnrengelman.shadow' version '8.1.0' apply false id 'com.github.ben-manes.versions' version '0.46.0' } @@ -830,7 +830,7 @@ tasks.named('dependencyUpdates').configure { } wrapper { - gradleVersion = '7.6' + gradleVersion = '8.0.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2b22d057a0..6ec1567a0f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 3296c5e1cd3ea5ba1d19b641dae3e32d4a7a420f Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 28 Feb 2023 15:43:12 +0100 Subject: [PATCH 1004/1594] [Java] Add JDK 20-ea to the build matrix. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1959daf8ab..2bc7b1a537 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '11', '17', '18' ] + java: [ '8', '11', '17', '20-ea' ] os: [ 'ubuntu-22.04', 'windows-latest' ] steps: - name: Checkout code From 7186909547e00ea8d623312b460c9859e573970c Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 28 Feb 2023 23:48:33 +0100 Subject: [PATCH 1005/1594] [Gradle] Revert back to Gradle 7.6. --- .github/workflows/ci.yml | 2 +- build.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 61608 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2bc7b1a537..ed6e5ae9bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '11', '17', '20-ea' ] + java: [ '8', '11', '17' ] os: [ 'ubuntu-22.04', 'windows-latest' ] steps: - name: Checkout code diff --git a/build.gradle b/build.gradle index 5d3bf9e3e9..b58ba21e0f 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ import java.security.MessageDigest plugins { id 'java-library' - id 'com.github.johnrengelman.shadow' version '8.1.0' apply false + id 'com.github.johnrengelman.shadow' version '7.1.2' apply false id 'com.github.ben-manes.versions' version '0.46.0' } @@ -830,7 +830,7 @@ tasks.named('dependencyUpdates').configure { } wrapper { - gradleVersion = '8.0.1' + gradleVersion = '7.6' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..ccebba7710deaf9f98673a68957ea02138b60d0a 100644 GIT binary patch delta 5094 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 delta 5107 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 I6Xdi10eY*&F8}}l diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6ec1567a0f..2b22d057a0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 65dcd68d65..79a61d421c 100755 --- a/gradlew +++ b/gradlew @@ -144,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac From 0385eb72e4be40ca3b3373400639ffbec3f2fe7b Mon Sep 17 00:00:00 2001 From: Renan Date: Sun, 12 Mar 2023 09:13:00 -0300 Subject: [PATCH 1006/1594] Added semantic version as a static public member (#931) * Added semantic version as a static public member accessible in the generated stubs. * Added generated java ir codecs. * Added constexpr in static c++ semanticVersion. * Fixing cpp codeGenTest. * Adjustments based on the pr comments. * Adjustments based on the pr comments. --- .../sbe/generation/c/CGenerator.java | 9 ++++++- .../sbe/generation/cpp/CppGenerator.java | 24 +++++++++++++++++-- .../generation/csharp/CSharpGenerator.java | 7 ++++-- .../generation/golang/GolangGenerator.java | 7 +++++- .../sbe/generation/java/JavaGenerator.java | 10 ++++++-- .../sbe/generation/rust/RustGenerator.java | 4 +++- .../sbe/ir/generated/FrameCodecDecoder.java | 1 + .../sbe/ir/generated/FrameCodecEncoder.java | 1 + .../ir/generated/MessageHeaderDecoder.java | 1 + .../ir/generated/MessageHeaderEncoder.java | 1 + .../sbe/ir/generated/TokenCodecDecoder.java | 1 + .../sbe/ir/generated/TokenCodecEncoder.java | 1 + .../ir/generated/VarDataEncodingDecoder.java | 1 + .../ir/generated/VarDataEncodingEncoder.java | 1 + sbe-tool/src/test/c/CodeGenTest.cpp | 1 + sbe-tool/src/test/cpp/CodeGenTest.cpp | 1 + 16 files changed, 62 insertions(+), 9 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 61f6cb87c7..8b71264be2 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1894,6 +1894,7 @@ private CharSequence generateMessageFlyweightFunctions( final String schemaVersionType = cTypeName(ir.headerStructure().schemaVersionType()); final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); final String messageHeaderStruct = formatScopedName(scope, "messageHeader"); + final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); return String.format("\n" + "SBE_ONE_DEF uint64_t %10$s_sbe_position(\n" + @@ -1974,6 +1975,11 @@ private CharSequence generateMessageFlyweightFunctions( " return %8$s;\n" + "}\n\n" + + "SBE_ONE_DEF const char* %10$s_sbe_semantic_version(void)\n" + + "{\n" + + " return \"%12$s\";\n" + + "}\n\n" + + "SBE_ONE_DEF const char *%10$s_sbe_semantic_type(void)\n" + "{\n" + " return \"%9$s\";\n" + @@ -2093,7 +2099,8 @@ private CharSequence generateMessageFlyweightFunctions( generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), semanticType, structName, - messageHeaderStruct); + messageHeaderStruct, + semanticVersion); } private CharSequence generateFieldFunctions( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 54fa183222..ddbc1aadcf 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -169,6 +169,7 @@ public void generate() throws IOException generateDisplay(sb, msgToken.name(), fields, groups, varData); sb.append(generateMessageLength(groups, varData, BASE_INDENT)); sb.append("};\n"); + sb.append(generateStaticVariablesInitialization(className)); sb.append(CppUtil.closingBraces(ir.namespaces().length)).append("#endif\n"); out.append(sb); } @@ -1973,6 +1974,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final final String schemaVersionType = cppTypeName(ir.headerStructure().schemaVersionType()); final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); final String headerType = ir.headerStructure().tokens().get(0).name(); + final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); return String.format( "private:\n" + @@ -1992,7 +1994,8 @@ private CharSequence generateMessageFlyweightCode(final String className, final " static const %1$s SBE_BLOCK_LENGTH = %2$s;\n" + " static const %3$s SBE_TEMPLATE_ID = %4$s;\n" + " static const %5$s SBE_SCHEMA_ID = %6$s;\n" + - " static const %7$s SBE_SCHEMA_VERSION = %8$s;\n\n" + + " static const %7$s SBE_SCHEMA_VERSION = %8$s;\n" + + " static const char* SBE_SEMANTIC_VERSION;\n\n" + " enum MetaAttribute\n" + " {\n" + @@ -2039,6 +2042,11 @@ private CharSequence generateMessageFlyweightCode(final String className, final " return %8$s;\n" + " }\n\n" + + " SBE_NODISCARD static const char *sbeSemanticVersion() SBE_NOEXCEPT\n" + + " {\n" + + " return \"%13$s\";\n" + + " }\n\n" + + " SBE_NODISCARD static SBE_CONSTEXPR const char *sbeSemanticType() SBE_NOEXCEPT\n" + " {\n" + " return \"%9$s\";\n" + @@ -2151,7 +2159,8 @@ private CharSequence generateMessageFlyweightCode(final String className, final semanticType, className, generateConstructorsAndOperators(className), - formatClassName(headerType)); + formatClassName(headerType), + semanticVersion); } private void generateFields( @@ -3184,4 +3193,15 @@ private CharSequence generateMessageLength(final List groups, final List< return sb; } + + private CharSequence generateStaticVariablesInitialization(final String className) + { + final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); + + return String.format( + "\n" + + "const char* %1$s::SBE_SEMANTIC_VERSION = \"%2$s\";\n\n", + className, + semanticVersion); + } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 732b322e8d..5a607a8414 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1163,13 +1163,15 @@ private CharSequence generateMessageFlyweightCode(final String className, final final String schemaIdType = cSharpTypeName(ir.headerStructure().schemaIdType()); final String schemaVersionType = cSharpTypeName(ir.headerStructure().schemaVersionType()); final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); + final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); return String.format( indent + INDENT + "public const %1$s BlockLength = %2$s;\n" + indent + INDENT + "public const %3$s TemplateId = %4$s;\n" + indent + INDENT + "public const %5$s SchemaId = %6$s;\n" + indent + INDENT + "public const %7$s SchemaVersion = %8$s;\n" + - indent + INDENT + "public const string SemanticType = \"%9$s\";\n\n" + + indent + INDENT + "public const string SemanticType = \"%9$s\";\n" + + indent + INDENT + "public const string SemanticVersion = \"%11$s\";\n\n" + indent + INDENT + "private readonly %10$s _parentMessage;\n" + indent + INDENT + "private DirectBuffer _buffer;\n" + indent + INDENT + "private int _offset;\n" + @@ -1238,7 +1240,8 @@ private CharSequence generateMessageFlyweightCode(final String className, final schemaVersionType, generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), semanticType, - className); + className, + semanticVersion); } private CharSequence generateFields(final List tokens, final String indent) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index e059524da8..1f5e238bff 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -2099,6 +2099,7 @@ private void generateMessageCode( final String templateIdType = golangTypeName(ir.headerStructure().templateIdType()); final String schemaIdType = golangTypeName(ir.headerStructure().schemaIdType()); final String schemaVersionType = golangTypeName(ir.headerStructure().schemaVersionType()); + final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); generateEncodeDecode(sb, typeName, tokens, true, true); @@ -2117,6 +2118,9 @@ private void generateMessageCode( "}\n" + "\nfunc (*%1$s) SbeSemanticType() (semanticType []byte) {\n" + "\treturn []byte(\"%10$s\")\n" + + "}\n" + + "\nfunc (*%1$s) SbeSemanticVersion() (semanticVersion string) {\n" + + "\treturn \"%11$s\"\n" + "}\n", typeName, blockLengthType, @@ -2127,7 +2131,8 @@ private void generateMessageCode( generateLiteral(ir.headerStructure().schemaIdType(), Integer.toString(ir.id())), schemaVersionType, generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), - semanticType)); + semanticType, + semanticVersion)); } // Used for groups which need to know the schema's definition diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 233c9aecbe..d44bf668b8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2611,10 +2611,12 @@ private CharSequence generateFixedFlyweightCode( final String schemaIdAccessorType = shouldGenerateInterfaces ? "int" : schemaIdType; final String schemaVersionType = javaTypeName(ir.headerStructure().schemaVersionType()); final String schemaVersionAccessorType = shouldGenerateInterfaces ? "int" : schemaVersionType; + final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); return String.format( " public static final %5$s SCHEMA_ID = %6$s;\n" + " public static final %7$s SCHEMA_VERSION = %8$s;\n" + + " public static final String SEMANTIC_VERSION = \"%11$s\";\n" + " public static final int ENCODED_LENGTH = %2$d;\n" + " public static final java.nio.ByteOrder BYTE_ORDER = java.nio.ByteOrder.%4$s;\n\n" + " private int offset;\n" + @@ -2657,7 +2659,8 @@ private CharSequence generateFixedFlyweightCode( schemaVersionType, generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), schemaIdAccessorType, - schemaVersionAccessorType); + schemaVersionAccessorType, + semanticVersion); } private CharSequence generateDecoderFlyweightCode(final String className, final Token token) @@ -2735,6 +2738,7 @@ private CharSequence generateFlyweightCode( final String schemaVersionType = javaTypeName(headerStructure.schemaVersionType()); final String schemaVersionAccessorType = shouldGenerateInterfaces ? "int" : schemaVersionType; final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); + final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); final String actingFields = codecType == CodecType.ENCODER ? "" : " int actingBlockLength;\n" + @@ -2745,6 +2749,7 @@ private CharSequence generateFlyweightCode( " public static final %3$s TEMPLATE_ID = %4$s;\n" + " public static final %5$s SCHEMA_ID = %6$s;\n" + " public static final %7$s SCHEMA_VERSION = %8$s;\n" + + " public static final String SEMANTIC_VERSION = \"%19$s\";\n" + " public static final java.nio.ByteOrder BYTE_ORDER = java.nio.ByteOrder.%14$s;\n\n" + " private final %9$s parentMessage = this;\n" + " private %11$s buffer;\n" + @@ -2815,7 +2820,8 @@ private CharSequence generateFlyweightCode( blockLengthAccessorType, templateIdAccessorType, schemaIdAccessorType, - schemaVersionAccessorType); + schemaVersionAccessorType, + semanticVersion); } private CharSequence generateEncoderFlyweightCode(final String className, final Token token) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index fe58ce4874..0514463237 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -157,10 +157,12 @@ public void generate() throws IOException final String templateIdType = rustTypeName(ir.headerStructure().templateIdType()); final String schemaIdType = rustTypeName(ir.headerStructure().schemaIdType()); final String schemaVersionType = schemaVersionType(); + final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); indent(out, 0, "pub const SBE_BLOCK_LENGTH: %s = %d;\n", blockLengthType, msgToken.encodedLength()); indent(out, 0, "pub const SBE_TEMPLATE_ID: %s = %d;\n", templateIdType, msgToken.id()); indent(out, 0, "pub const SBE_SCHEMA_ID: %s = %d;\n", schemaIdType, ir.id()); - indent(out, 0, "pub const SBE_SCHEMA_VERSION: %s = %d;\n\n", schemaVersionType, ir.version()); + indent(out, 0, "pub const SBE_SCHEMA_VERSION: %s = %d;\n", schemaVersionType, ir.version()); + indent(out, 0, "pub const SBE_SEMANTIC_VERSION: &str = \"%s\";\n\n", semanticVersion); MessageCoderDef.generateEncoder(ir, out, msgToken, fields, groups, varData); MessageCoderDef.generateDecoder(ir, out, msgToken, fields, groups, varData); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 12fc62b74b..2bdd4647fc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -15,6 +15,7 @@ public final class FrameCodecDecoder public static final int TEMPLATE_ID = 1; public static final int SCHEMA_ID = 1; public static final int SCHEMA_VERSION = 0; + public static final String SEMANTIC_VERSION = ""; public static final java.nio.ByteOrder BYTE_ORDER = java.nio.ByteOrder.LITTLE_ENDIAN; private final FrameCodecDecoder parentMessage = this; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index 4bcc266652..0fd115d556 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -15,6 +15,7 @@ public final class FrameCodecEncoder public static final int TEMPLATE_ID = 1; public static final int SCHEMA_ID = 1; public static final int SCHEMA_VERSION = 0; + public static final String SEMANTIC_VERSION = ""; public static final java.nio.ByteOrder BYTE_ORDER = java.nio.ByteOrder.LITTLE_ENDIAN; private final FrameCodecEncoder parentMessage = this; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java index b0f47e2bd5..380c8a649e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java @@ -12,6 +12,7 @@ public final class MessageHeaderDecoder { public static final int SCHEMA_ID = 1; public static final int SCHEMA_VERSION = 0; + public static final String SEMANTIC_VERSION = ""; public static final int ENCODED_LENGTH = 8; public static final java.nio.ByteOrder BYTE_ORDER = java.nio.ByteOrder.LITTLE_ENDIAN; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java index f295379b98..b1255198e5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java @@ -12,6 +12,7 @@ public final class MessageHeaderEncoder { public static final int SCHEMA_ID = 1; public static final int SCHEMA_VERSION = 0; + public static final String SEMANTIC_VERSION = ""; public static final int ENCODED_LENGTH = 8; public static final java.nio.ByteOrder BYTE_ORDER = java.nio.ByteOrder.LITTLE_ENDIAN; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 5f23d9ef9e..244fb30ec1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -15,6 +15,7 @@ public final class TokenCodecDecoder public static final int TEMPLATE_ID = 2; public static final int SCHEMA_ID = 1; public static final int SCHEMA_VERSION = 0; + public static final String SEMANTIC_VERSION = ""; public static final java.nio.ByteOrder BYTE_ORDER = java.nio.ByteOrder.LITTLE_ENDIAN; private final TokenCodecDecoder parentMessage = this; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index 1f429e09b5..793f10756f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -15,6 +15,7 @@ public final class TokenCodecEncoder public static final int TEMPLATE_ID = 2; public static final int SCHEMA_ID = 1; public static final int SCHEMA_VERSION = 0; + public static final String SEMANTIC_VERSION = ""; public static final java.nio.ByteOrder BYTE_ORDER = java.nio.ByteOrder.LITTLE_ENDIAN; private final TokenCodecEncoder parentMessage = this; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java index aad78db9fe..fef5471086 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java @@ -12,6 +12,7 @@ public final class VarDataEncodingDecoder { public static final int SCHEMA_ID = 1; public static final int SCHEMA_VERSION = 0; + public static final String SEMANTIC_VERSION = ""; public static final int ENCODED_LENGTH = -1; public static final java.nio.ByteOrder BYTE_ORDER = java.nio.ByteOrder.LITTLE_ENDIAN; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java index d86d2879a2..69ecabf325 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java @@ -12,6 +12,7 @@ public final class VarDataEncodingEncoder { public static final int SCHEMA_ID = 1; public static final int SCHEMA_VERSION = 0; + public static final String SEMANTIC_VERSION = ""; public static final int ENCODED_LENGTH = -1; public static final java.nio.ByteOrder BYTE_ORDER = java.nio.ByteOrder.LITTLE_ENDIAN; diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index 961db64b2d..68494c7993 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -432,6 +432,7 @@ TEST_F(CodeGenTest, shouldReturnCorrectValuesForCarStaticFields) EXPECT_EQ(CGT(car_sbe_schema_id)(), 6u); EXPECT_EQ(CGT(car_sbe_schema_version)(), 0u); EXPECT_EQ(std::string(CGT(car_sbe_semantic_type)()), std::string("")); + EXPECT_EQ(CGT(car_sbe_semantic_version)(), "5.2"); } TEST_F(CodeGenTest, shouldBeAbleToEncodeMessageHeaderCorrectly) diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index 5c7ad29b77..698d7ec849 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -331,6 +331,7 @@ TEST_F(CodeGenTest, shouldReturnCorrectValuesForCarStaticFields) EXPECT_EQ(Car::sbeSchemaId(), 6u); EXPECT_EQ(Car::sbeSchemaVersion(), 0u); EXPECT_EQ(std::string(Car::sbeSemanticType()), std::string("")); + EXPECT_EQ(std::string(Car::sbeSemanticVersion()), std::string("5.2")); } TEST_F(CodeGenTest, shouldBeAbleToEncodeMessageHeaderCorrectly) From 0f99a8219b1b79c779b734e4f02c3923d6691c1b Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 26 Mar 2023 18:50:22 +0200 Subject: [PATCH 1007/1594] [CI] Add Clang 16 to the build matrix. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed6e5ae9bf..7c3f07c143 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -218,7 +218,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '13', '14', '15' ] + version: [ '13', '14', '15', '16' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} From 3529fdb053624c29bba051c7f042ff683b8575db Mon Sep 17 00:00:00 2001 From: James Watson Date: Wed, 29 Mar 2023 12:09:15 +0100 Subject: [PATCH 1008/1594] [Java] Upgrade to Agrona 1.18.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b58ba21e0f..3527c6a0c2 100644 --- a/build.gradle +++ b/build.gradle @@ -47,8 +47,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.9.2' def jmhVersion = '1.36' -def agronaVersion = '1.17.1' -def agronaVersionRange = '[1.17.1,2.0[' // allow any release >= 1.17.1 and < 2.0.0 +def agronaVersion = '1.18.0' +def agronaVersionRange = '[1.18.0,2.0[' // allow any release >= 1.18.0 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 8f940f0407da54584e5322b17925df107f3991e8 Mon Sep 17 00:00:00 2001 From: James Watson Date: Wed, 29 Mar 2023 12:21:06 +0100 Subject: [PATCH 1009/1594] 1.27.1 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index f9aacd1c13..08002f86cc 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.27.1-SNAPSHOT +1.27.1 From 7995b239eec3db734339386ec0784f68a7a6529e Mon Sep 17 00:00:00 2001 From: James Watson Date: Wed, 29 Mar 2023 12:25:13 +0100 Subject: [PATCH 1010/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 08002f86cc..42c4c68219 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.27.1 +1.27.2-SNAPSHOT From ac613b0c5326556b33efe416dd94d6af8cab3695 Mon Sep 17 00:00:00 2001 From: James Watson Date: Wed, 29 Mar 2023 13:37:36 +0100 Subject: [PATCH 1011/1594] 1.28.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 42c4c68219..cfc730712d 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.27.2-SNAPSHOT +1.28.0 From 57011d1b0a3c65ed17dfd9227ccb8922fe2c2fef Mon Sep 17 00:00:00 2001 From: James Watson Date: Wed, 29 Mar 2023 13:39:32 +0100 Subject: [PATCH 1012/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index cfc730712d..f2ec2d3b39 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.28.0 +1.29.0-SNAPSHOT From 259655249cd36bccc555bf540d9abedb52aa56d9 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 29 Mar 2023 17:35:00 +0200 Subject: [PATCH 1013/1594] [Java] Fix SBE_SEMANTIC_VERSION field generation for C++. --- .../sbe/generation/cpp/CppGenerator.java | 14 +------------ .../sbe/generation/cpp/CppGeneratorTest.java | 20 +++++++++++++++++++ version.txt | 2 +- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index ddbc1aadcf..1aed7b0df4 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -169,7 +169,6 @@ public void generate() throws IOException generateDisplay(sb, msgToken.name(), fields, groups, varData); sb.append(generateMessageLength(groups, varData, BASE_INDENT)); sb.append("};\n"); - sb.append(generateStaticVariablesInitialization(className)); sb.append(CppUtil.closingBraces(ir.namespaces().length)).append("#endif\n"); out.append(sb); } @@ -1995,7 +1994,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final " static const %3$s SBE_TEMPLATE_ID = %4$s;\n" + " static const %5$s SBE_SCHEMA_ID = %6$s;\n" + " static const %7$s SBE_SCHEMA_VERSION = %8$s;\n" + - " static const char* SBE_SEMANTIC_VERSION;\n\n" + + " static constexpr const char* SBE_SEMANTIC_VERSION = \"%13$s\";\n\n" + " enum MetaAttribute\n" + " {\n" + @@ -3193,15 +3192,4 @@ private CharSequence generateMessageLength(final List groups, final List< return sb; } - - private CharSequence generateStaticVariablesInitialization(final String className) - { - final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); - - return String.format( - "\n" + - "const char* %1$s::SBE_SEMANTIC_VERSION = \"%2$s\";\n\n", - className, - semanticVersion); - } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index 73fa7664f2..63e2f6010b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -52,4 +52,24 @@ void shouldUseGeneratedLiteralForConstantOneWhenGeneratingBitsetCode() throws Ex assertThat(source, containsString("UINT64_C(0x1) << ")); } } + + @Test + void shouldUseConstexprWhenInitializingSemanticVersion() throws Exception + { + try (InputStream in = Tests.getLocalResource("code-generation-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + + final CppGenerator generator = new CppGenerator(ir, false, outputManager); + generator.generate(); + + final String source = outputManager.getSource("code.generation.test.Car").toString(); + assertThat(source, containsString("static constexpr const char* SBE_SEMANTIC_VERSION = \"5.2\"")); + } + } } diff --git a/version.txt b/version.txt index f2ec2d3b39..abf37a154b 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.29.0-SNAPSHOT +1.28.1-SNAPSHOT From b14ba4d6421734ece6e37d4bca2bb820c005cb02 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 29 Mar 2023 18:53:44 +0200 Subject: [PATCH 1014/1594] 1.28.1 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index abf37a154b..e787e4c523 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.28.1-SNAPSHOT +1.28.1 \ No newline at end of file From 2c7979e6912eea789e6f8910546bbed140d55673 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 29 Mar 2023 18:54:18 +0200 Subject: [PATCH 1015/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index e787e4c523..5daec50998 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.28.1 \ No newline at end of file +1.29.0-SNAPSHOT \ No newline at end of file From 9b2f42d9e42eba938050154f7f703532fa9c869a Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 17 Apr 2023 01:12:06 +0200 Subject: [PATCH 1016/1594] [Java] Upgrade to Agrona 1.18.1. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 3527c6a0c2..d0c1566e38 100644 --- a/build.gradle +++ b/build.gradle @@ -47,8 +47,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.9.2' def jmhVersion = '1.36' -def agronaVersion = '1.18.0' -def agronaVersionRange = '[1.18.0,2.0[' // allow any release >= 1.18.0 and < 2.0.0 +def agronaVersion = '1.18.1' +def agronaVersionRange = '[1.18.1,2.0[' // allow any release >= 1.18.1 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From f4c6618b0d3ea9c05c60e5922860ead3be375c1c Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 17 Apr 2023 09:02:41 +0200 Subject: [PATCH 1017/1594] 1.28.2 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 5daec50998..d0792325d8 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.29.0-SNAPSHOT \ No newline at end of file +1.28.2 \ No newline at end of file From 74e9df73e457a6abdd46479bbb5b93841b3d3c86 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 17 Apr 2023 09:03:16 +0200 Subject: [PATCH 1018/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index d0792325d8..5daec50998 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.28.2 \ No newline at end of file +1.29.0-SNAPSHOT \ No newline at end of file From 663934c5ef6f12f2430604c4300cee7e02db40c5 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 17 Apr 2023 12:35:11 +0200 Subject: [PATCH 1019/1594] Upgrade to Gradle 8.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 61608 -> 62076 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 7 ++++--- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index d0c1566e38..0008d80f84 100644 --- a/build.gradle +++ b/build.gradle @@ -830,7 +830,7 @@ tasks.named('dependencyUpdates').configure { } wrapper { - gradleVersion = '7.6' + gradleVersion = '8.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index ccebba7710deaf9f98673a68957ea02138b60d0a..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch delta 8979 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 F{TFmrHLU;u delta 8469 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 Date: Mon, 17 Apr 2023 12:35:35 +0200 Subject: [PATCH 1020/1594] Upgrade to Shadow 8.1.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0008d80f84..4b9be03a11 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ import java.security.MessageDigest plugins { id 'java-library' - id 'com.github.johnrengelman.shadow' version '7.1.2' apply false + id 'com.github.johnrengelman.shadow' version '8.1.1' apply false id 'com.github.ben-manes.versions' version '0.46.0' } From b52591a6dde57e27363ee62417a192554bd06445 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 17 Apr 2023 12:49:35 +0200 Subject: [PATCH 1021/1594] [CI] Add JDK 20 to the build matrix. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c3f07c143..1110358ff1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '11', '17' ] + java: [ '8', '11', '17', '20' ] os: [ 'ubuntu-22.04', 'windows-latest' ] steps: - name: Checkout code From 8d50a5e80530f2980f88cac8295c213586b52bc4 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 18 Apr 2023 15:14:25 +0200 Subject: [PATCH 1022/1594] [CI] Add JDK 21-ea to the build matrix. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1110358ff1..e89e54c175 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '11', '17', '20' ] + java: [ '8', '11', '17', '21-ea' ] os: [ 'ubuntu-22.04', 'windows-latest' ] steps: - name: Checkout code From 3cbb6f438c8803e14c0c70800109c44e8fb239a5 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 18 Apr 2023 15:32:33 +0200 Subject: [PATCH 1023/1594] [Gradle] Upgrade ASM dependency to the latest version to build on JDK 21. --- build.gradle | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/build.gradle b/build.gradle index 4b9be03a11..e2e7ebf89c 100644 --- a/build.gradle +++ b/build.gradle @@ -18,6 +18,17 @@ import java.nio.file.Files import java.nio.file.StandardOpenOption import java.security.MessageDigest +buildscript { + repositories { + gradlePluginPortal() + mavenCentral() + } + dependencies { + classpath 'org.ow2.asm:asm:9.5' + classpath 'org.ow2.asm:asm-commons:9.5' + } +} + plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '8.1.1' apply false From 2387ab4b258eb898400c249e7377dcea9c6f8e72 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 23 Apr 2023 10:09:37 +0200 Subject: [PATCH 1024/1594] Force CRLF for Windows files. --- .gitattributes | 64 ++------------------------------------------------ 1 file changed, 2 insertions(+), 62 deletions(-) diff --git a/.gitattributes b/.gitattributes index 1ff0c42304..94a7377068 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,63 +1,3 @@ -############################################################################### -# Set default behavior to automatically normalize line endings. -############################################################################### * text=auto - -############################################################################### -# Set default behavior for command prompt diff. -# -# This is need for earlier builds of msysgit that does not have it on by -# default for csharp files. -# Note: This is only used by command line -############################################################################### -#*.cs diff=csharp - -############################################################################### -# Set the merge driver for project and solution files -# -# Merging from the command prompt will add diff markers to the files if there -# are conflicts (Merging from VS is not affected by the settings below, in VS -# the diff markers are never inserted). Diff markers may cause the following -# file extensions to fail to load in VS. An alternative would be to treat -# these files as binary and thus will always conflict and require user -# intervention with every merge. To do so, just uncomment the entries below -############################################################################### -#*.sln merge=binary -#*.csproj merge=binary -#*.vbproj merge=binary -#*.vcxproj merge=binary -#*.vcproj merge=binary -#*.dbproj merge=binary -#*.fsproj merge=binary -#*.lsproj merge=binary -#*.wixproj merge=binary -#*.modelproj merge=binary -#*.sqlproj merge=binary -#*.wwaproj merge=binary - -############################################################################### -# behavior for image files -# -# image files are treated as binary by default. -############################################################################### -#*.jpg binary -#*.png binary -#*.gif binary - -############################################################################### -# diff behavior for common document formats -# -# Convert binary document formats to text before diffing them. This feature -# is only available from the command line. Turn it on by uncommenting the -# entries below. -############################################################################### -#*.doc diff=astextplain -#*.DOC diff=astextplain -#*.docx diff=astextplain -#*.DOCX diff=astextplain -#*.dot diff=astextplain -#*.DOT diff=astextplain -#*.pdf diff=astextplain -#*.PDF diff=astextplain -#*.rtf diff=astextplain -#*.RTF diff=astextplain +*.bat text eol=crlf +*.cmd text eol=crlf From c803dd105dc051c30002943aae3b02a31cb738c3 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 23 Apr 2023 10:09:46 +0200 Subject: [PATCH 1025/1594] [Java] Upgrade to Gradle 8.1.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index e2e7ebf89c..bcf3f5d988 100644 --- a/build.gradle +++ b/build.gradle @@ -841,7 +841,7 @@ tasks.named('dependencyUpdates').configure { } wrapper { - gradleVersion = '8.1' + gradleVersion = '8.1.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a21c6ebe28..8707e8b506 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-all.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 224fc95dd2096274dde8d5582a097283383213b3 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 28 Apr 2023 15:52:25 +0100 Subject: [PATCH 1026/1594] [Java] Upgrade to JUnit 5.9.3. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bcf3f5d988..3188587a49 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' -def junitVersion = '5.9.2' +def junitVersion = '5.9.3' def jmhVersion = '1.36' def agronaVersion = '1.18.1' def agronaVersionRange = '[1.18.1,2.0[' // allow any release >= 1.18.1 and < 2.0.0 From 461204a39c4d958490afc0ec09e9db41133e78f0 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 1 May 2023 15:24:32 +0200 Subject: [PATCH 1027/1594] [Java] Add `@SuppressWarnings("this-escape")` to fix the JDK 21-ea build. --- .../src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index f205802aae..ac175bb37b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -69,6 +69,7 @@ public EncodedDataType(final Node node) * @param givenName for this node. * @param referencedName of the type when created from a ref in a composite. */ + @SuppressWarnings("this-escape") public EncodedDataType(final Node node, final String givenName, final String referencedName) { super(node, givenName, referencedName); From b8a0247d2025983c031cc460600b1f7070442068 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 17 May 2023 09:40:15 +0200 Subject: [PATCH 1028/1594] [Rust] Add derive Copy Clone traits for decoders --- .../uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 2 +- .../sbe/generation/rust/MessageCoderDef.java | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 419f155e48..90078b796e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -149,7 +149,7 @@ static void generateEitherEnum(final Writer writer) throws IOException static void generateReadBuf(final Appendable writer, final ByteOrder byteOrder) throws IOException { - indent(writer, 0, "#[derive(Debug, Default)]\n"); + indent(writer, 0, "#[derive(Clone, Copy, Debug, Default)]\n"); indent(writer, 0, "pub struct %s<%s> {\n", READ_BUF_TYPE, BUF_LIFETIME); RustUtil.indent(writer, 1, "data: &%s [u8],\n", BUF_LIFETIME); indent(writer, 0, "}\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index d61f888f01..56b5e10cf2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -155,7 +155,15 @@ void appendMessageHeaderDecoderFn(final Appendable out) throws IOException void appendMessageStruct(final Appendable out, final String structName) throws IOException { - indent(out, 1, "#[derive(Debug, Default)]\n"); + if (this.codecType == Decoder) + { + indent(out, 1, "#[derive(Clone, Copy, Debug, Default)]\n"); + } + else + { + indent(out, 1, "#[derive(Debug, Default)]\n"); + } + indent(out, 1, "pub struct %s {\n", withLifetime(structName)); indent(out, 2, "buf: %s,\n", withLifetime(this.codecType.bufType())); indent(out, 2, "initial_offset: usize,\n"); From 0d4c36a475bebe657d30dba7f2606e63f32d0e0e Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 17 May 2023 10:13:43 +0200 Subject: [PATCH 1029/1594] [Rust] Fix clippy lint --- .../java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 419f155e48..2f92a0f611 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -131,7 +131,7 @@ static void generateSbeErrorEnum(final Writer writer) throws IOException indent(writer, 0, "impl core::fmt::Display for SbeErr {\n"); indent(writer, 1, "#[inline]\n"); indent(writer, 1, "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n"); - indent(writer, 2, "write!(f, \"{:?}\", self)\n"); + indent(writer, 2, "write!(f, \"{self:?}\")\n"); indent(writer, 1, "}\n"); indent(writer, 0, "}\n"); From d2ec8f8a225808a1392872473f6e5e85b828056e Mon Sep 17 00:00:00 2001 From: Philippe Serreault Date: Fri, 19 May 2023 15:44:42 +0200 Subject: [PATCH 1030/1594] CppGenerator: operator<< take messages as const-ref (#939) Following commit 1973c86f84b190d5b2507786e6445970c390ea62, using generated operator<< would require a mutable ref message. This is unnecessary and can be problematic. Ex: using wrappers such as fmt::streamed ( https://fmt.dev/latest/api.html#std-ostream-support ) --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 1aed7b0df4..482335b269 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2564,7 +2564,7 @@ private void generateDisplay( new Formatter(sb).format("\n" + "template\n" + "friend std::basic_ostream & operator << (\n" + - " std::basic_ostream &builder, %1$s &_writer)\n" + + " std::basic_ostream &builder, const %1$s &_writer)\n" + "{\n" + " %1$s writer(\n" + " _writer.m_buffer,\n" + From 76696c21b24a89a7db99cb69c5c20a847055eb9e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 8 Jun 2023 17:27:21 +0200 Subject: [PATCH 1031/1594] [Java] Upgrade to Agrona 1.18.2. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 3188587a49..792ef3856e 100644 --- a/build.gradle +++ b/build.gradle @@ -58,8 +58,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.9.3' def jmhVersion = '1.36' -def agronaVersion = '1.18.1' -def agronaVersionRange = '[1.18.1,2.0[' // allow any release >= 1.18.1 and < 2.0.0 +def agronaVersion = '1.18.2' +def agronaVersionRange = '[1.18.2,2.0[' // allow any release >= 1.18.2 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From bd602f949af8e9e4640c9c6a08d8aad0264051b8 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 8 Jun 2023 17:28:02 +0200 Subject: [PATCH 1032/1594] 1.28.3 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 5daec50998..ab461d1584 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.29.0-SNAPSHOT \ No newline at end of file +1.28.3 \ No newline at end of file From 7d7b2773d9308c58a08319f26943832da62aca22 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 8 Jun 2023 17:30:47 +0200 Subject: [PATCH 1033/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index ab461d1584..5daec50998 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.28.3 \ No newline at end of file +1.29.0-SNAPSHOT \ No newline at end of file From 2f51c36b72fa5999aced0e10b7658ad544c8ac1f Mon Sep 17 00:00:00 2001 From: Eric Stokes Date: Thu, 15 Jun 2023 18:39:28 -0400 Subject: [PATCH 1034/1594] fix array syntax error --- .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 0514463237..bff76d43a0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -641,7 +641,7 @@ private static void generatePrimitiveArrayDecoder( if (fieldToken.version() > 0) { indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); - indent(sb, level + 2, "return [%s, %d];\n", encoding.applicableNullValue(), arrayLength); + indent(sb, level + 2, "return [%s; %d];\n", encoding.applicableNullValue(), arrayLength); indent(sb, level + 1, "}\n\n"); } From 83e4a3a090d5046d5705eb86fd9fcf4bf82dad1e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 18 Jul 2023 21:58:33 +0200 Subject: [PATCH 1035/1594] [Java] Upgrade to versions 0.47.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 792ef3856e..bd4f38eeab 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ buildscript { plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '8.1.1' apply false - id 'com.github.ben-manes.versions' version '0.46.0' + id 'com.github.ben-manes.versions' version '0.47.0' } defaultTasks 'clean', 'build' From b0bfc35c168bfba3903f2e6de5ccf037bdc966d2 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 18 Jul 2023 21:59:19 +0200 Subject: [PATCH 1036/1594] [Java] Upgrade to Agrona 1.19.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index bd4f38eeab..8dba679bfd 100644 --- a/build.gradle +++ b/build.gradle @@ -58,8 +58,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.9.3' def jmhVersion = '1.36' -def agronaVersion = '1.18.2' -def agronaVersionRange = '[1.18.2,2.0[' // allow any release >= 1.18.2 and < 2.0.0 +def agronaVersion = '1.19.0' +def agronaVersionRange = '[1.19.0,2.0[' // allow any release >= 1.19.0 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 4454c853492051e30c09229bcd4f57c49c9c2906 Mon Sep 17 00:00:00 2001 From: ywhrh <115807920+ywhrh@users.noreply.github.com> Date: Wed, 19 Jul 2023 05:18:30 -0400 Subject: [PATCH 1037/1594] JsonPrinter remove trailing garbage after non-printable char (#950) --- .../sbe/json/JsonTokenListener.java | 23 +++++++++---- .../real_logic/sbe/json/JsonPrinterTest.java | 32 +++++++++++++++++++ 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index 92a38128b7..f889af19a8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -336,12 +336,7 @@ private void appendEncodingAsString( if (size > 1 && encoding.primitiveType() == CHAR) { doubleQuote(); - - for (int i = 0; i < size; i++) - { - escape((char)buffer.getByte(index + (i * elementSize))); - } - + escapePrintableChar(buffer, index, size, elementSize); doubleQuote(); } else @@ -369,6 +364,22 @@ private void appendEncodingAsString( } } + private void escapePrintableChar(final DirectBuffer buffer, final int index, final int size, final int elementSize) + { + for (int i = 0; i < size; i++) + { + final byte c = buffer.getByte(index + (i * elementSize)); + if (c > 0) + { + escape((char)c); + } + else + { + break; + } + } + } + private void backup() { final int newLength = output.length() - 2; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java index dc4bd822f0..40c59916e7 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java @@ -15,6 +15,7 @@ */ package uk.co.real_logic.sbe.json; +import baseline.CarEncoder; import baseline.CredentialsEncoder; import baseline.MessageHeaderEncoder; import org.agrona.concurrent.UnsafeBuffer; @@ -155,6 +156,37 @@ public void exampleVarData() throws Exception result); } + @Test + public void removeTrailingGarbage() throws Exception + { + final ByteBuffer encodedSchemaBuffer = ByteBuffer.allocate(SCHEMA_BUFFER_CAPACITY); + encodeSchema(encodedSchemaBuffer); + + final ByteBuffer encodedMsgBuffer = ByteBuffer.allocate(MSG_BUFFER_CAPACITY); + final UnsafeBuffer buffer = new UnsafeBuffer(encodedMsgBuffer); + final CarEncoder encoder = new CarEncoder(); + encoder.wrapAndApplyHeader(buffer, 0, new MessageHeaderEncoder()); + encoder.vehicleCode("vc\0ノ�"); + encodedMsgBuffer.position(encoder.encodedLength()); + encodedSchemaBuffer.flip(); + final Ir ir = decodeIr(encodedSchemaBuffer); + + final JsonPrinter printer = new JsonPrinter(ir); + final String result = printer.print(encodedMsgBuffer); + assertEquals("{\n" + " \"serialNumber\": 0,\n" + + " \"modelYear\": 0,\n" + + " \"available\": \"F\",\n" + " \"code\": \"null\",\n" + " \"someNumbers\": [0, 0, 0, 0, 0],\n" + + " \"vehicleCode\": \"vc\",\n" + //trailing garbage removed + " \"extras\": { \"sunRoof\": false, \"sportsPack\": false, \"cruiseControl\": false },\n" + + " \"engine\": \n" + " {\n" + " \"capacity\": 0,\n" + " \"numCylinders\": 0,\n" + + " \"maxRpm\": 9000,\n" + " \"manufacturerCode\": \"\",\n" + + " \"fuel\": \"Petrol\"\n" + " },\n" + " \"uuid\": [0, 0],\n" + " \"cupHolderCount\": 0,\n" + + " \"fuelFigures\": [],\n" + " \"performanceFigures\": [],\n" + " \"manufacturer\": \"\",\n" + + " \"model\": \"\",\n" + " \"activationCode\": \"\"\n" + "}", + result); + } + + private static void encodeSchema(final ByteBuffer buffer) throws Exception { final Path path = Paths.get("src/test/resources/json-printer-test-schema.xml"); From 09499a01556d68ee740e6c44677d80b09d9c7d7a Mon Sep 17 00:00:00 2001 From: jordy25519 Date: Thu, 20 Jul 2023 04:45:38 +1200 Subject: [PATCH 1038/1594] improve rust performance (#944) * rust specialize get_u8_at & put_u8_at improve performance use copy_from_slice instead of split_at when r/w u8 array * remove pointless comment * get_bytes_at crate scoped * fix java style lints --- .../sbe/generation/rust/LibRsDef.java | 23 ++++++++++++++----- .../sbe/generation/rust/RustGenerator.java | 15 ++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 349bc79c97..3d38b28aa2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -175,14 +175,21 @@ static void generateReadBuf(final Appendable writer, final ByteOrder byteOrder) indent(writer, 1, "}\n\n"); indent(writer, 1, "#[inline]\n"); - indent(writer, 1, "fn get_bytes_at(slice: &[u8], index: usize) -> [u8; COUNT] {\n"); - indent(writer, 2, "Self::get_bytes(slice.split_at(index).1.split_at(COUNT).0)\n"); + indent(writer, 1, "pub(crate) fn get_bytes_at(slice: &[u8], index: usize) -> [u8; N] {\n"); + indent(writer, 2, "slice[index..index+N].try_into().expect(\"slice with incorrect length\")\n"); indent(writer, 1, "}\n"); final LinkedHashSet uniquePrimitiveTypes = new LinkedHashSet<>(TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.values()); final String endianness = byteOrder == LITTLE_ENDIAN ? "le" : "be"; + uniquePrimitiveTypes.remove("u8"); + indent(writer, 0, "\n"); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "pub fn get_u8_at(&self, index: usize) -> u8 {\n"); + indent(writer, 2, "self.data[index]\n"); + indent(writer, 1, "}\n"); + for (final String primitiveType : uniquePrimitiveTypes) { // get__at @@ -197,7 +204,7 @@ static void generateReadBuf(final Appendable writer, final ByteOrder byteOrder) indent(writer, 0, "\n"); indent(writer, 1, "#[inline]\n"); indent(writer, 1, "pub fn get_slice_at(&self, index: usize, len: usize) -> &[u8] {\n"); - indent(writer, 2, "self.data.split_at(index).1.split_at(len).0\n"); + indent(writer, 2, "&self.data[index..index+len]\n"); indent(writer, 1, "}\n\n"); writer.append("}\n"); @@ -219,9 +226,7 @@ static void generateWriteBuf(final Writer writer, final ByteOrder byteOrder) thr indent(writer, 1, "#[inline]\n"); indent(writer, 1, "pub fn put_bytes_at(&mut self, index: usize, bytes: [u8; COUNT]) -> usize {\n"); - indent(writer, 2, "for (i, byte) in bytes.iter().enumerate() {\n"); - indent(writer, 3, "self.data[index + i] = *byte;\n"); - indent(writer, 2, "}\n"); + indent(writer, 2, "self.data[index..index + COUNT].copy_from_slice(&bytes);\n"); indent(writer, 2, "COUNT\n"); indent(writer, 1, "}\n\n"); @@ -229,6 +234,12 @@ static void generateWriteBuf(final Writer writer, final ByteOrder byteOrder) thr = new LinkedHashSet<>(TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.values()); final String endianness = byteOrder == LITTLE_ENDIAN ? "le" : "be"; + uniquePrimitiveTypes.remove("u8"); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "pub fn put_u8_at(&mut self, index: usize, value: u8) {\n"); + indent(writer, 2, "self.data[index] = value;\n"); + indent(writer, 1, "}\n\n"); + for (final String primitiveType : uniquePrimitiveTypes) { // put__at diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index bff76d43a0..25e200a268 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -376,6 +376,13 @@ private static void generatePrimitiveEncoder( indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); indent(sb, level + 1, "let buf = self.get_buf_mut();\n"); + if (rustPrimitiveType.equals("u8")) + { + indent(sb, level + 1, "buf.put_bytes_at(offset, value);\n"); + indent(sb, level, "}\n\n"); + return; + } + for (int i = 0; i < arrayLength; i++) { if (i == 0) @@ -646,6 +653,14 @@ private static void generatePrimitiveArrayDecoder( } indent(sb, level + 1, "let buf = self.get_buf();\n"); + if (rustPrimitiveType.equals("u8")) + { + indent(sb, level + 1, "ReadBuf::get_bytes_at(buf.data, self.%s)\n", + getBufOffset(typeToken)); + indent(sb, level, "}\n\n"); + return; + } + indent(sb, level + 1, "[\n"); for (int i = 0; i < arrayLength; i++) { From 85f46058399a5b5f08a88ed632944af0894d9a47 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 21 Jul 2023 16:39:42 +0200 Subject: [PATCH 1039/1594] 1.29.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 5daec50998..72f3c1dacc 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.29.0-SNAPSHOT \ No newline at end of file +1.29.0 \ No newline at end of file From 8680408574722b1934cb32b0bdf36dc1efbb5c5a Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 21 Jul 2023 17:14:22 +0200 Subject: [PATCH 1040/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 72f3c1dacc..f407f84d1d 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.29.0 \ No newline at end of file +1.30.0-SNAPSHOT \ No newline at end of file From abd25b49ed42eae44f90832f8611f2aa97a7246a Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 1 Aug 2023 17:38:39 +0200 Subject: [PATCH 1041/1594] [Java] Upgrade to JUnit 5.10.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8dba679bfd..c19f043865 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' -def junitVersion = '5.9.3' +def junitVersion = '5.10.0' def jmhVersion = '1.36' def agronaVersion = '1.19.0' def agronaVersionRange = '[1.19.0,2.0[' // allow any release >= 1.19.0 and < 2.0.0 From 7503aed720de09c894394aed06f3c2c32f497c10 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 3 Aug 2023 18:35:52 +0200 Subject: [PATCH 1042/1594] [Java] Upgrade to Gradle 8.2.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 63375 bytes gradle/wrapper/gradle-wrapper.properties | 3 ++- gradlew | 5 ++++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index c19f043865..c712f1a35b 100644 --- a/build.gradle +++ b/build.gradle @@ -841,7 +841,7 @@ tasks.named('dependencyUpdates').configure { } wrapper { - gradleVersion = '8.1.1' + gradleVersion = '8.2.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..033e24c4cdf41af1ab109bc7f253b2b887023340 100644 GIT binary patch delta 16170 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 delta 14892 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8707e8b506..c747538fb3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-all.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index aeb74cbb43..fcb6fca147 100755 --- a/gradlew +++ b/gradlew @@ -130,10 +130,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. From 18c0862d97abe4426a96245993bde078670df985 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 3 Aug 2023 18:50:38 +0200 Subject: [PATCH 1043/1594] [Java] Fix Gradle 8.2.1 Junit warning. --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index c712f1a35b..c4e255f11c 100644 --- a/build.gradle +++ b/build.gradle @@ -250,6 +250,7 @@ project(':sbe-tool') { testImplementation "org.mockito:mockito-core:${mockitoVersion}" testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" + testRuntimeOnly("org.junit.platform:junit-platform-launcher") } def generatedDir = 'build/generated-src' From 9f0c43abe91150cd90ab8bea024a19e1bf465d47 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 3 Aug 2023 21:12:23 +0200 Subject: [PATCH 1044/1594] Revert "[Java] Fix Gradle 8.2.1 Junit warning." This reverts commit 18c0862d97abe4426a96245993bde078670df985. --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index c4e255f11c..c712f1a35b 100644 --- a/build.gradle +++ b/build.gradle @@ -250,7 +250,6 @@ project(':sbe-tool') { testImplementation "org.mockito:mockito-core:${mockitoVersion}" testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" - testRuntimeOnly("org.junit.platform:junit-platform-launcher") } def generatedDir = 'build/generated-src' From 384e0219322ed6bc44184705d5a9f759efd1038d Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 3 Aug 2023 21:12:23 +0200 Subject: [PATCH 1045/1594] Revert "[Java] Upgrade to Gradle 8.2.1." This reverts commit 7503aed720de09c894394aed06f3c2c32f497c10. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 63375 -> 62076 bytes gradle/wrapper/gradle-wrapper.properties | 3 +-- gradlew | 5 +---- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index c712f1a35b..c19f043865 100644 --- a/build.gradle +++ b/build.gradle @@ -841,7 +841,7 @@ tasks.named('dependencyUpdates').configure { } wrapper { - gradleVersion = '8.2.1' + gradleVersion = '8.1.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 033e24c4cdf41af1ab109bc7f253b2b887023340..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch delta 14892 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 delta 16170 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c747538fb3..8707e8b506 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-all.zip networkTimeout=10000 -validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index fcb6fca147..aeb74cbb43 100755 --- a/gradlew +++ b/gradlew @@ -130,13 +130,10 @@ location of your Java installation." fi else JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." - fi fi # Increase the maximum file descriptors if we can. From 46071f77d633019e12f2aaf286a9e982f63a7170 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 9 Aug 2023 11:38:53 +0100 Subject: [PATCH 1046/1594] [Java] Upgrade to JMH 1.27. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c19f043865..3fa15b8065 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.10.0' -def jmhVersion = '1.36' +def jmhVersion = '1.37' def agronaVersion = '1.19.0' def agronaVersionRange = '[1.19.0,2.0[' // allow any release >= 1.19.0 and < 2.0.0 From 8f480b9a239a1ac4b9122055852322cdc69df29c Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 9 Aug 2023 18:00:39 +0200 Subject: [PATCH 1047/1594] [Java] Upgrade to Agrona 1.19.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3fa15b8065..6865c71331 100644 --- a/build.gradle +++ b/build.gradle @@ -58,7 +58,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.10.0' def jmhVersion = '1.37' -def agronaVersion = '1.19.0' +def agronaVersion = '1.19.1' def agronaVersionRange = '[1.19.0,2.0[' // allow any release >= 1.19.0 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' From 0aeb59ee5c80f3b64268f62a747df08341ac9112 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 1 Sep 2023 17:00:41 +0200 Subject: [PATCH 1048/1594] [Java] Upgrade to Agrona 1.19.2. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 6865c71331..c9a218bb34 100644 --- a/build.gradle +++ b/build.gradle @@ -58,8 +58,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.10.0' def jmhVersion = '1.37' -def agronaVersion = '1.19.1' -def agronaVersionRange = '[1.19.0,2.0[' // allow any release >= 1.19.0 and < 2.0.0 +def agronaVersion = '1.19.2' +def agronaVersionRange = '[1.19.2,2.0[' // allow any release >= 1.19.2 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 432ccfc3bf7f24c05f6a46adcd096e69c082b93c Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 7 Sep 2023 15:23:06 +0200 Subject: [PATCH 1049/1594] Upgrade to Versions plugin 0.48.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c9a218bb34..b0015d32af 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ buildscript { plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '8.1.1' apply false - id 'com.github.ben-manes.versions' version '0.47.0' + id 'com.github.ben-manes.versions' version '0.48.0' } defaultTasks 'clean', 'build' From 3f6b6297446a4a4d65d1460bd0d66c0d69500a3f Mon Sep 17 00:00:00 2001 From: ratcash Date: Thu, 14 Sep 2023 15:42:03 +0200 Subject: [PATCH 1050/1594] [Java] Expose actingVersion (#953) * [Java] Expose actingVersion * ir codec update --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 5 +++++ .../uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java | 5 +++++ .../uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index d44bf668b8..e40a02c6a1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2716,6 +2716,11 @@ private CharSequence generateDecoderFlyweightCode(final String className, final " final int decodedLength = encodedLength();\n" + " limit(currentLimit);\n\n" + " return decodedLength;\n" + + " }\n\n" + + + " public int actingVersion()\n" + + " {\n" + + " return actingVersion;\n" + " }\n\n"; return generateFlyweightCode(DECODER, className, token, methods, readOnlyBuffer); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 2bdd4647fc..8cbdc11954 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -120,6 +120,11 @@ public int sbeDecodedLength() return decodedLength; } + public int actingVersion() + { + return actingVersion; + } + public int encodedLength() { return limit - offset; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 244fb30ec1..8c7a7a1ee6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -120,6 +120,11 @@ public int sbeDecodedLength() return decodedLength; } + public int actingVersion() + { + return actingVersion; + } + public int encodedLength() { return limit - offset; From 0dcf92266164ecc1e8428a07feda8f4351d576f6 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:46:13 +0200 Subject: [PATCH 1051/1594] [CI] Use JDK 21 GA and drop JDK 11. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e89e54c175..d6a6ef95ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '11', '17', '21-ea' ] + java: [ '8', '17', '21' ] os: [ 'ubuntu-22.04', 'windows-latest' ] steps: - name: Checkout code From 510d3e8929ef72cb71b5258afdada16f6f08d486 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 20 Sep 2023 13:03:01 +0200 Subject: [PATCH 1052/1594] [Java] Fix javadoc link for JDK 21 GA. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b0015d32af..2761b537e4 100644 --- a/build.gradle +++ b/build.gradle @@ -202,7 +202,7 @@ subprojects { options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' options.links("https://www.javadoc.io/doc/org.agrona/agrona/${agronaVersion}/") - if (buildJavaVersion >= 19) { // early access JavaDoc location is different + if (buildJavaVersion > 21) { // early access JavaDoc location is different options.links("https://download.java.net/java/early_access/jdk${buildJavaVersion}/docs/api/") } else if (buildJavaVersion >= 11) { From 0a05d9a0e39f5ff5ac43c6a9eb57f1dcac0b81c3 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 29 Sep 2023 13:41:58 +0100 Subject: [PATCH 1053/1594] [C++] Rely on NAN from limits rather than pulling in cmath. Issue #956. --- .../sbe/generation/cpp/CppGenerator.java | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 482335b269..debb990d27 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1051,18 +1051,6 @@ private static CharSequence generateFileHeader( "#ifndef _%1$s_%2$s_CXX_H_\n" + "#define _%1$s_%2$s_CXX_H_\n\n" + - "#if defined(SBE_HAVE_CMATH)\n" + - "/* cmath needed for std::numeric_limits::quiet_NaN() */\n" + - "# include \n" + - "# define SBE_FLOAT_NAN std::numeric_limits::quiet_NaN()\n" + - "# define SBE_DOUBLE_NAN std::numeric_limits::quiet_NaN()\n" + - "#else\n" + - "/* math.h needed for NAN */\n" + - "# include \n" + - "# define SBE_FLOAT_NAN NAN\n" + - "# define SBE_DOUBLE_NAN NAN\n" + - "#endif\n\n" + - "#if __cplusplus >= 201103L\n" + "# define SBE_CONSTEXPR constexpr\n" + "# define SBE_NOEXCEPT noexcept\n" + @@ -1083,9 +1071,9 @@ private static CharSequence generateFileHeader( "#endif\n\n" + "#include \n" + + "#include \n" + "#include \n" + "#include \n" + - "#include \n" + "#include \n" + "#include \n" + "#include \n" + @@ -1130,6 +1118,8 @@ private static CharSequence generateFileHeader( "# endif\n\n" + "#endif\n\n" + + "#define SBE_FLOAT_NAN std::numeric_limits::quiet_NaN()\n" + + "#define SBE_DOUBLE_NAN std::numeric_limits::quiet_NaN()\n" + "#define SBE_NULLVALUE_INT8 (std::numeric_limits::min)()\n" + "#define SBE_NULLVALUE_INT16 (std::numeric_limits::min)()\n" + "#define SBE_NULLVALUE_INT32 (std::numeric_limits::min)()\n" + @@ -1141,7 +1131,7 @@ private static CharSequence generateFileHeader( String.join("_", namespaces).toUpperCase(), className.toUpperCase())); - if (typesToInclude != null && typesToInclude.size() != 0) + if (typesToInclude != null && !typesToInclude.isEmpty()) { sb.append("\n"); for (final String incName : typesToInclude) From 1aef658c474e72f78f6a56e48e98fe978ff33fc9 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 29 Sep 2023 13:53:40 +0100 Subject: [PATCH 1054/1594] [C++] Replace trivial String.format. --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index debb990d27..6448ce3e05 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1136,7 +1136,7 @@ private static CharSequence generateFileHeader( sb.append("\n"); for (final String incName : typesToInclude) { - sb.append(String.format("#include \"%1$s.h\"\n", toUpperFirstChar(incName))); + sb.append("#include \"").append(toUpperFirstChar(incName)).append(".h\"\n"); } } From 1467df86d8d81ee3ffb5683b952b1eb3c2bf03a2 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 1 Oct 2023 22:27:28 +0200 Subject: [PATCH 1055/1594] [Java] Upgrade to ASM 9.6. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 2761b537e4..a40ad4d16f 100644 --- a/build.gradle +++ b/build.gradle @@ -24,8 +24,8 @@ buildscript { mavenCentral() } dependencies { - classpath 'org.ow2.asm:asm:9.5' - classpath 'org.ow2.asm:asm-commons:9.5' + classpath 'org.ow2.asm:asm:9.6' + classpath 'org.ow2.asm:asm-commons:9.6' } } From 186b9aac0699c4b7bfd24deeb5945e7aaea671aa Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 9 Oct 2023 11:56:18 +0300 Subject: [PATCH 1056/1594] [Java] Upgrade to Versions 0.49.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a40ad4d16f..04b981c43f 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ buildscript { plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '8.1.1' apply false - id 'com.github.ben-manes.versions' version '0.48.0' + id 'com.github.ben-manes.versions' version '0.49.0' } defaultTasks 'clean', 'build' From 060031c86165fe291f8bee3b0daf56efe5a539bd Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 1 Nov 2023 16:36:42 +0000 Subject: [PATCH 1057/1594] [C++] Fix comment typo. --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 6448ce3e05..f52d4695eb 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -53,7 +53,7 @@ public class CppGenerator implements CodeGenerator private final boolean shouldDecodeUnknownEnumValues; /** - * Create a new Go language {@link CodeGenerator}. + * Create a new Cpp language {@link CodeGenerator}. * * @param ir for the messages and types. * @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding. From c0dae9ef7126da4a8fd756f2065283eb9a837dfa Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Wed, 1 Nov 2023 11:39:45 -0500 Subject: [PATCH 1058/1594] [Rust] update how "use declarations" are generated, now deriving Defaults for enums (#952) * Fixed several issues: #1: LibRsDef explicitly us crate:: to disambiguate from built in mods like bool #2: Added acting_version field to Composite structs to fix compilation errors when using Composite structs. This is an incomplete implementation because the parent doesn't pass the acting_version to the composite because you need to change the signature of wrap(parent, offset) to include the acting_version, so this version just ensures that if the acting_version isn't set on the composite, it disregards the version check. #3: fixed primitiveArrayDecoder to return an empty array of the right size if less than version required. * [Rust] removed 'acting_version' field from SubGroup decoder * [Rust] updated RustGenerator::generateEnum() to support derive "Default" instead of generating impl * fixed formatting issue * [Rust] updated how 'use declarations' are generated to prevent "ambiguous glob re-exports" warnings from rust compiler --------- Co-authored-by: Adam Krieg Co-authored-by: Michael Ward --- rust/Cargo.toml | 2 +- rust/benches/car_benchmark.rs | 1 + rust/benches/md_benchmark.rs | 1 + rust/tests/baseline_test.rs | 1 + rust/tests/big_endian_test.rs | 1 + rust/tests/extension_test.rs | 1 + rust/tests/issue_895_test.rs | 14 ++-- .../sbe/generation/rust/LibRsDef.java | 2 +- .../sbe/generation/rust/RustGenerator.java | 74 +++++++++++-------- .../sbe/generation/rust/RustUtil.java | 4 +- .../sbe/generation/rust/SubGroup.java | 3 - .../sbe/generation/rust/RustUtilTest.java | 2 + 12 files changed, 64 insertions(+), 42 deletions(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 8b7c1e774d..020747c06d 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -17,7 +17,7 @@ baseline_bigendian = { path = "../generated/rust/baseline-bigendian" } nested_composite_name = { path = "../generated/rust/nested-composite-name" } [dev-dependencies] -criterion = "0.3" +criterion = "0.5" [[bench]] name = "car_benchmark" diff --git a/rust/benches/car_benchmark.rs b/rust/benches/car_benchmark.rs index 7ca9c2e5c8..92b964147a 100644 --- a/rust/benches/car_benchmark.rs +++ b/rust/benches/car_benchmark.rs @@ -1,5 +1,6 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; use examples_uk_co_real_logic_sbe_benchmarks::*; +use car_codec::encoder::*; const MANUFACTURER: &[u8] = b"MANUFACTURER"; const MODEL: &[u8] = b"MODEL"; diff --git a/rust/benches/md_benchmark.rs b/rust/benches/md_benchmark.rs index b429622f92..ab7f4bf367 100644 --- a/rust/benches/md_benchmark.rs +++ b/rust/benches/md_benchmark.rs @@ -1,5 +1,6 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; use examples_uk_co_real_logic_sbe_benchmarks_fix::*; +use market_data_incremental_refresh_trades_codec::encoder::*; struct State { buffer: Vec, diff --git a/rust/tests/baseline_test.rs b/rust/tests/baseline_test.rs index ca45f14b43..c223c83989 100644 --- a/rust/tests/baseline_test.rs +++ b/rust/tests/baseline_test.rs @@ -2,6 +2,7 @@ use std::fs::File; use std::io::prelude::*; use examples_baseline::*; +use car_codec::encoder::*; fn read_sbe_file_generated_from_java_example() -> std::io::Result> { // Generated by the generateCarExampleDataFile gradle task. diff --git a/rust/tests/big_endian_test.rs b/rust/tests/big_endian_test.rs index d3a6952dec..a1e107bc8d 100644 --- a/rust/tests/big_endian_test.rs +++ b/rust/tests/big_endian_test.rs @@ -1,4 +1,5 @@ use baseline_bigendian::*; +use car_codec::encoder::*; #[test] fn big_endian_baseline_example() -> SbeResult<()> { diff --git a/rust/tests/extension_test.rs b/rust/tests/extension_test.rs index c189763c6f..ad813c056f 100644 --- a/rust/tests/extension_test.rs +++ b/rust/tests/extension_test.rs @@ -2,6 +2,7 @@ use std::fs::File; use std::io::prelude::*; use examples_extension::*; +use car_codec::encoder::*; fn read_sbe_file_generated_from_java_example() -> std::io::Result> { // Generated by the generateCarExampleDataFile gradle task. diff --git a/rust/tests/issue_895_test.rs b/rust/tests/issue_895_test.rs index 6c7090d2da..dd9b19fa04 100644 --- a/rust/tests/issue_895_test.rs +++ b/rust/tests/issue_895_test.rs @@ -1,10 +1,12 @@ -use ::issue_895::*; +use issue_895::{ + issue_895_codec::{decoder::Issue895Decoder, encoder::Issue895Encoder}, + MessageHeaderDecoder, ReadBuf, SbeResult, WriteBuf, ENCODED_LENGTH, SBE_BLOCK_LENGTH, + SBE_SCHEMA_ID, SBE_SCHEMA_VERSION, SBE_TEMPLATE_ID, +}; fn create_encoder(buffer: &mut Vec) -> Issue895Encoder { - let issue_895 = Issue895Encoder::default().wrap( - WriteBuf::new(buffer.as_mut_slice()), - ENCODED_LENGTH, - ); + let issue_895 = + Issue895Encoder::default().wrap(WriteBuf::new(buffer.as_mut_slice()), ENCODED_LENGTH); let mut header = issue_895.header(0); header.parent().unwrap() } @@ -72,4 +74,4 @@ fn issue_895_double_none() -> SbeResult<()> { assert_eq!(None, decoder.optional_double()); Ok(()) -} \ No newline at end of file +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 3d38b28aa2..67c949cbe0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -81,7 +81,7 @@ void generate() throws IOException // add re-export of modules for (final String module : modules) { - indent(libRs, 0, "pub use %s::*;\n", toLowerSnakeCase(module)); + indent(libRs, 0, "pub use crate::%s::*;\n", toLowerSnakeCase(module)); } indent(libRs, 0, "\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 25e200a268..cb06bbc96a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -15,6 +15,7 @@ */ package uk.co.real_logic.sbe.generation.rust; +import org.agrona.Strings; import org.agrona.Verify; import org.agrona.generation.OutputManager; import uk.co.real_logic.sbe.PrimitiveType; @@ -119,7 +120,7 @@ public void generate() throws IOException indent(writer, 0, "version = \"0.1.0\"\n"); indent(writer, 0, "authors = [\"sbetool\"]\n"); indent(writer, 0, "description = \"%s\"\n", ir.description()); - indent(writer, 0, "edition = \"2018\"\n\n"); + indent(writer, 0, "edition = \"2021\"\n\n"); indent(writer, 0, "[lib]\n"); indent(writer, 0, "name = \"%s\"\n", namespace); indent(writer, 0, "path = \"src/lib.rs\"\n"); @@ -151,8 +152,8 @@ public void generate() throws IOException try (Writer out = outputManager.createOutput(codecModName)) { indent(out, 0, "use crate::*;\n\n"); - indent(out, 0, "pub use encoder::*;\n"); - indent(out, 0, "pub use decoder::*;\n\n"); + indent(out, 0, "pub use encoder::%sEncoder;\n", formatStructName(msgToken.name())); + indent(out, 0, "pub use decoder::%sDecoder;\n\n", formatStructName(msgToken.name())); final String blockLengthType = blockLengthType(); final String templateIdType = rustTypeName(ir.headerStructure().templateIdType()); final String schemaIdType = rustTypeName(ir.headerStructure().schemaIdType()); @@ -274,7 +275,18 @@ static void generateEncoderGroups( final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); final PrimitiveType numInGroupPrimitiveType = numInGroupToken.encoding().primitiveType(); - indent(sb, level, "/// GROUP ENCODER\n"); + final String description = groupToken.description(); + if (!Strings.isEmpty(description)) + { + indent(sb, level, "/// GROUP ENCODER (id=%s, description='%s')\n", + groupToken.id(), description); + } + else + { + indent(sb, level, "/// GROUP ENCODER (id=%s)\n", + groupToken.id()); + } + assert 4 == groupHeaderTokenCount; indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(self, count: %s, %1$s: %3$s) -> %3$s {\n", @@ -553,7 +565,7 @@ private static void generateCompositeDecoder( decoderName, decoderTypeName); - indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version()); indent(sb, level + 2, "return Either::Left(self);\n"); indent(sb, level + 1, "}\n\n"); @@ -587,7 +599,7 @@ private static void generateBitSetDecoder( if (bitsetToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", bitsetToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", bitsetToken.version()); indent(sb, level + 2, "return %s::default();\n", structTypeName); indent(sb, level + 1, "}\n\n"); } @@ -647,7 +659,7 @@ private static void generatePrimitiveArrayDecoder( if (fieldToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version()); indent(sb, level + 2, "return [%s; %d];\n", encoding.applicableNullValue(), arrayLength); indent(sb, level + 1, "}\n\n"); } @@ -756,7 +768,7 @@ private static void generatePrimitiveOptionalDecoder( if (fieldToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version()); indent(sb, level + 2, "return None;\n"); indent(sb, level + 1, "}\n\n"); } @@ -809,7 +821,7 @@ private static void generatePrimitiveRequiredDecoder( if (fieldToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version()); indent(sb, level + 2, "return %s;\n", generateRustLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString())); indent(sb, level + 1, "}\n\n"); @@ -897,9 +909,19 @@ static void generateDecoderGroups( i = collectVarData(tokens, i, varData); final String groupName = decoderName(formatStructName(groupToken.name())); - indent(sb, level, "/// GROUP DECODER\n"); - assert 4 == groupHeaderTokenCount; + final String description = groupToken.description(); + if (!Strings.isEmpty(description)) + { + indent(sb, level, "/// GROUP DECODER (id=%s, description='%s')\n", + groupToken.id(), description); + } + else + { + indent(sb, level, "/// GROUP DECODER (id=%s)\n", + groupToken.id()); + } + assert 4 == groupHeaderTokenCount; indent(sb, level, "#[inline]\n"); if (groupToken.version() > 0) { @@ -910,18 +932,14 @@ static void generateDecoderGroups( indent(sb, level + 2, "return None;\n"); indent(sb, level + 1, "}\n\n"); - indent(sb, level + 1, "let acting_version = self.acting_version;\n"); - indent(sb, level + 1, "Some(%s::default().wrap(self, acting_version as usize))\n", - groupName); + indent(sb, level + 1, "Some(%s::default().wrap(self))\n", groupName); } else { indent(sb, level, "pub fn %s(self) -> %2$s {\n", formatFunctionName(groupName), groupName); - indent(sb, level + 1, "let acting_version = self.acting_version;\n"); - indent(sb, level + 1, "%s::default().wrap(self, acting_version as usize)\n", - groupName); + indent(sb, level + 1, "%s::default().wrap(self)\n", groupName); } indent(sb, level, "}\n\n"); @@ -958,7 +976,8 @@ static void generateDecoderVarData( { if (varDataToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", varDataToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", + varDataToken.version()); indent(sb, level + 2, "return (self.parent.as_ref().unwrap().get_limit(), 0);\n"); indent(sb, level + 1, "}\n\n"); } @@ -973,7 +992,8 @@ static void generateDecoderVarData( { if (varDataToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", varDataToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", + varDataToken.version()); indent(sb, level + 2, "return (self.get_limit(), 0);\n"); indent(sb, level + 1, "}\n\n"); } @@ -992,7 +1012,8 @@ static void generateDecoderVarData( if (varDataToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", varDataToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", + varDataToken.version()); indent(sb, level + 2, "return &[] as &[u8];\n"); indent(sb, level + 1, "}\n\n"); } @@ -1199,7 +1220,7 @@ private static void generateEnum( throw new IllegalArgumentException("No valid values provided for enum " + originalEnumName); } - indent(writer, 0, "#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]\n"); + indent(writer, 0, "#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]\n"); final String primitiveType = rustTypeName(messageBody.get(0).encoding().primitiveType()); indent(writer, 0, "#[repr(%s)]\n", primitiveType); indent(writer, 0, "pub enum %s {\n", enumRustName); @@ -1216,16 +1237,11 @@ private static void generateEnum( final Encoding encoding = messageBody.get(0).encoding(); final CharSequence nullVal = generateRustLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString()); + indent(writer, 1, "#[default]\n"); indent(writer, 1, "NullVal = %s, \n", nullVal); } indent(writer, 0, "}\n"); - // Default implementation to support Default in other structs - indent(writer, 0, "impl Default for %s {\n", enumRustName); - indent(writer, 1, "#[inline]\n"); - indent(writer, 1, "fn default() -> Self { %s::%s }\n", enumRustName, "NullVal"); - indent(writer, 0, "}\n"); - // From impl indent(writer, 0, "impl From<%s> for %s {\n", primitiveType, enumRustName); indent(writer, 1, "#[inline]\n"); @@ -1271,8 +1287,8 @@ private static void generateComposite( { indent(out, 0, "use crate::*;\n\n"); - indent(out, 0, "pub use encoder::*;\n"); - indent(out, 0, "pub use decoder::*;\n\n"); + indent(out, 0, "pub use encoder::%sEncoder;\n", formatStructName(compositeName)); + indent(out, 0, "pub use decoder::%sDecoder;\n\n", formatStructName(compositeName)); final int encodedLength = tokens.get(0).encodedLength(); if (encodedLength > 0) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index 4f71f0de84..13fa241a40 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -260,7 +260,7 @@ private static String sanitizeMethodOrProperty(final String name) { if (shadowsKeyword(name)) { - return name + "_"; + return "r#" + name; } else { @@ -310,7 +310,7 @@ enum ReservedKeyword { for (final ReservedKeyword value : ReservedKeyword.values()) { - LOWER_CASE_NAMES.add(value.name()); + LOWER_CASE_NAMES.add(value.name().toLowerCase()); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index 756e019fdf..d7fd2cc55d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -157,7 +157,6 @@ void generateDecoder( indent(sb, level - 1, "pub struct %s

      {\n", name); indent(sb, level, "parent: Option

      ,\n"); indent(sb, level, "block_length: usize,\n"); - indent(sb, level, "acting_version: usize,\n"); indent(sb, level, "count: %s,\n", rustTypeName(numInGroupPrimitiveType)); indent(sb, level, "index: usize,\n"); indent(sb, level, "offset: usize,\n"); @@ -174,7 +173,6 @@ void generateDecoder( indent(sb, level, "pub fn wrap(\n"); indent(sb, level + 1, "mut self,\n"); indent(sb, level + 1, "mut parent: P,\n"); - indent(sb, level + 1, "acting_version: usize,\n"); indent(sb, level, ") -> Self {\n"); indent(sb, level + 1, "let initial_offset = parent.get_limit();\n"); indent(sb, level + 1, "let block_length = parent.get_buf().get_%s_at(initial_offset) as usize;\n", @@ -186,7 +184,6 @@ void generateDecoder( indent(sb, level + 1, "self.parent = Some(parent);\n"); indent(sb, level + 1, "self.block_length = block_length;\n"); - indent(sb, level + 1, "self.acting_version = acting_version;\n"); indent(sb, level + 1, "self.count = count;\n"); indent(sb, level + 1, "self.index = usize::MAX;\n"); indent(sb, level + 1, "self.offset = 0;\n"); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java index 33f3a876d4..f7dcc14c28 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java @@ -136,6 +136,8 @@ void functionNameCasing() assertEquals("pricenull_9", formatFunctionName("PRICENULL9")); assertEquals("price_9_book", formatFunctionName("PRICE9Book")); assertEquals("issue_435", formatFunctionName("issue435")); + assertEquals("r#type", formatFunctionName("type")); + assertEquals("upper_case", formatFunctionName("UPPERCase")); assertEquals("no_md_entries", formatFunctionName("NoMDEntries")); assertEquals("md_entry_type_book", formatFunctionName("MD_EntryTYPEBook")); From 3b8101dffed86b4c76a30da4f2319036bcdf4b36 Mon Sep 17 00:00:00 2001 From: Wojciech Lukowicz Date: Thu, 2 Nov 2023 10:52:42 +0000 Subject: [PATCH 1059/1594] [Java] Upgrade to Agrona 1.20.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 04b981c43f..9e0286ff8c 100644 --- a/build.gradle +++ b/build.gradle @@ -58,8 +58,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.10.0' def jmhVersion = '1.37' -def agronaVersion = '1.19.2' -def agronaVersionRange = '[1.19.2,2.0[' // allow any release >= 1.19.2 and < 2.0.0 +def agronaVersion = '1.20.0' +def agronaVersionRange = '[1.20.0,2.0[' // allow any release >= 1.20.0 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 24ede47c74297b3db2d841df70c181736c7ac3df Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 6 Nov 2023 11:18:24 +0100 Subject: [PATCH 1060/1594] [Java] Upgrade to JUnit 5.10.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9e0286ff8c..143ef8c335 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' -def junitVersion = '5.10.0' +def junitVersion = '5.10.1' def jmhVersion = '1.37' def agronaVersion = '1.20.0' def agronaVersionRange = '[1.20.0,2.0[' // allow any release >= 1.20.0 and < 2.0.0 From 3a7d44595e054c377eb0044074b10bc2bb68f64e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 17 Nov 2023 09:35:27 +0000 Subject: [PATCH 1061/1594] [Java] Upgrade to Versions 0.50.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 143ef8c335..3838d1a1ce 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ buildscript { plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '8.1.1' apply false - id 'com.github.ben-manes.versions' version '0.49.0' + id 'com.github.ben-manes.versions' version '0.50.0' } defaultTasks 'clean', 'build' From dd6063fe8bf2ab03ca6c3a51b462a6aba5f2be74 Mon Sep 17 00:00:00 2001 From: pliard Date: Tue, 28 Nov 2023 16:18:28 +0100 Subject: [PATCH 1062/1594] [Java] Support `valueRef` with camelCase enum type identifiers (#963) The type identifier was previously used as-is (e.g. `carFilterType`) in the generated code for uses of `valueRef` while generated Java enums always start with a capital letter (`CarFilterType`). See the added test in ValueRefWithLowerCaseEnum.java. --- .../sbe/generation/java/JavaGenerator.java | 3 +- .../java/ValueRefWithLowerCaseEnum.java | 69 +++++++++++++++++++ .../value-ref-with-lower-case-enum.xml | 24 +++++++ 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnum.java create mode 100644 sbe-tool/src/test/resources/value-ref-with-lower-case-enum.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index e40a02c6a1..eb90237170 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3074,7 +3074,8 @@ private void generateEnumDecoder( if (fieldToken.isConstantEncoding()) { - final String enumValueStr = fieldToken.encoding().constValue().toString(); + final String enumValueStr = formatClassName( + fieldToken.encoding().constValue().toString()); new Formatter(sb).format( "\n" + diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnum.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnum.java new file mode 100644 index 0000000000..98cdf3852b --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnum.java @@ -0,0 +1,69 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; +import uk.co.real_logic.sbe.xml.XmlSchemaParser; + +import java.io.InputStream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.StringContains.containsString; + +class ValueRefWithLowerCaseEnum +{ + private static final Class BUFFER_CLASS = MutableDirectBuffer.class; + private static final String BUFFER_NAME = BUFFER_CLASS.getName(); + private static final Class READ_ONLY_BUFFER_CLASS = DirectBuffer.class; + private static final String READ_ONLY_BUFFER_NAME = READ_ONLY_BUFFER_CLASS.getName(); + + @Test + void shouldGenerateConstCharArrayMethods() throws Exception + { + try (InputStream in = Tests.getLocalResource("value-ref-with-lower-case-enum.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = XmlSchemaParser.parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager); + + generator.generate(); + final String sources = outputManager.getSources().toString(); + + // Prior to the fix the generated body of the following method was + // `return engineType.gas;` + final String expected = + " public EngineType engineType()\n" + + " {\n" + + " return EngineType.gas;\n" + + " }"; + assertThat(sources, containsString(expected)); + } + } +} diff --git a/sbe-tool/src/test/resources/value-ref-with-lower-case-enum.xml b/sbe-tool/src/test/resources/value-ref-with-lower-case-enum.xml new file mode 100644 index 0000000000..c33b4133c8 --- /dev/null +++ b/sbe-tool/src/test/resources/value-ref-with-lower-case-enum.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + 0 + + + + + + + From a259c7d5f6389f240700b7801d842940621b6151 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 6 Dec 2023 11:32:28 +0000 Subject: [PATCH 1063/1594] [Java,C#,C++] Support field access order checking (#948) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a squashed merge of many commits. I've kept the original commit messages below for posterity; however, a better summary is available in the description of [PR #948](https://github.com/real-logic/simple-binary-encoding/pull/948). Squashing makes it easy to revert, but sadly, it loses the fine-grained history available through `git blame`. --- * [Java] Add disabled tests around checking field access order. SBE does not support arbitrary access to fields when encoding and decoding. In particular, accessing groups and variable length fields advances a `limit`, which marks where the start of the next group/variable length field is expected. We aim to introduce some checking (in debug mode - when bounds checks are enabled) that verifies field access order is consistent enough with the order defined in the schema to encode or decode a valid message. * [Java] Spike an approach for checking field encode order. Also, enable some tests around field order checking. Outline of the approach: - Using a FSM, model the states of an encoder during encoding. - Hopefully, this model will be language independent. - Generate code to perform state transitions upon field accesses. - And to throw when transitions are not in the model. Assumptions: - JIT compilation will remove `if (DEBUG_MODE) { ... }` blocks when the static boolean constant, `DEBUG_MODE`, is `false`. Questions: - Is the approach reasonable? - Is the newly disallowed behaviour reasonable? - For example, it prevents encoding block fields after a group or variable length field has been encoded. Further work: - Decode path - More tests (including tests for decoding old messages where some fields may not be present) * [Java] Support printing field order access state machine. Use `-Dsbe.print.state.machine=$NAME_OF_MSG`. * [Java] Add checking around decoding order. This change builds upon the work to check field encoding order. It is a slightly more-complex problem than with encoding, as when decoding it is necessary to deal with multiple versions of encoded data. To handle this, we fuse together the state machines for decoding each possible version and branch on "decoder.wrap(...)". Further work: - More tests - Better error messages * [Java] Test field order checks across versions. "New" decoders (in Java at least) read null-like values for fields that are not present in "old" messages. There are no restrictions on the order in which these "new" fields are accessed when decoding "old" data. In Java, a version check returns a null-like value when a field is not present in the acting version. This behaviour matches the wiki documentation. C#, currently, has different behaviour: the application code needs to interrogate a boolean property, e.g., `IsFooInActingVersion`, before accessing the data property, e.g., `Foo`. The property itself assumes that the field is present. It will attempt to read it from the buffer and possibly advance a `limit` field. In this commit, I have moved the state transition beneath the existing version check in Java decoders. This change allows these fields to be accessed when decoding "old" messages without changing the state of decoding, which seems appropriate as there are no side-effects on internal state, e.g., the `limit` field. Also, in this commit, I have expanded the test coverage to include the getter and setter variants for fixed-size arrays and variable-length data. * [Java] Generate better error messages. Also, use an enum to represent codec states rather than a state number and generate (dot-based) state machine diagram in Javadoc for states enum. * [Java] Test field order checks with fixed-length strings. Also, fix some spots where I had forgotten to move the state transition below the version check in decoders. * [Java] Test field checks do not affect toString. * [Java] Fix field order checks to work with `decodedLength()`. * [Java] Test content of field order error messages. There is still work to do in this area. In particular: 1. States should be more descriptive. 1. Errors should contain full field paths. 2. Group error messages should be more clear, e.g., "cannot write group element before calling next()". * [Java] Fix field access order in tests and re-enable. * [Java] Permit block field access whenever it is safe (and, unfortunately, in some cases where it is not). This commit makes the field order checks more-lenient. The aim is to allow the application code to access fields in the root/top-level block or blocks inside groups whenever it is safe. However, the approach is broken and does not work in general. To (try to) achieve this aim, we rely on the fact that once a block is positioned correctly, it is safe to access during the remainder of encoding/decoding. For example, the following code is safe: ``` encoder.wrap(...); encoder.blockField1(42); encoder.varData("abc"); encoder.blockField2(43); ``` As soon as `wrap(...)` is called, the top-level block will be positioned over a valid region for the remainder of encoding. Groups are slightly trickier. The following code is _safe_: ``` encoder.wrap(...); Foo.BarEncoder bar = encoder.groupBarCount(2); bar.next() .x(1).y(2) .next(); .x(3).y(4); ``` But the following code is _unsafe_: ``` encoder.wrap(...); Foo.BarEncoder bar = encoder.groupBarCount(2); bar.x(1).y(2) .next(); .x(3).y(4); ``` And the following code is _unsafe_ too: ``` encoder.wrap(...) Foo.BarEncoder bar = encoder.groupBarCount(0); encoder.baz("abc"); bar.x(1).y(2); ``` The `offset` for the group encoder is only set when `next()` is called. Therefore, calling `x(1)` and `y(2)` will likely overwrite some data elsewhere in the buffer (probably near offset 0). We can still rely on the fact that once `next()` has been called - even if it is called multiple times, or too many times (causing it to throw) - the group's block fields will be safe to encode/decode. Thinking about this in terms of our state machine that models codec state and field accesses, we can put this another way. There is at least one transition that represents the `next()` method call. The states (transitively) reachable from these transitions can safely access the associated group block. As already mentioned, despite the passing tests, the approach in this commit doesn't always work. I had thought it would be possible to assign a number to each state as we find them using DFS and use this number as a shortcut to determining whether a block access was safe. For example, in each block field we would check: ``` if (currentState.number() >= firstStateAfterNextIsCalled.number()) { // ALLOW } else { // DENY } ``` However, (even ignoring the cycles due to repeating groups and the use of DFS) this solution makes the following assumptions: 1. There is a single state: `firstStateAfterNextIsCalled`, such that all subsequent transitively reachable states are safe. 2. It is possible to number the states in such a way that `numberOfState(b) >= numberOfState(a)` implies `b` is (transitively) reachable from `a`. Let's consider the following psuedo-schema w.r.t. our assumptions above: ``` group a { x: int32 } group b { y: int32 } ``` Can we set `x` if we've called `BEncoder#next`? Sometimes. The following code is invalid. ``` AEncoder a = encoder.aCount(0); BEncoder b = encoder.bCount(1).next(); b.y(2); a.x(1); // Whoops! We overwrote some data somewhere. ``` But this code is valid. ``` AEncoder a = encoder.aCount(1).next(); BEncoder b = encoder.bCount(1).next(); b.y(2); a.x(1); ``` Therefore, multiple transitions must exist for the `BEncoder#next` call with different exit states, which breaks Assumption 1. Assumption 2 is also problematic. As alluded to above, we must have a bifurcation of states depending on whether a group has elements or is empty. With arbitrary bifurcations, it is not possible to number the states in such a way that Assumption 2 holds. Consider the following state diagram: ``` state N / \ empty non-empty / \ state X state Y ``` Depending on whether a group is empty, e.g., `aCount(0)`, or not, e.g., `aCount(1)`, we transition to either `state X` or `state Y` from `state N`. For Assumption 2 to hold, we need `numberOf(state X) >= numberOf(state N)` (reachable) and `numberOf(state Y) >= numberOf(state N)` (reachable) and `numberOf(state X) < numberOf(state Y)` (unreachable) and `numberOf(state Y) < numberOf(state X)` (unreachable). Clearly, this is impossible. Prior to this commit, we avoided such problems by enforcing a more-strict ordering of field accesses. With this more-strict ordering, setting fields in a group block in later states was not allowed. Therefore, the state machine didn't have to have to split into mutually exclusive subgraphs of reachable states depending on whether or not the group is empty. For example, let's consider a psuedo-schema with two groups. ``` group a { x: int32 } group b { y: int32 } ``` Once the application code calls `encoder.bCount(2).next()`, our state machine will enter the `V0_B_N_BLOCK` state regardless of whether previously the application code called `encoder.aCount(0)` or `encoder.aCount(1).next()`. In `V_B_N_BLOCK` the application code is not allowed to call `AEncoder#x`; therefore, it is safe, i.e., it has no false positives. However, it is also too-strict, i.e., it has false negatives, e.g., the `encoder.aCount(1).next()` case. How likely are these false negatives to come up in the "wild"? If we think false negatives will often come up, is it possible to remove them whilst still using a state machine? We could consider generating more states to represent the reachable states under each fork of group emptiness. The number of states would grow exponentially w.r.t. the number of top-level groups, but let's ignore that for the moment and just consider whether or not it is possible. Continuing the example above with two groups, when the application code calls `encoder.bCount(2).next()`, the state it enters would depend on whether it had previously called `encoder.aCount(0)` or `encoder.aCount(n)...next()` for some value `n > 0`. To safely model this example, we'd need at least the following states: 1. has no `a` elements 2. has no `a` elements, and has no `b` elements 3. has `a` elements, but has not called `AEncoder#next` 4. has `a` elements, and has called `AEncoder#next` 5. has `a` elements, has called `AEncoder#next`, has `b` elements, but has not called `BEncoder#next` 6. has `a` elements, has called `AEncoder#next`, has `b` elements, and has called `BEncoder#next` 7. has no `a` elements, has `b` elements, but has not called `BEncoder#next` 8. has no `a` elements, has `b` elements, and has called `BEncoder#next` A trickier case is with nested groups: ``` group foo { x: int32 group bar { y: int32 } r: string s: string } ``` When is `Bar#y` safe to call? I believe it is safe to call in states where `FooEncoder#next` and `BarEncoder#next` have been called in-order more recently than `BarEncoder#count(0)`. Note, as `bar` is a group within `foo`, the `BarEncoder#next` and `BarEncoder#count` methods may be called repeatedly during the encoding of a single message. Implementing a more-permissive safety check, using this model, would entail checking that the current state of the encoder/decoder is in a state where this condition holds. To safely model this example, we'd need (at least) the following states: 1. has no `foo` elements 2. has `foo` elements, but has not called `FooEncoder#next` 3. has `foo` elements, and has called `FooEncoder#next` 4. has `foo` elements, has called `FooEncoder#next`, and has no `bar` elements 5. has `foo` elements, has called `FooEncoder#next`, has no `bar` elements, and has encoded `r` 6. has `foo` elements, has called `FooEncoder#next`, has no `bar` elements, and has encoded `s` 7. has `foo` elements, has called `FooEncoder#next`, has `bar` elements, but has not called `BarEncoder#next` 8. has `foo` elements, has called `FooEncoder#next`, has `bar` elements, has not called `BarEncoder#next`, and has encoded `r` 9. has `foo` elements, has called `FooEncoder#next`, has `bar` elements, has not called `BarEncoder#next`, and has encoded `s` 10. has `foo` elements, has called `FooEncoder#next`, has `bar` elements, and has called `BarEncoder#next` 11. has `foo` elements, has called `FooEncoder#next`, has `bar` elements, and has called `BarEncoder#next`, and has encoded `r` 12. has `foo` elements, has called `FooEncoder#next`, has `bar` elements, and has called `BarEncoder#next`, and has encoded `s` ``` FooEncoder foo = encoder.fooCount(3); // State 2 foo.next(); // State 3 foo.barCount(0); // State 4 foo.r("abc"); // State 5 foo.s("def"); // State 6 foo.next(); // State 4 BarEncoder bar = foo.barCount(1); // State 7 foo.r("abc"); // State 8 bar.next(); // State 11 bar.y(42); // State 11 foo.s("def"); // State 12 foo.next(); // State X? bar.y(43); // Weird but allowed. foo.barCount(0); // State Y? State X cannot be State 10, as State 10 should not allow _re-encoding_ of the bar group count ``` OK. We didn't have enough states. In the case where we "wrap back around", we need to model whether `bar` block access is allowed (State 13 vs State 3): 13. has `foo` elements, has called `FooEncoder#next`, has called `BarEncoder#next` for last iteration, but hasn't set `bar` group size in this iteration. An even trickier case is with doubly-nested groups: ``` group foo { x: int32 group bar { y: int32 group baz { z: int32 } } } ``` When is `Baz#z` safe to call? I believe it is safe to call in states where `FooEncoder#next`, `BarEncoder#next` and `BazEncoder#next` have been called in-order more recently than `BarEncoder#count(0)` or `BazEncoder#count(0). Encoding this in states is likely to result in more cases like State 13 above. Generalising: a group block field may be accessed only when all outer groups' and its own `#next` methods have been called in-order more recently than any outer groups' or its own `#count` method with a `0` argument. Can model "more-recently" exactly, i.e., with no false positives and no false negatives, using a state machine? Another way of looking at the state machines we generate, is as parsers for a language. Where our language, based on an SBE schema, comprises valid "strings" of calls to an encoder/decoder. Is this language a regular language? If not, representing it using a FSM will not work. Cue Pumping Lemma? Next steps: - Add more tests to show where this approach breaks - Revert the changes and see if it is acceptable that some valid uses of codecs will be prevented when enabling field order checking. I.e., it will give false negatives when testing the hypothesis "this encoding/decoding is valid". - Personally, I think false negatives are better than false positives. (False positives are possible as of this commit.) Having said that, it will discourage use of these checks in existing systems where valid code already exists that does not pass the checks. * [Java] Add (disabled) failing tests for false positives. (When testing the hypothesis "this decoding/encoding code is valid".) These tests show that there are problems with the approach in the last commit. * Revert "[Java] Permit block field access whenever it is safe (and, unfortunately, in some cases where it is not)." This reverts commit d9eb33dc793d7f62e696e4f40a1b4cf36d50316f. * [Java] Treat top-level block fields as a special case. To reduce the number of false negatives the field access order checker generates, in this commit, we treat the top-level block fields differently. We know that once the top-level encoder is wrapped, these fields are always safe to access. As a result, we were able to enable several tests that previously failed. * [Java] Support turning on access checks independently of bounds checks. Introduces the system property: ``` sbe.enable.access.order.checks ``` * [Java] Attempt to optimise code with disabled access order checks. Some JIT compilers are able to eliminate dead code within branches of if-statements where the conditional is a static expression. Some JIT compilers perform inlining to some degree and use heuristics, e.g., method size. It isn't clear whether code size metrics will be calculated after dead code elimination is performed. In this commit, I've moved the code that performs state transitions when access order checks are enabled into separate methods that the encoders/decoders call upon field accesses, e.g., the getter for a field `xyz` might look like this: ``` int xyz() { if (ENABLED_ACCESS_ORDER_CHECKS) { onXyzAccessed(); } // ... } ``` This keeps the initial size of `xyz` smaller than when the code of `onXyzAccessed()` is "inlined" by the code generator. There is a lot of noise on my ThinkPad P14s, but benchmarks do show improvements after this change. Before: ``` $ java -jar -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=false ./sbe-benchmarks/build/libs/sbe-benchmarks.jar ".*Car.*" -bm thrpt -f 2 -i 3 -wi 2 \# JMH version: 1.36 \# VM version: JDK 1.8.0_302, OpenJDK 64-Bit Server VM, 25.302-b08 \# VM invoker: /home/zach/.asdf/installs/java/zulu-8.56.0.21/jre/bin/java \# VM options: -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=false ... Benchmark Mode Cnt Score Error Units CarBenchmark.testDecode thrpt 6 18051405.792 ± 444296.898 ops/s CarBenchmark.testEncode thrpt 6 11964827.418 ± 221996.747 ops/s ``` After: ``` $ java -jar -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=false ./sbe-benchmarks/build/libs/sbe-benchmarks.jar ".*Car.*" -bm thrpt -f 2 -i 3 -wi 2 \# JMH version: 1.36 \# VM version: JDK 1.8.0_302, OpenJDK 64-Bit Server VM, 25.302-b08 \# VM invoker: /home/zach/.asdf/installs/java/zulu-8.56.0.21/jre/bin/java \# VM options: -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=false ... Benchmark Mode Cnt Score Error Units CarBenchmark.testDecode thrpt 6 18132922.415 ± 1964596.044 ops/s CarBenchmark.testEncode thrpt 6 20018131.180 ± 671367.070 ops/s ``` Baseline (d2ec8f8a225808a1392872473f6e5e85b828056e): ``` $ java -jar -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=false ./sbe-benchmarks/build/libs/sbe-benchmarks.jar ".*Car.*" -bm thrpt -f 2 -i 3 -wi 2 \# JMH version: 1.36 \# VM version: JDK 1.8.0_302, OpenJDK 64-Bit Server VM, 25.302-b08 \# VM invoker: /home/zach/.asdf/installs/java/zulu-8.56.0.21/jre/bin/java \# VM options: -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=false ... Benchmark Mode Cnt Score Error Units CarBenchmark.testDecode thrpt 6 19270366.357 ± 2618336.027 ops/s CarBenchmark.testEncode thrpt 6 22519718.535 ± 794169.180 ops/s ``` * [Java] Add feature toggle for access order check generation. The code generator will omit checks when the `sbe.generate.access.order.checks` system property is set to `false`. Adding the feature toggle allowed me to run the following benchmarks on my ThinkPad P14s, where (unfortunately) there is some noise. Baseline (d2ec8f8a225808a1392872473f6e5e85b828056e): ``` $ java -jar -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=false ./sbe-benchmarks/build/libs/sbe-benchmarks.jar ".*Car.*" -bm thrpt -f 2 -i 3 -wi 2 \# JMH version: 1.36 \# JMH version: 1.36 \# JMH version: 1.36 \# JMH version: 1.36 \# VM version: JDK 1.8.0_302, OpenJDK 64-Bit Server VM, 25.302-b08 \# VM invoker: /home/zach/.asdf/installs/java/zulu-8.56.0.21/jre/bin/java \# VM options: -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=false ... Benchmark Mode Cnt Score Error Units CarBenchmark.testDecode thrpt 6 19270366.357 ± 2618336.027 ops/s CarBenchmark.testEncode thrpt 6 22519718.535 ± 794169.180 ops/s ``` This commit with new code generation disabled, i.e., `-Dsbe.generate.access.order.checks=false` at build time: ``` $ java -jar -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=false ./sbe-benchmarks/build/libs/sbe-benchmarks.jar ".*Car.*" -bm thrpt -f 2 -i 3 -wi 2 \# JMH version: 1.36 \# VM version: JDK 1.8.0_302, OpenJDK 64-Bit Server VM, 25.302-b08 \# VM invoker: /home/zach/.asdf/installs/java/zulu-8.56.0.21/jre/bin/java \# VM options: -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=false ... Benchmark Mode Cnt Score Error Units CarBenchmark.testDecode thrpt 6 19290928.253 ± 2226604.698 ops/s CarBenchmark.testEncode thrpt 6 21957767.395 ± 567000.570 ops/s ``` This commit with new code generation enabled, but disabled checks, i.e., `-Dsbe.enable.access.order.checks=false` at runtime. ``` $ java -jar -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=false ./sbe-benchmarks/build/libs/sbe-benchmarks.jar ".*Car.*" -bm thrpt -f 2 -i 3 -wi 2 \# JMH version: 1.36 \# VM version: JDK 1.8.0_302, OpenJDK 64-Bit Server VM, 25.302-b08 \# VM invoker: /home/zach/.asdf/installs/java/zulu-8.56.0.21/jre/bin/java \# VM options: -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=false ... Benchmark Mode Cnt Score Error Units CarBenchmark.testDecode thrpt 6 19238066.328 ± 2557533.640 ops/s CarBenchmark.testEncode thrpt 6 22284274.779 ± 520984.898 ops/s ``` Whilst it is hard to definitively conclude anything using my noisy machine to benchmark, it seems like there is no obvious performance regression when the runtime checks are disabled in comparison to omitting the checks at build time. * [Java] Improve performance of field access order checking. This commit switches the generated code to using an int to represent the state rather than a reference to an enum case. The change improves performance significantly, which I suspect is due to avoiding a write barrier that updates the card table. Relevant benchmark runs are below. Perhaps different JVM versions and GC options will yield different relative improvements. All benchmark runs use: - `-Dsbe.generate.access.order.checks=true` at build time - `-Dsbe.enable.access.order.checks=true` at runtime Using an enum: ``` $ java -jar -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=true ./sbe-benchmarks/build/libs/sbe-benchmarks.jar ".*Car.*" -bm thrpt -f 2 -i 3 -wi 2 \# JMH version: 1.36 \# VM version: JDK 1.8.0_302, OpenJDK 64-Bit Server VM, 25.302-b08 \# VM invoker: /home/zach/.asdf/installs/java/zulu-8.56.0.21/jre/bin/java \# VM options: -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=true ... Benchmark Mode Cnt Score Error Units CarBenchmark.testDecode thrpt 6 8075519.641 ± 363346.224 ops/s CarBenchmark.testEncode thrpt 6 7211523.145 ± 504174.913 ops/s ``` Using an int: ``` $ java -jar -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=true ./sbe-benchmarks/build/libs/sbe-benchmarks.jar ".*Car.*" -bm thrpt -f 2 -i 3 -wi 2 \# JMH version: 1.36 \# VM version: JDK 1.8.0_302, OpenJDK 64-Bit Server VM, 25.302-b08 \# VM invoker: /home/zach/.asdf/installs/java/zulu-8.56.0.21/jre/bin/java \# VM options: -Dagrona.disable.bounds.checks=true -Dsbe.enable.access.order.checks=true ... Benchmark Mode Cnt Score Error Units CarBenchmark.testDecode thrpt 6 13030684.127 ± 155782.171 ops/s CarBenchmark.testEncode thrpt 6 9781612.505 ± 1342559.378 ops/s ``` * [Java] Provide more context in error messages. In this commit, we associate field tokens with the "path" through the message to it. We can then use this to generate code with better error messages that include the path to the field rather than just the field name, which could have been ambiguous when there are groups. * [Java] Provide more context in error messages. In this commit, I've customised the error messages around group access to give a better indication of what was attempted. * [Java] Specify expected transitions in error messages. In this commit, I've improved the error messages around field access order checks so that it reports the legal transitions in the current state. Hopefully, this will make it easier for users to fix problems. * [Java] Use fewer states to model encoding. Encoders can only encode the latest version, unlike decoders. Therefore, we do not need to model field access patterns other than that of the latest version. * [Java] Refactor field access order checking. Overview: - `AccessOrderModel.CodecInteraction` models the possible interactions with an encoder or decoder: - Wrapping it around a buffer - Accessing its fields (block or var data) - Encoding/decoding the count of a repeating group - Moving to the next element in a repeating group - Moving to the last element in a repeating group - `AccessOrderModel` models the encoder/decoder state transitions w.r.t. these interactions * [Java] Address review comment. A disabled test had an incorrect assertion. Also, I've replaced the term "group length" with "group count" in the test names. * [Java] Add tests for variable-length data in nested group. These tests are based on Mike's review comments. * [Java] Generate check that encoding is complete. Previously, we checked the order of encoding was correct but not that the encoding reached a terminal state. In this commit, I've added code to generate a new method `checkEncodingIsComplete` on Java encoders. It verifies that a terminal state has been reached; otherwise, it throws an exception with information about the current state and transitions. * [Java] Initialise buffer bytes before encoding in tests. Check that null checks are actually working, rather than just returning 0s from the buffer. Also, fix usage of bitsets to always set all options. * [C#] Ignore personal Rider file. * [C#] Fix bug in string encoding method. Previously it would generate something like: ``` buffer.PutByte(someOffset, (ushort) someValue); // ^^^^^^^^ ``` Where the source value was too wide for the destination. * [C#] Port field access order tests. In this commit, I've ported most of the tests from the Java suite of tests for field access order checking to CSharp. To get the tests to compile, I had to generate an empty method stub for `CheckEncodingIsComplete()` on the codecs. Some generated APIs are different, e.g., around strings and arrays. Therefore, test cases and their numbers differ slightly in some places. * [Java] Fix indent. * [C#,Java] Port access order checking implementation to C#. Tests remain ignored due to two pre-existing problems in the C# codecs: 1. `ToString()` alters the codec state, e.g., `_limit`. 2. Some accessors do not check the field is present in the version being decoded. * [C#] Recover codec state after `ToString()`. Previously, the `ToString()` call would fail or complete but alter the state of the codec such that it was in a terminal state. Now, we treat `codecState` much like `limit` and recover the original value before returning control from `ToString()`. * [C#] Generate (more) presence checks in accessors. Previously, some accessors did not check that the acting version (being decoded) had the field/group/varData being accessed. Therefore, it might return garbage. But other accessors did check. In this commit, I've attempted to make more of the accessors (hopefully all) check the acting version before attempting to read data from the underlying buffer. This change should make the C# codecs closer to the Java decoders. * [C#] Enable access order checking tests. Having ported the implementation from Java and fixed some issues where the C# codecs were not checking the acting version when decoding data, the tests now pass. * [C++] Port access order checking tests and implementation to C++. In this commit, I also addressed these issues (1-3): --- 1. Tidy up string format usage. --- For convenience and readability, I had inlined some concatenation into `string.format(...)` templates; however, this makes it unclear whether the variable/method-output being concatenated uses template parameters. Therefore, I have adjusted to inject these strings via template parameters. FWIW I'd prefer to use `StringBuilder` everywhere, as I think it is hard to read large string format templates. --- 2. Explcitly delete copy constructors of flyweights. --- I found it easy to accidentally write sub-optimal code where I relied on copy constructors. For example: ``` MyMessage::MyGroup myGroup = myMessage.myGroup(10); ``` rather than: ``` MyMessage::MyGroup &myGroup = myMessage.myGroup(10); ``` Copying semantics are a bit strange when it comes to flyweights and trees of flyweights. Therefore, I think it is best to avoid entirely. This change is behind a feature flag. To re-enable implicit copy constructors specify the system property `-Dsbe.generate.implicit.copy.constructors=true`. --- 3. Adjust state machines to allow repeated decoding of variable-length --- data lengths, as accesses do not advance `limit`. * [C#] Improve indentation generation. Previously, some sections were not correctly aligned. * [Java, C#, C++] Model `resetCountToIndex()` state machine transition. Previously, the access order checks did not work with the `resetCountToIndex()` methods (generated on flyweights for repeating groups). Now, the valid transitions using these methods are modelled in the state machine and this is reflected in the code we generate for Java, C# and C++. Note that the `resetCountToIndex()` method does not change the `limit`/`position` of the message; therefore, it is only valid to use it when the `limit` aligns with a boundary between group elements. * [Java, C++, C#] Disable access order checking feature by default. We can deliver this new feature (and the C++ changes around copy constructors and copy assignment operators) without breaking any existing consumers by disabling the new code generation by default. Once released, and we've started to get feedback, we can decide whether we want to change the default and encourage our users to make use of the new feature. * [C++] Make access listener methods private. Also, fix some indentation issues. * [C++, C#] Tidy up. Removes superfluous space before SBE_NOEXCEPT specifier in C++. Tightens access modifiers in C#. * [Java, C++] Tidy up. Removes extraneous space in Java output when access order checks are disabled. Removes unnecessary access modifiers in C++ when access order checks are disabled. * [Java, C#, C++] Rename flags to enable field access order checking. The aim of this change is to avoid naming collisions with other flags, particularly in financial domains where "order" is used frequently. * [Java,C#,C++] Allow custom flag/properties to enable precedence checks. Some users would like the ability to enable precedence checks on some schemas but not others. Initially, I considered generating flags or system properties with the schema namespace; however, this forces the more-complex scheme on all users. It also might get unwieldly with long namespaces. It also assumes a one-to-one correspondence between namespaces and schemas. Instead, I have introduced two new system properties that can be applied at code generation time: - `sbe.precedence.checks.flagName`, which controls the symbol/macro used to enable precedence checks at build time in the generated C#/C++ code. It defaults to `"SBE_ENABLE_PRECEDENCE_CHECKS"`. - `sbe.precedence.checks.propName`, which controls the property name used to enable precedence checks at runtime in the generated Java code. It defaults to `"sbe.enable.precedence.checks"`. Now, users can run SbeTool with different values for these system properties to generate code with different enablement flags. Note above that the defaults are: - `SBE_ENABLE_PRECEDENCE_CHECKS` rather than `SBE_ENABLE_SEQUENCING_CHECKS`, and - `sbe.enable.precedence.checks` rather than `sbe.enable.sequencing.checks`. These changes and a change to another system property: - `sbe.generate.sequencing.checks` -> `sbe.generate.precedence.checks` address some feedback from Martin on the associated PR #948. * Address Mike's feedback around depending directly on system properties. Also, addresses Mike's feedback around the names of those system properties. In this commit, I've introduced a factory-like class: `PrecedenceChecks`. It creates models for message field access when the checks are enabled. It also provides a convenient place to group together some properties affecting the generation of field precedence checks. I have also renamed `AccessOrderModel` to `FieldPrecedenceModel` in this commit, as it aligns better with the system property names. * Address Mike's feedback: provide more specific diagram location. Previously, we only gave the (quite ambiguous) name of the inner class in the error message. Now, we give a qualified name that includes the codec/encoder/decoder class name (for C++, C#, and Java). * Validate PrecedenceChecks#Context in conclude. * Address Mike's feedback: move sys prop eval higher. In this commit, I've removed the `PrecedenceChecks#Configuration` class in favour of a static method within `TargetCodeGeneratorLoader`. Unfortunately, C# behaves differently to all the other code generators. To avoid duplicating the default configuration for precedence checks in the `CSharp` class, I've made the method publicly visible, which is a bit ugly. It has also introduced a cyclic dependency between the code generators, e.g., `JavaGenerator`, and `TargetCodeGeneratorLoader`, as in order to preserve the existing public signatures I have kept the old constructors around and supplied a default `PrecedenceChecks`. * Avoid cyclic dependency between classes. Move defaults out of property evaluation and into context. --- .gitignore | 5 + build.gradle | 26 +- csharp/sbe-generated/sbe-generated.csproj | 8 + .../sbe-tests/FieldAccessOrderCheckTests.cs | 3185 +++++++++++ .../java/uk/co/real_logic/sbe/SbeTool.java | 18 + .../generation/TargetCodeGeneratorLoader.java | 35 +- .../common/FieldPrecedenceModel.java | 1190 ++++ .../generation/common/PrecedenceChecks.java | 253 + .../sbe/generation/cpp/CppGenerator.java | 1264 ++++- .../sbe/generation/csharp/CSharp.java | 6 +- .../generation/csharp/CSharpGenerator.java | 933 +++- .../sbe/generation/java/JavaGenerator.java | 1109 +++- .../sbe/ir/generated/FrameCodecDecoder.java | 329 ++ .../sbe/ir/generated/FrameCodecEncoder.java | 237 + .../sbe/ir/generated/TokenCodecDecoder.java | 988 ++++ .../sbe/ir/generated/TokenCodecEncoder.java | 636 +++ sbe-tool/src/test/cpp/BoundsCheckTest.cpp | 61 +- sbe-tool/src/test/cpp/CMakeLists.txt | 9 + sbe-tool/src/test/cpp/CodeGenTest.cpp | 80 +- .../test/cpp/CompositeOffsetsCodeGenTest.cpp | 2 +- .../test/cpp/FieldAccessOrderCheckTest.cpp | 4937 +++++++++++++++++ .../sbe/FieldAccessOrderCheckTest.java | 3425 ++++++++++++ .../generation/java/JavaGeneratorTest.java | 93 +- .../sbe/generation/java/ReflectionUtil.java | 34 +- .../resources/field-order-check-schema.xml | 292 + 25 files changed, 18686 insertions(+), 469 deletions(-) create mode 100644 csharp/sbe-tests/FieldAccessOrderCheckTests.cs create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/PrecedenceChecks.java create mode 100644 sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java create mode 100644 sbe-tool/src/test/resources/field-order-check-schema.xml diff --git a/.gitignore b/.gitignore index 117022a886..6769c8db69 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,9 @@ out # cmake cmake-build-debug codecs +.cmake +CMakeFiles +thirdparty # cpp build linux cppbuild/CMakeCache.txt @@ -101,10 +104,12 @@ csharp/sbe-generated/issue483 csharp/sbe-generated/issue560 csharp/sbe-generated/issue661 csharp/sbe-generated/since-deprecated +csharp/sbe-generated/order_check csharp/sbe-generated/mktdata/*.cs csharp/sbe-generated/uk_co_real_logic_sbe_benchmarks_fix csharp/sbe-tests/*.sbe csharp/nuget/ +csharp/csharp.sln.DotSettings.user # rust rust/target diff --git a/build.gradle b/build.gradle index 3838d1a1ce..3d08ca9f4a 100644 --- a/build.gradle +++ b/build.gradle @@ -229,6 +229,9 @@ subprojects { } javaLauncher.set(toolchainLauncher) + + systemProperty 'sbe.enable.ir.precedence.checks', 'true' + systemProperty 'sbe.enable.test.precedence.checks', 'true' } } @@ -279,9 +282,12 @@ project(':sbe-tool') { 'sbe.output.dir': generatedDir, 'sbe.target.language': 'Java', 'sbe.validation.stop.on.error': 'true', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.validation.xsd': validationXsdPath, + 'sbe.generate.precedence.checks': 'true', + 'sbe.java.precedence.checks.property.name': 'sbe.enable.test.precedence.checks') args = ['src/test/resources/json-printer-test-schema.xml', - 'src/test/resources/composite-elements-schema.xml'] + 'src/test/resources/composite-elements-schema.xml', + 'src/test/resources/field-order-check-schema.xml'] } jar { @@ -541,7 +547,8 @@ project(':sbe-benchmarks') { 'sbe.validation.stop.on.error': 'true', 'sbe.validation.xsd': validationXsdPath, 'sbe.java.encoding.buffer.type': 'org.agrona.concurrent.UnsafeBuffer', - 'sbe.java.decoding.buffer.type': 'org.agrona.concurrent.UnsafeBuffer') + 'sbe.java.decoding.buffer.type': 'org.agrona.concurrent.UnsafeBuffer', + 'sbe.generate.precedence.checks': 'false') args = ['src/main/resources/car.xml', 'src/main/resources/fix-message-samples.xml'] } @@ -730,13 +737,15 @@ tasks.register('generateCSharpCodecsTests', JavaExec) { 'sbe.output.dir': 'csharp/sbe-generated', 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharp', 'sbe.xinclude.aware': 'true', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.validation.xsd': validationXsdPath, + 'sbe.generate.precedence.checks': 'true') args = ['sbe-tool/src/test/resources/FixBinary.xml', 'sbe-tool/src/test/resources/issue435.xml', 'sbe-tool/src/test/resources/issue483.xml', 'sbe-tool/src/test/resources/issue560.xml', 'sbe-tool/src/test/resources/since-deprecated-test-schema.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', + 'sbe-tool/src/test/resources/field-order-check-schema.xml', 'sbe-benchmarks/src/main/resources/fix-message-samples.xml'] } @@ -753,7 +762,10 @@ tasks.register('generateJavaIrCodecs', JavaExec) { systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/java', 'sbe.target.language': 'Java', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.validation.xsd': validationXsdPath, + 'sbe.generate.precedence.checks': 'true', + 'sbe.precedence.checks.flag.name': 'SBE_ENABLE_IR_PRECEDENCE_CHECKS', + 'sbe.java.precedence.checks.property.name': 'sbe.enable.ir.precedence.checks') args = ['sbe-tool/src/main/resources/sbe-ir.xml'] } @@ -763,7 +775,9 @@ tasks.register('generateCppIrCodecs', JavaExec) { systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/cpp', 'sbe.target.language': 'cpp', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.validation.xsd': validationXsdPath, + 'sbe.generate.precedence.checks': 'true', + 'sbe.precedence.checks.flag.name': 'SBE_ENABLE_IR_PRECEDENCE_CHECKS') args = ['sbe-tool/src/main/resources/sbe-ir.xml'] } diff --git a/csharp/sbe-generated/sbe-generated.csproj b/csharp/sbe-generated/sbe-generated.csproj index 6b4fc7bdbc..806168d7d5 100644 --- a/csharp/sbe-generated/sbe-generated.csproj +++ b/csharp/sbe-generated/sbe-generated.csproj @@ -7,6 +7,14 @@ Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. + + TRACE,SBE_ENABLE_PRECEDENCE_CHECKS + + + + TRACE,SBE_ENABLE_PRECEDENCE_CHECKS + + diff --git a/csharp/sbe-tests/FieldAccessOrderCheckTests.cs b/csharp/sbe-tests/FieldAccessOrderCheckTests.cs new file mode 100644 index 0000000000..d0b7e16992 --- /dev/null +++ b/csharp/sbe-tests/FieldAccessOrderCheckTests.cs @@ -0,0 +1,3185 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Text; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Order.Check; +using Org.SbeTool.Sbe.Dll; + +namespace Org.SbeTool.Sbe.Tests +{ + [TestClass] + public class FieldAccessOrderCheckTests + { + private const int Offset = 0; + private readonly DirectBuffer _buffer = new DirectBuffer(); + private readonly MessageHeader _messageHeader = new MessageHeader(); + + [TestInitialize] + public void SetUp() + { + var byteArray = new byte[128]; + new Random().NextBytes(byteArray); + _buffer.Wrap(byteArray); + } + + [TestMethod] + public void AllowsEncodingAndDecodingVariableLengthFieldsInSchemaDefinedOrder() + { + var encoder = new MultipleVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.SetB("abc"); + encoder.SetC("def"); + encoder.CheckEncodingIsComplete(); + + var decoder = new MultipleVarLength(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + Assert.AreEqual("abc", decoder.GetB()); + Assert.AreEqual("def", decoder.GetC()); + Assert.IsTrue(decoder.ToString().Contains("A=42|B='abc'|C='def'")); + } + + [TestMethod] + public void AllowsReEncodingTopLevelPrimitiveFields() + { + var encoder = new MultipleVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.SetB("abc"); + encoder.SetC("def"); + encoder.A = 43; + encoder.CheckEncodingIsComplete(); + + var decoder = new MultipleVarLength(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(43, decoder.A); + Assert.AreEqual("abc", decoder.GetB()); + Assert.AreEqual("def", decoder.GetC()); + } + + [TestMethod] + public void DisallowsSkippingEncodingOfVariableLengthField1() + { + var encoder = new MultipleVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var exception = Assert.ThrowsException(() => encoder.SetC("def")); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"c\" in state: V0_BLOCK")); + } + + [TestMethod] + public void DisallowsSkippingEncodingOfVariableLengthField2() + { + var encoder = new MultipleVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var def = Encoding.ASCII.GetBytes("def"); + var exception = Assert.ThrowsException(() => encoder.SetC(def)); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"c\" in state: V0_BLOCK")); + } + + [TestMethod] + public void DisallowsReEncodingEarlierVariableLengthFields() + { + var encoder = new MultipleVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.SetB("abc"); + encoder.SetC("def"); + var exception = Assert.ThrowsException(() => encoder.SetB("ghi")); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b\" in state: V0_C_DONE")); + } + + [TestMethod] + public void DisallowsReEncodingLatestVariableLengthField() + { + var encoder = new MultipleVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.SetB("abc"); + encoder.SetC("def"); + var exception = Assert.ThrowsException(() => encoder.SetC("ghi")); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"c\" in state: V0_C_DONE")); + } + + [TestMethod] + public void DisallowsSkippingDecodingOfVariableLengthField1() + { + var decoder = DecodeUntilVarLengthFields(); + + var exception = Assert.ThrowsException(() => decoder.GetC()); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"c\" in state: V0_BLOCK")); + } + + [TestMethod] + public void DisallowsSkippingDecodingOfVariableLengthField2() + { + var decoder = DecodeUntilVarLengthFields(); + + var exception = Assert.ThrowsException(() => decoder.GetCBytes()); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"c\" in state: V0_BLOCK")); + } + + [TestMethod] + public void DisallowsSkippingDecodingOfVariableLengthField3() + { + var decoder = DecodeUntilVarLengthFields(); + + var exception = Assert.ThrowsException(() => decoder.GetC(new byte[8])); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"c\" in state: V0_BLOCK")); + } + + [TestMethod] + public void AllowsRepeatedDecodingOfVariableLengthDataLength() + { + var decoder = DecodeUntilVarLengthFields(); + Assert.AreEqual(3, decoder.BLength()); + Assert.AreEqual(3, decoder.BLength()); + Assert.AreEqual(3, decoder.BLength()); + Assert.AreEqual("abc", decoder.GetB()); + Assert.AreEqual(3, decoder.CLength()); + Assert.AreEqual(3, decoder.CLength()); + Assert.AreEqual(3, decoder.CLength()); + } + + [TestMethod] + public void DisallowsReDecodingEarlierVariableLengthField() + { + var decoder = DecodeUntilVarLengthFields(); + Assert.AreEqual("abc", decoder.GetB()); + Assert.AreEqual("def", decoder.GetC()); + + var exception = Assert.ThrowsException(() => decoder.GetB()); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b\" in state: V0_C_DONE")); + } + + [TestMethod] + public void DisallowsReDecodingLatestVariableLengthField() + { + var decoder = DecodeUntilVarLengthFields(); + Assert.AreEqual("abc", decoder.GetB()); + Assert.AreEqual("def", decoder.GetC()); + + var exception = Assert.ThrowsException(() => decoder.GetC()); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"c\" in state: V0_C_DONE")); + } + + private MultipleVarLength DecodeUntilVarLengthFields() + { + var encoder = new MultipleVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.SetB("abc"); + encoder.SetC("def"); + encoder.CheckEncodingIsComplete(); + + var decoder = new MultipleVarLength(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + + return decoder; + } + + [TestMethod] + public void AllowsEncodingAndDecodingGroupAndVariableLengthFieldsInSchemaDefinedOrder() + { + var encoder = new GroupAndVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2); + bEncoder.Next().C = 1; + bEncoder.Next().C = 2; + encoder.SetD("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new GroupAndVarLength(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(2, bDecoder.Count); + Assert.AreEqual(1, bDecoder.Next().C); + Assert.AreEqual(2, bDecoder.Next().C); + Assert.AreEqual("abc", decoder.GetD()); + Assert.IsTrue(decoder.ToString().Contains("A=42|B=[(C=1),(C=2)]|D='abc'")); + } + + [TestMethod] + public void AllowsEncodingAndDecodingEmptyGroupAndVariableLengthFieldsInSchemaDefinedOrder() + { + var encoder = new GroupAndVarLength() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.BCount(0); + encoder.SetD("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new GroupAndVarLength() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bs = decoder.B; + Assert.AreEqual(0, bs.Count); + Assert.AreEqual("abc", decoder.GetD()); + Assert.IsTrue(decoder.ToString().Contains("A=42|B=[]|D='abc'")); + } + + [TestMethod] + public void AllowsEncoderToResetZeroGroupLengthToZero() + { + var encoder = new GroupAndVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.BCount(0).ResetCountToIndex(); + encoder.SetD("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new GroupAndVarLength(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(0, bDecoder.Count); + Assert.AreEqual("abc", decoder.GetD()); + Assert.IsTrue(decoder.ToString().Contains("A=42|B=[]|D='abc'")); + } + + [TestMethod] + public void AllowsEncoderToResetNonZeroGroupLengthToZeroBeforeCallingNext() + { + var encoder = new GroupAndVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.BCount(2).ResetCountToIndex(); + encoder.SetD("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new GroupAndVarLength(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(0, bDecoder.Count); + Assert.AreEqual("abc", decoder.GetD()); + Assert.IsTrue(decoder.ToString().Contains("A=42|B=[]|D='abc'")); + } + + [TestMethod] + public void AllowsEncoderToResetNonZeroGroupLengthToNonZero() + { + var encoder = new GroupAndVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2); + bEncoder.Next().C = 43; + bEncoder.ResetCountToIndex(); + encoder.SetD("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new GroupAndVarLength(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(43, bDecoder.Next().C); + Assert.AreEqual("abc", decoder.GetD()); + Assert.IsTrue(decoder.ToString().Contains("A=42|B=[(C=43)]|D='abc'")); + } + + [TestMethod] + public void DisallowsEncoderToResetGroupLengthMidGroupElement() + { + var encoder = new NestedGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2).Next(); + bEncoder.C = 43; + var exception = Assert.ThrowsException(() => bEncoder.ResetCountToIndex()); + Assert.IsTrue(exception.Message.Contains( + "Cannot reset count of repeating group \"b\" in state: V0_B_N_BLOCK")); + } + + [TestMethod] + public void DisallowsEncodingGroupElementBeforeCallingNext() + { + var encoder = new GroupAndVarLength() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(1); + var exception = Assert.ThrowsException(() => bEncoder.C = 1); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsDecodingGroupElementBeforeCallingNext() + { + var encoder = new GroupAndVarLength() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2); + bEncoder + .Next() + .C = 1; + bEncoder.Next() + .C = 2; + encoder.SetD("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new GroupAndVarLength() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bs = decoder.B; + Assert.AreEqual(2, bs.Count); + var exception = Assert.ThrowsException(() => _ = bs.C); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsSkippingEncodingOfGroup() + { + var encoder = new GroupAndVarLength() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var exception = Assert.ThrowsException(() => encoder.SetD("abc")); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"d\" in state: V0_BLOCK")); + } + + [TestMethod] + public void DisallowsReEncodingVariableLengthFieldAfterGroup() + { + var encoder = new GroupAndVarLength() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2); + bEncoder + .Next() + .C = 1; + bEncoder.Next() + .C = 2; + encoder.SetD("abc"); + var exception = Assert.ThrowsException(() => encoder.SetD("def")); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"d\" in state: V0_D_DONE")); + } + + [TestMethod] + public void DisallowsReEncodingGroupCount() + { + var encoder = new GroupAndVarLength() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2); + bEncoder + .Next() + .C = 1; + bEncoder.Next() + .C = 2; + encoder.SetD("abc"); + var exception = Assert.ThrowsException(() => encoder.BCount(1)); + Assert.IsTrue( + exception.Message.Contains("Cannot encode count of repeating group \"b\" in state: V0_D_DONE")); + } + + [TestMethod] + public void DisallowsMissedDecodingOfGroupBeforeVariableLengthField() + { + var encoder = new GroupAndVarLength() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2); + bEncoder + .Next() + .C = 1; + bEncoder + .Next() + .C = 2; + encoder.SetD("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new GroupAndVarLength() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var exception = Assert.ThrowsException(() => decoder.GetD()); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"d\" in state: V0_BLOCK")); + } + + [TestMethod] + public void DisallowsReDecodingVariableLengthFieldAfterGroup() + { + var encoder = new GroupAndVarLength() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2); + bEncoder + .Next() + .C = 1; + bEncoder + .Next() + .C = 2; + encoder.SetD("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new GroupAndVarLength() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bs = decoder.B; + Assert.AreEqual(2, bs.Count); + Assert.AreEqual(1, bs.Next().C); + Assert.AreEqual(2, bs.Next().C); + Assert.AreEqual("abc", decoder.GetD()); + var exception = Assert.ThrowsException(() => decoder.GetD()); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"d\" in state: V0_D_DONE")); + } + + [TestMethod] + public void DisallowsReDecodingGroupAfterVariableLengthField() + { + var encoder = new GroupAndVarLength() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2); + bEncoder + .Next() + .C = 1; + bEncoder + .Next() + .C = 2; + encoder.SetD("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new GroupAndVarLength() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bs = decoder.B; + Assert.AreEqual(2, bs.Count); + Assert.AreEqual(1, bs.Next().C); + Assert.AreEqual(2, bs.Next().C); + Assert.AreEqual("abc", decoder.GetD()); + var exception = Assert.ThrowsException(() => decoder.B); + Assert.IsTrue( + exception.Message.Contains("Cannot decode count of repeating group \"b\" in state: V0_D_DONE")); + } + + [TestMethod] + public void AllowsEncodingAndDecodingVariableLengthFieldInsideGroupInSchemaDefinedOrder() + { + var encoder = new VarLengthInsideGroup() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2); + bEncoder + .Next() + .C = 1; + bEncoder + .SetD("abc"); + bEncoder + .Next() + .C = 2; + bEncoder + .SetD("def"); + encoder.SetE("ghi"); + encoder.CheckEncodingIsComplete(); + + var decoder = new VarLengthInsideGroup() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bs = decoder.B; + Assert.AreEqual(2, bs.Count); + Assert.AreEqual(1, bs.Next().C); + Assert.AreEqual("abc", bs.GetD()); + Assert.AreEqual(2, bs.Next().C); + Assert.AreEqual("def", bs.GetD()); + Assert.AreEqual("ghi", decoder.GetE()); + Assert.IsTrue(decoder.ToString().Contains("A=42|B=[(C=1|D='abc'),(C=2|D='def')]|E='ghi'")); + } + + [TestMethod] + public void DisallowsMissedGroupElementVariableLengthFieldToEncodeAtTopLevel() + { + var encoder = new VarLengthInsideGroup() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.BCount(1).Next().C = 1; + var exception = Assert.ThrowsException(() => encoder.SetE("abc")); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"e\" in state: V0_B_1_BLOCK")); + } + + [TestMethod] + public void DisallowsMissedGroupElementVariableLengthFieldToEncodeNextElement() + { + var encoder = new VarLengthInsideGroup() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2).Next(); + var exception = Assert.ThrowsException(() => bEncoder.Next()); + Assert.IsTrue( + exception.Message.Contains( + "Cannot access next element in repeating group \"b\" in state: V0_B_N_BLOCK")); + } + + [TestMethod] + public void DisallowsMissedGroupElementEncoding() + { + var encoder = new VarLengthInsideGroup() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2); + bEncoder.Next().C = 1; + bEncoder.SetD("abc"); + var exception = Assert.ThrowsException(() => encoder.SetE("abc")); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"e\" in state: V0_B_N_D_DONE")); + } + + [TestMethod] + public void DisallowsReEncodingGroupElementVariableLengthField() + { + var encoder = new VarLengthInsideGroup() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(1).Next(); + bEncoder.C = 1; + bEncoder.SetD("abc"); + encoder.SetE("def"); + var exception = Assert.ThrowsException(() => bEncoder.SetD("ghi")); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.d\" in state: V0_E_DONE")); + } + + [TestMethod] + public void DisallowsReDecodingGroupElementVariableLengthField() + { + var encoder = new VarLengthInsideGroup() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2).Next(); + bEncoder.C = 1; + bEncoder.SetD("abc"); + bEncoder.Next().C = 2; + bEncoder.SetD("def"); + encoder.SetE("ghi"); + encoder.CheckEncodingIsComplete(); + + var decoder = new VarLengthInsideGroup() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(2, bDecoder.Count); + Assert.AreEqual(1, bDecoder.Next().C); + Assert.AreEqual("abc", bDecoder.GetD()); + var exception = Assert.ThrowsException(() => bDecoder.GetD()); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.d\" in state: V0_B_N_D_DONE")); + } + + [TestMethod] + public void DisallowsMissedDecodingOfGroupElementVariableLengthFieldToNextElement() + { + var encoder = new VarLengthInsideGroup() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2).Next(); + bEncoder.C = 1; + bEncoder.SetD("abc"); + bEncoder.Next().C = 2; + bEncoder.SetD("def"); + encoder.SetE("ghi"); + encoder.CheckEncodingIsComplete(); + + var decoder = new VarLengthInsideGroup() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(2, bDecoder.Count); + Assert.AreEqual(1, bDecoder.Next().C); + var exception = Assert.ThrowsException(() => bDecoder.Next()); + Assert.IsTrue( + exception.Message.Contains( + "Cannot access next element in repeating group \"b\" in state: V0_B_N_BLOCK")); + } + + [TestMethod] + public void DisallowsMissedDecodingOfGroupElementVariableLengthFieldToTopLevel() + { + var encoder = new VarLengthInsideGroup() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(1).Next(); + bEncoder.C = 1; + bEncoder.SetD("abc"); + encoder.SetE("ghi"); + encoder.CheckEncodingIsComplete(); + + var decoder = new VarLengthInsideGroup() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(1, bDecoder.Next().C); + var exception = Assert.ThrowsException(() => decoder.GetE()); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"e\" in state: V0_B_1_BLOCK")); + } + + [TestMethod] + public void DisallowsMissedDecodingOfGroupElement() + { + var encoder = new VarLengthInsideGroup() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2).Next(); + bEncoder.C = 1; + bEncoder.SetD("abc"); + bEncoder.Next().C = 2; + bEncoder.SetD("def"); + encoder.SetE("ghi"); + encoder.CheckEncodingIsComplete(); + + var decoder = new VarLengthInsideGroup() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(2, bDecoder.Count); + Assert.AreEqual(1, bDecoder.Next().C); + var exception = Assert.ThrowsException(() => decoder.GetE()); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"e\" in state: V0_B_N_BLOCK")); + } + + [TestMethod] + public void AllowsEncodingNestedGroupsInSchemaDefinedOrder() + { + var encoder = new NestedGroups().WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(2).Next(); + bEncoder.C = 1; + var dEncoder = bEncoder.DCount(2).Next(); + dEncoder.E = 2; + dEncoder = dEncoder.Next(); + dEncoder.E = 3; + var fEncoder = bEncoder.FCount(1).Next(); + fEncoder.G = 4; + bEncoder = bEncoder.Next(); + bEncoder.C = 5; + dEncoder = bEncoder.DCount(1).Next(); + dEncoder.E = 6; + fEncoder = bEncoder.FCount(1).Next(); + fEncoder.G = 7; + var hEncoder = encoder.HCount(1).Next(); + hEncoder.I = 8; + encoder.CheckEncodingIsComplete(); + + var decoder = new NestedGroups().WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(2, bDecoder.Count); + var b0 = bDecoder.Next(); + Assert.AreEqual(1, b0.C); + var b0ds = b0.D; + Assert.AreEqual(2, b0ds.Count); + Assert.AreEqual(2, b0ds.Next().E); + Assert.AreEqual(3, b0ds.Next().E); + var b0Fs = b0.F; + Assert.AreEqual(1, b0Fs.Count); + Assert.AreEqual(4, b0Fs.Next().G); + var b1 = bDecoder.Next(); + Assert.AreEqual(5, b1.C); + var b1ds = b1.D; + Assert.AreEqual(1, b1ds.Count); + Assert.AreEqual(6, b1ds.Next().E); + var b1Fs = b1.F; + Assert.AreEqual(1, b1Fs.Count); + Assert.AreEqual(7, b1Fs.Next().G); + var hs = decoder.H; + Assert.AreEqual(1, hs.Count); + Assert.AreEqual(8, hs.Next().I); + Assert.IsTrue(decoder.ToString() + .Contains("A=42|B=[(C=1|D=[(E=2),(E=3)]|F=[(G=4)]),(C=5|D=[(E=6)]|F=[(G=7)])]|H=[(I=8)]")); + } + + [TestMethod] + public void AllowsEncodingEmptyNestedGroupsInSchemaDefinedOrder() + { + var encoder = new NestedGroups().WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.BCount(0); + encoder.HCount(0); + encoder.CheckEncodingIsComplete(); + + var decoder = new NestedGroups().WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(0, bDecoder.Count); + var hDecoder = decoder.H; + Assert.AreEqual(0, hDecoder.Count); + Assert.IsTrue(decoder.ToString().Contains("A=42|B=[]|H=[]")); + } + + [TestMethod] + public void DisallowsMissedEncodingOfNestedGroup() + { + var encoder = new NestedGroups().WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(1).Next(); + bEncoder.C = 1; + Exception exception = Assert.ThrowsException(() => bEncoder.FCount(1)); + Assert.IsTrue( + exception.Message.Contains("Cannot encode count of repeating group \"b.f\" in state: V0_B_1_BLOCK")); + } + + [TestMethod] + public void AllowsEncodingAndDecodingCompositeInsideGroupInSchemaDefinedOrder() + { + var encoder = new CompositeInsideGroup().WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + var aEncoder = encoder.A; + aEncoder.X = 1; + aEncoder.Y = 2; + var bEncoder = encoder.BCount(1).Next(); + var cEncoder = bEncoder.C; + cEncoder.X = 3; + cEncoder.Y = 4; + encoder.CheckEncodingIsComplete(); + + var decoder = new CompositeInsideGroup().WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + var aDecoder = decoder.A; + Assert.AreEqual(1, aDecoder.X); + Assert.AreEqual(2, aDecoder.Y); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + var cDecoder = bDecoder.Next().C; + Assert.AreEqual(3, cDecoder.X); + Assert.AreEqual(4, cDecoder.Y); + Assert.IsTrue(decoder.ToString().Contains("A=(X=1|Y=2)|B=[(C=(X=3|Y=4))]")); + } + + [TestMethod] + public void DisallowsEncodingCompositeInsideGroupBeforeCallingNext() + { + var encoder = new CompositeInsideGroup().WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + var aEncoder = encoder.A; + aEncoder.X = 1; + aEncoder.Y = 2; + var bEncoder = encoder.BCount(1); + Exception exception = Assert.ThrowsException(() => bEncoder.C); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void AllowsReEncodingTopLevelCompositeViaReWrap() + { + var encoder = new CompositeInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + var aEncoder = encoder.A; + aEncoder.X = 1; + aEncoder.Y = 2; + var bEncoder = encoder.BCount(1).Next(); + bEncoder.C.X = 3; + bEncoder.C.Y = 4; + aEncoder = encoder.A; + aEncoder.X = 5; + aEncoder.Y = 6; + encoder.CheckEncodingIsComplete(); + + var decoder = new CompositeInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + var a = decoder.A; + Assert.AreEqual(5, a.X); + Assert.AreEqual(6, a.Y); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + var c = b.Next().C; + Assert.AreEqual(3, c.X); + Assert.AreEqual(4, c.Y); + } + + [TestMethod] + public void AllowsReEncodingTopLevelCompositeViaEncoderReference() + { + var encoder = new CompositeInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + var aEncoder = encoder.A; + aEncoder.X = 1; + aEncoder.Y = 2; + var bEncoder = encoder.BCount(1).Next(); + bEncoder.C.X = 3; + bEncoder.C.Y = 4; + aEncoder.X = 5; + aEncoder.Y = 6; + encoder.CheckEncodingIsComplete(); + + var decoder = new CompositeInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + var a = decoder.A; + Assert.AreEqual(5, a.X); + Assert.AreEqual(6, a.Y); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + var c = b.Next().C; + Assert.AreEqual(3, c.X); + Assert.AreEqual(4, c.Y); + } + + [TestMethod] + public void AllowsReEncodingGroupElementCompositeViaReWrap() + { + var encoder = new CompositeInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + var aEncoder = encoder.A; + aEncoder.X = 1; + aEncoder.Y = 2; + var bEncoder = encoder.BCount(1).Next(); + var cEncoder = bEncoder.C; + cEncoder.X = 3; + cEncoder.Y = 4; + cEncoder = bEncoder.C; + cEncoder.X = 5; + cEncoder.Y = 6; + encoder.CheckEncodingIsComplete(); + + var decoder = new CompositeInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + var a = decoder.A; + Assert.AreEqual(1, a.X); + Assert.AreEqual(2, a.Y); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + var c = b.Next().C; + Assert.AreEqual(5, c.X); + Assert.AreEqual(6, c.Y); + } + + [TestMethod] + public void AllowsReEncodingGroupElementCompositeViaEncoderReference() + { + var encoder = new CompositeInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + var aEncoder = encoder.A; + aEncoder.X = 1; + aEncoder.Y = 2; + var bEncoder = encoder.BCount(1).Next(); + var cEncoder = bEncoder.C; + cEncoder.X = 3; + cEncoder.Y = 4; + cEncoder.X = 5; + cEncoder.Y = 6; + encoder.CheckEncodingIsComplete(); + + var decoder = new CompositeInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + var a = decoder.A; + Assert.AreEqual(1, a.X); + Assert.AreEqual(2, a.Y); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + var c = b.Next().C; + Assert.AreEqual(5, c.X); + Assert.AreEqual(6, c.Y); + } + + [TestMethod] + public void AllowsReDecodingTopLevelCompositeViaReWrap() + { + var encoder = new CompositeInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + var aEncoder = encoder.A; + aEncoder.X = 1; + aEncoder.Y = 2; + var bEncoder = encoder.BCount(1).Next(); + var cEncoder = bEncoder.C; + cEncoder.X = 3; + cEncoder.Y = 4; + encoder.CheckEncodingIsComplete(); + + var decoder = new CompositeInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + var a1 = decoder.A; + Assert.AreEqual(1, a1.X); + Assert.AreEqual(2, a1.Y); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + var c = b.Next().C; + Assert.AreEqual(3, c.X); + Assert.AreEqual(4, c.Y); + var a2 = decoder.A; + Assert.AreEqual(1, a2.X); + Assert.AreEqual(2, a2.Y); + } + + [TestMethod] + public void AllowsReDecodingTopLevelCompositeViaEncoderReference() + { + var encoder = new CompositeInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + var aEncoder = encoder.A; + aEncoder.X = 1; + aEncoder.Y = 2; + var bEncoder = encoder.BCount(1).Next(); + var cEncoder = bEncoder.C; + cEncoder.X = 3; + cEncoder.Y = 4; + encoder.CheckEncodingIsComplete(); + + var decoder = new CompositeInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + var a = decoder.A; + Assert.AreEqual(1, a.X); + Assert.AreEqual(2, a.Y); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + var c = b.Next().C; + Assert.AreEqual(3, c.X); + Assert.AreEqual(4, c.Y); + Assert.AreEqual(1, a.X); + Assert.AreEqual(2, a.Y); + } + + [TestMethod] + public void AllowsReDecodingGroupElementCompositeViaEncoderReference() + { + var encoder = new CompositeInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + var aEncoder = encoder.A; + aEncoder.X = 1; + aEncoder.Y = 2; + var bEncoder = encoder.BCount(1).Next(); + var cEncoder = bEncoder.C; + cEncoder.X = 3; + cEncoder.Y = 4; + encoder.CheckEncodingIsComplete(); + + var decoder = new CompositeInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + var a = decoder.A; + Assert.AreEqual(1, a.X); + Assert.AreEqual(2, a.Y); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + var c = b.Next().C; + Assert.AreEqual(3, c.X); + Assert.AreEqual(4, c.Y); + Assert.AreEqual(3, c.X); + Assert.AreEqual(4, c.Y); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedPrimitiveField() + { + var encoder = new AddPrimitiveV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.B = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddPrimitiveV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(2, decoder.B); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingPrimitiveFieldAsNullValue() + { + var encoder = new AddPrimitiveV0() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddPrimitiveV1() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(AddPrimitiveV1.BNullValue, decoder.B); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedPrimitiveFieldBeforeGroup() + { + var encoder = new AddPrimitiveBeforeGroupV1() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.D = 3; + encoder.BCount(1).Next().C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddPrimitiveBeforeGroupV1() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(3, decoder.D); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + Assert.AreEqual(2, b.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingPrimitiveFieldBeforeGroupAsNullValue() + { + var encoder = new AddPrimitiveBeforeGroupV0() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.BCount(1).Next().C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddPrimitiveBeforeGroupV1() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(AddPrimitiveBeforeGroupV1.DNullValue, decoder.D); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + Assert.AreEqual(2, b.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToSkipPresentButAddedPrimitiveFieldBeforeGroup() + { + var encoder = new AddPrimitiveBeforeGroupV1() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.D = 3; + encoder.BCount(1).Next().C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddPrimitiveBeforeGroupV1() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + Assert.AreEqual(2, b.Next().C); + } + + [TestMethod] + public void AllowsOldDecoderToSkipAddedPrimitiveFieldBeforeGroup() + { + var encoder = new AddPrimitiveBeforeGroupV1() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.D = 3; + encoder.BCount(1).Next().C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion1(); + + var decoder = new AddPrimitiveBeforeGroupV0() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + Assert.AreEqual(2, b.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedPrimitiveFieldBeforeVarData() + { + var encoder = new AddPrimitiveBeforeVarDataV1() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.C = 3; + encoder.SetB("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new AddPrimitiveBeforeVarDataV1() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(3, decoder.C); + Assert.AreEqual("abc", decoder.GetB()); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingPrimitiveFieldBeforeVarDataAsNullValue() + { + var encoder = new AddPrimitiveBeforeVarDataV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.SetB("abc"); + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddPrimitiveBeforeVarDataV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(AddPrimitiveBeforeVarDataV1.CNullValue, decoder.C); + Assert.AreEqual("abc", decoder.GetB()); + } + + [TestMethod] + public void AllowsNewDecoderToSkipPresentButAddedPrimitiveFieldBeforeVarData() + { + var encoder = new AddPrimitiveBeforeVarDataV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.C = 3; + encoder.SetB("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new AddPrimitiveBeforeVarDataV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual("abc", decoder.GetB()); + } + + [TestMethod] + public void AllowsOldDecoderToSkipAddedPrimitiveFieldBeforeVarData() + { + var encoder = new AddPrimitiveBeforeVarDataV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.C = 3; + encoder.SetB("abc"); + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion1(); + + var decoder = new AddPrimitiveBeforeVarDataV0(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual("abc", decoder.GetB()); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedPrimitiveFieldInsideGroup() + { + var encoder = new AddPrimitiveInsideGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var group1 = encoder.BCount(1); + group1.Next(); + group1.C = 2; + group1.D = 3; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddPrimitiveInsideGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var group2 = decoder.B; + Assert.AreEqual(1, group2.Count); + Assert.AreEqual(2, group2.Next().C); + Assert.AreEqual(3, group2.D); + } + + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingPrimitiveFieldInsideGroupAsNullValue() + { + var encoder = new AddPrimitiveInsideGroupV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.BCount(1).Next().C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddPrimitiveInsideGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + Assert.AreEqual(2, b.Next().C); + Assert.AreEqual(AddPrimitiveInsideGroupV1.BGroup.DNullValue, b.D); + } + + [TestMethod] + public void AllowsNewDecoderToSkipPresentButAddedPrimitiveFieldInsideGroup() + { + var encoder = new AddPrimitiveInsideGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var group = encoder.BCount(2); + group.Next().C = 2; + group.D = 3; + group.Next().C = 4; + group.D = 5; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddPrimitiveInsideGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var b = decoder.B; + Assert.AreEqual(2, b.Count); + Assert.AreEqual(2, b.Next().C); + Assert.AreEqual(4, b.Next().C); + } + + [TestMethod] + public void AllowsOldDecoderToSkipAddedPrimitiveFieldInsideGroup() + { + var encoder = new AddPrimitiveInsideGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var group = encoder.BCount(2); + group.Next().C = 2; + group.D = 3; + group.Next().C = 4; + group.D = 5; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion1(); + + var decoder = new AddPrimitiveInsideGroupV0(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var b = decoder.B; + Assert.AreEqual(2, b.Count); + Assert.AreEqual(2, b.Next().C); + Assert.AreEqual(4, b.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedGroupBeforeVarData() + { + var encoder = new AddGroupBeforeVarDataV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var groupEncoder = encoder.CCount(1); + groupEncoder.Next().D = 2; + encoder.SetB("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new AddGroupBeforeVarDataV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var groupDecoder = decoder.C; + Assert.AreEqual(1, groupDecoder.Count); + Assert.AreEqual(2, groupDecoder.Next().D); + Assert.AreEqual("abc", decoder.GetB()); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingGroupBeforeVarDataAsNullValue() + { + var encoder = new AddGroupBeforeVarDataV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.SetB("abc"); + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddGroupBeforeVarDataV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var groupDecoder = decoder.C; + Assert.AreEqual(0, groupDecoder.Count); + Assert.AreEqual("abc", decoder.GetB()); + Assert.IsTrue(decoder.ToString().Contains("A=1|C=[]|B='abc'")); + } + + [TestMethod] + public void AllowsNewDecoderToSkipMissingGroupBeforeVarData() + { + var encoder = new AddGroupBeforeVarDataV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.SetB("abc"); + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddGroupBeforeVarDataV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual("abc", decoder.GetB()); + } + + [TestMethod] + public void DisallowsNewDecoderToSkipPresentButAddedGroupBeforeVarData() + { + var encoder = new AddGroupBeforeVarDataV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var groupEncoder = encoder.CCount(1); + groupEncoder.Next().D = 2; + encoder.SetB("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new AddGroupBeforeVarDataV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + + var exception = Assert.ThrowsException(() => decoder.GetB()); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b\" in state: V1_BLOCK")); + } + + [TestMethod] + public void AllowsOldDecoderToSkipAddedGroupBeforeVarData() + { + var encoder = new AddGroupBeforeVarDataV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + _messageHeader.NumGroups = 1; + encoder.A = 1; + var groupEncoder = encoder.CCount(1); + groupEncoder.Next().D = 2; + encoder.SetB("abc"); + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion1(); + + var decoder = new AddGroupBeforeVarDataV0(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + + for (int i = 0; i < _messageHeader.NumGroups; i++) + { + SkipGroup(decoder); + } + + Assert.AreEqual("abc", decoder.GetB()); + } + + private void SkipGroup(AddGroupBeforeVarDataV0 decoder) + { + var groupSizeEncoding = new GroupSizeEncoding(); + groupSizeEncoding.Wrap(_buffer, decoder.Limit, MessageHeader.SbeSchemaVersion); + var bytesToSkip = GroupSizeEncoding.Size + + groupSizeEncoding.BlockLength * groupSizeEncoding.NumInGroup; + decoder.Limit += bytesToSkip; + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedEnumFieldBeforeGroup() + { + var encoder = new AddEnumBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.D = Direction.BUY; + var groupEncoder = encoder.BCount(1); + groupEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddEnumBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(Direction.BUY, decoder.D); + var groupDecoder = decoder.B; + Assert.AreEqual(1, groupDecoder.Count); + Assert.AreEqual(2, groupDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingEnumFieldBeforeGroupAsNullValue() + { + var encoder = new AddEnumBeforeGroupV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var myGroup = encoder.BCount(1); + myGroup.Next(); + myGroup.C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddEnumBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(Direction.NULL_VALUE, decoder.D); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + Assert.AreEqual(2, b.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToSkipPresentButAddedEnumFieldBeforeGroup() + { + var encoder = new AddEnumBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.D = Direction.SELL; + encoder.BCount(1).Next().C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddEnumBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + Assert.AreEqual(2, b.Next().C); + } + + [TestMethod] + public void AllowsOldDecoderToSkipAddedEnumFieldBeforeGroup() + { + var encoder = new AddEnumBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.D = Direction.BUY; + encoder.BCount(1).Next().C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion1(); + + var decoder = new AddEnumBeforeGroupV0(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var b = decoder.B; + Assert.AreEqual(1, b.Count); + Assert.AreEqual(2, b.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedCompositeFieldBeforeGroup() + { + var encoder = new AddCompositeBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var dEncoder = encoder.D; + dEncoder.X = -1; + dEncoder.Y = -2; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddCompositeBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var d = decoder.D; + Assert.IsNotNull(d); + Assert.AreEqual(-1, d.X); + Assert.AreEqual(-2, d.Y); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingCompositeFieldBeforeGroupAsNullValue() + { + var encoder = new AddCompositeBeforeGroupV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddCompositeBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.IsNull(decoder.D); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToSkipPresentButAddedCompositeFieldBeforeGroup() + { + var encoder = new AddCompositeBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var dEncoder = encoder.D; + dEncoder.X = -1; + dEncoder.Y = -2; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddCompositeBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsOldDecoderToSkipAddedCompositeFieldBeforeGroup() + { + var encoder = new AddCompositeBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var dEncoder = encoder.D; + dEncoder.X = -1; + dEncoder.Y = -2; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion1(); + + var decoder = new AddCompositeBeforeGroupV0(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedArrayFieldBeforeGroup1() + { + var encoder = new AddArrayBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var dEncoder = encoder.DAsSpan(); + dEncoder[0] = 1; + dEncoder[1] = 2; + dEncoder[2] = 3; + dEncoder[3] = 4; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddArrayBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual((short)1, decoder.GetD(0)); + Assert.AreEqual((short)2, decoder.GetD(1)); + Assert.AreEqual((short)3, decoder.GetD(2)); + Assert.AreEqual((short)4, decoder.GetD(3)); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedArrayFieldBeforeGroup2() + { + var encoder = new AddArrayBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.SetD(0, 1); + encoder.SetD(1, 2); + encoder.SetD(2, 3); + encoder.SetD(3, 4); + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddArrayBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual((short)1, decoder.GetD(0)); + Assert.AreEqual((short)2, decoder.GetD(1)); + Assert.AreEqual((short)3, decoder.GetD(2)); + Assert.AreEqual((short)4, decoder.GetD(3)); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingArrayFieldBeforeGroupAsNullValue1() + { + var encoder = new AddArrayBeforeGroupV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddArrayBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(AddArrayBeforeGroupV1.DNullValue, decoder.GetD(0)); + Assert.AreEqual(AddArrayBeforeGroupV1.DNullValue, decoder.GetD(1)); + Assert.AreEqual(AddArrayBeforeGroupV1.DNullValue, decoder.GetD(2)); + Assert.AreEqual(AddArrayBeforeGroupV1.DNullValue, decoder.GetD(3)); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingArrayFieldBeforeGroupAsNullValue2() + { + var encoder = new AddArrayBeforeGroupV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddArrayBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(0, decoder.D.Length); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToSkipPresentButAddedArrayFieldBeforeGroup() + { + var encoder = new AddArrayBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.SetD(0, 1); + encoder.SetD(1, 2); + encoder.SetD(2, 3); + encoder.SetD(3, 4); + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddArrayBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsOldDecoderToSkipAddedArrayFieldBeforeGroup() + { + var encoder = new AddArrayBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.SetD(0, 1); + encoder.SetD(1, 2); + encoder.SetD(2, 3); + encoder.SetD(3, 4); + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion1(); + + var decoder = new AddArrayBeforeGroupV0(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedBitSetFieldBeforeGroup() + { + var encoder = new AddBitSetBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.D = Flags.Guacamole | Flags.Cheese; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddBitSetBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.IsNotNull(decoder.D); + Assert.AreEqual(true, decoder.D.HasFlag(Flags.Guacamole)); + Assert.AreEqual(true, decoder.D.HasFlag(Flags.Cheese)); + Assert.AreEqual(false, decoder.D.HasFlag(Flags.SourCream)); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingBitSetFieldBeforeGroupAsNullValue() + { + var encoder = new AddBitSetBeforeGroupV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddBitSetBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual((byte)decoder.D, 0); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToSkipPresentButAddedBitSetFieldBeforeGroup() + { + var encoder = new AddBitSetBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.D = Flags.Guacamole | Flags.Cheese; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddBitSetBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsOldDecoderToSkipAddedBitSetFieldBeforeGroup() + { + var encoder = new AddBitSetBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.D = Flags.Guacamole | Flags.Cheese; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion1(); + + var decoder = new AddBitSetBeforeGroupV0(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsEncodingAndDecodingEnumInsideGroupInSchemaDefinedOrder() + { + var encoder = new EnumInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = Direction.BUY; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = Direction.SELL; + encoder.CheckEncodingIsComplete(); + + var decoder = new EnumInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(Direction.BUY, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(Direction.SELL, bDecoder.Next().C); + Assert.IsTrue(decoder.ToString().Contains("A=BUY|B=[(C=SELL)]")); + } + + [TestMethod] + public void DisallowsEncodingEnumInsideGroupBeforeCallingNext() + { + var encoder = new EnumInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = Direction.BUY; + var bEncoder = encoder.BCount(1); + var exception = Assert.ThrowsException(() => bEncoder.C = Direction.SELL); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsDecodingEnumInsideGroupBeforeCallingNext() + { + var encoder = new EnumInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = Direction.BUY; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = Direction.SELL; + encoder.CheckEncodingIsComplete(); + + var decoder = new EnumInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(Direction.BUY, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + var exception = Assert.ThrowsException(() => + { + var _ = bDecoder.C; + }); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void AllowsReEncodingTopLevelEnum() + { + var encoder = new EnumInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = Direction.BUY; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = Direction.SELL; + + encoder.A = Direction.SELL; + encoder.CheckEncodingIsComplete(); + + var decoder = new EnumInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(Direction.SELL, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(Direction.SELL, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsEncodingAndDecodingBitSetInsideGroupInSchemaDefinedOrder() + { + var encoder = new BitSetInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = Flags.Cheese | Flags.Guacamole; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = Flags.SourCream; + encoder.CheckEncodingIsComplete(); + + var decoder = new BitSetInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(true, decoder.A.HasFlag((Flags.Guacamole))); + Assert.AreEqual(true, decoder.A.HasFlag(Flags.Cheese)); + Assert.AreEqual(false, decoder.A.HasFlag(Flags.SourCream)); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + var cDecoder = bDecoder.Next().C; + Assert.AreEqual(false, cDecoder.HasFlag((Flags.Guacamole))); + Assert.AreEqual(false, cDecoder.HasFlag(Flags.Cheese)); + Assert.AreEqual(true, cDecoder.HasFlag(Flags.SourCream)); + Assert.IsTrue(decoder.ToString().Contains("A={Guacamole, Cheese}|B=[(C={SourCream})]")); + } + + [TestMethod] + public void DisallowsEncodingBitSetInsideGroupBeforeCallingNext() + { + var encoder = new BitSetInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = Flags.Cheese | Flags.Guacamole; + var bEncoder = encoder.BCount(1); + var exception = Assert.ThrowsException(() => + { + var _ = bEncoder.C; + }); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsDecodingBitSetInsideGroupBeforeCallingNext() + { + var encoder = new BitSetInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = Flags.Cheese | Flags.Guacamole; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = Flags.SourCream; + encoder.CheckEncodingIsComplete(); + + var decoder = new BitSetInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(true, decoder.A.HasFlag((Flags.Guacamole))); + Assert.AreEqual(true, decoder.A.HasFlag(Flags.Cheese)); + Assert.AreEqual(false, decoder.A.HasFlag(Flags.SourCream)); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + var exception = Assert.ThrowsException(() => + { + var _ = bDecoder.C; + }); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void AllowsReEncodingTopLevelBitSetViaReWrap() + { + var encoder = new BitSetInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = Flags.Cheese | Flags.Guacamole; + var bEncoder = encoder.BCount(1); + bEncoder.Next().C = Flags.SourCream; + + encoder.A |= Flags.SourCream; + encoder.CheckEncodingIsComplete(); + + var decoder = new BitSetInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(true, decoder.A.HasFlag((Flags.Guacamole))); + Assert.AreEqual(true, decoder.A.HasFlag(Flags.Cheese)); + Assert.AreEqual(true, decoder.A.HasFlag(Flags.SourCream)); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + var cDecoder = bDecoder.Next().C; + Assert.AreEqual(false, cDecoder.HasFlag((Flags.Guacamole))); + Assert.AreEqual(false, cDecoder.HasFlag(Flags.Cheese)); + Assert.AreEqual(true, cDecoder.HasFlag(Flags.SourCream)); + } + + [TestMethod] + public void AllowsEncodingAndDecodingArrayInsideGroupInSchemaDefinedOrder() + { + var encoder = new ArrayInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.SetA(0, 1); + encoder.SetA(1, 2); + encoder.SetA(2, 3); + encoder.SetA(3, 4); + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.SetC(0, 5); + bEncoder.SetC(1, 6); + bEncoder.SetC(2, 7); + bEncoder.SetC(3, 8); + encoder.CheckEncodingIsComplete(); + + var decoder = new ArrayInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A[0]); + Assert.AreEqual(2, decoder.A[1]); + Assert.AreEqual(3, decoder.A[2]); + Assert.AreEqual(4, decoder.A[3]); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + bDecoder.Next(); + Assert.AreEqual(5, bDecoder.C[0]); + Assert.AreEqual(6, bDecoder.C[1]); + Assert.AreEqual(7, bDecoder.C[2]); + Assert.AreEqual(8, bDecoder.C[3]); + StringAssert.Contains(decoder.ToString(), "A=[1,2,3,4]|B=[(C=[5,6,7,8])]"); + } + + [TestMethod] + public void DisallowsEncodingArrayInsideGroupBeforeCallingNext1() + { + var bEncoder = EncodeUntilGroupWithArrayInside(); + var exception = Assert.ThrowsException(() => { bEncoder.SetC(0, 5); }); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsEncodingArrayInsideGroupBeforeCallingNext2() + { + var bEncoder = EncodeUntilGroupWithArrayInside(); + var exception = Assert.ThrowsException(() => { bEncoder.CAsSpan()[0] = 1; }); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + private ArrayInsideGroup.BGroup EncodeUntilGroupWithArrayInside() + { + var encoder = new ArrayInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.SetA(0, 1); + encoder.SetA(1, 2); + encoder.SetA(2, 3); + encoder.SetA(3, 4); + return encoder.BCount(1); + } + + [TestMethod] + public void DisallowsDecodingArrayInsideGroupBeforeCallingNext1() + { + var bDecoder = DecodeUntilGroupWithArrayInside(); + var exception = Assert.ThrowsException(() => bDecoder.C[0]); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsDecodingArrayInsideGroupBeforeCallingNext2() + { + var bDecoder = DecodeUntilGroupWithArrayInside(); + var exception = Assert.ThrowsException(() => bDecoder.GetC(0)); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + private ArrayInsideGroup.BGroup DecodeUntilGroupWithArrayInside() + { + var encoder = new ArrayInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.SetA(0, 1); + encoder.SetA(1, 2); + encoder.SetA(2, 3); + encoder.SetA(3, 4); + var bEncoder = encoder.BCount(1).Next(); + bEncoder.SetC(0, 5); + bEncoder.SetC(1, 6); + bEncoder.SetC(2, 7); + bEncoder.SetC(3, 8); + + encoder.CheckEncodingIsComplete(); + + var decoder = new ArrayInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual((short)1, decoder.A[0]); + Assert.AreEqual((short)2, decoder.A[1]); + Assert.AreEqual((short)3, decoder.A[2]); + Assert.AreEqual((short)4, decoder.A[3]); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + return bDecoder; + } + + [TestMethod] + public void AllowsReEncodingTopLevelArrayViaReWrap() + { + var encoder = new ArrayInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.SetA(0, 1); + encoder.SetA(1, 2); + encoder.SetA(2, 3); + encoder.SetA(3, 4); + var bEncoder = encoder.BCount(1).Next(); + bEncoder.SetC(0, 5); + bEncoder.SetC(1, 6); + bEncoder.SetC(2, 7); + bEncoder.SetC(3, 8); + + encoder.SetA(0, 9); + encoder.SetA(1, 10); + encoder.SetA(2, 11); + encoder.SetA(3, 12); + encoder.CheckEncodingIsComplete(); + + var decoder = new ArrayInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(9, decoder.A[0]); + Assert.AreEqual(10, decoder.A[1]); + Assert.AreEqual(11, decoder.A[2]); + Assert.AreEqual(12, decoder.A[3]); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + bDecoder.Next(); + Assert.AreEqual(5, bDecoder.C[0]); + Assert.AreEqual(6, bDecoder.C[1]); + Assert.AreEqual(7, bDecoder.C[2]); + Assert.AreEqual(8, bDecoder.C[3]); + } + + [TestMethod] + public void AllowsEncodingAndDecodingGroupFieldsInSchemaDefinedOrder1() + { + var encoder = new MultipleGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.BCount(0); + var dEncoder = encoder.DCount(1).Next(); + dEncoder.E = 43; + encoder.CheckEncodingIsComplete(); + + var decoder = new MultipleGroups(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + Assert.AreEqual(0, decoder.B.Count); + var dDecoder = decoder.D; + Assert.AreEqual(1, dDecoder.Count); + Assert.AreEqual(dDecoder.Next().E, 43); + Assert.IsTrue(decoder.ToString().Contains("A=42|B=[]|D=[(E=43)]")); + } + + [TestMethod] + public void AllowsEncodingAndDecodingGroupFieldsInSchemaDefinedOrder2() + { + var encoder = new MultipleGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 41; + var bEncoder = encoder.BCount(1).Next(); + bEncoder.C = 42; + var dEncoder = encoder.DCount(1).Next(); + dEncoder.E = 43; + encoder.CheckEncodingIsComplete(); + + var decoder = new MultipleGroups(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(41, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(42, bDecoder.Next().C); + var dDecoder = decoder.D; + Assert.AreEqual(1, dDecoder.Count); + Assert.AreEqual(43, dDecoder.Next().E); + } + + [TestMethod] + public void AllowsReEncodingTopLevelPrimitiveFieldsAfterGroups() + { + var encoder = new MultipleGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 41; + var bEncoder = encoder.BCount(1).Next(); + bEncoder.C = 42; + var dEncoder = encoder.DCount(1).Next(); + dEncoder.E = 43; + encoder.A = 44; + encoder.CheckEncodingIsComplete(); + + var decoder = new MultipleGroups(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(44, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(42, bDecoder.Next().C); + var dDecoder = decoder.D; + Assert.AreEqual(1, dDecoder.Count); + Assert.AreEqual(43, dDecoder.Next().E); + } + + [TestMethod] + public void DisallowsMissedEncodingOfGroupField() + { + var encoder = new MultipleGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 41; + Assert.ThrowsException(() => encoder.DCount(0)); + } + + [TestMethod] + public void DisallowsReEncodingEarlierGroupFields() + { + var encoder = new MultipleGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 41; + var bEncoder = encoder.BCount(1).Next(); + bEncoder.C = 42; + var dEncoder = encoder.DCount(1).Next(); + dEncoder.E = 43; + Assert.ThrowsException(() => encoder.BCount(1)); + } + + [TestMethod] + public void DisallowsReEncodingLatestGroupField() + { + var encoder = new MultipleGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 41; + var bEncoder = encoder.BCount(1).Next(); + bEncoder.C = 42; + var dEncoder = encoder.DCount(1).Next(); + dEncoder.E = 43; + Assert.ThrowsException(() => encoder.DCount(1)); + } + + [TestMethod] + public void DisallowsMissedDecodingOfGroupField() + { + var encoder = new MultipleGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 41; + var bEncoder = encoder.BCount(1).Next(); + bEncoder.C = 42; + var dEncoder = encoder.DCount(1).Next(); + dEncoder.E = 43; + encoder.CheckEncodingIsComplete(); + + var decoder = new MultipleGroups(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(41, decoder.A); + Assert.ThrowsException(() => + { + // ReSharper disable once UnusedVariable + var ignored = decoder.D; + }); + } + + [TestMethod] + public void DisallowsReDecodingEarlierGroupField() + { + var encoder = new MultipleGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 41; + var bEncoder = encoder.BCount(1).Next(); + bEncoder.C = 42; + var dEncoder = encoder.DCount(1).Next(); + dEncoder.E = 43; + encoder.CheckEncodingIsComplete(); + + var decoder = new MultipleGroups(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(41, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(42, bDecoder.Next().C); + var dDecoder = decoder.D; + Assert.AreEqual(1, dDecoder.Count); + Assert.AreEqual(43, dDecoder.Next().E); + Assert.ThrowsException(() => + { + // ReSharper disable once UnusedVariable + var ignored = decoder.B; + }); + } + + [TestMethod] + public void DisallowsReDecodingLatestGroupField() + { + var encoder = new MultipleGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 41; + var bEncoder = encoder.BCount(1).Next(); + bEncoder.C = 42; + var dEncoder = encoder.DCount(1).Next(); + dEncoder.E = 43; + encoder.CheckEncodingIsComplete(); + + var decoder = new MultipleGroups(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(41, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(42, bDecoder.Next().C); + var dDecoder = decoder.D; + Assert.AreEqual(1, dDecoder.Count); + Assert.AreEqual(43, dDecoder.Next().E); + Assert.ThrowsException(() => + { + // ReSharper disable once UnusedVariable + var ignored = decoder.D; + }); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedVarData() + { + var encoder = new AddVarDataV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.SetB("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new AddVarDataV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + Assert.AreEqual("abc", decoder.GetB()); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingAddedVarDataAsNullValue1() + { + var encoder = new AddVarDataV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddVarDataV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + Assert.AreEqual("", decoder.GetB()); + Assert.IsTrue(decoder.ToString().Contains("A=42|B=''")); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingAddedVarDataAsNullValue2() + { + var encoder = new AddVarDataV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddVarDataV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + Assert.AreEqual(0, decoder.BLength()); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingAddedVarDataAsNullValue3() + { + var encoder = new AddVarDataV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddVarDataV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + Assert.AreEqual(0, decoder.GetB(new byte[16])); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingAddedVarDataAsNullValue4() + { + var encoder = new AddVarDataV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddVarDataV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(42, decoder.A); + Assert.AreEqual(0, decoder.GetB(new byte[16], 0, 16)); + } + + [TestMethod] + public void AllowsEncodingAndDecodingAsciiInsideGroupInSchemaDefinedOrder1() + { + var encoder = new AsciiInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.SetA("GBPUSD"); + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.SetC("EURUSD"); + encoder.CheckEncodingIsComplete(); + + var decoder = new AsciiInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual("GBPUSD", decoder.GetA()); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + bDecoder.Next(); + Assert.AreEqual("EURUSD", bDecoder.GetC()); + Assert.IsTrue(decoder.ToString().Contains("A='GBPUSD'|B=[(C='EURUSD')]")); + } + + [TestMethod] + public void AllowsEncodingAndDecodingAsciiInsideGroupInSchemaDefinedOrder2() + { + var encoder = new AsciiInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + var gbpUsdBytes = Encoding.ASCII.GetBytes("GBPUSD"); + encoder.SetA(gbpUsdBytes, 0); + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.SetC(Encoding.ASCII.GetBytes("EURUSD"), 0); + encoder.CheckEncodingIsComplete(); + + var decoder = new AsciiInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + var aBytes = new byte[6]; + decoder.GetA(aBytes, 0); + Assert.IsTrue(gbpUsdBytes.SequenceEqual(aBytes)); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + bDecoder.Next(); + Assert.AreEqual((byte)'E', bDecoder.GetC(0)); + Assert.AreEqual((byte)'U', bDecoder.GetC(1)); + Assert.AreEqual((byte)'R', bDecoder.GetC(2)); + Assert.AreEqual((byte)'U', bDecoder.GetC(3)); + Assert.AreEqual((byte)'S', bDecoder.GetC(4)); + Assert.AreEqual((byte)'D', bDecoder.GetC(5)); + } + + [TestMethod] + public void DisallowsEncodingAsciiInsideGroupBeforeCallingNext1() + { + var bEncoder = EncodeUntilGroupWithAsciiInside(); + + Exception exception = Assert.ThrowsException(() => bEncoder.SetC("EURUSD")); + + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsEncodingAsciiInsideGroupBeforeCallingNext2() + { + var bEncoder = EncodeUntilGroupWithAsciiInside(); + + Exception exception = Assert.ThrowsException(() => bEncoder.SetC(0, (byte)'E')); + + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsEncodingAsciiInsideGroupBeforeCallingNext3() + { + var bEncoder = EncodeUntilGroupWithAsciiInside(); + + Exception exception = + Assert.ThrowsException(() => bEncoder.CAsSpan()[0] = (byte)'E'); + + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsEncodingAsciiInsideGroupBeforeCallingNext4() + { + var bEncoder = EncodeUntilGroupWithAsciiInside(); + + Exception exception = Assert.ThrowsException(() => + { + bEncoder.SetC(Encoding.ASCII.GetBytes("EURUSD"), 0); + }); + + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsEncodingAsciiInsideGroupBeforeCallingNext5() + { + var bEncoder = EncodeUntilGroupWithAsciiInside(); + + Exception exception = Assert.ThrowsException(() => + bEncoder.SetC(Encoding.ASCII.GetBytes("EURUSD"), 0)); + + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsEncodingAsciiInsideGroupBeforeCallingNext6() + { + var bEncoder = EncodeUntilGroupWithAsciiInside(); + + Exception exception = Assert.ThrowsException(() => + bEncoder.SetC(Encoding.ASCII.GetBytes("EURUSD"))); + + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + private AsciiInsideGroup.BGroup EncodeUntilGroupWithAsciiInside() + { + var encoder = new AsciiInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.SetA("GBPUSD"); + return encoder.BCount(1); + } + + [TestMethod] + public void DisallowsDecodingAsciiInsideGroupBeforeCallingNext1() + { + var b = DecodeUntilGroupWithAsciiInside(); + + Exception exception = Assert.ThrowsException(() => b.GetC(0)); + + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsDecodingAsciiInsideGroupBeforeCallingNext2() + { + var b = DecodeUntilGroupWithAsciiInside(); + + Exception exception = Assert.ThrowsException(() => b.GetC()); + + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsDecodingAsciiInsideGroupBeforeCallingNext3() + { + var b = DecodeUntilGroupWithAsciiInside(); + + Exception exception = Assert.ThrowsException(() => b.C[0]); + + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsDecodingAsciiInsideGroupBeforeCallingNext4() + { + var b = DecodeUntilGroupWithAsciiInside(); + + Exception exception = Assert.ThrowsException(() => b.GetC(new byte[16], 0)); + + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + [TestMethod] + public void DisallowsDecodingAsciiInsideGroupBeforeCallingNext5() + { + var b = DecodeUntilGroupWithAsciiInside(); + + Exception exception = Assert.ThrowsException(() => b.GetC(new byte[16])); + + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_B_N")); + } + + private AsciiInsideGroup.BGroup DecodeUntilGroupWithAsciiInside() + { + var encoder = new AsciiInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.SetA("GBPUSD"); + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.SetC("EURUSD"); + encoder.CheckEncodingIsComplete(); + + var decoder = new AsciiInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual("GBPUSD", decoder.GetA()); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + return bDecoder; + } + + [TestMethod] + public void AllowsReEncodingTopLevelAsciiViaReWrap() + { + var encoder = new AsciiInsideGroup(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.SetA("GBPUSD"); + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.SetC("EURUSD"); + + encoder.SetA("CADUSD"); + encoder.CheckEncodingIsComplete(); + + var decoder = new AsciiInsideGroup(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual("CADUSD", decoder.GetA()); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + bDecoder.Next(); + Assert.AreEqual("EURUSD", bDecoder.GetC()); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedAsciiFieldBeforeGroup1() + { + var encoder = new AddAsciiBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.SetD("EURUSD"); + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddAsciiBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual("EURUSD", decoder.GetD()); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedAsciiFieldBeforeGroup2() + { + var encoder = new AddAsciiBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.SetD("EURUSD"); + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddAsciiBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual((byte)'E', decoder.GetD(0)); + Assert.AreEqual((byte)'U', decoder.GetD(1)); + Assert.AreEqual((byte)'R', decoder.GetD(2)); + Assert.AreEqual((byte)'U', decoder.GetD(3)); + Assert.AreEqual((byte)'S', decoder.GetD(4)); + Assert.AreEqual((byte)'D', decoder.GetD(5)); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeAddedAsciiFieldBeforeGroup3() + { + var encoder = new AddAsciiBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.SetD("EURUSD"); + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddAsciiBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual((byte)'E', decoder.D[0]); + Assert.AreEqual((byte)'U', decoder.D[1]); + Assert.AreEqual((byte)'R', decoder.D[2]); + Assert.AreEqual((byte)'U', decoder.D[3]); + Assert.AreEqual((byte)'S', decoder.D[4]); + Assert.AreEqual((byte)'D', decoder.D[5]); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingAsciiFieldBeforeGroupAsNullValue1() + { + var encoder = new AddAsciiBeforeGroupV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddAsciiBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(AddAsciiBeforeGroupV1.DNullValue, decoder.GetD(0)); + Assert.AreEqual(AddAsciiBeforeGroupV1.DNullValue, decoder.GetD(1)); + Assert.AreEqual(AddAsciiBeforeGroupV1.DNullValue, decoder.GetD(2)); + Assert.AreEqual(AddAsciiBeforeGroupV1.DNullValue, decoder.GetD(3)); + Assert.AreEqual(AddAsciiBeforeGroupV1.DNullValue, decoder.GetD(4)); + Assert.AreEqual(AddAsciiBeforeGroupV1.DNullValue, decoder.GetD(5)); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingAsciiFieldBeforeGroupAsNullValue2() + { + var encoder = new AddAsciiBeforeGroupV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddAsciiBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(0, decoder.D.Length); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingAsciiFieldBeforeGroupAsNullValue3() + { + var encoder = new AddAsciiBeforeGroupV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddAsciiBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(0, decoder.GetD(new byte[16])); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToDecodeMissingAsciiFieldBeforeGroupAsNullValue4() + { + var encoder = new AddAsciiBeforeGroupV0(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion0(); + + var decoder = new AddAsciiBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + Assert.AreEqual(0, decoder.GetD(new byte[16], 0)); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsNewDecoderToSkipPresentButAddedAsciiFieldBeforeGroup() + { + var encoder = new AddAsciiBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.SetD("EURUSD"); + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.C = 2; + encoder.CheckEncodingIsComplete(); + + var decoder = new AddAsciiBeforeGroupV1(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsOldDecoderToSkipAddedAsciiFieldBeforeGroup() + { + var encoder = new AddAsciiBeforeGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.SetD("EURUSD"); + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.C = 2; + encoder.CheckEncodingIsComplete(); + + ModifyHeaderToLookLikeVersion1(); + + var decoder = new AddAsciiBeforeGroupV0(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + } + + [TestMethod] + public void AllowsEncodeAndDecodeOfMessagesWithNoABlock() + { + var encoder = new NoBlock(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.SetA("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new NoBlock(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual("abc", decoder.GetA()); + } + + [TestMethod] + public void AllowsEncodeAndDecodeOfGroupsWithNoBlock() + { + var encoder = new GroupWithNoBlock(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + var aEncoder = encoder.ACount(1); + aEncoder.Next(); + aEncoder.SetB("abc"); + encoder.CheckEncodingIsComplete(); + + var decoder = new GroupWithNoBlock(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + var aDecoder = decoder.A; + Assert.AreEqual(1, aDecoder.Count); + Assert.AreEqual("abc", aDecoder.Next().GetB()); + } + + [TestMethod] + public void DisallowsEncodingElementOfEmptyGroup1() + { + var encoder = new MultipleGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(0); + var dEncoder = encoder.DCount(1); + dEncoder.Next(); + dEncoder.E = 43; + + var ex = Assert.ThrowsException(() => bEncoder.C = 44); + Assert.IsTrue(ex.Message.Contains("Cannot access field \"b.c\" in state: V0_D_1_BLOCK")); + } + + [TestMethod] + public void DisallowsEncodingElementOfEmptyGroup2() + { + var encoder = new NestedGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.C = 43; + var dEncoder = bEncoder.DCount(0); + bEncoder.FCount(0); + encoder.HCount(0); + + var ex = Assert.ThrowsException(() => dEncoder.E = 44); + Assert.IsTrue(ex.Message.Contains("Cannot access field \"b.d.e\" in state: V0_H_DONE")); + } + + [TestMethod] + public void DisallowsEncodingElementOfEmptyGroup3() + { + var encoder = new NestedGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.C = 43; + var dEncoder = bEncoder.DCount(0); + bEncoder.FCount(0); + encoder.HCount(0); + + var ex = Assert.ThrowsException(() => dEncoder.E = 44); + Assert.IsTrue(ex.Message.Contains("Cannot access field \"b.d.e\" in state: V0_H_DONE")); + } + + [TestMethod] + public void DisallowsEncodingElementOfEmptyGroup4() + { + var encoder = new NestedGroups(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(1); + bEncoder.Next(); + bEncoder.C = 43; + var dEncoder = bEncoder.DCount(0); + bEncoder.FCount(0); + + var ex = Assert.ThrowsException(() => dEncoder.E = 44); + Assert.IsTrue(ex.Message.Contains("Cannot access field \"b.d.e\" in state: V0_B_1_F_DONE")); + } + + + [TestMethod] + public void DisallowsEncodingElementOfEmptyGroup5() + { + var encoder = new AddPrimitiveInsideGroupV1(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(0); + var exception = Assert.ThrowsException(() => bEncoder.C = 43); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V1_B_DONE")); + } + + [TestMethod] + public void DisallowsEncodingElementOfEmptyGroup6() + { + var encoder = new GroupAndVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 42; + var bEncoder = encoder.BCount(0); + encoder.SetD("abc"); + var exception = Assert.ThrowsException(() => bEncoder.C = 43); + Assert.IsTrue(exception.Message.Contains("Cannot access field \"b.c\" in state: V0_D_DONE")); + } + + [TestMethod] + public void AllowsEncodingAndDecodingNestedGroupWithVarDataInSchemaDefinedOrder() + { + var encoder = new NestedGroupWithVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(3); + var bNext = bEncoder.Next(); + bNext.C = 2; + bNext.DCount(0); + bNext = bEncoder.Next(); + bNext.C = 3; + var dEncoder = bNext.DCount(1); + var dNext = dEncoder.Next(); + dNext.E = 4; + dEncoder.SetF("abc"); + bNext = bEncoder.Next(); + bNext.C = 5; + dEncoder = bNext.DCount(2); + dNext = dEncoder.Next(); + dNext.E = 6; + dEncoder.SetF("def"); + dNext = dEncoder.Next(); + dNext.E = 7; + dEncoder.SetF("ghi"); + encoder.CheckEncodingIsComplete(); + + var decoder = new NestedGroupWithVarLength(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(3, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + Assert.AreEqual(0, bDecoder.D.Count); + Assert.AreEqual(3, bDecoder.Next().C); + var dDecoder = bDecoder.D; + Assert.AreEqual(1, dDecoder.Count); + Assert.AreEqual(4, dDecoder.Next().E); + Assert.AreEqual("abc", dDecoder.GetF()); + Assert.AreEqual(5, bDecoder.Next().C); + Assert.AreEqual(dDecoder, bDecoder.D); + Assert.AreEqual(2, dDecoder.Count); + Assert.AreEqual(6, dDecoder.Next().E); + Assert.AreEqual("def", dDecoder.GetF()); + Assert.AreEqual(7, dDecoder.Next().E); + Assert.AreEqual("ghi", dDecoder.GetF()); + } + + [DataTestMethod] + [DataRow(1, "V0_B_N_D_1_BLOCK")] + [DataRow(2, "V0_B_N_D_N_BLOCK")] + public void DisallowsMissedEncodingOfVarLengthFieldInNestedGroupToNextOuterElement(int dCount, + string expectedState) + { + var encoder = new NestedGroupWithVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(2); + var bNext = bEncoder.Next(); + bNext.C = 3; + var dEncoder = bNext.DCount(dCount); + dEncoder.Next().E = 4; + var exception = Assert.ThrowsException(bEncoder.Next); + Assert.IsTrue(exception.Message.Contains("Cannot access next element in repeating group \"b\" in state: " + + expectedState)); + Assert.IsTrue( + exception.Message.Contains( + "Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + } + + [TestMethod] + public void DisallowsMissedDecodingOfVarLengthFieldInNestedGroupToNextInnerElement1() + { + var encoder = new NestedGroupWithVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(1); + var bNext = bEncoder.Next(); + bNext.C = 2; + var dEncoder = bNext.DCount(2); + var dNext = dEncoder.Next(); + dNext.E = 3; + dEncoder.SetF("abc"); + dNext = dEncoder.Next(); + dNext.E = 4; + dEncoder.SetF("def"); + encoder.CheckEncodingIsComplete(); + + var decoder = new NestedGroupWithVarLength(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(1, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + var dDecoder = bDecoder.D; + Assert.AreEqual(2, dDecoder.Count); + Assert.AreEqual(3, dDecoder.Next().E); + var exception = Assert.ThrowsException(dDecoder.Next); + Assert.IsTrue( + exception.Message.Contains( + "Cannot access next element in repeating group \"b.d\" in state: V0_B_1_D_N_BLOCK.")); + Assert.IsTrue( + exception.Message.Contains( + "Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + } + + [TestMethod] + public void DisallowsMissedDecodingOfVarLengthFieldInNestedGroupToNextInnerElement2() + { + var encoder = new NestedGroupWithVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(2); + var bNext = bEncoder.Next(); + bNext.C = 2; + var dEncoder = bNext.DCount(2); + var dNext = dEncoder.Next(); + dNext.E = 3; + dEncoder.SetF("abc"); + dNext = dEncoder.Next(); + dNext.E = 4; + dEncoder.SetF("def"); + bEncoder.Next().C = 5; + bEncoder.DCount(0); + encoder.CheckEncodingIsComplete(); + + var decoder = new NestedGroupWithVarLength(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(2, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + var dDecoder = bDecoder.D; + Assert.AreEqual(2, dDecoder.Count); + Assert.AreEqual(3, dDecoder.Next().E); + var exception = Assert.ThrowsException(dDecoder.Next); + Assert.IsTrue( + exception.Message.Contains( + "Cannot access next element in repeating group \"b.d\" in state: V0_B_N_D_N_BLOCK.")); + Assert.IsTrue( + exception.Message.Contains( + "Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + } + + [TestMethod] + public void DisallowsMissedDecodingOfVarLengthFieldInNestedGroupToNextOuterElement1() + { + var encoder = new NestedGroupWithVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(2); + var bNext = bEncoder.Next(); + bNext.C = 2; + var dEncoder = bNext.DCount(2); + var dNext = dEncoder.Next(); + dNext.E = 3; + dEncoder.SetF("abc"); + dNext = dEncoder.Next(); + dNext.E = 4; + dEncoder.SetF("def"); + bEncoder.Next().C = 5; + bEncoder.DCount(0); + encoder.CheckEncodingIsComplete(); + + var decoder = new NestedGroupWithVarLength(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(2, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + var dDecoder = bDecoder.D; + Assert.AreEqual(2, dDecoder.Count); + Assert.AreEqual(3, dDecoder.Next().E); + var exception = Assert.ThrowsException(bDecoder.Next); + Assert.IsTrue( + exception.Message.Contains( + "Cannot access next element in repeating group \"b\" in state: V0_B_N_D_N_BLOCK.")); + Assert.IsTrue( + exception.Message.Contains( + "Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + } + + [TestMethod] + public void DisallowsMissedDecodingOfVarLengthFieldInNestedGroupToNextOuterElement2() + { + var encoder = new NestedGroupWithVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(2); + var bNext = bEncoder.Next(); + bNext.C = 2; + var dEncoder = bNext.DCount(1); + var dNext = dEncoder.Next(); + dNext.E = 3; + dEncoder.SetF("abc"); + bEncoder.Next().C = 5; + bEncoder.DCount(0); + encoder.CheckEncodingIsComplete(); + + var decoder = new NestedGroupWithVarLength(); + decoder.WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + Assert.AreEqual(1, decoder.A); + var bDecoder = decoder.B; + Assert.AreEqual(2, bDecoder.Count); + Assert.AreEqual(2, bDecoder.Next().C); + var dDecoder = bDecoder.D; + Assert.AreEqual(1, dDecoder.Count); + Assert.AreEqual(3, dDecoder.Next().E); + var exception = Assert.ThrowsException(() => bDecoder.Next()); + Assert.IsTrue( + exception.Message.Contains( + "Cannot access next element in repeating group \"b\" in state: V0_B_N_D_1_BLOCK.")); + Assert.IsTrue( + exception.Message.Contains( + "Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + } + + [TestMethod] + public void DisallowsIncompleteMessagesDueToMissingVarLengthField1() + { + var encoder = new MultipleVarLength(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.SetB("abc"); + var exception = Assert.ThrowsException(() => encoder.CheckEncodingIsComplete()); + Assert.IsTrue( + exception.Message.Contains( + "Not fully encoded, current state: V0_B_DONE, allowed transitions: \"cLength()\", \"c(?)\"")); + } + + [TestMethod] + public void DisallowsIncompleteMessagesDueToMissingVarLengthField2() + { + var encoder = new NoBlock(); + encoder.WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + var exception = Assert.ThrowsException(() => encoder.CheckEncodingIsComplete()); + Assert.IsTrue( + exception.Message.Contains( + "Not fully encoded, current state: V0_BLOCK, allowed transitions: \"aLength()\", \"a(?)\"")); + } + + [TestMethod] + public void DisallowsIncompleteMessagesDueToMissingTopLevelGroup1() + { + var encoder = new MultipleGroups() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + encoder.BCount(0); + var exception = Assert.ThrowsException(encoder.CheckEncodingIsComplete); + StringAssert.Contains(exception.Message, + "Not fully encoded, current state: V0_B_DONE, allowed transitions: " + + "\"b.resetCountToIndex()\", \"dCount(0)\", \"dCount(>0)\""); + } + + [TestMethod] + public void DisallowsIncompleteMessagesDueToMissingTopLevelGroup2() + { + var encoder = new MultipleGroups() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(1).Next(); + bEncoder.C = 2; + var exception = Assert.ThrowsException(encoder.CheckEncodingIsComplete); + StringAssert.Contains(exception.Message, + "Not fully encoded, current state: V0_B_1_BLOCK, allowed transitions:" + + " \"b.c(?)\", \"b.resetCountToIndex()\", \"dCount(0)\", \"dCount(>0)\""); + } + + [TestMethod] + public void DisallowsIncompleteMessagesDueToMissingTopLevelGroup3() + { + var encoder = new MultipleGroups() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var exception = Assert.ThrowsException(encoder.CheckEncodingIsComplete); + StringAssert.Contains(exception.Message, + "Not fully encoded, current state: V0_BLOCK, allowed transitions: \"a(?)\", \"bCount(0)\", \"bCount(>0)\""); + } + + [DataTestMethod] + [DataRow(1, "V0_B_1_BLOCK")] + [DataRow(2, "V0_B_N_BLOCK")] + public void DisallowsIncompleteMessagesDueToMissingNestedGroup1(int bCount, string expectedState) + { + var encoder = new NestedGroupWithVarLength() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(bCount).Next(); + bEncoder.C = 2; + var exception = Assert.ThrowsException(encoder.CheckEncodingIsComplete); + StringAssert.Contains(exception.Message, $"Not fully encoded, current state: {expectedState}"); + } + + [DataTestMethod] + [DataRow(1, 1, "V0_B_1_D_N")] + [DataRow(1, 2, "V0_B_1_D_N")] + [DataRow(2, 0, "V0_B_N_D_DONE")] + [DataRow(2, 1, "V0_B_N_D_N")] + [DataRow(2, 2, "V0_B_N_D_N")] + public void DisallowsIncompleteMessagesDueToMissingNestedGroup2( + int bCount, + int dCount, + string expectedState) + { + var encoder = new NestedGroupWithVarLength() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(bCount).Next(); + bEncoder.C = 2; + bEncoder.DCount(dCount); + var exception = Assert.ThrowsException(encoder.CheckEncodingIsComplete); + StringAssert.Contains(exception.Message, $"Not fully encoded, current state: {expectedState}"); + } + + [DataTestMethod] + [DataRow(1, 1, "V0_B_1_D_1_BLOCK")] + [DataRow(1, 2, "V0_B_1_D_N_BLOCK")] + [DataRow(2, 1, "V0_B_N_D_1_BLOCK")] + [DataRow(2, 2, "V0_B_N_D_N_BLOCK")] + public void DisallowsIncompleteMessagesDueToMissingVarDataInNestedGroup( + int bCount, + int dCount, + string expectedState) + { + var encoder = new NestedGroupWithVarLength() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.A = 1; + var bEncoder = encoder.BCount(bCount).Next(); + bEncoder.C = 2; + bEncoder.DCount(dCount).Next().E = 10; + var exception = Assert.ThrowsException(encoder.CheckEncodingIsComplete); + StringAssert.Contains(exception.Message, $"Not fully encoded, current state: {expectedState}"); + } + + private void ModifyHeaderToLookLikeVersion0() + { + var messageHeaderDecoder = new MessageHeader(); + messageHeaderDecoder.Wrap(_buffer, Offset, MessageHeader.SbeSchemaVersion); + int v1TemplateId = messageHeaderDecoder.TemplateId + 1_000; + var messageHeaderEncoder = new MessageHeader(); + messageHeaderEncoder.Wrap(_buffer, Offset, MessageHeader.SbeSchemaVersion); + messageHeaderEncoder.TemplateId = (ushort)v1TemplateId; + messageHeaderEncoder.Version = 0; + } + + private void ModifyHeaderToLookLikeVersion1() + { + var messageHeaderDecoder = new MessageHeader(); + messageHeaderDecoder.Wrap(_buffer, Offset, MessageHeader.SbeSchemaVersion); + Debug.Assert(messageHeaderDecoder.Version == 1); + int v0TemplateId = messageHeaderDecoder.TemplateId - 1_000; + var messageHeaderEncoder = new MessageHeader(); + messageHeaderEncoder.Wrap(_buffer, Offset, MessageHeader.SbeSchemaVersion); + messageHeaderEncoder.TemplateId = (ushort)v0TemplateId; + } + } +} \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index 1134e90c0e..7c5ec14a9f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -204,6 +204,24 @@ public class SbeTool */ public static final String SCHEMA_TRANSFORM_VERSION = "sbe.schema.transform.version"; + /** + * Whether to generate field precedence checks. For example, whether to check that repeating groups are encoded + * in schema order. + */ + public static final String GENERATE_PRECEDENCE_CHECKS = "sbe.generate.precedence.checks"; + + /** + * The name of the symbol or macro that enables access order checks when building + * generated C# or C++ code. + */ + public static final String PRECEDENCE_CHECKS_FLAG_NAME = "sbe.precedence.checks.flag.name"; + + /** + * The name of the system property that enables access order checks at runtime + * in generated Java code. + */ + public static final String JAVA_PRECEDENCE_CHECKS_PROPERTY_NAME = "sbe.java.precedence.checks.property.name"; + /** * Main entry point for the SBE Tool. * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 5d81eb691b..6552a72c00 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -15,14 +15,15 @@ */ package uk.co.real_logic.sbe.generation; -import uk.co.real_logic.sbe.generation.java.JavaOutputManager; import uk.co.real_logic.sbe.generation.c.CGenerator; import uk.co.real_logic.sbe.generation.c.COutputManager; +import uk.co.real_logic.sbe.generation.common.PrecedenceChecks; import uk.co.real_logic.sbe.generation.cpp.CppGenerator; import uk.co.real_logic.sbe.generation.cpp.NamespaceOutputManager; import uk.co.real_logic.sbe.generation.golang.GolangGenerator; import uk.co.real_logic.sbe.generation.golang.GolangOutputManager; import uk.co.real_logic.sbe.generation.java.JavaGenerator; +import uk.co.real_logic.sbe.generation.java.JavaOutputManager; import uk.co.real_logic.sbe.generation.rust.RustGenerator; import uk.co.real_logic.sbe.generation.rust.RustOutputManager; import uk.co.real_logic.sbe.ir.Ir; @@ -53,6 +54,7 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) "true".equals(System.getProperty(JAVA_GENERATE_INTERFACES)), "true".equals(System.getProperty(DECODE_UNKNOWN_ENUM_VALUES)), "true".equals(System.getProperty(TYPES_PACKAGE_OVERRIDE)), + precedenceChecks(), new JavaOutputManager(outputDir, ir.applicableNamespace())); } }, @@ -84,6 +86,7 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) return new CppGenerator( ir, "true".equals(System.getProperty(DECODE_UNKNOWN_ENUM_VALUES)), + precedenceChecks(), new NamespaceOutputManager(outputDir, ir.applicableNamespace())); } }, @@ -118,6 +121,36 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) } }; + /** + * Returns the precedence checks to run, configured from system properties. + * + * @return the precedence checks to run, configured from system properties. + */ + public static PrecedenceChecks precedenceChecks() + { + final PrecedenceChecks.Context context = new PrecedenceChecks.Context(); + + final String shouldGeneratePrecedenceChecks = System.getProperty(GENERATE_PRECEDENCE_CHECKS); + if (shouldGeneratePrecedenceChecks != null) + { + context.shouldGeneratePrecedenceChecks(Boolean.parseBoolean(shouldGeneratePrecedenceChecks)); + } + + final String precedenceChecksFlagName = System.getProperty(PRECEDENCE_CHECKS_FLAG_NAME); + if (precedenceChecksFlagName != null) + { + context.precedenceChecksFlagName(precedenceChecksFlagName); + } + + final String precedenceChecksPropName = System.getProperty(JAVA_PRECEDENCE_CHECKS_PROPERTY_NAME); + if (precedenceChecksPropName != null) + { + context.precedenceChecksPropName(precedenceChecksPropName); + } + + return PrecedenceChecks.newInstance(context); + } + /** * Do a case-insensitive lookup of a target language for code generation. * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java new file mode 100644 index 0000000000..0e79f88568 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java @@ -0,0 +1,1190 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.common; + +import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.ir.Signal; +import uk.co.real_logic.sbe.ir.Token; +import org.agrona.collections.Int2ObjectHashMap; +import org.agrona.collections.IntHashSet; +import org.agrona.collections.IntObjConsumer; + +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.IntStream; + +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData; + +/** + * A state machine that models whether codec interactions are safe. + */ +@SuppressWarnings("CodeBlock2Expr") +// Lambdas without braces tend to conflict with the indentation Checkstyle expects. +// Therefore, we allow lambdas with code blocks even when a lambda expression is possible. +public final class FieldPrecedenceModel +{ + private final Map groupPathsByField = new HashMap<>(); + private final Set topLevelBlockFields = new HashSet<>(); + private final CodecInteraction.CodecInteractionFactory interactionFactory = + new CodecInteraction.CodecInteractionFactory(groupPathsByField, topLevelBlockFields); + private final Map> transitionsByInteraction = new LinkedHashMap<>(); + private final Map> transitionsByState = new HashMap<>(); + private final Int2ObjectHashMap versionWrappedStates = new Int2ObjectHashMap<>(); + private final State notWrappedState = allocateState("NOT_WRAPPED"); + private final String generatedRepresentationClassName; + private State encoderWrappedState; + private Set terminalEncoderStates; + + private FieldPrecedenceModel(final String generatedRepresentationClassName) + { + this.generatedRepresentationClassName = generatedRepresentationClassName; + } + + /** + * Builds a state machine that models whether codec interactions are safe. + * + * @param stateClassName the qualified name of the class that models the state machine in generated code + * @param msgToken the message token + * @param fields the fields in the message + * @param groups the groups in the message + * @param varData the varData in the message + * @param versionsSelector a function that selects the versions to model in the state machine + * @return the access order model + */ + public static FieldPrecedenceModel newInstance( + final String stateClassName, + final Token msgToken, + final List fields, + final List groups, + final List varData, + final Function versionsSelector) + { + final FieldPrecedenceModel model = new FieldPrecedenceModel(stateClassName); + model.findTransitions(msgToken, fields, groups, varData, versionsSelector); + return model; + } + + /** + * The initial state before a codec is wrapped. + * @return the initial state before a codec is wrapped. + */ + public State notWrappedState() + { + return notWrappedState; + } + + /** + * The state after a codec is wrapped in the latest version. + * @return the state after a codec is wrapped in the latest version. + */ + public State latestVersionWrappedState() + { + return encoderWrappedState; + } + + /** + * Iterates over the states after a codec is wrapped over a particular version of data. + * @param consumer the consumer of the states. + */ + public void forEachWrappedStateByVersion(final IntObjConsumer consumer) + { + final Int2ObjectHashMap.EntryIterator iterator = versionWrappedStates.entrySet().iterator(); + while (iterator.hasNext()) + { + iterator.next(); + consumer.accept(iterator.getIntKey(), iterator.getValue()); + } + } + + /** + * Returns the number of schema versions. + * @return the number of schema versions. + */ + public int versionCount() + { + return versionWrappedStates.size(); + } + + /** + * Iterates over the states in which a codec is fully encoded. + * @param consumer the consumer of the states. + */ + public void forEachTerminalEncoderState(final Consumer consumer) + { + terminalEncoderStates.forEach(consumer); + } + + /** + * Iterates over the codec states in the order of their state numbers. + * @param consumer the consumer of the states. + */ + public void forEachStateOrderedByStateNumber(final Consumer consumer) + { + transitionsByState.keySet().stream() + .sorted(Comparator.comparingInt(s -> s.number)) + .forEach(consumer); + } + + /** + * Returns the number of states in the state machine. + * @return the number of states in the state machine. + */ + public int stateCount() + { + return transitionsByState.size(); + } + + /** + * Returns a hash-consing factory for codec interactions. + * These interactions are the transitions in the state machine. + * @see CodecInteraction + * @return a hash-consing factory for codec interactions. + */ + public CodecInteraction.CodecInteractionFactory interactionFactory() + { + return interactionFactory; + } + + /** + * Returns the name of the class that models the state machine in generated code. + * @return the name of the class that models the state machine in generated code. + */ + public String generatedRepresentationClassName() + { + return generatedRepresentationClassName; + } + + /** + * Iterates over the possible state machine transitions due to the supplied codec interaction. + * @param interaction a codec interaction. + * @param consumer the consumer of the transitions. + */ + public void forEachTransition( + final CodecInteraction interaction, + final Consumer consumer) + { + final List transitionsForContext = transitionsByInteraction.get(interaction); + if (null != transitionsForContext) + { + transitionsForContext.forEach(consumer); + } + } + + /** + * Finds the possible transitions from a given state. + * @param state the state to find transitions from. + * @param consumer the consumer of the transitions. + */ + public void forEachTransitionFrom(final State state, final Consumer consumer) + { + final List transitionGroups = transitionsByState.get(state); + if (null != transitionGroups) + { + transitionGroups.forEach(consumer); + } + } + + /** + * Encodes the state machine as a graphviz dot diagram. + * @param sb the string builder to append to. + * @param indent the indentation to use. + */ + @SuppressWarnings("SameParameterValue") + public void generateGraph(final StringBuilder sb, final String indent) + { + sb.append(indent).append("digraph G {\n"); + transitionsByInteraction.values().forEach(transitionsForContext -> + { + transitionsForContext.forEach(transition -> + { + transition.forEachStartState(startState -> + { + sb.append(indent).append(" ") + .append(startState.name) + .append(" -> ") + .append(transition.endState().name) + .append(" [label=\" ").append(transition.interaction.exampleCode()); + + if (!transition.interaction.exampleConditions().isEmpty()) + { + sb.append("\\n").append(" where ").append(transition.interaction.exampleConditions()); + } + + sb.append(" \"];\n"); + }); + }); + }); + sb.append(indent).append("}\n"); + } + + private void findTransitions( + final Token msgToken, + final List fields, + final List groups, + final List varData, + final Function versionsSelector) + { + final IntHashSet versions = new IntHashSet(); + versions.add(msgToken.version()); + walkSchemaLevel(new VersionCollector(versions), fields, groups, varData); + walkSchemaLevel(new PathCollector(topLevelBlockFields, groupPathsByField), fields, groups, varData); + + final IntStream selectedVersions = versionsSelector.apply(versions.stream().mapToInt(i -> i)); + selectedVersions.sorted().forEach(version -> + { + final State versionWrappedState = allocateState("V" + version + "_BLOCK"); + + versionWrappedStates.put(version, versionWrappedState); + + final CodecInteraction wrapInteraction = interactionFactory.wrap(version); + + allocateTransitions( + wrapInteraction, + Collections.singletonList(notWrappedState), + versionWrappedState + ); + + final TransitionCollector transitionCollector = new TransitionCollector( + "V" + version + "_", + Collections.singleton(versionWrappedState), + versionWrappedState, + token -> token.version() <= version + ); + + walkSchemaLevel(transitionCollector, fields, groups, varData); + + // Last writer (highest version) wins when there are multiple versions + encoderWrappedState = versionWrappedState; + terminalEncoderStates = transitionCollector.exitStates(); + }); + } + + private State allocateState(final String name) + { + final State state = new State(transitionsByState.size(), name); + transitionsByState.put(state, new ArrayList<>()); + return state; + } + + private void allocateTransitions( + final CodecInteraction interaction, + final Collection from, + final State to) + { + final TransitionGroup transitionGroup = new TransitionGroup(interaction, from, to); + final List transitionsForInteraction = + transitionsByInteraction.computeIfAbsent(interaction, ignored -> new ArrayList<>()); + + final boolean duplicateEndState = + transitionsForInteraction.stream().anyMatch(t -> t.to.number == transitionGroup.to.number); + + if (duplicateEndState) + { + throw new IllegalStateException("Duplicate end state: " + transitionGroup.to.name); + } + + final Optional conflictingTransition = transitionsForInteraction.stream() + .filter(t -> t.from.stream().anyMatch(transitionGroup.from::contains)) + .findAny(); + + if (conflictingTransition.isPresent()) + { + throw new IllegalStateException( + "Conflicting transition: " + transitionGroup + " conflicts with " + conflictingTransition.get()); + } + + transitionsForInteraction.add(transitionGroup); + + from.forEach(fromState -> transitionsByState.get(fromState).add(transitionGroup)); + } + + private static void walkSchemaLevel( + final SchemaConsumer consumer, + final List fields, + final List groups, + final List varData) + { + Generators.forEachField(fields, (token, ignored) -> consumer.onBlockField(token)); + + for (int i = 0; i < groups.size(); i++) + { + final Token token = groups.get(i); + if (token.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + token); + } + + ++i; + final int groupHeaderTokenCount = groups.get(i).componentTokenCount(); + i += groupHeaderTokenCount; + + final ArrayList groupFields = new ArrayList<>(); + i = collectFields(groups, i, groupFields); + final ArrayList groupGroups = new ArrayList<>(); + i = collectGroups(groups, i, groupGroups); + final ArrayList groupVarData = new ArrayList<>(); + i = collectVarData(groups, i, groupVarData); + + consumer.onEnterRepeatingGroup(token, groupFields, groupGroups, groupVarData); + } + + for (int i = 0; i < varData.size(); ) + { + final Token token = varData.get(i); + if (token.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + token); + } + i += token.componentTokenCount(); + + consumer.onVarData(token); + } + } + + private interface SchemaConsumer + { + void onBlockField(Token token); + + void onEnterRepeatingGroup( + Token token, + List groupFields, + List groupGroups, + List groupVarData); + + void onVarData(Token token); + } + + private static final class PathCollector implements SchemaConsumer + { + private final ArrayDeque groupPath = new ArrayDeque<>(); + private final Set topLevelBlockFields; + private final Map groupPathsByField; + + private PathCollector( + final Set topLevelBlockFields, + final Map groupPathsByField) + { + this.topLevelBlockFields = topLevelBlockFields; + this.groupPathsByField = groupPathsByField; + } + + @Override + public void onBlockField(final Token token) + { + if (groupPath.isEmpty()) + { + topLevelBlockFields.add(token); + } + + groupPathsByField.put(token, currentGroupPath()); + } + + @Override + public void onEnterRepeatingGroup( + final Token token, + final List groupFields, + final List groupGroups, + final List groupVarData) + { + groupPathsByField.put(token, currentGroupPath()); + groupPath.addLast(token); + walkSchemaLevel(this, groupFields, groupGroups, groupVarData); + groupPath.removeLast(); + } + + @Override + public void onVarData(final Token token) + { + groupPathsByField.put(token, currentGroupPath()); + } + + private String currentGroupPath() + { + final StringBuilder sb = new StringBuilder(); + groupPath.forEach(token -> + { + sb.append(token.name()).append('.'); + }); + return sb.toString(); + } + } + + @SuppressWarnings("ClassCanBeRecord") + private static final class VersionCollector implements SchemaConsumer + { + private final IntHashSet versions; + + VersionCollector(final IntHashSet versions) + { + this.versions = versions; + } + + @Override + public void onBlockField(final Token token) + { + versions.add(token.version()); + } + + @Override + public void onEnterRepeatingGroup( + final Token token, + final List groupFields, + final List groupGroups, + final List groupVarData) + { + versions.add(token.version()); + walkSchemaLevel(this, groupFields, groupGroups, groupVarData); + } + + @Override + public void onVarData(final Token token) + { + versions.add(token.version()); + } + } + + private final class TransitionCollector implements SchemaConsumer + { + private final String statePrefix; + private final HashSet currentStates; + private final State blockState; + private final Predicate filter; + + private TransitionCollector( + final String statePrefix, + final Set fromStates, + final State blockState, + final Predicate filter) + { + this.statePrefix = statePrefix; + this.currentStates = new HashSet<>(fromStates); + this.blockState = blockState; + this.filter = filter; + + currentStates.add(blockState); + } + + @Override + public void onBlockField(final Token token) + { + if (filter.test(token)) + { + final CodecInteraction codecInteraction = interactionFactory.accessField(token); + allocateTransitions(codecInteraction, currentStates, blockState); + } + } + + @Override + public void onEnterRepeatingGroup( + final Token token, + final List groupFields, + final List groupGroups, + final List groupVarData) + { + if (filter.test(token)) + { + final String groupName = token.name().toUpperCase(); + final String groupPrefix = statePrefix + groupName + "_"; + final State nRemainingGroup = allocateState(groupPrefix + "N"); + final State nRemainingGroupElement = allocateState(groupPrefix + "N_BLOCK"); + final State oneRemainingGroupElement = allocateState(groupPrefix + "1_BLOCK"); + final State doneGroup = allocateState(groupPrefix + "DONE"); + + final Set beginGroupStates = new HashSet<>(currentStates); + + // fooCount(0) + final CodecInteraction emptyGroupInteraction = interactionFactory.determineGroupIsEmpty(token); + allocateTransitions(emptyGroupInteraction, beginGroupStates, doneGroup); + + // fooCount(N) where N > 0 + final CodecInteraction nonEmptyGroupInteraction = interactionFactory.determineGroupHasElements(token); + allocateTransitions(nonEmptyGroupInteraction, beginGroupStates, nRemainingGroup); + + currentStates.clear(); + currentStates.add(nRemainingGroupElement); + final TransitionCollector nRemainingCollector = new TransitionCollector( + groupPrefix + "N_", + currentStates, + nRemainingGroupElement, + filter + ); + walkSchemaLevel(nRemainingCollector, groupFields, groupGroups, groupVarData); + + currentStates.clear(); + currentStates.add(nRemainingGroup); + currentStates.addAll(nRemainingCollector.exitStates()); + + // where more than one element remains in the group + final CodecInteraction nextGroupElementInteraction = interactionFactory.moveToNextElement(token); + allocateTransitions(nextGroupElementInteraction, currentStates, nRemainingGroupElement); + + currentStates.clear(); + currentStates.add(nRemainingGroup); + currentStates.addAll(nRemainingCollector.exitStates()); + + // where only one element remains in the group + final CodecInteraction lastGroupElementInteraction = interactionFactory.moveToLastElement(token); + allocateTransitions(lastGroupElementInteraction, currentStates, oneRemainingGroupElement); + + currentStates.clear(); + currentStates.add(oneRemainingGroupElement); + + final TransitionCollector oneRemainingCollector = new TransitionCollector( + groupPrefix + "1_", + currentStates, + oneRemainingGroupElement, + filter + ); + walkSchemaLevel(oneRemainingCollector, groupFields, groupGroups, groupVarData); + + final CodecInteraction resetCountToIndexInteraction = interactionFactory.resetCountToIndex(token); + currentStates.clear(); + currentStates.add(doneGroup); + currentStates.add(nRemainingGroup); + currentStates.addAll(nRemainingCollector.exitStates()); + currentStates.addAll(oneRemainingCollector.exitStates()); + allocateTransitions(resetCountToIndexInteraction, currentStates, doneGroup); + + currentStates.clear(); + currentStates.add(doneGroup); + currentStates.addAll(oneRemainingCollector.exitStates()); + } + } + + @Override + public void onVarData(final Token token) + { + if (filter.test(token)) + { + final CodecInteraction lengthAccessInteraction = interactionFactory.accessVarDataLength(token); + currentStates.forEach(state -> + { + allocateTransitions(lengthAccessInteraction, Collections.singleton(state), state); + }); + + final CodecInteraction codecInteraction = interactionFactory.accessField(token); + final State accessedState = allocateState(statePrefix + token.name().toUpperCase() + "_DONE"); + allocateTransitions(codecInteraction, currentStates, accessedState); + currentStates.clear(); + currentStates.add(accessedState); + } + } + + private Set exitStates() + { + return currentStates; + } + } + + /** + * A state in which a codec may reside. + */ + public static final class State + { + private final int number; + private final String name; + + private State(final int number, final String name) + { + this.number = number; + this.name = name; + } + + /** + * In the scope of an {@code FieldPrecedenceModel} instance, state numbers are contiguous + * and start at 0. This numbering scheme allows easy generation of lookup tables. + * @return the state number + */ + public int number() + { + return number; + } + + /** + * Returns the name of the state. + * @return the name of the state. + */ + public String name() + { + return name; + } + + @Override + public String toString() + { + return "State{" + + "number=" + number + + ", name='" + name + '\'' + + '}'; + } + } + + /** + * A group of transitions that share the same end state. + */ + public static final class TransitionGroup + { + private final CodecInteraction interaction; + private final Set from; + private final State to; + + private TransitionGroup( + final CodecInteraction interaction, + final Collection from, + final State to) + { + this.interaction = interaction; + this.from = new HashSet<>(from); + this.to = to; + } + + /** + * Iterate over the start states of the transitions in this group. + * @param consumer the consumer of the start states. + */ + public void forEachStartState(final Consumer consumer) + { + from.forEach(consumer); + } + + /** + * Returns the end state of the transitions in this group. + * @return the end state of the transitions in this group. + */ + public State endState() + { + return to; + } + + /** + * Returns {@code true} if the transitions in this group do not change state. + * @return {@code true} if the transitions in this group do not change state. + */ + public boolean alwaysEndsInStartState() + { + return from.size() == 1 && from.contains(to); + } + + /** + * Returns some example code for the codec interaction that the transitions in this group share. + * Useful for producing error messages. + * @return some example code for the codec interaction that the transitions in this group share. + */ + public String exampleCode() + { + return interaction.exampleCode(); + } + + @Override + public String toString() + { + return "Transition{" + + "interaction='" + exampleCode() + '\'' + + ", from=" + from + + ", to=" + to + + '}'; + } + } + + /** + * Represents an interaction against a codec, e.g., {@code encoder.wrap(...)} or {@code decoder.myVarData()}. + */ + public abstract static class CodecInteraction + { + /** + * Returns a name for the interaction qualified by any groups that it is nested within. + * @return a name for the interaction qualified by any groups that it is nested within. + */ + public abstract String groupQualifiedName(); + + abstract String exampleCode(); + + abstract String exampleConditions(); + + /** + * Returns {@code true} if this interaction is a top-level block field access; {@code false} otherwise. + * @return {@code true} if this interaction is a top-level block field access; {@code false} otherwise. + */ + public final boolean isTopLevelBlockFieldAccess() + { + if (this instanceof AccessField) + { + //noinspection PatternVariableCanBeUsed + final AccessField accessField = (AccessField)this; + return accessField.isTopLevelBlockField(); + } + + return false; + } + + /** + * When an encoder or decoder is wrapped around a buffer. + */ + private static final class Wrap extends CodecInteraction + { + private final int version; + + Wrap(final int version) + { + this.version = version; + } + + @Override + public String groupQualifiedName() + { + return "wrap"; + } + + @Override + public String exampleCode() + { + return "wrap(version=" + version + ")"; + } + + @Override + public String exampleConditions() + { + return ""; + } + } + + /** + * When a block or variable-length field is accessed. + */ + private static final class AccessField extends CodecInteraction + { + private final String groupPath; + private final Token token; + private final boolean isTopLevelBlockField; + + private AccessField(final String groupPath, final Token token, final boolean isTopLevelBlockField) + { + this.isTopLevelBlockField = isTopLevelBlockField; + assert groupPath != null; + assert token.signal() == Signal.BEGIN_FIELD || token.signal() == Signal.BEGIN_VAR_DATA; + this.groupPath = groupPath; + this.token = token; + } + + boolean isTopLevelBlockField() + { + return isTopLevelBlockField; + } + + @Override + public String groupQualifiedName() + { + return groupPath + token.name(); + } + + @Override + public String exampleCode() + { + return groupPath + token.name() + "(?)"; + } + + @Override + public String exampleConditions() + { + return ""; + } + } + + /** + * When a repeating group count is supplied as zero. + */ + private static final class DetermineGroupIsEmpty extends CodecInteraction + { + private final String groupPath; + private final Token token; + + private DetermineGroupIsEmpty(final String groupPath, final Token token) + { + assert groupPath != null; + assert token.signal() == Signal.BEGIN_GROUP; + this.groupPath = groupPath; + this.token = token; + } + + @Override + public String groupQualifiedName() + { + return groupPath + token.name(); + } + + @Override + String exampleCode() + { + return groupPath + token.name() + "Count(0)"; + } + + @Override + String exampleConditions() + { + return ""; + } + } + + /** + * When a repeating group count is supplied as greater than zero. + */ + private static final class DetermineGroupHasElements extends CodecInteraction + { + private final String groupPath; + private final Token token; + + private DetermineGroupHasElements(final String groupPath, final Token token) + { + assert groupPath != null; + assert token.signal() == Signal.BEGIN_GROUP; + this.groupPath = groupPath; + this.token = token; + } + + @Override + public String groupQualifiedName() + { + return groupPath + token.name(); + } + + @Override + String exampleCode() + { + return groupPath + token.name() + "Count(>0)"; + } + + @Override + String exampleConditions() + { + return ""; + } + } + + /** + * When the next element in a repeating group is accessed, + * and it is not the last element. + */ + private static final class MoveToNextElement extends CodecInteraction + { + private final String groupPath; + private final Token token; + + private MoveToNextElement(final String groupPath, final Token token) + { + assert groupPath != null; + assert token.signal() == Signal.BEGIN_GROUP; + this.groupPath = groupPath; + this.token = token; + } + + @Override + public String groupQualifiedName() + { + return groupPath + token.name(); + } + + @Override + String exampleCode() + { + return groupPath + token.name() + ".next()"; + } + + @Override + String exampleConditions() + { + return "count - newIndex > 1"; + } + } + + /** + * When the next element in a repeating group is accessed, + * and it is the last element. + */ + private static final class MoveToLastElement extends CodecInteraction + { + private final String groupPath; + private final Token token; + + private MoveToLastElement(final String groupPath, final Token token) + { + assert groupPath != null; + assert token.signal() == Signal.BEGIN_GROUP; + this.groupPath = groupPath; + this.token = token; + } + + @Override + public String groupQualifiedName() + { + return groupPath + token.name(); + } + + @Override + String exampleCode() + { + return groupPath + token.name() + ".next()"; + } + + @Override + String exampleConditions() + { + return "count - newIndex == 1"; + } + } + + /** + * When the number of elements in a repeating group is set to be its current extent. + */ + private static final class ResetCountToIndex extends CodecInteraction + { + private final String groupPath; + private final Token token; + + private ResetCountToIndex(final String groupPath, final Token token) + { + assert groupPath != null; + assert token.signal() == Signal.BEGIN_GROUP; + this.groupPath = groupPath; + this.token = token; + } + + @Override + public String groupQualifiedName() + { + return groupPath + token.name(); + } + + @Override + String exampleCode() + { + return groupPath + token.name() + ".resetCountToIndex()"; + } + + @Override + String exampleConditions() + { + return ""; + } + } + + /** + * When the length of a variable length field is accessed without adjusting the position. + */ + private static final class AccessVarDataLength extends CodecInteraction + { + private final String groupPath; + private final Token token; + + private AccessVarDataLength(final String groupPath, final Token token) + { + assert groupPath != null; + assert token.signal() == Signal.BEGIN_VAR_DATA; + this.groupPath = groupPath; + this.token = token; + } + + @Override + public String groupQualifiedName() + { + return groupPath + token.name(); + } + + @Override + String exampleCode() + { + return groupPath + token.name() + "Length()"; + } + + @Override + String exampleConditions() + { + return ""; + } + } + + + /** + * Factory for creating {@link CodecInteraction} instances. This factory + * is used to hash-cons the instances, so that they can be compared by + * reference. + */ + public static final class CodecInteractionFactory + { + private final Int2ObjectHashMap wrapInteractions = new Int2ObjectHashMap<>(); + private final Map accessFieldInteractions = new HashMap<>(); + private final Map determineGroupIsEmptyInteractions = new HashMap<>(); + private final Map determineGroupHasElementsInteractions = new HashMap<>(); + private final Map moveToNextElementInteractions = new HashMap<>(); + private final Map moveToLastElementInteractions = new HashMap<>(); + private final Map resetCountToIndexInteractions = new HashMap<>(); + private final Map accessVarDataLengthInteractions = new HashMap<>(); + private final Map groupPathsByField; + private final Set topLevelBlockFields; + + CodecInteractionFactory( + final Map groupPathsByField, + final Set topLevelBlockFields) + { + + this.groupPathsByField = groupPathsByField; + this.topLevelBlockFields = topLevelBlockFields; + } + + /** + * Find or create a {@link CodecInteraction} to represent wrapping a codec around + * the given version of data. + * @param version the version of data to wrap + * @return the {@link CodecInteraction} instance + */ + public CodecInteraction wrap(final int version) + { + return wrapInteractions.computeIfAbsent(version, Wrap::new); + } + + /** + * Find or create a {@link CodecInteraction} to represent accessing the field identified + * by the given token. + * + *

      The supplied token must carry a {@link Signal#BEGIN_FIELD} + * or {@link Signal#BEGIN_VAR_DATA} signal. + * + * @param token the token identifying the field + * @return the {@link CodecInteraction} instance + */ + public CodecInteraction accessField(final Token token) + { + return accessFieldInteractions.computeIfAbsent(token, + t -> new AccessField(groupPathsByField.get(t), t, topLevelBlockFields.contains(t))); + } + + /** + * Find or create a {@link CodecInteraction} to represent determining a + * repeating group is empty. + * + *

      For encoding, this will be when the group count is supplied, e.g., + * {@code encoder.myGroupCount(0)}. + * + *

      For decoding, this will be when the group is read, e.g., + * {@code decoder.myGroup()}. + * + *

      The supplied token must carry a {@link Signal#BEGIN_GROUP} signal. + * + * @param token the token identifying the group + * @return the {@link CodecInteraction} instance + */ + public CodecInteraction determineGroupIsEmpty(final Token token) + { + return determineGroupIsEmptyInteractions.computeIfAbsent(token, + t -> new DetermineGroupIsEmpty(groupPathsByField.get(t), t)); + } + + /** + * Find or create a {@link CodecInteraction} to represent determining a + * repeating group has elements. + * + *

      For encoding, this will be when the group count is supplied, e.g., + * {@code encoder.myGroupCount(1)}. + * + *

      For decoding, this will be when the group is read, e.g., + * {@code decoder.myGroup()}. + * + *

      The supplied token must carry a {@link Signal#BEGIN_GROUP} signal. + * + * @param token the token identifying the group + * @return the {@link CodecInteraction} instance + */ + public CodecInteraction determineGroupHasElements(final Token token) + { + return determineGroupHasElementsInteractions.computeIfAbsent(token, + t -> new DetermineGroupHasElements(groupPathsByField.get(t), t)); + } + + /** + * Find or create a {@link CodecInteraction} to represent moving to the next + * element in a repeating group. + * + *

      For encoders, decoders, and codecs, this will be when the next element + * is accessed, e.g., {@code myGroup.next()} when {@code myGroup.count - myGroup.index > 1}. + * + *

      The supplied token must carry a {@link Signal#BEGIN_GROUP} signal. + * + * @param token the token identifying the group + * @return the {@link CodecInteraction} instance + */ + public CodecInteraction moveToNextElement(final Token token) + { + return moveToNextElementInteractions.computeIfAbsent(token, + t -> new MoveToNextElement(groupPathsByField.get(t), t)); + } + + /** + * Find or create a {@link CodecInteraction} to represent moving to the last + * element in a repeating group. + * + *

      For encoders, decoders, and codecs, this will be when the last element + * is accessed, e.g., {@code myGroup.next()} when {@code myGroup.count - myGroup.index == 1}. + * + * @param token the token identifying the group + * @return the {@link CodecInteraction} instance + */ + public CodecInteraction moveToLastElement(final Token token) + { + return moveToLastElementInteractions.computeIfAbsent(token, + t -> new MoveToLastElement(groupPathsByField.get(t), t)); + } + + /** + * Find or create a {@link CodecInteraction} to represent resetting the count + * of a repeating group to the current index. + * + *

      For encoders, decoders, and codecs, this will be when the {@code resetCountToIndex} + * method is called, e.g., {@code myGroup.resetCountToIndex()}. + * + *

      The supplied token must carry a {@link Signal#BEGIN_GROUP} signal. + * + * @param token the token identifying the group + * @return the {@link CodecInteraction} instance + */ + public CodecInteraction resetCountToIndex(final Token token) + { + return resetCountToIndexInteractions.computeIfAbsent(token, + t -> new ResetCountToIndex(groupPathsByField.get(t), t)); + } + + /** + * Find or create a {@link CodecInteraction} to represent accessing the length + * of a variable-length data field without advancing the codec position. + * + *

      For decoders and codecs, this will be when the length is accessed, e.g., + * {@code decoder.myVarDataLength()}. + * + *

      The supplied token must carry a {@link Signal#BEGIN_VAR_DATA} signal. + * + * @param token the token identifying the field + * @return the {@link CodecInteraction} instance + */ + public CodecInteraction accessVarDataLength(final Token token) + { + return accessVarDataLengthInteractions.computeIfAbsent(token, + t -> new AccessVarDataLength(groupPathsByField.get(t), t)); + } + } + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/PrecedenceChecks.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/PrecedenceChecks.java new file mode 100644 index 0000000000..9825a3e6b7 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/PrecedenceChecks.java @@ -0,0 +1,253 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.common; + +import uk.co.real_logic.sbe.ir.Token; + +import java.util.ArrayList; +import java.util.List; +import java.util.OptionalInt; +import java.util.function.Function; +import java.util.stream.IntStream; + +import static java.util.Objects.requireNonNull; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData; + +/** + * A factory for creating a {@link FieldPrecedenceModel} for a message from its IR tokens. + */ +public final class PrecedenceChecks +{ + private static final Function SELECT_LATEST_VERSION_ONLY = versions -> + { + final OptionalInt max = versions.max(); + return max.isPresent() ? IntStream.of(max.getAsInt()) : IntStream.empty(); + }; + + private final Context context; + + private PrecedenceChecks(final Context context) + { + context.conclude(); + this.context = context; + } + + /** + * Creates a {@link FieldPrecedenceModel} for the given message tokens, + * unless precedence checks are disabled, in which case {@code null} is returned. + *

      + * Only the latest version of the message is considered when creating the model. + *

      + * + * @param stateClassName the name of the generated class that models the state of the encoder. + * @param msgTokens the tokens of the message. + * @return a {@link FieldPrecedenceModel} for the given message tokens or {@code null} if precedence checks + * are disabled. + */ + public FieldPrecedenceModel createEncoderModel( + final String stateClassName, + final List msgTokens) + { + return createModel(stateClassName, msgTokens, SELECT_LATEST_VERSION_ONLY); + } + + /** + * Creates a {@link FieldPrecedenceModel} for the given message tokens, + * unless precedence checks are disabled, in which case {@code null} is returned. + *

      + * All versions of the message are considered when creating the model. + *

      + * + * @param stateClassName the name of the generated class that models the state of the decoder. + * @param msgTokens the tokens of the message. + * @return a {@link FieldPrecedenceModel} for the given message tokens or {@code null} if precedence checks + * are disabled. + */ + public FieldPrecedenceModel createDecoderModel( + final String stateClassName, + final List msgTokens) + { + return createModel(stateClassName, msgTokens, Function.identity()); + } + + /** + * Creates a {@link FieldPrecedenceModel} for the given message tokens, + * unless precedence checks are disabled, in which case {@code null} is returned. + *

      + * All versions of the message are considered when creating the model. + *

      + * + * @param stateClassName the name of the generated class that models the state of the codec. + * @param msgTokens the tokens of the message. + * @return a {@link FieldPrecedenceModel} for the given message tokens or {@code null} if precedence checks + * are disabled. + */ + public FieldPrecedenceModel createCodecModel( + final String stateClassName, + final List msgTokens + ) + { + return createModel(stateClassName, msgTokens, Function.identity()); + } + + /** + * Returns the {@link Context} describing how precedence checks should be generated. + * + * @return the {@link Context} describing how precedence checks should be generated. + */ + public Context context() + { + return context; + } + + /** + * Creates a new {@link PrecedenceChecks} instance. + * + * @param context the {@link Context} describing how precedence checks should be generated. + * @return a new {@link PrecedenceChecks} instance. + */ + public static PrecedenceChecks newInstance(final Context context) + { + return new PrecedenceChecks(context); + } + + private FieldPrecedenceModel createModel( + final String stateClassName, + final List tokens, + final Function versionsSelector + ) + { + if (context.shouldGeneratePrecedenceChecks()) + { + final Token msgToken = tokens.get(0); + + final List messageBody = tokens.subList(1, tokens.size() - 1); + int i = 0; + + final List fields = new ArrayList<>(); + i = collectFields(messageBody, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(messageBody, i, groups); + + final List varData = new ArrayList<>(); + collectVarData(messageBody, i, varData); + + return FieldPrecedenceModel.newInstance( + stateClassName, + msgToken, + fields, + groups, + varData, + versionsSelector); + } + + return null; + } + + /** + * The context describing how precedence checks should be generated. + */ + public static final class Context + { + private boolean shouldGeneratePrecedenceChecks; + private String precedenceChecksFlagName = "SBE_ENABLE_PRECEDENCE_CHECKS"; + private String precedenceChecksPropName = "sbe.enable.precedence.checks"; + + /** + * Returns {@code true} if precedence checks should be generated; {@code false} otherwise. + * + * @return {@code true} if precedence checks should be generated; {@code false} otherwise. + */ + public boolean shouldGeneratePrecedenceChecks() + { + return shouldGeneratePrecedenceChecks; + } + + /** + * Sets whether field precedence checks should be generated. + * + * @param shouldGeneratePrecedenceChecks {@code true} if precedence checks should be generated; + * {@code false} otherwise. + * @return this {@link Context} instance. + */ + public Context shouldGeneratePrecedenceChecks(final boolean shouldGeneratePrecedenceChecks) + { + this.shouldGeneratePrecedenceChecks = shouldGeneratePrecedenceChecks; + return this; + } + + /** + * Returns the name of the flag that can be used to enable precedence checks at runtime. + * + * @return the name of the flag that can be used to enable precedence checks at runtime. + */ + public String precedenceChecksFlagName() + { + return precedenceChecksFlagName; + } + + /** + * Sets the name of the flag that can be used to enable precedence checks at runtime. + * + * @param precedenceChecksFlagName the name of the flag that can be used to enable + * precedence checks at runtime. + * @return this {@link Context} instance. + */ + public Context precedenceChecksFlagName(final String precedenceChecksFlagName) + { + this.precedenceChecksFlagName = precedenceChecksFlagName; + return this; + } + + /** + * Returns the name of the system property that can be used to enable precedence checks + * at runtime. + * + * @return the name of the system property that can be used to enable precedence checks + * at runtime. + */ + public String precedenceChecksPropName() + { + return precedenceChecksPropName; + } + + /** + * Sets the name of the system property that can be used to enable precedence checks + * at runtime. + * + * @param precedenceChecksPropName the name of the system property that can be used to + * enable precedence checks at runtime. + * @return this {@link Context} instance. + */ + public Context precedenceChecksPropName(final String precedenceChecksPropName) + { + this.precedenceChecksPropName = precedenceChecksPropName; + return this; + } + + /** + * Validates this {@link Context} instance. + */ + public void conclude() + { + requireNonNull(precedenceChecksFlagName, "precedenceChecksFlagName"); + requireNonNull(precedenceChecksPropName, "precedenceChecksPropName"); + } + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index f52d4695eb..b47e1d2f4a 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -15,23 +15,24 @@ */ package uk.co.real_logic.sbe.generation.cpp; -import org.agrona.Strings; -import org.agrona.Verify; -import org.agrona.generation.OutputManager; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.generation.CodeGenerator; import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.generation.common.FieldPrecedenceModel; +import uk.co.real_logic.sbe.generation.common.PrecedenceChecks; import uk.co.real_logic.sbe.ir.Encoding; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.ir.Signal; import uk.co.real_logic.sbe.ir.Token; +import org.agrona.Strings; +import org.agrona.Verify; +import org.agrona.collections.MutableBoolean; +import org.agrona.generation.OutputManager; import java.io.IOException; import java.io.Writer; import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.Formatter; -import java.util.List; +import java.util.*; import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; @@ -45,12 +46,18 @@ @SuppressWarnings("MethodLength") public class CppGenerator implements CodeGenerator { + private static final boolean DISABLE_IMPLICIT_COPYING = Boolean.parseBoolean( + System.getProperty("sbe.cpp.disable.implicit.copying", "false")); private static final String BASE_INDENT = ""; private static final String INDENT = " "; + private static final String TWO_INDENT = INDENT + INDENT; + private static final String THREE_INDENT = TWO_INDENT + INDENT; private final Ir ir; private final OutputManager outputManager; private final boolean shouldDecodeUnknownEnumValues; + private final PrecedenceChecks precedenceChecks; + private final String precedenceChecksFlagName; /** * Create a new Cpp language {@link CodeGenerator}. @@ -60,12 +67,36 @@ public class CppGenerator implements CodeGenerator * @param outputManager for generating the codecs to. */ public CppGenerator(final Ir ir, final boolean shouldDecodeUnknownEnumValues, final OutputManager outputManager) + { + this( + ir, + shouldDecodeUnknownEnumValues, + PrecedenceChecks.newInstance(new PrecedenceChecks.Context()), + outputManager + ); + } + + /** + * Create a new Go language {@link CodeGenerator}. + * + * @param ir for the messages and types. + * @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding. + * @param precedenceChecks whether and how to generate field precedence checks. + * @param outputManager for generating the codecs to. + */ + public CppGenerator( + final Ir ir, + final boolean shouldDecodeUnknownEnumValues, + final PrecedenceChecks precedenceChecks, + final OutputManager outputManager) { Verify.notNull(ir, "ir"); Verify.notNull(outputManager, "outputManager"); this.ir = ir; this.shouldDecodeUnknownEnumValues = shouldDecodeUnknownEnumValues; + this.precedenceChecks = precedenceChecks; + this.precedenceChecksFlagName = precedenceChecks.context().precedenceChecksFlagName(); this.outputManager = outputManager; } @@ -143,12 +174,11 @@ public void generate() throws IOException { final Token msgToken = tokens.get(0); final String className = formatClassName(msgToken.name()); + final String stateClassName = className + "::CodecState"; + final FieldPrecedenceModel fieldPrecedenceModel = precedenceChecks.createCodecModel(stateClassName, tokens); try (Writer out = outputManager.createOutput(className)) { - out.append(generateFileHeader(ir.namespaces(), className, typesToInclude)); - out.append(generateClassDeclaration(className)); - out.append(generateMessageFlyweightCode(className, msgToken)); final List messageBody = tokens.subList(1, tokens.size() - 1); int i = 0; @@ -162,20 +192,393 @@ public void generate() throws IOException final List varData = new ArrayList<>(); collectVarData(messageBody, i, varData); + out.append(generateFileHeader(ir.namespaces(), className, typesToInclude)); + out.append(generateClassDeclaration(className)); + out.append(generateMessageFlyweightCode(className, msgToken, fieldPrecedenceModel)); + out.append(generateFullyEncodedCheck(fieldPrecedenceModel)); + final StringBuilder sb = new StringBuilder(); - generateFields(sb, className, fields, BASE_INDENT); - generateGroups(sb, groups, BASE_INDENT); - generateVarData(sb, className, varData, BASE_INDENT); + generateFields(sb, className, fields, fieldPrecedenceModel, BASE_INDENT); + generateGroups(sb, groups, fieldPrecedenceModel, BASE_INDENT); + generateVarData(sb, className, varData, fieldPrecedenceModel, BASE_INDENT); generateDisplay(sb, msgToken.name(), fields, groups, varData); sb.append(generateMessageLength(groups, varData, BASE_INDENT)); sb.append("};\n"); + generateLookupTableDefinitions(sb, className, fieldPrecedenceModel); sb.append(CppUtil.closingBraces(ir.namespaces().length)).append("#endif\n"); out.append(sb); } } } - private void generateGroups(final StringBuilder sb, final List tokens, final String indent) + private CharSequence generateFullyEncodedCheck(final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final String indent = " "; + final StringBuilder sb = new StringBuilder(); + sb.append("\n"); + + sb.append(indent).append("void checkEncodingIsComplete()\n") + .append(indent).append("{\n") + .append("#if defined(").append(precedenceChecksFlagName).append(")\n") + .append(indent).append(INDENT).append("switch (m_codecState)\n") + .append(indent).append(INDENT).append("{\n"); + + fieldPrecedenceModel.forEachTerminalEncoderState(state -> + { + sb.append(indent).append(TWO_INDENT).append("case ").append(stateCaseForSwitchCase(state)).append(":\n") + .append(indent).append(THREE_INDENT).append("return;\n"); + }); + + sb.append(indent).append(TWO_INDENT).append("default:\n") + .append(indent).append(THREE_INDENT) + .append("throw AccessOrderError(std::string(\"Not fully encoded, current state: \") +\n") + .append(indent).append(THREE_INDENT) + .append(INDENT).append("codecStateName(m_codecState) + \", allowed transitions: \" +\n") + .append(indent).append(THREE_INDENT) + .append(INDENT).append("codecStateTransitions(m_codecState));\n") + .append(indent).append(INDENT).append("}\n") + .append("#endif\n"); + + sb.append(indent).append("}\n\n"); + + return sb; + } + + private static String accessOrderListenerMethodName(final Token token) + { + return "on" + Generators.toUpperFirstChar(token.name()) + "Accessed"; + } + + private static String accessOrderListenerMethodName(final Token token, final String suffix) + { + return "on" + Generators.toUpperFirstChar(token.name()) + suffix + "Accessed"; + } + + private static void generateAccessOrderListenerMethod( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + final FieldPrecedenceModel.CodecInteraction fieldAccess = + fieldPrecedenceModel.interactionFactory().accessField(token); + + final String constDeclaration = canChangeState(fieldPrecedenceModel, fieldAccess) ? "" : " const"; + + sb.append("\n") + .append(indent).append("private:\n") + .append(indent).append(INDENT).append("void ").append(accessOrderListenerMethodName(token)).append("()") + .append(constDeclaration).append("\n") + .append(indent).append(INDENT).append("{\n"); + + generateAccessOrderListener( + sb, + indent + TWO_INDENT, + "access field", + fieldPrecedenceModel, + fieldAccess); + + sb.append(indent).append(INDENT).append("}\n\n") + .append(indent).append("public:"); + } + + private static boolean canChangeState( + final FieldPrecedenceModel fieldPrecedenceModel, + final FieldPrecedenceModel.CodecInteraction fieldAccess) + { + if (fieldAccess.isTopLevelBlockFieldAccess()) + { + return false; + } + + final MutableBoolean canChangeState = new MutableBoolean(false); + fieldPrecedenceModel.forEachTransition(fieldAccess, transition -> + { + if (!transition.alwaysEndsInStartState()) + { + canChangeState.set(true); + } + }); + + return canChangeState.get(); + } + + private CharSequence generateAccessOrderListenerCall( + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token, + final String... arguments) + { + return generateAccessOrderListenerCall( + fieldPrecedenceModel, + indent, + accessOrderListenerMethodName(token), + arguments); + } + + private CharSequence generateAccessOrderListenerCall( + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final String methodName, + final String... arguments) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + sb.append("#if defined(").append(precedenceChecksFlagName).append(")\n") + .append(indent).append(methodName).append("("); + + for (int i = 0; i < arguments.length; i++) + { + if (i > 0) + { + sb.append(", "); + } + sb.append(arguments[i]); + } + sb.append(");\n"); + + sb.append("#endif\n"); + + return sb; + } + + private static void generateAccessOrderListenerMethodForGroupWrap( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append("\n") + .append(indent).append("private:\n") + .append(indent).append(INDENT).append("void ").append(accessOrderListenerMethodName(token)) + .append("(std::uint64_t remaining, std::string action)\n") + .append(indent).append(INDENT).append("{\n") + .append(indent).append(TWO_INDENT).append("if (0 == remaining)\n") + .append(indent).append(TWO_INDENT).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction selectEmptyGroup = + fieldPrecedenceModel.interactionFactory().determineGroupIsEmpty(token); + + generateAccessOrderListener( + sb, + indent + THREE_INDENT, + "\" + action + \" count of repeating group", + fieldPrecedenceModel, + selectEmptyGroup); + + sb.append(indent).append(TWO_INDENT).append("}\n") + .append(indent).append(TWO_INDENT).append("else\n") + .append(indent).append(TWO_INDENT).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction selectNonEmptyGroup = + fieldPrecedenceModel.interactionFactory().determineGroupHasElements(token); + + generateAccessOrderListener( + sb, + indent + THREE_INDENT, + "\" + action + \" count of repeating group", + fieldPrecedenceModel, + selectNonEmptyGroup); + + sb.append(indent).append(TWO_INDENT).append("}\n") + .append(indent).append(INDENT).append("}\n\n") + .append(indent).append("public:"); + } + + private static void generateAccessOrderListenerMethodForVarDataLength( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append("\n") + .append(indent).append("private:\n") + .append(indent).append(INDENT).append("void ").append(accessOrderListenerMethodName(token, "Length")) + .append("() const\n") + .append(indent).append(INDENT).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction accessLength = + fieldPrecedenceModel.interactionFactory().accessVarDataLength(token); + + generateAccessOrderListener( + sb, + indent + TWO_INDENT, + "decode length of var data", + fieldPrecedenceModel, + accessLength); + + sb.append(indent).append(INDENT).append("}\n\n") + .append(indent).append("public:"); + } + + private static void generateAccessOrderListener( + final StringBuilder sb, + final String indent, + final String action, + final FieldPrecedenceModel fieldPrecedenceModel, + final FieldPrecedenceModel.CodecInteraction interaction) + { + if (interaction.isTopLevelBlockFieldAccess()) + { + sb.append(indent).append("if (codecState() == ") + .append(qualifiedStateCase(fieldPrecedenceModel.notWrappedState())) + .append(")\n") + .append(indent).append("{\n"); + generateAccessOrderException(sb, indent + INDENT, action, fieldPrecedenceModel, interaction); + sb.append(indent).append("}\n"); + } + else + { + sb.append(indent).append("switch (codecState())\n") + .append(indent).append("{\n"); + + fieldPrecedenceModel.forEachTransition(interaction, transitionGroup -> + { + + transitionGroup.forEachStartState(startState -> + { + sb.append(indent).append(INDENT) + .append("case ").append(stateCaseForSwitchCase(startState)).append(":\n"); + }); + + if (!transitionGroup.alwaysEndsInStartState()) + { + sb.append(indent).append(TWO_INDENT).append("codecState(") + .append(qualifiedStateCase(transitionGroup.endState())).append(");\n"); + } + + sb.append(indent).append(TWO_INDENT).append("break;\n"); + }); + + sb.append(indent).append(INDENT).append("default:\n"); + generateAccessOrderException(sb, indent + TWO_INDENT, action, fieldPrecedenceModel, interaction); + sb.append(indent).append("}\n"); + } + } + + private static void generateAccessOrderException( + final StringBuilder sb, + final String indent, + final String action, + final FieldPrecedenceModel fieldPrecedenceModel, + final FieldPrecedenceModel.CodecInteraction interaction) + { + sb.append(indent).append("throw AccessOrderError(") + .append("std::string(\"Illegal field access order. \") +\n") + .append(indent).append(INDENT) + .append("\"Cannot ").append(action).append(" \\\"").append(interaction.groupQualifiedName()) + .append("\\\" in state: \" + codecStateName(codecState()) +\n") + .append(indent).append(INDENT) + .append("\". Expected one of these transitions: [\" + codecStateTransitions(codecState()) +\n") + .append(indent).append(INDENT) + .append("\"]. Please see the diagram in the docs of the enum ") + .append(fieldPrecedenceModel.generatedRepresentationClassName()).append(".\");\n"); + } + + private static void generateAccessOrderListenerMethodForNextGroupElement( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append("\n"); + + sb.append(indent).append(INDENT).append("void onNextElementAccessed()\n") + .append(indent).append(INDENT).append("{\n") + .append(indent).append(TWO_INDENT).append("std::uint64_t remaining = m_count - m_index;\n") + .append(indent).append(TWO_INDENT).append("if (remaining > 1)\n") + .append(indent).append(TWO_INDENT).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction selectNextElementInGroup = + fieldPrecedenceModel.interactionFactory().moveToNextElement(token); + + generateAccessOrderListener( + sb, + indent + THREE_INDENT, + "access next element in repeating group", + fieldPrecedenceModel, + selectNextElementInGroup); + + sb.append(indent).append(TWO_INDENT).append("}\n") + .append(indent).append(TWO_INDENT).append("else if (1 == remaining)\n") + .append(indent).append(TWO_INDENT).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction selectLastElementInGroup = + fieldPrecedenceModel.interactionFactory().moveToLastElement(token); + + generateAccessOrderListener( + sb, + indent + THREE_INDENT, + "access next element in repeating group", + fieldPrecedenceModel, + selectLastElementInGroup); + + sb.append(indent).append(TWO_INDENT).append("}\n") + .append(indent).append(INDENT).append("}\n"); + } + + private static void generateAccessOrderListenerMethodForResetGroupCount( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append("\n") + .append(indent).append(INDENT).append("void onResetCountToIndex()\n") + .append(indent).append(INDENT).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction resetCountToIndex = + fieldPrecedenceModel.interactionFactory().resetCountToIndex(token); + + generateAccessOrderListener( + sb, + indent + TWO_INDENT, + "reset count of repeating group", + fieldPrecedenceModel, + resetCountToIndex); + + sb.append(indent).append(INDENT).append("}\n"); + } + + private void generateGroups( + final StringBuilder sb, + final List tokens, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent) { for (int i = 0, size = tokens.size(); i < size; i++) { @@ -189,7 +592,7 @@ private void generateGroups(final StringBuilder sb, final List tokens, fi final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, i); final String cppTypeForNumInGroup = cppTypeName(numInGroupToken.encoding().primitiveType()); - generateGroupClassHeader(sb, groupName, tokens, i, indent + INDENT); + generateGroupClassHeader(sb, groupName, groupToken, tokens, fieldPrecedenceModel, i, indent + INDENT); ++i; final int groupHeaderTokenCount = tokens.get(i).componentTokenCount(); @@ -197,26 +600,32 @@ private void generateGroups(final StringBuilder sb, final List tokens, fi final List fields = new ArrayList<>(); i = collectFields(tokens, i, fields); - generateFields(sb, formatClassName(groupName), fields, indent + INDENT); + generateFields(sb, formatClassName(groupName), fields, fieldPrecedenceModel, indent + INDENT); final List groups = new ArrayList<>(); i = collectGroups(tokens, i, groups); - generateGroups(sb, groups, indent + INDENT); + generateGroups(sb, groups, fieldPrecedenceModel, indent + INDENT); final List varData = new ArrayList<>(); i = collectVarData(tokens, i, varData); - generateVarData(sb, formatClassName(groupName), varData, indent + INDENT); + generateVarData(sb, formatClassName(groupName), varData, fieldPrecedenceModel, indent + INDENT); sb.append(generateGroupDisplay(groupName, fields, groups, varData, indent + INDENT + INDENT)); sb.append(generateMessageLength(groups, varData, indent + INDENT + INDENT)); sb.append(indent).append(" };\n"); - generateGroupProperty(sb, groupName, groupToken, cppTypeForNumInGroup, indent); + generateGroupProperty(sb, groupName, groupToken, cppTypeForNumInGroup, fieldPrecedenceModel, indent); } } - private static void generateGroupClassHeader( - final StringBuilder sb, final String groupName, final List tokens, final int index, final String indent) + private void generateGroupClassHeader( + final StringBuilder sb, + final String groupName, + final Token groupToken, + final List tokens, + final FieldPrecedenceModel fieldPrecedenceModel, + final int index, + final String indent) { final String dimensionsClassName = formatClassName(tokens.get(index + 1).name()); final int dimensionHeaderLength = tokens.get(index + 1).encodedLength(); @@ -226,6 +635,8 @@ private static void generateGroupClassHeader( final String cppTypeBlockLength = cppTypeName(blockLengthToken.encoding().primitiveType()); final String cppTypeNumInGroup = cppTypeName(numInGroupToken.encoding().primitiveType()); + final String groupClassName = formatClassName(groupName); + new Formatter(sb).format("\n" + indent + "class %1$s\n" + indent + "{\n" + @@ -243,17 +654,50 @@ private static void generateGroupClassHeader( indent + " SBE_NODISCARD std::uint64_t *sbePositionPtr() SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return m_positionPtr;\n" + - indent + " }\n\n" + + indent + " }\n\n", + groupClassName); - indent + "public:\n", - formatClassName(groupName)); + if (null != fieldPrecedenceModel) + { + new Formatter(sb).format( + indent + " CodecState *m_codecStatePtr = nullptr;\n\n" + + + indent + " CodecState codecState() const SBE_NOEXCEPT\n" + + indent + " {\n" + + indent + " return *m_codecStatePtr;\n" + + indent + " }\n\n" + + + indent + " CodecState *codecStatePtr()\n" + + indent + " {\n" + + indent + " return m_codecStatePtr;\n" + + indent + " }\n\n" + + + indent + " void codecState(CodecState codecState)\n" + + indent + " {\n" + + indent + " *m_codecStatePtr = codecState;\n" + + indent + " }\n\n" + ); + } + + sb.append(generateHiddenCopyConstructor(indent + " ", groupClassName)); + + final String codecStateParameter = null == fieldPrecedenceModel ? + ")\n" : + ",\n " + indent + " CodecState *codecState)\n"; + + final String codecStateAssignment = null == fieldPrecedenceModel ? + "" : + indent + " m_codecStatePtr = codecState;\n"; new Formatter(sb).format( + indent + "public:\n" + + indent + " %5$s() = default;\n\n" + + indent + " inline void wrapForDecode(\n" + indent + " char *buffer,\n" + indent + " std::uint64_t *pos,\n" + indent + " const std::uint64_t actingVersion,\n" + - indent + " const std::uint64_t bufferLength)\n" + + indent + " const std::uint64_t bufferLength%3$s" + indent + " {\n" + indent + " %2$s dimensions(buffer, *pos, bufferLength, actingVersion);\n" + indent + " m_buffer = buffer;\n" + @@ -265,8 +709,13 @@ private static void generateGroupClassHeader( indent + " m_initialPosition = *pos;\n" + indent + " m_positionPtr = pos;\n" + indent + " *m_positionPtr = *m_positionPtr + %1$d;\n" + + "%4$s" + indent + " }\n", - dimensionHeaderLength, dimensionsClassName); + dimensionHeaderLength, + dimensionsClassName, + codecStateParameter, + codecStateAssignment, + groupClassName); final long minCount = numInGroupToken.encoding().applicableMinValue().longValue(); final String minCheck = minCount > 0 ? "count < " + minCount + " || " : ""; @@ -277,7 +726,7 @@ private static void generateGroupClassHeader( indent + " const %3$s count,\n" + indent + " std::uint64_t *pos,\n" + indent + " const std::uint64_t actingVersion,\n" + - indent + " const std::uint64_t bufferLength)\n" + + indent + " const std::uint64_t bufferLength%8$s" + indent + " {\n" + indent + "#if defined(__GNUG__) && !defined(__clang__)\n" + indent + "#pragma GCC diagnostic push\n" + @@ -302,6 +751,7 @@ private static void generateGroupClassHeader( indent + " m_initialPosition = *pos;\n" + indent + " m_positionPtr = pos;\n" + indent + " *m_positionPtr = *m_positionPtr + %4$d;\n" + + "%9$s" + indent + " }\n", cppTypeBlockLength, blockLength, @@ -309,7 +759,43 @@ private static void generateGroupClassHeader( dimensionHeaderLength, minCheck, numInGroupToken.encoding().applicableMaxValue().longValue(), - dimensionsClassName); + dimensionsClassName, + codecStateParameter, + codecStateAssignment); + + if (groupToken.version() > 0) + { + final String codecStateNullAssignment = null == fieldPrecedenceModel ? + "" : + indent + " m_codecStatePtr = nullptr;\n"; + + new Formatter(sb).format( + indent + " inline void notPresent(std::uint64_t actingVersion)\n" + + indent + " {\n" + + indent + " m_buffer = nullptr;\n" + + indent + " m_bufferLength = 0;\n" + + indent + " m_blockLength = 0;\n" + + indent + " m_count = 0;\n" + + indent + " m_index = 0;\n" + + indent + " m_actingVersion = actingVersion;\n" + + indent + " m_initialPosition = 0;\n" + + indent + " m_positionPtr = nullptr;\n" + + "%1$s" + + indent + " }\n", + codecStateNullAssignment); + } + + + if (null != fieldPrecedenceModel) + { + sb.append("\n").append(indent).append("private:"); + generateAccessOrderListenerMethodForNextGroupElement(sb, fieldPrecedenceModel, indent, groupToken); + generateAccessOrderListenerMethodForResetGroupCount(sb, fieldPrecedenceModel, indent, groupToken); + sb.append("\n").append(indent).append("public:"); + } + + final CharSequence onNextAccessOrderCall = null == fieldPrecedenceModel ? "" : + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + TWO_INDENT, "onNextElementAccessed"); new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t sbeHeaderSize() SBE_NOEXCEPT\n" + @@ -358,6 +844,7 @@ private static void generateGroupClassHeader( indent + " {\n" + indent + " throw std::runtime_error(\"index >= count [E108]\");\n" + indent + " }\n" + + "%4$s" + indent + " m_offset = *m_positionPtr;\n" + indent + " if (SBE_BOUNDS_CHECK_EXPECT(((m_offset + m_blockLength) > m_bufferLength), false))\n" + indent + " {\n" + @@ -370,11 +857,13 @@ private static void generateGroupClassHeader( indent + " }\n", dimensionHeaderLength, blockLength, - formatClassName(groupName)); + groupClassName, + onNextAccessOrderCall); sb.append("\n") .append(indent).append(" inline std::uint64_t resetCountToIndex()\n") .append(indent).append(" {\n") + .append(generateAccessOrderListenerCall(fieldPrecedenceModel, indent + TWO_INDENT, "onResetCountToIndex")) .append(indent).append(" m_count = m_index;\n") .append(indent).append(" ").append(dimensionsClassName) .append(" dimensions(m_buffer, m_initialPosition, m_bufferLength, m_actingVersion);\n") @@ -394,11 +883,12 @@ private static void generateGroupClassHeader( .append(indent).append(" }\n\n"); } - private static void generateGroupProperty( + private void generateGroupProperty( final StringBuilder sb, final String groupName, final Token token, final String cppTypeForNumInGroup, + final FieldPrecedenceModel fieldPrecedenceModel, final String indent) { final String className = formatClassName(groupName); @@ -420,25 +910,76 @@ private static void generateGroupProperty( groupName, token.id()); - new Formatter(sb).format("\n" + - indent + " SBE_NODISCARD inline %1$s &%2$s()\n" + - indent + " {\n" + - indent + " m_%2$s.wrapForDecode(m_buffer, sbePositionPtr(), m_actingVersion, m_bufferLength);\n" + - indent + " return m_%2$s;\n" + - indent + " }\n", - className, - propertyName); + if (null != fieldPrecedenceModel) + { + generateAccessOrderListenerMethodForGroupWrap( + sb, + fieldPrecedenceModel, + indent, + token + ); + } + + final String codecStateArgument = null == fieldPrecedenceModel ? "" : ", codecStatePtr()"; + + final CharSequence onDecodeAccessOrderCall = null == fieldPrecedenceModel ? "" : + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + TWO_INDENT, token, + "m_" + propertyName + ".count()", "\"decode\""); + + if (token.version() > 0) + { + new Formatter(sb).format("\n" + + indent + " SBE_NODISCARD inline %1$s &%2$s()\n" + + indent + " {\n" + + indent + " if (m_actingVersion < %5$du)\n" + + indent + " {\n" + + indent + " m_%2$s.notPresent(m_actingVersion);\n" + + indent + " return m_%2$s;\n" + + indent + " }\n\n" + + + indent + " m_%2$s.wrapForDecode(" + + "m_buffer, sbePositionPtr(), m_actingVersion, m_bufferLength%3$s);\n" + + "%4$s" + + indent + " return m_%2$s;\n" + + indent + " }\n", + className, + propertyName, + codecStateArgument, + onDecodeAccessOrderCall, + token.version()); + } + else + { + new Formatter(sb).format("\n" + + indent + " SBE_NODISCARD inline %1$s &%2$s()\n" + + indent + " {\n" + + indent + " m_%2$s.wrapForDecode(" + + "m_buffer, sbePositionPtr(), m_actingVersion, m_bufferLength%3$s);\n" + + "%4$s" + + indent + " return m_%2$s;\n" + + indent + " }\n", + className, + propertyName, + codecStateArgument, + onDecodeAccessOrderCall); + } + + final CharSequence onEncodeAccessOrderCall = null == fieldPrecedenceModel ? "" : + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + TWO_INDENT, token, "count", "\"encode\""); new Formatter(sb).format("\n" + indent + " %1$s &%2$sCount(const %3$s count)\n" + indent + " {\n" + indent + " m_%2$s.wrapForEncode(" + - "m_buffer, count, sbePositionPtr(), m_actingVersion, m_bufferLength);\n" + + "m_buffer, count, sbePositionPtr(), m_actingVersion, m_bufferLength%4$s);\n" + + "%5$s" + indent + " return m_%2$s;\n" + indent + " }\n", className, propertyName, - cppTypeForNumInGroup); + cppTypeForNumInGroup, + codecStateArgument, + onEncodeAccessOrderCall); final int version = token.version(); final String versionCheck = 0 == version ? @@ -458,7 +999,11 @@ private static void generateGroupProperty( } private void generateVarData( - final StringBuilder sb, final String className, final List tokens, final String indent) + final StringBuilder sb, + final String className, + final List tokens, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent) { for (int i = 0, size = tokens.size(); i < size;) { @@ -480,12 +1025,39 @@ private void generateVarData( generateFieldMetaAttributeMethod(sb, token, indent); generateVarDataDescriptors( - sb, token, propertyName, characterEncoding, lengthToken, lengthOfLengthField, lengthCppType, indent); + sb, token, propertyName, characterEncoding, lengthOfLengthField, indent); + + generateAccessOrderListenerMethodForVarDataLength(sb, fieldPrecedenceModel, indent, token); + + final CharSequence lengthAccessListenerCall = generateAccessOrderListenerCall( + fieldPrecedenceModel, indent + TWO_INDENT, + accessOrderListenerMethodName(token, "Length")); + + new Formatter(sb).format("\n" + + indent + " SBE_NODISCARD %4$s %1$sLength() const\n" + + indent + " {\n" + + "%2$s" + + "%5$s" + + indent + " %4$s length;\n" + + indent + " std::memcpy(&length, m_buffer + sbePosition(), sizeof(%4$s));\n" + + indent + " return %3$s(length);\n" + + indent + " }\n", + toLowerFirstChar(propertyName), + generateArrayFieldNotPresentCondition(token.version(), BASE_INDENT), + formatByteOrderEncoding(lengthToken.encoding().byteOrder(), lengthToken.encoding().primitiveType()), + lengthCppType, + lengthAccessListenerCall); + + generateAccessOrderListenerMethod(sb, fieldPrecedenceModel, indent, token); + + final CharSequence accessOrderListenerCall = + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + TWO_INDENT, token); new Formatter(sb).format("\n" + indent + " std::uint64_t skip%1$s()\n" + indent + " {\n" + "%2$s" + + "%6$s" + indent + " std::uint64_t lengthOfLengthField = %3$d;\n" + indent + " std::uint64_t lengthPosition = sbePosition();\n" + indent + " %5$s lengthFieldValue;\n" + @@ -498,12 +1070,14 @@ private void generateVarData( generateArrayFieldNotPresentCondition(token.version(), indent), lengthOfLengthField, lengthByteOrderStr, - lengthCppType); + lengthCppType, + accessOrderListenerCall); new Formatter(sb).format("\n" + indent + " SBE_NODISCARD const char *%1$s()\n" + indent + " {\n" + "%2$s" + + "%6$s" + indent + " %4$s lengthFieldValue;\n" + indent + " std::memcpy(&lengthFieldValue, m_buffer + sbePosition(), sizeof(%4$s));\n" + indent + " const char *fieldPtr = m_buffer + sbePosition() + %3$d;\n" + @@ -514,12 +1088,14 @@ private void generateVarData( generateTypeFieldNotPresentCondition(token.version(), indent), lengthOfLengthField, lengthCppType, - lengthByteOrderStr); + lengthByteOrderStr, + accessOrderListenerCall); new Formatter(sb).format("\n" + indent + " std::uint64_t get%1$s(char *dst, const std::uint64_t length)\n" + indent + " {\n" + "%2$s" + + "%6$s" + indent + " std::uint64_t lengthOfLengthField = %3$d;\n" + indent + " std::uint64_t lengthPosition = sbePosition();\n" + indent + " sbePosition(lengthPosition + lengthOfLengthField);\n" + @@ -536,11 +1112,13 @@ private void generateVarData( generateArrayFieldNotPresentCondition(token.version(), indent), lengthOfLengthField, lengthByteOrderStr, - lengthCppType); + lengthCppType, + accessOrderListenerCall); new Formatter(sb).format("\n" + indent + " %5$s &put%1$s(const char *src, const %3$s length)\n" + indent + " {\n" + + "%6$s" + indent + " std::uint64_t lengthOfLengthField = %2$d;\n" + indent + " std::uint64_t lengthPosition = sbePosition();\n" + indent + " %3$s lengthFieldValue = %4$s(length);\n" + @@ -558,12 +1136,14 @@ private void generateVarData( lengthOfLengthField, lengthCppType, lengthByteOrderStr, - className); + className, + accessOrderListenerCall); new Formatter(sb).format("\n" + indent + " std::string get%1$sAsString()\n" + indent + " {\n" + "%2$s" + + "%6$s" + indent + " std::uint64_t lengthOfLengthField = %3$d;\n" + indent + " std::uint64_t lengthPosition = sbePosition();\n" + indent + " sbePosition(lengthPosition + lengthOfLengthField);\n" + @@ -579,15 +1159,17 @@ private void generateVarData( generateStringNotPresentCondition(token.version(), indent), lengthOfLengthField, lengthByteOrderStr, - lengthCppType); + lengthCppType, + accessOrderListenerCall); - generateJsonEscapedStringGetter(sb, token, indent, propertyName); + generateJsonEscapedStringGetter(sb, token, indent, propertyName, accessOrderListenerCall); new Formatter(sb).format("\n" + indent + " #if __cplusplus >= 201703L\n" + indent + " std::string_view get%1$sAsStringView()\n" + indent + " {\n" + "%2$s" + + "%6$s" + indent + " std::uint64_t lengthOfLengthField = %3$d;\n" + indent + " std::uint64_t lengthPosition = sbePosition();\n" + indent + " sbePosition(lengthPosition + lengthOfLengthField);\n" + @@ -604,7 +1186,8 @@ private void generateVarData( generateStringViewNotPresentCondition(token.version(), indent), lengthOfLengthField, lengthByteOrderStr, - lengthCppType); + lengthCppType, + accessOrderListenerCall); new Formatter(sb).format("\n" + indent + " %1$s &put%2$s(const std::string &str)\n" + @@ -645,9 +1228,7 @@ private void generateVarDataDescriptors( final Token token, final String propertyName, final String characterEncoding, - final Token lengthToken, final Integer sizeOfLengthField, - final String lengthCppType, final String indent) { new Formatter(sb).format("\n" + @@ -687,19 +1268,6 @@ private void generateVarDataDescriptors( indent + " }\n", toLowerFirstChar(propertyName), sizeOfLengthField); - - new Formatter(sb).format("\n" + - indent + " SBE_NODISCARD %4$s %1$sLength() const\n" + - indent + " {\n" + - "%2$s" + - indent + " %4$s length;\n" + - indent + " std::memcpy(&length, m_buffer + sbePosition(), sizeof(%4$s));\n" + - indent + " return %3$s(length);\n" + - indent + " }\n", - toLowerFirstChar(propertyName), - generateArrayFieldNotPresentCondition(version, BASE_INDENT), - formatByteOrderEncoding(lengthToken.encoding().byteOrder(), lengthToken.encoding().primitiveType()), - lengthCppType); } private void generateChoiceSet(final List tokens) throws IOException @@ -1216,19 +1784,21 @@ private CharSequence generateCompositePropertyElements( switch (fieldToken.signal()) { case ENCODING: - generatePrimitiveProperty(sb, containingClassName, propertyName, fieldToken, fieldToken, indent); + generatePrimitiveProperty(sb, containingClassName, propertyName, fieldToken, fieldToken, + null, indent); break; case BEGIN_ENUM: - generateEnumProperty(sb, containingClassName, fieldToken, propertyName, fieldToken, indent); + generateEnumProperty(sb, containingClassName, fieldToken, propertyName, fieldToken, + null, indent); break; case BEGIN_SET: - generateBitsetProperty(sb, propertyName, fieldToken, indent); + generateBitsetProperty(sb, propertyName, fieldToken, fieldToken, null, indent); break; case BEGIN_COMPOSITE: - generateCompositeProperty(sb, propertyName, fieldToken, indent); + generateCompositeProperty(sb, propertyName, fieldToken, fieldToken, null, indent); break; default: @@ -1247,6 +1817,7 @@ private void generatePrimitiveProperty( final String propertyName, final Token propertyToken, final Token encodingToken, + final FieldPrecedenceModel fieldPrecedenceModel, final String indent) { generatePrimitiveFieldMetaData(sb, propertyName, encodingToken, indent); @@ -1258,7 +1829,7 @@ private void generatePrimitiveProperty( else { generatePrimitivePropertyMethods( - sb, containingClassName, propertyName, propertyToken, encodingToken, indent); + sb, containingClassName, propertyName, propertyToken, encodingToken, fieldPrecedenceModel, indent); } } @@ -1268,16 +1839,19 @@ private void generatePrimitivePropertyMethods( final String propertyName, final Token propertyToken, final Token encodingToken, + final FieldPrecedenceModel fieldPrecedenceModel, final String indent) { final int arrayLength = encodingToken.arrayLength(); if (arrayLength == 1) { - generateSingleValueProperty(sb, containingClassName, propertyName, propertyToken, encodingToken, indent); + generateSingleValueProperty(sb, containingClassName, propertyName, propertyToken, encodingToken, + fieldPrecedenceModel, indent); } else if (arrayLength > 1) { - generateArrayProperty(sb, containingClassName, propertyName, propertyToken, encodingToken, indent); + generateArrayProperty(sb, containingClassName, propertyName, propertyToken, encodingToken, + fieldPrecedenceModel, indent); } } @@ -1405,42 +1979,59 @@ private CharSequence generateStoreValue( return sb; } + private static String noexceptDeclaration(final FieldPrecedenceModel fieldPrecedenceModel) + { + return fieldPrecedenceModel == null ? " SBE_NOEXCEPT" : ""; + } + private void generateSingleValueProperty( final StringBuilder sb, final String containingClassName, final String propertyName, final Token propertyToken, final Token encodingToken, + final FieldPrecedenceModel fieldPrecedenceModel, final String indent) { final PrimitiveType primitiveType = encodingToken.encoding().primitiveType(); final String cppTypeName = cppTypeName(primitiveType); final int offset = encodingToken.offset(); + final CharSequence accessOrderListenerCall = + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + TWO_INDENT, propertyToken); + + final String noexceptDeclaration = noexceptDeclaration(fieldPrecedenceModel); + new Formatter(sb).format("\n" + - indent + " SBE_NODISCARD %1$s %2$s() const SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD %1$s %2$s() const%6$s\n" + indent + " {\n" + "%3$s" + "%4$s" + + "%5$s" + indent + " }\n", cppTypeName, propertyName, generateFieldNotPresentCondition(propertyToken.version(), encodingToken.encoding(), indent), - generateLoadValue(primitiveType, Integer.toString(offset), encodingToken.encoding().byteOrder(), indent)); + accessOrderListenerCall, + generateLoadValue(primitiveType, Integer.toString(offset), encodingToken.encoding().byteOrder(), indent), + noexceptDeclaration); final CharSequence storeValue = generateStoreValue( primitiveType, "", Integer.toString(offset), encodingToken.encoding().byteOrder(), indent); new Formatter(sb).format("\n" + - indent + " %1$s &%2$s(const %3$s value) SBE_NOEXCEPT\n" + + indent + " %1$s &%2$s(const %3$s value)%6$s\n" + indent + " {\n" + "%4$s" + + "%5$s" + indent + " return *this;\n" + indent + " }\n", formatClassName(containingClassName), propertyName, cppTypeName, - storeValue); + storeValue, + accessOrderListenerCall, + noexceptDeclaration); } private void generateArrayProperty( @@ -1449,12 +2040,18 @@ private void generateArrayProperty( final String propertyName, final Token propertyToken, final Token encodingToken, + final FieldPrecedenceModel fieldPrecedenceModel, final String indent) { final PrimitiveType primitiveType = encodingToken.encoding().primitiveType(); final String cppTypeName = cppTypeName(primitiveType); final int offset = encodingToken.offset(); + final CharSequence accessOrderListenerCall = + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + TWO_INDENT, propertyToken); + + final String noexceptDeclaration = noexceptDeclaration(fieldPrecedenceModel); + final int arrayLength = encodingToken.arrayLength(); new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR std::uint64_t %1$sLength() SBE_NOEXCEPT\n" + @@ -1465,24 +2062,30 @@ private void generateArrayProperty( arrayLength); new Formatter(sb).format("\n" + - indent + " SBE_NODISCARD const char *%1$s() const SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD const char *%1$s() const%5$s\n" + indent + " {\n" + "%2$s" + + "%4$s" + indent + " return m_buffer + m_offset + %3$d;\n" + indent + " }\n", propertyName, generateTypeFieldNotPresentCondition(propertyToken.version(), indent), - offset); + offset, + accessOrderListenerCall, + noexceptDeclaration); new Formatter(sb).format("\n" + - indent + " SBE_NODISCARD char *%1$s() SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD char *%1$s()%5$s\n" + indent + " {\n" + "%2$s" + + "%4$s" + indent + " return m_buffer + m_offset + %3$d;\n" + indent + " }\n", propertyName, generateTypeFieldNotPresentCondition(propertyToken.version(), indent), - offset); + offset, + accessOrderListenerCall, + noexceptDeclaration); final CharSequence loadValue = generateLoadValue( primitiveType, @@ -1498,13 +2101,15 @@ private void generateArrayProperty( indent + " throw std::runtime_error(\"index out of range for %2$s [E104]\");\n" + indent + " }\n\n" + "%4$s" + + "%6$s" + "%5$s" + indent + " }\n", cppTypeName, propertyName, arrayLength, generateFieldNotPresentCondition(propertyToken.version(), encodingToken.encoding(), indent), - loadValue); + loadValue, + accessOrderListenerCall); final CharSequence storeValue = generateStoreValue( primitiveType, @@ -1521,6 +2126,7 @@ private void generateArrayProperty( indent + " throw std::runtime_error(\"index out of range for %2$s [E105]\");\n" + indent + " }\n\n" + + "%6$s" + "%5$s" + indent + " return *this;\n" + indent + " }\n", @@ -1528,7 +2134,8 @@ private void generateArrayProperty( propertyName, cppTypeName, arrayLength, - storeValue); + storeValue, + accessOrderListenerCall); new Formatter(sb).format("\n" + indent + " std::uint64_t get%1$s(char *const dst, const std::uint64_t length) const\n" + @@ -1539,6 +2146,7 @@ private void generateArrayProperty( indent + " }\n\n" + "%3$s" + + "%6$s" + indent + " std::memcpy(dst, m_buffer + m_offset + %4$d, " + "sizeof(%5$s) * static_cast(length));\n" + indent + " return length;\n" + @@ -1547,11 +2155,13 @@ private void generateArrayProperty( arrayLength, generateArrayFieldNotPresentCondition(propertyToken.version(), indent), offset, - cppTypeName); + cppTypeName, + accessOrderListenerCall); new Formatter(sb).format("\n" + - indent + " %1$s &put%2$s(const char *const src) SBE_NOEXCEPT\n" + + indent + " %1$s &put%2$s(const char *const src)%7$s\n" + indent + " {\n" + + "%6$s" + indent + " std::memcpy(m_buffer + m_offset + %3$d, src, sizeof(%4$s) * %5$d);\n" + indent + " return *this;\n" + indent + " }\n", @@ -1559,7 +2169,9 @@ private void generateArrayProperty( toUpperFirstChar(propertyName), offset, cppTypeName, - arrayLength); + arrayLength, + accessOrderListenerCall, + noexceptDeclaration); if (arrayLength > 1 && arrayLength <= 4) { @@ -1578,8 +2190,9 @@ private void generateArrayProperty( } } - sb.append(") SBE_NOEXCEPT\n"); + sb.append(")").append(noexceptDeclaration).append("\n"); sb.append(indent).append(" {\n"); + sb.append(accessOrderListenerCall); for (int i = 0; i < arrayLength; i++) { @@ -1601,6 +2214,8 @@ private void generateArrayProperty( new Formatter(sb).format("\n" + indent + " SBE_NODISCARD std::string get%1$sAsString() const\n" + indent + " {\n" + + "%4$s" + + "%5$s" + indent + " const char *buffer = m_buffer + m_offset + %2$d;\n" + indent + " std::size_t length = 0;\n\n" + @@ -1611,14 +2226,18 @@ private void generateArrayProperty( indent + " }\n", toUpperFirstChar(propertyName), offset, - arrayLength); + arrayLength, + generateStringNotPresentCondition(propertyToken.version(), indent), + accessOrderListenerCall); - generateJsonEscapedStringGetter(sb, encodingToken, indent, propertyName); + generateJsonEscapedStringGetter(sb, encodingToken, indent, propertyName, accessOrderListenerCall); new Formatter(sb).format("\n" + indent + " #if __cplusplus >= 201703L\n" + - indent + " SBE_NODISCARD std::string_view get%1$sAsStringView() const SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD std::string_view get%1$sAsStringView() const%6$s\n" + indent + " {\n" + + "%4$s" + + "%5$s" + indent + " const char *buffer = m_buffer + m_offset + %2$d;\n" + indent + " std::size_t length = 0;\n\n" + @@ -1630,7 +2249,10 @@ private void generateArrayProperty( indent + " #endif\n", toUpperFirstChar(propertyName), offset, - arrayLength); + arrayLength, + generateStringViewNotPresentCondition(propertyToken.version(), indent), + accessOrderListenerCall, + noexceptDeclaration); new Formatter(sb).format("\n" + indent + " #if __cplusplus >= 201703L\n" + @@ -1642,6 +2264,7 @@ private void generateArrayProperty( indent + " throw std::runtime_error(\"string too large for put%2$s [E106]\");\n" + indent + " }\n\n" + + "%5$s" + indent + " std::memcpy(m_buffer + m_offset + %3$d, str.data(), srcLength);\n" + indent + " for (std::size_t start = srcLength; start < %4$d; ++start)\n" + indent + " {\n" + @@ -1659,6 +2282,7 @@ private void generateArrayProperty( indent + " throw std::runtime_error(\"string too large for put%2$s [E106]\");\n" + indent + " }\n\n" + + "%5$s" + indent + " std::memcpy(m_buffer + m_offset + %3$d, str.c_str(), srcLength);\n" + indent + " for (std::size_t start = srcLength; start < %4$d; ++start)\n" + indent + " {\n" + @@ -1671,17 +2295,23 @@ private void generateArrayProperty( containingClassName, toUpperFirstChar(propertyName), offset, - arrayLength); + arrayLength, + accessOrderListenerCall); } } private void generateJsonEscapedStringGetter( - final StringBuilder sb, final Token token, final String indent, final String propertyName) + final StringBuilder sb, + final Token token, + final String indent, + final String propertyName, + final CharSequence accessOrderListenerCall) { new Formatter(sb).format("\n" + indent + " std::string get%1$sAsJsonEscapedString()\n" + indent + " {\n" + "%2$s" + + "%3$s" + indent + " std::ostringstream oss;\n" + indent + " std::string s = get%1$sAsString();\n\n" + indent + " for (const auto c : s)\n" + @@ -1710,7 +2340,8 @@ private void generateJsonEscapedStringGetter( indent + " return oss.str();\n" + indent + " }\n", toUpperFirstChar(propertyName), - generateStringNotPresentCondition(token.version(), indent)); + generateStringNotPresentCondition(token.version(), indent), + accessOrderListenerCall); } private void generateConstPropertyMethods( @@ -1797,7 +2428,7 @@ private void generateConstPropertyMethods( values, constantValue.length); - generateJsonEscapedStringGetter(sb, token, indent, propertyName); + generateJsonEscapedStringGetter(sb, token, indent, propertyName, ""); } private CharSequence generateFixedFlyweightCode(final String className, final int size) @@ -1811,6 +2442,7 @@ private CharSequence generateFixedFlyweightCode(final String className, final in " std::uint64_t m_bufferLength = 0;\n" + " std::uint64_t m_offset = 0;\n" + " std::uint64_t m_actingVersion = 0;\n\n" + + "%7$s" + "public:\n" + " enum MetaAttribute\n" + @@ -1869,7 +2501,17 @@ private CharSequence generateFixedFlyweightCode(final String className, final in " const std::uint64_t actingVersion,\n" + " const std::uint64_t bufferLength)\n" + " {\n" + - " return *this = %1$s(buffer, offset, bufferLength, actingVersion);\n" + + " m_buffer = buffer;\n" + + " m_bufferLength = bufferLength;\n" + + " m_offset = offset;\n" + + " m_actingVersion = actingVersion;\n\n" + + + " if (SBE_BOUNDS_CHECK_EXPECT(((m_offset + %2$s) > m_bufferLength), false))\n" + + " {\n" + + " throw std::runtime_error(\"buffer too short for flyweight [E107]\");\n" + + " }\n\n" + + + " return *this;\n" + " }\n\n" + " SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t encodedLength() SBE_NOEXCEPT\n" + @@ -1916,14 +2558,53 @@ private CharSequence generateFixedFlyweightCode(final String className, final in schemaIdType, generateLiteral(ir.headerStructure().schemaIdType(), Integer.toString(ir.id())), schemaVersionType, - generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version()))); + generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), + generateHiddenCopyConstructor(" ", className)); + } + + private static String generateHiddenCopyConstructor(final String indent, final String className) + { + final String ctorAndCopyAssignmentDeletion = String.format( + "#if __cplusplus >= 201103L\n" + + "%1$s%2$s(const %2$s&) = delete;\n" + + "%1$s%2$s& operator=(const %2$s&) = delete;\n" + + "#else\n" + + "%1$s%2$s(const %2$s&);\n" + + "%1$s%2$s& operator=(const %2$s&);\n" + + "#endif\n\n", + indent, className); + + return DISABLE_IMPLICIT_COPYING ? ctorAndCopyAssignmentDeletion : ""; } - private static CharSequence generateConstructorsAndOperators(final String className) + private static CharSequence generateConstructorsAndOperators( + final String className, + final FieldPrecedenceModel fieldPrecedenceModel) { + final String constructorWithCodecState = null == fieldPrecedenceModel ? "" : String.format( + " %1$s(\n" + + " char *buffer,\n" + + " const std::uint64_t offset,\n" + + " const std::uint64_t bufferLength,\n" + + " const std::uint64_t actingBlockLength,\n" + + " const std::uint64_t actingVersion,\n" + + " CodecState codecState) :\n" + + " m_buffer(buffer),\n" + + " m_bufferLength(bufferLength),\n" + + " m_offset(offset),\n" + + " m_position(sbeCheckPosition(offset + actingBlockLength)),\n" + + " m_actingBlockLength(actingBlockLength),\n" + + " m_actingVersion(actingVersion),\n" + + " m_codecState(codecState)\n" + + " {\n" + + " }\n\n", + className); + return String.format( " %1$s() = default;\n\n" + + "%2$s" + + " %1$s(\n" + " char *buffer,\n" + " const std::uint64_t offset,\n" + @@ -1952,10 +2633,14 @@ private static CharSequence generateConstructorsAndOperators(final String classN " %1$s(buffer, 0, bufferLength, actingBlockLength, actingVersion)\n" + " {\n" + " }\n\n", - className); + className, + constructorWithCodecState); } - private CharSequence generateMessageFlyweightCode(final String className, final Token token) + private CharSequence generateMessageFlyweightCode( + final String className, + final Token token, + final FieldPrecedenceModel fieldPrecedenceModel) { final String blockLengthType = cppTypeName(ir.headerStructure().blockLengthType()); final String templateIdType = cppTypeName(ir.headerStructure().templateIdType()); @@ -1965,20 +2650,28 @@ private CharSequence generateMessageFlyweightCode(final String className, final final String headerType = ir.headerStructure().tokens().get(0).name(); final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); + + final String codecStateArgument = null == fieldPrecedenceModel ? "" : ", m_codecState"; + return String.format( "private:\n" + + "%15$s" + + "%16$s" + " char *m_buffer = nullptr;\n" + " std::uint64_t m_bufferLength = 0;\n" + " std::uint64_t m_offset = 0;\n" + " std::uint64_t m_position = 0;\n" + " std::uint64_t m_actingBlockLength = 0;\n" + - " std::uint64_t m_actingVersion = 0;\n\n" + + " std::uint64_t m_actingVersion = 0;\n" + + "%17$s" + " inline std::uint64_t *sbePositionPtr() SBE_NOEXCEPT\n" + " {\n" + " return &m_position;\n" + " }\n\n" + + "%22$s" + + "public:\n" + " static const %1$s SBE_BLOCK_LENGTH = %2$s;\n" + " static const %3$s SBE_TEMPLATE_ID = %4$s;\n" + @@ -2005,7 +2698,9 @@ private CharSequence generateMessageFlyweightCode(final String className, final " using messageHeader = %12$s;\n\n" + + "%18$s" + "%11$s" + + " SBE_NODISCARD static SBE_CONSTEXPR %1$s sbeBlockLength() SBE_NOEXCEPT\n" + " {\n" + " return %2$s;\n" + @@ -2048,7 +2743,14 @@ private CharSequence generateMessageFlyweightCode(final String className, final " %10$s &wrapForEncode(char *buffer, const std::uint64_t offset, const std::uint64_t bufferLength)\n" + " {\n" + - " return *this = %10$s(buffer, offset, bufferLength, sbeBlockLength(), sbeSchemaVersion());\n" + + " m_buffer = buffer;\n" + + " m_bufferLength = bufferLength;\n" + + " m_offset = offset;\n" + + " m_actingBlockLength = sbeBlockLength();\n" + + " m_actingVersion = sbeSchemaVersion();\n" + + " m_position = sbeCheckPosition(m_offset + m_actingBlockLength);\n" + + "%19$s" + + " return *this;\n" + " }\n\n" + " %10$s &wrapAndApplyHeader(" + @@ -2062,14 +2764,18 @@ private CharSequence generateMessageFlyweightCode(final String className, final " .schemaId(sbeSchemaId())\n" + " .version(sbeSchemaVersion());\n\n" + - " return *this = %10$s(\n" + - " buffer,\n" + - " offset + messageHeader::encodedLength(),\n" + - " bufferLength,\n" + - " sbeBlockLength(),\n" + - " sbeSchemaVersion());\n" + + " m_buffer = buffer;\n" + + " m_bufferLength = bufferLength;\n" + + " m_offset = offset + messageHeader::encodedLength();\n" + + " m_actingBlockLength = sbeBlockLength();\n" + + " m_actingVersion = sbeSchemaVersion();\n" + + " m_position = sbeCheckPosition(m_offset + m_actingBlockLength);\n" + + "%19$s" + + " return *this;\n" + " }\n\n" + + "%20$s" + + " %10$s &wrapForDecode(\n" + " char *buffer,\n" + " const std::uint64_t offset,\n" + @@ -2077,7 +2783,14 @@ private CharSequence generateMessageFlyweightCode(final String className, final " const std::uint64_t actingVersion,\n" + " const std::uint64_t bufferLength)\n" + " {\n" + - " return *this = %10$s(buffer, offset, bufferLength, actingBlockLength, actingVersion);\n" + + " m_buffer = buffer;\n" + + " m_bufferLength = bufferLength;\n" + + " m_offset = offset;\n" + + " m_actingBlockLength = actingBlockLength;\n" + + " m_actingVersion = actingVersion;\n" + + " m_position = sbeCheckPosition(m_offset + m_actingBlockLength);\n" + + "%21$s" + + " return *this;\n" + " }\n\n" + " %10$s &sbeRewind()\n" + @@ -2113,7 +2826,7 @@ private CharSequence generateMessageFlyweightCode(final String className, final " SBE_NODISCARD std::uint64_t decodeLength() const\n" + " {\n" + - " %10$s skipper(m_buffer, m_offset, m_bufferLength, sbeBlockLength(), m_actingVersion);\n" + + " %10$s skipper(m_buffer, m_offset, m_bufferLength, sbeBlockLength(), m_actingVersion%14$s);\n" + " skipper.skip();\n" + " return skipper.encodedLength();\n" + " }\n\n" + @@ -2147,15 +2860,269 @@ private CharSequence generateMessageFlyweightCode(final String className, final generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), semanticType, className, - generateConstructorsAndOperators(className), + generateConstructorsAndOperators(className, fieldPrecedenceModel), formatClassName(headerType), - semanticVersion); + semanticVersion, + codecStateArgument, + generateFieldOrderStateEnum(fieldPrecedenceModel), + generateLookupTableDeclarations(fieldPrecedenceModel), + generateFieldOrderStateMember(fieldPrecedenceModel), + generateAccessOrderErrorType(fieldPrecedenceModel), + generateEncoderWrapListener(fieldPrecedenceModel), + generateDecoderWrapListener(fieldPrecedenceModel), + generateDecoderWrapListenerCall(fieldPrecedenceModel), + generateHiddenCopyConstructor(" ", className)); + } + + private CharSequence generateAccessOrderErrorType(final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + sb.append(INDENT).append("class AccessOrderError : public std::logic_error\n") + .append(INDENT).append("{\n") + .append(INDENT).append("public:\n") + .append(INDENT).append(" explicit AccessOrderError(const std::string &msg) : std::logic_error(msg) {}\n") + .append(INDENT).append("};\n\n"); + return sb; + } + + private static CharSequence generateLookupTableDeclarations(final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + sb.append(INDENT).append("static const std::string STATE_NAME_LOOKUP[") + .append(fieldPrecedenceModel.stateCount()) + .append("];\n"); + sb.append(INDENT).append("static const std::string STATE_TRANSITIONS_LOOKUP[") + .append(fieldPrecedenceModel.stateCount()) + .append("];\n\n"); + + sb.append(INDENT).append("static std::string codecStateName(CodecState state)\n") + .append(INDENT).append("{\n") + .append(TWO_INDENT).append("return STATE_NAME_LOOKUP[static_cast(state)];\n") + .append(INDENT).append("}\n\n"); + + sb.append(INDENT).append("static std::string codecStateTransitions(CodecState state)\n") + .append(INDENT).append("{\n") + .append(TWO_INDENT).append("return STATE_TRANSITIONS_LOOKUP[static_cast(state)];\n") + .append(INDENT).append("}\n\n"); + + return sb; + } + + private static void generateLookupTableDefinitions( + final StringBuilder sb, + final String className, + final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append("\n").append("const std::string ").append(className).append("::STATE_NAME_LOOKUP[") + .append(fieldPrecedenceModel.stateCount()).append("] =\n") + .append("{\n"); + fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> + { + sb.append(INDENT).append("\"").append(state.name()).append("\",\n"); + }); + sb.append("};\n\n"); + + sb.append("const std::string ").append(className).append("::STATE_TRANSITIONS_LOOKUP[") + .append(fieldPrecedenceModel.stateCount()).append("] =\n") + .append("{\n"); + fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> + { + sb.append(INDENT).append("\""); + final MutableBoolean isFirst = new MutableBoolean(true); + final Set transitionDescriptions = new HashSet<>(); + fieldPrecedenceModel.forEachTransitionFrom(state, transitionGroup -> + { + if (transitionDescriptions.add(transitionGroup.exampleCode())) + { + if (isFirst.get()) + { + isFirst.set(false); + } + else + { + sb.append(", "); + } + + sb.append("\\\"").append(transitionGroup.exampleCode()).append("\\\""); + } + }); + sb.append("\",\n"); + }); + sb.append("};\n\n"); + } + + private static CharSequence qualifiedStateCase(final FieldPrecedenceModel.State state) + { + return "CodecState::" + state.name(); + } + + private static CharSequence stateCaseForSwitchCase(final FieldPrecedenceModel.State state) + { + return qualifiedStateCase(state); + } + + private static CharSequence unqualifiedStateCase(final FieldPrecedenceModel.State state) + { + return state.name(); + } + + private static CharSequence generateFieldOrderStateEnum(final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + + sb.append(" /**\n"); + sb.append(" * The states in which a encoder/decoder/codec can live.\n"); + sb.append(" *\n"); + sb.append(" *

      The state machine diagram below, encoded in the dot language, describes\n"); + sb.append(" * the valid state transitions according to the order in which fields may be\n"); + sb.append(" * accessed safely. Tools such as PlantUML and Graphviz can render it.\n"); + sb.append(" *\n"); + sb.append(" *

      {@code\n");
      +        fieldPrecedenceModel.generateGraph(sb, "     *   ");
      +        sb.append("     * }
      \n"); + sb.append(" */\n"); + sb.append(INDENT).append("enum class CodecState\n") + .append(INDENT).append("{\n"); + fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> + { + sb.append(INDENT).append(INDENT).append(unqualifiedStateCase(state)) + .append(" = ").append(state.number()) + .append(",\n"); + }); + sb.append(INDENT).append("};\n\n"); + + return sb; + } + + private static CharSequence generateFieldOrderStateMember(final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return "\n"; + } + + final StringBuilder sb = new StringBuilder(); + + sb.append(INDENT).append("CodecState m_codecState = ") + .append(qualifiedStateCase(fieldPrecedenceModel.notWrappedState())) + .append(";\n\n"); + + sb.append(INDENT).append("CodecState codecState() const\n") + .append(INDENT).append("{\n") + .append(INDENT).append(INDENT).append("return m_codecState;\n") + .append(INDENT).append("}\n\n"); + + sb.append(INDENT).append("CodecState *codecStatePtr()\n") + .append(INDENT).append("{\n") + .append(INDENT).append(INDENT).append("return &m_codecState;\n") + .append(INDENT).append("}\n\n"); + + sb.append(INDENT).append("void codecState(CodecState newState)\n") + .append(INDENT).append("{\n") + .append(INDENT).append(INDENT).append("m_codecState = newState;\n") + .append(INDENT).append("}\n\n"); + + return sb; + } + + private static CharSequence generateDecoderWrapListener(final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + if (fieldPrecedenceModel.versionCount() == 1) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + sb.append(INDENT).append("void onWrapForDecode(std::uint64_t actingVersion)\n") + .append(INDENT).append("{\n") + .append(INDENT).append(INDENT).append("switch(actingVersion)\n") + .append(INDENT).append(INDENT).append("{\n"); + + fieldPrecedenceModel.forEachWrappedStateByVersion((version, state) -> + { + sb.append(INDENT).append(TWO_INDENT).append("case ").append(version).append(":\n") + .append(INDENT).append(THREE_INDENT).append("codecState(") + .append(qualifiedStateCase(state)).append(");\n") + .append(INDENT).append(THREE_INDENT).append("break;\n"); + }); + + sb.append(INDENT).append(TWO_INDENT).append("default:\n") + .append(INDENT).append(THREE_INDENT).append("codecState(") + .append(qualifiedStateCase(fieldPrecedenceModel.latestVersionWrappedState())).append(");\n") + .append(INDENT).append(THREE_INDENT).append("break;\n") + .append(INDENT).append(INDENT).append("}\n") + .append(INDENT).append("}\n\n"); + + return sb; + } + + + private CharSequence generateDecoderWrapListenerCall(final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + if (fieldPrecedenceModel.versionCount() == 1) + { + final StringBuilder sb = new StringBuilder(); + sb.append("#if defined(").append(precedenceChecksFlagName).append(")\n") + .append(TWO_INDENT).append("codecState(") + .append(qualifiedStateCase(fieldPrecedenceModel.latestVersionWrappedState())).append(");\n") + .append("#endif\n"); + return sb; + } + + return generateAccessOrderListenerCall(fieldPrecedenceModel, TWO_INDENT, "onWrapForDecode", "actingVersion"); + } + + private CharSequence generateEncoderWrapListener(final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + sb.append("#if defined(").append(precedenceChecksFlagName).append(")\n") + .append(TWO_INDENT).append("codecState(") + .append(qualifiedStateCase(fieldPrecedenceModel.latestVersionWrappedState())) + .append(");\n") + .append("#endif\n"); + return sb; } private void generateFields( final StringBuilder sb, final String containingClassName, final List tokens, + final FieldPrecedenceModel fieldPrecedenceModel, final String indent) { for (int i = 0, size = tokens.size(); i < size; i++) @@ -2169,23 +3136,29 @@ private void generateFields( generateFieldMetaAttributeMethod(sb, signalToken, indent); generateFieldCommonMethods(indent, sb, signalToken, encodingToken, propertyName); + generateAccessOrderListenerMethod(sb, fieldPrecedenceModel, indent, signalToken); + switch (encodingToken.signal()) { case ENCODING: generatePrimitiveProperty( - sb, containingClassName, propertyName, signalToken, encodingToken, indent); + sb, containingClassName, propertyName, signalToken, encodingToken, + fieldPrecedenceModel, indent); break; case BEGIN_ENUM: - generateEnumProperty(sb, containingClassName, signalToken, propertyName, encodingToken, indent); + generateEnumProperty(sb, containingClassName, signalToken, propertyName, encodingToken, + fieldPrecedenceModel, indent); break; case BEGIN_SET: - generateBitsetProperty(sb, propertyName, encodingToken, indent); + generateBitsetProperty(sb, propertyName, signalToken, encodingToken, + fieldPrecedenceModel, indent); break; case BEGIN_COMPOSITE: - generateCompositeProperty(sb, propertyName, encodingToken, indent); + generateCompositeProperty(sb, propertyName, signalToken, encodingToken, + fieldPrecedenceModel, indent); break; default: @@ -2300,6 +3273,7 @@ private void generateEnumProperty( final Token fieldToken, final String propertyName, final Token encodingToken, + final FieldPrecedenceModel fieldPrecedenceModel, final String indent) { final String enumName = formatClassName(encodingToken.applicableTypeName()); @@ -2352,21 +3326,31 @@ private void generateEnumProperty( else { final String offsetStr = Integer.toString(offset); + + final CharSequence accessOrderListenerCall = generateAccessOrderListenerCall( + fieldPrecedenceModel, indent + TWO_INDENT, fieldToken); + + final String noexceptDeclaration = noexceptDeclaration(fieldPrecedenceModel); + new Formatter(sb).format("\n" + - indent + " SBE_NODISCARD %1$s %2$sRaw() const SBE_NOEXCEPT\n" + + indent + " SBE_NODISCARD %1$s %2$sRaw() const%6$s\n" + indent + " {\n" + "%3$s" + "%4$s" + + "%5$s" + indent + " }\n", typeName, propertyName, generateFieldNotPresentCondition(fieldToken.version(), encodingToken.encoding(), indent), - generateLoadValue(primitiveType, offsetStr, encodingToken.encoding().byteOrder(), indent)); + accessOrderListenerCall, + generateLoadValue(primitiveType, offsetStr, encodingToken.encoding().byteOrder(), indent), + noexceptDeclaration); new Formatter(sb).format("\n" + indent + " SBE_NODISCARD %1$s::Value %2$s() const\n" + indent + " {\n" + "%3$s" + + "%7$s" + indent + " %5$s val;\n" + indent + " std::memcpy(&val, m_buffer + m_offset + %6$d, sizeof(%5$s));\n" + indent + " return %1$s::get(%4$s(val));\n" + @@ -2376,11 +3360,13 @@ private void generateEnumProperty( generateEnumFieldNotPresentCondition(fieldToken.version(), enumName, indent), formatByteOrderEncoding(encodingToken.encoding().byteOrder(), primitiveType), typeName, - offset); + offset, + accessOrderListenerCall); new Formatter(sb).format("\n" + - indent + " %1$s &%2$s(const %3$s::Value value) SBE_NOEXCEPT\n" + + indent + " %1$s &%2$s(const %3$s::Value value)%8$s\n" + indent + " {\n" + + "%7$s" + indent + " %4$s val = %6$s(value);\n" + indent + " std::memcpy(m_buffer + m_offset + %5$d, &val, sizeof(%4$s));\n" + indent + " return *this;\n" + @@ -2390,15 +3376,22 @@ private void generateEnumProperty( enumName, typeName, offset, - formatByteOrderEncoding(encodingToken.encoding().byteOrder(), primitiveType)); + formatByteOrderEncoding(encodingToken.encoding().byteOrder(), primitiveType), + accessOrderListenerCall, + noexceptDeclaration); } } - private static void generateBitsetProperty( - final StringBuilder sb, final String propertyName, final Token token, final String indent) + private void generateBitsetProperty( + final StringBuilder sb, + final String propertyName, + final Token fieldToken, + final Token encodingToken, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent) { - final String bitsetName = formatClassName(token.applicableTypeName()); - final int offset = token.offset(); + final String bitsetName = formatClassName(encodingToken.applicableTypeName()); + final int offset = encodingToken.offset(); new Formatter(sb).format("\n" + indent + "private:\n" + @@ -2408,15 +3401,20 @@ private static void generateBitsetProperty( bitsetName, propertyName); + final CharSequence accessOrderListenerCall = generateAccessOrderListenerCall( + fieldPrecedenceModel, indent + TWO_INDENT, fieldToken); + new Formatter(sb).format( indent + " SBE_NODISCARD %1$s &%2$s()\n" + indent + " {\n" + + "%4$s" + indent + " m_%2$s.wrap(m_buffer, m_offset + %3$d, m_actingVersion, m_bufferLength);\n" + indent + " return m_%2$s;\n" + indent + " }\n", bitsetName, propertyName, - offset); + offset, + accessOrderListenerCall); new Formatter(sb).format("\n" + indent + " static SBE_CONSTEXPR std::size_t %1$sEncodingLength() SBE_NOEXCEPT\n" + @@ -2424,13 +3422,18 @@ private static void generateBitsetProperty( indent + " return %2$d;\n" + indent + " }\n", propertyName, - token.encoding().primitiveType().size()); + encodingToken.encoding().primitiveType().size()); } - private static void generateCompositeProperty( - final StringBuilder sb, final String propertyName, final Token token, final String indent) + private void generateCompositeProperty( + final StringBuilder sb, + final String propertyName, + final Token fieldToken, + final Token encodingToken, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent) { - final String compositeName = formatClassName(token.applicableTypeName()); + final String compositeName = formatClassName(encodingToken.applicableTypeName()); new Formatter(sb).format("\n" + "private:\n" + @@ -2440,15 +3443,20 @@ private static void generateCompositeProperty( compositeName, propertyName); + final CharSequence accessOrderListenerCall = generateAccessOrderListenerCall( + fieldPrecedenceModel, indent + TWO_INDENT, fieldToken); + new Formatter(sb).format( indent + " SBE_NODISCARD %1$s &%2$s()\n" + indent + " {\n" + + "%4$s" + indent + " m_%2$s.wrap(m_buffer, m_offset + %3$d, m_actingVersion, m_bufferLength);\n" + indent + " return m_%2$s;\n" + indent + " }\n", compositeName, propertyName, - token.offset()); + encodingToken.offset(), + accessOrderListenerCall); } private CharSequence generateNullValueLiteral(final PrimitiveType primitiveType, final Encoding encoding) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java index 5b4870a321..ee55d214d5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java @@ -18,6 +18,7 @@ import uk.co.real_logic.sbe.generation.CodeGenerator; import uk.co.real_logic.sbe.generation.TargetCodeGenerator; +import uk.co.real_logic.sbe.generation.TargetCodeGeneratorLoader; import uk.co.real_logic.sbe.ir.Ir; /** @@ -30,6 +31,9 @@ public class CSharp implements TargetCodeGenerator */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { - return new CSharpGenerator(ir, new CSharpNamespaceOutputManager(outputDir, ir.applicableNamespace())); + return new CSharpGenerator( + ir, + TargetCodeGeneratorLoader.precedenceChecks(), + new CSharpNamespaceOutputManager(outputDir, ir.applicableNamespace())); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 5a607a8414..8fe17df71a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -19,26 +19,30 @@ import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.PrimitiveValue; import uk.co.real_logic.sbe.generation.CodeGenerator; -import org.agrona.generation.OutputManager; import uk.co.real_logic.sbe.generation.Generators; -import uk.co.real_logic.sbe.ir.*; +import uk.co.real_logic.sbe.generation.common.FieldPrecedenceModel; +import uk.co.real_logic.sbe.generation.common.PrecedenceChecks; +import uk.co.real_logic.sbe.ir.Encoding; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.ir.Signal; +import uk.co.real_logic.sbe.ir.Token; import org.agrona.Verify; +import org.agrona.collections.MutableBoolean; +import org.agrona.generation.OutputManager; import java.io.IOException; import java.io.Writer; import java.nio.ByteOrder; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import static java.lang.System.lineSeparator; - import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; import static uk.co.real_logic.sbe.generation.csharp.CSharpUtil.*; -import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData; -import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; -import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; -import static uk.co.real_logic.sbe.ir.GenerationUtil.findEndSignal; +import static uk.co.real_logic.sbe.ir.GenerationUtil.*; /** * Codec generator for the CSharp programming language. @@ -54,6 +58,8 @@ public class CSharpGenerator implements CodeGenerator private final Ir ir; private final OutputManager outputManager; + private final PrecedenceChecks precedenceChecks; + private final String precedenceChecksFlagName; /** * Create a new C# language {@link CodeGenerator}. @@ -62,11 +68,32 @@ public class CSharpGenerator implements CodeGenerator * @param outputManager for generating the codecs to. */ public CSharpGenerator(final Ir ir, final OutputManager outputManager) + { + this( + ir, + PrecedenceChecks.newInstance(new PrecedenceChecks.Context()), + outputManager + ); + } + + /** + * Create a new C# language {@link CodeGenerator}. + * + * @param ir for the messages and types. + * @param precedenceChecks whether and how to perform field precedence checks. + * @param outputManager for generating the codecs to. + */ + public CSharpGenerator( + final Ir ir, + final PrecedenceChecks precedenceChecks, + final OutputManager outputManager) { Verify.notNull(ir, "ir"); Verify.notNull(outputManager, "outputManager"); this.ir = ir; + this.precedenceChecks = precedenceChecks; + this.precedenceChecksFlagName = precedenceChecks.context().precedenceChecksFlagName(); this.outputManager = outputManager; } @@ -123,32 +150,38 @@ public void generate() throws IOException { final Token msgToken = tokens.get(0); final String className = formatClassName(msgToken.name()); + final String stateClassName = className + ".CodecState"; + final FieldPrecedenceModel fieldPrecedenceModel = precedenceChecks.createCodecModel(stateClassName, tokens); try (Writer out = outputManager.createOutput(className)) { - out.append(generateFileHeader(ir.applicableNamespace())); - out.append(generateDocumentation(BASE_INDENT, msgToken)); - out.append(generateClassDeclaration(className)); - out.append(generateMessageFlyweightCode(className, msgToken, BASE_INDENT)); - final List messageBody = tokens.subList(1, tokens.size() - 1); int offset = 0; - final List fields = new ArrayList<>(); offset = collectFields(messageBody, offset, fields); - out.append(generateFields(fields, BASE_INDENT)); - final List groups = new ArrayList<>(); offset = collectGroups(messageBody, offset, groups); + final List varData = new ArrayList<>(); + collectVarData(messageBody, offset, varData); + + out.append(generateFileHeader(ir.applicableNamespace())); + out.append(generateDocumentation(BASE_INDENT, msgToken)); + out.append(generateClassDeclaration(className)); + out.append(generateMessageFlyweightCode(className, msgToken, fieldPrecedenceModel, BASE_INDENT)); + + out.append(generateFieldOrderStates(BASE_INDENT + INDENT, fieldPrecedenceModel)); + out.append(generateFullyEncodedCheck(BASE_INDENT + INDENT, fieldPrecedenceModel)); + + out.append(generateFields(fieldPrecedenceModel, fields, BASE_INDENT)); + final StringBuilder sb = new StringBuilder(); - generateGroups(sb, className, groups, BASE_INDENT); + generateGroups(sb, className, groups, fieldPrecedenceModel, BASE_INDENT); out.append(sb); - final List varData = new ArrayList<>(); - collectVarData(messageBody, offset, varData); - out.append(generateVarData(varData, BASE_INDENT + INDENT)); + out.append(generateVarData(fieldPrecedenceModel, varData, BASE_INDENT + INDENT)); - out.append(generateDisplay(toUpperFirstChar(msgToken.name()), fields, groups, varData)); + out.append(generateDisplay(toUpperFirstChar(msgToken.name()), + fields, groups, varData, fieldPrecedenceModel)); out.append(INDENT + "}\n"); out.append("}\n"); @@ -160,6 +193,7 @@ private void generateGroups( final StringBuilder sb, final String parentMessageClassName, final List tokens, + final FieldPrecedenceModel fieldPrecedenceModel, final String indent) { for (int i = 0, size = tokens.size(); i < size; i++) @@ -170,23 +204,24 @@ private void generateGroups( throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); } final String groupName = groupToken.name(); - sb.append(generateGroupProperty(groupName, groupToken, indent + INDENT)); + sb.append(generateGroupProperty(groupName, fieldPrecedenceModel, groupToken, indent + INDENT)); - generateGroupClassHeader(sb, groupName, parentMessageClassName, tokens, i, indent + INDENT); + generateGroupClassHeader(sb, groupName, parentMessageClassName, tokens, + fieldPrecedenceModel, i, indent + INDENT); i++; i += tokens.get(i).componentTokenCount(); final List fields = new ArrayList<>(); i = collectFields(tokens, i, fields); - sb.append(generateFields(fields, indent + INDENT)); + sb.append(generateFields(fieldPrecedenceModel, fields, indent + INDENT)); final List groups = new ArrayList<>(); i = collectGroups(tokens, i, groups); - generateGroups(sb, parentMessageClassName, groups, indent + INDENT); + generateGroups(sb, parentMessageClassName, groups, fieldPrecedenceModel, indent + INDENT); final List varData = new ArrayList<>(); i = collectVarData(tokens, i, varData); - sb.append(generateVarData(varData, indent + INDENT + INDENT)); + sb.append(generateVarData(fieldPrecedenceModel, varData, indent + INDENT + INDENT)); appendGroupInstanceDisplay(sb, fields, groups, varData, indent + TWO_INDENT); @@ -199,6 +234,7 @@ private void generateGroupClassHeader( final String groupName, final String parentMessageClassName, final List tokens, + final FieldPrecedenceModel fieldPrecedenceModel, final int index, final String indent) { @@ -232,6 +268,16 @@ private void generateGroupClassHeader( groupName)); } + sb.append("\n") + // The "file" access modifier is more suitable but only available from C# 11 onwards. + .append(indent).append(INDENT).append("internal void NotPresent()\n") + .append(indent).append(INDENT).append("{\n") + .append(indent).append(TWO_INDENT).append("_count = 0;\n") + .append(indent).append(TWO_INDENT).append("_index = 0;\n") + .append(indent).append(TWO_INDENT).append("_buffer = null;\n") + .append(indent).append(TWO_INDENT).append("_offset = 0;\n") + .append(indent).append(INDENT).append("}\n"); + sb.append(String.format("\n" + indent + INDENT + "public void WrapForDecode(%s parentMessage, DirectBuffer buffer, int actingVersion)\n" + indent + INDENT + "{\n" + @@ -284,27 +330,50 @@ private void generateGroupClassHeader( blockLength, dimensionHeaderLength)); - generateGroupEnumerator(sb, groupName, typeForNumInGroup, indent); + if (null != fieldPrecedenceModel) + { + sb.append("\n") + .append(indent).append(" private CodecState codecState()\n") + .append(indent).append(" {\n") + .append(indent).append(" return _parentMessage.codecState();\n") + .append(indent).append(" }\n"); + + sb.append("\n") + .append(indent).append(" private void codecState(CodecState newState)\n") + .append(indent).append(" {\n") + .append(indent).append(" _parentMessage.codecState(newState);\n") + .append(indent).append(" }\n"); + } + + final Token groupToken = tokens.get(index); + generateGroupEnumerator(sb, fieldPrecedenceModel, groupToken, groupName, typeForNumInGroup, indent); } private void generateGroupEnumerator( final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final Token groupToken, final String groupName, final String typeForNumInGroup, final String indent) { + generateAccessOrderListenerMethodForNextGroupElement(sb, fieldPrecedenceModel, indent + INDENT, groupToken); + generateAccessOrderListenerMethodForResetGroupCount(sb, fieldPrecedenceModel, indent + INDENT, groupToken); + sb.append( indent + INDENT + "public int ActingBlockLength { get { return _blockLength; } }\n\n" + indent + INDENT + "public int Count { get { return _count; } }\n\n" + - indent + INDENT + "public bool HasNext { get { return _index < _count; } }\n"); + indent + INDENT + "public bool HasNext { get { return _index < _count; } }\n\n"); sb.append(String.format("\n" + indent + INDENT + "public int ResetCountToIndex()\n" + indent + INDENT + "{\n" + + "%s" + indent + INDENT + INDENT + "_count = _index;\n" + indent + INDENT + INDENT + "_dimensions.NumInGroup = (%s) _count;\n\n" + indent + INDENT + INDENT + "return _count;\n" + indent + INDENT + "}\n", + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + TWO_INDENT, "OnResetCountToIndex"), typeForNumInGroup)); sb.append(String.format("\n" + @@ -314,6 +383,7 @@ private void generateGroupEnumerator( indent + INDENT + INDENT + "{\n" + indent + INDENT + INDENT + INDENT + "ThrowHelper.ThrowInvalidOperationException();\n" + indent + INDENT + INDENT + "}\n\n" + + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + TWO_INDENT, "OnNextElementAccessed") + indent + INDENT + INDENT + "_offset = _parentMessage.Limit;\n" + indent + INDENT + INDENT + "_parentMessage.Limit = _offset + _blockLength;\n" + indent + INDENT + INDENT + "++_index;\n\n" + @@ -338,7 +408,11 @@ private boolean isRepresentableByInt32(final Encoding encoding) encoding.applicableMaxValue().longValue() <= Integer.MAX_VALUE; } - private CharSequence generateGroupProperty(final String groupName, final Token token, final String indent) + private CharSequence generateGroupProperty( + final String groupName, + final FieldPrecedenceModel fieldPrecedenceModel, + final Token token, + final String indent) { final StringBuilder sb = new StringBuilder(); @@ -355,37 +429,65 @@ private CharSequence generateGroupProperty(final String groupName, final Token t toUpperFirstChar(groupName), token.id())); + generateAccessOrderListenerMethodForGroupWrap(sb, fieldPrecedenceModel, indent, token); + generateSinceActingDeprecated(sb, indent, toUpperFirstChar(groupName), token); + final String groupField = "_" + toLowerFirstChar(groupName); + + final CharSequence accessOrderListenerCallOnDecode = generateAccessOrderListenerCall( + fieldPrecedenceModel, + indent + TWO_INDENT, + token, + groupField + ".Count", + "\"decode\""); + sb.append(String.format("\n" + "%1$s" + indent + "public %2$sGroup %3$s\n" + indent + "{\n" + indent + INDENT + "get\n" + indent + INDENT + "{\n" + + "%5$s" + + indent + INDENT + INDENT + "_%4$s.WrapForDecode(_parentMessage, _buffer, _actingVersion);\n" + + "%6$s" + + indent + INDENT + INDENT + "return _%4$s;\n" + indent + INDENT + "}\n" + indent + "}\n", generateDocumentation(indent, token), className, toUpperFirstChar(groupName), - toLowerFirstChar(groupName))); - + toLowerFirstChar(groupName), + generateGroupNotPresentCondition(token.version(), indent + INDENT + INDENT, groupField), + accessOrderListenerCallOnDecode)); + + final CharSequence accessOrderListenerCallOnEncode = generateAccessOrderListenerCall( + fieldPrecedenceModel, + indent + INDENT, + token, + "count", + "\"encode\""); sb.append(String.format("\n" + indent + "public %1$sGroup %2$sCount(int count)\n" + indent + "{\n" + + "%4$s" + indent + INDENT + "_%3$s.WrapForEncode(_parentMessage, _buffer, count);\n" + indent + INDENT + "return _%3$s;\n" + indent + "}\n", className, toUpperFirstChar(groupName), - toLowerFirstChar(groupName))); + toLowerFirstChar(groupName), + accessOrderListenerCallOnEncode)); return sb; } - private CharSequence generateVarData(final List tokens, final String indent) + private CharSequence generateVarData( + final FieldPrecedenceModel fieldPrecedenceModel, + final List tokens, + final String indent) { final StringBuilder sb = new StringBuilder(); @@ -412,21 +514,34 @@ private CharSequence generateVarData(final List tokens, final String inde final ByteOrder byteOrder = lengthEncoding.byteOrder(); final String byteOrderStr = generateByteOrder(byteOrder, lengthEncoding.primitiveType().size()); + generateAccessOrderListenerMethodForVarDataLength(sb, fieldPrecedenceModel, indent, token); + generateAccessOrderListenerMethod(sb, fieldPrecedenceModel, indent, token); + sb.append(String.format("\n" + indent + "public const int %sHeaderSize = %d;\n", propertyName, sizeOfLengthField)); + final CharSequence lengthAccessOrderListenerCall = generateAccessOrderListenerCall( + fieldPrecedenceModel, indent + INDENT, accessOrderListenerMethodName(token, "Length")); + sb.append(String.format(indent + "\n" + indent + "public int %1$sLength()\n" + indent + "{\n" + + "%5$s" + + "%6$s" + indent + INDENT + "_buffer.CheckLimit(_parentMessage.Limit + %2$d);\n" + indent + INDENT + "return (int)_buffer.%3$sGet%4$s(_parentMessage.Limit);\n" + indent + "}\n", propertyName, sizeOfLengthField, lengthTypePrefix, - byteOrderStr)); + byteOrderStr, + generateArrayFieldNotPresentCondition(token.version(), indent, "0"), + lengthAccessOrderListenerCall)); + + final CharSequence accessOrderListenerCall = + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + INDENT, token); sb.append(String.format("\n" + indent + "public int Get%1$s(byte[] dst, int dstOffset, int length) =>\n" + @@ -437,6 +552,7 @@ private CharSequence generateVarData(final List tokens, final String inde indent + "public int Get%1$s(Span dst)\n" + indent + "{\n" + "%2$s" + + "%6$s" + indent + INDENT + "const int sizeOfLengthField = %3$d;\n" + indent + INDENT + "int limit = _parentMessage.Limit;\n" + indent + INDENT + "_buffer.CheckLimit(limit + sizeOfLengthField);\n" + @@ -447,15 +563,18 @@ private CharSequence generateVarData(final List tokens, final String inde indent + INDENT + "return bytesCopied;\n" + indent + "}\n", propertyName, - generateArrayFieldNotPresentCondition(token.version(), indent), + generateArrayFieldNotPresentCondition(token.version(), indent, "0"), sizeOfLengthField, lengthTypePrefix, - byteOrderStr)); + byteOrderStr, + accessOrderListenerCall)); sb.append(String.format(indent + "\n" + indent + "// Allocates and returns a new byte array\n" + indent + "public byte[] Get%1$sBytes()\n" + indent + "{\n" + + "%5$s" + + "%6$s" + indent + INDENT + "const int sizeOfLengthField = %2$d;\n" + indent + INDENT + "int limit = _parentMessage.Limit;\n" + indent + INDENT + "_buffer.CheckLimit(limit + sizeOfLengthField);\n" + @@ -468,7 +587,9 @@ private CharSequence generateVarData(final List tokens, final String inde propertyName, sizeOfLengthField, lengthTypePrefix, - byteOrderStr)); + byteOrderStr, + generateArrayFieldNotPresentCondition(token.version(), indent, "new byte[0]"), + accessOrderListenerCall)); sb.append(String.format("\n" + indent + "public int Set%1$s(byte[] src, int srcOffset, int length) =>\n" + @@ -478,6 +599,7 @@ private CharSequence generateVarData(final List tokens, final String inde sb.append(String.format("\n" + indent + "public int Set%1$s(ReadOnlySpan src)\n" + indent + "{\n" + + "%6$s" + indent + INDENT + "const int sizeOfLengthField = %2$d;\n" + indent + INDENT + "int limit = _parentMessage.Limit;\n" + indent + INDENT + "_parentMessage.Limit = limit + sizeOfLengthField + src.Length;\n" + @@ -489,7 +611,8 @@ private CharSequence generateVarData(final List tokens, final String inde sizeOfLengthField, lengthTypePrefix, lengthCSharpType, - byteOrderStr)); + byteOrderStr, + accessOrderListenerCall)); if (characterEncoding != null) // only generate these string based methods if there is an encoding { @@ -497,6 +620,8 @@ private CharSequence generateVarData(final List tokens, final String inde .append(String.format( indent + "public string Get%1$s()\n" + indent + "{\n" + + "%6$s" + + "%7$s" + indent + INDENT + "const int sizeOfLengthField = %2$d;\n" + indent + INDENT + "int limit = _parentMessage.Limit;\n" + indent + INDENT + "_buffer.CheckLimit(limit + sizeOfLengthField);\n" + @@ -507,15 +632,22 @@ private CharSequence generateVarData(final List tokens, final String inde indent + "}\n\n" + indent + "public void Set%1$s(string value)\n" + indent + "{\n" + + "%7$s" + indent + INDENT + "var encoding = %1$sResolvedCharacterEncoding;\n" + indent + INDENT + "const int sizeOfLengthField = %2$d;\n" + indent + INDENT + "int limit = _parentMessage.Limit;\n" + indent + INDENT + "int byteCount = _buffer.SetBytesFromString(encoding, value, " + "limit + sizeOfLengthField);\n" + indent + INDENT + "_parentMessage.Limit = limit + sizeOfLengthField + byteCount;\n" + - indent + INDENT + "_buffer.%3$sPut%4$s(limit, (ushort)byteCount);\n" + + indent + INDENT + "_buffer.%3$sPut%4$s(limit, (%5$s)byteCount);\n" + indent + "}\n", - propertyName, sizeOfLengthField, lengthTypePrefix, byteOrderStr)); + propertyName, + sizeOfLengthField, + lengthTypePrefix, + byteOrderStr, + lengthCSharpType, + generateArrayFieldNotPresentCondition(token.version(), indent, "\"\""), + accessOrderListenerCall)); } } } @@ -588,23 +720,24 @@ private CharSequence generateCompositePropertyElements(final List tokens, { final Token token = tokens.get(i); final String propertyName = formatPropertyName(token.name()); + final FieldPrecedenceModel fieldPrecedenceModel = null; switch (token.signal()) { case ENCODING: - sb.append(generatePrimitiveProperty(propertyName, token, token, indent)); + sb.append(generatePrimitiveProperty(propertyName, token, token, fieldPrecedenceModel, indent)); break; case BEGIN_ENUM: - sb.append(generateEnumProperty(propertyName, token, token, indent)); + sb.append(generateEnumProperty(propertyName, token, token, fieldPrecedenceModel, indent)); break; case BEGIN_SET: - sb.append(generateBitSetProperty(propertyName, token, token, indent)); + sb.append(generateBitSetProperty(propertyName, token, token, fieldPrecedenceModel, indent)); break; case BEGIN_COMPOSITE: - sb.append(generateCompositeProperty(propertyName, token, token, indent)); + sb.append(generateCompositeProperty(propertyName, token, token, fieldPrecedenceModel, indent)); break; default: @@ -747,7 +880,11 @@ private CharSequence generateEnumDeclaration( } private CharSequence generatePrimitiveProperty( - final String propertyName, final Token fieldToken, final Token typeToken, final String indent) + final String propertyName, + final Token fieldToken, + final Token typeToken, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent) { final StringBuilder sb = new StringBuilder(); @@ -759,7 +896,8 @@ private CharSequence generatePrimitiveProperty( } else { - sb.append(generatePrimitivePropertyMethods(propertyName, fieldToken, typeToken, indent)); + sb.append(generatePrimitivePropertyMethods(propertyName, fieldToken, typeToken, + fieldPrecedenceModel, indent)); } return sb; @@ -769,17 +907,20 @@ private CharSequence generatePrimitivePropertyMethods( final String propertyName, final Token fieldToken, final Token typeToken, + final FieldPrecedenceModel fieldPrecedenceModel, final String indent) { final int arrayLength = typeToken.arrayLength(); if (arrayLength == 1) { - return generateSingleValueProperty(propertyName, fieldToken, typeToken, indent + INDENT); + return generateSingleValueProperty(propertyName, fieldToken, typeToken, + fieldPrecedenceModel, indent + INDENT); } else if (arrayLength > 1) { - return generateArrayProperty(propertyName, fieldToken, typeToken, indent + INDENT); + return generateArrayProperty(propertyName, fieldToken, typeToken, + fieldPrecedenceModel, indent + INDENT); } return ""; @@ -809,6 +950,7 @@ private CharSequence generateSingleValueProperty( final String propertyName, final Token fieldToken, final Token typeToken, + final FieldPrecedenceModel fieldPrecedenceModel, final String indent) { final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); @@ -817,6 +959,9 @@ private CharSequence generateSingleValueProperty( final ByteOrder byteOrder = typeToken.encoding().byteOrder(); final String byteOrderStr = generateByteOrder(byteOrder, typeToken.encoding().primitiveType().size()); + final CharSequence accessOrderListenerCall = + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + TWO_INDENT, fieldToken); + return String.format("\n" + "%1$s" + indent + "public %2$s %3$s\n" + @@ -824,10 +969,12 @@ private CharSequence generateSingleValueProperty( indent + INDENT + "get\n" + indent + INDENT + "{\n" + "%4$s" + + "%8$s" + indent + INDENT + INDENT + "return _buffer.%5$sGet%7$s(_offset + %6$d);\n" + indent + INDENT + "}\n" + indent + INDENT + "set\n" + indent + INDENT + "{\n" + + "%8$s" + indent + INDENT + INDENT + "_buffer.%5$sPut%7$s(_offset + %6$d, value);\n" + indent + INDENT + "}\n" + indent + "}\n\n", @@ -837,7 +984,8 @@ private CharSequence generateSingleValueProperty( generateFieldNotPresentCondition(fieldToken.version(), typeToken.encoding(), indent), typePrefix, offset, - byteOrderStr); + byteOrderStr, + accessOrderListenerCall); } private CharSequence generateFieldNotPresentCondition( @@ -866,16 +1014,34 @@ private CharSequence generateFieldNotPresentCondition( literal); } - private CharSequence generateArrayFieldNotPresentCondition(final int sinceVersion, final String indent) + private CharSequence generateGroupNotPresentCondition( + final int sinceVersion, + final String indent, + final String groupInstanceField) { if (0 == sinceVersion) { return ""; } - return String.format( - indent + INDENT + INDENT + "if (_actingVersion < %d) return 0;\n\n", - sinceVersion); + return indent + "if (_actingVersion < " + sinceVersion + ")" + + indent + "{\n" + + indent + INDENT + groupInstanceField + ".NotPresent();\n" + + indent + INDENT + "return " + groupInstanceField + ";\n" + + indent + "}\n\n"; + } + + private CharSequence generateArrayFieldNotPresentCondition( + final int sinceVersion, + final String indent, + final String defaultValue) + { + if (0 == sinceVersion) + { + return ""; + } + + return indent + INDENT + "if (_actingVersion < " + sinceVersion + ") return " + defaultValue + ";\n\n"; } private CharSequence generateBitSetNotPresentCondition( @@ -912,7 +1078,7 @@ private CharSequence generateArrayProperty( final String propertyName, final Token fieldToken, final Token typeToken, - final String indent) + final FieldPrecedenceModel fieldPrecedenceModel, final String indent) { final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); final String typePrefix = toUpperFirstChar(typeToken.encoding().primitiveType().primitiveName()); @@ -923,6 +1089,11 @@ private CharSequence generateArrayProperty( final int typeSize = typeToken.encoding().primitiveType().size(); final String propName = toUpperFirstChar(propertyName); + final CharSequence accessOrderListenerCall = + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + INDENT, fieldToken); + final CharSequence accessOrderListenerCallDoubleIndent = + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + TWO_INDENT, fieldToken); + final StringBuilder sb = new StringBuilder(); sb.append(String.format("\n" + @@ -938,12 +1109,14 @@ private CharSequence generateArrayProperty( indent + INDENT + INDENT + "ThrowHelper.ThrowIndexOutOfRangeException(index);\n" + indent + INDENT + "}\n\n" + "%5$s" + + "%10$s" + indent + INDENT + "return _buffer.%6$sGet%9$s(_offset + %7$d + (index * %8$d));\n" + indent + "}\n", generateDocumentation(indent, fieldToken), typeName, propName, fieldLength, generateFieldNotPresentCondition(fieldToken.version(), typeToken.encoding(), indent), - typePrefix, offset, typeSize, byteOrderStr)); + typePrefix, offset, typeSize, byteOrderStr, + accessOrderListenerCall)); sb.append(String.format("\n" + "%1$s" + @@ -953,29 +1126,48 @@ private CharSequence generateArrayProperty( indent + INDENT + "{\n" + indent + INDENT + INDENT + "ThrowHelper.ThrowIndexOutOfRangeException(index);\n" + indent + INDENT + "}\n\n" + + "%9$s" + indent + INDENT + "_buffer.%5$sPut%8$s(_offset + %6$d + (index * %7$d), value);\n" + indent + "}\n", generateDocumentation(indent, fieldToken), - propName, typeName, fieldLength, typePrefix, offset, typeSize, byteOrderStr)); + propName, typeName, fieldLength, typePrefix, offset, typeSize, byteOrderStr, + accessOrderListenerCall)); sb.append(String.format("\n" + "%1$s" + indent + "public ReadOnlySpan<%2$s> %3$s\n" + indent + "{\n" + - indent + INDENT + "get => _buffer.AsReadOnlySpan<%2$s>(_offset + %4$s, %3$sLength);\n" + - indent + INDENT + "set => value.CopyTo(_buffer.AsSpan<%2$s>(_offset + %4$s, %3$sLength));\n" + + indent + INDENT + "get\n" + + indent + INDENT + "{\n" + + "%5$s" + + "%6$s" + + indent + INDENT + INDENT + "return _buffer.AsReadOnlySpan<%2$s>(_offset + %4$s, %3$sLength);\n" + + indent + INDENT + "}\n" + + indent + INDENT + "set\n" + + indent + INDENT + "{\n" + + "%6$s" + + indent + INDENT + INDENT + "value.CopyTo(_buffer.AsSpan<%2$s>(_offset + %4$s, %3$sLength));\n" + + indent + INDENT + "}\n" + indent + "}\n", generateDocumentation(indent, fieldToken), - typeName, propName, offset)); + typeName, propName, offset, + generateArrayFieldNotPresentCondition(fieldToken.version(), + indent + INDENT + INDENT, "new " + typeName + "[0]"), + accessOrderListenerCallDoubleIndent)); sb.append(String.format("\n" + "%1$s" + indent + "public Span<%2$s> %3$sAsSpan()\n" + indent + "{\n" + + "%5$s" + + "%6$s" + indent + INDENT + "return _buffer.AsSpan<%2$s>(_offset + %4$s, %3$sLength);\n" + indent + "}\n", generateDocumentation(indent, fieldToken), - typeName, propName, offset)); + typeName, propName, offset, + generateArrayFieldNotPresentCondition(fieldToken.version(), + indent + INDENT + INDENT, "new " + typeName + "[0]"), + accessOrderListenerCall)); if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { @@ -986,9 +1178,13 @@ private CharSequence generateArrayProperty( indent + "{\n" + indent + INDENT + "const int length = %2$d;\n" + "%3$s" + + "%4$s" + indent + INDENT + "return Get%1$s(new Span(dst, dstOffset, length));\n" + indent + "}\n", - propName, fieldLength, generateArrayFieldNotPresentCondition(fieldToken.version(), indent), offset)); + propName, + fieldLength, + generateArrayFieldNotPresentCondition(fieldToken.version(), indent, "0"), + accessOrderListenerCall)); sb.append(String.format("\n" + indent + "public int Get%1$s(Span dst)\n" + @@ -999,10 +1195,15 @@ private CharSequence generateArrayProperty( indent + INDENT + INDENT + "ThrowHelper.ThrowWhenSpanLengthTooSmall(dst.Length);\n" + indent + INDENT + "}\n\n" + "%3$s" + + "%5$s" + indent + INDENT + "_buffer.GetBytes(_offset + %4$d, dst);\n" + indent + INDENT + "return length;\n" + indent + "}\n", - propName, fieldLength, generateArrayFieldNotPresentCondition(fieldToken.version(), indent), offset)); + propName, + fieldLength, + generateArrayFieldNotPresentCondition(fieldToken.version(), indent, "0"), + offset, + accessOrderListenerCall)); sb.append(String.format("\n" + indent + "public void Set%1$s(byte[] src, int srcOffset)\n" + @@ -1019,22 +1220,28 @@ private CharSequence generateArrayProperty( indent + INDENT + "{\n" + indent + INDENT + INDENT + "ThrowHelper.ThrowWhenSpanLengthTooLarge(src.Length);\n" + indent + INDENT + "}\n\n" + + "%4$s" + indent + INDENT + "_buffer.SetBytes(_offset + %3$d, src);\n" + indent + "}\n", - propName, fieldLength, offset)); + propName, fieldLength, offset, + accessOrderListenerCall)); sb.append(String.format("\n" + indent + "public void Set%1$s(string value)\n" + indent + "{\n" + + "%3$s" + indent + INDENT + "_buffer.SetNullTerminatedBytesFromString(%1$sResolvedCharacterEncoding, " + "value, _offset + %2$s, %1$sLength, %1$sNullValue);\n" + indent + "}\n" + indent + "public string Get%1$s()\n" + indent + "{\n" + + "%3$s" + indent + INDENT + "return _buffer.GetStringFromNullTerminatedBytes(%1$sResolvedCharacterEncoding, " + "_offset + %2$s, %1$sLength, %1$sNullValue);\n" + indent + "}\n", - propName, offset)); + propName, + offset, + accessOrderListenerCall)); } return sb; @@ -1156,7 +1363,11 @@ private CharSequence generateFixedFlyweightCode(final int size) size); } - private CharSequence generateMessageFlyweightCode(final String className, final Token token, final String indent) + private CharSequence generateMessageFlyweightCode( + final String className, + final Token token, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent) { final String blockLengthType = cSharpTypeName(ir.headerStructure().blockLengthType()); final String templateIdType = cSharpTypeName(ir.headerStructure().templateIdType()); @@ -1184,16 +1395,18 @@ private CharSequence generateMessageFlyweightCode(final String className, final indent + INDENT + "{\n" + indent + INDENT + INDENT + "_parentMessage = this;\n" + indent + INDENT + "}\n\n" + - indent + INDENT + "public void WrapForEncode(DirectBuffer buffer, int offset)\n" + + indent + INDENT + "public %10$s WrapForEncode(DirectBuffer buffer, int offset)\n" + indent + INDENT + "{\n" + + "%12$s" + indent + INDENT + INDENT + "_buffer = buffer;\n" + indent + INDENT + INDENT + "_offset = offset;\n" + indent + INDENT + INDENT + "_actingBlockLength = BlockLength;\n" + indent + INDENT + INDENT + "_actingVersion = SchemaVersion;\n" + indent + INDENT + INDENT + "Limit = offset + _actingBlockLength;\n" + + indent + INDENT + INDENT + "return this;\n" + indent + INDENT + "}\n\n" + - indent + INDENT + "public void WrapForEncodeAndApplyHeader(DirectBuffer buffer, int offset, " + - " MessageHeader headerEncoder)\n" + + indent + INDENT + "public %10$s WrapForEncodeAndApplyHeader(DirectBuffer buffer, int offset, " + + "MessageHeader headerEncoder)\n" + indent + INDENT + "{\n" + indent + INDENT + INDENT + "headerEncoder.Wrap(buffer, offset, SchemaVersion);\n" + indent + INDENT + INDENT + "headerEncoder.BlockLength = BlockLength;\n" + @@ -1201,16 +1414,27 @@ private CharSequence generateMessageFlyweightCode(final String className, final indent + INDENT + INDENT + "headerEncoder.SchemaId = SchemaId;\n" + indent + INDENT + INDENT + "headerEncoder.Version = SchemaVersion;\n" + indent + INDENT + INDENT + "\n" + - indent + INDENT + INDENT + "WrapForEncode(buffer, offset + MessageHeader.Size);\n" + + indent + INDENT + INDENT + "return WrapForEncode(buffer, offset + MessageHeader.Size);\n" + indent + INDENT + "}\n\n" + - indent + INDENT + "public void WrapForDecode(DirectBuffer buffer, int offset, " + + "%13$s" + + indent + INDENT + "public %10$s WrapForDecode(DirectBuffer buffer, int offset, " + "int actingBlockLength, int actingVersion)\n" + indent + INDENT + "{\n" + + "%14$s" + indent + INDENT + INDENT + "_buffer = buffer;\n" + indent + INDENT + INDENT + "_offset = offset;\n" + indent + INDENT + INDENT + "_actingBlockLength = actingBlockLength;\n" + indent + INDENT + INDENT + "_actingVersion = actingVersion;\n" + indent + INDENT + INDENT + "Limit = offset + _actingBlockLength;\n" + + indent + INDENT + INDENT + "return this;\n" + + indent + INDENT + "}\n\n" + + indent + INDENT + "public %10$s WrapForDecodeAndApplyHeader(DirectBuffer buffer, int offset, " + + "MessageHeader headerDecoder)\n" + + indent + INDENT + "{\n" + + indent + INDENT + INDENT + "headerDecoder.Wrap(buffer, offset, SchemaVersion);\n" + + indent + INDENT + INDENT + "\n" + + indent + INDENT + INDENT + "return WrapForDecode(buffer, offset + MessageHeader.Size, " + + " headerDecoder.BlockLength, headerDecoder.Version);\n" + indent + INDENT + "}\n\n" + indent + INDENT + "public int Size\n" + indent + INDENT + "{\n" + @@ -1241,10 +1465,507 @@ private CharSequence generateMessageFlyweightCode(final String className, final generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), semanticType, className, - semanticVersion); + semanticVersion, + generateEncoderWrapListener(fieldPrecedenceModel, indent + TWO_INDENT), + generateDecoderWrapListener(fieldPrecedenceModel, indent + INDENT), + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + TWO_INDENT, + "OnWrapForDecode", "actingVersion")); + } + + private static CharSequence qualifiedStateCase(final FieldPrecedenceModel.State state) + { + return "CodecState." + state.name(); + } + + private static CharSequence stateCaseForSwitchCase(final FieldPrecedenceModel.State state) + { + return qualifiedStateCase(state); + } + + private static CharSequence unqualifiedStateCase(final FieldPrecedenceModel.State state) + { + return state.name(); + } + + private static CharSequence generateFieldOrderStates( + final String indent, + final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + + sb.append(indent).append("///\n"); + + sb.append(indent).append("/// \n"); + sb.append(indent).append("/// \n"); + sb.append(indent).append("/// The states in which a encoder/decoder/codec can live.\n"); + sb.append(indent).append("/// \n"); + sb.append(indent).append("/// \n"); + sb.append(indent).append("/// The state machine diagram below, encoded in the dot language, describes\n"); + sb.append(indent).append("/// the valid state transitions according to the order in which fields may be\n"); + sb.append(indent).append("/// accessed safely. Tools such as PlantUML and Graphviz can render it.\n"); + sb.append(indent).append("/// \n"); + sb.append(indent).append("/// \n"); + fieldPrecedenceModel.generateGraph(sb, indent + "/// "); + sb.append(indent).append("/// \n"); + sb.append(indent).append("/// \n"); + sb.append(indent).append("private enum CodecState\n") + .append(indent).append("{\n"); + fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> + { + sb.append(indent).append(INDENT).append(unqualifiedStateCase(state)) + .append(" = ").append(state.number()) + .append(",\n"); + }); + sb.append(indent).append("}\n\n"); + + sb.append("\n").append(indent).append("private static readonly string[] StateNameLookup = new []\n") + .append(indent).append("{\n"); + fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> + { + sb.append(indent).append(INDENT).append("\"").append(state.name()).append("\",\n"); + }); + sb.append(indent).append("};\n\n"); + + sb.append(indent).append("private static readonly string[] StateTransitionsLookup = new []\n") + .append(indent).append("{\n"); + fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> + { + sb.append(indent).append(INDENT).append("\""); + final MutableBoolean isFirst = new MutableBoolean(true); + final Set transitionDescriptions = new HashSet<>(); + fieldPrecedenceModel.forEachTransitionFrom(state, transitionGroup -> + { + if (transitionDescriptions.add(transitionGroup.exampleCode())) + { + if (isFirst.get()) + { + isFirst.set(false); + } + else + { + sb.append(", "); + } + + sb.append("\\\"").append(transitionGroup.exampleCode()).append("\\\""); + } + }); + sb.append("\",\n"); + }); + sb.append(indent).append("};\n\n"); + + sb.append(indent).append("private static string codecStateName(CodecState state)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return StateNameLookup[(int) state];\n") + .append(indent).append("}\n\n"); + + sb.append(indent).append("private static string codecStateTransitions(CodecState state)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return StateTransitionsLookup[(int) state];\n") + .append(indent).append("}\n\n"); + + sb.append(indent).append("private CodecState _codecState = ") + .append(qualifiedStateCase(fieldPrecedenceModel.notWrappedState())) + .append(";\n\n"); + + sb.append(indent).append("private CodecState codecState()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return _codecState;\n") + .append(indent).append("}\n\n"); + + sb.append(indent).append("private void codecState(CodecState newState)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("_codecState = newState;\n") + .append(indent).append("}\n"); + + return sb; + } + + private CharSequence generateFullyEncodedCheck( + final String indent, + final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + sb.append("\n"); + + sb.append(indent).append("public void CheckEncodingIsComplete()\n") + .append(indent).append("{\n") + .append("#if ").append(precedenceChecksFlagName).append("\n") + .append(indent).append(INDENT).append("switch (_codecState)\n") + .append(indent).append(INDENT).append("{\n"); + + fieldPrecedenceModel.forEachTerminalEncoderState(state -> + { + sb.append(indent).append(TWO_INDENT).append("case ").append(stateCaseForSwitchCase(state)).append(":\n") + .append(indent).append(THREE_INDENT).append("return;\n"); + }); + + sb.append(indent).append(TWO_INDENT).append("default:\n") + .append(indent).append(THREE_INDENT) + .append("throw new InvalidOperationException(\"Not fully encoded, current state: \" +\n") + .append(indent).append(THREE_INDENT) + .append(INDENT).append("codecStateName(_codecState) + \", allowed transitions: \" +\n") + .append(indent).append(THREE_INDENT) + .append(INDENT).append("codecStateTransitions(_codecState));\n") + .append(indent).append(INDENT).append("}\n") + .append("#endif\n") + .append(indent).append("}\n\n"); + + return sb; + } + + private static String accessOrderListenerMethodName(final Token token) + { + return "On" + Generators.toUpperFirstChar(token.name()) + "Accessed"; } - private CharSequence generateFields(final List tokens, final String indent) + private static String accessOrderListenerMethodName(final Token token, final String suffix) + { + return "On" + Generators.toUpperFirstChar(token.name()) + suffix + "Accessed"; + } + + private static void generateAccessOrderListenerMethod( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append("\n") + .append(indent).append("private void ").append(accessOrderListenerMethodName(token)).append("()\n") + .append(indent).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction fieldAccess = + fieldPrecedenceModel.interactionFactory().accessField(token); + + generateAccessOrderListener( + sb, + indent + INDENT, + "access field", + fieldPrecedenceModel, + fieldAccess); + + sb.append(indent).append("}\n"); + } + + private CharSequence generateAccessOrderListenerCall( + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token, + final String... arguments) + { + return generateAccessOrderListenerCall( + fieldPrecedenceModel, + indent, + accessOrderListenerMethodName(token), + arguments); + } + + private CharSequence generateAccessOrderListenerCall( + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final String methodName, + final String... arguments) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + sb.append("#if ").append(precedenceChecksFlagName).append("\n") + .append(indent).append(methodName).append("("); + + for (int i = 0; i < arguments.length; i++) + { + if (i > 0) + { + sb.append(", "); + } + sb.append(arguments[i]); + } + sb.append(");\n"); + + sb.append("#endif\n"); + + return sb; + } + + private static void generateAccessOrderListenerMethodForGroupWrap( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append("\n") + .append(indent).append("private void ").append(accessOrderListenerMethodName(token)) + .append("(int remaining, string action)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("if (remaining == 0)\n") + .append(indent).append(INDENT).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction selectEmptyGroup = + fieldPrecedenceModel.interactionFactory().determineGroupIsEmpty(token); + + generateAccessOrderListener( + sb, + indent + TWO_INDENT, + "\" + action + \" count of repeating group", + fieldPrecedenceModel, + selectEmptyGroup); + + sb.append(indent).append(INDENT).append("}\n") + .append(indent).append(INDENT).append("else\n") + .append(indent).append(INDENT).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction selectNonEmptyGroup = + fieldPrecedenceModel.interactionFactory().determineGroupHasElements(token); + + generateAccessOrderListener( + sb, + indent + TWO_INDENT, + "\" + action + \" count of repeating group", + fieldPrecedenceModel, + selectNonEmptyGroup); + + sb.append(indent).append(INDENT).append("}\n") + .append(indent).append("}\n"); + } + + private static void generateAccessOrderListener( + final StringBuilder sb, + final String indent, + final String action, + final FieldPrecedenceModel fieldPrecedenceModel, + final FieldPrecedenceModel.CodecInteraction interaction) + { + if (interaction.isTopLevelBlockFieldAccess()) + { + sb.append(indent).append("if (codecState() == ") + .append(qualifiedStateCase(fieldPrecedenceModel.notWrappedState())) + .append(")\n") + .append(indent).append("{\n"); + generateAccessOrderException(sb, indent + INDENT, action, fieldPrecedenceModel, interaction); + sb.append(indent).append("}\n"); + } + else + { + sb.append(indent).append("switch (codecState())\n") + .append(indent).append("{\n"); + + fieldPrecedenceModel.forEachTransition(interaction, transitionGroup -> + { + transitionGroup.forEachStartState(startState -> + { + sb.append(indent).append(INDENT) + .append("case ").append(stateCaseForSwitchCase(startState)).append(":\n"); + }); + sb.append(indent).append(TWO_INDENT).append("codecState(") + .append(qualifiedStateCase(transitionGroup.endState())).append(");\n") + .append(indent).append(TWO_INDENT).append("break;\n"); + }); + + sb.append(indent).append(INDENT).append("default:\n"); + generateAccessOrderException(sb, indent + TWO_INDENT, action, fieldPrecedenceModel, interaction); + sb.append(indent).append("}\n"); + } + } + + private static void generateAccessOrderException( + final StringBuilder sb, + final String indent, + final String action, + final FieldPrecedenceModel fieldPrecedenceModel, + final FieldPrecedenceModel.CodecInteraction interaction) + { + sb.append(indent).append("throw new InvalidOperationException(") + .append("\"Illegal field access order. \" +\n") + .append(indent).append(INDENT) + .append("\"Cannot ").append(action).append(" \\\"").append(interaction.groupQualifiedName()) + .append("\\\" in state: \" + codecStateName(codecState()) +\n") + .append(indent).append(INDENT) + .append("\". Expected one of these transitions: [\" + codecStateTransitions(codecState()) +\n") + .append(indent).append(INDENT) + .append("\"]. Please see the diagram in the docs of the enum ") + .append(fieldPrecedenceModel.generatedRepresentationClassName()).append(".\");\n"); + } + + private static void generateAccessOrderListenerMethodForNextGroupElement( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append("\n"); + + sb.append(indent).append("private void OnNextElementAccessed()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("int remaining = ").append("_count - _index").append(";\n") + .append(indent).append(INDENT).append("if (remaining > 1)\n") + .append(indent).append(INDENT).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction selectNextElementInGroup = + fieldPrecedenceModel.interactionFactory().moveToNextElement(token); + + generateAccessOrderListener( + sb, + indent + TWO_INDENT, + "access next element in repeating group", + fieldPrecedenceModel, + selectNextElementInGroup); + + sb.append(indent).append(INDENT).append("}\n") + .append(indent).append(INDENT).append("else if (remaining == 1)\n") + .append(indent).append(INDENT).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction selectLastElementInGroup = + fieldPrecedenceModel.interactionFactory().moveToLastElement(token); + + generateAccessOrderListener( + sb, + indent + TWO_INDENT, + "access next element in repeating group", + fieldPrecedenceModel, + selectLastElementInGroup); + + sb.append(indent).append(INDENT).append("}\n") + .append(indent).append("}\n"); + } + + private static void generateAccessOrderListenerMethodForResetGroupCount( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append(indent).append("private void OnResetCountToIndex()\n") + .append(indent).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction resetCountToIndex = + fieldPrecedenceModel.interactionFactory().resetCountToIndex(token); + + generateAccessOrderListener( + sb, + indent + " ", + "reset count of repeating group", + fieldPrecedenceModel, + resetCountToIndex); + + sb.append(indent).append("}\n"); + } + + private static void generateAccessOrderListenerMethodForVarDataLength( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append("\n") + .append(indent).append("private void ") + .append(accessOrderListenerMethodName(token, "Length")).append("()\n") + .append(indent).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction accessLength = + fieldPrecedenceModel.interactionFactory().accessVarDataLength(token); + + generateAccessOrderListener( + sb, + indent + INDENT, + "decode length of var data", + fieldPrecedenceModel, + accessLength); + + sb.append(indent).append("}\n"); + } + + private static CharSequence generateDecoderWrapListener( + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + sb.append(indent).append("private void OnWrapForDecode(int actingVersion)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("switch(actingVersion)\n") + .append(indent).append(INDENT).append("{\n"); + + fieldPrecedenceModel.forEachWrappedStateByVersion((version, state) -> + { + sb.append(indent).append(TWO_INDENT).append("case ").append(version).append(":\n") + .append(indent).append(THREE_INDENT).append("codecState(") + .append(qualifiedStateCase(state)).append(");\n") + .append(indent).append(THREE_INDENT).append("break;\n"); + }); + + sb.append(indent).append(TWO_INDENT).append("default:\n") + .append(indent).append(THREE_INDENT).append("codecState(") + .append(qualifiedStateCase(fieldPrecedenceModel.latestVersionWrappedState())).append(");\n") + .append(indent).append(THREE_INDENT).append("break;\n") + .append(indent).append(INDENT).append("}\n") + .append(indent).append("}\n\n"); + + return sb; + } + + private CharSequence generateEncoderWrapListener( + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + sb.append("#if ").append(precedenceChecksFlagName).append("\n") + .append(indent).append("codecState(") + .append(qualifiedStateCase(fieldPrecedenceModel.latestVersionWrappedState())) + .append(");\n") + .append("#endif\n"); + return sb; + } + + private CharSequence generateFields( + final FieldPrecedenceModel fieldPrecedenceModel, + final List tokens, + final String indent) { final StringBuilder sb = new StringBuilder(); @@ -1258,26 +1979,32 @@ private CharSequence generateFields(final List tokens, final String inden generateFieldIdMethod(sb, signalToken, indent + INDENT); generateSinceActingDeprecated( - sb, indent, CSharpUtil.formatPropertyName(signalToken.name()), signalToken); + sb, indent + INDENT, CSharpUtil.formatPropertyName(signalToken.name()), signalToken); generateOffsetMethod(sb, signalToken, indent + INDENT); generateFieldMetaAttributeMethod(sb, signalToken, indent + INDENT); + generateAccessOrderListenerMethod(sb, fieldPrecedenceModel, indent + INDENT, signalToken); + switch (encodingToken.signal()) { case ENCODING: - sb.append(generatePrimitiveProperty(propertyName, signalToken, encodingToken, indent)); + sb.append(generatePrimitiveProperty(propertyName, signalToken, encodingToken, + fieldPrecedenceModel, indent)); break; case BEGIN_ENUM: - sb.append(generateEnumProperty(propertyName, signalToken, encodingToken, indent)); + sb.append(generateEnumProperty(propertyName, signalToken, encodingToken, + fieldPrecedenceModel, indent)); break; case BEGIN_SET: - sb.append(generateBitSetProperty(propertyName, signalToken, encodingToken, indent)); + sb.append(generateBitSetProperty(propertyName, signalToken, encodingToken, + fieldPrecedenceModel, indent)); break; case BEGIN_COMPOSITE: - sb.append(generateCompositeProperty(propertyName, signalToken, encodingToken, indent)); + sb.append(generateCompositeProperty(propertyName, signalToken, encodingToken, + fieldPrecedenceModel, indent)); break; default: @@ -1352,6 +2079,7 @@ private CharSequence generateEnumProperty( final String propertyName, final Token fieldToken, final Token typeToken, + final FieldPrecedenceModel fieldPrecedenceModel, final String indent) { final String enumName = formatClassName(typeToken.applicableTypeName()); @@ -1381,6 +2109,9 @@ private CharSequence generateEnumProperty( } else { + final CharSequence accessOrderListenerCall = generateAccessOrderListenerCall( + fieldPrecedenceModel, indent + TWO_INDENT, fieldToken); + return String.format("\n" + "%1$s" + indent + INDENT + "public %2$s %3$s\n" + @@ -1388,10 +2119,12 @@ private CharSequence generateEnumProperty( indent + INDENT + INDENT + "get\n" + indent + INDENT + INDENT + "{\n" + "%4$s" + + "%10$s" + indent + INDENT + INDENT + INDENT + "return (%5$s)_buffer.%6$sGet%8$s(_offset + %7$d);\n" + indent + INDENT + INDENT + "}\n" + indent + INDENT + INDENT + "set\n" + indent + INDENT + INDENT + "{\n" + + "%10$s" + indent + INDENT + INDENT + INDENT + "_buffer.%6$sPut%8$s(_offset + %7$d, (%9$s)value);\n" + indent + INDENT + INDENT + "}\n" + indent + INDENT + "}\n\n", @@ -1403,12 +2136,17 @@ private CharSequence generateEnumProperty( typePrefix, offset, byteOrderStr, - enumUnderlyingType); + enumUnderlyingType, + accessOrderListenerCall); } } private String generateBitSetProperty( - final String propertyName, final Token fieldToken, final Token typeToken, final String indent) + final String propertyName, + final Token fieldToken, + final Token typeToken, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent) { final String bitSetName = formatClassName(typeToken.applicableTypeName()); final int offset = typeToken.offset(); @@ -1416,6 +2154,8 @@ private String generateBitSetProperty( final ByteOrder byteOrder = typeToken.encoding().byteOrder(); final String byteOrderStr = generateByteOrder(byteOrder, typeToken.encoding().primitiveType().size()); final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); + final CharSequence accessOrderListenerCall = generateAccessOrderListenerCall( + fieldPrecedenceModel, indent + TWO_INDENT, fieldToken); return String.format("\n" + "%1$s" + @@ -1424,10 +2164,12 @@ private String generateBitSetProperty( indent + INDENT + INDENT + "get\n" + indent + INDENT + INDENT + "{\n" + "%4$s" + + "%10$s" + indent + INDENT + INDENT + INDENT + "return (%5$s)_buffer.%6$sGet%8$s(_offset + %7$d);\n" + indent + INDENT + INDENT + "}\n" + indent + INDENT + INDENT + "set\n" + indent + INDENT + INDENT + "{\n" + + "%10$s" + indent + INDENT + INDENT + INDENT + "_buffer.%6$sPut%8$s(_offset + %7$d, (%9$s)value);\n" + indent + INDENT + INDENT + "}\n" + indent + INDENT + "}\n", @@ -1439,14 +2181,21 @@ private String generateBitSetProperty( typePrefix, offset, byteOrderStr, - typeName); + typeName, + accessOrderListenerCall); } private Object generateCompositeProperty( - final String propertyName, final Token fieldToken, final Token typeToken, final String indent) + final String propertyName, + final Token fieldToken, + final Token typeToken, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent) { final String compositeName = CSharpUtil.formatClassName(typeToken.applicableTypeName()); final int offset = typeToken.offset(); + final CharSequence accessOrderListenerCall = generateAccessOrderListenerCall( + fieldPrecedenceModel, indent + THREE_INDENT, fieldToken); final StringBuilder sb = new StringBuilder(); sb.append(String.format("\n" + @@ -1462,6 +2211,7 @@ private Object generateCompositeProperty( indent + INDENT + INDENT + "get\n" + indent + INDENT + INDENT + "{\n" + "%4$s" + + "%7$s" + indent + INDENT + INDENT + INDENT + "_%5$s.Wrap(_buffer, _offset + %6$d, _actingVersion);\n" + indent + INDENT + INDENT + INDENT + "return _%5$s;\n" + indent + INDENT + INDENT + "}\n" + @@ -1471,7 +2221,8 @@ private Object generateCompositeProperty( toUpperFirstChar(propertyName), generateTypeFieldNotPresentCondition(fieldToken.version(), indent), toLowerFirstChar(propertyName), - offset)); + offset, + accessOrderListenerCall)); return sb; } @@ -1715,11 +2466,13 @@ private int writeTokenDisplay( { if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { + append(sb, indent, "builder.Append(\"'\");"); append(sb, indent, "for (int i = 0; i < " + fieldName + "Length && this.Get" + fieldName + "(i) > 0; ++i)"); append(sb, indent, "{"); append(sb, indent, " builder.Append((char)this.Get" + fieldName + "(i));"); append(sb, indent, "}"); + append(sb, indent, "builder.Append(\"'\");"); } else { @@ -1804,7 +2557,8 @@ private CharSequence generateDisplay( final String name, final List tokens, final List groups, - final List varData) + final List varData, + final FieldPrecedenceModel fieldPrecedenceModel) { final StringBuilder sb = new StringBuilder(100); @@ -1818,6 +2572,15 @@ private CharSequence generateDisplay( append(sb, TWO_INDENT, " }"); sb.append('\n'); append(sb, TWO_INDENT, " int originalLimit = this.Limit;"); + if (null != fieldPrecedenceModel) + { + sb.append("#if ").append(precedenceChecksFlagName).append("\n"); + append(sb, TWO_INDENT, " CodecState originalState = _codecState;"); + sb.append(THREE_INDENT).append("_codecState = ") + .append(qualifiedStateCase(fieldPrecedenceModel.notWrappedState())).append(";\n"); + append(sb, TWO_INDENT, " OnWrapForDecode(_actingVersion);"); + sb.append("#endif\n"); + } append(sb, TWO_INDENT, " this.Limit = _offset + _actingBlockLength;"); append(sb, TWO_INDENT, " builder.Append(\"[" + name + "](sbeTemplateId=\");"); append(sb, TWO_INDENT, " builder.Append(" + name + ".TemplateId);"); @@ -1841,6 +2604,12 @@ private CharSequence generateDisplay( sb.append('\n'); appendDisplay(sb, tokens, groups, varData, THREE_INDENT); sb.append('\n'); + if (null != fieldPrecedenceModel) + { + sb.append("#if ").append(precedenceChecksFlagName).append("\n"); + append(sb, TWO_INDENT, " _codecState = originalState;"); + sb.append("#endif\n"); + } append(sb, TWO_INDENT, " this.Limit = originalLimit;"); sb.append('\n'); append(sb, TWO_INDENT, "}"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index eb90237170..3e6dd222eb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -15,25 +15,23 @@ */ package uk.co.real_logic.sbe.generation.java; +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.generation.CodeGenerator; +import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.generation.common.FieldPrecedenceModel; +import uk.co.real_logic.sbe.generation.common.PrecedenceChecks; +import uk.co.real_logic.sbe.ir.*; import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; import org.agrona.Strings; import org.agrona.Verify; +import org.agrona.collections.MutableBoolean; import org.agrona.generation.DynamicPackageOutputManager; import org.agrona.sbe.*; -import uk.co.real_logic.sbe.PrimitiveType; -import uk.co.real_logic.sbe.generation.CodeGenerator; -import uk.co.real_logic.sbe.generation.Generators; -import uk.co.real_logic.sbe.ir.*; import java.io.IOException; import java.io.Writer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Formatter; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.function.Function; import static uk.co.real_logic.sbe.SbeTool.JAVA_INTERFACE_PACKAGE; @@ -73,6 +71,9 @@ enum CodecType private final boolean shouldGenerateInterfaces; private final boolean shouldDecodeUnknownEnumValues; private final boolean shouldSupportTypesPackageNames; + private final PrecedenceChecks precedenceChecks; + private final String precedenceChecksFlagName; + private final String precedenceChecksPropName; private final Set packageNameByTypes = new HashSet<>(); /** @@ -120,6 +121,43 @@ public JavaGenerator( final boolean shouldDecodeUnknownEnumValues, final boolean shouldSupportTypesPackageNames, final DynamicPackageOutputManager outputManager) + { + this( + ir, + mutableBuffer, + readOnlyBuffer, + shouldGenerateGroupOrderAnnotation, + shouldGenerateInterfaces, + shouldDecodeUnknownEnumValues, + shouldSupportTypesPackageNames, + PrecedenceChecks.newInstance(new PrecedenceChecks.Context()), + outputManager + ); + } + + /** + * Create a new Java language {@link CodeGenerator}. + * + * @param ir for the messages and types. + * @param mutableBuffer implementation used for mutating underlying buffers. + * @param readOnlyBuffer implementation used for reading underlying buffers. + * @param shouldGenerateGroupOrderAnnotation in the codecs. + * @param shouldGenerateInterfaces for common methods. + * @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding. + * @param shouldSupportTypesPackageNames generator support for types in their own package. + * @param precedenceChecks whether and how to generate field precedence checks. + * @param outputManager for generating the codecs to. + */ + public JavaGenerator( + final Ir ir, + final String mutableBuffer, + final String readOnlyBuffer, + final boolean shouldGenerateGroupOrderAnnotation, + final boolean shouldGenerateInterfaces, + final boolean shouldDecodeUnknownEnumValues, + final boolean shouldSupportTypesPackageNames, + final PrecedenceChecks precedenceChecks, + final DynamicPackageOutputManager outputManager) { Verify.notNull(ir, "ir"); Verify.notNull(outputManager, "outputManager"); @@ -137,6 +175,10 @@ public JavaGenerator( this.shouldGenerateGroupOrderAnnotation = shouldGenerateGroupOrderAnnotation; this.shouldGenerateInterfaces = shouldGenerateInterfaces; this.shouldDecodeUnknownEnumValues = shouldDecodeUnknownEnumValues; + + this.precedenceChecks = precedenceChecks; + this.precedenceChecksFlagName = precedenceChecks.context().precedenceChecksFlagName(); + this.precedenceChecksPropName = precedenceChecks.context().precedenceChecksPropName(); } /** @@ -230,20 +272,30 @@ public void generate() throws IOException final List varData = new ArrayList<>(); collectVarData(messageBody, i, varData); - generateDecoder(msgToken, fields, groups, varData, hasVarData); - generateEncoder(msgToken, fields, groups, varData, hasVarData); + final String decoderClassName = formatClassName(decoderName(msgToken.name())); + final String decoderStateClassName = decoderClassName + "#CodecStates"; + final FieldPrecedenceModel decoderPrecedenceModel = + precedenceChecks.createDecoderModel(decoderStateClassName, tokens); + generateDecoder(decoderClassName, msgToken, fields, groups, varData, hasVarData, decoderPrecedenceModel); + + final String encoderClassName = formatClassName(encoderName(msgToken.name())); + final String encoderStateClassName = encoderClassName + "#CodecStates"; + final FieldPrecedenceModel encoderPrecedenceModel = + precedenceChecks.createEncoderModel(encoderStateClassName, tokens); + generateEncoder(encoderClassName, msgToken, fields, groups, varData, hasVarData, encoderPrecedenceModel); } } private void generateEncoder( + final String className, final Token msgToken, final List fields, final List groups, final List varData, - final boolean hasVarData) + final boolean hasVarData, + final FieldPrecedenceModel fieldPrecedenceModel) throws IOException { - final String className = formatClassName(encoderName(msgToken.name())); final String implementsString = implementsInterface(MessageEncoderFlyweight.class.getSimpleName()); try (Writer out = outputManager.createOutput(className)) @@ -255,29 +307,519 @@ private void generateEncoder( generateAnnotations(BASE_INDENT, className, groups, out, this::encoderName); } out.append(generateDeclaration(className, implementsString, msgToken)); - out.append(generateEncoderFlyweightCode(className, msgToken)); + + out.append(generateFieldOrderStates(fieldPrecedenceModel)); + out.append(generateEncoderFlyweightCode(className, fieldPrecedenceModel, msgToken)); final StringBuilder sb = new StringBuilder(); - generateEncoderFields(sb, className, fields, BASE_INDENT); - generateEncoderGroups(sb, className, groups, BASE_INDENT, false); - generateEncoderVarData(sb, className, varData, BASE_INDENT); + generateEncoderFields(sb, className, fieldPrecedenceModel, fields, BASE_INDENT); + generateEncoderGroups(sb, className, fieldPrecedenceModel, groups, BASE_INDENT, false); + generateEncoderVarData(sb, className, fieldPrecedenceModel, varData, BASE_INDENT); generateEncoderDisplay(sb, decoderName(msgToken.name())); + generateFullyEncodedCheck(sb, fieldPrecedenceModel); out.append(sb); out.append("}\n"); } } + private static CharSequence qualifiedStateCase(final FieldPrecedenceModel.State state) + { + return "CodecStates." + state.name(); + } + + private static CharSequence stateCaseForSwitchCase(final FieldPrecedenceModel.State state) + { + return qualifiedStateCase(state); + } + + private static CharSequence unqualifiedStateCase(final FieldPrecedenceModel.State state) + { + return state.name(); + } + + private CharSequence generateFieldOrderStates(final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + + sb.append(" private static final boolean ENABLE_BOUNDS_CHECKS = ") + .append("!Boolean.getBoolean(\"agrona.disable.bounds.checks\");\n\n"); + sb.append(" private static final boolean ") + .append(precedenceChecksFlagName).append(" = ") + .append("Boolean.parseBoolean(System.getProperty(\n") + .append(" \"").append(precedenceChecksPropName).append("\",\n") + .append(" Boolean.toString(ENABLE_BOUNDS_CHECKS)));\n\n"); + + sb.append(" /**\n"); + sb.append(" * The states in which a encoder/decoder/codec can live.\n"); + sb.append(" *\n"); + sb.append(" *

      The state machine diagram below, encoded in the dot language, describes\n"); + sb.append(" * the valid state transitions according to the order in which fields may be\n"); + sb.append(" * accessed safely. Tools such as PlantUML and Graphviz can render it.\n"); + sb.append(" *\n"); + sb.append(" *

      {@code\n");
      +        fieldPrecedenceModel.generateGraph(sb, "     *   ");
      +        sb.append("     * }
      \n"); + sb.append(" */\n"); + sb.append(" private static class CodecStates\n") + .append(" {\n"); + fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> + { + sb.append(" private static final int ") + .append(unqualifiedStateCase(state)) + .append(" = ").append(state.number()) + .append(";\n"); + }); + + sb.append("\n").append(" private static final String[] STATE_NAME_LOOKUP =\n") + .append(" {\n"); + fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> + { + sb.append(" \"").append(state.name()).append("\",\n"); + }); + sb.append(" };\n\n"); + + sb.append(" private static final String[] STATE_TRANSITIONS_LOOKUP =\n") + .append(" {\n"); + fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> + { + sb.append(" \""); + final MutableBoolean isFirst = new MutableBoolean(true); + final Set transitionDescriptions = new HashSet<>(); + fieldPrecedenceModel.forEachTransitionFrom(state, transitionGroup -> + { + if (transitionDescriptions.add(transitionGroup.exampleCode())) + { + if (isFirst.get()) + { + isFirst.set(false); + } + else + { + sb.append(", "); + } + + sb.append("\\\"").append(transitionGroup.exampleCode()).append("\\\""); + } + }); + sb.append("\",\n"); + }); + sb.append(" };\n\n"); + + sb.append(" private static String name(final int state)\n") + .append(" {\n") + .append(" return STATE_NAME_LOOKUP[state];\n") + .append(" }\n\n"); + + sb.append(" private static String transitions(final int state)\n") + .append(" {\n") + .append(" return STATE_TRANSITIONS_LOOKUP[state];\n") + .append(" }\n"); + + sb.append(" }\n\n"); + + sb.append(" private int codecState = ") + .append(qualifiedStateCase(fieldPrecedenceModel.notWrappedState())) + .append(";\n\n"); + + sb.append(" private int codecState()\n") + .append(" {\n") + .append(" return codecState;\n") + .append(" }\n\n"); + + sb.append(" private void codecState(int newState)\n") + .append(" {\n") + .append(" codecState = newState;\n") + .append(" }\n\n"); + + return sb; + } + + private void generateFullyEncodedCheck( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append("\n"); + + sb.append(" public void checkEncodingIsComplete()\n") + .append(" {\n") + .append(" if (").append(precedenceChecksFlagName).append(")\n") + .append(" {\n") + .append(" switch (codecState)\n") + .append(" {\n"); + + fieldPrecedenceModel.forEachTerminalEncoderState(state -> + { + sb.append(" case ").append(stateCaseForSwitchCase(state)).append(":\n") + .append(" return;\n"); + }); + + sb.append(" default:\n") + .append(" throw new IllegalStateException(\"Not fully encoded, current state: \" +\n") + .append(" CodecStates.name(codecState) + \", allowed transitions: \" +\n") + .append(" CodecStates.transitions(codecState));\n") + .append(" }\n") + .append(" }\n") + .append(" }\n\n"); + } + + private static String accessOrderListenerMethodName(final Token token) + { + return "on" + Generators.toUpperFirstChar(token.name()) + "Accessed"; + } + + private static String accessOrderListenerMethodName(final Token token, final String suffix) + { + return "on" + Generators.toUpperFirstChar(token.name()) + suffix + "Accessed"; + } + + private static void generateAccessOrderListenerMethod( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append("\n") + .append(indent).append("private void ").append(accessOrderListenerMethodName(token)).append("()\n") + .append(indent).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction fieldAccess = + fieldPrecedenceModel.interactionFactory().accessField(token); + + generateAccessOrderListener( + sb, + indent + " ", + "access field", + fieldPrecedenceModel, + fieldAccess); + + sb.append(indent).append("}\n"); + } + + private CharSequence generateAccessOrderListenerCall( + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token, + final String... arguments) + { + return generateAccessOrderListenerCall( + fieldPrecedenceModel, + indent, + accessOrderListenerMethodName(token), + arguments); + } + + private CharSequence generateAccessOrderListenerCall( + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final String methodName, + final String... arguments) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + sb.append(indent).append("if (").append(precedenceChecksFlagName).append(")\n") + .append(indent).append("{\n") + .append(indent).append(" ").append(methodName).append("("); + + for (int i = 0; i < arguments.length; i++) + { + if (i > 0) + { + sb.append(", "); + } + sb.append(arguments[i]); + } + sb.append(");\n"); + + sb.append(indent).append("}\n\n"); + + return sb; + } + + private static void generateAccessOrderListenerMethodForGroupWrap( + final StringBuilder sb, + final String action, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append("\n") + .append(indent).append("private void ").append(accessOrderListenerMethodName(token)) + .append("(final int count)\n") + .append(indent).append("{\n") + .append(indent).append(" if (count == 0)\n") + .append(indent).append(" {\n"); + + final FieldPrecedenceModel.CodecInteraction selectEmptyGroup = + fieldPrecedenceModel.interactionFactory().determineGroupIsEmpty(token); + + generateAccessOrderListener( + sb, + indent + " ", + action + " count of repeating group", + fieldPrecedenceModel, + selectEmptyGroup); + + sb.append(indent).append(" }\n") + .append(indent).append(" else\n") + .append(indent).append(" {\n"); + + final FieldPrecedenceModel.CodecInteraction selectNonEmptyGroup = + fieldPrecedenceModel.interactionFactory().determineGroupHasElements(token); + + generateAccessOrderListener( + sb, + indent + " ", + action + " count of repeating group", + fieldPrecedenceModel, + selectNonEmptyGroup); + + sb.append(indent).append(" }\n") + .append(indent).append("}\n"); + } + + private static void generateAccessOrderListener( + final StringBuilder sb, + final String indent, + final String action, + final FieldPrecedenceModel fieldPrecedenceModel, + final FieldPrecedenceModel.CodecInteraction interaction) + { + if (interaction.isTopLevelBlockFieldAccess()) + { + sb.append(indent).append("if (codecState() == ") + .append(qualifiedStateCase(fieldPrecedenceModel.notWrappedState())) + .append(")\n") + .append(indent).append("{\n"); + generateAccessOrderException(sb, indent + " ", action, fieldPrecedenceModel, interaction); + sb.append(indent).append("}\n"); + } + else + { + sb.append(indent).append("switch (codecState())\n") + .append(indent).append("{\n"); + + fieldPrecedenceModel.forEachTransition(interaction, transitionGroup -> + { + transitionGroup.forEachStartState(startState -> + sb.append(indent).append(" case ").append(stateCaseForSwitchCase(startState)).append(":\n")); + sb.append(indent).append(" codecState(") + .append(qualifiedStateCase(transitionGroup.endState())).append(");\n") + .append(indent).append(" break;\n"); + }); + + sb.append(indent).append(" default:\n"); + generateAccessOrderException(sb, indent + " ", action, fieldPrecedenceModel, interaction); + sb.append(indent).append("}\n"); + } + } + + private static void generateAccessOrderException( + final StringBuilder sb, + final String indent, + final String action, + final FieldPrecedenceModel fieldPrecedenceModel, + final FieldPrecedenceModel.CodecInteraction interaction) + { + sb.append(indent).append("throw new IllegalStateException(") + .append("\"Illegal field access order. \" +\n") + .append(indent) + .append(" \"Cannot ").append(action).append(" \\\"").append(interaction.groupQualifiedName()) + .append("\\\" in state: \" + CodecStates.name(codecState()) +\n") + .append(indent) + .append(" \". Expected one of these transitions: [\" + CodecStates.transitions(codecState()) +\n") + .append(indent) + .append(" \"]. Please see the diagram in the Javadoc of the class ") + .append(fieldPrecedenceModel.generatedRepresentationClassName()).append(".\");\n"); + } + + private static void generateAccessOrderListenerMethodForNextGroupElement( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append(indent).append("private void onNextElementAccessed()\n") + .append(indent).append("{\n") + .append(indent).append(" final int remaining = ").append("count - index").append(";\n") + .append(indent).append(" if (remaining > 1)\n") + .append(indent).append(" {\n"); + + final FieldPrecedenceModel.CodecInteraction selectNextElementInGroup = + fieldPrecedenceModel.interactionFactory().moveToNextElement(token); + + generateAccessOrderListener( + sb, + indent + " ", + "access next element in repeating group", + fieldPrecedenceModel, + selectNextElementInGroup); + + sb.append(indent).append(" }\n") + .append(indent).append(" else if (remaining == 1)\n") + .append(indent).append(" {\n"); + + final FieldPrecedenceModel.CodecInteraction selectLastElementInGroup = + fieldPrecedenceModel.interactionFactory().moveToLastElement(token); + + generateAccessOrderListener( + sb, + indent + " ", + "access next element in repeating group", + fieldPrecedenceModel, + selectLastElementInGroup); + + sb.append(indent).append(" }\n") + .append(indent).append("}\n\n"); + } + + private static void generateAccessOrderListenerMethodForResetGroupCount( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append(indent).append("private void onResetCountToIndex()\n") + .append(indent).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction resetCountToIndex = + fieldPrecedenceModel.interactionFactory().resetCountToIndex(token); + + generateAccessOrderListener( + sb, + indent + " ", + "reset count of repeating group", + fieldPrecedenceModel, + resetCountToIndex); + + sb.append(indent).append("}\n\n"); + } + + private static void generateAccessOrderListenerMethodForVarDataLength( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent, + final Token token) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb.append("\n") + .append(indent).append("void ").append(accessOrderListenerMethodName(token, "Length")).append("()\n") + .append(indent).append("{\n"); + + final FieldPrecedenceModel.CodecInteraction accessLength = + fieldPrecedenceModel.interactionFactory().accessVarDataLength(token); + + generateAccessOrderListener( + sb, + indent + INDENT, + "decode length of var data", + fieldPrecedenceModel, + accessLength); + + sb.append(indent).append("}\n"); + } + + private static CharSequence generateDecoderWrapListener( + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + sb.append(indent).append("private void onWrap(final int actingVersion)\n") + .append(indent).append("{\n") + .append(indent).append(" switch(actingVersion)\n") + .append(indent).append(" {\n"); + + fieldPrecedenceModel.forEachWrappedStateByVersion((version, state) -> + { + sb.append(indent).append(" case ").append(version).append(":\n") + .append(indent).append(" codecState(") + .append(qualifiedStateCase(state)).append(");\n") + .append(indent).append(" break;\n"); + }); + + sb.append(indent).append(" default:\n") + .append(indent).append(" codecState(") + .append(qualifiedStateCase(fieldPrecedenceModel.latestVersionWrappedState())).append(");\n") + .append(indent).append(" break;\n") + .append(indent).append(" }\n") + .append(indent).append("}\n\n"); + + return sb; + } + + private CharSequence generateEncoderWrapListener( + final FieldPrecedenceModel fieldPrecedenceModel, + final String indent) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + sb.append(indent).append("if (").append(precedenceChecksFlagName).append(")") + .append("\n").append(indent).append("{\n") + .append(indent).append(" codecState(") + .append(qualifiedStateCase(fieldPrecedenceModel.latestVersionWrappedState())) + .append(");\n") + .append(indent).append("}\n\n"); + return sb; + } + private void generateDecoder( + final String className, final Token msgToken, final List fields, final List groups, final List varData, - final boolean hasVarData) + final boolean hasVarData, + final FieldPrecedenceModel fieldPrecedenceModel) throws IOException { - final String className = formatClassName(decoderName(msgToken.name())); final String implementsString = implementsInterface(MessageDecoderFlyweight.class.getSimpleName()); try (Writer out = outputManager.createOutput(className)) @@ -288,13 +830,15 @@ private void generateDecoder( { generateAnnotations(BASE_INDENT, className, groups, out, this::decoderName); } + out.append(generateDeclaration(className, implementsString, msgToken)); - out.append(generateDecoderFlyweightCode(className, msgToken)); + out.append(generateFieldOrderStates(fieldPrecedenceModel)); + out.append(generateDecoderFlyweightCode(fieldPrecedenceModel, className, msgToken)); final StringBuilder sb = new StringBuilder(); - generateDecoderFields(sb, fields, BASE_INDENT); - generateDecoderGroups(sb, className, groups, BASE_INDENT, false); - generateDecoderVarData(sb, varData, BASE_INDENT); + generateDecoderFields(sb, fieldPrecedenceModel, fields, BASE_INDENT); + generateDecoderGroups(sb, fieldPrecedenceModel, className, groups, BASE_INDENT, false); + generateDecoderVarData(sb, fieldPrecedenceModel, varData, BASE_INDENT); generateDecoderDisplay(sb, msgToken.name(), fields, groups, varData); generateMessageLength(sb, className, true, groups, varData, BASE_INDENT); @@ -306,7 +850,7 @@ private void generateDecoder( private void generateDecoderGroups( final StringBuilder sb, - final String outerClassName, + final FieldPrecedenceModel fieldPrecedenceModel, final String outerClassName, final List tokens, final String indent, final boolean isSubGroup) throws IOException @@ -335,18 +879,19 @@ private void generateDecoderGroups( final List varData = new ArrayList<>(); i = collectVarData(tokens, i, varData); - generateGroupDecoderProperty(sb, groupName, groupToken, indent, isSubGroup); + generateGroupDecoderProperty(sb, groupName, fieldPrecedenceModel, groupToken, indent, isSubGroup); generateTypeJavadoc(sb, indent + INDENT, groupToken); if (shouldGenerateGroupOrderAnnotation) { generateAnnotations(indent + INDENT, groupName, groups, sb, this::decoderName); } - generateGroupDecoderClassHeader(sb, groupName, outerClassName, tokens, groups, index, indent + INDENT); + generateGroupDecoderClassHeader(sb, groupName, outerClassName, fieldPrecedenceModel, groupToken, + tokens, groups, index, indent + INDENT); - generateDecoderFields(sb, fields, indent + INDENT); - generateDecoderGroups(sb, outerClassName, groups, indent + INDENT, true); - generateDecoderVarData(sb, varData, indent + INDENT); + generateDecoderFields(sb, fieldPrecedenceModel, fields, indent + INDENT); + generateDecoderGroups(sb, fieldPrecedenceModel, outerClassName, groups, indent + INDENT, true); + generateDecoderVarData(sb, fieldPrecedenceModel, varData, indent + INDENT); appendGroupInstanceDecoderDisplay(sb, fields, groups, varData, indent + INDENT); generateMessageLength(sb, groupName, false, groups, varData, indent + INDENT); @@ -358,6 +903,7 @@ private void generateDecoderGroups( private void generateEncoderGroups( final StringBuilder sb, final String outerClassName, + final FieldPrecedenceModel fieldPrecedenceModel, final List tokens, final String indent, final boolean isSubGroup) throws IOException @@ -387,18 +933,20 @@ private void generateEncoderGroups( final List varData = new ArrayList<>(); i = collectVarData(tokens, i, varData); - generateGroupEncoderProperty(sb, groupName, groupToken, indent, isSubGroup); + generateGroupEncoderProperty(sb, groupName, fieldPrecedenceModel, groupToken, indent, isSubGroup); generateTypeJavadoc(sb, indent + INDENT, groupToken); if (shouldGenerateGroupOrderAnnotation) { generateAnnotations(indent + INDENT, groupClassName, groups, sb, this::encoderName); } - generateGroupEncoderClassHeader(sb, groupName, outerClassName, tokens, groups, index, indent + INDENT); + generateGroupEncoderClassHeader( + sb, groupName, outerClassName, fieldPrecedenceModel, groupToken, + tokens, groups, index, indent + INDENT); - generateEncoderFields(sb, groupClassName, fields, indent + INDENT); - generateEncoderGroups(sb, outerClassName, groups, indent + INDENT, true); - generateEncoderVarData(sb, groupClassName, varData, indent + INDENT); + generateEncoderFields(sb, groupClassName, fieldPrecedenceModel, fields, indent + INDENT); + generateEncoderGroups(sb, outerClassName, fieldPrecedenceModel, groups, indent + INDENT, true); + generateEncoderVarData(sb, groupClassName, fieldPrecedenceModel, varData, indent + INDENT); sb.append(indent).append(" }\n"); } @@ -408,6 +956,8 @@ private void generateGroupDecoderClassHeader( final StringBuilder sb, final String groupName, final String parentMessageClassName, + final FieldPrecedenceModel fieldPrecedenceModel, + final Token groupToken, final List tokens, final List subGroupTokens, final int index, @@ -452,15 +1002,18 @@ private void generateGroupDecoderClassHeader( .append(indent).append(" parentMessage.limit(limit + HEADER_SIZE);\n") .append(indent).append(" blockLength = ").append(blockLenCast).append(blockLengthGet).append(";\n") .append(indent).append(" count = ").append(numInGroupCast).append(numInGroupGet).append(";\n") - .append(indent).append(" }\n"); + .append(indent).append(" }\n\n"); - sb.append("\n") - .append(indent).append(" public ").append(className).append(" next()\n") + + generateAccessOrderListenerMethodForNextGroupElement(sb, fieldPrecedenceModel, indent + " ", groupToken); + + sb.append(indent).append(" public ").append(className).append(" next()\n") .append(indent).append(" {\n") .append(indent).append(" if (index >= count)\n") .append(indent).append(" {\n") .append(indent).append(" throw new java.util.NoSuchElementException();\n") .append(indent).append(" }\n\n") + .append(generateAccessOrderListenerCall(fieldPrecedenceModel, indent + " ", "onNextElementAccessed")) .append(indent).append(" offset = parentMessage.limit();\n") .append(indent).append(" parentMessage.limit(offset + blockLength);\n") .append(indent).append(" ++index;\n\n") @@ -508,12 +1061,29 @@ private void generateGroupDecoderClassHeader( .append(indent).append(" {\n") .append(indent).append(" return index < count;\n") .append(indent).append(" }\n"); + + if (null != fieldPrecedenceModel) + { + sb.append("\n") + .append(indent).append(" private int codecState()\n") + .append(indent).append(" {\n") + .append(indent).append(" return parentMessage.codecState();\n") + .append(indent).append(" }\n"); + + sb.append("\n") + .append(indent).append(" private void codecState(final int newState)\n") + .append(indent).append(" {\n") + .append(indent).append(" parentMessage.codecState(newState);\n") + .append(indent).append(" }\n"); + } } private void generateGroupEncoderClassHeader( final StringBuilder sb, final String groupName, final String parentMessageClassName, + final FieldPrecedenceModel fieldPrecedenceModel, + final Token groupToken, final List tokens, final List subGroupTokens, final int index, @@ -566,7 +1136,7 @@ private void generateGroupEncoderClassHeader( ind + " parentMessage.limit(limit + HEADER_SIZE);\n" + ind + " %5$s;\n" + ind + " %6$s;\n" + - ind + " }\n", + ind + " }\n\n", parentMessageClassName, mutableBuffer, numInGroupToken.encoding().applicableMinValue().longValue(), @@ -574,9 +1144,12 @@ private void generateGroupEncoderClassHeader( blockLengthPut, numInGroupPut); - sb.append("\n") - .append(ind).append(" public ").append(encoderName(groupName)).append(" next()\n") + generateAccessOrderListenerMethodForNextGroupElement(sb, fieldPrecedenceModel, ind + " ", groupToken); + generateAccessOrderListenerMethodForResetGroupCount(sb, fieldPrecedenceModel, ind + " ", groupToken); + + sb.append(ind).append(" public ").append(encoderName(groupName)).append(" next()\n") .append(ind).append(" {\n") + .append(generateAccessOrderListenerCall(fieldPrecedenceModel, ind + " ", "onNextElementAccessed")) .append(ind).append(" if (index >= count)\n") .append(ind).append(" {\n") .append(ind).append(" throw new java.util.NoSuchElementException();\n") @@ -585,15 +1158,15 @@ private void generateGroupEncoderClassHeader( .append(ind).append(" parentMessage.limit(offset + sbeBlockLength());\n") .append(ind).append(" ++index;\n\n") .append(ind).append(" return this;\n") - .append(ind).append(" }\n"); + .append(ind).append(" }\n\n"); final String countOffset = "initialLimit + " + numInGroupToken.offset(); final String resetCountPut = generatePut( numInGroupTypeCast, countOffset, numInGroupValue, byteOrderString(numInGroupToken.encoding())); - sb.append("\n") - .append(ind).append(" public int resetCountToIndex()\n") + sb.append(ind).append(" public int resetCountToIndex()\n") .append(ind).append(" {\n") + .append(generateAccessOrderListenerCall(fieldPrecedenceModel, ind + " ", "onResetCountToIndex")) .append(ind).append(" count = index;\n") .append(ind).append(" ").append(resetCountPut).append(";\n\n") .append(ind).append(" return count;\n") @@ -618,6 +1191,21 @@ private void generateGroupEncoderClassHeader( .append(ind).append(" {\n") .append(ind).append(" return ").append(blockLength).append(";\n") .append(ind).append(" }\n"); + + if (null != fieldPrecedenceModel) + { + sb.append("\n") + .append(ind).append(" private int codecState()\n") + .append(ind).append(" {\n") + .append(ind).append(" return parentMessage.codecState();\n") + .append(ind).append(" }\n"); + + sb.append("\n") + .append(ind).append(" private void codecState(final int newState)\n") + .append(ind).append(" {\n") + .append(ind).append(" parentMessage.codecState(newState);\n") + .append(ind).append(" }\n"); + } } private static String primitiveTypeName(final Token token) @@ -728,9 +1316,10 @@ private void generateGroupEncoderClassDeclaration( sb.append(indent).append(" }\n"); } - private static void generateGroupDecoderProperty( + private void generateGroupDecoderProperty( final StringBuilder sb, final String groupName, + final FieldPrecedenceModel fieldPrecedenceModel, final Token token, final String indent, final boolean isSubGroup) @@ -772,22 +1361,27 @@ private static void generateGroupDecoderProperty( indent + " return " + propertyName + ";\n" + indent + " }\n\n"; + generateAccessOrderListenerMethodForGroupWrap(sb, "decode", fieldPrecedenceModel, indent + " ", token); + generateFlyweightPropertyJavadoc(sb, indent + INDENT, token, className); new Formatter(sb).format("\n" + indent + " public %1$s %2$s()\n" + indent + " {\n" + "%3$s" + indent + " %2$s.wrap(buffer);\n" + + "%4$s" + indent + " return %2$s;\n" + indent + " }\n", className, propertyName, - actingVersionGuard); + actingVersionGuard, + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + " ", token, propertyName + ".count")); } private void generateGroupEncoderProperty( final StringBuilder sb, final String groupName, + final FieldPrecedenceModel fieldPrecedenceModel, final Token token, final String indent, final boolean isSubGroup) @@ -812,19 +1406,26 @@ private void generateGroupEncoderProperty( formatPropertyName(groupName), token.id()); + generateAccessOrderListenerMethodForGroupWrap(sb, "encode", fieldPrecedenceModel, indent + " ", token); + generateGroupEncodePropertyJavadoc(sb, indent + INDENT, token, className); new Formatter(sb).format("\n" + indent + " public %1$s %2$sCount(final int count)\n" + indent + " {\n" + + "%3$s" + indent + " %2$s.wrap(buffer, count);\n" + indent + " return %2$s;\n" + indent + " }\n", className, - propertyName); + propertyName, + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + " ", token, "count")); } private void generateDecoderVarData( - final StringBuilder sb, final List tokens, final String indent) + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final List tokens, + final String indent) { for (int i = 0, size = tokens.size(); i < size;) { @@ -855,24 +1456,39 @@ private void generateDecoderVarData( .append(indent).append(" return ").append(sizeOfLengthField).append(";\n") .append(indent).append(" }\n"); + generateAccessOrderListenerMethodForVarDataLength(sb, fieldPrecedenceModel, indent + " ", token); + + final CharSequence lengthAccessOrderListenerCall = generateAccessOrderListenerCall( + fieldPrecedenceModel, indent + " ", accessOrderListenerMethodName(token, "Length")); + + generateAccessOrderListenerMethod(sb, fieldPrecedenceModel, indent + " ", token); + sb.append("\n") .append(indent).append(" public int ").append(methodPropName).append("Length()\n") .append(indent).append(" {\n") .append(generateArrayFieldNotPresentCondition(token.version(), indent)) + .append(lengthAccessOrderListenerCall) .append(indent).append(" final int limit = parentMessage.limit();\n") .append(indent).append(" return ").append(PrimitiveType.UINT32 == lengthType ? "(int)" : "") .append(generateGet(lengthType, "limit", byteOrderStr)).append(";\n") .append(indent).append(" }\n"); - generateDataDecodeMethods( - sb, token, propertyName, sizeOfLengthField, lengthType, byteOrderStr, characterEncoding, indent); + final CharSequence accessOrderListenerCall = + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + " ", token); + + generateDataDecodeMethods(sb, token, propertyName, sizeOfLengthField, lengthType, + byteOrderStr, characterEncoding, accessOrderListenerCall, indent); i += token.componentTokenCount(); } } private void generateEncoderVarData( - final StringBuilder sb, final String className, final List tokens, final String indent) + final StringBuilder sb, + final String className, + final FieldPrecedenceModel fieldPrecedenceModel, + final List tokens, + final String indent) { for (int i = 0, size = tokens.size(); i < size;) { @@ -903,9 +1519,14 @@ private void generateEncoderVarData( .append(sizeOfLengthField).append(";\n") .append(indent).append(" }\n"); + generateAccessOrderListenerMethod(sb, fieldPrecedenceModel, indent + " ", token); + final CharSequence accessOrderListenerCall = + generateAccessOrderListenerCall(fieldPrecedenceModel, indent + " ", token); + generateDataEncodeMethods( sb, propertyName, + accessOrderListenerCall, sizeOfLengthField, maxLengthValue, lengthEncoding.primitiveType(), @@ -926,12 +1547,14 @@ private void generateDataDecodeMethods( final PrimitiveType lengthType, final String byteOrderStr, final String characterEncoding, + final CharSequence accessOrderListenerCall, final String indent) { new Formatter(sb).format("\n" + indent + " public int skip%1$s()\n" + indent + " {\n" + "%2$s" + + "%6$s" + indent + " final int headerLength = %3$d;\n" + indent + " final int limit = parentMessage.limit();\n" + indent + " final int dataLength = %4$s%5$s;\n" + @@ -943,7 +1566,8 @@ private void generateDataDecodeMethods( generateStringNotPresentConditionForAppendable(token.version(), indent), sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", - generateGet(lengthType, "limit", byteOrderStr)); + generateGet(lengthType, "limit", byteOrderStr), + accessOrderListenerCall); generateVarDataTypedDecoder( sb, @@ -953,6 +1577,7 @@ private void generateDataDecodeMethods( mutableBuffer, lengthType, byteOrderStr, + accessOrderListenerCall, indent); generateVarDataTypedDecoder( @@ -963,9 +1588,18 @@ private void generateDataDecodeMethods( "byte[]", lengthType, byteOrderStr, + accessOrderListenerCall, indent); - generateVarDataWrapDecoder(sb, token, propertyName, sizeOfLengthField, lengthType, byteOrderStr, indent); + generateVarDataWrapDecoder( + sb, + token, + propertyName, + sizeOfLengthField, + lengthType, + byteOrderStr, + accessOrderListenerCall, + indent); if (null != characterEncoding) { @@ -973,6 +1607,7 @@ private void generateDataDecodeMethods( indent + " public String %1$s()\n" + indent + " {\n" + "%2$s" + + "%7$s" + indent + " final int headerLength = %3$d;\n" + indent + " final int limit = parentMessage.limit();\n" + indent + " final int dataLength = %4$s%5$s;\n" + @@ -990,7 +1625,8 @@ private void generateDataDecodeMethods( sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", generateGet(lengthType, "limit", byteOrderStr), - charset(characterEncoding)); + charset(characterEncoding), + accessOrderListenerCall); if (isAsciiEncoding(characterEncoding)) { @@ -998,6 +1634,7 @@ private void generateDataDecodeMethods( indent + " public int get%1$s(final Appendable appendable)\n" + indent + " {\n" + "%2$s" + + "%6$s" + indent + " final int headerLength = %3$d;\n" + indent + " final int limit = parentMessage.limit();\n" + indent + " final int dataLength = %4$s%5$s;\n" + @@ -1010,7 +1647,8 @@ private void generateDataDecodeMethods( generateStringNotPresentConditionForAppendable(token.version(), indent), sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", - generateGet(lengthType, "limit", byteOrderStr)); + generateGet(lengthType, "limit", byteOrderStr), + accessOrderListenerCall); } } } @@ -1022,12 +1660,14 @@ private void generateVarDataWrapDecoder( final int sizeOfLengthField, final PrimitiveType lengthType, final String byteOrderStr, + final CharSequence accessOrderListenerCall, final String indent) { new Formatter(sb).format("\n" + indent + " public void wrap%s(final %s wrapBuffer)\n" + indent + " {\n" + "%s" + + "%s" + indent + " final int headerLength = %d;\n" + indent + " final int limit = parentMessage.limit();\n" + indent + " final int dataLength = %s%s;\n" + @@ -1037,6 +1677,7 @@ private void generateVarDataWrapDecoder( propertyName, readOnlyBuffer, generateWrapFieldNotPresentCondition(token.version(), indent), + accessOrderListenerCall, sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", generateGet(lengthType, "limit", byteOrderStr)); @@ -1045,6 +1686,7 @@ private void generateVarDataWrapDecoder( private void generateDataEncodeMethods( final StringBuilder sb, final String propertyName, + final CharSequence accessOrderListenerCall, final int sizeOfLengthField, final int maxLengthValue, final PrimitiveType lengthType, @@ -1057,6 +1699,7 @@ private void generateDataEncodeMethods( sb, className, propertyName, + accessOrderListenerCall, sizeOfLengthField, maxLengthValue, readOnlyBuffer, @@ -1068,6 +1711,7 @@ private void generateDataEncodeMethods( sb, className, propertyName, + accessOrderListenerCall, sizeOfLengthField, maxLengthValue, "byte[]", @@ -1080,6 +1724,7 @@ private void generateDataEncodeMethods( generateCharArrayEncodeMethods( sb, propertyName, + accessOrderListenerCall, sizeOfLengthField, maxLengthValue, lengthType, @@ -1093,6 +1738,7 @@ private void generateDataEncodeMethods( private void generateCharArrayEncodeMethods( final StringBuilder sb, final String propertyName, + final CharSequence accessOrderListenerCall, final int sizeOfLengthField, final int maxLengthValue, final PrimitiveType lengthType, @@ -1113,6 +1759,7 @@ private void generateCharArrayEncodeMethods( indent + " {\n" + indent + " throw new IllegalStateException(\"length > maxValue for type: \" + length);\n" + indent + " }\n\n" + + "%6$s" + indent + " final int headerLength = %4$d;\n" + indent + " final int limit = parentMessage.limit();\n" + indent + " parentMessage.limit(limit + headerLength + length);\n" + @@ -1124,7 +1771,8 @@ private void generateCharArrayEncodeMethods( formatPropertyName(propertyName), maxLengthValue, sizeOfLengthField, - generatePut(lengthPutType, "limit", "length", byteOrderStr)); + generatePut(lengthPutType, "limit", "length", byteOrderStr), + accessOrderListenerCall); new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final CharSequence value)\n" + @@ -1134,6 +1782,7 @@ private void generateCharArrayEncodeMethods( indent + " {\n" + indent + " throw new IllegalStateException(\"length > maxValue for type: \" + length);\n" + indent + " }\n\n" + + "%6$s" + indent + " final int headerLength = %4$d;\n" + indent + " final int limit = parentMessage.limit();\n" + indent + " parentMessage.limit(limit + headerLength + length);\n" + @@ -1145,7 +1794,8 @@ private void generateCharArrayEncodeMethods( formatPropertyName(propertyName), maxLengthValue, sizeOfLengthField, - generatePut(lengthPutType, "limit", "length", byteOrderStr)); + generatePut(lengthPutType, "limit", "length", byteOrderStr), + accessOrderListenerCall); } else { @@ -1159,6 +1809,7 @@ private void generateCharArrayEncodeMethods( indent + " {\n" + indent + " throw new IllegalStateException(\"length > maxValue for type: \" + length);\n" + indent + " }\n\n" + + "%7$s" + indent + " final int headerLength = %5$d;\n" + indent + " final int limit = parentMessage.limit();\n" + indent + " parentMessage.limit(limit + headerLength + length);\n" + @@ -1171,7 +1822,8 @@ private void generateCharArrayEncodeMethods( charset(characterEncoding), maxLengthValue, sizeOfLengthField, - generatePut(lengthPutType, "limit", "length", byteOrderStr)); + generatePut(lengthPutType, "limit", "length", byteOrderStr), + accessOrderListenerCall); } } @@ -1183,12 +1835,14 @@ private void generateVarDataTypedDecoder( final String exchangeType, final PrimitiveType lengthType, final String byteOrderStr, + final CharSequence accessOrderListenerCall, final String indent) { new Formatter(sb).format("\n" + indent + " public int get%s(final %s dst, final int dstOffset, final int length)\n" + indent + " {\n" + "%s" + + "%s" + indent + " final int headerLength = %d;\n" + indent + " final int limit = parentMessage.limit();\n" + indent + " final int dataLength = %s%s;\n" + @@ -1200,6 +1854,7 @@ private void generateVarDataTypedDecoder( propertyName, exchangeType, generateArrayFieldNotPresentCondition(token.version(), indent), + accessOrderListenerCall, sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", generateGet(lengthType, "limit", byteOrderStr)); @@ -1209,6 +1864,7 @@ private void generateDataTypedEncoder( final StringBuilder sb, final String className, final String propertyName, + final CharSequence accessOrderListenerCall, final int sizeOfLengthField, final int maxLengthValue, final String exchangeType, @@ -1225,6 +1881,7 @@ private void generateDataTypedEncoder( indent + " {\n" + indent + " throw new IllegalStateException(\"length > maxValue for type: \" + length);\n" + indent + " }\n\n" + + "%7$s" + indent + " final int headerLength = %5$d;\n" + indent + " final int limit = parentMessage.limit();\n" + indent + " parentMessage.limit(limit + headerLength + length);\n" + @@ -1237,7 +1894,8 @@ private void generateDataTypedEncoder( exchangeType, maxLengthValue, sizeOfLengthField, - generatePut(lengthPutType, "limit", "length", byteOrderStr)); + generatePut(lengthPutType, "limit", "length", byteOrderStr), + accessOrderListenerCall); } private void generateBitSet(final List tokens) throws IOException @@ -1359,26 +2017,29 @@ private void generateComposite(final List tokens) throws IOException generateEncodingOffsetMethod(sb, propertyName, encodingToken.offset(), BASE_INDENT); generateEncodingLengthMethod(sb, propertyName, encodingToken.encodedLength(), BASE_INDENT); generateFieldSinceVersionMethod(sb, encodingToken, BASE_INDENT); + final String accessOrderListenerCall = ""; switch (encodingToken.signal()) { case ENCODING: generatePrimitiveDecoder( - sb, true, encodingToken.name(), encodingToken, encodingToken, BASE_INDENT); + sb, true, encodingToken.name(), "", encodingToken, encodingToken, BASE_INDENT); break; case BEGIN_ENUM: - generateEnumDecoder(sb, true, encodingToken, propertyName, encodingToken, BASE_INDENT); + generateEnumDecoder(sb, true, "", encodingToken, propertyName, encodingToken, BASE_INDENT); break; case BEGIN_SET: generateBitSetProperty( - sb, true, DECODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName); + sb, true, DECODER, propertyName, accessOrderListenerCall, + encodingToken, encodingToken, BASE_INDENT, typeName); break; case BEGIN_COMPOSITE: generateCompositeProperty( - sb, true, DECODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName); + sb, true, DECODER, propertyName, accessOrderListenerCall, + encodingToken, encodingToken, BASE_INDENT, typeName); break; default: @@ -1410,25 +2071,30 @@ private void generateComposite(final List tokens) throws IOException final StringBuilder sb = new StringBuilder(); generateEncodingOffsetMethod(sb, propertyName, encodingToken.offset(), BASE_INDENT); generateEncodingLengthMethod(sb, propertyName, encodingToken.encodedLength(), BASE_INDENT); + final String accessOrderListenerCall = ""; switch (encodingToken.signal()) { case ENCODING: - generatePrimitiveEncoder(sb, encoderName, encodingToken.name(), encodingToken, BASE_INDENT); + generatePrimitiveEncoder(sb, encoderName, encodingToken.name(), + accessOrderListenerCall, encodingToken, BASE_INDENT); break; case BEGIN_ENUM: - generateEnumEncoder(sb, encoderName, encodingToken, propertyName, encodingToken, BASE_INDENT); + generateEnumEncoder(sb, encoderName, accessOrderListenerCall, + encodingToken, propertyName, encodingToken, BASE_INDENT); break; case BEGIN_SET: generateBitSetProperty( - sb, true, ENCODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName); + sb, true, ENCODER, propertyName, accessOrderListenerCall, + encodingToken, encodingToken, BASE_INDENT, typeName); break; case BEGIN_COMPOSITE: generateCompositeProperty( - sb, true, ENCODER, propertyName, encodingToken, encodingToken, BASE_INDENT, typeName); + sb, true, ENCODER, propertyName, accessOrderListenerCall, + encodingToken, encodingToken, BASE_INDENT, typeName); break; default: @@ -1855,6 +2521,7 @@ private void generatePrimitiveDecoder( final StringBuilder sb, final boolean inComposite, final String propertyName, + final CharSequence accessOrderListenerCall, final Token propertyToken, final Token encodingToken, final String indent) @@ -1870,7 +2537,7 @@ private void generatePrimitiveDecoder( else { sb.append(generatePrimitivePropertyDecodeMethods( - inComposite, formattedPropertyName, propertyToken, encodingToken, indent)); + inComposite, formattedPropertyName, accessOrderListenerCall, propertyToken, encodingToken, indent)); } } @@ -1878,43 +2545,52 @@ private void generatePrimitiveEncoder( final StringBuilder sb, final String containingClassName, final String propertyName, - final Token token, + final CharSequence accessOrderListenerCall, + final Token typeToken, final String indent) { final String formattedPropertyName = formatPropertyName(propertyName); - generatePrimitiveFieldMetaMethod(sb, formattedPropertyName, token, indent); + generatePrimitiveFieldMetaMethod(sb, formattedPropertyName, typeToken, indent); - if (!token.isConstantEncoding()) + if (!typeToken.isConstantEncoding()) { sb.append(generatePrimitivePropertyEncodeMethods( - containingClassName, formattedPropertyName, token, indent)); + containingClassName, formattedPropertyName, accessOrderListenerCall, typeToken, indent)); } else { - generateConstPropertyMethods(sb, formattedPropertyName, token, indent); + generateConstPropertyMethods(sb, formattedPropertyName, typeToken, indent); } } private CharSequence generatePrimitivePropertyDecodeMethods( final boolean inComposite, final String propertyName, + final CharSequence accessOrderListenerCall, final Token propertyToken, final Token encodingToken, final String indent) { return encodingToken.matchOnLength( - () -> generatePrimitivePropertyDecode(inComposite, propertyName, propertyToken, encodingToken, indent), + () -> generatePrimitivePropertyDecode( + inComposite, propertyName, accessOrderListenerCall, propertyToken, encodingToken, indent), () -> generatePrimitiveArrayPropertyDecode( - inComposite, propertyName, propertyToken, encodingToken, indent)); + inComposite, propertyName, accessOrderListenerCall, propertyToken, encodingToken, indent)); } private CharSequence generatePrimitivePropertyEncodeMethods( - final String containingClassName, final String propertyName, final Token token, final String indent) + final String containingClassName, + final String propertyName, + final CharSequence accessOrderListenerCall, + final Token typeToken, + final String indent) { - return token.matchOnLength( - () -> generatePrimitivePropertyEncode(containingClassName, propertyName, token, indent), - () -> generatePrimitiveArrayPropertyEncode(containingClassName, propertyName, token, indent)); + return typeToken.matchOnLength( + () -> generatePrimitivePropertyEncode( + containingClassName, propertyName, accessOrderListenerCall, typeToken, indent), + () -> generatePrimitiveArrayPropertyEncode( + containingClassName, propertyName, accessOrderListenerCall, typeToken, indent)); } private void generatePrimitiveFieldMetaMethod( @@ -1953,6 +2629,7 @@ private void generatePrimitiveFieldMetaMethod( private CharSequence generatePrimitivePropertyDecode( final boolean inComposite, final String propertyName, + final CharSequence accessOrderListenerCall, final Token propertyToken, final Token encodingToken, final String indent) @@ -1968,32 +2645,40 @@ private CharSequence generatePrimitivePropertyDecode( indent + " public %s %s()\n" + indent + " {\n" + "%s" + + "%s" + indent + " return %s;\n" + indent + " }\n\n", javaTypeName, formatPropertyName(propertyName), generateFieldNotPresentCondition(inComposite, propertyToken.version(), encoding, indent), + accessOrderListenerCall, generateGet(encoding.primitiveType(), "offset + " + offset, byteOrderStr)); } private CharSequence generatePrimitivePropertyEncode( - final String containingClassName, final String propertyName, final Token token, final String indent) + final String containingClassName, + final String propertyName, + final CharSequence accessOrderListenerCall, + final Token typeToken, + final String indent) { - final Encoding encoding = token.encoding(); + final Encoding encoding = typeToken.encoding(); final String javaTypeName = javaTypeName(encoding.primitiveType()); - final int offset = token.offset(); + final int offset = typeToken.offset(); final String byteOrderStr = byteOrderString(encoding); return String.format( "\n" + indent + " public %s %s(final %s value)\n" + indent + " {\n" + + "%s" + indent + " %s;\n" + indent + " return this;\n" + indent + " }\n\n", formatClassName(containingClassName), formatPropertyName(propertyName), javaTypeName, + accessOrderListenerCall, generatePut(encoding.primitiveType(), "offset + " + offset, "value", byteOrderStr)); } @@ -2094,6 +2779,7 @@ private static CharSequence generatePropertyNotPresentCondition( private CharSequence generatePrimitiveArrayPropertyDecode( final boolean inComposite, final String propertyName, + final CharSequence accessOrderListenerCall, final Token propertyToken, final Token encodingToken, final String indent) @@ -2117,6 +2803,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( indent + " throw new IndexOutOfBoundsException(\"index out of range: index=\" + index);\n" + indent + " }\n\n" + "%s" + + "%s" + indent + " final int pos = offset + %d + (index * %d);\n\n" + indent + " return %s;\n" + indent + " }\n\n", @@ -2124,6 +2811,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( propertyName, fieldLength, generateFieldNotPresentCondition(inComposite, propertyToken.version(), encoding, indent), + accessOrderListenerCall, offset, typeSize, generateGet(encoding.primitiveType(), "pos", byteOrderStr)); @@ -2142,18 +2830,21 @@ private CharSequence generatePrimitiveArrayPropertyDecode( "\"Copy will go out of range: offset=\" + dstOffset);\n" + indent + " }\n\n" + "%s" + + "%s" + indent + " buffer.getBytes(offset + %d, dst, dstOffset, length);\n\n" + indent + " return length;\n" + indent + " }\n", Generators.toUpperFirstChar(propertyName), fieldLength, generateArrayFieldNotPresentCondition(propertyToken.version(), indent), + accessOrderListenerCall, offset); new Formatter(sb).format("\n" + indent + " public String %s()\n" + indent + " {\n" + "%s" + + "%s" + indent + " final byte[] dst = new byte[%d];\n" + indent + " buffer.getBytes(offset + %d, dst, 0, %d);\n\n" + indent + " int end = 0;\n" + @@ -2162,6 +2853,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( indent + " }\n\n", propertyName, generateStringNotPresentCondition(propertyToken.version(), indent), + accessOrderListenerCall, fieldLength, offset, fieldLength, @@ -2174,6 +2866,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( indent + " public int get%1$s(final Appendable value)\n" + indent + " {\n" + "%2$s" + + "%5$s" + indent + " for (int i = 0; i < %3$d; ++i)\n" + indent + " {\n" + indent + " final int c = buffer.getByte(offset + %4$d + i) & 0xFF;\n" + @@ -2195,7 +2888,8 @@ private CharSequence generatePrimitiveArrayPropertyDecode( Generators.toUpperFirstChar(propertyName), generateStringNotPresentConditionForAppendable(propertyToken.version(), indent), fieldLength, - offset); + offset, + accessOrderListenerCall); } } else if (encoding.primitiveType() == PrimitiveType.UINT8) @@ -2204,12 +2898,14 @@ else if (encoding.primitiveType() == PrimitiveType.UINT8) indent + " public int get%s(final byte[] dst, final int dstOffset, final int length)\n" + indent + " {\n" + "%s" + + "%s" + indent + " final int bytesCopied = Math.min(length, %d);\n" + indent + " buffer.getBytes(offset + %d, dst, dstOffset, bytesCopied);\n\n" + indent + " return bytesCopied;\n" + indent + " }\n", Generators.toUpperFirstChar(propertyName), generateArrayFieldNotPresentCondition(propertyToken.version(), indent), + accessOrderListenerCall, fieldLength, offset); @@ -2217,6 +2913,7 @@ else if (encoding.primitiveType() == PrimitiveType.UINT8) indent + " public int get%s(final %s dst, final int dstOffset, final int length)\n" + indent + " {\n" + "%s" + + "%s" + indent + " final int bytesCopied = Math.min(length, %d);\n" + indent + " buffer.getBytes(offset + %d, dst, dstOffset, bytesCopied);\n\n" + indent + " return bytesCopied;\n" + @@ -2224,6 +2921,7 @@ else if (encoding.primitiveType() == PrimitiveType.UINT8) Generators.toUpperFirstChar(propertyName), fqMutableBuffer, generateArrayFieldNotPresentCondition(propertyToken.version(), indent), + accessOrderListenerCall, fieldLength, offset); @@ -2231,11 +2929,13 @@ else if (encoding.primitiveType() == PrimitiveType.UINT8) indent + " public void wrap%s(final %s wrapBuffer)\n" + indent + " {\n" + "%s" + + "%s" + indent + " wrapBuffer.wrap(buffer, offset + %d, %d);\n" + indent + " }\n", Generators.toUpperFirstChar(propertyName), readOnlyBuffer, generateWrapFieldNotPresentCondition(propertyToken.version(), indent), + accessOrderListenerCall, offset, fieldLength); } @@ -2260,14 +2960,18 @@ private String byteOrderString(final Encoding encoding) } private CharSequence generatePrimitiveArrayPropertyEncode( - final String containingClassName, final String propertyName, final Token token, final String indent) + final String containingClassName, + final String propertyName, + final CharSequence accessOrderListenerCall, + final Token typeToken, + final String indent) { - final Encoding encoding = token.encoding(); + final Encoding encoding = typeToken.encoding(); final PrimitiveType primitiveType = encoding.primitiveType(); final String javaTypeName = javaTypeName(primitiveType); - final int offset = token.offset(); + final int offset = typeToken.offset(); final String byteOrderStr = byteOrderString(encoding); - final int arrayLength = token.arrayLength(); + final int arrayLength = typeToken.arrayLength(); final int typeSize = sizeOfPrimitive(encoding); final StringBuilder sb = new StringBuilder(); @@ -2282,6 +2986,7 @@ private CharSequence generatePrimitiveArrayPropertyEncode( indent + " {\n" + indent + " throw new IndexOutOfBoundsException(\"index out of range: index=\" + index);\n" + indent + " }\n\n" + + "%s" + indent + " final int pos = offset + %d + (index * %d);\n" + indent + " %s;\n\n" + indent + " return this;\n" + @@ -2290,6 +2995,7 @@ private CharSequence generatePrimitiveArrayPropertyEncode( propertyName, javaTypeName, arrayLength, + accessOrderListenerCall, offset, typeSize, generatePut(primitiveType, "pos", "value", byteOrderStr)); @@ -2310,6 +3016,8 @@ private CharSequence generatePrimitiveArrayPropertyEncode( sb.append(")\n"); sb.append(indent).append(" {\n"); + sb.append(accessOrderListenerCall); + for (int i = 0; i < arrayLength; i++) { final String indexStr = "offset + " + (offset + (typeSize * i)); @@ -2327,12 +3035,25 @@ private CharSequence generatePrimitiveArrayPropertyEncode( if (primitiveType == PrimitiveType.CHAR) { generateCharArrayEncodeMethods( - containingClassName, propertyName, indent, encoding, offset, arrayLength, sb); + containingClassName, + propertyName, + indent, + accessOrderListenerCall, + encoding, + offset, + arrayLength, + sb); } else if (primitiveType == PrimitiveType.UINT8) { generateByteArrayEncodeMethods( - containingClassName, propertyName, indent, offset, arrayLength, sb); + containingClassName, + propertyName, + indent, + accessOrderListenerCall, + offset, + arrayLength, + sb); } return sb; @@ -2342,6 +3063,7 @@ private void generateCharArrayEncodeMethods( final String containingClassName, final String propertyName, final String indent, + final CharSequence accessOrderListenerCall, final Encoding encoding, final int offset, final int fieldLength, @@ -2358,12 +3080,14 @@ private void generateCharArrayEncodeMethods( indent + " throw new IndexOutOfBoundsException(" + "\"Copy will go out of range: offset=\" + srcOffset);\n" + indent + " }\n\n" + + "%s" + indent + " buffer.putBytes(offset + %d, src, srcOffset, length);\n\n" + indent + " return this;\n" + indent + " }\n", formatClassName(containingClassName), Generators.toUpperFirstChar(propertyName), fieldLength, + accessOrderListenerCall, offset); if (isAsciiEncoding(encoding.characterEncoding())) @@ -2378,6 +3102,7 @@ private void generateCharArrayEncodeMethods( indent + " throw new IndexOutOfBoundsException(" + "\"String too large for copy: byte length=\" + srcLength);\n" + indent + " }\n\n" + + "%5$s" + indent + " buffer.putStringWithoutLengthAscii(offset + %4$d, src);\n\n" + indent + " for (int start = srcLength; start < length; ++start)\n" + indent + " {\n" + @@ -2388,7 +3113,8 @@ private void generateCharArrayEncodeMethods( formatClassName(containingClassName), propertyName, fieldLength, - offset); + offset, + accessOrderListenerCall); new Formatter(sb).format("\n" + indent + " public %1$s %2$s(final CharSequence src)\n" + @@ -2400,6 +3126,7 @@ private void generateCharArrayEncodeMethods( indent + " throw new IndexOutOfBoundsException(" + "\"CharSequence too large for copy: byte length=\" + srcLength);\n" + indent + " }\n\n" + + "%5$s" + indent + " buffer.putStringWithoutLengthAscii(offset + %4$d, src);\n\n" + indent + " for (int start = srcLength; start < length; ++start)\n" + indent + " {\n" + @@ -2410,7 +3137,8 @@ private void generateCharArrayEncodeMethods( formatClassName(containingClassName), propertyName, fieldLength, - offset); + offset, + accessOrderListenerCall); } else { @@ -2425,6 +3153,7 @@ private void generateCharArrayEncodeMethods( indent + " throw new IndexOutOfBoundsException(" + "\"String too large for copy: byte length=\" + bytes.length);\n" + indent + " }\n\n" + + "%s" + indent + " buffer.putBytes(offset + %d, bytes, 0, bytes.length);\n\n" + indent + " for (int start = bytes.length; start < length; ++start)\n" + indent + " {\n" + @@ -2436,6 +3165,7 @@ private void generateCharArrayEncodeMethods( propertyName, fieldLength, charset(encoding.characterEncoding()), + accessOrderListenerCall, offset, offset); } @@ -2445,6 +3175,7 @@ private void generateByteArrayEncodeMethods( final String containingClassName, final String propertyName, final String indent, + final CharSequence accessOrderListenerCall, final int offset, final int fieldLength, final StringBuilder sb) @@ -2457,6 +3188,7 @@ private void generateByteArrayEncodeMethods( indent + " throw new IllegalStateException(" + "\"length > maxValue for type: \" + length);\n" + indent + " }\n\n" + + "%s" + indent + " buffer.putBytes(offset + %d, src, srcOffset, length);\n" + indent + " for (int i = length; i < %d; i++)\n" + indent + " {\n" + @@ -2467,6 +3199,7 @@ private void generateByteArrayEncodeMethods( formatClassName(containingClassName), Generators.toUpperFirstChar(propertyName), fieldLength, + accessOrderListenerCall, offset, fieldLength, offset); @@ -2479,6 +3212,7 @@ private void generateByteArrayEncodeMethods( indent + " throw new IllegalStateException(" + "\"length > maxValue for type: \" + length);\n" + indent + " }\n\n" + + "%s" + indent + " buffer.putBytes(offset + %d, src, srcOffset, length);\n" + indent + " for (int i = length; i < %d; i++)\n" + indent + " {\n" + @@ -2490,6 +3224,7 @@ private void generateByteArrayEncodeMethods( Generators.toUpperFirstChar(propertyName), fqReadOnlyBuffer, fieldLength, + accessOrderListenerCall, offset, fieldLength, offset); @@ -2663,67 +3398,90 @@ private CharSequence generateFixedFlyweightCode( semanticVersion); } - private CharSequence generateDecoderFlyweightCode(final String className, final Token token) + private CharSequence generateDecoderFlyweightCode( + final FieldPrecedenceModel fieldPrecedenceModel, + final String className, + final Token token) { final String headerClassName = formatClassName(ir.headerStructure().tokens().get(0).applicableTypeName()); - final String methods = - " public " + className + " wrap(\n" + - " final " + readOnlyBuffer + " buffer,\n" + - " final int offset,\n" + - " final int actingBlockLength,\n" + - " final int actingVersion)\n" + - " {\n" + - " if (buffer != this.buffer)\n" + - " {\n" + - " this.buffer = buffer;\n" + - " }\n" + - " this.initialOffset = offset;\n" + - " this.offset = offset;\n" + - " this.actingBlockLength = actingBlockLength;\n" + - " this.actingVersion = actingVersion;\n" + - " limit(offset + actingBlockLength);\n\n" + - " return this;\n" + - " }\n\n" + + final StringBuilder methods = new StringBuilder(); - " public " + className + " wrapAndApplyHeader(\n" + - " final " + readOnlyBuffer + " buffer,\n" + - " final int offset,\n" + - " final " + headerClassName + "Decoder headerDecoder)\n" + - " {\n" + - " headerDecoder.wrap(buffer, offset);\n\n" + - " final int templateId = headerDecoder.templateId();\n" + - " if (TEMPLATE_ID != templateId)\n" + - " {\n" + - " throw new IllegalStateException(\"Invalid TEMPLATE_ID: \" + templateId);\n" + - " }\n\n" + - " return wrap(\n" + - " buffer,\n" + - " offset + " + headerClassName + "Decoder.ENCODED_LENGTH,\n" + - " headerDecoder.blockLength(),\n" + - " headerDecoder.version());\n" + - " }\n\n" + + methods.append(generateDecoderWrapListener(fieldPrecedenceModel, " ")); - " public " + className + " sbeRewind()\n" + - " {\n" + - " return wrap(buffer, initialOffset, actingBlockLength, actingVersion);\n" + - " }\n\n" + + methods.append(" public ").append(className).append(" wrap(\n") + .append(" final ").append(readOnlyBuffer).append(" buffer,\n") + .append(" final int offset,\n") + .append(" final int actingBlockLength,\n") + .append(" final int actingVersion)\n") + .append(" {\n") + .append(" if (buffer != this.buffer)\n") + .append(" {\n") + .append(" this.buffer = buffer;\n") + .append(" }\n") + .append(" this.initialOffset = offset;\n") + .append(" this.offset = offset;\n") + .append(" this.actingBlockLength = actingBlockLength;\n") + .append(" this.actingVersion = actingVersion;\n") + .append(" limit(offset + actingBlockLength);\n\n") + .append(generateAccessOrderListenerCall(fieldPrecedenceModel, " ", "onWrap", "actingVersion")) + .append(" return this;\n") + .append(" }\n\n"); - " public int sbeDecodedLength()\n" + - " {\n" + - " final int currentLimit = limit();\n" + - " sbeSkip();\n" + - " final int decodedLength = encodedLength();\n" + - " limit(currentLimit);\n\n" + - " return decodedLength;\n" + - " }\n\n" + + methods.append(" public ").append(className).append(" wrapAndApplyHeader(\n") + .append(" final ").append(readOnlyBuffer).append(" buffer,\n") + .append(" final int offset,\n") + .append(" final ").append(headerClassName).append("Decoder headerDecoder)\n") + .append(" {\n") + .append(" headerDecoder.wrap(buffer, offset);\n\n") + .append(" final int templateId = headerDecoder.templateId();\n") + .append(" if (TEMPLATE_ID != templateId)\n") + .append(" {\n") + .append(" throw new IllegalStateException(\"Invalid TEMPLATE_ID: \" + templateId);\n") + .append(" }\n\n") + .append(" return wrap(\n") + .append(" buffer,\n") + .append(" offset + ").append(headerClassName).append("Decoder.ENCODED_LENGTH,\n") + .append(" headerDecoder.blockLength(),\n") + .append(" headerDecoder.version());\n") + .append(" }\n\n"); + + methods.append(" public ").append(className).append(" sbeRewind()\n") + .append(" {\n") + .append(" return wrap(buffer, initialOffset, actingBlockLength, actingVersion);\n") + .append(" }\n\n"); - " public int actingVersion()\n" + - " {\n" + - " return actingVersion;\n" + - " }\n\n"; + methods.append(" public int sbeDecodedLength()\n") + .append(" {\n") + .append(" final int currentLimit = limit();\n"); - return generateFlyweightCode(DECODER, className, token, methods, readOnlyBuffer); + if (null != fieldPrecedenceModel) + { + methods.append(" final int currentCodecState = codecState();\n"); + } + + methods + .append(" sbeSkip();\n") + .append(" final int decodedLength = encodedLength();\n") + .append(" limit(currentLimit);\n\n"); + + if (null != fieldPrecedenceModel) + { + methods.append(" if (").append(precedenceChecksFlagName).append(")\n") + .append(" {\n") + .append(" codecState(currentCodecState);\n") + .append(" }\n\n"); + } + + methods.append(" return decodedLength;\n") + .append(" }\n\n"); + + methods.append(" public int actingVersion()\n") + .append(" {\n") + .append(" return actingVersion;\n") + .append(" }\n\n"); + + return generateFlyweightCode(DECODER, className, token, methods.toString(), readOnlyBuffer); } private CharSequence generateFlyweightCode( @@ -2829,7 +3587,10 @@ private CharSequence generateFlyweightCode( semanticVersion); } - private CharSequence generateEncoderFlyweightCode(final String className, final Token token) + private CharSequence generateEncoderFlyweightCode( + final String className, + final FieldPrecedenceModel fieldPrecedenceModel, + final Token token) { final String wrapMethod = " public " + className + " wrap(final " + mutableBuffer + " buffer, final int offset)\n" + @@ -2841,6 +3602,7 @@ private CharSequence generateEncoderFlyweightCode(final String className, final " this.initialOffset = offset;\n" + " this.offset = offset;\n" + " limit(offset + BLOCK_LENGTH);\n\n" + + generateEncoderWrapListener(fieldPrecedenceModel, " ") + " return this;\n" + " }\n\n"; @@ -2889,7 +3651,11 @@ private CharSequence generateEncoderFlyweightCode(final String className, final } private void generateEncoderFields( - final StringBuilder sb, final String containingClassName, final List tokens, final String indent) + final StringBuilder sb, + final String containingClassName, + final FieldPrecedenceModel fieldPrecedenceModel, + final List tokens, + final String indent) { Generators.forEachField( tokens, @@ -2903,25 +3669,32 @@ private void generateEncoderFields( generateEncodingOffsetMethod(sb, propertyName, fieldToken.offset(), indent); generateEncodingLengthMethod(sb, propertyName, typeToken.encodedLength(), indent); generateFieldMetaAttributeMethod(sb, fieldToken, indent); + generateAccessOrderListenerMethod(sb, fieldPrecedenceModel, indent + " ", fieldToken); + final CharSequence accessOrderListenerCall = generateAccessOrderListenerCall( + fieldPrecedenceModel, indent + " ", fieldToken); switch (typeToken.signal()) { case ENCODING: - generatePrimitiveEncoder(sb, containingClassName, propertyName, typeToken, indent); + generatePrimitiveEncoder(sb, containingClassName, propertyName, + accessOrderListenerCall, typeToken, indent); break; case BEGIN_ENUM: - generateEnumEncoder(sb, containingClassName, fieldToken, propertyName, typeToken, indent); + generateEnumEncoder(sb, containingClassName, + accessOrderListenerCall, fieldToken, propertyName, typeToken, indent); break; case BEGIN_SET: generateBitSetProperty( - sb, false, ENCODER, propertyName, fieldToken, typeToken, indent, typeName); + sb, false, ENCODER, propertyName, accessOrderListenerCall, + fieldToken, typeToken, indent, typeName); break; case BEGIN_COMPOSITE: generateCompositeProperty( - sb, false, ENCODER, propertyName, fieldToken, typeToken, indent, typeName); + sb, false, ENCODER, propertyName, accessOrderListenerCall, + fieldToken, typeToken, indent, typeName); break; default: @@ -2930,7 +3703,11 @@ private void generateEncoderFields( }); } - private void generateDecoderFields(final StringBuilder sb, final List tokens, final String indent) + private void generateDecoderFields( + final StringBuilder sb, + final FieldPrecedenceModel fieldPrecedenceModel, + final List tokens, + final String indent) { Generators.forEachField( tokens, @@ -2945,24 +3722,32 @@ private void generateDecoderFields(final StringBuilder sb, final List tok generateEncodingLengthMethod(sb, propertyName, typeToken.encodedLength(), indent); generateFieldMetaAttributeMethod(sb, fieldToken, indent); + generateAccessOrderListenerMethod(sb, fieldPrecedenceModel, indent + " ", fieldToken); + final CharSequence accessOrderListenerCall = generateAccessOrderListenerCall( + fieldPrecedenceModel, indent + " ", fieldToken); + switch (typeToken.signal()) { case ENCODING: - generatePrimitiveDecoder(sb, false, propertyName, fieldToken, typeToken, indent); + generatePrimitiveDecoder( + sb, false, propertyName, accessOrderListenerCall, fieldToken, typeToken, indent); break; case BEGIN_ENUM: - generateEnumDecoder(sb, false, fieldToken, propertyName, typeToken, indent); + generateEnumDecoder( + sb, false, accessOrderListenerCall, fieldToken, propertyName, typeToken, indent); break; case BEGIN_SET: generateBitSetProperty( - sb, false, DECODER, propertyName, fieldToken, typeToken, indent, typeName); + sb, false, DECODER, propertyName, accessOrderListenerCall, + fieldToken, typeToken, indent, typeName); break; case BEGIN_COMPOSITE: generateCompositeProperty( - sb, false, DECODER, propertyName, fieldToken, typeToken, indent, typeName); + sb, false, DECODER, propertyName, accessOrderListenerCall, + fieldToken, typeToken, indent, typeName); break; default: @@ -3063,6 +3848,7 @@ private static void generateFieldMetaAttributeMethod(final StringBuilder sb, fin private void generateEnumDecoder( final StringBuilder sb, final boolean inComposite, + final CharSequence accessOrderListenerCall, final Token fieldToken, final String propertyName, final Token typeToken, @@ -3107,11 +3893,13 @@ private void generateEnumDecoder( indent + " public %s %sRaw()\n" + indent + " {\n" + "%s" + + "%s" + indent + " return %s;\n" + indent + " }\n", javaTypeName, formatPropertyName(propertyName), generateFieldNotPresentCondition(inComposite, fieldToken.version(), encoding, indent), + accessOrderListenerCall, rawGetStr); new Formatter(sb).format( @@ -3119,11 +3907,13 @@ private void generateEnumDecoder( indent + " public %s %s()\n" + indent + " {\n" + "%s" + + "%s" + indent + " return %s.get(%s);\n" + indent + " }\n\n", enumName, propertyName, generatePropertyNotPresentCondition(inComposite, DECODER, fieldToken, enumName, indent), + accessOrderListenerCall, enumName, rawGetStr); } @@ -3132,6 +3922,7 @@ private void generateEnumDecoder( private void generateEnumEncoder( final StringBuilder sb, final String containingClassName, + final CharSequence accessOrderListenerCall, final Token fieldToken, final String propertyName, final Token typeToken, @@ -3147,12 +3938,14 @@ private void generateEnumEncoder( new Formatter(sb).format("\n" + indent + " public %s %s(final %s value)\n" + indent + " {\n" + + "%s" + indent + " %s;\n" + indent + " return this;\n" + indent + " }\n", formatClassName(containingClassName), propertyName, enumName, + accessOrderListenerCall, generatePut(encoding.primitiveType(), "offset + " + offset, "value.value()", byteOrderString)); } } @@ -3162,6 +3955,7 @@ private void generateBitSetProperty( final boolean inComposite, final CodecType codecType, final String propertyName, + final CharSequence accessOrderListenerCall, final Token propertyToken, final Token bitsetToken, final String indent, @@ -3178,12 +3972,14 @@ private void generateBitSetProperty( indent + " public %s %s()\n" + indent + " {\n" + "%s" + + "%s" + indent + " %s.wrap(buffer, offset + %d);\n" + indent + " return %s;\n" + indent + " }\n", bitSetName, propertyName, generatePropertyNotPresentCondition(inComposite, codecType, propertyToken, null, indent), + accessOrderListenerCall, propertyName, bitsetToken.offset(), propertyName); @@ -3194,6 +3990,7 @@ private void generateCompositeProperty( final boolean inComposite, final CodecType codecType, final String propertyName, + final CharSequence accessOrderListenerCall, final Token propertyToken, final Token compositeToken, final String indent, @@ -3210,12 +4007,14 @@ private void generateCompositeProperty( indent + " public %s %s()\n" + indent + " {\n" + "%s" + + "%s" + indent + " %s.wrap(buffer, offset + %d);\n" + indent + " return %s;\n" + indent + " }\n", compositeName, propertyName, generatePropertyNotPresentCondition(inComposite, codecType, propertyToken, null, indent), + accessOrderListenerCall, propertyName, compositeToken.offset(), propertyName); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 8cbdc11954..89962bd61f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -11,6 +11,83 @@ @SuppressWarnings("all") public final class FrameCodecDecoder { + private static final boolean ENABLE_BOUNDS_CHECKS = !Boolean.getBoolean("agrona.disable.bounds.checks"); + + private static final boolean SBE_ENABLE_IR_PRECEDENCE_CHECKS = Boolean.parseBoolean(System.getProperty( + "sbe.enable.ir.precedence.checks", + Boolean.toString(ENABLE_BOUNDS_CHECKS))); + + /** + * The states in which a encoder/decoder/codec can live. + * + *

      The state machine diagram below, encoded in the dot language, describes + * the valid state transitions according to the order in which fields may be + * accessed safely. Tools such as PlantUML and Graphviz can render it. + * + *

      {@code
      +     *   digraph G {
      +     *       NOT_WRAPPED -> V0_BLOCK [label="  wrap(version=0)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  irId(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  irVersion(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  schemaVersion(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  packageNameLength()  "];
      +     *       V0_BLOCK -> V0_PACKAGENAME_DONE [label="  packageName(?)  "];
      +     *       V0_PACKAGENAME_DONE -> V0_PACKAGENAME_DONE [label="  namespaceNameLength()  "];
      +     *       V0_PACKAGENAME_DONE -> V0_NAMESPACENAME_DONE [label="  namespaceName(?)  "];
      +     *       V0_NAMESPACENAME_DONE -> V0_NAMESPACENAME_DONE [label="  semanticVersionLength()  "];
      +     *       V0_NAMESPACENAME_DONE -> V0_SEMANTICVERSION_DONE [label="  semanticVersion(?)  "];
      +     *   }
      +     * }
      + */ + private static class CodecStates + { + private static final int NOT_WRAPPED = 0; + private static final int V0_BLOCK = 1; + private static final int V0_PACKAGENAME_DONE = 2; + private static final int V0_NAMESPACENAME_DONE = 3; + private static final int V0_SEMANTICVERSION_DONE = 4; + + private static final String[] STATE_NAME_LOOKUP = + { + "NOT_WRAPPED", + "V0_BLOCK", + "V0_PACKAGENAME_DONE", + "V0_NAMESPACENAME_DONE", + "V0_SEMANTICVERSION_DONE", + }; + + private static final String[] STATE_TRANSITIONS_LOOKUP = + { + "\"wrap(version=0)\"", + "\"irId(?)\", \"irVersion(?)\", \"schemaVersion(?)\", \"packageNameLength()\", \"packageName(?)\"", + "\"namespaceNameLength()\", \"namespaceName(?)\"", + "\"semanticVersionLength()\", \"semanticVersion(?)\"", + "", + }; + + private static String name(final int state) + { + return STATE_NAME_LOOKUP[state]; + } + + private static String transitions(final int state) + { + return STATE_TRANSITIONS_LOOKUP[state]; + } + } + + private int codecState = CodecStates.NOT_WRAPPED; + + private int codecState() + { + return codecState; + } + + private void codecState(int newState) + { + codecState = newState; + } + public static final int BLOCK_LENGTH = 12; public static final int TEMPLATE_ID = 1; public static final int SCHEMA_ID = 1; @@ -66,6 +143,19 @@ public int offset() return offset; } + private void onWrap(final int actingVersion) + { + switch(actingVersion) + { + case 0: + codecState(CodecStates.V0_BLOCK); + break; + default: + codecState(CodecStates.V0_BLOCK); + break; + } + } + public FrameCodecDecoder wrap( final DirectBuffer buffer, final int offset, @@ -82,6 +172,11 @@ public FrameCodecDecoder wrap( this.actingVersion = actingVersion; limit(offset + actingBlockLength); + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onWrap(actingVersion); + } + return this; } @@ -113,10 +208,16 @@ public FrameCodecDecoder sbeRewind() public int sbeDecodedLength() { final int currentLimit = limit(); + final int currentCodecState = codecState(); sbeSkip(); final int decodedLength = encodedLength(); limit(currentLimit); + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + codecState(currentCodecState); + } + return decodedLength; } @@ -170,6 +271,17 @@ public static String irIdMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onIrIdAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"irId\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecDecoder#CodecStates."); + } + } + public static int irIdNullValue() { return -2147483648; @@ -187,6 +299,11 @@ public static int irIdMaxValue() public int irId() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onIrIdAccessed(); + } + return buffer.getInt(offset + 0, java.nio.ByteOrder.LITTLE_ENDIAN); } @@ -221,6 +338,17 @@ public static String irVersionMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onIrVersionAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"irVersion\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecDecoder#CodecStates."); + } + } + public static int irVersionNullValue() { return -2147483648; @@ -238,6 +366,11 @@ public static int irVersionMaxValue() public int irVersion() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onIrVersionAccessed(); + } + return buffer.getInt(offset + 4, java.nio.ByteOrder.LITTLE_ENDIAN); } @@ -272,6 +405,17 @@ public static String schemaVersionMetaAttribute(final MetaAttribute metaAttribut return ""; } + private void onSchemaVersionAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"schemaVersion\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecDecoder#CodecStates."); + } + } + public static int schemaVersionNullValue() { return -2147483648; @@ -289,6 +433,11 @@ public static int schemaVersionMaxValue() public int schemaVersion() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSchemaVersionAccessed(); + } + return buffer.getInt(offset + 8, java.nio.ByteOrder.LITTLE_ENDIAN); } @@ -323,14 +472,54 @@ public static int packageNameHeaderLength() return 2; } + void onPackageNameLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_BLOCK: + codecState(CodecStates.V0_BLOCK); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"packageName\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecDecoder#CodecStates."); + } + } + + private void onPackageNameAccessed() + { + switch (codecState()) + { + case CodecStates.V0_BLOCK: + codecState(CodecStates.V0_PACKAGENAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"packageName\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecDecoder#CodecStates."); + } + } + public int packageNameLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipPackageName() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -342,6 +531,11 @@ public int skipPackageName() public int getPackageName(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -354,6 +548,11 @@ public int getPackageName(final MutableDirectBuffer dst, final int dstOffset, fi public int getPackageName(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -366,6 +565,11 @@ public int getPackageName(final byte[] dst, final int dstOffset, final int lengt public void wrapPackageName(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -375,6 +579,11 @@ public void wrapPackageName(final DirectBuffer wrapBuffer) public String packageName() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -421,14 +630,54 @@ public static int namespaceNameHeaderLength() return 2; } + void onNamespaceNameLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_PACKAGENAME_DONE: + codecState(CodecStates.V0_PACKAGENAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"namespaceName\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecDecoder#CodecStates."); + } + } + + private void onNamespaceNameAccessed() + { + switch (codecState()) + { + case CodecStates.V0_PACKAGENAME_DONE: + codecState(CodecStates.V0_NAMESPACENAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"namespaceName\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecDecoder#CodecStates."); + } + } + public int namespaceNameLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNamespaceNameLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipNamespaceName() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNamespaceNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -440,6 +689,11 @@ public int skipNamespaceName() public int getNamespaceName(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNamespaceNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -452,6 +706,11 @@ public int getNamespaceName(final MutableDirectBuffer dst, final int dstOffset, public int getNamespaceName(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNamespaceNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -464,6 +723,11 @@ public int getNamespaceName(final byte[] dst, final int dstOffset, final int len public void wrapNamespaceName(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNamespaceNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -473,6 +737,11 @@ public void wrapNamespaceName(final DirectBuffer wrapBuffer) public String namespaceName() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNamespaceNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -519,14 +788,54 @@ public static int semanticVersionHeaderLength() return 2; } + void onSemanticVersionLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_NAMESPACENAME_DONE: + codecState(CodecStates.V0_NAMESPACENAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"semanticVersion\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecDecoder#CodecStates."); + } + } + + private void onSemanticVersionAccessed() + { + switch (codecState()) + { + case CodecStates.V0_NAMESPACENAME_DONE: + codecState(CodecStates.V0_SEMANTICVERSION_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"semanticVersion\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecDecoder#CodecStates."); + } + } + public int semanticVersionLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticVersionLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipSemanticVersion() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticVersionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -538,6 +847,11 @@ public int skipSemanticVersion() public int getSemanticVersion(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticVersionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -550,6 +864,11 @@ public int getSemanticVersion(final MutableDirectBuffer dst, final int dstOffset public int getSemanticVersion(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticVersionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -562,6 +881,11 @@ public int getSemanticVersion(final byte[] dst, final int dstOffset, final int l public void wrapSemanticVersion(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticVersionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -571,6 +895,11 @@ public void wrapSemanticVersion(final DirectBuffer wrapBuffer) public String semanticVersion() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticVersionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index 0fd115d556..a5524033fc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -11,6 +11,83 @@ @SuppressWarnings("all") public final class FrameCodecEncoder { + private static final boolean ENABLE_BOUNDS_CHECKS = !Boolean.getBoolean("agrona.disable.bounds.checks"); + + private static final boolean SBE_ENABLE_IR_PRECEDENCE_CHECKS = Boolean.parseBoolean(System.getProperty( + "sbe.enable.ir.precedence.checks", + Boolean.toString(ENABLE_BOUNDS_CHECKS))); + + /** + * The states in which a encoder/decoder/codec can live. + * + *

      The state machine diagram below, encoded in the dot language, describes + * the valid state transitions according to the order in which fields may be + * accessed safely. Tools such as PlantUML and Graphviz can render it. + * + *

      {@code
      +     *   digraph G {
      +     *       NOT_WRAPPED -> V0_BLOCK [label="  wrap(version=0)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  irId(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  irVersion(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  schemaVersion(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  packageNameLength()  "];
      +     *       V0_BLOCK -> V0_PACKAGENAME_DONE [label="  packageName(?)  "];
      +     *       V0_PACKAGENAME_DONE -> V0_PACKAGENAME_DONE [label="  namespaceNameLength()  "];
      +     *       V0_PACKAGENAME_DONE -> V0_NAMESPACENAME_DONE [label="  namespaceName(?)  "];
      +     *       V0_NAMESPACENAME_DONE -> V0_NAMESPACENAME_DONE [label="  semanticVersionLength()  "];
      +     *       V0_NAMESPACENAME_DONE -> V0_SEMANTICVERSION_DONE [label="  semanticVersion(?)  "];
      +     *   }
      +     * }
      + */ + private static class CodecStates + { + private static final int NOT_WRAPPED = 0; + private static final int V0_BLOCK = 1; + private static final int V0_PACKAGENAME_DONE = 2; + private static final int V0_NAMESPACENAME_DONE = 3; + private static final int V0_SEMANTICVERSION_DONE = 4; + + private static final String[] STATE_NAME_LOOKUP = + { + "NOT_WRAPPED", + "V0_BLOCK", + "V0_PACKAGENAME_DONE", + "V0_NAMESPACENAME_DONE", + "V0_SEMANTICVERSION_DONE", + }; + + private static final String[] STATE_TRANSITIONS_LOOKUP = + { + "\"wrap(version=0)\"", + "\"irId(?)\", \"irVersion(?)\", \"schemaVersion(?)\", \"packageNameLength()\", \"packageName(?)\"", + "\"namespaceNameLength()\", \"namespaceName(?)\"", + "\"semanticVersionLength()\", \"semanticVersion(?)\"", + "", + }; + + private static String name(final int state) + { + return STATE_NAME_LOOKUP[state]; + } + + private static String transitions(final int state) + { + return STATE_TRANSITIONS_LOOKUP[state]; + } + } + + private int codecState = CodecStates.NOT_WRAPPED; + + private int codecState() + { + return codecState; + } + + private void codecState(int newState) + { + codecState = newState; + } + public static final int BLOCK_LENGTH = 12; public static final int TEMPLATE_ID = 1; public static final int SCHEMA_ID = 1; @@ -74,6 +151,11 @@ public FrameCodecEncoder wrap(final MutableDirectBuffer buffer, final int offset this.offset = offset; limit(offset + BLOCK_LENGTH); + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + codecState(CodecStates.V0_BLOCK); + } + return this; } @@ -135,6 +217,17 @@ public static String irIdMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onIrIdAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"irId\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecEncoder#CodecStates."); + } + } + public static int irIdNullValue() { return -2147483648; @@ -152,6 +245,11 @@ public static int irIdMaxValue() public FrameCodecEncoder irId(final int value) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onIrIdAccessed(); + } + buffer.putInt(offset + 0, value, java.nio.ByteOrder.LITTLE_ENDIAN); return this; } @@ -187,6 +285,17 @@ public static String irVersionMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onIrVersionAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"irVersion\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecEncoder#CodecStates."); + } + } + public static int irVersionNullValue() { return -2147483648; @@ -204,6 +313,11 @@ public static int irVersionMaxValue() public FrameCodecEncoder irVersion(final int value) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onIrVersionAccessed(); + } + buffer.putInt(offset + 4, value, java.nio.ByteOrder.LITTLE_ENDIAN); return this; } @@ -239,6 +353,17 @@ public static String schemaVersionMetaAttribute(final MetaAttribute metaAttribut return ""; } + private void onSchemaVersionAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"schemaVersion\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecEncoder#CodecStates."); + } + } + public static int schemaVersionNullValue() { return -2147483648; @@ -256,6 +381,11 @@ public static int schemaVersionMaxValue() public FrameCodecEncoder schemaVersion(final int value) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSchemaVersionAccessed(); + } + buffer.putInt(offset + 8, value, java.nio.ByteOrder.LITTLE_ENDIAN); return this; } @@ -286,6 +416,21 @@ public static int packageNameHeaderLength() return 2; } + private void onPackageNameAccessed() + { + switch (codecState()) + { + case CodecStates.V0_BLOCK: + codecState(CodecStates.V0_PACKAGENAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"packageName\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecEncoder#CodecStates."); + } + } + public FrameCodecEncoder putPackageName(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -293,6 +438,11 @@ public FrameCodecEncoder putPackageName(final DirectBuffer src, final int srcOff throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -309,6 +459,11 @@ public FrameCodecEncoder putPackageName(final byte[] src, final int srcOffset, f throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -328,6 +483,11 @@ public FrameCodecEncoder packageName(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -362,6 +522,21 @@ public static int namespaceNameHeaderLength() return 2; } + private void onNamespaceNameAccessed() + { + switch (codecState()) + { + case CodecStates.V0_PACKAGENAME_DONE: + codecState(CodecStates.V0_NAMESPACENAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"namespaceName\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecEncoder#CodecStates."); + } + } + public FrameCodecEncoder putNamespaceName(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -369,6 +544,11 @@ public FrameCodecEncoder putNamespaceName(final DirectBuffer src, final int srcO throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNamespaceNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -385,6 +565,11 @@ public FrameCodecEncoder putNamespaceName(final byte[] src, final int srcOffset, throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNamespaceNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -404,6 +589,11 @@ public FrameCodecEncoder namespaceName(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNamespaceNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -438,6 +628,21 @@ public static int semanticVersionHeaderLength() return 2; } + private void onSemanticVersionAccessed() + { + switch (codecState()) + { + case CodecStates.V0_NAMESPACENAME_DONE: + codecState(CodecStates.V0_SEMANTICVERSION_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"semanticVersion\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class FrameCodecEncoder#CodecStates."); + } + } + public FrameCodecEncoder putSemanticVersion(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -445,6 +650,11 @@ public FrameCodecEncoder putSemanticVersion(final DirectBuffer src, final int sr throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticVersionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -461,6 +671,11 @@ public FrameCodecEncoder putSemanticVersion(final byte[] src, final int srcOffse throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticVersionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -480,6 +695,11 @@ public FrameCodecEncoder semanticVersion(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticVersionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -511,4 +731,21 @@ public StringBuilder appendTo(final StringBuilder builder) return decoder.appendTo(builder); } + + public void checkEncodingIsComplete() + { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + switch (codecState) + { + case CodecStates.V0_SEMANTICVERSION_DONE: + return; + default: + throw new IllegalStateException("Not fully encoded, current state: " + + CodecStates.name(codecState) + ", allowed transitions: " + + CodecStates.transitions(codecState)); + } + } + } + } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 8c7a7a1ee6..6a48488936 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -11,6 +11,130 @@ @SuppressWarnings("all") public final class TokenCodecDecoder { + private static final boolean ENABLE_BOUNDS_CHECKS = !Boolean.getBoolean("agrona.disable.bounds.checks"); + + private static final boolean SBE_ENABLE_IR_PRECEDENCE_CHECKS = Boolean.parseBoolean(System.getProperty( + "sbe.enable.ir.precedence.checks", + Boolean.toString(ENABLE_BOUNDS_CHECKS))); + + /** + * The states in which a encoder/decoder/codec can live. + * + *

      The state machine diagram below, encoded in the dot language, describes + * the valid state transitions according to the order in which fields may be + * accessed safely. Tools such as PlantUML and Graphviz can render it. + * + *

      {@code
      +     *   digraph G {
      +     *       NOT_WRAPPED -> V0_BLOCK [label="  wrap(version=0)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  tokenOffset(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  tokenSize(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  fieldId(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  tokenVersion(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  componentTokenCount(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  signal(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  primitiveType(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  byteOrder(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  presence(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  deprecated(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  nameLength()  "];
      +     *       V0_BLOCK -> V0_NAME_DONE [label="  name(?)  "];
      +     *       V0_NAME_DONE -> V0_NAME_DONE [label="  constValueLength()  "];
      +     *       V0_NAME_DONE -> V0_CONSTVALUE_DONE [label="  constValue(?)  "];
      +     *       V0_CONSTVALUE_DONE -> V0_CONSTVALUE_DONE [label="  minValueLength()  "];
      +     *       V0_CONSTVALUE_DONE -> V0_MINVALUE_DONE [label="  minValue(?)  "];
      +     *       V0_MINVALUE_DONE -> V0_MINVALUE_DONE [label="  maxValueLength()  "];
      +     *       V0_MINVALUE_DONE -> V0_MAXVALUE_DONE [label="  maxValue(?)  "];
      +     *       V0_MAXVALUE_DONE -> V0_MAXVALUE_DONE [label="  nullValueLength()  "];
      +     *       V0_MAXVALUE_DONE -> V0_NULLVALUE_DONE [label="  nullValue(?)  "];
      +     *       V0_NULLVALUE_DONE -> V0_NULLVALUE_DONE [label="  characterEncodingLength()  "];
      +     *       V0_NULLVALUE_DONE -> V0_CHARACTERENCODING_DONE [label="  characterEncoding(?)  "];
      +     *       V0_CHARACTERENCODING_DONE -> V0_CHARACTERENCODING_DONE [label="  epochLength()  "];
      +     *       V0_CHARACTERENCODING_DONE -> V0_EPOCH_DONE [label="  epoch(?)  "];
      +     *       V0_EPOCH_DONE -> V0_EPOCH_DONE [label="  timeUnitLength()  "];
      +     *       V0_EPOCH_DONE -> V0_TIMEUNIT_DONE [label="  timeUnit(?)  "];
      +     *       V0_TIMEUNIT_DONE -> V0_TIMEUNIT_DONE [label="  semanticTypeLength()  "];
      +     *       V0_TIMEUNIT_DONE -> V0_SEMANTICTYPE_DONE [label="  semanticType(?)  "];
      +     *       V0_SEMANTICTYPE_DONE -> V0_SEMANTICTYPE_DONE [label="  descriptionLength()  "];
      +     *       V0_SEMANTICTYPE_DONE -> V0_DESCRIPTION_DONE [label="  description(?)  "];
      +     *       V0_DESCRIPTION_DONE -> V0_DESCRIPTION_DONE [label="  referencedNameLength()  "];
      +     *       V0_DESCRIPTION_DONE -> V0_REFERENCEDNAME_DONE [label="  referencedName(?)  "];
      +     *   }
      +     * }
      + */ + private static class CodecStates + { + private static final int NOT_WRAPPED = 0; + private static final int V0_BLOCK = 1; + private static final int V0_NAME_DONE = 2; + private static final int V0_CONSTVALUE_DONE = 3; + private static final int V0_MINVALUE_DONE = 4; + private static final int V0_MAXVALUE_DONE = 5; + private static final int V0_NULLVALUE_DONE = 6; + private static final int V0_CHARACTERENCODING_DONE = 7; + private static final int V0_EPOCH_DONE = 8; + private static final int V0_TIMEUNIT_DONE = 9; + private static final int V0_SEMANTICTYPE_DONE = 10; + private static final int V0_DESCRIPTION_DONE = 11; + private static final int V0_REFERENCEDNAME_DONE = 12; + + private static final String[] STATE_NAME_LOOKUP = + { + "NOT_WRAPPED", + "V0_BLOCK", + "V0_NAME_DONE", + "V0_CONSTVALUE_DONE", + "V0_MINVALUE_DONE", + "V0_MAXVALUE_DONE", + "V0_NULLVALUE_DONE", + "V0_CHARACTERENCODING_DONE", + "V0_EPOCH_DONE", + "V0_TIMEUNIT_DONE", + "V0_SEMANTICTYPE_DONE", + "V0_DESCRIPTION_DONE", + "V0_REFERENCEDNAME_DONE", + }; + + private static final String[] STATE_TRANSITIONS_LOOKUP = + { + "\"wrap(version=0)\"", + "\"tokenOffset(?)\", \"tokenSize(?)\", \"fieldId(?)\", \"tokenVersion(?)\", \"componentTokenCount(?)\", \"signal(?)\", \"primitiveType(?)\", \"byteOrder(?)\", \"presence(?)\", \"deprecated(?)\", \"nameLength()\", \"name(?)\"", + "\"constValueLength()\", \"constValue(?)\"", + "\"minValueLength()\", \"minValue(?)\"", + "\"maxValueLength()\", \"maxValue(?)\"", + "\"nullValueLength()\", \"nullValue(?)\"", + "\"characterEncodingLength()\", \"characterEncoding(?)\"", + "\"epochLength()\", \"epoch(?)\"", + "\"timeUnitLength()\", \"timeUnit(?)\"", + "\"semanticTypeLength()\", \"semanticType(?)\"", + "\"descriptionLength()\", \"description(?)\"", + "\"referencedNameLength()\", \"referencedName(?)\"", + "", + }; + + private static String name(final int state) + { + return STATE_NAME_LOOKUP[state]; + } + + private static String transitions(final int state) + { + return STATE_TRANSITIONS_LOOKUP[state]; + } + } + + private int codecState = CodecStates.NOT_WRAPPED; + + private int codecState() + { + return codecState; + } + + private void codecState(int newState) + { + codecState = newState; + } + public static final int BLOCK_LENGTH = 28; public static final int TEMPLATE_ID = 2; public static final int SCHEMA_ID = 1; @@ -66,6 +190,19 @@ public int offset() return offset; } + private void onWrap(final int actingVersion) + { + switch(actingVersion) + { + case 0: + codecState(CodecStates.V0_BLOCK); + break; + default: + codecState(CodecStates.V0_BLOCK); + break; + } + } + public TokenCodecDecoder wrap( final DirectBuffer buffer, final int offset, @@ -82,6 +219,11 @@ public TokenCodecDecoder wrap( this.actingVersion = actingVersion; limit(offset + actingBlockLength); + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onWrap(actingVersion); + } + return this; } @@ -113,10 +255,16 @@ public TokenCodecDecoder sbeRewind() public int sbeDecodedLength() { final int currentLimit = limit(); + final int currentCodecState = codecState(); sbeSkip(); final int decodedLength = encodedLength(); limit(currentLimit); + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + codecState(currentCodecState); + } + return decodedLength; } @@ -170,6 +318,17 @@ public static String tokenOffsetMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onTokenOffsetAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"tokenOffset\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public static int tokenOffsetNullValue() { return -2147483648; @@ -187,6 +346,11 @@ public static int tokenOffsetMaxValue() public int tokenOffset() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTokenOffsetAccessed(); + } + return buffer.getInt(offset + 0, java.nio.ByteOrder.LITTLE_ENDIAN); } @@ -221,6 +385,17 @@ public static String tokenSizeMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onTokenSizeAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"tokenSize\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public static int tokenSizeNullValue() { return -2147483648; @@ -238,6 +413,11 @@ public static int tokenSizeMaxValue() public int tokenSize() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTokenSizeAccessed(); + } + return buffer.getInt(offset + 4, java.nio.ByteOrder.LITTLE_ENDIAN); } @@ -272,6 +452,17 @@ public static String fieldIdMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onFieldIdAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"fieldId\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public static int fieldIdNullValue() { return -2147483648; @@ -289,6 +480,11 @@ public static int fieldIdMaxValue() public int fieldId() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onFieldIdAccessed(); + } + return buffer.getInt(offset + 8, java.nio.ByteOrder.LITTLE_ENDIAN); } @@ -323,6 +519,17 @@ public static String tokenVersionMetaAttribute(final MetaAttribute metaAttribute return ""; } + private void onTokenVersionAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"tokenVersion\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public static int tokenVersionNullValue() { return -2147483648; @@ -340,6 +547,11 @@ public static int tokenVersionMaxValue() public int tokenVersion() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTokenVersionAccessed(); + } + return buffer.getInt(offset + 12, java.nio.ByteOrder.LITTLE_ENDIAN); } @@ -374,6 +586,17 @@ public static String componentTokenCountMetaAttribute(final MetaAttribute metaAt return ""; } + private void onComponentTokenCountAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"componentTokenCount\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public static int componentTokenCountNullValue() { return -2147483648; @@ -391,6 +614,11 @@ public static int componentTokenCountMaxValue() public int componentTokenCount() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onComponentTokenCountAccessed(); + } + return buffer.getInt(offset + 16, java.nio.ByteOrder.LITTLE_ENDIAN); } @@ -425,13 +653,34 @@ public static String signalMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onSignalAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"signal\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public short signalRaw() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSignalAccessed(); + } + return ((short)(buffer.getByte(offset + 20) & 0xFF)); } public SignalCodec signal() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSignalAccessed(); + } + return SignalCodec.get(((short)(buffer.getByte(offset + 20) & 0xFF))); } @@ -466,13 +715,34 @@ public static String primitiveTypeMetaAttribute(final MetaAttribute metaAttribut return ""; } + private void onPrimitiveTypeAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"primitiveType\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public short primitiveTypeRaw() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPrimitiveTypeAccessed(); + } + return ((short)(buffer.getByte(offset + 21) & 0xFF)); } public PrimitiveTypeCodec primitiveType() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPrimitiveTypeAccessed(); + } + return PrimitiveTypeCodec.get(((short)(buffer.getByte(offset + 21) & 0xFF))); } @@ -507,13 +777,34 @@ public static String byteOrderMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onByteOrderAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"byteOrder\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public short byteOrderRaw() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onByteOrderAccessed(); + } + return ((short)(buffer.getByte(offset + 22) & 0xFF)); } public ByteOrderCodec byteOrder() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onByteOrderAccessed(); + } + return ByteOrderCodec.get(((short)(buffer.getByte(offset + 22) & 0xFF))); } @@ -548,13 +839,34 @@ public static String presenceMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onPresenceAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"presence\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public short presenceRaw() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPresenceAccessed(); + } + return ((short)(buffer.getByte(offset + 23) & 0xFF)); } public PresenceCodec presence() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPresenceAccessed(); + } + return PresenceCodec.get(((short)(buffer.getByte(offset + 23) & 0xFF))); } @@ -589,6 +901,17 @@ public static String deprecatedMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onDeprecatedAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"deprecated\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public static int deprecatedNullValue() { return 0; @@ -606,6 +929,11 @@ public static int deprecatedMaxValue() public int deprecated() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onDeprecatedAccessed(); + } + return buffer.getInt(offset + 24, java.nio.ByteOrder.LITTLE_ENDIAN); } @@ -640,14 +968,54 @@ public static int nameHeaderLength() return 2; } + void onNameLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_BLOCK: + codecState(CodecStates.V0_BLOCK); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"name\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + + private void onNameAccessed() + { + switch (codecState()) + { + case CodecStates.V0_BLOCK: + codecState(CodecStates.V0_NAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"name\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public int nameLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNameLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipName() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -659,6 +1027,11 @@ public int skipName() public int getName(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -671,6 +1044,11 @@ public int getName(final MutableDirectBuffer dst, final int dstOffset, final int public int getName(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -683,6 +1061,11 @@ public int getName(final byte[] dst, final int dstOffset, final int length) public void wrapName(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -692,6 +1075,11 @@ public void wrapName(final DirectBuffer wrapBuffer) public String name() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -738,14 +1126,54 @@ public static int constValueHeaderLength() return 2; } + void onConstValueLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_NAME_DONE: + codecState(CodecStates.V0_NAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"constValue\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + + private void onConstValueAccessed() + { + switch (codecState()) + { + case CodecStates.V0_NAME_DONE: + codecState(CodecStates.V0_CONSTVALUE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"constValue\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public int constValueLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onConstValueLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipConstValue() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onConstValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -757,6 +1185,11 @@ public int skipConstValue() public int getConstValue(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onConstValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -769,6 +1202,11 @@ public int getConstValue(final MutableDirectBuffer dst, final int dstOffset, fin public int getConstValue(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onConstValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -781,6 +1219,11 @@ public int getConstValue(final byte[] dst, final int dstOffset, final int length public void wrapConstValue(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onConstValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -790,6 +1233,11 @@ public void wrapConstValue(final DirectBuffer wrapBuffer) public String constValue() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onConstValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -836,14 +1284,54 @@ public static int minValueHeaderLength() return 2; } + void onMinValueLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_CONSTVALUE_DONE: + codecState(CodecStates.V0_CONSTVALUE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"minValue\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + + private void onMinValueAccessed() + { + switch (codecState()) + { + case CodecStates.V0_CONSTVALUE_DONE: + codecState(CodecStates.V0_MINVALUE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"minValue\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public int minValueLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMinValueLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipMinValue() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMinValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -855,6 +1343,11 @@ public int skipMinValue() public int getMinValue(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMinValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -867,6 +1360,11 @@ public int getMinValue(final MutableDirectBuffer dst, final int dstOffset, final public int getMinValue(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMinValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -879,6 +1377,11 @@ public int getMinValue(final byte[] dst, final int dstOffset, final int length) public void wrapMinValue(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMinValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -888,6 +1391,11 @@ public void wrapMinValue(final DirectBuffer wrapBuffer) public String minValue() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMinValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -934,14 +1442,54 @@ public static int maxValueHeaderLength() return 2; } + void onMaxValueLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_MINVALUE_DONE: + codecState(CodecStates.V0_MINVALUE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"maxValue\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + + private void onMaxValueAccessed() + { + switch (codecState()) + { + case CodecStates.V0_MINVALUE_DONE: + codecState(CodecStates.V0_MAXVALUE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"maxValue\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public int maxValueLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMaxValueLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipMaxValue() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMaxValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -953,6 +1501,11 @@ public int skipMaxValue() public int getMaxValue(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMaxValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -965,6 +1518,11 @@ public int getMaxValue(final MutableDirectBuffer dst, final int dstOffset, final public int getMaxValue(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMaxValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -977,6 +1535,11 @@ public int getMaxValue(final byte[] dst, final int dstOffset, final int length) public void wrapMaxValue(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMaxValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -986,6 +1549,11 @@ public void wrapMaxValue(final DirectBuffer wrapBuffer) public String maxValue() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMaxValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1032,14 +1600,54 @@ public static int nullValueHeaderLength() return 2; } + void onNullValueLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_MAXVALUE_DONE: + codecState(CodecStates.V0_MAXVALUE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"nullValue\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + + private void onNullValueAccessed() + { + switch (codecState()) + { + case CodecStates.V0_MAXVALUE_DONE: + codecState(CodecStates.V0_NULLVALUE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"nullValue\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public int nullValueLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNullValueLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipNullValue() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNullValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1051,6 +1659,11 @@ public int skipNullValue() public int getNullValue(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNullValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1063,6 +1676,11 @@ public int getNullValue(final MutableDirectBuffer dst, final int dstOffset, fina public int getNullValue(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNullValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1075,6 +1693,11 @@ public int getNullValue(final byte[] dst, final int dstOffset, final int length) public void wrapNullValue(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNullValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1084,6 +1707,11 @@ public void wrapNullValue(final DirectBuffer wrapBuffer) public String nullValue() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNullValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1130,14 +1758,54 @@ public static int characterEncodingHeaderLength() return 2; } + void onCharacterEncodingLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_NULLVALUE_DONE: + codecState(CodecStates.V0_NULLVALUE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"characterEncoding\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + + private void onCharacterEncodingAccessed() + { + switch (codecState()) + { + case CodecStates.V0_NULLVALUE_DONE: + codecState(CodecStates.V0_CHARACTERENCODING_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"characterEncoding\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public int characterEncodingLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onCharacterEncodingLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipCharacterEncoding() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onCharacterEncodingAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1149,6 +1817,11 @@ public int skipCharacterEncoding() public int getCharacterEncoding(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onCharacterEncodingAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1161,6 +1834,11 @@ public int getCharacterEncoding(final MutableDirectBuffer dst, final int dstOffs public int getCharacterEncoding(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onCharacterEncodingAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1173,6 +1851,11 @@ public int getCharacterEncoding(final byte[] dst, final int dstOffset, final int public void wrapCharacterEncoding(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onCharacterEncodingAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1182,6 +1865,11 @@ public void wrapCharacterEncoding(final DirectBuffer wrapBuffer) public String characterEncoding() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onCharacterEncodingAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1228,14 +1916,54 @@ public static int epochHeaderLength() return 2; } + void onEpochLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_CHARACTERENCODING_DONE: + codecState(CodecStates.V0_CHARACTERENCODING_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"epoch\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + + private void onEpochAccessed() + { + switch (codecState()) + { + case CodecStates.V0_CHARACTERENCODING_DONE: + codecState(CodecStates.V0_EPOCH_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"epoch\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public int epochLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onEpochLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipEpoch() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onEpochAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1247,6 +1975,11 @@ public int skipEpoch() public int getEpoch(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onEpochAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1259,6 +1992,11 @@ public int getEpoch(final MutableDirectBuffer dst, final int dstOffset, final in public int getEpoch(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onEpochAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1271,6 +2009,11 @@ public int getEpoch(final byte[] dst, final int dstOffset, final int length) public void wrapEpoch(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onEpochAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1280,6 +2023,11 @@ public void wrapEpoch(final DirectBuffer wrapBuffer) public String epoch() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onEpochAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1326,14 +2074,54 @@ public static int timeUnitHeaderLength() return 2; } + void onTimeUnitLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_EPOCH_DONE: + codecState(CodecStates.V0_EPOCH_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"timeUnit\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + + private void onTimeUnitAccessed() + { + switch (codecState()) + { + case CodecStates.V0_EPOCH_DONE: + codecState(CodecStates.V0_TIMEUNIT_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"timeUnit\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public int timeUnitLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTimeUnitLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipTimeUnit() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTimeUnitAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1345,6 +2133,11 @@ public int skipTimeUnit() public int getTimeUnit(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTimeUnitAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1357,6 +2150,11 @@ public int getTimeUnit(final MutableDirectBuffer dst, final int dstOffset, final public int getTimeUnit(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTimeUnitAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1369,6 +2167,11 @@ public int getTimeUnit(final byte[] dst, final int dstOffset, final int length) public void wrapTimeUnit(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTimeUnitAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1378,6 +2181,11 @@ public void wrapTimeUnit(final DirectBuffer wrapBuffer) public String timeUnit() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTimeUnitAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1424,14 +2232,54 @@ public static int semanticTypeHeaderLength() return 2; } + void onSemanticTypeLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_TIMEUNIT_DONE: + codecState(CodecStates.V0_TIMEUNIT_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"semanticType\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + + private void onSemanticTypeAccessed() + { + switch (codecState()) + { + case CodecStates.V0_TIMEUNIT_DONE: + codecState(CodecStates.V0_SEMANTICTYPE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"semanticType\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public int semanticTypeLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticTypeLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipSemanticType() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticTypeAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1443,6 +2291,11 @@ public int skipSemanticType() public int getSemanticType(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticTypeAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1455,6 +2308,11 @@ public int getSemanticType(final MutableDirectBuffer dst, final int dstOffset, f public int getSemanticType(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticTypeAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1467,6 +2325,11 @@ public int getSemanticType(final byte[] dst, final int dstOffset, final int leng public void wrapSemanticType(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticTypeAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1476,6 +2339,11 @@ public void wrapSemanticType(final DirectBuffer wrapBuffer) public String semanticType() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticTypeAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1522,14 +2390,54 @@ public static int descriptionHeaderLength() return 2; } + void onDescriptionLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_SEMANTICTYPE_DONE: + codecState(CodecStates.V0_SEMANTICTYPE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"description\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + + private void onDescriptionAccessed() + { + switch (codecState()) + { + case CodecStates.V0_SEMANTICTYPE_DONE: + codecState(CodecStates.V0_DESCRIPTION_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"description\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public int descriptionLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onDescriptionLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipDescription() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onDescriptionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1541,6 +2449,11 @@ public int skipDescription() public int getDescription(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onDescriptionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1553,6 +2466,11 @@ public int getDescription(final MutableDirectBuffer dst, final int dstOffset, fi public int getDescription(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onDescriptionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1565,6 +2483,11 @@ public int getDescription(final byte[] dst, final int dstOffset, final int lengt public void wrapDescription(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onDescriptionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1574,6 +2497,11 @@ public void wrapDescription(final DirectBuffer wrapBuffer) public String description() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onDescriptionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1620,14 +2548,54 @@ public static int referencedNameHeaderLength() return 2; } + void onReferencedNameLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_DESCRIPTION_DONE: + codecState(CodecStates.V0_DESCRIPTION_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"referencedName\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + + private void onReferencedNameAccessed() + { + switch (codecState()) + { + case CodecStates.V0_DESCRIPTION_DONE: + codecState(CodecStates.V0_REFERENCEDNAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"referencedName\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + public int referencedNameLength() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onReferencedNameLengthAccessed(); + } + final int limit = parentMessage.limit(); return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); } public int skipReferencedName() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onReferencedNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1639,6 +2607,11 @@ public int skipReferencedName() public int getReferencedName(final MutableDirectBuffer dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onReferencedNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1651,6 +2624,11 @@ public int getReferencedName(final MutableDirectBuffer dst, final int dstOffset, public int getReferencedName(final byte[] dst, final int dstOffset, final int length) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onReferencedNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1663,6 +2641,11 @@ public int getReferencedName(final byte[] dst, final int dstOffset, final int le public void wrapReferencedName(final DirectBuffer wrapBuffer) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onReferencedNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); @@ -1672,6 +2655,11 @@ public void wrapReferencedName(final DirectBuffer wrapBuffer) public String referencedName() { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onReferencedNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index 793f10756f..a0ece1099d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -11,6 +11,130 @@ @SuppressWarnings("all") public final class TokenCodecEncoder { + private static final boolean ENABLE_BOUNDS_CHECKS = !Boolean.getBoolean("agrona.disable.bounds.checks"); + + private static final boolean SBE_ENABLE_IR_PRECEDENCE_CHECKS = Boolean.parseBoolean(System.getProperty( + "sbe.enable.ir.precedence.checks", + Boolean.toString(ENABLE_BOUNDS_CHECKS))); + + /** + * The states in which a encoder/decoder/codec can live. + * + *

      The state machine diagram below, encoded in the dot language, describes + * the valid state transitions according to the order in which fields may be + * accessed safely. Tools such as PlantUML and Graphviz can render it. + * + *

      {@code
      +     *   digraph G {
      +     *       NOT_WRAPPED -> V0_BLOCK [label="  wrap(version=0)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  tokenOffset(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  tokenSize(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  fieldId(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  tokenVersion(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  componentTokenCount(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  signal(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  primitiveType(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  byteOrder(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  presence(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  deprecated(?)  "];
      +     *       V0_BLOCK -> V0_BLOCK [label="  nameLength()  "];
      +     *       V0_BLOCK -> V0_NAME_DONE [label="  name(?)  "];
      +     *       V0_NAME_DONE -> V0_NAME_DONE [label="  constValueLength()  "];
      +     *       V0_NAME_DONE -> V0_CONSTVALUE_DONE [label="  constValue(?)  "];
      +     *       V0_CONSTVALUE_DONE -> V0_CONSTVALUE_DONE [label="  minValueLength()  "];
      +     *       V0_CONSTVALUE_DONE -> V0_MINVALUE_DONE [label="  minValue(?)  "];
      +     *       V0_MINVALUE_DONE -> V0_MINVALUE_DONE [label="  maxValueLength()  "];
      +     *       V0_MINVALUE_DONE -> V0_MAXVALUE_DONE [label="  maxValue(?)  "];
      +     *       V0_MAXVALUE_DONE -> V0_MAXVALUE_DONE [label="  nullValueLength()  "];
      +     *       V0_MAXVALUE_DONE -> V0_NULLVALUE_DONE [label="  nullValue(?)  "];
      +     *       V0_NULLVALUE_DONE -> V0_NULLVALUE_DONE [label="  characterEncodingLength()  "];
      +     *       V0_NULLVALUE_DONE -> V0_CHARACTERENCODING_DONE [label="  characterEncoding(?)  "];
      +     *       V0_CHARACTERENCODING_DONE -> V0_CHARACTERENCODING_DONE [label="  epochLength()  "];
      +     *       V0_CHARACTERENCODING_DONE -> V0_EPOCH_DONE [label="  epoch(?)  "];
      +     *       V0_EPOCH_DONE -> V0_EPOCH_DONE [label="  timeUnitLength()  "];
      +     *       V0_EPOCH_DONE -> V0_TIMEUNIT_DONE [label="  timeUnit(?)  "];
      +     *       V0_TIMEUNIT_DONE -> V0_TIMEUNIT_DONE [label="  semanticTypeLength()  "];
      +     *       V0_TIMEUNIT_DONE -> V0_SEMANTICTYPE_DONE [label="  semanticType(?)  "];
      +     *       V0_SEMANTICTYPE_DONE -> V0_SEMANTICTYPE_DONE [label="  descriptionLength()  "];
      +     *       V0_SEMANTICTYPE_DONE -> V0_DESCRIPTION_DONE [label="  description(?)  "];
      +     *       V0_DESCRIPTION_DONE -> V0_DESCRIPTION_DONE [label="  referencedNameLength()  "];
      +     *       V0_DESCRIPTION_DONE -> V0_REFERENCEDNAME_DONE [label="  referencedName(?)  "];
      +     *   }
      +     * }
      + */ + private static class CodecStates + { + private static final int NOT_WRAPPED = 0; + private static final int V0_BLOCK = 1; + private static final int V0_NAME_DONE = 2; + private static final int V0_CONSTVALUE_DONE = 3; + private static final int V0_MINVALUE_DONE = 4; + private static final int V0_MAXVALUE_DONE = 5; + private static final int V0_NULLVALUE_DONE = 6; + private static final int V0_CHARACTERENCODING_DONE = 7; + private static final int V0_EPOCH_DONE = 8; + private static final int V0_TIMEUNIT_DONE = 9; + private static final int V0_SEMANTICTYPE_DONE = 10; + private static final int V0_DESCRIPTION_DONE = 11; + private static final int V0_REFERENCEDNAME_DONE = 12; + + private static final String[] STATE_NAME_LOOKUP = + { + "NOT_WRAPPED", + "V0_BLOCK", + "V0_NAME_DONE", + "V0_CONSTVALUE_DONE", + "V0_MINVALUE_DONE", + "V0_MAXVALUE_DONE", + "V0_NULLVALUE_DONE", + "V0_CHARACTERENCODING_DONE", + "V0_EPOCH_DONE", + "V0_TIMEUNIT_DONE", + "V0_SEMANTICTYPE_DONE", + "V0_DESCRIPTION_DONE", + "V0_REFERENCEDNAME_DONE", + }; + + private static final String[] STATE_TRANSITIONS_LOOKUP = + { + "\"wrap(version=0)\"", + "\"tokenOffset(?)\", \"tokenSize(?)\", \"fieldId(?)\", \"tokenVersion(?)\", \"componentTokenCount(?)\", \"signal(?)\", \"primitiveType(?)\", \"byteOrder(?)\", \"presence(?)\", \"deprecated(?)\", \"nameLength()\", \"name(?)\"", + "\"constValueLength()\", \"constValue(?)\"", + "\"minValueLength()\", \"minValue(?)\"", + "\"maxValueLength()\", \"maxValue(?)\"", + "\"nullValueLength()\", \"nullValue(?)\"", + "\"characterEncodingLength()\", \"characterEncoding(?)\"", + "\"epochLength()\", \"epoch(?)\"", + "\"timeUnitLength()\", \"timeUnit(?)\"", + "\"semanticTypeLength()\", \"semanticType(?)\"", + "\"descriptionLength()\", \"description(?)\"", + "\"referencedNameLength()\", \"referencedName(?)\"", + "", + }; + + private static String name(final int state) + { + return STATE_NAME_LOOKUP[state]; + } + + private static String transitions(final int state) + { + return STATE_TRANSITIONS_LOOKUP[state]; + } + } + + private int codecState = CodecStates.NOT_WRAPPED; + + private int codecState() + { + return codecState; + } + + private void codecState(int newState) + { + codecState = newState; + } + public static final int BLOCK_LENGTH = 28; public static final int TEMPLATE_ID = 2; public static final int SCHEMA_ID = 1; @@ -74,6 +198,11 @@ public TokenCodecEncoder wrap(final MutableDirectBuffer buffer, final int offset this.offset = offset; limit(offset + BLOCK_LENGTH); + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + codecState(CodecStates.V0_BLOCK); + } + return this; } @@ -135,6 +264,17 @@ public static String tokenOffsetMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onTokenOffsetAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"tokenOffset\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public static int tokenOffsetNullValue() { return -2147483648; @@ -152,6 +292,11 @@ public static int tokenOffsetMaxValue() public TokenCodecEncoder tokenOffset(final int value) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTokenOffsetAccessed(); + } + buffer.putInt(offset + 0, value, java.nio.ByteOrder.LITTLE_ENDIAN); return this; } @@ -187,6 +332,17 @@ public static String tokenSizeMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onTokenSizeAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"tokenSize\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public static int tokenSizeNullValue() { return -2147483648; @@ -204,6 +360,11 @@ public static int tokenSizeMaxValue() public TokenCodecEncoder tokenSize(final int value) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTokenSizeAccessed(); + } + buffer.putInt(offset + 4, value, java.nio.ByteOrder.LITTLE_ENDIAN); return this; } @@ -239,6 +400,17 @@ public static String fieldIdMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onFieldIdAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"fieldId\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public static int fieldIdNullValue() { return -2147483648; @@ -256,6 +428,11 @@ public static int fieldIdMaxValue() public TokenCodecEncoder fieldId(final int value) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onFieldIdAccessed(); + } + buffer.putInt(offset + 8, value, java.nio.ByteOrder.LITTLE_ENDIAN); return this; } @@ -291,6 +468,17 @@ public static String tokenVersionMetaAttribute(final MetaAttribute metaAttribute return ""; } + private void onTokenVersionAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"tokenVersion\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public static int tokenVersionNullValue() { return -2147483648; @@ -308,6 +496,11 @@ public static int tokenVersionMaxValue() public TokenCodecEncoder tokenVersion(final int value) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTokenVersionAccessed(); + } + buffer.putInt(offset + 12, value, java.nio.ByteOrder.LITTLE_ENDIAN); return this; } @@ -343,6 +536,17 @@ public static String componentTokenCountMetaAttribute(final MetaAttribute metaAt return ""; } + private void onComponentTokenCountAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"componentTokenCount\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public static int componentTokenCountNullValue() { return -2147483648; @@ -360,6 +564,11 @@ public static int componentTokenCountMaxValue() public TokenCodecEncoder componentTokenCount(final int value) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onComponentTokenCountAccessed(); + } + buffer.putInt(offset + 16, value, java.nio.ByteOrder.LITTLE_ENDIAN); return this; } @@ -395,8 +604,24 @@ public static String signalMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onSignalAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"signal\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder signal(final SignalCodec value) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSignalAccessed(); + } + buffer.putByte(offset + 20, (byte)value.value()); return this; } @@ -431,8 +656,24 @@ public static String primitiveTypeMetaAttribute(final MetaAttribute metaAttribut return ""; } + private void onPrimitiveTypeAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"primitiveType\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder primitiveType(final PrimitiveTypeCodec value) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPrimitiveTypeAccessed(); + } + buffer.putByte(offset + 21, (byte)value.value()); return this; } @@ -467,8 +708,24 @@ public static String byteOrderMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onByteOrderAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"byteOrder\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder byteOrder(final ByteOrderCodec value) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onByteOrderAccessed(); + } + buffer.putByte(offset + 22, (byte)value.value()); return this; } @@ -503,8 +760,24 @@ public static String presenceMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onPresenceAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"presence\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder presence(final PresenceCodec value) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPresenceAccessed(); + } + buffer.putByte(offset + 23, (byte)value.value()); return this; } @@ -539,6 +812,17 @@ public static String deprecatedMetaAttribute(final MetaAttribute metaAttribute) return ""; } + private void onDeprecatedAccessed() + { + if (codecState() == CodecStates.NOT_WRAPPED) + { + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"deprecated\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public static int deprecatedNullValue() { return 0; @@ -556,6 +840,11 @@ public static int deprecatedMaxValue() public TokenCodecEncoder deprecated(final int value) { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onDeprecatedAccessed(); + } + buffer.putInt(offset + 24, value, java.nio.ByteOrder.LITTLE_ENDIAN); return this; } @@ -586,6 +875,21 @@ public static int nameHeaderLength() return 2; } + private void onNameAccessed() + { + switch (codecState()) + { + case CodecStates.V0_BLOCK: + codecState(CodecStates.V0_NAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"name\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder putName(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -593,6 +897,11 @@ public TokenCodecEncoder putName(final DirectBuffer src, final int srcOffset, fi throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -609,6 +918,11 @@ public TokenCodecEncoder putName(final byte[] src, final int srcOffset, final in throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -628,6 +942,11 @@ public TokenCodecEncoder name(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -662,6 +981,21 @@ public static int constValueHeaderLength() return 2; } + private void onConstValueAccessed() + { + switch (codecState()) + { + case CodecStates.V0_NAME_DONE: + codecState(CodecStates.V0_CONSTVALUE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"constValue\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder putConstValue(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -669,6 +1003,11 @@ public TokenCodecEncoder putConstValue(final DirectBuffer src, final int srcOffs throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onConstValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -685,6 +1024,11 @@ public TokenCodecEncoder putConstValue(final byte[] src, final int srcOffset, fi throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onConstValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -704,6 +1048,11 @@ public TokenCodecEncoder constValue(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onConstValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -738,6 +1087,21 @@ public static int minValueHeaderLength() return 2; } + private void onMinValueAccessed() + { + switch (codecState()) + { + case CodecStates.V0_CONSTVALUE_DONE: + codecState(CodecStates.V0_MINVALUE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"minValue\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder putMinValue(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -745,6 +1109,11 @@ public TokenCodecEncoder putMinValue(final DirectBuffer src, final int srcOffset throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMinValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -761,6 +1130,11 @@ public TokenCodecEncoder putMinValue(final byte[] src, final int srcOffset, fina throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMinValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -780,6 +1154,11 @@ public TokenCodecEncoder minValue(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMinValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -814,6 +1193,21 @@ public static int maxValueHeaderLength() return 2; } + private void onMaxValueAccessed() + { + switch (codecState()) + { + case CodecStates.V0_MINVALUE_DONE: + codecState(CodecStates.V0_MAXVALUE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"maxValue\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder putMaxValue(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -821,6 +1215,11 @@ public TokenCodecEncoder putMaxValue(final DirectBuffer src, final int srcOffset throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMaxValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -837,6 +1236,11 @@ public TokenCodecEncoder putMaxValue(final byte[] src, final int srcOffset, fina throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMaxValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -856,6 +1260,11 @@ public TokenCodecEncoder maxValue(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onMaxValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -890,6 +1299,21 @@ public static int nullValueHeaderLength() return 2; } + private void onNullValueAccessed() + { + switch (codecState()) + { + case CodecStates.V0_MAXVALUE_DONE: + codecState(CodecStates.V0_NULLVALUE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"nullValue\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder putNullValue(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -897,6 +1321,11 @@ public TokenCodecEncoder putNullValue(final DirectBuffer src, final int srcOffse throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNullValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -913,6 +1342,11 @@ public TokenCodecEncoder putNullValue(final byte[] src, final int srcOffset, fin throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNullValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -932,6 +1366,11 @@ public TokenCodecEncoder nullValue(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onNullValueAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -966,6 +1405,21 @@ public static int characterEncodingHeaderLength() return 2; } + private void onCharacterEncodingAccessed() + { + switch (codecState()) + { + case CodecStates.V0_NULLVALUE_DONE: + codecState(CodecStates.V0_CHARACTERENCODING_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"characterEncoding\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder putCharacterEncoding(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -973,6 +1427,11 @@ public TokenCodecEncoder putCharacterEncoding(final DirectBuffer src, final int throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onCharacterEncodingAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -989,6 +1448,11 @@ public TokenCodecEncoder putCharacterEncoding(final byte[] src, final int srcOff throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onCharacterEncodingAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1008,6 +1472,11 @@ public TokenCodecEncoder characterEncoding(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onCharacterEncodingAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1042,6 +1511,21 @@ public static int epochHeaderLength() return 2; } + private void onEpochAccessed() + { + switch (codecState()) + { + case CodecStates.V0_CHARACTERENCODING_DONE: + codecState(CodecStates.V0_EPOCH_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"epoch\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder putEpoch(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -1049,6 +1533,11 @@ public TokenCodecEncoder putEpoch(final DirectBuffer src, final int srcOffset, f throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onEpochAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1065,6 +1554,11 @@ public TokenCodecEncoder putEpoch(final byte[] src, final int srcOffset, final i throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onEpochAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1084,6 +1578,11 @@ public TokenCodecEncoder epoch(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onEpochAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1118,6 +1617,21 @@ public static int timeUnitHeaderLength() return 2; } + private void onTimeUnitAccessed() + { + switch (codecState()) + { + case CodecStates.V0_EPOCH_DONE: + codecState(CodecStates.V0_TIMEUNIT_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"timeUnit\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder putTimeUnit(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -1125,6 +1639,11 @@ public TokenCodecEncoder putTimeUnit(final DirectBuffer src, final int srcOffset throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTimeUnitAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1141,6 +1660,11 @@ public TokenCodecEncoder putTimeUnit(final byte[] src, final int srcOffset, fina throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTimeUnitAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1160,6 +1684,11 @@ public TokenCodecEncoder timeUnit(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onTimeUnitAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1194,6 +1723,21 @@ public static int semanticTypeHeaderLength() return 2; } + private void onSemanticTypeAccessed() + { + switch (codecState()) + { + case CodecStates.V0_TIMEUNIT_DONE: + codecState(CodecStates.V0_SEMANTICTYPE_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"semanticType\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder putSemanticType(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -1201,6 +1745,11 @@ public TokenCodecEncoder putSemanticType(final DirectBuffer src, final int srcOf throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticTypeAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1217,6 +1766,11 @@ public TokenCodecEncoder putSemanticType(final byte[] src, final int srcOffset, throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticTypeAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1236,6 +1790,11 @@ public TokenCodecEncoder semanticType(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onSemanticTypeAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1270,6 +1829,21 @@ public static int descriptionHeaderLength() return 2; } + private void onDescriptionAccessed() + { + switch (codecState()) + { + case CodecStates.V0_SEMANTICTYPE_DONE: + codecState(CodecStates.V0_DESCRIPTION_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"description\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder putDescription(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -1277,6 +1851,11 @@ public TokenCodecEncoder putDescription(final DirectBuffer src, final int srcOff throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onDescriptionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1293,6 +1872,11 @@ public TokenCodecEncoder putDescription(final byte[] src, final int srcOffset, f throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onDescriptionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1312,6 +1896,11 @@ public TokenCodecEncoder description(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onDescriptionAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1346,6 +1935,21 @@ public static int referencedNameHeaderLength() return 2; } + private void onReferencedNameAccessed() + { + switch (codecState()) + { + case CodecStates.V0_DESCRIPTION_DONE: + codecState(CodecStates.V0_REFERENCEDNAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"referencedName\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + public TokenCodecEncoder putReferencedName(final DirectBuffer src, final int srcOffset, final int length) { if (length > 65534) @@ -1353,6 +1957,11 @@ public TokenCodecEncoder putReferencedName(final DirectBuffer src, final int src throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onReferencedNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1369,6 +1978,11 @@ public TokenCodecEncoder putReferencedName(final byte[] src, final int srcOffset throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onReferencedNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1388,6 +2002,11 @@ public TokenCodecEncoder referencedName(final String value) throw new IllegalStateException("length > maxValue for type: " + length); } + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onReferencedNameAccessed(); + } + final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); @@ -1419,4 +2038,21 @@ public StringBuilder appendTo(final StringBuilder builder) return decoder.appendTo(builder); } + + public void checkEncodingIsComplete() + { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + switch (codecState) + { + case CodecStates.V0_REFERENCEDNAME_DONE: + return; + default: + throw new IllegalStateException("Not fully encoded, current state: " + + CodecStates.name(codecState) + ", allowed transitions: " + + CodecStates.transitions(codecState)); + } + } + } + } diff --git a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp index e3b81677dc..2adf48f06c 100644 --- a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include #include #include @@ -217,43 +216,43 @@ class BoundsCheckTest : public testing::Test performanceFigures.next(); EXPECT_EQ(performanceFigures.octaneRating(), 95); - Car::PerformanceFigures::Acceleration &acceleration = performanceFigures.acceleration(); - EXPECT_EQ(acceleration.count(), 3u); - EXPECT_TRUE(acceleration.hasNext()); - acceleration.next(); - EXPECT_EQ(acceleration.mph(), 30); - EXPECT_EQ(acceleration.seconds(), 4.0f); + Car::PerformanceFigures::Acceleration &acceleration1 = performanceFigures.acceleration(); + EXPECT_EQ(acceleration1.count(), 3u); + EXPECT_TRUE(acceleration1.hasNext()); + acceleration1.next(); + EXPECT_EQ(acceleration1.mph(), 30); + EXPECT_EQ(acceleration1.seconds(), 4.0f); - EXPECT_TRUE(acceleration.hasNext()); - acceleration.next(); - EXPECT_EQ(acceleration.mph(), 60); - EXPECT_EQ(acceleration.seconds(), 7.5f); + EXPECT_TRUE(acceleration1.hasNext()); + acceleration1.next(); + EXPECT_EQ(acceleration1.mph(), 60); + EXPECT_EQ(acceleration1.seconds(), 7.5f); - EXPECT_TRUE(acceleration.hasNext()); - acceleration.next(); - EXPECT_EQ(acceleration.mph(), 100); - EXPECT_EQ(acceleration.seconds(), 12.2f); + EXPECT_TRUE(acceleration1.hasNext()); + acceleration1.next(); + EXPECT_EQ(acceleration1.mph(), 100); + EXPECT_EQ(acceleration1.seconds(), 12.2f); EXPECT_TRUE(performanceFigures.hasNext()); performanceFigures.next(); EXPECT_EQ(performanceFigures.octaneRating(), 99); - acceleration = performanceFigures.acceleration(); - EXPECT_EQ(acceleration.count(), 3u); - EXPECT_TRUE(acceleration.hasNext()); - acceleration.next(); - EXPECT_EQ(acceleration.mph(), 30); - EXPECT_EQ(acceleration.seconds(), 3.8f); - - EXPECT_TRUE(acceleration.hasNext()); - acceleration.next(); - EXPECT_EQ(acceleration.mph(), 60); - EXPECT_EQ(acceleration.seconds(), 7.1f); - - EXPECT_TRUE(acceleration.hasNext()); - acceleration.next(); - EXPECT_EQ(acceleration.mph(), 100); - EXPECT_EQ(acceleration.seconds(), 11.8f); + Car::PerformanceFigures::Acceleration &acceleration2 = performanceFigures.acceleration(); + EXPECT_EQ(acceleration2.count(), 3u); + EXPECT_TRUE(acceleration2.hasNext()); + acceleration2.next(); + EXPECT_EQ(acceleration2.mph(), 30); + EXPECT_EQ(acceleration2.seconds(), 3.8f); + + EXPECT_TRUE(acceleration2.hasNext()); + acceleration2.next(); + EXPECT_EQ(acceleration2.mph(), 60); + EXPECT_EQ(acceleration2.seconds(), 7.1f); + + EXPECT_TRUE(acceleration2.hasNext()); + acceleration2.next(); + EXPECT_EQ(acceleration2.mph(), 100); + EXPECT_EQ(acceleration2.seconds(), 11.8f); return m_carDecoder.encodedLength(); } diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index 03d1ab1cfb..8c698c83c3 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -18,6 +18,7 @@ function(sbe_test name) add_executable("${name}" "${name}.cpp") target_include_directories("${name}" PRIVATE ${GTEST_SOURCE_DIR}/googletest/include + PRIVATE ${GTEST_SOURCE_DIR}/googlemock/include PRIVATE ${CXX_CODEC_TARGET_DIR} ) target_compile_options("${name}" PRIVATE $<$:-Werror>) @@ -40,6 +41,7 @@ set(MESSAGE_BLOCK_LENGTH_TEST ${CODEC_SCHEMA_DIR}/message-block-length-test.xml) set(GROUP_WITH_DATA_SCHEMA ${CODEC_SCHEMA_DIR}/group-with-data-schema.xml) set(ISSUE835_SCHEMA ${CODEC_SCHEMA_DIR}/issue835.xml) set(ISSUE889_SCHEMA ${CODEC_SCHEMA_DIR}/issue889.xml) +set(ACCESS_ORDER_SCHEMA ${CODEC_SCHEMA_DIR}/field-order-check-schema.xml) set(GENERATED_CODECS ${CXX_CODEC_TARGET_DIR} @@ -54,12 +56,16 @@ add_custom_command( ${GROUP_WITH_DATA_SCHEMA} ${ISSUE835_SCHEMA} ${ISSUE889_SCHEMA} + ${ACCESS_ORDER_SCHEMA} sbe-jar ${SBE_JAR} COMMAND ${Java_JAVA_EXECUTABLE} -Dsbe.output.dir=${CXX_CODEC_TARGET_DIR} -Dsbe.generate.ir="true" -Dsbe.target.language="cpp" + -Dsbe.generate.precedence.checks="true" + -Dsbe.precedence.checks.flag.name="SBE_ENABLE_PRECEDENCE_CHECKS_IN_TESTS" + -Dsbe.cpp.disable.implicit.copying="true" -jar ${SBE_JAR} ${CODE_GENERATION_SCHEMA} ${COMPOSITE_OFFSETS_SCHEMA} @@ -68,6 +74,7 @@ add_custom_command( ${COMPOSITE_ELEMENTS_SCHEMA} ${ISSUE835_SCHEMA} ${ISSUE889_SCHEMA} + ${ACCESS_ORDER_SCHEMA} ) add_custom_target(codecs DEPENDS ${GENERATED_CODECS}) @@ -83,3 +90,5 @@ sbe_test(Rc3OtfFullIrTest codecs) sbe_test(CompositeElementsTest codecs) sbe_test(Issue835Test codecs) sbe_test(Issue889Test codecs) +sbe_test(FieldAccessOrderCheckTest codecs) +target_compile_definitions(FieldAccessOrderCheckTest PRIVATE SBE_ENABLE_PRECEDENCE_CHECKS_IN_TESTS) diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index 698d7ec849..6675172c8d 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -680,43 +680,43 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) performanceFigures.next(); EXPECT_EQ(performanceFigures.octaneRating(), perf1Octane); - Car::PerformanceFigures::Acceleration &acceleration = performanceFigures.acceleration(); - EXPECT_EQ(acceleration.count(), ACCELERATION_COUNT); - ASSERT_TRUE(acceleration.hasNext()); - acceleration.next(); - EXPECT_EQ(acceleration.mph(), perf1aMph); - EXPECT_EQ(acceleration.seconds(), perf1aSeconds); - - ASSERT_TRUE(acceleration.hasNext()); - acceleration.next(); - EXPECT_EQ(acceleration.mph(), perf1bMph); - EXPECT_EQ(acceleration.seconds(), perf1bSeconds); - - ASSERT_TRUE(acceleration.hasNext()); - acceleration.next(); - EXPECT_EQ(acceleration.mph(), perf1cMph); - EXPECT_EQ(acceleration.seconds(), perf1cSeconds); + Car::PerformanceFigures::Acceleration &acceleration1 = performanceFigures.acceleration(); + EXPECT_EQ(acceleration1.count(), ACCELERATION_COUNT); + ASSERT_TRUE(acceleration1.hasNext()); + acceleration1.next(); + EXPECT_EQ(acceleration1.mph(), perf1aMph); + EXPECT_EQ(acceleration1.seconds(), perf1aSeconds); + + ASSERT_TRUE(acceleration1.hasNext()); + acceleration1.next(); + EXPECT_EQ(acceleration1.mph(), perf1bMph); + EXPECT_EQ(acceleration1.seconds(), perf1bSeconds); + + ASSERT_TRUE(acceleration1.hasNext()); + acceleration1.next(); + EXPECT_EQ(acceleration1.mph(), perf1cMph); + EXPECT_EQ(acceleration1.seconds(), perf1cSeconds); ASSERT_TRUE(performanceFigures.hasNext()); performanceFigures.next(); EXPECT_EQ(performanceFigures.octaneRating(), perf2Octane); - acceleration = performanceFigures.acceleration(); - EXPECT_EQ(acceleration.count(), ACCELERATION_COUNT); - ASSERT_TRUE(acceleration.hasNext()); - acceleration.next(); - EXPECT_EQ(acceleration.mph(), perf2aMph); - EXPECT_EQ(acceleration.seconds(), perf2aSeconds); + Car::PerformanceFigures::Acceleration &acceleration2 = performanceFigures.acceleration(); + EXPECT_EQ(acceleration2.count(), ACCELERATION_COUNT); + ASSERT_TRUE(acceleration2.hasNext()); + acceleration2.next(); + EXPECT_EQ(acceleration2.mph(), perf2aMph); + EXPECT_EQ(acceleration2.seconds(), perf2aSeconds); - ASSERT_TRUE(acceleration.hasNext()); - acceleration.next(); - EXPECT_EQ(acceleration.mph(), perf2bMph); - EXPECT_EQ(acceleration.seconds(), perf2bSeconds); + ASSERT_TRUE(acceleration2.hasNext()); + acceleration2.next(); + EXPECT_EQ(acceleration2.mph(), perf2bMph); + EXPECT_EQ(acceleration2.seconds(), perf2bSeconds); - ASSERT_TRUE(acceleration.hasNext()); - acceleration.next(); - EXPECT_EQ(acceleration.mph(), perf2cMph); - EXPECT_EQ(acceleration.seconds(), perf2cSeconds); + ASSERT_TRUE(acceleration2.hasNext()); + acceleration2.next(); + EXPECT_EQ(acceleration2.mph(), perf2cMph); + EXPECT_EQ(acceleration2.seconds(), perf2cSeconds); EXPECT_EQ(m_carDecoder.manufacturerLength(), MANUFACTURER_LENGTH); EXPECT_EQ(std::string(m_carDecoder.manufacturer(), MANUFACTURER_LENGTH), MANUFACTURER); @@ -748,7 +748,7 @@ struct CallbacksForEach void operator()(Car::PerformanceFigures &performanceFigures) { - Car::PerformanceFigures::Acceleration acceleration = performanceFigures.acceleration(); + Car::PerformanceFigures::Acceleration &acceleration = performanceFigures.acceleration(); countOfPerformanceFigures++; acceleration.forEach(*this); @@ -806,7 +806,7 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) #if __cplusplus >= 201103L performanceFigures.forEach([&](Car::PerformanceFigures &figures) { - Car::PerformanceFigures::Acceleration acceleration = figures.acceleration(); + Car::PerformanceFigures::Acceleration &acceleration = figures.acceleration(); cbs.countOfPerformanceFigures++; acceleration.forEach( @@ -964,13 +964,13 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) Car::PerformanceFigures &perfFigures = carDecoder.performanceFigures(); perfFigures.next(); - Car::PerformanceFigures::Acceleration &acceleration = perfFigures.acceleration(); + Car::PerformanceFigures::Acceleration &acceleration1 = perfFigures.acceleration(); - acceleration.next().next().next(); + acceleration1.next().next().next(); perfFigures.next(); - acceleration = perfFigures.acceleration(); - acceleration.next().next().next(); + Car::PerformanceFigures::Acceleration &acceleration2 = perfFigures.acceleration(); + acceleration2.next().next().next(); EXPECT_EQ(carDecoder.getManufacturerAsString(), manufacturer); EXPECT_EQ(carDecoder.getModelAsString(), model); @@ -1037,15 +1037,15 @@ TEST_F(CodeGenTest, shouldPrintFullDecodedFlyweightRegardlessOfReadPosition) Car::PerformanceFigures &perfFigures = carDecoder.performanceFigures(); perfFigures.next(); - Car::PerformanceFigures::Acceleration &acceleration = perfFigures.acceleration(); + Car::PerformanceFigures::Acceleration &acceleration1 = perfFigures.acceleration(); - acceleration.next().next().next(); + acceleration1.next().next().next(); expectDisplayString(expectedDisplayString, carDecoder); perfFigures.next(); - acceleration = perfFigures.acceleration(); - acceleration.next().next().next(); + Car::PerformanceFigures::Acceleration &acceleration2 = perfFigures.acceleration(); + acceleration2.next().next().next(); EXPECT_EQ(carDecoder.getManufacturerAsString(), manufacturer); EXPECT_EQ(carDecoder.getModelAsString(), model); diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp index 28bcbb1880..39759c1d50 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp @@ -141,7 +141,7 @@ TEST_F(CompositeOffsetsCodeGenTest, shouldBeAbleToDecodeHeaderAndMsgCorrectly) m_msgDecoder.wrapForDecode( buffer, hdrSz, TestMessage1::sbeBlockLength(), TestMessage1::sbeSchemaVersion(), hdrSz + sz); - TestMessage1::Entries entries = m_msgDecoder.entries(); + TestMessage1::Entries &entries = m_msgDecoder.entries(); EXPECT_EQ(entries.count(), 2u); ASSERT_TRUE(entries.hasNext()); diff --git a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp new file mode 100644 index 0000000000..89aeeca267 --- /dev/null +++ b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp @@ -0,0 +1,4937 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "order_check/MultipleVarLength.h" +#include "order_check/GroupAndVarLength.h" +#include "order_check/VarLengthInsideGroup.h" +#include "order_check/NestedGroups.h" +#include "order_check/CompositeInsideGroup.h" +#include "order_check/AddPrimitiveV1.h" +#include "order_check/AddPrimitiveV0.h" +#include "order_check/AddPrimitiveBeforeGroupV1.h" +#include "order_check/AddPrimitiveBeforeGroupV0.h" +#include "order_check/AddPrimitiveBeforeVarDataV1.h" +#include "order_check/AddPrimitiveBeforeVarDataV0.h" +#include "order_check/AddPrimitiveInsideGroupV1.h" +#include "order_check/AddPrimitiveInsideGroupV0.h" +#include "order_check/AddGroupBeforeVarDataV1.h" +#include "order_check/AddGroupBeforeVarDataV0.h" +#include "order_check/AddEnumBeforeGroupV1.h" +#include "order_check/AddEnumBeforeGroupV0.h" +#include "order_check/AddCompositeBeforeGroupV1.h" +#include "order_check/AddCompositeBeforeGroupV0.h" +#include "order_check/AddArrayBeforeGroupV1.h" +#include "order_check/AddArrayBeforeGroupV0.h" +#include "order_check/AddBitSetBeforeGroupV1.h" +#include "order_check/AddBitSetBeforeGroupV0.h" +#include "order_check/EnumInsideGroup.h" +#include "order_check/BitSetInsideGroup.h" +#include "order_check/ArrayInsideGroup.h" +#include "order_check/MultipleGroups.h" +#include "order_check/AddVarDataV1.h" +#include "order_check/AddVarDataV0.h" +#include "order_check/AsciiInsideGroup.h" +#include "order_check/AddAsciiBeforeGroupV1.h" +#include "order_check/AddAsciiBeforeGroupV0.h" +#include "order_check/NoBlock.h" +#include "order_check/GroupWithNoBlock.h" +#include "order_check/NestedGroupWithVarLength.h" + +using namespace order::check; +using ::testing::HasSubstr; + +class FieldAccessOrderCheckTest : public testing::Test +{ +public: + static const std::size_t BUFFER_LEN = 2048u; + static const std::size_t OFFSET = 0; + + char m_buffer[BUFFER_LEN] = {}; + +}; + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingVariableLengthFieldsInSchemaDefinedOrder1) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.getBAsString(), "abc"); + EXPECT_EQ(decoder.getCAsString(), "def"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingVariableLengthFieldsInSchemaDefinedOrder2) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 42); + auto bLength = decoder.bLength(); + auto *b = decoder.b(); + const std::string bStr(b, bLength); + EXPECT_EQ(bStr, "abc"); + auto cLength = decoder.cLength(); + auto *c = decoder.c(); + const std::string cStr(c, cLength); + EXPECT_EQ(cStr, "def"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingVariableLengthFieldsInSchemaDefinedOrder3) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + auto *bIn = "abc"; + encoder.putB(bIn, strlen(bIn)); + auto *cIn = "def"; + encoder.putC(cIn, strlen(cIn)); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 42); + + const auto bLength = decoder.bLength(); + auto *bOut = new char[bLength]; + decoder.getB(bOut, bLength); + EXPECT_EQ(std::strncmp(bOut, "abc", bLength), 0); + delete[] bOut; + + auto cLength = decoder.cLength(); + auto *cOut = new char[cLength]; + decoder.getC(cOut, cLength); + EXPECT_EQ(std::strncmp(cOut, "def", cLength), 0); + delete[] cOut; +} + +TEST_F(FieldAccessOrderCheckTest, allowsDecodingVariableLengthFieldsAfterRewind) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.getBAsString(), "abc"); + EXPECT_EQ(decoder.getCAsString(), "def"); + + decoder.sbeRewind(); + + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.getBAsString(), "abc"); + EXPECT_EQ(decoder.getCAsString(), "def"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsDecodingToSkipVariableLengthFields) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.skipB(), 3ul); + EXPECT_EQ(decoder.getCAsString(), "def"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReEncodingTopLevelPrimitiveFields) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.a(43); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 43); + EXPECT_EQ(decoder.getBAsString(), "abc"); + EXPECT_EQ(decoder.getCAsString(), "def"); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsSkippingEncodingOfVariableLengthField1) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + EXPECT_THROW( + { + try + { + encoder.putC("def"); + } + catch (const std::exception &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"c\" in state: V0_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsSkippingEncodingOfVariableLengthField2) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + EXPECT_THROW( + { + try + { + auto *cIn = "cIn"; + encoder.putC(cIn, std::strlen(cIn)); + } + catch (const std::exception &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"c\" in state: V0_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReEncodingEarlierVariableLengthFields) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + EXPECT_THROW( + { + try + { + encoder.putB("ghi"); + } + catch (const std::exception &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b\" in state: V0_C_DONE") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReEncodingLatestVariableLengthField) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + EXPECT_THROW( + { + try + { + encoder.putC("ghi"); + } + catch (const std::exception &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"c\" in state: V0_C_DONE") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsSkippingDecodingOfVariableLengthField1) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 42); + + EXPECT_THROW( + { + try + { + decoder.getCAsString(); + } + catch (const std::exception &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"c\" in state: V0_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsSkippingDecodingOfVariableLengthField2) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 42); + + EXPECT_THROW( + { + try + { + decoder.cLength(); + } + catch (const std::exception &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot decode length of var data \"c\" in state: V0_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsSkippingDecodingOfVariableLengthField3) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 42); + + EXPECT_THROW( + { + try + { + char cOut[3]; + decoder.getC(cOut, 3); + } + catch (const std::exception &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"c\" in state: V0_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReDecodingEarlierVariableLengthField) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.getBAsString(), "abc"); + EXPECT_EQ(decoder.getCAsString(), "def"); + + EXPECT_THROW( + { + try + { + decoder.getBAsString(); + } + catch (const std::exception &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b\" in state: V0_C_DONE") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReDecodingLatestVariableLengthField) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.getBAsString(), "abc"); + EXPECT_EQ(decoder.getCAsString(), "def"); + + EXPECT_THROW( + { + try + { + decoder.getCAsString(); + } + catch (const std::exception &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"c\" in state: V0_C_DONE") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingGroupAndVariableLengthFieldsInSchemaDefinedOrder) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + GroupAndVarLength::B &b = encoder.bCount(2); + b.next().c(1); + b.next().c(2); + encoder.putD("abc"); + encoder.checkEncodingIsComplete(); + + GroupAndVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + GroupAndVarLength::sbeBlockLength(), + GroupAndVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 42); + GroupAndVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 1); + EXPECT_EQ(bDecoder.next().c(), 2); + EXPECT_EQ(decoder.getDAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsDecodingGroupAndVariableLengthFieldsAfterRewind) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + GroupAndVarLength::B &b = encoder.bCount(2); + b.next().c(1); + b.next().c(2); + encoder.putD("abc"); + encoder.checkEncodingIsComplete(); + + GroupAndVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + GroupAndVarLength::sbeBlockLength(), + GroupAndVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 42); + GroupAndVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 1); + EXPECT_EQ(bDecoder.next().c(), 2); + EXPECT_EQ(decoder.getDAsString(), "abc"); + + decoder.sbeRewind(); + + EXPECT_EQ(decoder.a(), 42); + GroupAndVarLength::B &bDecoder2 = decoder.b(); + EXPECT_EQ(bDecoder2.count(), 2u); + EXPECT_EQ(bDecoder2.next().c(), 1); + EXPECT_EQ(bDecoder2.next().c(), 2); + EXPECT_EQ(decoder.getDAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsDecodingToSkipMessage) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + GroupAndVarLength::B &b = encoder.bCount(2); + b.next().c(1); + b.next().c(2); + encoder.putD("abc"); + encoder.checkEncodingIsComplete(); + + const std::uint64_t nextEncodeOffset = encoder.sbePosition(); + encoder.wrapForEncode(m_buffer, nextEncodeOffset, BUFFER_LEN); + encoder.a(43); + GroupAndVarLength::B &b2 = encoder.bCount(2); + b2.next().c(3); + b2.next().c(4); + encoder.putD("def"); + encoder.checkEncodingIsComplete(); + + GroupAndVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + GroupAndVarLength::sbeBlockLength(), + GroupAndVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + decoder.skip(); + const std::uint64_t nextDecodeOffset = decoder.sbePosition(); + EXPECT_EQ(nextDecodeOffset, nextEncodeOffset); + + decoder.wrapForDecode( + m_buffer, + nextDecodeOffset, + GroupAndVarLength::sbeBlockLength(), + GroupAndVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 43); + GroupAndVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 3); + EXPECT_EQ(bDecoder.next().c(), 4); + EXPECT_EQ(decoder.getDAsString(), "def"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsDecodingToDetermineMessageLengthBeforeReadingFields) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(43); + GroupAndVarLength::B &b = encoder.bCount(2); + b.next().c(3); + b.next().c(4); + encoder.putD("def"); + encoder.checkEncodingIsComplete(); + + GroupAndVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + GroupAndVarLength::sbeBlockLength(), + GroupAndVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + EXPECT_EQ(decoder.decodeLength(), 18u); + EXPECT_EQ(decoder.a(), 43); + GroupAndVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 3); + EXPECT_EQ(bDecoder.next().c(), 4); + EXPECT_EQ(decoder.getDAsString(), "def"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingEmptyGroupAndVariableLengthFieldsInSchemaDefinedOrder) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.bCount(0); + encoder.putD("abc"); + encoder.checkEncodingIsComplete(); + + GroupAndVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + GroupAndVarLength::sbeBlockLength(), + GroupAndVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + GroupAndVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 0u); + EXPECT_EQ(decoder.getDAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncoderToResetZeroGroupLengthToNonZero) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.bCount(0).resetCountToIndex(); + encoder.putD("abc"); + encoder.checkEncodingIsComplete(); + + GroupAndVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + GroupAndVarLength::sbeBlockLength(), + GroupAndVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + GroupAndVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 0u); + EXPECT_EQ(decoder.getDAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncoderToResetNonZeroGroupLengthToNonZeroBeforeCallingNext) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.bCount(2).resetCountToIndex(); + encoder.putD("abc"); + encoder.checkEncodingIsComplete(); + + GroupAndVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + GroupAndVarLength::sbeBlockLength(), + GroupAndVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + GroupAndVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 0u); + EXPECT_EQ(decoder.getDAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncoderToResetNonZeroGroupLengthToNonZero) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + GroupAndVarLength::B &bEncoder = encoder.bCount(2).next(); + bEncoder.c(43); + bEncoder.resetCountToIndex(); + encoder.putD("abc"); + encoder.checkEncodingIsComplete(); + + GroupAndVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + GroupAndVarLength::sbeBlockLength(), + GroupAndVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + GroupAndVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + EXPECT_EQ(bDecoder.next().c(), 43); + EXPECT_EQ(decoder.getDAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncoderToResetGroupLengthMidGroupElement) +{ + NestedGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + NestedGroups::B &bEncoder = encoder.bCount(2).next(); + bEncoder.c(43); + EXPECT_THROW( + { + try + { + bEncoder.resetCountToIndex(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot reset count of repeating group \"b\" in state: V0_B_N_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingGroupElementBeforeCallingNext) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + GroupAndVarLength::B &bEncoder = encoder.bCount(1); + EXPECT_THROW( + { + try + { + bEncoder.c(1); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsDecodingGroupElementBeforeCallingNext) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + GroupAndVarLength::B &bEncoder = encoder.bCount(2); + bEncoder.next().c(1); + bEncoder.next().c(2); + encoder.putD("abc"); + encoder.checkEncodingIsComplete(); + + GroupAndVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + GroupAndVarLength::sbeBlockLength(), + GroupAndVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + GroupAndVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + + EXPECT_THROW( + { + try + { + bDecoder.c(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsSkippingEncodingOfGroup) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + EXPECT_THROW( + { + try + { + encoder.putD("abc"); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"d\" in state: V0_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReEncodingVariableLengthFieldAfterGroup) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + GroupAndVarLength::B &bEncoder = encoder.bCount(2); + bEncoder.next().c(1); + bEncoder.next().c(2); + encoder.putD("abc"); + EXPECT_THROW( + { + try + { + encoder.putD("def"); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"d\" in state: V0_D_DONE") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReEncodingGroupCount) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + GroupAndVarLength::B &bEncoder = encoder.bCount(2); + bEncoder.next().c(1); + bEncoder.next().c(2); + encoder.putD("abc"); + EXPECT_THROW( + { + try + { + encoder.bCount(1); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot encode count of repeating group \"b\" in state: V0_D_DONE") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedDecodingOfGroupBeforeVariableLengthField) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + GroupAndVarLength::B &bEncoder = encoder.bCount(2); + bEncoder.next().c(1); + bEncoder.next().c(2); + encoder.putD("abc"); + encoder.checkEncodingIsComplete(); + + GroupAndVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + GroupAndVarLength::sbeBlockLength(), + GroupAndVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + EXPECT_THROW( + { + try + { + decoder.getDAsString(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"d\" in state: V0_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReDecodingVariableLengthFieldAfterGroup) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + GroupAndVarLength::B &bEncoder = encoder.bCount(2); + bEncoder.next().c(1); + bEncoder.next().c(2); + encoder.putD("abc"); + encoder.checkEncodingIsComplete(); + + GroupAndVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + GroupAndVarLength::sbeBlockLength(), + GroupAndVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + GroupAndVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 1); + EXPECT_EQ(bDecoder.next().c(), 2); + EXPECT_EQ(decoder.getDAsString(), "abc"); + EXPECT_THROW( + { + try + { + decoder.getDAsString(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"d\" in state: V0_D_DONE") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReDecodingGroupAfterVariableLengthField) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + GroupAndVarLength::B &bEncoder = encoder.bCount(2); + bEncoder.next().c(1); + bEncoder.next().c(2); + encoder.putD("abc"); + encoder.checkEncodingIsComplete(); + + GroupAndVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + GroupAndVarLength::sbeBlockLength(), + GroupAndVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + GroupAndVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 1); + EXPECT_EQ(bDecoder.next().c(), 2); + EXPECT_EQ(decoder.getDAsString(), "abc"); + EXPECT_THROW( + { + try + { + decoder.b(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot decode count of repeating group \"b\" in state: V0_D_DONE") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingVariableLengthFieldInsideGroupInSchemaDefinedOrder) +{ + VarLengthInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + VarLengthInsideGroup::B &bEncoder = encoder.bCount(2); + bEncoder.next().c(1).putD("abc"); + bEncoder.next().c(2).putD("def"); + encoder.putE("ghi"); + encoder.checkEncodingIsComplete(); + + VarLengthInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + VarLengthInsideGroup::sbeBlockLength(), + VarLengthInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + VarLengthInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 1); + EXPECT_EQ(bDecoder.getDAsString(), "abc"); + EXPECT_EQ(bDecoder.next().c(), 2); + EXPECT_EQ(bDecoder.getDAsString(), "def"); + EXPECT_EQ(decoder.getEAsString(), "ghi"); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedGroupElementVariableLengthFieldToEncodeAtTopLevel) +{ + VarLengthInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + VarLengthInsideGroup::B &bEncoder = encoder.bCount(1); + bEncoder.next().c(1); + EXPECT_THROW( + { + try + { + encoder.putE("abc"); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"e\" in state: V0_B_1_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedGroupElementVariableLengthFieldToEncodeNextElement) +{ + VarLengthInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + VarLengthInsideGroup::B &bEncoder = encoder.bCount(2); + bEncoder.next(); + EXPECT_THROW( + { + try + { + bEncoder.next(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access next element in repeating group \"b\" in state: V0_B_N_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedGroupElementEncoding) +{ + VarLengthInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + VarLengthInsideGroup::B &bEncoder = encoder.bCount(2); + bEncoder.next().c(1).putD("abc"); + EXPECT_THROW( + { + try + { + encoder.putE("abc"); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"e\" in state: V0_B_N_D_DONE") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReEncodingGroupElementVariableLengthField) +{ + VarLengthInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + VarLengthInsideGroup::B &bEncoder = encoder.bCount(1); + bEncoder.next().c(1).putD("abc"); + encoder.putE("def"); + EXPECT_THROW( + { + try + { + bEncoder.putD("ghi"); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.d\" in state: V0_E_DONE") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReDecodingGroupElementVariableLengthField) +{ + VarLengthInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + VarLengthInsideGroup::B &bEncoder = encoder.bCount(2); + bEncoder.next().c(1).putD("abc"); + bEncoder.next().c(2).putD("def"); + encoder.putE("ghi"); + encoder.checkEncodingIsComplete(); + + VarLengthInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + VarLengthInsideGroup::sbeBlockLength(), + VarLengthInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + VarLengthInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 1); + EXPECT_EQ(bDecoder.getDAsString(), "abc"); + EXPECT_THROW( + { + try + { + bDecoder.getDAsString(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.d\" in state: V0_B_N_D_DONE") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedDecodingOfGroupElementVariableLengthFieldToNextElement) +{ + VarLengthInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + VarLengthInsideGroup::B &bEncoder = encoder.bCount(2); + bEncoder.next().c(1).putD("abc"); + bEncoder.next().c(2).putD("def"); + encoder.putE("ghi"); + encoder.checkEncodingIsComplete(); + + VarLengthInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + VarLengthInsideGroup::sbeBlockLength(), + VarLengthInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + VarLengthInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 1); + EXPECT_THROW( + { + try + { + bDecoder.next(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access next element in repeating group \"b\" in state: V0_B_N_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedDecodingOfGroupElementVariableLengthFieldToTopLevel) +{ + VarLengthInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + VarLengthInsideGroup::B &bEncoder = encoder.bCount(1); + bEncoder.next().c(1).putD("abc"); + encoder.putE("ghi"); + encoder.checkEncodingIsComplete(); + + VarLengthInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + VarLengthInsideGroup::sbeBlockLength(), + VarLengthInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + VarLengthInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + EXPECT_EQ(bDecoder.next().c(), 1); + EXPECT_THROW( + { + try + { + decoder.getEAsString(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"e\" in state: V0_B_1_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedDecodingOfGroupElement) +{ + VarLengthInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + VarLengthInsideGroup::B &bEncoder = encoder.bCount(2); + bEncoder.next().c(1).putD("abc"); + bEncoder.next().c(2).putD("def"); + encoder.putE("ghi"); + encoder.checkEncodingIsComplete(); + + VarLengthInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + VarLengthInsideGroup::sbeBlockLength(), + VarLengthInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + VarLengthInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 1); + EXPECT_THROW( + { + try + { + decoder.getEAsString(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"e\" in state: V0_B_N_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingNestedGroupsInSchemaDefinedOrder) +{ + NestedGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + NestedGroups::B &bEncoder = encoder.bCount(2); + bEncoder.next(); + bEncoder.c(1); + NestedGroups::B::D &b0dEncoder = bEncoder.dCount(2); + b0dEncoder.next().e(2); + b0dEncoder.next().e(3); + NestedGroups::B::F &b0fEncoder = bEncoder.fCount(1); + b0fEncoder.next().g(4); + bEncoder.next(); + bEncoder.c(5); + NestedGroups::B::D &b1dEncoder = bEncoder.dCount(1); + b1dEncoder.next().e(6); + NestedGroups::B::F &b1fEncoder = bEncoder.fCount(1); + b1fEncoder.next().g(7); + NestedGroups::H &hEncoder = encoder.hCount(1); + hEncoder.next().i(8); + encoder.checkEncodingIsComplete(); + + NestedGroups decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + NestedGroups::sbeBlockLength(), + NestedGroups::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + NestedGroups::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + NestedGroups::B &b0Decoder = bDecoder.next(); + EXPECT_EQ(b0Decoder.c(), 1); + NestedGroups::B::D &b0dDecoder = b0Decoder.d(); + EXPECT_EQ(b0dDecoder.count(), 2u); + EXPECT_EQ(b0dDecoder.next().e(), 2); + EXPECT_EQ(b0dDecoder.next().e(), 3); + NestedGroups::B::F &b0fDecoder = b0Decoder.f(); + EXPECT_EQ(b0fDecoder.count(), 1u); + EXPECT_EQ(b0fDecoder.next().g(), 4); + NestedGroups::B &b1Decoder = bDecoder.next(); + EXPECT_EQ(b1Decoder.c(), 5); + NestedGroups::B::D &b1dDecoder = b1Decoder.d(); + EXPECT_EQ(b1dDecoder.count(), 1u); + EXPECT_EQ(b1dDecoder.next().e(), 6); + NestedGroups::B::F &b1fDecoder = b1Decoder.f(); + EXPECT_EQ(b1fDecoder.count(), 1u); + EXPECT_EQ(b1fDecoder.next().g(), 7); + NestedGroups::H &hDecoder = decoder.h(); + EXPECT_EQ(hDecoder.count(), 1u); + EXPECT_EQ(hDecoder.next().i(), 8); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingEmptyNestedGroupsInSchemaDefinedOrder) +{ + NestedGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.bCount(0); + encoder.hCount(0); + encoder.checkEncodingIsComplete(); + + NestedGroups decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + NestedGroups::sbeBlockLength(), + NestedGroups::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + NestedGroups::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 0u); + NestedGroups::H &hDecoder = decoder.h(); + EXPECT_EQ(hDecoder.count(), 0u); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedEncodingOfNestedGroup) +{ + NestedGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + NestedGroups::B &bEncoder = encoder.bCount(1).next(); + bEncoder.c(1); + EXPECT_THROW( + { + try + { + bEncoder.fCount(1); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot encode count of repeating group \"b.f\" in state: V0_B_1_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingCompositeInsideGroupInSchemaDefinedOrder) +{ + CompositeInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Point &aEncoder = encoder.a(); + aEncoder.x(1); + aEncoder.y(2); + CompositeInsideGroup::B &bEncoder = encoder.bCount(1).next(); + Point &cEncoder = bEncoder.c(); + cEncoder.x(3); + cEncoder.y(4); + encoder.checkEncodingIsComplete(); + + CompositeInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + CompositeInsideGroup::sbeBlockLength(), + CompositeInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + Point &aDecoder = decoder.a(); + EXPECT_EQ(aDecoder.x(), 1); + EXPECT_EQ(aDecoder.y(), 2); + CompositeInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + Point &cDecoder = bDecoder.next().c(); + EXPECT_EQ(cDecoder.x(), 3); + EXPECT_EQ(cDecoder.y(), 4); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingCompositeInsideGroupBeforeCallingNext) +{ + CompositeInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Point &aEncoder = encoder.a(); + aEncoder.x(1); + aEncoder.y(2); + CompositeInsideGroup::B &bEncoder = encoder.bCount(1); + EXPECT_THROW( + { + try + { + bEncoder.c(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsDecodingCompositeInsideGroupBeforeCallingNext) +{ + CompositeInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Point &aEncoder = encoder.a(); + aEncoder.x(1); + aEncoder.y(2); + CompositeInsideGroup::B &bEncoder = encoder.bCount(1).next(); + Point &cEncoder = bEncoder.c(); + cEncoder.x(3); + cEncoder.y(4); + + CompositeInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + CompositeInsideGroup::sbeBlockLength(), + CompositeInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + Point &aDecoder = decoder.a(); + EXPECT_EQ(aDecoder.x(), 1); + EXPECT_EQ(aDecoder.y(), 2); + CompositeInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + EXPECT_THROW( + { + try + { + bDecoder.c(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReEncodingTopLevelCompositeViaReWrap) +{ + CompositeInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Point &aEncoder = encoder.a(); + aEncoder.x(1); + aEncoder.y(2); + CompositeInsideGroup::B &bEncoder = encoder.bCount(1).next(); + Point &cEncoder = bEncoder.c(); + cEncoder.x(3); + cEncoder.y(4); + encoder.a().x(5); + encoder.a().y(6); + encoder.checkEncodingIsComplete(); + + CompositeInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + CompositeInsideGroup::sbeBlockLength(), + CompositeInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + Point &aDecoder = decoder.a(); + EXPECT_EQ(aDecoder.x(), 5); + EXPECT_EQ(aDecoder.y(), 6); + CompositeInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + Point &cDecoder = bDecoder.next().c(); + EXPECT_EQ(cDecoder.x(), 3); + EXPECT_EQ(cDecoder.y(), 4); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReEncodingTopLevelCompositeViaEncoderReference) +{ + CompositeInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Point &aEncoder = encoder.a(); + aEncoder.x(1); + aEncoder.y(2); + CompositeInsideGroup::B &bEncoder = encoder.bCount(1).next(); + Point &cEncoder = bEncoder.c(); + cEncoder.x(3); + cEncoder.y(4); + aEncoder.x(5); + aEncoder.y(6); + encoder.checkEncodingIsComplete(); + + CompositeInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + CompositeInsideGroup::sbeBlockLength(), + CompositeInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + Point &aDecoder = decoder.a(); + EXPECT_EQ(aDecoder.x(), 5); + EXPECT_EQ(aDecoder.y(), 6); + CompositeInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + Point &cDecoder = bDecoder.next().c(); + EXPECT_EQ(cDecoder.x(), 3); + EXPECT_EQ(cDecoder.y(), 4); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReEncodingGroupElementCompositeViaReWrap) +{ + CompositeInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Point &aEncoder = encoder.a(); + aEncoder.x(1); + aEncoder.y(2); + CompositeInsideGroup::B &bEncoder = encoder.bCount(1).next(); + bEncoder.c().x(3).y(4); + bEncoder.c().x(5).y(6); + encoder.checkEncodingIsComplete(); + + CompositeInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + CompositeInsideGroup::sbeBlockLength(), + CompositeInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + Point &aDecoder = decoder.a(); + EXPECT_EQ(aDecoder.x(), 1); + EXPECT_EQ(aDecoder.y(), 2); + CompositeInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + Point &cDecoder = bDecoder.next().c(); + EXPECT_EQ(cDecoder.x(), 5); + EXPECT_EQ(cDecoder.y(), 6); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReEncodingGroupElementCompositeViaEncoderReference) +{ + CompositeInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Point &aEncoder = encoder.a(); + aEncoder.x(1); + aEncoder.y(2); + CompositeInsideGroup::B &bEncoder = encoder.bCount(1).next(); + Point &cEncoder = bEncoder.c(); + cEncoder.x(3); + cEncoder.y(4); + cEncoder.x(5); + cEncoder.y(6); + encoder.checkEncodingIsComplete(); + + CompositeInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + CompositeInsideGroup::sbeBlockLength(), + CompositeInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + Point &aDecoder = decoder.a(); + EXPECT_EQ(aDecoder.x(), 1); + EXPECT_EQ(aDecoder.y(), 2); + CompositeInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + Point &cDecoder = bDecoder.next().c(); + EXPECT_EQ(cDecoder.x(), 5); + EXPECT_EQ(cDecoder.y(), 6); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReDecodingTopLevelCompositeViaReWrap) +{ + CompositeInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Point &aEncoder = encoder.a(); + aEncoder.x(1); + aEncoder.y(2); + CompositeInsideGroup::B &bEncoder = encoder.bCount(1).next(); + bEncoder.c().x(3).y(4); + encoder.checkEncodingIsComplete(); + + CompositeInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + CompositeInsideGroup::sbeBlockLength(), + CompositeInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + Point &a1Decoder = decoder.a(); + EXPECT_EQ(a1Decoder.x(), 1); + EXPECT_EQ(a1Decoder.y(), 2); + CompositeInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + Point &cDecoder = bDecoder.next().c(); + EXPECT_EQ(cDecoder.x(), 3); + EXPECT_EQ(cDecoder.y(), 4); + Point &a2Decoder = decoder.a(); + EXPECT_EQ(a2Decoder.x(), 1); + EXPECT_EQ(a2Decoder.y(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReDecodingTopLevelCompositeViaEncoderReference) +{ + CompositeInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Point &aEncoder = encoder.a(); + aEncoder.x(1); + aEncoder.y(2); + CompositeInsideGroup::B &bEncoder = encoder.bCount(1).next(); + bEncoder.c().x(3).y(4); + encoder.checkEncodingIsComplete(); + + CompositeInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + CompositeInsideGroup::sbeBlockLength(), + CompositeInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + Point &aDecoder = decoder.a(); + EXPECT_EQ(aDecoder.x(), 1); + EXPECT_EQ(aDecoder.y(), 2); + CompositeInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + Point &cDecoder = bDecoder.next().c(); + EXPECT_EQ(cDecoder.x(), 3); + EXPECT_EQ(cDecoder.y(), 4); + EXPECT_EQ(aDecoder.x(), 1); + EXPECT_EQ(aDecoder.y(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReDecodingGroupElementCompositeViaReWrap) +{ + CompositeInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Point &aEncoder = encoder.a(); + aEncoder.x(1); + aEncoder.y(2); + CompositeInsideGroup::B &bEncoder = encoder.bCount(1).next(); + bEncoder.c().x(3).y(4); + encoder.checkEncodingIsComplete(); + + CompositeInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + CompositeInsideGroup::sbeBlockLength(), + CompositeInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + Point &aDecoder = decoder.a(); + EXPECT_EQ(aDecoder.x(), 1); + EXPECT_EQ(aDecoder.y(), 2); + CompositeInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + Point &c1Decoder = bDecoder.next().c(); + EXPECT_EQ(c1Decoder.x(), 3); + EXPECT_EQ(c1Decoder.y(), 4); + Point &c2Decoder = bDecoder.c(); + EXPECT_EQ(c2Decoder.x(), 3); + EXPECT_EQ(c2Decoder.y(), 4); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReDecodingGroupElementCompositeViaEncoderReference) +{ + CompositeInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Point &aEncoder = encoder.a(); + aEncoder.x(1); + aEncoder.y(2); + CompositeInsideGroup::B &bEncoder = encoder.bCount(1).next(); + bEncoder.c().x(3).y(4); + encoder.checkEncodingIsComplete(); + + CompositeInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + CompositeInsideGroup::sbeBlockLength(), + CompositeInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + Point &aDecoder = decoder.a(); + EXPECT_EQ(aDecoder.x(), 1); + EXPECT_EQ(aDecoder.y(), 2); + CompositeInsideGroup::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + Point &cDecoder = bDecoder.next().c(); + EXPECT_EQ(cDecoder.x(), 3); + EXPECT_EQ(cDecoder.y(), 4); + EXPECT_EQ(cDecoder.x(), 3); + EXPECT_EQ(cDecoder.y(), 4); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedPrimitiveField) +{ + AddPrimitiveV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.b(2); + encoder.checkEncodingIsComplete(); + + AddPrimitiveV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveV1::sbeBlockLength(), + AddPrimitiveV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.b(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingPrimitiveFieldAsNullValue) +{ + AddPrimitiveV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.checkEncodingIsComplete(); + + AddPrimitiveV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.b(), AddPrimitiveV1::bNullValue()); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedPrimitiveFieldBeforeGroup) +{ + AddPrimitiveBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.d(3); + AddPrimitiveBeforeGroupV1::B &bEncoder = encoder.bCount(1).next(); + bEncoder.c(2); + encoder.checkEncodingIsComplete(); + + AddPrimitiveBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveBeforeGroupV1::sbeBlockLength(), + AddPrimitiveBeforeGroupV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.d(), 3); + AddPrimitiveBeforeGroupV1::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + EXPECT_EQ(bDecoder.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingPrimitiveFieldBeforeGroupAsNullValue) +{ + AddPrimitiveBeforeGroupV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + AddPrimitiveBeforeGroupV0::B &bEncoder = encoder.bCount(1).next(); + bEncoder.c(2); + encoder.checkEncodingIsComplete(); + + AddPrimitiveBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveBeforeGroupV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.d(), AddPrimitiveBeforeGroupV1::dNullValue()); + AddPrimitiveBeforeGroupV1::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + EXPECT_EQ(bDecoder.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToSkipPresentButAddedPrimitiveFieldBeforeGroup) +{ + AddPrimitiveBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.d(3); + AddPrimitiveBeforeGroupV1::B &bEncoder = encoder.bCount(1).next(); + bEncoder.c(2); + encoder.checkEncodingIsComplete(); + + AddPrimitiveBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveBeforeGroupV1::sbeBlockLength(), + AddPrimitiveBeforeGroupV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddPrimitiveBeforeGroupV1::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + EXPECT_EQ(bDecoder.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsOldDecoderToSkipAddedPrimitiveFieldBeforeGroup) +{ + AddPrimitiveBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.d(3); + AddPrimitiveBeforeGroupV1::B &bEncoder = encoder.bCount(1).next(); + bEncoder.c(2); + encoder.checkEncodingIsComplete(); + + AddPrimitiveBeforeGroupV0 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveBeforeGroupV1::sbeBlockLength(), + 1, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddPrimitiveBeforeGroupV0::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + EXPECT_EQ(bDecoder.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedPrimitiveFieldBeforeVarData) +{ + AddPrimitiveBeforeVarDataV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.c(3); + encoder.putB("abc"); + encoder.checkEncodingIsComplete(); + + AddPrimitiveBeforeVarDataV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveBeforeVarDataV1::sbeBlockLength(), + AddPrimitiveBeforeVarDataV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.c(), 3); + EXPECT_EQ(decoder.getBAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingPrimitiveFieldBeforeVarDataAsNullValue) +{ + AddPrimitiveBeforeVarDataV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putB("abc"); + encoder.checkEncodingIsComplete(); + + AddPrimitiveBeforeVarDataV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveBeforeVarDataV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.c(), AddPrimitiveBeforeVarDataV1::cNullValue()); + EXPECT_EQ(decoder.getBAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToSkipPresentButAddedPrimitiveFieldBeforeVarData) +{ + AddPrimitiveBeforeVarDataV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.c(3); + encoder.putB("abc"); + encoder.checkEncodingIsComplete(); + + AddPrimitiveBeforeVarDataV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveBeforeVarDataV1::sbeBlockLength(), + AddPrimitiveBeforeVarDataV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.getBAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsOldDecoderToSkipAddedPrimitiveFieldBeforeVarData) +{ + AddPrimitiveBeforeVarDataV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.c(3); + encoder.putB("abc"); + encoder.checkEncodingIsComplete(); + + AddPrimitiveBeforeVarDataV0 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveBeforeVarDataV1::sbeBlockLength(), + 1, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.getBAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedPrimitiveFieldInsideGroup) +{ + AddPrimitiveInsideGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.bCount(1).next().c(2).d(3); + encoder.checkEncodingIsComplete(); + + AddPrimitiveInsideGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveInsideGroupV1::sbeBlockLength(), + AddPrimitiveInsideGroupV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddPrimitiveInsideGroupV1::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + EXPECT_EQ(bDecoder.next().c(), 2); + EXPECT_EQ(bDecoder.d(), 3); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingPrimitiveFieldInsideGroupAsNullValue) +{ + AddPrimitiveInsideGroupV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddPrimitiveInsideGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveInsideGroupV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddPrimitiveInsideGroupV1::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + EXPECT_EQ(bDecoder.next().c(), 2); + EXPECT_EQ(bDecoder.d(), AddPrimitiveInsideGroupV1::B::dNullValue()); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToSkipPresentButAddedPrimitiveFieldInsideGroup) +{ + AddPrimitiveInsideGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.bCount(2).next().c(2).d(3).next().c(4).d(5); + encoder.checkEncodingIsComplete(); + + AddPrimitiveInsideGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveInsideGroupV1::sbeBlockLength(), + AddPrimitiveInsideGroupV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddPrimitiveInsideGroupV1::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 2); + EXPECT_EQ(bDecoder.next().c(), 4); +} + +TEST_F(FieldAccessOrderCheckTest, allowsOldDecoderToSkipAddedPrimitiveFieldInsideGroup) +{ + AddPrimitiveInsideGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.bCount(2).next().c(2).d(3).next().c(4).d(5); + encoder.checkEncodingIsComplete(); + + AddPrimitiveInsideGroupV0 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddPrimitiveInsideGroupV1::sbeBlockLength(), + 1, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddPrimitiveInsideGroupV0::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 2); + EXPECT_EQ(bDecoder.next().c(), 4); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedGroupBeforeVarData) +{ + AddGroupBeforeVarDataV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.cCount(1).next().d(2); + encoder.putB("abc"); + encoder.checkEncodingIsComplete(); + + AddGroupBeforeVarDataV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddGroupBeforeVarDataV1::sbeBlockLength(), + AddGroupBeforeVarDataV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddGroupBeforeVarDataV1::C &cDecoder = decoder.c(); + EXPECT_EQ(cDecoder.count(), 1u); + EXPECT_EQ(cDecoder.next().d(), 2); + EXPECT_EQ(decoder.getBAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingGroupBeforeVarDataAsNullValue) +{ + AddGroupBeforeVarDataV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putB("abc"); + encoder.checkEncodingIsComplete(); + + AddGroupBeforeVarDataV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddGroupBeforeVarDataV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddGroupBeforeVarDataV1::C &cDecoder = decoder.c(); + EXPECT_EQ(cDecoder.count(), 0u); + EXPECT_EQ(decoder.getBAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToSkipMissingGroupBeforeVarData) +{ + AddGroupBeforeVarDataV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putB("abc"); + encoder.checkEncodingIsComplete(); + + AddGroupBeforeVarDataV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddGroupBeforeVarDataV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.getBAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsNewDecoderToSkipPresentButAddedGroupBeforeVarData) +{ + AddGroupBeforeVarDataV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.cCount(1).next().d(2); + encoder.putB("abc"); + encoder.checkEncodingIsComplete(); + + AddGroupBeforeVarDataV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddGroupBeforeVarDataV1::sbeBlockLength(), + AddGroupBeforeVarDataV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_THROW( + { + try + { + decoder.b(); + } + catch (const std::exception &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b\" in state: V1_BLOCK") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, allowsOldDecoderToSkipAddedGroupBeforeVarData) +{ + AddGroupBeforeVarDataV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.cCount(1).next().d(2); + encoder.putB("abc"); + encoder.checkEncodingIsComplete(); + + AddGroupBeforeVarDataV0 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddGroupBeforeVarDataV1::sbeBlockLength(), + AddGroupBeforeVarDataV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + + // In reality, we would use a numGroups field in the message header to skip over unknown groups + // rather than the hardcoded knowledge of one extra group below: + + GroupSizeEncoding groupSizeEncodingDecoder; + groupSizeEncodingDecoder.wrap( + m_buffer, + decoder.sbePosition(), + GroupSizeEncoding::sbeSchemaVersion(), + BUFFER_LEN + ); + const std::uint64_t bytesToSkip = GroupSizeEncoding::encodedLength() + + groupSizeEncodingDecoder.blockLength() * groupSizeEncodingDecoder.numInGroup(); + decoder.sbePosition(decoder.sbePosition() + bytesToSkip); + + EXPECT_EQ(decoder.getBAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedEnumFieldBeforeGroup) +{ + AddEnumBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.d(Direction::BUY); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddEnumBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddEnumBeforeGroupV1::sbeBlockLength(), + 1, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.d(), Direction::BUY); + AddEnumBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingEnumFieldBeforeGroupAsNullValue) +{ + AddEnumBeforeGroupV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddEnumBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddEnumBeforeGroupV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.d(), Direction::NULL_VALUE); + AddEnumBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToSkipPresentButAddedEnumFieldBeforeGroup) +{ + AddEnumBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.d(Direction::SELL); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddEnumBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddEnumBeforeGroupV1::sbeBlockLength(), + 1, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddEnumBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsOldDecoderToSkipAddedEnumFieldBeforeGroup) +{ + AddEnumBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.d(Direction::BUY); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddEnumBeforeGroupV0 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddEnumBeforeGroupV1::sbeBlockLength(), + 1, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddEnumBeforeGroupV0::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedCompositeFieldBeforeGroup) +{ + AddCompositeBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + Point &d = encoder.d(); + d.x(-1); + d.y(-2); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddCompositeBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddCompositeBeforeGroupV1::sbeBlockLength(), + 1, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + Point &d2 = decoder.d(); + EXPECT_EQ(d2.x(), -1); + EXPECT_EQ(d2.y(), -2); + AddCompositeBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToSkipPresentButAddedCompositeFieldBeforeGroup) +{ + AddCompositeBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + Point &d = encoder.d(); + d.x(-1); + d.y(-2); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddCompositeBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddCompositeBeforeGroupV1::sbeBlockLength(), + 1, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddCompositeBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsOldDecoderToSkipAddedCompositeFieldBeforeGroup) +{ + AddCompositeBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + Point &d = encoder.d(); + d.x(-1); + d.y(-2); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddCompositeBeforeGroupV0 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddCompositeBeforeGroupV1::sbeBlockLength(), + 1, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddCompositeBeforeGroupV0::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedArrayFieldBeforeGroup) +{ + AddArrayBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putD(1, 2, 3, 4); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddArrayBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddArrayBeforeGroupV1::sbeBlockLength(), + 1, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.d(0), 1); + EXPECT_EQ(decoder.d(1), 2); + EXPECT_EQ(decoder.d(2), 3); + EXPECT_EQ(decoder.d(3), 4); + AddArrayBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingArrayFieldBeforeGroupAsNullValue1) +{ + AddArrayBeforeGroupV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddArrayBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddArrayBeforeGroupV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.d(0), AddArrayBeforeGroupV1::dNullValue()); + EXPECT_EQ(decoder.d(1), AddArrayBeforeGroupV1::dNullValue()); + EXPECT_EQ(decoder.d(2), AddArrayBeforeGroupV1::dNullValue()); + EXPECT_EQ(decoder.d(3), AddArrayBeforeGroupV1::dNullValue()); + AddArrayBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingArrayFieldBeforeGroupAsNullValue2) +{ + AddArrayBeforeGroupV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddArrayBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddArrayBeforeGroupV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + char *d = decoder.d(); + EXPECT_EQ(d, nullptr); + AddArrayBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingArrayFieldBeforeGroupAsNullValue3) +{ + AddArrayBeforeGroupV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddArrayBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddArrayBeforeGroupV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + const AddArrayBeforeGroupV1 &constDecoder = decoder; + const char *d = constDecoder.d(); + EXPECT_EQ(d, nullptr); + AddArrayBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToSkipPresentButAddedArrayFieldBeforeGroup) +{ + AddArrayBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putD(1, 2, 3, 4); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddArrayBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddArrayBeforeGroupV1::sbeBlockLength(), + 1, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddArrayBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsOldDecoderToSkipAddedArrayFieldBeforeGroup) +{ + AddArrayBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putD(1, 2, 3, 4); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddArrayBeforeGroupV0 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddArrayBeforeGroupV1::sbeBlockLength(), + 1, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddArrayBeforeGroupV0::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedBitSetFieldBeforeGroup) +{ + AddBitSetBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1).d().guacamole(true).cheese(true).sourCream(false); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddBitSetBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddBitSetBeforeGroupV1::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + Flags &d = decoder.d(); + EXPECT_EQ(d.guacamole(), true); + EXPECT_EQ(d.cheese(), true); + EXPECT_EQ(d.sourCream(), false); + AddBitSetBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingBitSetFieldBeforeGroupAsNullValue) +{ + AddBitSetBeforeGroupV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddBitSetBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddBitSetBeforeGroupV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.dInActingVersion(), false); + AddBitSetBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToSkipPresentButAddedBitSetFieldBeforeGroup) +{ + AddBitSetBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1).d().guacamole(true).cheese(true).sourCream(false); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddBitSetBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddBitSetBeforeGroupV1::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddBitSetBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsOldDecoderToSkipAddedBitSetFieldBeforeGroup) +{ + AddBitSetBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1).d().guacamole(true).cheese(true).sourCream(false); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + AddBitSetBeforeGroupV0 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddBitSetBeforeGroupV1::sbeBlockLength(), + 1, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddBitSetBeforeGroupV0::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingEnumInsideGroupInSchemaDefinedOrder) +{ + EnumInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(Direction::BUY) + .bCount(1) + .next() + .c(Direction::SELL); + encoder.checkEncodingIsComplete(); + + EnumInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + EnumInsideGroup::sbeBlockLength(), + EnumInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), Direction::BUY); + EnumInsideGroup::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), Direction::SELL); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingEnumInsideGroupBeforeCallingNext) +{ + EnumInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(Direction::BUY); + EnumInsideGroup::B &bEncoder = encoder.bCount(1); + EXPECT_THROW( + { + try + { + bEncoder.c(Direction::SELL); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsDecodingEnumInsideGroupBeforeCallingNext) +{ + EnumInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(Direction::BUY) + .bCount(1) + .next() + .c(Direction::SELL); + encoder.checkEncodingIsComplete(); + + EnumInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + EnumInsideGroup::sbeBlockLength(), + EnumInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), Direction::BUY); + EnumInsideGroup::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_THROW( + { + try + { + b.c(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReEncodingTopLevelEnum) +{ + EnumInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(Direction::BUY) + .bCount(1) + .next() + .c(Direction::SELL); + + encoder.a(Direction::SELL); + encoder.checkEncodingIsComplete(); + + EnumInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + EnumInsideGroup::sbeBlockLength(), + EnumInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), Direction::SELL); + EnumInsideGroup::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), Direction::SELL); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingBitSetInsideGroupInSchemaDefinedOrder) +{ + BitSetInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Flags &a = encoder.a(); + a.cheese(true).guacamole(true).sourCream(false); + BitSetInsideGroup::B &b = encoder.bCount(1) + .next(); + Flags &c = b.c(); + c.cheese(false).guacamole(false).sourCream(true); + encoder.checkEncodingIsComplete(); + + BitSetInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + BitSetInsideGroup::sbeBlockLength(), + BitSetInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + Flags &aFlags = decoder.a(); + EXPECT_EQ(aFlags.guacamole(), true); + EXPECT_EQ(aFlags.cheese(), true); + EXPECT_EQ(aFlags.sourCream(), false); + BitSetInsideGroup::B &bGroup = decoder.b(); + EXPECT_EQ(bGroup.count(), 1u); + Flags &cFlags = bGroup.next().c(); + EXPECT_EQ(cFlags.guacamole(), false); + EXPECT_EQ(cFlags.cheese(), false); + EXPECT_EQ(cFlags.sourCream(), true); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingBitSetInsideGroupBeforeCallingNext) +{ + BitSetInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Flags &a = encoder.a(); + a.cheese(true).guacamole(true).sourCream(false); + BitSetInsideGroup::B &b = encoder.bCount(1); + EXPECT_THROW( + { + try + { + b.c(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsDecodingBitSetInsideGroupBeforeCallingNext) +{ + BitSetInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Flags &a = encoder.a(); + a.cheese(true).guacamole(true).sourCream(false); + BitSetInsideGroup::B &b = encoder.bCount(1) + .next(); + Flags &c = b.c(); + c.cheese(false).guacamole(false).sourCream(true); + encoder.checkEncodingIsComplete(); + + BitSetInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + BitSetInsideGroup::sbeBlockLength(), + BitSetInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + Flags &aFlags = decoder.a(); + EXPECT_EQ(aFlags.guacamole(), true); + EXPECT_EQ(aFlags.cheese(), true); + EXPECT_EQ(aFlags.sourCream(), false); + BitSetInsideGroup::B &bGroup = decoder.b(); + EXPECT_EQ(bGroup.count(), 1u); + EXPECT_THROW( + { + try + { + bGroup.c(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReEncodingTopLevelBitSetViaReWrap) +{ + BitSetInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + Flags &a = encoder.a(); + a.cheese(true).guacamole(true).sourCream(false); + BitSetInsideGroup::B &b = encoder.bCount(1) + .next(); + Flags &c = b.c(); + c.cheese(false).guacamole(false).sourCream(true); + + Flags &aPrime = encoder.a(); + aPrime.sourCream(true); + encoder.checkEncodingIsComplete(); + + BitSetInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + BitSetInsideGroup::sbeBlockLength(), + BitSetInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + Flags &aFlags = decoder.a(); + EXPECT_EQ(aFlags.guacamole(), true); + EXPECT_EQ(aFlags.cheese(), true); + EXPECT_EQ(aFlags.sourCream(), true); + BitSetInsideGroup::B &bGroup = decoder.b(); + EXPECT_EQ(bGroup.count(), 1u); + Flags &cFlags = bGroup.next().c(); + EXPECT_EQ(cFlags.guacamole(), false); + EXPECT_EQ(cFlags.cheese(), false); + EXPECT_EQ(cFlags.sourCream(), true); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingArrayInsideGroupInSchemaDefinedOrder) +{ + ArrayInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA(1, 2, 3, 4); + ArrayInsideGroup::B &b = encoder.bCount(1) + .next(); + b.putC(5, 6, 7, 8); + encoder.checkEncodingIsComplete(); + + ArrayInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + ArrayInsideGroup::sbeBlockLength(), + ArrayInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(0), 1); + EXPECT_EQ(decoder.a(1), 2); + EXPECT_EQ(decoder.a(2), 3); + EXPECT_EQ(decoder.a(3), 4); + ArrayInsideGroup::B &bGroup = decoder.b(); + EXPECT_EQ(bGroup.count(), 1u); + bGroup.next(); + EXPECT_EQ(bGroup.c(0), 5); + EXPECT_EQ(bGroup.c(1), 6); + EXPECT_EQ(bGroup.c(2), 7); + EXPECT_EQ(bGroup.c(3), 8); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingArrayInsideGroupBeforeCallingNext1) +{ + ArrayInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA(1, 2, 3, 4); + ArrayInsideGroup::B &bEncoder = encoder.bCount(1); + EXPECT_THROW( + { + try + { + bEncoder.putC(5, 6, 7, 8); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr("Cannot access field \"b.c\" in state: V0_B_N")); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingArrayInsideGroupBeforeCallingNext2) +{ + ArrayInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA(1, 2, 3, 4); + ArrayInsideGroup::B &bEncoder = encoder.bCount(1); + const char c[4] = {5, 6, 7, 8}; + const char *cPtr = c; + EXPECT_THROW( + { + try + { + bEncoder.putC(cPtr); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr("Cannot access field \"b.c\" in state: V0_B_N")); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsDecodingArrayInsideGroupBeforeCallingNext1) +{ + ArrayInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA(1, 2, 3, 4); + ArrayInsideGroup::B &bEncoder = encoder.bCount(1); + bEncoder.next(); + bEncoder.putC(5, 6, 7, 8); + encoder.checkEncodingIsComplete(); + + ArrayInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + ArrayInsideGroup::sbeBlockLength(), + ArrayInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(0), 1); + EXPECT_EQ(decoder.a(1), 2); + EXPECT_EQ(decoder.a(2), 3); + EXPECT_EQ(decoder.a(3), 4); + ArrayInsideGroup::B &bGroup = decoder.b(); + EXPECT_EQ(bGroup.count(), 1u); + EXPECT_THROW( + { + try + { + bGroup.c(0); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr("Cannot access field \"b.c\" in state: V0_B_N")); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsDecodingArrayInsideGroupBeforeCallingNext2) +{ + ArrayInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA(1, 2, 3, 4); + ArrayInsideGroup::B &bEncoder = encoder.bCount(1); + bEncoder.next(); + bEncoder.putC(5, 6, 7, 8); + encoder.checkEncodingIsComplete(); + + ArrayInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + ArrayInsideGroup::sbeBlockLength(), + ArrayInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(0), 1); + EXPECT_EQ(decoder.a(1), 2); + EXPECT_EQ(decoder.a(2), 3); + EXPECT_EQ(decoder.a(3), 4); + ArrayInsideGroup::B &bGroup = decoder.b(); + EXPECT_EQ(bGroup.count(), 1u); + EXPECT_THROW( + { + try + { + const std::uint64_t charCount = 4; + char c[charCount]; + bGroup.getC(c, charCount); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr("Cannot access field \"b.c\" in state: V0_B_N")); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsDecodingArrayInsideGroupBeforeCallingNext3) +{ + ArrayInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA(1, 2, 3, 4); + ArrayInsideGroup::B &bEncoder = encoder.bCount(1); + bEncoder.next(); + bEncoder.putC(5, 6, 7, 8); + encoder.checkEncodingIsComplete(); + + ArrayInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + ArrayInsideGroup::sbeBlockLength(), + ArrayInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(0), 1); + EXPECT_EQ(decoder.a(1), 2); + EXPECT_EQ(decoder.a(2), 3); + EXPECT_EQ(decoder.a(3), 4); + ArrayInsideGroup::B &bGroup = decoder.b(); + EXPECT_EQ(bGroup.count(), 1u); + EXPECT_THROW( + { + try + { + bGroup.c(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr("Cannot access field \"b.c\" in state: V0_B_N")); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReEncodingTopLevelArray) +{ + ArrayInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA(1, 2, 3, 4); + ArrayInsideGroup::B &bEncoder = encoder.bCount(1); + bEncoder.next(); + bEncoder.putC(5, 6, 7, 8); + + encoder.putA(9, 10, 11, 12); + encoder.checkEncodingIsComplete(); + + ArrayInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + ArrayInsideGroup::sbeBlockLength(), + ArrayInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(0), 9); + EXPECT_EQ(decoder.a(1), 10); + EXPECT_EQ(decoder.a(2), 11); + EXPECT_EQ(decoder.a(3), 12); + ArrayInsideGroup::B &bGroup = decoder.b(); + EXPECT_EQ(bGroup.count(), 1u); + bGroup.next(); + EXPECT_EQ(bGroup.c(0), 5); + EXPECT_EQ(bGroup.c(1), 6); + EXPECT_EQ(bGroup.c(2), 7); + EXPECT_EQ(bGroup.c(3), 8); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingGroupFieldsInSchemaDefinedOrder1) +{ + MultipleGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.bCount(0); + MultipleGroups::D &dEncoder = encoder.dCount(1); + dEncoder.next(); + dEncoder.e(43); + encoder.checkEncodingIsComplete(); + + MultipleGroups decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleGroups::sbeBlockLength(), + MultipleGroups::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + MultipleGroups::B &bGroup = decoder.b(); + EXPECT_EQ(bGroup.count(), 0u); + MultipleGroups::D &dGroup = decoder.d(); + EXPECT_EQ(dGroup.count(), 1u); + dGroup.next(); + EXPECT_EQ(dGroup.e(), 43); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingGroupFieldsInSchemaDefinedOrder2) +{ + MultipleGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(41); + MultipleGroups::B &bEncoder = encoder.bCount(1); + bEncoder.next(); + bEncoder.c(42); + MultipleGroups::D &dEncoder = encoder.dCount(1); + dEncoder.next(); + dEncoder.e(43); + encoder.checkEncodingIsComplete(); + + MultipleGroups decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleGroups::sbeBlockLength(), + MultipleGroups::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 41); + MultipleGroups::B &bGroup = decoder.b(); + EXPECT_EQ(bGroup.count(), 1u); + bGroup.next(); + EXPECT_EQ(bGroup.c(), 42); + MultipleGroups::D &dGroup = decoder.d(); + EXPECT_EQ(dGroup.count(), 1u); + dGroup.next(); + EXPECT_EQ(dGroup.e(), 43); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReEncodingTopLevelPrimitiveFieldsAfterGroups) +{ + MultipleGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(41); + MultipleGroups::B &bEncoder = encoder.bCount(1); + bEncoder.next(); + bEncoder.c(42); + MultipleGroups::D &dEncoder = encoder.dCount(1); + dEncoder.next(); + dEncoder.e(43); + encoder.a(44); + encoder.checkEncodingIsComplete(); + + MultipleGroups decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleGroups::sbeBlockLength(), + MultipleGroups::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 44); + MultipleGroups::B &bGroup = decoder.b(); + EXPECT_EQ(bGroup.count(), 1u); + bGroup.next(); + EXPECT_EQ(bGroup.c(), 42); + MultipleGroups::D &dGroup = decoder.d(); + EXPECT_EQ(dGroup.count(), 1u); + dGroup.next(); + EXPECT_EQ(dGroup.e(), 43); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedEncodingOfGroupField) +{ + MultipleGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(41); + EXPECT_THROW( + { + try + { + encoder.dCount(0); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot encode count of repeating group \"d\" in state: V0_BLOCK") + ); + throw; + } + }, std::logic_error); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReEncodingEarlierGroupFields) +{ + MultipleGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(41); + MultipleGroups::B &bEncoder = encoder.bCount(1); + bEncoder.next(); + bEncoder.c(42); + MultipleGroups::D &dEncoder = encoder.dCount(1); + dEncoder.next(); + dEncoder.e(43); + EXPECT_THROW( + { + try + { + encoder.bCount(1); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot encode count of repeating group \"b\" in state: V0_D_1_BLOCK") + ); + throw; + } + }, std::logic_error); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReEncodingLatestGroupField) +{ + MultipleGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(41); + MultipleGroups::B &bEncoder = encoder.bCount(1); + bEncoder.next(); + bEncoder.c(42); + MultipleGroups::D &dEncoder = encoder.dCount(1); + dEncoder.next(); + dEncoder.e(43); + EXPECT_THROW( + { + try + { + encoder.dCount(1); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot encode count of repeating group \"d\" in state: V0_D_1_BLOCK") + ); + throw; + } + }, std::logic_error); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedDecodingOfGroupField) +{ + MultipleGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(41); + MultipleGroups::B &bEncoder = encoder.bCount(1); + bEncoder.next(); + bEncoder.c(42); + MultipleGroups::D &dEncoder = encoder.dCount(1); + dEncoder.next(); + dEncoder.e(43); + encoder.checkEncodingIsComplete(); + + MultipleGroups decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleGroups::sbeBlockLength(), + MultipleGroups::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 41); + EXPECT_THROW( + { + try + { + decoder.d(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot decode count of repeating group \"d\" in state: V0_BLOCK") + ); + throw; + } + }, std::logic_error); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReDecodingEarlierGroupField) +{ + MultipleGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(41); + MultipleGroups::B &bEncoder = encoder.bCount(1); + bEncoder.next(); + bEncoder.c(42); + MultipleGroups::D &dEncoder = encoder.dCount(1); + dEncoder.next(); + dEncoder.e(43); + encoder.checkEncodingIsComplete(); + + MultipleGroups decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleGroups::sbeBlockLength(), + MultipleGroups::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 41); + MultipleGroups::B &bGroup = decoder.b(); + EXPECT_EQ(bGroup.count(), 1u); + EXPECT_EQ(bGroup.next().c(), 42); + MultipleGroups::D &dGroup = decoder.d(); + EXPECT_EQ(dGroup.count(), 1u); + EXPECT_EQ(dGroup.next().e(), 43); + EXPECT_THROW( + { + try + { + decoder.b(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot decode count of repeating group \"b\" in state: V0_D_1_BLOCK") + ); + throw; + } + }, std::logic_error); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsReDecodingLatestGroupField) +{ + MultipleGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(41); + MultipleGroups::B &bEncoder = encoder.bCount(1); + bEncoder.next(); + bEncoder.c(42); + MultipleGroups::D &dEncoder = encoder.dCount(1); + dEncoder.next(); + dEncoder.e(43); + encoder.checkEncodingIsComplete(); + + MultipleGroups decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleGroups::sbeBlockLength(), + MultipleGroups::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 41); + MultipleGroups::B &bGroup = decoder.b(); + EXPECT_EQ(bGroup.count(), 1u); + EXPECT_EQ(bGroup.next().c(), 42); + MultipleGroups::D &dGroup = decoder.d(); + EXPECT_EQ(dGroup.count(), 1u); + EXPECT_EQ(dGroup.next().e(), 43); + EXPECT_THROW( + { + try + { + decoder.d(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot decode count of repeating group \"d\" in state: V0_D_1_BLOCK") + ); + throw; + } + }, std::logic_error); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedVarData) +{ + AddVarDataV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.checkEncodingIsComplete(); + + AddVarDataV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddVarDataV1::sbeBlockLength(), + AddVarDataV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.getBAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingAddedVarDataAsNullValue1) +{ + AddVarDataV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.checkEncodingIsComplete(); + + AddVarDataV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddVarDataV1::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.b(), nullptr); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingAddedVarDataAsNullValue2) +{ + AddVarDataV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.checkEncodingIsComplete(); + + AddVarDataV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddVarDataV1::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.getBAsString(), ""); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingAddedVarDataAsNullValue3) +{ + AddVarDataV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.checkEncodingIsComplete(); + + AddVarDataV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddVarDataV1::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.getBAsJsonEscapedString(), ""); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingAddedVarDataAsNullValue4) +{ + AddVarDataV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.checkEncodingIsComplete(); + + AddVarDataV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddVarDataV1::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 42); + char b[16]; + EXPECT_EQ(decoder.getB(b, 16), 0u); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingAsciiInsideGroupInSchemaDefinedOrder1) +{ + AsciiInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA("GBPUSD"); + AsciiInsideGroup::B &bGroup = encoder.bCount(1); + bGroup.next().putC("EURUSD"); + encoder.checkEncodingIsComplete(); + + AsciiInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AsciiInsideGroup::sbeBlockLength(), + AsciiInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.getAAsString(), "GBPUSD"); + AsciiInsideGroup::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().getCAsString(), "EURUSD"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingAsciiInsideGroupInSchemaDefinedOrder2) +{ + AsciiInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + std::string a("GBPUSD"); + encoder.putA(a); + AsciiInsideGroup::B &bGroup = encoder.bCount(1); + bGroup.next() + .c(0, 'E') + .c(1, 'U') + .c(2, 'R') + .c(3, 'U') + .c(4, 'S') + .c(5, 'D'); + encoder.checkEncodingIsComplete(); + + AsciiInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AsciiInsideGroup::sbeBlockLength(), + AsciiInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + char aOut[6]; + decoder.getA(aOut, 6); + EXPECT_STREQ(aOut, "GBPUSD"); + AsciiInsideGroup::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(0), 'E'); + EXPECT_EQ(b.c(1), 'U'); + EXPECT_EQ(b.c(2), 'R'); + EXPECT_EQ(b.c(3), 'U'); + EXPECT_EQ(b.c(4), 'S'); + EXPECT_EQ(b.c(5), 'D'); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingAsciiInsideGroupBeforeCallingNext1) +{ + AsciiInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA("GBPUSD"); + AsciiInsideGroup::B &bGroup = encoder.bCount(1); + EXPECT_THROW( + { + try + { + bGroup.putC("EURUSD"); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingAsciiInsideGroupBeforeCallingNext2) +{ + AsciiInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA("GBPUSD"); + AsciiInsideGroup::B &bGroup = encoder.bCount(1); + EXPECT_THROW( + { + try + { + const std::string c("EURUSD"); + bGroup.putC(c); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingAsciiInsideGroupBeforeCallingNext3) +{ + AsciiInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA("GBPUSD"); + AsciiInsideGroup::B &bGroup = encoder.bCount(1); + EXPECT_THROW( + { + try + { + bGroup.c(0, 'E') + .c(1, 'U') + .c(2, 'R') + .c(3, 'U') + .c(4, 'S') + .c(5, 'D'); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsDecodingAsciiInsideGroupBeforeCallingNext1) +{ + AsciiInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA("GBPUSD"); + AsciiInsideGroup::B &bGroup = encoder.bCount(1); + bGroup.next().putC("EURUSD"); + encoder.checkEncodingIsComplete(); + + AsciiInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AsciiInsideGroup::sbeBlockLength(), + AsciiInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.getAAsString(), "GBPUSD"); + AsciiInsideGroup::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_THROW( + { + try + { + b.getCAsString(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsDecodingAsciiInsideGroupBeforeCallingNext2) +{ + AsciiInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA("GBPUSD"); + AsciiInsideGroup::B &bGroup = encoder.bCount(1); + bGroup.next().putC("EURUSD"); + encoder.checkEncodingIsComplete(); + + AsciiInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AsciiInsideGroup::sbeBlockLength(), + AsciiInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.getAAsString(), "GBPUSD"); + AsciiInsideGroup::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_THROW( + { + try + { + b.c(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsDecodingAsciiInsideGroupBeforeCallingNext3) +{ + AsciiInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA("GBPUSD"); + AsciiInsideGroup::B &bGroup = encoder.bCount(1); + bGroup.next().putC("EURUSD"); + encoder.checkEncodingIsComplete(); + + AsciiInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AsciiInsideGroup::sbeBlockLength(), + AsciiInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.getAAsString(), "GBPUSD"); + AsciiInsideGroup::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_THROW( + { + try + { + char c[6]; + b.getC(c, 6); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsDecodingAsciiInsideGroupBeforeCallingNext4) +{ + AsciiInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA("GBPUSD"); + AsciiInsideGroup::B &bGroup = encoder.bCount(1); + bGroup.next().putC("EURUSD"); + encoder.checkEncodingIsComplete(); + + AsciiInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AsciiInsideGroup::sbeBlockLength(), + AsciiInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.getAAsString(), "GBPUSD"); + AsciiInsideGroup::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_THROW( + { + try + { + b.c(0); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsDecodingAsciiInsideGroupBeforeCallingNext5) +{ + AsciiInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA("GBPUSD"); + AsciiInsideGroup::B &bGroup = encoder.bCount(1); + bGroup.next().putC("EURUSD"); + encoder.checkEncodingIsComplete(); + + AsciiInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AsciiInsideGroup::sbeBlockLength(), + AsciiInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.getAAsString(), "GBPUSD"); + AsciiInsideGroup::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_THROW( + { + try + { + b.getCAsJsonEscapedString(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Cannot access field \"b.c\" in state: V0_B_N") + ); + throw; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, allowsReEncodingTopLevelAscii) +{ + AsciiInsideGroup encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA("GBPUSD"); + AsciiInsideGroup::B &bGroup = encoder.bCount(1); + bGroup.next().putC("EURUSD"); + + encoder.putA("CADUSD"); + encoder.checkEncodingIsComplete(); + + AsciiInsideGroup decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AsciiInsideGroup::sbeBlockLength(), + AsciiInsideGroup::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.getAAsString(), "CADUSD"); + AsciiInsideGroup::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + b.next(); + EXPECT_EQ(b.getCAsString(), "EURUSD"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedAsciiFieldBeforeGroup1) +{ + AddAsciiBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putD("EURUSD"); + AddAsciiBeforeGroupV1::B &bGroup = encoder.bCount(1); + bGroup.next().c(2); + encoder.checkEncodingIsComplete(); + + AddAsciiBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddAsciiBeforeGroupV1::sbeBlockLength(), + AddAsciiBeforeGroupV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + EXPECT_EQ(decoder.getDAsString(), "EURUSD"); + AddAsciiBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedAsciiFieldBeforeGroup2) +{ + AddAsciiBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putD("EURUSD"); + AddAsciiBeforeGroupV1::B &bGroup = encoder.bCount(1); + bGroup.next().c(2); + encoder.checkEncodingIsComplete(); + + AddAsciiBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddAsciiBeforeGroupV1::sbeBlockLength(), + AddAsciiBeforeGroupV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + const char *d = decoder.d(); + const std::string dAsString(d, 6); + ASSERT_EQ(dAsString, "EURUSD"); + AddAsciiBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedAsciiFieldBeforeGroup3) +{ + AddAsciiBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putD("EURUSD"); + AddAsciiBeforeGroupV1::B &bGroup = encoder.bCount(1); + bGroup.next().c(2); + encoder.checkEncodingIsComplete(); + + AddAsciiBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddAsciiBeforeGroupV1::sbeBlockLength(), + AddAsciiBeforeGroupV1::sbeSchemaVersion(), + BUFFER_LEN + ); + const AddAsciiBeforeGroupV1 &constDecoder = decoder; + EXPECT_EQ(constDecoder.a(), 1); + const char *d = constDecoder.d(); + const std::string dAsString(d, 6); + ASSERT_EQ(dAsString, "EURUSD"); + AddAsciiBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedAsciiFieldBeforeGroup4) +{ + AddAsciiBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putD("EURUSD"); + AddAsciiBeforeGroupV1::B &bGroup = encoder.bCount(1); + bGroup.next().c(2); + encoder.checkEncodingIsComplete(); + + AddAsciiBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddAsciiBeforeGroupV1::sbeBlockLength(), + AddAsciiBeforeGroupV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + char d[6]; + decoder.getD(d, 6); + const std::string dAsString(d, 6); + ASSERT_EQ(dAsString, "EURUSD"); + AddAsciiBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedAsciiFieldBeforeGroup5) +{ + AddAsciiBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putD("EURUSD"); + AddAsciiBeforeGroupV1::B &bGroup = encoder.bCount(1); + bGroup.next().c(2); + encoder.checkEncodingIsComplete(); + + AddAsciiBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddAsciiBeforeGroupV1::sbeBlockLength(), + AddAsciiBeforeGroupV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + ASSERT_EQ(decoder.d(0), 'E'); + ASSERT_EQ(decoder.d(1), 'U'); + ASSERT_EQ(decoder.d(2), 'R'); + ASSERT_EQ(decoder.d(3), 'U'); + ASSERT_EQ(decoder.d(4), 'S'); + ASSERT_EQ(decoder.d(5), 'D'); + AddAsciiBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeAddedAsciiFieldBeforeGroup6) +{ + AddAsciiBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putD("EURUSD"); + AddAsciiBeforeGroupV1::B &bGroup = encoder.bCount(1); + bGroup.next().c(2); + encoder.checkEncodingIsComplete(); + + AddAsciiBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddAsciiBeforeGroupV1::sbeBlockLength(), + AddAsciiBeforeGroupV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + ASSERT_EQ(decoder.dLength(), 6u); + AddAsciiBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingAsciiFieldBeforeGroupAsNullValue1) +{ + AddAsciiBeforeGroupV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + AddAsciiBeforeGroupV0::B &bGroup = encoder.bCount(1); + bGroup.next().c(2); + encoder.checkEncodingIsComplete(); + + AddAsciiBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddAsciiBeforeGroupV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + ASSERT_EQ(decoder.d(0), AddAsciiBeforeGroupV1::dNullValue()); + ASSERT_EQ(decoder.d(1), AddAsciiBeforeGroupV1::dNullValue()); + ASSERT_EQ(decoder.d(2), AddAsciiBeforeGroupV1::dNullValue()); + ASSERT_EQ(decoder.d(3), AddAsciiBeforeGroupV1::dNullValue()); + ASSERT_EQ(decoder.d(4), AddAsciiBeforeGroupV1::dNullValue()); + ASSERT_EQ(decoder.d(5), AddAsciiBeforeGroupV1::dNullValue()); + AddAsciiBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingAsciiFieldBeforeGroupAsNullValue2) +{ + AddAsciiBeforeGroupV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + AddAsciiBeforeGroupV0::B &bGroup = encoder.bCount(1); + bGroup.next().c(2); + encoder.checkEncodingIsComplete(); + + AddAsciiBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddAsciiBeforeGroupV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + char d[6]; + ASSERT_EQ(decoder.getD(d, 6), 0u); + AddAsciiBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToDecodeMissingAsciiFieldBeforeGroupAsNullValue3) +{ + AddAsciiBeforeGroupV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + AddAsciiBeforeGroupV0::B &bGroup = encoder.bCount(1); + bGroup.next().c(2); + encoder.checkEncodingIsComplete(); + + AddAsciiBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddAsciiBeforeGroupV0::sbeBlockLength(), + 0, + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + ASSERT_EQ(decoder.getDAsString(), ""); + AddAsciiBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsNewDecoderToSkipPresentButAddedAsciiFieldBeforeGroup) +{ + AddAsciiBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putD("EURUSD"); + AddAsciiBeforeGroupV1::B &bGroup = encoder.bCount(1); + bGroup.next().c(2); + encoder.checkEncodingIsComplete(); + + AddAsciiBeforeGroupV1 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddAsciiBeforeGroupV1::sbeBlockLength(), + AddAsciiBeforeGroupV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddAsciiBeforeGroupV1::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsOldDecoderToSkipAddedAsciiFieldBeforeGroup) +{ + AddAsciiBeforeGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + encoder.putD("EURUSD"); + AddAsciiBeforeGroupV1::B &bGroup = encoder.bCount(1); + bGroup.next().c(2); + encoder.checkEncodingIsComplete(); + + AddAsciiBeforeGroupV0 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddAsciiBeforeGroupV1::sbeBlockLength(), + AddAsciiBeforeGroupV1::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + AddAsciiBeforeGroupV0::B &b = decoder.b(); + EXPECT_EQ(b.count(), 1u); + EXPECT_EQ(b.next().c(), 2); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodeAndDecodeOfMessagesWithNoBlock) +{ + NoBlock encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.putA("abc"); + encoder.checkEncodingIsComplete(); + + NoBlock decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + NoBlock::sbeBlockLength(), + NoBlock::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.getAAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodeAndDecodeOfGroupsWithNoBlock) +{ + GroupWithNoBlock encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + GroupWithNoBlock::A &aGroup = encoder.aCount(1); + aGroup.next().putB("abc"); + encoder.checkEncodingIsComplete(); + + GroupWithNoBlock decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + GroupWithNoBlock::sbeBlockLength(), + GroupWithNoBlock::sbeSchemaVersion(), + BUFFER_LEN + ); + GroupWithNoBlock::A &a = decoder.a(); + EXPECT_EQ(a.count(), 1u); + EXPECT_EQ(a.next().getBAsString(), "abc"); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingElementOfEmptyGroup1) +{ + MultipleGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + MultipleGroups::B &bGroup = encoder.bCount(0); + MultipleGroups::D &dGroup = encoder.dCount(1); + dGroup.next().e(43); + + EXPECT_THROW( + { + try + { + bGroup.c(44); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr("Cannot access field \"b.c\" in state: V0_D_1_BLOCK")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingElementOfEmptyGroup2) +{ + NestedGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + NestedGroups::B &bGroup = encoder.bCount(1); + bGroup.next(); + bGroup.c(43); + NestedGroups::B::D &dGroup = bGroup.dCount(0); + bGroup.fCount(0); + encoder.hCount(0); + + EXPECT_THROW( + { + try + { + dGroup.e(44); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr("Cannot access field \"b.d.e\" in state: V0_H_DONE")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingElementOfEmptyGroup3) +{ + NestedGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + NestedGroups::B &bGroup = encoder.bCount(1); + bGroup.next(); + bGroup.c(43); + NestedGroups::B::D &dGroup = bGroup.dCount(0); + bGroup.fCount(0); + + EXPECT_THROW( + { + try + { + dGroup.e(44); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr("Cannot access field \"b.d.e\" in state: V0_B_1_F_DONE")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingElementOfEmptyGroup4) +{ + AddPrimitiveInsideGroupV1 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + AddPrimitiveInsideGroupV1::B &bGroup = encoder.bCount(0); + + EXPECT_THROW( + { + try + { + bGroup.c(43); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr("Cannot access field \"b.c\" in state: V1_B_DONE")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsEncodingElementOfEmptyGroup5) +{ + GroupAndVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + GroupAndVarLength::B &bGroup = encoder.bCount(0); + encoder.putD("abc"); + + EXPECT_THROW( + { + try + { + bGroup.c(43); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr("Cannot access field \"b.c\" in state: V0_D_DONE")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingNestedGroupWithVarDataInSchemaDefinedOrder) +{ + NestedGroupWithVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + NestedGroupWithVarLength::B &bGroup = encoder.bCount(3); + bGroup.next().c(2).dCount(0); + bGroup.next().c(3).dCount(1).next().e(4).putF("abc"); + bGroup.next().c(5).dCount(2).next().e(6).putF("def").next().e(7).putF("ghi"); + encoder.checkEncodingIsComplete(); + + NestedGroupWithVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + NestedGroupWithVarLength::sbeBlockLength(), + NestedGroupWithVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + NestedGroupWithVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 3u); + EXPECT_EQ(bDecoder.next().c(), 2); + NestedGroupWithVarLength::B::D &dDecoder1 = bDecoder.d(); + EXPECT_EQ(dDecoder1.count(), 0u); + EXPECT_EQ(bDecoder.next().c(), 3); + NestedGroupWithVarLength::B::D &dDecoder2 = bDecoder.d(); + EXPECT_EQ(dDecoder2.count(), 1u); + EXPECT_EQ(dDecoder2.next().e(), 4); + EXPECT_EQ(dDecoder2.getFAsString(), "abc"); + EXPECT_EQ(bDecoder.next().c(), 5); + NestedGroupWithVarLength::B::D &dDecoder3 = bDecoder.d(); + EXPECT_EQ(dDecoder3.count(), 2u); + EXPECT_EQ(dDecoder3.next().e(), 6); + EXPECT_EQ(dDecoder3.getFAsString(), "def"); + EXPECT_EQ(dDecoder3.next().e(), 7); + EXPECT_EQ(dDecoder3.getFAsString(), "ghi"); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedEncodingOfVarLengthFieldInNestedGroupToNextInnerElement1) +{ + NestedGroupWithVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + NestedGroupWithVarLength::B &bGroup = encoder.bCount(1); + NestedGroupWithVarLength::B::D &dGroup = bGroup.next().c(5).dCount(2); + dGroup.next().e(7); + + EXPECT_THROW( + { + try + { + dGroup.next(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), + testing::HasSubstr( + "Cannot access next element in repeating group \"b.d\" in state: V0_B_1_D_N_BLOCK")); + EXPECT_THAT(e.what(), + testing::HasSubstr( + "Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedEncodingOfVarLengthFieldInNestedGroupToNextInnerElement2) +{ + NestedGroupWithVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + NestedGroupWithVarLength::B &bGroup = encoder.bCount(2); + NestedGroupWithVarLength::B::D &dGroup = bGroup.next().c(5).dCount(2); + dGroup.next().e(7); + + EXPECT_THROW( + { + try + { + dGroup.next(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), + testing::HasSubstr( + "Cannot access next element in repeating group \"b.d\" in state: V0_B_N_D_N_BLOCK")); + EXPECT_THAT(e.what(), + testing::HasSubstr( + "Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedDecodingOfVarLengthFieldInNestedGroupToNextInnerElement1) +{ + NestedGroupWithVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + NestedGroupWithVarLength::B &bGroup = encoder.bCount(1); + NestedGroupWithVarLength::B::D &dGroup = bGroup.next().c(2).dCount(2); + dGroup.next().e(3).putF("abc"); + dGroup.next().e(4).putF("def"); + encoder.checkEncodingIsComplete(); + + NestedGroupWithVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + NestedGroupWithVarLength::sbeBlockLength(), + NestedGroupWithVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + NestedGroupWithVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 1u); + EXPECT_EQ(bDecoder.next().c(), 2); + NestedGroupWithVarLength::B::D &dDecoder = bDecoder.d(); + EXPECT_EQ(dDecoder.count(), 2u); + EXPECT_EQ(dDecoder.next().e(), 3); + + EXPECT_THROW( + { + try + { + dDecoder.next(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), + testing::HasSubstr( + "Cannot access next element in repeating group \"b.d\" in state: V0_B_1_D_N_BLOCK.")); + EXPECT_THAT(e.what(), + testing::HasSubstr( + "Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedDecodingOfVarLengthFieldInNestedGroupToNextInnerElement2) +{ + NestedGroupWithVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + NestedGroupWithVarLength::B &bGroup = encoder.bCount(2); + NestedGroupWithVarLength::B::D &dGroup = bGroup.next().c(2).dCount(2); + dGroup.next().e(3).putF("abc"); + dGroup.next().e(4).putF("def"); + bGroup.next().c(5).dCount(0); + encoder.checkEncodingIsComplete(); + + NestedGroupWithVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + NestedGroupWithVarLength::sbeBlockLength(), + NestedGroupWithVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + NestedGroupWithVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 2); + NestedGroupWithVarLength::B::D &dDecoder = bDecoder.d(); + EXPECT_EQ(dDecoder.count(), 2u); + EXPECT_EQ(dDecoder.next().e(), 3); + + EXPECT_THROW( + { + try + { + dDecoder.next(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), + testing::HasSubstr( + "Cannot access next element in repeating group \"b.d\" in state: V0_B_N_D_N_BLOCK.")); + EXPECT_THAT(e.what(), + testing::HasSubstr( + "Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedDecodingOfVarLengthFieldInNestedGroupToNextOuterElement1) +{ + NestedGroupWithVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + NestedGroupWithVarLength::B &bGroup = encoder.bCount(2); + NestedGroupWithVarLength::B::D &dGroup = bGroup.next().c(2).dCount(2); + dGroup.next().e(3).putF("abc"); + dGroup.next().e(4).putF("def"); + bGroup.next().c(5).dCount(0); + encoder.checkEncodingIsComplete(); + + NestedGroupWithVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + NestedGroupWithVarLength::sbeBlockLength(), + NestedGroupWithVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + NestedGroupWithVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 2); + NestedGroupWithVarLength::B::D &dDecoder = bDecoder.d(); + EXPECT_EQ(dDecoder.count(), 2u); + EXPECT_EQ(dDecoder.next().e(), 3); + + EXPECT_THROW( + { + try + { + bDecoder.next(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), + testing::HasSubstr( + "Cannot access next element in repeating group \"b\" in state: V0_B_N_D_N_BLOCK.")); + EXPECT_THAT(e.what(), + testing::HasSubstr( + "Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsMissedDecodingOfVarLengthFieldInNestedGroupToNextOuterElement2) +{ + NestedGroupWithVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + NestedGroupWithVarLength::B &bGroup = encoder.bCount(2); + NestedGroupWithVarLength::B::D &dGroup = bGroup.next().c(2).dCount(1); + dGroup.next().e(3).putF("abc"); + bGroup.next().c(5).dCount(0); + encoder.checkEncodingIsComplete(); + + NestedGroupWithVarLength decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + NestedGroupWithVarLength::sbeBlockLength(), + NestedGroupWithVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + EXPECT_EQ(decoder.a(), 1); + NestedGroupWithVarLength::B &bDecoder = decoder.b(); + EXPECT_EQ(bDecoder.count(), 2u); + EXPECT_EQ(bDecoder.next().c(), 2); + NestedGroupWithVarLength::B::D &dDecoder = bDecoder.d(); + EXPECT_EQ(dDecoder.count(), 1u); + EXPECT_EQ(dDecoder.next().e(), 3); + + EXPECT_THROW( + { + try + { + bDecoder.next(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), + testing::HasSubstr( + "Cannot access next element in repeating group \"b\" in state: V0_B_N_D_1_BLOCK.")); + EXPECT_THAT(e.what(), + testing::HasSubstr( + "Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsIncompleteMessagesDueToMissingVarLengthField1) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1).putB("abc"); + + EXPECT_THROW( + { + try + { + encoder.checkEncodingIsComplete(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), + testing::HasSubstr( + std::string("Not fully encoded, current state: V0_B_DONE, ") + + "allowed transitions: \"cLength()\", \"c(?)\"")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsIncompleteMessagesDueToMissingVarLengthField2) +{ + NoBlock encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + + EXPECT_THROW( + { + try + { + encoder.checkEncodingIsComplete(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), + testing::HasSubstr( + std::string("Not fully encoded, current state: V0_BLOCK, ") + + "allowed transitions: \"aLength()\", \"a(?)\"")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsIncompleteMessagesDueToMissingTopLevelGroup1) +{ + MultipleGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1).bCount(0); + + EXPECT_THROW( + { + try + { + encoder.checkEncodingIsComplete(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr( + "Not fully encoded, current state: V0_B_DONE, allowed transitions:" + " \"b.resetCountToIndex()\", \"dCount(0)\", \"dCount(>0)\"")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsIncompleteMessagesDueToMissingTopLevelGroup2) +{ + MultipleGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1).bCount(1).next().c(2); + + EXPECT_THROW( + { + try + { + encoder.checkEncodingIsComplete(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr( + "Not fully encoded, current state: V0_B_1_BLOCK, allowed transitions: " + "\"b.c(?)\", \"b.resetCountToIndex()\", \"dCount(0)\", \"dCount(>0)\"")); + throw e; + } + }, + std::logic_error + ); +} + +TEST_F(FieldAccessOrderCheckTest, disallowsIncompleteMessagesDueToMissingTopLevelGroup3) +{ + MultipleGroups encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1); + + EXPECT_THROW( + { + try + { + encoder.checkEncodingIsComplete(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr( + "Not fully encoded, current state: V0_BLOCK, allowed transitions: " + "\"a(?)\", \"bCount(0)\", \"bCount(>0)\"")); + throw e; + } + }, + std::logic_error + ); +} + +class DisallowsIncompleteMessagesPart1Test : public FieldAccessOrderCheckTest, + public testing::WithParamInterface> +{ +}; + +TEST_P(DisallowsIncompleteMessagesPart1Test, disallowsIncompleteMessagesDueToMissingNestedGroup1) +{ + const auto bCount = std::get<0>(GetParam()); + const auto expectedState = std::get<1>(GetParam()); + + NestedGroupWithVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1).bCount(bCount).next().c(2); + + EXPECT_THROW( + { + try + { + encoder.checkEncodingIsComplete(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr( + "Not fully encoded, current state: " + expectedState)); + throw e; + } + }, + std::logic_error + ); +} + +INSTANTIATE_TEST_SUITE_P( + FieldAccessOrderCheckTest, + DisallowsIncompleteMessagesPart1Test, + testing::Values( + std::make_tuple(1, "V0_B_1_BLOCK"), + std::make_tuple(2, "V0_B_N_BLOCK") + ) +); + +class DisallowsIncompleteMessagesPart2Test : public FieldAccessOrderCheckTest, + public testing::WithParamInterface> +{ +}; + +TEST_P(DisallowsIncompleteMessagesPart2Test, disallowsIncompleteMessagesDueToMissingNestedGroup2) +{ + const auto bCount = std::get<0>(GetParam()); + const auto dCount = std::get<1>(GetParam()); + const auto expectedState = std::get<2>(GetParam()); + + NestedGroupWithVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1).bCount(bCount).next().c(2).dCount(dCount); + + EXPECT_THROW( + { + try + { + encoder.checkEncodingIsComplete(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr( + "Not fully encoded, current state: " + expectedState)); + throw e; + } + }, + std::logic_error + ); +} + +INSTANTIATE_TEST_SUITE_P( + FieldAccessOrderCheckTest, + DisallowsIncompleteMessagesPart2Test, + testing::Values( + std::make_tuple(1, 1, "V0_B_1_D_N"), + std::make_tuple(1, 2, "V0_B_1_D_N"), + std::make_tuple(2, 0, "V0_B_N_D_DONE"), + std::make_tuple(2, 1, "V0_B_N_D_N"), + std::make_tuple(2, 2, "V0_B_N_D_N") + ) +); + +class DisallowsIncompleteMessagesPart3Test : public FieldAccessOrderCheckTest, + public testing::WithParamInterface> +{ +}; + +TEST_P(DisallowsIncompleteMessagesPart3Test, disallowsIncompleteMessagesDueToMissingVarDataInNestedGroup) +{ + const auto bCount = std::get<0>(GetParam()); + const auto dCount = std::get<1>(GetParam()); + const auto expectedState = std::get<2>(GetParam()); + + NestedGroupWithVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(1).bCount(bCount).next().c(2).dCount(dCount).next().e(10); + + EXPECT_THROW( + { + try + { + encoder.checkEncodingIsComplete(); + } + catch (const std::logic_error &e) + { + EXPECT_THAT(e.what(), testing::HasSubstr( + "Not fully encoded, current state: " + expectedState)); + throw e; + } + }, + std::logic_error + ); +} + +INSTANTIATE_TEST_SUITE_P( + FieldAccessOrderCheckTest, + DisallowsIncompleteMessagesPart3Test, + testing::Values( + std::make_tuple(1, 1, "V0_B_1_D_1_BLOCK"), + std::make_tuple(1, 2, "V0_B_1_D_N_BLOCK"), + std::make_tuple(2, 1, "V0_B_N_D_1_BLOCK"), + std::make_tuple(2, 2, "V0_B_N_D_N_BLOCK") + ) +); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java new file mode 100644 index 0000000000..97d51b199c --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java @@ -0,0 +1,3425 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe; + +import order.check.*; +import org.agrona.ExpandableArrayBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.concurrent.UnsafeBuffer; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import java.nio.charset.StandardCharsets; +import java.util.Random; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assumptions.assumeFalse; + +public class FieldAccessOrderCheckTest +{ + private static final Class INCORRECT_ORDER_EXCEPTION_CLASS = IllegalStateException.class; + private static final int OFFSET = 0; + private final MutableDirectBuffer buffer = new ExpandableArrayBuffer(); + private final MessageHeaderEncoder messageHeaderEncoder = new MessageHeaderEncoder(); + private final MessageHeaderDecoder messageHeaderDecoder = new MessageHeaderDecoder(); + + @BeforeAll + static void assumeDebugMode() + { + final boolean productionMode = Boolean.getBoolean("agrona.disable.bounds.checks"); + assumeFalse(productionMode); + } + + @BeforeEach + void setUp() + { + new Random().nextBytes(buffer.byteArray()); + } + + @Test + void allowsEncodingAndDecodingVariableLengthFieldsInSchemaDefinedOrder() + { + final MultipleVarLengthEncoder encoder = new MultipleVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.b("abc"); + encoder.c("def"); + encoder.checkEncodingIsComplete(); + + final MultipleVarLengthDecoder decoder = new MultipleVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.b(), equalTo("abc")); + assertThat(decoder.c(), equalTo("def")); + assertThat(decoder.toString(), containsString("a=42|b='abc'|c='def'")); + } + + @Test + void allowsDecodingVariableLengthFieldsAfterRewind() + { + final MultipleVarLengthEncoder encoder = new MultipleVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.b("abc"); + encoder.c("def"); + encoder.checkEncodingIsComplete(); + + final MultipleVarLengthDecoder decoder = new MultipleVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.b(), equalTo("abc")); + assertThat(decoder.c(), equalTo("def")); + assertThat(decoder.toString(), containsString("a=42|b='abc'|c='def'")); + + decoder.sbeRewind(); + + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.b(), equalTo("abc")); + assertThat(decoder.c(), equalTo("def")); + assertThat(decoder.toString(), containsString("a=42|b='abc'|c='def'")); + } + + @Test + void allowsDecodingToSkipVariableLengthFields() + { + final MultipleVarLengthEncoder encoder = new MultipleVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.b("abc"); + encoder.c("def"); + encoder.checkEncodingIsComplete(); + + final MultipleVarLengthDecoder decoder = new MultipleVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.skipB(), equalTo(3)); + assertThat(decoder.c(), equalTo("def")); + assertThat(decoder.toString(), containsString("a=42|b='abc'|c='def'")); + } + + @Test + void allowsReEncodingTopLevelPrimitiveFields() + { + final MultipleVarLengthEncoder encoder = new MultipleVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.b("abc"); + encoder.c("def"); + encoder.a(43); + encoder.checkEncodingIsComplete(); + + final MultipleVarLengthDecoder decoder = new MultipleVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(43)); + assertThat(decoder.b(), equalTo("abc")); + assertThat(decoder.c(), equalTo("def")); + } + + @Test + void disallowsSkippingEncodingOfVariableLengthField1() + { + final MultipleVarLengthEncoder encoder = new MultipleVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.c("def")); + assertThat(exception.getMessage(), containsString("Cannot access field \"c\" in state: V0_BLOCK")); + } + + @Test + void disallowsSkippingEncodingOfVariableLengthField2() + { + final MultipleVarLengthEncoder encoder = new MultipleVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final CharSequence def = new StringBuilder("def"); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.c(def)); + assertThat(exception.getMessage(), containsString("Cannot access field \"c\" in state: V0_BLOCK")); + } + + @Test + void disallowsSkippingEncodingOfVariableLengthField3() + { + final MultipleVarLengthEncoder encoder = new MultipleVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final byte[] value = "def".getBytes(StandardCharsets.US_ASCII); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.putC(value, 0, value.length)); + assertThat(exception.getMessage(), containsString("Cannot access field \"c\" in state: V0_BLOCK")); + } + + @Test + void disallowsSkippingEncodingOfVariableLengthField4() + { + final MultipleVarLengthEncoder encoder = new MultipleVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final byte[] value = "def".getBytes(StandardCharsets.US_ASCII); + final UnsafeBuffer buffer = new UnsafeBuffer(value); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.putC(buffer, 0, buffer.capacity())); + assertThat(exception.getMessage(), containsString("Cannot access field \"c\" in state: V0_BLOCK")); + } + + @Test + void disallowsReEncodingEarlierVariableLengthFields() + { + final MultipleVarLengthEncoder encoder = new MultipleVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.b("abc"); + encoder.c("def"); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.b("ghi")); + assertThat(exception.getMessage(), containsString("Cannot access field \"b\" in state: V0_C_DONE")); + } + + @Test + void disallowsReEncodingLatestVariableLengthField() + { + final MultipleVarLengthEncoder encoder = new MultipleVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.b("abc"); + encoder.c("def"); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.c("ghi")); + assertThat(exception.getMessage(), containsString("Cannot access field \"c\" in state: V0_C_DONE")); + } + + @Test + void disallowsSkippingDecodingOfVariableLengthField1() + { + final MultipleVarLengthDecoder decoder = decodeUntilVarLengthFields(); + + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, decoder::c); + assertThat(exception.getMessage(), containsString("Cannot access field \"c\" in state: V0_BLOCK")); + } + + @Test + void disallowsSkippingDecodingOfVariableLengthField2() + { + final MultipleVarLengthDecoder decoder = decodeUntilVarLengthFields(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> decoder.wrapC(new UnsafeBuffer())); + assertThat(exception.getMessage(), containsString("Cannot access field \"c\" in state: V0_BLOCK")); + } + + @Test + void disallowsSkippingDecodingOfVariableLengthField3() + { + final MultipleVarLengthDecoder decoder = decodeUntilVarLengthFields(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> decoder.getC(new StringBuilder())); + assertThat(exception.getMessage(), containsString("Cannot access field \"c\" in state: V0_BLOCK")); + } + + @Test + void disallowsSkippingDecodingOfVariableLengthField4() + { + final MultipleVarLengthDecoder decoder = decodeUntilVarLengthFields(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> decoder.getC(new byte[3], 0, 3)); + assertThat(exception.getMessage(), containsString("Cannot access field \"c\" in state: V0_BLOCK")); + } + + @Test + void disallowsSkippingDecodingOfVariableLengthField5() + { + final MultipleVarLengthDecoder decoder = decodeUntilVarLengthFields(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> decoder.getC(new ExpandableArrayBuffer(), 0, 3)); + assertThat(exception.getMessage(), containsString("Cannot access field \"c\" in state: V0_BLOCK")); + } + + @Test + void allowsRepeatedDecodingOfVariableLengthDataLength() + { + final MultipleVarLengthDecoder decoder = decodeUntilVarLengthFields(); + assertThat(decoder.bLength(), equalTo(3)); + assertThat(decoder.bLength(), equalTo(3)); + assertThat(decoder.bLength(), equalTo(3)); + assertThat(decoder.b(), equalTo("abc")); + assertThat(decoder.cLength(), equalTo(3)); + assertThat(decoder.cLength(), equalTo(3)); + assertThat(decoder.cLength(), equalTo(3)); + } + + @Test + void disallowsReDecodingEarlierVariableLengthField() + { + final MultipleVarLengthDecoder decoder = decodeUntilVarLengthFields(); + assertThat(decoder.b(), equalTo("abc")); + assertThat(decoder.c(), equalTo("def")); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, decoder::b); + assertThat(exception.getMessage(), containsString("Cannot access field \"b\" in state: V0_C_DONE")); + } + + @Test + void disallowsReDecodingLatestVariableLengthField() + { + final MultipleVarLengthDecoder decoder = decodeUntilVarLengthFields(); + assertThat(decoder.b(), equalTo("abc")); + assertThat(decoder.c(), equalTo("def")); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, decoder::c); + assertThat(exception.getMessage(), containsString("Cannot access field \"c\" in state: V0_C_DONE")); + } + + private MultipleVarLengthDecoder decodeUntilVarLengthFields() + { + final MultipleVarLengthEncoder encoder = new MultipleVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.b("abc"); + encoder.c("def"); + encoder.checkEncodingIsComplete(); + + final MultipleVarLengthDecoder decoder = new MultipleVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + return decoder; + } + + @Test + void allowsEncodingAndDecodingGroupAndVariableLengthFieldsInSchemaDefinedOrder() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .next() + .c(2); + encoder.d("abc"); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final GroupAndVarLengthDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + assertThat(bs.next().c(), equalTo(1)); + assertThat(bs.next().c(), equalTo(2)); + assertThat(decoder.d(), equalTo("abc")); + assertThat(decoder.toString(), containsString("a=42|b=[(c=1),(c=2)]|d='abc'")); + } + + @Test + void allowsEncoderToResetZeroGroupLengthToZero() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(0).resetCountToIndex(); + encoder.d("abc"); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final GroupAndVarLengthDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(0)); + assertThat(decoder.d(), equalTo("abc")); + assertThat(decoder.toString(), containsString("a=42|b=[]|d='abc'")); + } + + @Test + void allowsEncoderToResetNonZeroGroupLengthToZeroBeforeCallingNext() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2).resetCountToIndex(); + encoder.d("abc"); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final GroupAndVarLengthDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(0)); + assertThat(decoder.d(), equalTo("abc")); + assertThat(decoder.toString(), containsString("a=42|b=[]|d='abc'")); + } + + @Test + void allowsEncoderToResetNonZeroGroupLengthToNonZero() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2).next().c(43).resetCountToIndex(); + encoder.d("abc"); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final GroupAndVarLengthDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(1)); + assertThat(bs.next().c(), equalTo(43)); + assertThat(decoder.d(), equalTo("abc")); + assertThat(decoder.toString(), containsString("a=42|b=[(c=43)]|d='abc'")); + } + + @Test + void disallowsEncoderToResetGroupLengthMidGroupElement() + { + final NestedGroupsEncoder encoder = new NestedGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final NestedGroupsEncoder.BEncoder bEncoder = encoder.bCount(2).next().c(43); + final IllegalStateException exception = assertThrows(IllegalStateException.class, bEncoder::resetCountToIndex); + assertThat(exception.getMessage(), + containsString("Cannot reset count of repeating group \"b\" in state: V0_B_N_BLOCK")); + } + + @Test + void allowsDecodingGroupAndVariableLengthFieldsAfterRewind() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .next() + .c(2); + encoder.d("abc"); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final GroupAndVarLengthDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + assertThat(bs.next().c(), equalTo(1)); + assertThat(bs.next().c(), equalTo(2)); + assertThat(decoder.d(), equalTo("abc")); + assertThat(decoder.toString(), containsString("a=42|b=[(c=1),(c=2)]|d='abc'")); + + decoder.sbeRewind(); + + assertThat(decoder.a(), equalTo(42)); + final GroupAndVarLengthDecoder.BDecoder bs2 = decoder.b(); + assertThat(bs2.count(), equalTo(2)); + assertThat(bs2.next().c(), equalTo(1)); + assertThat(bs2.next().c(), equalTo(2)); + assertThat(decoder.d(), equalTo("abc")); + assertThat(decoder.toString(), containsString("a=42|b=[(c=1),(c=2)]|d='abc'")); + } + + @Test + void allowsDecodingToSkipMessage() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .next() + .c(2); + encoder.d("abc"); + encoder.checkEncodingIsComplete(); + + final int nextEncodeOffset = encoder.limit(); + encoder.wrapAndApplyHeader(buffer, nextEncodeOffset, messageHeaderEncoder); + encoder.a(43); + encoder.bCount(2) + .next() + .c(3) + .next() + .c(4); + encoder.d("def"); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + + decoder.sbeSkip(); + final int nextDecodeOffset = decoder.limit(); + assertThat(nextDecodeOffset, equalTo(nextEncodeOffset)); + + decoder.wrapAndApplyHeader(buffer, nextDecodeOffset, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(43)); + final GroupAndVarLengthDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + assertThat(bs.next().c(), equalTo(3)); + assertThat(bs.next().c(), equalTo(4)); + assertThat(decoder.d(), equalTo("def")); + } + + @Test + void allowsDecodingToDetermineMessageLengthBeforeReadingFields() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(43); + encoder.bCount(2) + .next() + .c(3) + .next() + .c(4); + encoder.d("def"); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + + assertThat(decoder.sbeDecodedLength(), equalTo(18)); + assertThat(decoder.a(), equalTo(43)); + final GroupAndVarLengthDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + assertThat(bs.next().c(), equalTo(3)); + assertThat(bs.next().c(), equalTo(4)); + assertThat(decoder.d(), equalTo("def")); + } + + @Test + void allowsEncodingAndDecodingEmptyGroupAndVariableLengthFieldsInSchemaDefinedOrder() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(0); + encoder.d("abc"); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final GroupAndVarLengthDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(0)); + assertThat(decoder.d(), equalTo("abc")); + assertThat(decoder.toString(), containsString("a=42|b=[]|d='abc'")); + } + + @Test + @Disabled("Our access checks are too strict to allow the behaviour in this test.") + void allowsReEncodingPrimitiveFieldInGroupElementAfterTopLevelVariableLengthField() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final GroupAndVarLengthEncoder.BEncoder bEncoder = encoder.bCount(2); + bEncoder + .next() + .c(1) + .next() + .c(2); + encoder.d("abc"); + bEncoder.c(3); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final GroupAndVarLengthDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + assertThat(bs.next().c(), equalTo(1)); + assertThat(bs.next().c(), equalTo(3)); + assertThat(decoder.d(), equalTo("abc")); + } + + @Test + @Disabled("Our access checks are too strict to allow the behaviour in this test.") + void allowsReWrappingGroupDecoderAfterAccessingGroupCount() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final GroupAndVarLengthEncoder.BEncoder bEncoder = encoder.bCount(2); + bEncoder + .next() + .c(1) + .next() + .c(2); + encoder.d("abc"); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.b().count(), equalTo(2)); + final GroupAndVarLengthDecoder.BDecoder b = decoder.b(); + assertThat(b.next().c(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + assertThat(decoder.d(), equalTo("abc")); + } + + @Test + void disallowsEncodingGroupElementBeforeCallingNext() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final GroupAndVarLengthEncoder.BEncoder bEncoder = encoder.bCount(1); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> bEncoder.c(1)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsDecodingGroupElementBeforeCallingNext() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .next() + .c(2); + encoder.d("abc"); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final GroupAndVarLengthDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, bs::c); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsSkippingEncodingOfGroup() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.d("abc")); + assertThat(exception.getMessage(), containsString("Cannot access field \"d\" in state: V0_BLOCK")); + } + + @Test + void disallowsReEncodingVariableLengthFieldAfterGroup() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .next() + .c(2); + encoder.d("abc"); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.d("def")); + assertThat(exception.getMessage(), containsString("Cannot access field \"d\" in state: V0_D_DONE")); + } + + @Test + void disallowsReEncodingGroupCount() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .next() + .c(2); + encoder.d("abc"); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.bCount(1)); + assertThat(exception.getMessage(), + containsString("Cannot encode count of repeating group \"b\" in state: V0_D_DONE")); + } + + @Test + @Disabled("Our access checks are too strict to allow the behaviour in this test.") + void allowsReEncodingGroupElementBlockFieldAfterTopLevelVariableLengthField() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final GroupAndVarLengthEncoder.BEncoder b = encoder.bCount(2) + .next() + .c(1) + .next() + .c(2); + encoder.d("abc"); + b.c(3); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final GroupAndVarLengthDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + assertThat(bs.next().c(), equalTo(1)); + assertThat(bs.next().c(), equalTo(3)); + assertThat(decoder.d(), equalTo("abc")); + } + + @Test + void disallowsMissedDecodingOfGroupBeforeVariableLengthField() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .next() + .c(2); + encoder.d("abc"); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, decoder::d); + assertThat(exception.getMessage(), containsString("Cannot access field \"d\" in state: V0_BLOCK")); + } + + @Test + void disallowsReDecodingVariableLengthFieldAfterGroup() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .next() + .c(2); + encoder.d("abc"); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final GroupAndVarLengthDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + assertThat(bs.next().c(), equalTo(1)); + assertThat(bs.next().c(), equalTo(2)); + assertThat(decoder.d(), equalTo("abc")); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, decoder::d); + assertThat(exception.getMessage(), containsString("Cannot access field \"d\" in state: V0_D_DONE")); + } + + @Test + void disallowsReDecodingGroupAfterVariableLengthField() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .next() + .c(2); + encoder.d("abc"); + encoder.checkEncodingIsComplete(); + + final GroupAndVarLengthDecoder decoder = new GroupAndVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final GroupAndVarLengthDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + assertThat(bs.next().c(), equalTo(1)); + assertThat(bs.next().c(), equalTo(2)); + assertThat(decoder.d(), equalTo("abc")); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, decoder::b); + assertThat(exception.getMessage(), + containsString("Cannot decode count of repeating group \"b\" in state: V0_D_DONE")); + } + + @Test + void allowsEncodingAndDecodingVariableLengthFieldInsideGroupInSchemaDefinedOrder() + { + final VarLengthInsideGroupEncoder encoder = new VarLengthInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .d("abc") + .next() + .c(2) + .d("def"); + encoder.e("ghi"); + encoder.checkEncodingIsComplete(); + + final VarLengthInsideGroupDecoder decoder = new VarLengthInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final VarLengthInsideGroupDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + assertThat(bs.next().c(), equalTo(1)); + assertThat(bs.d(), equalTo("abc")); + assertThat(bs.next().c(), equalTo(2)); + assertThat(bs.d(), equalTo("def")); + assertThat(decoder.e(), equalTo("ghi")); + assertThat(decoder.toString(), containsString("a=42|b=[(c=1|d='abc'),(c=2|d='def')]|e='ghi'")); + } + + @Test + @Disabled("Our access checks are too strict to allow the behaviour in this test.") + void allowsReEncodingGroupElementPrimitiveFieldAfterElementVariableLengthField() + { + final VarLengthInsideGroupEncoder encoder = new VarLengthInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final VarLengthInsideGroupEncoder.BEncoder bEncoder = encoder.bCount(1); + bEncoder + .next() + .c(1) + .d("abc"); + bEncoder.c(2); + encoder.e("ghi"); + encoder.checkEncodingIsComplete(); + + final VarLengthInsideGroupDecoder decoder = new VarLengthInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final VarLengthInsideGroupDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(1)); + assertThat(bs.next().c(), equalTo(2)); + assertThat(bs.d(), equalTo("abc")); + assertThat(decoder.e(), equalTo("ghi")); + } + + @Test + void disallowsMissedGroupElementVariableLengthFieldToEncodeAtTopLevel() + { + final VarLengthInsideGroupEncoder encoder = new VarLengthInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(1).next().c(1); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.e("abc")); + assertThat(exception.getMessage(), containsString("Cannot access field \"e\" in state: V0_B_1_BLOCK")); + } + + @Test + void disallowsMissedGroupElementVariableLengthFieldToEncodeNextElement() + { + final VarLengthInsideGroupEncoder encoder = new VarLengthInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final VarLengthInsideGroupEncoder.BEncoder b = encoder.bCount(2) + .next(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, b::next); + assertThat(exception.getMessage(), + containsString("Cannot access next element in repeating group \"b\" in state: V0_B_N_BLOCK")); + } + + @Test + void disallowsMissedGroupElementEncoding() + { + final VarLengthInsideGroupEncoder encoder = new VarLengthInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .d("abc"); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.e("abc")); + assertThat(exception.getMessage(), containsString("Cannot access field \"e\" in state: V0_B_N_D_DONE")); + } + + @Test + void disallowsReEncodingGroupElementVariableLengthField() + { + final VarLengthInsideGroupEncoder encoder = new VarLengthInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final VarLengthInsideGroupEncoder.BEncoder b = encoder.bCount(1) + .next() + .c(1) + .d("abc"); + encoder.e("def"); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> b.d("ghi")); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.d\" in state: V0_E_DONE")); + } + + @Test + void disallowsReDecodingGroupElementVariableLengthField() + { + final VarLengthInsideGroupEncoder encoder = new VarLengthInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .d("abc") + .next() + .c(2) + .d("def"); + encoder.e("ghi"); + encoder.checkEncodingIsComplete(); + + final VarLengthInsideGroupDecoder decoder = new VarLengthInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final VarLengthInsideGroupDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + assertThat(bs.next().c(), equalTo(1)); + assertThat(bs.d(), equalTo("abc")); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, bs::d); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.d\" in state: V0_B_N_D_DONE")); + } + + @Test + void disallowsMissedDecodingOfGroupElementVariableLengthFieldToNextElement() + { + final VarLengthInsideGroupEncoder encoder = new VarLengthInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .d("abc") + .next() + .c(2) + .d("def"); + encoder.e("ghi"); + encoder.checkEncodingIsComplete(); + + final VarLengthInsideGroupDecoder decoder = new VarLengthInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final VarLengthInsideGroupDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + assertThat(bs.next().c(), equalTo(1)); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, bs::next); + assertThat(exception.getMessage(), + containsString("Cannot access next element in repeating group \"b\" in state: V0_B_N_BLOCK")); + } + + @Test + void disallowsMissedDecodingOfGroupElementVariableLengthFieldToTopLevel() + { + final VarLengthInsideGroupEncoder encoder = new VarLengthInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(1) + .next() + .c(1) + .d("abc"); + encoder.e("ghi"); + encoder.checkEncodingIsComplete(); + + final VarLengthInsideGroupDecoder decoder = new VarLengthInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final VarLengthInsideGroupDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(1)); + assertThat(bs.next().c(), equalTo(1)); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, decoder::e); + assertThat(exception.getMessage(), containsString("Cannot access field \"e\" in state: V0_B_1_BLOCK")); + } + + @Test + void disallowsMissedDecodingOfGroupElement() + { + final VarLengthInsideGroupEncoder encoder = new VarLengthInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(2) + .next() + .c(1) + .d("abc") + .next() + .c(2) + .d("def"); + encoder.e("ghi"); + encoder.checkEncodingIsComplete(); + + final VarLengthInsideGroupDecoder decoder = new VarLengthInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final VarLengthInsideGroupDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + assertThat(bs.next().c(), equalTo(1)); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, decoder::e); + assertThat(exception.getMessage(), containsString("Cannot access field \"e\" in state: V0_B_N_BLOCK")); + } + + @Test + void allowsEncodingNestedGroupsInSchemaDefinedOrder() + { + final NestedGroupsEncoder encoder = new NestedGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final NestedGroupsEncoder.BEncoder b = encoder.bCount(2) + .next(); + b.c(1); + b.dCount(2) + .next() + .e(2) + .next() + .e(3); + b.fCount(1) + .next() + .g(4); + b.next(); + b.c(5); + b.dCount(1) + .next() + .e(6); + b.fCount(1) + .next() + .g(7); + encoder.hCount(1) + .next() + .i(8); + encoder.checkEncodingIsComplete(); + + final NestedGroupsDecoder decoder = new NestedGroupsDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final NestedGroupsDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(2)); + final NestedGroupsDecoder.BDecoder b0 = bs.next(); + assertThat(b0.c(), equalTo(1)); + final NestedGroupsDecoder.BDecoder.DDecoder b0ds = b0.d(); + assertThat(b0ds.count(), equalTo(2)); + assertThat(b0ds.next().e(), equalTo(2)); + assertThat(b0ds.next().e(), equalTo(3)); + final NestedGroupsDecoder.BDecoder.FDecoder b0fs = b0.f(); + assertThat(b0fs.count(), equalTo(1)); + assertThat(b0fs.next().g(), equalTo(4)); + final NestedGroupsDecoder.BDecoder b1 = bs.next(); + assertThat(b1.c(), equalTo(5)); + final NestedGroupsDecoder.BDecoder.DDecoder b1ds = b1.d(); + assertThat(b1ds.count(), equalTo(1)); + assertThat(b1ds.next().e(), equalTo(6)); + final NestedGroupsDecoder.BDecoder.FDecoder b1fs = b1.f(); + assertThat(b1fs.count(), equalTo(1)); + assertThat(b1fs.next().g(), equalTo(7)); + final NestedGroupsDecoder.HDecoder hs = decoder.h(); + assertThat(hs.count(), equalTo(1)); + assertThat(hs.next().i(), equalTo(8)); + assertThat(decoder.toString(), + containsString("a=42|b=[(c=1|d=[(e=2),(e=3)]|f=[(g=4)]),(c=5|d=[(e=6)]|f=[(g=7)])]|h=[(i=8)]")); + } + + @Test + void allowsEncodingEmptyNestedGroupsInSchemaDefinedOrder() + { + final NestedGroupsEncoder encoder = new NestedGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(0); + encoder.hCount(0); + encoder.checkEncodingIsComplete(); + + final NestedGroupsDecoder decoder = new NestedGroupsDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + final NestedGroupsDecoder.BDecoder bs = decoder.b(); + assertThat(bs.count(), equalTo(0)); + final NestedGroupsDecoder.HDecoder hs = decoder.h(); + assertThat(hs.count(), equalTo(0)); + assertThat(decoder.toString(), containsString("a=42|b=[]|h=[]")); + } + + @Test + void disallowsMissedEncodingOfNestedGroup() + { + final NestedGroupsEncoder encoder = new NestedGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final NestedGroupsEncoder.BEncoder b = encoder.bCount(1) + .next() + .c(1); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> b.fCount(1)); + assertThat(exception.getMessage(), + containsString("Cannot encode count of repeating group \"b.f\" in state: V0_B_1_BLOCK")); + } + + @Test + void allowsEncodingAndDecodingCompositeInsideGroupInSchemaDefinedOrder() + { + final CompositeInsideGroupEncoder encoder = new CompositeInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().x(1).y(2); + encoder.bCount(1) + .next() + .c().x(3).y(4); + encoder.checkEncodingIsComplete(); + + final CompositeInsideGroupDecoder decoder = new CompositeInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final PointDecoder a = decoder.a(); + assertThat(a.x(), equalTo(1)); + assertThat(a.y(), equalTo(2)); + final CompositeInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final PointDecoder c = b.next().c(); + assertThat(c.x(), equalTo(3)); + assertThat(c.y(), equalTo(4)); + assertThat(decoder.toString(), containsString("a=(x=1|y=2)|b=[(c=(x=3|y=4))]")); + } + + @Test + void disallowsEncodingCompositeInsideGroupBeforeCallingNext() + { + final CompositeInsideGroupEncoder encoder = new CompositeInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().x(1).y(2); + final CompositeInsideGroupEncoder.BEncoder bEncoder = encoder.bCount(1); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, bEncoder::c); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsDecodingCompositeInsideGroupBeforeCallingNext() + { + final CompositeInsideGroupEncoder encoder = new CompositeInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().x(1).y(2); + encoder.bCount(1) + .next() + .c().x(3).y(4); + + final CompositeInsideGroupDecoder decoder = new CompositeInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final PointDecoder a = decoder.a(); + assertThat(a.x(), equalTo(1)); + assertThat(a.y(), equalTo(2)); + final CompositeInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, b::c); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void allowsReEncodingTopLevelCompositeViaReWrap() + { + final CompositeInsideGroupEncoder encoder = new CompositeInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().x(1).y(2); + encoder.bCount(1) + .next() + .c().x(3).y(4); + encoder.a().x(5).y(6); + encoder.checkEncodingIsComplete(); + + final CompositeInsideGroupDecoder decoder = new CompositeInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final PointDecoder a = decoder.a(); + assertThat(a.x(), equalTo(5)); + assertThat(a.y(), equalTo(6)); + final CompositeInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final PointDecoder c = b.next().c(); + assertThat(c.x(), equalTo(3)); + assertThat(c.y(), equalTo(4)); + } + + @Test + void allowsReEncodingTopLevelCompositeViaEncoderReference() + { + final CompositeInsideGroupEncoder encoder = new CompositeInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + final PointEncoder aEncoder = encoder.a(); + aEncoder.x(1).y(2); + encoder.bCount(1) + .next() + .c().x(3).y(4); + aEncoder.x(5).y(6); + encoder.checkEncodingIsComplete(); + + final CompositeInsideGroupDecoder decoder = new CompositeInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final PointDecoder a = decoder.a(); + assertThat(a.x(), equalTo(5)); + assertThat(a.y(), equalTo(6)); + final CompositeInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final PointDecoder c = b.next().c(); + assertThat(c.x(), equalTo(3)); + assertThat(c.y(), equalTo(4)); + } + + @Test + void allowsReEncodingGroupElementCompositeViaReWrap() + { + final CompositeInsideGroupEncoder encoder = new CompositeInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().x(1).y(2); + final CompositeInsideGroupEncoder.BEncoder bEncoder = encoder.bCount(1).next(); + bEncoder.c().x(3).y(4); + bEncoder.c().x(5).y(6); + encoder.checkEncodingIsComplete(); + + final CompositeInsideGroupDecoder decoder = new CompositeInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final PointDecoder a = decoder.a(); + assertThat(a.x(), equalTo(1)); + assertThat(a.y(), equalTo(2)); + final CompositeInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final PointDecoder c = b.next().c(); + assertThat(c.x(), equalTo(5)); + assertThat(c.y(), equalTo(6)); + } + + @Test + void allowsReEncodingGroupElementCompositeViaEncoderReference() + { + final CompositeInsideGroupEncoder encoder = new CompositeInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().x(1).y(2); + final CompositeInsideGroupEncoder.BEncoder bEncoder = encoder.bCount(1).next(); + final PointEncoder cEncoder = bEncoder.c(); + cEncoder.x(3).y(4); + cEncoder.x(5).y(6); + encoder.checkEncodingIsComplete(); + + final CompositeInsideGroupDecoder decoder = new CompositeInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final PointDecoder a = decoder.a(); + assertThat(a.x(), equalTo(1)); + assertThat(a.y(), equalTo(2)); + final CompositeInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final PointDecoder c = b.next().c(); + assertThat(c.x(), equalTo(5)); + assertThat(c.y(), equalTo(6)); + } + + @Test + void allowsReDecodingTopLevelCompositeViaReWrap() + { + final CompositeInsideGroupEncoder encoder = new CompositeInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().x(1).y(2); + encoder.bCount(1) + .next() + .c().x(3).y(4); + encoder.checkEncodingIsComplete(); + + final CompositeInsideGroupDecoder decoder = new CompositeInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final PointDecoder a1 = decoder.a(); + assertThat(a1.x(), equalTo(1)); + assertThat(a1.y(), equalTo(2)); + final CompositeInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final PointDecoder c = b.next().c(); + assertThat(c.x(), equalTo(3)); + assertThat(c.y(), equalTo(4)); + final PointDecoder a2 = decoder.a(); + assertThat(a2.x(), equalTo(1)); + assertThat(a2.y(), equalTo(2)); + } + + @Test + void allowsReDecodingTopLevelCompositeViaEncoderReference() + { + final CompositeInsideGroupEncoder encoder = new CompositeInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().x(1).y(2); + encoder.bCount(1) + .next() + .c().x(3).y(4); + encoder.checkEncodingIsComplete(); + + final CompositeInsideGroupDecoder decoder = new CompositeInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final PointDecoder a = decoder.a(); + assertThat(a.x(), equalTo(1)); + assertThat(a.y(), equalTo(2)); + final CompositeInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final PointDecoder c = b.next().c(); + assertThat(c.x(), equalTo(3)); + assertThat(c.y(), equalTo(4)); + assertThat(a.x(), equalTo(1)); + assertThat(a.y(), equalTo(2)); + } + + @Test + void allowsReDecodingGroupElementCompositeViaReWrap() + { + final CompositeInsideGroupEncoder encoder = new CompositeInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().x(1).y(2); + encoder.bCount(1) + .next() + .c().x(3).y(4); + encoder.checkEncodingIsComplete(); + + final CompositeInsideGroupDecoder decoder = new CompositeInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final PointDecoder a = decoder.a(); + assertThat(a.x(), equalTo(1)); + assertThat(a.y(), equalTo(2)); + final CompositeInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final PointDecoder c1 = b.next().c(); + assertThat(c1.x(), equalTo(3)); + assertThat(c1.y(), equalTo(4)); + final PointDecoder c2 = b.c(); + assertThat(c2.x(), equalTo(3)); + assertThat(c2.y(), equalTo(4)); + } + + @Test + void allowsReDecodingGroupElementCompositeViaEncoderReference() + { + final CompositeInsideGroupEncoder encoder = new CompositeInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().x(1).y(2); + encoder.bCount(1) + .next() + .c().x(3).y(4); + encoder.checkEncodingIsComplete(); + + final CompositeInsideGroupDecoder decoder = new CompositeInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final PointDecoder a = decoder.a(); + assertThat(a.x(), equalTo(1)); + assertThat(a.y(), equalTo(2)); + final CompositeInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final PointDecoder c = b.next().c(); + assertThat(c.x(), equalTo(3)); + assertThat(c.y(), equalTo(4)); + assertThat(c.x(), equalTo(3)); + assertThat(c.y(), equalTo(4)); + } + + @Test + void allowsNewDecoderToDecodeAddedPrimitiveField() + { + final AddPrimitiveV1Encoder encoder = new AddPrimitiveV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).b(2); + encoder.checkEncodingIsComplete(); + + final AddPrimitiveV1Decoder decoder = new AddPrimitiveV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.b(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeMissingPrimitiveFieldAsNullValue() + { + final AddPrimitiveV0Encoder encoder = new AddPrimitiveV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddPrimitiveV1Decoder decoder = new AddPrimitiveV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.b(), equalTo(AddPrimitiveV1Decoder.bNullValue())); + } + + @Test + void allowsNewDecoderToDecodeAddedPrimitiveFieldBeforeGroup() + { + final AddPrimitiveBeforeGroupV1Encoder encoder = new AddPrimitiveBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).d(3).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + final AddPrimitiveBeforeGroupV1Decoder decoder = new AddPrimitiveBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.d(), equalTo(3)); + final AddPrimitiveBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeMissingPrimitiveFieldBeforeGroupAsNullValue() + { + final AddPrimitiveBeforeGroupV0Encoder encoder = new AddPrimitiveBeforeGroupV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddPrimitiveBeforeGroupV1Decoder decoder = new AddPrimitiveBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.d(), equalTo(AddPrimitiveBeforeGroupV1Decoder.dNullValue())); + final AddPrimitiveBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToSkipPresentButAddedPrimitiveFieldBeforeGroup() + { + final AddPrimitiveBeforeGroupV1Encoder encoder = new AddPrimitiveBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).d(3).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + final AddPrimitiveBeforeGroupV1Decoder decoder = new AddPrimitiveBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddPrimitiveBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsOldDecoderToSkipAddedPrimitiveFieldBeforeGroup() + { + final AddPrimitiveBeforeGroupV1Encoder encoder = new AddPrimitiveBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).d(3).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion1(); + + final AddPrimitiveBeforeGroupV0Decoder decoder = new AddPrimitiveBeforeGroupV0Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddPrimitiveBeforeGroupV0Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeAddedPrimitiveFieldBeforeVarData() + { + final AddPrimitiveBeforeVarDataV1Encoder encoder = new AddPrimitiveBeforeVarDataV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).c(3).b("abc"); + encoder.checkEncodingIsComplete(); + + final AddPrimitiveBeforeVarDataV1Decoder decoder = new AddPrimitiveBeforeVarDataV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.c(), equalTo(3)); + assertThat(decoder.b(), equalTo("abc")); + } + + @Test + void allowsNewDecoderToDecodeMissingPrimitiveFieldBeforeVarDataAsNullValue() + { + final AddPrimitiveBeforeVarDataV0Encoder encoder = new AddPrimitiveBeforeVarDataV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).b("abc"); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddPrimitiveBeforeVarDataV1Decoder decoder = new AddPrimitiveBeforeVarDataV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.c(), equalTo(AddPrimitiveBeforeVarDataV1Decoder.cNullValue())); + assertThat(decoder.b(), equalTo("abc")); + } + + @Test + void allowsNewDecoderToSkipPresentButAddedPrimitiveFieldBeforeVarData() + { + final AddPrimitiveBeforeVarDataV1Encoder encoder = new AddPrimitiveBeforeVarDataV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).c(3).b("abc"); + encoder.checkEncodingIsComplete(); + + final AddPrimitiveBeforeVarDataV1Decoder decoder = new AddPrimitiveBeforeVarDataV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.b(), equalTo("abc")); + } + + @Test + void allowsOldDecoderToSkipAddedPrimitiveFieldBeforeVarData() + { + final AddPrimitiveBeforeVarDataV1Encoder encoder = new AddPrimitiveBeforeVarDataV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).c(3).b("abc"); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion1(); + + final AddPrimitiveBeforeVarDataV0Decoder decoder = new AddPrimitiveBeforeVarDataV0Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.b(), equalTo("abc")); + } + + @Test + void allowsNewDecoderToDecodeAddedPrimitiveFieldInsideGroup() + { + final AddPrimitiveInsideGroupV1Encoder encoder = new AddPrimitiveInsideGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2).d(3); + encoder.checkEncodingIsComplete(); + + final AddPrimitiveInsideGroupV1Decoder decoder = new AddPrimitiveInsideGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddPrimitiveInsideGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + assertThat(b.d(), equalTo(3)); + } + + @Test + void allowsNewDecoderToDecodeMissingPrimitiveFieldInsideGroupAsNullValue() + { + final AddPrimitiveInsideGroupV0Encoder encoder = new AddPrimitiveInsideGroupV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddPrimitiveInsideGroupV1Decoder decoder = new AddPrimitiveInsideGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddPrimitiveInsideGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + assertThat(b.d(), equalTo(AddPrimitiveInsideGroupV1Decoder.BDecoder.dNullValue())); + } + + @Test + void allowsNewDecoderToSkipPresentButAddedPrimitiveFieldInsideGroup() + { + final AddPrimitiveInsideGroupV1Encoder encoder = new AddPrimitiveInsideGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(2).next().c(2).d(3).next().c(4).d(5); + encoder.checkEncodingIsComplete(); + + final AddPrimitiveInsideGroupV1Decoder decoder = new AddPrimitiveInsideGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddPrimitiveInsideGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(2)); + assertThat(b.next().c(), equalTo(2)); + assertThat(b.next().c(), equalTo(4)); + } + + @Test + void allowsOldDecoderToSkipAddedPrimitiveFieldInsideGroup() + { + final AddPrimitiveInsideGroupV1Encoder encoder = new AddPrimitiveInsideGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(2).next().c(2).d(3).next().c(4).d(5); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion1(); + + final AddPrimitiveInsideGroupV0Decoder decoder = new AddPrimitiveInsideGroupV0Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddPrimitiveInsideGroupV0Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(2)); + assertThat(b.next().c(), equalTo(2)); + assertThat(b.next().c(), equalTo(4)); + } + + @Test + void allowsNewDecoderToDecodeAddedGroupBeforeVarData() + { + final AddGroupBeforeVarDataV1Encoder encoder = new AddGroupBeforeVarDataV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).cCount(1).next().d(2); + encoder.b("abc"); + encoder.checkEncodingIsComplete(); + + final AddGroupBeforeVarDataV1Decoder decoder = new AddGroupBeforeVarDataV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddGroupBeforeVarDataV1Decoder.CDecoder c = decoder.c(); + assertThat(c.count(), equalTo(1)); + assertThat(c.next().d(), equalTo(2)); + assertThat(decoder.b(), equalTo("abc")); + } + + @Test + void allowsNewDecoderToDecodeMissingGroupBeforeVarDataAsNullValue() + { + final AddGroupBeforeVarDataV0Encoder encoder = new AddGroupBeforeVarDataV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).b("abc"); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddGroupBeforeVarDataV1Decoder decoder = new AddGroupBeforeVarDataV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddGroupBeforeVarDataV1Decoder.CDecoder c = decoder.c(); + assertThat(c.count(), equalTo(0)); + assertThat(decoder.b(), equalTo("abc")); + assertThat(decoder.toString(), containsString("a=1|c=[]|b='abc'")); + } + + @Test + void allowsNewDecoderToSkipMissingGroupBeforeVarData() + { + final AddGroupBeforeVarDataV0Encoder encoder = new AddGroupBeforeVarDataV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).b("abc"); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddGroupBeforeVarDataV1Decoder decoder = new AddGroupBeforeVarDataV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.b(), equalTo("abc")); + } + + @Test + void disallowsNewDecoderToSkipPresentButAddedGroupBeforeVarData() + { + final AddGroupBeforeVarDataV1Encoder encoder = new AddGroupBeforeVarDataV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).cCount(1).next().d(2); + encoder.b("abc"); + encoder.checkEncodingIsComplete(); + + final AddGroupBeforeVarDataV1Decoder decoder = new AddGroupBeforeVarDataV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, decoder::b); + assertThat(exception.getMessage(), containsString("Cannot access field \"b\" in state: V1_BLOCK")); + } + + @Test + void allowsOldDecoderToSkipAddedGroupBeforeVarData() + { + final AddGroupBeforeVarDataV1Encoder encoder = new AddGroupBeforeVarDataV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + messageHeaderEncoder.numGroups(1); + encoder.a(1).cCount(1).next().d(2); + encoder.b("abc"); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion1(); + + final AddGroupBeforeVarDataV0Decoder decoder = new AddGroupBeforeVarDataV0Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + + for (int i = 0; i < messageHeaderDecoder.numGroups(); i++) + { + skipGroup(decoder); + } + + assertThat(decoder.b(), equalTo("abc")); + } + + private void skipGroup(final AddGroupBeforeVarDataV0Decoder decoder) + { + final GroupSizeEncodingDecoder groupSizeEncodingDecoder = new GroupSizeEncodingDecoder() + .wrap(buffer, decoder.limit()); + final int bytesToSkip = groupSizeEncodingDecoder.encodedLength() + + groupSizeEncodingDecoder.blockLength() * groupSizeEncodingDecoder.numInGroup(); + decoder.limit(decoder.limit() + bytesToSkip); + } + + @Test + void allowsNewDecoderToDecodeAddedEnumFieldBeforeGroup() + { + final AddEnumBeforeGroupV1Encoder encoder = new AddEnumBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).d(Direction.BUY).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + final AddEnumBeforeGroupV1Decoder decoder = new AddEnumBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.d(), equalTo(Direction.BUY)); + final AddEnumBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeMissingEnumFieldBeforeGroupAsNullValue() + { + final AddEnumBeforeGroupV0Encoder encoder = new AddEnumBeforeGroupV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddEnumBeforeGroupV1Decoder decoder = new AddEnumBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.d(), equalTo(Direction.NULL_VAL)); + final AddEnumBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToSkipPresentButAddedEnumFieldBeforeGroup() + { + final AddEnumBeforeGroupV1Encoder encoder = new AddEnumBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).d(Direction.SELL).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + final AddEnumBeforeGroupV1Decoder decoder = new AddEnumBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddEnumBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsOldDecoderToSkipAddedEnumFieldBeforeGroup() + { + final AddEnumBeforeGroupV1Encoder encoder = new AddEnumBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).d(Direction.BUY).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion1(); + + final AddEnumBeforeGroupV0Decoder decoder = new AddEnumBeforeGroupV0Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddEnumBeforeGroupV0Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeAddedCompositeFieldBeforeGroup() + { + final AddCompositeBeforeGroupV1Encoder encoder = new AddCompositeBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).d().x(-1).y(-2); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + final AddCompositeBeforeGroupV1Decoder decoder = new AddCompositeBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final PointDecoder d = decoder.d(); + assertThat(d, notNullValue()); + assertThat(d.x(), equalTo(-1)); + assertThat(d.y(), equalTo(-2)); + final AddCompositeBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeMissingCompositeFieldBeforeGroupAsNullValue() + { + final AddCompositeBeforeGroupV0Encoder encoder = new AddCompositeBeforeGroupV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddCompositeBeforeGroupV1Decoder decoder = new AddCompositeBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.d(), nullValue()); + final AddCompositeBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToSkipPresentButAddedCompositeFieldBeforeGroup() + { + final AddCompositeBeforeGroupV1Encoder encoder = new AddCompositeBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).d().x(-1).y(-2); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + final AddCompositeBeforeGroupV1Decoder decoder = new AddCompositeBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddCompositeBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsOldDecoderToSkipAddedCompositeFieldBeforeGroup() + { + final AddCompositeBeforeGroupV1Encoder encoder = new AddCompositeBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).d().x(-1).y(-2); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion1(); + + final AddCompositeBeforeGroupV0Decoder decoder = new AddCompositeBeforeGroupV0Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddCompositeBeforeGroupV0Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeAddedArrayFieldBeforeGroup() + { + final AddArrayBeforeGroupV1Encoder encoder = new AddArrayBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1) + .putD((short)1, (short)2, (short)3, (short)4) + .bCount(1) + .next().c(2); + encoder.checkEncodingIsComplete(); + + final AddArrayBeforeGroupV1Decoder decoder = new AddArrayBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.d(0), equalTo((short)1)); + assertThat(decoder.d(1), equalTo((short)2)); + assertThat(decoder.d(2), equalTo((short)3)); + assertThat(decoder.d(3), equalTo((short)4)); + final AddArrayBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeMissingArrayFieldBeforeGroupAsNullValue1() + { + final AddArrayBeforeGroupV0Encoder encoder = new AddArrayBeforeGroupV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddArrayBeforeGroupV1Decoder decoder = new AddArrayBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.d(0), equalTo(AddArrayBeforeGroupV1Decoder.dNullValue())); + assertThat(decoder.d(1), equalTo(AddArrayBeforeGroupV1Decoder.dNullValue())); + assertThat(decoder.d(2), equalTo(AddArrayBeforeGroupV1Decoder.dNullValue())); + assertThat(decoder.d(3), equalTo(AddArrayBeforeGroupV1Decoder.dNullValue())); + final AddArrayBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeMissingArrayFieldBeforeGroupAsNullValue2() + { + final AddArrayBeforeGroupV0Encoder encoder = new AddArrayBeforeGroupV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddArrayBeforeGroupV1Decoder decoder = new AddArrayBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.getD(new byte[8], 0, 8), equalTo(0)); + final AddArrayBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeMissingArrayFieldBeforeGroupAsNullValue3() + { + final AddArrayBeforeGroupV0Encoder encoder = new AddArrayBeforeGroupV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddArrayBeforeGroupV1Decoder decoder = new AddArrayBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.getD(new ExpandableArrayBuffer(), 0, 8), equalTo(0)); + final AddArrayBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeMissingArrayFieldBeforeGroupAsNullValue4() + { + final AddArrayBeforeGroupV0Encoder encoder = new AddArrayBeforeGroupV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddArrayBeforeGroupV1Decoder decoder = new AddArrayBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final UnsafeBuffer buffer = new UnsafeBuffer(); + decoder.wrapD(buffer); + assertThat(buffer.capacity(), equalTo(0)); + final AddArrayBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToSkipPresentButAddedArrayFieldBeforeGroup() + { + final AddArrayBeforeGroupV1Encoder encoder = new AddArrayBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1) + .putD((short)1, (short)2, (short)3, (short)4) + .bCount(1) + .next().c(2); + encoder.checkEncodingIsComplete(); + + final AddArrayBeforeGroupV1Decoder decoder = new AddArrayBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddArrayBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsOldDecoderToSkipAddedArrayFieldBeforeGroup() + { + final AddArrayBeforeGroupV1Encoder encoder = new AddArrayBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1) + .putD((short)1, (short)2, (short)3, (short)4) + .bCount(1) + .next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion1(); + + final AddArrayBeforeGroupV0Decoder decoder = new AddArrayBeforeGroupV0Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddArrayBeforeGroupV0Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeAddedBitSetFieldBeforeGroup() + { + final AddBitSetBeforeGroupV1Encoder encoder = new AddBitSetBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).d().guacamole(true).cheese(true).sourCream(false); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + final AddBitSetBeforeGroupV1Decoder decoder = new AddBitSetBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final FlagsDecoder d = decoder.d(); + assertThat(d, notNullValue()); + assertThat(d.guacamole(), equalTo(true)); + assertThat(d.cheese(), equalTo(true)); + assertThat(d.sourCream(), equalTo(false)); + final AddBitSetBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeMissingBitSetFieldBeforeGroupAsNullValue() + { + final AddBitSetBeforeGroupV0Encoder encoder = new AddBitSetBeforeGroupV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddBitSetBeforeGroupV1Decoder decoder = new AddBitSetBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.d(), nullValue()); + final AddBitSetBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToSkipPresentButAddedBitSetFieldBeforeGroup() + { + final AddBitSetBeforeGroupV1Encoder encoder = new AddBitSetBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).d().guacamole(true).cheese(true).sourCream(false); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + final AddBitSetBeforeGroupV1Decoder decoder = new AddBitSetBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddBitSetBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsOldDecoderToSkipAddedBitSetFieldBeforeGroup() + { + final AddBitSetBeforeGroupV1Encoder encoder = new AddBitSetBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).d().guacamole(true).cheese(true).sourCream(false); + encoder.bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion1(); + + final AddBitSetBeforeGroupV0Decoder decoder = new AddBitSetBeforeGroupV0Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddBitSetBeforeGroupV0Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsEncodingAndDecodingEnumInsideGroupInSchemaDefinedOrder() + { + final EnumInsideGroupEncoder encoder = new EnumInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(Direction.BUY) + .bCount(1) + .next() + .c(Direction.SELL); + encoder.checkEncodingIsComplete(); + + final EnumInsideGroupDecoder decoder = new EnumInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(Direction.BUY)); + final EnumInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(Direction.SELL)); + assertThat(decoder.toString(), containsString("a=BUY|b=[(c=SELL)]")); + } + + @Test + void disallowsEncodingEnumInsideGroupBeforeCallingNext() + { + final EnumInsideGroupEncoder encoder = new EnumInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(Direction.BUY); + final EnumInsideGroupEncoder.BEncoder bEncoder = encoder.bCount(1); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> bEncoder.c(Direction.SELL)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsDecodingEnumInsideGroupBeforeCallingNext() + { + final EnumInsideGroupEncoder encoder = new EnumInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(Direction.BUY) + .bCount(1) + .next() + .c(Direction.SELL); + encoder.checkEncodingIsComplete(); + + final EnumInsideGroupDecoder decoder = new EnumInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(Direction.BUY)); + final EnumInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, b::c); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void allowsReEncodingTopLevelEnum() + { + final EnumInsideGroupEncoder encoder = new EnumInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(Direction.BUY) + .bCount(1) + .next() + .c(Direction.SELL); + + encoder.a(Direction.SELL); + encoder.checkEncodingIsComplete(); + + + final EnumInsideGroupDecoder decoder = new EnumInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(Direction.SELL)); + final EnumInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(Direction.SELL)); + } + + @Test + void allowsEncodingAndDecodingBitSetInsideGroupInSchemaDefinedOrder() + { + final BitSetInsideGroupEncoder encoder = new BitSetInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().cheese(true).guacamole(true).sourCream(false); + encoder.bCount(1) + .next() + .c().cheese(false).guacamole(false).sourCream(true); + encoder.checkEncodingIsComplete(); + + final BitSetInsideGroupDecoder decoder = new BitSetInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final FlagsDecoder a = decoder.a(); + assertThat(a.guacamole(), equalTo(true)); + assertThat(a.cheese(), equalTo(true)); + assertThat(a.sourCream(), equalTo(false)); + final BitSetInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final FlagsDecoder c = b.next().c(); + assertThat(c.guacamole(), equalTo(false)); + assertThat(c.cheese(), equalTo(false)); + assertThat(c.sourCream(), equalTo(true)); + assertThat(decoder.toString(), containsString("a={guacamole,cheese}|b=[(c={sourCream})]")); + } + + @Test + void disallowsEncodingBitSetInsideGroupBeforeCallingNext() + { + final BitSetInsideGroupEncoder encoder = new BitSetInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().cheese(true).guacamole(true).sourCream(false); + final BitSetInsideGroupEncoder.BEncoder bEncoder = encoder.bCount(1); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, bEncoder::c); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsDecodingBitSetInsideGroupBeforeCallingNext() + { + final BitSetInsideGroupEncoder encoder = new BitSetInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().cheese(true).guacamole(true).sourCream(false); + encoder.bCount(1) + .next() + .c().guacamole(false).cheese(false).sourCream(true); + encoder.checkEncodingIsComplete(); + + final BitSetInsideGroupDecoder decoder = new BitSetInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final FlagsDecoder a = decoder.a(); + assertThat(a.guacamole(), equalTo(true)); + assertThat(a.cheese(), equalTo(true)); + assertThat(a.sourCream(), equalTo(false)); + final BitSetInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, b::c); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void allowsReEncodingTopLevelBitSetViaReWrap() + { + final BitSetInsideGroupEncoder encoder = new BitSetInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a().cheese(true).guacamole(true).sourCream(false); + encoder.bCount(1) + .next() + .c().cheese(false).guacamole(false).sourCream(true); + + encoder.a().sourCream(true); + encoder.checkEncodingIsComplete(); + + final BitSetInsideGroupDecoder decoder = new BitSetInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final FlagsDecoder a = decoder.a(); + assertThat(a.guacamole(), equalTo(true)); + assertThat(a.cheese(), equalTo(true)); + assertThat(a.sourCream(), equalTo(true)); + final BitSetInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + final FlagsDecoder c = b.next().c(); + assertThat(c.guacamole(), equalTo(false)); + assertThat(c.cheese(), equalTo(false)); + assertThat(c.sourCream(), equalTo(true)); + } + + @Test + void allowsEncodingAndDecodingArrayInsideGroupInSchemaDefinedOrder() + { + final ArrayInsideGroupEncoder encoder = new ArrayInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.putA((short)1, (short)2, (short)3, (short)4); + encoder.bCount(1) + .next() + .putC((short)5, (short)6, (short)7, (short)8); + encoder.checkEncodingIsComplete(); + + final ArrayInsideGroupDecoder decoder = new ArrayInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(0), equalTo((short)1)); + assertThat(decoder.a(1), equalTo((short)2)); + assertThat(decoder.a(2), equalTo((short)3)); + assertThat(decoder.a(3), equalTo((short)4)); + final ArrayInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + b.next(); + assertThat(b.c(0), equalTo((short)5)); + assertThat(b.c(1), equalTo((short)6)); + assertThat(b.c(2), equalTo((short)7)); + assertThat(b.c(3), equalTo((short)8)); + assertThat(decoder.toString(), containsString("a=[1,2,3,4]|b=[(c=[5,6,7,8])]")); + } + + @Test + void disallowsEncodingArrayInsideGroupBeforeCallingNext1() + { + final ArrayInsideGroupEncoder.BEncoder bEncoder = encodeUntilGroupWithArrayInside(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> bEncoder.putC((short)5, (short)6, (short)7, (short)8)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsEncodingArrayInsideGroupBeforeCallingNext2() + { + final ArrayInsideGroupEncoder.BEncoder bEncoder = encodeUntilGroupWithArrayInside(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> bEncoder.c(0, (short)5)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsEncodingArrayInsideGroupBeforeCallingNext3() + { + final ArrayInsideGroupEncoder.BEncoder bEncoder = encodeUntilGroupWithArrayInside(); + final byte[] bytes = {5, 6, 7, 8}; + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> bEncoder.putC(bytes, 0, 4)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsEncodingArrayInsideGroupBeforeCallingNext4() + { + final ArrayInsideGroupEncoder.BEncoder bEncoder = encodeUntilGroupWithArrayInside(); + final UnsafeBuffer buffer = new UnsafeBuffer(new byte[8]); + buffer.putByte(0, (byte)5); + buffer.putByte(2, (byte)6); + buffer.putByte(4, (byte)7); + buffer.putByte(6, (byte)8); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> bEncoder.putC(buffer, 0, 4)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + private ArrayInsideGroupEncoder.BEncoder encodeUntilGroupWithArrayInside() + { + final ArrayInsideGroupEncoder encoder = new ArrayInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.putA((short)1, (short)2, (short)3, (short)4); + return encoder.bCount(1); + } + + @Test + void disallowsDecodingArrayInsideGroupBeforeCallingNext1() + { + final ArrayInsideGroupDecoder.BDecoder b = decodeUntilGroupWithArrayInside(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> b.c(0)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsDecodingArrayInsideGroupBeforeCallingNext2() + { + final ArrayInsideGroupDecoder.BDecoder b = decodeUntilGroupWithArrayInside(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> b.getC(new byte[8], 0, 8)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsDecodingArrayInsideGroupBeforeCallingNext3() + { + final ArrayInsideGroupDecoder.BDecoder b = decodeUntilGroupWithArrayInside(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> b.getC(new ExpandableArrayBuffer(), 0, 8)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsDecodingArrayInsideGroupBeforeCallingNext4() + { + final ArrayInsideGroupDecoder.BDecoder b = decodeUntilGroupWithArrayInside(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> b.wrapC(new UnsafeBuffer())); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + private ArrayInsideGroupDecoder.BDecoder decodeUntilGroupWithArrayInside() + { + final ArrayInsideGroupEncoder encoder = new ArrayInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.putA((short)1, (short)2, (short)3, (short)4); + encoder.bCount(1) + .next() + .putC((short)5, (short)6, (short)7, (short)8); + encoder.checkEncodingIsComplete(); + + final ArrayInsideGroupDecoder decoder = new ArrayInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(0), equalTo((short)1)); + assertThat(decoder.a(1), equalTo((short)2)); + assertThat(decoder.a(2), equalTo((short)3)); + assertThat(decoder.a(3), equalTo((short)4)); + final ArrayInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + return b; + } + + @Test + void allowsReEncodingTopLevelArrayViaReWrap() + { + final ArrayInsideGroupEncoder encoder = new ArrayInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.putA((short)1, (short)2, (short)3, (short)4); + encoder.bCount(1) + .next() + .putC((short)5, (short)6, (short)7, (short)8); + + encoder.putA((short)9, (short)10, (short)11, (short)12); + encoder.checkEncodingIsComplete(); + + final ArrayInsideGroupDecoder decoder = new ArrayInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(0), equalTo((short)9)); + assertThat(decoder.a(1), equalTo((short)10)); + assertThat(decoder.a(2), equalTo((short)11)); + assertThat(decoder.a(3), equalTo((short)12)); + final ArrayInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + b.next(); + assertThat(b.c(0), equalTo((short)5)); + assertThat(b.c(1), equalTo((short)6)); + assertThat(b.c(2), equalTo((short)7)); + assertThat(b.c(3), equalTo((short)8)); + } + + @Test + void allowsEncodingAndDecodingGroupFieldsInSchemaDefinedOrder1() + { + final MultipleGroupsEncoder encoder = new MultipleGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.bCount(0); + encoder.dCount(1).next().e(43); + encoder.checkEncodingIsComplete(); + + final MultipleGroupsDecoder decoder = new MultipleGroupsDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.b().count(), equalTo(0)); + final MultipleGroupsDecoder.DDecoder d = decoder.d(); + assertThat(d.count(), equalTo(1)); + assertThat(d.next().e(), equalTo(43)); + assertThat(decoder.toString(), containsString("a=42|b=[]|d=[(e=43)]")); + } + + @Test + void allowsEncodingAndDecodingGroupFieldsInSchemaDefinedOrder2() + { + final MultipleGroupsEncoder encoder = new MultipleGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(41); + encoder.bCount(1).next().c(42); + encoder.dCount(1).next().e(43); + encoder.checkEncodingIsComplete(); + + final MultipleGroupsDecoder decoder = new MultipleGroupsDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(41)); + final MultipleGroupsDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(42)); + final MultipleGroupsDecoder.DDecoder d = decoder.d(); + assertThat(d.count(), equalTo(1)); + assertThat(d.next().e(), equalTo(43)); + } + + @Test + void allowsReEncodingTopLevelPrimitiveFieldsAfterGroups() + { + final MultipleGroupsEncoder encoder = new MultipleGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(41); + encoder.bCount(1).next().c(42); + encoder.dCount(1).next().e(43); + encoder.a(44); + encoder.checkEncodingIsComplete(); + + final MultipleGroupsDecoder decoder = new MultipleGroupsDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(44)); + final MultipleGroupsDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(42)); + final MultipleGroupsDecoder.DDecoder d = decoder.d(); + assertThat(d.count(), equalTo(1)); + assertThat(d.next().e(), equalTo(43)); + } + + @Test + void disallowsMissedEncodingOfGroupField() + { + final MultipleGroupsEncoder encoder = new MultipleGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(41); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.dCount(0)); + assertThat(exception.getMessage(), + containsString("Cannot encode count of repeating group \"d\" in state: V0_BLOCK")); + } + + @Test + void disallowsReEncodingEarlierGroupFields() + { + final MultipleGroupsEncoder encoder = new MultipleGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(41); + encoder.bCount(1).next().c(42); + encoder.dCount(1).next().e(43); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.bCount(1)); + assertThat(exception.getMessage(), + containsString("Cannot encode count of repeating group \"b\" in state: V0_D_1_BLOCK")); + } + + @Test + void disallowsReEncodingLatestGroupField() + { + final MultipleGroupsEncoder encoder = new MultipleGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(41); + encoder.bCount(1).next().c(42); + encoder.dCount(1).next().e(43); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> encoder.dCount(1)); + assertThat(exception.getMessage(), + containsString("Cannot encode count of repeating group \"d\" in state: V0_D_1_BLOCK")); + } + + @Test + void disallowsMissedDecodingOfGroupField() + { + final MultipleGroupsEncoder encoder = new MultipleGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(41); + encoder.bCount(1).next().c(42); + encoder.dCount(1).next().e(43); + encoder.checkEncodingIsComplete(); + + final MultipleGroupsDecoder decoder = new MultipleGroupsDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(41)); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, decoder::d); + assertThat(exception.getMessage(), + containsString("Cannot decode count of repeating group \"d\" in state: V0_BLOCK")); + } + + @Test + void disallowsReDecodingEarlierGroupField() + { + final MultipleGroupsEncoder encoder = new MultipleGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(41); + encoder.bCount(1).next().c(42); + encoder.dCount(1).next().e(43); + encoder.checkEncodingIsComplete(); + + final MultipleGroupsDecoder decoder = new MultipleGroupsDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(41)); + final MultipleGroupsDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(42)); + final MultipleGroupsDecoder.DDecoder d = decoder.d(); + assertThat(d.count(), equalTo(1)); + assertThat(d.next().e(), equalTo(43)); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, decoder::b); + assertThat(exception.getMessage(), + containsString("Cannot decode count of repeating group \"b\" in state: V0_D_1_BLOCK")); + } + + @Test + void disallowsReDecodingLatestGroupField() + { + final MultipleGroupsEncoder encoder = new MultipleGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(41); + encoder.bCount(1).next().c(42); + encoder.dCount(1).next().e(43); + encoder.checkEncodingIsComplete(); + + final MultipleGroupsDecoder decoder = new MultipleGroupsDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(41)); + final MultipleGroupsDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(42)); + final MultipleGroupsDecoder.DDecoder d = decoder.d(); + assertThat(d.count(), equalTo(1)); + assertThat(d.next().e(), equalTo(43)); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, decoder::d); + assertThat(exception.getMessage(), + containsString("Cannot decode count of repeating group \"d\" in state: V0_D_1_BLOCK")); + } + + @Test + void allowsNewDecoderToDecodeAddedVarData() + { + final AddVarDataV1Encoder encoder = new AddVarDataV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.b("abc"); + encoder.checkEncodingIsComplete(); + + final AddVarDataV1Decoder decoder = new AddVarDataV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.b(), equalTo("abc")); + } + + @Test + void allowsNewDecoderToDecodeMissingAddedVarDataAsNullValue1() + { + final AddVarDataV0Encoder encoder = new AddVarDataV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddVarDataV1Decoder decoder = new AddVarDataV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.b(), equalTo("")); + assertThat(decoder.toString(), containsString("a=42|b=''")); + } + + @Test + void allowsNewDecoderToDecodeMissingAddedVarDataAsNullValue2() + { + final AddVarDataV0Encoder encoder = new AddVarDataV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddVarDataV1Decoder decoder = new AddVarDataV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.getB(new StringBuilder()), equalTo(0)); + } + + @Test + void allowsNewDecoderToDecodeMissingAddedVarDataAsNullValue3() + { + final AddVarDataV0Encoder encoder = new AddVarDataV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddVarDataV1Decoder decoder = new AddVarDataV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.getB(new byte[3], 0, 3), equalTo(0)); + } + + @Test + void allowsNewDecoderToDecodeMissingAddedVarDataAsNullValue4() + { + final AddVarDataV0Encoder encoder = new AddVarDataV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddVarDataV1Decoder decoder = new AddVarDataV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.getB(new ExpandableArrayBuffer(), 0, 3), equalTo(0)); + } + + @Test + void allowsNewDecoderToDecodeMissingAddedVarDataAsNullValue5() + { + final AddVarDataV0Encoder encoder = new AddVarDataV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddVarDataV1Decoder decoder = new AddVarDataV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.bLength(), equalTo(0)); + } + + @Test + void allowsEncodingAndDecodingAsciiInsideGroupInSchemaDefinedOrder1() + { + final AsciiInsideGroupEncoder encoder = new AsciiInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a("GBPUSD"); + encoder.bCount(1) + .next() + .c("EURUSD"); + encoder.checkEncodingIsComplete(); + + final AsciiInsideGroupDecoder decoder = new AsciiInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo("GBPUSD")); + final AsciiInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + b.next(); + assertThat(b.c(), equalTo("EURUSD")); + assertThat(decoder.toString(), containsString("a=GBPUSD|b=[(c=EURUSD)]")); + } + + @Test + void allowsEncodingAndDecodingAsciiInsideGroupInSchemaDefinedOrder2() + { + final AsciiInsideGroupEncoder encoder = new AsciiInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + final byte[] gbpUsdBytes = "GBPUSD".getBytes(StandardCharsets.US_ASCII); + encoder.putA(gbpUsdBytes, 0); + encoder.bCount(1) + .next() + .c(0, (byte)'E') + .c(1, (byte)'U') + .c(2, (byte)'R') + .c(3, (byte)'U') + .c(4, (byte)'S') + .c(5, (byte)'D'); + encoder.checkEncodingIsComplete(); + + final AsciiInsideGroupDecoder decoder = new AsciiInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final byte[] aBytes = new byte[6]; + decoder.getA(aBytes, 0); + assertThat(aBytes, equalTo(gbpUsdBytes)); + final AsciiInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + b.next(); + assertThat(b.c(0), equalTo((byte)'E')); + assertThat(b.c(1), equalTo((byte)'U')); + assertThat(b.c(2), equalTo((byte)'R')); + assertThat(b.c(3), equalTo((byte)'U')); + assertThat(b.c(4), equalTo((byte)'S')); + assertThat(b.c(5), equalTo((byte)'D')); + } + + @Test + void disallowsEncodingAsciiInsideGroupBeforeCallingNext1() + { + final AsciiInsideGroupEncoder.BEncoder bEncoder = encodeUntilGroupWithAsciiInside(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> bEncoder.c("EURUSD")); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsEncodingAsciiInsideGroupBeforeCallingNext2() + { + final AsciiInsideGroupEncoder.BEncoder bEncoder = encodeUntilGroupWithAsciiInside(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> bEncoder.c(0, (byte)'E')); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsEncodingAsciiInsideGroupBeforeCallingNext3() + { + final AsciiInsideGroupEncoder.BEncoder bEncoder = encodeUntilGroupWithAsciiInside(); + final byte[] eurUsdBytes = "EURUSD".getBytes(StandardCharsets.US_ASCII); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> bEncoder.putC(eurUsdBytes, 0)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + private AsciiInsideGroupEncoder.BEncoder encodeUntilGroupWithAsciiInside() + { + final AsciiInsideGroupEncoder encoder = new AsciiInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a("GBPUSD"); + return encoder.bCount(1); + } + + @Test + void disallowsDecodingAsciiInsideGroupBeforeCallingNext1() + { + final AsciiInsideGroupDecoder.BDecoder b = decodeUntilGroupWithAsciiInside(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> b.c(0)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsDecodingAsciiInsideGroupBeforeCallingNext2() + { + final AsciiInsideGroupDecoder.BDecoder b = decodeUntilGroupWithAsciiInside(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> b.getC(new byte[6], 0)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsDecodingAsciiInsideGroupBeforeCallingNext3() + { + final AsciiInsideGroupDecoder.BDecoder b = decodeUntilGroupWithAsciiInside(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, b::c); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + @Test + void disallowsDecodingAsciiInsideGroupBeforeCallingNext4() + { + final AsciiInsideGroupDecoder.BDecoder b = decodeUntilGroupWithAsciiInside(); + final Exception exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> b.getC(new StringBuilder())); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_B_N")); + } + + private AsciiInsideGroupDecoder.BDecoder decodeUntilGroupWithAsciiInside() + { + final AsciiInsideGroupEncoder encoder = new AsciiInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a("GBPUSD"); + encoder.bCount(1) + .next() + .c("EURUSD"); + encoder.checkEncodingIsComplete(); + + final AsciiInsideGroupDecoder decoder = new AsciiInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo("GBPUSD")); + final AsciiInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + return b; + } + + @Test + void allowsReEncodingTopLevelAsciiViaReWrap() + { + final AsciiInsideGroupEncoder encoder = new AsciiInsideGroupEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a("GBPUSD"); + encoder.bCount(1) + .next() + .c("EURUSD"); + + encoder.a("CADUSD"); + encoder.checkEncodingIsComplete(); + + final AsciiInsideGroupDecoder decoder = new AsciiInsideGroupDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo("CADUSD")); + final AsciiInsideGroupDecoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + b.next(); + assertThat(b.c(), equalTo("EURUSD")); + } + + @Test + void allowsNewDecoderToDecodeAddedAsciiFieldBeforeGroup1() + { + final AddAsciiBeforeGroupV1Encoder encoder = new AddAsciiBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1) + .d("EURUSD") + .bCount(1) + .next().c(2); + encoder.checkEncodingIsComplete(); + + final AddAsciiBeforeGroupV1Decoder decoder = new AddAsciiBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.d(), equalTo("EURUSD")); + final AddAsciiBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeAddedAsciiFieldBeforeGroup2() + { + final AddAsciiBeforeGroupV1Encoder encoder = new AddAsciiBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1) + .d("EURUSD") + .bCount(1) + .next().c(2); + encoder.checkEncodingIsComplete(); + + final AddAsciiBeforeGroupV1Decoder decoder = new AddAsciiBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final StringBuilder aValue = new StringBuilder(); + decoder.getD(aValue); + assertThat(aValue.toString(), equalTo("EURUSD")); + final AddAsciiBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + + @Test + void allowsNewDecoderToDecodeAddedAsciiFieldBeforeGroup3() + { + final AddAsciiBeforeGroupV1Encoder encoder = new AddAsciiBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + final byte[] eurUsdBytes = "EURUSD".getBytes(StandardCharsets.US_ASCII); + encoder.a(1) + .putD(eurUsdBytes, 0) + .bCount(1) + .next().c(2); + encoder.checkEncodingIsComplete(); + + final AddAsciiBeforeGroupV1Decoder decoder = new AddAsciiBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final byte[] aBytes = new byte[6]; + decoder.getD(aBytes, 0); + assertThat(aBytes, equalTo(eurUsdBytes)); + final AddAsciiBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + + @Test + void allowsNewDecoderToDecodeAddedAsciiFieldBeforeGroup4() + { + final AddAsciiBeforeGroupV1Encoder encoder = new AddAsciiBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1) + .d(0, (byte)'E') + .d(1, (byte)'U') + .d(2, (byte)'R') + .d(3, (byte)'U') + .d(4, (byte)'S') + .d(5, (byte)'D') + .bCount(1) + .next().c(2); + encoder.checkEncodingIsComplete(); + + final AddAsciiBeforeGroupV1Decoder decoder = new AddAsciiBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.d(0), equalTo((byte)'E')); + assertThat(decoder.d(1), equalTo((byte)'U')); + assertThat(decoder.d(2), equalTo((byte)'R')); + assertThat(decoder.d(3), equalTo((byte)'U')); + assertThat(decoder.d(4), equalTo((byte)'S')); + assertThat(decoder.d(5), equalTo((byte)'D')); + final AddAsciiBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeMissingAsciiFieldBeforeGroupAsNullValue1() + { + final AddAsciiBeforeGroupV0Encoder encoder = new AddAsciiBeforeGroupV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddAsciiBeforeGroupV1Decoder decoder = new AddAsciiBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.d(0), equalTo(AddAsciiBeforeGroupV1Decoder.dNullValue())); + assertThat(decoder.d(1), equalTo(AddAsciiBeforeGroupV1Decoder.dNullValue())); + assertThat(decoder.d(2), equalTo(AddAsciiBeforeGroupV1Decoder.dNullValue())); + assertThat(decoder.d(3), equalTo(AddAsciiBeforeGroupV1Decoder.dNullValue())); + assertThat(decoder.d(4), equalTo(AddAsciiBeforeGroupV1Decoder.dNullValue())); + assertThat(decoder.d(5), equalTo(AddAsciiBeforeGroupV1Decoder.dNullValue())); + final AddAsciiBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeMissingAsciiFieldBeforeGroupAsNullValue2() + { + final AddAsciiBeforeGroupV0Encoder encoder = new AddAsciiBeforeGroupV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddAsciiBeforeGroupV1Decoder decoder = new AddAsciiBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.d(), equalTo("")); + final AddAsciiBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeMissingAsciiFieldBeforeGroupAsNullValue3() + { + final AddAsciiBeforeGroupV0Encoder encoder = new AddAsciiBeforeGroupV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddAsciiBeforeGroupV1Decoder decoder = new AddAsciiBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final StringBuilder aValue = new StringBuilder(); + assertThat(decoder.getD(aValue), equalTo(0)); + assertThat(aValue.length(), equalTo(0)); + final AddAsciiBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToDecodeMissingAsciiFieldBeforeGroupAsNullValue4() + { + final AddAsciiBeforeGroupV0Encoder encoder = new AddAsciiBeforeGroupV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion0(); + + final AddAsciiBeforeGroupV1Decoder decoder = new AddAsciiBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + assertThat(decoder.getD(new byte[6], 0), equalTo(0)); + final AddAsciiBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsNewDecoderToSkipPresentButAddedAsciiFieldBeforeGroup() + { + final AddAsciiBeforeGroupV1Encoder encoder = new AddAsciiBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1) + .d("EURUSD") + .bCount(1) + .next().c(2); + encoder.checkEncodingIsComplete(); + + final AddAsciiBeforeGroupV1Decoder decoder = new AddAsciiBeforeGroupV1Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddAsciiBeforeGroupV1Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsOldDecoderToSkipAddedAsciiFieldBeforeGroup() + { + final AddAsciiBeforeGroupV1Encoder encoder = new AddAsciiBeforeGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1) + .d("EURUSD") + .bCount(1) + .next().c(2); + encoder.checkEncodingIsComplete(); + + modifyHeaderToLookLikeVersion1(); + + final AddAsciiBeforeGroupV0Decoder decoder = new AddAsciiBeforeGroupV0Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final AddAsciiBeforeGroupV0Decoder.BDecoder b = decoder.b(); + assertThat(b.count(), equalTo(1)); + assertThat(b.next().c(), equalTo(2)); + } + + @Test + void allowsEncodeAndDecodeOfMessagesWithNoBlock() + { + final NoBlockEncoder encoder = new NoBlockEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a("abc"); + encoder.checkEncodingIsComplete(); + + final NoBlockDecoder decoder = new NoBlockDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo("abc")); + } + + @Test + void allowsEncodeAndDecodeOfGroupsWithNoBlock() + { + final GroupWithNoBlockEncoder encoder = new GroupWithNoBlockEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.aCount(1).next().b("abc"); + encoder.checkEncodingIsComplete(); + + final GroupWithNoBlockDecoder decoder = new GroupWithNoBlockDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + final GroupWithNoBlockDecoder.ADecoder a = decoder.a(); + assertThat(a.count(), equalTo(1)); + assertThat(a.next().b(), equalTo("abc")); + } + + @Test + void disallowsEncodingElementOfEmptyGroup1() + { + final MultipleGroupsEncoder encoder = new MultipleGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final MultipleGroupsEncoder.BEncoder bEncoder = encoder.bCount(0); + encoder.dCount(1).next().e(43); + final IllegalStateException exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> bEncoder.c(44)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_D_1_BLOCK")); + } + + @Test + void disallowsEncodingElementOfEmptyGroup2() + { + final NestedGroupsEncoder encoder = new NestedGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final NestedGroupsEncoder.BEncoder bEncoder = encoder.bCount(1); + bEncoder.next(); + bEncoder.c(43); + final NestedGroupsEncoder.BEncoder.DEncoder dEncoder = bEncoder.dCount(0); + bEncoder.fCount(0); + encoder.hCount(0); + final IllegalStateException exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> dEncoder.e(44)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.d.e\" in state: V0_H_DONE")); + } + + @Test + void disallowsEncodingElementOfEmptyGroup3() + { + final NestedGroupsEncoder encoder = new NestedGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final NestedGroupsEncoder.BEncoder bEncoder = encoder.bCount(1); + bEncoder.next(); + bEncoder.c(43); + final NestedGroupsEncoder.BEncoder.DEncoder dEncoder = bEncoder.dCount(0); + bEncoder.fCount(0); + final IllegalStateException exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> dEncoder.e(44)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.d.e\" in state: V0_B_1_F_DONE")); + } + + @Test + void disallowsEncodingElementOfEmptyGroup4() + { + final AddPrimitiveInsideGroupV1Encoder encoder = new AddPrimitiveInsideGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final AddPrimitiveInsideGroupV1Encoder.BEncoder bEncoder = encoder.bCount(0); + final IllegalStateException exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> bEncoder.c(43)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V1_B_DONE")); + } + + @Test + void disallowsEncodingElementOfEmptyGroup5() + { + final GroupAndVarLengthEncoder encoder = new GroupAndVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(42); + final GroupAndVarLengthEncoder.BEncoder bEncoder = encoder.bCount(0); + encoder.d("abc"); + final IllegalStateException exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, () -> bEncoder.c(43)); + assertThat(exception.getMessage(), containsString("Cannot access field \"b.c\" in state: V0_D_DONE")); + } + + @Test + void allowsEncodingAndDecodingNestedGroupWithVarDataInSchemaDefinedOrder() + { + final NestedGroupWithVarLengthEncoder encoder = new NestedGroupWithVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1); + final NestedGroupWithVarLengthEncoder.BEncoder bEncoder = encoder.bCount(3); + bEncoder.next().c(2).dCount(0); + bEncoder.next().c(3).dCount(1).next().e(4).f("abc"); + bEncoder.next().c(5).dCount(2).next().e(6).f("def").next().e(7).f("ghi"); + encoder.checkEncodingIsComplete(); + + final NestedGroupWithVarLengthDecoder decoder = new NestedGroupWithVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final NestedGroupWithVarLengthDecoder.BDecoder bDecoder = decoder.b(); + assertThat(bDecoder.count(), equalTo(3)); + assertThat(bDecoder.next().c(), equalTo(2)); + assertThat(bDecoder.d().count(), equalTo(0)); + assertThat(bDecoder.next().c(), equalTo(3)); + final NestedGroupWithVarLengthDecoder.BDecoder.DDecoder dDecoder = bDecoder.d(); + assertThat(dDecoder.count(), equalTo(1)); + assertThat(dDecoder.next().e(), equalTo(4)); + assertThat(dDecoder.f(), equalTo("abc")); + assertThat(bDecoder.next().c(), equalTo(5)); + assertThat(bDecoder.d(), sameInstance(dDecoder)); + assertThat(dDecoder.count(), equalTo(2)); + assertThat(dDecoder.next().e(), equalTo(6)); + assertThat(dDecoder.f(), equalTo("def")); + assertThat(dDecoder.next().e(), equalTo(7)); + assertThat(dDecoder.f(), equalTo("ghi")); + } + + @CsvSource(value = { + "1,V0_B_1_D_N_BLOCK", + "2,V0_B_N_D_N_BLOCK" + }) + @ParameterizedTest + void disallowsMissedEncodingOfVarLengthFieldInNestedGroupToNextInnerElement( + final int bCount, + final String expectedState) + { + final NestedGroupWithVarLengthEncoder encoder = new NestedGroupWithVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1); + final NestedGroupWithVarLengthEncoder.BEncoder bEncoder = encoder.bCount(bCount); + final NestedGroupWithVarLengthEncoder.BEncoder.DEncoder dEncoder = bEncoder.next().c(5).dCount(2); + dEncoder.next().e(7); + final IllegalStateException exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, dEncoder::next); + assertThat(exception.getMessage(), + containsString("Cannot access next element in repeating group \"b.d\" in state: " + expectedState)); + assertThat(exception.getMessage(), + containsString("Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + } + + @CsvSource(value = { + "1,V0_B_N_D_1_BLOCK", + "2,V0_B_N_D_N_BLOCK", + }) + @ParameterizedTest + void disallowsMissedEncodingOfVarLengthFieldInNestedGroupToNextOuterElement( + final int dCount, + final String expectedState) + { + final NestedGroupWithVarLengthEncoder encoder = new NestedGroupWithVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1); + final NestedGroupWithVarLengthEncoder.BEncoder bEncoder = encoder.bCount(2); + bEncoder.next().c(3).dCount(dCount).next().e(4); + final IllegalStateException exception = + assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, bEncoder::next); + assertThat(exception.getMessage(), + containsString("Cannot access next element in repeating group \"b\" in state: " + expectedState)); + assertThat(exception.getMessage(), + containsString("Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + } + + @Test + void disallowsMissedDecodingOfVarLengthFieldInNestedGroupToNextInnerElement1() + { + final NestedGroupWithVarLengthEncoder encoder = new NestedGroupWithVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1); + final NestedGroupWithVarLengthEncoder.BEncoder bEncoder = encoder.bCount(1); + bEncoder.next().c(2).dCount(2).next().e(3).f("abc").next().e(4).f("def"); + encoder.checkEncodingIsComplete(); + + final NestedGroupWithVarLengthDecoder decoder = new NestedGroupWithVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final NestedGroupWithVarLengthDecoder.BDecoder bDecoder = decoder.b(); + assertThat(bDecoder.count(), equalTo(1)); + assertThat(bDecoder.next().c(), equalTo(2)); + final NestedGroupWithVarLengthDecoder.BDecoder.DDecoder dDecoder = bDecoder.d(); + assertThat(dDecoder.count(), equalTo(2)); + assertThat(dDecoder.next().e(), equalTo(3)); + final Exception exception = assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, dDecoder::next); + assertThat(exception.getMessage(), + containsString("Cannot access next element in repeating group \"b.d\" in state: V0_B_1_D_N_BLOCK.")); + assertThat(exception.getMessage(), + containsString("Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + } + + @Test + void disallowsMissedDecodingOfVarLengthFieldInNestedGroupToNextInnerElement2() + { + final NestedGroupWithVarLengthEncoder encoder = new NestedGroupWithVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1); + final NestedGroupWithVarLengthEncoder.BEncoder bEncoder = encoder.bCount(2); + bEncoder.next().c(2).dCount(2).next().e(3).f("abc").next().e(4).f("def"); + bEncoder.next().c(5).dCount(0); + encoder.checkEncodingIsComplete(); + + final NestedGroupWithVarLengthDecoder decoder = new NestedGroupWithVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final NestedGroupWithVarLengthDecoder.BDecoder bDecoder = decoder.b(); + assertThat(bDecoder.count(), equalTo(2)); + assertThat(bDecoder.next().c(), equalTo(2)); + final NestedGroupWithVarLengthDecoder.BDecoder.DDecoder dDecoder = bDecoder.d(); + assertThat(dDecoder.count(), equalTo(2)); + assertThat(dDecoder.next().e(), equalTo(3)); + final Exception exception = assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, dDecoder::next); + assertThat(exception.getMessage(), + containsString("Cannot access next element in repeating group \"b.d\" in state: V0_B_N_D_N_BLOCK.")); + assertThat(exception.getMessage(), + containsString("Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + } + + @Test + void disallowsMissedDecodingOfVarLengthFieldInNestedGroupToNextOuterElement1() + { + final NestedGroupWithVarLengthEncoder encoder = new NestedGroupWithVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1); + final NestedGroupWithVarLengthEncoder.BEncoder bEncoder = encoder.bCount(2); + bEncoder.next().c(2).dCount(2).next().e(3).f("abc").next().e(4).f("def"); + bEncoder.next().c(5).dCount(0); + encoder.checkEncodingIsComplete(); + + final NestedGroupWithVarLengthDecoder decoder = new NestedGroupWithVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final NestedGroupWithVarLengthDecoder.BDecoder bDecoder = decoder.b(); + assertThat(bDecoder.count(), equalTo(2)); + assertThat(bDecoder.next().c(), equalTo(2)); + final NestedGroupWithVarLengthDecoder.BDecoder.DDecoder dDecoder = bDecoder.d(); + assertThat(dDecoder.count(), equalTo(2)); + assertThat(dDecoder.next().e(), equalTo(3)); + final Exception exception = assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, bDecoder::next); + assertThat(exception.getMessage(), + containsString("Cannot access next element in repeating group \"b\" in state: V0_B_N_D_N_BLOCK.")); + assertThat(exception.getMessage(), + containsString("Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + } + + @Test + void disallowsMissedDecodingOfVarLengthFieldInNestedGroupToNextOuterElement2() + { + final NestedGroupWithVarLengthEncoder encoder = new NestedGroupWithVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1); + final NestedGroupWithVarLengthEncoder.BEncoder bEncoder = encoder.bCount(2); + bEncoder.next().c(2).dCount(1).next().e(3).f("abc"); + bEncoder.next().c(5).dCount(0); + encoder.checkEncodingIsComplete(); + + final NestedGroupWithVarLengthDecoder decoder = new NestedGroupWithVarLengthDecoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + assertThat(decoder.a(), equalTo(1)); + final NestedGroupWithVarLengthDecoder.BDecoder bDecoder = decoder.b(); + assertThat(bDecoder.count(), equalTo(2)); + assertThat(bDecoder.next().c(), equalTo(2)); + final NestedGroupWithVarLengthDecoder.BDecoder.DDecoder dDecoder = bDecoder.d(); + assertThat(dDecoder.count(), equalTo(1)); + assertThat(dDecoder.next().e(), equalTo(3)); + final Exception exception = assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, bDecoder::next); + assertThat(exception.getMessage(), + containsString("Cannot access next element in repeating group \"b\" in state: V0_B_N_D_1_BLOCK.")); + assertThat(exception.getMessage(), + containsString("Expected one of these transitions: [\"b.d.e(?)\", \"b.d.fLength()\", \"b.d.f(?)\"].")); + } + + @Test + void disallowsIncompleteMessagesDueToMissingVarLengthField1() + { + final MultipleVarLengthEncoder encoder = new MultipleVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).b("abc"); + final Exception exception = assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, encoder::checkEncodingIsComplete); + assertThat(exception.getMessage(), containsString( + "Not fully encoded, current state: V0_B_DONE, allowed transitions: \"cLength()\", \"c(?)\"")); + } + + @Test + void disallowsIncompleteMessagesDueToMissingVarLengthField2() + { + final NoBlockEncoder encoder = new NoBlockEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + final Exception exception = assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, encoder::checkEncodingIsComplete); + assertThat(exception.getMessage(), containsString( + "Not fully encoded, current state: V0_BLOCK, allowed transitions: \"aLength()\", \"a(?)\"")); + } + + @Test + void disallowsIncompleteMessagesDueToMissingTopLevelGroup1() + { + final MultipleGroupsEncoder encoder = new MultipleGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(0); + final Exception exception = assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, encoder::checkEncodingIsComplete); + assertThat(exception.getMessage(), containsString( + "Not fully encoded, current state: V0_B_DONE, allowed transitions: " + + "\"b.resetCountToIndex()\", \"dCount(0)\", \"dCount(>0)\"")); + } + + @Test + void disallowsIncompleteMessagesDueToMissingTopLevelGroup2() + { + final MultipleGroupsEncoder encoder = new MultipleGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(1).next().c(2); + final Exception exception = assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, encoder::checkEncodingIsComplete); + assertThat(exception.getMessage(), containsString( + "Not fully encoded, current state: V0_B_1_BLOCK, allowed transitions: " + + "\"b.c(?)\", \"b.resetCountToIndex()\", \"dCount(0)\", \"dCount(>0)\"")); + } + + @Test + void disallowsIncompleteMessagesDueToMissingTopLevelGroup3() + { + final MultipleGroupsEncoder encoder = new MultipleGroupsEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1); + final Exception exception = assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, encoder::checkEncodingIsComplete); + assertThat(exception.getMessage(), containsString( + "Not fully encoded, current state: V0_BLOCK, allowed transitions: " + + "\"a(?)\", \"bCount(0)\", \"bCount(>0)\"")); + } + + @CsvSource(value = { + "1,V0_B_1_BLOCK", + "2,V0_B_N_BLOCK", + }) + @ParameterizedTest + void disallowsIncompleteMessagesDueToMissingNestedGroup1(final int bCount, final String expectedState) + { + final NestedGroupWithVarLengthEncoder encoder = new NestedGroupWithVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(bCount).next().c(2); + final Exception exception = assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, encoder::checkEncodingIsComplete); + assertThat(exception.getMessage(), containsString("Not fully encoded, current state: " + expectedState)); + } + + @CsvSource(value = { + "1,1,V0_B_1_D_N", + "1,2,V0_B_1_D_N", + "2,0,V0_B_N_D_DONE", + "2,1,V0_B_N_D_N", + "2,2,V0_B_N_D_N", + }) + @ParameterizedTest + void disallowsIncompleteMessagesDueToMissingNestedGroup2( + final int bCount, + final int dCount, + final String expectedState) + { + final NestedGroupWithVarLengthEncoder encoder = new NestedGroupWithVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(bCount).next().c(2).dCount(dCount); + final Exception exception = assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, encoder::checkEncodingIsComplete); + assertThat(exception.getMessage(), containsString("Not fully encoded, current state: " + expectedState)); + } + + @CsvSource(value = { + "1,1,V0_B_1_D_1_BLOCK", + "1,2,V0_B_1_D_N_BLOCK", + "2,1,V0_B_N_D_1_BLOCK", + "2,2,V0_B_N_D_N_BLOCK", + }) + @ParameterizedTest + void disallowsIncompleteMessagesDueToMissingVarDataInNestedGroup( + final int bCount, + final int dCount, + final String expectedState) + { + final NestedGroupWithVarLengthEncoder encoder = new NestedGroupWithVarLengthEncoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder); + encoder.a(1).bCount(bCount).next().c(2).dCount(dCount).next().e(10); + final Exception exception = assertThrows(INCORRECT_ORDER_EXCEPTION_CLASS, encoder::checkEncodingIsComplete); + assertThat(exception.getMessage(), containsString("Not fully encoded, current state: " + expectedState)); + } + + private void modifyHeaderToLookLikeVersion0() + { + messageHeaderDecoder.wrap(buffer, OFFSET); + final int v1TemplateId = messageHeaderDecoder.templateId() + 1_000; + messageHeaderEncoder.wrap(buffer, OFFSET); + messageHeaderEncoder.templateId(v1TemplateId).version(0); + } + + private void modifyHeaderToLookLikeVersion1() + { + messageHeaderDecoder.wrap(buffer, OFFSET); + assert messageHeaderDecoder.version() == 1; + final int v0TemplateId = messageHeaderDecoder.templateId() - 1_000; + messageHeaderEncoder.wrap(buffer, OFFSET); + messageHeaderEncoder.templateId(v0TemplateId); + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index f12fef3751..3f253ed778 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -15,6 +15,12 @@ */ package uk.co.real_logic.sbe.generation.java; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.generation.common.PrecedenceChecks; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; import org.agrona.concurrent.UnsafeBuffer; @@ -22,23 +28,23 @@ import org.agrona.generation.StringWriterOutputManager; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.Tests; -import uk.co.real_logic.sbe.ir.Ir; -import uk.co.real_logic.sbe.xml.IrGenerator; -import uk.co.real_logic.sbe.xml.MessageSchema; -import uk.co.real_logic.sbe.xml.ParserOptions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.ByteOrder; +import java.util.Arrays; import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.Matchers.*; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import static uk.co.real_logic.sbe.generation.java.JavaGenerator.MESSAGE_HEADER_DECODER_TYPE; import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -251,6 +257,37 @@ void shouldGenerateBasicMessage() throws Exception assertThat(msgFlyweight.toString(), startsWith("[Car]")); } + @Test + void shouldGenerateWithoutPrecedenceChecksByDefault() throws Exception + { + final PrecedenceChecks.Context context = new PrecedenceChecks.Context(); + final PrecedenceChecks precedenceChecks = PrecedenceChecks.newInstance(context); + generator(precedenceChecks).generate(); + + final Field field = Arrays.stream(compileCarEncoder().getDeclaredFields()) + .filter(f -> f.getName().equals(context.precedenceChecksFlagName())) + .findFirst() + .orElse(null); + + assertNull(field); + } + + @Test + void shouldGeneratePrecedenceChecksWhenEnabled() throws Exception + { + final PrecedenceChecks.Context context = new PrecedenceChecks.Context() + .shouldGeneratePrecedenceChecks(true); + final PrecedenceChecks precedenceChecks = PrecedenceChecks.newInstance(context); + generator(precedenceChecks).generate(); + + final Field field = Arrays.stream(compileCarEncoder().getDeclaredFields()) + .filter(f -> f.getName().equals(context.precedenceChecksFlagName())) + .findFirst() + .orElse(null); + + assertNotNull(field); + } + @Test void shouldGenerateRepeatingGroupDecoder() throws Exception { @@ -298,8 +335,12 @@ void shouldGenerateVarDataCodecs() throws Exception final Object encoder = wrap(buffer, compileCarEncoder().getConstructor().newInstance()); final Object decoder = getCarDecoder(buffer, encoder); + setEmptyFuelFiguresGroup(encoder); + setEmptyPerformanceFiguresGroup(encoder); setManufacturer(encoder, expectedManufacturer); + skipFuelFiguresGroup(decoder); + skipPerformanceFiguresGroup(decoder); final String manufacturer = getManufacturer(decoder); assertEquals(expectedManufacturer, manufacturer); @@ -402,28 +443,30 @@ void shouldGenerateGetFixedLengthStringUsingAppendable() throws Exception assertThat(result.toString(), is("R11R12")); } - @Test - void shouldGenerateGetVariableStringUsingAppendable() throws Exception + @ParameterizedTest + @ValueSource(strings = {"Red", "", "Red and Blue"}) + void shouldGenerateGetVariableStringUsingAppendable(final String color) throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); final StringBuilder result = new StringBuilder(); generator().generate(); final Object encoder = wrap(buffer, compileCarEncoder().getDeclaredConstructor().newInstance()); - final Object decoder = getCarDecoder(buffer, encoder); - set(encoder, "color", String.class, "Red"); - get(decoder, "color", result); - assertThat(result.toString(), is("Red")); + setEmptyFuelFiguresGroup(encoder); + setEmptyPerformanceFiguresGroup(encoder); + set(encoder, "manufacturer", String.class, "Bristol"); + set(encoder, "model", String.class, "Britannia"); + set(encoder, "activationCode", String.class, "12345"); + set(encoder, "color", String.class, color); - result.setLength(0); - set(encoder, "color", String.class, ""); - get(decoder, "color", result); - assertThat(result.toString(), is("")); - - result.setLength(0); - set(encoder, "color", String.class, "Red and Blue"); - get(decoder, "color", result); - assertThat(result.toString(), is("Red and Blue")); + final Object decoder = getCarDecoder(buffer, encoder); + skipFuelFiguresGroup(decoder); + skipPerformanceFiguresGroup(decoder); + assertThat(get(decoder, "manufacturer"), equalTo("Bristol")); + assertThat(get(decoder, "model"), equalTo("Britannia")); + assertThat(get(decoder, "activationCode"), equalTo("12345")); + assertThat(get(decoder, "color", result), equalTo(color.length())); + assertThat(result.toString(), equalTo(color)); } @Test @@ -664,6 +707,12 @@ private JavaGenerator generator() return new JavaGenerator(ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager); } + private JavaGenerator generator(final PrecedenceChecks precedenceChecks) + { + return new JavaGenerator(ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, false, + precedenceChecks, outputManager); + } + private void generateTypeStubs() throws IOException { final JavaGenerator javaGenerator = generator(); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java index a48074eb89..beead1799e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java @@ -41,10 +41,30 @@ static Object get(final Object object, final String fieldName) throws Exception return object.getClass().getMethod(fieldName).invoke(object); } - static void get(final Object object, final String fieldName, final Appendable arg) throws Exception + static Object get(final Object object, final String fieldName, final Appendable arg) throws Exception { final String methodName = "get" + Generators.toUpperFirstChar(fieldName); - object.getClass().getMethod(methodName, Appendable.class).invoke(object, arg); + return object.getClass().getMethod(methodName, Appendable.class).invoke(object, arg); + } + + static void skipFuelFiguresGroup(final Object decoder) throws Exception + { + skipGroup(decoder, "fuelFigures"); + } + + static void skipPerformanceFiguresGroup(final Object decoder) throws Exception + { + skipGroup(decoder, "performanceFigures"); + } + + private static void skipGroup(final Object decoder, final String groupName) throws Exception + { + final Object group = get(decoder, groupName); + while ((boolean)get(group, "hasNext")) + { + get(group, "next"); + get(group, "sbeSkip"); + } } static String getManufacturer(final Object decoder) throws Exception @@ -52,6 +72,16 @@ static String getManufacturer(final Object decoder) throws Exception return (String)get(decoder, "manufacturer"); } + static void setEmptyFuelFiguresGroup(final Object encoder) throws Exception + { + encoder.getClass().getMethod("fuelFiguresCount", int.class).invoke(encoder, 0); + } + + static void setEmptyPerformanceFiguresGroup(final Object encoder) throws Exception + { + encoder.getClass().getMethod("performanceFiguresCount", int.class).invoke(encoder, 0); + } + static void setManufacturer(final Object encoder, final String value) throws Exception { encoder.getClass().getMethod("manufacturer", String.class).invoke(encoder, value); diff --git a/sbe-tool/src/test/resources/field-order-check-schema.xml b/sbe-tool/src/test/resources/field-order-check-schema.xml new file mode 100644 index 0000000000..e4d62ebfd6 --- /dev/null +++ b/sbe-tool/src/test/resources/field-order-check-schema.xml @@ -0,0 +1,292 @@ + + + + + + + + + + + + + + + + + + + + + + + + 1 + 2 + + + + 1 + 2 + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From b166f352b8ca67d5a286f151726762e306331d4a Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 6 Dec 2023 14:26:01 +0000 Subject: [PATCH 1064/1594] 1.30.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index f407f84d1d..034552a83e 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.30.0-SNAPSHOT \ No newline at end of file +1.30.0 From 25b007dfda00f629f251dfa7b53cfe8e7f0e79f5 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 6 Dec 2023 14:27:05 +0000 Subject: [PATCH 1065/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 034552a83e..e576fe33d3 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.30.0 +1.31.0-SNAPSHOT From fb3292d1d87b934bd1c889c3bd63cb0f36f94d78 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 14 Dec 2023 10:24:33 +0100 Subject: [PATCH 1066/1594] [C/C++] Add Clang 17. --- .github/workflows/ci.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6a6ef95ea..c6d62899c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -202,8 +202,9 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | - curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${{ matrix.version }} main" + sudo mkdir -p /etc/apt/keyrings/ + curl https://apt.llvm.org/llvm-snapshot.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/llvm-snapshot.gpg + echo "deb [signed-by=/etc/apt/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/focal/ llvm-toolchain-focal-${{ matrix.version }} main" | sudo tee /etc/apt/sources.list.d/llvm.list sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev libidn11 curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz @@ -218,7 +219,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '13', '14', '15', '16' ] + version: [ '13', '14', '15', '16', '17' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} @@ -239,8 +240,9 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | - curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${{ matrix.version }} main" + sudo mkdir -p /etc/apt/keyrings/ + curl https://apt.llvm.org/llvm-snapshot.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/llvm-snapshot.gpg + echo "deb [signed-by=/etc/apt/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${{ matrix.version }} main" | sudo tee /etc/apt/sources.list.d/llvm.list sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz From 062a127e62b6928b0d294d7ef1f5020556d9e344 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 14 Dec 2023 12:32:58 +0100 Subject: [PATCH 1067/1594] [C/C++] Add GCC 13. --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6d62899c2..e317d2bfc8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -147,7 +147,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '11', '12' ] + version: [ '11', '12', '13' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} @@ -168,6 +168,8 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/ppa + sudo apt-get update sudo apt-get install -y g++-${{ matrix.version }} curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz From fa671da7efb8c4834e50a15f8e88745f1dbb936e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 2 Jan 2024 13:11:36 +0100 Subject: [PATCH 1068/1594] Update copyright. --- CMakeLists.txt | 2 +- CONTRIBUTING.md | 2 +- README.md | 2 +- build.gradle | 2 +- config/checkstyle/checkstyle.xml | 2 +- sbe-benchmarks/src/main/cpp/CMakeLists.txt | 2 +- sbe-benchmarks/src/main/cpp/CarBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/CodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/MarketDataBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/benchlet-main.cpp | 2 +- sbe-benchmarks/src/main/cpp/benchlet.h | 2 +- .../src/main/java/uk/co/real_logic/sbe/CarBenchmark.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/package-info.java | 2 +- sbe-samples/src/main/cpp/CMakeLists.txt | 2 +- sbe-samples/src/main/cpp/GeneratedStubExample.cpp | 2 +- sbe-samples/src/main/cpp/OtfExample.cpp | 2 +- .../uk/co/real_logic/sbe/examples/ExampleTokenListener.java | 2 +- .../co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java | 2 +- .../sbe/examples/ExampleUsingGeneratedStubExtension.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java | 2 +- .../main/java/uk/co/real_logic/sbe/examples/package-info.java | 2 +- sbe-tool/src/main/cpp/CMakeLists.txt | 2 +- sbe-tool/src/main/cpp/otf/Encoding.h | 2 +- sbe-tool/src/main/cpp/otf/IrDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/Token.h | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java | 2 +- .../main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java | 2 +- .../java/uk/co/real_logic/sbe/codec/java/MethodSelector.java | 2 +- .../main/java/uk/co/real_logic/sbe/codec/java/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/CodeGenerator.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/Generators.java | 2 +- .../uk/co/real_logic/sbe/generation/TargetCodeGenerator.java | 2 +- .../co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/c/COutputManager.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/c/package-info.java | 2 +- .../real_logic/sbe/generation/common/FieldPrecedenceModel.java | 2 +- .../co/real_logic/sbe/generation/common/PrecedenceChecks.java | 2 +- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java | 2 +- .../real_logic/sbe/generation/cpp/NamespaceOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/cpp/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/csharp/CSharp.java | 2 +- .../uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java | 2 +- .../sbe/generation/csharp/CSharpNamespaceOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/csharp/package-info.java | 2 +- .../uk/co/real_logic/sbe/generation/golang/GolangGenerator.java | 2 +- .../real_logic/sbe/generation/golang/GolangOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/golang/package-info.java | 2 +- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 2 +- .../uk/co/real_logic/sbe/generation/java/JavaOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/JavaUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/package-info.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/RustOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/RustUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/SubGroup.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/package-info.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/package-info.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java | 2 +- .../main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/json/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java | 2 +- .../main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java | 2 +- .../main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/otf/package-info.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java | 2 +- .../java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java | 2 +- .../java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java | 2 +- .../uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/package-info.java | 2 +- sbe-tool/src/test/c/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/c/CComplianceTest.c | 2 +- sbe-tool/src/test/c/CMakeLists.txt | 2 +- sbe-tool/src/test/c/CodeGenTest.cpp | 2 +- sbe-tool/src/test/c/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/c/Issue889Test.cpp | 2 +- sbe-tool/src/test/cpp/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/cpp/CMakeLists.txt | 2 +- sbe-tool/src/test/cpp/CodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeElementsTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp | 2 +- sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp | 2 +- sbe-tool/src/test/cpp/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/cpp/Issue835Test.cpp | 2 +- sbe-tool/src/test/cpp/Issue889Test.cpp | 2 +- sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp | 2 +- sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp | 2 +- .../src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java | 2 +- .../java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java | 2 +- sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java | 2 +- .../test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java | 2 +- .../uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java | 2 +- .../real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java | 2 +- .../real_logic/sbe/generation/java/CharacterEncodingTest.java | 2 +- .../sbe/generation/java/CompositeElementsGenerationTest.java | 2 +- .../real_logic/sbe/generation/java/ConstantCharArrayTest.java | 2 +- .../sbe/generation/java/FixedSizeDataGeneratorTest.java | 2 +- .../real_logic/sbe/generation/java/GenerateFixBinaryTest.java | 2 +- .../real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java | 2 +- .../real_logic/sbe/generation/java/JavaOutputManagerTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java | 2 +- .../sbe/generation/java/PackageOutputManagerTest.java | 2 +- .../co/real_logic/sbe/generation/java/QualifiedYieldTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/ReflectionUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/RewindTest.java | 2 +- .../co/real_logic/sbe/generation/java/SchemaExtensionTest.java | 2 +- .../java/SinceVersionTransformedSchemaJavaGenerationTest.java | 2 +- .../sbe/generation/java/SkipAndDecodedLengthTest.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/ToStringTest.java | 2 +- .../sbe/generation/java/ValueRefWithLowerCaseEnum.java | 2 +- .../real_logic/sbe/generation/java/WarningFormattingTest.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java | 2 +- .../uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java | 2 +- .../co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java | 2 +- .../uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java | 2 +- .../real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java | 2 +- 180 files changed, 180 insertions(+), 180 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 878df9b951..7b78278fca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2023 Real Logic Limited. +# Copyright 2013-2024 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ab34fb164c..24b6402de5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ If you are adding a new file it should have the following header: ``` /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 8affd43e68..c393d2dd26 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ Or run test directly with `Cargo` License (See LICENSE file for full license) ------------------------------------------- -Copyright 2013-2023 Real Logic Limited. +Copyright 2013-2024 Real Logic Limited. Copyright 2017 MarketFactory Inc. Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/build.gradle b/build.gradle index 3d08ca9f4a..47a0287f06 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 84cd75c377..4f40d0b3fa 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -23,7 +23,7 @@ - + diff --git a/sbe-benchmarks/src/main/cpp/CMakeLists.txt b/sbe-benchmarks/src/main/cpp/CMakeLists.txt index d35adebb49..085e8bf224 100644 --- a/sbe-benchmarks/src/main/cpp/CMakeLists.txt +++ b/sbe-benchmarks/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2023 Real Logic Limited. +# Copyright 2013-2024 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/CarBench.cpp b/sbe-benchmarks/src/main/cpp/CarBench.cpp index 101974e8de..42c757efd2 100644 --- a/sbe-benchmarks/src/main/cpp/CarBench.cpp +++ b/sbe-benchmarks/src/main/cpp/CarBench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/CodecBench.h b/sbe-benchmarks/src/main/cpp/CodecBench.h index 2cbb379e15..14cf19547e 100644 --- a/sbe-benchmarks/src/main/cpp/CodecBench.h +++ b/sbe-benchmarks/src/main/cpp/CodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp index 84cbee18ee..a320b30ab7 100644 --- a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp +++ b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h index f55c4bed4c..fb044428ae 100644 --- a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h index 69cbf98890..fbe11e6de0 100644 --- a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp index e292d64255..f60927438f 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp +++ b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/benchlet.h b/sbe-benchmarks/src/main/cpp/benchlet.h index 37c39222fa..c883dd0faf 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet.h +++ b/sbe-benchmarks/src/main/cpp/benchlet.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java index 117dfefec0..1531933165 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java index a182c61331..1125c6ccc3 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java index 974d94de21..5e8842c2c8 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/CMakeLists.txt b/sbe-samples/src/main/cpp/CMakeLists.txt index ea9213e665..dd6a5f0b32 100644 --- a/sbe-samples/src/main/cpp/CMakeLists.txt +++ b/sbe-samples/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2023 Real Logic Limited. +# Copyright 2013-2024 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index 810c667be8..2ee019f9df 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/OtfExample.cpp b/sbe-samples/src/main/cpp/OtfExample.cpp index fe9ceeb64a..ed24a59a6c 100644 --- a/sbe-samples/src/main/cpp/OtfExample.cpp +++ b/sbe-samples/src/main/cpp/OtfExample.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java index a64d203640..fb03fb954e 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java index 8af8d1094d..16e4617ce3 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java index f9b1233468..02daba6701 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java index 86a754fa3c..a45f734aea 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java index fd12f685ba..a582d13016 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/CMakeLists.txt b/sbe-tool/src/main/cpp/CMakeLists.txt index a2c4081141..c79be7c58a 100644 --- a/sbe-tool/src/main/cpp/CMakeLists.txt +++ b/sbe-tool/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2023 Real Logic Limited. +# Copyright 2013-2024 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/Encoding.h b/sbe-tool/src/main/cpp/otf/Encoding.h index bad608a880..c6464e5ffc 100644 --- a/sbe-tool/src/main/cpp/otf/Encoding.h +++ b/sbe-tool/src/main/cpp/otf/Encoding.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index 2b4571b5b7..6374fecdd2 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h index 78a49c8eda..56249a832b 100644 --- a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h index c61658aa35..8b59b5df7d 100644 --- a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/Token.h b/sbe-tool/src/main/cpp/otf/Token.h index b187a86198..69e06224cc 100644 --- a/sbe-tool/src/main/cpp/otf/Token.h +++ b/sbe-tool/src/main/cpp/otf/Token.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java index 307e4a3b02..92cb21c32d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index 70553f642b..27411749b5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index 7c5ec14a9f..aae460dc2b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index eac6dd4ba1..0af4506b75 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java index a69e280d0d..93e86eee1e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java index 4ebebf2f83..7f17222cdc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java index 4ffba79157..f10999cff9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java index df4040e2bf..03dcf30090 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java index be906f06e0..a6ba5850ea 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java index 83afb9928b..461cb2bb22 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 6552a72c00..54a9766449 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 8b71264be2..f77143e47b 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java index 5877162f56..0da63b7c09 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java index cadc1399fb..fa0cbe1f10 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java index d0e6656cc4..956b86d379 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java index 0e79f88568..3122926ba5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/PrecedenceChecks.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/PrecedenceChecks.java index 9825a3e6b7..cd5e1856aa 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/PrecedenceChecks.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/PrecedenceChecks.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index b47e1d2f4a..0c7f258720 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index 3e561bd207..76b75687d2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java index 7616ad4b28..43c45fa9f7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java index 5c58a2d237..4ea7958015 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java index ee55d214d5..157309f319 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 8fe17df71a..d7ab193126 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java index c2c500f5bc..6ec2505238 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index 1140ae8b02..cac937c67f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java index d1431f3343..54b9fdd77c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index 1f5e238bff..8fad299bb9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java index c225f8b4a9..1675d69fed 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java index d658a7e759..0aa379216b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java index 9bc17ee5fa..c30d9ed062 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 3e6dd222eb..3934c154cc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java index 516093b5f8..9bbe32bc86 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index c29db9cbc2..5bdc6e38b0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java index e7ae8909e2..cfe10b0723 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java index dd303f9a0e..7a6cae1bac 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 67c949cbe0..7d0b79a0aa 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index 56b5e10cf2..00c9ac03f6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index cb06bbc96a..b1620446a2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java index 2e28bd67c8..49f5f6747d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index 13fa241a40..8f2724759f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index d7fd2cc55d..6407220065 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java index e2e3f52525..bfaccf83ee 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java index 6f1c114103..db4e41a9ff 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java index 744fb0c15c..318cc3061f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java index 57e946b0df..1ca42e82d1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java index 2f7a309a99..0485f9a903 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index d80ca04b46..359975a8b5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java index 4bbcfaef95..82ad99d714 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java index 9b57dee5bf..b72f8b46a0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java index e4b14a08f4..db6d2cb849 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index a6845a15ae..83ab2d1538 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java index 34a0ea2c56..b4533bccb0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java index bd74f67e44..5e58d4f0e7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index f889af19a8..9ae537b397 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java index 22e7595740..a7214788a4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java index 947f6fb053..3f2e518d31 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java index c480a328bc..7bbe1fb11f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java index 23910e4910..f9c243555b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java index 0a7671a020..df2782b168 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java index 8cd16555fc..0f8916d55b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java index efd0d150b8..d3e1aebfb7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java index bc5d5ee6c2..06dfbeb735 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index 966f5f0e2e..f7d6052df2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index ac175bb37b..e7842ea47c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index e805dd8fc0..60a9cdc66e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java index 7fad3ab7ea..8d3c48ea3f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java index dd93a87fb7..d445da2f92 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java index 7def2d9aed..49cf4ca722 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index de4ceff388..8f507ca366 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java index 1fbe750a2e..3c1e6a78f2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index a196df56d0..46dac06dfd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java index 9e38fd8c94..93aa9c8260 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java index 191f4e8279..2eee8a20c0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java index 2c8b402f88..11bdccbe08 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java index 8f1ec8c23c..c52ae6feed 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index 63618fdebf..fb6914774f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java index 2d65a39044..b96605d860 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java index 8b54fb6cfc..db25c1a291 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index d9ecb33df3..008e5a1629 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java index 3ffcf30830..c16ea698f3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/BoundsCheckTest.cpp b/sbe-tool/src/test/c/BoundsCheckTest.cpp index f7656e2dd8..047fab85e6 100644 --- a/sbe-tool/src/test/c/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/c/BoundsCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CComplianceTest.c b/sbe-tool/src/test/c/CComplianceTest.c index 3ba67f78da..9acbb22334 100644 --- a/sbe-tool/src/test/c/CComplianceTest.c +++ b/sbe-tool/src/test/c/CComplianceTest.c @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index bb58cfc3cb..52bf553afd 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2023 Real Logic Limited. +# Copyright 2013-2024 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index 68494c7993..cda5433609 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/GroupWithDataTest.cpp b/sbe-tool/src/test/c/GroupWithDataTest.cpp index d8da323877..f643b2de43 100644 --- a/sbe-tool/src/test/c/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/c/GroupWithDataTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/Issue889Test.cpp b/sbe-tool/src/test/c/Issue889Test.cpp index c621653028..800065e7da 100644 --- a/sbe-tool/src/test/c/Issue889Test.cpp +++ b/sbe-tool/src/test/c/Issue889Test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp index 2adf48f06c..aaa6a174a0 100644 --- a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index 8c698c83c3..b1319e2389 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2023 Real Logic Limited. +# Copyright 2013-2024 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index 6675172c8d..ea00b8120c 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp index 6b772b976e..cede889d68 100644 --- a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp index 39759c1d50..f767072ac6 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp index 2ef126a774..22ebe9ecc2 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp index 89aeeca267..2c5fa0b1a0 100644 --- a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp +++ b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp index 2c0c242d8b..03d35c2dee 100644 --- a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/Issue835Test.cpp b/sbe-tool/src/test/cpp/Issue835Test.cpp index 01aa455037..9f59ae3fb0 100644 --- a/sbe-tool/src/test/cpp/Issue835Test.cpp +++ b/sbe-tool/src/test/cpp/Issue835Test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/Issue889Test.cpp b/sbe-tool/src/test/cpp/Issue889Test.cpp index f730936a16..2acafb021a 100644 --- a/sbe-tool/src/test/cpp/Issue889Test.cpp +++ b/sbe-tool/src/test/cpp/Issue889Test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp index 6ff568dd9d..881dd0c020 100644 --- a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp +++ b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp index ad46bab3a9..fe8a58e6b1 100644 --- a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp +++ b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java index 63bcc2e412..335e3a59b0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java index 97d51b199c..e233b02c26 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java index a354a11d43..d0a0bdbdeb 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java index eeea08ac0d..616aa06603 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java index 4f5228f46f..be6fad4b98 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java index 11df1c5919..b09495875d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index 63e2f6010b..8b3575e0ab 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index 48b436b289..f96c1ee283 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java index 59fe07b2f3..4e063e9b4a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java index 8342f439e7..487ce653d3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java index 124faba06c..ffc38c539f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java index 7b823d5a86..e6fe0c252a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java index 7827dac2b3..cd334d9cc1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java index 82a280ed5e..277404993f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java index 6448428ff8..babefc9391 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 3f253ed778..3ceaf14e14 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java index d953828de5..1eff4fa662 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java index 09d6f5b00e..d949d6dfe8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java index 6122cdfd13..36e78d2a28 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java index 36ef9bed42..c5f0133783 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java index beead1799e..2db082c6fc 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java index c2c3e07f4b..de19ed99ed 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index 1774666139..ee85bc2abe 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java index c626e044d4..d69fc82a26 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java index 8d8fcf3d4d..a69c9bfadb 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java index 11b28123e1..daec79f9ec 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnum.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnum.java index 98cdf3852b..2a51451651 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnum.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnum.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java index f48ce8e830..2871b78d54 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java index f7dcc14c28..d6d7652b83 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index e99a73f272..7f89f2e18d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java index cf900c22d0..c888b3f9c5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java index 0f20f59520..ee2eef15e9 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java index 1cab824202..0d0416dd5a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index 824e3acd1f..d534863d86 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java index 80ccc9f1a2..5519bcbf15 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java index 9306e75f95..d0bf85fb41 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java index f6eea310f5..b4bdfe9b52 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java index 40c59916e7..b5995c4dac 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java index 73999d9fd4..3d392e0e95 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java index b726352632..a44ee8d4cd 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java index fdba65bc5b..38d399d1e0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java index d982667e8a..b3b3f7ae4e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java index cd32bde628..63495cd586 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index edd151623a..a0648b730c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index 08c0132c6e..70d8159f9b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index bda3393aa9..bfb2965116 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * Copyright 2017 MarketFactory Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java index 3a45e114bd..265b088c7d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java index 1e784cffcc..b8c2c130fb 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java index 3e73957429..7c134861be 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java index 2b6dfa3607..f4ec8c63db 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index b04463d244..256e832ded 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java index 7a06142707..32690f6b87 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From b75bd644f6d1babc42b1803bf1b581ffa988723f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 10 Jan 2024 12:22:43 +0000 Subject: [PATCH 1069/1594] [Java] Remove unused initialOffset member from generated codecs. --- .../sbe/generation/java/JavaGenerator.java | 15 ++++----------- .../sbe/ir/generated/FrameCodecDecoder.java | 13 +++---------- .../sbe/ir/generated/FrameCodecEncoder.java | 9 +-------- .../sbe/ir/generated/TokenCodecDecoder.java | 13 +++---------- .../sbe/ir/generated/TokenCodecEncoder.java | 9 +-------- 5 files changed, 12 insertions(+), 47 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 3934c154cc..bd277284bd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -3419,7 +3419,6 @@ private CharSequence generateDecoderFlyweightCode( .append(" {\n") .append(" this.buffer = buffer;\n") .append(" }\n") - .append(" this.initialOffset = offset;\n") .append(" this.offset = offset;\n") .append(" this.actingBlockLength = actingBlockLength;\n") .append(" this.actingVersion = actingVersion;\n") @@ -3448,7 +3447,7 @@ private CharSequence generateDecoderFlyweightCode( methods.append(" public ").append(className).append(" sbeRewind()\n") .append(" {\n") - .append(" return wrap(buffer, initialOffset, actingBlockLength, actingVersion);\n") + .append(" return wrap(buffer, offset, actingBlockLength, actingVersion);\n") .append(" }\n\n"); methods.append(" public int sbeDecodedLength()\n") @@ -3516,7 +3515,6 @@ private CharSequence generateFlyweightCode( " public static final java.nio.ByteOrder BYTE_ORDER = java.nio.ByteOrder.%14$s;\n\n" + " private final %9$s parentMessage = this;\n" + " private %11$s buffer;\n" + - " private int initialOffset;\n" + " private int offset;\n" + " private int limit;\n" + "%13$s" + @@ -3545,10 +3543,6 @@ private CharSequence generateFlyweightCode( " {\n" + " return buffer;\n" + " }\n\n" + - " public int initialOffset()\n" + - " {\n" + - " return initialOffset;\n" + - " }\n\n" + " public int offset()\n" + " {\n" + " return offset;\n" + @@ -3599,7 +3593,6 @@ private CharSequence generateEncoderFlyweightCode( " {\n" + " this.buffer = buffer;\n" + " }\n" + - " this.initialOffset = offset;\n" + " this.offset = offset;\n" + " limit(offset + BLOCK_LENGTH);\n\n" + generateEncoderWrapListener(fieldPrecedenceModel, " ") + @@ -4250,7 +4243,7 @@ private void generateEncoderDisplay(final StringBuilder sb, final String decoder append(sb, INDENT, " }"); sb.append('\n'); append(sb, INDENT, " final " + decoderName + " decoder = new " + decoderName + "();"); - append(sb, INDENT, " decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION);"); + append(sb, INDENT, " decoder.wrap(buffer, offset, BLOCK_LENGTH, SCHEMA_VERSION);"); sb.append('\n'); append(sb, INDENT, " return decoder.appendTo(builder);"); append(sb, INDENT, "}"); @@ -4369,7 +4362,7 @@ private void generateDecoderDisplay( append(sb, INDENT, " }"); sb.append('\n'); append(sb, INDENT, " final int originalLimit = limit();"); - append(sb, INDENT, " limit(initialOffset + actingBlockLength);"); + append(sb, INDENT, " limit(offset + actingBlockLength);"); append(sb, INDENT, " builder.append(\"[" + name + "](sbeTemplateId=\");"); append(sb, INDENT, " builder.append(TEMPLATE_ID);"); append(sb, INDENT, " builder.append(\"|sbeSchemaId=\");"); @@ -4631,7 +4624,7 @@ private void appendMessageToString(final StringBuilder sb, final String decoderN append(sb, INDENT, " }"); sb.append('\n'); append(sb, INDENT, " final " + decoderName + " decoder = new " + decoderName + "();"); - append(sb, INDENT, " decoder.wrap(buffer, initialOffset, actingBlockLength, actingVersion);"); + append(sb, INDENT, " decoder.wrap(buffer, offset, actingBlockLength, actingVersion);"); sb.append('\n'); append(sb, INDENT, " return decoder.appendTo(new StringBuilder()).toString();"); append(sb, INDENT, "}"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 89962bd61f..81f28e8dc5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -97,7 +97,6 @@ private void codecState(int newState) private final FrameCodecDecoder parentMessage = this; private DirectBuffer buffer; - private int initialOffset; private int offset; private int limit; int actingBlockLength; @@ -133,11 +132,6 @@ public DirectBuffer buffer() return buffer; } - public int initialOffset() - { - return initialOffset; - } - public int offset() { return offset; @@ -166,7 +160,6 @@ public FrameCodecDecoder wrap( { this.buffer = buffer; } - this.initialOffset = offset; this.offset = offset; this.actingBlockLength = actingBlockLength; this.actingVersion = actingVersion; @@ -202,7 +195,7 @@ public FrameCodecDecoder wrapAndApplyHeader( public FrameCodecDecoder sbeRewind() { - return wrap(buffer, initialOffset, actingBlockLength, actingVersion); + return wrap(buffer, offset, actingBlockLength, actingVersion); } public int sbeDecodedLength() @@ -924,7 +917,7 @@ public String toString() } final FrameCodecDecoder decoder = new FrameCodecDecoder(); - decoder.wrap(buffer, initialOffset, actingBlockLength, actingVersion); + decoder.wrap(buffer, offset, actingBlockLength, actingVersion); return decoder.appendTo(new StringBuilder()).toString(); } @@ -937,7 +930,7 @@ public StringBuilder appendTo(final StringBuilder builder) } final int originalLimit = limit(); - limit(initialOffset + actingBlockLength); + limit(offset + actingBlockLength); builder.append("[FrameCodec](sbeTemplateId="); builder.append(TEMPLATE_ID); builder.append("|sbeSchemaId="); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index a5524033fc..aaf9df42c9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -97,7 +97,6 @@ private void codecState(int newState) private final FrameCodecEncoder parentMessage = this; private MutableDirectBuffer buffer; - private int initialOffset; private int offset; private int limit; @@ -131,11 +130,6 @@ public MutableDirectBuffer buffer() return buffer; } - public int initialOffset() - { - return initialOffset; - } - public int offset() { return offset; @@ -147,7 +141,6 @@ public FrameCodecEncoder wrap(final MutableDirectBuffer buffer, final int offset { this.buffer = buffer; } - this.initialOffset = offset; this.offset = offset; limit(offset + BLOCK_LENGTH); @@ -727,7 +720,7 @@ public StringBuilder appendTo(final StringBuilder builder) } final FrameCodecDecoder decoder = new FrameCodecDecoder(); - decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION); + decoder.wrap(buffer, offset, BLOCK_LENGTH, SCHEMA_VERSION); return decoder.appendTo(builder); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 6a48488936..57abf338a1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -144,7 +144,6 @@ private void codecState(int newState) private final TokenCodecDecoder parentMessage = this; private DirectBuffer buffer; - private int initialOffset; private int offset; private int limit; int actingBlockLength; @@ -180,11 +179,6 @@ public DirectBuffer buffer() return buffer; } - public int initialOffset() - { - return initialOffset; - } - public int offset() { return offset; @@ -213,7 +207,6 @@ public TokenCodecDecoder wrap( { this.buffer = buffer; } - this.initialOffset = offset; this.offset = offset; this.actingBlockLength = actingBlockLength; this.actingVersion = actingVersion; @@ -249,7 +242,7 @@ public TokenCodecDecoder wrapAndApplyHeader( public TokenCodecDecoder sbeRewind() { - return wrap(buffer, initialOffset, actingBlockLength, actingVersion); + return wrap(buffer, offset, actingBlockLength, actingVersion); } public int sbeDecodedLength() @@ -2684,7 +2677,7 @@ public String toString() } final TokenCodecDecoder decoder = new TokenCodecDecoder(); - decoder.wrap(buffer, initialOffset, actingBlockLength, actingVersion); + decoder.wrap(buffer, offset, actingBlockLength, actingVersion); return decoder.appendTo(new StringBuilder()).toString(); } @@ -2697,7 +2690,7 @@ public StringBuilder appendTo(final StringBuilder builder) } final int originalLimit = limit(); - limit(initialOffset + actingBlockLength); + limit(offset + actingBlockLength); builder.append("[TokenCodec](sbeTemplateId="); builder.append(TEMPLATE_ID); builder.append("|sbeSchemaId="); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index a0ece1099d..e81e14bc4a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -144,7 +144,6 @@ private void codecState(int newState) private final TokenCodecEncoder parentMessage = this; private MutableDirectBuffer buffer; - private int initialOffset; private int offset; private int limit; @@ -178,11 +177,6 @@ public MutableDirectBuffer buffer() return buffer; } - public int initialOffset() - { - return initialOffset; - } - public int offset() { return offset; @@ -194,7 +188,6 @@ public TokenCodecEncoder wrap(final MutableDirectBuffer buffer, final int offset { this.buffer = buffer; } - this.initialOffset = offset; this.offset = offset; limit(offset + BLOCK_LENGTH); @@ -2034,7 +2027,7 @@ public StringBuilder appendTo(final StringBuilder builder) } final TokenCodecDecoder decoder = new TokenCodecDecoder(); - decoder.wrap(buffer, initialOffset, BLOCK_LENGTH, SCHEMA_VERSION); + decoder.wrap(buffer, offset, BLOCK_LENGTH, SCHEMA_VERSION); return decoder.appendTo(builder); } From ab9336080e000c90a01f1d1b0921fcc8fadc531c Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 10 Jan 2024 14:15:34 +0000 Subject: [PATCH 1070/1594] [Java] Fix warning. --- .../java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java index e233b02c26..80a4ba4416 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java @@ -42,6 +42,7 @@ public class FieldAccessOrderCheckTest private final MutableDirectBuffer buffer = new ExpandableArrayBuffer(); private final MessageHeaderEncoder messageHeaderEncoder = new MessageHeaderEncoder(); private final MessageHeaderDecoder messageHeaderDecoder = new MessageHeaderDecoder(); + private final Random random = new Random(); @BeforeAll static void assumeDebugMode() @@ -53,7 +54,7 @@ static void assumeDebugMode() @BeforeEach void setUp() { - new Random().nextBytes(buffer.byteArray()); + random.nextBytes(buffer.byteArray()); } @Test From 363f450ae2ccf59b5df0bf4ec77364c5089adfd3 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 18 Jan 2024 16:07:52 +0000 Subject: [PATCH 1071/1594] [Java] Check for being in a composite when generating array access methods based on version. --- .../sbe/generation/java/JavaGenerator.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index bd277284bd..5c479aedb9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -131,8 +131,7 @@ public JavaGenerator( shouldDecodeUnknownEnumValues, shouldSupportTypesPackageNames, PrecedenceChecks.newInstance(new PrecedenceChecks.Context()), - outputManager - ); + outputManager); } /** @@ -1466,7 +1465,7 @@ private void generateDecoderVarData( sb.append("\n") .append(indent).append(" public int ").append(methodPropName).append("Length()\n") .append(indent).append(" {\n") - .append(generateArrayFieldNotPresentCondition(token.version(), indent)) + .append(generateArrayFieldNotPresentCondition(false, token.version(), indent)) .append(lengthAccessOrderListenerCall) .append(indent).append(" final int limit = parentMessage.limit();\n") .append(indent).append(" return ").append(PrimitiveType.UINT32 == lengthType ? "(int)" : "") @@ -1563,7 +1562,7 @@ private void generateDataDecodeMethods( indent + " return dataLength;\n" + indent + " }\n", Generators.toUpperFirstChar(propertyName), - generateStringNotPresentConditionForAppendable(token.version(), indent), + generateStringNotPresentConditionForAppendable(false, token.version(), indent), sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", generateGet(lengthType, "limit", byteOrderStr), @@ -1621,7 +1620,7 @@ private void generateDataDecodeMethods( indent + " return new String(tmp, %6$s);\n" + indent + " }\n", formatPropertyName(propertyName), - generateStringNotPresentCondition(token.version(), indent), + generateStringNotPresentCondition(false, token.version(), indent), sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", generateGet(lengthType, "limit", byteOrderStr), @@ -1644,7 +1643,7 @@ private void generateDataDecodeMethods( indent + " return dataLength;\n" + indent + " }\n", Generators.toUpperFirstChar(propertyName), - generateStringNotPresentConditionForAppendable(token.version(), indent), + generateStringNotPresentConditionForAppendable(false, token.version(), indent), sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", generateGet(lengthType, "limit", byteOrderStr), @@ -1853,7 +1852,7 @@ private void generateVarDataTypedDecoder( indent + " }\n", propertyName, exchangeType, - generateArrayFieldNotPresentCondition(token.version(), indent), + generateArrayFieldNotPresentCondition(false, token.version(), indent), accessOrderListenerCall, sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", @@ -2713,9 +2712,10 @@ private CharSequence generateFieldNotPresentCondition( indent + " }\n\n"; } - private static CharSequence generateArrayFieldNotPresentCondition(final int sinceVersion, final String indent) + private static CharSequence generateArrayFieldNotPresentCondition( + final boolean inComposite, final int sinceVersion, final String indent) { - if (0 == sinceVersion) + if (inComposite || 0 == sinceVersion) { return ""; } @@ -2728,9 +2728,9 @@ private static CharSequence generateArrayFieldNotPresentCondition(final int sinc } private static CharSequence generateStringNotPresentConditionForAppendable( - final int sinceVersion, final String indent) + final boolean inComposite, final int sinceVersion, final String indent) { - if (0 == sinceVersion) + if (inComposite || 0 == sinceVersion) { return ""; } @@ -2742,9 +2742,10 @@ private static CharSequence generateStringNotPresentConditionForAppendable( indent + " }\n\n"; } - private static CharSequence generateStringNotPresentCondition(final int sinceVersion, final String indent) + private static CharSequence generateStringNotPresentCondition( + final boolean inComposite, final int sinceVersion, final String indent) { - if (0 == sinceVersion) + if (inComposite || 0 == sinceVersion) { return ""; } @@ -2836,7 +2837,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( indent + " }\n", Generators.toUpperFirstChar(propertyName), fieldLength, - generateArrayFieldNotPresentCondition(propertyToken.version(), indent), + generateArrayFieldNotPresentCondition(inComposite, propertyToken.version(), indent), accessOrderListenerCall, offset); @@ -2852,7 +2853,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( indent + " return new String(dst, 0, end, %s);\n" + indent + " }\n\n", propertyName, - generateStringNotPresentCondition(propertyToken.version(), indent), + generateStringNotPresentCondition(inComposite, propertyToken.version(), indent), accessOrderListenerCall, fieldLength, offset, @@ -2886,7 +2887,7 @@ private CharSequence generatePrimitiveArrayPropertyDecode( indent + " return %3$d;\n" + indent + " }\n\n", Generators.toUpperFirstChar(propertyName), - generateStringNotPresentConditionForAppendable(propertyToken.version(), indent), + generateStringNotPresentConditionForAppendable(inComposite, propertyToken.version(), indent), fieldLength, offset, accessOrderListenerCall); @@ -2904,7 +2905,7 @@ else if (encoding.primitiveType() == PrimitiveType.UINT8) indent + " return bytesCopied;\n" + indent + " }\n", Generators.toUpperFirstChar(propertyName), - generateArrayFieldNotPresentCondition(propertyToken.version(), indent), + generateArrayFieldNotPresentCondition(inComposite, propertyToken.version(), indent), accessOrderListenerCall, fieldLength, offset); @@ -2920,7 +2921,7 @@ else if (encoding.primitiveType() == PrimitiveType.UINT8) indent + " }\n", Generators.toUpperFirstChar(propertyName), fqMutableBuffer, - generateArrayFieldNotPresentCondition(propertyToken.version(), indent), + generateArrayFieldNotPresentCondition(inComposite, propertyToken.version(), indent), accessOrderListenerCall, fieldLength, offset); From a43b4ae6cd1111aa6a10aaf2a4874fdfed87089a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 18 Jan 2024 17:04:42 +0000 Subject: [PATCH 1072/1594] [C++] Fix type conversion warnings. --- sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp index 2c5fa0b1a0..9f7bb9184c 100644 --- a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp +++ b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp @@ -123,9 +123,9 @@ TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingVariableLengthFieldsI encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); encoder.a(42); auto *bIn = "abc"; - encoder.putB(bIn, strlen(bIn)); + encoder.putB(bIn, static_cast(strlen(bIn))); auto *cIn = "def"; - encoder.putC(cIn, strlen(cIn)); + encoder.putC(cIn, static_cast(strlen(cIn))); encoder.checkEncodingIsComplete(); MultipleVarLength decoder; @@ -262,7 +262,7 @@ TEST_F(FieldAccessOrderCheckTest, disallowsSkippingEncodingOfVariableLengthField try { auto *cIn = "cIn"; - encoder.putC(cIn, std::strlen(cIn)); + encoder.putC(cIn, static_cast(std::strlen(cIn))); } catch (const std::exception &e) { From b8ac926f0aba3807d43fd30e6c3b336bd310a45f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 18 Jan 2024 17:21:20 +0000 Subject: [PATCH 1073/1594] Captured types in IR should be for the minimum version used in a schema. Issue #967. --- .../main/java/uk/co/real_logic/sbe/ir/Ir.java | 9 ++++++- .../sbe/ir/SinceVersionValidationTest.java | 19 ++++++++++++++ sbe-tool/src/test/resources/issue967.xml | 25 +++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 sbe-tool/src/test/resources/issue967.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java index 0485f9a903..3587a8a05f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java @@ -328,7 +328,14 @@ private int captureType( while (endSignal != token.signal() || !name.equals(token.name())); updateComponentTokenCounts(typeTokens); - typesByNameMap.put(null == referencedName ? name : referencedName, typeTokens); + + final String typeName = null == referencedName ? name : referencedName; + final List existingTypeTokens = typesByNameMap.get(typeName); + + if (null == existingTypeTokens || existingTypeTokens.get(0).version() > typeTokens.get(0).version()) + { + typesByNameMap.put(typeName, typeTokens); + } return i; } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java index d0bf85fb41..a2223ced19 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java @@ -16,10 +16,15 @@ package uk.co.real_logic.sbe.ir; import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; import java.io.InputStream; +import java.util.List; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.lessThan; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static uk.co.real_logic.sbe.Tests.getLocalResource; @@ -43,4 +48,18 @@ void shouldErrorOnTypeWithGreaterSinceVersion() throws Exception fail("expected IllegalStateException"); } + + @Test + void shouldApplySinceVersionOnComposites() throws Exception + { + try (InputStream in = getLocalResource("issue967.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + final List priceNull9Tokens = ir.getType("PRICENULL9"); + assertThat(priceNull9Tokens.get(0).version(), lessThan(13)); + } + } } diff --git a/sbe-tool/src/test/resources/issue967.xml b/sbe-tool/src/test/resources/issue967.xml new file mode 100644 index 0000000000..2190821b61 --- /dev/null +++ b/sbe-tool/src/test/resources/issue967.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + -9 + + + + + + + \ No newline at end of file From b35481928a63a4ebe9e4a29c5222a644974458e0 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 18 Jan 2024 17:32:03 +0000 Subject: [PATCH 1074/1594] [C++] Provide access to acting block length of repeating group via the sbeActingBlockLength() method. Issue #968. --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 0c7f258720..a22556e639 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -785,7 +785,6 @@ private void generateGroupClassHeader( codecStateNullAssignment); } - if (null != fieldPrecedenceModel) { sb.append("\n").append(indent).append("private:"); @@ -808,6 +807,11 @@ private void generateGroupClassHeader( indent + " return %2$d;\n" + indent + " }\n\n" + + indent + " SBE_NODISCARD std::uint64_t sbeActingBlockLength() SBE_NOEXCEPT\n" + + indent + " {\n" + + indent + " return m_blockLength;\n" + + indent + " }\n\n" + + indent + " SBE_NODISCARD std::uint64_t sbePosition() const SBE_NOEXCEPT\n" + indent + " {\n" + indent + " return *m_positionPtr;\n" + From 18d778189a82fd14761b141cbe4bf71b511044a0 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 22 Jan 2024 21:46:53 +0100 Subject: [PATCH 1075/1594] [Java] Upgrade to Versions 0.51.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 47a0287f06..3e9a6dea27 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ buildscript { plugins { id 'java-library' id 'com.github.johnrengelman.shadow' version '8.1.1' apply false - id 'com.github.ben-manes.versions' version '0.50.0' + id 'com.github.ben-manes.versions' version '0.51.0' } defaultTasks 'clean', 'build' From 92e5488c4a34a7af4760cd0152e031d4d3d969a8 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 29 Jan 2024 11:20:06 +0000 Subject: [PATCH 1076/1594] Warnings cleanup. --- .../uk/co/real_logic/sbe/ValidationUtil.java | 2 +- .../sbe/generation/c/CGenerator.java | 2 +- .../sbe/generation/cpp/CppGenerator.java | 40 ++++++--------- .../generation/csharp/CSharpGenerator.java | 49 +++++++------------ .../sbe/generation/java/JavaGenerator.java | 34 +++++-------- .../uk/co/real_logic/sbe/ir/IrDecoder.java | 2 +- ...ava => ValueRefWithLowerCaseEnumTest.java} | 2 +- .../test/resources/nested-composite-name.xml | 1 - 8 files changed, 51 insertions(+), 81 deletions(-) rename sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/{ValueRefWithLowerCaseEnum.java => ValueRefWithLowerCaseEnumTest.java} (98%) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index 0af4506b75..3ba64ef105 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -266,7 +266,7 @@ public static boolean isJavaKeyword(final String token) private static boolean isJavaIdentifier(final String token) { - if (token.length() == 0) + if (token.isEmpty()) { return false; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index f77143e47b..301532e771 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1085,7 +1085,7 @@ private static CharSequence generateFileHeader(final String structName, final Li "#include \n", structName.toUpperCase())); - if (typesToInclude != null && typesToInclude.size() != 0) + if (typesToInclude != null && !typesToInclude.isEmpty()) { sb.append("\n"); for (final String incName : typesToInclude) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index a22556e639..c82a0f0a14 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -228,11 +228,9 @@ private CharSequence generateFullyEncodedCheck(final FieldPrecedenceModel fieldP .append(indent).append(INDENT).append("switch (m_codecState)\n") .append(indent).append(INDENT).append("{\n"); - fieldPrecedenceModel.forEachTerminalEncoderState(state -> - { + fieldPrecedenceModel.forEachTerminalEncoderState((state) -> sb.append(indent).append(TWO_INDENT).append("case ").append(stateCaseForSwitchCase(state)).append(":\n") - .append(indent).append(THREE_INDENT).append("return;\n"); - }); + .append(indent).append(THREE_INDENT).append("return;\n")); sb.append(indent).append(TWO_INDENT).append("default:\n") .append(indent).append(THREE_INDENT) @@ -456,14 +454,12 @@ private static void generateAccessOrderListener( sb.append(indent).append("switch (codecState())\n") .append(indent).append("{\n"); - fieldPrecedenceModel.forEachTransition(interaction, transitionGroup -> + fieldPrecedenceModel.forEachTransition(interaction, (transitionGroup) -> { - transitionGroup.forEachStartState(startState -> - { + transitionGroup.forEachStartState((startState) -> sb.append(indent).append(INDENT) - .append("case ").append(stateCaseForSwitchCase(startState)).append(":\n"); - }); + .append("case ").append(stateCaseForSwitchCase(startState)).append(":\n")); if (!transitionGroup.alwaysEndsInStartState()) { @@ -2935,21 +2931,19 @@ private static void generateLookupTableDefinitions( sb.append("\n").append("const std::string ").append(className).append("::STATE_NAME_LOOKUP[") .append(fieldPrecedenceModel.stateCount()).append("] =\n") .append("{\n"); - fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> - { - sb.append(INDENT).append("\"").append(state.name()).append("\",\n"); - }); + fieldPrecedenceModel.forEachStateOrderedByStateNumber((state) -> + sb.append(INDENT).append("\"").append(state.name()).append("\",\n")); sb.append("};\n\n"); sb.append("const std::string ").append(className).append("::STATE_TRANSITIONS_LOOKUP[") .append(fieldPrecedenceModel.stateCount()).append("] =\n") .append("{\n"); - fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> + fieldPrecedenceModel.forEachStateOrderedByStateNumber((state) -> { sb.append(INDENT).append("\""); final MutableBoolean isFirst = new MutableBoolean(true); final Set transitionDescriptions = new HashSet<>(); - fieldPrecedenceModel.forEachTransitionFrom(state, transitionGroup -> + fieldPrecedenceModel.forEachTransitionFrom(state, (transitionGroup) -> { if (transitionDescriptions.add(transitionGroup.exampleCode())) { @@ -3007,12 +3001,10 @@ private static CharSequence generateFieldOrderStateEnum(final FieldPrecedenceMod sb.append(" */\n"); sb.append(INDENT).append("enum class CodecState\n") .append(INDENT).append("{\n"); - fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> - { + fieldPrecedenceModel.forEachStateOrderedByStateNumber((state) -> sb.append(INDENT).append(INDENT).append(unqualifiedStateCase(state)) - .append(" = ").append(state.number()) - .append(",\n"); - }); + .append(" = ").append(state.number()) + .append(",\n")); sb.append(INDENT).append("};\n\n"); return sb; @@ -3068,12 +3060,10 @@ private static CharSequence generateDecoderWrapListener(final FieldPrecedenceMod .append(INDENT).append(INDENT).append("{\n"); fieldPrecedenceModel.forEachWrappedStateByVersion((version, state) -> - { sb.append(INDENT).append(TWO_INDENT).append("case ").append(version).append(":\n") - .append(INDENT).append(THREE_INDENT).append("codecState(") - .append(qualifiedStateCase(state)).append(");\n") - .append(INDENT).append(THREE_INDENT).append("break;\n"); - }); + .append(INDENT).append(THREE_INDENT).append("codecState(") + .append(qualifiedStateCase(state)).append(");\n") + .append(INDENT).append(THREE_INDENT).append("break;\n")); sb.append(INDENT).append(TWO_INDENT).append("default:\n") .append(INDENT).append(THREE_INDENT).append("codecState(") diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index d7ab193126..f141c7876f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -720,24 +720,23 @@ private CharSequence generateCompositePropertyElements(final List tokens, { final Token token = tokens.get(i); final String propertyName = formatPropertyName(token.name()); - final FieldPrecedenceModel fieldPrecedenceModel = null; switch (token.signal()) { case ENCODING: - sb.append(generatePrimitiveProperty(propertyName, token, token, fieldPrecedenceModel, indent)); + sb.append(generatePrimitiveProperty(propertyName, token, token, null, indent)); break; case BEGIN_ENUM: - sb.append(generateEnumProperty(propertyName, token, token, fieldPrecedenceModel, indent)); + sb.append(generateEnumProperty(propertyName, token, token, null, indent)); break; case BEGIN_SET: - sb.append(generateBitSetProperty(propertyName, token, token, fieldPrecedenceModel, indent)); + sb.append(generateBitSetProperty(propertyName, token, token, null, indent)); break; case BEGIN_COMPOSITE: - sb.append(generateCompositeProperty(propertyName, token, token, fieldPrecedenceModel, indent)); + sb.append(generateCompositeProperty(propertyName, token, token, null, indent)); break; default: @@ -1515,30 +1514,26 @@ private static CharSequence generateFieldOrderStates( sb.append(indent).append("/// \n"); sb.append(indent).append("private enum CodecState\n") .append(indent).append("{\n"); - fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> - { + fieldPrecedenceModel.forEachStateOrderedByStateNumber((state) -> sb.append(indent).append(INDENT).append(unqualifiedStateCase(state)) - .append(" = ").append(state.number()) - .append(",\n"); - }); + .append(" = ").append(state.number()) + .append(",\n")); sb.append(indent).append("}\n\n"); sb.append("\n").append(indent).append("private static readonly string[] StateNameLookup = new []\n") .append(indent).append("{\n"); - fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> - { - sb.append(indent).append(INDENT).append("\"").append(state.name()).append("\",\n"); - }); + fieldPrecedenceModel.forEachStateOrderedByStateNumber((state) -> + sb.append(indent).append(INDENT).append("\"").append(state.name()).append("\",\n")); sb.append(indent).append("};\n\n"); sb.append(indent).append("private static readonly string[] StateTransitionsLookup = new []\n") .append(indent).append("{\n"); - fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> + fieldPrecedenceModel.forEachStateOrderedByStateNumber((state) -> { sb.append(indent).append(INDENT).append("\""); final MutableBoolean isFirst = new MutableBoolean(true); final Set transitionDescriptions = new HashSet<>(); - fieldPrecedenceModel.forEachTransitionFrom(state, transitionGroup -> + fieldPrecedenceModel.forEachTransitionFrom(state, (transitionGroup) -> { if (transitionDescriptions.add(transitionGroup.exampleCode())) { @@ -1603,11 +1598,9 @@ private CharSequence generateFullyEncodedCheck( .append(indent).append(INDENT).append("switch (_codecState)\n") .append(indent).append(INDENT).append("{\n"); - fieldPrecedenceModel.forEachTerminalEncoderState(state -> - { + fieldPrecedenceModel.forEachTerminalEncoderState((state) -> sb.append(indent).append(TWO_INDENT).append("case ").append(stateCaseForSwitchCase(state)).append(":\n") - .append(indent).append(THREE_INDENT).append("return;\n"); - }); + .append(indent).append(THREE_INDENT).append("return;\n")); sb.append(indent).append(TWO_INDENT).append("default:\n") .append(indent).append(THREE_INDENT) @@ -1771,13 +1764,11 @@ private static void generateAccessOrderListener( sb.append(indent).append("switch (codecState())\n") .append(indent).append("{\n"); - fieldPrecedenceModel.forEachTransition(interaction, transitionGroup -> + fieldPrecedenceModel.forEachTransition(interaction, (transitionGroup) -> { - transitionGroup.forEachStartState(startState -> - { + transitionGroup.forEachStartState((startState) -> sb.append(indent).append(INDENT) - .append("case ").append(stateCaseForSwitchCase(startState)).append(":\n"); - }); + .append("case ").append(stateCaseForSwitchCase(startState)).append(":\n")); sb.append(indent).append(TWO_INDENT).append("codecState(") .append(qualifiedStateCase(transitionGroup.endState())).append(");\n") .append(indent).append(TWO_INDENT).append("break;\n"); @@ -1927,12 +1918,10 @@ private static CharSequence generateDecoderWrapListener( .append(indent).append(INDENT).append("{\n"); fieldPrecedenceModel.forEachWrappedStateByVersion((version, state) -> - { sb.append(indent).append(TWO_INDENT).append("case ").append(version).append(":\n") - .append(indent).append(THREE_INDENT).append("codecState(") - .append(qualifiedStateCase(state)).append(");\n") - .append(indent).append(THREE_INDENT).append("break;\n"); - }); + .append(indent).append(THREE_INDENT).append("codecState(") + .append(qualifiedStateCase(state)).append(");\n") + .append(indent).append(THREE_INDENT).append("break;\n")); sb.append(indent).append(TWO_INDENT).append("default:\n") .append(indent).append(THREE_INDENT).append("codecState(") diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 5c479aedb9..fe49069b5c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -368,30 +368,26 @@ private CharSequence generateFieldOrderStates(final FieldPrecedenceModel fieldPr sb.append(" */\n"); sb.append(" private static class CodecStates\n") .append(" {\n"); - fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> - { + fieldPrecedenceModel.forEachStateOrderedByStateNumber((state) -> sb.append(" private static final int ") - .append(unqualifiedStateCase(state)) - .append(" = ").append(state.number()) - .append(";\n"); - }); + .append(unqualifiedStateCase(state)) + .append(" = ").append(state.number()) + .append(";\n")); sb.append("\n").append(" private static final String[] STATE_NAME_LOOKUP =\n") .append(" {\n"); - fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> - { - sb.append(" \"").append(state.name()).append("\",\n"); - }); + fieldPrecedenceModel.forEachStateOrderedByStateNumber((state) -> + sb.append(" \"").append(state.name()).append("\",\n")); sb.append(" };\n\n"); sb.append(" private static final String[] STATE_TRANSITIONS_LOOKUP =\n") .append(" {\n"); - fieldPrecedenceModel.forEachStateOrderedByStateNumber(state -> + fieldPrecedenceModel.forEachStateOrderedByStateNumber((state) -> { sb.append(" \""); final MutableBoolean isFirst = new MutableBoolean(true); final Set transitionDescriptions = new HashSet<>(); - fieldPrecedenceModel.forEachTransitionFrom(state, transitionGroup -> + fieldPrecedenceModel.forEachTransitionFrom(state, (transitionGroup) -> { if (transitionDescriptions.add(transitionGroup.exampleCode())) { @@ -458,11 +454,9 @@ private void generateFullyEncodedCheck( .append(" switch (codecState)\n") .append(" {\n"); - fieldPrecedenceModel.forEachTerminalEncoderState(state -> - { + fieldPrecedenceModel.forEachTerminalEncoderState((state) -> sb.append(" case ").append(stateCaseForSwitchCase(state)).append(":\n") - .append(" return;\n"); - }); + .append(" return;\n")); sb.append(" default:\n") .append(" throw new IllegalStateException(\"Not fully encoded, current state: \" +\n") @@ -773,12 +767,10 @@ private static CharSequence generateDecoderWrapListener( .append(indent).append(" {\n"); fieldPrecedenceModel.forEachWrappedStateByVersion((version, state) -> - { sb.append(indent).append(" case ").append(version).append(":\n") - .append(indent).append(" codecState(") - .append(qualifiedStateCase(state)).append(");\n") - .append(indent).append(" break;\n"); - }); + .append(indent).append(" codecState(") + .append(qualifiedStateCase(state)).append(");\n") + .append(indent).append(" break;\n")); sb.append(indent).append(" default:\n") .append(indent).append(" codecState(") diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index 359975a8b5..b7da2ead1c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -126,7 +126,7 @@ public Ir decode() i = captureHeader(tokens); } - final ByteOrder byteOrder = tokens.size() > 0 ? tokens.get(0).encoding().byteOrder() : null; + final ByteOrder byteOrder = !tokens.isEmpty() ? tokens.get(0).encoding().byteOrder() : null; final Ir ir = new Ir( irPackageName, irNamespaceName, irId, irVersion, null, semanticVersion, byteOrder, irHeader); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnum.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnumTest.java similarity index 98% rename from sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnum.java rename to sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnumTest.java index 2a51451651..675f99d05e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnum.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnumTest.java @@ -31,7 +31,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.StringContains.containsString; -class ValueRefWithLowerCaseEnum +class ValueRefWithLowerCaseEnumTest { private static final Class BUFFER_CLASS = MutableDirectBuffer.class; private static final String BUFFER_NAME = BUFFER_CLASS.getName(); diff --git a/sbe-tool/src/test/resources/nested-composite-name.xml b/sbe-tool/src/test/resources/nested-composite-name.xml index e7fb3a0566..1005edff29 100644 --- a/sbe-tool/src/test/resources/nested-composite-name.xml +++ b/sbe-tool/src/test/resources/nested-composite-name.xml @@ -1,6 +1,5 @@ Date: Mon, 29 Jan 2024 12:00:31 +0000 Subject: [PATCH 1077/1594] [C++] Fix warnings. --- sbe-tool/src/main/cpp/otf/IrDecoder.h | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index 6374fecdd2..0b5c048669 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -48,8 +48,7 @@ namespace sbe { namespace otf { class IrDecoder { public: - IrDecoder() : - m_length(0) + IrDecoder() { } @@ -142,7 +141,7 @@ class IrDecoder // OS specifics static long long getFileSize(const char *filename) { - struct stat fileStat; + struct stat fileStat{}; if (::stat(filename, &fileStat) != 0) { @@ -165,7 +164,7 @@ class IrDecoder int fd = fileno(fptr); while (remaining > 0) { - unsigned int bytes = static_cast(4098 < remaining ? 4098 : remaining); + auto bytes = static_cast(4098 < remaining ? 4098 : remaining); long long sz = ::read(fd, buffer + (length - remaining), bytes); remaining -= sz; if (sz < 0) @@ -183,8 +182,8 @@ class IrDecoder std::shared_ptr> m_headerTokens; std::vector>> m_messages; std::unique_ptr m_buffer; - std::uint64_t m_length; - int m_id; + std::uint64_t m_length = 0; + int m_id = 0; int decodeIr() { @@ -232,10 +231,10 @@ class IrDecoder tokenCodec.wrapForDecode( m_buffer.get(), offset, tokenCodec.sbeBlockLength(), tokenCodec.sbeSchemaVersion(), m_length); - Signal signal = static_cast(tokenCodec.signal()); - PrimitiveType type = static_cast(tokenCodec.primitiveType()); - Presence presence = static_cast(tokenCodec.presence()); - ByteOrder byteOrder = static_cast(tokenCodec.byteOrder()); + auto signal = static_cast(tokenCodec.signal()); + auto type = static_cast(tokenCodec.primitiveType()); + auto presence = static_cast(tokenCodec.presence()); + auto byteOrder = static_cast(tokenCodec.byteOrder()); std::int32_t tokenOffset = tokenCodec.tokenOffset(); std::int32_t tokenSize = tokenCodec.tokenSize(); std::int32_t id = tokenCodec.fieldId(); From 8d442477bf5d0f2779d5a59920523e60f4cf7729 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 2 Feb 2024 12:05:34 +0100 Subject: [PATCH 1078/1594] [Gradle] Use `lifecycle` logging and `--console=plain`. --- gradle.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 65930afd28..dbc8af63bb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,8 @@ org.gradle.java.installations.auto-download=false org.gradle.java.installations.fromEnv=BUILD_JAVA_HOME -org.gradle.logging.level=warn +org.gradle.console=plain +org.gradle.logging.level=lifecycle org.gradle.warning.mode=all # HTTP timeouts for Gradle From dfa6d8987b560b05864e6429d33c1137ec9882cb Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 2 Feb 2024 12:09:50 +0100 Subject: [PATCH 1079/1594] [CI] Upgrade to Github actions to v4. --- .github/workflows/ci.yml | 52 ++++++++++++++++++------------------ .github/workflows/codeql.yml | 22 +++++++-------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e317d2bfc8..4661a213ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,21 +32,21 @@ jobs: os: [ 'ubuntu-22.04', 'windows-latest' ] steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache Gradle dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Setup java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ matrix.java }} @@ -56,7 +56,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - name: Setup java 8 to run the Gradle script - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 8 @@ -75,21 +75,21 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache Gradle dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Cache NuGet dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.nuget/packages key: ${{ runner.os }}-nuget-${{ hashFiles('csharp/**/*.sln') }} @@ -118,16 +118,16 @@ jobs: CXX: g++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache Gradle dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} @@ -153,16 +153,16 @@ jobs: CXX: g++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache Gradle dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} @@ -189,16 +189,16 @@ jobs: CXX: clang++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache Gradle dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} @@ -227,16 +227,16 @@ jobs: CXX: clang++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache Gradle dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} @@ -265,7 +265,7 @@ jobs: CXX: clang++ steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install CMake run: | curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz @@ -286,7 +286,7 @@ jobs: CXX: cl steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install CMake run: | $client = new-object System.Net.WebClient @@ -305,16 +305,16 @@ jobs: rust: [ stable, beta, nightly ] steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache Gradle dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index fba15354c6..37de50f0d6 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -37,21 +37,21 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache Gradle dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Setup java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ matrix.java }} @@ -92,21 +92,21 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache Gradle dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Cache NuGet dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.nuget/packages key: ${{ runner.os }}-nuget-${{ hashFiles('csharp/**/*.sln') }} @@ -148,16 +148,16 @@ jobs: CXX: g++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache Gradle dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: | ${{ runner.os }}-gradle- - name: Cache Gradle wrappers - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} From ecb63d82cd5c36fea3c0155ad8b6490802c2244f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 2 Feb 2024 12:22:56 +0100 Subject: [PATCH 1080/1594] [CI] Expect Gradle to detect that it is running in a terminal. --- gradle.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index dbc8af63bb..13abd18beb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,6 @@ org.gradle.java.installations.auto-download=false org.gradle.java.installations.fromEnv=BUILD_JAVA_HOME -org.gradle.console=plain org.gradle.logging.level=lifecycle org.gradle.warning.mode=all From 8005dbc317e6346471c6d54a21878440703097e8 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 5 Feb 2024 10:07:07 +0100 Subject: [PATCH 1081/1594] [Java] Upgrade to JUnit 5.10.2. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3e9a6dea27..8cf1d0f03d 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' -def junitVersion = '5.10.1' +def junitVersion = '5.10.2' def jmhVersion = '1.37' def agronaVersion = '1.20.0' def agronaVersionRange = '[1.20.0,2.0[' // allow any release >= 1.20.0 and < 2.0.0 From a4430f2a60a9764b9e5697411693f91aacc70194 Mon Sep 17 00:00:00 2001 From: Odysseas Georgoudis Date: Tue, 6 Feb 2024 18:36:32 +0000 Subject: [PATCH 1082/1594] [C++] make message header members constexpr (#971) --- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index c82a0f0a14..54a1683371 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2673,10 +2673,10 @@ private CharSequence generateMessageFlyweightCode( "%22$s" + "public:\n" + - " static const %1$s SBE_BLOCK_LENGTH = %2$s;\n" + - " static const %3$s SBE_TEMPLATE_ID = %4$s;\n" + - " static const %5$s SBE_SCHEMA_ID = %6$s;\n" + - " static const %7$s SBE_SCHEMA_VERSION = %8$s;\n" + + " static constexpr %1$s SBE_BLOCK_LENGTH = %2$s;\n" + + " static constexpr %3$s SBE_TEMPLATE_ID = %4$s;\n" + + " static constexpr %5$s SBE_SCHEMA_ID = %6$s;\n" + + " static constexpr %7$s SBE_SCHEMA_VERSION = %8$s;\n" + " static constexpr const char* SBE_SEMANTIC_VERSION = \"%13$s\";\n\n" + " enum MetaAttribute\n" + From 3e22c2e779ae05643c6b295e2b154000dd3a389a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 16 Feb 2024 11:32:12 +0000 Subject: [PATCH 1083/1594] [C++] Code tidy up and address Issue #970. --- sbe-tool/src/main/cpp/otf/IrDecoder.h | 29 ++++++++++++------- sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h | 21 ++++++-------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index 0b5c048669..b4ed9cefd8 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -48,9 +48,7 @@ namespace sbe { namespace otf { class IrDecoder { public: - IrDecoder() - { - } + IrDecoder() = default; int decode(char *irBuffer, std::uint64_t length) { @@ -106,11 +104,13 @@ class IrDecoder std::shared_ptr> result; std::for_each(m_messages.begin(), m_messages.end(), - [&](std::shared_ptr> tokens) + [&](const std::shared_ptr> &tokens) { Token &token = tokens->at(0); - if (token.signal() == Signal::BEGIN_MESSAGE && token.fieldId() == id && token.tokenVersion() == version) + if (token.signal() == Signal::BEGIN_MESSAGE && + token.fieldId() == id && + token.tokenVersion() <= version) { result = tokens; } @@ -124,7 +124,7 @@ class IrDecoder std::shared_ptr> result; std::for_each(m_messages.begin(), m_messages.end(), - [&](std::shared_ptr> tokens) + [&](const std::shared_ptr> &tokens) { Token &token = tokens->at(0); @@ -191,9 +191,14 @@ class IrDecoder FrameCodec frame; std::uint64_t offset = 0; - char tmp[256]; + char tmp[256] = {}; - frame.wrapForDecode(m_buffer.get(), offset, frame.sbeBlockLength(), frame.sbeSchemaVersion(), m_length); + frame.wrapForDecode( + m_buffer.get(), + offset, + FrameCodec::sbeBlockLength(), + FrameCodec::sbeSchemaVersion(), + m_length); frame.getPackageName(tmp, sizeof(tmp)); @@ -229,7 +234,11 @@ class IrDecoder TokenCodec tokenCodec; tokenCodec.wrapForDecode( - m_buffer.get(), offset, tokenCodec.sbeBlockLength(), tokenCodec.sbeSchemaVersion(), m_length); + m_buffer.get(), + offset, + TokenCodec::sbeBlockLength(), + TokenCodec::sbeSchemaVersion(), + m_length); auto signal = static_cast(tokenCodec.signal()); auto type = static_cast(tokenCodec.primitiveType()); @@ -240,7 +249,7 @@ class IrDecoder std::int32_t id = tokenCodec.fieldId(); std::int32_t version = tokenCodec.tokenVersion(); std::int32_t componentTokenCount = tokenCodec.componentTokenCount(); - char tmpBuffer[256]; + char tmpBuffer[256] = {}; std::uint64_t tmpLen = 0; tmpLen = tokenCodec.getName(tmpBuffer, sizeof(tmpBuffer)); diff --git a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h index 8b59b5df7d..edd65bff17 100644 --- a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h @@ -157,14 +157,13 @@ static void decodeComposite( std::uint64_t actingVersion, TokenListener &listener) { - listener.onBeginComposite(fieldToken, *tokens.get(), tokenIndex, toIndex); + listener.onBeginComposite(fieldToken, *tokens, tokenIndex, toIndex); for (size_t i = tokenIndex + 1; i < toIndex;) { Token &token = tokens->at(i); const size_t nextFieldIndex = i + token.componentTokenCount(); - - const std::size_t offset = static_cast(token.offset()); + const auto offset = static_cast(token.offset()); switch (token.signal()) { @@ -183,12 +182,12 @@ static void decodeComposite( case Signal::BEGIN_ENUM: listener.onEnum( - fieldToken, buffer + bufferIndex + offset, *tokens.get(), i, nextFieldIndex - 1, actingVersion); + fieldToken, buffer + bufferIndex + offset, *tokens, i, nextFieldIndex - 1, actingVersion); break; case Signal::BEGIN_SET: listener.onBitSet( - fieldToken, buffer + bufferIndex + offset, *tokens.get(), i, nextFieldIndex - 1, actingVersion); + fieldToken, buffer + bufferIndex + offset, *tokens, i, nextFieldIndex - 1, actingVersion); break; case Signal::ENCODING: @@ -202,7 +201,7 @@ static void decodeComposite( i += token.componentTokenCount(); } - listener.onEndComposite(fieldToken, *tokens.get(), tokenIndex, toIndex); + listener.onEndComposite(fieldToken, *tokens, tokenIndex, toIndex); } template @@ -246,13 +245,11 @@ static size_t decodeFields( break; case Signal::BEGIN_ENUM: - listener.onEnum( - fieldToken, buffer + offset, *tokens.get(), tokenIndex, nextFieldIndex - 2, actingVersion); + listener.onEnum(fieldToken, buffer + offset, *tokens, tokenIndex, nextFieldIndex - 2, actingVersion); break; case Signal::BEGIN_SET: - listener.onBitSet( - fieldToken, buffer + offset, *tokens.get(), tokenIndex, nextFieldIndex - 2, actingVersion); + listener.onBitSet(fieldToken, buffer + offset, *tokens, tokenIndex, nextFieldIndex - 2, actingVersion); break; case Signal::ENCODING: @@ -342,7 +339,7 @@ std::pair decodeGroups( const bool isPresent = token.tokenVersion() <= static_cast(actingVersion); Token &dimensionsTypeComposite = tokens->at(tokenIndex + 1); - std::size_t dimensionsLength = static_cast(dimensionsTypeComposite.encodedLength()); + auto dimensionsLength = static_cast(dimensionsTypeComposite.encodedLength()); if ((bufferIndex + dimensionsLength) > length) { @@ -391,7 +388,7 @@ std::pair decodeGroups( tokenIndex += token.componentTokenCount(); } - return std::pair(bufferIndex, tokenIndex); + return { bufferIndex, tokenIndex }; } /** From 04d10387c783a9de9e23800e0ee433143714cbec Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:07:43 +0100 Subject: [PATCH 1084/1594] [CI] Ensure that the HEAD of the PR branch is checked out instead of the generated merge commit. --- .github/workflows/ci.yml | 18 ++++++++++++++++++ .github/workflows/codeql.yml | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4661a213ea..5fa80caccd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -76,6 +78,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -119,6 +123,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -154,6 +160,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -190,6 +198,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -228,6 +238,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -266,6 +278,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Install CMake run: | curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz @@ -287,6 +301,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Install CMake run: | $client = new-object System.Net.WebClient @@ -306,6 +322,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 37de50f0d6..98c49cca6a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -38,6 +38,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -93,6 +95,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -149,6 +153,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: From 39b75cfdf3806a08c6c9d68c4720ec400511b43a Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 22 Feb 2024 10:31:49 +0000 Subject: [PATCH 1085/1594] [Java] Formatting. --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index fe49069b5c..0c8481b997 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -617,9 +617,9 @@ private static void generateAccessOrderListener( sb.append(indent).append("switch (codecState())\n") .append(indent).append("{\n"); - fieldPrecedenceModel.forEachTransition(interaction, transitionGroup -> + fieldPrecedenceModel.forEachTransition(interaction, (transitionGroup) -> { - transitionGroup.forEachStartState(startState -> + transitionGroup.forEachStartState((startState) -> sb.append(indent).append(" case ").append(stateCaseForSwitchCase(startState)).append(":\n")); sb.append(indent).append(" codecState(") .append(qualifiedStateCase(transitionGroup.endState())).append(");\n") From a146c569323d3c2f72c1a3bd1b19f0e1b5c63b45 Mon Sep 17 00:00:00 2001 From: pcdv Date: Thu, 22 Feb 2024 11:39:39 +0100 Subject: [PATCH 1086/1594] [Java] Cope with optional sets not being present when pretty printing decoders for debugging. Issue #976 (#977) Co-authored-by: Paul COLIN DE VERDIERE --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 0c8481b997..9acd9cf9a7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -4564,9 +4564,6 @@ private int writeTokenDisplay( break; case BEGIN_SET: - append(sb, indent, "this." + fieldName + "().appendTo(builder);"); - break; - case BEGIN_COMPOSITE: { final String typeName = formatClassName(decoderName(typeToken.applicableTypeName())); From 104d79d0c6fb44b0553639cd2f20925adcff5329 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 22 Feb 2024 10:45:22 +0000 Subject: [PATCH 1087/1594] [Java] Formatting. --- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 9acd9cf9a7..f4889e3751 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -4568,7 +4568,7 @@ private int writeTokenDisplay( { final String typeName = formatClassName(decoderName(typeToken.applicableTypeName())); append(sb, indent, "final " + typeName + " " + fieldName + " = this." + fieldName + "();"); - append(sb, indent, "if (" + fieldName + " != null)"); + append(sb, indent, "if (null != " + fieldName + ")"); append(sb, indent, "{"); append(sb, indent, " " + fieldName + ".appendTo(builder);"); append(sb, indent, "}"); From 6d9c83d59d6647444fbe96bbc4540a1909f80303 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 22 Feb 2024 10:55:51 +0000 Subject: [PATCH 1088/1594] Upgrade codeql-actions to v3. --- .github/workflows/codeql.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 98c49cca6a..613037cdf9 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -64,7 +64,7 @@ jobs: echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml @@ -73,7 +73,7 @@ jobs: run: ./gradlew - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" @@ -122,7 +122,7 @@ jobs: dotnet-version: ${{ matrix.dotnet }} - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml @@ -131,7 +131,7 @@ jobs: run: ./csharp/build.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" @@ -175,7 +175,7 @@ jobs: echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml @@ -184,7 +184,7 @@ jobs: run: ./cppbuild/cppbuild - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{ matrix.language }}" upload: false @@ -199,6 +199,6 @@ jobs: output: sarif-results/${{ matrix.language }}.sarif - name: Upload SARIF - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v3 with: sarif_file: sarif-results/${{ matrix.language }}.sarif From f63f24f5b6981cfaa507d0fa43f51d921bc1de8b Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 22 Feb 2024 11:03:40 +0000 Subject: [PATCH 1089/1594] Upgrade CodeQl to use setup-dotnet to v3. --- .github/workflows/codeql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 613037cdf9..6909739161 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -117,7 +117,7 @@ jobs: restore-keys: | ${{ runner.os }}-nuget- - name: Setup dotnet - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@v3 with: dotnet-version: ${{ matrix.dotnet }} From 6511ecef1cfec1c622f59f8dbb48e5853c1ceda5 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 22 Feb 2024 11:13:54 +0000 Subject: [PATCH 1090/1594] Upgrade CodeQl to use setup-dotnet to v4. --- .github/workflows/codeql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 6909739161..e9842e0a1e 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -117,7 +117,7 @@ jobs: restore-keys: | ${{ runner.os }}-nuget- - name: Setup dotnet - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: ${{ matrix.dotnet }} From ddd64672e4fa73600413d5d1c7999f99715bbf9f Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Thu, 22 Feb 2024 11:19:45 +0000 Subject: [PATCH 1091/1594] Use 3.1.x for C# in CI --- .github/workflows/ci.yml | 4 ++-- .github/workflows/codeql.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5fa80caccd..d3272dee71 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: strategy: fail-fast: false matrix: - dotnet: [ '3.1.301' ] + dotnet: [ '3.1.x' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -100,7 +100,7 @@ jobs: restore-keys: | ${{ runner.os }}-nuget- - name: Setup dotnet - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@v4 with: dotnet-version: ${{ matrix.dotnet }} - name: Build diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e9842e0a1e..d9819c349b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -88,7 +88,7 @@ jobs: fail-fast: false matrix: language: [ 'csharp' ] - dotnet: [ '3.1.301' ] + dotnet: [ '3.1.x' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 From 66813a4b6a8a9d2a97e5f241c590f86ea77d2879 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Mon, 26 Feb 2024 13:25:23 +0000 Subject: [PATCH 1092/1594] Upgrade .NET SDK to 8.0.201. (#978) I've updated the .NET SDK to `8.0`, which is the most recent LTS version. Support ends on 10 November 2026. There are several C# projects in the SBE solution. Only `sbe-dll` is consumed by users of SBE. Previously, `sbe-dll` had two targets: - `.NET Standard 2.0` (2017, supported by `.NET Framework >= 4.6.1` and `.NET Core >= 2.0`, which were both superseded by `.NET`) - `.NET Framework 4.5` (2012) In this commit, I have removed the _ancient_ `.NET Framework 4.5` target. This makes it easier to build SBE on Linux, as one only needs a recent .NET installation. I have also changed the other C# projects to target `.NET 8.0` and updated their dependencies. --- .github/workflows/ci.yml | 2 +- csharp/sbe-benchmarks/sbe-benchmarks.csproj | 9 ++++----- csharp/sbe-dll/sbe-dll.csproj | 8 ++------ csharp/sbe-generated/sbe-generated.csproj | 13 +++++-------- csharp/sbe-samples-car/sbe-samples-car.csproj | 6 +----- .../sbe-samples-extension.csproj | 9 ++------- csharp/sbe-tests/sbe-tests.csproj | 11 +++++------ 7 files changed, 20 insertions(+), 38 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3272dee71..cfb5c13454 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: strategy: fail-fast: false matrix: - dotnet: [ '3.1.x' ] + dotnet: [ '8.0.x' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 diff --git a/csharp/sbe-benchmarks/sbe-benchmarks.csproj b/csharp/sbe-benchmarks/sbe-benchmarks.csproj index 8d10e86c4f..3324fe01c2 100644 --- a/csharp/sbe-benchmarks/sbe-benchmarks.csproj +++ b/csharp/sbe-benchmarks/sbe-benchmarks.csproj @@ -1,11 +1,11 @@  - net461;netcoreapp3.1 + net8.0 Org.SbeTool.Sbe.Benchmarks sbe-benchmarks exe - Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. + Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014-2024. All rights reserved. SBE Exe @@ -16,9 +16,8 @@ - - - + + diff --git a/csharp/sbe-dll/sbe-dll.csproj b/csharp/sbe-dll/sbe-dll.csproj index 2c369ba21e..747306310d 100644 --- a/csharp/sbe-dll/sbe-dll.csproj +++ b/csharp/sbe-dll/sbe-dll.csproj @@ -1,11 +1,11 @@  - net45;netstandard2.0 + netstandard2.0 True SBE Org.SbeTool.Sbe.Dll Org.SbeTool.Sbe.Dll - Copyright (C) Bill Segall 2018-2021, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. + Copyright (C) Bill Segall 2018-2021, MarketFactory Inc 2017, Adaptive 2014-2024. All rights reserved. true Bill Segall, MarketFactory Inc, Adaptive Consulting Apache-2.0 @@ -37,10 +37,6 @@ - - - - diff --git a/csharp/sbe-generated/sbe-generated.csproj b/csharp/sbe-generated/sbe-generated.csproj index 806168d7d5..f5b42e2355 100644 --- a/csharp/sbe-generated/sbe-generated.csproj +++ b/csharp/sbe-generated/sbe-generated.csproj @@ -1,26 +1,23 @@  - net45;netstandard2.0 + net8.0 Org.SbeTool.Sbe.Generated Org.SbeTool.Sbe.Generated - Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. + Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014-2024. All rights reserved. + 9 - TRACE,SBE_ENABLE_PRECEDENCE_CHECKS + TRACE;SBE_ENABLE_PRECEDENCE_CHECKS - TRACE,SBE_ENABLE_PRECEDENCE_CHECKS + TRACE;SBE_ENABLE_PRECEDENCE_CHECKS - - - - diff --git a/csharp/sbe-samples-car/sbe-samples-car.csproj b/csharp/sbe-samples-car/sbe-samples-car.csproj index 8ee29c2329..cf39c0d9ef 100644 --- a/csharp/sbe-samples-car/sbe-samples-car.csproj +++ b/csharp/sbe-samples-car/sbe-samples-car.csproj @@ -1,7 +1,7 @@  - net45;netcoreapp3.1 + net8.0 exe Org.SbeTool.Sbe.Example.Car Org.SbeTool.Sbe.Example.Car @@ -16,8 +16,4 @@ - - - - diff --git a/csharp/sbe-samples-extension/sbe-samples-extension.csproj b/csharp/sbe-samples-extension/sbe-samples-extension.csproj index 97899b3aa4..f4f7a7e311 100644 --- a/csharp/sbe-samples-extension/sbe-samples-extension.csproj +++ b/csharp/sbe-samples-extension/sbe-samples-extension.csproj @@ -1,11 +1,11 @@  - net45;netstandard2.0 + net8.0 exe Org.SbeTool.Sbe.Example.Extension Org.SbeTool.Sbe.Example.Extension - Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. + Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014-2024. All rights reserved. @@ -17,9 +17,4 @@ - - - - - diff --git a/csharp/sbe-tests/sbe-tests.csproj b/csharp/sbe-tests/sbe-tests.csproj index 468a1ab8ba..4d8bcee13f 100644 --- a/csharp/sbe-tests/sbe-tests.csproj +++ b/csharp/sbe-tests/sbe-tests.csproj @@ -1,10 +1,10 @@  - net45;netcoreapp3.1 + net8.0 Org.SbeTool.Sbe.Tests Org.SbeTool.Sbe.UnitTests True - Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014. All rights reserved. + Copyright (C) Bill Segall 2018, MarketFactory Inc 2017, Adaptive 2014-2024. All rights reserved. @@ -18,10 +18,9 @@ - - - - + + + From c942cc6cf3e9f97e5d475c0e4b7e9a44df160228 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 26 Feb 2024 21:27:37 +0100 Subject: [PATCH 1093/1594] [CI] Build PRs against merge commit. --- .github/workflows/ci.yml | 18 +++++++++--------- .github/workflows/codeql.yml | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cfb5c13454..7ac853b7cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -79,7 +79,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -124,7 +124,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -161,7 +161,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -199,7 +199,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -239,7 +239,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -279,7 +279,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.sha }} - name: Install CMake run: | curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz @@ -302,7 +302,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.sha }} - name: Install CMake run: | $client = new-object System.Net.WebClient @@ -323,7 +323,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d9819c349b..db70001ed7 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,7 +39,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -96,7 +96,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: @@ -154,7 +154,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.sha }} - name: Cache Gradle dependencies uses: actions/cache@v4 with: From fae3e45ae39d78f5b8db2bf06cab752be352b0cc Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:37:57 +0100 Subject: [PATCH 1094/1594] [Java] Upgrade to Agrona 1.21.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 8cf1d0f03d..bb0605be01 100644 --- a/build.gradle +++ b/build.gradle @@ -58,8 +58,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.10.2' def jmhVersion = '1.37' -def agronaVersion = '1.20.0' -def agronaVersionRange = '[1.20.0,2.0[' // allow any release >= 1.20.0 and < 2.0.0 +def agronaVersion = '1.21.0' +def agronaVersionRange = '[1.21.0,2.0[' // allow any release >= 1.20.0 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 4c32cfbfff12bce30053ac9b986ca773918f3f9c Mon Sep 17 00:00:00 2001 From: BenBudr <34384555+BenBudr@users.noreply.github.com> Date: Wed, 20 Mar 2024 09:17:32 +0000 Subject: [PATCH 1095/1594] [C++] small test fix (#980) --- sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp index 9f7bb9184c..ecd3df1336 100644 --- a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp +++ b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp @@ -3624,7 +3624,7 @@ TEST_F(FieldAccessOrderCheckTest, allowsEncodingAndDecodingAsciiInsideGroupInSch AsciiInsideGroup::sbeSchemaVersion(), BUFFER_LEN ); - char aOut[6]; + char aOut[7] = {'\0'}; decoder.getA(aOut, 6); EXPECT_STREQ(aOut, "GBPUSD"); AsciiInsideGroup::B &b = decoder.b(); From 6d3f6b629ddef538839a684451ee4e6ce9b0cd70 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Thu, 21 Mar 2024 10:47:20 -0500 Subject: [PATCH 1096/1594] [Rust] Updated RustGenerator.generatePrimitiveOptionalDecoder() to resolve Issue #972 (#981) Co-authored-by: Michael Ward --- build.gradle | 1 + rust/Cargo.toml | 1 + rust/tests/issue_972_test.rs | 37 +++++++++++++++++++ .../sbe/generation/rust/RustGenerator.java | 8 ---- sbe-tool/src/test/resources/issue972.xml | 25 +++++++++++++ 5 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 rust/tests/issue_972_test.rs create mode 100644 sbe-tool/src/test/resources/issue972.xml diff --git a/build.gradle b/build.gradle index bb0605be01..a8d9b00dfb 100644 --- a/build.gradle +++ b/build.gradle @@ -587,6 +587,7 @@ tasks.register('generateRustTestCodecs', JavaExec) { 'sbe.validation.xsd': validationXsdPath) args = ['sbe-tool/src/test/resources/issue435.xml', 'sbe-tool/src/test/resources/issue895.xml', + 'sbe-tool/src/test/resources/issue972.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', 'sbe-tool/src/test/resources/nested-composite-name.xml', ] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 020747c06d..6d47fc3746 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -13,6 +13,7 @@ examples_uk_co_real_logic_sbe_benchmarks_fix = { path = "../generated/rust/uk_co issue_435 = { path = "../generated/rust/issue435" } issue_895 = { path = "../generated/rust/issue895" } +issue_972 = { path = "../generated/rust/issue972" } baseline_bigendian = { path = "../generated/rust/baseline-bigendian" } nested_composite_name = { path = "../generated/rust/nested-composite-name" } diff --git a/rust/tests/issue_972_test.rs b/rust/tests/issue_972_test.rs new file mode 100644 index 0000000000..bc3a938247 --- /dev/null +++ b/rust/tests/issue_972_test.rs @@ -0,0 +1,37 @@ +use issue_972::*; + +fn create_encoder(buffer: &mut Vec) -> Issue972Encoder { + let issue_972 = Issue972Encoder::default().wrap( + WriteBuf::new(buffer.as_mut_slice()), + message_header_codec::ENCODED_LENGTH, + ); + let mut header = issue_972.header(0); + header.parent().unwrap() +} + +#[test] +fn round_trip() -> SbeResult<()> { + // encode... + let mut buffer = vec![0u8; 256]; + let encoder = create_encoder(&mut buffer); + let mut new_composite_encoder = encoder.new_field_encoder(); + new_composite_encoder.f1(2007); + new_composite_encoder.f2(2012); + + // decode... + let buf = ReadBuf::new(buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + assert_eq!(SBE_BLOCK_LENGTH, header.block_length()); + assert_eq!(SBE_SCHEMA_VERSION, header.version()); + assert_eq!(SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(SBE_SCHEMA_ID, header.schema_id()); + + let decoder = Issue972Decoder::default().header(header); + if let Either::Right(composite) = decoder.new_field_decoder() { + assert_eq!(2007, composite.f1().unwrap()); + assert_eq!(2012, composite.f2().unwrap()); + } else { + panic!() + } + Ok(()) +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index b1620446a2..d30bd318f6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -766,18 +766,10 @@ private static void generatePrimitiveOptionalDecoder( formatFunctionName(name), rustPrimitiveType); - if (fieldToken.version() > 0) - { - indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version()); - indent(sb, level + 2, "return None;\n"); - indent(sb, level + 1, "}\n\n"); - } - indent(sb, level + 1, "let value = self.get_buf().get_%s_at(self.%s);\n", rustPrimitiveType, getBufOffset(fieldToken)); - final String literal = generateRustLiteral(primitiveType, encoding.applicableNullValue().toString()); if (literal.endsWith("::NAN")) { diff --git a/sbe-tool/src/test/resources/issue972.xml b/sbe-tool/src/test/resources/issue972.xml new file mode 100644 index 0000000000..f64bd616be --- /dev/null +++ b/sbe-tool/src/test/resources/issue972.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 7800371538ce8f6953bf89bbda1ef057a7fb7e1e Mon Sep 17 00:00:00 2001 From: Grzegorz Gierlach Date: Thu, 21 Mar 2024 16:48:28 +0100 Subject: [PATCH 1097/1594] [Rust] Take slices by reference. (#979) --- rust/tests/baseline_test.rs | 6 +++--- rust/tests/big_endian_test.rs | 6 +++--- rust/tests/extension_test.rs | 6 +++--- .../uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 8 ++++---- .../co/real_logic/sbe/generation/rust/RustGenerator.java | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/rust/tests/baseline_test.rs b/rust/tests/baseline_test.rs index c223c83989..bff75170c4 100644 --- a/rust/tests/baseline_test.rs +++ b/rust/tests/baseline_test.rs @@ -176,8 +176,8 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { car.model_year(2013); car.available(BooleanType::T); car.code(Model::A); - car.some_numbers([1, 2, 3, 4]); - car.vehicle_code([97, 98, 99, 100, 101, 102]); // abcdef + car.some_numbers(&[1, 2, 3, 4]); + car.vehicle_code(&[97, 98, 99, 100, 101, 102]); // abcdef extras.set_cruise_control(true); extras.set_sports_pack(true); @@ -187,7 +187,7 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { let mut engine = car.engine_encoder(); engine.capacity(2000); engine.num_cylinders(4); - engine.manufacturer_code([49, 50, 51]); // 123 + engine.manufacturer_code(&[49, 50, 51]); // 123 engine.efficiency(35); engine.booster_enabled(BooleanType::T); let mut booster = engine.booster_encoder(); diff --git a/rust/tests/big_endian_test.rs b/rust/tests/big_endian_test.rs index a1e107bc8d..a5a749c94a 100644 --- a/rust/tests/big_endian_test.rs +++ b/rust/tests/big_endian_test.rs @@ -170,8 +170,8 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { car.model_year(2013); car.available(BooleanType::T); car.code(Model::A); - car.some_numbers([0, 1, 2, 3, 4]); - car.vehicle_code(*b"abcdef"); + car.some_numbers(&[0, 1, 2, 3, 4]); + car.vehicle_code(b"abcdef"); extras.set_cruise_control(true); extras.set_sports_pack(true); @@ -181,7 +181,7 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { let mut engine = car.engine_encoder(); engine.capacity(2000); engine.num_cylinders(4); - engine.manufacturer_code(*b"123"); + engine.manufacturer_code(b"123"); engine.efficiency(35); engine.booster_enabled(BooleanType::T); let mut booster = engine.booster_encoder(); diff --git a/rust/tests/extension_test.rs b/rust/tests/extension_test.rs index ad813c056f..07c81e9fb7 100644 --- a/rust/tests/extension_test.rs +++ b/rust/tests/extension_test.rs @@ -177,8 +177,8 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { car.model_year(2013); car.available(BooleanType::T); car.code(Model::A); - car.some_numbers([0, 1, 2, 3]); - car.vehicle_code([97, 98, 99, 100, 101, 102]); // abcdef + car.some_numbers(&[0, 1, 2, 3]); + car.vehicle_code(&[97, 98, 99, 100, 101, 102]); // abcdef extras.set_cruise_control(true); extras.set_sports_pack(true); @@ -188,7 +188,7 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { let mut engine = car.engine_encoder(); engine.capacity(2000); engine.num_cylinders(4); - engine.manufacturer_code([49, 50, 51]); // 123 + engine.manufacturer_code(&[49, 50, 51]); // 123 engine.efficiency(35); engine.booster_enabled(BooleanType::T); let mut booster = engine.booster_encoder(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 7d0b79a0aa..a51b2746da 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -56,7 +56,7 @@ void generate() throws IOException { indent(libRs, 0, "#![forbid(unsafe_code)]\n"); indent(libRs, 0, "#![allow(clippy::upper_case_acronyms)]\n"); - indent(libRs, 0, "#![allow(non_camel_case_types)]\n"); + indent(libRs, 0, "#![allow(non_camel_case_types)]\n\n"); indent(libRs, 0, "use ::core::{convert::TryInto};\n\n"); final ArrayList modules = new ArrayList<>(); @@ -225,8 +225,8 @@ static void generateWriteBuf(final Writer writer, final ByteOrder byteOrder) thr indent(writer, 1, "#[inline]\n"); indent(writer, 1, - "pub fn put_bytes_at(&mut self, index: usize, bytes: [u8; COUNT]) -> usize {\n"); - indent(writer, 2, "self.data[index..index + COUNT].copy_from_slice(&bytes);\n"); + "pub fn put_bytes_at(&mut self, index: usize, bytes: &[u8; COUNT]) -> usize {\n"); + indent(writer, 2, "self.data[index..index + COUNT].copy_from_slice(bytes);\n"); indent(writer, 2, "COUNT\n"); indent(writer, 1, "}\n\n"); @@ -245,7 +245,7 @@ static void generateWriteBuf(final Writer writer, final ByteOrder byteOrder) thr // put__at indent(writer, 1, "#[inline]\n"); indent(writer, 1, "pub fn put_%1$s_at(&mut self, index: usize, value: %1$s) {\n", primitiveType); - indent(writer, 2, "self.put_bytes_at(index, %s::to_%s_bytes(value));\n", primitiveType, endianness); + indent(writer, 2, "self.put_bytes_at(index, &%s::to_%s_bytes(value));\n", primitiveType, endianness); indent(writer, 1, "}\n\n"); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index d30bd318f6..d0067d836c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -379,7 +379,7 @@ private static void generatePrimitiveEncoder( indent(sb, level, "/// - encodedLength: %d\n", typeToken.encodedLength()); indent(sb, level, "/// - version: %d\n", typeToken.version()); indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn %s(&mut self, value: [%s; %d]) {\n", + indent(sb, level, "pub fn %s(&mut self, value: &[%s; %d]) {\n", formatFunctionName(name), rustPrimitiveType, arrayLength); From a29ea3e4ea581aacdf7cceff67540f12bcb1bf34 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Fri, 22 Mar 2024 04:03:52 -0500 Subject: [PATCH 1098/1594] [Rust] updated code generator to prevent rust warning for "ambiguous glob re-exports" (#982) Co-authored-by: Michael Ward --- rust/benches/car_benchmark.rs | 2 +- rust/tests/baseline_test.rs | 19 ++++++++---- rust/tests/big_endian_test.rs | 15 ++++++++-- rust/tests/extension_test.rs | 19 ++++++++---- rust/tests/issue_435_test.rs | 4 +++ rust/tests/issue_895_test.rs | 6 +--- rust/tests/issue_972_test.rs | 2 +- .../sbe/generation/rust/LibRsDef.java | 8 +---- .../sbe/generation/rust/MessageCoderDef.java | 3 +- .../sbe/generation/rust/RustGenerator.java | 30 ++++++++++++++----- 10 files changed, 74 insertions(+), 34 deletions(-) diff --git a/rust/benches/car_benchmark.rs b/rust/benches/car_benchmark.rs index 92b964147a..06b542452a 100644 --- a/rust/benches/car_benchmark.rs +++ b/rust/benches/car_benchmark.rs @@ -1,6 +1,6 @@ +use car_codec::encoder::*; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use examples_uk_co_real_logic_sbe_benchmarks::*; -use car_codec::encoder::*; const MANUFACTURER: &[u8] = b"MANUFACTURER"; const MODEL: &[u8] = b"MODEL"; diff --git a/rust/tests/baseline_test.rs b/rust/tests/baseline_test.rs index bff75170c4..58a8503d20 100644 --- a/rust/tests/baseline_test.rs +++ b/rust/tests/baseline_test.rs @@ -1,8 +1,17 @@ -use std::fs::File; -use std::io::prelude::*; - -use examples_baseline::*; -use car_codec::encoder::*; +use examples_baseline::{ + boolean_type::BooleanType, + boost_type::BoostType, + car_codec::{ + encoder::{AccelerationEncoder, FuelFiguresEncoder, PerformanceFiguresEncoder}, + *, + }, + message_header_codec, + message_header_codec::MessageHeaderDecoder, + model::Model, + optional_extras::OptionalExtras, + Encoder, ReadBuf, SbeResult, WriteBuf, +}; +use std::{fs::File, io::prelude::*}; fn read_sbe_file_generated_from_java_example() -> std::io::Result> { // Generated by the generateCarExampleDataFile gradle task. diff --git a/rust/tests/big_endian_test.rs b/rust/tests/big_endian_test.rs index a5a749c94a..aabea63ce2 100644 --- a/rust/tests/big_endian_test.rs +++ b/rust/tests/big_endian_test.rs @@ -1,5 +1,16 @@ -use baseline_bigendian::*; -use car_codec::encoder::*; +use baseline_bigendian::{ + boolean_type::BooleanType, + boost_type::BoostType, + car_codec::{ + encoder::{AccelerationEncoder, FuelFiguresEncoder, PerformanceFiguresEncoder}, + *, + }, + message_header_codec, + message_header_codec::MessageHeaderDecoder, + model::Model, + optional_extras::OptionalExtras, + Encoder, ReadBuf, SbeResult, WriteBuf, +}; #[test] fn big_endian_baseline_example() -> SbeResult<()> { diff --git a/rust/tests/extension_test.rs b/rust/tests/extension_test.rs index 07c81e9fb7..072b9b8baa 100644 --- a/rust/tests/extension_test.rs +++ b/rust/tests/extension_test.rs @@ -1,8 +1,17 @@ -use std::fs::File; -use std::io::prelude::*; - -use examples_extension::*; -use car_codec::encoder::*; +use examples_extension::{ + boolean_type::BooleanType, + boost_type::BoostType, + car_codec::{ + encoder::{AccelerationEncoder, FuelFiguresEncoder, PerformanceFiguresEncoder}, + *, + }, + message_header_codec, + message_header_codec::MessageHeaderDecoder, + model::Model, + optional_extras::OptionalExtras, + Encoder, ReadBuf, SbeResult, WriteBuf, +}; +use std::{fs::File, io::prelude::*}; fn read_sbe_file_generated_from_java_example() -> std::io::Result> { // Generated by the generateCarExampleDataFile gradle task. diff --git a/rust/tests/issue_435_test.rs b/rust/tests/issue_435_test.rs index 87bd9a075e..8ac9ce8a50 100644 --- a/rust/tests/issue_435_test.rs +++ b/rust/tests/issue_435_test.rs @@ -1,4 +1,8 @@ use ::issue_435::*; +use issue_435::{ + enum_ref::EnumRef, issue_435_codec::*, message_header_codec::MessageHeaderDecoder, + set_ref::SetRef, +}; fn create_encoder(buffer: &mut Vec) -> Issue435Encoder { let issue_435 = Issue435Encoder::default().wrap( diff --git a/rust/tests/issue_895_test.rs b/rust/tests/issue_895_test.rs index dd9b19fa04..96968d2459 100644 --- a/rust/tests/issue_895_test.rs +++ b/rust/tests/issue_895_test.rs @@ -1,8 +1,4 @@ -use issue_895::{ - issue_895_codec::{decoder::Issue895Decoder, encoder::Issue895Encoder}, - MessageHeaderDecoder, ReadBuf, SbeResult, WriteBuf, ENCODED_LENGTH, SBE_BLOCK_LENGTH, - SBE_SCHEMA_ID, SBE_SCHEMA_VERSION, SBE_TEMPLATE_ID, -}; +use issue_895::{issue_895_codec::*, message_header_codec::*, *}; fn create_encoder(buffer: &mut Vec) -> Issue895Encoder { let issue_895 = diff --git a/rust/tests/issue_972_test.rs b/rust/tests/issue_972_test.rs index bc3a938247..2cbab324d0 100644 --- a/rust/tests/issue_972_test.rs +++ b/rust/tests/issue_972_test.rs @@ -1,4 +1,4 @@ -use issue_972::*; +use issue_972::{issue_972_codec::*, message_header_codec::MessageHeaderDecoder, *}; fn create_encoder(buffer: &mut Vec) -> Issue972Encoder { let issue_972 = Issue972Encoder::default().wrap( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index a51b2746da..3c5ae1542d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -78,13 +78,6 @@ void generate() throws IOException } indent(libRs, 0, "\n"); - // add re-export of modules - for (final String module : modules) - { - indent(libRs, 0, "pub use crate::%s::*;\n", toLowerSnakeCase(module)); - } - indent(libRs, 0, "\n"); - generateSbeErrorEnum(libRs); generateEitherEnum(libRs); @@ -163,6 +156,7 @@ static void generateReadBuf(final Appendable writer, final ByteOrder byteOrder) indent(writer, 0, "}\n"); // impl ReadBuf ... + indent(writer, 0, "#[allow(dead_code)]\n"); indent(writer, 0, "impl<%s> %s<%s> {\n", BUF_LIFETIME, READ_BUF_TYPE, BUF_LIFETIME); indent(writer, 1, "#[inline]\n"); indent(writer, 1, "pub fn new(data: &%s [u8]) -> Self {\n", BUF_LIFETIME); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index 00c9ac03f6..dbe6fabc8f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -63,7 +63,8 @@ void generate( final List varData) throws IOException { indent(sb, 0, "pub mod %s {\n", codecType.toString().toLowerCase()); - indent(sb, 1, "use super::*;\n\n"); + indent(sb, 1, "use super::*;\n"); + indent(sb, 1, "use message_header_codec::*;\n\n"); // i.e. Decoder or Encoder final String msgTypeName = formatStructName(msgToken.name()) + codecType.name(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index d0067d836c..6569599993 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -449,7 +449,9 @@ private static void generateEnumEncoder( final String name) throws IOException { final String referencedName = typeToken.referencedName(); - final String enumType = formatStructName(referencedName == null ? typeToken.name() : referencedName); + final String enumType = format("%s::%s", + toLowerSnakeCase(referencedName == null ? typeToken.name() : referencedName), + formatStructName(referencedName == null ? typeToken.name() : referencedName)); if (fieldToken.isConstantEncoding()) { @@ -479,7 +481,10 @@ private static void generateBitSetEncoder( { final Encoding encoding = bitsetToken.encoding(); final String rustPrimitiveType = rustTypeName(encoding.primitiveType()); - final String structTypeName = formatStructName(bitsetToken.applicableTypeName()); + final String referencedName = bitsetToken.referencedName(); + final String structTypeName = format("%s::%s", + toLowerSnakeCase(referencedName == null ? bitsetToken.name() : referencedName), + formatStructName(bitsetToken.applicableTypeName())); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", formatFunctionName(name), structTypeName); @@ -496,7 +501,9 @@ private static void generateCompositeEncoder( final String name) throws IOException { final String encoderName = toLowerSnakeCase(encoderName(name)); - final String encoderTypeName = encoderName(formatStructName(typeToken.applicableTypeName())); + final String encoderTypeName = format("%s::%s", + codecModName(typeToken.referencedName() == null ? typeToken.name() : typeToken.referencedName()), + encoderName(formatStructName(typeToken.applicableTypeName()))); indent(sb, level, "/// COMPOSITE ENCODER\n"); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(self) -> %2$s {\n", @@ -556,7 +563,10 @@ private static void generateCompositeDecoder( final String name) throws IOException { final String decoderName = toLowerSnakeCase(decoderName(name)); - final String decoderTypeName = decoderName(formatStructName(typeToken.applicableTypeName())); + final String referencedName = typeToken.referencedName(); + final String decoderTypeName = format("%s::%s", + codecModName(referencedName == null ? typeToken.name() : referencedName), + decoderName(formatStructName(typeToken.applicableTypeName()))); indent(sb, level, "/// COMPOSITE DECODER\n"); indent(sb, level, "#[inline]\n"); if (fieldToken.version() > 0) @@ -575,7 +585,7 @@ private static void generateCompositeDecoder( } else { - indent(sb, level, "pub fn %s(self) -> %2$s {\n", + indent(sb, level, "pub fn %s(self) -> %s {\n", decoderName, decoderTypeName); @@ -593,7 +603,11 @@ private static void generateBitSetDecoder( { final Encoding encoding = bitsetToken.encoding(); final String rustPrimitiveType = rustTypeName(encoding.primitiveType()); - final String structTypeName = formatStructName(bitsetToken.applicableTypeName()); + final String referencedName = bitsetToken.referencedName(); + final String structTypeName = format("%s::%s", + toLowerSnakeCase(referencedName == null ? bitsetToken.name() : referencedName), + formatStructName(bitsetToken.applicableTypeName())); + indent(sb, level, "/// BIT SET DECODER\n"); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&self) -> %s {\n", formatFunctionName(name), structTypeName); @@ -834,7 +848,9 @@ private static void generateEnumDecoder( final String name) throws IOException { final String referencedName = typeToken.referencedName(); - final String enumType = formatStructName(referencedName == null ? typeToken.name() : referencedName); + final String enumType = format("%s::%s", + toLowerSnakeCase(referencedName == null ? typeToken.name() : referencedName), + formatStructName(referencedName == null ? typeToken.name() : referencedName)); if (fieldToken.isConstantEncoding()) { From cef4546dbf24aa857a40ae2fd2722cdb3a1e8179 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 29 Mar 2024 11:48:56 +0100 Subject: [PATCH 1099/1594] [Java] Upgrade to ASM 9.7. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index a8d9b00dfb..cafd1885c7 100644 --- a/build.gradle +++ b/build.gradle @@ -24,8 +24,8 @@ buildscript { mavenCentral() } dependencies { - classpath 'org.ow2.asm:asm:9.6' - classpath 'org.ow2.asm:asm-commons:9.6' + classpath 'org.ow2.asm:asm:9.7' + classpath 'org.ow2.asm:asm-commons:9.7' } } From 5bb47ee1068a90145e5b48cdf0596d60b2e2dba3 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 29 Mar 2024 11:55:56 +0100 Subject: [PATCH 1100/1594] [Java] Fix Javadoc copyright year range. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cafd1885c7..0f74a5e005 100644 --- a/build.gradle +++ b/build.gradle @@ -197,7 +197,7 @@ subprojects { javadoc { failOnError false title = '

      Simple Binary Encoding (SBE)

      ' - options.bottom = 'Copyright © 2013-2022 Real Logic Limited. All Rights Reserved.' + options.bottom = 'Copyright © 2013-2024 Real Logic Limited. All Rights Reserved.' options.encoding = 'UTF-8' options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' From f83d97680ce68bed3f85eea99c8069177b6c0ddd Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 29 Mar 2024 13:00:16 +0100 Subject: [PATCH 1101/1594] [Go] Capitalize enum element names to make them accessible outside the declaration unit. --- .../generation/golang/GolangGenerator.java | 2 +- .../golang/GolangGeneratorTest.java | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index 8fad299bb9..74f3d851c4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -1574,7 +1574,7 @@ private void generateEnumDecls( { sb.append(String.format( "\t%1$s%2$s%3$sEnum\n", - token.name(), + formatPropertyName(token.name()), generateWhitespace(longest - token.name().length() + 1), enumName)); } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java new file mode 100644 index 0000000000..4c7cbab82c --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.golang; + +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.io.InputStream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.containsString; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +class GolangGeneratorTest +{ + @Test + void shouldUseUpperCaseTypeNamesWhenReferencingEnumValues() throws Exception + { + try (InputStream in = Tests.getLocalResource("value-ref-with-lower-case-enum.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + + final GolangGenerator generator = new GolangGenerator(ir, outputManager); + generator.generate(); + + final String engineTypeSource = outputManager.getSource("issue505.EngineType").toString(); + assertThat(engineTypeSource, allOf( + containsString("type EngineTypeEnum uint8"), + containsString("type EngineTypeValues struct {\n" + + "\tGas EngineTypeEnum\n" + + "\tNullValue EngineTypeEnum\n}"))); + } + } +} From f33cd87414d3dcd5e1b96870c8b62d9fc8c1ee92 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 29 Mar 2024 13:09:01 +0100 Subject: [PATCH 1102/1594] [Go] Use upper case type name when referencing enums. Fixes #983 --- .../uk/co/real_logic/sbe/generation/golang/GolangGenerator.java | 2 +- .../real_logic/sbe/generation/golang/GolangGeneratorTest.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index 74f3d851c4..6580e373bb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -1768,7 +1768,7 @@ private void generateTypeBody( sb.append("\t").append(propertyName) .append(generateWhitespace(length)) .append(arrayspec) - .append(encodingToken.applicableTypeName()) + .append(formatTypeName(encodingToken.applicableTypeName())) .append("Enum\n"); break; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java index 4c7cbab82c..3de2d9c91d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java @@ -53,6 +53,8 @@ void shouldUseUpperCaseTypeNamesWhenReferencingEnumValues() throws Exception containsString("type EngineTypeValues struct {\n" + "\tGas EngineTypeEnum\n" + "\tNullValue EngineTypeEnum\n}"))); + final String messageSource = outputManager.getSource("issue505.SomeMessage").toString(); + assertThat(messageSource, containsString("type SomeMessage struct {\n\tEngineType EngineTypeEnum\n}")); } } } From 05c9f3c0ec5f082480a746d89c442cd27033962f Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 29 Mar 2024 13:34:01 +0100 Subject: [PATCH 1103/1594] [Go] Use upper case type name when referencing bit sets. --- .../generation/golang/GolangGenerator.java | 2 +- .../golang/GolangGeneratorTest.java | 31 +++++++++++++++++++ .../message-with-lower-case-bitset.xml | 28 +++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 sbe-tool/src/test/resources/message-with-lower-case-bitset.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index 6580e373bb..e4667ceabb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -1776,7 +1776,7 @@ private void generateTypeBody( sb.append("\t").append(propertyName) .append(generateWhitespace(length)) .append(arrayspec) - .append(encodingToken.applicableTypeName()) + .append(formatTypeName(encodingToken.applicableTypeName())) .append("\n"); break; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java index 3de2d9c91d..367e8644da 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java @@ -57,4 +57,35 @@ void shouldUseUpperCaseTypeNamesWhenReferencingEnumValues() throws Exception assertThat(messageSource, containsString("type SomeMessage struct {\n\tEngineType EngineTypeEnum\n}")); } } + + @Test + void shouldUseUpperCaseTypeNamesWhenReferencingBitSet() throws Exception + { + try (InputStream in = Tests.getLocalResource("message-with-lower-case-bitset.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + + final GolangGenerator generator = new GolangGenerator(ir, outputManager); + generator.generate(); + + final String eventTypeSource = outputManager.getSource("test.EventType").toString(); + assertThat(eventTypeSource, + containsString("type EventType [8]bool\n" + + "type EventTypeChoiceValue uint8\n" + + "type EventTypeChoiceValues struct {\n" + + "\tA EventTypeChoiceValue\n" + + "\tBb EventTypeChoiceValue\n" + + "\tCcc EventTypeChoiceValue\n" + + "\tD EventTypeChoiceValue\n" + + "\tEeeee EventTypeChoiceValue\n}\n\n" + + "var EventTypeChoice = EventTypeChoiceValues{0, 1, 2, 3, 4}")); + final String messageSource = outputManager.getSource("test.SomeMessage").toString(); + assertThat(messageSource, containsString("type SomeMessage struct {\n\tMyEvent EventType\n}")); + } + } } diff --git a/sbe-tool/src/test/resources/message-with-lower-case-bitset.xml b/sbe-tool/src/test/resources/message-with-lower-case-bitset.xml new file mode 100644 index 0000000000..b9bd91c5d4 --- /dev/null +++ b/sbe-tool/src/test/resources/message-with-lower-case-bitset.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + 0 + 1 + 2 + 3 + 4 + + + + + + + From 62adfb4d5e512d66c832a203955c84e8d355d3cc Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 29 Mar 2024 15:43:46 +0100 Subject: [PATCH 1104/1594] [Go] Use upper case names when generating methods for enum. --- .../generation/golang/GolangGenerator.java | 10 +- .../golang/GolangGeneratorTest.java | 242 +++++++++++++++++- .../value-ref-with-lower-case-enum.xml | 3 + 3 files changed, 246 insertions(+), 9 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index e4667ceabb..f87e32c710 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -1055,12 +1055,16 @@ private int generateFieldEncodeDecode( // Encode of a constant is a nullop, decode is assignment if (signalToken.isConstantEncoding()) { + final String rawValue = signalToken.encoding().constValue().toString(); + final int dotIndex = rawValue.indexOf('.'); + final String constantValue = toUpperFirstChar(rawValue.substring(0, dotIndex)) + "." + + toUpperFirstChar(rawValue.substring(dotIndex + 1)); decode.append(String.format( "\t%1$s.%2$s = %3$s\n", - varName, propertyName, signalToken.encoding().constValue())); + varName, propertyName, constantValue)); init.append(String.format( "\t%1$s.%2$s = %3$s\n", - varName, propertyName, signalToken.encoding().constValue())); + varName, propertyName, constantValue)); } else { @@ -1510,7 +1514,7 @@ private void generateEnum(final List tokens) throws IOException for (final Token token : tokens.subList(1, tokens.size() - 1)) { - generateSinceActingDeprecated(sb, enumName + "Enum", token.name(), token); + generateSinceActingDeprecated(sb, enumName + "Enum", formatPropertyName(token.name()), token); } out.append(generateFileHeader(ir.namespaces())); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java index 367e8644da..9e24f804b6 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java @@ -28,11 +28,13 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; class GolangGeneratorTest { @Test + @SuppressWarnings("MethodLength") void shouldUseUpperCaseTypeNamesWhenReferencingEnumValues() throws Exception { try (InputStream in = Tests.getLocalResource("value-ref-with-lower-case-enum.xml")) @@ -48,13 +50,208 @@ void shouldUseUpperCaseTypeNamesWhenReferencingEnumValues() throws Exception generator.generate(); final String engineTypeSource = outputManager.getSource("issue505.EngineType").toString(); - assertThat(engineTypeSource, allOf( - containsString("type EngineTypeEnum uint8"), - containsString("type EngineTypeValues struct {\n" + + assertEquals("// Generated SBE (Simple Binary Encoding) message codec\n" + + "\n" + + "package issue505\n" + + "\n" + + "import (\n" + + "\t\"fmt\"\n" + + "\t\"io\"\n" + + "\t\"reflect\"\n" + + ")\n" + + "\n" + + "type EngineTypeEnum uint8\n" + + "type EngineTypeValues struct {\n" + "\tGas EngineTypeEnum\n" + - "\tNullValue EngineTypeEnum\n}"))); + "\tOIl EngineTypeEnum\n" + + "\tWinD EngineTypeEnum\n" + + "\tSOLAR EngineTypeEnum\n" + + "\tNullValue EngineTypeEnum\n" + + "}\n" + + "\n" + + "var EngineType = EngineTypeValues{0, 1, 2, 3, 255}\n" + + "\n" + + "func (e EngineTypeEnum) Encode(_m *SbeGoMarshaller, _w io.Writer) error {\n" + + "\tif err := _m.WriteUint8(_w, uint8(e)); err != nil {\n" + + "\t\treturn err\n" + + "\t}\n" + + "\treturn nil\n" + + "}\n" + + "\n" + + "func (e *EngineTypeEnum) Decode(_m *SbeGoMarshaller, _r io.Reader, actingVersion uint16) error {\n" + + "\tif err := _m.ReadUint8(_r, (*uint8)(e)); err != nil {\n" + + "\t\treturn err\n" + + "\t}\n" + + "\treturn nil\n" + + "}\n" + + "\n" + + "func (e EngineTypeEnum) RangeCheck(actingVersion uint16, schemaVersion uint16) error {\n" + + "\tif actingVersion > schemaVersion {\n" + + "\t\treturn nil\n" + + "\t}\n" + + "\tvalue := reflect.ValueOf(EngineType)\n" + + "\tfor idx := 0; idx < value.NumField(); idx++ {\n" + + "\t\tif e == value.Field(idx).Interface() {\n" + + "\t\t\treturn nil\n" + + "\t\t}\n" + + "\t}\n" + + "\treturn fmt.Errorf(\"Range check failed on EngineType, unknown enumeration value %d\", e)\n" + + "}\n" + + "\n" + + "func (*EngineTypeEnum) EncodedLength() int64 {\n" + + "\treturn 1\n" + + "}\n" + + "\n" + + "func (*EngineTypeEnum) GasSinceVersion() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (e *EngineTypeEnum) GasInActingVersion(actingVersion uint16) bool {\n" + + "\treturn actingVersion >= e.GasSinceVersion()\n" + + "}\n" + + "\n" + + "func (*EngineTypeEnum) GasDeprecated() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (*EngineTypeEnum) OIlSinceVersion() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (e *EngineTypeEnum) OIlInActingVersion(actingVersion uint16) bool {\n" + + "\treturn actingVersion >= e.OIlSinceVersion()\n" + + "}\n" + + "\n" + + "func (*EngineTypeEnum) OIlDeprecated() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (*EngineTypeEnum) WinDSinceVersion() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (e *EngineTypeEnum) WinDInActingVersion(actingVersion uint16) bool {\n" + + "\treturn actingVersion >= e.WinDSinceVersion()\n" + + "}\n" + + "\n" + + "func (*EngineTypeEnum) WinDDeprecated() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (*EngineTypeEnum) SOLARSinceVersion() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (e *EngineTypeEnum) SOLARInActingVersion(actingVersion uint16) bool {\n" + + "\treturn actingVersion >= e.SOLARSinceVersion()\n" + + "}\n" + + "\n" + + "func (*EngineTypeEnum) SOLARDeprecated() uint16 {\n" + + "\treturn 0\n" + + "}\n", engineTypeSource); + final String messageSource = outputManager.getSource("issue505.SomeMessage").toString(); - assertThat(messageSource, containsString("type SomeMessage struct {\n\tEngineType EngineTypeEnum\n}")); + assertEquals("// Generated SBE (Simple Binary Encoding) message codec\n" + + "\n" + + "package issue505\n" + + "\n" + + "import (\n" + + "\t\"io\"\n" + + "\t\"io/ioutil\"\n" + + ")\n" + + "\n" + + "type SomeMessage struct {\n" + + "\tEngineType EngineTypeEnum\n" + + "}\n" + + "\n" + + "func (s *SomeMessage) Encode(_m *SbeGoMarshaller, _w io.Writer, doRangeCheck bool) error {\n" + + "\tif doRangeCheck {\n" + + "\t\tif err := s.RangeCheck(s.SbeSchemaVersion(), s.SbeSchemaVersion()); err != nil {\n" + + "\t\t\treturn err\n" + + "\t\t}\n" + + "\t}\n" + + "\treturn nil\n" + + "}\n" + + "\n" + + "func (s *SomeMessage) Decode(_m *SbeGoMarshaller, _r io.Reader, actingVersion uint16, " + + "blockLength uint16, doRangeCheck bool) error {\n" + + "\ts.EngineType = EngineType.Gas\n" + + "\tif actingVersion > s.SbeSchemaVersion() && blockLength > s.SbeBlockLength() {\n" + + "\t\tio.CopyN(ioutil.Discard, _r, int64(blockLength-s.SbeBlockLength()))\n" + + "\t}\n" + + "\tif doRangeCheck {\n" + + "\t\tif err := s.RangeCheck(actingVersion, s.SbeSchemaVersion()); err != nil {\n" + + "\t\t\treturn err\n" + + "\t\t}\n" + + "\t}\n" + + "\treturn nil\n" + + "}\n" + + "\n" + + "func (s *SomeMessage) RangeCheck(actingVersion uint16, schemaVersion uint16) error {\n" + + "\tif err := s.EngineType.RangeCheck(actingVersion, schemaVersion); err != nil {\n" + + "\t\treturn err\n" + + "\t}\n" + + "\treturn nil\n" + + "}\n" + + "\n" + + "func SomeMessageInit(s *SomeMessage) {\n" + + "\ts.EngineType = EngineType.Gas\n" + + "\treturn\n" + + "}\n" + + "\n" + + "func (*SomeMessage) SbeBlockLength() (blockLength uint16) {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (*SomeMessage) SbeTemplateId() (templateId uint16) {\n" + + "\treturn 1\n" + + "}\n" + + "\n" + + "func (*SomeMessage) SbeSchemaId() (schemaId uint16) {\n" + + "\treturn 505\n" + + "}\n" + + "\n" + + "func (*SomeMessage) SbeSchemaVersion() (schemaVersion uint16) {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (*SomeMessage) SbeSemanticType() (semanticType []byte) {\n" + + "\treturn []byte(\"\")\n" + + "}\n" + + "\n" + + "func (*SomeMessage) SbeSemanticVersion() (semanticVersion string) {\n" + + "\treturn \"1.0\"\n" + + "}\n" + + "\n" + + "func (*SomeMessage) EngineTypeId() uint16 {\n" + + "\treturn 1\n" + + "}\n" + + "\n" + + "func (*SomeMessage) EngineTypeSinceVersion() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (s *SomeMessage) EngineTypeInActingVersion(actingVersion uint16) bool {\n" + + "\treturn actingVersion >= s.EngineTypeSinceVersion()\n" + + "}\n" + + "\n" + + "func (*SomeMessage) EngineTypeDeprecated() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (*SomeMessage) EngineTypeMetaAttribute(meta int) string {\n" + + "\tswitch meta {\n" + + "\tcase 1:\n" + + "\t\treturn \"\"\n" + + "\tcase 2:\n" + + "\t\treturn \"\"\n" + + "\tcase 3:\n" + + "\t\treturn \"\"\n" + + "\tcase 4:\n" + + "\t\treturn \"constant\"\n" + + "\t}\n" + + "\treturn \"\"\n" + + "}\n", messageSource); } } @@ -74,6 +271,7 @@ void shouldUseUpperCaseTypeNamesWhenReferencingBitSet() throws Exception generator.generate(); final String eventTypeSource = outputManager.getSource("test.EventType").toString(); + System.out.println(eventTypeSource); assertThat(eventTypeSource, containsString("type EventType [8]bool\n" + "type EventTypeChoiceValue uint8\n" + @@ -84,8 +282,40 @@ void shouldUseUpperCaseTypeNamesWhenReferencingBitSet() throws Exception "\tD EventTypeChoiceValue\n" + "\tEeeee EventTypeChoiceValue\n}\n\n" + "var EventTypeChoice = EventTypeChoiceValues{0, 1, 2, 3, 4}")); + final String messageSource = outputManager.getSource("test.SomeMessage").toString(); - assertThat(messageSource, containsString("type SomeMessage struct {\n\tMyEvent EventType\n}")); + assertThat(messageSource, + allOf( + containsString("type SomeMessage struct {\n\tMyEvent EventType\n}"), + containsString("func (s *SomeMessage) Encode(_m *SbeGoMarshaller, _w io.Writer," + + " doRangeCheck bool) error {\n" + + "\tif doRangeCheck {\n" + + "\t\tif err := s.RangeCheck(s.SbeSchemaVersion(), s.SbeSchemaVersion()); err != nil {\n" + + "\t\t\treturn err\n" + + "\t\t}\n" + + "\t}\n" + + "\tif err := s.MyEvent.Encode(_m, _w); err != nil {\n" + + "\t\treturn err\n" + + "\t}\n" + + "\treturn nil\n" + + "}\n"), + containsString("func (s *SomeMessage) Decode(_m *SbeGoMarshaller, _r io.Reader," + + " actingVersion uint16, blockLength uint16, doRangeCheck bool) error {\n" + + "\tif s.MyEventInActingVersion(actingVersion) {\n" + + "\t\tif err := s.MyEvent.Decode(_m, _r, actingVersion); err != nil {\n" + + "\t\t\treturn err\n" + + "\t\t}\n" + + "\t}\n" + + "\tif actingVersion > s.SbeSchemaVersion() && blockLength > s.SbeBlockLength() {\n" + + "\t\tio.CopyN(ioutil.Discard, _r, int64(blockLength-s.SbeBlockLength()))\n" + + "\t}\n" + + "\tif doRangeCheck {\n" + + "\t\tif err := s.RangeCheck(actingVersion, s.SbeSchemaVersion()); err != nil {\n" + + "\t\t\treturn err\n" + + "\t\t}\n" + + "\t}\n" + + "\treturn nil\n" + + "}\n"))); } } } diff --git a/sbe-tool/src/test/resources/value-ref-with-lower-case-enum.xml b/sbe-tool/src/test/resources/value-ref-with-lower-case-enum.xml index c33b4133c8..421a94e11a 100644 --- a/sbe-tool/src/test/resources/value-ref-with-lower-case-enum.xml +++ b/sbe-tool/src/test/resources/value-ref-with-lower-case-enum.xml @@ -15,6 +15,9 @@ 0 + 1 + 2 + 3
      From b5bb3c16c49f3826860b4240ae79f02bc1d77b08 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 29 Mar 2024 15:49:00 +0100 Subject: [PATCH 1105/1594] [Go] Use upper case names when generating methods for bitset. --- .../generation/golang/GolangGenerator.java | 2 +- .../golang/GolangGeneratorTest.java | 200 ++++++++++++++++-- .../message-with-lower-case-bitset.xml | 2 +- 3 files changed, 185 insertions(+), 19 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index f87e32c710..ef9c04cc3b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -1475,7 +1475,7 @@ private void generateChoiceSet(final List tokens) throws IOException for (final Token token : tokens.subList(1, tokens.size() - 1)) { - generateSinceActingDeprecated(sb, choiceName, token.name(), token); + generateSinceActingDeprecated(sb, choiceName, formatPropertyName(token.name()), token); } out.append(generateFileHeader(ir.namespaces())); out.append(sb); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java index 9e24f804b6..14ce4087c8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java @@ -25,9 +25,6 @@ import java.io.InputStream; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.containsString; import static org.junit.jupiter.api.Assertions.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -256,6 +253,7 @@ void shouldUseUpperCaseTypeNamesWhenReferencingEnumValues() throws Exception } @Test + @SuppressWarnings("MethodLength") void shouldUseUpperCaseTypeNamesWhenReferencingBitSet() throws Exception { try (InputStream in = Tests.getLocalResource("message-with-lower-case-bitset.xml")) @@ -271,24 +269,129 @@ void shouldUseUpperCaseTypeNamesWhenReferencingBitSet() throws Exception generator.generate(); final String eventTypeSource = outputManager.getSource("test.EventType").toString(); - System.out.println(eventTypeSource); - assertThat(eventTypeSource, - containsString("type EventType [8]bool\n" + + assertEquals("// Generated SBE (Simple Binary Encoding) message codec\n" + + "\n" + + "package test\n" + + "\n" + + "import (\n" + + "\t\"io\"\n" + + ")\n" + + "\n" + + "type EventType [8]bool\n" + "type EventTypeChoiceValue uint8\n" + "type EventTypeChoiceValues struct {\n" + "\tA EventTypeChoiceValue\n" + "\tBb EventTypeChoiceValue\n" + "\tCcc EventTypeChoiceValue\n" + "\tD EventTypeChoiceValue\n" + - "\tEeeee EventTypeChoiceValue\n}\n\n" + - "var EventTypeChoice = EventTypeChoiceValues{0, 1, 2, 3, 4}")); + "\tEeEee EventTypeChoiceValue\n" + + "}\n" + + "\n" + + "var EventTypeChoice = EventTypeChoiceValues{0, 1, 2, 3, 4}\n" + + "\n" + + "func (e *EventType) Encode(_m *SbeGoMarshaller, _w io.Writer) error {\n" + + "\tvar wireval uint8 = 0\n" + + "\tfor k, v := range e {\n" + + "\t\tif v {\n" + + "\t\t\twireval |= (1 << uint(k))\n" + + "\t\t}\n" + + "\t}\n" + + "\treturn _m.WriteUint8(_w, wireval)\n" + + "}\n" + + "\n" + + "func (e *EventType) Decode(_m *SbeGoMarshaller, _r io.Reader, actingVersion uint16) error {\n" + + "\tvar wireval uint8\n" + + "\n" + + "\tif err := _m.ReadUint8(_r, &wireval); err != nil {\n" + + "\t\treturn err\n" + + "\t}\n" + + "\n" + + "\tvar idx uint\n" + + "\tfor idx = 0; idx < 8; idx++ {\n" + + "\t\te[idx] = (wireval & (1 << idx)) > 0\n" + + "\t}\n" + + "\treturn nil\n" + + "}\n" + + "\n" + + "func (EventType) EncodedLength() int64 {\n" + + "\treturn 1\n" + + "}\n" + + "\n" + + "func (*EventType) ASinceVersion() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (e *EventType) AInActingVersion(actingVersion uint16) bool {\n" + + "\treturn actingVersion >= e.ASinceVersion()\n" + + "}\n" + + "\n" + + "func (*EventType) ADeprecated() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (*EventType) BbSinceVersion() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (e *EventType) BbInActingVersion(actingVersion uint16) bool {\n" + + "\treturn actingVersion >= e.BbSinceVersion()\n" + + "}\n" + + "\n" + + "func (*EventType) BbDeprecated() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (*EventType) CccSinceVersion() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (e *EventType) CccInActingVersion(actingVersion uint16) bool {\n" + + "\treturn actingVersion >= e.CccSinceVersion()\n" + + "}\n" + + "\n" + + "func (*EventType) CccDeprecated() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (*EventType) DSinceVersion() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (e *EventType) DInActingVersion(actingVersion uint16) bool {\n" + + "\treturn actingVersion >= e.DSinceVersion()\n" + + "}\n" + + "\n" + + "func (*EventType) DDeprecated() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (*EventType) EeEeeSinceVersion() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (e *EventType) EeEeeInActingVersion(actingVersion uint16) bool {\n" + + "\treturn actingVersion >= e.EeEeeSinceVersion()\n" + + "}\n" + + "\n" + + "func (*EventType) EeEeeDeprecated() uint16 {\n" + + "\treturn 0\n" + + "}\n", eventTypeSource); final String messageSource = outputManager.getSource("test.SomeMessage").toString(); - assertThat(messageSource, - allOf( - containsString("type SomeMessage struct {\n\tMyEvent EventType\n}"), - containsString("func (s *SomeMessage) Encode(_m *SbeGoMarshaller, _w io.Writer," + - " doRangeCheck bool) error {\n" + + assertEquals("// Generated SBE (Simple Binary Encoding) message codec\n" + + "\n" + + "package test\n" + + "\n" + + "import (\n" + + "\t\"io\"\n" + + "\t\"io/ioutil\"\n" + + ")\n" + + "\n" + + "type SomeMessage struct {\n" + + "\tMyEvent EventType\n" + + "}\n" + + "\n" + + "func (s *SomeMessage) Encode(_m *SbeGoMarshaller, _w io.Writer, doRangeCheck bool) error {\n" + "\tif doRangeCheck {\n" + "\t\tif err := s.RangeCheck(s.SbeSchemaVersion(), s.SbeSchemaVersion()); err != nil {\n" + "\t\t\treturn err\n" + @@ -298,9 +401,10 @@ void shouldUseUpperCaseTypeNamesWhenReferencingBitSet() throws Exception "\t\treturn err\n" + "\t}\n" + "\treturn nil\n" + - "}\n"), - containsString("func (s *SomeMessage) Decode(_m *SbeGoMarshaller, _r io.Reader," + - " actingVersion uint16, blockLength uint16, doRangeCheck bool) error {\n" + + "}\n" + + "\n" + + "func (s *SomeMessage) Decode(_m *SbeGoMarshaller, _r io.Reader, actingVersion uint16, " + + "blockLength uint16, doRangeCheck bool) error {\n" + "\tif s.MyEventInActingVersion(actingVersion) {\n" + "\t\tif err := s.MyEvent.Decode(_m, _r, actingVersion); err != nil {\n" + "\t\t\treturn err\n" + @@ -315,7 +419,69 @@ void shouldUseUpperCaseTypeNamesWhenReferencingBitSet() throws Exception "\t\t}\n" + "\t}\n" + "\treturn nil\n" + - "}\n"))); + "}\n" + + "\n" + + "func (s *SomeMessage) RangeCheck(actingVersion uint16, schemaVersion uint16) error {\n" + + "\treturn nil\n" + + "}\n" + + "\n" + + "func SomeMessageInit(s *SomeMessage) {\n" + + "\treturn\n" + + "}\n" + + "\n" + + "func (*SomeMessage) SbeBlockLength() (blockLength uint16) {\n" + + "\treturn 1\n" + + "}\n" + + "\n" + + "func (*SomeMessage) SbeTemplateId() (templateId uint16) {\n" + + "\treturn 1\n" + + "}\n" + + "\n" + + "func (*SomeMessage) SbeSchemaId() (schemaId uint16) {\n" + + "\treturn 973\n" + + "}\n" + + "\n" + + "func (*SomeMessage) SbeSchemaVersion() (schemaVersion uint16) {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (*SomeMessage) SbeSemanticType() (semanticType []byte) {\n" + + "\treturn []byte(\"\")\n" + + "}\n" + + "\n" + + "func (*SomeMessage) SbeSemanticVersion() (semanticVersion string) {\n" + + "\treturn \"1.0\"\n" + + "}\n" + + "\n" + + "func (*SomeMessage) MyEventId() uint16 {\n" + + "\treturn 1\n" + + "}\n" + + "\n" + + "func (*SomeMessage) MyEventSinceVersion() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (s *SomeMessage) MyEventInActingVersion(actingVersion uint16) bool {\n" + + "\treturn actingVersion >= s.MyEventSinceVersion()\n" + + "}\n" + + "\n" + + "func (*SomeMessage) MyEventDeprecated() uint16 {\n" + + "\treturn 0\n" + + "}\n" + + "\n" + + "func (*SomeMessage) MyEventMetaAttribute(meta int) string {\n" + + "\tswitch meta {\n" + + "\tcase 1:\n" + + "\t\treturn \"\"\n" + + "\tcase 2:\n" + + "\t\treturn \"\"\n" + + "\tcase 3:\n" + + "\t\treturn \"\"\n" + + "\tcase 4:\n" + + "\t\treturn \"required\"\n" + + "\t}\n" + + "\treturn \"\"\n" + + "}\n", messageSource); } } } diff --git a/sbe-tool/src/test/resources/message-with-lower-case-bitset.xml b/sbe-tool/src/test/resources/message-with-lower-case-bitset.xml index b9bd91c5d4..ba08af1fc7 100644 --- a/sbe-tool/src/test/resources/message-with-lower-case-bitset.xml +++ b/sbe-tool/src/test/resources/message-with-lower-case-bitset.xml @@ -18,7 +18,7 @@ 1 2 3 - 4 + 4
      From 660c96b7835125ff913f00e6b14d0225f719e25a Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 29 Mar 2024 16:25:57 +0100 Subject: [PATCH 1106/1594] [Go] Add tests with lower-case enums and bitsets. --- build.gradle | 2 + gocode/Makefile | 2 +- gocode/src/issue505/Issue505_test.go | 29 ++ gocode/src/test973/EventType.go | 107 +++++++ gocode/src/test973/MessageHeader.go | 192 ++++++++++++ gocode/src/test973/SbeMarshalling.go | 283 ++++++++++++++++++ gocode/src/test973/SomeMessage.go | 103 +++++++ gocode/src/test973/test973_test.go | 38 +++ .../golang/GolangGeneratorTest.java | 8 +- .../message-with-lower-case-bitset.xml | 2 +- 10 files changed, 760 insertions(+), 6 deletions(-) create mode 100644 gocode/src/issue505/Issue505_test.go create mode 100644 gocode/src/test973/EventType.go create mode 100644 gocode/src/test973/MessageHeader.go create mode 100644 gocode/src/test973/SbeMarshalling.go create mode 100644 gocode/src/test973/SomeMessage.go create mode 100644 gocode/src/test973/test973_test.go diff --git a/build.gradle b/build.gradle index 0f74a5e005..587bddc0a0 100644 --- a/build.gradle +++ b/build.gradle @@ -700,6 +700,8 @@ tasks.register('generateGolangCodecsWithXSD', JavaExec) { 'sbe-tool/src/test/resources/issue849.xml', 'sbe-tool/src/test/resources/since-deprecated-test-schema.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', + 'sbe-tool/src/test/resources/value-ref-with-lower-case-enum.xml', + 'sbe-tool/src/test/resources/message-with-lower-case-bitset.xml', 'gocode/resources/example-composite.xml', 'gocode/resources/group-with-data-extension-schema.xml', 'gocode/resources/simple.xml'] diff --git a/gocode/Makefile b/gocode/Makefile index 456cced904..eebb2b4f38 100644 --- a/gocode/Makefile +++ b/gocode/Makefile @@ -72,7 +72,7 @@ test: $(DEP) go install \ ;done)) (export GOPATH=$(GOPATH) && \ - (for t in baseline-bigendian mktdata group_with_data group_with_data_extension composite_elements composite since-deprecated simple issue435 issue472 issue483 issue488 issue560 issue847 issue848 issue849; do \ + (for t in baseline-bigendian mktdata group_with_data group_with_data_extension composite_elements composite since-deprecated simple issue435 issue472 issue483 issue488 issue560 issue847 issue848 issue849 issue505 test973; do \ cd $(GOPATH)/src/$$t && \ go build && \ go fmt && \ diff --git a/gocode/src/issue505/Issue505_test.go b/gocode/src/issue505/Issue505_test.go new file mode 100644 index 0000000000..5e939a4f0d --- /dev/null +++ b/gocode/src/issue505/Issue505_test.go @@ -0,0 +1,29 @@ +package issue505 + +import ( + "bytes" + "testing" +) + +func TestConstant(t *testing.T) { + message := new(SomeMessage) + SomeMessageInit(message) + + if message.EngineType != EngineType.Gas { + t.Log("message.EngineType != EngineType.Gas:\n", message.EngineType, EngineType.Gas) + t.Fail() + } + + m := NewSbeGoMarshaller() + var buf = new(bytes.Buffer) + var out = *new(SomeMessage) + if err := out.Decode(m, buf, message.SbeSchemaVersion(), message.SbeBlockLength(), true); err != nil { + t.Log("Decoding Error", err) + t.Fail() + } + + if out.EngineType != EngineType.Gas { + t.Log("out.EngineType != EngineType.Gas:\n", out.EngineType, EngineType.Gas) + t.Fail() + } +} diff --git a/gocode/src/test973/EventType.go b/gocode/src/test973/EventType.go new file mode 100644 index 0000000000..fe08752472 --- /dev/null +++ b/gocode/src/test973/EventType.go @@ -0,0 +1,107 @@ +// Generated SBE (Simple Binary Encoding) message codec + +package test973 + +import ( + "io" +) + +type EventType [8]bool +type EventTypeChoiceValue uint8 +type EventTypeChoiceValues struct { + A EventTypeChoiceValue + Bb EventTypeChoiceValue + Ccc EventTypeChoiceValue + D EventTypeChoiceValue + EeEee EventTypeChoiceValue +} + +var EventTypeChoice = EventTypeChoiceValues{0, 1, 2, 3, 4} + +func (e *EventType) Encode(_m *SbeGoMarshaller, _w io.Writer) error { + var wireval uint8 = 0 + for k, v := range e { + if v { + wireval |= (1 << uint(k)) + } + } + return _m.WriteUint8(_w, wireval) +} + +func (e *EventType) Decode(_m *SbeGoMarshaller, _r io.Reader, actingVersion uint16) error { + var wireval uint8 + + if err := _m.ReadUint8(_r, &wireval); err != nil { + return err + } + + var idx uint + for idx = 0; idx < 8; idx++ { + e[idx] = (wireval & (1 << idx)) > 0 + } + return nil +} + +func (EventType) EncodedLength() int64 { + return 1 +} + +func (*EventType) ASinceVersion() uint16 { + return 0 +} + +func (e *EventType) AInActingVersion(actingVersion uint16) bool { + return actingVersion >= e.ASinceVersion() +} + +func (*EventType) ADeprecated() uint16 { + return 0 +} + +func (*EventType) BbSinceVersion() uint16 { + return 0 +} + +func (e *EventType) BbInActingVersion(actingVersion uint16) bool { + return actingVersion >= e.BbSinceVersion() +} + +func (*EventType) BbDeprecated() uint16 { + return 0 +} + +func (*EventType) CccSinceVersion() uint16 { + return 0 +} + +func (e *EventType) CccInActingVersion(actingVersion uint16) bool { + return actingVersion >= e.CccSinceVersion() +} + +func (*EventType) CccDeprecated() uint16 { + return 0 +} + +func (*EventType) DSinceVersion() uint16 { + return 0 +} + +func (e *EventType) DInActingVersion(actingVersion uint16) bool { + return actingVersion >= e.DSinceVersion() +} + +func (*EventType) DDeprecated() uint16 { + return 0 +} + +func (*EventType) EeEeeSinceVersion() uint16 { + return 0 +} + +func (e *EventType) EeEeeInActingVersion(actingVersion uint16) bool { + return actingVersion >= e.EeEeeSinceVersion() +} + +func (*EventType) EeEeeDeprecated() uint16 { + return 0 +} diff --git a/gocode/src/test973/MessageHeader.go b/gocode/src/test973/MessageHeader.go new file mode 100644 index 0000000000..a7ed9008b5 --- /dev/null +++ b/gocode/src/test973/MessageHeader.go @@ -0,0 +1,192 @@ +// Generated SBE (Simple Binary Encoding) message codec + +package test973 + +import ( + "fmt" + "io" + "math" +) + +type MessageHeader struct { + BlockLength uint16 + TemplateId uint16 + SchemaId uint16 + Version uint16 +} + +func (m *MessageHeader) Encode(_m *SbeGoMarshaller, _w io.Writer) error { + if err := _m.WriteUint16(_w, m.BlockLength); err != nil { + return err + } + if err := _m.WriteUint16(_w, m.TemplateId); err != nil { + return err + } + if err := _m.WriteUint16(_w, m.SchemaId); err != nil { + return err + } + if err := _m.WriteUint16(_w, m.Version); err != nil { + return err + } + return nil +} + +func (m *MessageHeader) Decode(_m *SbeGoMarshaller, _r io.Reader, actingVersion uint16) error { + if !m.BlockLengthInActingVersion(actingVersion) { + m.BlockLength = m.BlockLengthNullValue() + } else { + if err := _m.ReadUint16(_r, &m.BlockLength); err != nil { + return err + } + } + if !m.TemplateIdInActingVersion(actingVersion) { + m.TemplateId = m.TemplateIdNullValue() + } else { + if err := _m.ReadUint16(_r, &m.TemplateId); err != nil { + return err + } + } + if !m.SchemaIdInActingVersion(actingVersion) { + m.SchemaId = m.SchemaIdNullValue() + } else { + if err := _m.ReadUint16(_r, &m.SchemaId); err != nil { + return err + } + } + if !m.VersionInActingVersion(actingVersion) { + m.Version = m.VersionNullValue() + } else { + if err := _m.ReadUint16(_r, &m.Version); err != nil { + return err + } + } + return nil +} + +func (m *MessageHeader) RangeCheck(actingVersion uint16, schemaVersion uint16) error { + if m.BlockLengthInActingVersion(actingVersion) { + if m.BlockLength < m.BlockLengthMinValue() || m.BlockLength > m.BlockLengthMaxValue() { + return fmt.Errorf("Range check failed on m.BlockLength (%v < %v > %v)", m.BlockLengthMinValue(), m.BlockLength, m.BlockLengthMaxValue()) + } + } + if m.TemplateIdInActingVersion(actingVersion) { + if m.TemplateId < m.TemplateIdMinValue() || m.TemplateId > m.TemplateIdMaxValue() { + return fmt.Errorf("Range check failed on m.TemplateId (%v < %v > %v)", m.TemplateIdMinValue(), m.TemplateId, m.TemplateIdMaxValue()) + } + } + if m.SchemaIdInActingVersion(actingVersion) { + if m.SchemaId < m.SchemaIdMinValue() || m.SchemaId > m.SchemaIdMaxValue() { + return fmt.Errorf("Range check failed on m.SchemaId (%v < %v > %v)", m.SchemaIdMinValue(), m.SchemaId, m.SchemaIdMaxValue()) + } + } + if m.VersionInActingVersion(actingVersion) { + if m.Version < m.VersionMinValue() || m.Version > m.VersionMaxValue() { + return fmt.Errorf("Range check failed on m.Version (%v < %v > %v)", m.VersionMinValue(), m.Version, m.VersionMaxValue()) + } + } + return nil +} + +func MessageHeaderInit(m *MessageHeader) { + return +} + +func (*MessageHeader) EncodedLength() int64 { + return 8 +} + +func (*MessageHeader) BlockLengthMinValue() uint16 { + return 0 +} + +func (*MessageHeader) BlockLengthMaxValue() uint16 { + return math.MaxUint16 - 1 +} + +func (*MessageHeader) BlockLengthNullValue() uint16 { + return math.MaxUint16 +} + +func (*MessageHeader) BlockLengthSinceVersion() uint16 { + return 0 +} + +func (m *MessageHeader) BlockLengthInActingVersion(actingVersion uint16) bool { + return actingVersion >= m.BlockLengthSinceVersion() +} + +func (*MessageHeader) BlockLengthDeprecated() uint16 { + return 0 +} + +func (*MessageHeader) TemplateIdMinValue() uint16 { + return 0 +} + +func (*MessageHeader) TemplateIdMaxValue() uint16 { + return math.MaxUint16 - 1 +} + +func (*MessageHeader) TemplateIdNullValue() uint16 { + return math.MaxUint16 +} + +func (*MessageHeader) TemplateIdSinceVersion() uint16 { + return 0 +} + +func (m *MessageHeader) TemplateIdInActingVersion(actingVersion uint16) bool { + return actingVersion >= m.TemplateIdSinceVersion() +} + +func (*MessageHeader) TemplateIdDeprecated() uint16 { + return 0 +} + +func (*MessageHeader) SchemaIdMinValue() uint16 { + return 0 +} + +func (*MessageHeader) SchemaIdMaxValue() uint16 { + return math.MaxUint16 - 1 +} + +func (*MessageHeader) SchemaIdNullValue() uint16 { + return math.MaxUint16 +} + +func (*MessageHeader) SchemaIdSinceVersion() uint16 { + return 0 +} + +func (m *MessageHeader) SchemaIdInActingVersion(actingVersion uint16) bool { + return actingVersion >= m.SchemaIdSinceVersion() +} + +func (*MessageHeader) SchemaIdDeprecated() uint16 { + return 0 +} + +func (*MessageHeader) VersionMinValue() uint16 { + return 0 +} + +func (*MessageHeader) VersionMaxValue() uint16 { + return math.MaxUint16 - 1 +} + +func (*MessageHeader) VersionNullValue() uint16 { + return math.MaxUint16 +} + +func (*MessageHeader) VersionSinceVersion() uint16 { + return 0 +} + +func (m *MessageHeader) VersionInActingVersion(actingVersion uint16) bool { + return actingVersion >= m.VersionSinceVersion() +} + +func (*MessageHeader) VersionDeprecated() uint16 { + return 0 +} diff --git a/gocode/src/test973/SbeMarshalling.go b/gocode/src/test973/SbeMarshalling.go new file mode 100644 index 0000000000..76cd098c51 --- /dev/null +++ b/gocode/src/test973/SbeMarshalling.go @@ -0,0 +1,283 @@ +// Copyright (C) 2017 MarketFactory, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This file provides a simple bespoke marshalling layer for the +// standard binary encoding golang backend and is part of: +// +// https://github.com/real-logic/simple-binary-encoding + +package test973 + +import ( + "io" + "math" +) + +// Allocate via NewSbeGoMarshaller to initialize +type SbeGoMarshaller struct { + b8 []byte // statically allocated tmp space to avoid alloc + b1 []byte // previously created slice into b to save time + b2 []byte // previously created slice into b to save time + b4 []byte // previously created slice into b to save time +} + +func NewSbeGoMarshaller() *SbeGoMarshaller { + var m SbeGoMarshaller + m.b8 = make([]byte, 8) + m.b1 = m.b8[:1] + m.b2 = m.b8[:2] + m.b4 = m.b8[:4] + return &m +} + +// The "standard" MessageHeader. +// +// Most applications will use this as it's the default and optimized +// although it's possible to change it by: +// a) using a different sized BlockLength, or +// b) adding arbitrary fields +// +// If the MessageHeader is not "standard" then you can use the +// generated MessageHeader type in MessageHeader.go otherwise we +// recommend this one. +type SbeGoMessageHeader struct { + BlockLength uint16 + TemplateId uint16 + SchemaId uint16 + Version uint16 +} + +func (m SbeGoMessageHeader) Encode(_m *SbeGoMarshaller, _w io.Writer) error { + _m.b8[0] = byte(m.BlockLength) + _m.b8[1] = byte(m.BlockLength >> 8) + _m.b8[2] = byte(m.TemplateId) + _m.b8[3] = byte(m.TemplateId >> 8) + _m.b8[4] = byte(m.SchemaId) + _m.b8[5] = byte(m.SchemaId >> 8) + _m.b8[6] = byte(m.Version) + _m.b8[7] = byte(m.Version >> 8) + if _, err := _w.Write(_m.b8); err != nil { + return err + } + return nil +} + +func (m *SbeGoMessageHeader) Decode(_m *SbeGoMarshaller, _r io.Reader) error { + if _, err := io.ReadFull(_r, _m.b8); err != nil { + return err + } + m.BlockLength = uint16(_m.b8[0]) | uint16(_m.b8[1])<<8 + m.TemplateId = uint16(_m.b8[2]) | uint16(_m.b8[3])<<8 + m.SchemaId = uint16(_m.b8[4]) | uint16(_m.b8[5])<<8 + m.Version = uint16(_m.b8[6]) | uint16(_m.b8[7])<<8 + return nil +} + +func (m *SbeGoMarshaller) WriteUint8(w io.Writer, v uint8) error { + m.b1[0] = byte(v) + _, err := w.Write(m.b1) + return err +} + +func (m *SbeGoMarshaller) WriteUint16(w io.Writer, v uint16) error { + m.b2[0] = byte(v) + m.b2[1] = byte(v >> 8) + _, err := w.Write(m.b2) + return err +} + +func (m *SbeGoMarshaller) WriteUint32(w io.Writer, v uint32) error { + m.b4[0] = byte(v) + m.b4[1] = byte(v >> 8) + m.b4[2] = byte(v >> 16) + m.b4[3] = byte(v >> 24) + _, err := w.Write(m.b4) + return err +} + +func (m *SbeGoMarshaller) WriteUint64(w io.Writer, v uint64) error { + m.b8[0] = byte(v) + m.b8[1] = byte(v >> 8) + m.b8[2] = byte(v >> 16) + m.b8[3] = byte(v >> 24) + m.b8[4] = byte(v >> 32) + m.b8[5] = byte(v >> 40) + m.b8[6] = byte(v >> 48) + m.b8[7] = byte(v >> 56) + _, err := w.Write(m.b8) + return err +} + +func (m *SbeGoMarshaller) WriteInt8(w io.Writer, v int8) error { + m.b1[0] = byte(v) + _, err := w.Write(m.b1) + return err +} + +func (m *SbeGoMarshaller) WriteInt16(w io.Writer, v int16) error { + m.b2[0] = byte(v) + m.b2[1] = byte(v >> 8) + _, err := w.Write(m.b2) + return err +} + +func (m *SbeGoMarshaller) WriteInt32(w io.Writer, v int32) error { + m.b4[0] = byte(v) + m.b4[1] = byte(v >> 8) + m.b4[2] = byte(v >> 16) + m.b4[3] = byte(v >> 24) + _, err := w.Write(m.b4) + return err +} + +func (m *SbeGoMarshaller) WriteInt64(w io.Writer, v int64) error { + m.b8[0] = byte(v) + m.b8[1] = byte(v >> 8) + m.b8[2] = byte(v >> 16) + m.b8[3] = byte(v >> 24) + m.b8[4] = byte(v >> 32) + m.b8[5] = byte(v >> 40) + m.b8[6] = byte(v >> 48) + m.b8[7] = byte(v >> 56) + _, err := w.Write(m.b8) + return err +} + +func (m *SbeGoMarshaller) WriteFloat32(w io.Writer, v float32) error { + u32 := math.Float32bits(v) + m.b4[0] = byte(u32) + m.b4[1] = byte(u32 >> 8) + m.b4[2] = byte(u32 >> 16) + m.b4[3] = byte(u32 >> 24) + _, err := w.Write(m.b4) + return err +} + +func (m *SbeGoMarshaller) WriteFloat64(w io.Writer, v float64) error { + u64 := math.Float64bits(v) + m.b8[0] = byte(u64) + m.b8[1] = byte(u64 >> 8) + m.b8[2] = byte(u64 >> 16) + m.b8[3] = byte(u64 >> 24) + m.b8[4] = byte(u64 >> 32) + m.b8[5] = byte(u64 >> 40) + m.b8[6] = byte(u64 >> 48) + m.b8[7] = byte(u64 >> 56) + _, err := w.Write(m.b8) + return err +} + +func (m *SbeGoMarshaller) WriteBytes(w io.Writer, v []byte) error { + _, err := w.Write(v) + return err +} + +func (m *SbeGoMarshaller) ReadUint8(r io.Reader, v *uint8) error { + if _, err := io.ReadFull(r, m.b1); err != nil { + return err + } + *v = uint8(m.b1[0]) + return nil +} + +func (m *SbeGoMarshaller) ReadUint16(r io.Reader, v *uint16) error { + if _, err := io.ReadFull(r, m.b2); err != nil { + return err + } + *v = (uint16(m.b2[0]) | uint16(m.b2[1])<<8) + return nil +} + +func (m *SbeGoMarshaller) ReadUint32(r io.Reader, v *uint32) error { + if _, err := io.ReadFull(r, m.b4); err != nil { + return err + } + *v = (uint32(m.b4[0]) | uint32(m.b4[1])<<8 | + uint32(m.b4[2])<<16 | uint32(m.b4[3])<<24) + return nil +} + +func (m *SbeGoMarshaller) ReadUint64(r io.Reader, v *uint64) error { + if _, err := io.ReadFull(r, m.b8); err != nil { + return err + } + *v = (uint64(m.b8[0]) | uint64(m.b8[1])<<8 | + uint64(m.b8[2])<<16 | uint64(m.b8[3])<<24 | + uint64(m.b8[4])<<32 | uint64(m.b8[5])<<40 | + uint64(m.b8[6])<<48 | uint64(m.b8[7])<<56) + return nil +} + +func (m *SbeGoMarshaller) ReadInt8(r io.Reader, v *int8) error { + if _, err := io.ReadFull(r, m.b1); err != nil { + return err + } + *v = int8(m.b1[0]) + return nil +} + +func (m *SbeGoMarshaller) ReadInt16(r io.Reader, v *int16) error { + if _, err := io.ReadFull(r, m.b2); err != nil { + return err + } + *v = (int16(m.b2[0]) | int16(m.b2[1])<<8) + return nil +} + +func (m *SbeGoMarshaller) ReadInt32(r io.Reader, v *int32) error { + if _, err := io.ReadFull(r, m.b4); err != nil { + return err + } + *v = (int32(m.b4[0]) | int32(m.b4[1])<<8 | + int32(m.b4[2])<<16 | int32(m.b4[3])<<24) + return nil +} + +func (m *SbeGoMarshaller) ReadInt64(r io.Reader, v *int64) error { + if _, err := io.ReadFull(r, m.b8); err != nil { + return err + } + *v = (int64(m.b8[0]) | int64(m.b8[1])<<8 | + int64(m.b8[2])<<16 | int64(m.b8[3])<<24 | + int64(m.b8[4])<<32 | int64(m.b8[5])<<40 | + int64(m.b8[6])<<48 | int64(m.b8[7])<<56) + return nil +} + +func (m *SbeGoMarshaller) ReadFloat32(r io.Reader, v *float32) error { + if _, err := io.ReadFull(r, m.b4); err != nil { + return err + } + *v = math.Float32frombits(uint32(m.b4[0]) | uint32(m.b4[1])<<8 | + uint32(m.b4[2])<<16 | uint32(m.b4[3])<<24) + return nil +} + +func (m *SbeGoMarshaller) ReadFloat64(r io.Reader, v *float64) error { + if _, err := io.ReadFull(r, m.b8); err != nil { + return err + } + *v = math.Float64frombits(uint64(m.b8[0]) | uint64(m.b8[1])<<8 | + uint64(m.b8[2])<<16 | uint64(m.b8[3])<<24 | + uint64(m.b8[4])<<32 | uint64(m.b8[5])<<40 | + uint64(m.b8[6])<<48 | uint64(m.b8[7])<<56) + return nil +} + +func (m *SbeGoMarshaller) ReadBytes(r io.Reader, b []byte) error { + if _, err := io.ReadFull(r, b); err != nil { + return err + } + return nil +} diff --git a/gocode/src/test973/SomeMessage.go b/gocode/src/test973/SomeMessage.go new file mode 100644 index 0000000000..460c5e89d1 --- /dev/null +++ b/gocode/src/test973/SomeMessage.go @@ -0,0 +1,103 @@ +// Generated SBE (Simple Binary Encoding) message codec + +package test973 + +import ( + "io" + "io/ioutil" +) + +type SomeMessage struct { + MyEvent EventType +} + +func (s *SomeMessage) Encode(_m *SbeGoMarshaller, _w io.Writer, doRangeCheck bool) error { + if doRangeCheck { + if err := s.RangeCheck(s.SbeSchemaVersion(), s.SbeSchemaVersion()); err != nil { + return err + } + } + if err := s.MyEvent.Encode(_m, _w); err != nil { + return err + } + return nil +} + +func (s *SomeMessage) Decode(_m *SbeGoMarshaller, _r io.Reader, actingVersion uint16, blockLength uint16, doRangeCheck bool) error { + if s.MyEventInActingVersion(actingVersion) { + if err := s.MyEvent.Decode(_m, _r, actingVersion); err != nil { + return err + } + } + if actingVersion > s.SbeSchemaVersion() && blockLength > s.SbeBlockLength() { + io.CopyN(ioutil.Discard, _r, int64(blockLength-s.SbeBlockLength())) + } + if doRangeCheck { + if err := s.RangeCheck(actingVersion, s.SbeSchemaVersion()); err != nil { + return err + } + } + return nil +} + +func (s *SomeMessage) RangeCheck(actingVersion uint16, schemaVersion uint16) error { + return nil +} + +func SomeMessageInit(s *SomeMessage) { + return +} + +func (*SomeMessage) SbeBlockLength() (blockLength uint16) { + return 1 +} + +func (*SomeMessage) SbeTemplateId() (templateId uint16) { + return 1 +} + +func (*SomeMessage) SbeSchemaId() (schemaId uint16) { + return 973 +} + +func (*SomeMessage) SbeSchemaVersion() (schemaVersion uint16) { + return 0 +} + +func (*SomeMessage) SbeSemanticType() (semanticType []byte) { + return []byte("") +} + +func (*SomeMessage) SbeSemanticVersion() (semanticVersion string) { + return "1.0" +} + +func (*SomeMessage) MyEventId() uint16 { + return 1 +} + +func (*SomeMessage) MyEventSinceVersion() uint16 { + return 0 +} + +func (s *SomeMessage) MyEventInActingVersion(actingVersion uint16) bool { + return actingVersion >= s.MyEventSinceVersion() +} + +func (*SomeMessage) MyEventDeprecated() uint16 { + return 0 +} + +func (*SomeMessage) MyEventMetaAttribute(meta int) string { + switch meta { + case 1: + return "" + case 2: + return "" + case 3: + return "" + case 4: + return "required" + } + return "" +} diff --git a/gocode/src/test973/test973_test.go b/gocode/src/test973/test973_test.go new file mode 100644 index 0000000000..418550b473 --- /dev/null +++ b/gocode/src/test973/test973_test.go @@ -0,0 +1,38 @@ +package test973 + +import ( + "bytes" + "testing" +) + +func TestEncodeDecode(t *testing.T) { + message := new(SomeMessage) + SomeMessageInit(message) + + m := NewSbeGoMarshaller() + var buf = new(bytes.Buffer) + + message.MyEvent[EventTypeChoice.A] = true + message.MyEvent[EventTypeChoice.Ccc] = true + + if err := message.Encode(m, buf, true); err != nil { + t.Log("Encoding Error", err) + t.Fail() + } + + var out = *new(SomeMessage) + if err := out.Decode(m, buf, message.SbeSchemaVersion(), message.SbeBlockLength(), true); err != nil { + t.Log("Decoding Error", err) + t.Fail() + } + + if out.MyEvent != message.MyEvent { + t.Log("Value mismatch: ", out.MyEvent, message.MyEvent) + t.Fail() + } + + if !out.MyEvent[EventTypeChoice.A] || !out.MyEvent[EventTypeChoice.Ccc] || out.MyEvent[EventTypeChoice.EeEee] { + t.Log("Sanity check failed: ", out.MyEvent) + t.Fail() + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java index 14ce4087c8..af647727f2 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java @@ -268,10 +268,10 @@ void shouldUseUpperCaseTypeNamesWhenReferencingBitSet() throws Exception final GolangGenerator generator = new GolangGenerator(ir, outputManager); generator.generate(); - final String eventTypeSource = outputManager.getSource("test.EventType").toString(); + final String eventTypeSource = outputManager.getSource("test973.EventType").toString(); assertEquals("// Generated SBE (Simple Binary Encoding) message codec\n" + "\n" + - "package test\n" + + "package test973\n" + "\n" + "import (\n" + "\t\"io\"\n" + @@ -377,10 +377,10 @@ void shouldUseUpperCaseTypeNamesWhenReferencingBitSet() throws Exception "\treturn 0\n" + "}\n", eventTypeSource); - final String messageSource = outputManager.getSource("test.SomeMessage").toString(); + final String messageSource = outputManager.getSource("test973.SomeMessage").toString(); assertEquals("// Generated SBE (Simple Binary Encoding) message codec\n" + "\n" + - "package test\n" + + "package test973\n" + "\n" + "import (\n" + "\t\"io\"\n" + diff --git a/sbe-tool/src/test/resources/message-with-lower-case-bitset.xml b/sbe-tool/src/test/resources/message-with-lower-case-bitset.xml index ba08af1fc7..a160ddbceb 100644 --- a/sbe-tool/src/test/resources/message-with-lower-case-bitset.xml +++ b/sbe-tool/src/test/resources/message-with-lower-case-bitset.xml @@ -1,6 +1,6 @@ Date: Fri, 29 Mar 2024 16:38:26 +0100 Subject: [PATCH 1107/1594] [CI] Add Golang build. --- .github/workflows/ci.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ac853b7cb..e458580f91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -343,3 +343,32 @@ jobs: toolchain: ${{ matrix.rust }} override: true - run: ./gradlew runRustTests + + golang-build: + name: Golang ${{ matrix.version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + version: [ '1.22.x' ] + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.sha }} + - name: Cache Gradle dependencies + uses: actions/cache@v4 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v4 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + - name: Generate codecs + run: ./gradlew generateGolangCodecs + - name: Go + run: cd gocode && make From 2c8ff6be8501e8bd60963db1987ebec682cff356 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 29 Mar 2024 16:39:35 +0100 Subject: [PATCH 1108/1594] [CI] Add missing task. --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e458580f91..149150af21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -368,6 +368,10 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + - name: Setup Go + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.version }} - name: Generate codecs run: ./gradlew generateGolangCodecs - name: Go From 7dd2b76b6c4ac48fc94e36a9411137f235b52c96 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 29 Mar 2024 16:49:03 +0100 Subject: [PATCH 1109/1594] [Go] Add dependency on sbe-all. --- build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 587bddc0a0..6bc00c4418 100644 --- a/build.gradle +++ b/build.gradle @@ -714,7 +714,8 @@ tasks.register('generateGolangCodecs') { 'generateGolangCodecTestBasic', 'generateGolangCodecTestComposite', 'generateGolangCodecsWithXIncludes', - 'generateGolangCodecsWithXSD' + 'generateGolangCodecsWithXSD', + ':sbe-all:jar' } /* From e1b8520f448c0ec4fab0306815c05621eb629e0e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 29 Mar 2024 17:25:55 +0100 Subject: [PATCH 1110/1594] [Java] Upgrade to Agrona 1.21.1. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 6bc00c4418..d932fa2ece 100644 --- a/build.gradle +++ b/build.gradle @@ -58,8 +58,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.10.2' def jmhVersion = '1.37' -def agronaVersion = '1.21.0' -def agronaVersionRange = '[1.21.0,2.0[' // allow any release >= 1.20.0 and < 2.0.0 +def agronaVersion = '1.21.1' +def agronaVersionRange = '[1.21.1,2.0[' // allow any release >= 1.21.1 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From b49348c443a547703c5d2507519659a760792310 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 29 Mar 2024 18:06:21 +0100 Subject: [PATCH 1111/1594] [Java] Use `BYTE_ORDER` constant instead of accessing `java.nio.ByteOrder` directly. --- .../sbe/generation/java/JavaGenerator.java | 2 +- .../sbe/ir/generated/FrameCodecDecoder.java | 42 ++--- .../sbe/ir/generated/FrameCodecEncoder.java | 24 +-- .../ir/generated/MessageHeaderDecoder.java | 8 +- .../ir/generated/MessageHeaderEncoder.java | 8 +- .../sbe/ir/generated/TokenCodecDecoder.java | 144 +++++++++--------- .../sbe/ir/generated/TokenCodecEncoder.java | 78 +++++----- .../ir/generated/VarDataEncodingDecoder.java | 2 +- .../ir/generated/VarDataEncodingEncoder.java | 2 +- .../generation/java/JavaGeneratorTest.java | 55 +++++-- 10 files changed, 200 insertions(+), 165 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index f4889e3751..8009f7a073 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2949,7 +2949,7 @@ private static void generateArrayLengthMethod( private String byteOrderString(final Encoding encoding) { - return sizeOfPrimitive(encoding) == 1 ? "" : ", java.nio.ByteOrder." + encoding.byteOrder(); + return sizeOfPrimitive(encoding) == 1 ? "" : ", BYTE_ORDER"; } private CharSequence generatePrimitiveArrayPropertyEncode( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 81f28e8dc5..12bdde9ae0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -297,7 +297,7 @@ public int irId() onIrIdAccessed(); } - return buffer.getInt(offset + 0, java.nio.ByteOrder.LITTLE_ENDIAN); + return buffer.getInt(offset + 0, BYTE_ORDER); } @@ -364,7 +364,7 @@ public int irVersion() onIrVersionAccessed(); } - return buffer.getInt(offset + 4, java.nio.ByteOrder.LITTLE_ENDIAN); + return buffer.getInt(offset + 4, BYTE_ORDER); } @@ -431,7 +431,7 @@ public int schemaVersion() onSchemaVersionAccessed(); } - return buffer.getInt(offset + 8, java.nio.ByteOrder.LITTLE_ENDIAN); + return buffer.getInt(offset + 8, BYTE_ORDER); } @@ -503,7 +503,7 @@ public int packageNameLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipPackageName() @@ -515,7 +515,7 @@ public int skipPackageName() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -531,7 +531,7 @@ public int getPackageName(final MutableDirectBuffer dst, final int dstOffset, fi final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -548,7 +548,7 @@ public int getPackageName(final byte[] dst, final int dstOffset, final int lengt final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -565,7 +565,7 @@ public void wrapPackageName(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -579,7 +579,7 @@ public String packageName() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -661,7 +661,7 @@ public int namespaceNameLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipNamespaceName() @@ -673,7 +673,7 @@ public int skipNamespaceName() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -689,7 +689,7 @@ public int getNamespaceName(final MutableDirectBuffer dst, final int dstOffset, final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -706,7 +706,7 @@ public int getNamespaceName(final byte[] dst, final int dstOffset, final int len final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -723,7 +723,7 @@ public void wrapNamespaceName(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -737,7 +737,7 @@ public String namespaceName() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -819,7 +819,7 @@ public int semanticVersionLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipSemanticVersion() @@ -831,7 +831,7 @@ public int skipSemanticVersion() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -847,7 +847,7 @@ public int getSemanticVersion(final MutableDirectBuffer dst, final int dstOffset final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -864,7 +864,7 @@ public int getSemanticVersion(final byte[] dst, final int dstOffset, final int l final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -881,7 +881,7 @@ public void wrapSemanticVersion(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -895,7 +895,7 @@ public String semanticVersion() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java index aaf9df42c9..d7c0a14d12 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java @@ -243,7 +243,7 @@ public FrameCodecEncoder irId(final int value) onIrIdAccessed(); } - buffer.putInt(offset + 0, value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putInt(offset + 0, value, BYTE_ORDER); return this; } @@ -311,7 +311,7 @@ public FrameCodecEncoder irVersion(final int value) onIrVersionAccessed(); } - buffer.putInt(offset + 4, value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putInt(offset + 4, value, BYTE_ORDER); return this; } @@ -379,7 +379,7 @@ public FrameCodecEncoder schemaVersion(final int value) onSchemaVersionAccessed(); } - buffer.putInt(offset + 8, value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putInt(offset + 8, value, BYTE_ORDER); return this; } @@ -439,7 +439,7 @@ public FrameCodecEncoder putPackageName(final DirectBuffer src, final int srcOff final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -460,7 +460,7 @@ public FrameCodecEncoder putPackageName(final byte[] src, final int srcOffset, f final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -484,7 +484,7 @@ public FrameCodecEncoder packageName(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; @@ -545,7 +545,7 @@ public FrameCodecEncoder putNamespaceName(final DirectBuffer src, final int srcO final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -566,7 +566,7 @@ public FrameCodecEncoder putNamespaceName(final byte[] src, final int srcOffset, final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -590,7 +590,7 @@ public FrameCodecEncoder namespaceName(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; @@ -651,7 +651,7 @@ public FrameCodecEncoder putSemanticVersion(final DirectBuffer src, final int sr final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -672,7 +672,7 @@ public FrameCodecEncoder putSemanticVersion(final byte[] src, final int srcOffse final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -696,7 +696,7 @@ public FrameCodecEncoder semanticVersion(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java index 380c8a649e..f7b916999f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderDecoder.java @@ -87,7 +87,7 @@ public static int blockLengthMaxValue() public int blockLength() { - return (buffer.getShort(offset + 0, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(offset + 0, BYTE_ORDER) & 0xFFFF); } @@ -123,7 +123,7 @@ public static int templateIdMaxValue() public int templateId() { - return (buffer.getShort(offset + 2, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(offset + 2, BYTE_ORDER) & 0xFFFF); } @@ -159,7 +159,7 @@ public static int schemaIdMaxValue() public int schemaId() { - return (buffer.getShort(offset + 4, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(offset + 4, BYTE_ORDER) & 0xFFFF); } @@ -195,7 +195,7 @@ public static int versionMaxValue() public int version() { - return (buffer.getShort(offset + 6, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(offset + 6, BYTE_ORDER) & 0xFFFF); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java index b1255198e5..393b3a9add 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/MessageHeaderEncoder.java @@ -82,7 +82,7 @@ public static int blockLengthMaxValue() public MessageHeaderEncoder blockLength(final int value) { - buffer.putShort(offset + 0, (short)value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(offset + 0, (short)value, BYTE_ORDER); return this; } @@ -114,7 +114,7 @@ public static int templateIdMaxValue() public MessageHeaderEncoder templateId(final int value) { - buffer.putShort(offset + 2, (short)value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(offset + 2, (short)value, BYTE_ORDER); return this; } @@ -146,7 +146,7 @@ public static int schemaIdMaxValue() public MessageHeaderEncoder schemaId(final int value) { - buffer.putShort(offset + 4, (short)value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(offset + 4, (short)value, BYTE_ORDER); return this; } @@ -178,7 +178,7 @@ public static int versionMaxValue() public MessageHeaderEncoder version(final int value) { - buffer.putShort(offset + 6, (short)value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(offset + 6, (short)value, BYTE_ORDER); return this; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 57abf338a1..e6e0fba7b9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -344,7 +344,7 @@ public int tokenOffset() onTokenOffsetAccessed(); } - return buffer.getInt(offset + 0, java.nio.ByteOrder.LITTLE_ENDIAN); + return buffer.getInt(offset + 0, BYTE_ORDER); } @@ -411,7 +411,7 @@ public int tokenSize() onTokenSizeAccessed(); } - return buffer.getInt(offset + 4, java.nio.ByteOrder.LITTLE_ENDIAN); + return buffer.getInt(offset + 4, BYTE_ORDER); } @@ -478,7 +478,7 @@ public int fieldId() onFieldIdAccessed(); } - return buffer.getInt(offset + 8, java.nio.ByteOrder.LITTLE_ENDIAN); + return buffer.getInt(offset + 8, BYTE_ORDER); } @@ -545,7 +545,7 @@ public int tokenVersion() onTokenVersionAccessed(); } - return buffer.getInt(offset + 12, java.nio.ByteOrder.LITTLE_ENDIAN); + return buffer.getInt(offset + 12, BYTE_ORDER); } @@ -612,7 +612,7 @@ public int componentTokenCount() onComponentTokenCountAccessed(); } - return buffer.getInt(offset + 16, java.nio.ByteOrder.LITTLE_ENDIAN); + return buffer.getInt(offset + 16, BYTE_ORDER); } @@ -927,7 +927,7 @@ public int deprecated() onDeprecatedAccessed(); } - return buffer.getInt(offset + 24, java.nio.ByteOrder.LITTLE_ENDIAN); + return buffer.getInt(offset + 24, BYTE_ORDER); } @@ -999,7 +999,7 @@ public int nameLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipName() @@ -1011,7 +1011,7 @@ public int skipName() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1027,7 +1027,7 @@ public int getName(final MutableDirectBuffer dst, final int dstOffset, final int final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1044,7 +1044,7 @@ public int getName(final byte[] dst, final int dstOffset, final int length) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1061,7 +1061,7 @@ public void wrapName(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -1075,7 +1075,7 @@ public String name() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -1157,7 +1157,7 @@ public int constValueLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipConstValue() @@ -1169,7 +1169,7 @@ public int skipConstValue() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1185,7 +1185,7 @@ public int getConstValue(final MutableDirectBuffer dst, final int dstOffset, fin final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1202,7 +1202,7 @@ public int getConstValue(final byte[] dst, final int dstOffset, final int length final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1219,7 +1219,7 @@ public void wrapConstValue(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -1233,7 +1233,7 @@ public String constValue() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -1315,7 +1315,7 @@ public int minValueLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipMinValue() @@ -1327,7 +1327,7 @@ public int skipMinValue() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1343,7 +1343,7 @@ public int getMinValue(final MutableDirectBuffer dst, final int dstOffset, final final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1360,7 +1360,7 @@ public int getMinValue(final byte[] dst, final int dstOffset, final int length) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1377,7 +1377,7 @@ public void wrapMinValue(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -1391,7 +1391,7 @@ public String minValue() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -1473,7 +1473,7 @@ public int maxValueLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipMaxValue() @@ -1485,7 +1485,7 @@ public int skipMaxValue() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1501,7 +1501,7 @@ public int getMaxValue(final MutableDirectBuffer dst, final int dstOffset, final final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1518,7 +1518,7 @@ public int getMaxValue(final byte[] dst, final int dstOffset, final int length) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1535,7 +1535,7 @@ public void wrapMaxValue(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -1549,7 +1549,7 @@ public String maxValue() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -1631,7 +1631,7 @@ public int nullValueLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipNullValue() @@ -1643,7 +1643,7 @@ public int skipNullValue() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1659,7 +1659,7 @@ public int getNullValue(final MutableDirectBuffer dst, final int dstOffset, fina final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1676,7 +1676,7 @@ public int getNullValue(final byte[] dst, final int dstOffset, final int length) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1693,7 +1693,7 @@ public void wrapNullValue(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -1707,7 +1707,7 @@ public String nullValue() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -1789,7 +1789,7 @@ public int characterEncodingLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipCharacterEncoding() @@ -1801,7 +1801,7 @@ public int skipCharacterEncoding() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1817,7 +1817,7 @@ public int getCharacterEncoding(final MutableDirectBuffer dst, final int dstOffs final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1834,7 +1834,7 @@ public int getCharacterEncoding(final byte[] dst, final int dstOffset, final int final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1851,7 +1851,7 @@ public void wrapCharacterEncoding(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -1865,7 +1865,7 @@ public String characterEncoding() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -1947,7 +1947,7 @@ public int epochLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipEpoch() @@ -1959,7 +1959,7 @@ public int skipEpoch() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -1975,7 +1975,7 @@ public int getEpoch(final MutableDirectBuffer dst, final int dstOffset, final in final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -1992,7 +1992,7 @@ public int getEpoch(final byte[] dst, final int dstOffset, final int length) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -2009,7 +2009,7 @@ public void wrapEpoch(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -2023,7 +2023,7 @@ public String epoch() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -2105,7 +2105,7 @@ public int timeUnitLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipTimeUnit() @@ -2117,7 +2117,7 @@ public int skipTimeUnit() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -2133,7 +2133,7 @@ public int getTimeUnit(final MutableDirectBuffer dst, final int dstOffset, final final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -2150,7 +2150,7 @@ public int getTimeUnit(final byte[] dst, final int dstOffset, final int length) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -2167,7 +2167,7 @@ public void wrapTimeUnit(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -2181,7 +2181,7 @@ public String timeUnit() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -2263,7 +2263,7 @@ public int semanticTypeLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipSemanticType() @@ -2275,7 +2275,7 @@ public int skipSemanticType() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -2291,7 +2291,7 @@ public int getSemanticType(final MutableDirectBuffer dst, final int dstOffset, f final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -2308,7 +2308,7 @@ public int getSemanticType(final byte[] dst, final int dstOffset, final int leng final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -2325,7 +2325,7 @@ public void wrapSemanticType(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -2339,7 +2339,7 @@ public String semanticType() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -2421,7 +2421,7 @@ public int descriptionLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipDescription() @@ -2433,7 +2433,7 @@ public int skipDescription() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -2449,7 +2449,7 @@ public int getDescription(final MutableDirectBuffer dst, final int dstOffset, fi final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -2466,7 +2466,7 @@ public int getDescription(final byte[] dst, final int dstOffset, final int lengt final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -2483,7 +2483,7 @@ public void wrapDescription(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -2497,7 +2497,7 @@ public String description() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) @@ -2579,7 +2579,7 @@ public int referencedNameLength() } final int limit = parentMessage.limit(); - return (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); } public int skipReferencedName() @@ -2591,7 +2591,7 @@ public int skipReferencedName() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int dataOffset = limit + headerLength; parentMessage.limit(dataOffset + dataLength); @@ -2607,7 +2607,7 @@ public int getReferencedName(final MutableDirectBuffer dst, final int dstOffset, final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -2624,7 +2624,7 @@ public int getReferencedName(final byte[] dst, final int dstOffset, final int le final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); final int bytesCopied = Math.min(length, dataLength); parentMessage.limit(limit + headerLength + dataLength); buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); @@ -2641,7 +2641,7 @@ public void wrapReferencedName(final DirectBuffer wrapBuffer) final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); wrapBuffer.wrap(buffer, limit + headerLength, dataLength); } @@ -2655,7 +2655,7 @@ public String referencedName() final int headerLength = 2; final int limit = parentMessage.limit(); - final int dataLength = (buffer.getShort(limit, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); parentMessage.limit(limit + headerLength + dataLength); if (0 == dataLength) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index e81e14bc4a..9e201cbf52 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -290,7 +290,7 @@ public TokenCodecEncoder tokenOffset(final int value) onTokenOffsetAccessed(); } - buffer.putInt(offset + 0, value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putInt(offset + 0, value, BYTE_ORDER); return this; } @@ -358,7 +358,7 @@ public TokenCodecEncoder tokenSize(final int value) onTokenSizeAccessed(); } - buffer.putInt(offset + 4, value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putInt(offset + 4, value, BYTE_ORDER); return this; } @@ -426,7 +426,7 @@ public TokenCodecEncoder fieldId(final int value) onFieldIdAccessed(); } - buffer.putInt(offset + 8, value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putInt(offset + 8, value, BYTE_ORDER); return this; } @@ -494,7 +494,7 @@ public TokenCodecEncoder tokenVersion(final int value) onTokenVersionAccessed(); } - buffer.putInt(offset + 12, value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putInt(offset + 12, value, BYTE_ORDER); return this; } @@ -562,7 +562,7 @@ public TokenCodecEncoder componentTokenCount(final int value) onComponentTokenCountAccessed(); } - buffer.putInt(offset + 16, value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putInt(offset + 16, value, BYTE_ORDER); return this; } @@ -838,7 +838,7 @@ public TokenCodecEncoder deprecated(final int value) onDeprecatedAccessed(); } - buffer.putInt(offset + 24, value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putInt(offset + 24, value, BYTE_ORDER); return this; } @@ -898,7 +898,7 @@ public TokenCodecEncoder putName(final DirectBuffer src, final int srcOffset, fi final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -919,7 +919,7 @@ public TokenCodecEncoder putName(final byte[] src, final int srcOffset, final in final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -943,7 +943,7 @@ public TokenCodecEncoder name(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; @@ -1004,7 +1004,7 @@ public TokenCodecEncoder putConstValue(final DirectBuffer src, final int srcOffs final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1025,7 +1025,7 @@ public TokenCodecEncoder putConstValue(final byte[] src, final int srcOffset, fi final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1049,7 +1049,7 @@ public TokenCodecEncoder constValue(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; @@ -1110,7 +1110,7 @@ public TokenCodecEncoder putMinValue(final DirectBuffer src, final int srcOffset final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1131,7 +1131,7 @@ public TokenCodecEncoder putMinValue(final byte[] src, final int srcOffset, fina final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1155,7 +1155,7 @@ public TokenCodecEncoder minValue(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; @@ -1216,7 +1216,7 @@ public TokenCodecEncoder putMaxValue(final DirectBuffer src, final int srcOffset final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1237,7 +1237,7 @@ public TokenCodecEncoder putMaxValue(final byte[] src, final int srcOffset, fina final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1261,7 +1261,7 @@ public TokenCodecEncoder maxValue(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; @@ -1322,7 +1322,7 @@ public TokenCodecEncoder putNullValue(final DirectBuffer src, final int srcOffse final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1343,7 +1343,7 @@ public TokenCodecEncoder putNullValue(final byte[] src, final int srcOffset, fin final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1367,7 +1367,7 @@ public TokenCodecEncoder nullValue(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; @@ -1428,7 +1428,7 @@ public TokenCodecEncoder putCharacterEncoding(final DirectBuffer src, final int final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1449,7 +1449,7 @@ public TokenCodecEncoder putCharacterEncoding(final byte[] src, final int srcOff final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1473,7 +1473,7 @@ public TokenCodecEncoder characterEncoding(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; @@ -1534,7 +1534,7 @@ public TokenCodecEncoder putEpoch(final DirectBuffer src, final int srcOffset, f final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1555,7 +1555,7 @@ public TokenCodecEncoder putEpoch(final byte[] src, final int srcOffset, final i final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1579,7 +1579,7 @@ public TokenCodecEncoder epoch(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; @@ -1640,7 +1640,7 @@ public TokenCodecEncoder putTimeUnit(final DirectBuffer src, final int srcOffset final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1661,7 +1661,7 @@ public TokenCodecEncoder putTimeUnit(final byte[] src, final int srcOffset, fina final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1685,7 +1685,7 @@ public TokenCodecEncoder timeUnit(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; @@ -1746,7 +1746,7 @@ public TokenCodecEncoder putSemanticType(final DirectBuffer src, final int srcOf final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1767,7 +1767,7 @@ public TokenCodecEncoder putSemanticType(final byte[] src, final int srcOffset, final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1791,7 +1791,7 @@ public TokenCodecEncoder semanticType(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; @@ -1852,7 +1852,7 @@ public TokenCodecEncoder putDescription(final DirectBuffer src, final int srcOff final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1873,7 +1873,7 @@ public TokenCodecEncoder putDescription(final byte[] src, final int srcOffset, f final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1897,7 +1897,7 @@ public TokenCodecEncoder description(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; @@ -1958,7 +1958,7 @@ public TokenCodecEncoder putReferencedName(final DirectBuffer src, final int src final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -1979,7 +1979,7 @@ public TokenCodecEncoder putReferencedName(final byte[] src, final int srcOffset final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, src, srcOffset, length); return this; @@ -2003,7 +2003,7 @@ public TokenCodecEncoder referencedName(final String value) final int headerLength = 2; final int limit = parentMessage.limit(); parentMessage.limit(limit + headerLength + length); - buffer.putShort(limit, (short)length, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(limit, (short)length, BYTE_ORDER); buffer.putBytes(limit + headerLength, bytes, 0, length); return this; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java index fef5471086..530284ceff 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingDecoder.java @@ -87,7 +87,7 @@ public static int lengthMaxValue() public int length() { - return (buffer.getShort(offset + 0, java.nio.ByteOrder.LITTLE_ENDIAN) & 0xFFFF); + return (buffer.getShort(offset + 0, BYTE_ORDER) & 0xFFFF); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java index 69ecabf325..15461efd3a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/VarDataEncodingEncoder.java @@ -82,7 +82,7 @@ public static int lengthMaxValue() public VarDataEncodingEncoder length(final int value) { - buffer.putShort(offset + 0, (short)value, java.nio.ByteOrder.LITTLE_ENDIAN); + buffer.putShort(offset + 0, (short)value, BYTE_ORDER); return this; } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 3ceaf14e14..e93a7c1eba 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -15,12 +15,6 @@ */ package uk.co.real_logic.sbe.generation.java; -import uk.co.real_logic.sbe.Tests; -import uk.co.real_logic.sbe.generation.common.PrecedenceChecks; -import uk.co.real_logic.sbe.ir.Ir; -import uk.co.real_logic.sbe.xml.IrGenerator; -import uk.co.real_logic.sbe.xml.MessageSchema; -import uk.co.real_logic.sbe.xml.ParserOptions; import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; import org.agrona.concurrent.UnsafeBuffer; @@ -29,7 +23,14 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.generation.common.PrecedenceChecks; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; import java.io.IOException; import java.io.InputStream; @@ -40,11 +41,10 @@ import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.Matchers.*; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; import static uk.co.real_logic.sbe.generation.java.JavaGenerator.MESSAGE_HEADER_DECODER_TYPE; import static uk.co.real_logic.sbe.generation.java.ReflectionUtil.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -444,7 +444,7 @@ void shouldGenerateGetFixedLengthStringUsingAppendable() throws Exception } @ParameterizedTest - @ValueSource(strings = {"Red", "", "Red and Blue"}) + @ValueSource(strings = { "Red", "", "Red and Blue" }) void shouldGenerateGetVariableStringUsingAppendable(final String color) throws Exception { final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); @@ -601,6 +601,41 @@ void shouldCreateTypesInSamePackageIfSupportDisabled() throws Exception } } + @ParameterizedTest + @CsvSource( + { + "code-generation-schema.xml, java.nio.ByteOrder.LITTLE_ENDIAN", + "example-bigendian-test-schema.xml, java.nio.ByteOrder.BIG_ENDIAN" + }) + void shouldUseByteOrderConstantField(final String schemaFile, final String encodingType) throws Exception + { + try (InputStream in = Tests.getLocalResource(schemaFile)) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + ir = irg.generate(schema); + + outputManager.clear(); + outputManager.setPackageName(ir.applicableNamespace()); + + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, false, outputManager); + + generator.generate(); + + for (final CharSequence code : new CharSequence[]{ + outputManager.getSource(ir.applicableNamespace() + ".CarEncoder"), + outputManager.getSource(ir.applicableNamespace() + ".CarDecoder") }) + { + assertThat(code.toString(), allOf( + containsString("public static final java.nio.ByteOrder BYTE_ORDER = " + encodingType + ";"), + not(containsString(encodingType + ")")), + containsString(", BYTE_ORDER)"))); + } + } + } + private Class getModelClass(final Object encoder) throws ClassNotFoundException { final String className = "Model"; From 7401858ebb3e441ff425b27b573500f2e2beab48 Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Wed, 3 Apr 2024 09:52:42 -0500 Subject: [PATCH 1112/1594] 1.31.0 released --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index e576fe33d3..34aae156b1 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.31.0-SNAPSHOT +1.31.0 From 2fd4adbffb14a3d66cec7e8c61079eba9b990e1a Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Wed, 3 Apr 2024 09:56:52 -0500 Subject: [PATCH 1113/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 34aae156b1..7341032ba0 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.31.0 +1.32.0-SNAPSHOT From c5aab07e0483bd019a0751b8d637bd70bf5a19f5 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Fri, 5 Apr 2024 10:19:41 -0500 Subject: [PATCH 1114/1594] [Rust] Updated code generator to resolve Issue #984 (#985) * [Rust] updated code generator to prevent rust warning for "ambiguous glob re-exports" * [Rust] defined new trait 'ActingVersion' * fixed code formatting issues * [Rust] fixed benchmarks * [Rust] added test for issue 984 --------- Co-authored-by: Michael Ward --- build.gradle | 1 + rust/Cargo.toml | 1 + rust/benches/car_benchmark.rs | 16 +++-- rust/benches/md_benchmark.rs | 10 ++- rust/tests/issue_435_test.rs | 3 +- rust/tests/issue_984_test.rs | 47 +++++++++++++ .../sbe/generation/rust/LibRsDef.java | 18 +++-- .../sbe/generation/rust/MessageCoderDef.java | 4 +- .../sbe/generation/rust/RustGenerator.java | 67 +++++++++++++------ .../sbe/generation/rust/SubGroup.java | 14 +++- sbe-tool/src/test/resources/issue984.xml | 31 +++++++++ 11 files changed, 174 insertions(+), 38 deletions(-) create mode 100644 rust/tests/issue_984_test.rs create mode 100644 sbe-tool/src/test/resources/issue984.xml diff --git a/build.gradle b/build.gradle index d932fa2ece..be16408906 100644 --- a/build.gradle +++ b/build.gradle @@ -588,6 +588,7 @@ tasks.register('generateRustTestCodecs', JavaExec) { args = ['sbe-tool/src/test/resources/issue435.xml', 'sbe-tool/src/test/resources/issue895.xml', 'sbe-tool/src/test/resources/issue972.xml', + 'sbe-tool/src/test/resources/issue984.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', 'sbe-tool/src/test/resources/nested-composite-name.xml', ] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 6d47fc3746..4be04c957b 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -14,6 +14,7 @@ examples_uk_co_real_logic_sbe_benchmarks_fix = { path = "../generated/rust/uk_co issue_435 = { path = "../generated/rust/issue435" } issue_895 = { path = "../generated/rust/issue895" } issue_972 = { path = "../generated/rust/issue972" } +issue_984 = { path = "../generated/rust/issue984" } baseline_bigendian = { path = "../generated/rust/baseline-bigendian" } nested_composite_name = { path = "../generated/rust/nested-composite-name" } diff --git a/rust/benches/car_benchmark.rs b/rust/benches/car_benchmark.rs index 06b542452a..5f78fff1e4 100644 --- a/rust/benches/car_benchmark.rs +++ b/rust/benches/car_benchmark.rs @@ -1,6 +1,12 @@ -use car_codec::encoder::*; use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use examples_uk_co_real_logic_sbe_benchmarks::*; +use examples_uk_co_real_logic_sbe_benchmarks::{ + boolean_type::BooleanType, + car_codec::{decoder::*, encoder::*}, + message_header_codec::MessageHeaderDecoder, + model::Model, + optional_extras::OptionalExtras, + *, +}; const MANUFACTURER: &[u8] = b"MANUFACTURER"; const MODEL: &[u8] = b"MODEL"; @@ -36,8 +42,8 @@ fn encode(state: &mut State) -> SbeResult { car.model_year(2005); car.serial_number(12345); car.available(BooleanType::T); - car.vehicle_code([97, 98, 99, 100, 101, 102]); // abcdef - car.some_numbers([0, 1, 2, 3, 4]); + car.vehicle_code(&[97, 98, 99, 100, 101, 102]); // abcdef + car.some_numbers(&[0, 1, 2, 3, 4]); extras.set_sports_pack(true); extras.set_sun_roof(true); @@ -46,7 +52,7 @@ fn encode(state: &mut State) -> SbeResult { let mut engine = car.engine_encoder(); engine.capacity(4200); engine.num_cylinders(8); - engine.manufacturer_code([97, 98, 99]); // abc + engine.manufacturer_code(&[97, 98, 99]); // abc car = engine.parent()?; fuel_figures = car.fuel_figures_encoder(3, fuel_figures); diff --git a/rust/benches/md_benchmark.rs b/rust/benches/md_benchmark.rs index ab7f4bf367..025df09f4f 100644 --- a/rust/benches/md_benchmark.rs +++ b/rust/benches/md_benchmark.rs @@ -1,6 +1,12 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use examples_uk_co_real_logic_sbe_benchmarks_fix::*; -use market_data_incremental_refresh_trades_codec::encoder::*; +use examples_uk_co_real_logic_sbe_benchmarks_fix::{ + market_data_incremental_refresh_trades_codec::{encoder::*, *}, + match_event_indicator::*, + md_update_action::*, + message_header_codec::*, + side::*, + *, +}; struct State { buffer: Vec, diff --git a/rust/tests/issue_435_test.rs b/rust/tests/issue_435_test.rs index 8ac9ce8a50..8664be42cd 100644 --- a/rust/tests/issue_435_test.rs +++ b/rust/tests/issue_435_test.rs @@ -1,7 +1,6 @@ -use ::issue_435::*; use issue_435::{ enum_ref::EnumRef, issue_435_codec::*, message_header_codec::MessageHeaderDecoder, - set_ref::SetRef, + set_ref::SetRef, *, }; fn create_encoder(buffer: &mut Vec) -> Issue435Encoder { diff --git a/rust/tests/issue_984_test.rs b/rust/tests/issue_984_test.rs new file mode 100644 index 0000000000..7ca0dcfc76 --- /dev/null +++ b/rust/tests/issue_984_test.rs @@ -0,0 +1,47 @@ +use issue_984::{ + message_header_codec::MessageHeaderDecoder, + simple_message_codec::{encoder::MyGroupEncoder, *}, + *, +}; + +fn create_encoder(buffer: &mut Vec) -> SimpleMessageEncoder { + let simple_msg = SimpleMessageEncoder::default().wrap( + WriteBuf::new(buffer.as_mut_slice()), + message_header_codec::ENCODED_LENGTH, + ); + let mut header = simple_msg.header(0); + header.parent().unwrap() +} + +#[test] +fn round_trip() -> SbeResult<()> { + // encode... + let mut buffer = vec![0u8; 256]; + let mut simple_msg_encoder = create_encoder(&mut buffer); + simple_msg_encoder.id(1985); + + let mut my_grp_encoder = simple_msg_encoder.my_group_encoder(1, MyGroupEncoder::default()); + my_grp_encoder.advance()?; + my_grp_encoder.f1(&[1, 2, 3, 4]); + my_grp_encoder.f2(&[1, 2, 3, 4, 5]); + my_grp_encoder.f3(&[1, 2, 3, 4, 5, 6]); + + // decode... + let buf = ReadBuf::new(buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + assert_eq!(SBE_BLOCK_LENGTH, header.block_length()); + assert_eq!(SBE_SCHEMA_VERSION, header.version()); + assert_eq!(SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(SBE_SCHEMA_ID, header.schema_id()); + + let simple_msg_decoder = SimpleMessageDecoder::default().header(header); + assert_eq!(1985, simple_msg_decoder.id()); + let mut grp_decoder = simple_msg_decoder.my_group_decoder(); + assert_eq!(1, grp_decoder.count()); + grp_decoder.advance()?; + + assert_eq!([1, 2, 3, 4], grp_decoder.f1()); + assert_eq!([1, 2, 3, 4, 5], grp_decoder.f2()); + assert_eq!([1, 2, 3, 4, 5, 6], grp_decoder.f3()); + Ok(()) +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 3c5ae1542d..2ed6eb1fcb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -35,19 +35,23 @@ class LibRsDef { private final RustOutputManager outputManager; private final ByteOrder byteOrder; + private final String schemaVersionType; /** * Create a new 'lib.rs' for the library being generated * - * @param outputManager for generating the codecs to. - * @param byteOrder for the Encoding. + * @param outputManager for generating the codecs to. + * @param byteOrder for the Encoding. + * @param schemaVersionType for acting_version type */ LibRsDef( final RustOutputManager outputManager, - final ByteOrder byteOrder) + final ByteOrder byteOrder, + final String schemaVersionType) { this.outputManager = outputManager; this.byteOrder = byteOrder; + this.schemaVersionType = schemaVersionType; } void generate() throws IOException @@ -82,7 +86,7 @@ void generate() throws IOException generateEitherEnum(libRs); generateEncoderTraits(libRs); - generateDecoderTraits(libRs); + generateDecoderTraits(schemaVersionType, libRs); generateReadBuf(libRs, byteOrder); generateWriteBuf(libRs, byteOrder); @@ -101,8 +105,12 @@ static void generateEncoderTraits(final Writer writer) throws IOException indent(writer, 0, "}\n\n"); } - static void generateDecoderTraits(final Writer writer) throws IOException + static void generateDecoderTraits(final String schemaVersionType, final Writer writer) throws IOException { + indent(writer, 0, "pub trait ActingVersion {\n"); + indent(writer, 1, "fn acting_version(&self) -> %s;\n", schemaVersionType); + indent(writer, 0, "}\n\n"); + indent(writer, 0, "pub trait Reader<'a>: Sized {\n"); indent(writer, 1, "fn get_buf(&self) -> &ReadBuf<'a>;\n"); indent(writer, 0, "}\n\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index dbe6fabc8f..67c37f22fd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -76,7 +76,7 @@ void generate( } else { - RustGenerator.appendImplDecoderTrait(sb, msgTypeName); + RustGenerator.appendImplDecoderTrait(schemaVersionType(), sb, msgTypeName); } RustGenerator.appendImplWithLifetimeHeader(sb, msgTypeName); // impl start @@ -92,7 +92,7 @@ void generate( appendMessageHeaderDecoderFn(sb); RustGenerator.generateDecoderFields(sb, fields, 2); - RustGenerator.generateDecoderGroups(sb, groups, 2, this); + RustGenerator.generateDecoderGroups(schemaVersionType(), sb, groups, 2, this); RustGenerator.generateDecoderVarData(sb, varData, 2, false); } else diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 6569599993..1b53987098 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -127,11 +127,11 @@ public void generate() throws IOException } // lib.rs - final LibRsDef libRsDef = new LibRsDef(outputManager, ir.byteOrder()); + final LibRsDef libRsDef = new LibRsDef(outputManager, ir.byteOrder(), schemaVersionType()); generateEnums(ir, outputManager); generateBitSets(ir, outputManager); - generateComposites(ir, outputManager); + generateComposites(schemaVersionType(), ir, outputManager); for (final List tokens : ir.messages()) { @@ -428,6 +428,7 @@ private static void generatePrimitiveEncoder( indent(sb, level, "/// - semanticType: %s\n", encoding.semanticType()); indent(sb, level, "/// - encodedOffset: %d\n", typeToken.offset()); indent(sb, level, "/// - encodedLength: %d\n", typeToken.encodedLength()); + indent(sb, level, "/// - version: %d\n", typeToken.version()); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", formatFunctionName(name), @@ -575,7 +576,7 @@ private static void generateCompositeDecoder( decoderName, decoderTypeName); - indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version()); + indent(sb, level + 1, "if self.acting_version() < %d {\n", fieldToken.version()); indent(sb, level + 2, "return Either::Left(self);\n"); indent(sb, level + 1, "}\n\n"); @@ -613,7 +614,7 @@ private static void generateBitSetDecoder( if (bitsetToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", bitsetToken.version()); + indent(sb, level + 1, "if self.acting_version() < %d {\n", bitsetToken.version()); indent(sb, level + 2, "return %s::default();\n", structTypeName); indent(sb, level + 1, "}\n\n"); } @@ -673,7 +674,7 @@ private static void generatePrimitiveArrayDecoder( if (fieldToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version()); + indent(sb, level + 1, "if self.acting_version() < %d {\n", fieldToken.version()); indent(sb, level + 2, "return [%s; %d];\n", encoding.applicableNullValue(), arrayLength); indent(sb, level + 1, "}\n\n"); } @@ -827,7 +828,7 @@ private static void generatePrimitiveRequiredDecoder( if (fieldToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version()); + indent(sb, level + 1, "if self.acting_version() < %d {\n", fieldToken.version()); indent(sb, level + 2, "return %s;\n", generateRustLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString())); indent(sb, level + 1, "}\n\n"); @@ -876,7 +877,7 @@ private static void generateEnumDecoder( if (fieldToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); + indent(sb, level + 1, "if self.acting_version() < %d {\n", fieldToken.version()); indent(sb, level + 2, "return %s::default();\n", enumType); indent(sb, level + 1, "}\n\n"); } @@ -889,6 +890,7 @@ private static void generateEnumDecoder( } static void generateDecoderGroups( + final String schemaVersionType, final StringBuilder sb, final List tokens, final int level, @@ -936,7 +938,7 @@ static void generateDecoderGroups( indent(sb, level, "pub fn %s(self) -> Option<%2$s> {\n", formatFunctionName(groupName), groupName); - indent(sb, level + 1, "if self.acting_version < %d {\n", groupToken.version()); + indent(sb, level + 1, "if self.acting_version() < %d {\n", groupToken.version()); indent(sb, level + 2, "return None;\n"); indent(sb, level + 1, "}\n\n"); @@ -952,7 +954,7 @@ static void generateDecoderGroups( indent(sb, level, "}\n\n"); final SubGroup subGroup = parentDef.addSubGroup(groupName, level, groupToken); - subGroup.generateDecoder(tokens, fields, groups, varData, index); + subGroup.generateDecoder(schemaVersionType, tokens, fields, groups, varData, index); } } @@ -984,7 +986,7 @@ static void generateDecoderVarData( { if (varDataToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", + indent(sb, level + 1, "if self.acting_version() < %d {\n", varDataToken.version()); indent(sb, level + 2, "return (self.parent.as_ref().unwrap().get_limit(), 0);\n"); indent(sb, level + 1, "}\n\n"); @@ -1000,7 +1002,7 @@ static void generateDecoderVarData( { if (varDataToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", + indent(sb, level + 1, "if self.acting_version() < %d {\n", varDataToken.version()); indent(sb, level + 2, "return (self.get_limit(), 0);\n"); indent(sb, level + 1, "}\n\n"); @@ -1020,7 +1022,7 @@ static void generateDecoderVarData( if (varDataToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", + indent(sb, level + 1, "if self.acting_version() < %d {\n", varDataToken.version()); indent(sb, level + 2, "return &[] as &[u8];\n"); indent(sb, level + 1, "}\n\n"); @@ -1162,9 +1164,17 @@ static void appendImplEncoderTrait( } static void appendImplDecoderTrait( + final String schemaVersionType, final Appendable out, final String typeName) throws IOException { + indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, "ActingVersion", withLifetime(typeName)); + indent(out, 2, "#[inline]\n"); + indent(out, 2, "fn acting_version(&self) -> %s {\n", schemaVersionType); + indent(out, 3, "self.acting_version\n"); + indent(out, 2, "}\n"); + indent(out, 1, "}\n\n"); + indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withLifetime("Reader"), withLifetime(typeName)); indent(out, 2, "#[inline]\n"); indent(out, 2, "fn get_buf(&self) -> &ReadBuf<'a> {\n"); @@ -1271,6 +1281,7 @@ private static void generateEnum( } private static void generateComposites( + final String schemaVersionType, final Ir ir, final RustOutputManager outputManager) throws IOException { @@ -1278,12 +1289,13 @@ private static void generateComposites( { if (!tokens.isEmpty() && tokens.get(0).signal() == Signal.BEGIN_COMPOSITE) { - generateComposite(tokens, outputManager); + generateComposite(schemaVersionType, tokens, outputManager); } } } private static void generateComposite( + final String schemaVersionType, final List tokens, final RustOutputManager outputManager) throws IOException { @@ -1306,7 +1318,7 @@ private static void generateComposite( generateCompositeEncoder(tokens, encoderName(compositeName), out); indent(out, 0, "\n"); - generateCompositeDecoder(tokens, decoderName(compositeName), out); + generateCompositeDecoder(schemaVersionType, tokens, decoderName(compositeName), out); } } @@ -1350,12 +1362,23 @@ static void appendImplEncoderForComposite( } static void appendImplReaderForComposite( + final String schemaVersionType, + final int version, final Appendable out, final int level, final String name) throws IOException { + indent(out, level, "impl<'a, P> ActingVersion for %s

      where P: Reader<'a> + ActingVersion + Default {\n", + name); + indent(out, level + 1, "#[inline]\n"); + indent(out, level + 1, "fn acting_version(&self) -> %s {\n", schemaVersionType); + indent(out, level + 2, "self.parent.as_ref().unwrap().acting_version()\n"); + indent(out, level + 1, "}\n"); + indent(out, level, "}\n\n"); + // impl Reader... - indent(out, level, "impl<'a, P> Reader<'a> for %s

      where P: Reader<'a> + Default {\n", name); + indent(out, level, "impl<'a, P> Reader<'a> for %s

      where P: Reader<'a> %s+ Default {\n", + name, version > 0 ? "+ ActingVersion " : ""); indent(out, level + 1, "#[inline]\n"); indent(out, level + 1, "fn get_buf(&self) -> &ReadBuf<'a> {\n"); indent(out, level + 2, "self.parent.as_ref().expect(\"parent missing\").get_buf()\n"); @@ -1364,14 +1387,17 @@ static void appendImplReaderForComposite( } static void appendImplDecoderForComposite( + final String schemaVersionType, + final int version, final Appendable out, final int level, final String name) throws IOException { - appendImplReaderForComposite(out, level, name); + appendImplReaderForComposite(schemaVersionType, version, out, level, name); // impl Decoder... - indent(out, level, "impl<'a, P> Decoder<'a> for %s

      where P: Decoder<'a> + Default {\n", name); + indent(out, level, "impl<'a, P> Decoder<'a> for %s

      where P: Decoder<'a> + ActingVersion + Default {\n", + name); indent(out, level + 1, "#[inline]\n"); indent(out, level + 1, "fn get_limit(&self) -> usize {\n"); indent(out, level + 2, "self.parent.as_ref().expect(\"parent missing\").get_limit()\n"); @@ -1447,6 +1473,7 @@ private static void generateCompositeEncoder( } private static void generateCompositeDecoder( + final String schemaVersionType, final List tokens, final String decoderName, final Writer out) throws IOException @@ -1460,10 +1487,12 @@ private static void generateCompositeDecoder( indent(out, 2, "offset: usize,\n"); indent(out, 1, "}\n\n"); - appendImplReaderForComposite(out, 1, decoderName); + final int version = tokens.stream().findFirst().get().version(); + appendImplReaderForComposite(schemaVersionType, version, out, 1, decoderName); // impl<'a, P> start - indent(out, 1, "impl<'a, P> %s

      where P: Reader<'a> + Default {\n", decoderName); + indent(out, 1, "impl<'a, P> %s

      where P: Reader<'a> %s+ Default {\n", + decoderName, version > 0 ? "+ ActingVersion " : ""); indent(out, 2, "pub fn wrap(mut self, parent: P, offset: usize) -> Self {\n"); indent(out, 3, "self.parent = Some(parent);\n"); indent(out, 3, "self.offset = offset;\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index 6407220065..d7a6123ec9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -140,6 +140,7 @@ void generateEncoder( } void generateDecoder( + final String schemaVersionType, final List tokens, final List fields, final List groups, @@ -162,10 +163,11 @@ void generateDecoder( indent(sb, level, "offset: usize,\n"); indent(sb, level - 1, "}\n\n"); - RustGenerator.appendImplDecoderForComposite(sb, level - 1, name); + final int version = tokens.stream().findFirst().get().version(); + RustGenerator.appendImplDecoderForComposite(schemaVersionType, version, sb, level - 1, name); // define impl... - indent(sb, level - 1, "impl<'a, P> %s

      where P: Decoder<'a> + Default {\n", name); + indent(sb, level - 1, "impl<'a, P> %s

      where P: Decoder<'a> + ActingVersion + Default {\n", name); final int dimensionHeaderSize = tokens.get(index).encodedLength(); @@ -197,6 +199,12 @@ void generateDecoder( indent(sb, level + 1, "self.parent.take().ok_or(SbeErr::ParentNotSet)\n"); indent(sb, level, "}\n\n"); + // acting_version fn... + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn acting_version(&mut self) -> %s {\n", schemaVersionType); + indent(sb, level + 1, "self.parent.as_ref().unwrap().acting_version()\n"); + indent(sb, level, "}\n\n"); + // count function indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn count(&self) -> %s {\n", rustTypeName(numInGroupPrimitiveType)); @@ -221,7 +229,7 @@ void generateDecoder( indent(sb, level, "}\n\n"); RustGenerator.generateDecoderFields(sb, fields, level); - RustGenerator.generateDecoderGroups(sb, groups, level, this); + RustGenerator.generateDecoderGroups(schemaVersionType, sb, groups, level, this); RustGenerator.generateDecoderVarData(sb, varData, level, true); indent(sb, level - 1, "}\n\n"); // close impl diff --git a/sbe-tool/src/test/resources/issue984.xml b/sbe-tool/src/test/resources/issue984.xml new file mode 100644 index 0000000000..bfbc961ace --- /dev/null +++ b/sbe-tool/src/test/resources/issue984.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From c9be629310791b7af281e4091b39a37327ce4e25 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Sun, 7 Apr 2024 09:41:40 -0500 Subject: [PATCH 1115/1594] [Rust] updated SubGroup.generateDecoder() to resolve unnecessary cast warning in generated code (#986) * [Rust] updated code generator to prevent rust warning for "ambiguous glob re-exports" * [Rust] defined new trait 'ActingVersion' * fixed code formatting issues * [Rust] fixed benchmarks * [Rust] added test for issue 984 * [Rust] updated SubGroup.generateDecoder() to resolve unnecessary cast warning --------- Co-authored-by: Michael Ward --- .../java/uk/co/real_logic/sbe/generation/rust/SubGroup.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index d7a6123ec9..d0b5abc433 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -157,7 +157,7 @@ void generateDecoder( indent(sb, level - 1, "#[derive(Debug, Default)]\n"); indent(sb, level - 1, "pub struct %s

      {\n", name); indent(sb, level, "parent: Option

      ,\n"); - indent(sb, level, "block_length: usize,\n"); + indent(sb, level, "block_length: %s,\n", rustTypeName(blockLengthPrimitiveType)); indent(sb, level, "count: %s,\n", rustTypeName(numInGroupPrimitiveType)); indent(sb, level, "index: usize,\n"); indent(sb, level, "offset: usize,\n"); @@ -177,7 +177,7 @@ void generateDecoder( indent(sb, level + 1, "mut parent: P,\n"); indent(sb, level, ") -> Self {\n"); indent(sb, level + 1, "let initial_offset = parent.get_limit();\n"); - indent(sb, level + 1, "let block_length = parent.get_buf().get_%s_at(initial_offset) as usize;\n", + indent(sb, level + 1, "let block_length = parent.get_buf().get_%s_at(initial_offset);\n", rustTypeName(blockLengthPrimitiveType)); indent(sb, level + 1, "let count = parent.get_buf().get_%s_at(initial_offset + %d);\n", rustTypeName(numInGroupPrimitiveType), numInGroupToken.offset()); From 7e6e5039b15c728094c20772a5dd0dd7eceb91b2 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Thu, 11 Apr 2024 22:48:59 +0100 Subject: [PATCH 1116/1594] [Java, C#, C++] Fix precedence checks to account for non-contiguous versions. (#989) Relates to issue #988. An SBE message might not change in every version of a schema. For example, another message might change. Previously, the field precedence checking model would expect an exact match for `actingVersion` in `wrap` to enter one of its initial states. However, it is only aware of the versions in which a message schema has changed. Therefore, it was possible for `actingVersion` not to match any of these versions, in which case the initial state that represented a codec wrapped around the latest known version of the format was picked. Now, we do _not_ expect an exact match in `wrap`. Instead, we select the "best" match. For example, if a codec was changed in v1 and v3, and the acting version is v2, we will decode using v1. However, if the acting version is v4, we would decode as v3. --- .../sbe-tests/FieldAccessOrderCheckTests.cs | 19 +++ .../common/FieldPrecedenceModel.java | 10 +- .../sbe/generation/cpp/CppGenerator.java | 47 ++++--- .../generation/csharp/CSharpGenerator.java | 22 ++-- .../sbe/generation/java/JavaGenerator.java | 21 ++-- .../sbe/ir/generated/FrameCodecDecoder.java | 12 +- .../sbe/ir/generated/TokenCodecDecoder.java | 12 +- .../test/cpp/FieldAccessOrderCheckTest.cpp | 20 +++ .../sbe/FieldAccessOrderCheckTest.java | 115 +++++++++++++++++- .../resources/field-order-check-schema.xml | 42 ++++++- 10 files changed, 257 insertions(+), 63 deletions(-) diff --git a/csharp/sbe-tests/FieldAccessOrderCheckTests.cs b/csharp/sbe-tests/FieldAccessOrderCheckTests.cs index d0b7e16992..1ee4569643 100644 --- a/csharp/sbe-tests/FieldAccessOrderCheckTests.cs +++ b/csharp/sbe-tests/FieldAccessOrderCheckTests.cs @@ -3159,6 +3159,25 @@ public void DisallowsIncompleteMessagesDueToMissingVarDataInNestedGroup( var exception = Assert.ThrowsException(encoder.CheckEncodingIsComplete); StringAssert.Contains(exception.Message, $"Not fully encoded, current state: {expectedState}"); } + + [TestMethod] + public void AllowsSkippingFutureGroupWhenDecodingFromVersionWithNoChangesInMessage() + { + var encoder = new AddGroupBeforeVarDataV0() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + + _messageHeader.TemplateId = SkipVersionAddGroupBeforeVarDataV2.TemplateId; + _messageHeader.Version = 1; + + encoder.A = 42; + encoder.SetB("abc"); + + var decoder = new SkipVersionAddGroupBeforeVarDataV2() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + + Assert.AreEqual(42, decoder.A); + Assert.AreEqual(decoder.GetB(), "abc"); + } private void ModifyHeaderToLookLikeVersion0() { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java index 3122926ba5..58a68c17ff 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java @@ -46,7 +46,7 @@ public final class FieldPrecedenceModel new CodecInteraction.CodecInteractionFactory(groupPathsByField, topLevelBlockFields); private final Map> transitionsByInteraction = new LinkedHashMap<>(); private final Map> transitionsByState = new HashMap<>(); - private final Int2ObjectHashMap versionWrappedStates = new Int2ObjectHashMap<>(); + private final TreeMap versionWrappedStates = new TreeMap<>(); private final State notWrappedState = allocateState("NOT_WRAPPED"); private final String generatedRepresentationClassName; private State encoderWrappedState; @@ -103,13 +103,11 @@ public State latestVersionWrappedState() * Iterates over the states after a codec is wrapped over a particular version of data. * @param consumer the consumer of the states. */ - public void forEachWrappedStateByVersion(final IntObjConsumer consumer) + public void forEachWrappedStateByVersionDesc(final IntObjConsumer consumer) { - final Int2ObjectHashMap.EntryIterator iterator = versionWrappedStates.entrySet().iterator(); - while (iterator.hasNext()) + for (final Map.Entry entry : versionWrappedStates.descendingMap().entrySet()) { - iterator.next(); - consumer.accept(iterator.getIntKey(), iterator.getValue()); + consumer.accept(entry.getKey(), entry.getValue()); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 54a1683371..5b5e6f0721 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -3055,22 +3055,37 @@ private static CharSequence generateDecoderWrapListener(final FieldPrecedenceMod final StringBuilder sb = new StringBuilder(); sb.append(INDENT).append("void onWrapForDecode(std::uint64_t actingVersion)\n") - .append(INDENT).append("{\n") - .append(INDENT).append(INDENT).append("switch(actingVersion)\n") - .append(INDENT).append(INDENT).append("{\n"); - - fieldPrecedenceModel.forEachWrappedStateByVersion((version, state) -> - sb.append(INDENT).append(TWO_INDENT).append("case ").append(version).append(":\n") - .append(INDENT).append(THREE_INDENT).append("codecState(") - .append(qualifiedStateCase(state)).append(");\n") - .append(INDENT).append(THREE_INDENT).append("break;\n")); - - sb.append(INDENT).append(TWO_INDENT).append("default:\n") - .append(INDENT).append(THREE_INDENT).append("codecState(") - .append(qualifiedStateCase(fieldPrecedenceModel.latestVersionWrappedState())).append(");\n") - .append(INDENT).append(THREE_INDENT).append("break;\n") - .append(INDENT).append(INDENT).append("}\n") - .append(INDENT).append("}\n\n"); + .append(INDENT).append("{\n"); + + final MutableBoolean actingVersionCanBeTooLowToBeValid = new MutableBoolean(true); + + fieldPrecedenceModel.forEachWrappedStateByVersionDesc((version, state) -> + { + if (version == 0) + { + actingVersionCanBeTooLowToBeValid.set(false); + + sb.append(INDENT).append(" codecState(") + .append(qualifiedStateCase(state)).append(");\n"); + } + else + { + sb.append(INDENT).append(" if (actingVersion >= ").append(version).append(")\n") + .append(INDENT).append(" {\n") + .append(INDENT).append(" codecState(") + .append(qualifiedStateCase(state)).append(");\n") + .append(INDENT).append(" return;\n") + .append(INDENT).append(" }\n\n"); + } + }); + + if (actingVersionCanBeTooLowToBeValid.get()) + { + sb.append(INDENT) + .append(" throw std::runtime_error(\"Unsupported acting version: \" + actingVersion);\n"); + } + + sb.append(INDENT).append("}\n\n"); return sb; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index f141c7876f..8d15021814 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1912,22 +1912,20 @@ private static CharSequence generateDecoderWrapListener( } final StringBuilder sb = new StringBuilder(); + sb.append(indent).append("private void OnWrapForDecode(int actingVersion)\n") - .append(indent).append("{\n") - .append(indent).append(INDENT).append("switch(actingVersion)\n") - .append(indent).append(INDENT).append("{\n"); + .append(indent).append("{\n"); - fieldPrecedenceModel.forEachWrappedStateByVersion((version, state) -> - sb.append(indent).append(TWO_INDENT).append("case ").append(version).append(":\n") - .append(indent).append(THREE_INDENT).append("codecState(") + fieldPrecedenceModel.forEachWrappedStateByVersionDesc((version, state) -> + sb.append(indent).append(" if (actingVersion >= ").append(version).append(")\n") + .append(indent).append(" {\n") + .append(indent).append(" codecState(") .append(qualifiedStateCase(state)).append(");\n") - .append(indent).append(THREE_INDENT).append("break;\n")); + .append(indent).append(" return;\n") + .append(indent).append(" }\n\n")); - sb.append(indent).append(TWO_INDENT).append("default:\n") - .append(indent).append(THREE_INDENT).append("codecState(") - .append(qualifiedStateCase(fieldPrecedenceModel.latestVersionWrappedState())).append(");\n") - .append(indent).append(THREE_INDENT).append("break;\n") - .append(indent).append(INDENT).append("}\n") + sb.append(indent) + .append(" throw new InvalidOperationException(\"Unsupported acting version: \" + actingVersion);\n") .append(indent).append("}\n\n"); return sb; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 8009f7a073..1a5e17bb20 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -762,21 +762,18 @@ private static CharSequence generateDecoderWrapListener( final StringBuilder sb = new StringBuilder(); sb.append(indent).append("private void onWrap(final int actingVersion)\n") - .append(indent).append("{\n") - .append(indent).append(" switch(actingVersion)\n") - .append(indent).append(" {\n"); + .append(indent).append("{\n"); - fieldPrecedenceModel.forEachWrappedStateByVersion((version, state) -> - sb.append(indent).append(" case ").append(version).append(":\n") - .append(indent).append(" codecState(") + fieldPrecedenceModel.forEachWrappedStateByVersionDesc((version, state) -> + sb.append(indent).append(" if (actingVersion >= ").append(version).append(")\n") + .append(indent).append(" {\n") + .append(indent).append(" codecState(") .append(qualifiedStateCase(state)).append(");\n") - .append(indent).append(" break;\n")); + .append(indent).append(" return;\n") + .append(indent).append(" }\n\n")); - sb.append(indent).append(" default:\n") - .append(indent).append(" codecState(") - .append(qualifiedStateCase(fieldPrecedenceModel.latestVersionWrappedState())).append(");\n") - .append(indent).append(" break;\n") - .append(indent).append(" }\n") + sb.append(indent) + .append(" throw new IllegalStateException(\"Unsupported acting version: \" + actingVersion);\n") .append(indent).append("}\n\n"); return sb; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java index 12bdde9ae0..3563540650 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecDecoder.java @@ -139,15 +139,13 @@ public int offset() private void onWrap(final int actingVersion) { - switch(actingVersion) + if (actingVersion >= 0) { - case 0: - codecState(CodecStates.V0_BLOCK); - break; - default: - codecState(CodecStates.V0_BLOCK); - break; + codecState(CodecStates.V0_BLOCK); + return; } + + throw new IllegalStateException("Unsupported acting version: " + actingVersion); } public FrameCodecDecoder wrap( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index e6e0fba7b9..7b2e69831b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -186,15 +186,13 @@ public int offset() private void onWrap(final int actingVersion) { - switch(actingVersion) + if (actingVersion >= 0) { - case 0: - codecState(CodecStates.V0_BLOCK); - break; - default: - codecState(CodecStates.V0_BLOCK); - break; + codecState(CodecStates.V0_BLOCK); + return; } + + throw new IllegalStateException("Unsupported acting version: " + actingVersion); } public TokenCodecDecoder wrap( diff --git a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp index ecd3df1336..ef2b58d75c 100644 --- a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp +++ b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp @@ -51,6 +51,7 @@ #include "order_check/NoBlock.h" #include "order_check/GroupWithNoBlock.h" #include "order_check/NestedGroupWithVarLength.h" +#include "order_check/SkipVersionAddGroupBeforeVarDataV2.h" using namespace order::check; using ::testing::HasSubstr; @@ -4935,3 +4936,22 @@ INSTANTIATE_TEST_SUITE_P( std::make_tuple(2, 2, "V0_B_N_D_N_BLOCK") ) ); + +TEST_F(FieldAccessOrderCheckTest, allowsSkippingFutureGroupWhenDecodingFromVersionWithNoChangesInMessagePart1) +{ + AddGroupBeforeVarDataV0 encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42).putB("abc"); + + SkipVersionAddGroupBeforeVarDataV2 decoder; + decoder.wrapForDecode( + m_buffer, + OFFSET, + AddGroupBeforeVarDataV0::sbeBlockLength(), + 1, + BUFFER_LEN + ); + + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.getBAsString(), "abc"); +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java index 80a4ba4416..6ac554b8a7 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java @@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; import java.nio.charset.StandardCharsets; import java.util.Random; @@ -3407,6 +3408,116 @@ void disallowsIncompleteMessagesDueToMissingVarDataInNestedGroup( assertThat(exception.getMessage(), containsString("Not fully encoded, current state: " + expectedState)); } + @Test + void decodesNullValueForFutureVersionBlockFieldWhenCurrentVersionHasNoChangesInMessage() + { + final MessageHeaderEncoder headerEncoder = new MessageHeaderEncoder(); + final SkipVersionAddPrimitiveV1Encoder encoder = new SkipVersionAddPrimitiveV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, headerEncoder); + + headerEncoder + .templateId(SkipVersionAddPrimitiveV2Encoder.TEMPLATE_ID) + .version(1); + + encoder.b("abc"); + + final SkipVersionAddPrimitiveV2Decoder decoder = new SkipVersionAddPrimitiveV2Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + + assertThat(decoder.a(), equalTo(SkipVersionAddPrimitiveV2Decoder.aNullValue())); + assertThat(decoder.b(), equalTo("abc")); + } + + @Test + void decodesEmptyFutureGroupWhenDecodingFromVersionWithNoChangesInMessage() + { + final MessageHeaderEncoder headerEncoder = new MessageHeaderEncoder(); + final SkipVersionAddGroupV1Encoder encoder = new SkipVersionAddGroupV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, headerEncoder); + + headerEncoder + .templateId(SkipVersionAddGroupV2Decoder.TEMPLATE_ID) + .version(1); + + encoder.a(42); + + final SkipVersionAddGroupV2Decoder decoder = new SkipVersionAddGroupV2Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.b().count(), equalTo(0)); + } + + @Test + void decodesNullValueForFutureVarDataFieldWhenDecodingFromVersionWithNoChangesInMessage() + { + final MessageHeaderEncoder headerEncoder = new MessageHeaderEncoder(); + final SkipVersionAddVarDataV1Encoder encoder = new SkipVersionAddVarDataV1Encoder() + .wrapAndApplyHeader(buffer, OFFSET, headerEncoder); + + headerEncoder + .templateId(SkipVersionAddVarDataV2Decoder.TEMPLATE_ID) + .version(1); + + encoder.a(42); + + final SkipVersionAddVarDataV2Decoder decoder = new SkipVersionAddVarDataV2Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + + assertThat(decoder.a(), equalTo(42)); + assertThat(decoder.b(), equalTo("")); + } + + @Test + void allowsDecodingUnknownFutureVersions() + { + final MessageHeaderEncoder headerEncoder = new MessageHeaderEncoder(); + final SkipVersionAddPrimitiveV2Encoder encoder = new SkipVersionAddPrimitiveV2Encoder() + .wrapAndApplyHeader(buffer, OFFSET, headerEncoder); + + headerEncoder + .templateId(SkipVersionAddPrimitiveV2Encoder.TEMPLATE_ID) + .version(42); + + encoder.a(43).b("abc"); + + final SkipVersionAddPrimitiveV2Decoder decoder = new SkipVersionAddPrimitiveV2Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + + assertThat(decoder.a(), equalTo(43)); + assertThat(decoder.b(), equalTo("abc")); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + void allowsSkippingFutureGroupWhenDecodingFromVersionWithNoChangesInMessage(final boolean decodeGroup) + { + final MessageHeaderEncoder headerEncoder = new MessageHeaderEncoder(); + final AddGroupBeforeVarDataV0Encoder encoder = new AddGroupBeforeVarDataV0Encoder() + .wrapAndApplyHeader(buffer, OFFSET, headerEncoder); + + headerEncoder + .templateId(SkipVersionAddGroupBeforeVarDataV2Decoder.TEMPLATE_ID) + .version(1); + + encoder.a(42).b("abc"); + + final SkipVersionAddGroupBeforeVarDataV2Decoder decoder = new SkipVersionAddGroupBeforeVarDataV2Decoder() + .wrapAndApplyHeader(buffer, OFFSET, messageHeaderDecoder); + + assertThat(decoder.a(), equalTo(42)); + + if (decodeGroup) + { + for (final SkipVersionAddGroupBeforeVarDataV2Decoder.CDecoder group : decoder.c()) + { + group.sbeSkip(); + } + } + + assertThat(decoder.b(), equalTo("abc")); + } + private void modifyHeaderToLookLikeVersion0() { messageHeaderDecoder.wrap(buffer, OFFSET); @@ -3418,9 +3529,9 @@ private void modifyHeaderToLookLikeVersion0() private void modifyHeaderToLookLikeVersion1() { messageHeaderDecoder.wrap(buffer, OFFSET); - assert messageHeaderDecoder.version() == 1; + assert messageHeaderDecoder.version() >= 1; final int v0TemplateId = messageHeaderDecoder.templateId() - 1_000; messageHeaderEncoder.wrap(buffer, OFFSET); - messageHeaderEncoder.templateId(v0TemplateId); + messageHeaderEncoder.templateId(v0TemplateId).version(1); } } diff --git a/sbe-tool/src/test/resources/field-order-check-schema.xml b/sbe-tool/src/test/resources/field-order-check-schema.xml index e4d62ebfd6..8bedfd4b3f 100644 --- a/sbe-tool/src/test/resources/field-order-check-schema.xml +++ b/sbe-tool/src/test/resources/field-order-check-schema.xml @@ -4,7 +4,7 @@ id="1" description="Unit Test" byteOrder="littleEndian" - version="1"> + version="3"> @@ -141,6 +141,7 @@ + @@ -289,4 +290,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 4b6cbf7d35b08b688cdd74822ef8f1a5f1ca45f6 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 11 Apr 2024 23:50:32 +0200 Subject: [PATCH 1117/1594] [C#] Fix assertion. --- csharp/sbe-tests/FieldAccessOrderCheckTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/sbe-tests/FieldAccessOrderCheckTests.cs b/csharp/sbe-tests/FieldAccessOrderCheckTests.cs index 1ee4569643..89ba377fd6 100644 --- a/csharp/sbe-tests/FieldAccessOrderCheckTests.cs +++ b/csharp/sbe-tests/FieldAccessOrderCheckTests.cs @@ -3194,7 +3194,7 @@ private void ModifyHeaderToLookLikeVersion1() { var messageHeaderDecoder = new MessageHeader(); messageHeaderDecoder.Wrap(_buffer, Offset, MessageHeader.SbeSchemaVersion); - Debug.Assert(messageHeaderDecoder.Version == 1); + Debug.Assert(messageHeaderDecoder.Version >= 1); int v0TemplateId = messageHeaderDecoder.TemplateId - 1_000; var messageHeaderEncoder = new MessageHeader(); messageHeaderEncoder.Wrap(_buffer, Offset, MessageHeader.SbeSchemaVersion); From 813a32870a5cbd98db0459a49c292d57703136f5 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 11 Apr 2024 23:53:01 +0200 Subject: [PATCH 1118/1594] 1.31.1 released --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 7341032ba0..6bae540243 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.32.0-SNAPSHOT +1.31.1 From 261f8a33753ba6c6b40ac646799e75149054e4be Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 11 Apr 2024 23:56:18 +0200 Subject: [PATCH 1119/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 6bae540243..365468802a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.31.1 +1.32.0-SNAPSHOT \ No newline at end of file From 782014f97b22eea8de05498dd9a73c7051a8c452 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:28:10 +0200 Subject: [PATCH 1120/1594] [CI] Fix GCC installation. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 149150af21..6c15932fdf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -176,7 +176,7 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | - sudo add-apt-repository ppa:ubuntu-toolchain-r/ppa + sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install -y g++-${{ matrix.version }} curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz From 0053ff3e605efb2af3e79a2b20178a6e1f18255a Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 13 May 2024 11:15:03 +0200 Subject: [PATCH 1121/1594] [CI] Install JDK 8 for running Gradle commands. --- .github/workflows/ci.yml | 69 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c15932fdf..7c117207db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,6 +92,11 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + - name: Setup java 8 to run the Gradle script + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 8 - name: Cache NuGet dependencies uses: actions/cache@v4 with: @@ -144,6 +149,11 @@ jobs: curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH + - name: Setup java 8 to run the Gradle script + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 8 - name: Build run: ./cppbuild/cppbuild @@ -182,6 +192,11 @@ jobs: curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH + - name: Setup java 8 to run the Gradle script + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 8 - name: Build run: ./cppbuild/cppbuild @@ -222,6 +237,11 @@ jobs: curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH + - name: Setup java 8 to run the Gradle script + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 8 - name: Build run: ./cppbuild/cppbuild @@ -262,6 +282,11 @@ jobs: curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH + - name: Setup java 8 to run the Gradle script + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 8 - name: Build run: ./cppbuild/cppbuild @@ -280,11 +305,28 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} + - name: Cache Gradle dependencies + uses: actions/cache@v4 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v4 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install CMake run: | curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz tar xf cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz echo "cmake-${CMAKE_VERSION}-Darwin-x86_64/CMake.app/Contents/bin" >> $GITHUB_PATH + - name: Setup java 8 to run the Gradle script + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 8 - name: Build run: cmake --version && ./cppbuild/cppbuild @@ -303,12 +345,29 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} + - name: Cache Gradle dependencies + uses: actions/cache@v4 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache Gradle wrappers + uses: actions/cache@v4 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install CMake run: | $client = new-object System.Net.WebClient $client.DownloadFile("https://github.com/Kitware/CMake/releases/download/v$Env:CMAKE_VERSION/cmake-$Env:CMAKE_VERSION-win64-x64.zip","cmake-$Env:CMAKE_VERSION-win64-x64.zip") 7z x cmake-$Env:CMAKE_VERSION-win64-x64.zip echo "cmake-$Env:CMAKE_VERSION-win64-x64/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 + - name: Setup java 8 to run the Gradle script + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 8 - name: Build run: cppbuild/cppbuild.cmd @@ -342,6 +401,11 @@ jobs: profile: minimal toolchain: ${{ matrix.rust }} override: true + - name: Setup java 8 to run the Gradle script + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 8 - run: ./gradlew runRustTests golang-build: @@ -372,6 +436,11 @@ jobs: uses: actions/setup-go@v4 with: go-version: ${{ matrix.version }} + - name: Setup java 8 to run the Gradle script + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 8 - name: Generate codecs run: ./gradlew generateGolangCodecs - name: Go From 3533f8d070c1502a53968e3d0d9dbfa2631bf54c Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 13 May 2024 11:38:16 +0200 Subject: [PATCH 1122/1594] [CI] Explicitly use `macos-14`. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c117207db..e6bb6a9736 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -296,7 +296,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ 'macos-latest' ] + os: [ 'macos-14' ] env: CC: clang CXX: clang++ From 2231d52a954ade38e64897afaf2cdb7680619a2e Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 30 May 2024 10:15:34 +0200 Subject: [PATCH 1123/1594] Update name. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index be16408906..691665c2b4 100644 --- a/build.gradle +++ b/build.gradle @@ -136,8 +136,8 @@ def projectPom = { } developer { id = 'vyazelenko' - name = 'Dmitry Vyazelenko' - email = 'vyazelenko@yahoo.com' + name = 'Dmytro Vyazelenko' + email = 'vyazelenko@protonmail.com' url = 'https://github.com/vyazelenko' } } From f381fd433319824b8d462c86d00939103d510b5c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 4 Jun 2024 13:21:31 +0200 Subject: [PATCH 1124/1594] [Java] Upgrade to Agrona 1.21.2. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 691665c2b4..1811fc9913 100644 --- a/build.gradle +++ b/build.gradle @@ -58,8 +58,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.10.2' def jmhVersion = '1.37' -def agronaVersion = '1.21.1' -def agronaVersionRange = '[1.21.1,2.0[' // allow any release >= 1.21.1 and < 2.0.0 +def agronaVersion = '1.21.2' +def agronaVersionRange = '[1.21.2,2.0[' // allow any release >= 1.21.2 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 2a2d308d280f24762b189e59cd6ed092c140cc5a Mon Sep 17 00:00:00 2001 From: Yuhanun Citgez <122264445+YuhanunCitgez@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:04:36 +0200 Subject: [PATCH 1125/1594] Rust Generation: Avoid warnings (#995) --- .../java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 2ed6eb1fcb..109d3ba4c5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -61,6 +61,7 @@ void generate() throws IOException indent(libRs, 0, "#![forbid(unsafe_code)]\n"); indent(libRs, 0, "#![allow(clippy::upper_case_acronyms)]\n"); indent(libRs, 0, "#![allow(non_camel_case_types)]\n\n"); + indent(libRs, 0, "#![allow(ambiguous_glob_reexports)]\n\n"); indent(libRs, 0, "use ::core::{convert::TryInto};\n\n"); final ArrayList modules = new ArrayList<>(); @@ -171,11 +172,6 @@ static void generateReadBuf(final Appendable writer, final ByteOrder byteOrder) indent(writer, 2, "Self { data }\n"); indent(writer, 1, "}\n\n"); - indent(writer, 1, "#[inline]\n"); - indent(writer, 1, "fn get_bytes(slice: &[u8]) -> [u8; COUNT] {\n"); - indent(writer, 2, "slice.try_into().expect(\"slice with incorrect length\")\n"); - indent(writer, 1, "}\n\n"); - indent(writer, 1, "#[inline]\n"); indent(writer, 1, "pub(crate) fn get_bytes_at(slice: &[u8], index: usize) -> [u8; N] {\n"); indent(writer, 2, "slice[index..index+N].try_into().expect(\"slice with incorrect length\")\n"); From e4dd8721fcf7b07d246b966149dc613174a4ddca Mon Sep 17 00:00:00 2001 From: adam-talos <87664036+adam-talos@users.noreply.github.com> Date: Tue, 18 Jun 2024 08:05:07 -0400 Subject: [PATCH 1126/1594] Fix to not allocate to the heap when iterating over repeating groups in golang 1.22 (#994) Verify by running ```golang go build -gcflags=all=-d=loopvar=2 ``` --- .../real_logic/sbe/generation/golang/GolangGenerator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java index ef9c04cc3b..1c1582380a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java @@ -1276,8 +1276,8 @@ private int generateGroupEncodeDecode( // Write the group itself encode.append(String.format( - "\tfor _, prop := range %1$s.%2$s {\n" + - "\t\tif err := prop.Encode(_m, _w); err != nil {\n" + + "\tfor i := range %1$s.%2$s {\n" + + "\t\tif err := %1$s.%2$s[i].Encode(_m, _w); err != nil {\n" + "\t\t\treturn err\n" + "\t\t}\n", varName, @@ -1329,8 +1329,8 @@ private int generateGroupEncodeDecode( // Range check the group itself rc.append(String.format( - "\tfor _, prop := range %1$s.%2$s {\n" + - "\t\tif err := prop.RangeCheck(actingVersion, schemaVersion); err != nil {\n" + + "\tfor i := range %1$s.%2$s {\n" + + "\t\tif err := %1$s.%2$s[i].RangeCheck(actingVersion, schemaVersion); err != nil {\n" + "\t\t\treturn err\n" + "\t\t}\n" + "\t}\n", From 5389910a15df61c0c0f1f27810d2c4cfb47d0a21 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 27 Sep 2023 13:48:36 +0100 Subject: [PATCH 1127/1594] [C#] Generate DTOs from SBE IR for non-perf-sensitive usecases. In some applications performance is not cricital. Some users would like to use SBE across their whole "estate", but don't want the "sharp edges" associated with using flyweight codecs, e.g., accidental escape. In this commit, I've added a first cut of DTO generation for C# and a simple test based on the Car Example. The DTOs support encoding and decoding via the generated codecs using `EncodeInto(CodecT codec)` and `DecodeFrom(CodecT codec)` methods. Currently there is no support for equality/comparison or read-only views over the data; although, these have been requested. Here are some points that we may or may not wish to change in the future: 1. Non-present (due to the encoded version) string/array data and repeating groups are represented as `null` rather than empty. 2. Non-present primitive values are represented as their associated null value rather than using nullable types. 3. Non-present bitsets are represented as `0`. 4. DTOs are generated via a separate `CodeGenerator` rather than a flag to the existing C# `CodeGenerator`. --- build.gradle | 16 +- csharp/sbe-dll/DirectBuffer.cs | 7 +- csharp/sbe-tests/DtoTests.cs | 110 ++ .../generation/csharp/CSharpDtoGenerator.java | 1076 +++++++++++++++++ .../sbe/generation/csharp/CSharpDtos.java | 35 + .../generation/csharp/CSharpGenerator.java | 109 +- .../sbe/generation/csharp/CSharpUtil.java | 116 +- 7 files changed, 1353 insertions(+), 116 deletions(-) create mode 100644 csharp/sbe-tests/DtoTests.cs create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java diff --git a/build.gradle b/build.gradle index 1811fc9913..7dbd8d24fc 100644 --- a/build.gradle +++ b/build.gradle @@ -735,7 +735,7 @@ tasks.register('generateCSharpCodecsWithXIncludes', JavaExec) { 'sbe-samples/src/main/resources/example-extension-schema.xml'] } -tasks.register('generateCSharpCodecsTests', JavaExec) { +tasks.register('generateCSharpTestCodecs', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( @@ -754,9 +754,21 @@ tasks.register('generateCSharpCodecsTests', JavaExec) { 'sbe-benchmarks/src/main/resources/fix-message-samples.xml'] } +tasks.register('generateCSharpTestDtos', JavaExec) { + mainClass.set('uk.co.real_logic.sbe.SbeTool') + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'csharp/sbe-generated', + 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharpDtos', + 'sbe.xinclude.aware': 'true', + 'sbe.validation.xsd': validationXsdPath) + args = ['sbe-samples/src/main/resources/example-extension-schema.xml'] +} + tasks.register('generateCSharpCodecs') { description = 'Generate csharp codecs' - dependsOn 'generateCSharpCodecsTests', + dependsOn 'generateCSharpTestCodecs', + 'generateCSharpTestDtos', 'generateCSharpCodecsWithXIncludes' } diff --git a/csharp/sbe-dll/DirectBuffer.cs b/csharp/sbe-dll/DirectBuffer.cs index 09eb64ec7e..87f08b96b5 100644 --- a/csharp/sbe-dll/DirectBuffer.cs +++ b/csharp/sbe-dll/DirectBuffer.cs @@ -694,7 +694,6 @@ public int SetBytes(int index, ReadOnlySpan src) ///

      /// Writes a string into the underlying buffer, encoding using the provided . - /// If there is not enough room in the buffer for the bytes it will throw IndexOutOfRangeException. /// /// encoding to use to write the bytes from the string /// source string @@ -702,13 +701,9 @@ public int SetBytes(int index, ReadOnlySpan src) /// count of bytes written public unsafe int SetBytesFromString(Encoding encoding, string src, int index) { - int available = _capacity - index; int byteCount = encoding.GetByteCount(src); - if (byteCount > available) - { - ThrowHelper.ThrowIndexOutOfRangeException(_capacity); - } + CheckLimit(index + byteCount); fixed (char* ptr = src) { diff --git a/csharp/sbe-tests/DtoTests.cs b/csharp/sbe-tests/DtoTests.cs new file mode 100644 index 0000000000..99fbcadc74 --- /dev/null +++ b/csharp/sbe-tests/DtoTests.cs @@ -0,0 +1,110 @@ +using Extension; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Org.SbeTool.Sbe.Dll; + +namespace Org.SbeTool.Sbe.Tests +{ + [TestClass] + public class DtoTests + { + [TestMethod] + public void ShouldRoundTripCar() + { + var inputByteArray = new byte[1024]; + var inputBuffer = new DirectBuffer(inputByteArray); + EncodeCar(inputBuffer); + var decoder = new Car(); + decoder.WrapForDecode(inputBuffer, 0, Car.BlockLength, Car.SchemaVersion); + var decoderString = decoder.ToString(); + var dto = new CarDto(); + dto.DecodeFrom(decoder); + var outputByteArray = new byte[1024]; + var outputBuffer = new DirectBuffer(outputByteArray); + var encoder = new Car(); + encoder.WrapForEncode(outputBuffer, 0); + dto.EncodeInto(encoder); + var dtoString = dto.ToString(); + CollectionAssert.AreEqual(inputByteArray, outputByteArray); + Assert.AreEqual(decoderString, dtoString); + } + + private static void EncodeCar(DirectBuffer buffer) + { + var car = new Car(); + car.WrapForEncode(buffer, 0); + car.SerialNumber = 1234; + car.ModelYear = 2013; + car.Available = BooleanType.T; + car.Code = Model.A; + car.SetVehicleCode("ABCDEF"); + + for (int i = 0, size = Car.SomeNumbersLength; i < size; i++) + { + car.SetSomeNumbers(i, (uint)i); + } + + car.Extras = OptionalExtras.CruiseControl | OptionalExtras.SportsPack; + + car.CupHolderCount = 119; + + car.Engine.Capacity = 2000; + car.Engine.NumCylinders = 4; + car.Engine.SetManufacturerCode("ABC"); + car.Engine.Efficiency = 35; + car.Engine.BoosterEnabled = BooleanType.T; + car.Engine.Booster.BoostType = BoostType.NITROUS; + car.Engine.Booster.HorsePower = 200; + + var fuelFigures = car.FuelFiguresCount(3); + fuelFigures.Next(); + fuelFigures.Speed = 30; + fuelFigures.Mpg = 35.9f; + fuelFigures.SetUsageDescription("this is a description"); + + fuelFigures.Next(); + fuelFigures.Speed = 55; + fuelFigures.Mpg = 49.0f; + fuelFigures.SetUsageDescription("this is a description"); + + fuelFigures.Next(); + fuelFigures.Speed = 75; + fuelFigures.Mpg = 40.0f; + fuelFigures.SetUsageDescription("this is a description"); + + Car.PerformanceFiguresGroup perfFigures = car.PerformanceFiguresCount(2); + perfFigures.Next(); + perfFigures.OctaneRating = 95; + + Car.PerformanceFiguresGroup.AccelerationGroup acceleration = perfFigures.AccelerationCount(3).Next(); + acceleration.Mph = 30; + acceleration.Seconds = 4.0f; + + acceleration.Next(); + acceleration.Mph = 60; + acceleration.Seconds = 7.5f; + + acceleration.Next(); + acceleration.Mph = 100; + acceleration.Seconds = 12.2f; + + perfFigures.Next(); + perfFigures.OctaneRating = 99; + acceleration = perfFigures.AccelerationCount(3).Next(); + + acceleration.Mph = 30; + acceleration.Seconds = 3.8f; + + acceleration.Next(); + acceleration.Mph = 60; + acceleration.Seconds = 7.1f; + + acceleration.Next(); + acceleration.Mph = 100; + acceleration.Seconds = 11.8f; + + car.SetManufacturer("Ford"); + car.SetModel("Fiesta"); + car.SetActivationCode("1234"); + } + } +} \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java new file mode 100644 index 0000000000..a0f1e21d9d --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -0,0 +1,1076 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * Copyright (C) 2017 MarketFactory, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.generation.csharp; + +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.generation.CodeGenerator; +import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.ir.Signal; +import uk.co.real_logic.sbe.ir.Token; +import org.agrona.Verify; +import org.agrona.generation.OutputManager; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiConsumer; + +import static uk.co.real_logic.sbe.generation.csharp.CSharpUtil.*; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData; + +/** + * DTO generator for the CSharp programming language. + */ +@SuppressWarnings("CodeBlock2Expr") +public class CSharpDtoGenerator implements CodeGenerator +{ + private static final String INDENT = " "; + private static final String BASE_INDENT = INDENT; + + private final Ir ir; + private final OutputManager outputManager; + + /** + * Create a new C# DTO {@link CodeGenerator}. + * + * @param ir for the messages and types. + * @param outputManager for generating the DTOs to. + */ + public CSharpDtoGenerator(final Ir ir, final OutputManager outputManager) + { + Verify.notNull(ir, "ir"); + Verify.notNull(outputManager, "outputManager"); + + this.ir = ir; + this.outputManager = outputManager; + } + + /** + * {@inheritDoc} + */ + public void generate() throws IOException + { + generateDtosForTypes(); + + for (final List tokens : ir.messages()) + { + final Token msgToken = tokens.get(0); + final String codecClassName = formatClassName(msgToken.name()); + final String className = formatDtoClassName(msgToken.name()); + + final List messageBody = tokens.subList(1, tokens.size() - 1); + int offset = 0; + + final StringBuilder sb = new StringBuilder(); + + final List fields = new ArrayList<>(); + offset = collectFields(messageBody, offset, fields); + generateFields(sb, fields, BASE_INDENT + INDENT); + + final List groups = new ArrayList<>(); + offset = collectGroups(messageBody, offset, groups); + generateGroups(sb, codecClassName, groups, BASE_INDENT + INDENT); + + final List varData = new ArrayList<>(); + collectVarData(messageBody, offset, varData); + generateVarData(sb, varData, BASE_INDENT + INDENT); + + generateDecodeFrom(sb, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); + generateEncodeInto(sb, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); + generateDisplay(sb, codecClassName, "WrapForEncode", null, BASE_INDENT + INDENT); + + try (Writer out = outputManager.createOutput(className)) + { + out.append(generateFileHeader(ir.applicableNamespace(), "using System.Collections.Generic;\n")); + out.append(generateDocumentation(BASE_INDENT, msgToken)); + + out.append(BASE_INDENT).append("public sealed partial class ").append(className).append("\n") + .append(BASE_INDENT).append("{") + .append(sb) + .append(BASE_INDENT).append("}\n") + .append("}\n"); + } + } + } + + private void generateGroups( + final StringBuilder sb, + final String parentMessageClassName, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + final String groupName = groupToken.name(); + final String groupClassName = formatDtoClassName(groupName); + + sb.append("\n") + .append(generateDocumentation(indent, groupToken)) + .append(indent).append("public List<").append(groupClassName).append("> ") + .append(formatPropertyName(groupName)) + .append(" { get; set; } = new List<").append(groupClassName).append(">();\n"); + + sb.append("\n") + .append(generateDocumentation(indent, groupToken)) + .append(indent).append("public sealed partial class ").append(groupClassName).append("\n") + .append(indent).append("{"); + + i++; + i += tokens.get(i).componentTokenCount(); + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + generateFields(sb, fields, indent + INDENT); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + final String codecClassName = parentMessageClassName + "." + formatClassName(groupName) + "Group"; + generateGroups(sb, codecClassName, groups, indent + INDENT); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + generateVarData(sb, varData, indent + INDENT); + + generateDecodeFrom(sb, codecClassName, fields, groups, varData, indent + INDENT); + generateEncodeInto(sb, codecClassName, fields, groups, varData, indent + INDENT); + + sb.append(indent).append("}\n"); + } + } + + private void generateCompositeDecodeFrom( + final StringBuilder sb, + final String codecClassName, + final List tokens, + final String indent) + { + sb.append("\n") + .append(indent).append("public void DecodeFrom(").append(codecClassName).append(" codec)\n") + .append(indent).append("{\n"); + + for (int i = 0; i < tokens.size(); ) + { + final Token token = tokens.get(i); + + generateFieldDecodeFrom(sb, token, token, codecClassName, indent + INDENT); + + i += tokens.get(i).componentTokenCount(); + } + + sb.append(indent).append("}\n"); + } + + private void generateCompositeEncodeInto( + final StringBuilder sb, + final String codecClassName, + final List tokens, + final String indent) + { + sb.append("\n") + .append(indent).append("public void EncodeInto(").append(codecClassName).append(" codec)\n") + .append(indent).append("{\n"); + + for (int i = 0; i < tokens.size(); ) + { + final Token token = tokens.get(i); + + generateFieldEncodeInto(sb, token, token, indent + INDENT); + + i += tokens.get(i).componentTokenCount(); + } + + sb.append(indent).append("}\n"); + } + + private void generateDecodeFrom( + final StringBuilder sb, + final String codecClassName, + final List fields, + final List groups, + final List varData, + final String indent) + { + sb.append("\n") + .append(indent).append("public void DecodeFrom(").append(codecClassName).append(" codec)\n") + .append(indent).append("{\n"); + + generateFieldsDecodeFrom(sb, fields, codecClassName, indent + INDENT); + generateGroupsDecodeFrom(sb, groups, indent + INDENT); + generateVarDataDecodeFrom(sb, varData, indent + INDENT); + + sb.append(indent).append("}\n"); + } + + private void generateFieldsDecodeFrom( + final StringBuilder sb, + final List tokens, + final String codecClassName, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token signalToken = tokens.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = tokens.get(i + 1); + + generateFieldDecodeFrom(sb, signalToken, encodingToken, codecClassName, indent); + } + } + } + + private void generateFieldDecodeFrom( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String codecClassName, final String indent) + { + switch (typeToken.signal()) + { + case ENCODING: + generatePrimitiveDecodeFrom(sb, fieldToken, typeToken, codecClassName, indent); + break; + + case BEGIN_SET: + generatePropertyDecodeFrom(sb, fieldToken, "0", indent); + break; + + case BEGIN_ENUM: + final String enumName = formatClassName(typeToken.applicableTypeName()); + final String nullValue = formatNamespace(ir.packageName()) + "." + enumName + ".NULL_VALUE"; + generatePropertyDecodeFrom(sb, fieldToken, nullValue, indent); + break; + + case BEGIN_COMPOSITE: + generateComplexDecodeFrom(sb, fieldToken, indent); + break; + + default: + break; + } + } + + private void generatePrimitiveDecodeFrom( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String codecClassName, + final String indent) + { + if (typeToken.isConstantEncoding()) + { + return; + } + + final int arrayLength = typeToken.arrayLength(); + + if (arrayLength == 1) + { + final String nullValue = codecClassName + "." + formatPropertyName(fieldToken.name()) + "NullValue"; + generatePropertyDecodeFrom(sb, fieldToken, nullValue, indent); + } + else if (arrayLength > 1) + { + generateArrayDecodeFrom(sb, fieldToken, typeToken, indent); + } + } + + private void generateArrayDecodeFrom( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + wrapInActingVersionCheck( + sb, + fieldToken, + indent, + (blkSb, blkIndent) -> + { + blkSb.append(blkIndent).append(formattedPropertyName) + .append(" = codec.Get").append(formattedPropertyName).append("();\n"); + }, + (blkSb, blkIndent) -> + { + blkSb.append(blkIndent).append(formattedPropertyName).append(" = null;\n"); + } + ); + } + else + { + final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); + + wrapInActingVersionCheck( + sb, + fieldToken, + indent, + (blkSb, blkIndent) -> + { + blkSb.append(blkIndent).append(formattedPropertyName) + .append(" = new ").append(typeName).append("[") + .append(typeToken.arrayLength()).append("];\n") + .append(blkIndent).append("codec.").append(formattedPropertyName) + .append(".CopyTo(new Span<").append(typeName).append(">(") + .append(formattedPropertyName).append("));\n"); + }, + (blkSb, blkIndent) -> + { + blkSb.append(blkIndent).append(formattedPropertyName).append(" = null;\n"); + } + ); + } + } + + private void generatePropertyDecodeFrom( + final StringBuilder sb, + final Token fieldToken, + final String nullValue, + final String indent) + { + + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + wrapInActingVersionCheck( + sb, + fieldToken, + indent, + (blkSb, blkIndent) -> + { + blkSb.append(blkIndent).append(formattedPropertyName).append(" = codec.") + .append(formattedPropertyName).append(";\n"); + }, + (blkSb, blkIndent) -> + { + blkSb.append(blkIndent).append(formattedPropertyName).append(" = ").append(nullValue).append(";\n"); + } + ); + } + + private void generateComplexDecodeFrom( + final StringBuilder sb, + final Token fieldToken, + final String indent) + { + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + wrapInActingVersionCheck( + sb, + fieldToken, + indent, + (blkSb, blkIndent) -> + { + blkSb.append(blkIndent).append(formattedPropertyName).append(" = new ") + .append(formatDtoClassName(propertyName)).append("();\n") + .append(blkIndent).append(formattedPropertyName).append(".DecodeFrom(codec.") + .append(formattedPropertyName).append(");\n"); + }, + (blkSb, blkIndent) -> + { + blkSb.append(blkIndent).append(formattedPropertyName).append(" = null;\n"); + } + ); + } + + private void generateGroupsDecodeFrom( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + final String groupName = groupToken.name(); + final String formattedPropertyName = formatPropertyName(groupName); + final String groupDtoClassName = formatDtoClassName(groupName); + final String groupCodecVarName = groupName + "Codec"; + + sb.append("\n") + .append(indent) + .append(formattedPropertyName).append(" = new List<").append(groupDtoClassName).append(">();\n"); + + wrapInActingVersionCheck( + sb, + groupToken, + indent, + (blkSb, blkIndent) -> + { + blkSb.append(blkIndent).append("var ").append(groupCodecVarName).append(" = codec.") + .append(formattedPropertyName).append(";\n") + .append(blkIndent).append("while (").append(groupCodecVarName).append(".HasNext)\n") + .append(blkIndent).append("{\n") + .append(blkIndent).append(INDENT) + .append("var element = new ").append(groupDtoClassName).append("();\n") + .append(blkIndent).append(INDENT) + .append("element.DecodeFrom(").append(groupCodecVarName).append(".Next());\n") + .append(blkIndent).append(INDENT) + .append(formattedPropertyName).append(".Add(element);\n") + .append(blkIndent).append("}\n"); + }, + null + ); + + i++; + i += tokens.get(i).componentTokenCount(); + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + } + } + + private void generateVarDataDecodeFrom( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0; i < tokens.size(); i++) + { + final Token token = tokens.get(i); + if (token.signal() == Signal.BEGIN_VAR_DATA) + { + final String propertyName = token.name(); + final Token varDataToken = Generators.findFirst("varData", tokens, i); + final String characterEncoding = varDataToken.encoding().characterEncoding(); + + final String formattedPropertyName = formatPropertyName(propertyName); + final String accessor = characterEncoding == null ? + "Get" + formattedPropertyName + "Bytes" : + "Get" + formattedPropertyName; + + wrapInActingVersionCheck( + sb, + token, + indent, + (blkSb, blkIndent) -> + { + blkSb.append(blkIndent).append(formattedPropertyName) + .append(" = codec.").append(accessor).append("();\n"); + }, + (blkSb, blkIndent) -> + { + blkSb.append(blkIndent).append(formattedPropertyName).append(" = null;\n"); + } + ); + } + } + } + + private void wrapInActingVersionCheck( + final StringBuilder sb, + final Token token, + final String indent, + final BiConsumer generatePresentBlock, + final BiConsumer generateNotPresentBlock) + { + final String propertyName = token.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + if (token.version() > 0) + { + sb.append("\n").append(indent).append("if (codec.").append(formattedPropertyName) + .append("InActingVersion())\n") + .append(indent).append("{\n"); + generatePresentBlock.accept(sb, indent + INDENT); + sb.append(indent).append("}\n"); + if (null != generateNotPresentBlock) + { + sb.append(indent).append("else\n") + .append(indent).append("{\n"); + generateNotPresentBlock.accept(sb, indent + INDENT); + sb.append(indent).append("}\n"); + } + } + else + { + generatePresentBlock.accept(sb, indent); + } + } + + private void generateEncodeInto( + final StringBuilder sb, + final String codecClassName, + final List fields, + final List groups, + final List varData, + final String indent) + { + sb.append("\n") + .append(indent).append("public void EncodeInto(").append(codecClassName).append(" codec)\n") + .append(indent).append("{\n"); + + generateFieldsEncodeInto(sb, fields, indent + INDENT); + generateGroupsEncodeInto(sb, groups, indent + INDENT); + generateVarDataEncodeInto(sb, varData, indent + INDENT); + + sb.append(indent).append("}\n"); + } + + private void generateFieldsEncodeInto( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token signalToken = tokens.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = tokens.get(i + 1); + generateFieldEncodeInto(sb, signalToken, encodingToken, indent); + } + } + } + + private void generateFieldEncodeInto( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String indent) + { + + switch (typeToken.signal()) + { + case ENCODING: + generatePrimitiveEncodeInto(sb, fieldToken, typeToken, indent); + break; + + case BEGIN_SET: + case BEGIN_ENUM: + generatePropertyEncodeInto(sb, fieldToken, indent); + break; + + case BEGIN_COMPOSITE: + generateComplexEncodeInto(sb, fieldToken, indent); + break; + + default: + break; + } + } + + private void generatePrimitiveEncodeInto( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (typeToken.isConstantEncoding()) + { + return; + } + + final int arrayLength = typeToken.arrayLength(); + + if (arrayLength == 1) + { + generatePropertyEncodeInto(sb, fieldToken, indent); + } + else if (arrayLength > 1) + { + generateArrayEncodeInto(sb, fieldToken, typeToken, indent); + } + } + + private void generateArrayEncodeInto( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + sb.append(indent).append("codec.Set").append(formattedPropertyName).append("(") + .append(formattedPropertyName).append(");\n"); + } + else + { + final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); + + sb.append(indent).append("new Span<").append(typeName).append(">(").append(formattedPropertyName) + .append(").CopyTo(codec.").append(formattedPropertyName).append("AsSpan());\n"); + } + } + + private void generatePropertyEncodeInto( + final StringBuilder sb, + final Token fieldToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + sb.append(indent).append("codec.").append(formattedPropertyName).append(" = ") + .append(formattedPropertyName).append(";\n"); + } + + private void generateComplexEncodeInto( + final StringBuilder sb, + final Token fieldToken, + final String indent) + { + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + sb.append(indent).append(formattedPropertyName).append(".EncodeInto(codec.") + .append(formattedPropertyName).append(");\n"); + } + + private void generateGroupsEncodeInto( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + final String groupName = groupToken.name(); + final String formattedPropertyName = formatPropertyName(groupName); + final String groupCodecVarName = groupName + "Codec"; + + sb.append("\n") + .append(indent).append("var ").append(groupCodecVarName) + .append(" = codec.").append(formattedPropertyName) + .append("Count(").append(formattedPropertyName).append(".Count);\n\n") + .append(indent).append("foreach (var group in ").append(formattedPropertyName).append(")\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("group.EncodeInto(").append(groupCodecVarName) + .append(".Next()").append(");\n") + .append(indent).append("}\n\n"); + + i++; + i += tokens.get(i).componentTokenCount(); + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + } + } + + private void generateVarDataEncodeInto( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (final Token token : tokens) + { + if (token.signal() == Signal.BEGIN_VAR_DATA) + { + final String propertyName = token.name(); + + sb.append(indent).append("codec.Set").append(formatPropertyName(propertyName)) + .append("(").append(formatPropertyName(propertyName)).append(");\n"); + } + } + } + + private void generateDisplay( + final StringBuilder sb, + final String codecClassName, + final String wrapMethod, + final String actingVersion, + final String indent) + { + sb.append("\n") + .append(indent).append("public override string ToString()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT) + .append("var buffer = new DirectBuffer(new byte[128], (ignored, newSize) => new byte[newSize]);\n") + .append(indent).append(INDENT).append("var codec = new ").append(codecClassName).append("();\n") + .append(indent).append(INDENT).append("codec."); + sb.append(wrapMethod).append("(buffer, 0"); + if (null != actingVersion) + { + sb.append(", ").append(actingVersion); + } + sb.append(");\n"); + sb.append(indent).append(INDENT).append("EncodeInto(codec);\n") + .append(indent).append(INDENT).append("StringBuilder sb = new StringBuilder();\n") + .append(indent).append(INDENT).append("codec.BuildString(sb);\n") + .append(indent).append(INDENT).append("return sb.ToString();\n") + .append(indent).append("}\n"); + } + + private void generateFields( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token signalToken = tokens.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = tokens.get(i + 1); + final String propertyName = signalToken.name(); + + switch (encodingToken.signal()) + { + case ENCODING: + generatePrimitiveProperty(sb, propertyName, signalToken, encodingToken, indent); + break; + + case BEGIN_ENUM: + generateEnumProperty(sb, propertyName, signalToken, encodingToken, indent); + break; + + case BEGIN_SET: + generateBitSetProperty(sb, propertyName, signalToken, encodingToken, indent); + break; + + case BEGIN_COMPOSITE: + generateCompositeProperty(sb, propertyName, signalToken, encodingToken, indent); + break; + + default: + break; + } + } + } + } + + private void generateCompositeProperty( + final StringBuilder sb, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String bitSetName = formatDtoClassName(typeToken.applicableTypeName()); + sb.append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public ").append(bitSetName).append(" ").append(formatPropertyName(propertyName)) + .append(" { get; set; } = new ").append(bitSetName).append("();\n"); + } + + private void generateBitSetProperty( + final StringBuilder sb, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String enumName = formatClassName(typeToken.applicableTypeName()); + + sb.append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public ").append(enumName).append(" ") + .append(formatPropertyName(propertyName)).append(" { get; set; }\n"); + } + + private void generateEnumProperty( + final StringBuilder sb, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String enumName = formatClassName(typeToken.applicableTypeName()); + + if (fieldToken.isConstantEncoding()) + { + final String constValue = fieldToken.encoding().constValue().toString(); + + sb.append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public static ").append(enumName).append(" ") + .append(formatPropertyName(propertyName)).append("\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("get { return ") + .append(formatNamespace(ir.packageName())).append(".").append(constValue) + .append("; }\n") + .append(indent).append("}\n"); + } + else + { + sb.append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public ").append(enumName).append(" ").append(formatPropertyName(propertyName)) + .append(" { get; set; }\n"); + } + } + + private void generatePrimitiveProperty( + final StringBuilder sb, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (typeToken.isConstantEncoding()) + { + generateConstPropertyMethods(sb, propertyName, fieldToken, typeToken, indent); + } + else + { + generatePrimitivePropertyMethods(sb, propertyName, fieldToken, typeToken, indent); + } + } + + private void generatePrimitivePropertyMethods( + final StringBuilder sb, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final int arrayLength = typeToken.arrayLength(); + + if (arrayLength == 1) + { + generateSingleValueProperty(sb, propertyName, fieldToken, typeToken, indent); + } + else if (arrayLength > 1) + { + generateArrayProperty(sb, propertyName, fieldToken, typeToken, indent); + } + } + + private void generateArrayProperty( + final StringBuilder sb, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + sb.append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public string ") + .append(formatPropertyName(propertyName)).append(" { get; set; }\n"); + } + else + { + final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); + + sb.append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public ").append(typeName).append("[] ") + .append(formatPropertyName(propertyName)).append(" { get; set; }\n"); + } + } + + private void generateSingleValueProperty( + final StringBuilder sb, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); + + sb.append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public ").append(typeName).append(" ") + .append(formatPropertyName(propertyName)).append(" { get; set; }\n"); + } + + private void generateConstPropertyMethods( + final StringBuilder sb, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + sb.append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public static string ").append(toUpperFirstChar(propertyName)).append("\n") + .append(indent).append("{\n") + .append(indent).append(INDENT) + .append("get { return \"").append(typeToken.encoding().constValue().toString()).append("\"; }\n") + .append(indent).append("}\n"); + } + else + { + final String literalValue = + generateLiteral(typeToken.encoding().primitiveType(), typeToken.encoding().constValue().toString()); + + sb.append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public static ").append(cSharpTypeName(typeToken.encoding().primitiveType())) + .append(" ").append(formatPropertyName(propertyName)).append("\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("get { return ").append(literalValue).append("; }\n") + .append(indent).append("}\n"); + } + } + + private void generateVarData( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token token = tokens.get(i); + if (token.signal() == Signal.BEGIN_VAR_DATA) + { + final String propertyName = token.name(); + final Token varDataToken = Generators.findFirst("varData", tokens, i); + final String characterEncoding = varDataToken.encoding().characterEncoding(); + final String dtoType = characterEncoding == null ? "byte[]" : "string"; + + sb.append("\n") + .append(indent).append("public ").append(dtoType).append(" ") + .append(formatPropertyName(propertyName)).append(" { get; set; }\n"); + } + } + } + + private String formatDtoClassName(final String name) + { + return formatClassName(name + "Dto"); + } + + private void generateDtosForTypes() throws IOException + { + for (final List tokens : ir.types()) + { + switch (tokens.get(0).signal()) + { + case BEGIN_COMPOSITE: + generateComposite(tokens); + break; + + default: + break; + } + } + } + + private void generateComposite(final List tokens) throws IOException + { + final String name = tokens.get(0).applicableTypeName(); + final String className = formatDtoClassName(name); + final String codecClassName = formatClassName(name); + + try (Writer out = outputManager.createOutput(className)) + { + out.append(generateFileHeader(ir.applicableNamespace())); + out.append(generateDocumentation(BASE_INDENT, tokens.get(0))); + + final StringBuilder sb = new StringBuilder(); + + final List compositeTokens = tokens.subList(1, tokens.size() - 1); + generateCompositePropertyElements(sb, compositeTokens, BASE_INDENT + INDENT); + generateCompositeDecodeFrom(sb, codecClassName, compositeTokens, BASE_INDENT + INDENT); + generateCompositeEncodeInto(sb, codecClassName, compositeTokens, BASE_INDENT + INDENT); + generateDisplay(sb, codecClassName, "Wrap", codecClassName + ".SbeSchemaVersion", BASE_INDENT + INDENT); + + out.append(BASE_INDENT).append("public sealed partial class ").append(className).append("\n") + .append(BASE_INDENT).append("{") + .append(sb) + .append(BASE_INDENT).append("}\n") + .append("}\n"); + } + } + + private void generateCompositePropertyElements( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0; i < tokens.size(); ) + { + final Token token = tokens.get(i); + final String propertyName = formatPropertyName(token.name()); + + switch (token.signal()) + { + case ENCODING: + generatePrimitiveProperty(sb, propertyName, token, token, indent); + break; + + case BEGIN_ENUM: + generateEnumProperty(sb, propertyName, token, token, indent); + break; + + case BEGIN_SET: + generateBitSetProperty(sb, propertyName, token, token, indent); + break; + + case BEGIN_COMPOSITE: + generateCompositeProperty(sb, propertyName, token, token, indent); + break; + + default: + break; + } + + i += tokens.get(i).componentTokenCount(); + } + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java new file mode 100644 index 0000000000..79859d6764 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * Copyright 2017 MarketFactory Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.csharp; + +import uk.co.real_logic.sbe.generation.CodeGenerator; +import uk.co.real_logic.sbe.generation.TargetCodeGenerator; +import uk.co.real_logic.sbe.ir.Ir; + +/** + * {@link CodeGenerator} factory for CSharp DTOs. + */ +public class CSharpDtos implements TargetCodeGenerator +{ + /** + * {@inheritDoc} + */ + public CodeGenerator newInstance(final Ir ir, final String outputDir) + { + return new CSharpDtoGenerator(ir, new CSharpNamespaceOutputManager(outputDir, ir.applicableNamespace())); + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 8d15021814..530717c9c4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -786,40 +786,6 @@ private CharSequence generateEnumValues(final List tokens, final Token en return sb; } - private CharSequence generateFileHeader(final String packageName) - { - String[] tokens = packageName.split("\\."); - final StringBuilder sb = new StringBuilder(); - for (final String t : tokens) - { - sb.append(toUpperFirstChar(t)).append("."); - } - if (sb.length() > 0) - { - sb.setLength(sb.length() - 1); - } - - tokens = sb.toString().split("-"); - sb.setLength(0); - - for (final String t : tokens) - { - sb.append(toUpperFirstChar(t)); - } - - return String.format( - "// \n" + - "// Generated SBE (Simple Binary Encoding) message codec\n" + - "// \n\n" + - "#pragma warning disable 1591 // disable warning on missing comments\n" + - "using System;\n" + - "using System.Text;\n" + - "using Org.SbeTool.Sbe.Dll;\n\n" + - "namespace %s\n" + - "{\n", - sb); - } - private CharSequence generateClassDeclaration(final String className) { return String.format( @@ -828,20 +794,6 @@ private CharSequence generateClassDeclaration(final String className) className); } - private static String generateDocumentation(final String indent, final Token token) - { - final String description = token.description(); - if (null == description || description.isEmpty()) - { - return ""; - } - - return - indent + "/// \n" + - indent + "/// " + description + "\n" + - indent + "/// \n"; - } - private void generateMetaAttributeEnum() throws IOException { try (Writer out = outputManager.createOutput(META_ATTRIBUTE_ENUM)) @@ -1282,7 +1234,7 @@ private CharSequence generateConstPropertyMethods( final StringBuilder sb = new StringBuilder(); - final String javaTypeName = cSharpTypeName(token.encoding().primitiveType()); + final String csharpTypeName = cSharpTypeName(token.encoding().primitiveType()); final byte[] constantValue = token.encoding().constValue().byteArrayValue(token.encoding().primitiveType()); final CharSequence values = generateByteLiteralList( token.encoding().constValue().byteArrayValue(token.encoding().primitiveType())); @@ -1304,7 +1256,7 @@ private CharSequence generateConstPropertyMethods( indent + INDENT + "{\n" + indent + INDENT + INDENT + "return _%3$sValue[index];\n" + indent + INDENT + "}\n\n", - javaTypeName, + csharpTypeName, toUpperFirstChar(propertyName), propertyName)); @@ -2247,63 +2199,6 @@ private String generateByteOrder(final ByteOrder byteOrder, final int primitiveT return "LittleEndian"; } - private String generateLiteral(final PrimitiveType type, final String value) - { - String literal = ""; - - final String castType = cSharpTypeName(type); - switch (type) - { - case CHAR: - case UINT8: - case INT8: - case INT16: - case UINT16: - literal = "(" + castType + ")" + value; - break; - - case INT32: - literal = value; - break; - - case UINT32: - literal = value + "U"; - break; - - case FLOAT: - if (value.endsWith("NaN")) - { - literal = "float.NaN"; - } - else - { - literal = value + "f"; - } - break; - - case UINT64: - literal = "0x" + Long.toHexString(Long.parseLong(value)) + "UL"; - break; - - case INT64: - literal = value + "L"; - break; - - case DOUBLE: - if (value.endsWith("NaN")) - { - literal = "double.NaN"; - } - else - { - literal = value + "d"; - } - break; - } - - return literal; - } - private void appendGroupInstanceDisplay( final StringBuilder sb, final List fields, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index cac937c67f..124b352629 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -17,6 +17,8 @@ package uk.co.real_logic.sbe.generation.csharp; import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.ir.Token; import java.util.EnumMap; import java.util.Map; @@ -26,6 +28,118 @@ */ public class CSharpUtil { + static String generateLiteral(final PrimitiveType type, final String value) + { + String literal = ""; + + final String castType = cSharpTypeName(type); + switch (type) + { + case CHAR: + case UINT8: + case INT8: + case INT16: + case UINT16: + literal = "(" + castType + ")" + value; + break; + + case INT32: + literal = value; + break; + + case UINT32: + literal = value + "U"; + break; + + case FLOAT: + if (value.endsWith("NaN")) + { + literal = "float.NaN"; + } + else + { + literal = value + "f"; + } + break; + + case UINT64: + literal = "0x" + Long.toHexString(Long.parseLong(value)) + "UL"; + break; + + case INT64: + literal = value + "L"; + break; + + case DOUBLE: + if (value.endsWith("NaN")) + { + literal = "double.NaN"; + } + else + { + literal = value + "d"; + } + break; + } + + return literal; + } + + static CharSequence generateFileHeader(final String packageName, final String... imports) + { + return String.format( + "// \n" + + "// Generated SBE (Simple Binary Encoding) message codec\n" + + "// \n\n" + + "#pragma warning disable 1591 // disable warning on missing comments\n" + + "using System;\n" + + "using System.Text;\n" + + "%1$s" + + "using Org.SbeTool.Sbe.Dll;\n\n" + + "namespace %2$s\n" + + "{\n", + String.join("", imports), + formatNamespace(packageName)); + } + + static String formatNamespace(final String packageName) + { + String[] tokens = packageName.split("\\."); + final StringBuilder sb = new StringBuilder(); + for (final String t : tokens) + { + sb.append(Generators.toUpperFirstChar(t)).append("."); + } + if (sb.length() > 0) + { + sb.setLength(sb.length() - 1); + } + + tokens = sb.toString().split("-"); + sb.setLength(0); + + for (final String t : tokens) + { + sb.append(Generators.toUpperFirstChar(t)); + } + + return sb.toString(); + } + + static String generateDocumentation(final String indent, final Token token) + { + final String description = token.description(); + if (null == description || description.isEmpty()) + { + return ""; + } + + return + indent + "/// \n" + + indent + "/// " + description + "\n" + + indent + "/// \n"; + } + enum Separators { BEGIN_GROUP('['), @@ -89,7 +203,7 @@ public String toString() * @param primitiveType to map. * @return the name of the Java primitive that most closely maps. */ - public static String cSharpTypeName(final PrimitiveType primitiveType) + static String cSharpTypeName(final PrimitiveType primitiveType) { return PRIMITIVE_TYPE_STRING_ENUM_MAP.get(primitiveType); } From 68af4f64b24367d89d635fbff9246fe5eecd7e67 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Thu, 5 Oct 2023 18:45:53 +0100 Subject: [PATCH 1128/1594] [Java] Start to introduce property based testing (PBT). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In this commit, I've: 1. Added a test dependency on JQwik. 2. Added a JQwik-based generator of arbitrary valid SBE message schemas. This generator exercises a lot of possibilities but not all. In particular, it is missing the generation of constants, min/max, and custom offsets. 3. Added a test that shows the parser parses any arbitrary SBE message schema. Why have I introduced PBT? My aim is to eventually test (an approximation of) the following property: ``` ∀ msgSchema ∈ PossibleMessageSchemas, ∀ bytes ∈ PossibleValidValues(msgSchema), DtoEncode(DtoDecode(bytes)) = bytes ``` I.e., that `DtoEncode` is the inverse of `DtoDecode` and that it preserves the information in an encoded message. --- .gitignore | 3 + build.gradle | 2 + .../sbe/properties/ParserPropertyTest.java | 48 ++ .../sbe/properties/SchemaDomain.java | 360 +++++++++++++++ .../sbe/properties/XmlSchemaWriter.java | 435 ++++++++++++++++++ 5 files changed, 848 insertions(+) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/SchemaDomain.java create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java diff --git a/.gitignore b/.gitignore index 6769c8db69..4ffe2537bc 100644 --- a/.gitignore +++ b/.gitignore @@ -119,4 +119,7 @@ rust/Cargo.lock .DS_Store /sbe-tool/src/main/golang/uk_co_real_logic_sbe_ir_generated/ +# JQwik +*.jqwik-database + /generated/ diff --git a/build.gradle b/build.gradle index 7dbd8d24fc..c71515f561 100644 --- a/build.gradle +++ b/build.gradle @@ -57,6 +57,7 @@ def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.10.2' +def jqwikVersion = '1.8.0' def jmhVersion = '1.37' def agronaVersion = '1.21.2' def agronaVersionRange = '[1.21.2,2.0[' // allow any release >= 1.21.2 and < 2.0.0 @@ -251,6 +252,7 @@ project(':sbe-tool') { testImplementation files('build/classes/java/generated') testImplementation "org.hamcrest:hamcrest:${hamcrestVersion}" testImplementation "org.mockito:mockito-core:${mockitoVersion}" + testImplementation "net.jqwik:jqwik:${jqwikVersion}" testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java new file mode 100644 index 0000000000..7abb2b65ca --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java @@ -0,0 +1,48 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties; + +import net.jqwik.api.Arbitrary; +import net.jqwik.api.ForAll; +import net.jqwik.api.Property; +import net.jqwik.api.Provide; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +public class ParserPropertyTest +{ + @Property + void shouldParseAnyValidSchema(@ForAll("schemas") final SchemaDomain.MessageSchema schema) throws Exception + { + final String xml = XmlSchemaWriter.writeString(schema); + try (InputStream in = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) + { + parse(in, ParserOptions.DEFAULT); + } + } + + @Provide + Arbitrary schemas() + { + return SchemaDomain.MessageSchema.arbitrary(); + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/SchemaDomain.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/SchemaDomain.java new file mode 100644 index 0000000000..1605d7d781 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/SchemaDomain.java @@ -0,0 +1,360 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties; + +import net.jqwik.api.Arbitraries; +import net.jqwik.api.Arbitrary; +import net.jqwik.api.Combinators; +import uk.co.real_logic.sbe.PrimitiveType; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public final class SchemaDomain +{ + private static final int MAX_COMPOSITE_DEPTH = 3; + private static final int MAX_GROUP_DEPTH = 3; + + private SchemaDomain() + { + } + + static final class EncodedDataTypeSchema implements TypeSchema + { + private final PrimitiveType primitiveType; + private final boolean isEmbedded; + + private EncodedDataTypeSchema( + final PrimitiveType primitiveType, + final boolean isEmbedded + ) + { + this.primitiveType = primitiveType; + this.isEmbedded = isEmbedded; + } + + public PrimitiveType primitiveType() + { + return primitiveType; + } + + @Override + public boolean isEmbedded() + { + return isEmbedded; + } + + @Override + public void accept(final TypeSchemaVisitor visitor) + { + visitor.onEncoded(this); + } + + static Arbitrary arbitrary() + { + return Combinators.combine( + Arbitraries.of(PrimitiveType.values()), + Arbitraries.of(true, false) + ).as(EncodedDataTypeSchema::new); + } + } + + static final class CompositeTypeSchema implements TypeSchema + { + private final List fields; + + private CompositeTypeSchema(final List fields) + { + this.fields = fields; + } + + public List fields() + { + return fields; + } + + static Arbitrary arbitrary(final int depth) + { + return TypeSchema.arbitrary(depth - 1) + .list() + .ofMinSize(1) + .ofMaxSize(3) + .injectDuplicates(0.2) + .map(CompositeTypeSchema::new); + } + + @Override + public void accept(final TypeSchemaVisitor visitor) + { + visitor.onComposite(this); + } + } + + static final class EnumTypeSchema implements TypeSchema + { + private final String encodingType; + private final List validValues; + + private EnumTypeSchema( + final String encodingType, + final List validValues) + { + this.encodingType = encodingType; + this.validValues = validValues; + } + + public String encodingType() + { + return encodingType; + } + + public List validValues() + { + return validValues; + } + + static Arbitrary arbitrary() + { + return Arbitraries.oneOf( + Arbitraries.chars().alpha() + .map(Character::toUpperCase) + .list() + .ofMaxSize(10) + .uniqueElements() + .map(values -> new EnumTypeSchema( + "char", + values.stream().map(String::valueOf).collect(Collectors.toList()) + )), + Arbitraries.integers() + .between(1, 254) + .list() + .ofMaxSize(254) + .uniqueElements() + .map(values -> new EnumTypeSchema( + "uint8", + values.stream().map(String::valueOf).collect(Collectors.toList()) + )) + ); + } + + @Override + public void accept(final TypeSchemaVisitor visitor) + { + visitor.onEnum(this); + } + } + + static final class SetSchema implements TypeSchema + { + private final String encodingType; + private final int choiceCount; + + private SetSchema( + final String encodingType, + final int choiceCount) + { + this.choiceCount = choiceCount; + this.encodingType = encodingType; + } + + public String encodingType() + { + return encodingType; + } + + public int choiceCount() + { + return choiceCount; + } + + @Override + public void accept(final TypeSchemaVisitor visitor) + { + visitor.onSet(this); + } + + static Arbitrary arbitrary() + { + return Combinators.combine( + Arbitraries.of( + "uint8", + "uint16", + "uint32", + "uint64" + ), + Arbitraries.integers().between(1, 4) + ).as(SetSchema::new); + } + } + + interface TypeSchema + { + static Arbitrary arbitrary(final int depth) + { + if (depth == 1) + { + return Arbitraries.oneOf( + EncodedDataTypeSchema.arbitrary(), + EnumTypeSchema.arbitrary(), + SetSchema.arbitrary() + ); + } + else + { + return Arbitraries.oneOf( + CompositeTypeSchema.arbitrary(depth), + EncodedDataTypeSchema.arbitrary(), + EnumTypeSchema.arbitrary(), + SetSchema.arbitrary() + ); + } + } + + default boolean isEmbedded() + { + return false; + } + + void accept(TypeSchemaVisitor visitor); + } + + interface TypeSchemaVisitor + { + void onEncoded(EncodedDataTypeSchema type); + + void onComposite(CompositeTypeSchema type); + + void onEnum(EnumTypeSchema type); + + void onSet(SetSchema type); + } + + static final class VarDataSchema + { + private final Encoding encoding; + + VarDataSchema(final Encoding encoding) + { + this.encoding = encoding; + } + + public Encoding encoding() + { + return encoding; + } + + static Arbitrary arbitrary() + { + return Arbitraries.of(Encoding.values()) + .map(VarDataSchema::new); + } + + enum Encoding + { + ASCII, + BYTES + } + } + + static final class GroupSchema + { + private final List blockFields; + private final List groups; + private final List varData; + + GroupSchema( + final List blockFields, + final List groups, + final List varData) + { + this.blockFields = blockFields; + this.groups = groups; + this.varData = varData; + } + + public List blockFields() + { + return blockFields; + } + + public List groups() + { + return groups; + } + + public List varData() + { + return varData; + } + + static Arbitrary arbitrary(final int depth) + { + final Arbitrary> subGroups = depth == 1 ? + Arbitraries.of(0).map(ignored -> new ArrayList<>()) : + arbitrary(depth - 1).list().ofMaxSize(3); + + return Combinators.combine( + TypeSchema.arbitrary(MAX_COMPOSITE_DEPTH).list().ofMaxSize(5), + subGroups, + VarDataSchema.arbitrary().list().ofMaxSize(3) + ).as(GroupSchema::new); + } + } + + static final class MessageSchema + { + private final List blockFields; + private final List groups; + private final List varData; + + MessageSchema( + final List blockFields, + final List groups, + final List varData + ) + { + this.blockFields = blockFields; + this.groups = groups; + this.varData = varData; + } + + public List blockFields() + { + return blockFields; + } + + public List groups() + { + return groups; + } + + public List varData() + { + return varData; + } + + static Arbitrary arbitrary() + { + return Combinators.combine( + TypeSchema.arbitrary(MAX_COMPOSITE_DEPTH).list().ofMaxSize(10), + GroupSchema.arbitrary(MAX_GROUP_DEPTH).list().ofMaxSize(3), + VarDataSchema.arbitrary().list().ofMaxSize(3) + ).as(MessageSchema::new); + } + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java new file mode 100644 index 0000000000..84ff1b2881 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java @@ -0,0 +1,435 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties; + +import org.agrona.collections.MutableInteger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.io.File; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import static java.util.Objects.requireNonNull; +import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; + +final class XmlSchemaWriter +{ + private XmlSchemaWriter() + { + } + + public static String writeString(final SchemaDomain.MessageSchema schema) + { + final StringWriter writer = new StringWriter(); + final StreamResult result = new StreamResult(writer); + writeTo(schema, result); + return writer.toString(); + } + + public static void writeFile( + final SchemaDomain.MessageSchema schema, + final File destination) + { + final StreamResult result = new StreamResult(destination); + writeTo(schema, result); + } + + private static void writeTo( + final SchemaDomain.MessageSchema schema, + final StreamResult destination) + { + try + { + final Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); + + final Element root = document.createElementNS("http://fixprotocol.io/2016/sbe", "sbe:messageSchema"); + root.setAttribute("id", "42"); + root.setAttribute("package", "uk.co.real_logic.sbe.properties"); + document.appendChild(root); + + final Element topLevelTypes = createTypesElement(document); + root.appendChild(topLevelTypes); + + final HashMap typeToName = new HashMap<>(); + + final TypeSchemaConverter typeSchemaConverter = new TypeSchemaConverter( + document, + topLevelTypes, + typeToName + ); + + appendTypes( + topLevelTypes, + typeSchemaConverter, + schema.blockFields(), + schema.groups()); + + final Element message = document.createElement("sbe:message"); + message.setAttribute("name", "TestMessage"); + message.setAttribute("id", "1"); + root.appendChild(message); + final MutableInteger nextMemberId = new MutableInteger(1); + appendMembers( + document, + typeToName, + schema.blockFields(), + schema.groups(), + schema.varData(), + nextMemberId, + message); + + try + { + final Transformer transformer = TransformerFactory.newInstance().newTransformer(); + + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + + final DOMSource source = new DOMSource(document); + + transformer.transform(source, destination); + } + catch (final Exception e) + { + throw new RuntimeException(e); + } + } + catch (final ParserConfigurationException e) + { + throw new RuntimeException(e); + } + } + + private static void appendMembers( + final Document document, + final HashMap typeToName, + final List blockFields, + final List groups, + final List varData, + final MutableInteger nextMemberId, + final Element parent) + { + for (final SchemaDomain.TypeSchema field : blockFields) + { + final int id = nextMemberId.getAndIncrement(); + + final boolean usePrimitiveName = field.isEmbedded() && field instanceof SchemaDomain.EncodedDataTypeSchema; + final String typeName = usePrimitiveName ? + ((SchemaDomain.EncodedDataTypeSchema)field).primitiveType().primitiveName() : + requireNonNull(typeToName.get(field)); + + final Element element = document.createElement("field"); + element.setAttribute("id", Integer.toString(id)); + element.setAttribute("name", "member" + id); + element.setAttribute("type", typeName); + parent.appendChild(element); + } + + for (final SchemaDomain.GroupSchema group : groups) + { + final int id = nextMemberId.getAndIncrement(); + + final Element element = document.createElement("group"); + element.setAttribute("id", Integer.toString(id)); + element.setAttribute("name", "member" + id); + appendMembers( + document, + typeToName, + group.blockFields(), + group.groups(), + group.varData(), + nextMemberId, + element); + parent.appendChild(element); + } + + for (final SchemaDomain.VarDataSchema data : varData) + { + final int id = nextMemberId.getAndIncrement(); + + final Element element = document.createElement("data"); + element.setAttribute("id", Integer.toString(id)); + element.setAttribute("name", "member" + id); + switch (data.encoding()) + { + case ASCII: + element.setAttribute("type", "varStringEncoding"); + break; + case BYTES: + element.setAttribute("type", "varDataEncoding"); + break; + default: + throw new IllegalStateException("Unknown encoding: " + data.encoding()); + } + parent.appendChild(element); + } + } + + private static Element createTypesElement(final Document document) + { + final Element types = document.createElement("types"); + + types.appendChild(createCompositeElement( + document, + "messageHeader", + createTypeElement(document, "blockLength", "uint16"), + createTypeElement(document, "templateId", "uint16"), + createTypeElement(document, "schemaId", "uint16"), + createTypeElement(document, "version", "uint16") + )); + + types.appendChild(createCompositeElement( + document, + "groupSizeEncoding", + createTypeElement(document, "blockLength", "uint16"), + createTypeElement(document, "numInGroup", "uint16") + )); + + final Element varString = createTypeElement(document, "varData", "uint8"); + varString.setAttribute("length", "0"); + varString.setAttribute("characterEncoding", "US-ASCII"); + types.appendChild(createCompositeElement( + document, + "varStringEncoding", + createTypeElement(document, "length", "uint16"), + varString + )); + + final Element varData = createTypeElement(document, "varData", "uint8"); + final Element varDataLength = createTypeElement(document, "length", "uint32"); + varDataLength.setAttribute("maxValue", "1000000"); + varData.setAttribute("length", "0"); + types.appendChild(createCompositeElement( + document, + "varDataEncoding", + varDataLength, + varData + )); + + return types; + } + + private static Element createSetElement( + final Document document, + final String name, + final String encodingType, + final int choiceCount) + { + final Element enumElement = document.createElement("set"); + enumElement.setAttribute("name", name); + enumElement.setAttribute("encodingType", encodingType); + + int caseId = 0; + for (int i = 0; i < choiceCount; i++) + { + final Element choice = document.createElement("choice"); + choice.setAttribute("name", "option" + caseId++); + choice.setTextContent(Integer.toString(i)); + enumElement.appendChild(choice); + } + + return enumElement; + } + + private static Element createEnumElement( + final Document document, + final String name, + final String encodingType, + final List validValues) + { + final Element enumElement = document.createElement("enum"); + enumElement.setAttribute("name", name); + enumElement.setAttribute("encodingType", encodingType); + + int caseId = 0; + for (final String value : validValues) + { + final Element validValue = document.createElement("validValue"); + validValue.setAttribute("name", "Case" + caseId++); + validValue.setTextContent(value); + enumElement.appendChild(validValue); + } + + return enumElement; + } + + private static Element createCompositeElement( + final Document document, + final String name, + final Element... types + ) + { + final Element composite = document.createElement("composite"); + composite.setAttribute("name", name); + + for (final Element type : types) + { + composite.appendChild(type); + } + + return composite; + } + + private static Element createTypeElement( + final Document document, + final String name, + final String primitiveType) + { + final Element blockLength = document.createElement("type"); + blockLength.setAttribute("name", name); + blockLength.setAttribute("primitiveType", primitiveType); + return blockLength; + } + + private static Element createRefElement( + final Document document, + final String name, + final String type) + { + final Element blockLength = document.createElement("ref"); + blockLength.setAttribute("name", name); + blockLength.setAttribute("type", type); + return blockLength; + } + + private static void appendTypes( + final Element topLevelTypes, + final TypeSchemaConverter typeSchemaConverter, + final List blockFields, + final List groups) + { + for (final SchemaDomain.TypeSchema field : blockFields) + { + if (!field.isEmbedded()) + { + topLevelTypes.appendChild(typeSchemaConverter.convert(field)); + } + } + + for (final SchemaDomain.GroupSchema group : groups) + { + appendTypes(topLevelTypes, typeSchemaConverter, group.blockFields(), group.groups()); + } + } + + private static final class TypeSchemaConverter implements SchemaDomain.TypeSchemaVisitor + { + private final Document document; + private final Element topLevelTypes; + private final Map typeToName; + private final Function nextName; + private Element result; + + private TypeSchemaConverter( + final Document document, + final Element topLevelTypes, + final Map typeToName) + { + this.document = document; + this.topLevelTypes = topLevelTypes; + this.typeToName = typeToName; + nextName = ignored -> "Type" + typeToName.size(); + } + + @Override + public void onEncoded(final SchemaDomain.EncodedDataTypeSchema type) + { + result = createTypeElement( + document, + typeToName.computeIfAbsent(type, nextName), + type.primitiveType().primitiveName() + ); + } + + @Override + public void onComposite(final SchemaDomain.CompositeTypeSchema type) + { + final Element[] parts = type.fields().stream() + .map(this::embedOrReference) + .toArray(Element[]::new); + result = createCompositeElement( + document, + typeToName.computeIfAbsent(type, nextName), + parts + ); + } + + @Override + public void onEnum(final SchemaDomain.EnumTypeSchema type) + { + result = createEnumElement( + document, + typeToName.computeIfAbsent(type, nextName), + type.encodingType(), + type.validValues() + ); + } + + @Override + public void onSet(final SchemaDomain.SetSchema type) + { + result = createSetElement( + document, + typeToName.computeIfAbsent(type, nextName), + type.encodingType(), + type.choiceCount() + ); + } + + private Element embedOrReference(final SchemaDomain.TypeSchema type) + { + if (type.isEmbedded()) + { + return convert(type); + } + else + { + final boolean hasWritten = typeToName.containsKey(type); + if (!hasWritten) + { + topLevelTypes.appendChild(convert(type)); + } + + final String typeName = requireNonNull(typeToName.get(type)); + return createRefElement( + document, + toLowerFirstChar(typeName), + typeName + ); + } + } + + public Element convert(final SchemaDomain.TypeSchema type) + { + result = null; + type.accept(this); + return requireNonNull(result); + } + } +} From 439ee4baada8d36f451e4d8c0c10b68df2308370 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Thu, 5 Oct 2023 19:08:49 +0100 Subject: [PATCH 1129/1594] [Java] Fix typos. --- .../src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index e7842ea47c..981bcaa8db 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -89,7 +89,7 @@ public EncodedDataType(final Node node, final String givenName, final String ref if (presence() != CONSTANT) { - handleError(node, "present must be constant when valueRef is set: " + valueRef); + handleError(node, "presence must be constant when valueRef is set: " + valueRef); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java index db25c1a291..9590c3e756 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java @@ -94,7 +94,7 @@ public Type( * @param presence of the type. * @param description of the type or null. * @param sinceVersion for the type - * @param deprecated version in which this wa.s deprecated. + * @param deprecated version in which this was deprecated. * @param semanticType of the type or null. */ public Type( From b94ef12eb404bd77b90f19a9b8028ec8f271d1b2 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Fri, 6 Oct 2023 00:43:37 +0100 Subject: [PATCH 1130/1594] [Java] Move property tests to their own source set. Gradle 8 complains about deprecations when using the "old style" test source set creation. Therefore, I have had to use `jvm-test-suites`, which is the Gradle 9 way of doing things. I have moved the property tests into their own source set and own test task: `propertyTest`, as they may be more expensive to run than the other unit tests. We may only wish to run them nightly in CI. I have also profiled the `propertyTest` task and removed usage of JQwik list item duplication, as it dominates the time taken during testing. The time taken is now dominated by compiling XPaths. --- build.gradle | 79 ++++++++++++++----- .../sbe/properties/ParserPropertyTest.java | 2 +- .../sbe/properties/SchemaDomain.java | 64 +++++++++++++-- .../sbe/properties/XmlSchemaWriter.java | 25 +++--- .../resources/junit-platform.properties | 3 + 5 files changed, 135 insertions(+), 38 deletions(-) rename sbe-tool/src/{test => propertyTest}/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java (97%) rename sbe-tool/src/{test => propertyTest}/java/uk/co/real_logic/sbe/properties/SchemaDomain.java (81%) rename sbe-tool/src/{test => propertyTest}/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java (95%) create mode 100644 sbe-tool/src/propertyTest/resources/junit-platform.properties diff --git a/build.gradle b/build.gradle index c71515f561..191c4c156a 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,7 @@ buildscript { plugins { id 'java-library' + id 'jvm-test-suite' id 'com.github.johnrengelman.shadow' version '8.1.1' apply false id 'com.github.ben-manes.versions' version '0.51.0' } @@ -165,6 +166,7 @@ jar.enabled = false subprojects { apply plugin: 'java-library' + apply plugin: 'jvm-test-suite' apply plugin: 'checkstyle' group = sbeGroup @@ -217,22 +219,34 @@ subprojects { } } - test { - useJUnitPlatform() + testing { + suites { + test { + useJUnitJupiter junitVersion - testLogging { - for (def level : LogLevel.values()) - { - def testLogging = get(level) - testLogging.exceptionFormat = 'full' - testLogging.events = ["FAILED", "STANDARD_OUT", "STANDARD_ERROR"] - } - } + targets { + all { + testTask.configure { + useJUnitPlatform() - javaLauncher.set(toolchainLauncher) + testLogging { + for (def level : LogLevel.values()) + { + def testLogging = get(level) + testLogging.exceptionFormat = 'full' + testLogging.events = ["FAILED", "STANDARD_OUT", "STANDARD_ERROR"] + } + } + + javaLauncher.set(toolchainLauncher) - systemProperty 'sbe.enable.ir.precedence.checks', 'true' - systemProperty 'sbe.enable.test.precedence.checks', 'true' + systemProperty 'sbe.enable.ir.precedence.checks', 'true' + systemProperty 'sbe.enable.test.precedence.checks', 'true' + } + } + } + } + } } } @@ -249,12 +263,6 @@ project(':sbe-tool') { prefer(agronaVersion) } } - testImplementation files('build/classes/java/generated') - testImplementation "org.hamcrest:hamcrest:${hamcrestVersion}" - testImplementation "org.mockito:mockito-core:${mockitoVersion}" - testImplementation "net.jqwik:jqwik:${jqwikVersion}" - testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" } def generatedDir = 'build/generated-src' @@ -276,6 +284,39 @@ project(':sbe-tool') { compileTestJava.dependsOn compileGeneratedJava + testing { + suites { + test { + dependencies { + implementation files('build/classes/java/generated') + implementation "org.hamcrest:hamcrest:${hamcrestVersion}" + implementation "org.mockito:mockito-core:${mockitoVersion}" + implementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" + } + } + + propertyTest(JvmTestSuite) { + useJUnitJupiter junitVersion + + dependencies { + implementation project() + implementation "net.jqwik:jqwik:${jqwikVersion}" + } + + targets { + all { + testTask.configure { + minHeapSize = '2g' + maxHeapSize = '2g' + + javaLauncher.set(toolchainLauncher) + } + } + } + } + } + } + tasks.register('generateTestCodecs', JavaExec) { dependsOn 'compileJava' mainClass.set('uk.co.real_logic.sbe.SbeTool') diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java similarity index 97% rename from sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java rename to sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java index 7abb2b65ca..5781777274 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java @@ -28,7 +28,7 @@ import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -public class ParserPropertyTest +class ParserPropertyTest { @Property void shouldParseAnyValidSchema(@ForAll("schemas") final SchemaDomain.MessageSchema schema) throws Exception diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/SchemaDomain.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/SchemaDomain.java similarity index 81% rename from sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/SchemaDomain.java rename to sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/SchemaDomain.java index 1605d7d781..ab2d58db15 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/SchemaDomain.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/SchemaDomain.java @@ -19,13 +19,14 @@ import net.jqwik.api.Arbitraries; import net.jqwik.api.Arbitrary; import net.jqwik.api.Combinators; +import net.jqwik.api.arbitraries.ListArbitrary; import uk.co.real_logic.sbe.PrimitiveType; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; -public final class SchemaDomain +final class SchemaDomain { private static final int MAX_COMPOSITE_DEPTH = 3; private static final int MAX_GROUP_DEPTH = 3; @@ -34,6 +35,57 @@ private SchemaDomain() { } + /** + * This combinator adds duplicates to an arbitrary list. We prefer this to JQwik's built-in functionality, + * as that is inefficient and dominates test runs. + *

      + * This method works by generating a list of integers, which represent, in an alternating manner, + * the number of items to skip before selecting an item to duplicate + * and the number of items to skip before inserting the duplicate. + * + * @param maxDuplicates the maximum number of duplicates to add + * @param arbitrary the arbitrary list to duplicate items in + * @param the type of the list + * @return an arbitrary list with duplicates + */ + private static Arbitrary> withDuplicates( + final int maxDuplicates, + final ListArbitrary arbitrary) + { + return Combinators.combine( + Arbitraries.integers().list().ofMaxSize(2 * maxDuplicates), + arbitrary + ).as((positions, originalItems) -> + { + if (originalItems.isEmpty()) + { + return originalItems; + } + + final List items = new ArrayList<>(originalItems); + T itemToDupe = null; + int j = 0; + + for (final int position : positions) + { + j += position; + j %= items.size(); + j = Math.abs(j); + if (itemToDupe == null) + { + itemToDupe = items.get(j); + } + else + { + items.add(j, itemToDupe); + itemToDupe = null; + } + } + + return items; + }); + } + static final class EncodedDataTypeSchema implements TypeSchema { private final PrimitiveType primitiveType; @@ -90,11 +142,7 @@ public List fields() static Arbitrary arbitrary(final int depth) { - return TypeSchema.arbitrary(depth - 1) - .list() - .ofMinSize(1) - .ofMaxSize(3) - .injectDuplicates(0.2) + return withDuplicates(2, TypeSchema.arbitrary(depth - 1).list().ofMinSize(1).ofMaxSize(3)) .map(CompositeTypeSchema::new); } @@ -309,7 +357,7 @@ static Arbitrary arbitrary(final int depth) arbitrary(depth - 1).list().ofMaxSize(3); return Combinators.combine( - TypeSchema.arbitrary(MAX_COMPOSITE_DEPTH).list().ofMaxSize(5), + withDuplicates(2, TypeSchema.arbitrary(MAX_COMPOSITE_DEPTH).list().ofMaxSize(5)), subGroups, VarDataSchema.arbitrary().list().ofMaxSize(3) ).as(GroupSchema::new); @@ -351,7 +399,7 @@ public List varData() static Arbitrary arbitrary() { return Combinators.combine( - TypeSchema.arbitrary(MAX_COMPOSITE_DEPTH).list().ofMaxSize(10), + withDuplicates(3, TypeSchema.arbitrary(MAX_COMPOSITE_DEPTH).list().ofMaxSize(10)), GroupSchema.arbitrary(MAX_GROUP_DEPTH).list().ofMaxSize(3), VarDataSchema.arbitrary().list().ofMaxSize(3) ).as(MessageSchema::new); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java similarity index 95% rename from sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java rename to sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java index 84ff1b2881..2572bb69ca 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java @@ -22,9 +22,7 @@ import java.io.File; import java.io.StringWriter; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.function.Function; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -35,7 +33,6 @@ import javax.xml.transform.stream.StreamResult; import static java.util.Objects.requireNonNull; -import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; final class XmlSchemaWriter { @@ -83,7 +80,9 @@ private static void writeTo( typeToName ); + final Set visitedTypes = new HashSet<>(); appendTypes( + visitedTypes, topLevelTypes, typeSchemaConverter, schema.blockFields(), @@ -93,7 +92,7 @@ private static void writeTo( message.setAttribute("name", "TestMessage"); message.setAttribute("id", "1"); root.appendChild(message); - final MutableInteger nextMemberId = new MutableInteger(1); + final MutableInteger nextMemberId = new MutableInteger(0); appendMembers( document, typeToName, @@ -319,6 +318,7 @@ private static Element createRefElement( } private static void appendTypes( + final Set visitedTypes, final Element topLevelTypes, final TypeSchemaConverter typeSchemaConverter, final List blockFields, @@ -326,7 +326,7 @@ private static void appendTypes( { for (final SchemaDomain.TypeSchema field : blockFields) { - if (!field.isEmbedded()) + if (!field.isEmbedded() && visitedTypes.add(field)) { topLevelTypes.appendChild(typeSchemaConverter.convert(field)); } @@ -334,7 +334,7 @@ private static void appendTypes( for (final SchemaDomain.GroupSchema group : groups) { - appendTypes(topLevelTypes, typeSchemaConverter, group.blockFields(), group.groups()); + appendTypes(visitedTypes, topLevelTypes, typeSchemaConverter, group.blockFields(), group.groups()); } } @@ -370,13 +370,18 @@ public void onEncoded(final SchemaDomain.EncodedDataTypeSchema type) @Override public void onComposite(final SchemaDomain.CompositeTypeSchema type) { - final Element[] parts = type.fields().stream() + final Element[] members = type.fields().stream() .map(this::embedOrReference) .toArray(Element[]::new); + for (int i = 0; i < members.length; i++) + { + final Element member = members[i]; + member.setAttribute("name", "member" + i + "Of" + member.getAttribute("name")); + } result = createCompositeElement( document, typeToName.computeIfAbsent(type, nextName), - parts + members ); } @@ -419,7 +424,7 @@ private Element embedOrReference(final SchemaDomain.TypeSchema type) final String typeName = requireNonNull(typeToName.get(type)); return createRefElement( document, - toLowerFirstChar(typeName), + typeName, typeName ); } diff --git a/sbe-tool/src/propertyTest/resources/junit-platform.properties b/sbe-tool/src/propertyTest/resources/junit-platform.properties new file mode 100644 index 0000000000..8a3fb086c1 --- /dev/null +++ b/sbe-tool/src/propertyTest/resources/junit-platform.properties @@ -0,0 +1,3 @@ +jqwik.edgecases.default=MIXIN +jqwik.tries.default=5000 +jqwik.failures.runfirst=true \ No newline at end of file From ea7e84bacb42a4de44087ec78bb359b628a40be2 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Fri, 6 Oct 2023 09:24:01 +0100 Subject: [PATCH 1131/1594] [Java] Suppress javadoc warnings in propertyTest source set. --- config/checkstyle/suppressions.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml index 84e7e82814..2823a9547e 100644 --- a/config/checkstyle/suppressions.xml +++ b/config/checkstyle/suppressions.xml @@ -6,5 +6,6 @@ + From 526eac24d96245e4d4ca64b21e3aa9e9368d248e Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Fri, 6 Oct 2023 09:24:32 +0100 Subject: [PATCH 1132/1594] [Java] Split apart schema generation files. I think separate files improves the readability of the arbitrary message schema generation. --- .../sbe/properties/ParserPropertyTest.java | 9 +- .../sbe/properties/SchemaDomain.java | 408 ------------------ .../arbitraries/SbeArbitraries.java | 189 ++++++++ .../schema/CompositeTypeSchema.java | 40 ++ .../schema/EncodedDataTypeSchema.java | 52 +++ .../sbe/properties/schema/EnumTypeSchema.java | 49 +++ .../sbe/properties/schema/GroupSchema.java | 52 +++ .../sbe/properties/schema/MessageSchema.java | 52 +++ .../sbe/properties/schema/SetSchema.java | 48 +++ .../sbe/properties/schema/TypeSchema.java | 27 ++ .../properties/schema/TypeSchemaVisitor.java | 28 ++ .../sbe/properties/schema/VarDataSchema.java | 38 ++ .../{ => schema}/XmlSchemaWriter.java | 62 +-- 13 files changed, 612 insertions(+), 442 deletions(-) delete mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/SchemaDomain.java create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java rename sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/{ => schema}/XmlSchemaWriter.java (86%) diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java index 5781777274..9f0517c5b8 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java @@ -20,6 +20,9 @@ import net.jqwik.api.ForAll; import net.jqwik.api.Property; import net.jqwik.api.Provide; +import uk.co.real_logic.sbe.properties.arbitraries.SbeArbitraries; +import uk.co.real_logic.sbe.properties.schema.MessageSchema; +import uk.co.real_logic.sbe.properties.schema.XmlSchemaWriter; import uk.co.real_logic.sbe.xml.ParserOptions; import java.io.ByteArrayInputStream; @@ -31,7 +34,7 @@ class ParserPropertyTest { @Property - void shouldParseAnyValidSchema(@ForAll("schemas") final SchemaDomain.MessageSchema schema) throws Exception + void shouldParseAnyValidSchema(@ForAll("schemas") final MessageSchema schema) throws Exception { final String xml = XmlSchemaWriter.writeString(schema); try (InputStream in = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) @@ -41,8 +44,8 @@ void shouldParseAnyValidSchema(@ForAll("schemas") final SchemaDomain.MessageSche } @Provide - Arbitrary schemas() + Arbitrary schemas() { - return SchemaDomain.MessageSchema.arbitrary(); + return SbeArbitraries.message(); } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/SchemaDomain.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/SchemaDomain.java deleted file mode 100644 index ab2d58db15..0000000000 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/SchemaDomain.java +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright 2013-2023 Real Logic Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package uk.co.real_logic.sbe.properties; - -import net.jqwik.api.Arbitraries; -import net.jqwik.api.Arbitrary; -import net.jqwik.api.Combinators; -import net.jqwik.api.arbitraries.ListArbitrary; -import uk.co.real_logic.sbe.PrimitiveType; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -final class SchemaDomain -{ - private static final int MAX_COMPOSITE_DEPTH = 3; - private static final int MAX_GROUP_DEPTH = 3; - - private SchemaDomain() - { - } - - /** - * This combinator adds duplicates to an arbitrary list. We prefer this to JQwik's built-in functionality, - * as that is inefficient and dominates test runs. - *

      - * This method works by generating a list of integers, which represent, in an alternating manner, - * the number of items to skip before selecting an item to duplicate - * and the number of items to skip before inserting the duplicate. - * - * @param maxDuplicates the maximum number of duplicates to add - * @param arbitrary the arbitrary list to duplicate items in - * @param the type of the list - * @return an arbitrary list with duplicates - */ - private static Arbitrary> withDuplicates( - final int maxDuplicates, - final ListArbitrary arbitrary) - { - return Combinators.combine( - Arbitraries.integers().list().ofMaxSize(2 * maxDuplicates), - arbitrary - ).as((positions, originalItems) -> - { - if (originalItems.isEmpty()) - { - return originalItems; - } - - final List items = new ArrayList<>(originalItems); - T itemToDupe = null; - int j = 0; - - for (final int position : positions) - { - j += position; - j %= items.size(); - j = Math.abs(j); - if (itemToDupe == null) - { - itemToDupe = items.get(j); - } - else - { - items.add(j, itemToDupe); - itemToDupe = null; - } - } - - return items; - }); - } - - static final class EncodedDataTypeSchema implements TypeSchema - { - private final PrimitiveType primitiveType; - private final boolean isEmbedded; - - private EncodedDataTypeSchema( - final PrimitiveType primitiveType, - final boolean isEmbedded - ) - { - this.primitiveType = primitiveType; - this.isEmbedded = isEmbedded; - } - - public PrimitiveType primitiveType() - { - return primitiveType; - } - - @Override - public boolean isEmbedded() - { - return isEmbedded; - } - - @Override - public void accept(final TypeSchemaVisitor visitor) - { - visitor.onEncoded(this); - } - - static Arbitrary arbitrary() - { - return Combinators.combine( - Arbitraries.of(PrimitiveType.values()), - Arbitraries.of(true, false) - ).as(EncodedDataTypeSchema::new); - } - } - - static final class CompositeTypeSchema implements TypeSchema - { - private final List fields; - - private CompositeTypeSchema(final List fields) - { - this.fields = fields; - } - - public List fields() - { - return fields; - } - - static Arbitrary arbitrary(final int depth) - { - return withDuplicates(2, TypeSchema.arbitrary(depth - 1).list().ofMinSize(1).ofMaxSize(3)) - .map(CompositeTypeSchema::new); - } - - @Override - public void accept(final TypeSchemaVisitor visitor) - { - visitor.onComposite(this); - } - } - - static final class EnumTypeSchema implements TypeSchema - { - private final String encodingType; - private final List validValues; - - private EnumTypeSchema( - final String encodingType, - final List validValues) - { - this.encodingType = encodingType; - this.validValues = validValues; - } - - public String encodingType() - { - return encodingType; - } - - public List validValues() - { - return validValues; - } - - static Arbitrary arbitrary() - { - return Arbitraries.oneOf( - Arbitraries.chars().alpha() - .map(Character::toUpperCase) - .list() - .ofMaxSize(10) - .uniqueElements() - .map(values -> new EnumTypeSchema( - "char", - values.stream().map(String::valueOf).collect(Collectors.toList()) - )), - Arbitraries.integers() - .between(1, 254) - .list() - .ofMaxSize(254) - .uniqueElements() - .map(values -> new EnumTypeSchema( - "uint8", - values.stream().map(String::valueOf).collect(Collectors.toList()) - )) - ); - } - - @Override - public void accept(final TypeSchemaVisitor visitor) - { - visitor.onEnum(this); - } - } - - static final class SetSchema implements TypeSchema - { - private final String encodingType; - private final int choiceCount; - - private SetSchema( - final String encodingType, - final int choiceCount) - { - this.choiceCount = choiceCount; - this.encodingType = encodingType; - } - - public String encodingType() - { - return encodingType; - } - - public int choiceCount() - { - return choiceCount; - } - - @Override - public void accept(final TypeSchemaVisitor visitor) - { - visitor.onSet(this); - } - - static Arbitrary arbitrary() - { - return Combinators.combine( - Arbitraries.of( - "uint8", - "uint16", - "uint32", - "uint64" - ), - Arbitraries.integers().between(1, 4) - ).as(SetSchema::new); - } - } - - interface TypeSchema - { - static Arbitrary arbitrary(final int depth) - { - if (depth == 1) - { - return Arbitraries.oneOf( - EncodedDataTypeSchema.arbitrary(), - EnumTypeSchema.arbitrary(), - SetSchema.arbitrary() - ); - } - else - { - return Arbitraries.oneOf( - CompositeTypeSchema.arbitrary(depth), - EncodedDataTypeSchema.arbitrary(), - EnumTypeSchema.arbitrary(), - SetSchema.arbitrary() - ); - } - } - - default boolean isEmbedded() - { - return false; - } - - void accept(TypeSchemaVisitor visitor); - } - - interface TypeSchemaVisitor - { - void onEncoded(EncodedDataTypeSchema type); - - void onComposite(CompositeTypeSchema type); - - void onEnum(EnumTypeSchema type); - - void onSet(SetSchema type); - } - - static final class VarDataSchema - { - private final Encoding encoding; - - VarDataSchema(final Encoding encoding) - { - this.encoding = encoding; - } - - public Encoding encoding() - { - return encoding; - } - - static Arbitrary arbitrary() - { - return Arbitraries.of(Encoding.values()) - .map(VarDataSchema::new); - } - - enum Encoding - { - ASCII, - BYTES - } - } - - static final class GroupSchema - { - private final List blockFields; - private final List groups; - private final List varData; - - GroupSchema( - final List blockFields, - final List groups, - final List varData) - { - this.blockFields = blockFields; - this.groups = groups; - this.varData = varData; - } - - public List blockFields() - { - return blockFields; - } - - public List groups() - { - return groups; - } - - public List varData() - { - return varData; - } - - static Arbitrary arbitrary(final int depth) - { - final Arbitrary> subGroups = depth == 1 ? - Arbitraries.of(0).map(ignored -> new ArrayList<>()) : - arbitrary(depth - 1).list().ofMaxSize(3); - - return Combinators.combine( - withDuplicates(2, TypeSchema.arbitrary(MAX_COMPOSITE_DEPTH).list().ofMaxSize(5)), - subGroups, - VarDataSchema.arbitrary().list().ofMaxSize(3) - ).as(GroupSchema::new); - } - } - - static final class MessageSchema - { - private final List blockFields; - private final List groups; - private final List varData; - - MessageSchema( - final List blockFields, - final List groups, - final List varData - ) - { - this.blockFields = blockFields; - this.groups = groups; - this.varData = varData; - } - - public List blockFields() - { - return blockFields; - } - - public List groups() - { - return groups; - } - - public List varData() - { - return varData; - } - - static Arbitrary arbitrary() - { - return Combinators.combine( - withDuplicates(3, TypeSchema.arbitrary(MAX_COMPOSITE_DEPTH).list().ofMaxSize(10)), - GroupSchema.arbitrary(MAX_GROUP_DEPTH).list().ofMaxSize(3), - VarDataSchema.arbitrary().list().ofMaxSize(3) - ).as(MessageSchema::new); - } - } -} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java new file mode 100644 index 0000000000..a892a27a57 --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -0,0 +1,189 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties.arbitraries; + +import net.jqwik.api.Arbitraries; +import net.jqwik.api.Arbitrary; +import net.jqwik.api.Combinators; +import net.jqwik.api.arbitraries.ListArbitrary; +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.properties.schema.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public final class SbeArbitraries +{ + private static final int MAX_COMPOSITE_DEPTH = 3; + private static final int MAX_GROUP_DEPTH = 3; + + private SbeArbitraries() + { + } + + /** + * This combinator adds duplicates to an arbitrary list. We prefer this to JQwik's built-in functionality, + * as that is inefficient and dominates test runs. + *

      + * This method works by generating a list of integers, which represent, in an alternating manner, + * the number of items to skip before selecting an item to duplicate + * and the number of items to skip before inserting the duplicate. + * + * @param maxDuplicates the maximum number of duplicates to add + * @param arbitrary the arbitrary list to duplicate items in + * @param the type of the list + * @return an arbitrary list with duplicates + */ + private static Arbitrary> withDuplicates( + final int maxDuplicates, + final ListArbitrary arbitrary) + { + return Combinators.combine( + Arbitraries.integers().list().ofMaxSize(2 * maxDuplicates), + arbitrary + ).as((positions, originalItems) -> + { + if (originalItems.isEmpty()) + { + return originalItems; + } + + final List items = new ArrayList<>(originalItems); + T itemToDupe = null; + int j = 0; + + for (final int position : positions) + { + j += position; + j %= items.size(); + j = Math.abs(j); + if (itemToDupe == null) + { + itemToDupe = items.get(j); + } + else + { + items.add(j, itemToDupe); + itemToDupe = null; + } + } + + return items; + }); + } + + private static Arbitrary encodedDataType() + { + return Combinators.combine( + Arbitraries.of(PrimitiveType.values()), + Arbitraries.of(true, false) + ).as(EncodedDataTypeSchema::new); + } + + private static Arbitrary enumType() + { + return Arbitraries.oneOf( + Arbitraries.chars().alpha() + .map(Character::toUpperCase) + .list() + .ofMaxSize(10) + .uniqueElements() + .map(values -> new EnumTypeSchema( + "char", + values.stream().map(String::valueOf).collect(Collectors.toList()) + )), + Arbitraries.integers() + .between(1, 254) + .list() + .ofMaxSize(254) + .uniqueElements() + .map(values -> new EnumTypeSchema( + "uint8", + values.stream().map(String::valueOf).collect(Collectors.toList()) + )) + ); + } + + private static Arbitrary setType() + { + return Combinators.combine( + Arbitraries.of( + "uint8", + "uint16", + "uint32", + "uint64" + ), + Arbitraries.integers().between(1, 4) + ).as(SetSchema::new); + } + + private static Arbitrary compositeType(final int depth) + { + return withDuplicates(2, type(depth - 1).list().ofMinSize(1).ofMaxSize(3)) + .map(CompositeTypeSchema::new); + } + + private static Arbitrary type(final int depth) + { + if (depth == 1) + { + return Arbitraries.oneOf( + encodedDataType(), + enumType(), + setType() + ); + } + else + { + return Arbitraries.oneOf( + compositeType(depth), + encodedDataType(), + enumType(), + setType() + ); + } + } + + private static Arbitrary group(final int depth) + { + final Arbitrary> subGroups = depth == 1 ? + Arbitraries.of(0).map(ignored -> new ArrayList<>()) : + group(depth - 1).list().ofMaxSize(3); + + return Combinators.combine( + withDuplicates(2, type(MAX_COMPOSITE_DEPTH).list().ofMaxSize(5)), + subGroups, + varData().list().ofMaxSize(3) + ).as(GroupSchema::new); + } + + private static Arbitrary varData() + { + return Arbitraries.of(VarDataSchema.Encoding.values()) + .map(VarDataSchema::new); + } + + public static Arbitrary message() + { + return Combinators.combine( + withDuplicates(3, type(MAX_COMPOSITE_DEPTH).list().ofMaxSize(10)), + group(MAX_GROUP_DEPTH).list().ofMaxSize(3), + varData().list().ofMaxSize(3) + ).as(MessageSchema::new); + } +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java new file mode 100644 index 0000000000..a6df53d778 --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties.schema; + +import java.util.List; + +public final class CompositeTypeSchema implements TypeSchema +{ + private final List fields; + + public CompositeTypeSchema(final List fields) + { + this.fields = fields; + } + + public List fields() + { + return fields; + } + + @Override + public void accept(final TypeSchemaVisitor visitor) + { + visitor.onComposite(this); + } +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java new file mode 100644 index 0000000000..b5fe76941d --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties.schema; + +import uk.co.real_logic.sbe.PrimitiveType; + +public final class EncodedDataTypeSchema implements TypeSchema +{ + private final PrimitiveType primitiveType; + private final boolean isEmbedded; + + public EncodedDataTypeSchema( + final PrimitiveType primitiveType, + final boolean isEmbedded + ) + { + this.primitiveType = primitiveType; + this.isEmbedded = isEmbedded; + } + + public PrimitiveType primitiveType() + { + return primitiveType; + } + + @Override + public boolean isEmbedded() + { + return isEmbedded; + } + + @Override + public void accept(final TypeSchemaVisitor visitor) + { + visitor.onEncoded(this); + } + +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java new file mode 100644 index 0000000000..fa669fe04a --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties.schema; + +import java.util.List; + +public final class EnumTypeSchema implements TypeSchema +{ + private final String encodingType; + private final List validValues; + + public EnumTypeSchema( + final String encodingType, + final List validValues) + { + this.encodingType = encodingType; + this.validValues = validValues; + } + + public String encodingType() + { + return encodingType; + } + + public List validValues() + { + return validValues; + } + + @Override + public void accept(final TypeSchemaVisitor visitor) + { + visitor.onEnum(this); + } +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java new file mode 100644 index 0000000000..df34e0a9b6 --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties.schema; + +import java.util.List; + +public final class GroupSchema +{ + private final List blockFields; + private final List groups; + private final List varData; + + public GroupSchema( + final List blockFields, + final List groups, + final List varData) + { + this.blockFields = blockFields; + this.groups = groups; + this.varData = varData; + } + + public List blockFields() + { + return blockFields; + } + + public List groups() + { + return groups; + } + + public List varData() + { + return varData; + } + +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java new file mode 100644 index 0000000000..c275defe3d --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties.schema; + +import java.util.List; + +public final class MessageSchema +{ + private final List blockFields; + private final List groups; + private final List varData; + + public MessageSchema( + final List blockFields, + final List groups, + final List varData + ) + { + this.blockFields = blockFields; + this.groups = groups; + this.varData = varData; + } + + public List blockFields() + { + return blockFields; + } + + public List groups() + { + return groups; + } + + public List varData() + { + return varData; + } +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java new file mode 100644 index 0000000000..95874e8381 --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java @@ -0,0 +1,48 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties.schema; + +public final class SetSchema implements TypeSchema +{ + private final String encodingType; + private final int choiceCount; + + public SetSchema( + final String encodingType, + final int choiceCount) + { + this.choiceCount = choiceCount; + this.encodingType = encodingType; + } + + public String encodingType() + { + return encodingType; + } + + public int choiceCount() + { + return choiceCount; + } + + @Override + public void accept(final TypeSchemaVisitor visitor) + { + visitor.onSet(this); + } + +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java new file mode 100644 index 0000000000..311521e697 --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties.schema; + +public interface TypeSchema +{ + default boolean isEmbedded() + { + return false; + } + + void accept(TypeSchemaVisitor visitor); +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java new file mode 100644 index 0000000000..830a2e1cf7 --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties.schema; + +public interface TypeSchemaVisitor +{ + void onEncoded(EncodedDataTypeSchema type); + + void onComposite(CompositeTypeSchema type); + + void onEnum(EnumTypeSchema type); + + void onSet(SetSchema type); +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java new file mode 100644 index 0000000000..c6b39db56b --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties.schema; + +public final class VarDataSchema +{ + private final Encoding encoding; + + public VarDataSchema(final Encoding encoding) + { + this.encoding = encoding; + } + + public Encoding encoding() + { + return encoding; + } + + public enum Encoding + { + ASCII, + BYTES + } +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/XmlSchemaWriter.java similarity index 86% rename from sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java rename to sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/XmlSchemaWriter.java index 2572bb69ca..63a10903ca 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/XmlSchemaWriter.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/XmlSchemaWriter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package uk.co.real_logic.sbe.properties; +package uk.co.real_logic.sbe.properties.schema; import org.agrona.collections.MutableInteger; import org.w3c.dom.Document; @@ -34,13 +34,13 @@ import static java.util.Objects.requireNonNull; -final class XmlSchemaWriter +public final class XmlSchemaWriter { private XmlSchemaWriter() { } - public static String writeString(final SchemaDomain.MessageSchema schema) + public static String writeString(final MessageSchema schema) { final StringWriter writer = new StringWriter(); final StreamResult result = new StreamResult(writer); @@ -49,7 +49,7 @@ public static String writeString(final SchemaDomain.MessageSchema schema) } public static void writeFile( - final SchemaDomain.MessageSchema schema, + final MessageSchema schema, final File destination) { final StreamResult result = new StreamResult(destination); @@ -57,7 +57,7 @@ public static void writeFile( } private static void writeTo( - final SchemaDomain.MessageSchema schema, + final MessageSchema schema, final StreamResult destination) { try @@ -72,7 +72,7 @@ private static void writeTo( final Element topLevelTypes = createTypesElement(document); root.appendChild(topLevelTypes); - final HashMap typeToName = new HashMap<>(); + final HashMap typeToName = new HashMap<>(); final TypeSchemaConverter typeSchemaConverter = new TypeSchemaConverter( document, @@ -80,7 +80,7 @@ private static void writeTo( typeToName ); - final Set visitedTypes = new HashSet<>(); + final Set visitedTypes = new HashSet<>(); appendTypes( visitedTypes, topLevelTypes, @@ -127,20 +127,20 @@ private static void writeTo( private static void appendMembers( final Document document, - final HashMap typeToName, - final List blockFields, - final List groups, - final List varData, + final HashMap typeToName, + final List blockFields, + final List groups, + final List varData, final MutableInteger nextMemberId, final Element parent) { - for (final SchemaDomain.TypeSchema field : blockFields) + for (final TypeSchema field : blockFields) { final int id = nextMemberId.getAndIncrement(); - final boolean usePrimitiveName = field.isEmbedded() && field instanceof SchemaDomain.EncodedDataTypeSchema; + final boolean usePrimitiveName = field.isEmbedded() && field instanceof EncodedDataTypeSchema; final String typeName = usePrimitiveName ? - ((SchemaDomain.EncodedDataTypeSchema)field).primitiveType().primitiveName() : + ((EncodedDataTypeSchema)field).primitiveType().primitiveName() : requireNonNull(typeToName.get(field)); final Element element = document.createElement("field"); @@ -150,7 +150,7 @@ private static void appendMembers( parent.appendChild(element); } - for (final SchemaDomain.GroupSchema group : groups) + for (final GroupSchema group : groups) { final int id = nextMemberId.getAndIncrement(); @@ -168,7 +168,7 @@ private static void appendMembers( parent.appendChild(element); } - for (final SchemaDomain.VarDataSchema data : varData) + for (final VarDataSchema data : varData) { final int id = nextMemberId.getAndIncrement(); @@ -318,13 +318,13 @@ private static Element createRefElement( } private static void appendTypes( - final Set visitedTypes, + final Set visitedTypes, final Element topLevelTypes, final TypeSchemaConverter typeSchemaConverter, - final List blockFields, - final List groups) + final List blockFields, + final List groups) { - for (final SchemaDomain.TypeSchema field : blockFields) + for (final TypeSchema field : blockFields) { if (!field.isEmbedded() && visitedTypes.add(field)) { @@ -332,24 +332,24 @@ private static void appendTypes( } } - for (final SchemaDomain.GroupSchema group : groups) + for (final GroupSchema group : groups) { appendTypes(visitedTypes, topLevelTypes, typeSchemaConverter, group.blockFields(), group.groups()); } } - private static final class TypeSchemaConverter implements SchemaDomain.TypeSchemaVisitor + private static final class TypeSchemaConverter implements TypeSchemaVisitor { private final Document document; private final Element topLevelTypes; - private final Map typeToName; - private final Function nextName; + private final Map typeToName; + private final Function nextName; private Element result; private TypeSchemaConverter( final Document document, final Element topLevelTypes, - final Map typeToName) + final Map typeToName) { this.document = document; this.topLevelTypes = topLevelTypes; @@ -358,7 +358,7 @@ private TypeSchemaConverter( } @Override - public void onEncoded(final SchemaDomain.EncodedDataTypeSchema type) + public void onEncoded(final EncodedDataTypeSchema type) { result = createTypeElement( document, @@ -368,7 +368,7 @@ public void onEncoded(final SchemaDomain.EncodedDataTypeSchema type) } @Override - public void onComposite(final SchemaDomain.CompositeTypeSchema type) + public void onComposite(final CompositeTypeSchema type) { final Element[] members = type.fields().stream() .map(this::embedOrReference) @@ -386,7 +386,7 @@ public void onComposite(final SchemaDomain.CompositeTypeSchema type) } @Override - public void onEnum(final SchemaDomain.EnumTypeSchema type) + public void onEnum(final EnumTypeSchema type) { result = createEnumElement( document, @@ -397,7 +397,7 @@ public void onEnum(final SchemaDomain.EnumTypeSchema type) } @Override - public void onSet(final SchemaDomain.SetSchema type) + public void onSet(final SetSchema type) { result = createSetElement( document, @@ -407,7 +407,7 @@ public void onSet(final SchemaDomain.SetSchema type) ); } - private Element embedOrReference(final SchemaDomain.TypeSchema type) + private Element embedOrReference(final TypeSchema type) { if (type.isEmbedded()) { @@ -430,7 +430,7 @@ private Element embedOrReference(final SchemaDomain.TypeSchema type) } } - public Element convert(final SchemaDomain.TypeSchema type) + public Element convert(final TypeSchema type) { result = null; type.accept(this); From 0a2a6e43e0cdfbc60f47ff9c078cfe74148dbd2d Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Sat, 7 Oct 2023 00:06:46 +0100 Subject: [PATCH 1133/1594] [Java] Extend PBT to generate arbitrary encoded messages. In this commit, I've also demonstrated the usage of arbitrary encoded messages in a JsonPrinter test. In the test, I print an arbitrary value of an arbitrary schema and check that it is valid JSON. The test passes as long as we constrain the generation of strings, as JsonPrinter currently does not do any escaping. I also noted that it uses `'` rather than `"`, which AFAICS is not permitted by the JSON specification, but is permitted by our (less strict) JSON testing tool. --- build.gradle | 2 + .../sbe/properties/JsonPropertyTest.java | 56 ++ .../sbe/properties/ParserPropertyTest.java | 6 +- .../arbitraries/SbeArbitraries.java | 622 +++++++++++++++++- .../sbe/properties/schema/MessageSchema.java | 10 + ...maWriter.java => TestXmlSchemaWriter.java} | 8 +- .../resources/junit-platform.properties | 5 +- 7 files changed, 678 insertions(+), 31 deletions(-) create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java rename sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/{XmlSchemaWriter.java => TestXmlSchemaWriter.java} (98%) diff --git a/build.gradle b/build.gradle index 191c4c156a..2ccfad6010 100644 --- a/build.gradle +++ b/build.gradle @@ -59,6 +59,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.10.2' def jqwikVersion = '1.8.0' +def jsonVersion = '20230618' def jmhVersion = '1.37' def agronaVersion = '1.21.2' def agronaVersionRange = '[1.21.2,2.0[' // allow any release >= 1.21.2 and < 2.0.0 @@ -301,6 +302,7 @@ project(':sbe-tool') { dependencies { implementation project() implementation "net.jqwik:jqwik:${jqwikVersion}" + implementation "org.json:json:${jsonVersion}" } targets { diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java new file mode 100644 index 0000000000..ab5c8d955e --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties; + +import net.jqwik.api.Arbitrary; +import net.jqwik.api.ForAll; +import net.jqwik.api.Property; +import net.jqwik.api.Provide; +import uk.co.real_logic.sbe.json.JsonPrinter; +import uk.co.real_logic.sbe.properties.arbitraries.SbeArbitraries; +import org.agrona.concurrent.UnsafeBuffer; +import org.json.JSONException; +import org.json.JSONObject; + +public class JsonPropertyTest +{ + @Property + void shouldGenerateValidJson( + @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage + ) + { + final StringBuilder output = new StringBuilder(); + final JsonPrinter printer = new JsonPrinter(encodedMessage.ir()); + printer.print(output, new UnsafeBuffer(encodedMessage.buffer()), 0); + try + { + new JSONObject(output.toString()); + } + catch (final JSONException e) + { + throw new AssertionError("Invalid JSON: " + output + "\n\nSchema:\n" + encodedMessage.schema(), e); + } + } + + @Provide + Arbitrary encodedMessage() + { + final SbeArbitraries.CharGenerationMode mode = + SbeArbitraries.CharGenerationMode.JSON_PRINTER_COMPATIBLE; + return SbeArbitraries.encodedMessage(mode); + } +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java index 9f0517c5b8..b6ce84ef3a 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java @@ -22,7 +22,7 @@ import net.jqwik.api.Provide; import uk.co.real_logic.sbe.properties.arbitraries.SbeArbitraries; import uk.co.real_logic.sbe.properties.schema.MessageSchema; -import uk.co.real_logic.sbe.properties.schema.XmlSchemaWriter; +import uk.co.real_logic.sbe.properties.schema.TestXmlSchemaWriter; import uk.co.real_logic.sbe.xml.ParserOptions; import java.io.ByteArrayInputStream; @@ -36,7 +36,7 @@ class ParserPropertyTest @Property void shouldParseAnyValidSchema(@ForAll("schemas") final MessageSchema schema) throws Exception { - final String xml = XmlSchemaWriter.writeString(schema); + final String xml = TestXmlSchemaWriter.writeString(schema); try (InputStream in = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) { parse(in, ParserOptions.DEFAULT); @@ -46,6 +46,6 @@ void shouldParseAnyValidSchema(@ForAll("schemas") final MessageSchema schema) th @Provide Arbitrary schemas() { - return SbeArbitraries.message(); + return SbeArbitraries.messageSchema(); } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index a892a27a57..eb6ef0603f 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -19,18 +19,38 @@ import net.jqwik.api.Arbitraries; import net.jqwik.api.Arbitrary; import net.jqwik.api.Combinators; +import net.jqwik.api.arbitraries.CharacterArbitrary; import net.jqwik.api.arbitraries.ListArbitrary; import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.PrimitiveValue; +import uk.co.real_logic.sbe.ir.Encoding; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.ir.Token; import uk.co.real_logic.sbe.properties.schema.*; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.ParserOptions; +import org.agrona.BitUtil; +import org.agrona.ExpandableArrayBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.collections.MutableInteger; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.stream.Collectors; +import static uk.co.real_logic.sbe.ir.Signal.*; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +@SuppressWarnings("EnhancedSwitchMigration") public final class SbeArbitraries { private static final int MAX_COMPOSITE_DEPTH = 3; private static final int MAX_GROUP_DEPTH = 3; + public static final int NULL_VALUE = Integer.MIN_VALUE; private SbeArbitraries() { @@ -87,7 +107,7 @@ private static Arbitrary> withDuplicates( }); } - private static Arbitrary encodedDataType() + private static Arbitrary encodedDataTypeSchema() { return Combinators.combine( Arbitraries.of(PrimitiveType.values()), @@ -95,7 +115,13 @@ private static Arbitrary encodedDataType() ).as(EncodedDataTypeSchema::new); } - private static Arbitrary enumType() + public enum CharGenerationMode + { + UNRESTRICTED, + JSON_PRINTER_COMPATIBLE + } + + private static Arbitrary enumTypeSchema() { return Arbitraries.oneOf( Arbitraries.chars().alpha() @@ -119,7 +145,7 @@ private static Arbitrary enumType() ); } - private static Arbitrary setType() + private static Arbitrary setTypeSchema() { return Combinators.combine( Arbitraries.of( @@ -132,58 +158,610 @@ private static Arbitrary setType() ).as(SetSchema::new); } - private static Arbitrary compositeType(final int depth) + private static Arbitrary compositeTypeSchema(final int depth) { - return withDuplicates(2, type(depth - 1).list().ofMinSize(1).ofMaxSize(3)) + return withDuplicates(2, typeSchema(depth - 1).list().ofMinSize(1).ofMaxSize(3)) .map(CompositeTypeSchema::new); } - private static Arbitrary type(final int depth) + private static Arbitrary typeSchema(final int depth) { if (depth == 1) { return Arbitraries.oneOf( - encodedDataType(), - enumType(), - setType() + encodedDataTypeSchema(), + enumTypeSchema(), + setTypeSchema() ); } else { return Arbitraries.oneOf( - compositeType(depth), - encodedDataType(), - enumType(), - setType() + compositeTypeSchema(depth), + encodedDataTypeSchema(), + enumTypeSchema(), + setTypeSchema() ); } } - private static Arbitrary group(final int depth) + private static Arbitrary groupSchema(final int depth) { final Arbitrary> subGroups = depth == 1 ? Arbitraries.of(0).map(ignored -> new ArrayList<>()) : - group(depth - 1).list().ofMaxSize(3); + groupSchema(depth - 1).list().ofMaxSize(3); return Combinators.combine( - withDuplicates(2, type(MAX_COMPOSITE_DEPTH).list().ofMaxSize(5)), + withDuplicates(2, typeSchema(MAX_COMPOSITE_DEPTH).list().ofMaxSize(5)), subGroups, - varData().list().ofMaxSize(3) + varDataSchema().list().ofMaxSize(3) ).as(GroupSchema::new); } - private static Arbitrary varData() + private static Arbitrary varDataSchema() { return Arbitraries.of(VarDataSchema.Encoding.values()) .map(VarDataSchema::new); } - public static Arbitrary message() + public static Arbitrary messageSchema() { return Combinators.combine( - withDuplicates(3, type(MAX_COMPOSITE_DEPTH).list().ofMaxSize(10)), - group(MAX_GROUP_DEPTH).list().ofMaxSize(3), - varData().list().ofMaxSize(3) + withDuplicates(3, typeSchema(MAX_COMPOSITE_DEPTH).list().ofMaxSize(10)), + groupSchema(MAX_GROUP_DEPTH).list().ofMaxSize(3), + varDataSchema().list().ofMaxSize(3) ).as(MessageSchema::new); } + + public interface Encoder + { + void encode(MutableDirectBuffer buffer, int offset, MutableInteger limit); + } + + private static Encoder combineEncoders(final Collection encoders) + { + return (buffer, offset, limit) -> + { + for (final Encoder encoder : encoders) + { + encoder.encode(buffer, offset, limit); + } + }; + } + + private static Arbitrary combineArbitraryEncoders(final List> encoders) + { + if (encoders.isEmpty()) + { + return Arbitraries.of(emptyEncoder()); + } + else + { + return Combinators.combine(encoders).as(SbeArbitraries::combineEncoders); + } + } + + public static CharacterArbitrary chars(final CharGenerationMode mode) + { + switch (mode) + { + case UNRESTRICTED: + return Arbitraries.chars(); + case JSON_PRINTER_COMPATIBLE: + return Arbitraries.chars().alpha(); + default: + throw new IllegalArgumentException("Unsupported mode: " + mode); + } + } + + private static Arbitrary encodedTypeEncoder( + final Encoding encoding, + final CharGenerationMode charGenerationMode) + { + final PrimitiveValue minValue = encoding.applicableMinValue(); + final PrimitiveValue maxValue = encoding.applicableMaxValue(); + + switch (encoding.primitiveType()) + { + case CHAR: + assert minValue.longValue() <= maxValue.longValue(); + return chars(charGenerationMode).map(c -> + (buffer, offset, limit) -> buffer.putChar(offset, c, encoding.byteOrder())); + + case UINT8: + case INT8: + assert (short)minValue.longValue() <= (short)maxValue.longValue(); + return Arbitraries.shorts() + .between((short)minValue.longValue(), (short)maxValue.longValue()) + .map(b -> (buffer, offset, limit) -> buffer.putByte(offset, (byte)(short)b)); + + case UINT16: + case INT16: + assert (int)minValue.longValue() <= (int)maxValue.longValue(); + return Arbitraries.integers() + .between((int)minValue.longValue(), (int)maxValue.longValue()) + .map(s -> (buffer, offset, limit) -> buffer.putShort(offset, (short)(int)s, encoding.byteOrder())); + + case UINT32: + case INT32: + assert minValue.longValue() <= maxValue.longValue(); + return Arbitraries.longs() + .between(minValue.longValue(), maxValue.longValue()) + .map(i -> (buffer, offset, limit) -> buffer.putInt(offset, (int)(long)i, encoding.byteOrder())); + + case UINT64: + return Arbitraries.longs() + .map(l -> (buffer, offset, limit) -> buffer.putLong(offset, l, encoding.byteOrder())); + + case INT64: + assert minValue.longValue() <= maxValue.longValue(); + return Arbitraries.longs() + .between(minValue.longValue(), maxValue.longValue()) + .map(l -> (buffer, offset, limit) -> buffer.putLong(offset, l, encoding.byteOrder())); + + case FLOAT: + return Arbitraries.floats() + .map(f -> (buffer, offset, limit) -> buffer.putFloat(offset, f, encoding.byteOrder())); + + case DOUBLE: + return Arbitraries.doubles() + .map(d -> (buffer, offset, limit) -> buffer.putDouble(offset, d, encoding.byteOrder())); + + default: + throw new IllegalArgumentException("Unsupported type: " + encoding.primitiveType()); + } + } + + private static Arbitrary encodedTypeEncoder( + final int offset, + final Token typeToken, + final CharGenerationMode charGenerationMode) + { + final Encoding encoding = typeToken.encoding(); + final Arbitrary arbEncoder = encodedTypeEncoder(encoding, charGenerationMode); + + if (typeToken.arrayLength() == 1) + { + return arbEncoder.map(encoder -> (buffer, bufferOffset, limit) -> + encoder.encode(buffer, bufferOffset + offset, limit)); + } + else + { + return arbEncoder.map(encoder -> (buffer, bufferOffset, limit) -> + { + for (int i = 0; i < typeToken.arrayLength(); i++) + { + encoder.encode(buffer, bufferOffset + offset + i * encoding.primitiveType().size(), limit); + } + }); + } + } + + private static Encoder emptyEncoder() + { + return (buffer, offset, limit) -> + { + }; + } + + private static Encoder integerValueEncoder(final Encoding encoding, final long value) + { + final PrimitiveType type = encoding.primitiveType(); + switch (type) + { + case CHAR: + case UINT8: + case INT8: + return (buffer, offset, limit) -> buffer.putByte(offset, (byte)value); + + case UINT16: + case INT16: + return (buffer, offset, limit) -> buffer.putShort(offset, (short)value, encoding.byteOrder()); + + case UINT32: + case INT32: + return (buffer, offset, limit) -> buffer.putInt(offset, (int)value, encoding.byteOrder()); + + case UINT64: + case INT64: + return (buffer, offset, limit) -> buffer.putLong(offset, value, encoding.byteOrder()); + + default: + throw new IllegalArgumentException("Unsupported type: " + type); + } + } + + private static Arbitrary enumEncoder( + final int offset, + final List tokens, + final Token typeToken, + final MutableInteger cursor, + final int endIdxInclusive) + { + cursor.increment(); + + final List encoders = new ArrayList<>(); + for (; cursor.get() <= endIdxInclusive; cursor.increment()) + { + final Token token = tokens.get(cursor.get()); + + if (VALID_VALUE != token.signal()) + { + throw new IllegalArgumentException("Expected VALID_VALUE token"); + } + + final Encoding encoding = token.encoding(); + final Encoder caseEncoder = integerValueEncoder(encoding, encoding.constValue().longValue()); + encoders.add(caseEncoder); + } + + if (encoders.isEmpty()) + { + final Encoder nullEncoder = integerValueEncoder( + typeToken.encoding(), + typeToken.encoding().nullValue().longValue()); + encoders.add(nullEncoder); + } + + return Arbitraries.of(encoders).map(encoder -> + (buffer, bufferOffset, limit) -> encoder.encode(buffer, bufferOffset + offset, limit)); + } + + private static Encoder choiceEncoder(final Encoding encoding) + { + final long choiceBitIdx = encoding.constValue().longValue(); + final PrimitiveType type = encoding.primitiveType(); + switch (type) + { + case UINT8: + case INT8: + return (buffer, offset, limit) -> + { + buffer.checkLimit(offset + BitUtil.SIZE_OF_BYTE); + final byte oldValue = buffer.getByte(offset); + final byte newValue = (byte)(oldValue | (1 << choiceBitIdx)); + buffer.putByte(offset, newValue); + }; + + case UINT16: + case INT16: + return (buffer, offset, limit) -> + { + buffer.checkLimit(offset + BitUtil.SIZE_OF_SHORT); + final short oldValue = buffer.getShort(offset, encoding.byteOrder()); + final short newValue = (short)(oldValue | (1 << choiceBitIdx)); + buffer.putShort(offset, newValue, encoding.byteOrder()); + }; + + case UINT32: + case INT32: + return (buffer, offset, limit) -> + { + buffer.checkLimit(offset + BitUtil.SIZE_OF_INT); + final int oldValue = buffer.getInt(offset, encoding.byteOrder()); + final int newValue = oldValue | (1 << choiceBitIdx); + buffer.putInt(offset, newValue, encoding.byteOrder()); + }; + + case UINT64: + case INT64: + return (buffer, offset, limit) -> + { + buffer.checkLimit(offset + BitUtil.SIZE_OF_LONG); + final long oldValue = buffer.getLong(offset, encoding.byteOrder()); + final long newValue = oldValue | (1L << choiceBitIdx); + buffer.putLong(offset, newValue, encoding.byteOrder()); + }; + + default: + throw new IllegalArgumentException("Unsupported type: " + type); + } + } + + private static Arbitrary bitSetEncoder( + final int offset, + final List tokens, + final MutableInteger cursor, + final int endIdxInclusive) + { + cursor.increment(); + + final List encoders = new ArrayList<>(); + for (; cursor.get() <= endIdxInclusive; cursor.increment()) + { + final Token token = tokens.get(cursor.get()); + + if (CHOICE != token.signal()) + { + throw new IllegalArgumentException("Expected CHOICE token"); + } + + final Encoding encoding = token.encoding(); + final Encoder choiceEncoder = choiceEncoder(encoding); + encoders.add(choiceEncoder); + } + + return Arbitraries.subsetOf(encoders) + .map(SbeArbitraries::combineEncoders) + .map(encoder -> (buffer, bufferOffset, limit) -> encoder.encode(buffer, bufferOffset + offset, limit)); + } + + private static Arbitrary fieldsEncoder( + final List tokens, + final MutableInteger cursor, + final int endIdxInclusive, + final boolean expectFields, + final CharGenerationMode charGenerationMode) + { + final List> encoders = new ArrayList<>(); + while (cursor.get() <= endIdxInclusive) + { + final Token memberToken = tokens.get(cursor.get()); + final int nextFieldIdx = cursor.get() + memberToken.componentTokenCount(); + + Token typeToken = memberToken; + int endFieldTokenCount = 0; + + if (BEGIN_FIELD == memberToken.signal()) + { + cursor.increment(); + typeToken = tokens.get(cursor.get()); + endFieldTokenCount = 1; + } + else if (expectFields) + { + break; + } + + final int offset = typeToken.offset(); + + if (!memberToken.isConstantEncoding()) + { + switch (typeToken.signal()) + { + case BEGIN_COMPOSITE: + cursor.increment(); + final int endCompositeTokenCount = 1; + final int lastMemberIdx = nextFieldIdx - endCompositeTokenCount - endFieldTokenCount - 1; + final Arbitrary encoder = fieldsEncoder( + tokens, cursor, lastMemberIdx, false, charGenerationMode); + final Arbitrary positionedEncoder = encoder.map(e -> + (buffer, bufferOffset, limit) -> e.encode(buffer, bufferOffset + offset, limit)); + encoders.add(positionedEncoder); + break; + + case BEGIN_ENUM: + final int endEnumTokenCount = 1; + final int lastValidValueIdx = nextFieldIdx - endFieldTokenCount - endEnumTokenCount - 1; + encoders.add(enumEncoder(offset, tokens, typeToken, cursor, lastValidValueIdx)); + break; + + case BEGIN_SET: + final int endSetTokenCount = 1; + final int lastChoiceIdx = nextFieldIdx - endFieldTokenCount - endSetTokenCount - 1; + encoders.add(bitSetEncoder(offset, tokens, cursor, lastChoiceIdx)); + break; + + case ENCODING: + encoders.add(encodedTypeEncoder(offset, typeToken, charGenerationMode)); + break; + + default: + break; + } + } + + cursor.set(nextFieldIdx); + } + + return combineArbitraryEncoders(encoders); + } + + + private static Arbitrary groupsEncoder( + final List tokens, + final MutableInteger cursor, + final int endIdxInclusive, + final CharGenerationMode charGenerationMode) + { + final List> encoders = new ArrayList<>(); + + while (cursor.get() <= endIdxInclusive) + { + final Token token = tokens.get(cursor.get()); + if (BEGIN_GROUP != token.signal()) + { + break; + } + final int nextFieldIdx = cursor.get() + token.componentTokenCount(); + + cursor.increment(); // consume BEGIN_GROUP + cursor.increment(); // consume BEGIN_COMPOSITE + final Token blockLengthToken = tokens.get(cursor.get()); + final int blockLength = token.encodedLength(); + final Encoder blockLengthEncoder = integerValueEncoder(blockLengthToken.encoding(), blockLength); + cursor.increment(); // consume ENCODED + final Token numInGroupToken = tokens.get(cursor.get()); + cursor.increment(); // consume ENCODED + cursor.increment(); // consume END_COMPOSITE + final int headerLength = blockLengthToken.encodedLength() + numInGroupToken.encodedLength(); + + + final Arbitrary groupElement = Combinators.combine( + fieldsEncoder(tokens, cursor, nextFieldIdx - 1, true, charGenerationMode), + groupsEncoder(tokens, cursor, nextFieldIdx - 1, charGenerationMode), + varDataEncoder(tokens, cursor, nextFieldIdx - 1, charGenerationMode) + ).as((fieldsEncoder, groupsEncoder, varDataEncoder) -> + (buffer, ignored, limit) -> + { + final int offset = limit.get(); + fieldsEncoder.encode(buffer, offset, null); + limit.set(offset + blockLength); + groupsEncoder.encode(buffer, NULL_VALUE, limit); + varDataEncoder.encode(buffer, NULL_VALUE, limit); + }); + + final Arbitrary repeatingGroupEncoder = groupElement.list() + .ofMaxSize(10) + .map(elements -> (buffer, ignored, limit) -> + { + final int offset = limit.get(); + limit.set(offset + headerLength); + blockLengthEncoder.encode(buffer, offset, null); + integerValueEncoder(numInGroupToken.encoding(), elements.size()) + .encode(buffer, offset + blockLengthToken.encodedLength(), null); + + for (final Encoder element : elements) + { + element.encode(buffer, NULL_VALUE, limit); + } + }); + + encoders.add(repeatingGroupEncoder); + + cursor.set(nextFieldIdx); + } + + return combineArbitraryEncoders(encoders); + } + + private static Arbitrary varDataEncoder( + final List tokens, + final MutableInteger cursor, + final int endIdxInclusive, + final CharGenerationMode charGenerationMode) + { + final List> encoders = new ArrayList<>(); + + while (cursor.get() <= endIdxInclusive) + { + final Token token = tokens.get(cursor.get()); + if (BEGIN_VAR_DATA != token.signal()) + { + break; + } + final int nextFieldIdx = cursor.get() + token.componentTokenCount(); + + cursor.increment(); // BEGIN_COMPOSITE + cursor.increment(); // ENCODED + final Token lengthToken = tokens.get(cursor.get()); + cursor.increment(); // ENCODED + final Token varDataToken = tokens.get(cursor.get()); + cursor.increment(); // END_COMPOSITE + + final String characterEncoding = varDataToken.encoding().characterEncoding(); + final Arbitrary arbitraryByte = null == characterEncoding ? + Arbitraries.bytes() : + chars(charGenerationMode).map(c -> (byte)c.charValue()); + encoders.add(arbitraryByte.list().map(bytes -> + (buffer, ignored, limit) -> + { + final int offset = limit.get(); + final int elementLength = varDataToken.encoding().primitiveType().size(); + limit.set(offset + lengthToken.encodedLength() + bytes.size() * elementLength); + integerValueEncoder(lengthToken.encoding(), bytes.size()) + .encode(buffer, offset, null); + for (int i = 0; i < bytes.size(); i++) + { + final int dataOffset = offset + lengthToken.encodedLength() + i * elementLength; + integerValueEncoder(varDataToken.encoding(), bytes.get(i)) + .encode(buffer, dataOffset, null); + } + })); + + cursor.set(nextFieldIdx); + } + + return combineArbitraryEncoders(encoders); + } + + public static Arbitrary messageValueEncoder( + final Ir ir, + final short messageId, + final CharGenerationMode charGenerationMode) + { + final List tokens = ir.getMessage(messageId); + final MutableInteger cursor = new MutableInteger(1); + + final Token token = tokens.get(0); + if (BEGIN_MESSAGE != token.signal()) + { + throw new IllegalArgumentException("Expected BEGIN_MESSAGE token"); + } + + final Arbitrary fieldsEncoder = fieldsEncoder( + tokens, cursor, tokens.size() - 1, true, charGenerationMode); + final Arbitrary groupsEncoder = groupsEncoder( + tokens, cursor, tokens.size() - 1, charGenerationMode); + final Arbitrary varDataEncoder = varDataEncoder( + tokens, cursor, tokens.size() - 1, charGenerationMode); + return Combinators.combine(fieldsEncoder, groupsEncoder, varDataEncoder) + .as((fields, groups, varData) -> (buffer, offset, limit) -> + { + final int blockLength = token.encodedLength(); + buffer.putShort(0, (short)blockLength, ir.byteOrder()); + buffer.putShort(2, messageId, ir.byteOrder()); + buffer.putShort(4, (short)ir.id(), ir.byteOrder()); + buffer.putShort(6, (short)0, ir.byteOrder()); + final int headerLength = 8; + fields.encode(buffer, offset + headerLength, null); + limit.set(offset + headerLength + blockLength); + groups.encode(buffer, NULL_VALUE, limit); + varData.encode(buffer, NULL_VALUE, limit); + }); + } + + public static final class EncodedMessage + { + private final String schema; + private final Ir ir; + private final ExpandableArrayBuffer buffer; + + private EncodedMessage(final String schema, final Ir ir, final ExpandableArrayBuffer buffer) + { + this.schema = schema; + this.ir = ir; + this.buffer = buffer; + } + + public String schema() + { + return schema; + } + + public Ir ir() + { + return ir; + } + + public ExpandableArrayBuffer buffer() + { + return buffer; + } + } + + public static Arbitrary encodedMessage(final CharGenerationMode mode) + { + return SbeArbitraries.messageSchema().flatMap(testSchema -> + { + final String xml = TestXmlSchemaWriter.writeString(testSchema); + try (InputStream in = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) + { + final uk.co.real_logic.sbe.xml.MessageSchema parsedSchema = parse(in, ParserOptions.DEFAULT); + final Ir ir = new IrGenerator().generate(parsedSchema); + return SbeArbitraries.messageValueEncoder(ir, testSchema.templateId(), mode) + .map(encoder -> + { + final ExpandableArrayBuffer buffer = new ExpandableArrayBuffer(); + final MutableInteger limit = new MutableInteger(); + encoder.encode(buffer, 0, limit); + return new EncodedMessage(xml, ir, buffer); + }); + } + catch (final Exception e) + { + throw new RuntimeException(e); + } + }).withoutEdgeCases(); + } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java index c275defe3d..451f61a34f 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java @@ -35,6 +35,16 @@ public MessageSchema( this.varData = varData; } + public short schemaId() + { + return 42; + } + + public short templateId() + { + return 1; + } + public List blockFields() { return blockFields; diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/XmlSchemaWriter.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java similarity index 98% rename from sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/XmlSchemaWriter.java rename to sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java index 63a10903ca..242f7c9946 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/XmlSchemaWriter.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java @@ -34,9 +34,9 @@ import static java.util.Objects.requireNonNull; -public final class XmlSchemaWriter +public final class TestXmlSchemaWriter { - private XmlSchemaWriter() + private TestXmlSchemaWriter() { } @@ -65,7 +65,7 @@ private static void writeTo( final Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); final Element root = document.createElementNS("http://fixprotocol.io/2016/sbe", "sbe:messageSchema"); - root.setAttribute("id", "42"); + root.setAttribute("id", Short.toString(schema.schemaId())); root.setAttribute("package", "uk.co.real_logic.sbe.properties"); document.appendChild(root); @@ -90,7 +90,7 @@ private static void writeTo( final Element message = document.createElement("sbe:message"); message.setAttribute("name", "TestMessage"); - message.setAttribute("id", "1"); + message.setAttribute("id", Short.toString(schema.templateId())); root.appendChild(message); final MutableInteger nextMemberId = new MutableInteger(0); appendMembers( diff --git a/sbe-tool/src/propertyTest/resources/junit-platform.properties b/sbe-tool/src/propertyTest/resources/junit-platform.properties index 8a3fb086c1..8194cc7e80 100644 --- a/sbe-tool/src/propertyTest/resources/junit-platform.properties +++ b/sbe-tool/src/propertyTest/resources/junit-platform.properties @@ -1,3 +1,4 @@ jqwik.edgecases.default=MIXIN -jqwik.tries.default=5000 -jqwik.failures.runfirst=true \ No newline at end of file +jqwik.tries.default=500 +jqwik.failures.runfirst=true +jqwik.shrinking.bounded.seconds=90 \ No newline at end of file From 5af0274372a8a8498fa7ee2b2fdcafcca745856e Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Sat, 7 Oct 2023 03:15:25 +0100 Subject: [PATCH 1134/1594] [Java] Test DTOs preserve information. In this commit, I've added a round trip property test, where I show `dto.EncodeInto(...)` is the inverse of `dto.DecodeFrom(...)` and that the original encoded value is preserved through the transformation. --- .../generation/csharp/CSharpDtoGenerator.java | 7 +- .../properties/CSharpDtosPropertyTest.java | 130 ++++++++++++++++++ .../CSharpDtosPropertyTest/Program.cs | 31 +++++ .../SbePropertyTest.csproj | 14 ++ 4 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java create mode 100644 sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/Program.cs create mode 100644 sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java index a0f1e21d9d..e7ceeeb155 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -266,7 +266,7 @@ private void generateFieldDecodeFrom( break; case BEGIN_COMPOSITE: - generateComplexDecodeFrom(sb, fieldToken, indent); + generateComplexDecodeFrom(sb, fieldToken, typeToken, indent); break; default: @@ -389,10 +389,12 @@ private void generatePropertyDecodeFrom( private void generateComplexDecodeFrom( final StringBuilder sb, final Token fieldToken, + final Token typeToken, final String indent) { final String propertyName = fieldToken.name(); final String formattedPropertyName = formatPropertyName(propertyName); + final String dtoClassName = formatDtoClassName(typeToken.applicableTypeName()); wrapInActingVersionCheck( sb, @@ -401,7 +403,7 @@ private void generateComplexDecodeFrom( (blkSb, blkIndent) -> { blkSb.append(blkIndent).append(formattedPropertyName).append(" = new ") - .append(formatDtoClassName(propertyName)).append("();\n") + .append(dtoClassName).append("();\n") .append(blkIndent).append(formattedPropertyName).append(".DecodeFrom(codec.") .append(formattedPropertyName).append(");\n"); }, @@ -577,7 +579,6 @@ private void generateFieldEncodeInto( final Token typeToken, final String indent) { - switch (typeToken.signal()) { case ENCODING: diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java new file mode 100644 index 0000000000..2c3cc814e1 --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java @@ -0,0 +1,130 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties; + +import net.jqwik.api.Arbitrary; +import net.jqwik.api.ForAll; +import net.jqwik.api.Property; +import net.jqwik.api.Provide; +import uk.co.real_logic.sbe.generation.csharp.CSharpDtoGenerator; +import uk.co.real_logic.sbe.generation.csharp.CSharpGenerator; +import uk.co.real_logic.sbe.generation.csharp.CSharpNamespaceOutputManager; +import uk.co.real_logic.sbe.properties.arbitraries.SbeArbitraries; +import org.agrona.IoUtil; +import org.agrona.io.DirectBufferInputStream; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; + +public class CSharpDtosPropertyTest +{ + @Property + void dtoEncodeShouldBeTheInverseOfDtoDecode( + @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage + ) throws IOException, InterruptedException + { + final Path tempDir = Files.createTempDirectory("sbe-csharp-dto-test"); + try + { + final CSharpNamespaceOutputManager outputManager = new CSharpNamespaceOutputManager( + tempDir.toString(), + "SbePropertyTest" + ); + new CSharpGenerator(encodedMessage.ir(), outputManager) + .generate(); + new CSharpDtoGenerator(encodedMessage.ir(), outputManager) + .generate(); + copyResourceToFile("/CSharpDtosPropertyTest/SbePropertyTest.csproj", tempDir); + copyResourceToFile("/CSharpDtosPropertyTest/Program.cs", tempDir); + try ( + DirectBufferInputStream inputStream = new DirectBufferInputStream(encodedMessage.buffer()); + OutputStream outputStream = Files.newOutputStream(tempDir.resolve("input.dat"))) + { + final byte[] buffer = new byte[2048]; + int read; + while ((read = inputStream.read(buffer, 0, buffer.length)) >= 0) + { + outputStream.write(buffer, 0, read); + } + } + + final Path stdout = tempDir.resolve("stdout.txt"); + final Path stderr = tempDir.resolve("stderr.txt"); + final ProcessBuilder processBuilder = new ProcessBuilder("dotnet", "run", "--", "input.dat") + .directory(tempDir.toFile()) + .redirectOutput(stdout.toFile()) + .redirectError(stderr.toFile()); + + final Process process = processBuilder.start(); + if (0 != process.waitFor()) + { + throw new AssertionError( + "Process failed with exit code: " + process.exitValue() + "\n\n" + + "STDOUT:\n" + new String(Files.readAllBytes(stdout)) + "\n\n" + + "STDERR:\n" + new String(Files.readAllBytes(stderr)) + "\n\n" + + "SCHEMA:\n" + encodedMessage.schema()); + } + + final byte[] inputBytes = encodedMessage.buffer().byteArray(); + final byte[] outputBytes = Files.readAllBytes(tempDir.resolve("output.dat")); + if (!Arrays.equals(inputBytes, outputBytes)) + { + throw new AssertionError( + "Input and output files differ\n\n" + + "SCHEMA:\n" + encodedMessage.schema()); + } + } + finally + { + IoUtil.delete(tempDir.toFile(), true); + } + } + + @Provide + Arbitrary encodedMessage() + { + final SbeArbitraries.CharGenerationMode mode = + SbeArbitraries.CharGenerationMode.JSON_PRINTER_COMPATIBLE; + return SbeArbitraries.encodedMessage(mode); + } + + private static void copyResourceToFile( + final String resourcePath, + final Path outputDir) + { + try (InputStream inputStream = CSharpDtosPropertyTest.class.getResourceAsStream(resourcePath)) + { + if (inputStream == null) + { + throw new IOException("Resource not found: " + resourcePath); + } + + final int resourceNameIndex = resourcePath.lastIndexOf('/') + 1; + final String resourceName = resourcePath.substring(resourceNameIndex); + final Path outputFilePath = outputDir.resolve(resourceName); + Files.copy(inputStream, outputFilePath); + } + catch (final IOException e) + { + throw new RuntimeException(e); + } + } +} diff --git a/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/Program.cs b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/Program.cs new file mode 100644 index 0000000000..1efcf4bfa7 --- /dev/null +++ b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/Program.cs @@ -0,0 +1,31 @@ +using System; +using System.IO; +using Org.SbeTool.Sbe.Dll; +using Uk.Co.Real_logic.Sbe.Properties; + +namespace SbePropertyTest { + static class Test { + static int Main(string[] args) { + if (args.Length != 1) { + Console.WriteLine("Usage: dotnet run -- $BINARY_FILE"); + return 1; + } + var binaryFile = args[0]; + var inputBytes = File.ReadAllBytes(binaryFile); + var buffer = new DirectBuffer(inputBytes); + var messageHeader = new MessageHeader(); + messageHeader.Wrap(buffer, 0, 0); + var decoder = new TestMessage(); + decoder.WrapForDecode(buffer, 8, messageHeader.BlockLength, messageHeader.Version); + var dto = new TestMessageDto(); + dto.DecodeFrom(decoder); + var outputBytes = new byte[inputBytes.Length]; + var outputBuffer = new DirectBuffer(outputBytes); + var encoder = new TestMessage(); + encoder.WrapForEncodeAndApplyHeader(outputBuffer, 0, new MessageHeader()); + dto.EncodeInto(encoder); + File.WriteAllBytes("output.dat", outputBytes); + return 0; + } + } +} diff --git a/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj new file mode 100644 index 0000000000..a1bbc69f1c --- /dev/null +++ b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj @@ -0,0 +1,14 @@ + + + + Exe + net7.0 + + + + + /home/zach/src/real-logic/simple-binary-encoding/csharp/sbe-dll/bin/Release/netstandard2.0/SBE.dll + + + + From fdf77422434e6a2c81c1e8f426cc83451f9e3fcb Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Tue, 10 Oct 2023 11:36:17 +0100 Subject: [PATCH 1135/1594] [Java,C#] Make dotnet executable customisable in tests. Addresses CodeQL comment. --- .../co/real_logic/sbe/properties/CSharpDtosPropertyTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java index 2c3cc814e1..3834b86e11 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java @@ -36,6 +36,8 @@ public class CSharpDtosPropertyTest { + private static final String DOTNET_EXECUTABLE = System.getProperty("sbe.tests.dotnet.executable", "dotnet"); + @Property void dtoEncodeShouldBeTheInverseOfDtoDecode( @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage @@ -68,7 +70,7 @@ void dtoEncodeShouldBeTheInverseOfDtoDecode( final Path stdout = tempDir.resolve("stdout.txt"); final Path stderr = tempDir.resolve("stderr.txt"); - final ProcessBuilder processBuilder = new ProcessBuilder("dotnet", "run", "--", "input.dat") + final ProcessBuilder processBuilder = new ProcessBuilder(DOTNET_EXECUTABLE, "run", "--", "input.dat") .directory(tempDir.toFile()) .redirectOutput(stdout.toFile()) .redirectError(stderr.toFile()); From 852a0fe38989d8de7f224405c7551c208a83ea68 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Tue, 10 Oct 2023 12:08:09 +0100 Subject: [PATCH 1136/1594] [Java] Extend schema generation to include bitsets with gaps. --- .../properties/arbitraries/SbeArbitraries.java | 15 ++++++--------- .../sbe/properties/schema/SetSchema.java | 13 +++++++------ .../properties/schema/TestXmlSchemaWriter.java | 11 +++++------ 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index eb6ef0603f..1efd68e7c0 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -147,15 +147,12 @@ private static Arbitrary enumTypeSchema() private static Arbitrary setTypeSchema() { - return Combinators.combine( - Arbitraries.of( - "uint8", - "uint16", - "uint32", - "uint64" - ), - Arbitraries.integers().between(1, 4) - ).as(SetSchema::new); + return Arbitraries.oneOf( + Arbitraries.integers().between(0, 7).set().map(choices -> new SetSchema("uint8", choices)), + Arbitraries.integers().between(0, 15).set().map(choices -> new SetSchema("uint16", choices)), + Arbitraries.integers().between(0, 31).set().map(choices -> new SetSchema("uint32", choices)), + Arbitraries.integers().between(0, 63).set().map(choices -> new SetSchema("uint64", choices)) + ); } private static Arbitrary compositeTypeSchema(final int depth) diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java index 95874e8381..4ed41fc013 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java @@ -16,17 +16,19 @@ package uk.co.real_logic.sbe.properties.schema; +import java.util.Set; + public final class SetSchema implements TypeSchema { private final String encodingType; - private final int choiceCount; + private final Set choices; public SetSchema( final String encodingType, - final int choiceCount) + final Set choices) { - this.choiceCount = choiceCount; this.encodingType = encodingType; + this.choices = choices; } public String encodingType() @@ -34,9 +36,9 @@ public String encodingType() return encodingType; } - public int choiceCount() + public Set choices() { - return choiceCount; + return choices; } @Override @@ -44,5 +46,4 @@ public void accept(final TypeSchemaVisitor visitor) { visitor.onSet(this); } - } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java index 242f7c9946..c7c23533bd 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java @@ -238,18 +238,17 @@ private static Element createSetElement( final Document document, final String name, final String encodingType, - final int choiceCount) + final Set choices) { final Element enumElement = document.createElement("set"); enumElement.setAttribute("name", name); enumElement.setAttribute("encodingType", encodingType); - int caseId = 0; - for (int i = 0; i < choiceCount; i++) + for (final Integer value : choices) { final Element choice = document.createElement("choice"); - choice.setAttribute("name", "option" + caseId++); - choice.setTextContent(Integer.toString(i)); + choice.setAttribute("name", "option" + value); + choice.setTextContent(value.toString()); enumElement.appendChild(choice); } @@ -403,7 +402,7 @@ public void onSet(final SetSchema type) document, typeToName.computeIfAbsent(type, nextName), type.encodingType(), - type.choiceCount() + type.choices() ); } From 92588c0433373590fd18a6d561fef1b886028d3f Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Tue, 10 Oct 2023 16:23:23 +0100 Subject: [PATCH 1137/1594] [Java] Use arbitrary fixed-length arrays in property tests. Previously, we were only generating non-array fields in blocks. Now, we can exercise more possibly specifications in our property-based tests. --- .../arbitraries/SbeArbitraries.java | 20 +++++++++++++------ .../schema/EncodedDataTypeSchema.java | 8 ++++++++ .../schema/TestXmlSchemaWriter.java | 20 ++++++++++++++++++- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index 1efd68e7c0..4750da7c19 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -111,6 +111,7 @@ private static Arbitrary encodedDataTypeSchema() { return Combinators.combine( Arbitraries.of(PrimitiveType.values()), + Arbitraries.of(1, 1, 1, 2, 13), Arbitraries.of(true, false) ).as(EncodedDataTypeSchema::new); } @@ -324,13 +325,15 @@ private static Arbitrary encodedTypeEncoder( } else { - return arbEncoder.map(encoder -> (buffer, bufferOffset, limit) -> - { - for (int i = 0; i < typeToken.arrayLength(); i++) + return arbEncoder.list().ofSize(typeToken.arrayLength()) + .map(encoders -> (buffer, bufferOffset, limit) -> { - encoder.encode(buffer, bufferOffset + offset + i * encoding.primitiveType().size(), limit); - } - }); + for (int i = 0; i < typeToken.arrayLength(); i++) + { + final int elementOffset = bufferOffset + offset + i * encoding.primitiveType().size(); + encoders.get(i).encode(buffer, elementOffset, limit); + } + }); } } @@ -478,6 +481,11 @@ private static Arbitrary bitSetEncoder( encoders.add(choiceEncoder); } + if (encoders.isEmpty()) + { + return Arbitraries.of(emptyEncoder()); + } + return Arbitraries.subsetOf(encoders) .map(SbeArbitraries::combineEncoders) .map(encoder -> (buffer, bufferOffset, limit) -> encoder.encode(buffer, bufferOffset + offset, limit)); diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java index b5fe76941d..5eb092150f 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java @@ -21,14 +21,17 @@ public final class EncodedDataTypeSchema implements TypeSchema { private final PrimitiveType primitiveType; + private final int length; private final boolean isEmbedded; public EncodedDataTypeSchema( final PrimitiveType primitiveType, + final int length, final boolean isEmbedded ) { this.primitiveType = primitiveType; + this.length = length; this.isEmbedded = isEmbedded; } @@ -37,6 +40,11 @@ public PrimitiveType primitiveType() return primitiveType; } + public int length() + { + return length; + } + @Override public boolean isEmbedded() { diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java index c7c23533bd..2211c31860 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java @@ -305,6 +305,23 @@ private static Element createTypeElement( return blockLength; } + private static Element createTypeElement( + final Document document, + final String name, + final String primitiveType, + final int length) + { + final Element blockLength = document.createElement("type"); + blockLength.setAttribute("name", name); + blockLength.setAttribute("primitiveType", primitiveType); + if (length > 1) + { + blockLength.setAttribute("length", Integer.toString(length)); + } + + return blockLength; + } + private static Element createRefElement( final Document document, final String name, @@ -362,7 +379,8 @@ public void onEncoded(final EncodedDataTypeSchema type) result = createTypeElement( document, typeToName.computeIfAbsent(type, nextName), - type.primitiveType().primitiveName() + type.primitiveType().primitiveName(), + type.length() ); } From b205c4b919ed5f84bef110fad1c6be3cd8c142cb Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 11 Oct 2023 10:00:17 +0100 Subject: [PATCH 1138/1594] [Java] Model optional fields in property-based tests. Previously, we were only supplying required fields in the schema. Now, we allow fields and primitive types to be marked as optional. Note that they can be marked as optional in two places. Optional => null value. There are some oddities around specifying `nullValue`s: https://github.com/real-logic/simple-binary-encoding/issues/429 We currently use the default `nullValue`s for types rather than generating arbitrary ones. --- .../arbitraries/SbeArbitraries.java | 33 ++++++++++- .../schema/EncodedDataTypeSchema.java | 9 +++ .../sbe/properties/schema/FieldSchema.java | 44 +++++++++++++++ .../sbe/properties/schema/GroupSchema.java | 6 +- .../sbe/properties/schema/MessageSchema.java | 6 +- .../schema/TestXmlSchemaWriter.java | 56 ++++++++++++++----- 6 files changed, 131 insertions(+), 23 deletions(-) create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index 4750da7c19..2a3d2bd9b3 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -112,6 +112,7 @@ private static Arbitrary encodedDataTypeSchema() return Combinators.combine( Arbitraries.of(PrimitiveType.values()), Arbitraries.of(1, 1, 1, 2, 13), + presence(), Arbitraries.of(true, false) ).as(EncodedDataTypeSchema::new); } @@ -190,12 +191,26 @@ private static Arbitrary groupSchema(final int depth) groupSchema(depth - 1).list().ofMaxSize(3); return Combinators.combine( - withDuplicates(2, typeSchema(MAX_COMPOSITE_DEPTH).list().ofMaxSize(5)), + withDuplicates( + 2, + Combinators.combine( + typeSchema(MAX_COMPOSITE_DEPTH), + presence() + ).as(FieldSchema::new).list().ofMaxSize(5) + ), subGroups, varDataSchema().list().ofMaxSize(3) ).as(GroupSchema::new); } + private static Arbitrary presence() + { + return Arbitraries.of( + Encoding.Presence.REQUIRED, + Encoding.Presence.OPTIONAL + ); + } + private static Arbitrary varDataSchema() { return Arbitraries.of(VarDataSchema.Encoding.values()) @@ -205,7 +220,14 @@ private static Arbitrary varDataSchema() public static Arbitrary messageSchema() { return Combinators.combine( - withDuplicates(3, typeSchema(MAX_COMPOSITE_DEPTH).list().ofMaxSize(10)), + + withDuplicates( + 3, + Combinators.combine( + typeSchema(MAX_COMPOSITE_DEPTH), + presence() + ).as(FieldSchema::new).list().ofMaxSize(10) + ), groupSchema(MAX_GROUP_DEPTH).list().ofMaxSize(3), varDataSchema().list().ofMaxSize(3) ).as(MessageSchema::new); @@ -752,7 +774,12 @@ public static Arbitrary encodedMessage(final CharGenerationMode final String xml = TestXmlSchemaWriter.writeString(testSchema); try (InputStream in = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) { - final uk.co.real_logic.sbe.xml.MessageSchema parsedSchema = parse(in, ParserOptions.DEFAULT); + final ParserOptions options = ParserOptions.builder() + .suppressOutput(false) + .warningsFatal(true) + .stopOnError(true) + .build(); + final uk.co.real_logic.sbe.xml.MessageSchema parsedSchema = parse(in, options); final Ir ir = new IrGenerator().generate(parsedSchema); return SbeArbitraries.messageValueEncoder(ir, testSchema.templateId(), mode) .map(encoder -> diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java index 5eb092150f..a1bbeba14e 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java @@ -17,21 +17,25 @@ package uk.co.real_logic.sbe.properties.schema; import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.ir.Encoding; public final class EncodedDataTypeSchema implements TypeSchema { private final PrimitiveType primitiveType; private final int length; + private final Encoding.Presence presence; private final boolean isEmbedded; public EncodedDataTypeSchema( final PrimitiveType primitiveType, final int length, + final Encoding.Presence presence, final boolean isEmbedded ) { this.primitiveType = primitiveType; this.length = length; + this.presence = presence; this.isEmbedded = isEmbedded; } @@ -45,6 +49,11 @@ public int length() return length; } + public Encoding.Presence presence() + { + return presence; + } + @Override public boolean isEmbedded() { diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java new file mode 100644 index 0000000000..406ee65cdd --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties.schema; + +import uk.co.real_logic.sbe.ir.Encoding; + +public final class FieldSchema +{ + private final TypeSchema type; + private final Encoding.Presence presence; + + public FieldSchema( + final TypeSchema type, + final Encoding.Presence presence + ) + { + this.type = type; + this.presence = presence; + } + + public TypeSchema type() + { + return type; + } + + public Encoding.Presence presence() + { + return presence; + } +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java index df34e0a9b6..53c3c81df7 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java @@ -20,12 +20,12 @@ public final class GroupSchema { - private final List blockFields; + private final List blockFields; private final List groups; private final List varData; public GroupSchema( - final List blockFields, + final List blockFields, final List groups, final List varData) { @@ -34,7 +34,7 @@ public GroupSchema( this.varData = varData; } - public List blockFields() + public List blockFields() { return blockFields; } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java index 451f61a34f..a0decb2d6b 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java @@ -20,12 +20,12 @@ public final class MessageSchema { - private final List blockFields; + private final List blockFields; private final List groups; private final List varData; public MessageSchema( - final List blockFields, + final List blockFields, final List groups, final List varData ) @@ -45,7 +45,7 @@ public short templateId() return 1; } - public List blockFields() + public List blockFields() { return blockFields; } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java index 2211c31860..1481126646 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java @@ -16,6 +16,7 @@ package uk.co.real_logic.sbe.properties.schema; +import uk.co.real_logic.sbe.ir.Encoding; import org.agrona.collections.MutableInteger; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -24,6 +25,7 @@ import java.io.StringWriter; import java.util.*; import java.util.function.Function; +import java.util.stream.Collectors; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; @@ -85,7 +87,7 @@ private static void writeTo( visitedTypes, topLevelTypes, typeSchemaConverter, - schema.blockFields(), + schema.blockFields().stream().map(FieldSchema::type).collect(Collectors.toList()), schema.groups()); final Element message = document.createElement("sbe:message"); @@ -128,25 +130,26 @@ private static void writeTo( private static void appendMembers( final Document document, final HashMap typeToName, - final List blockFields, + final List blockFields, final List groups, final List varData, final MutableInteger nextMemberId, final Element parent) { - for (final TypeSchema field : blockFields) + for (final FieldSchema field : blockFields) { final int id = nextMemberId.getAndIncrement(); - final boolean usePrimitiveName = field.isEmbedded() && field instanceof EncodedDataTypeSchema; + final boolean usePrimitiveName = field.type().isEmbedded() && field.type() instanceof EncodedDataTypeSchema; final String typeName = usePrimitiveName ? - ((EncodedDataTypeSchema)field).primitiveType().primitiveName() : - requireNonNull(typeToName.get(field)); + ((EncodedDataTypeSchema)field.type()).primitiveType().primitiveName() : + requireNonNull(typeToName.get(field.type())); final Element element = document.createElement("field"); element.setAttribute("id", Integer.toString(id)); element.setAttribute("name", "member" + id); element.setAttribute("type", typeName); + element.setAttribute("presence", field.presence().name().toLowerCase()); parent.appendChild(element); } @@ -309,17 +312,35 @@ private static Element createTypeElement( final Document document, final String name, final String primitiveType, - final int length) + final int length, + final Encoding.Presence presence) { - final Element blockLength = document.createElement("type"); - blockLength.setAttribute("name", name); - blockLength.setAttribute("primitiveType", primitiveType); + final Element typeElement = document.createElement("type"); + typeElement.setAttribute("name", name); + typeElement.setAttribute("primitiveType", primitiveType); + if (length > 1) { - blockLength.setAttribute("length", Integer.toString(length)); + typeElement.setAttribute("length", Integer.toString(length)); } - return blockLength; + switch (presence) + { + + case REQUIRED: + typeElement.setAttribute("presence", "required"); + break; + case OPTIONAL: + typeElement.setAttribute("presence", "optional"); + break; + case CONSTANT: + typeElement.setAttribute("presence", "constant"); + break; + default: + throw new IllegalArgumentException("Unknown presence: " + presence); + } + + return typeElement; } private static Element createRefElement( @@ -350,7 +371,13 @@ private static void appendTypes( for (final GroupSchema group : groups) { - appendTypes(visitedTypes, topLevelTypes, typeSchemaConverter, group.blockFields(), group.groups()); + appendTypes( + visitedTypes, + topLevelTypes, + typeSchemaConverter, + group.blockFields().stream().map(FieldSchema::type).collect(Collectors.toList()), + group.groups() + ); } } @@ -380,7 +407,8 @@ public void onEncoded(final EncodedDataTypeSchema type) document, typeToName.computeIfAbsent(type, nextName), type.primitiveType().primitiveName(), - type.length() + type.length(), + type.presence() ); } From 58b0e927615750902cece9c62a5b9d18f1c95bbc Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 11 Oct 2023 10:17:38 +0100 Subject: [PATCH 1139/1594] [Java, C#] Add a GitHub workflow for slow checks. This workflow is configured to run once per day or when manually requested. At the moment, the slow checks include several property-based tests. These tests take a significant amount of time to execute; therefore, we decided it was better to keep them out of the CI build. --- .github/workflows/slow.yml | 58 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/workflows/slow.yml diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml new file mode 100644 index 0000000000..9a22c1f415 --- /dev/null +++ b/.github/workflows/slow.yml @@ -0,0 +1,58 @@ +name: Slow checks + +on: + workflow_dispatch: + branches: + - '**' + schedule: + - cron: '0 12 * * *' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail' + +permissions: + contents: read + +jobs: + property-tests: + name: Property tests + runs-on: ubuntu-22.04 + strategy: + matrix: + java: [ '21' ] + dotnet: [ '3.1.301' ] + env: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + steps: + - name: Checkout code + uses: actions/checkout@v3 + - name: Setup java + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: ${{ matrix.java }} + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV + - name: Setup java 8 to run the Gradle script + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: 8 + - name: Setup dotnet + uses: actions/setup-dotnet@v2 + with: + dotnet-version: ${{ matrix.dotnet }} + - name: Build SbeTool + run: ./gradlew + - name: Build .NET library + run: ./csharp/build.sh + - name: Run property tests + run: ./gradlew propertyTest From 4f9d51b18607ace0e4297dd6c38a8bc3300409d6 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 11 Oct 2023 19:41:37 +0100 Subject: [PATCH 1140/1594] [Java] Extend arbitrary varData encodings. We now explore more of the "schema space", as we generate lengths of different encodings. It surfaces an issue, reported in #955, which was fixed in another outstanding PR's commit: 3885a63d3103ac52406c660147ee929fa9aaee63. --- .../arbitraries/SbeArbitraries.java | 27 ++++-- .../schema/TestXmlSchemaWriter.java | 87 ++++++++++--------- .../sbe/properties/schema/VarDataSchema.java | 21 +++-- 3 files changed, 81 insertions(+), 54 deletions(-) diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index 2a3d2bd9b3..cc2f5ff9ab 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -150,10 +150,18 @@ private static Arbitrary enumTypeSchema() private static Arbitrary setTypeSchema() { return Arbitraries.oneOf( - Arbitraries.integers().between(0, 7).set().map(choices -> new SetSchema("uint8", choices)), - Arbitraries.integers().between(0, 15).set().map(choices -> new SetSchema("uint16", choices)), - Arbitraries.integers().between(0, 31).set().map(choices -> new SetSchema("uint32", choices)), - Arbitraries.integers().between(0, 63).set().map(choices -> new SetSchema("uint64", choices)) + Arbitraries.integers().between(0, 7).set() + .ofMaxSize(8) + .map(choices -> new SetSchema("uint8", choices)), + Arbitraries.integers().between(0, 15).set() + .ofMaxSize(16) + .map(choices -> new SetSchema("uint16", choices)), + Arbitraries.integers().between(0, 31).set() + .ofMaxSize(32) + .map(choices -> new SetSchema("uint32", choices)), + Arbitraries.integers().between(0, 63).set() + .ofMaxSize(64) + .map(choices -> new SetSchema("uint64", choices)) ); } @@ -213,14 +221,19 @@ private static Arbitrary presence() private static Arbitrary varDataSchema() { - return Arbitraries.of(VarDataSchema.Encoding.values()) - .map(VarDataSchema::new); + return Combinators.combine( + Arbitraries.of(VarDataSchema.Encoding.values()), + Arbitraries.of( + PrimitiveType.UINT8, + PrimitiveType.UINT16, + PrimitiveType.UINT32 + ) + ).as(VarDataSchema::new); } public static Arbitrary messageSchema() { return Combinators.combine( - withDuplicates( 3, Combinators.combine( diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java index 1481126646..7ccd273017 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java @@ -20,6 +20,7 @@ import org.agrona.collections.MutableInteger; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.Node; import java.io.File; import java.io.StringWriter; @@ -74,7 +75,7 @@ private static void writeTo( final Element topLevelTypes = createTypesElement(document); root.appendChild(topLevelTypes); - final HashMap typeToName = new HashMap<>(); + final HashMap typeToName = new HashMap<>(); final TypeSchemaConverter typeSchemaConverter = new TypeSchemaConverter( document, @@ -88,7 +89,8 @@ private static void writeTo( topLevelTypes, typeSchemaConverter, schema.blockFields().stream().map(FieldSchema::type).collect(Collectors.toList()), - schema.groups()); + schema.groups(), + schema.varData()); final Element message = document.createElement("sbe:message"); message.setAttribute("name", "TestMessage"); @@ -129,7 +131,7 @@ private static void writeTo( private static void appendMembers( final Document document, - final HashMap typeToName, + final HashMap typeToName, final List blockFields, final List groups, final List varData, @@ -174,21 +176,10 @@ private static void appendMembers( for (final VarDataSchema data : varData) { final int id = nextMemberId.getAndIncrement(); - final Element element = document.createElement("data"); element.setAttribute("id", Integer.toString(id)); element.setAttribute("name", "member" + id); - switch (data.encoding()) - { - case ASCII: - element.setAttribute("type", "varStringEncoding"); - break; - case BYTES: - element.setAttribute("type", "varDataEncoding"); - break; - default: - throw new IllegalStateException("Unknown encoding: " + data.encoding()); - } + element.setAttribute("type", requireNonNull(typeToName.get(data))); parent.appendChild(element); } } @@ -213,27 +204,6 @@ private static Element createTypesElement(final Document document) createTypeElement(document, "numInGroup", "uint16") )); - final Element varString = createTypeElement(document, "varData", "uint8"); - varString.setAttribute("length", "0"); - varString.setAttribute("characterEncoding", "US-ASCII"); - types.appendChild(createCompositeElement( - document, - "varStringEncoding", - createTypeElement(document, "length", "uint16"), - varString - )); - - final Element varData = createTypeElement(document, "varData", "uint8"); - final Element varDataLength = createTypeElement(document, "length", "uint32"); - varDataLength.setAttribute("maxValue", "1000000"); - varData.setAttribute("length", "0"); - types.appendChild(createCompositeElement( - document, - "varDataEncoding", - varDataLength, - varData - )); - return types; } @@ -359,7 +329,8 @@ private static void appendTypes( final Element topLevelTypes, final TypeSchemaConverter typeSchemaConverter, final List blockFields, - final List groups) + final List groups, + final List varDataFields) { for (final TypeSchema field : blockFields) { @@ -376,23 +347,29 @@ private static void appendTypes( topLevelTypes, typeSchemaConverter, group.blockFields().stream().map(FieldSchema::type).collect(Collectors.toList()), - group.groups() - ); + group.groups(), + group.varData()); + } + + for (final VarDataSchema varData : varDataFields) + { + topLevelTypes.appendChild(typeSchemaConverter.convert(varData)); } } + @SuppressWarnings("EnhancedSwitchMigration") private static final class TypeSchemaConverter implements TypeSchemaVisitor { private final Document document; private final Element topLevelTypes; - private final Map typeToName; - private final Function nextName; + private final Map typeToName; + private final Function nextName; private Element result; private TypeSchemaConverter( final Document document, final Element topLevelTypes, - final Map typeToName) + final Map typeToName) { this.document = document; this.topLevelTypes = topLevelTypes; @@ -481,5 +458,31 @@ public Element convert(final TypeSchema type) type.accept(this); return requireNonNull(result); } + + public Node convert(final VarDataSchema varData) + { + final Element lengthElement = createTypeElement(document, "length", + varData.lengthEncoding().primitiveName()); + + if (varData.lengthEncoding().size() >= 4) + { + lengthElement.setAttribute("maxValue", Integer.toString(1_000_000)); + } + + final Element varDataElement = createTypeElement(document, "varData", "uint8"); + varDataElement.setAttribute("length", "0"); + + if (varData.dataEncoding().equals(VarDataSchema.Encoding.ASCII)) + { + varDataElement.setAttribute("characterEncoding", "US-ASCII"); + } + + return createCompositeElement( + document, + typeToName.computeIfAbsent(varData, nextName), + lengthElement, + varDataElement + ); + } } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java index c6b39db56b..b5e98c02c7 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java @@ -16,18 +16,29 @@ package uk.co.real_logic.sbe.properties.schema; +import uk.co.real_logic.sbe.PrimitiveType; + public final class VarDataSchema { - private final Encoding encoding; + private final Encoding dataEncoding; + private final PrimitiveType lengthEncoding; + + public VarDataSchema( + final Encoding dataEncoding, + final PrimitiveType lengthEncoding) + { + this.dataEncoding = dataEncoding; + this.lengthEncoding = lengthEncoding; + } - public VarDataSchema(final Encoding encoding) + public Encoding dataEncoding() { - this.encoding = encoding; + return dataEncoding; } - public Encoding encoding() + public PrimitiveType lengthEncoding() { - return encoding; + return lengthEncoding; } public enum Encoding From 77711dd7e6285c2763794f0ee048745b250d6f4e Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Thu, 12 Oct 2023 13:27:22 +0100 Subject: [PATCH 1141/1594] [Java, C#] Tidy up encoded message writing in tests. Previously, we were writing all bytes in a buffer rather than just those used for encoding the message. Now, we keep track of the "limit" of the message and only use the bytes in the buffer up to the limit. --- .../sbe/properties/CSharpDtosPropertyTest.java | 9 +++++++-- .../properties/arbitraries/SbeArbitraries.java | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java index 3834b86e11..7a4dde3f49 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java @@ -57,7 +57,11 @@ void dtoEncodeShouldBeTheInverseOfDtoDecode( copyResourceToFile("/CSharpDtosPropertyTest/SbePropertyTest.csproj", tempDir); copyResourceToFile("/CSharpDtosPropertyTest/Program.cs", tempDir); try ( - DirectBufferInputStream inputStream = new DirectBufferInputStream(encodedMessage.buffer()); + DirectBufferInputStream inputStream = new DirectBufferInputStream( + encodedMessage.buffer(), + 0, + encodedMessage.length() + ); OutputStream outputStream = Files.newOutputStream(tempDir.resolve("input.dat"))) { final byte[] buffer = new byte[2048]; @@ -85,7 +89,8 @@ void dtoEncodeShouldBeTheInverseOfDtoDecode( "SCHEMA:\n" + encodedMessage.schema()); } - final byte[] inputBytes = encodedMessage.buffer().byteArray(); + final byte[] inputBytes = new byte[encodedMessage.length()]; + encodedMessage.buffer().getBytes(0, inputBytes); final byte[] outputBytes = Files.readAllBytes(tempDir.resolve("output.dat")); if (!Arrays.equals(inputBytes, outputBytes)) { diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index cc2f5ff9ab..2e3db4bda0 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -756,12 +756,18 @@ public static final class EncodedMessage private final String schema; private final Ir ir; private final ExpandableArrayBuffer buffer; + private final int length; - private EncodedMessage(final String schema, final Ir ir, final ExpandableArrayBuffer buffer) + private EncodedMessage( + final String schema, + final Ir ir, + final ExpandableArrayBuffer buffer, + final int length) { this.schema = schema; this.ir = ir; this.buffer = buffer; + this.length = length; } public String schema() @@ -778,6 +784,11 @@ public ExpandableArrayBuffer buffer() { return buffer; } + + public int length() + { + return length; + } } public static Arbitrary encodedMessage(final CharGenerationMode mode) @@ -800,7 +811,7 @@ public static Arbitrary encodedMessage(final CharGenerationMode final ExpandableArrayBuffer buffer = new ExpandableArrayBuffer(); final MutableInteger limit = new MutableInteger(); encoder.encode(buffer, 0, limit); - return new EncodedMessage(xml, ir, buffer); + return new EncodedMessage(xml, ir, buffer, limit.get()); }); } catch (final Exception e) From 19f69a9fae941dd5018e68c546bc7d60528a2683 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Fri, 13 Oct 2023 00:00:41 +0100 Subject: [PATCH 1142/1594] [C#] Upgrade to latest LTS .NET version. To support records in DTOs, we require C# 9+. This is not supported by .NET 3. Also, this old version is no longer supported by Microsoft. Therefore, I have upgraded to the latest LTS release. --- .github/workflows/codeql.yml | 2 +- .github/workflows/slow.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index db70001ed7..44a604749a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -88,7 +88,7 @@ jobs: fail-fast: false matrix: language: [ 'csharp' ] - dotnet: [ '3.1.x' ] + dotnet: [ '8.0.x' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 9a22c1f415..a5f007f6bf 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -24,7 +24,7 @@ jobs: strategy: matrix: java: [ '21' ] - dotnet: [ '3.1.301' ] + dotnet: [ '8.0.x' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 From 520cdb1c5eb7156b68a7789819fd4c9e2b332987 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Thu, 12 Oct 2023 23:20:21 +0100 Subject: [PATCH 1143/1594] [C#] Generate DTOs using C# 9+ records. The reason behind this change is to support equality and comparison of DTOs in tests by leveraging records. --- .../sbe/generation/csharp/CSharpDtoGenerator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java index e7ceeeb155..ad6c68db38 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -103,7 +103,7 @@ public void generate() throws IOException out.append(generateFileHeader(ir.applicableNamespace(), "using System.Collections.Generic;\n")); out.append(generateDocumentation(BASE_INDENT, msgToken)); - out.append(BASE_INDENT).append("public sealed partial class ").append(className).append("\n") + out.append(BASE_INDENT).append("public sealed partial record ").append(className).append("\n") .append(BASE_INDENT).append("{") .append(sb) .append(BASE_INDENT).append("}\n") @@ -136,7 +136,7 @@ private void generateGroups( sb.append("\n") .append(generateDocumentation(indent, groupToken)) - .append(indent).append("public sealed partial class ").append(groupClassName).append("\n") + .append(indent).append("public sealed partial record ").append(groupClassName).append("\n") .append(indent).append("{"); i++; @@ -1031,7 +1031,7 @@ private void generateComposite(final List tokens) throws IOException generateCompositeEncodeInto(sb, codecClassName, compositeTokens, BASE_INDENT + INDENT); generateDisplay(sb, codecClassName, "Wrap", codecClassName + ".SbeSchemaVersion", BASE_INDENT + INDENT); - out.append(BASE_INDENT).append("public sealed partial class ").append(className).append("\n") + out.append(BASE_INDENT).append("public sealed partial record ").append(className).append("\n") .append(BASE_INDENT).append("{") .append(sb) .append(BASE_INDENT).append("}\n") From c1afd033456fc7d264dad9ce22a188e877271ae4 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Tue, 17 Oct 2023 17:04:37 +0100 Subject: [PATCH 1144/1594] [C#] Use more-idiomatic null representations. Also, make records immutable, as it is more idiomatic to use `with` expressions. In the future, it may be preferable to declare record fields in the constructor rather than as init-only properties; however, this would be a much larger change. This is the current mapping of optional fields: - Primitives: as nullable value types - Composites: as nullable references - Enums: we already generate a `NULL_VALUE` case and we use that - Bitsets: as a flags enum where `0` is the null value - Strings: as empty string - Arrays: as empty read-only lists --- csharp/sbe-tests/DtoTests.cs | 5 +- .../generation/csharp/CSharpDtoGenerator.java | 286 ++++++++++-------- .../sbe/generation/csharp/CSharpUtil.java | 6 +- .../CSharpDtosPropertyTest/Program.cs | 3 +- .../SbePropertyTest.csproj | 2 +- 5 files changed, 169 insertions(+), 133 deletions(-) diff --git a/csharp/sbe-tests/DtoTests.cs b/csharp/sbe-tests/DtoTests.cs index 99fbcadc74..fcd0007bf7 100644 --- a/csharp/sbe-tests/DtoTests.cs +++ b/csharp/sbe-tests/DtoTests.cs @@ -16,14 +16,13 @@ public void ShouldRoundTripCar() var decoder = new Car(); decoder.WrapForDecode(inputBuffer, 0, Car.BlockLength, Car.SchemaVersion); var decoderString = decoder.ToString(); - var dto = new CarDto(); - dto.DecodeFrom(decoder); + var dto = CarDto.DecodeFrom(decoder); var outputByteArray = new byte[1024]; var outputBuffer = new DirectBuffer(outputByteArray); var encoder = new Car(); encoder.WrapForEncode(outputBuffer, 0); dto.EncodeInto(encoder); - var dtoString = dto.ToString(); + var dtoString = dto.ToSbeString(); CollectionAssert.AreEqual(inputByteArray, outputByteArray); Assert.AreEqual(decoderString, dtoString); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java index ad6c68db38..b6ab8638d9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -30,7 +30,6 @@ import java.io.Writer; import java.util.ArrayList; import java.util.List; -import java.util.function.BiConsumer; import static uk.co.real_logic.sbe.generation.csharp.CSharpUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; @@ -40,7 +39,6 @@ /** * DTO generator for the CSharp programming language. */ -@SuppressWarnings("CodeBlock2Expr") public class CSharpDtoGenerator implements CodeGenerator { private static final String INDENT = " "; @@ -94,13 +92,17 @@ public void generate() throws IOException collectVarData(messageBody, offset, varData); generateVarData(sb, varData, BASE_INDENT + INDENT); - generateDecodeFrom(sb, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); + generateDecodeFrom(sb, className, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); generateEncodeInto(sb, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); generateDisplay(sb, codecClassName, "WrapForEncode", null, BASE_INDENT + INDENT); try (Writer out = outputManager.createOutput(className)) { - out.append(generateFileHeader(ir.applicableNamespace(), "using System.Collections.Generic;\n")); + out.append(generateFileHeader( + ir.applicableNamespace(), + "#nullable enable\n\n", + "using System.Collections.Generic;\n", + "using System.Linq;\n")); out.append(generateDocumentation(BASE_INDENT, msgToken)); out.append(BASE_INDENT).append("public sealed partial record ").append(className).append("\n") @@ -130,9 +132,9 @@ private void generateGroups( sb.append("\n") .append(generateDocumentation(indent, groupToken)) - .append(indent).append("public List<").append(groupClassName).append("> ") + .append(indent).append("public IReadOnlyList<").append(groupClassName).append("> ") .append(formatPropertyName(groupName)) - .append(" { get; set; } = new List<").append(groupClassName).append(">();\n"); + .append(" { get; init; }\n"); sb.append("\n") .append(generateDocumentation(indent, groupToken)) @@ -155,7 +157,8 @@ private void generateGroups( i = collectVarData(tokens, i, varData); generateVarData(sb, varData, indent + INDENT); - generateDecodeFrom(sb, codecClassName, fields, groups, varData, indent + INDENT); + generateDecodeListFrom(sb, groupClassName, codecClassName, indent + INDENT); + generateDecodeFrom(sb, groupClassName, codecClassName, fields, groups, varData, indent + INDENT); generateEncodeInto(sb, codecClassName, fields, groups, varData, indent + INDENT); sb.append(indent).append("}\n"); @@ -164,23 +167,29 @@ private void generateGroups( private void generateCompositeDecodeFrom( final StringBuilder sb, + final String dtoClassName, final String codecClassName, final List tokens, final String indent) { sb.append("\n") - .append(indent).append("public void DecodeFrom(").append(codecClassName).append(" codec)\n") + .append(indent).append("public static ").append(dtoClassName).append(" DecodeFrom(") + .append(codecClassName).append(" codec)\n") .append(indent).append("{\n"); + sb.append(indent).append(INDENT).append("return new ").append(dtoClassName).append("()\n") + .append(indent).append(INDENT).append("{\n"); + for (int i = 0; i < tokens.size(); ) { final Token token = tokens.get(i); - generateFieldDecodeFrom(sb, token, token, codecClassName, indent + INDENT); + generateFieldDecodeFrom(sb, token, token, codecClassName, indent + INDENT + INDENT); i += tokens.get(i).componentTokenCount(); } + sb.append(indent).append(INDENT).append("};\n"); sb.append(indent).append("}\n"); } @@ -198,7 +207,7 @@ private void generateCompositeEncodeInto( { final Token token = tokens.get(i); - generateFieldEncodeInto(sb, token, token, indent + INDENT); + generateFieldEncodeInto(sb, codecClassName, token, token, indent + INDENT); i += tokens.get(i).componentTokenCount(); } @@ -206,8 +215,36 @@ private void generateCompositeEncodeInto( sb.append(indent).append("}\n"); } + private void generateDecodeListFrom( + final StringBuilder sb, + final String dtoClassName, + final String codecClassName, + final String indent) + { + sb.append("\n") + .append(indent).append("public static IReadOnlyList<").append(dtoClassName).append("> DecodeListFrom(") + .append(codecClassName).append(" codec)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("var ").append("list = new List<").append(dtoClassName) + .append(">(codec.Count);\n") + .append(indent).append(INDENT) + .append("while (codec.HasNext)\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("var element = ").append(dtoClassName).append(".DecodeFrom(codec.Next());\n") + .append(indent).append(INDENT).append(INDENT) + .append("list.Add(element);\n") + .append(indent).append(INDENT) + .append("}\n") + .append(indent).append(INDENT) + .append("return list.AsReadOnly();\n") + .append(indent).append("}\n"); + } + private void generateDecodeFrom( final StringBuilder sb, + final String dtoClassName, final String codecClassName, final List fields, final List groups, @@ -215,12 +252,16 @@ private void generateDecodeFrom( final String indent) { sb.append("\n") - .append(indent).append("public void DecodeFrom(").append(codecClassName).append(" codec)\n") + .append(indent).append("public static ").append(dtoClassName) + .append(" DecodeFrom(").append(codecClassName).append(" codec)\n") .append(indent).append("{\n"); - generateFieldsDecodeFrom(sb, fields, codecClassName, indent + INDENT); - generateGroupsDecodeFrom(sb, groups, indent + INDENT); - generateVarDataDecodeFrom(sb, varData, indent + INDENT); + sb.append(indent).append(INDENT).append("return new ").append(dtoClassName).append("()\n") + .append(indent).append(INDENT).append("{\n"); + generateFieldsDecodeFrom(sb, fields, codecClassName, indent + INDENT + INDENT); + generateGroupsDecodeFrom(sb, groups, indent + INDENT + INDENT); + generateVarDataDecodeFrom(sb, varData, indent + INDENT + INDENT); + sb.append(indent).append(INDENT).append("};\n"); sb.append(indent).append("}\n"); } @@ -256,13 +297,13 @@ private void generateFieldDecodeFrom( break; case BEGIN_SET: - generatePropertyDecodeFrom(sb, fieldToken, "0", indent); + generatePropertyDecodeFrom(sb, codecClassName, fieldToken, "0", indent); break; case BEGIN_ENUM: final String enumName = formatClassName(typeToken.applicableTypeName()); final String nullValue = formatNamespace(ir.packageName()) + "." + enumName + ".NULL_VALUE"; - generatePropertyDecodeFrom(sb, fieldToken, nullValue, indent); + generatePropertyDecodeFrom(sb, codecClassName, fieldToken, nullValue, indent); break; case BEGIN_COMPOSITE: @@ -291,7 +332,7 @@ private void generatePrimitiveDecodeFrom( if (arrayLength == 1) { final String nullValue = codecClassName + "." + formatPropertyName(fieldToken.name()) + "NullValue"; - generatePropertyDecodeFrom(sb, fieldToken, nullValue, indent); + generatePropertyDecodeFrom(sb, codecClassName, fieldToken, nullValue, indent); } else if (arrayLength > 1) { @@ -319,44 +360,27 @@ private void generateArrayDecodeFrom( sb, fieldToken, indent, - (blkSb, blkIndent) -> - { - blkSb.append(blkIndent).append(formattedPropertyName) - .append(" = codec.Get").append(formattedPropertyName).append("();\n"); - }, - (blkSb, blkIndent) -> - { - blkSb.append(blkIndent).append(formattedPropertyName).append(" = null;\n"); - } + "codec.Get" + formattedPropertyName + "()", + "null", + null ); } else { - final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); - wrapInActingVersionCheck( sb, fieldToken, indent, - (blkSb, blkIndent) -> - { - blkSb.append(blkIndent).append(formattedPropertyName) - .append(" = new ").append(typeName).append("[") - .append(typeToken.arrayLength()).append("];\n") - .append(blkIndent).append("codec.").append(formattedPropertyName) - .append(".CopyTo(new Span<").append(typeName).append(">(") - .append(formattedPropertyName).append("));\n"); - }, - (blkSb, blkIndent) -> - { - blkSb.append(blkIndent).append(formattedPropertyName).append(" = null;\n"); - } + "codec." + formattedPropertyName + "AsSpan().ToArray()", + "null", + null ); } } private void generatePropertyDecodeFrom( final StringBuilder sb, + final String codecClassName, final Token fieldToken, final String nullValue, final String indent) @@ -374,15 +398,9 @@ private void generatePropertyDecodeFrom( sb, fieldToken, indent, - (blkSb, blkIndent) -> - { - blkSb.append(blkIndent).append(formattedPropertyName).append(" = codec.") - .append(formattedPropertyName).append(";\n"); - }, - (blkSb, blkIndent) -> - { - blkSb.append(blkIndent).append(formattedPropertyName).append(" = ").append(nullValue).append(";\n"); - } + "codec." + formattedPropertyName, + nullValue, + codecClassName + "." + formattedPropertyName + "NullValue" ); } @@ -400,17 +418,9 @@ private void generateComplexDecodeFrom( sb, fieldToken, indent, - (blkSb, blkIndent) -> - { - blkSb.append(blkIndent).append(formattedPropertyName).append(" = new ") - .append(dtoClassName).append("();\n") - .append(blkIndent).append(formattedPropertyName).append(".DecodeFrom(codec.") - .append(formattedPropertyName).append(");\n"); - }, - (blkSb, blkIndent) -> - { - blkSb.append(blkIndent).append(formattedPropertyName).append(" = null;\n"); - } + dtoClassName + ".DecodeFrom(codec." + formattedPropertyName + ")", + "null", + "null" ); } @@ -429,30 +439,13 @@ private void generateGroupsDecodeFrom( final String groupName = groupToken.name(); final String formattedPropertyName = formatPropertyName(groupName); final String groupDtoClassName = formatDtoClassName(groupName); - final String groupCodecVarName = groupName + "Codec"; - - sb.append("\n") - .append(indent) - .append(formattedPropertyName).append(" = new List<").append(groupDtoClassName).append(">();\n"); wrapInActingVersionCheck( sb, groupToken, indent, - (blkSb, blkIndent) -> - { - blkSb.append(blkIndent).append("var ").append(groupCodecVarName).append(" = codec.") - .append(formattedPropertyName).append(";\n") - .append(blkIndent).append("while (").append(groupCodecVarName).append(".HasNext)\n") - .append(blkIndent).append("{\n") - .append(blkIndent).append(INDENT) - .append("var element = new ").append(groupDtoClassName).append("();\n") - .append(blkIndent).append(INDENT) - .append("element.DecodeFrom(").append(groupCodecVarName).append(".Next());\n") - .append(blkIndent).append(INDENT) - .append(formattedPropertyName).append(".Add(element);\n") - .append(blkIndent).append("}\n"); - }, + groupDtoClassName + ".DecodeListFrom(codec." + formattedPropertyName + ")", + "new List<" + groupDtoClassName + ">(0).AsReadOnly()", null ); @@ -493,15 +486,9 @@ private void generateVarDataDecodeFrom( sb, token, indent, - (blkSb, blkIndent) -> - { - blkSb.append(blkIndent).append(formattedPropertyName) - .append(" = codec.").append(accessor).append("();\n"); - }, - (blkSb, blkIndent) -> - { - blkSb.append(blkIndent).append(formattedPropertyName).append(" = null;\n"); - } + "codec." + accessor + "()", + "null", + null ); } } @@ -511,30 +498,31 @@ private void wrapInActingVersionCheck( final StringBuilder sb, final Token token, final String indent, - final BiConsumer generatePresentBlock, - final BiConsumer generateNotPresentBlock) + final String presentExpression, + final String notPresentExpression, + final String nullCodecValueOrNull) { final String propertyName = token.name(); final String formattedPropertyName = formatPropertyName(propertyName); + sb.append(indent).append(formattedPropertyName).append(" = "); + if (token.version() > 0) { - sb.append("\n").append(indent).append("if (codec.").append(formattedPropertyName) - .append("InActingVersion())\n") - .append(indent).append("{\n"); - generatePresentBlock.accept(sb, indent + INDENT); - sb.append(indent).append("}\n"); - if (null != generateNotPresentBlock) + sb.append("codec.").append(formattedPropertyName).append("InActingVersion()"); + + if (null != nullCodecValueOrNull) { - sb.append(indent).append("else\n") - .append(indent).append("{\n"); - generateNotPresentBlock.accept(sb, indent + INDENT); - sb.append(indent).append("}\n"); + sb.append(" && codec.").append(formattedPropertyName).append(" != ").append(nullCodecValueOrNull); } + + sb.append(" ?\n"); + sb.append(indent).append(INDENT).append(presentExpression).append(" :\n") + .append(indent).append(INDENT).append(notPresentExpression).append(",\n"); } else { - generatePresentBlock.accept(sb, indent); + sb.append(presentExpression).append(",\n"); } } @@ -550,7 +538,7 @@ private void generateEncodeInto( .append(indent).append("public void EncodeInto(").append(codecClassName).append(" codec)\n") .append(indent).append("{\n"); - generateFieldsEncodeInto(sb, fields, indent + INDENT); + generateFieldsEncodeInto(sb, codecClassName, fields, indent + INDENT); generateGroupsEncodeInto(sb, groups, indent + INDENT); generateVarDataEncodeInto(sb, varData, indent + INDENT); @@ -559,6 +547,7 @@ private void generateEncodeInto( private void generateFieldsEncodeInto( final StringBuilder sb, + final String codecClassName, final List tokens, final String indent) { @@ -568,13 +557,14 @@ private void generateFieldsEncodeInto( if (signalToken.signal() == Signal.BEGIN_FIELD) { final Token encodingToken = tokens.get(i + 1); - generateFieldEncodeInto(sb, signalToken, encodingToken, indent); + generateFieldEncodeInto(sb, codecClassName, signalToken, encodingToken, indent); } } } private void generateFieldEncodeInto( final StringBuilder sb, + final String codecClassName, final Token fieldToken, final Token typeToken, final String indent) @@ -582,12 +572,12 @@ private void generateFieldEncodeInto( switch (typeToken.signal()) { case ENCODING: - generatePrimitiveEncodeInto(sb, fieldToken, typeToken, indent); + generatePrimitiveEncodeInto(sb, codecClassName, fieldToken, typeToken, indent); break; case BEGIN_SET: case BEGIN_ENUM: - generatePropertyEncodeInto(sb, fieldToken, indent); + generateEnumEncodeInto(sb, fieldToken, indent); break; case BEGIN_COMPOSITE: @@ -601,6 +591,7 @@ private void generateFieldEncodeInto( private void generatePrimitiveEncodeInto( final StringBuilder sb, + final String codecClassName, final Token fieldToken, final Token typeToken, final String indent) @@ -614,7 +605,7 @@ private void generatePrimitiveEncodeInto( if (arrayLength == 1) { - generatePropertyEncodeInto(sb, fieldToken, indent); + generatePropertyEncodeInto(sb, codecClassName, fieldToken, indent); } else if (arrayLength > 1) { @@ -638,19 +629,53 @@ private void generateArrayEncodeInto( if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { + final String value = nullableConvertedExpression(fieldToken, formattedPropertyName, "\"\""); sb.append(indent).append("codec.Set").append(formattedPropertyName).append("(") - .append(formattedPropertyName).append(");\n"); + .append(value).append(");\n"); } else { final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); sb.append(indent).append("new Span<").append(typeName).append(">(").append(formattedPropertyName) - .append(").CopyTo(codec.").append(formattedPropertyName).append("AsSpan());\n"); + .append("?.ToArray()).CopyTo(codec.").append(formattedPropertyName).append("AsSpan());\n"); } } + private String nullableConvertedExpression( + final Token fieldToken, + final String expression, + final String nullValue) + { + return fieldToken.version() > 0 || fieldToken.isOptionalEncoding() ? + expression + " ?? " + nullValue : + expression; + } + private void generatePropertyEncodeInto( + final StringBuilder sb, + final String codecClassName, + final Token fieldToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + final String value = nullableConvertedExpression( + fieldToken, + formattedPropertyName, + codecClassName + "." + formattedPropertyName + "NullValue"); + + sb.append(indent).append("codec.").append(formattedPropertyName).append(" = ") + .append(value).append(";\n"); + } + + private void generateEnumEncodeInto( final StringBuilder sb, final Token fieldToken, final String indent) @@ -743,7 +768,7 @@ private void generateDisplay( final String indent) { sb.append("\n") - .append(indent).append("public override string ToString()\n") + .append(indent).append("public string ToSbeString()\n") .append(indent).append("{\n") .append(indent).append(INDENT) .append("var buffer = new DirectBuffer(new byte[128], (ignored, newSize) => new byte[newSize]);\n") @@ -800,6 +825,11 @@ private void generateFields( } } + private String optionality(final Token fieldToken, final Token typeToken) + { + return fieldToken.isOptionalEncoding() ? "?" : ""; + } + private void generateCompositeProperty( final StringBuilder sb, final String propertyName, @@ -807,11 +837,12 @@ private void generateCompositeProperty( final Token typeToken, final String indent) { - final String bitSetName = formatDtoClassName(typeToken.applicableTypeName()); + final String compositeName = formatDtoClassName(typeToken.applicableTypeName()); sb.append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("public ").append(bitSetName).append(" ").append(formatPropertyName(propertyName)) - .append(" { get; set; } = new ").append(bitSetName).append("();\n"); + .append(indent).append("public ").append(compositeName) + .append(optionality(fieldToken, typeToken)).append(" ").append(formatPropertyName(propertyName)) + .append(" { get; init; }\n"); } private void generateBitSetProperty( @@ -826,7 +857,7 @@ private void generateBitSetProperty( sb.append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("public ").append(enumName).append(" ") - .append(formatPropertyName(propertyName)).append(" { get; set; }\n"); + .append(formatPropertyName(propertyName)).append(" { get; init; }\n"); } private void generateEnumProperty( @@ -856,8 +887,8 @@ private void generateEnumProperty( { sb.append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("public ").append(enumName).append(" ").append(formatPropertyName(propertyName)) - .append(" { get; set; }\n"); + .append(indent).append("public ").append(enumName).append(" ") + .append(formatPropertyName(propertyName)).append(" { get; init; }\n"); } } @@ -909,7 +940,7 @@ private void generateArrayProperty( sb.append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("public string ") - .append(formatPropertyName(propertyName)).append(" { get; set; }\n"); + .append(formatPropertyName(propertyName)).append(" { get; init; }\n"); } else { @@ -917,8 +948,9 @@ private void generateArrayProperty( sb.append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("public ").append(typeName).append("[] ") - .append(formatPropertyName(propertyName)).append(" { get; set; }\n"); + .append(indent).append("public IReadOnlyList<").append(typeName).append(">") + .append(optionality(fieldToken, typeToken)).append(" ") + .append(formatPropertyName(propertyName)).append(" { get; init; }\n"); } } @@ -933,8 +965,9 @@ private void generateSingleValueProperty( sb.append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("public ").append(typeName).append(" ") - .append(formatPropertyName(propertyName)).append(" { get; set; }\n"); + .append(indent).append("public ").append(typeName) + .append(optionality(fieldToken, typeToken)).append(" ") + .append(formatPropertyName(propertyName)).append(" { get; init; }\n"); } private void generateConstPropertyMethods( @@ -984,9 +1017,11 @@ private void generateVarData( final String characterEncoding = varDataToken.encoding().characterEncoding(); final String dtoType = characterEncoding == null ? "byte[]" : "string"; + final String optionality = token.version() > 0 ? "?" : ""; + sb.append("\n") .append(indent).append("public ").append(dtoType).append(" ") - .append(formatPropertyName(propertyName)).append(" { get; set; }\n"); + .append(formatPropertyName(propertyName)).append(" { get; init; }\n"); } } } @@ -1020,14 +1055,17 @@ private void generateComposite(final List tokens) throws IOException try (Writer out = outputManager.createOutput(className)) { - out.append(generateFileHeader(ir.applicableNamespace())); + out.append(generateFileHeader(ir.applicableNamespace(), + "#nullable enable\n", + "using System.Collections.Generic;\n", + "using System.Linq;\n")); out.append(generateDocumentation(BASE_INDENT, tokens.get(0))); final StringBuilder sb = new StringBuilder(); final List compositeTokens = tokens.subList(1, tokens.size() - 1); generateCompositePropertyElements(sb, compositeTokens, BASE_INDENT + INDENT); - generateCompositeDecodeFrom(sb, codecClassName, compositeTokens, BASE_INDENT + INDENT); + generateCompositeDecodeFrom(sb, className, codecClassName, compositeTokens, BASE_INDENT + INDENT); generateCompositeEncodeInto(sb, codecClassName, compositeTokens, BASE_INDENT + INDENT); generateDisplay(sb, codecClassName, "Wrap", codecClassName + ".SbeSchemaVersion", BASE_INDENT + INDENT); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index 124b352629..1fc1cb64b2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -85,20 +85,20 @@ static String generateLiteral(final PrimitiveType type, final String value) return literal; } - static CharSequence generateFileHeader(final String packageName, final String... imports) + static CharSequence generateFileHeader(final String packageName, final String... topLevelStatements) { return String.format( "// \n" + "// Generated SBE (Simple Binary Encoding) message codec\n" + "// \n\n" + "#pragma warning disable 1591 // disable warning on missing comments\n" + + "%1$s" + "using System;\n" + "using System.Text;\n" + - "%1$s" + "using Org.SbeTool.Sbe.Dll;\n\n" + "namespace %2$s\n" + "{\n", - String.join("", imports), + String.join("", topLevelStatements), formatNamespace(packageName)); } diff --git a/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/Program.cs b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/Program.cs index 1efcf4bfa7..60bdc22616 100644 --- a/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/Program.cs +++ b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/Program.cs @@ -17,8 +17,7 @@ static int Main(string[] args) { messageHeader.Wrap(buffer, 0, 0); var decoder = new TestMessage(); decoder.WrapForDecode(buffer, 8, messageHeader.BlockLength, messageHeader.Version); - var dto = new TestMessageDto(); - dto.DecodeFrom(decoder); + var dto = TestMessageDto.DecodeFrom(decoder); var outputBytes = new byte[inputBytes.Length]; var outputBuffer = new DirectBuffer(outputBytes); var encoder = new TestMessage(); diff --git a/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj index a1bbc69f1c..8b0b167d2b 100644 --- a/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj +++ b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net6.0 From 207ab1f3be2e28c9d3aa867f8dedf82191a6ebb9 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 18 Oct 2023 14:23:08 +0100 Subject: [PATCH 1145/1594] [IR] Change default float and double values to minimum representable values. Previously, we were using the minimum positive value as the `minValue`. --- .../src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index 27411749b5..0754d9a485 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -197,7 +197,7 @@ public enum Representation /** * Maximum value representation for a single precision 32-bit floating point type. */ - public static final float MIN_VALUE_FLOAT = Float.MIN_VALUE; + public static final float MIN_VALUE_FLOAT = -Float.MAX_VALUE; /** * Maximum value representation for a single precision 32-bit floating point type. @@ -212,7 +212,7 @@ public enum Representation /** * Minimum value representation for a double precision 64-bit floating point type. */ - public static final double MIN_VALUE_DOUBLE = Double.MIN_VALUE; + public static final double MIN_VALUE_DOUBLE = -Double.MAX_VALUE; /** * Maximum value representation for a double precision 64-bit floating point type. From 4201789439cd009daa73683231485bc6dc0295de Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 18 Oct 2023 15:57:17 +0100 Subject: [PATCH 1146/1594] [C#] Add validation to DTOs and improve use of records. The aim of these changes are to avoid multiple representations in DTOs and to support read-only views over data. The new validation includes: - Checking null values "idiomatic null values" rather than the reserved null value, to prevent against multiple kinds of null in DTOs. - Checking primitive field values are at least `minValue` and at most `maxValue`. Note that this validation is not applied to fixed-size arrays as the specification says, "Data range attributes minValue and maxValue do not apply", under the "Fixed-length data" section. Records are now immutable. Record expressions, i.e., using `with`, are supported and will apply validation, as we have customised the `init` property accessor. I have not included support for encoding null composite values from DTOs; however, in theory, this could be added later. --- .../generation/csharp/CSharpDtoGenerator.java | 347 ++++++++++++++---- .../arbitraries/SbeArbitraries.java | 7 +- 2 files changed, 278 insertions(+), 76 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java index b6ab8638d9..d50030351a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -79,23 +79,26 @@ public void generate() throws IOException int offset = 0; final StringBuilder sb = new StringBuilder(); + final StringBuilder ctorArgs = new StringBuilder(); final List fields = new ArrayList<>(); offset = collectFields(messageBody, offset, fields); - generateFields(sb, fields, BASE_INDENT + INDENT); + generateFields(sb, ctorArgs, codecClassName, fields, BASE_INDENT + INDENT); final List groups = new ArrayList<>(); offset = collectGroups(messageBody, offset, groups); - generateGroups(sb, codecClassName, groups, BASE_INDENT + INDENT); + generateGroups(sb, ctorArgs, className, codecClassName, groups, BASE_INDENT + INDENT); final List varData = new ArrayList<>(); collectVarData(messageBody, offset, varData); - generateVarData(sb, varData, BASE_INDENT + INDENT); + generateVarData(sb, ctorArgs, varData, BASE_INDENT + INDENT); generateDecodeFrom(sb, className, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); generateEncodeInto(sb, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); generateDisplay(sb, codecClassName, "WrapForEncode", null, BASE_INDENT + INDENT); + removeTrailingComma(ctorArgs); + try (Writer out = outputManager.createOutput(className)) { out.append(generateFileHeader( @@ -105,7 +108,9 @@ public void generate() throws IOException "using System.Linq;\n")); out.append(generateDocumentation(BASE_INDENT, msgToken)); - out.append(BASE_INDENT).append("public sealed partial record ").append(className).append("\n") + out.append(BASE_INDENT).append("public sealed partial record ").append(className).append("(\n") + .append(ctorArgs) + .append(BASE_INDENT).append(")\n") .append(BASE_INDENT).append("{") .append(sb) .append(BASE_INDENT).append("}\n") @@ -116,7 +121,9 @@ public void generate() throws IOException private void generateGroups( final StringBuilder sb, - final String parentMessageClassName, + final StringBuilder ctorArgs, + final String qualifiedParentDtoClassName, + final String qualifiedParentCodecClassName, final List tokens, final String indent) { @@ -130,38 +137,58 @@ private void generateGroups( final String groupName = groupToken.name(); final String groupClassName = formatDtoClassName(groupName); + final String formattedPropertyName = formatPropertyName(groupName); + + ctorArgs.append(indent).append("IReadOnlyList<") + .append(qualifiedParentDtoClassName).append(".").append(groupClassName).append("> ") + .append(formattedPropertyName).append(",\n"); + sb.append("\n") .append(generateDocumentation(indent, groupToken)) .append(indent).append("public IReadOnlyList<").append(groupClassName).append("> ") - .append(formatPropertyName(groupName)) - .append(" { get; init; }\n"); + .append(formattedPropertyName) + .append(" { get; init; } = ").append(formattedPropertyName).append(";\n"); - sb.append("\n") - .append(generateDocumentation(indent, groupToken)) - .append(indent).append("public sealed partial record ").append(groupClassName).append("\n") - .append(indent).append("{"); + final StringBuilder groupCtorArgs = new StringBuilder(); + final StringBuilder groupRecordBody = new StringBuilder(); i++; i += tokens.get(i).componentTokenCount(); + final String qualifiedDtoClassName = qualifiedParentDtoClassName + "." + groupClassName; + final String qualifiedCodecClassName = + qualifiedParentCodecClassName + "." + formatClassName(groupName) + "Group"; + final List fields = new ArrayList<>(); i = collectFields(tokens, i, fields); - generateFields(sb, fields, indent + INDENT); + generateFields(groupRecordBody, groupCtorArgs, qualifiedCodecClassName, fields, indent + INDENT); final List groups = new ArrayList<>(); i = collectGroups(tokens, i, groups); - final String codecClassName = parentMessageClassName + "." + formatClassName(groupName) + "Group"; - generateGroups(sb, codecClassName, groups, indent + INDENT); + generateGroups(groupRecordBody, groupCtorArgs, qualifiedDtoClassName, + qualifiedCodecClassName, groups, indent + INDENT); final List varData = new ArrayList<>(); i = collectVarData(tokens, i, varData); - generateVarData(sb, varData, indent + INDENT); + generateVarData(groupRecordBody, groupCtorArgs, varData, indent + INDENT); - generateDecodeListFrom(sb, groupClassName, codecClassName, indent + INDENT); - generateDecodeFrom(sb, groupClassName, codecClassName, fields, groups, varData, indent + INDENT); - generateEncodeInto(sb, codecClassName, fields, groups, varData, indent + INDENT); + generateDecodeListFrom( + groupRecordBody, groupClassName, qualifiedCodecClassName, indent + INDENT); + generateDecodeFrom( + groupRecordBody, groupClassName, qualifiedCodecClassName, fields, groups, varData, indent + INDENT); + generateEncodeInto( + groupRecordBody, qualifiedCodecClassName, fields, groups, varData, indent + INDENT); - sb.append(indent).append("}\n"); + removeTrailingComma(groupCtorArgs); + + sb.append("\n") + .append(generateDocumentation(indent, groupToken)) + .append(indent).append("public sealed partial record ").append(groupClassName).append("(\n") + .append(groupCtorArgs) + .append(indent).append(")\n") + .append(indent).append("{\n") + .append(groupRecordBody) + .append(indent).append("}\n"); } } @@ -177,8 +204,7 @@ private void generateCompositeDecodeFrom( .append(codecClassName).append(" codec)\n") .append(indent).append("{\n"); - sb.append(indent).append(INDENT).append("return new ").append(dtoClassName).append("()\n") - .append(indent).append(INDENT).append("{\n"); + sb.append(indent).append(INDENT).append("return new ").append(dtoClassName).append("(\n"); for (int i = 0; i < tokens.size(); ) { @@ -189,7 +215,9 @@ private void generateCompositeDecodeFrom( i += tokens.get(i).componentTokenCount(); } - sb.append(indent).append(INDENT).append("};\n"); + removeTrailingComma(sb); + + sb.append(indent).append(INDENT).append(");\n"); sb.append(indent).append("}\n"); } @@ -256,12 +284,12 @@ private void generateDecodeFrom( .append(" DecodeFrom(").append(codecClassName).append(" codec)\n") .append(indent).append("{\n"); - sb.append(indent).append(INDENT).append("return new ").append(dtoClassName).append("()\n") - .append(indent).append(INDENT).append("{\n"); + sb.append(indent).append(INDENT).append("return new ").append(dtoClassName).append("(\n"); generateFieldsDecodeFrom(sb, fields, codecClassName, indent + INDENT + INDENT); generateGroupsDecodeFrom(sb, groups, indent + INDENT + INDENT); generateVarDataDecodeFrom(sb, varData, indent + INDENT + INDENT); - sb.append(indent).append(INDENT).append("};\n"); + removeTrailingComma(sb); + sb.append(indent).append(INDENT).append(");\n"); sb.append(indent).append("}\n"); } @@ -297,13 +325,13 @@ private void generateFieldDecodeFrom( break; case BEGIN_SET: - generatePropertyDecodeFrom(sb, codecClassName, fieldToken, "0", indent); + generatePropertyDecodeFrom(sb, fieldToken, "0", null, indent); break; case BEGIN_ENUM: final String enumName = formatClassName(typeToken.applicableTypeName()); final String nullValue = formatNamespace(ir.packageName()) + "." + enumName + ".NULL_VALUE"; - generatePropertyDecodeFrom(sb, codecClassName, fieldToken, nullValue, indent); + generatePropertyDecodeFrom(sb, fieldToken, nullValue, null, indent); break; case BEGIN_COMPOSITE: @@ -331,8 +359,8 @@ private void generatePrimitiveDecodeFrom( if (arrayLength == 1) { - final String nullValue = codecClassName + "." + formatPropertyName(fieldToken.name()) + "NullValue"; - generatePropertyDecodeFrom(sb, codecClassName, fieldToken, nullValue, indent); + final String codecNullValue = codecClassName + "." + formatPropertyName(fieldToken.name()) + "NullValue"; + generatePropertyDecodeFrom(sb, fieldToken, "null", codecNullValue, indent); } else if (arrayLength > 1) { @@ -356,7 +384,7 @@ private void generateArrayDecodeFrom( if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { - wrapInActingVersionCheck( + generateRecordPropertyAssignment( sb, fieldToken, indent, @@ -367,7 +395,7 @@ private void generateArrayDecodeFrom( } else { - wrapInActingVersionCheck( + generateRecordPropertyAssignment( sb, fieldToken, indent, @@ -380,12 +408,11 @@ private void generateArrayDecodeFrom( private void generatePropertyDecodeFrom( final StringBuilder sb, - final String codecClassName, final Token fieldToken, - final String nullValue, + final String dtoNullValue, + final String codecNullValue, final String indent) { - if (fieldToken.isConstantEncoding()) { return; @@ -394,13 +421,13 @@ private void generatePropertyDecodeFrom( final String propertyName = fieldToken.name(); final String formattedPropertyName = formatPropertyName(propertyName); - wrapInActingVersionCheck( + generateRecordPropertyAssignment( sb, fieldToken, indent, "codec." + formattedPropertyName, - nullValue, - codecClassName + "." + formattedPropertyName + "NullValue" + dtoNullValue, + codecNullValue ); } @@ -414,7 +441,7 @@ private void generateComplexDecodeFrom( final String formattedPropertyName = formatPropertyName(propertyName); final String dtoClassName = formatDtoClassName(typeToken.applicableTypeName()); - wrapInActingVersionCheck( + generateRecordPropertyAssignment( sb, fieldToken, indent, @@ -440,7 +467,7 @@ private void generateGroupsDecodeFrom( final String formattedPropertyName = formatPropertyName(groupName); final String groupDtoClassName = formatDtoClassName(groupName); - wrapInActingVersionCheck( + generateRecordPropertyAssignment( sb, groupToken, indent, @@ -482,7 +509,7 @@ private void generateVarDataDecodeFrom( "Get" + formattedPropertyName + "Bytes" : "Get" + formattedPropertyName; - wrapInActingVersionCheck( + generateRecordPropertyAssignment( sb, token, indent, @@ -494,7 +521,7 @@ private void generateVarDataDecodeFrom( } } - private void wrapInActingVersionCheck( + private void generateRecordPropertyAssignment( final StringBuilder sb, final Token token, final String indent, @@ -505,7 +532,7 @@ private void wrapInActingVersionCheck( final String propertyName = token.name(); final String formattedPropertyName = formatPropertyName(propertyName); - sb.append(indent).append(formattedPropertyName).append(" = "); + sb.append(indent).append(formattedPropertyName).append(": "); if (token.version() > 0) { @@ -699,6 +726,17 @@ private void generateComplexEncodeInto( { final String propertyName = fieldToken.name(); final String formattedPropertyName = formatPropertyName(propertyName); + + if (fieldToken.isOptionalEncoding()) + { + sb.append(indent).append("if (null == ").append(formattedPropertyName).append(")\n") + .append(indent).append("{") + .append(indent).append(INDENT).append("throw new System.InvalidOperationException(\"") + .append("Null composite value encoding (").append(formattedPropertyName) + .append(") is not supported via DTOs\");\n") + .append(indent).append("}\n\n"); + } + sb.append(indent).append(formattedPropertyName).append(".EncodeInto(codec.") .append(formattedPropertyName).append(");\n"); } @@ -789,6 +827,8 @@ private void generateDisplay( private void generateFields( final StringBuilder sb, + final StringBuilder ctorArgs, + final String codecClassName, final List tokens, final String indent) { @@ -803,19 +843,20 @@ private void generateFields( switch (encodingToken.signal()) { case ENCODING: - generatePrimitiveProperty(sb, propertyName, signalToken, encodingToken, indent); + generatePrimitiveProperty( + sb, ctorArgs, codecClassName, propertyName, signalToken, encodingToken, indent); break; case BEGIN_ENUM: - generateEnumProperty(sb, propertyName, signalToken, encodingToken, indent); + generateEnumProperty(sb, ctorArgs, propertyName, signalToken, encodingToken, indent); break; case BEGIN_SET: - generateBitSetProperty(sb, propertyName, signalToken, encodingToken, indent); + generateBitSetProperty(sb, ctorArgs, propertyName, signalToken, encodingToken, indent); break; case BEGIN_COMPOSITE: - generateCompositeProperty(sb, propertyName, signalToken, encodingToken, indent); + generateCompositeProperty(sb, ctorArgs, propertyName, signalToken, encodingToken, indent); break; default: @@ -825,28 +866,30 @@ private void generateFields( } } - private String optionality(final Token fieldToken, final Token typeToken) - { - return fieldToken.isOptionalEncoding() ? "?" : ""; - } - private void generateCompositeProperty( final StringBuilder sb, + final StringBuilder ctorArgs, final String propertyName, final Token fieldToken, final Token typeToken, final String indent) { final String compositeName = formatDtoClassName(typeToken.applicableTypeName()); + final String nullableSuffix = fieldToken.isOptionalEncoding() ? "?" : ""; + final String formattedPropertyName = formatPropertyName(propertyName); + + ctorArgs.append(indent).append(compositeName).append(" ").append(formattedPropertyName).append(",\n"); + sb.append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("public ").append(compositeName) - .append(optionality(fieldToken, typeToken)).append(" ").append(formatPropertyName(propertyName)) - .append(" { get; init; }\n"); + .append(nullableSuffix).append(" ").append(formattedPropertyName) + .append(" { get; init; } = ").append(formattedPropertyName).append(";\n"); } private void generateBitSetProperty( final StringBuilder sb, + final StringBuilder ctorArgs, final String propertyName, final Token fieldToken, final Token typeToken, @@ -854,14 +897,20 @@ private void generateBitSetProperty( { final String enumName = formatClassName(typeToken.applicableTypeName()); + final String formattedPropertyName = formatPropertyName(propertyName); + + ctorArgs.append(indent).append(enumName).append(" ").append(formattedPropertyName).append(",\n"); + sb.append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("public ").append(enumName).append(" ") - .append(formatPropertyName(propertyName)).append(" { get; init; }\n"); + .append(formattedPropertyName).append(" { get; init; } = ") + .append(formattedPropertyName).append(";\n"); } private void generateEnumProperty( final StringBuilder sb, + final StringBuilder ctorArgs, final String propertyName, final Token fieldToken, final Token typeToken, @@ -869,6 +918,8 @@ private void generateEnumProperty( { final String enumName = formatClassName(typeToken.applicableTypeName()); + final String formattedPropertyName = formatPropertyName(propertyName); + if (fieldToken.isConstantEncoding()) { final String constValue = fieldToken.encoding().constValue().toString(); @@ -876,7 +927,7 @@ private void generateEnumProperty( sb.append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("public static ").append(enumName).append(" ") - .append(formatPropertyName(propertyName)).append("\n") + .append(formattedPropertyName).append("\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("get { return ") .append(formatNamespace(ir.packageName())).append(".").append(constValue) @@ -885,15 +936,19 @@ private void generateEnumProperty( } else { + ctorArgs.append(indent).append(enumName).append(" ").append(formattedPropertyName).append(",\n"); + sb.append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("public ").append(enumName).append(" ") - .append(formatPropertyName(propertyName)).append(" { get; init; }\n"); + .append(formattedPropertyName).append(" { get; init; } = ").append(formattedPropertyName).append(";\n"); } } private void generatePrimitiveProperty( final StringBuilder sb, + final StringBuilder ctorArgs, + final String codecClassName, final String propertyName, final Token fieldToken, final Token typeToken, @@ -905,12 +960,14 @@ private void generatePrimitiveProperty( } else { - generatePrimitivePropertyMethods(sb, propertyName, fieldToken, typeToken, indent); + generatePrimitivePropertyMethods(sb, ctorArgs, codecClassName, propertyName, fieldToken, typeToken, indent); } } private void generatePrimitivePropertyMethods( final StringBuilder sb, + final StringBuilder ctorArgs, + final String codecClassName, final String propertyName, final Token fieldToken, final Token typeToken, @@ -920,54 +977,162 @@ private void generatePrimitivePropertyMethods( if (arrayLength == 1) { - generateSingleValueProperty(sb, propertyName, fieldToken, typeToken, indent); + generateSingleValueProperty(sb, ctorArgs, codecClassName, propertyName, fieldToken, typeToken, indent); } else if (arrayLength > 1) { - generateArrayProperty(sb, propertyName, fieldToken, typeToken, indent); + generateArrayProperty(sb, ctorArgs, codecClassName, propertyName, fieldToken, typeToken, indent); } } private void generateArrayProperty( final StringBuilder sb, + final StringBuilder ctorArgs, + final String codecClassName, final String propertyName, final Token fieldToken, final Token typeToken, final String indent) { + final String formattedPropertyName = formatPropertyName(propertyName); + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { + ctorArgs.append(indent).append("string ").append(formattedPropertyName).append(",\n"); + sb.append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("public string ") - .append(formatPropertyName(propertyName)).append(" { get; init; }\n"); + .append(formattedPropertyName).append(" { get; init; } = ") + .append(formattedPropertyName).append(";\n"); } else { final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); + final String fieldName = "_" + toLowerFirstChar(propertyName); + final String nullableSuffix = fieldToken.isOptionalEncoding() ? "?" : ""; + final String listTypeName = "IReadOnlyList<" + typeName + ">" + nullableSuffix; + + ctorArgs.append(indent).append(listTypeName).append(" ").append(formattedPropertyName).append(",\n"); + + sb.append("\n") + .append(indent).append("private ").append(listTypeName).append(" ").append(fieldName) + .append(" = Validate").append(formattedPropertyName).append("(").append(formattedPropertyName) + .append(");\n"); sb.append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("public IReadOnlyList<").append(typeName).append(">") - .append(optionality(fieldToken, typeToken)).append(" ") - .append(formatPropertyName(propertyName)).append(" { get; init; }\n"); + .append(indent).append("public ").append(listTypeName).append(" ") + .append(formattedPropertyName).append("\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("get => ").append(fieldName).append(";\n") + .append(indent).append(INDENT).append("init => ").append(fieldName).append(" = Validate") + .append(formattedPropertyName).append("(value);\n") + .append(indent).append("}\n"); + + sb.append("\n") + .append(indent).append("private static ").append(listTypeName).append(" Validate") + .append(formattedPropertyName).append("(").append(listTypeName).append(" value)\n") + .append(indent).append("{\n"); + + if (fieldToken.isOptionalEncoding()) + { + sb.append(indent).append(INDENT) + .append("if (value == null)\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("return null;\n") + .append(indent).append(INDENT) + .append("}\n"); + } + + sb.append(indent).append(INDENT) + .append("if (value.Count > ").append(codecClassName).append(".") + .append(formattedPropertyName).append("Length)\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("throw new ArgumentException(\"too many elements: \" + value.Count);\n") + .append(indent).append(INDENT) + .append("}\n") + .append(indent).append(INDENT) + .append("return value;\n") + .append(indent).append("}\n"); } } private void generateSingleValueProperty( final StringBuilder sb, + final StringBuilder ctorArgs, + final String codecClassName, final String propertyName, final Token fieldToken, final Token typeToken, final String indent) { - final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); + final String nullableSuffix = fieldToken.isOptionalEncoding() ? "?" : ""; + final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()) + nullableSuffix; + final String formattedPropertyName = formatPropertyName(propertyName); + final String fieldName = "_" + toLowerFirstChar(propertyName); + + ctorArgs.append(indent).append(typeName).append(" ").append(formattedPropertyName).append(",\n"); + + sb.append("\n") + .append(indent).append("private ").append(typeName).append(" ").append(fieldName) + .append(" = Validate").append(formattedPropertyName) + .append("(").append(formattedPropertyName).append(");\n"); sb.append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("public ").append(typeName) - .append(optionality(fieldToken, typeToken)).append(" ") - .append(formatPropertyName(propertyName)).append(" { get; init; }\n"); + .append(indent).append("public ").append(typeName).append(" ") + .append(formattedPropertyName).append("\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("get => ").append(fieldName).append(";\n") + .append(indent).append(INDENT).append("init => ").append(fieldName).append(" = Validate") + .append(formattedPropertyName).append("(value);\n") + .append(indent).append("}\n"); + + sb.append("\n") + .append(indent).append("private static ").append(typeName).append(" Validate") + .append(formattedPropertyName).append("(").append(typeName).append(" value)\n") + .append(indent).append("{\n"); + + if (fieldToken.isOptionalEncoding()) + { + sb.append(indent).append(INDENT) + .append("if (value == null)\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("return null;\n") + .append(indent).append(INDENT) + .append("}\n"); + + sb.append(indent).append(INDENT) + .append("if (value == ").append(codecClassName).append(".") + .append(formattedPropertyName).append("NullValue)\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("throw new ArgumentException(\"null value is reserved: \" + value);\n") + .append(indent).append(INDENT) + .append("}\n"); + } + + sb.append(indent).append(INDENT) + .append("if (value < ") + .append(codecClassName).append(".").append(formattedPropertyName).append("MinValue || value > ") + .append(codecClassName).append(".").append(formattedPropertyName).append("MaxValue)\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("throw new ArgumentException(\"value is out of allowed range: \" + value);\n") + .append(indent).append(INDENT) + .append("}\n") + .append(indent).append(INDENT) + .append("return value;\n") + .append(indent).append("}\n"); } private void generateConstPropertyMethods( @@ -1004,6 +1169,7 @@ private void generateConstPropertyMethods( private void generateVarData( final StringBuilder sb, + final StringBuilder ctorArgs, final List tokens, final String indent) { @@ -1017,11 +1183,14 @@ private void generateVarData( final String characterEncoding = varDataToken.encoding().characterEncoding(); final String dtoType = characterEncoding == null ? "byte[]" : "string"; - final String optionality = token.version() > 0 ? "?" : ""; + final String formattedPropertyName = formatPropertyName(propertyName); + + ctorArgs.append(indent).append(dtoType).append(" ").append(formattedPropertyName).append(",\n"); sb.append("\n") .append(indent).append("public ").append(dtoType).append(" ") - .append(formatPropertyName(propertyName)).append(" { get; init; }\n"); + .append(formattedPropertyName).append(" { get; init; } = ") + .append(formattedPropertyName).append(";\n"); } } } @@ -1062,14 +1231,19 @@ private void generateComposite(final List tokens) throws IOException out.append(generateDocumentation(BASE_INDENT, tokens.get(0))); final StringBuilder sb = new StringBuilder(); + final StringBuilder ctorArgs = new StringBuilder(); final List compositeTokens = tokens.subList(1, tokens.size() - 1); - generateCompositePropertyElements(sb, compositeTokens, BASE_INDENT + INDENT); + generateCompositePropertyElements(sb, ctorArgs, codecClassName, compositeTokens, BASE_INDENT + INDENT); generateCompositeDecodeFrom(sb, className, codecClassName, compositeTokens, BASE_INDENT + INDENT); generateCompositeEncodeInto(sb, codecClassName, compositeTokens, BASE_INDENT + INDENT); generateDisplay(sb, codecClassName, "Wrap", codecClassName + ".SbeSchemaVersion", BASE_INDENT + INDENT); - out.append(BASE_INDENT).append("public sealed partial record ").append(className).append("\n") + removeTrailingComma(ctorArgs); + + out.append(BASE_INDENT).append("public sealed partial record ").append(className).append("(\n") + .append(ctorArgs) + .append(BASE_INDENT).append(")\n") .append(BASE_INDENT).append("{") .append(sb) .append(BASE_INDENT).append("}\n") @@ -1077,8 +1251,31 @@ private void generateComposite(final List tokens) throws IOException } } + private static void removeTrailingComma(final StringBuilder ctorArgs) + { + if (ctorArgs.length() < 2) + { + return; + } + + if (ctorArgs.charAt(ctorArgs.length() - 1) != '\n') + { + return; + } + + if (ctorArgs.charAt(ctorArgs.length() - 2) != ',') + { + return; + } + + ctorArgs.setLength(ctorArgs.length() - 2); + ctorArgs.append("\n"); + } + private void generateCompositePropertyElements( final StringBuilder sb, + final StringBuilder ctorArgs, + final String codecClassName, final List tokens, final String indent) { @@ -1090,19 +1287,19 @@ private void generateCompositePropertyElements( switch (token.signal()) { case ENCODING: - generatePrimitiveProperty(sb, propertyName, token, token, indent); + generatePrimitiveProperty(sb, ctorArgs, codecClassName, propertyName, token, token, indent); break; case BEGIN_ENUM: - generateEnumProperty(sb, propertyName, token, token, indent); + generateEnumProperty(sb, ctorArgs, propertyName, token, token, indent); break; case BEGIN_SET: - generateBitSetProperty(sb, propertyName, token, token, indent); + generateBitSetProperty(sb, ctorArgs, propertyName, token, token, indent); break; case BEGIN_COMPOSITE: - generateCompositeProperty(sb, propertyName, token, token, indent); + generateCompositeProperty(sb, ctorArgs, propertyName, token, token, indent); break; default: diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index 2e3db4bda0..b1b025d4d9 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -324,7 +324,12 @@ private static Arbitrary encodedTypeEncoder( case UINT64: return Arbitraries.longs() - .map(l -> (buffer, offset, limit) -> buffer.putLong(offset, l, encoding.byteOrder())); + .map(l -> (buffer, offset, limit) -> + { + final long nullValue = encoding.applicableNullValue().longValue(); + final long nonNullValue = l == nullValue ? minValue.longValue() : l; + buffer.putLong(offset, nonNullValue, encoding.byteOrder()); + }); case INT64: assert minValue.longValue() <= maxValue.longValue(); From bc17a46ba35ed5c8adc175d95fac952325be14d5 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 18 Oct 2023 16:57:47 +0100 Subject: [PATCH 1147/1594] [C#] Support DTO generation via system property. Previously, you had to pass the `CSharpDtos` FQN as the `TargetCodeGenerator` when running sbe-tool; however, that means the XML schema was parsed multiple times, as DTOs depend on flyweights, which seems wasteful. Therefore, I have introduced a system property, `sbe.csharp.generate.dtos` that also controls the generation of DTOs when targetting `CSharp`. --- .../sbe/generation/csharp/CSharp.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java index 157309f319..8a88cbce56 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java @@ -26,14 +26,30 @@ */ public class CSharp implements TargetCodeGenerator { + private static final boolean GENERATE_DTOS = Boolean.getBoolean("sbe.csharp.generate.dtos"); + /** * {@inheritDoc} */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { - return new CSharpGenerator( + final CSharpGenerator flyweightGenerator = new CSharpGenerator( ir, TargetCodeGeneratorLoader.precedenceChecks(), new CSharpNamespaceOutputManager(outputDir, ir.applicableNamespace())); + + if (GENERATE_DTOS) + { + final CSharpDtoGenerator dtoGenerator = + new CSharpDtoGenerator(ir, new CSharpNamespaceOutputManager(outputDir, ir.applicableNamespace())); + + return () -> + { + flyweightGenerator.generate(); + dtoGenerator.generate(); + }; + } + + return flyweightGenerator; } } From 248eae90e8c67111e1888a7f7fd9dec0c90a9da2 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Thu, 19 Oct 2023 16:49:33 +0100 Subject: [PATCH 1148/1594] [C#] Extend tests to cover extended schemas. These tests showed some deficiencies in the DTO generation. For example, added variable-length data was not represented as nullable nor properly handled in `EncodeInto(...)`. During this work, I noticed composite "field" tokens (i.e., types) take their `token.version()` from their containing message/group field. I had to adjust some code that was using `token.version() > 0` to determine whether a field had been added, as this only works with message/group fields. --- .../generation/csharp/CSharpDtoGenerator.java | 87 ++++++++++++++----- .../properties/CSharpDtosPropertyTest.java | 11 +++ .../arbitraries/SbeArbitraries.java | 55 +++++++++--- .../sbe/properties/schema/FieldSchema.java | 11 ++- .../sbe/properties/schema/GroupSchema.java | 10 ++- .../sbe/properties/schema/MessageSchema.java | 35 +++++++- .../schema/TestXmlSchemaWriter.java | 3 + .../sbe/properties/schema/VarDataSchema.java | 10 ++- 8 files changed, 184 insertions(+), 38 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java index d50030351a..9335295663 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -93,8 +93,8 @@ public void generate() throws IOException collectVarData(messageBody, offset, varData); generateVarData(sb, ctorArgs, varData, BASE_INDENT + INDENT); - generateDecodeFrom(sb, className, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); - generateEncodeInto(sb, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); + generateMessageDecodeFrom(sb, className, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); + generateMessageEncodeInto(sb, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); generateDisplay(sb, codecClassName, "WrapForEncode", null, BASE_INDENT + INDENT); removeTrailingComma(ctorArgs); @@ -119,6 +119,12 @@ public void generate() throws IOException } } + private enum DefinitionKind + { + Composite, + Message + } + private void generateGroups( final StringBuilder sb, final StringBuilder ctorArgs, @@ -174,9 +180,9 @@ private void generateGroups( generateDecodeListFrom( groupRecordBody, groupClassName, qualifiedCodecClassName, indent + INDENT); - generateDecodeFrom( + generateMessageDecodeFrom( groupRecordBody, groupClassName, qualifiedCodecClassName, fields, groups, varData, indent + INDENT); - generateEncodeInto( + generateMessageEncodeInto( groupRecordBody, qualifiedCodecClassName, fields, groups, varData, indent + INDENT); removeTrailingComma(groupCtorArgs); @@ -210,7 +216,8 @@ private void generateCompositeDecodeFrom( { final Token token = tokens.get(i); - generateFieldDecodeFrom(sb, token, token, codecClassName, indent + INDENT + INDENT); + generateFieldDecodeFrom( + sb, DefinitionKind.Composite, token, token, codecClassName, indent + INDENT + INDENT); i += tokens.get(i).componentTokenCount(); } @@ -270,7 +277,7 @@ private void generateDecodeListFrom( .append(indent).append("}\n"); } - private void generateDecodeFrom( + private void generateMessageDecodeFrom( final StringBuilder sb, final String dtoClassName, final String codecClassName, @@ -285,7 +292,7 @@ private void generateDecodeFrom( .append(indent).append("{\n"); sb.append(indent).append(INDENT).append("return new ").append(dtoClassName).append("(\n"); - generateFieldsDecodeFrom(sb, fields, codecClassName, indent + INDENT + INDENT); + generateMessageFieldsDecodeFrom(sb, fields, codecClassName, indent + INDENT + INDENT); generateGroupsDecodeFrom(sb, groups, indent + INDENT + INDENT); generateVarDataDecodeFrom(sb, varData, indent + INDENT + INDENT); removeTrailingComma(sb); @@ -294,7 +301,7 @@ private void generateDecodeFrom( sb.append(indent).append("}\n"); } - private void generateFieldsDecodeFrom( + private void generateMessageFieldsDecodeFrom( final StringBuilder sb, final List tokens, final String codecClassName, @@ -307,35 +314,37 @@ private void generateFieldsDecodeFrom( { final Token encodingToken = tokens.get(i + 1); - generateFieldDecodeFrom(sb, signalToken, encodingToken, codecClassName, indent); + generateFieldDecodeFrom(sb, DefinitionKind.Message, signalToken, encodingToken, codecClassName, indent); } } } private void generateFieldDecodeFrom( final StringBuilder sb, + final DefinitionKind rootKind, final Token fieldToken, final Token typeToken, - final String codecClassName, final String indent) + final String codecClassName, + final String indent) { switch (typeToken.signal()) { case ENCODING: - generatePrimitiveDecodeFrom(sb, fieldToken, typeToken, codecClassName, indent); + generatePrimitiveDecodeFrom(sb, rootKind, fieldToken, typeToken, codecClassName, indent); break; case BEGIN_SET: - generatePropertyDecodeFrom(sb, fieldToken, "0", null, indent); + generatePropertyDecodeFrom(sb, rootKind, fieldToken, "0", null, indent); break; case BEGIN_ENUM: final String enumName = formatClassName(typeToken.applicableTypeName()); final String nullValue = formatNamespace(ir.packageName()) + "." + enumName + ".NULL_VALUE"; - generatePropertyDecodeFrom(sb, fieldToken, nullValue, null, indent); + generatePropertyDecodeFrom(sb, rootKind, fieldToken, nullValue, null, indent); break; case BEGIN_COMPOSITE: - generateComplexDecodeFrom(sb, fieldToken, typeToken, indent); + generateComplexDecodeFrom(sb, rootKind, fieldToken, typeToken, indent); break; default: @@ -345,6 +354,7 @@ private void generateFieldDecodeFrom( private void generatePrimitiveDecodeFrom( final StringBuilder sb, + final DefinitionKind rootKind, final Token fieldToken, final Token typeToken, final String codecClassName, @@ -360,16 +370,17 @@ private void generatePrimitiveDecodeFrom( if (arrayLength == 1) { final String codecNullValue = codecClassName + "." + formatPropertyName(fieldToken.name()) + "NullValue"; - generatePropertyDecodeFrom(sb, fieldToken, "null", codecNullValue, indent); + generatePropertyDecodeFrom(sb, rootKind, fieldToken, "null", codecNullValue, indent); } else if (arrayLength > 1) { - generateArrayDecodeFrom(sb, fieldToken, typeToken, indent); + generateArrayDecodeFrom(sb, rootKind, fieldToken, typeToken, indent); } } private void generateArrayDecodeFrom( final StringBuilder sb, + final DefinitionKind rootKind, final Token fieldToken, final Token typeToken, final String indent) @@ -386,6 +397,7 @@ private void generateArrayDecodeFrom( { generateRecordPropertyAssignment( sb, + rootKind, fieldToken, indent, "codec.Get" + formattedPropertyName + "()", @@ -397,6 +409,7 @@ private void generateArrayDecodeFrom( { generateRecordPropertyAssignment( sb, + rootKind, fieldToken, indent, "codec." + formattedPropertyName + "AsSpan().ToArray()", @@ -408,6 +421,7 @@ private void generateArrayDecodeFrom( private void generatePropertyDecodeFrom( final StringBuilder sb, + final DefinitionKind rootKind, final Token fieldToken, final String dtoNullValue, final String codecNullValue, @@ -423,6 +437,7 @@ private void generatePropertyDecodeFrom( generateRecordPropertyAssignment( sb, + rootKind, fieldToken, indent, "codec." + formattedPropertyName, @@ -433,6 +448,7 @@ private void generatePropertyDecodeFrom( private void generateComplexDecodeFrom( final StringBuilder sb, + final DefinitionKind rootKind, final Token fieldToken, final Token typeToken, final String indent) @@ -443,6 +459,7 @@ private void generateComplexDecodeFrom( generateRecordPropertyAssignment( sb, + rootKind, fieldToken, indent, dtoClassName + ".DecodeFrom(codec." + formattedPropertyName + ")", @@ -469,6 +486,7 @@ private void generateGroupsDecodeFrom( generateRecordPropertyAssignment( sb, + DefinitionKind.Message, groupToken, indent, groupDtoClassName + ".DecodeListFrom(codec." + formattedPropertyName + ")", @@ -511,6 +529,7 @@ private void generateVarDataDecodeFrom( generateRecordPropertyAssignment( sb, + DefinitionKind.Message, token, indent, "codec." + accessor + "()", @@ -523,6 +542,7 @@ private void generateVarDataDecodeFrom( private void generateRecordPropertyAssignment( final StringBuilder sb, + final DefinitionKind rootKind, final Token token, final String indent, final String presentExpression, @@ -534,8 +554,20 @@ private void generateRecordPropertyAssignment( sb.append(indent).append(formattedPropertyName).append(": "); - if (token.version() > 0) + // N.B., in the IR, the composite information is "embedded" into each message/group field. + // When we are looking at a composite "field" (i.e., a type) the `token.version()` method + // returns the "sinceVersion" of the containing field. Therefore, we cannot decide presence + // based on `token.version()` when dealing with composites. + if (rootKind.equals(DefinitionKind.Message) && token.version() > 0) { + if (token.signal() != Signal.BEGIN_VAR_DATA && !token.isOptionalEncoding()) + { + throw new IllegalStateException( + "Expected added field " + propertyName + + " (sinceVersion=" + token.version() + ") to have optional presence." + ); + } + sb.append("codec.").append(formattedPropertyName).append("InActingVersion()"); if (null != nullCodecValueOrNull) @@ -553,7 +585,7 @@ private void generateRecordPropertyAssignment( } } - private void generateEncodeInto( + private void generateMessageEncodeInto( final StringBuilder sb, final String codecClassName, final List fields, @@ -674,7 +706,7 @@ private String nullableConvertedExpression( final String expression, final String nullValue) { - return fieldToken.version() > 0 || fieldToken.isOptionalEncoding() ? + return fieldToken.isOptionalEncoding() ? expression + " ?? " + nullValue : expression; } @@ -791,9 +823,19 @@ private void generateVarDataEncodeInto( if (token.signal() == Signal.BEGIN_VAR_DATA) { final String propertyName = token.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + if (token.version() > 0) + { + sb.append(indent).append("if (null == ").append(formattedPropertyName).append(")\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("throw new System.InvalidOperationException(\"") + .append(formattedPropertyName).append(" must not be null.\");\n") + .append(indent).append("}\n\n"); + } - sb.append(indent).append("codec.Set").append(formatPropertyName(propertyName)) - .append("(").append(formatPropertyName(propertyName)).append(");\n"); + sb.append(indent).append("codec.Set").append(formattedPropertyName) + .append("(").append(formattedPropertyName).append(");\n"); } } } @@ -1181,7 +1223,8 @@ private void generateVarData( final String propertyName = token.name(); final Token varDataToken = Generators.findFirst("varData", tokens, i); final String characterEncoding = varDataToken.encoding().characterEncoding(); - final String dtoType = characterEncoding == null ? "byte[]" : "string"; + final String nullableSuffix = token.version() > 0 ? "?" : ""; + final String dtoType = (characterEncoding == null ? "byte[]" : "string") + nullableSuffix; final String formattedPropertyName = formatPropertyName(propertyName); diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java index 7a4dde3f49..8a8be0fdde 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java @@ -89,6 +89,17 @@ void dtoEncodeShouldBeTheInverseOfDtoDecode( "SCHEMA:\n" + encodedMessage.schema()); } + final byte[] errorBytes = Files.readAllBytes(stderr); + if (errorBytes.length != 0) + { + throw new AssertionError( + "Process wrote to stderr.\n\n" + + "STDOUT:\n" + new String(Files.readAllBytes(stdout)) + "\n\n" + + "STDERR:\n" + new String(errorBytes) + "\n\n" + + "SCHEMA:\n" + encodedMessage.schema() + "\n\n" + ); + } + final byte[] inputBytes = new byte[encodedMessage.length()]; encodedMessage.buffer().getBytes(0, inputBytes); final byte[] outputBytes = Files.readAllBytes(tempDir.resolve("output.dat")); diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index b1b025d4d9..13f027fb30 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -192,6 +192,37 @@ private static Arbitrary typeSchema(final int depth) } } + private static Arbitrary addedField() + { + return Combinators.combine( + typeSchema(MAX_COMPOSITE_DEPTH), + Arbitraries.of(Encoding.Presence.OPTIONAL), + Arbitraries.of((short)1, (short)2) + ).as(FieldSchema::new); + } + + private static Arbitrary originalField() + { + return Combinators.combine( + typeSchema(MAX_COMPOSITE_DEPTH), + presence(), + Arbitraries.of((short)0) + ).as(FieldSchema::new); + } + + private static Arbitrary skewedFieldDistribution() + { + final Arbitrary originalField = originalField(); + final Arbitrary addedField = addedField(); + + return Arbitraries.oneOf( + originalField, + originalField, + originalField, + addedField + ); + } + private static Arbitrary groupSchema(final int depth) { final Arbitrary> subGroups = depth == 1 ? @@ -201,10 +232,7 @@ private static Arbitrary groupSchema(final int depth) return Combinators.combine( withDuplicates( 2, - Combinators.combine( - typeSchema(MAX_COMPOSITE_DEPTH), - presence() - ).as(FieldSchema::new).list().ofMaxSize(5) + skewedFieldDistribution().list().ofMaxSize(5) ), subGroups, varDataSchema().list().ofMaxSize(3) @@ -227,6 +255,13 @@ private static Arbitrary varDataSchema() PrimitiveType.UINT8, PrimitiveType.UINT16, PrimitiveType.UINT32 + ), + Arbitraries.of( + (short)0, + (short)0, + (short)0, + (short)1, + (short)2 ) ).as(VarDataSchema::new); } @@ -236,10 +271,7 @@ public static Arbitrary messageSchema() return Combinators.combine( withDuplicates( 3, - Combinators.combine( - typeSchema(MAX_COMPOSITE_DEPTH), - presence() - ).as(FieldSchema::new).list().ofMaxSize(10) + skewedFieldDistribution().list().ofMaxSize(10) ), groupSchema(MAX_GROUP_DEPTH).list().ofMaxSize(3), varDataSchema().list().ofMaxSize(3) @@ -747,7 +779,7 @@ public static Arbitrary messageValueEncoder( buffer.putShort(0, (short)blockLength, ir.byteOrder()); buffer.putShort(2, messageId, ir.byteOrder()); buffer.putShort(4, (short)ir.id(), ir.byteOrder()); - buffer.putShort(6, (short)0, ir.byteOrder()); + buffer.putShort(6, (short)ir.version(), ir.byteOrder()); final int headerLength = 8; fields.encode(buffer, offset + headerLength, null); limit.set(offset + headerLength + blockLength); @@ -821,7 +853,10 @@ public static Arbitrary encodedMessage(final CharGenerationMode } catch (final Exception e) { - throw new RuntimeException(e); + throw new AssertionError( + "Failed to generate encoded value for schema.\n\n" + + "SCHEMA:\n" + xml, + e); } }).withoutEdgeCases(); } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java index 406ee65cdd..c1fad8abc4 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java @@ -22,14 +22,18 @@ public final class FieldSchema { private final TypeSchema type; private final Encoding.Presence presence; + private final short sinceVersion; public FieldSchema( final TypeSchema type, - final Encoding.Presence presence + final Encoding.Presence presence, + final short sinceVersion ) { + assert sinceVersion == 0 || presence.equals(Encoding.Presence.OPTIONAL); this.type = type; this.presence = presence; + this.sinceVersion = sinceVersion; } public TypeSchema type() @@ -41,4 +45,9 @@ public Encoding.Presence presence() { return presence; } + + public short sinceVersion() + { + return sinceVersion; + } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java index 53c3c81df7..47cfe343a7 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java @@ -16,7 +16,9 @@ package uk.co.real_logic.sbe.properties.schema; +import java.util.Comparator; import java.util.List; +import java.util.stream.Collectors; public final class GroupSchema { @@ -29,9 +31,13 @@ public GroupSchema( final List groups, final List varData) { - this.blockFields = blockFields; + this.blockFields = blockFields.stream() + .sorted(Comparator.comparing(FieldSchema::sinceVersion)) + .collect(Collectors.toList()); this.groups = groups; - this.varData = varData; + this.varData = varData.stream() + .sorted(Comparator.comparing(VarDataSchema::sinceVersion)) + .collect(Collectors.toList()); } public List blockFields() diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java index a0decb2d6b..2095628c39 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java @@ -16,13 +16,16 @@ package uk.co.real_logic.sbe.properties.schema; +import java.util.Comparator; import java.util.List; +import java.util.stream.Collectors; public final class MessageSchema { private final List blockFields; private final List groups; private final List varData; + private final short version; public MessageSchema( final List blockFields, @@ -30,9 +33,14 @@ public MessageSchema( final List varData ) { - this.blockFields = blockFields; + this.blockFields = blockFields.stream() + .sorted(Comparator.comparing(FieldSchema::sinceVersion)) + .collect(Collectors.toList()); this.groups = groups; - this.varData = varData; + this.varData = varData.stream() + .sorted(Comparator.comparing(VarDataSchema::sinceVersion)) + .collect(Collectors.toList()); + this.version = findMaxVersion(blockFields, groups, varData); } public short schemaId() @@ -45,6 +53,11 @@ public short templateId() return 1; } + public short version() + { + return version; + } + public List blockFields() { return blockFields; @@ -59,4 +72,22 @@ public List varData() { return varData; } + + private static short findMaxVersion( + final List fields, + final List groups, + final List varData + ) + { + final int maxFieldVersion = fields.stream() + .mapToInt(FieldSchema::sinceVersion) + .max().orElse(0); + final int maxGroupVersion = groups.stream() + .mapToInt(group -> findMaxVersion(group.blockFields(), group.groups(), group.varData())) + .max().orElse(0); + final int maxVarDataVersion = varData.stream() + .mapToInt(VarDataSchema::sinceVersion) + .max().orElse(0); + return (short)Math.max(maxFieldVersion, Math.max(maxGroupVersion, maxVarDataVersion)); + } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java index 7ccd273017..3c43228099 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java @@ -70,6 +70,7 @@ private static void writeTo( final Element root = document.createElementNS("http://fixprotocol.io/2016/sbe", "sbe:messageSchema"); root.setAttribute("id", Short.toString(schema.schemaId())); root.setAttribute("package", "uk.co.real_logic.sbe.properties"); + root.setAttribute("version", Short.toString(schema.version())); document.appendChild(root); final Element topLevelTypes = createTypesElement(document); @@ -152,6 +153,7 @@ private static void appendMembers( element.setAttribute("name", "member" + id); element.setAttribute("type", typeName); element.setAttribute("presence", field.presence().name().toLowerCase()); + element.setAttribute("sinceVersion", Short.toString(field.sinceVersion())); parent.appendChild(element); } @@ -180,6 +182,7 @@ private static void appendMembers( element.setAttribute("id", Integer.toString(id)); element.setAttribute("name", "member" + id); element.setAttribute("type", requireNonNull(typeToName.get(data))); + element.setAttribute("sinceVersion", Short.toString(data.sinceVersion())); parent.appendChild(element); } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java index b5e98c02c7..db3d5900a1 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java @@ -22,13 +22,16 @@ public final class VarDataSchema { private final Encoding dataEncoding; private final PrimitiveType lengthEncoding; + private final short sinceVersion; public VarDataSchema( final Encoding dataEncoding, - final PrimitiveType lengthEncoding) + final PrimitiveType lengthEncoding, + final short sinceVersion) { this.dataEncoding = dataEncoding; this.lengthEncoding = lengthEncoding; + this.sinceVersion = sinceVersion; } public Encoding dataEncoding() @@ -41,6 +44,11 @@ public PrimitiveType lengthEncoding() return lengthEncoding; } + public short sinceVersion() + { + return sinceVersion; + } + public enum Encoding { ASCII, From 7ee92651a2471aa7ee4fe087283397c4ac5b697d Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Thu, 9 Nov 2023 15:25:34 +0000 Subject: [PATCH 1149/1594] [C#] Address some of Martin's feedback re "added" var data representation. The SBE spec doesn't explicitly allow variable-length data or groups to be added to existing message schemas, i.e., only block-level fields may be added; however in practice the encoders/decoders for some languages do support the addition of var data fields. Previously, I had represented these "added" var data fields as optional strings or byte arrays, but having chatted with Martin, we think it is better to mimick the existing decoder representation, i.e., use empty strings/arrays to represent missing elements. In this commit, I've also fixed some instances where I was checking `token.version() > 0` where I should have been checking `token.version() > sinceVersionOfParentContainer`. Ideally, I would have liked to remove such checks entirely, but the C# and C++ codecs do not give sensible responses when decoding older versions in some cases, i.e., you _must_ check the presence of the field before accessing it. --- .../generation/csharp/CSharpDtoGenerator.java | 196 ++++++++++-------- .../properties/CSharpDtosPropertyTest.java | 19 +- .../arbitraries/SbeArbitraries.java | 14 +- 3 files changed, 131 insertions(+), 98 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java index 9335295663..6f25151a56 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -30,6 +30,7 @@ import java.io.Writer; import java.util.ArrayList; import java.util.List; +import java.util.function.Predicate; import static uk.co.real_logic.sbe.generation.csharp.CSharpUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; @@ -43,6 +44,7 @@ public class CSharpDtoGenerator implements CodeGenerator { private static final String INDENT = " "; private static final String BASE_INDENT = INDENT; + private static final Predicate CANNOT_EXTEND = ignored -> false; private final Ir ir; private final OutputManager outputManager; @@ -93,8 +95,10 @@ public void generate() throws IOException collectVarData(messageBody, offset, varData); generateVarData(sb, ctorArgs, varData, BASE_INDENT + INDENT); - generateMessageDecodeFrom(sb, className, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); - generateMessageEncodeInto(sb, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); + generateDecodeFrom(sb, className, codecClassName, fields, groups, varData, + token -> token.version() > msgToken.version(), + BASE_INDENT + INDENT); + generateEncodeInto(sb, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); generateDisplay(sb, codecClassName, "WrapForEncode", null, BASE_INDENT + INDENT); removeTrailingComma(ctorArgs); @@ -119,12 +123,6 @@ public void generate() throws IOException } } - private enum DefinitionKind - { - Composite, - Message - } - private void generateGroups( final StringBuilder sb, final StringBuilder ctorArgs, @@ -142,9 +140,15 @@ private void generateGroups( } final String groupName = groupToken.name(); final String groupClassName = formatDtoClassName(groupName); - final String formattedPropertyName = formatPropertyName(groupName); + final Token dimToken = tokens.get(i + 1); + if (dimToken.signal() != Signal.BEGIN_COMPOSITE) + { + throw new IllegalStateException("groups must start with BEGIN_COMPOSITE: token=" + dimToken); + } + final int sinceVersion = dimToken.version(); + ctorArgs.append(indent).append("IReadOnlyList<") .append(qualifiedParentDtoClassName).append(".").append(groupClassName).append("> ") .append(formattedPropertyName).append(",\n"); @@ -167,22 +171,40 @@ private void generateGroups( final List fields = new ArrayList<>(); i = collectFields(tokens, i, fields); + generateFields(groupRecordBody, groupCtorArgs, qualifiedCodecClassName, fields, indent + INDENT); final List groups = new ArrayList<>(); i = collectGroups(tokens, i, groups); + generateGroups(groupRecordBody, groupCtorArgs, qualifiedDtoClassName, qualifiedCodecClassName, groups, indent + INDENT); final List varData = new ArrayList<>(); i = collectVarData(tokens, i, varData); + generateVarData(groupRecordBody, groupCtorArgs, varData, indent + INDENT); generateDecodeListFrom( groupRecordBody, groupClassName, qualifiedCodecClassName, indent + INDENT); - generateMessageDecodeFrom( - groupRecordBody, groupClassName, qualifiedCodecClassName, fields, groups, varData, indent + INDENT); - generateMessageEncodeInto( + + final Predicate wasAddedAfterGroup = token -> + { + final boolean addedAfterParent = token.version() > sinceVersion; + + if (addedAfterParent && token.signal() == Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("Cannot extend var data inside a group."); + } + + return addedAfterParent; + }; + + generateDecodeFrom( + groupRecordBody, groupClassName, qualifiedCodecClassName, fields, groups, varData, + wasAddedAfterGroup, indent + INDENT); + + generateEncodeInto( groupRecordBody, qualifiedCodecClassName, fields, groups, varData, indent + INDENT); removeTrailingComma(groupCtorArgs); @@ -217,7 +239,7 @@ private void generateCompositeDecodeFrom( final Token token = tokens.get(i); generateFieldDecodeFrom( - sb, DefinitionKind.Composite, token, token, codecClassName, indent + INDENT + INDENT); + sb, CANNOT_EXTEND, token, token, codecClassName, indent + INDENT + INDENT); i += tokens.get(i).componentTokenCount(); } @@ -277,13 +299,14 @@ private void generateDecodeListFrom( .append(indent).append("}\n"); } - private void generateMessageDecodeFrom( + private void generateDecodeFrom( final StringBuilder sb, final String dtoClassName, final String codecClassName, final List fields, final List groups, final List varData, + final Predicate wasAddedAfterParent, final String indent) { sb.append("\n") @@ -292,9 +315,9 @@ private void generateMessageDecodeFrom( .append(indent).append("{\n"); sb.append(indent).append(INDENT).append("return new ").append(dtoClassName).append("(\n"); - generateMessageFieldsDecodeFrom(sb, fields, codecClassName, indent + INDENT + INDENT); + generateMessageFieldsDecodeFrom(sb, wasAddedAfterParent, fields, codecClassName, indent + INDENT + INDENT); generateGroupsDecodeFrom(sb, groups, indent + INDENT + INDENT); - generateVarDataDecodeFrom(sb, varData, indent + INDENT + INDENT); + generateVarDataDecodeFrom(sb, varData, wasAddedAfterParent, indent + INDENT + INDENT); removeTrailingComma(sb); sb.append(indent).append(INDENT).append(");\n"); @@ -303,6 +326,7 @@ private void generateMessageDecodeFrom( private void generateMessageFieldsDecodeFrom( final StringBuilder sb, + final Predicate wasAddedAfterParent, final List tokens, final String codecClassName, final String indent) @@ -314,14 +338,15 @@ private void generateMessageFieldsDecodeFrom( { final Token encodingToken = tokens.get(i + 1); - generateFieldDecodeFrom(sb, DefinitionKind.Message, signalToken, encodingToken, codecClassName, indent); + generateFieldDecodeFrom( + sb, wasAddedAfterParent, signalToken, encodingToken, codecClassName, indent); } } } private void generateFieldDecodeFrom( final StringBuilder sb, - final DefinitionKind rootKind, + final Predicate wasAddedAfterParent, final Token fieldToken, final Token typeToken, final String codecClassName, @@ -330,21 +355,21 @@ private void generateFieldDecodeFrom( switch (typeToken.signal()) { case ENCODING: - generatePrimitiveDecodeFrom(sb, rootKind, fieldToken, typeToken, codecClassName, indent); + generatePrimitiveDecodeFrom(sb, fieldToken, typeToken, wasAddedAfterParent, codecClassName, indent); break; case BEGIN_SET: - generatePropertyDecodeFrom(sb, rootKind, fieldToken, "0", null, indent); + generatePropertyDecodeFrom(sb, fieldToken, wasAddedAfterParent, "0", null, indent); break; case BEGIN_ENUM: final String enumName = formatClassName(typeToken.applicableTypeName()); final String nullValue = formatNamespace(ir.packageName()) + "." + enumName + ".NULL_VALUE"; - generatePropertyDecodeFrom(sb, rootKind, fieldToken, nullValue, null, indent); + generatePropertyDecodeFrom(sb, fieldToken, wasAddedAfterParent, nullValue, null, indent); break; case BEGIN_COMPOSITE: - generateComplexDecodeFrom(sb, rootKind, fieldToken, typeToken, indent); + generateComplexDecodeFrom(sb, fieldToken, typeToken, indent); break; default: @@ -354,9 +379,9 @@ private void generateFieldDecodeFrom( private void generatePrimitiveDecodeFrom( final StringBuilder sb, - final DefinitionKind rootKind, final Token fieldToken, final Token typeToken, + final Predicate wasAddedAfterParent, final String codecClassName, final String indent) { @@ -370,19 +395,19 @@ private void generatePrimitiveDecodeFrom( if (arrayLength == 1) { final String codecNullValue = codecClassName + "." + formatPropertyName(fieldToken.name()) + "NullValue"; - generatePropertyDecodeFrom(sb, rootKind, fieldToken, "null", codecNullValue, indent); + generatePropertyDecodeFrom(sb, fieldToken, wasAddedAfterParent, "null", codecNullValue, indent); } else if (arrayLength > 1) { - generateArrayDecodeFrom(sb, rootKind, fieldToken, typeToken, indent); + generateArrayDecodeFrom(sb, fieldToken, typeToken, wasAddedAfterParent, indent); } } private void generateArrayDecodeFrom( final StringBuilder sb, - final DefinitionKind rootKind, final Token fieldToken, final Token typeToken, + final Predicate wasAddedAfterParent, final String indent) { if (fieldToken.isConstantEncoding()) @@ -397,8 +422,8 @@ private void generateArrayDecodeFrom( { generateRecordPropertyAssignment( sb, - rootKind, fieldToken, + wasAddedAfterParent, indent, "codec.Get" + formattedPropertyName + "()", "null", @@ -409,8 +434,8 @@ private void generateArrayDecodeFrom( { generateRecordPropertyAssignment( sb, - rootKind, fieldToken, + wasAddedAfterParent, indent, "codec." + formattedPropertyName + "AsSpan().ToArray()", "null", @@ -421,8 +446,8 @@ private void generateArrayDecodeFrom( private void generatePropertyDecodeFrom( final StringBuilder sb, - final DefinitionKind rootKind, final Token fieldToken, + final Predicate wasAddedAfterParent, final String dtoNullValue, final String codecNullValue, final String indent) @@ -437,8 +462,8 @@ private void generatePropertyDecodeFrom( generateRecordPropertyAssignment( sb, - rootKind, fieldToken, + wasAddedAfterParent, indent, "codec." + formattedPropertyName, dtoNullValue, @@ -448,7 +473,6 @@ private void generatePropertyDecodeFrom( private void generateComplexDecodeFrom( final StringBuilder sb, - final DefinitionKind rootKind, final Token fieldToken, final Token typeToken, final String indent) @@ -457,15 +481,9 @@ private void generateComplexDecodeFrom( final String formattedPropertyName = formatPropertyName(propertyName); final String dtoClassName = formatDtoClassName(typeToken.applicableTypeName()); - generateRecordPropertyAssignment( - sb, - rootKind, - fieldToken, - indent, - dtoClassName + ".DecodeFrom(codec." + formattedPropertyName + ")", - "null", - "null" - ); + sb.append(indent).append(formattedPropertyName).append(": ") + .append(dtoClassName).append(".DecodeFrom(codec.") + .append(formattedPropertyName).append(")").append(",\n"); } private void generateGroupsDecodeFrom( @@ -484,10 +502,17 @@ private void generateGroupsDecodeFrom( final String formattedPropertyName = formatPropertyName(groupName); final String groupDtoClassName = formatDtoClassName(groupName); + final Token dimToken = tokens.get(i + 1); + if (dimToken.signal() != Signal.BEGIN_COMPOSITE) + { + throw new IllegalStateException("groups must start with BEGIN_COMPOSITE: token=" + dimToken); + } + final int sinceVersion = dimToken.version(); + generateRecordPropertyAssignment( sb, - DefinitionKind.Message, groupToken, + token -> token.version() > sinceVersion, indent, groupDtoClassName + ".DecodeListFrom(codec." + formattedPropertyName + ")", "new List<" + groupDtoClassName + ">(0).AsReadOnly()", @@ -511,6 +536,7 @@ private void generateGroupsDecodeFrom( private void generateVarDataDecodeFrom( final StringBuilder sb, final List tokens, + final Predicate wasAddedAfterParent, final String indent) { for (int i = 0; i < tokens.size(); i++) @@ -526,24 +552,32 @@ private void generateVarDataDecodeFrom( final String accessor = characterEncoding == null ? "Get" + formattedPropertyName + "Bytes" : "Get" + formattedPropertyName; + final String missingValue = characterEncoding == null ? + "new byte[0]" : + "\"\""; + + sb.append(indent).append(formattedPropertyName).append(": "); - generateRecordPropertyAssignment( - sb, - DefinitionKind.Message, - token, - indent, - "codec." + accessor + "()", - "null", - null - ); + if (wasAddedAfterParent.test(token)) + { + sb.append("codec.").append(formattedPropertyName).append("InActingVersion()"); + sb.append(" ?\n"); + sb.append(indent).append(INDENT).append("codec.").append(accessor).append("()") + .append(" :\n") + .append(indent).append(INDENT).append(missingValue).append(",\n"); + } + else + { + sb.append("codec.").append(accessor).append("()").append(",\n"); + } } } } private void generateRecordPropertyAssignment( final StringBuilder sb, - final DefinitionKind rootKind, final Token token, + final Predicate wasAddedAfterParent, final String indent, final String presentExpression, final String notPresentExpression, @@ -554,27 +588,29 @@ private void generateRecordPropertyAssignment( sb.append(indent).append(formattedPropertyName).append(": "); - // N.B., in the IR, the composite information is "embedded" into each message/group field. - // When we are looking at a composite "field" (i.e., a type) the `token.version()` method - // returns the "sinceVersion" of the containing field. Therefore, we cannot decide presence - // based on `token.version()` when dealing with composites. - if (rootKind.equals(DefinitionKind.Message) && token.version() > 0) - { - if (token.signal() != Signal.BEGIN_VAR_DATA && !token.isOptionalEncoding()) - { - throw new IllegalStateException( - "Expected added field " + propertyName + - " (sinceVersion=" + token.version() + ") to have optional presence." - ); - } + boolean hasPresenceCondition = false; + // Unfortunately, we need to check whether the field is in the acting version, + // as the codec may incorrectly decode data for missing fields. + if (wasAddedAfterParent.test(token)) + { sb.append("codec.").append(formattedPropertyName).append("InActingVersion()"); + hasPresenceCondition = true; + } - if (null != nullCodecValueOrNull) + if (token.isOptionalEncoding() && null != nullCodecValueOrNull) + { + if (hasPresenceCondition) { - sb.append(" && codec.").append(formattedPropertyName).append(" != ").append(nullCodecValueOrNull); + sb.append(" && "); } + sb.append("codec.").append(formattedPropertyName).append(" != ").append(nullCodecValueOrNull); + hasPresenceCondition = true; + } + + if (hasPresenceCondition) + { sb.append(" ?\n"); sb.append(indent).append(INDENT).append(presentExpression).append(" :\n") .append(indent).append(INDENT).append(notPresentExpression).append(",\n"); @@ -585,7 +621,7 @@ private void generateRecordPropertyAssignment( } } - private void generateMessageEncodeInto( + private void generateEncodeInto( final StringBuilder sb, final String codecClassName, final List fields, @@ -758,17 +794,6 @@ private void generateComplexEncodeInto( { final String propertyName = fieldToken.name(); final String formattedPropertyName = formatPropertyName(propertyName); - - if (fieldToken.isOptionalEncoding()) - { - sb.append(indent).append("if (null == ").append(formattedPropertyName).append(")\n") - .append(indent).append("{") - .append(indent).append(INDENT).append("throw new System.InvalidOperationException(\"") - .append("Null composite value encoding (").append(formattedPropertyName) - .append(") is not supported via DTOs\");\n") - .append(indent).append("}\n\n"); - } - sb.append(indent).append(formattedPropertyName).append(".EncodeInto(codec.") .append(formattedPropertyName).append(");\n"); } @@ -825,15 +850,6 @@ private void generateVarDataEncodeInto( final String propertyName = token.name(); final String formattedPropertyName = formatPropertyName(propertyName); - if (token.version() > 0) - { - sb.append(indent).append("if (null == ").append(formattedPropertyName).append(")\n") - .append(indent).append("{\n") - .append(indent).append(INDENT).append("throw new System.InvalidOperationException(\"") - .append(formattedPropertyName).append(" must not be null.\");\n") - .append(indent).append("}\n\n"); - } - sb.append(indent).append("codec.Set").append(formattedPropertyName) .append("(").append(formattedPropertyName).append(");\n"); } @@ -917,7 +933,6 @@ private void generateCompositeProperty( final String indent) { final String compositeName = formatDtoClassName(typeToken.applicableTypeName()); - final String nullableSuffix = fieldToken.isOptionalEncoding() ? "?" : ""; final String formattedPropertyName = formatPropertyName(propertyName); ctorArgs.append(indent).append(compositeName).append(" ").append(formattedPropertyName).append(",\n"); @@ -925,7 +940,7 @@ private void generateCompositeProperty( sb.append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("public ").append(compositeName) - .append(nullableSuffix).append(" ").append(formattedPropertyName) + .append(" ").append(formattedPropertyName) .append(" { get; init; } = ").append(formattedPropertyName).append(";\n"); } @@ -1223,8 +1238,7 @@ private void generateVarData( final String propertyName = token.name(); final Token varDataToken = Generators.findFirst("varData", tokens, i); final String characterEncoding = varDataToken.encoding().characterEncoding(); - final String nullableSuffix = token.version() > 0 ? "?" : ""; - final String dtoType = (characterEncoding == null ? "byte[]" : "string") + nullableSuffix; + final String dtoType = characterEncoding == null ? "byte[]" : "string"; final String formattedPropertyName = formatPropertyName(propertyName); diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java index 8a8be0fdde..701ca2fcf4 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java @@ -50,10 +50,21 @@ void dtoEncodeShouldBeTheInverseOfDtoDecode( tempDir.toString(), "SbePropertyTest" ); - new CSharpGenerator(encodedMessage.ir(), outputManager) - .generate(); - new CSharpDtoGenerator(encodedMessage.ir(), outputManager) - .generate(); + + try + { + new CSharpGenerator(encodedMessage.ir(), outputManager) + .generate(); + new CSharpDtoGenerator(encodedMessage.ir(), outputManager) + .generate(); + } + catch (final Exception generationException) + { + throw new AssertionError( + "Code generation failed.\n\nSCHEMA:\n" + encodedMessage.schema(), + generationException); + } + copyResourceToFile("/CSharpDtosPropertyTest/SbePropertyTest.csproj", tempDir); copyResourceToFile("/CSharpDtosPropertyTest/Program.cs", tempDir); try ( diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index 13f027fb30..25207cdf96 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -21,6 +21,7 @@ import net.jqwik.api.Combinators; import net.jqwik.api.arbitraries.CharacterArbitrary; import net.jqwik.api.arbitraries.ListArbitrary; +import net.jqwik.api.arbitraries.ShortArbitrary; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.PrimitiveValue; import uk.co.real_logic.sbe.ir.Encoding; @@ -235,7 +236,7 @@ private static Arbitrary groupSchema(final int depth) skewedFieldDistribution().list().ofMaxSize(5) ), subGroups, - varDataSchema().list().ofMaxSize(3) + varDataSchema(Arbitraries.of((short)0)).list().ofMaxSize(3) ).as(GroupSchema::new); } @@ -247,7 +248,7 @@ private static Arbitrary presence() ); } - private static Arbitrary varDataSchema() + private static Arbitrary varDataSchema(final Arbitrary sinceVersion) { return Combinators.combine( Arbitraries.of(VarDataSchema.Encoding.values()), @@ -256,6 +257,13 @@ private static Arbitrary varDataSchema() PrimitiveType.UINT16, PrimitiveType.UINT32 ), + sinceVersion + ).as(VarDataSchema::new); + } + + private static Arbitrary varDataSchema() + { + return varDataSchema( Arbitraries.of( (short)0, (short)0, @@ -263,7 +271,7 @@ private static Arbitrary varDataSchema() (short)1, (short)2 ) - ).as(VarDataSchema::new); + ); } public static Arbitrary messageSchema() From 1b98e1de06346eb350045fd6bdb253774e15a22d Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Fri, 10 Nov 2023 19:06:29 +0000 Subject: [PATCH 1150/1594] [C#] Address feedback around encode/decode methods. This commit addresses some feedback from Martin: - Makes encode and decode methods static - Improves naming: - `EncodeInto(codec)` -> `EncodeWith` - `DecodeFrom(codec)` -> `DecodeWith` - Introduces version that works directly with buffer --- csharp/sbe-tests/DtoTests.cs | 27 ++- .../generation/csharp/CSharpDtoGenerator.java | 215 ++++++++++++------ .../CSharpDtosPropertyTest/Program.cs | 4 +- 3 files changed, 163 insertions(+), 83 deletions(-) diff --git a/csharp/sbe-tests/DtoTests.cs b/csharp/sbe-tests/DtoTests.cs index fcd0007bf7..1986db5738 100644 --- a/csharp/sbe-tests/DtoTests.cs +++ b/csharp/sbe-tests/DtoTests.cs @@ -8,29 +8,42 @@ namespace Org.SbeTool.Sbe.Tests public class DtoTests { [TestMethod] - public void ShouldRoundTripCar() + public void ShouldRoundTripCar1() { var inputByteArray = new byte[1024]; var inputBuffer = new DirectBuffer(inputByteArray); - EncodeCar(inputBuffer); + EncodeCar(inputBuffer, 0); var decoder = new Car(); decoder.WrapForDecode(inputBuffer, 0, Car.BlockLength, Car.SchemaVersion); var decoderString = decoder.ToString(); - var dto = CarDto.DecodeFrom(decoder); + var dto = CarDto.DecodeWith(decoder); var outputByteArray = new byte[1024]; var outputBuffer = new DirectBuffer(outputByteArray); var encoder = new Car(); encoder.WrapForEncode(outputBuffer, 0); - dto.EncodeInto(encoder); + CarDto.EncodeWith(encoder, dto); var dtoString = dto.ToSbeString(); CollectionAssert.AreEqual(inputByteArray, outputByteArray); Assert.AreEqual(decoderString, dtoString); } + + [TestMethod] + public void ShouldRoundTripCar2() + { + var inputByteArray = new byte[1024]; + var inputBuffer = new DirectBuffer(inputByteArray); + var length = EncodeCar(inputBuffer, 0); + var dto = CarDto.DecodeFrom(inputBuffer, 0, length, Car.BlockLength, Car.SchemaVersion); + var outputByteArray = new byte[1024]; + var outputBuffer = new DirectBuffer(outputByteArray); + CarDto.EncodeInto(outputBuffer, 0, dto); + CollectionAssert.AreEqual(inputByteArray, outputByteArray); + } - private static void EncodeCar(DirectBuffer buffer) + private static int EncodeCar(DirectBuffer buffer, int offset) { var car = new Car(); - car.WrapForEncode(buffer, 0); + car.WrapForEncode(buffer, offset); car.SerialNumber = 1234; car.ModelYear = 2013; car.Available = BooleanType.T; @@ -104,6 +117,8 @@ private static void EncodeCar(DirectBuffer buffer) car.SetManufacturer("Ford"); car.SetModel("Fiesta"); car.SetActivationCode("1234"); + + return car.Limit - offset; } } } \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java index 6f25151a56..a132e751d6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -75,7 +75,7 @@ public void generate() throws IOException { final Token msgToken = tokens.get(0); final String codecClassName = formatClassName(msgToken.name()); - final String className = formatDtoClassName(msgToken.name()); + final String dtoClassName = formatDtoClassName(msgToken.name()); final List messageBody = tokens.subList(1, tokens.size() - 1); int offset = 0; @@ -89,21 +89,24 @@ public void generate() throws IOException final List groups = new ArrayList<>(); offset = collectGroups(messageBody, offset, groups); - generateGroups(sb, ctorArgs, className, codecClassName, groups, BASE_INDENT + INDENT); + generateGroups(sb, ctorArgs, dtoClassName, codecClassName, groups, BASE_INDENT + INDENT); final List varData = new ArrayList<>(); collectVarData(messageBody, offset, varData); generateVarData(sb, ctorArgs, varData, BASE_INDENT + INDENT); - generateDecodeFrom(sb, className, codecClassName, fields, groups, varData, + generateDecodeWith(sb, dtoClassName, codecClassName, fields, groups, varData, token -> token.version() > msgToken.version(), BASE_INDENT + INDENT); - generateEncodeInto(sb, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); + generateDecodeFrom(sb, dtoClassName, codecClassName, BASE_INDENT + INDENT); + generateEncodeWith(sb, dtoClassName, codecClassName, fields, groups, varData, + BASE_INDENT + INDENT); + generateEncodeInto(sb, dtoClassName, codecClassName, BASE_INDENT + INDENT); generateDisplay(sb, codecClassName, "WrapForEncode", null, BASE_INDENT + INDENT); removeTrailingComma(ctorArgs); - try (Writer out = outputManager.createOutput(className)) + try (Writer out = outputManager.createOutput(dtoClassName)) { out.append(generateFileHeader( ir.applicableNamespace(), @@ -112,7 +115,7 @@ public void generate() throws IOException "using System.Linq;\n")); out.append(generateDocumentation(BASE_INDENT, msgToken)); - out.append(BASE_INDENT).append("public sealed partial record ").append(className).append("(\n") + out.append(BASE_INDENT).append("public sealed partial record ").append(dtoClassName).append("(\n") .append(ctorArgs) .append(BASE_INDENT).append(")\n") .append(BASE_INDENT).append("{") @@ -185,7 +188,7 @@ private void generateGroups( generateVarData(groupRecordBody, groupCtorArgs, varData, indent + INDENT); - generateDecodeListFrom( + generateDecodeListWith( groupRecordBody, groupClassName, qualifiedCodecClassName, indent + INDENT); final Predicate wasAddedAfterGroup = token -> @@ -200,12 +203,13 @@ private void generateGroups( return addedAfterParent; }; - generateDecodeFrom( + generateDecodeWith( groupRecordBody, groupClassName, qualifiedCodecClassName, fields, groups, varData, wasAddedAfterGroup, indent + INDENT); - generateEncodeInto( - groupRecordBody, qualifiedCodecClassName, fields, groups, varData, indent + INDENT); + generateEncodeWith( + groupRecordBody, groupClassName, qualifiedCodecClassName, fields, groups, varData, + indent + INDENT); removeTrailingComma(groupCtorArgs); @@ -220,7 +224,7 @@ private void generateGroups( } } - private void generateCompositeDecodeFrom( + private void generateCompositeDecodeWith( final StringBuilder sb, final String dtoClassName, final String codecClassName, @@ -228,7 +232,7 @@ private void generateCompositeDecodeFrom( final String indent) { sb.append("\n") - .append(indent).append("public static ").append(dtoClassName).append(" DecodeFrom(") + .append(indent).append("public static ").append(dtoClassName).append(" DecodeWith(") .append(codecClassName).append(" codec)\n") .append(indent).append("{\n"); @@ -238,7 +242,7 @@ private void generateCompositeDecodeFrom( { final Token token = tokens.get(i); - generateFieldDecodeFrom( + generateFieldDecodeWith( sb, CANNOT_EXTEND, token, token, codecClassName, indent + INDENT + INDENT); i += tokens.get(i).componentTokenCount(); @@ -250,21 +254,24 @@ private void generateCompositeDecodeFrom( sb.append(indent).append("}\n"); } - private void generateCompositeEncodeInto( + private void generateCompositeEncodeWith( final StringBuilder sb, + final String dtoClassName, final String codecClassName, final List tokens, final String indent) { sb.append("\n") - .append(indent).append("public void EncodeInto(").append(codecClassName).append(" codec)\n") + .append(indent).append("public static void EncodeWith(") + .append(codecClassName).append(" codec, ") + .append(dtoClassName).append(" dto)\n") .append(indent).append("{\n"); for (int i = 0; i < tokens.size(); ) { final Token token = tokens.get(i); - generateFieldEncodeInto(sb, codecClassName, token, token, indent + INDENT); + generateFieldEncodeWith(sb, codecClassName, token, token, indent + INDENT); i += tokens.get(i).componentTokenCount(); } @@ -272,14 +279,14 @@ private void generateCompositeEncodeInto( sb.append(indent).append("}\n"); } - private void generateDecodeListFrom( + private void generateDecodeListWith( final StringBuilder sb, final String dtoClassName, final String codecClassName, final String indent) { sb.append("\n") - .append(indent).append("public static IReadOnlyList<").append(dtoClassName).append("> DecodeListFrom(") + .append(indent).append("public static IReadOnlyList<").append(dtoClassName).append("> DecodeListWith(") .append(codecClassName).append(" codec)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("var ").append("list = new List<").append(dtoClassName) @@ -289,7 +296,7 @@ private void generateDecodeListFrom( .append(indent).append(INDENT) .append("{\n") .append(indent).append(INDENT).append(INDENT) - .append("var element = ").append(dtoClassName).append(".DecodeFrom(codec.Next());\n") + .append("var element = ").append(dtoClassName).append(".DecodeWith(codec.Next());\n") .append(indent).append(INDENT).append(INDENT) .append("list.Add(element);\n") .append(indent).append(INDENT) @@ -299,7 +306,7 @@ private void generateDecodeListFrom( .append(indent).append("}\n"); } - private void generateDecodeFrom( + private void generateDecodeWith( final StringBuilder sb, final String dtoClassName, final String codecClassName, @@ -311,20 +318,40 @@ private void generateDecodeFrom( { sb.append("\n") .append(indent).append("public static ").append(dtoClassName) - .append(" DecodeFrom(").append(codecClassName).append(" codec)\n") + .append(" DecodeWith(").append(codecClassName).append(" codec)\n") .append(indent).append("{\n"); sb.append(indent).append(INDENT).append("return new ").append(dtoClassName).append("(\n"); - generateMessageFieldsDecodeFrom(sb, wasAddedAfterParent, fields, codecClassName, indent + INDENT + INDENT); - generateGroupsDecodeFrom(sb, groups, indent + INDENT + INDENT); - generateVarDataDecodeFrom(sb, varData, wasAddedAfterParent, indent + INDENT + INDENT); + generateMessageFieldsDecodeWith(sb, wasAddedAfterParent, fields, codecClassName, indent + INDENT + INDENT); + generateGroupsDecodeWith(sb, groups, indent + INDENT + INDENT); + generateVarDataDecodeWith(sb, varData, wasAddedAfterParent, indent + INDENT + INDENT); removeTrailingComma(sb); sb.append(indent).append(INDENT).append(");\n"); sb.append(indent).append("}\n"); } - private void generateMessageFieldsDecodeFrom( + private void generateDecodeFrom( + final StringBuilder sb, + final String dtoClassName, + final String codecClassName, + final String indent) + { + sb.append("\n") + .append(indent).append("public static ").append(dtoClassName) + .append(" DecodeFrom(DirectBuffer buffer, int offset, int length, ") + .append("int actingBlockLength, int actingVersion)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT) + .append("var decoder = new ").append(codecClassName).append("();\n") + .append(indent).append(INDENT) + .append("decoder.WrapForDecode(buffer, offset, actingBlockLength, actingVersion);\n") + .append(indent).append(INDENT) + .append("return DecodeWith(decoder);\n") + .append(indent).append("}\n"); + } + + private void generateMessageFieldsDecodeWith( final StringBuilder sb, final Predicate wasAddedAfterParent, final List tokens, @@ -338,13 +365,13 @@ private void generateMessageFieldsDecodeFrom( { final Token encodingToken = tokens.get(i + 1); - generateFieldDecodeFrom( + generateFieldDecodeWith( sb, wasAddedAfterParent, signalToken, encodingToken, codecClassName, indent); } } } - private void generateFieldDecodeFrom( + private void generateFieldDecodeWith( final StringBuilder sb, final Predicate wasAddedAfterParent, final Token fieldToken, @@ -355,21 +382,21 @@ private void generateFieldDecodeFrom( switch (typeToken.signal()) { case ENCODING: - generatePrimitiveDecodeFrom(sb, fieldToken, typeToken, wasAddedAfterParent, codecClassName, indent); + generatePrimitiveDecodeWith(sb, fieldToken, typeToken, wasAddedAfterParent, codecClassName, indent); break; case BEGIN_SET: - generatePropertyDecodeFrom(sb, fieldToken, wasAddedAfterParent, "0", null, indent); + generatePropertyDecodeWith(sb, fieldToken, wasAddedAfterParent, "0", null, indent); break; case BEGIN_ENUM: final String enumName = formatClassName(typeToken.applicableTypeName()); final String nullValue = formatNamespace(ir.packageName()) + "." + enumName + ".NULL_VALUE"; - generatePropertyDecodeFrom(sb, fieldToken, wasAddedAfterParent, nullValue, null, indent); + generatePropertyDecodeWith(sb, fieldToken, wasAddedAfterParent, nullValue, null, indent); break; case BEGIN_COMPOSITE: - generateComplexDecodeFrom(sb, fieldToken, typeToken, indent); + generateComplexDecodeWith(sb, fieldToken, typeToken, indent); break; default: @@ -377,7 +404,7 @@ private void generateFieldDecodeFrom( } } - private void generatePrimitiveDecodeFrom( + private void generatePrimitiveDecodeWith( final StringBuilder sb, final Token fieldToken, final Token typeToken, @@ -395,15 +422,15 @@ private void generatePrimitiveDecodeFrom( if (arrayLength == 1) { final String codecNullValue = codecClassName + "." + formatPropertyName(fieldToken.name()) + "NullValue"; - generatePropertyDecodeFrom(sb, fieldToken, wasAddedAfterParent, "null", codecNullValue, indent); + generatePropertyDecodeWith(sb, fieldToken, wasAddedAfterParent, "null", codecNullValue, indent); } else if (arrayLength > 1) { - generateArrayDecodeFrom(sb, fieldToken, typeToken, wasAddedAfterParent, indent); + generateArrayDecodeWith(sb, fieldToken, typeToken, wasAddedAfterParent, indent); } } - private void generateArrayDecodeFrom( + private void generateArrayDecodeWith( final StringBuilder sb, final Token fieldToken, final Token typeToken, @@ -444,7 +471,7 @@ private void generateArrayDecodeFrom( } } - private void generatePropertyDecodeFrom( + private void generatePropertyDecodeWith( final StringBuilder sb, final Token fieldToken, final Predicate wasAddedAfterParent, @@ -471,7 +498,7 @@ private void generatePropertyDecodeFrom( ); } - private void generateComplexDecodeFrom( + private void generateComplexDecodeWith( final StringBuilder sb, final Token fieldToken, final Token typeToken, @@ -482,11 +509,11 @@ private void generateComplexDecodeFrom( final String dtoClassName = formatDtoClassName(typeToken.applicableTypeName()); sb.append(indent).append(formattedPropertyName).append(": ") - .append(dtoClassName).append(".DecodeFrom(codec.") + .append(dtoClassName).append(".DecodeWith(codec.") .append(formattedPropertyName).append(")").append(",\n"); } - private void generateGroupsDecodeFrom( + private void generateGroupsDecodeWith( final StringBuilder sb, final List tokens, final String indent) @@ -514,7 +541,7 @@ private void generateGroupsDecodeFrom( groupToken, token -> token.version() > sinceVersion, indent, - groupDtoClassName + ".DecodeListFrom(codec." + formattedPropertyName + ")", + groupDtoClassName + ".DecodeListWith(codec." + formattedPropertyName + ")", "new List<" + groupDtoClassName + ">(0).AsReadOnly()", null ); @@ -533,7 +560,7 @@ private void generateGroupsDecodeFrom( } } - private void generateVarDataDecodeFrom( + private void generateVarDataDecodeWith( final StringBuilder sb, final List tokens, final Predicate wasAddedAfterParent, @@ -621,8 +648,9 @@ private void generateRecordPropertyAssignment( } } - private void generateEncodeInto( + private void generateEncodeWith( final StringBuilder sb, + final String dtoClassName, final String codecClassName, final List fields, final List groups, @@ -630,17 +658,49 @@ private void generateEncodeInto( final String indent) { sb.append("\n") - .append(indent).append("public void EncodeInto(").append(codecClassName).append(" codec)\n") + .append(indent).append("public static void EncodeWith(") + .append(codecClassName).append(" codec, ") + .append(dtoClassName).append(" dto)\n") .append(indent).append("{\n"); - generateFieldsEncodeInto(sb, codecClassName, fields, indent + INDENT); - generateGroupsEncodeInto(sb, groups, indent + INDENT); - generateVarDataEncodeInto(sb, varData, indent + INDENT); + generateFieldsEncodeWith(sb, codecClassName, fields, indent + INDENT); + generateGroupsEncodeWith(sb, groups, indent + INDENT); + generateVarDataEncodeWith(sb, varData, indent + INDENT); sb.append(indent).append("}\n"); } - private void generateFieldsEncodeInto( + private void generateEncodeInto( + final StringBuilder sb, + final String dtoClassName, + final String codecClassName, + final String indent) + { + sb.append("\n") + .append(indent).append("public static int EncodeInto(") + .append("DirectBuffer buffer, int offset, ") + .append(dtoClassName).append(" dto)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("var encoder = new ").append(codecClassName).append("();\n") + .append(indent).append(INDENT).append("encoder.WrapForEncode(buffer, offset);\n") + .append(indent).append(INDENT).append("EncodeWith(encoder, dto);\n") + .append(indent).append(INDENT).append("return encoder.Limit - offset;\n") + .append(indent).append("}\n"); + + sb.append("\n") + .append(indent).append("public static int EncodeWithHeaderInto(") + .append("DirectBuffer buffer, int offset, ") + .append(dtoClassName).append(" dto)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("var encoder = new ").append(codecClassName).append("();\n") + .append(indent).append(INDENT) + .append("encoder.WrapForEncodeAndApplyHeader(buffer, offset, new MessageHeader());\n") + .append(indent).append(INDENT).append("EncodeWith(encoder, dto);\n") + .append(indent).append(INDENT).append("return encoder.Limit - offset;\n") + .append(indent).append("}\n"); + } + + private void generateFieldsEncodeWith( final StringBuilder sb, final String codecClassName, final List tokens, @@ -652,12 +712,12 @@ private void generateFieldsEncodeInto( if (signalToken.signal() == Signal.BEGIN_FIELD) { final Token encodingToken = tokens.get(i + 1); - generateFieldEncodeInto(sb, codecClassName, signalToken, encodingToken, indent); + generateFieldEncodeWith(sb, codecClassName, signalToken, encodingToken, indent); } } } - private void generateFieldEncodeInto( + private void generateFieldEncodeWith( final StringBuilder sb, final String codecClassName, final Token fieldToken, @@ -667,16 +727,16 @@ private void generateFieldEncodeInto( switch (typeToken.signal()) { case ENCODING: - generatePrimitiveEncodeInto(sb, codecClassName, fieldToken, typeToken, indent); + generatePrimitiveEncodeWith(sb, codecClassName, fieldToken, typeToken, indent); break; case BEGIN_SET: case BEGIN_ENUM: - generateEnumEncodeInto(sb, fieldToken, indent); + generateEnumEncodeWith(sb, fieldToken, indent); break; case BEGIN_COMPOSITE: - generateComplexEncodeInto(sb, fieldToken, indent); + generateComplexEncodeWith(sb, fieldToken, typeToken, indent); break; default: @@ -684,7 +744,7 @@ private void generateFieldEncodeInto( } } - private void generatePrimitiveEncodeInto( + private void generatePrimitiveEncodeWith( final StringBuilder sb, final String codecClassName, final Token fieldToken, @@ -700,15 +760,15 @@ private void generatePrimitiveEncodeInto( if (arrayLength == 1) { - generatePropertyEncodeInto(sb, codecClassName, fieldToken, indent); + generatePropertyEncodeWith(sb, codecClassName, fieldToken, indent); } else if (arrayLength > 1) { - generateArrayEncodeInto(sb, fieldToken, typeToken, indent); + generateArrayEncodeWith(sb, fieldToken, typeToken, indent); } } - private void generateArrayEncodeInto( + private void generateArrayEncodeWith( final StringBuilder sb, final Token fieldToken, final Token typeToken, @@ -724,7 +784,7 @@ private void generateArrayEncodeInto( if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { - final String value = nullableConvertedExpression(fieldToken, formattedPropertyName, "\"\""); + final String value = nullableConvertedExpression(fieldToken, "dto." + formattedPropertyName, "\"\""); sb.append(indent).append("codec.Set").append(formattedPropertyName).append("(") .append(value).append(");\n"); } @@ -732,7 +792,7 @@ private void generateArrayEncodeInto( { final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()); - sb.append(indent).append("new Span<").append(typeName).append(">(").append(formattedPropertyName) + sb.append(indent).append("new Span<").append(typeName).append(">(dto.").append(formattedPropertyName) .append("?.ToArray()).CopyTo(codec.").append(formattedPropertyName).append("AsSpan());\n"); } } @@ -747,7 +807,7 @@ private String nullableConvertedExpression( expression; } - private void generatePropertyEncodeInto( + private void generatePropertyEncodeWith( final StringBuilder sb, final String codecClassName, final Token fieldToken, @@ -763,14 +823,14 @@ private void generatePropertyEncodeInto( final String value = nullableConvertedExpression( fieldToken, - formattedPropertyName, + "dto." + formattedPropertyName, codecClassName + "." + formattedPropertyName + "NullValue"); sb.append(indent).append("codec.").append(formattedPropertyName).append(" = ") .append(value).append(";\n"); } - private void generateEnumEncodeInto( + private void generateEnumEncodeWith( final StringBuilder sb, final Token fieldToken, final String indent) @@ -783,22 +843,25 @@ private void generateEnumEncodeInto( final String propertyName = fieldToken.name(); final String formattedPropertyName = formatPropertyName(propertyName); - sb.append(indent).append("codec.").append(formattedPropertyName).append(" = ") + sb.append(indent).append("codec.").append(formattedPropertyName).append(" = dto.") .append(formattedPropertyName).append(";\n"); } - private void generateComplexEncodeInto( + private void generateComplexEncodeWith( final StringBuilder sb, final Token fieldToken, + final Token typeToken, final String indent) { final String propertyName = fieldToken.name(); final String formattedPropertyName = formatPropertyName(propertyName); - sb.append(indent).append(formattedPropertyName).append(".EncodeInto(codec.") - .append(formattedPropertyName).append(");\n"); + final String dtoClassName = formatDtoClassName(typeToken.applicableTypeName()); + sb.append(indent) + .append(dtoClassName).append(".EncodeWith(codec.").append(formattedPropertyName) + .append(", dto.").append(formattedPropertyName).append(");\n"); } - private void generateGroupsEncodeInto( + private void generateGroupsEncodeWith( final StringBuilder sb, final List tokens, final String indent) @@ -813,15 +876,17 @@ private void generateGroupsEncodeInto( final String groupName = groupToken.name(); final String formattedPropertyName = formatPropertyName(groupName); final String groupCodecVarName = groupName + "Codec"; + final String groupDtoClassName = formatDtoClassName(groupName); sb.append("\n") .append(indent).append("var ").append(groupCodecVarName) .append(" = codec.").append(formattedPropertyName) - .append("Count(").append(formattedPropertyName).append(".Count);\n\n") - .append(indent).append("foreach (var group in ").append(formattedPropertyName).append(")\n") + .append("Count(dto.").append(formattedPropertyName).append(".Count);\n\n") + .append(indent).append("foreach (var group in dto.").append(formattedPropertyName).append(")\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append("group.EncodeInto(").append(groupCodecVarName) - .append(".Next()").append(");\n") + .append(indent).append(INDENT).append(groupDtoClassName).append(".EncodeWith(") + .append(groupCodecVarName) + .append(".Next()").append(", group);\n") .append(indent).append("}\n\n"); i++; @@ -838,7 +903,7 @@ private void generateGroupsEncodeInto( } } - private void generateVarDataEncodeInto( + private void generateVarDataEncodeWith( final StringBuilder sb, final List tokens, final String indent) @@ -851,7 +916,7 @@ private void generateVarDataEncodeInto( final String formattedPropertyName = formatPropertyName(propertyName); sb.append(indent).append("codec.Set").append(formattedPropertyName) - .append("(").append(formattedPropertyName).append(");\n"); + .append("(dto.").append(formattedPropertyName).append(");\n"); } } } @@ -876,7 +941,7 @@ private void generateDisplay( sb.append(", ").append(actingVersion); } sb.append(");\n"); - sb.append(indent).append(INDENT).append("EncodeInto(codec);\n") + sb.append(indent).append(INDENT).append("EncodeWith(codec, this);\n") .append(indent).append(INDENT).append("StringBuilder sb = new StringBuilder();\n") .append(indent).append(INDENT).append("codec.BuildString(sb);\n") .append(indent).append(INDENT).append("return sb.ToString();\n") @@ -1292,8 +1357,8 @@ private void generateComposite(final List tokens) throws IOException final List compositeTokens = tokens.subList(1, tokens.size() - 1); generateCompositePropertyElements(sb, ctorArgs, codecClassName, compositeTokens, BASE_INDENT + INDENT); - generateCompositeDecodeFrom(sb, className, codecClassName, compositeTokens, BASE_INDENT + INDENT); - generateCompositeEncodeInto(sb, codecClassName, compositeTokens, BASE_INDENT + INDENT); + generateCompositeDecodeWith(sb, className, codecClassName, compositeTokens, BASE_INDENT + INDENT); + generateCompositeEncodeWith(sb, className, codecClassName, compositeTokens, BASE_INDENT + INDENT); generateDisplay(sb, codecClassName, "Wrap", codecClassName + ".SbeSchemaVersion", BASE_INDENT + INDENT); removeTrailingComma(ctorArgs); diff --git a/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/Program.cs b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/Program.cs index 60bdc22616..fa73cd118d 100644 --- a/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/Program.cs +++ b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/Program.cs @@ -17,12 +17,12 @@ static int Main(string[] args) { messageHeader.Wrap(buffer, 0, 0); var decoder = new TestMessage(); decoder.WrapForDecode(buffer, 8, messageHeader.BlockLength, messageHeader.Version); - var dto = TestMessageDto.DecodeFrom(decoder); + var dto = TestMessageDto.DecodeWith(decoder); var outputBytes = new byte[inputBytes.Length]; var outputBuffer = new DirectBuffer(outputBytes); var encoder = new TestMessage(); encoder.WrapForEncodeAndApplyHeader(outputBuffer, 0, new MessageHeader()); - dto.EncodeInto(encoder); + TestMessageDto.EncodeWith(encoder, dto); File.WriteAllBytes("output.dat", outputBytes); return 0; } From 96b70326c33c1f1756aca7e5f5746022d8aee72c Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Thu, 2 Nov 2023 11:55:35 +0000 Subject: [PATCH 1151/1594] [C++] Generate DTOs for non-perf-sensitive usecases. In some applications performance is not cricital. Some users would like to use SBE across their whole "estate", but don't want the "sharp edges" associated with using flyweight codecs, e.g., accidental escape. In this commit, I've added a first cut of DTO generation for C++ and a simple test based on the Car Example. The DTOs support encoding and decoding via the generated codecs using `DtoT::encode(CodecT& codec, const DtoT& dto)` and `DtoT::decode(CodecT& codec, Dto& dto)` methods. Generation can be enabled specifying the target code generator class, `uk.co.real_logic.sbe.generation.cpp.CppDtos`, or by passing a system property `-Dsbe.cpp.generate.dtos=true`. --- .../java/uk/co/real_logic/sbe/SbeTool.java | 5 + .../generation/TargetCodeGeneratorLoader.java | 21 +- .../sbe/generation/cpp/CppDtoGenerator.java | 1824 +++++++++++++++++ .../sbe/generation/cpp/CppDtos.java | 36 + .../sbe/generation/cpp/CppGenerator.java | 58 - .../sbe/generation/cpp/CppUtil.java | 58 + sbe-tool/src/test/cpp/CMakeLists.txt | 6 + sbe-tool/src/test/cpp/DtoTest.cpp | 195 ++ .../src/test/resources/dto-test-schema.xml | 110 + 9 files changed, 2250 insertions(+), 63 deletions(-) create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java create mode 100644 sbe-tool/src/test/cpp/DtoTest.cpp create mode 100644 sbe-tool/src/test/resources/dto-test-schema.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index aae460dc2b..a6958a12bf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -192,6 +192,11 @@ public class SbeTool */ public static final String DECODE_UNKNOWN_ENUM_VALUES = "sbe.decode.unknown.enum.values"; + /** + * Should generate C++ DTOs. Defaults to false. + */ + public static final String GENERATE_CPP_DTOS = "sbe.cpp.generate.dtos"; + /** * Configuration option used to manage sinceVersion based transformations. When set, parsed schemas will be * transformed to discard messages and types higher than the specified version. This can be useful when needing diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 54a9766449..6f872cd55e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -18,6 +18,7 @@ import uk.co.real_logic.sbe.generation.c.CGenerator; import uk.co.real_logic.sbe.generation.c.COutputManager; import uk.co.real_logic.sbe.generation.common.PrecedenceChecks; +import uk.co.real_logic.sbe.generation.cpp.CppDtoGenerator; import uk.co.real_logic.sbe.generation.cpp.CppGenerator; import uk.co.real_logic.sbe.generation.cpp.NamespaceOutputManager; import uk.co.real_logic.sbe.generation.golang.GolangGenerator; @@ -83,11 +84,21 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { - return new CppGenerator( - ir, - "true".equals(System.getProperty(DECODE_UNKNOWN_ENUM_VALUES)), - precedenceChecks(), - new NamespaceOutputManager(outputDir, ir.applicableNamespace())); + final NamespaceOutputManager outputManager = new NamespaceOutputManager( + outputDir, ir.applicableNamespace()); + final boolean decodeUnknownEnumValues = "true".equals(System.getProperty(DECODE_UNKNOWN_ENUM_VALUES)); + + final CodeGenerator codecGenerator = new CppGenerator(ir, decodeUnknownEnumValues, precedenceChecks(), + outputManager); + final CodeGenerator dtoGenerator = new CppDtoGenerator(ir, outputManager); + final CodeGenerator combinedGenerator = () -> + { + codecGenerator.generate(); + dtoGenerator.generate(); + }; + + final boolean generateDtos = "true".equals(System.getProperty(GENERATE_CPP_DTOS)); + return generateDtos ? combinedGenerator : codecGenerator; } }, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java new file mode 100644 index 0000000000..e1e3793da8 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -0,0 +1,1824 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * Copyright (C) 2017 MarketFactory, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.generation.cpp; + +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.generation.CodeGenerator; +import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.ir.Signal; +import uk.co.real_logic.sbe.ir.Token; +import org.agrona.LangUtil; +import org.agrona.Verify; +import org.agrona.generation.OutputManager; + +import java.io.IOException; +import java.io.Writer; +import java.util.*; +import java.util.stream.Collectors; + +import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; +import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; +import static uk.co.real_logic.sbe.generation.cpp.CppUtil.*; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData; + +/** + * DTO generator for the CSharp programming language. + */ +public class CppDtoGenerator implements CodeGenerator +{ + private static final String INDENT = " "; + private static final String BASE_INDENT = INDENT; + + private final Ir ir; + private final OutputManager outputManager; + + /** + * Create a new C# DTO {@link CodeGenerator}. + * + * @param ir for the messages and types. + * @param outputManager for generating the DTOs to. + */ + public CppDtoGenerator(final Ir ir, final OutputManager outputManager) + { + Verify.notNull(ir, "ir"); + Verify.notNull(outputManager, "outputManager"); + + this.ir = ir; + this.outputManager = outputManager; + } + + /** + * {@inheritDoc} + */ + public void generate() throws IOException + { + generateDtosForTypes(); + + for (final List tokens : ir.messages()) + { + final Token msgToken = tokens.get(0); + final String codecClassName = formatClassName(msgToken.name()); + final String className = formatDtoClassName(msgToken.name()); + + final List messageBody = tokens.subList(1, tokens.size() - 1); + int offset = 0; + + final ClassBuilder classBuilder = new ClassBuilder(className, BASE_INDENT); + + final List fields = new ArrayList<>(); + offset = collectFields(messageBody, offset, fields); + generateFields(classBuilder, codecClassName, fields, BASE_INDENT + INDENT); + + final List groups = new ArrayList<>(); + offset = collectGroups(messageBody, offset, groups); + generateGroups(classBuilder, className, codecClassName, groups, + BASE_INDENT + INDENT); + + final List varData = new ArrayList<>(); + collectVarData(messageBody, offset, varData); + generateVarData(classBuilder, varData, BASE_INDENT + INDENT); + + generateMessageDecodeFrom(classBuilder, className, codecClassName, fields, + groups, varData, BASE_INDENT + INDENT); + generateMessageEncodeInto(classBuilder, className, codecClassName, fields, groups, varData, + BASE_INDENT + INDENT); + generateDisplay(classBuilder, codecClassName, "wrapForEncode", null, BASE_INDENT + INDENT); + + try (Writer out = outputManager.createOutput(className)) + { + final List beginTypeTokensInSchema = ir.types().stream() + .map(t -> t.get(0)) + .collect(Collectors.toList()); + + final Set referencedTypes = generateTypesToIncludes(beginTypeTokensInSchema); + referencedTypes.add(codecClassName); + + out.append(generateDtoFileHeader( + ir.namespaces(), + className, + referencedTypes)); + out.append(generateDocumentation(BASE_INDENT, msgToken)); + classBuilder.appendTo(out); + out.append("} // namespace\n"); + out.append("#endif\n"); + } + } + } + + private static final class ClassBuilder + { + private final StringBuilder publicSb = new StringBuilder(); + private final StringBuilder privateSb = new StringBuilder(); + private final StringBuilder fieldSb = new StringBuilder(); + private final String className; + private final String indent; + + private ClassBuilder(final String className, final String indent) + { + this.className = className; + this.indent = indent; + } + + public StringBuilder appendPublic() + { + return publicSb; + } + + public StringBuilder appendPrivate() + { + return privateSb; + } + + public StringBuilder appendField() + { + return fieldSb; + } + + public void appendTo(final Appendable out) + { + try + { + out.append(indent).append("class ").append(className).append("\n") + .append(indent).append("{\n") + .append(indent).append("private:\n") + .append(privateSb) + .append("\n") + .append(indent).append("public:\n") + .append(publicSb) + .append("\n") + .append(indent).append("private:\n") + .append(fieldSb) + .append(indent).append("};\n"); + } + catch (final IOException exception) + { + LangUtil.rethrowUnchecked(exception); + } + } + } + + private void generateGroups( + final ClassBuilder classBuilder, + final String qualifiedParentDtoClassName, + final String qualifiedParentCodecClassName, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + final String groupName = groupToken.name(); + final String groupClassName = formatDtoClassName(groupName); + final String qualifiedDtoClassName = qualifiedParentDtoClassName + "::" + groupClassName; + + final String fieldName = "m_" + toLowerFirstChar(groupName); + final String formattedPropertyName = formatPropertyName(groupName); + + classBuilder.appendField().append(indent).append("std::vector<") + .append(qualifiedDtoClassName).append("> ") + .append(fieldName).append(";\n"); + + final ClassBuilder groupClassBuilder = new ClassBuilder(groupClassName, indent); + + i++; + i += tokens.get(i).componentTokenCount(); + + final String qualifiedCodecClassName = + qualifiedParentCodecClassName + "::" + formatClassName(groupName); + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + generateFields(groupClassBuilder, qualifiedCodecClassName, fields, indent + INDENT); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + generateGroups(groupClassBuilder, qualifiedDtoClassName, + qualifiedCodecClassName, groups, indent + INDENT); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + generateVarData(groupClassBuilder, varData, indent + INDENT); + + generateDecodeListFrom( + groupClassBuilder, groupClassName, qualifiedCodecClassName, indent + INDENT); + generateMessageDecodeFrom(groupClassBuilder, groupClassName, qualifiedCodecClassName, + fields, groups, varData, indent + INDENT); + generateMessageEncodeInto( + groupClassBuilder, groupClassName, qualifiedCodecClassName, fields, groups, varData, indent + INDENT); + + groupClassBuilder.appendTo( + classBuilder.appendPublic().append("\n").append(generateDocumentation(indent, groupToken)) + ); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, groupToken)) + .append(indent).append("[[nodiscard]] const std::vector<").append(qualifiedDtoClassName).append(">& ") + .append(formattedPropertyName).append("() const\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, groupToken)) + .append(indent).append("[[nodiscard]] std::vector<").append(qualifiedDtoClassName).append(">& ") + .append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, groupToken)) + .append(indent).append("void ").append(formattedPropertyName).append("(") + .append("const std::vector<").append(qualifiedDtoClassName).append(">& values)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(fieldName).append(" = values;\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, groupToken)) + .append(indent).append("void ").append(formattedPropertyName).append("(") + .append("std::vector<").append(qualifiedDtoClassName).append(">&& values)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(fieldName).append(" = std::move(values);\n") + .append(indent).append("}\n"); + } + } + + private void generateCompositeDecodeFrom( + final ClassBuilder classBuilder, + final String dtoClassName, + final String codecClassName, + final List tokens, + final String indent) + { + final StringBuilder decodeBuilder = classBuilder.appendPublic().append("\n") + .append(indent).append("static void decode(").append(codecClassName).append("& codec, ") + .append(dtoClassName).append("& dto)\n") + .append(indent).append("{\n"); + + for (int i = 0; i < tokens.size(); ) + { + final Token token = tokens.get(i); + + generateFieldDecodeFrom( + decodeBuilder, token, token, codecClassName, indent + INDENT); + + i += tokens.get(i).componentTokenCount(); + } + + decodeBuilder.append(indent).append("}\n"); + } + + private void generateCompositeEncodeInto( + final ClassBuilder classBuilder, + final String dtoClassName, + final String codecClassName, + final List tokens, + final String indent) + { + final StringBuilder encodeBuilder = classBuilder.appendPublic().append("\n") + .append(indent).append("static void encode(").append(codecClassName).append("& codec,") + .append("const ").append(dtoClassName).append("& dto)\n") + .append(indent).append("{\n"); + + for (int i = 0; i < tokens.size(); ) + { + final Token token = tokens.get(i); + + generateFieldEncodeInto(encodeBuilder, codecClassName, token, token, indent + INDENT); + + i += tokens.get(i).componentTokenCount(); + } + + encodeBuilder.append(indent).append("}\n"); + } + + private void generateDecodeListFrom( + final ClassBuilder classBuilder, + final String dtoClassName, + final String codecClassName, + final String indent) + { + classBuilder.appendPublic().append("\n") + .append(indent).append("static std::vector<").append(dtoClassName).append("> decodeMany(") + .append(codecClassName).append("& codec)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("std::vector<").append(dtoClassName) + .append("> dtos(codec.count());\n") + .append(indent).append(INDENT) + .append("for (std::size_t i = 0; i < dtos.size(); i++)\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append(dtoClassName).append(" dto;\n") + .append(indent).append(INDENT).append(INDENT) + .append(dtoClassName).append("::decode(codec.next(), dto);\n") + .append(indent).append(INDENT).append(INDENT) + .append("dtos[i] = dto;\n") + .append(indent).append(INDENT) + .append("}\n") + .append(indent).append(INDENT) + .append("return dtos;\n") + .append(indent).append("}\n"); + } + + private void generateMessageDecodeFrom( + final ClassBuilder classBuilder, + final String dtoClassName, + final String codecClassName, + final List fields, + final List groups, + final List varData, + final String indent) + { + final StringBuilder decodeBuilder = classBuilder.appendPublic().append("\n") + .append(indent).append("static void decode(").append(codecClassName).append("& codec, ") + .append(dtoClassName).append("& dto)\n") + .append(indent).append("{\n"); + + generateMessageFieldsDecodeFrom(decodeBuilder, fields, codecClassName, indent + INDENT); + generateGroupsDecodeFrom(decodeBuilder, groups, indent + INDENT); + generateVarDataDecodeFrom(decodeBuilder, varData, indent + INDENT); + decodeBuilder.append(indent).append("}\n"); + } + + private void generateMessageFieldsDecodeFrom( + final StringBuilder sb, + final List tokens, + final String codecClassName, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token signalToken = tokens.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = tokens.get(i + 1); + + generateFieldDecodeFrom(sb, signalToken, encodingToken, codecClassName, indent); + } + } + } + + private void generateFieldDecodeFrom( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String codecClassName, + final String indent) + { + switch (typeToken.signal()) + { + case ENCODING: + generatePrimitiveDecodeFrom(sb, fieldToken, typeToken, codecClassName, indent); + break; + + case BEGIN_SET: + final String bitSetName = formatDtoClassName(typeToken.applicableTypeName()); + generateBitSetDecodeFrom(sb, fieldToken, bitSetName, indent); + break; + + case BEGIN_ENUM: + generateEnumDecodeFrom(sb, fieldToken, indent); + break; + + case BEGIN_COMPOSITE: + generateCompositePropertyDecodeFrom(sb, fieldToken, typeToken, indent); + break; + + default: + break; + } + } + + private void generatePrimitiveDecodeFrom( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String codecClassName, + final String indent) + { + if (typeToken.isConstantEncoding()) + { + return; + } + + final int arrayLength = typeToken.arrayLength(); + + if (arrayLength == 1) + { + final String typeName = cppTypeName(typeToken.encoding().primitiveType()); + final String codecNullValue = codecClassName + "::" + formatPropertyName(fieldToken.name()) + "NullValue()"; + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + generateRecordPropertyAssignment( + sb, + fieldToken, + indent, + "codec." + formattedPropertyName + "()", + codecNullValue, + typeName + ); + } + else if (arrayLength > 1) + { + generateArrayDecodeFrom(sb, fieldToken, typeToken, codecClassName, indent); + } + } + + private void generateArrayDecodeFrom( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String codecClassName, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + generateRecordPropertyAssignment( + sb, + fieldToken, + indent, + "std::string(codec." + formattedPropertyName + "(), " + + codecClassName + "::" + formattedPropertyName + "Length())", + null, + "std::string" + ); + } + else + { + final StringBuilder initializerList = new StringBuilder(); + initializerList.append("{ "); + final int arrayLength = typeToken.arrayLength(); + for (int i = 0; i < arrayLength; i++) + { + initializerList.append("codec.").append(formattedPropertyName).append("(").append(i).append("),"); + } + assert arrayLength > 0; + initializerList.setLength(initializerList.length() - 1); + initializerList.append(" }"); + + generateRecordPropertyAssignment( + sb, + fieldToken, + indent, + initializerList, + null, + "std::vector<" + cppTypeName(typeToken.encoding().primitiveType()) + ">" + ); + } + } + + private void generateBitSetDecodeFrom( + final StringBuilder sb, + final Token fieldToken, + final String dtoTypeName, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + if (fieldToken.isOptionalEncoding()) + { + sb.append(indent).append("if (codec.").append(formattedPropertyName).append("InActingVersion()"); + + sb.append(")\n") + .append(indent).append("{\n"); + + sb.append(indent).append(INDENT).append(dtoTypeName).append("::decode(codec.") + .append(formattedPropertyName).append("(), ") + .append("dto.").append(formattedPropertyName).append("());\n"); + + sb.append(indent).append("}\n") + .append(indent).append("else\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("dto.").append(formattedPropertyName).append("().clear();\n") + .append(indent).append("}\n"); + } + else + { + sb.append(indent).append(dtoTypeName).append("::decode(codec.") + .append(formattedPropertyName).append("(), ") + .append("dto.").append(formattedPropertyName).append("());\n"); + } + } + + private void generateEnumDecodeFrom( + final StringBuilder sb, + final Token fieldToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + sb.append(indent).append("dto.").append(formattedPropertyName).append("(") + .append("codec.").append(formattedPropertyName).append("());\n"); + } + + private void generateCompositePropertyDecodeFrom( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + final String dtoClassName = formatDtoClassName(typeToken.applicableTypeName()); + + sb.append(indent).append(dtoClassName).append("::decode(codec.") + .append(formattedPropertyName).append("(), ") + .append("dto.").append(formattedPropertyName).append("());\n"); + } + + private void generateGroupsDecodeFrom( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + final String groupName = groupToken.name(); + final String formattedPropertyName = formatPropertyName(groupName); + final String groupDtoClassName = formatDtoClassName(groupName); + + sb.append(indent).append("dto.").append(formattedPropertyName).append("(") + .append(groupDtoClassName).append("::decodeMany(codec.") + .append(formattedPropertyName).append("()));\n"); + + i++; + i += tokens.get(i).componentTokenCount(); + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + } + } + + private void generateVarDataDecodeFrom( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0; i < tokens.size(); i++) + { + final Token token = tokens.get(i); + if (token.signal() == Signal.BEGIN_VAR_DATA) + { + final String propertyName = token.name(); + final Token varDataToken = Generators.findFirst("varData", tokens, i); + final String characterEncoding = varDataToken.encoding().characterEncoding(); + final String formattedPropertyName = formatPropertyName(propertyName); + + final boolean isOptional = token.version() > 0; + + final String dataVar = toLowerFirstChar(propertyName) + "Data"; + final String lengthVar = toLowerFirstChar(propertyName) + "Length"; + final String blockIndent = isOptional ? indent + INDENT : indent; + final StringBuilder codecValueExtraction = new StringBuilder() + .append(blockIndent).append("std::size_t ").append(lengthVar) + .append(" = codec.").append(formattedPropertyName).append("Length();\n") + .append(blockIndent).append("const char* ").append(dataVar) + .append(" = codec.").append(formattedPropertyName).append("();\n"); + + final String dtoValue; + final String nullDtoValue; + + if (characterEncoding == null) + { + dtoValue = "std::vector(" + dataVar + ", " + dataVar + " + " + lengthVar + ")"; + nullDtoValue = "std::vector()"; + } + else + { + dtoValue = "std::string(" + dataVar + ", " + lengthVar + ")"; + nullDtoValue = "\"\""; + } + + if (isOptional) + { + sb.append(indent).append("if (codec.").append(formattedPropertyName).append("InActingVersion()"); + + sb.append(")\n") + .append(indent).append("{\n"); + + sb.append(codecValueExtraction); + + sb.append(indent).append(INDENT).append("dto.").append(formattedPropertyName).append("(") + .append(dtoValue).append(");\n"); + + sb.append(indent).append("}\n") + .append(indent).append("else\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("dto.") + .append(formattedPropertyName).append("(").append(nullDtoValue).append(");\n") + .append(indent).append("}\n"); + } + else + { + sb.append(codecValueExtraction); + + sb.append(indent).append("dto.").append(formattedPropertyName).append("(") + .append(dtoValue).append(");\n"); + } + } + } + } + + private void generateRecordPropertyAssignment( + final StringBuilder sb, + final Token token, + final String indent, + final CharSequence presentExpression, + final String nullCodecValueOrNull, + final String dtoTypeName) + { + final String propertyName = token.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + if (token.isOptionalEncoding()) + { + sb.append(indent).append("if (codec.").append(formattedPropertyName).append("InActingVersion()"); + + if (null != nullCodecValueOrNull) + { + sb.append(" && codec.").append(formattedPropertyName).append("() != ").append(nullCodecValueOrNull); + } + + sb.append(")\n") + .append(indent).append("{\n"); + + sb.append(indent).append(INDENT).append("dto.").append(formattedPropertyName).append("(std::make_optional<") + .append(dtoTypeName).append(">(").append(presentExpression).append("));\n"); + + sb.append(indent).append("}\n") + .append(indent).append("else\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("dto.").append(formattedPropertyName).append("(std::nullopt);\n") + .append(indent).append("}\n"); + } + else + { + sb.append(indent).append("dto.").append(formattedPropertyName).append("(") + .append(presentExpression).append(");\n"); + } + } + + private void generateMessageEncodeInto( + final ClassBuilder classBuilder, + final String dtoClassName, + final String codecClassName, + final List fields, + final List groups, + final List varData, + final String indent) + { + final StringBuilder encodeBuilder = classBuilder.appendPublic().append("\n") + .append(indent).append("static void encode(").append(codecClassName).append("& codec, const ") + .append(dtoClassName).append("& dto)\n") + .append(indent).append("{\n"); + + generateFieldsEncodeInto(encodeBuilder, codecClassName, fields, indent + INDENT); + generateGroupsEncodeInto(encodeBuilder, groups, indent + INDENT); + generateVarDataEncodeInto(encodeBuilder, varData, indent + INDENT); + + encodeBuilder.append(indent).append("}\n"); + } + + private void generateFieldsEncodeInto( + final StringBuilder sb, + final String codecClassName, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token signalToken = tokens.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = tokens.get(i + 1); + generateFieldEncodeInto(sb, codecClassName, signalToken, encodingToken, indent); + } + } + } + + private void generateFieldEncodeInto( + final StringBuilder sb, + final String codecClassName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + switch (typeToken.signal()) + { + case ENCODING: + generatePrimitiveEncodeInto(sb, codecClassName, fieldToken, typeToken, indent); + break; + + case BEGIN_ENUM: + generateEnumEncodeInto(sb, fieldToken, indent); + break; + + case BEGIN_SET: + case BEGIN_COMPOSITE: + generateComplexPropertyEncodeInto(sb, fieldToken, typeToken, indent); + break; + + default: + break; + } + } + + private void generatePrimitiveEncodeInto( + final StringBuilder sb, + final String codecClassName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (typeToken.isConstantEncoding()) + { + return; + } + + final int arrayLength = typeToken.arrayLength(); + + if (arrayLength == 1) + { + generatePrimitiveValueEncodeInto(sb, codecClassName, fieldToken, indent); + } + else if (arrayLength > 1) + { + generateArrayEncodeInto(sb, fieldToken, typeToken, indent); + } + } + + private void generateArrayEncodeInto( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + final String accessor = "dto." + formattedPropertyName + "()"; + final String value = fieldToken.isOptionalEncoding() ? + accessor + ".value_or(" + "\"\"" + ")" : + accessor; + sb.append(indent).append("codec.put").append(toUpperFirstChar(propertyName)).append("(") + .append(value).append(".c_str());\n"); + } + else + { + final String typeName = cppTypeName(typeToken.encoding().primitiveType()); + final String vectorVar = toLowerFirstChar(propertyName) + "Vector"; + + final String accessor = "dto." + formattedPropertyName + "()"; + final String value = fieldToken.isOptionalEncoding() ? + accessor + ".value_or(std::vector<" + typeName + ">())" : + accessor; + + sb.append(indent).append("std::vector<").append(typeName).append("> ").append(vectorVar) + .append(" = ").append(value).append(";\n\n"); + + sb.append(indent).append("if (").append(vectorVar).append(".size() != ") + .append(typeToken.arrayLength()).append(")\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("throw std::invalid_argument(\"") + .append(propertyName) + .append(": array length != ") + .append(typeToken.arrayLength()) + .append("\");\n") + .append(indent).append("}\n\n"); + + sb.append(indent).append("for (std::uint64_t i = 0; i < ").append(typeToken.arrayLength()) + .append("; i++)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("codec.").append(formattedPropertyName).append("(i, ") + .append(vectorVar).append("[i]);\n") + .append(indent).append("}\n"); + } + } + + private void generatePrimitiveValueEncodeInto( + final StringBuilder sb, + final String codecClassName, + final Token fieldToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + final String nullValue = codecClassName + "::" + formattedPropertyName + "NullValue()"; + final String accessor = "dto." + formattedPropertyName + "()"; + final String value = fieldToken.isOptionalEncoding() ? + accessor + ".value_or(" + nullValue + ")" : + accessor; + + sb.append(indent).append("codec.").append(formattedPropertyName).append("(") + .append(value).append(");\n"); + } + + private void generateEnumEncodeInto( + final StringBuilder sb, + final Token fieldToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + sb.append(indent).append("codec.").append(formattedPropertyName).append("(dto.") + .append(formattedPropertyName).append("());\n"); + } + + private void generateComplexPropertyEncodeInto( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + final String typeName = formatDtoClassName(typeToken.applicableTypeName()); + + sb.append(indent).append(typeName).append("::encode(codec.") + .append(formattedPropertyName).append("(), dto.") + .append(formattedPropertyName).append("());\n"); + } + + private void generateGroupsEncodeInto( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + final String groupName = groupToken.name(); + final String formattedPropertyName = formatPropertyName(groupName); + final String groupCodecVarName = groupName + "Codec"; + final String groupDtoTypeName = formatDtoClassName(groupName); + + sb.append("\n") + .append(indent).append("const std::vector<").append(groupDtoTypeName).append(">& ") + .append(formattedPropertyName).append(" = dto.").append(formattedPropertyName).append("();\n\n") + .append(indent).append("auto&").append(" ").append(groupCodecVarName) + .append(" = codec.").append(formattedPropertyName) + .append("Count(").append(formattedPropertyName).append(".size());\n\n") + .append(indent).append("for (const auto& group: ").append(formattedPropertyName).append(")\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(groupDtoTypeName).append("::encode(").append(groupCodecVarName) + .append(".next(), group);\n") + .append(indent).append("}\n\n"); + + i++; + i += tokens.get(i).componentTokenCount(); + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + } + } + + private void generateVarDataEncodeInto( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0; i < tokens.size(); i++) + { + final Token token = tokens.get(i); + if (token.signal() == Signal.BEGIN_VAR_DATA) + { + final String propertyName = token.name(); + final Token lengthToken = Generators.findFirst("length", tokens, i); + final String lengthTypeName = cppTypeName(lengthToken.encoding().primitiveType()); + final Token varDataToken = Generators.findFirst("varData", tokens, i); + final String characterEncoding = varDataToken.encoding().characterEncoding(); + final String formattedPropertyName = formatPropertyName(propertyName); + final String varName = toLowerFirstChar(propertyName) + "Vector"; + + sb.append(indent).append("auto& ").append(varName).append(" = dto.") + .append(formattedPropertyName).append("();\n") + .append(indent).append("codec.put").append(toUpperFirstChar(propertyName)) + .append("("); + + if (null == characterEncoding) + { + sb.append("reinterpret_cast(").append(varName).append(".data()), ") + .append("static_cast<").append(lengthTypeName).append(">(").append(varName).append(".size())"); + } + else + { + sb.append(varName); + } + + sb.append(");\n"); + } + } + } + + private void generateDisplay( + final ClassBuilder classBuilder, + final String codecClassName, + final String wrapMethod, + final String actingVersion, + final String indent) + { + final StringBuilder toStringBuilder = classBuilder.appendPublic() + .append("\n") + .append(indent).append( + "std::string string(char* tempBuffer, std::uint64_t offset, std::uint64_t length) const\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(codecClassName).append(" codec;\n") + .append(indent).append(INDENT).append("codec."); + + toStringBuilder.append(wrapMethod).append("(tempBuffer, offset"); + + if (null != actingVersion) + { + toStringBuilder.append(", ").append(actingVersion); + } + + toStringBuilder.append(", ").append("length);\n"); + + toStringBuilder.append(indent).append(INDENT).append("encode(codec, *this);\n") + .append(indent).append(INDENT).append("std::ostringstream oss;\n") + .append(indent).append(INDENT).append("oss << codec;\n") + .append(indent).append(INDENT).append("return oss.str();\n") + .append(indent).append("}\n"); + } + + private void generateFields( + final ClassBuilder classBuilder, + final String codecClassName, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token signalToken = tokens.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = tokens.get(i + 1); + final String propertyName = signalToken.name(); + + switch (encodingToken.signal()) + { + case ENCODING: + generatePrimitiveProperty( + classBuilder, codecClassName, propertyName, signalToken, encodingToken, indent); + break; + + case BEGIN_ENUM: + generateEnumProperty(classBuilder, propertyName, signalToken, encodingToken, indent); + break; + + case BEGIN_SET: + case BEGIN_COMPOSITE: + generateComplexProperty(classBuilder, propertyName, signalToken, encodingToken, indent); + break; + + default: + break; + } + } + } + } + + private void generateComplexProperty( + final ClassBuilder classBuilder, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String typeName = formatDtoClassName(typeToken.applicableTypeName()); + final String formattedPropertyName = formatPropertyName(propertyName); + final String fieldName = "m_" + toLowerFirstChar(propertyName); + + classBuilder.appendField() + .append(indent).append(typeName).append(" ").append(fieldName).append(";\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("[[nodiscard]] const ").append(typeName).append("& ") + .append(formattedPropertyName).append("() const\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("[[nodiscard]] ").append(typeName).append("& ") + .append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + } + + private void generateEnumProperty( + final ClassBuilder classBuilder, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String enumName = formatClassName(typeToken.applicableTypeName()) + "::Value"; + + final String formattedPropertyName = formatPropertyName(propertyName); + + if (fieldToken.isConstantEncoding()) + { + final String constValue = fieldToken.encoding().constValue().toString(); + final String caseName = constValue.substring(constValue.indexOf(".") + 1); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("[[nodiscard]] static ").append(enumName).append(" ") + .append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(enumName).append("::") + .append(caseName).append(";\n") + .append(indent).append("}\n"); + } + else + { + final String fieldName = "m_" + toLowerFirstChar(propertyName); + + classBuilder.appendField() + .append(indent).append(enumName).append(" ").append(fieldName).append(";\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("[[nodiscard]] ").append(enumName).append(" ") + .append(formattedPropertyName).append("() const\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("void ").append(formattedPropertyName) + .append("(").append(enumName).append(" value)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append("}\n"); + } + } + + private void generatePrimitiveProperty( + final ClassBuilder classBuilder, + final String codecClassName, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (typeToken.isConstantEncoding()) + { + generateConstPropertyMethods(classBuilder, propertyName, fieldToken, typeToken, indent); + } + else + { + generatePrimitivePropertyMethods(classBuilder, codecClassName, propertyName, fieldToken, typeToken, indent); + } + } + + private void generatePrimitivePropertyMethods( + final ClassBuilder classBuilder, + final String codecClassName, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final int arrayLength = typeToken.arrayLength(); + + if (arrayLength == 1) + { + generateSingleValueProperty(classBuilder, codecClassName, propertyName, fieldToken, typeToken, indent); + } + else if (arrayLength > 1) + { + generateArrayProperty(classBuilder, codecClassName, propertyName, fieldToken, typeToken, indent); + } + } + + private void generateArrayProperty( + final ClassBuilder classBuilder, + final String codecClassName, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String fieldName = "m_" + toLowerFirstChar(propertyName); + final String formattedPropertyName = formatPropertyName(propertyName); + + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + classBuilder.appendField() + .append(indent).append("std::string ").append(fieldName).append(";\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("[[nodiscard]] const std::string& ") + .append(formattedPropertyName).append("() const\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("void ").append(formattedPropertyName) + .append("(const std::string& borrowedValue)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(fieldName).append(" = borrowedValue;\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("void ").append(formattedPropertyName) + .append("(std::string&& ownedValue)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(fieldName).append(" = std::move(ownedValue);\n") + .append(indent).append("}\n"); + } + else + { + final String validateMethod = "validate" + toUpperFirstChar(propertyName); + final String elementTypeName = cppTypeName(typeToken.encoding().primitiveType()); + final String vectorTypeName = "std::vector<" + elementTypeName + ">"; + final CharSequence typeName = typeWithFieldOptionality( + fieldToken, + vectorTypeName + ); + + classBuilder.appendField() + .append(indent).append(typeName).append(" ").append(fieldName).append(";\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("[[nodiscard]] ").append(typeName).append(" ") + .append(formattedPropertyName).append("() const\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("void ").append(formattedPropertyName).append("(") + .append(typeName).append("& borrowedValue").append(")\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(validateMethod).append("(borrowedValue);\n") + .append(indent).append(INDENT).append(fieldName).append(" = borrowedValue;\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("void ").append(formattedPropertyName).append("(") + .append(typeName).append("&& ownedValue").append(")\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(validateMethod).append("(ownedValue);\n") + .append(indent).append(INDENT).append(fieldName).append(" = std::move(ownedValue);\n") + .append(indent).append("}\n"); + + generateArrayValidateMethod( + classBuilder, + codecClassName, + fieldToken, + indent, + validateMethod, + typeName, + vectorTypeName, + formattedPropertyName); + } + } + + private static void generateArrayValidateMethod( + final ClassBuilder classBuilder, + final String codecClassName, + final Token fieldToken, + final String indent, + final String validateMethod, + final CharSequence typeName, + final String vectorTypeName, + final String formattedPropertyName) + { + final StringBuilder validateBuilder = classBuilder.appendPrivate().append("\n") + .append(indent).append("static void ").append(validateMethod).append("(") + .append(typeName).append(" value)\n") + .append(indent).append("{\n"); + + String value = "value"; + + if (fieldToken.isOptionalEncoding()) + { + validateBuilder.append(indent).append(INDENT) + .append("if (!value.has_value())\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("return;\n") + .append(indent).append(INDENT) + .append("}\n"); + + validateBuilder.append(indent).append(INDENT) + .append(vectorTypeName).append(" actualValue = value.value();\n"); + + value = "actualValue"; + } + + validateBuilder.append(indent).append(INDENT) + .append("if (").append(value).append(".size() > ").append(codecClassName).append("::") + .append(formattedPropertyName).append("Length())\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("throw std::invalid_argument(\"") + .append(formattedPropertyName) + .append(": too many elements: \" + std::to_string(") + .append(value).append(".size()));\n") + .append(indent).append(INDENT) + .append("}\n") + .append(indent).append("}\n"); + } + + private void generateSingleValueProperty( + final ClassBuilder classBuilder, + final String codecClassName, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String elementTypeName = cppTypeName(typeToken.encoding().primitiveType()); + final CharSequence typeName = typeWithFieldOptionality( + fieldToken, + elementTypeName + ); + final String formattedPropertyName = formatPropertyName(propertyName); + final String fieldName = "m_" + toLowerFirstChar(propertyName); + final String validateMethod = "validate" + toUpperFirstChar(propertyName); + + classBuilder.appendField() + .append(indent).append(typeName).append(" ").append(fieldName).append(";\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("[[nodiscard]] ").append(typeName).append(" ") + .append(formattedPropertyName).append("() const\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("void ").append(formattedPropertyName).append("(") + .append(typeName).append(" value)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(validateMethod).append("(value);\n") + .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append("}\n"); + + final StringBuilder validateBuilder = classBuilder.appendPrivate().append("\n") + .append(indent).append("static void ").append(validateMethod).append("(") + .append(typeName).append(" value)\n") + .append(indent).append("{\n"); + + String value = "value"; + + if (fieldToken.isOptionalEncoding()) + { + validateBuilder.append(indent).append(INDENT) + .append("if (!value.has_value())\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("return;\n") + .append(indent).append(INDENT) + .append("}\n"); + + validateBuilder.append(indent).append(INDENT) + .append("if (value.value() == ").append(codecClassName).append("::") + .append(formattedPropertyName).append("NullValue())\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("throw std::invalid_argument(\"") + .append(propertyName) + .append(": null value is reserved: \" + std::to_string(value.value()));\n") + .append(indent).append(INDENT) + .append("}\n"); + + validateBuilder.append(indent).append(INDENT) + .append(elementTypeName).append(" actualValue = value.value();\n"); + + value = "actualValue"; + } + + validateBuilder.append(indent).append(INDENT) + .append("if (").append(value).append(" < ") + .append(codecClassName).append("::").append(formattedPropertyName).append("MinValue() || ") + .append(value).append(" > ") + .append(codecClassName).append("::").append(formattedPropertyName).append("MaxValue())\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("throw std::invalid_argument(\"") + .append(propertyName) + .append(": value is out of allowed range: \" + std::to_string(") + .append(value).append("));\n") + .append(indent).append(INDENT) + .append("}\n") + .append(indent).append("}\n"); + } + + private void generateConstPropertyMethods( + final ClassBuilder classBuilder, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("static std::string ").append(toLowerFirstChar(propertyName)).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT) + .append("return \"").append(typeToken.encoding().constValue().toString()).append("\";\n") + .append(indent).append("}\n"); + } + else + { + final CharSequence literalValue = + generateLiteral(typeToken.encoding().primitiveType(), typeToken.encoding().constValue().toString()); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("[[nodiscard]] static ") + .append(cppTypeName(typeToken.encoding().primitiveType())) + .append(" ").append(formatPropertyName(propertyName)).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(literalValue).append(";\n") + .append(indent).append("}\n"); + } + } + + private void generateVarData( + final ClassBuilder classBuilder, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token token = tokens.get(i); + if (token.signal() == Signal.BEGIN_VAR_DATA) + { + final String propertyName = token.name(); + final Token varDataToken = Generators.findFirst("varData", tokens, i); + final String characterEncoding = varDataToken.encoding().characterEncoding(); + final String dtoType = characterEncoding == null ? "std::vector" : "std::string"; + + final String fieldName = "m_" + toLowerFirstChar(propertyName); + final String formattedPropertyName = formatPropertyName(propertyName); + + classBuilder.appendField() + .append(indent).append(dtoType).append(" ").append(fieldName).append(";\n"); + + classBuilder.appendPublic().append("\n") + .append(indent).append("[[nodiscard]] const ").append(dtoType).append("& ") + .append(formattedPropertyName).append("() const\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(indent).append("[[nodiscard]] ").append(dtoType).append("& ") + .append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(indent).append("void ").append(formattedPropertyName) + .append("(const ").append(dtoType).append("& borrowedValue)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(fieldName).append(" = borrowedValue;\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(indent).append("void ").append(formattedPropertyName) + .append("(").append(dtoType).append("&& ownedValue)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(fieldName).append(" = std::move(ownedValue);\n") + .append(indent).append("}\n"); + } + } + } + + private static String formatDtoClassName(final String name) + { + return formatClassName(name + "Dto"); + } + + private void generateDtosForTypes() throws IOException + { + for (final List tokens : ir.types()) + { + switch (tokens.get(0).signal()) + { + case BEGIN_COMPOSITE: + generateComposite(tokens); + break; + + case BEGIN_SET: + generateChoiceSet(tokens); + break; + + default: + break; + } + } + } + + private void generateComposite(final List tokens) throws IOException + { + final String name = tokens.get(0).applicableTypeName(); + final String className = formatDtoClassName(name); + final String codecClassName = formatClassName(name); + + try (Writer out = outputManager.createOutput(className)) + { + final List compositeTokens = tokens.subList(1, tokens.size() - 1); + final Set referencedTypes = generateTypesToIncludes(compositeTokens); + referencedTypes.add(codecClassName); + out.append(generateDtoFileHeader(ir.namespaces(), className, referencedTypes)); + out.append(generateDocumentation(BASE_INDENT, tokens.get(0))); + + final ClassBuilder classBuilder = new ClassBuilder(className, BASE_INDENT); + + generateCompositePropertyElements(classBuilder, codecClassName, compositeTokens, BASE_INDENT + INDENT); + generateCompositeDecodeFrom(classBuilder, className, codecClassName, compositeTokens, + BASE_INDENT + INDENT); + generateCompositeEncodeInto(classBuilder, className, codecClassName, compositeTokens, BASE_INDENT + INDENT); + generateDisplay(classBuilder, codecClassName, "wrap", + codecClassName + "::sbeSchemaVersion()", BASE_INDENT + INDENT); + + classBuilder.appendTo(out); + out.append("} // namespace\n"); + out.append("#endif\n"); + } + } + + private void generateChoiceSet(final List tokens) throws IOException + { + final String name = tokens.get(0).applicableTypeName(); + final String className = formatDtoClassName(name); + final String codecClassName = formatClassName(name); + + try (Writer out = outputManager.createOutput(className)) + { + final List setTokens = tokens.subList(1, tokens.size() - 1); + final Set referencedTypes = generateTypesToIncludes(setTokens); + referencedTypes.add(codecClassName); + out.append(generateDtoFileHeader(ir.namespaces(), className, referencedTypes)); + out.append(generateDocumentation(BASE_INDENT, tokens.get(0))); + + final ClassBuilder classBuilder = new ClassBuilder(className, BASE_INDENT); + + generateChoices(classBuilder, className, setTokens, BASE_INDENT + INDENT); + generateChoiceSetDecodeFrom(classBuilder, className, codecClassName, setTokens, BASE_INDENT + INDENT); + generateChoiceSetEncodeInto(classBuilder, className, codecClassName, setTokens, BASE_INDENT + INDENT); + + classBuilder.appendTo(out); + out.append("} // namespace\n"); + out.append("#endif\n"); + } + } + + private void generateChoiceSetEncodeInto( + final ClassBuilder classBuilder, + final String dtoClassName, + final String codecClassName, + final List setTokens, + final String indent) + { + final StringBuilder encodeBuilder = classBuilder.appendPublic() + .append("\n") + .append(indent).append("static void encode(\n") + .append(indent).append(INDENT).append(codecClassName).append("& codec, ") + .append("const ").append(dtoClassName).append("& dto)\n") + .append(indent).append("{\n"); + + encodeBuilder.append(indent).append(INDENT).append("codec.clear();\n"); + + for (final Token token : setTokens) + { + if (token.signal() == Signal.CHOICE) + { + final String formattedPropertyName = formatPropertyName(token.name()); + encodeBuilder.append(indent).append(INDENT).append("codec.").append(formattedPropertyName) + .append("(dto.").append(formattedPropertyName).append("());\n"); + } + } + + encodeBuilder.append(indent).append("}\n"); + } + + private void generateChoiceSetDecodeFrom( + final ClassBuilder classBuilder, + final String dtoClassName, + final String codecClassName, + final List setTokens, + final String indent) + { + final StringBuilder decodeBuilder = classBuilder.appendPublic() + .append("\n") + .append(indent).append("static void decode(\n") + .append(indent).append(INDENT).append("const ").append(codecClassName).append("& codec, ") + .append(dtoClassName).append("& dto)\n") + .append(indent).append("{\n"); + + for (final Token token : setTokens) + { + if (token.signal() == Signal.CHOICE) + { + final String formattedPropertyName = formatPropertyName(token.name()); + decodeBuilder.append(indent).append(INDENT).append("dto.").append(formattedPropertyName) + .append("(codec.").append(formattedPropertyName).append("());\n"); + } + } + + decodeBuilder.append(indent).append("}\n"); + } + + private void generateChoices( + final ClassBuilder classBuilder, + final String dtoClassName, + final List setTokens, + final String indent) + { + final List fields = new ArrayList<>(); + + for (final Token token : setTokens) + { + if (token.signal() == Signal.CHOICE) + { + final String fieldName = "m_" + toLowerFirstChar(token.name()); + final String formattedPropertyName = formatPropertyName(token.name()); + + fields.add(fieldName); + + classBuilder.appendField() + .append(indent).append("bool ").append(fieldName).append(";\n"); + + classBuilder.appendPublic() + .append("\n") + .append(indent).append("[[nodiscard]] bool ").append(formattedPropertyName).append("() const\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic() + .append("\n") + .append(indent).append(dtoClassName).append("& ") + .append(formattedPropertyName).append("(bool value)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append(INDENT).append("return *this;\n") + .append(indent).append("}\n"); + } + } + + final StringBuilder clearBuilder = classBuilder.appendPublic() + .append(indent).append(dtoClassName).append("& clear()\n") + .append(indent).append("{\n"); + + for (final String field : fields) + { + clearBuilder.append(indent).append(INDENT).append(field).append(" = false;\n"); + } + + clearBuilder.append(indent).append(INDENT).append("return *this;\n") + .append(indent).append("}\n"); + } + + private void generateCompositePropertyElements( + final ClassBuilder classBuilder, + final String codecClassName, + final List tokens, + final String indent) + { + for (int i = 0; i < tokens.size(); ) + { + final Token token = tokens.get(i); + final String propertyName = formatPropertyName(token.name()); + + switch (token.signal()) + { + case ENCODING: + generatePrimitiveProperty(classBuilder, codecClassName, propertyName, token, token, indent); + break; + + case BEGIN_ENUM: + generateEnumProperty(classBuilder, propertyName, token, token, indent); + break; + + case BEGIN_SET: + case BEGIN_COMPOSITE: + generateComplexProperty(classBuilder, propertyName, token, token, indent); + break; + + default: + break; + } + + i += tokens.get(i).componentTokenCount(); + } + } + + private static Set generateTypesToIncludes(final List tokens) + { + final Set typesToInclude = new HashSet<>(); + + for (final Token token : tokens) + { + switch (token.signal()) + { + case BEGIN_ENUM: + typesToInclude.add(formatClassName(token.applicableTypeName())); + break; + + case BEGIN_SET: + case BEGIN_COMPOSITE: + typesToInclude.add(formatDtoClassName(token.applicableTypeName())); + break; + + default: + break; + } + } + + return typesToInclude; + } + + private static CharSequence typeWithFieldOptionality( + final Token fieldToken, + final String typeName) + { + if (fieldToken.isOptionalEncoding()) + { + return "std::optional<" + typeName + ">"; + } + else + { + return typeName; + } + } + + private static CharSequence generateDtoFileHeader( + final CharSequence[] namespaces, + final String className, + final Collection typesToInclude) + { + final StringBuilder sb = new StringBuilder(); + + sb.append("/* Generated SBE (Simple Binary Encoding) message DTO */\n"); + + sb.append(String.format( + "#ifndef _%1$s_%2$s_CXX_H_\n" + + "#define _%1$s_%2$s_CXX_H_\n\n", + String.join("_", namespaces).toUpperCase(), + className.toUpperCase())); + + sb.append("#if __cplusplus < 201703L\n") + .append("#error DTO code requires at least C++17.\n") + .append("#endif\n\n"); + + sb.append("#include \n") + .append("#include \n") + .append("#include \n") + .append("#include \n") + .append("#include \n") + .append("#include \n") + .append("#include \n") + .append("#include \n") + .append("#include \n") + .append("#include \n"); + + if (typesToInclude != null && !typesToInclude.isEmpty()) + { + sb.append("\n"); + for (final String incName : typesToInclude) + { + sb.append("#include \"").append(incName).append(".h\"\n"); + } + } + + sb.append("\nnamespace "); + sb.append(String.join(" {\nnamespace ", namespaces)); + sb.append(" {\n\n"); + + return sb; + } + + private static String generateDocumentation(final String indent, final Token token) + { + final String description = token.description(); + if (null == description || description.isEmpty()) + { + return ""; + } + + return + indent + "/**\n" + + indent + " * " + description + "\n" + + indent + " */\n"; + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java new file mode 100644 index 0000000000..dfe00b449e --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * Copyright 2017 MarketFactory Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.generation.cpp; + +import uk.co.real_logic.sbe.generation.CodeGenerator; +import uk.co.real_logic.sbe.generation.TargetCodeGenerator; +import uk.co.real_logic.sbe.ir.Ir; + +/** + * {@link CodeGenerator} factory for CSharp DTOs. + */ +public class CppDtos implements TargetCodeGenerator +{ + /** + * {@inheritDoc} + */ + public CodeGenerator newInstance(final Ir ir, final String outputDir) + { + return new CppDtoGenerator(ir, new NamespaceOutputManager(outputDir, ir.applicableNamespace())); + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 5b5e6f0721..99f5498e38 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -3503,64 +3503,6 @@ private CharSequence generateNullValueLiteral(final PrimitiveType primitiveType, return generateLiteral(primitiveType, encoding.applicableNullValue().toString()); } - private static CharSequence generateLiteral(final PrimitiveType type, final String value) - { - String literal = ""; - - switch (type) - { - case CHAR: - case UINT8: - case UINT16: - case INT8: - case INT16: - literal = "static_cast<" + cppTypeName(type) + ">(" + value + ")"; - break; - - case UINT32: - literal = "UINT32_C(0x" + Integer.toHexString((int)Long.parseLong(value)) + ")"; - break; - - case INT32: - final long intValue = Long.parseLong(value); - if (intValue == Integer.MIN_VALUE) - { - literal = "INT32_MIN"; - } - else - { - literal = "INT32_C(" + value + ")"; - } - break; - - case FLOAT: - literal = value.endsWith("NaN") ? "SBE_FLOAT_NAN" : value + "f"; - break; - - case INT64: - final long longValue = Long.parseLong(value); - if (longValue == Long.MIN_VALUE) - { - literal = "INT64_MIN"; - } - else - { - literal = "INT64_C(" + value + ")"; - } - break; - - case UINT64: - literal = "UINT64_C(0x" + Long.toHexString(Long.parseLong(value)) + ")"; - break; - - case DOUBLE: - literal = value.endsWith("NaN") ? "SBE_DOUBLE_NAN" : value; - break; - } - - return literal; - } - private void generateDisplay( final StringBuilder sb, final String name, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index 76b75687d2..6ac6d8afa8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -137,4 +137,62 @@ public static String closingBraces(final int count) return sb.toString(); } + + static CharSequence generateLiteral(final PrimitiveType type, final String value) + { + String literal = ""; + + switch (type) + { + case CHAR: + case UINT8: + case UINT16: + case INT8: + case INT16: + literal = "static_cast<" + cppTypeName(type) + ">(" + value + ")"; + break; + + case UINT32: + literal = "UINT32_C(0x" + Integer.toHexString((int)Long.parseLong(value)) + ")"; + break; + + case INT32: + final long intValue = Long.parseLong(value); + if (intValue == Integer.MIN_VALUE) + { + literal = "INT32_MIN"; + } + else + { + literal = "INT32_C(" + value + ")"; + } + break; + + case FLOAT: + literal = value.endsWith("NaN") ? "SBE_FLOAT_NAN" : value + "f"; + break; + + case INT64: + final long longValue = Long.parseLong(value); + if (longValue == Long.MIN_VALUE) + { + literal = "INT64_MIN"; + } + else + { + literal = "INT64_C(" + value + ")"; + } + break; + + case UINT64: + literal = "UINT64_C(0x" + Long.toHexString(Long.parseLong(value)) + ")"; + break; + + case DOUBLE: + literal = value.endsWith("NaN") ? "SBE_DOUBLE_NAN" : value; + break; + } + + return literal; + } } diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index b1319e2389..92f061d2ef 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -39,6 +39,7 @@ set(COMPOSITE_ELEMENTS_SCHEMA ${CODEC_SCHEMA_DIR}/composite-elements-schema.xml) set(COMPOSITE_OFFSETS_SCHEMA ${CODEC_SCHEMA_DIR}/composite-offsets-schema.xml) set(MESSAGE_BLOCK_LENGTH_TEST ${CODEC_SCHEMA_DIR}/message-block-length-test.xml) set(GROUP_WITH_DATA_SCHEMA ${CODEC_SCHEMA_DIR}/group-with-data-schema.xml) +set(DTO_SCHEMA ${CODEC_SCHEMA_DIR}/dto-test-schema.xml) set(ISSUE835_SCHEMA ${CODEC_SCHEMA_DIR}/issue835.xml) set(ISSUE889_SCHEMA ${CODEC_SCHEMA_DIR}/issue889.xml) set(ACCESS_ORDER_SCHEMA ${CODEC_SCHEMA_DIR}/field-order-check-schema.xml) @@ -54,6 +55,7 @@ add_custom_command( ${COMPOSITE_OFFSETS_SCHEMA} ${MESSAGE_BLOCK_LENGTH_TEST} ${GROUP_WITH_DATA_SCHEMA} + ${DTO_SCHEMA} ${ISSUE835_SCHEMA} ${ISSUE889_SCHEMA} ${ACCESS_ORDER_SCHEMA} @@ -66,12 +68,14 @@ add_custom_command( -Dsbe.generate.precedence.checks="true" -Dsbe.precedence.checks.flag.name="SBE_ENABLE_PRECEDENCE_CHECKS_IN_TESTS" -Dsbe.cpp.disable.implicit.copying="true" + -Dsbe.cpp.generate.dtos="true" -jar ${SBE_JAR} ${CODE_GENERATION_SCHEMA} ${COMPOSITE_OFFSETS_SCHEMA} ${MESSAGE_BLOCK_LENGTH_TEST} ${GROUP_WITH_DATA_SCHEMA} ${COMPOSITE_ELEMENTS_SCHEMA} + ${DTO_SCHEMA} ${ISSUE835_SCHEMA} ${ISSUE889_SCHEMA} ${ACCESS_ORDER_SCHEMA} @@ -92,3 +96,5 @@ sbe_test(Issue835Test codecs) sbe_test(Issue889Test codecs) sbe_test(FieldAccessOrderCheckTest codecs) target_compile_definitions(FieldAccessOrderCheckTest PRIVATE SBE_ENABLE_PRECEDENCE_CHECKS_IN_TESTS) +sbe_test(DtoTest codecs) +target_compile_features(DtoTest PRIVATE cxx_std_17) diff --git a/sbe-tool/src/test/cpp/DtoTest.cpp b/sbe-tool/src/test/cpp/DtoTest.cpp new file mode 100644 index 0000000000..59f46fe149 --- /dev/null +++ b/sbe-tool/src/test/cpp/DtoTest.cpp @@ -0,0 +1,195 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if __cplusplus < 201703L +#error DTO code requires at least C++17. +#endif + +#include +#include "dto_test/ExtendedCar.h" +#include "dto_test/ExtendedCarDto.h" + +using namespace dto_test; + +static const std::size_t BUFFER_LEN = 2048; + +static const std::uint32_t SERIAL_NUMBER = 1234; +static const std::uint16_t MODEL_YEAR = 2013; +static const BooleanType::Value AVAILABLE = BooleanType::T; +static const Model::Value CODE = Model::A; +static const bool CRUISE_CONTROL = true; +static const bool SPORTS_PACK = true; +static const bool SUNROOF = false; +static const BoostType::Value BOOST_TYPE = BoostType::NITROUS; +static const std::uint8_t BOOSTER_HORSEPOWER = 200; +static const std::int32_t ADDED1 = 7; +static const std::int8_t ADDED6_1 = 11; +static const std::int8_t ADDED6_2 = 13; + +static char VEHICLE_CODE[] = { 'a', 'b', 'c', 'd', 'e', 'f' }; +static char MANUFACTURER_CODE[] = { '1', '2', '3' }; +static const char *FUEL_FIGURES_1_USAGE_DESCRIPTION = "Urban Cycle"; +static const char *FUEL_FIGURES_2_USAGE_DESCRIPTION = "Combined Cycle"; +static const char *FUEL_FIGURES_3_USAGE_DESCRIPTION = "Highway Cycle"; +static const char *MANUFACTURER = "Honda"; +static const char *MODEL = "Civic VTi"; +static const char *ACTIVATION_CODE = "deadbeef"; +static const char *ADDED5 = "feedface"; + +static const std::uint8_t PERFORMANCE_FIGURES_COUNT = 2; +static const std::uint8_t FUEL_FIGURES_COUNT = 3; +static const std::uint8_t ACCELERATION_COUNT = 3; + +static const std::uint16_t fuel1Speed = 30; +static const float fuel1Mpg = 35.9f; +static const std::int8_t fuel1Added2Element1 = 42; +static const std::int8_t fuel1Added2Element2 = 43; +static const std::int8_t fuel1Added3 = 44; +static const std::uint16_t fuel2Speed = 55; +static const float fuel2Mpg = 49.0f; +static const std::int8_t fuel2Added2Element1 = 45; +static const std::int8_t fuel2Added2Element2 = 46; +static const std::int8_t fuel2Added3 = 47; +static const std::uint16_t fuel3Speed = 75; +static const float fuel3Mpg = 40.0f; +static const std::int8_t fuel3Added2Element1 = 48; +static const std::int8_t fuel3Added2Element2 = 49; +static const std::int8_t fuel3Added3 = 50; + +static const std::uint8_t perf1Octane = 95; +static const std::uint16_t perf1aMph = 30; +static const float perf1aSeconds = 4.0f; +static const std::uint16_t perf1bMph = 60; +static const float perf1bSeconds = 7.5f; +static const std::uint16_t perf1cMph = 100; +static const float perf1cSeconds = 12.2f; + +static const std::uint8_t perf2Octane = 99; +static const std::uint16_t perf2aMph = 30; +static const float perf2aSeconds = 3.8f; +static const std::uint16_t perf2bMph = 60; +static const float perf2bSeconds = 7.1f; +static const std::uint16_t perf2cMph = 100; +static const float perf2cSeconds = 11.8f; + +static const std::uint16_t engineCapacity = 2000; +static const std::uint8_t engineNumCylinders = 4; + +class DtoTest : public testing::Test +{ + +public: + static std::uint64_t encodeCar(ExtendedCar &car) + { + car.serialNumber(SERIAL_NUMBER) + .modelYear(MODEL_YEAR) + .available(AVAILABLE) + .code(CODE) + .putVehicleCode(VEHICLE_CODE); + + car.extras().clear() + .cruiseControl(CRUISE_CONTROL) + .sportsPack(SPORTS_PACK) + .sunRoof(SUNROOF); + + car.engine() + .capacity(engineCapacity) + .numCylinders(engineNumCylinders) + .putManufacturerCode(MANUFACTURER_CODE) + .efficiency(50) + .boosterEnabled(BooleanType::Value::T) + .booster().boostType(BOOST_TYPE).horsePower(BOOSTER_HORSEPOWER); + + car.added1(ADDED1); + + car.added4(BooleanType::Value::T); + + car.added6().one(ADDED6_1).two(ADDED6_2); + + ExtendedCar::FuelFigures &fuelFigures = car.fuelFiguresCount(FUEL_FIGURES_COUNT); + + fuelFigures + .next().speed(fuel1Speed).mpg(fuel1Mpg) + .putAdded2(fuel1Added2Element1, fuel1Added2Element2) + .added3(fuel1Added3) + .putUsageDescription( + FUEL_FIGURES_1_USAGE_DESCRIPTION, static_cast(strlen(FUEL_FIGURES_1_USAGE_DESCRIPTION))); + + fuelFigures + .next().speed(fuel2Speed).mpg(fuel2Mpg) + .putAdded2(fuel2Added2Element1, fuel2Added2Element2) + .added3(fuel2Added3) + .putUsageDescription( + FUEL_FIGURES_2_USAGE_DESCRIPTION, static_cast(strlen(FUEL_FIGURES_2_USAGE_DESCRIPTION))); + + fuelFigures + .next().speed(fuel3Speed).mpg(fuel3Mpg) + .putAdded2(fuel3Added2Element1, fuel3Added2Element2) + .added3(fuel3Added3) + .putUsageDescription( + FUEL_FIGURES_3_USAGE_DESCRIPTION, static_cast(strlen(FUEL_FIGURES_3_USAGE_DESCRIPTION))); + + ExtendedCar::PerformanceFigures &perfFigs = car.performanceFiguresCount(PERFORMANCE_FIGURES_COUNT); + + perfFigs.next() + .octaneRating(perf1Octane) + .accelerationCount(ACCELERATION_COUNT) + .next().mph(perf1aMph).seconds(perf1aSeconds) + .next().mph(perf1bMph).seconds(perf1bSeconds) + .next().mph(perf1cMph).seconds(perf1cSeconds); + + perfFigs.next() + .octaneRating(perf2Octane) + .accelerationCount(ACCELERATION_COUNT) + .next().mph(perf2aMph).seconds(perf2aSeconds) + .next().mph(perf2bMph).seconds(perf2bSeconds) + .next().mph(perf2cMph).seconds(perf2cSeconds); + + car.putManufacturer(MANUFACTURER, static_cast(strlen(MANUFACTURER))) + .putModel(MODEL, static_cast(strlen(MODEL))) + .putActivationCode(ACTIVATION_CODE, static_cast(strlen(ACTIVATION_CODE))) + .putAdded5(ADDED5, static_cast(strlen(ADDED5))); + + return car.encodedLength(); + } +}; + +TEST_F(DtoTest, shouldRoundTripCar) +{ + char input[BUFFER_LEN]; + std::memset(input, 0, BUFFER_LEN); + ExtendedCar encoder1; + encoder1.wrapForEncode(input, 0, BUFFER_LEN); + const std::uint64_t encodedCarLength = encodeCar(encoder1); + ExtendedCar decoder; + decoder.wrapForDecode( + input, + 0, + ExtendedCar::sbeBlockLength(), + ExtendedCar::sbeSchemaVersion(), + encodedCarLength); + ExtendedCarDto dto; + ExtendedCarDto::decode(decoder, dto); + char output[BUFFER_LEN]; + std::memset(output, 0, BUFFER_LEN); + ExtendedCar encoder2; + encoder2.wrapForEncode(output, 0, BUFFER_LEN); + ExtendedCarDto::encode(encoder2, dto); + const std::uint64_t encodedCarLength2 = encoder2.encodedLength(); + + EXPECT_EQ(encodedCarLength, encodedCarLength2); + EXPECT_EQ(0, std::memcmp(input, output, encodedCarLength2)); +} diff --git a/sbe-tool/src/test/resources/dto-test-schema.xml b/sbe-tool/src/test/resources/dto-test-schema.xml new file mode 100644 index 0000000000..f6f832e990 --- /dev/null +++ b/sbe-tool/src/test/resources/dto-test-schema.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + T + S + N + K + + + + + + + 9000 + + Petrol + + + + + + 0 + 1 + + + A + B + C + + + 0 + 1 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 029fb2573432fe44fa2b9f0855614242f8511ade Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Thu, 2 Nov 2023 15:09:35 +0000 Subject: [PATCH 1152/1594] [C++] Only build DTOs with compilers that support C++ 17. --- .../sbe/generation/cpp/CppDtoGenerator.java | 6 +++-- sbe-tool/src/test/cpp/CMakeLists.txt | 26 +++++++++++++++++-- sbe-tool/src/test/cpp/DtoTest.cpp | 2 +- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index e1e3793da8..60924dd8f2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -1777,7 +1777,8 @@ private static CharSequence generateDtoFileHeader( String.join("_", namespaces).toUpperCase(), className.toUpperCase())); - sb.append("#if __cplusplus < 201703L\n") + sb.append("#if (defined(_MSVC_LANG) && _MSVC_LANG < 201703L) || ") + .append("(!defined(_MSVC_LANG) && defined(__cplusplus) && __cplusplus < 201703L)\n") .append("#error DTO code requires at least C++17.\n") .append("#endif\n\n"); @@ -1790,7 +1791,8 @@ private static CharSequence generateDtoFileHeader( .append("#include \n") .append("#include \n") .append("#include \n") - .append("#include \n"); + .append("#include \n") + .append("#include \n"); if (typesToInclude != null && !typesToInclude.isEmpty()) { diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index 92f061d2ef..1de7412623 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -96,5 +96,27 @@ sbe_test(Issue835Test codecs) sbe_test(Issue889Test codecs) sbe_test(FieldAccessOrderCheckTest codecs) target_compile_definitions(FieldAccessOrderCheckTest PRIVATE SBE_ENABLE_PRECEDENCE_CHECKS_IN_TESTS) -sbe_test(DtoTest codecs) -target_compile_features(DtoTest PRIVATE cxx_std_17) + +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # Check if the GCC version supports C++17 + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0") + sbe_test(DtoTest codecs) + target_compile_features(DtoTest PRIVATE cxx_std_17) + endif() +endif() + +if (CMAKE_CXX_COMPILER_ID STREQUAL "CLang") + # Check if CLang version supports C++17 + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "4.0") + sbe_test(DtoTest codecs) + target_compile_features(DtoTest PRIVATE cxx_std_17) + endif() +endif() + +if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + # Check if MSVC version supports C++17 + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "19.14") + sbe_test(DtoTest codecs) + target_compile_options(DtoTest PRIVATE /std:c++17) + endif() +endif() diff --git a/sbe-tool/src/test/cpp/DtoTest.cpp b/sbe-tool/src/test/cpp/DtoTest.cpp index 59f46fe149..3c8f675051 100644 --- a/sbe-tool/src/test/cpp/DtoTest.cpp +++ b/sbe-tool/src/test/cpp/DtoTest.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#if __cplusplus < 201703L +#if (defined(_MSVC_LANG) && _MSVC_LANG < 201703L) || (!defined(_MSVC_LANG) && defined(__cplusplus) && __cplusplus < 201703L) #error DTO code requires at least C++17. #endif From 246e6f77a0405435881666835be2c01b73ce891c Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Fri, 3 Nov 2023 09:57:00 +0000 Subject: [PATCH 1153/1594] [C++] Improve naming conventions in DTOs. Changes: - `encode` -> `encodeWith` - `decode` -> `decodeWith` --- .../sbe/generation/cpp/CppDtoGenerator.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index 60924dd8f2..651a3aa676 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -274,7 +274,7 @@ private void generateCompositeDecodeFrom( final String indent) { final StringBuilder decodeBuilder = classBuilder.appendPublic().append("\n") - .append(indent).append("static void decode(").append(codecClassName).append("& codec, ") + .append(indent).append("static void decodeWith(").append(codecClassName).append("& codec, ") .append(dtoClassName).append("& dto)\n") .append(indent).append("{\n"); @@ -299,7 +299,7 @@ private void generateCompositeEncodeInto( final String indent) { final StringBuilder encodeBuilder = classBuilder.appendPublic().append("\n") - .append(indent).append("static void encode(").append(codecClassName).append("& codec,") + .append(indent).append("static void encodeWith(").append(codecClassName).append("& codec,") .append("const ").append(dtoClassName).append("& dto)\n") .append(indent).append("{\n"); @@ -322,7 +322,7 @@ private void generateDecodeListFrom( final String indent) { classBuilder.appendPublic().append("\n") - .append(indent).append("static std::vector<").append(dtoClassName).append("> decodeMany(") + .append(indent).append("static std::vector<").append(dtoClassName).append("> decodeManyWith(") .append(codecClassName).append("& codec)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("std::vector<").append(dtoClassName) @@ -334,7 +334,7 @@ private void generateDecodeListFrom( .append(indent).append(INDENT).append(INDENT) .append(dtoClassName).append(" dto;\n") .append(indent).append(INDENT).append(INDENT) - .append(dtoClassName).append("::decode(codec.next(), dto);\n") + .append(dtoClassName).append("::decodeWith(codec.next(), dto);\n") .append(indent).append(INDENT).append(INDENT) .append("dtos[i] = dto;\n") .append(indent).append(INDENT) @@ -354,7 +354,7 @@ private void generateMessageDecodeFrom( final String indent) { final StringBuilder decodeBuilder = classBuilder.appendPublic().append("\n") - .append(indent).append("static void decode(").append(codecClassName).append("& codec, ") + .append(indent).append("static void decodeWith(").append(codecClassName).append("& codec, ") .append(dtoClassName).append("& dto)\n") .append(indent).append("{\n"); @@ -526,7 +526,7 @@ private void generateBitSetDecodeFrom( sb.append(")\n") .append(indent).append("{\n"); - sb.append(indent).append(INDENT).append(dtoTypeName).append("::decode(codec.") + sb.append(indent).append(INDENT).append(dtoTypeName).append("::decodeWith(codec.") .append(formattedPropertyName).append("(), ") .append("dto.").append(formattedPropertyName).append("());\n"); @@ -538,7 +538,7 @@ private void generateBitSetDecodeFrom( } else { - sb.append(indent).append(dtoTypeName).append("::decode(codec.") + sb.append(indent).append(dtoTypeName).append("::decodeWith(codec.") .append(formattedPropertyName).append("(), ") .append("dto.").append(formattedPropertyName).append("());\n"); } @@ -571,7 +571,7 @@ private void generateCompositePropertyDecodeFrom( final String formattedPropertyName = formatPropertyName(propertyName); final String dtoClassName = formatDtoClassName(typeToken.applicableTypeName()); - sb.append(indent).append(dtoClassName).append("::decode(codec.") + sb.append(indent).append(dtoClassName).append("::decodeWith(codec.") .append(formattedPropertyName).append("(), ") .append("dto.").append(formattedPropertyName).append("());\n"); } @@ -593,7 +593,7 @@ private void generateGroupsDecodeFrom( final String groupDtoClassName = formatDtoClassName(groupName); sb.append(indent).append("dto.").append(formattedPropertyName).append("(") - .append(groupDtoClassName).append("::decodeMany(codec.") + .append(groupDtoClassName).append("::decodeManyWith(codec.") .append(formattedPropertyName).append("()));\n"); i++; @@ -729,7 +729,7 @@ private void generateMessageEncodeInto( final String indent) { final StringBuilder encodeBuilder = classBuilder.appendPublic().append("\n") - .append(indent).append("static void encode(").append(codecClassName).append("& codec, const ") + .append(indent).append("static void encodeWith(").append(codecClassName).append("& codec, const ") .append(dtoClassName).append("& dto)\n") .append(indent).append("{\n"); @@ -914,7 +914,7 @@ private void generateComplexPropertyEncodeInto( final String formattedPropertyName = formatPropertyName(propertyName); final String typeName = formatDtoClassName(typeToken.applicableTypeName()); - sb.append(indent).append(typeName).append("::encode(codec.") + sb.append(indent).append(typeName).append("::encodeWith(codec.") .append(formattedPropertyName).append("(), dto.") .append(formattedPropertyName).append("());\n"); } @@ -944,7 +944,7 @@ private void generateGroupsEncodeInto( .append("Count(").append(formattedPropertyName).append(".size());\n\n") .append(indent).append("for (const auto& group: ").append(formattedPropertyName).append(")\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append(groupDtoTypeName).append("::encode(").append(groupCodecVarName) + .append(indent).append(INDENT).append(groupDtoTypeName).append("::encodeWith(").append(groupCodecVarName) .append(".next(), group);\n") .append(indent).append("}\n\n"); @@ -1024,7 +1024,7 @@ private void generateDisplay( toStringBuilder.append(", ").append("length);\n"); - toStringBuilder.append(indent).append(INDENT).append("encode(codec, *this);\n") + toStringBuilder.append(indent).append(INDENT).append("encodeWith(codec, *this);\n") .append(indent).append(INDENT).append("std::ostringstream oss;\n") .append(indent).append(INDENT).append("oss << codec;\n") .append(indent).append(INDENT).append("return oss.str();\n") @@ -1591,7 +1591,7 @@ private void generateChoiceSetEncodeInto( { final StringBuilder encodeBuilder = classBuilder.appendPublic() .append("\n") - .append(indent).append("static void encode(\n") + .append(indent).append("static void encodeWith(\n") .append(indent).append(INDENT).append(codecClassName).append("& codec, ") .append("const ").append(dtoClassName).append("& dto)\n") .append(indent).append("{\n"); @@ -1620,7 +1620,7 @@ private void generateChoiceSetDecodeFrom( { final StringBuilder decodeBuilder = classBuilder.appendPublic() .append("\n") - .append(indent).append("static void decode(\n") + .append(indent).append("static void decodeWith(\n") .append(indent).append(INDENT).append("const ").append(codecClassName).append("& codec, ") .append(dtoClassName).append("& dto)\n") .append(indent).append("{\n"); From e33c6a86affbed5a8b976483f667bb4d4e72c93f Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Fri, 3 Nov 2023 11:31:02 +0000 Subject: [PATCH 1154/1594] [C++] Support "to string" without specification of buffer length. As we use the generated codecs to create a string representation of our DTOs, we don't use Agrona buffers in C++, and there is no concept of resizing, it is necessary to size a temporary buffer during the construction of the string data. Previously, we were letting the user supply this value, which wasn't a very friendly API. Now, we use the `computeLength` methods on the codec to determine how big of a temporary buffer we need. Perhaps the methods will also be useful for avoiding a buffer copy when used in conjunction with Aeron. For example, a developer could use `dto.computeEncodedLength()` to initialise a buffer claim rather than copying via the `offer(...)` API. --- .../sbe/generation/cpp/CppDtoGenerator.java | 145 ++++++++++++++++-- sbe-tool/src/test/cpp/DtoTest.cpp | 16 +- 2 files changed, 143 insertions(+), 18 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index 651a3aa676..8ee894cf08 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -100,7 +100,9 @@ public void generate() throws IOException groups, varData, BASE_INDENT + INDENT); generateMessageEncodeInto(classBuilder, className, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); - generateDisplay(classBuilder, codecClassName, "wrapForEncode", null, BASE_INDENT + INDENT); + generateComputeEncodedLength(classBuilder, codecClassName, groups, varData, BASE_INDENT + INDENT); + generateDisplay(classBuilder, className, codecClassName, "dto.computeEncodedLength()", + "wrapForEncode", null, BASE_INDENT + INDENT); try (Writer out = outputManager.createOutput(className)) { @@ -227,6 +229,8 @@ private void generateGroups( fields, groups, varData, indent + INDENT); generateMessageEncodeInto( groupClassBuilder, groupClassName, qualifiedCodecClassName, fields, groups, varData, indent + INDENT); + generateComputeEncodedLength(groupClassBuilder, qualifiedCodecClassName, groups, varData, + indent + INDENT); groupClassBuilder.appendTo( classBuilder.appendPublic().append("\n").append(generateDocumentation(indent, groupToken)) @@ -266,6 +270,103 @@ private void generateGroups( } } + private void generateComputeEncodedLength( + final ClassBuilder classBuilder, + final String qualifiedCodecClassName, + final List groupTokens, + final List varDataTokens, + final String indent) + { + final StringBuilder lengthBuilder = classBuilder.appendPublic() + .append("\n") + .append(indent).append("[[nodiscard]] std::size_t computeEncodedLength() const\n") + .append(indent).append("{\n"); + + final StringBuilder arguments = new StringBuilder(); + + for (int i = 0, size = groupTokens.size(); i < size; i++) + { + final Token groupToken = groupTokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + i++; + i += groupTokens.get(i).componentTokenCount(); + + final List fields = new ArrayList<>(); + i = collectFields(groupTokens, i, fields); + final List subGroups = new ArrayList<>(); + i = collectGroups(groupTokens, i, subGroups); + final List subVarData = new ArrayList<>(); + i = collectVarData(groupTokens, i, subVarData); + + final String groupName = groupToken.name(); + final String fieldName = "m_" + toLowerFirstChar(groupName); + + final boolean isConstLength = subGroups.isEmpty() && subVarData.isEmpty(); + final String argumentName = isConstLength ? + toLowerFirstChar(groupName) + "Count" : + toLowerFirstChar(groupName) + "Lengths"; + + if (isConstLength) + { + lengthBuilder + .append(indent).append(INDENT).append("std::size_t ").append(argumentName) + .append(" = ").append(fieldName).append(".size();\n"); + } + else + { + final String countName = argumentName + "Count"; + + lengthBuilder + .append(indent).append(INDENT).append("std::size_t ").append(countName).append(" = ") + .append(fieldName).append(".size();\n") + .append(indent).append(INDENT).append("std::vector> ") + .append(argumentName).append("(").append(countName).append(");\n") + .append(indent).append(INDENT).append("for (std::size_t i = 0; i < ").append(countName) + .append("; i++)\n") + .append(indent).append(INDENT).append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("auto& group = ").append(fieldName).append("[i];\n") + .append(indent).append(INDENT).append(INDENT) + .append(argumentName).append("[i] = group.computeEncodedLength();\n") + .append(indent).append(INDENT).append("}\n") + .append("\n"); + } + + arguments.append(argumentName).append(", "); + } + + for (int i = 0, size = varDataTokens.size(); i < size; i++) + { + final Token token = varDataTokens.get(i); + if (token.signal() == Signal.BEGIN_VAR_DATA) + { + final String propertyName = token.name(); + final Token varDataToken = Generators.findFirst("varData", varDataTokens, i); + final String fieldName = "m_" + toLowerFirstChar(propertyName); + final String argumentName = toLowerFirstChar(propertyName) + "Length"; + + lengthBuilder.append(indent).append(INDENT).append("std::size_t ").append(argumentName) + .append(" = ").append(fieldName).append(".size() * sizeof(") + .append(cppTypeName(varDataToken.encoding().primitiveType())).append(");\n"); + + arguments.append(argumentName).append(", "); + } + } + + if (arguments.length() >= 2) + { + arguments.setLength(arguments.length() - 2); + } + + lengthBuilder.append(indent).append(INDENT).append("return ").append(qualifiedCodecClassName) + .append("::computeLength(").append(arguments).append(");\n") + .append(indent).append("}\n"); + } + private void generateCompositeDecodeFrom( final ClassBuilder classBuilder, final String dtoClassName, @@ -944,8 +1045,8 @@ private void generateGroupsEncodeInto( .append("Count(").append(formattedPropertyName).append(".size());\n\n") .append(indent).append("for (const auto& group: ").append(formattedPropertyName).append(")\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append(groupDtoTypeName).append("::encodeWith(").append(groupCodecVarName) - .append(".next(), group);\n") + .append(indent).append(INDENT).append(groupDtoTypeName) + .append("::encodeWith(").append(groupCodecVarName).append(".next(), group);\n") .append(indent).append("}\n\n"); i++; @@ -1002,32 +1103,44 @@ private void generateVarDataEncodeInto( private void generateDisplay( final ClassBuilder classBuilder, + final String dtoClassName, final String codecClassName, + final String lengthExpression, final String wrapMethod, final String actingVersion, final String indent) { - final StringBuilder toStringBuilder = classBuilder.appendPublic() + final StringBuilder streamBuilder = classBuilder.appendPublic() .append("\n") - .append(indent).append( - "std::string string(char* tempBuffer, std::uint64_t offset, std::uint64_t length) const\n") + .append(indent).append("friend std::ostream& operator << (std::ostream& stream, const ") + .append(dtoClassName).append("& dto)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append(codecClassName).append(" codec;\n") - .append(indent).append(INDENT).append("codec."); - - toStringBuilder.append(wrapMethod).append("(tempBuffer, offset"); + .append(indent).append(INDENT).append("const std::size_t length = ") + .append(lengthExpression).append(";\n") + .append(indent).append(INDENT).append("std::vector buffer(length);\n") + .append(indent).append(INDENT).append("codec.").append(wrapMethod) + .append("(buffer.data(), 0"); if (null != actingVersion) { - toStringBuilder.append(", ").append(actingVersion); + streamBuilder.append(", ").append(actingVersion); } - toStringBuilder.append(", ").append("length);\n"); + streamBuilder.append(", ").append("length);\n"); + + streamBuilder.append(indent).append(INDENT).append("encodeWith(codec, dto);\n") + .append(indent).append(INDENT).append("stream << codec;\n") + .append(indent).append(INDENT).append("return stream;\n") + .append(indent).append("}\n"); - toStringBuilder.append(indent).append(INDENT).append("encodeWith(codec, *this);\n") - .append(indent).append(INDENT).append("std::ostringstream oss;\n") - .append(indent).append(INDENT).append("oss << codec;\n") - .append(indent).append(INDENT).append("return oss.str();\n") + classBuilder.appendPublic() + .append("\n") + .append(indent).append("[[nodiscard]] std::string string() const\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("std::ostringstream stream;\n") + .append(indent).append(INDENT).append("stream << *this;\n") + .append(indent).append(INDENT).append("return stream.str();\n") .append(indent).append("}\n"); } @@ -1547,7 +1660,7 @@ private void generateComposite(final List tokens) throws IOException generateCompositeDecodeFrom(classBuilder, className, codecClassName, compositeTokens, BASE_INDENT + INDENT); generateCompositeEncodeInto(classBuilder, className, codecClassName, compositeTokens, BASE_INDENT + INDENT); - generateDisplay(classBuilder, codecClassName, "wrap", + generateDisplay(classBuilder, className, codecClassName, codecClassName + "::encodedLength()", "wrap", codecClassName + "::sbeSchemaVersion()", BASE_INDENT + INDENT); classBuilder.appendTo(out); diff --git a/sbe-tool/src/test/cpp/DtoTest.cpp b/sbe-tool/src/test/cpp/DtoTest.cpp index 3c8f675051..2b37c6b910 100644 --- a/sbe-tool/src/test/cpp/DtoTest.cpp +++ b/sbe-tool/src/test/cpp/DtoTest.cpp @@ -174,6 +174,7 @@ TEST_F(DtoTest, shouldRoundTripCar) ExtendedCar encoder1; encoder1.wrapForEncode(input, 0, BUFFER_LEN); const std::uint64_t encodedCarLength = encodeCar(encoder1); + ExtendedCar decoder; decoder.wrapForDecode( input, @@ -182,14 +183,25 @@ TEST_F(DtoTest, shouldRoundTripCar) ExtendedCar::sbeSchemaVersion(), encodedCarLength); ExtendedCarDto dto; - ExtendedCarDto::decode(decoder, dto); + ExtendedCarDto::decodeWith(decoder, dto); + char output[BUFFER_LEN]; std::memset(output, 0, BUFFER_LEN); ExtendedCar encoder2; encoder2.wrapForEncode(output, 0, BUFFER_LEN); - ExtendedCarDto::encode(encoder2, dto); + ExtendedCarDto::encodeWith(encoder2, dto); const std::uint64_t encodedCarLength2 = encoder2.encodedLength(); + decoder.sbeRewind(); + std::ostringstream originalStringStream; + originalStringStream << decoder; + std::string originalString = originalStringStream.str(); + + std::ostringstream dtoStringStream; + dtoStringStream << dto; + std::string dtoString = dtoStringStream.str(); + EXPECT_EQ(encodedCarLength, encodedCarLength2); EXPECT_EQ(0, std::memcmp(input, output, encodedCarLength2)); + EXPECT_EQ(originalString, dtoString); } From f88d345519583d4ea84a496c71ae59bbcdc0324e Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Fri, 3 Nov 2023 15:34:09 +0000 Subject: [PATCH 1155/1594] [C++] Fix issues with length computation. I had incorrectly assumed that the `Flyweight::computeLength` method took _encoded lengths_ of groups etc., but actually it takes a complicated structure of group counts and variable lengths. As it was hard to build this list, I've opted for a simpler approach: do the length calculation within the generated DTO message and its groups. In this commit, I've also added some convenience methods for converting between DTOs and "byte arrays". --- .../sbe/generation/cpp/CppDtoGenerator.java | 251 +++++++++++------- sbe-tool/src/test/cpp/DtoTest.cpp | 34 ++- 2 files changed, 186 insertions(+), 99 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index 8ee894cf08..c13a3211b1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -96,10 +96,12 @@ public void generate() throws IOException collectVarData(messageBody, offset, varData); generateVarData(classBuilder, varData, BASE_INDENT + INDENT); - generateMessageDecodeFrom(classBuilder, className, codecClassName, fields, + generateDecodeWith(classBuilder, className, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); - generateMessageEncodeInto(classBuilder, className, codecClassName, fields, groups, varData, + generateDecodeFrom(classBuilder, className, codecClassName, BASE_INDENT + INDENT); + generateEncodeWith(classBuilder, className, codecClassName, fields, groups, varData, BASE_INDENT + INDENT); + generateEncodeInto(classBuilder, className, codecClassName, BASE_INDENT + INDENT); generateComputeEncodedLength(classBuilder, codecClassName, groups, varData, BASE_INDENT + INDENT); generateDisplay(classBuilder, className, codecClassName, "dto.computeEncodedLength()", "wrapForEncode", null, BASE_INDENT + INDENT); @@ -225,9 +227,9 @@ private void generateGroups( generateDecodeListFrom( groupClassBuilder, groupClassName, qualifiedCodecClassName, indent + INDENT); - generateMessageDecodeFrom(groupClassBuilder, groupClassName, qualifiedCodecClassName, + generateDecodeWith(groupClassBuilder, groupClassName, qualifiedCodecClassName, fields, groups, varData, indent + INDENT); - generateMessageEncodeInto( + generateEncodeWith( groupClassBuilder, groupClassName, qualifiedCodecClassName, fields, groups, varData, indent + INDENT); generateComputeEncodedLength(groupClassBuilder, qualifiedCodecClassName, groups, varData, indent + INDENT); @@ -282,7 +284,11 @@ private void generateComputeEncodedLength( .append(indent).append("[[nodiscard]] std::size_t computeEncodedLength() const\n") .append(indent).append("{\n"); - final StringBuilder arguments = new StringBuilder(); + lengthBuilder + .append(indent).append(INDENT).append("std::size_t encodedLength = 0;\n"); + + lengthBuilder.append(indent).append(INDENT).append("encodedLength += ").append(qualifiedCodecClassName) + .append("::sbeBlockLength();\n\n"); for (int i = 0, size = groupTokens.size(); i < size; i++) { @@ -304,39 +310,17 @@ private void generateComputeEncodedLength( final String groupName = groupToken.name(); final String fieldName = "m_" + toLowerFirstChar(groupName); - - final boolean isConstLength = subGroups.isEmpty() && subVarData.isEmpty(); - final String argumentName = isConstLength ? - toLowerFirstChar(groupName) + "Count" : - toLowerFirstChar(groupName) + "Lengths"; - - if (isConstLength) - { - lengthBuilder - .append(indent).append(INDENT).append("std::size_t ").append(argumentName) - .append(" = ").append(fieldName).append(".size();\n"); - } - else - { - final String countName = argumentName + "Count"; - - lengthBuilder - .append(indent).append(INDENT).append("std::size_t ").append(countName).append(" = ") - .append(fieldName).append(".size();\n") - .append(indent).append(INDENT).append("std::vector> ") - .append(argumentName).append("(").append(countName).append(");\n") - .append(indent).append(INDENT).append("for (std::size_t i = 0; i < ").append(countName) - .append("; i++)\n") - .append(indent).append(INDENT).append("{\n") - .append(indent).append(INDENT).append(INDENT) - .append("auto& group = ").append(fieldName).append("[i];\n") - .append(indent).append(INDENT).append(INDENT) - .append(argumentName).append("[i] = group.computeEncodedLength();\n") - .append(indent).append(INDENT).append("}\n") - .append("\n"); - } - - arguments.append(argumentName).append(", "); + final String groupCodecClassName = qualifiedCodecClassName + "::" + formatClassName(groupName); + + lengthBuilder + .append(indent).append(INDENT).append("encodedLength += ") + .append(groupCodecClassName).append("::sbeHeaderSize();\n\n") + .append(indent).append(INDENT).append("for (auto& group : ") + .append(fieldName).append(")\n") + .append(indent).append(INDENT).append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("encodedLength += group.computeEncodedLength();\n") + .append(indent).append(INDENT).append("}\n\n"); } for (int i = 0, size = varDataTokens.size(); i < size; i++) @@ -347,27 +331,23 @@ private void generateComputeEncodedLength( final String propertyName = token.name(); final Token varDataToken = Generators.findFirst("varData", varDataTokens, i); final String fieldName = "m_" + toLowerFirstChar(propertyName); - final String argumentName = toLowerFirstChar(propertyName) + "Length"; - lengthBuilder.append(indent).append(INDENT).append("std::size_t ").append(argumentName) - .append(" = ").append(fieldName).append(".size() * sizeof(") - .append(cppTypeName(varDataToken.encoding().primitiveType())).append(");\n"); + lengthBuilder.append(indent).append(INDENT).append("encodedLength += ") + .append(qualifiedCodecClassName).append("::") + .append(formatPropertyName(propertyName)).append("HeaderLength();\n"); - arguments.append(argumentName).append(", "); - } - } + lengthBuilder.append(indent).append(INDENT).append("encodedLength += ") + .append(fieldName).append(".size() * sizeof(") + .append(cppTypeName(varDataToken.encoding().primitiveType())).append(");\n\n"); - if (arguments.length() >= 2) - { - arguments.setLength(arguments.length() - 2); + } } - lengthBuilder.append(indent).append(INDENT).append("return ").append(qualifiedCodecClassName) - .append("::computeLength(").append(arguments).append(");\n") + lengthBuilder.append(indent).append(INDENT).append("return encodedLength;\n") .append(indent).append("}\n"); } - private void generateCompositeDecodeFrom( + private void generateCompositeDecodeWith( final ClassBuilder classBuilder, final String dtoClassName, final String codecClassName, @@ -383,7 +363,7 @@ private void generateCompositeDecodeFrom( { final Token token = tokens.get(i); - generateFieldDecodeFrom( + generateFieldDecodeWith( decodeBuilder, token, token, codecClassName, indent + INDENT); i += tokens.get(i).componentTokenCount(); @@ -392,7 +372,7 @@ private void generateCompositeDecodeFrom( decodeBuilder.append(indent).append("}\n"); } - private void generateCompositeEncodeInto( + private void generateCompositeEncodeWith( final ClassBuilder classBuilder, final String dtoClassName, final String codecClassName, @@ -408,7 +388,7 @@ private void generateCompositeEncodeInto( { final Token token = tokens.get(i); - generateFieldEncodeInto(encodeBuilder, codecClassName, token, token, indent + INDENT); + generateFieldEncodeWith(encodeBuilder, codecClassName, token, token, indent + INDENT); i += tokens.get(i).componentTokenCount(); } @@ -445,7 +425,7 @@ private void generateDecodeListFrom( .append(indent).append("}\n"); } - private void generateMessageDecodeFrom( + private void generateDecodeWith( final ClassBuilder classBuilder, final String dtoClassName, final String codecClassName, @@ -459,13 +439,35 @@ private void generateMessageDecodeFrom( .append(dtoClassName).append("& dto)\n") .append(indent).append("{\n"); - generateMessageFieldsDecodeFrom(decodeBuilder, fields, codecClassName, indent + INDENT); - generateGroupsDecodeFrom(decodeBuilder, groups, indent + INDENT); - generateVarDataDecodeFrom(decodeBuilder, varData, indent + INDENT); + generateMessageFieldsDecodeWith(decodeBuilder, fields, codecClassName, indent + INDENT); + generateGroupsDecodeWith(decodeBuilder, groups, indent + INDENT); + generateVarDataDecodeWith(decodeBuilder, varData, indent + INDENT); decodeBuilder.append(indent).append("}\n"); } - private void generateMessageFieldsDecodeFrom( + private static void generateDecodeFrom( + final ClassBuilder classBuilder, + final String dtoClassName, + final String codecClassName, + final String indent) + { + classBuilder.appendPublic() + .append("\n") + .append(indent).append("static ").append(dtoClassName).append(" decodeFrom(") + .append("char* buffer, std::uint64_t offset, ") + .append("std::uint64_t actingBlockLength, std::uint64_t actingVersion, ") + .append("std::uint64_t bufferLength)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(codecClassName).append(" codec;\n") + .append(indent).append(INDENT) + .append("codec.wrapForDecode(buffer, offset, actingBlockLength, actingVersion, bufferLength);\n") + .append(indent).append(INDENT).append(dtoClassName).append(" dto;\n") + .append(indent).append(INDENT).append(dtoClassName).append("::decodeWith(codec, dto);\n") + .append(indent).append(INDENT).append("return dto;\n") + .append(indent).append("}\n"); + } + + private void generateMessageFieldsDecodeWith( final StringBuilder sb, final List tokens, final String codecClassName, @@ -478,12 +480,12 @@ private void generateMessageFieldsDecodeFrom( { final Token encodingToken = tokens.get(i + 1); - generateFieldDecodeFrom(sb, signalToken, encodingToken, codecClassName, indent); + generateFieldDecodeWith(sb, signalToken, encodingToken, codecClassName, indent); } } } - private void generateFieldDecodeFrom( + private void generateFieldDecodeWith( final StringBuilder sb, final Token fieldToken, final Token typeToken, @@ -493,20 +495,20 @@ private void generateFieldDecodeFrom( switch (typeToken.signal()) { case ENCODING: - generatePrimitiveDecodeFrom(sb, fieldToken, typeToken, codecClassName, indent); + generatePrimitiveDecodeWith(sb, fieldToken, typeToken, codecClassName, indent); break; case BEGIN_SET: final String bitSetName = formatDtoClassName(typeToken.applicableTypeName()); - generateBitSetDecodeFrom(sb, fieldToken, bitSetName, indent); + generateBitSetDecodeWith(sb, fieldToken, bitSetName, indent); break; case BEGIN_ENUM: - generateEnumDecodeFrom(sb, fieldToken, indent); + generateEnumDecodeWith(sb, fieldToken, indent); break; case BEGIN_COMPOSITE: - generateCompositePropertyDecodeFrom(sb, fieldToken, typeToken, indent); + generateCompositePropertyDecodeWith(sb, fieldToken, typeToken, indent); break; default: @@ -514,7 +516,7 @@ private void generateFieldDecodeFrom( } } - private void generatePrimitiveDecodeFrom( + private void generatePrimitiveDecodeWith( final StringBuilder sb, final Token fieldToken, final Token typeToken, @@ -551,11 +553,11 @@ private void generatePrimitiveDecodeFrom( } else if (arrayLength > 1) { - generateArrayDecodeFrom(sb, fieldToken, typeToken, codecClassName, indent); + generateArrayDecodeWith(sb, fieldToken, typeToken, codecClassName, indent); } } - private void generateArrayDecodeFrom( + private void generateArrayDecodeWith( final StringBuilder sb, final Token fieldToken, final Token typeToken, @@ -606,7 +608,7 @@ private void generateArrayDecodeFrom( } } - private void generateBitSetDecodeFrom( + private void generateBitSetDecodeWith( final StringBuilder sb, final Token fieldToken, final String dtoTypeName, @@ -645,7 +647,7 @@ private void generateBitSetDecodeFrom( } } - private void generateEnumDecodeFrom( + private void generateEnumDecodeWith( final StringBuilder sb, final Token fieldToken, final String indent) @@ -662,7 +664,7 @@ private void generateEnumDecodeFrom( .append("codec.").append(formattedPropertyName).append("());\n"); } - private void generateCompositePropertyDecodeFrom( + private void generateCompositePropertyDecodeWith( final StringBuilder sb, final Token fieldToken, final Token typeToken, @@ -677,7 +679,7 @@ private void generateCompositePropertyDecodeFrom( .append("dto.").append(formattedPropertyName).append("());\n"); } - private void generateGroupsDecodeFrom( + private void generateGroupsDecodeWith( final StringBuilder sb, final List tokens, final String indent) @@ -711,7 +713,7 @@ private void generateGroupsDecodeFrom( } } - private void generateVarDataDecodeFrom( + private void generateVarDataDecodeWith( final StringBuilder sb, final List tokens, final String indent) @@ -820,7 +822,7 @@ private void generateRecordPropertyAssignment( } } - private void generateMessageEncodeInto( + private void generateEncodeWith( final ClassBuilder classBuilder, final String dtoClassName, final String codecClassName, @@ -834,14 +836,67 @@ private void generateMessageEncodeInto( .append(dtoClassName).append("& dto)\n") .append(indent).append("{\n"); - generateFieldsEncodeInto(encodeBuilder, codecClassName, fields, indent + INDENT); - generateGroupsEncodeInto(encodeBuilder, groups, indent + INDENT); - generateVarDataEncodeInto(encodeBuilder, varData, indent + INDENT); + generateFieldsEncodeWith(encodeBuilder, codecClassName, fields, indent + INDENT); + generateGroupsEncodeWith(encodeBuilder, groups, indent + INDENT); + generateVarDataEncodeWith(encodeBuilder, varData, indent + INDENT); encodeBuilder.append(indent).append("}\n"); } - private void generateFieldsEncodeInto( + private static void generateEncodeInto( + final ClassBuilder classBuilder, + final String dtoClassName, + final String codecClassName, + final String indent) + { + classBuilder.appendPublic() + .append("\n") + .append(indent).append("static std::size_t encodeInto(const ").append(dtoClassName).append("& dto, ") + .append("char *buffer, std::uint64_t offset, std::uint64_t bufferLength)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(codecClassName).append(" codec;\n") + .append(indent).append(INDENT).append("codec.wrapForEncode(buffer, offset, bufferLength);\n") + .append(indent).append(INDENT).append(dtoClassName).append("::encodeWith(codec, dto);\n") + .append(indent).append(INDENT).append("return codec.encodedLength();\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic() + .append("\n") + .append(indent).append("static std::size_t encodeWithHeaderInto(const ") + .append(dtoClassName).append("& dto, ") + .append("char *buffer, std::uint64_t offset, std::uint64_t bufferLength)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(codecClassName).append(" codec;\n") + .append(indent).append(INDENT).append("codec.wrapAndApplyHeader(buffer, offset, bufferLength);\n") + .append(indent).append(INDENT).append(dtoClassName).append("::encodeWith(codec, dto);\n") + .append(indent).append(INDENT).append("return codec.sbePosition() - offset;\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic() + .append("\n") + .append(indent).append("[[nodiscard]] static std::vector bytes(const ") + .append(dtoClassName).append("& dto)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("std::vector bytes(dto.computeEncodedLength());\n") + .append(indent).append(INDENT).append(dtoClassName) + .append("::encodeInto(dto, reinterpret_cast(bytes.data()), 0, bytes.size());\n") + .append(indent).append(INDENT).append("return bytes;\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic() + .append("\n") + .append(indent).append("[[nodiscard]] static std::vector bytesWithHeader(const ") + .append(dtoClassName).append("& dto)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("std::vector bytes(dto.computeEncodedLength() + ") + .append("MessageHeader::encodedLength());\n") + .append(indent).append(INDENT).append(dtoClassName) + .append("::encodeWithHeaderInto(dto, reinterpret_cast(bytes.data()), 0, bytes.size());\n") + .append(indent).append(INDENT).append("return bytes;\n") + .append(indent).append("}\n"); + } + + private void generateFieldsEncodeWith( final StringBuilder sb, final String codecClassName, final List tokens, @@ -853,12 +908,12 @@ private void generateFieldsEncodeInto( if (signalToken.signal() == Signal.BEGIN_FIELD) { final Token encodingToken = tokens.get(i + 1); - generateFieldEncodeInto(sb, codecClassName, signalToken, encodingToken, indent); + generateFieldEncodeWith(sb, codecClassName, signalToken, encodingToken, indent); } } } - private void generateFieldEncodeInto( + private void generateFieldEncodeWith( final StringBuilder sb, final String codecClassName, final Token fieldToken, @@ -868,16 +923,16 @@ private void generateFieldEncodeInto( switch (typeToken.signal()) { case ENCODING: - generatePrimitiveEncodeInto(sb, codecClassName, fieldToken, typeToken, indent); + generatePrimitiveEncodeWith(sb, codecClassName, fieldToken, typeToken, indent); break; case BEGIN_ENUM: - generateEnumEncodeInto(sb, fieldToken, indent); + generateEnumEncodeWith(sb, fieldToken, indent); break; case BEGIN_SET: case BEGIN_COMPOSITE: - generateComplexPropertyEncodeInto(sb, fieldToken, typeToken, indent); + generateComplexPropertyEncodeWith(sb, fieldToken, typeToken, indent); break; default: @@ -885,7 +940,7 @@ private void generateFieldEncodeInto( } } - private void generatePrimitiveEncodeInto( + private void generatePrimitiveEncodeWith( final StringBuilder sb, final String codecClassName, final Token fieldToken, @@ -901,15 +956,15 @@ private void generatePrimitiveEncodeInto( if (arrayLength == 1) { - generatePrimitiveValueEncodeInto(sb, codecClassName, fieldToken, indent); + generatePrimitiveValueEncodeWith(sb, codecClassName, fieldToken, indent); } else if (arrayLength > 1) { - generateArrayEncodeInto(sb, fieldToken, typeToken, indent); + generateArrayEncodeWith(sb, fieldToken, typeToken, indent); } } - private void generateArrayEncodeInto( + private void generateArrayEncodeWith( final StringBuilder sb, final Token fieldToken, final Token typeToken, @@ -964,7 +1019,7 @@ private void generateArrayEncodeInto( } } - private void generatePrimitiveValueEncodeInto( + private void generatePrimitiveValueEncodeWith( final StringBuilder sb, final String codecClassName, final Token fieldToken, @@ -988,7 +1043,7 @@ private void generatePrimitiveValueEncodeInto( .append(value).append(");\n"); } - private void generateEnumEncodeInto( + private void generateEnumEncodeWith( final StringBuilder sb, final Token fieldToken, final String indent) @@ -1005,7 +1060,7 @@ private void generateEnumEncodeInto( .append(formattedPropertyName).append("());\n"); } - private void generateComplexPropertyEncodeInto( + private void generateComplexPropertyEncodeWith( final StringBuilder sb, final Token fieldToken, final Token typeToken, @@ -1020,7 +1075,7 @@ private void generateComplexPropertyEncodeInto( .append(formattedPropertyName).append("());\n"); } - private void generateGroupsEncodeInto( + private void generateGroupsEncodeWith( final StringBuilder sb, final List tokens, final String indent) @@ -1063,7 +1118,7 @@ private void generateGroupsEncodeInto( } } - private void generateVarDataEncodeInto( + private void generateVarDataEncodeWith( final StringBuilder sb, final List tokens, final String indent) @@ -1657,9 +1712,9 @@ private void generateComposite(final List tokens) throws IOException final ClassBuilder classBuilder = new ClassBuilder(className, BASE_INDENT); generateCompositePropertyElements(classBuilder, codecClassName, compositeTokens, BASE_INDENT + INDENT); - generateCompositeDecodeFrom(classBuilder, className, codecClassName, compositeTokens, + generateCompositeDecodeWith(classBuilder, className, codecClassName, compositeTokens, BASE_INDENT + INDENT); - generateCompositeEncodeInto(classBuilder, className, codecClassName, compositeTokens, BASE_INDENT + INDENT); + generateCompositeEncodeWith(classBuilder, className, codecClassName, compositeTokens, BASE_INDENT + INDENT); generateDisplay(classBuilder, className, codecClassName, codecClassName + "::encodedLength()", "wrap", codecClassName + "::sbeSchemaVersion()", BASE_INDENT + INDENT); @@ -1686,8 +1741,8 @@ private void generateChoiceSet(final List tokens) throws IOException final ClassBuilder classBuilder = new ClassBuilder(className, BASE_INDENT); generateChoices(classBuilder, className, setTokens, BASE_INDENT + INDENT); - generateChoiceSetDecodeFrom(classBuilder, className, codecClassName, setTokens, BASE_INDENT + INDENT); - generateChoiceSetEncodeInto(classBuilder, className, codecClassName, setTokens, BASE_INDENT + INDENT); + generateChoiceSetDecodeWith(classBuilder, className, codecClassName, setTokens, BASE_INDENT + INDENT); + generateChoiceSetEncodeWith(classBuilder, className, codecClassName, setTokens, BASE_INDENT + INDENT); classBuilder.appendTo(out); out.append("} // namespace\n"); @@ -1695,7 +1750,7 @@ private void generateChoiceSet(final List tokens) throws IOException } } - private void generateChoiceSetEncodeInto( + private void generateChoiceSetEncodeWith( final ClassBuilder classBuilder, final String dtoClassName, final String codecClassName, @@ -1724,7 +1779,7 @@ private void generateChoiceSetEncodeInto( encodeBuilder.append(indent).append("}\n"); } - private void generateChoiceSetDecodeFrom( + private void generateChoiceSetDecodeWith( final ClassBuilder classBuilder, final String dtoClassName, final String codecClassName, diff --git a/sbe-tool/src/test/cpp/DtoTest.cpp b/sbe-tool/src/test/cpp/DtoTest.cpp index 2b37c6b910..f5d2d0cd58 100644 --- a/sbe-tool/src/test/cpp/DtoTest.cpp +++ b/sbe-tool/src/test/cpp/DtoTest.cpp @@ -167,7 +167,7 @@ class DtoTest : public testing::Test } }; -TEST_F(DtoTest, shouldRoundTripCar) +TEST_F(DtoTest, shouldRoundTripCar1) { char input[BUFFER_LEN]; std::memset(input, 0, BUFFER_LEN); @@ -205,3 +205,35 @@ TEST_F(DtoTest, shouldRoundTripCar) EXPECT_EQ(0, std::memcmp(input, output, encodedCarLength2)); EXPECT_EQ(originalString, dtoString); } + +TEST_F(DtoTest, shouldRoundTripCar2) +{ + char input[BUFFER_LEN]; + std::memset(input, 0, BUFFER_LEN); + ExtendedCar encoder; + encoder.wrapForEncode(input, 0, BUFFER_LEN); + const std::uint64_t encodedCarLength = encodeCar(encoder); + + ExtendedCarDto dto = ExtendedCarDto::decodeFrom( + input, + 0, + ExtendedCar::sbeBlockLength(), + ExtendedCar::sbeSchemaVersion(), + encodedCarLength); + + EXPECT_EQ(encodedCarLength, dto.computeEncodedLength()); + + std::vector output = ExtendedCarDto::bytes(dto); + + std::ostringstream originalStringStream; + originalStringStream << encoder; + std::string originalString = originalStringStream.str(); + + std::ostringstream dtoStringStream; + dtoStringStream << dto; + std::string dtoString = dtoStringStream.str(); + + EXPECT_EQ(originalString, dtoString); + EXPECT_EQ(encodedCarLength, output.size()); + EXPECT_EQ(0, std::memcmp(input, output.data(), encodedCarLength)); +} From f965d2a7e649d8b2b4646e54e8ccd032accc0057 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Thu, 9 Nov 2023 15:07:44 +0000 Subject: [PATCH 1156/1594] [C++] Address feedback from Todd re var data representation. It is more-idiomatic to represent variable-length data using `std::string` even when there is no character encoding specified, the the `std::string` API provides useful utilities regardless. --- .../sbe/generation/cpp/CppDtoGenerator.java | 39 ++----------------- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index c13a3211b1..99aae05c3b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -724,8 +724,6 @@ private void generateVarDataDecodeWith( if (token.signal() == Signal.BEGIN_VAR_DATA) { final String propertyName = token.name(); - final Token varDataToken = Generators.findFirst("varData", tokens, i); - final String characterEncoding = varDataToken.encoding().characterEncoding(); final String formattedPropertyName = formatPropertyName(propertyName); final boolean isOptional = token.version() > 0; @@ -739,19 +737,8 @@ private void generateVarDataDecodeWith( .append(blockIndent).append("const char* ").append(dataVar) .append(" = codec.").append(formattedPropertyName).append("();\n"); - final String dtoValue; - final String nullDtoValue; - - if (characterEncoding == null) - { - dtoValue = "std::vector(" + dataVar + ", " + dataVar + " + " + lengthVar + ")"; - nullDtoValue = "std::vector()"; - } - else - { - dtoValue = "std::string(" + dataVar + ", " + lengthVar + ")"; - nullDtoValue = "\"\""; - } + final String dtoValue = "std::string(" + dataVar + ", " + lengthVar + ")"; + final String nullDtoValue = "\"\""; if (isOptional) { @@ -1129,29 +1116,13 @@ private void generateVarDataEncodeWith( if (token.signal() == Signal.BEGIN_VAR_DATA) { final String propertyName = token.name(); - final Token lengthToken = Generators.findFirst("length", tokens, i); - final String lengthTypeName = cppTypeName(lengthToken.encoding().primitiveType()); - final Token varDataToken = Generators.findFirst("varData", tokens, i); - final String characterEncoding = varDataToken.encoding().characterEncoding(); final String formattedPropertyName = formatPropertyName(propertyName); final String varName = toLowerFirstChar(propertyName) + "Vector"; sb.append(indent).append("auto& ").append(varName).append(" = dto.") .append(formattedPropertyName).append("();\n") .append(indent).append("codec.put").append(toUpperFirstChar(propertyName)) - .append("("); - - if (null == characterEncoding) - { - sb.append("reinterpret_cast(").append(varName).append(".data()), ") - .append("static_cast<").append(lengthTypeName).append(">(").append(varName).append(".size())"); - } - else - { - sb.append(varName); - } - - sb.append(");\n"); + .append("(").append(varName).append(");\n"); } } } @@ -1629,9 +1600,7 @@ private void generateVarData( if (token.signal() == Signal.BEGIN_VAR_DATA) { final String propertyName = token.name(); - final Token varDataToken = Generators.findFirst("varData", tokens, i); - final String characterEncoding = varDataToken.encoding().characterEncoding(); - final String dtoType = characterEncoding == null ? "std::vector" : "std::string"; + final String dtoType = "std::string"; final String fieldName = "m_" + toLowerFirstChar(propertyName); final String formattedPropertyName = formatPropertyName(propertyName); From 21cde2a3d9fc82e09b28fa228c3dfda27bf3201a Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Sat, 11 Nov 2023 17:56:52 +0000 Subject: [PATCH 1157/1594] [C++] Add PBT for C++ DTOs. The main change in this commit is to add property-based testing around the C++ DTOs. We check the same property as the C# tests, i.e., that decoding and re-encoding via a DTO preserves the original bytes. There are some other smaller changes in this commit: 1. We now only generate arbitrary schemas where enums have at least one case, as this is required by the spec. 2. We now log details about how we encoded the `input.dat` file used in property-based tests, which can help diagnose problems in the test. --- .../sbe/generation/cpp/CppDtoGenerator.java | 33 ++- .../properties/CSharpDtosPropertyTest.java | 159 ---------- .../sbe/properties/DtosPropertyTest.java | 273 ++++++++++++++++++ .../arbitraries/SbeArbitraries.java | 267 +++++++++++++---- .../resources/CppDtosPropertyTest/main.cpp | 54 ++++ 5 files changed, 559 insertions(+), 227 deletions(-) delete mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java create mode 100644 sbe-tool/src/propertyTest/resources/CppDtosPropertyTest/main.cpp diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index 99aae05c3b..f2371181d0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -121,7 +121,7 @@ public void generate() throws IOException referencedTypes)); out.append(generateDocumentation(BASE_INDENT, msgToken)); classBuilder.appendTo(out); - out.append("} // namespace\n"); + out.append(CppUtil.closingBraces(ir.namespaces().length)); out.append("#endif\n"); } } @@ -1336,15 +1336,21 @@ private void generateArrayProperty( { final String fieldName = "m_" + toLowerFirstChar(propertyName); final String formattedPropertyName = formatPropertyName(propertyName); + final String validateMethod = "validate" + toUpperFirstChar(propertyName); if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { + final CharSequence typeName = typeWithFieldOptionality( + fieldToken, + "std::string" + ); + classBuilder.appendField() - .append(indent).append("std::string ").append(fieldName).append(";\n"); + .append(indent).append(typeName).append(" ").append(fieldName).append(";\n"); classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("[[nodiscard]] const std::string& ") + .append(indent).append("[[nodiscard]] const ").append(typeName).append("& ") .append(formattedPropertyName).append("() const\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") @@ -1353,22 +1359,31 @@ private void generateArrayProperty( classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("void ").append(formattedPropertyName) - .append("(const std::string& borrowedValue)\n") + .append("(const ").append(typeName).append("& borrowedValue)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append(fieldName).append(" = borrowedValue;\n") .append(indent).append("}\n"); classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("void ").append(formattedPropertyName) - .append("(std::string&& ownedValue)\n") + .append(indent).append("void ").append(formattedPropertyName).append("(") + .append(typeName).append("&& ownedValue)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append(fieldName).append(" = std::move(ownedValue);\n") .append(indent).append("}\n"); + + generateArrayValidateMethod( + classBuilder, + codecClassName, + fieldToken, + indent, + validateMethod, + typeName, + "std::string", + formattedPropertyName); } else { - final String validateMethod = "validate" + toUpperFirstChar(propertyName); final String elementTypeName = cppTypeName(typeToken.encoding().primitiveType()); final String vectorTypeName = "std::vector<" + elementTypeName + ">"; final CharSequence typeName = typeWithFieldOptionality( @@ -1688,7 +1703,7 @@ private void generateComposite(final List tokens) throws IOException codecClassName + "::sbeSchemaVersion()", BASE_INDENT + INDENT); classBuilder.appendTo(out); - out.append("} // namespace\n"); + out.append(CppUtil.closingBraces(ir.namespaces().length)); out.append("#endif\n"); } } @@ -1714,7 +1729,7 @@ private void generateChoiceSet(final List tokens) throws IOException generateChoiceSetEncodeWith(classBuilder, className, codecClassName, setTokens, BASE_INDENT + INDENT); classBuilder.appendTo(out); - out.append("} // namespace\n"); + out.append(CppUtil.closingBraces(ir.namespaces().length)); out.append("#endif\n"); } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java deleted file mode 100644 index 701ca2fcf4..0000000000 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/CSharpDtosPropertyTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2013-2023 Real Logic Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package uk.co.real_logic.sbe.properties; - -import net.jqwik.api.Arbitrary; -import net.jqwik.api.ForAll; -import net.jqwik.api.Property; -import net.jqwik.api.Provide; -import uk.co.real_logic.sbe.generation.csharp.CSharpDtoGenerator; -import uk.co.real_logic.sbe.generation.csharp.CSharpGenerator; -import uk.co.real_logic.sbe.generation.csharp.CSharpNamespaceOutputManager; -import uk.co.real_logic.sbe.properties.arbitraries.SbeArbitraries; -import org.agrona.IoUtil; -import org.agrona.io.DirectBufferInputStream; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Arrays; - -public class CSharpDtosPropertyTest -{ - private static final String DOTNET_EXECUTABLE = System.getProperty("sbe.tests.dotnet.executable", "dotnet"); - - @Property - void dtoEncodeShouldBeTheInverseOfDtoDecode( - @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage - ) throws IOException, InterruptedException - { - final Path tempDir = Files.createTempDirectory("sbe-csharp-dto-test"); - try - { - final CSharpNamespaceOutputManager outputManager = new CSharpNamespaceOutputManager( - tempDir.toString(), - "SbePropertyTest" - ); - - try - { - new CSharpGenerator(encodedMessage.ir(), outputManager) - .generate(); - new CSharpDtoGenerator(encodedMessage.ir(), outputManager) - .generate(); - } - catch (final Exception generationException) - { - throw new AssertionError( - "Code generation failed.\n\nSCHEMA:\n" + encodedMessage.schema(), - generationException); - } - - copyResourceToFile("/CSharpDtosPropertyTest/SbePropertyTest.csproj", tempDir); - copyResourceToFile("/CSharpDtosPropertyTest/Program.cs", tempDir); - try ( - DirectBufferInputStream inputStream = new DirectBufferInputStream( - encodedMessage.buffer(), - 0, - encodedMessage.length() - ); - OutputStream outputStream = Files.newOutputStream(tempDir.resolve("input.dat"))) - { - final byte[] buffer = new byte[2048]; - int read; - while ((read = inputStream.read(buffer, 0, buffer.length)) >= 0) - { - outputStream.write(buffer, 0, read); - } - } - - final Path stdout = tempDir.resolve("stdout.txt"); - final Path stderr = tempDir.resolve("stderr.txt"); - final ProcessBuilder processBuilder = new ProcessBuilder(DOTNET_EXECUTABLE, "run", "--", "input.dat") - .directory(tempDir.toFile()) - .redirectOutput(stdout.toFile()) - .redirectError(stderr.toFile()); - - final Process process = processBuilder.start(); - if (0 != process.waitFor()) - { - throw new AssertionError( - "Process failed with exit code: " + process.exitValue() + "\n\n" + - "STDOUT:\n" + new String(Files.readAllBytes(stdout)) + "\n\n" + - "STDERR:\n" + new String(Files.readAllBytes(stderr)) + "\n\n" + - "SCHEMA:\n" + encodedMessage.schema()); - } - - final byte[] errorBytes = Files.readAllBytes(stderr); - if (errorBytes.length != 0) - { - throw new AssertionError( - "Process wrote to stderr.\n\n" + - "STDOUT:\n" + new String(Files.readAllBytes(stdout)) + "\n\n" + - "STDERR:\n" + new String(errorBytes) + "\n\n" + - "SCHEMA:\n" + encodedMessage.schema() + "\n\n" - ); - } - - final byte[] inputBytes = new byte[encodedMessage.length()]; - encodedMessage.buffer().getBytes(0, inputBytes); - final byte[] outputBytes = Files.readAllBytes(tempDir.resolve("output.dat")); - if (!Arrays.equals(inputBytes, outputBytes)) - { - throw new AssertionError( - "Input and output files differ\n\n" + - "SCHEMA:\n" + encodedMessage.schema()); - } - } - finally - { - IoUtil.delete(tempDir.toFile(), true); - } - } - - @Provide - Arbitrary encodedMessage() - { - final SbeArbitraries.CharGenerationMode mode = - SbeArbitraries.CharGenerationMode.JSON_PRINTER_COMPATIBLE; - return SbeArbitraries.encodedMessage(mode); - } - - private static void copyResourceToFile( - final String resourcePath, - final Path outputDir) - { - try (InputStream inputStream = CSharpDtosPropertyTest.class.getResourceAsStream(resourcePath)) - { - if (inputStream == null) - { - throw new IOException("Resource not found: " + resourcePath); - } - - final int resourceNameIndex = resourcePath.lastIndexOf('/') + 1; - final String resourceName = resourcePath.substring(resourceNameIndex); - final Path outputFilePath = outputDir.resolve(resourceName); - Files.copy(inputStream, outputFilePath); - } - catch (final IOException e) - { - throw new RuntimeException(e); - } - } -} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java new file mode 100644 index 0000000000..d68a1c327c --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java @@ -0,0 +1,273 @@ +/* + * Copyright 2013-2023 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties; + +import net.jqwik.api.*; +import uk.co.real_logic.sbe.generation.cpp.CppDtoGenerator; +import uk.co.real_logic.sbe.generation.cpp.CppGenerator; +import uk.co.real_logic.sbe.generation.cpp.NamespaceOutputManager; +import uk.co.real_logic.sbe.generation.csharp.CSharpDtoGenerator; +import uk.co.real_logic.sbe.generation.csharp.CSharpGenerator; +import uk.co.real_logic.sbe.generation.csharp.CSharpNamespaceOutputManager; +import uk.co.real_logic.sbe.properties.arbitraries.SbeArbitraries; +import org.agrona.IoUtil; +import org.agrona.io.DirectBufferInputStream; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; + +@SuppressWarnings("ReadWriteStringCanBeUsed") +public class DtosPropertyTest +{ + private static final String DOTNET_EXECUTABLE = System.getProperty("sbe.tests.dotnet.executable", "dotnet"); + private static final String CPP_EXECUTABLE = System.getProperty("sbe.tests.cpp.executable", "g++"); + private static final boolean KEEP_DIR_ON_FAILURE = Boolean.parseBoolean( + System.getProperty("sbe.tests.keep.dir.on.failure", "true")); + + @Property + void csharpDtoEncodeShouldBeTheInverseOfDtoDecode( + @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage + ) throws IOException, InterruptedException + { + final Path tempDir = Files.createTempDirectory("sbe-csharp-dto-test"); + boolean success = false; + + try + { + final CSharpNamespaceOutputManager outputManager = new CSharpNamespaceOutputManager( + tempDir.toString(), + "SbePropertyTest" + ); + + try + { + new CSharpGenerator(encodedMessage.ir(), outputManager) + .generate(); + new CSharpDtoGenerator(encodedMessage.ir(), outputManager) + .generate(); + } + catch (final Exception generationException) + { + throw new AssertionError( + "Code generation failed.\n\n" + + "DIR:" + tempDir + "\n\n" + + "SCHEMA:\n" + encodedMessage.schema(), + generationException); + } + + copyResourceToFile("/CSharpDtosPropertyTest/SbePropertyTest.csproj", tempDir); + copyResourceToFile("/CSharpDtosPropertyTest/Program.cs", tempDir); + + writeInputFile(encodedMessage, tempDir); + + execute(encodedMessage.schema(), tempDir, "test", + DOTNET_EXECUTABLE, "run", "--", "input.dat"); + + final byte[] inputBytes = new byte[encodedMessage.length()]; + encodedMessage.buffer().getBytes(0, inputBytes); + final byte[] outputBytes = Files.readAllBytes(tempDir.resolve("output.dat")); + if (!Arrays.equals(inputBytes, outputBytes)) + { + throw new AssertionError( + "Input and output files differ\n\n" + + "DIR:" + tempDir + "\n\n" + + "SCHEMA:\n" + encodedMessage.schema()); + } + success = true; + } + finally + { + if (!KEEP_DIR_ON_FAILURE || success) + { + IoUtil.delete(tempDir.toFile(), true); + } + else + { + Files.write( + tempDir.resolve("schema.xml"), + encodedMessage.schema().getBytes(StandardCharsets.UTF_8)); + + Files.write( + tempDir.resolve("encoding.log"), + encodedMessage.encodingLog().getBytes(StandardCharsets.UTF_8)); + } + } + } + + @Property(shrinking = ShrinkingMode.OFF) + void cppDtoEncodeShouldBeTheInverseOfDtoDecode( + @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage + ) throws IOException, InterruptedException + { + final Path tempDir = Files.createTempDirectory("sbe-cpp-dto-test"); + boolean success = false; + + try + { + final NamespaceOutputManager outputManager = new NamespaceOutputManager( + tempDir.toString(), + "sbe_property_test" + ); + + try + { + new CppGenerator(encodedMessage.ir(), true, outputManager) + .generate(); + new CppDtoGenerator(encodedMessage.ir(), outputManager) + .generate(); + } + catch (final Exception generationException) + { + throw new AssertionError( + "Code generation failed.\n\nSCHEMA:\n" + encodedMessage.schema(), + generationException); + } + + copyResourceToFile("/CppDtosPropertyTest/main.cpp", tempDir); + + writeInputFile(encodedMessage, tempDir); + + execute(encodedMessage.schema(), tempDir, "compile", + CPP_EXECUTABLE, "--std", "c++17", "-o", "round-trip-test", "main.cpp"); + + execute(encodedMessage.schema(), tempDir, "test", + tempDir.resolve("round-trip-test").toString(), "input.dat"); + + final byte[] inputBytes = new byte[encodedMessage.length()]; + encodedMessage.buffer().getBytes(0, inputBytes); + final byte[] outputBytes = Files.readAllBytes(tempDir.resolve("output.dat")); + if (!Arrays.equals(inputBytes, outputBytes)) + { + throw new AssertionError( + "Input and output files differ\n\n" + + "SCHEMA:\n" + encodedMessage.schema()); + } + success = true; + } + finally + { + if (!KEEP_DIR_ON_FAILURE || success) + { + IoUtil.delete(tempDir.toFile(), true); + } + else + { + Files.write( + tempDir.resolve("schema.xml"), + encodedMessage.schema().getBytes(StandardCharsets.UTF_8)); + + Files.write( + tempDir.resolve("encoding.log"), + encodedMessage.encodingLog().getBytes(StandardCharsets.UTF_8)); + } + } + } + + private static void writeInputFile( + final SbeArbitraries.EncodedMessage encodedMessage, + final Path tempDir) throws IOException + { + try ( + DirectBufferInputStream inputStream = new DirectBufferInputStream( + encodedMessage.buffer(), + 0, + encodedMessage.length() + ); + OutputStream outputStream = Files.newOutputStream(tempDir.resolve("input.dat"))) + { + final byte[] buffer = new byte[2048]; + int read; + while ((read = inputStream.read(buffer, 0, buffer.length)) >= 0) + { + outputStream.write(buffer, 0, read); + } + } + } + + private static void execute( + final String schema, + final Path tempDir, + final String name, + final String... args) throws InterruptedException, IOException + { + final Path stdout = tempDir.resolve(name + "_stdout.txt"); + final Path stderr = tempDir.resolve(name + "_stderr.txt"); + final ProcessBuilder compileProcessBuilder = new ProcessBuilder(args) + .directory(tempDir.toFile()) + .redirectOutput(stdout.toFile()) + .redirectError(stderr.toFile()); + + final Process process = compileProcessBuilder.start(); + + if (0 != process.waitFor()) + { + throw new AssertionError( + "Process failed with exit code: " + process.exitValue() + "\n\n" + + "DIR:" + tempDir + "\n\n" + + "STDOUT:\n" + new String(Files.readAllBytes(stdout)) + "\n\n" + + "STDERR:\n" + new String(Files.readAllBytes(stderr)) + "\n\n" + + "SCHEMA:\n" + schema); + } + + final byte[] errorBytes = Files.readAllBytes(stderr); + if (errorBytes.length != 0) + { + throw new AssertionError( + "Process wrote to stderr.\n\n" + + "DIR:" + tempDir + "\n\n" + + "STDOUT:\n" + new String(Files.readAllBytes(stdout)) + "\n\n" + + "STDERR:\n" + new String(errorBytes) + "\n\n" + + "SCHEMA:\n" + schema + "\n\n" + ); + } + } + + @Provide + Arbitrary encodedMessage() + { + final SbeArbitraries.CharGenerationMode mode = + SbeArbitraries.CharGenerationMode.JSON_PRINTER_COMPATIBLE; + return SbeArbitraries.encodedMessage(mode); + } + + private static void copyResourceToFile( + final String resourcePath, + final Path outputDir) + { + try (InputStream inputStream = DtosPropertyTest.class.getResourceAsStream(resourcePath)) + { + if (inputStream == null) + { + throw new IOException("Resource not found: " + resourcePath); + } + + final int resourceNameIndex = resourcePath.lastIndexOf('/') + 1; + final String resourceName = resourcePath.substring(resourceNameIndex); + final Path outputFilePath = outputDir.resolve(resourceName); + Files.copy(inputStream, outputFilePath); + } + catch (final IOException e) + { + throw new RuntimeException(e); + } + } +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index 25207cdf96..bfc1f9bd88 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -21,7 +21,6 @@ import net.jqwik.api.Combinators; import net.jqwik.api.arbitraries.CharacterArbitrary; import net.jqwik.api.arbitraries.ListArbitrary; -import net.jqwik.api.arbitraries.ShortArbitrary; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.PrimitiveValue; import uk.co.real_logic.sbe.ir.Encoding; @@ -38,9 +37,7 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; import static uk.co.real_logic.sbe.ir.Signal.*; @@ -130,6 +127,7 @@ private static Arbitrary enumTypeSchema() Arbitraries.chars().alpha() .map(Character::toUpperCase) .list() + .ofMinSize(1) .ofMaxSize(10) .uniqueElements() .map(values -> new EnumTypeSchema( @@ -139,6 +137,7 @@ private static Arbitrary enumTypeSchema() Arbitraries.integers() .between(1, 254) .list() + .ofMinSize(1) .ofMaxSize(254) .uniqueElements() .map(values -> new EnumTypeSchema( @@ -286,18 +285,51 @@ public static Arbitrary messageSchema() ).as(MessageSchema::new); } - public interface Encoder + private interface Encoder { - void encode(MutableDirectBuffer buffer, int offset, MutableInteger limit); + void encode( + EncodingLogger logger, + MutableDirectBuffer buffer, + int offset, + MutableInteger limit); + } + + private static final class EncodingLogger + { + private final StringBuilder builder = new StringBuilder(); + private final Deque scope = new ArrayDeque<>(); + + public void beginScope(final String name) + { + scope.addLast(name); + } + + public StringBuilder appendLine() + { + builder.append("\n"); + scope.forEach(s -> builder.append(".").append(s)); + builder.append(": "); + return builder; + } + + public void endScope() + { + scope.removeLast(); + } + + public String toString() + { + return builder.toString(); + } } private static Encoder combineEncoders(final Collection encoders) { - return (buffer, offset, limit) -> + return (builder, buffer, offset, limit) -> { for (final Encoder encoder : encoders) { - encoder.encode(buffer, offset, limit); + encoder.encode(builder, buffer, offset, limit); } }; } @@ -339,35 +371,57 @@ private static Arbitrary encodedTypeEncoder( case CHAR: assert minValue.longValue() <= maxValue.longValue(); return chars(charGenerationMode).map(c -> - (buffer, offset, limit) -> buffer.putChar(offset, c, encoding.byteOrder())); + (builder, buffer, offset, limit) -> + { + builder.appendLine().append(c).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_BYTE).append("]"); + buffer.putChar(offset, c, encoding.byteOrder()); + }); case UINT8: case INT8: assert (short)minValue.longValue() <= (short)maxValue.longValue(); return Arbitraries.shorts() .between((short)minValue.longValue(), (short)maxValue.longValue()) - .map(b -> (buffer, offset, limit) -> buffer.putByte(offset, (byte)(short)b)); + .map(b -> (builder, buffer, offset, limit) -> + { + builder.appendLine().append((byte)(short)b).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_BYTE).append("]"); + buffer.putByte(offset, (byte)(short)b); + }); case UINT16: case INT16: assert (int)minValue.longValue() <= (int)maxValue.longValue(); return Arbitraries.integers() .between((int)minValue.longValue(), (int)maxValue.longValue()) - .map(s -> (buffer, offset, limit) -> buffer.putShort(offset, (short)(int)s, encoding.byteOrder())); + .map(s -> (builder, buffer, offset, limit) -> + { + builder.appendLine().append((short)(int)s).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_SHORT).append("]"); + buffer.putShort(offset, (short)(int)s, encoding.byteOrder()); + }); case UINT32: case INT32: assert minValue.longValue() <= maxValue.longValue(); return Arbitraries.longs() .between(minValue.longValue(), maxValue.longValue()) - .map(i -> (buffer, offset, limit) -> buffer.putInt(offset, (int)(long)i, encoding.byteOrder())); + .map(i -> (builder, buffer, offset, limit) -> + { + builder.appendLine().append((int)(long)i).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_INT).append("]"); + buffer.putInt(offset, (int)(long)i, encoding.byteOrder()); + }); case UINT64: return Arbitraries.longs() - .map(l -> (buffer, offset, limit) -> + .map(l -> (builder, buffer, offset, limit) -> { final long nullValue = encoding.applicableNullValue().longValue(); final long nonNullValue = l == nullValue ? minValue.longValue() : l; + builder.appendLine().append(nonNullValue).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_LONG).append("]"); buffer.putLong(offset, nonNullValue, encoding.byteOrder()); }); @@ -375,15 +429,30 @@ private static Arbitrary encodedTypeEncoder( assert minValue.longValue() <= maxValue.longValue(); return Arbitraries.longs() .between(minValue.longValue(), maxValue.longValue()) - .map(l -> (buffer, offset, limit) -> buffer.putLong(offset, l, encoding.byteOrder())); + .map(l -> (builder, buffer, offset, limit) -> + { + builder.appendLine().append(l).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_LONG).append("]"); + buffer.putLong(offset, l, encoding.byteOrder()); + }); case FLOAT: return Arbitraries.floats() - .map(f -> (buffer, offset, limit) -> buffer.putFloat(offset, f, encoding.byteOrder())); + .map(f -> (builder, buffer, offset, limit) -> + { + builder.appendLine().append(f).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_FLOAT).append("]"); + buffer.putFloat(offset, f, encoding.byteOrder()); + }); case DOUBLE: return Arbitraries.doubles() - .map(d -> (buffer, offset, limit) -> buffer.putDouble(offset, d, encoding.byteOrder())); + .map(d -> (builder, buffer, offset, limit) -> + { + builder.appendLine().append(d).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_DOUBLE).append("]"); + buffer.putDouble(offset, d, encoding.byteOrder()); + }); default: throw new IllegalArgumentException("Unsupported type: " + encoding.primitiveType()); @@ -400,18 +469,20 @@ private static Arbitrary encodedTypeEncoder( if (typeToken.arrayLength() == 1) { - return arbEncoder.map(encoder -> (buffer, bufferOffset, limit) -> - encoder.encode(buffer, bufferOffset + offset, limit)); + return arbEncoder.map(encoder -> (builder, buffer, bufferOffset, limit) -> + encoder.encode(builder, buffer, bufferOffset + offset, limit)); } else { return arbEncoder.list().ofSize(typeToken.arrayLength()) - .map(encoders -> (buffer, bufferOffset, limit) -> + .map(encoders -> (builder, buffer, bufferOffset, limit) -> { for (int i = 0; i < typeToken.arrayLength(); i++) { + builder.beginScope("[" + i + "]"); final int elementOffset = bufferOffset + offset + i * encoding.primitiveType().size(); - encoders.get(i).encode(buffer, elementOffset, limit); + encoders.get(i).encode(builder, buffer, elementOffset, limit); + builder.endScope(); } }); } @@ -419,7 +490,7 @@ private static Arbitrary encodedTypeEncoder( private static Encoder emptyEncoder() { - return (buffer, offset, limit) -> + return (builder, buffer, offset, limit) -> { }; } @@ -432,19 +503,43 @@ private static Encoder integerValueEncoder(final Encoding encoding, final long v case CHAR: case UINT8: case INT8: - return (buffer, offset, limit) -> buffer.putByte(offset, (byte)value); + return (builder, buffer, offset, limit) -> + { + builder.appendLine().append((byte)value).append("[").append(value).append("]") + .append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_BYTE).append("]"); + buffer.putByte(offset, (byte)value); + }; case UINT16: case INT16: - return (buffer, offset, limit) -> buffer.putShort(offset, (short)value, encoding.byteOrder()); + return (builder, buffer, offset, limit) -> + { + builder.appendLine().append((short)value).append("[").append(value).append("]") + .append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_SHORT).append("]"); + buffer.putShort(offset, (short)value, encoding.byteOrder()); + }; case UINT32: case INT32: - return (buffer, offset, limit) -> buffer.putInt(offset, (int)value, encoding.byteOrder()); + return (builder, buffer, offset, limit) -> + { + builder.appendLine().append((int)value).append("[").append(value).append("]") + .append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_INT).append("]"); + buffer.putInt(offset, (int)value, encoding.byteOrder()); + }; case UINT64: case INT64: - return (buffer, offset, limit) -> buffer.putLong(offset, value, encoding.byteOrder()); + return (builder, buffer, offset, limit) -> + { + builder.appendLine().append(value).append("[").append(value).append("]") + .append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_LONG).append("]"); + buffer.putLong(offset, value, encoding.byteOrder()); + }; default: throw new IllegalArgumentException("Unsupported type: " + type); @@ -484,7 +579,8 @@ private static Arbitrary enumEncoder( } return Arbitraries.of(encoders).map(encoder -> - (buffer, bufferOffset, limit) -> encoder.encode(buffer, bufferOffset + offset, limit)); + (builder, buffer, bufferOffset, limit) -> + encoder.encode(builder, buffer, bufferOffset + offset, limit)); } private static Encoder choiceEncoder(final Encoding encoding) @@ -495,42 +591,54 @@ private static Encoder choiceEncoder(final Encoding encoding) { case UINT8: case INT8: - return (buffer, offset, limit) -> + return (builder, buffer, offset, limit) -> { buffer.checkLimit(offset + BitUtil.SIZE_OF_BYTE); final byte oldValue = buffer.getByte(offset); final byte newValue = (byte)(oldValue | (1 << choiceBitIdx)); buffer.putByte(offset, newValue); + builder.appendLine().append("oldValue: ").append(oldValue); + builder.appendLine().append(newValue).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_BYTE).append("]"); }; case UINT16: case INT16: - return (buffer, offset, limit) -> + return (builder, buffer, offset, limit) -> { buffer.checkLimit(offset + BitUtil.SIZE_OF_SHORT); final short oldValue = buffer.getShort(offset, encoding.byteOrder()); final short newValue = (short)(oldValue | (1 << choiceBitIdx)); buffer.putShort(offset, newValue, encoding.byteOrder()); + builder.appendLine().append("oldValue: ").append(oldValue); + builder.appendLine().append(newValue).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_SHORT).append("]"); }; case UINT32: case INT32: - return (buffer, offset, limit) -> + return (builder, buffer, offset, limit) -> { buffer.checkLimit(offset + BitUtil.SIZE_OF_INT); final int oldValue = buffer.getInt(offset, encoding.byteOrder()); final int newValue = oldValue | (1 << choiceBitIdx); buffer.putInt(offset, newValue, encoding.byteOrder()); + builder.appendLine().append("oldValue: ").append(oldValue); + builder.appendLine().append(newValue).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_INT).append("]"); }; case UINT64: case INT64: - return (buffer, offset, limit) -> + return (builder, buffer, offset, limit) -> { buffer.checkLimit(offset + BitUtil.SIZE_OF_LONG); final long oldValue = buffer.getLong(offset, encoding.byteOrder()); final long newValue = oldValue | (1L << choiceBitIdx); buffer.putLong(offset, newValue, encoding.byteOrder()); + builder.appendLine().append("oldValue: ").append(oldValue); + builder.appendLine().append(newValue).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_LONG).append("]"); }; default: @@ -568,7 +676,8 @@ private static Arbitrary bitSetEncoder( return Arbitraries.subsetOf(encoders) .map(SbeArbitraries::combineEncoders) - .map(encoder -> (buffer, bufferOffset, limit) -> encoder.encode(buffer, bufferOffset + offset, limit)); + .map(encoder -> (builder, buffer, bufferOffset, limit) -> + encoder.encode(builder, buffer, bufferOffset + offset, limit)); } private static Arbitrary fieldsEncoder( @@ -602,6 +711,7 @@ else if (expectFields) if (!memberToken.isConstantEncoding()) { + Arbitrary fieldEncoder = null; switch (typeToken.signal()) { case BEGIN_COMPOSITE: @@ -610,30 +720,40 @@ else if (expectFields) final int lastMemberIdx = nextFieldIdx - endCompositeTokenCount - endFieldTokenCount - 1; final Arbitrary encoder = fieldsEncoder( tokens, cursor, lastMemberIdx, false, charGenerationMode); - final Arbitrary positionedEncoder = encoder.map(e -> - (buffer, bufferOffset, limit) -> e.encode(buffer, bufferOffset + offset, limit)); - encoders.add(positionedEncoder); + fieldEncoder = encoder.map(e -> + (builder, buffer, bufferOffset, limit) -> + e.encode(builder, buffer, bufferOffset + offset, limit)); break; case BEGIN_ENUM: final int endEnumTokenCount = 1; final int lastValidValueIdx = nextFieldIdx - endFieldTokenCount - endEnumTokenCount - 1; - encoders.add(enumEncoder(offset, tokens, typeToken, cursor, lastValidValueIdx)); + fieldEncoder = enumEncoder(offset, tokens, typeToken, cursor, lastValidValueIdx); break; case BEGIN_SET: final int endSetTokenCount = 1; final int lastChoiceIdx = nextFieldIdx - endFieldTokenCount - endSetTokenCount - 1; - encoders.add(bitSetEncoder(offset, tokens, cursor, lastChoiceIdx)); + fieldEncoder = bitSetEncoder(offset, tokens, cursor, lastChoiceIdx); break; case ENCODING: - encoders.add(encodedTypeEncoder(offset, typeToken, charGenerationMode)); + fieldEncoder = encodedTypeEncoder(offset, typeToken, charGenerationMode); break; default: break; } + + if (fieldEncoder != null) + { + encoders.add(fieldEncoder.map(encoder -> (builder, buffer, off, limit) -> + { + builder.beginScope(memberToken.name()); + encoder.encode(builder, buffer, off, limit); + builder.endScope(); + })); + } } cursor.set(nextFieldIdx); @@ -677,29 +797,39 @@ private static Arbitrary groupsEncoder( groupsEncoder(tokens, cursor, nextFieldIdx - 1, charGenerationMode), varDataEncoder(tokens, cursor, nextFieldIdx - 1, charGenerationMode) ).as((fieldsEncoder, groupsEncoder, varDataEncoder) -> - (buffer, ignored, limit) -> + (builder, buffer, ignored, limit) -> { final int offset = limit.get(); - fieldsEncoder.encode(buffer, offset, null); + fieldsEncoder.encode(builder, buffer, offset, null); limit.set(offset + blockLength); - groupsEncoder.encode(buffer, NULL_VALUE, limit); - varDataEncoder.encode(buffer, NULL_VALUE, limit); + builder.appendLine().append("limit: ").append(offset).append(" -> ").append(limit.get()); + groupsEncoder.encode(builder, buffer, NULL_VALUE, limit); + varDataEncoder.encode(builder, buffer, NULL_VALUE, limit); }); final Arbitrary repeatingGroupEncoder = groupElement.list() .ofMaxSize(10) - .map(elements -> (buffer, ignored, limit) -> + .map(elements -> (builder, buffer, ignored, limit) -> { final int offset = limit.get(); limit.set(offset + headerLength); - blockLengthEncoder.encode(buffer, offset, null); + builder.beginScope(token.name()); + builder.appendLine().append("limit: ").append(offset).append(" -> ").append(limit.get()); + builder.beginScope("blockLength"); + blockLengthEncoder.encode(builder, buffer, offset, null); + builder.endScope(); + builder.beginScope("numInGroup"); integerValueEncoder(numInGroupToken.encoding(), elements.size()) - .encode(buffer, offset + blockLengthToken.encodedLength(), null); - - for (final Encoder element : elements) + .encode(builder, buffer, offset + blockLengthToken.encodedLength(), null); + builder.endScope(); + for (int i = 0; i < elements.size(); i++) { - element.encode(buffer, NULL_VALUE, limit); + final Encoder element = elements.get(i); + builder.beginScope("[" + i + "]"); + element.encode(builder, buffer, NULL_VALUE, limit); + builder.endScope(); } + builder.endScope(); }); encoders.add(repeatingGroupEncoder); @@ -738,20 +868,28 @@ private static Arbitrary varDataEncoder( final Arbitrary arbitraryByte = null == characterEncoding ? Arbitraries.bytes() : chars(charGenerationMode).map(c -> (byte)c.charValue()); - encoders.add(arbitraryByte.list().map(bytes -> - (buffer, ignored, limit) -> + encoders.add(arbitraryByte.list() + .ofMaxSize((int)Math.min(lengthToken.encoding().applicableMaxValue().longValue(), 260L)) + .map(bytes -> (builder, buffer, ignored, limit) -> { final int offset = limit.get(); final int elementLength = varDataToken.encoding().primitiveType().size(); limit.set(offset + lengthToken.encodedLength() + bytes.size() * elementLength); + builder.beginScope(token.name()); + builder.appendLine().append("limit: ").append(offset).append(" -> ").append(limit.get()); + builder.beginScope("length"); integerValueEncoder(lengthToken.encoding(), bytes.size()) - .encode(buffer, offset, null); + .encode(builder, buffer, offset, null); + builder.endScope(); for (int i = 0; i < bytes.size(); i++) { final int dataOffset = offset + lengthToken.encodedLength() + i * elementLength; + builder.beginScope("[" + i + "]"); integerValueEncoder(varDataToken.encoding(), bytes.get(i)) - .encode(buffer, dataOffset, null); + .encode(builder, buffer, dataOffset, null); + builder.endScope(); } + builder.endScope(); })); cursor.set(nextFieldIdx); @@ -760,7 +898,7 @@ private static Arbitrary varDataEncoder( return combineArbitraryEncoders(encoders); } - public static Arbitrary messageValueEncoder( + private static Arbitrary messageValueEncoder( final Ir ir, final short messageId, final CharGenerationMode charGenerationMode) @@ -781,7 +919,7 @@ public static Arbitrary messageValueEncoder( final Arbitrary varDataEncoder = varDataEncoder( tokens, cursor, tokens.size() - 1, charGenerationMode); return Combinators.combine(fieldsEncoder, groupsEncoder, varDataEncoder) - .as((fields, groups, varData) -> (buffer, offset, limit) -> + .as((fields, groups, varData) -> (builder, buffer, offset, limit) -> { final int blockLength = token.encodedLength(); buffer.putShort(0, (short)blockLength, ir.byteOrder()); @@ -789,10 +927,12 @@ public static Arbitrary messageValueEncoder( buffer.putShort(4, (short)ir.id(), ir.byteOrder()); buffer.putShort(6, (short)ir.version(), ir.byteOrder()); final int headerLength = 8; - fields.encode(buffer, offset + headerLength, null); + fields.encode(builder, buffer, offset + headerLength, null); + final int oldLimit = limit.get(); limit.set(offset + headerLength + blockLength); - groups.encode(buffer, NULL_VALUE, limit); - varData.encode(buffer, NULL_VALUE, limit); + builder.appendLine().append("limit: ").append(oldLimit).append(" -> ").append(limit.get()); + groups.encode(builder, buffer, NULL_VALUE, limit); + varData.encode(builder, buffer, NULL_VALUE, limit); }); } @@ -802,17 +942,20 @@ public static final class EncodedMessage private final Ir ir; private final ExpandableArrayBuffer buffer; private final int length; + private final String encodingLog; private EncodedMessage( final String schema, final Ir ir, final ExpandableArrayBuffer buffer, - final int length) + final int length, + final String encodingLog) { this.schema = schema; this.ir = ir; this.buffer = buffer; this.length = length; + this.encodingLog = encodingLog; } public String schema() @@ -834,6 +977,11 @@ public int length() { return length; } + + public String encodingLog() + { + return encodingLog; + } } public static Arbitrary encodedMessage(final CharGenerationMode mode) @@ -853,10 +1001,11 @@ public static Arbitrary encodedMessage(final CharGenerationMode return SbeArbitraries.messageValueEncoder(ir, testSchema.templateId(), mode) .map(encoder -> { + final EncodingLogger logger = new EncodingLogger(); final ExpandableArrayBuffer buffer = new ExpandableArrayBuffer(); final MutableInteger limit = new MutableInteger(); - encoder.encode(buffer, 0, limit); - return new EncodedMessage(xml, ir, buffer, limit.get()); + encoder.encode(logger, buffer, 0, limit); + return new EncodedMessage(xml, ir, buffer, limit.get(), logger.toString()); }); } catch (final Exception e) diff --git a/sbe-tool/src/propertyTest/resources/CppDtosPropertyTest/main.cpp b/sbe-tool/src/propertyTest/resources/CppDtosPropertyTest/main.cpp new file mode 100644 index 0000000000..5d366adf6d --- /dev/null +++ b/sbe-tool/src/propertyTest/resources/CppDtosPropertyTest/main.cpp @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include "sbe_property_test/MessageHeader.h" +#include "sbe_property_test/TestMessage.h" +#include "sbe_property_test/TestMessageDto.h" + +using namespace uk::co::real_logic::sbe::properties; + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " $BINARY_FILE" << std::endl; + return 1; + } + + std::string binaryFile = argv[1]; + + std::cout << "Reading binary file: " << binaryFile << std::endl; + std::ifstream file(binaryFile, std::ios::binary); + std::vector inputBytes((std::istreambuf_iterator(file)), + std::istreambuf_iterator()); + + char* buffer = inputBytes.data(); + std::size_t bufferLength = inputBytes.size(); + + MessageHeader messageHeader(buffer, bufferLength); + + TestMessage decoder; + decoder.wrapForDecode( + buffer, + MessageHeader::encodedLength(), + messageHeader.blockLength(), + messageHeader.version(), + bufferLength); + + std::cout << "Decoding binary into DTO" << std::endl; + TestMessageDto dto; + TestMessageDto::decodeWith(decoder, dto); + std::vector outputBytes(inputBytes.size()); + char* outputBuffer = outputBytes.data(); + + TestMessage encoder; + encoder.wrapAndApplyHeader(outputBuffer, 0, bufferLength); + TestMessageDto::encodeWith(encoder, dto); + + std::cout << "Writing binary file: output.dat" << std::endl; + std::ofstream outputFile("output.dat", std::ios::binary); + outputFile.write(outputBuffer, outputBytes.size()); + + std::cout << "Done" << std::endl; + + return 0; +} From a0fc52546fe42059102280e39a15140cfce3acc1 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Mon, 13 Nov 2023 00:40:01 +0000 Subject: [PATCH 1158/1594] [Java, C++, C#] Ensure buffer is large enough to contain message. Previously, when generating arbitrary encoded values the generator would not necessarily extend the buffer to the size necessary to hold the message, e.g., if optional fields were left unset at the end of the message block. We now call `checkLimit` to "reserve" space for the full block length at the message and group level. This fixes an exception seen in the slow tests: ``` java.lang.IndexOutOfBoundsException: index=0 length=129 capacity=128 at org.agrona.AbstractMutableDirectBuffer.boundsCheck0(AbstractMutableDirectBuffer.java:1719) at org.agrona.AbstractMutableDirectBuffer.getBytes(AbstractMutableDirectBuffer.java:464) at org.agrona.io.DirectBufferInputStream.read(DirectBufferInputStream.java:175) at uk.co.real_logic.sbe.properties.DtosPropertyTest.writeInputFile(DtosPropertyTest.java:199) at uk.co.real_logic.sbe.properties.DtosPropertyTest.cppDtoEncodeShouldBeTheInverseOfDtoDecode(DtosPropertyTest.java:147) at java.lang.reflect.Method.invoke(Method.java:498) at net.jqwik.engine.execution.CheckedPropertyFactory.lambda$createRawFunction$1(CheckedPropertyFactory.java:84) at net.jqwik.engine.execution.CheckedPropertyFactory.lambda$createRawFunction$2(CheckedPropertyFactory.java:91) at net.jqwik.engine.properties.CheckedFunction.execute(CheckedFunction.java:17) at net.jqwik.api.lifecycle.AroundTryHook.lambda$static$0(AroundTryHook.java:57) at net.jqwik.engine.execution.lifecycle.HookSupport.lambda$wrap$2(HookSupport.java:48) at net.jqwik.engine.hooks.lifecycle.TryLifecycleMethodsHook.aroundTry(TryLifecycleMethodsHook.java:57) at net.jqwik.engine.execution.lifecycle.HookSupport.lambda$wrap$3(HookSupport.java:53) at net.jqwik.engine.execution.lifecycle.HookSupport.lambda$wrap$2(HookSupport.java:48) at net.jqwik.engine.hooks.lifecycle.BeforeTryMembersHook.aroundTry(BeforeTryMembersHook.java:69) at net.jqwik.engine.execution.lifecycle.HookSupport.lambda$wrap$3(HookSupport.java:53) at net.jqwik.engine.execution.CheckedPropertyFactory.lambda$createTryExecutor$0(CheckedPropertyFactory.java:60) at net.jqwik.engine.execution.lifecycle.AroundTryLifecycle.execute(AroundTryLifecycle.java:23) at net.jqwik.engine.properties.GenericProperty.testPredicate(GenericProperty.java:166) at net.jqwik.engine.properties.GenericProperty.check(GenericProperty.java:68) at net.jqwik.engine.execution.CheckedProperty.check(CheckedProperty.java:67) at net.jqwik.engine.execution.PropertyMethodExecutor.executeProperty(PropertyMethodExecutor.java:90) at net.jqwik.engine.execution.PropertyMethodExecutor.executeMethod(PropertyMethodExecutor.java:69) at net.jqwik.engine.execution.PropertyMethodExecutor.lambda$execute$0(PropertyMethodExecutor.java:49) at net.jqwik.api.lifecycle.AroundPropertyHook.lambda$static$0(AroundPropertyHook.java:46) at net.jqwik.engine.execution.lifecycle.HookSupport.lambda$wrap$0(HookSupport.java:26) at net.jqwik.api.lifecycle.PropertyExecutor.executeAndFinally(PropertyExecutor.java:39) at net.jqwik.engine.hooks.lifecycle.PropertyLifecycleMethodsHook.aroundProperty(PropertyLifecycleMethodsHook.java:56) at net.jqwik.engine.execution.lifecycle.HookSupport.lambda$wrap$1(HookSupport.java:31) at net.jqwik.engine.execution.lifecycle.HookSupport.lambda$wrap$0(HookSupport.java:26) at net.jqwik.engine.hooks.statistics.StatisticsHook.aroundProperty(StatisticsHook.java:37) at net.jqwik.engine.execution.lifecycle.HookSupport.lambda$wrap$1(HookSupport.java:31) at net.jqwik.engine.execution.lifecycle.HookSupport.lambda$wrap$0(HookSupport.java:26) at net.jqwik.engine.hooks.lifecycle.AutoCloseableHook.aroundProperty(AutoCloseableHook.java:13) at net.jqwik.engine.execution.lifecycle.HookSupport.lambda$wrap$1(HookSupport.java:31) at net.jqwik.engine.execution.PropertyMethodExecutor.execute(PropertyMethodExecutor.java:47) at net.jqwik.engine.execution.PropertyTaskCreator.executeTestMethod(PropertyTaskCreator.java:166) at net.jqwik.engine.execution.PropertyTaskCreator.lambda$createTask$1(PropertyTaskCreator.java:51) at net.jqwik.engine.execution.lifecycle.CurrentDomainContext.runWithContext(CurrentDomainContext.java:28) at net.jqwik.engine.execution.PropertyTaskCreator.lambda$createTask$2(PropertyTaskCreator.java:50) at net.jqwik.engine.execution.pipeline.ExecutionTask$1.lambda$execute$0(ExecutionTask.java:31) at net.jqwik.engine.execution.lifecycle.CurrentTestDescriptor.runWithDescriptor(CurrentTestDescriptor.java:17) at net.jqwik.engine.execution.pipeline.ExecutionTask$1.execute(ExecutionTask.java:31) at net.jqwik.engine.execution.pipeline.ExecutionPipeline.runToTermination(ExecutionPipeline.java:82) at net.jqwik.engine.execution.JqwikExecutor.execute(JqwikExecutor.java:46) at net.jqwik.engine.JqwikTestEngine.executeTests(JqwikTestEngine.java:70) at net.jqwik.engine.JqwikTestEngine.execute(JqwikTestEngine.java:53) ``` --- .../real_logic/sbe/properties/arbitraries/SbeArbitraries.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index bfc1f9bd88..66bfeebcf0 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -801,6 +801,7 @@ private static Arbitrary groupsEncoder( { final int offset = limit.get(); fieldsEncoder.encode(builder, buffer, offset, null); + buffer.checkLimit(offset + blockLength); limit.set(offset + blockLength); builder.appendLine().append("limit: ").append(offset).append(" -> ").append(limit.get()); groupsEncoder.encode(builder, buffer, NULL_VALUE, limit); @@ -929,6 +930,7 @@ private static Arbitrary messageValueEncoder( final int headerLength = 8; fields.encode(builder, buffer, offset + headerLength, null); final int oldLimit = limit.get(); + buffer.checkLimit(offset + headerLength + blockLength); limit.set(offset + headerLength + blockLength); builder.appendLine().append("limit: ").append(oldLimit).append(" -> ").append(limit.get()); groups.encode(builder, buffer, NULL_VALUE, limit); From 2195d6e9754c56780009d8721bd3e69bb95ee3c3 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Sat, 11 Nov 2023 18:41:10 +0000 Subject: [PATCH 1159/1594] [CI] Fix dependency conflict in JQwik. Recently JUnit was upgraded. Rebasing revealed a dependency conflict. --- .github/workflows/slow.yml | 2 -- build.gradle | 10 ++++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index a5f007f6bf..ba932f8a9e 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -50,8 +50,6 @@ jobs: uses: actions/setup-dotnet@v2 with: dotnet-version: ${{ matrix.dotnet }} - - name: Build SbeTool - run: ./gradlew - name: Build .NET library run: ./csharp/build.sh - name: Run property tests diff --git a/build.gradle b/build.gradle index 2ccfad6010..2bb3c39f22 100644 --- a/build.gradle +++ b/build.gradle @@ -58,7 +58,7 @@ def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.10.2' -def jqwikVersion = '1.8.0' +def jqwikVersion = '1.8.1' def jsonVersion = '20230618' def jmhVersion = '1.37' def agronaVersion = '1.21.2' @@ -297,11 +297,17 @@ project(':sbe-tool') { } propertyTest(JvmTestSuite) { + // We should be able to use _only_ the JQwik engine, but this issue is outstanding: + // https://github.com/gradle/gradle/issues/21299 useJUnitJupiter junitVersion dependencies { implementation project() - implementation "net.jqwik:jqwik:${jqwikVersion}" + implementation("net.jqwik:jqwik:${jqwikVersion}") { + // Exclude JUnit 5 dependencies that are already provided due to useJUnitJupiter + exclude group: 'org.junit.platform', module: 'junit-platform-commons' + exclude group: 'org.junit.platform', module: 'junit-platform-engine' + } implementation "org.json:json:${jsonVersion}" } From b9ed08b7e29b06e5f85280f43a77bb9c7c9aceee Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Mon, 13 Nov 2023 10:01:22 +0000 Subject: [PATCH 1160/1594] [CI] Upload slow test artifacts upon failure. --- .github/workflows/slow.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index ba932f8a9e..9b790d276e 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -54,3 +54,9 @@ jobs: run: ./csharp/build.sh - name: Run property tests run: ./gradlew propertyTest + - name: Upload test results + uses: actions/upload-artifact@v3 + if: success() || failure() + with: + name: property-tests + path: sbe-tool/build/reports/tests/propertyTest From b27bb68c83c5aef1da5f8ca4800d04bfde7716c6 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Mon, 13 Nov 2023 12:45:25 +0000 Subject: [PATCH 1161/1594] [C#] Provide path to SBE.dll for C# property tests in CI. --- build.gradle | 3 +++ .../co/real_logic/sbe/properties/DtosPropertyTest.java | 10 +++++++--- .../CSharpDtosPropertyTest/SbePropertyTest.csproj | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 2bb3c39f22..c21ddf3eba 100644 --- a/build.gradle +++ b/build.gradle @@ -311,6 +311,7 @@ project(':sbe-tool') { implementation "org.json:json:${jsonVersion}" } + targets { all { testTask.configure { @@ -318,6 +319,8 @@ project(':sbe-tool') { maxHeapSize = '2g' javaLauncher.set(toolchainLauncher) + + systemProperty 'sbe.dll', "${rootProject.projectDir}/csharp/sbe-dll/bin/Release/netstandard2.0/SBE.dll" } } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java index d68a1c327c..8adc57679d 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java @@ -39,6 +39,8 @@ public class DtosPropertyTest { private static final String DOTNET_EXECUTABLE = System.getProperty("sbe.tests.dotnet.executable", "dotnet"); + private static final String SBE_DLL = + System.getProperty("sbe.dll", "csharp/sbe-dll/bin/Release/netstandard2.0/SBE.dll"); private static final String CPP_EXECUTABLE = System.getProperty("sbe.tests.cpp.executable", "g++"); private static final boolean KEEP_DIR_ON_FAILURE = Boolean.parseBoolean( System.getProperty("sbe.tests.keep.dir.on.failure", "true")); @@ -80,7 +82,9 @@ void csharpDtoEncodeShouldBeTheInverseOfDtoDecode( writeInputFile(encodedMessage, tempDir); execute(encodedMessage.schema(), tempDir, "test", - DOTNET_EXECUTABLE, "run", "--", "input.dat"); + DOTNET_EXECUTABLE, "run", + "--property:SBE_DLL=" + SBE_DLL, + "--", "input.dat"); final byte[] inputBytes = new byte[encodedMessage.length()]; encodedMessage.buffer().getBytes(0, inputBytes); @@ -211,12 +215,12 @@ private static void execute( { final Path stdout = tempDir.resolve(name + "_stdout.txt"); final Path stderr = tempDir.resolve(name + "_stderr.txt"); - final ProcessBuilder compileProcessBuilder = new ProcessBuilder(args) + final ProcessBuilder processBuilder = new ProcessBuilder(args) .directory(tempDir.toFile()) .redirectOutput(stdout.toFile()) .redirectError(stderr.toFile()); - final Process process = compileProcessBuilder.start(); + final Process process = processBuilder.start(); if (0 != process.waitFor()) { diff --git a/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj index 8b0b167d2b..5da3f76095 100644 --- a/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj +++ b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj @@ -7,7 +7,7 @@ - /home/zach/src/real-logic/simple-binary-encoding/csharp/sbe-dll/bin/Release/netstandard2.0/SBE.dll + $(SBE_DLL) From 1e3cf8fea5afc3c8adcc08f9b55bb144b106ec9f Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 1 May 2024 16:19:14 +0100 Subject: [PATCH 1162/1594] [Java] Adjust copyright banners. --- .../uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java | 2 +- .../co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java | 2 +- .../java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java | 2 +- .../java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java | 2 +- .../uk/co/real_logic/sbe/properties/ParserPropertyTest.java | 2 +- .../real_logic/sbe/properties/arbitraries/SbeArbitraries.java | 2 +- .../real_logic/sbe/properties/schema/CompositeTypeSchema.java | 2 +- .../real_logic/sbe/properties/schema/EncodedDataTypeSchema.java | 2 +- .../uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java | 2 +- .../uk/co/real_logic/sbe/properties/schema/FieldSchema.java | 2 +- .../uk/co/real_logic/sbe/properties/schema/GroupSchema.java | 2 +- .../uk/co/real_logic/sbe/properties/schema/MessageSchema.java | 2 +- .../java/uk/co/real_logic/sbe/properties/schema/SetSchema.java | 2 +- .../real_logic/sbe/properties/schema/TestXmlSchemaWriter.java | 2 +- .../java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java | 2 +- .../co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java | 2 +- .../uk/co/real_logic/sbe/properties/schema/VarDataSchema.java | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index f2371181d0..168f6df665 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java index dfe00b449e..344e48d213 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java index a132e751d6..e023b8fd95 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java index 79859d6764..4fc0cc513f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java index 8adc57679d..f71e416309 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java index ab5c8d955e..a9b8cd0987 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java index b6ce84ef3a..1b59dca624 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index 66bfeebcf0..a47a93eabf 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java index a6df53d778..06123ffc9f 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java index a1bbeba14e..7abc254e0b 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java index fa669fe04a..fa28ef0a3a 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java index c1fad8abc4..9745b042a1 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java index 47cfe343a7..2aa3dcd3c3 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java index 2095628c39..d992d6559f 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java index 4ed41fc013..5acbc9da40 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java index 3c43228099..b7e3d6f8c1 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java index 311521e697..ca236a0673 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java index 830a2e1cf7..2651febfc7 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java index db3d5900a1..1bfd64621d 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 Real Logic Limited. + * Copyright 2013-2024 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 328cc427f23629e7bfdaf9caae1f1b540aa9b430 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Mon, 13 May 2024 13:40:51 +0100 Subject: [PATCH 1163/1594] [Java] Add support for DTO generation. This commit adds support for generating SBE DTOs in Java. Unlike the C# and C++ support, there isn't a natural candidate for the idiomatic representation of optional fields, e.g., `Optional` is only meant for use as a return type. Therefore, the mapping between Java types and the encoding is simpler than in these other languages. In a future commit, I will extend the property-based tests to cover Java DTOs. --- build.gradle | 16 + .../java/uk/co/real_logic/sbe/SbeTool.java | 7 +- .../generation/TargetCodeGeneratorLoader.java | 20 +- .../sbe/generation/cpp/CppDtos.java | 2 +- .../sbe/generation/java/JavaDtoGenerator.java | 1794 +++++++++++++++++ .../sbe/generation/java/JavaDtos.java | 35 + .../sbe/generation/java/JavaGenerator.java | 18 +- .../sbe/generation/java/JavaUtil.java | 11 + .../sbe/generation/java/DtoTest.java | 154 ++ .../resources/example-extension-schema.xml | 103 + 10 files changed, 2141 insertions(+), 19 deletions(-) create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java create mode 100644 sbe-tool/src/test/resources/example-extension-schema.xml diff --git a/build.gradle b/build.gradle index c21ddf3eba..b661f8b406 100644 --- a/build.gradle +++ b/build.gradle @@ -280,6 +280,7 @@ project(':sbe-tool') { compileGeneratedJava { dependsOn 'generateTestCodecs' + dependsOn 'generateTestDtos' classpath += sourceSets.main.runtimeClasspath } @@ -344,6 +345,21 @@ project(':sbe-tool') { 'src/test/resources/field-order-check-schema.xml'] } + tasks.register('generateTestDtos', JavaExec) { + dependsOn 'compileJava' + mainClass.set('uk.co.real_logic.sbe.SbeTool') + classpath = sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': generatedDir, + 'sbe.target.language': 'java', + 'sbe.validation.stop.on.error': 'true', + 'sbe.validation.xsd': validationXsdPath, + 'sbe.generate.precedence.checks': 'true', + 'sbe.java.precedence.checks.property.name': 'sbe.enable.test.precedence.checks', + 'sbe.java.generate.dtos': 'true') + args = ['src/test/resources/example-extension-schema.xml'] + } + jar { manifest.attributes( 'Specification-Title': 'Simple Binary Encoding', diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index a6958a12bf..d65a6a4601 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -195,7 +195,12 @@ public class SbeTool /** * Should generate C++ DTOs. Defaults to false. */ - public static final String GENERATE_CPP_DTOS = "sbe.cpp.generate.dtos"; + public static final String CPP_GENERATE_DTOS = "sbe.cpp.generate.dtos"; + + /** + * Should generate Java DTOs. Defaults to false. + */ + public static final String JAVA_GENERATE_DTOS = "sbe.java.generate.dtos"; /** * Configuration option used to manage sinceVersion based transformations. When set, parsed schemas will be diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 6f872cd55e..2b2383dfd2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -23,6 +23,7 @@ import uk.co.real_logic.sbe.generation.cpp.NamespaceOutputManager; import uk.co.real_logic.sbe.generation.golang.GolangGenerator; import uk.co.real_logic.sbe.generation.golang.GolangOutputManager; +import uk.co.real_logic.sbe.generation.java.JavaDtoGenerator; import uk.co.real_logic.sbe.generation.java.JavaGenerator; import uk.co.real_logic.sbe.generation.java.JavaOutputManager; import uk.co.real_logic.sbe.generation.rust.RustGenerator; @@ -47,7 +48,9 @@ public enum TargetCodeGeneratorLoader implements TargetCodeGenerator */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { - return new JavaGenerator( + final JavaOutputManager outputManager = new JavaOutputManager(outputDir, ir.applicableNamespace()); + + final JavaGenerator codecGenerator = new JavaGenerator( ir, System.getProperty(JAVA_ENCODING_BUFFER_TYPE, JAVA_DEFAULT_ENCODING_BUFFER_TYPE), System.getProperty(JAVA_DECODING_BUFFER_TYPE, JAVA_DEFAULT_DECODING_BUFFER_TYPE), @@ -56,7 +59,18 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) "true".equals(System.getProperty(DECODE_UNKNOWN_ENUM_VALUES)), "true".equals(System.getProperty(TYPES_PACKAGE_OVERRIDE)), precedenceChecks(), - new JavaOutputManager(outputDir, ir.applicableNamespace())); + outputManager); + + final JavaDtoGenerator dtoGenerator = new JavaDtoGenerator(ir, outputManager); + + final CodeGenerator combinedGenerator = () -> + { + codecGenerator.generate(); + dtoGenerator.generate(); + }; + + final boolean generateDtos = "true".equals(System.getProperty(JAVA_GENERATE_DTOS)); + return generateDtos ? combinedGenerator : codecGenerator; } }, @@ -97,7 +111,7 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) dtoGenerator.generate(); }; - final boolean generateDtos = "true".equals(System.getProperty(GENERATE_CPP_DTOS)); + final boolean generateDtos = "true".equals(System.getProperty(CPP_GENERATE_DTOS)); return generateDtos ? combinedGenerator : codecGenerator; } }, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java index 344e48d213..09dbfb052f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java @@ -22,7 +22,7 @@ import uk.co.real_logic.sbe.ir.Ir; /** - * {@link CodeGenerator} factory for CSharp DTOs. + * {@link CodeGenerator} factory for C++ DTOs. */ public class CppDtos implements TargetCodeGenerator { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java new file mode 100644 index 0000000000..b5fd05e665 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -0,0 +1,1794 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * Copyright (C) 2017 MarketFactory, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.generation.CodeGenerator; +import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.ir.Signal; +import uk.co.real_logic.sbe.ir.Token; +import org.agrona.LangUtil; +import org.agrona.Verify; +import org.agrona.generation.OutputManager; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; + +import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; +import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; +import static uk.co.real_logic.sbe.generation.java.JavaUtil.*; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; +import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData; + +/** + * DTO generator for the Java programming language. + */ +public class JavaDtoGenerator implements CodeGenerator +{ + private static final String INDENT = " "; + private static final String BASE_INDENT = ""; + + private final Ir ir; + private final OutputManager outputManager; + + /** + * Create a new C# DTO {@link CodeGenerator}. + * + * @param ir for the messages and types. + * @param outputManager for generating the DTOs to. + */ + public JavaDtoGenerator(final Ir ir, final OutputManager outputManager) + { + Verify.notNull(ir, "ir"); + Verify.notNull(outputManager, "outputManager"); + + this.ir = ir; + this.outputManager = outputManager; + } + + /** + * {@inheritDoc} + */ + public void generate() throws IOException + { + generateDtosForTypes(); + + for (final List tokens : ir.messages()) + { + final Token msgToken = tokens.get(0); + final String encoderClassName = encoderName(msgToken.name()); + final String decoderClassName = decoderName(msgToken.name()); + final String dtoClassName = formatDtoClassName(msgToken.name()); + + final List messageBody = tokens.subList(1, tokens.size() - 1); + int offset = 0; + + final ClassBuilder classBuilder = new ClassBuilder(dtoClassName, BASE_INDENT, "public final"); + + final List fields = new ArrayList<>(); + offset = collectFields(messageBody, offset, fields); + generateFields(classBuilder, decoderClassName, fields, BASE_INDENT + INDENT); + + final List groups = new ArrayList<>(); + offset = collectGroups(messageBody, offset, groups); + generateGroups(classBuilder, dtoClassName, encoderClassName, decoderClassName, groups, + BASE_INDENT + INDENT); + + final List varData = new ArrayList<>(); + collectVarData(messageBody, offset, varData); + generateVarData(classBuilder, varData, BASE_INDENT + INDENT); + + generateDecodeWith(classBuilder, dtoClassName, decoderClassName, fields, + groups, varData, BASE_INDENT + INDENT); + generateDecodeFrom(classBuilder, dtoClassName, decoderClassName, BASE_INDENT + INDENT); + generateEncodeWith(classBuilder, dtoClassName, encoderClassName, fields, groups, varData, + BASE_INDENT + INDENT); + generateEncodeWithOverloads(classBuilder, dtoClassName, encoderClassName, BASE_INDENT + INDENT); + generateComputeEncodedLength(classBuilder, decoderClassName, + decoderClassName + ".BLOCK_LENGTH", + groups, varData, BASE_INDENT + INDENT); + generateDisplay(classBuilder, encoderClassName, "computeEncodedLength()", + BASE_INDENT + INDENT); + + try (Writer out = outputManager.createOutput(dtoClassName)) + { + out.append(generateDtoFileHeader(ir.applicableNamespace())); + out.append("import org.agrona.DirectBuffer;\n"); + out.append("import org.agrona.MutableDirectBuffer;\n"); + out.append("import org.agrona.concurrent.UnsafeBuffer;\n\n"); + out.append("import java.util.ArrayList;\n"); + out.append("import java.util.List;\n\n"); + out.append(generateDocumentation(BASE_INDENT, msgToken)); + classBuilder.appendTo(out); + } + } + } + + private static final class ClassBuilder + { + private final StringBuilder fieldSb = new StringBuilder(); + private final StringBuilder privateSb = new StringBuilder(); + private final StringBuilder publicSb = new StringBuilder(); + private final String className; + private final String indent; + private final String modifiers; + + private ClassBuilder( + final String className, + final String indent, + final String modifiers) + { + this.className = className; + this.indent = indent; + this.modifiers = modifiers.length() == 0 ? modifiers : modifiers + " "; + } + + public StringBuilder appendField() + { + return fieldSb; + } + + public StringBuilder appendPrivate() + { + return privateSb; + } + + public StringBuilder appendPublic() + { + return publicSb; + } + + public void appendTo(final Appendable out) + { + try + { + out.append(indent).append(modifiers).append("class ").append(className).append("\n") + .append(indent).append("{\n") + .append(fieldSb) + .append("\n") + .append(privateSb) + .append("\n") + .append(publicSb) + .append("\n") + .append(indent).append("}\n"); + } + catch (final IOException exception) + { + LangUtil.rethrowUnchecked(exception); + } + } + } + + private void generateGroups( + final ClassBuilder classBuilder, + final String qualifiedParentDtoClassName, + final String qualifiedParentEncoderClassName, + final String qualifiedParentDecoderClassName, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + final String groupName = groupToken.name(); + final String groupClassName = formatDtoClassName(groupName); + final String qualifiedDtoClassName = qualifiedParentDtoClassName + "." + groupClassName; + + final String fieldName = formatFieldName(groupName); + final String formattedPropertyName = formatPropertyName(groupName); + + classBuilder.appendField().append(indent).append("private List<") + .append(qualifiedDtoClassName).append("> ") + .append(fieldName).append(" = new ArrayList<>();\n"); + + final ClassBuilder groupClassBuilder = new ClassBuilder(groupClassName, indent, "public static final"); + + i++; + i += tokens.get(i).componentTokenCount(); + + final String qualifiedEncoderClassName = + qualifiedParentEncoderClassName + "." + encoderName(groupName); + final String qualifiedDecoderClassName = + qualifiedParentDecoderClassName + "." + decoderName(groupName); + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + generateFields(groupClassBuilder, qualifiedDecoderClassName, fields, indent + INDENT); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + generateGroups(groupClassBuilder, qualifiedDtoClassName, + qualifiedEncoderClassName, qualifiedDecoderClassName, groups, indent + INDENT); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + generateVarData(groupClassBuilder, varData, indent + INDENT); + + generateDecodeListWith( + groupClassBuilder, groupClassName, qualifiedDecoderClassName, indent + INDENT); + generateDecodeWith(groupClassBuilder, groupClassName, qualifiedDecoderClassName, + fields, groups, varData, indent + INDENT); + generateEncodeWith( + groupClassBuilder, groupClassName, qualifiedEncoderClassName, fields, groups, varData, indent + INDENT); + generateComputeEncodedLength(groupClassBuilder, qualifiedDecoderClassName, + qualifiedDecoderClassName + ".sbeBlockLength()", + groups, varData, indent + INDENT); + + groupClassBuilder.appendTo( + classBuilder.appendPublic().append("\n").append(generateDocumentation(indent, groupToken)) + ); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, groupToken)) + .append(indent).append("public List<").append(qualifiedDtoClassName).append("> ") + .append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, groupToken)) + .append(indent).append("public void ").append(formattedPropertyName).append("(") + .append("List<").append(qualifiedDtoClassName).append("> value)") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append("}\n"); + } + } + + private void generateComputeEncodedLength( + final ClassBuilder classBuilder, + final String qualifiedDecoderClassName, + final String blockLengthExpression, + final List groupTokens, + final List varDataTokens, + final String indent) + { + final StringBuilder lengthBuilder = classBuilder.appendPublic() + .append("\n") + .append(indent).append("public int computeEncodedLength()\n") + .append(indent).append("{\n"); + + lengthBuilder + .append(indent).append(INDENT).append("int encodedLength = 0;\n"); + + lengthBuilder.append(indent).append(INDENT).append("encodedLength += ").append(blockLengthExpression) + .append(";\n\n"); + + for (int i = 0, size = groupTokens.size(); i < size; i++) + { + final Token groupToken = groupTokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + i++; + i += groupTokens.get(i).componentTokenCount(); + + final List fields = new ArrayList<>(); + i = collectFields(groupTokens, i, fields); + final List subGroups = new ArrayList<>(); + i = collectGroups(groupTokens, i, subGroups); + final List subVarData = new ArrayList<>(); + i = collectVarData(groupTokens, i, subVarData); + + final String groupName = groupToken.name(); + final String fieldName = formatFieldName(groupName); + final String groupDecoderClassName = qualifiedDecoderClassName + "." + decoderName(groupName); + final String groupDtoClassName = formatDtoClassName(groupName); + + lengthBuilder + .append(indent).append(INDENT).append("encodedLength += ") + .append(groupDecoderClassName).append(".sbeHeaderSize();\n\n") + .append(indent).append(INDENT).append("for (").append(groupDtoClassName).append(" group : ") + .append(fieldName).append(")\n") + .append(indent).append(INDENT).append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("encodedLength += group.computeEncodedLength();\n") + .append(indent).append(INDENT).append("}\n\n"); + } + + for (int i = 0, size = varDataTokens.size(); i < size; i++) + { + final Token token = varDataTokens.get(i); + if (token.signal() == Signal.BEGIN_VAR_DATA) + { + final String propertyName = token.name(); + final Token varDataToken = Generators.findFirst("varData", varDataTokens, i); + final String fieldName = formatFieldName(propertyName); + + lengthBuilder.append(indent).append(INDENT).append("encodedLength += ") + .append(qualifiedDecoderClassName).append(".") + .append(formatPropertyName(propertyName)).append("HeaderLength();\n"); + + lengthBuilder.append(indent).append(INDENT).append("encodedLength += ") + .append(fieldName).append(".length()"); + + final int elementByteLength = varDataToken.encoding().primitiveType().size(); + if (elementByteLength != 1) + { + lengthBuilder.append(" * ").append(elementByteLength); + } + + lengthBuilder.append(";\n\n"); + } + } + + lengthBuilder.append(indent).append(INDENT).append("return encodedLength;\n") + .append(indent).append("}\n"); + } + + private void generateCompositeDecodeWith( + final ClassBuilder classBuilder, + final String dtoClassName, + final String decoderClassName, + final List tokens, + final String indent) + { + final StringBuilder decodeBuilder = classBuilder.appendPublic().append("\n") + .append(indent).append("public static void decodeWith(").append(decoderClassName).append(" decoder, ") + .append(dtoClassName).append(" dto)\n") + .append(indent).append("{\n"); + + for (int i = 0; i < tokens.size(); ) + { + final Token token = tokens.get(i); + + generateFieldDecodeWith( + decodeBuilder, token, token, decoderClassName, indent + INDENT); + + i += tokens.get(i).componentTokenCount(); + } + + decodeBuilder.append(indent).append("}\n"); + } + + private void generateCompositeEncodeWith( + final ClassBuilder classBuilder, + final String dtoClassName, + final String encoderClassName, + final List tokens, + final String indent) + { + final StringBuilder encodeBuilder = classBuilder.appendPublic().append("\n") + .append(indent).append("public static void encodeWith(").append(encoderClassName).append(" encoder, ") + .append(dtoClassName).append(" dto)\n") + .append(indent).append("{\n"); + + for (int i = 0; i < tokens.size(); ) + { + final Token token = tokens.get(i); + + generateFieldEncodeWith(encodeBuilder, token, token, indent + INDENT); + + i += tokens.get(i).componentTokenCount(); + } + + encodeBuilder.append(indent).append("}\n"); + } + + private void generateDecodeListWith( + final ClassBuilder classBuilder, + final String dtoClassName, + final String decoderClassName, + final String indent) + { + classBuilder.appendPublic().append("\n") + .append(indent).append("static List<").append(dtoClassName).append("> decodeManyWith(") + .append(decoderClassName).append(" decoder)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("List<").append(dtoClassName) + .append("> dtos = new ArrayList<>(decoder.count());\n") + .append(indent).append(INDENT) + .append("while (decoder.hasNext())\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append(dtoClassName).append(" dto = new ").append(dtoClassName).append("();\n") + .append(indent).append(INDENT).append(INDENT) + .append(dtoClassName).append(".decodeWith(decoder.next(), dto);\n") + .append(indent).append(INDENT).append(INDENT) + .append("dtos.add(dto);\n") + .append(indent).append(INDENT) + .append("}\n") + .append(indent).append(INDENT) + .append("return dtos;\n") + .append(indent).append("}\n"); + } + + private void generateDecodeWith( + final ClassBuilder classBuilder, + final String dtoClassName, + final String decoderClassName, + final List fields, + final List groups, + final List varData, + final String indent) + { + final StringBuilder decodeBuilder = classBuilder.appendPublic().append("\n") + .append(indent).append("public static void decodeWith(").append(decoderClassName).append(" decoder, ") + .append(dtoClassName).append(" dto)\n") + .append(indent).append("{\n"); + + generateMessageFieldsDecodeWith(decodeBuilder, fields, decoderClassName, indent + INDENT); + generateGroupsDecodeWith(decodeBuilder, groups, indent + INDENT); + generateVarDataDecodeWith(decodeBuilder, varData, indent + INDENT); + decodeBuilder.append(indent).append("}\n"); + } + + private static void generateDecodeFrom( + final ClassBuilder classBuilder, + final String dtoClassName, + final String decoderClassName, + final String indent) + { + classBuilder.appendPublic() + .append("\n") + .append(indent).append("public static ").append(dtoClassName).append(" decodeFrom(") + .append("DirectBuffer buffer, int offset, ") + .append("short actingBlockLength, short actingVersion)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(decoderClassName).append(" decoder = new ") + .append(decoderClassName).append("();\n") + .append(indent).append(INDENT) + .append("decoder.wrap(buffer, offset, actingBlockLength, actingVersion);\n") + .append(indent).append(INDENT).append(dtoClassName).append(" dto = new ") + .append(dtoClassName).append("();\n") + .append(indent).append(INDENT).append("decodeWith(decoder, dto);\n") + .append(indent).append(INDENT).append("return dto;\n") + .append(indent).append("}\n"); + } + + private void generateMessageFieldsDecodeWith( + final StringBuilder sb, + final List tokens, + final String decoderClassName, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token signalToken = tokens.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = tokens.get(i + 1); + + generateFieldDecodeWith(sb, signalToken, encodingToken, decoderClassName, indent); + } + } + } + + private void generateFieldDecodeWith( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String decoderClassName, + final String indent) + { + switch (typeToken.signal()) + { + case ENCODING: + generatePrimitiveDecodeWith(sb, fieldToken, typeToken, decoderClassName, indent); + break; + + case BEGIN_SET: + final String bitSetName = formatDtoClassName(typeToken.applicableTypeName()); + generateBitSetDecodeWith(sb, fieldToken, bitSetName, indent); + break; + + case BEGIN_ENUM: + generateEnumDecodeWith(sb, fieldToken, indent); + break; + + case BEGIN_COMPOSITE: + generateCompositePropertyDecodeWith(sb, fieldToken, typeToken, indent); + break; + + default: + break; + } + } + + private void generatePrimitiveDecodeWith( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String decoderClassName, + final String indent) + { + if (typeToken.isConstantEncoding()) + { + return; + } + + final int arrayLength = typeToken.arrayLength(); + + if (arrayLength == 1) + { + final String decoderNullValue = + decoderClassName + "." + formatPropertyName(fieldToken.name()) + "NullValue()"; + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + generateRecordPropertyAssignment( + sb, + fieldToken, + indent, + "decoder.actingVersion() >= " + decoderClassName + "." + formattedPropertyName + "SinceVersion()", + "decoder." + formattedPropertyName + "()", + decoderNullValue + ); + } + else if (arrayLength > 1) + { + generateArrayDecodeWith(sb, decoderClassName, fieldToken, typeToken, indent); + } + } + + private void generateArrayDecodeWith( + final StringBuilder sb, + final String decoderClassName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + generateRecordPropertyAssignment( + sb, + fieldToken, + indent, + "decoder.actingVersion() >= " + decoderClassName + "." + formattedPropertyName + "SinceVersion()", + "decoder." + formattedPropertyName + "()", + "\"\"" + ); + } + else + { + final StringBuilder initializerList = new StringBuilder(); + final String elementType = javaTypeName(typeToken.encoding().primitiveType()); + initializerList.append("new ").append(elementType).append("[] { "); + final int arrayLength = typeToken.arrayLength(); + for (int i = 0; i < arrayLength; i++) + { + initializerList.append("decoder.").append(formattedPropertyName).append("(").append(i).append("),"); + } + assert arrayLength > 0; + initializerList.setLength(initializerList.length() - 1); + initializerList.append(" }"); + + generateRecordPropertyAssignment( + sb, + fieldToken, + indent, + "decoder.actingVersion() >= " + decoderClassName + "." + formattedPropertyName + "SinceVersion()", + initializerList, + null + ); + } + } + + private void generateBitSetDecodeWith( + final StringBuilder sb, + final Token fieldToken, + final String dtoTypeName, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + if (fieldToken.isOptionalEncoding()) + { + sb.append(indent).append("if (decoder.").append(formattedPropertyName).append("InActingVersion()"); + + sb.append(")\n") + .append(indent).append("{\n"); + + sb.append(indent).append(INDENT).append(dtoTypeName).append(".decodeWith(decoder.") + .append(formattedPropertyName).append("(), ") + .append("dto.").append(formattedPropertyName).append("());\n"); + + sb.append(indent).append("}\n") + .append(indent).append("else\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("dto.").append(formattedPropertyName).append("().clear();\n") + .append(indent).append("}\n"); + } + else + { + sb.append(indent).append(dtoTypeName).append(".decodeWith(decoder.") + .append(formattedPropertyName).append("(), ") + .append("dto.").append(formattedPropertyName).append("());\n"); + } + } + + private void generateEnumDecodeWith( + final StringBuilder sb, + final Token fieldToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + sb.append(indent).append("dto.").append(formattedPropertyName).append("(") + .append("decoder.").append(formattedPropertyName).append("());\n"); + } + + private void generateCompositePropertyDecodeWith( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + final String dtoClassName = formatDtoClassName(typeToken.applicableTypeName()); + + sb.append(indent).append(dtoClassName).append(".decodeWith(decoder.") + .append(formattedPropertyName).append("(), ") + .append("dto.").append(formattedPropertyName).append("());\n"); + } + + private void generateGroupsDecodeWith( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + final String groupName = groupToken.name(); + final String formattedPropertyName = formatPropertyName(groupName); + final String groupDtoClassName = formatDtoClassName(groupName); + + sb.append(indent).append("dto.").append(formattedPropertyName).append("(") + .append(groupDtoClassName).append(".decodeManyWith(decoder.") + .append(formattedPropertyName).append("()));\n"); + + i++; + i += tokens.get(i).componentTokenCount(); + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + } + } + + private void generateVarDataDecodeWith( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0; i < tokens.size(); i++) + { + final Token token = tokens.get(i); + if (token.signal() == Signal.BEGIN_VAR_DATA) + { + final String propertyName = token.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + final Token varDataToken = Generators.findFirst("varData", tokens, i); + final String characterEncoding = varDataToken.encoding().characterEncoding(); + + final boolean isOptional = token.version() > 0; + final String blockIndent = isOptional ? indent + INDENT : indent; + + final String dataVar = toLowerFirstChar(propertyName) + "Data"; + + final StringBuilder decoderValueExtraction = new StringBuilder(); + + if (characterEncoding == null) + { + decoderValueExtraction.append(blockIndent).append("byte[] ").append(dataVar) + .append(" = new byte[decoder.").append(formattedPropertyName).append("Length()];\n") + .append(blockIndent).append("decoder.get").append(formattedPropertyName) + .append("(").append(dataVar).append(", 0, decoder.").append(formattedPropertyName) + .append("Length());\n"); + } + else + { + decoderValueExtraction.append(blockIndent).append("String ").append(dataVar) + .append(" = decoder.").append(formattedPropertyName).append("();\n"); + } + + if (isOptional) + { + sb.append(indent).append("if (decoder.").append(formattedPropertyName).append("InActingVersion()"); + + sb.append(")\n") + .append(indent).append("{\n"); + + sb.append(decoderValueExtraction); + + sb.append(indent).append(INDENT).append("dto.").append(formattedPropertyName).append("(") + .append(dataVar).append(");\n"); + + final String nullDtoValue = "\"\""; + + sb.append(indent).append("}\n") + .append(indent).append("else\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("dto.") + .append(formattedPropertyName).append("(").append(nullDtoValue).append(");\n") + .append(indent).append("}\n"); + } + else + { + sb.append(decoderValueExtraction); + + sb.append(indent).append("dto.").append(formattedPropertyName).append("(") + .append(dataVar).append(");\n"); + } + } + } + } + + private void generateRecordPropertyAssignment( + final StringBuilder sb, + final Token token, + final String indent, + final String presenceExpression, + final CharSequence getExpression, + final String nullDecoderValueOrNull) + { + final String propertyName = token.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + if (token.isOptionalEncoding()) + { + + sb.append(indent).append("if (").append(presenceExpression).append(")\n") + .append(indent).append("{\n"); + + sb.append(indent).append(INDENT).append("dto.").append(formattedPropertyName).append("(") + .append(getExpression).append(");\n"); + + final String nullValue = nullDecoderValueOrNull == null ? "null" : nullDecoderValueOrNull; + + sb.append(indent).append("}\n") + .append(indent).append("else\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("dto.").append(formattedPropertyName).append("(") + .append(nullValue).append(");\n") + .append(indent).append("}\n"); + } + else + { + sb.append(indent).append("dto.").append(formattedPropertyName).append("(") + .append(getExpression).append(");\n"); + } + } + + private void generateEncodeWith( + final ClassBuilder classBuilder, + final String dtoClassName, + final String encoderClassName, + final List fields, + final List groups, + final List varData, + final String indent) + { + final StringBuilder encodeBuilder = classBuilder.appendPublic().append("\n") + .append(indent).append("public static void encodeWith(").append(encoderClassName).append(" encoder, ") + .append(dtoClassName).append(" dto)\n") + .append(indent).append("{\n"); + + generateFieldsEncodeWith(encodeBuilder, fields, indent + INDENT); + generateGroupsEncodeWith(encodeBuilder, encoderClassName, groups, indent + INDENT); + generateVarDataEncodeWith(encodeBuilder, varData, indent + INDENT); + + encodeBuilder.append(indent).append("}\n"); + } + + private static void generateEncodeWithOverloads( + final ClassBuilder classBuilder, + final String dtoClassName, + final String encoderClassName, + final String indent) + { + classBuilder.appendPublic() + .append("\n") + .append(indent).append("public static int encodeWith(").append(dtoClassName).append(" dto, ") + .append("MutableDirectBuffer buffer, int offset)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(encoderClassName).append(" encoder = new ") + .append(encoderClassName).append("();\n") + .append(indent).append(INDENT).append("encoder.wrap(buffer, offset);\n") + .append(indent).append(INDENT).append("encodeWith(encoder, dto);\n") + .append(indent).append(INDENT).append("return encoder.encodedLength();\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic() + .append("\n") + .append(indent).append("public static int encodeWithHeaderWith(") + .append(dtoClassName).append(" dto, ") + .append("MutableDirectBuffer buffer, int offset)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(encoderClassName).append(" encoder = new ") + .append(encoderClassName).append("();\n") + .append(indent).append(INDENT) + .append("encoder.wrapAndApplyHeader(buffer, offset, new MessageHeaderEncoder());\n") + .append(indent).append(INDENT).append("encodeWith(encoder, dto);\n") + .append(indent).append(INDENT).append("return encoder.limit() - offset;\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic() + .append("\n") + .append(indent).append("public static byte[] bytes(") + .append(dtoClassName).append(" dto)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("byte[] bytes = new byte[dto.computeEncodedLength()];\n") + .append(indent).append(INDENT).append("encodeWith(dto, new UnsafeBuffer(bytes), 0);\n") + .append(indent).append(INDENT).append("return bytes;\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic() + .append("\n") + .append(indent).append("public static byte[] bytesWithHeader(") + .append(dtoClassName).append(" dto)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("byte[] bytes = new byte[dto.computeEncodedLength() + ") + .append("MessageHeaderEncoder.ENCODED_LENGTH];\n") + .append(indent).append(INDENT).append("encodeWithHeaderWith(dto, new UnsafeBuffer(bytes), 0);\n") + .append(indent).append(INDENT).append("return bytes;\n") + .append(indent).append("}\n"); + } + + private void generateFieldsEncodeWith( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token signalToken = tokens.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = tokens.get(i + 1); + generateFieldEncodeWith(sb, signalToken, encodingToken, indent); + } + } + } + + private void generateFieldEncodeWith( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String indent) + { + switch (typeToken.signal()) + { + case ENCODING: + generatePrimitiveEncodeWith(sb, fieldToken, typeToken, indent); + break; + + case BEGIN_ENUM: + generateEnumEncodeWith(sb, fieldToken, indent); + break; + + case BEGIN_SET: + case BEGIN_COMPOSITE: + generateComplexPropertyEncodeWith(sb, fieldToken, typeToken, indent); + break; + + default: + break; + } + } + + private void generatePrimitiveEncodeWith( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (typeToken.isConstantEncoding()) + { + return; + } + + final int arrayLength = typeToken.arrayLength(); + + if (arrayLength == 1) + { + generatePrimitiveValueEncodeWith(sb, fieldToken, indent); + } + else if (arrayLength > 1) + { + generateArrayEncodeWith(sb, fieldToken, typeToken, indent); + } + } + + private void generateArrayEncodeWith( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + sb.append(indent).append("encoder.").append(toLowerFirstChar(propertyName)).append("(") + .append("dto.").append(formattedPropertyName).append("());\n"); + } + else if (typeToken.encoding().primitiveType() == PrimitiveType.UINT8) + { + sb.append(indent).append("encoder.put").append(toUpperFirstChar(propertyName)).append("(") + .append("dto.").append(formattedPropertyName).append("());\n"); + } + else + { + final String javaTypeName = javaTypeName(typeToken.encoding().primitiveType()); + sb.append(indent).append(javaTypeName).append("[] ").append(formattedPropertyName).append(" = ") + .append("dto.").append(formattedPropertyName).append("();\n") + .append(indent).append("for (int i = 0; i < ").append(formattedPropertyName).append(".length; i++)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("encoder.").append(formattedPropertyName).append("(") + .append("i, ").append(formattedPropertyName).append("[i]);\n") + .append(indent).append("}\n"); + } + } + + private void generatePrimitiveValueEncodeWith( + final StringBuilder sb, + final Token fieldToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + final String accessor = "dto." + formattedPropertyName + "()"; + + sb.append(indent).append("encoder.").append(formattedPropertyName).append("(") + .append(accessor).append(");\n"); + } + + private void generateEnumEncodeWith( + final StringBuilder sb, + final Token fieldToken, + final String indent) + { + if (fieldToken.isConstantEncoding()) + { + return; + } + + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + + sb.append(indent).append("encoder.").append(formattedPropertyName).append("(dto.") + .append(formattedPropertyName).append("());\n"); + } + + private void generateComplexPropertyEncodeWith( + final StringBuilder sb, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String propertyName = fieldToken.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + final String typeName = formatDtoClassName(typeToken.applicableTypeName()); + + sb.append(indent).append(typeName).append(".encodeWith(encoder.") + .append(formattedPropertyName).append("(), dto.") + .append(formattedPropertyName).append("());\n"); + } + + private void generateGroupsEncodeWith( + final StringBuilder sb, + final String parentEncoderClassName, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + final String groupName = groupToken.name(); + final String formattedPropertyName = formatPropertyName(groupName); + final String groupEncoderVarName = groupName + "Encoder"; + final String groupDtoTypeName = formatDtoClassName(groupName); + final String groupEncoderTypeName = parentEncoderClassName + "." + encoderName(groupName); + + sb.append("\n") + .append(indent).append("List<").append(groupDtoTypeName).append("> ") + .append(formattedPropertyName).append(" = dto.").append(formattedPropertyName).append("();\n\n") + .append(indent).append(groupEncoderTypeName).append(" ").append(groupEncoderVarName) + .append(" = encoder.").append(formattedPropertyName) + .append("Count(").append(formattedPropertyName).append(".size());\n\n") + .append(indent).append("for (").append(groupDtoTypeName).append(" group : ") + .append(formattedPropertyName).append(")\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(groupDtoTypeName) + .append(".encodeWith(").append(groupEncoderVarName).append(".next(), group);\n") + .append(indent).append("}\n\n"); + + i++; + i += tokens.get(i).componentTokenCount(); + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + } + } + + private void generateVarDataEncodeWith( + final StringBuilder sb, + final List tokens, + final String indent) + { + for (int i = 0; i < tokens.size(); i++) + { + final Token token = tokens.get(i); + if (token.signal() == Signal.BEGIN_VAR_DATA) + { + final String propertyName = token.name(); + final String formattedPropertyName = formatPropertyName(propertyName); + final Token varDataToken = Generators.findFirst("varData", tokens, i); + final String characterEncoding = varDataToken.encoding().characterEncoding(); + + if (characterEncoding == null) + { + sb.append(indent).append("encoder.put").append(toUpperFirstChar(propertyName)).append("(") + .append("dto.").append(formattedPropertyName).append("());\n"); + } + else + { + sb.append(indent).append("encoder.").append(formattedPropertyName).append("(") + .append("dto.").append(formattedPropertyName).append("());\n"); + } + } + } + } + + private void generateDisplay( + final ClassBuilder classBuilder, + final String encoderClassName, + final String lengthExpression, + final String indent) + { + final StringBuilder sb = classBuilder.appendPublic(); + + sb.append("\n") + .append(indent).append("public String toString()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT) + .append("MutableDirectBuffer buffer = new UnsafeBuffer(new byte[").append(lengthExpression).append("]);\n") + .append(indent).append(INDENT).append(encoderClassName).append(" encoder = new ") + .append(encoderClassName).append("();\n") + .append(indent).append(INDENT).append("encoder."); + + sb.append("wrap").append("(buffer, 0);\n"); + + sb.append(indent).append(INDENT).append("encodeWith(encoder, this);\n") + .append(indent).append(INDENT).append("StringBuilder sb = new StringBuilder();\n") + .append(indent).append(INDENT).append("encoder.appendTo(sb);\n") + .append(indent).append(INDENT).append("return sb.toString();\n") + .append(indent).append("}\n"); + } + + private void generateFields( + final ClassBuilder classBuilder, + final String decoderClassName, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token signalToken = tokens.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = tokens.get(i + 1); + final String propertyName = signalToken.name(); + + switch (encodingToken.signal()) + { + case ENCODING: + generatePrimitiveProperty( + classBuilder, decoderClassName, propertyName, signalToken, encodingToken, indent); + break; + + case BEGIN_ENUM: + generateEnumProperty(classBuilder, propertyName, signalToken, encodingToken, indent); + break; + + case BEGIN_SET: + case BEGIN_COMPOSITE: + generateComplexProperty(classBuilder, propertyName, signalToken, encodingToken, indent); + break; + + default: + break; + } + } + } + } + + private void generateComplexProperty( + final ClassBuilder classBuilder, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String typeName = formatDtoClassName(typeToken.applicableTypeName()); + final String formattedPropertyName = formatPropertyName(propertyName); + final String fieldName = formatFieldName(propertyName); + + classBuilder.appendField() + .append(indent).append("private ").append(typeName).append(" ").append(fieldName) + .append(" = new ").append(typeName).append("();\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public ").append(typeName).append(" ") + .append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public void ") + .append(formattedPropertyName).append("(").append(typeName).append(" value)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append("}\n"); + } + + private void generateEnumProperty( + final ClassBuilder classBuilder, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String enumName = formatClassName(typeToken.applicableTypeName()); + + final String formattedPropertyName = formatPropertyName(propertyName); + + if (fieldToken.isConstantEncoding()) + { + final String constValue = fieldToken.encoding().constValue().toString(); + final String caseName = constValue.substring(constValue.indexOf(".") + 1); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public static ").append(enumName).append(" ") + .append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(enumName).append(".") + .append(caseName).append(";\n") + .append(indent).append("}\n"); + } + else + { + final String fieldName = formatFieldName(propertyName); + + classBuilder.appendField() + .append(indent).append("private ").append(enumName).append(" ").append(fieldName).append(";\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public ").append(enumName).append(" ") + .append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public void ").append(formattedPropertyName) + .append("(").append(enumName).append(" value)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append("}\n"); + } + } + + private void generatePrimitiveProperty( + final ClassBuilder classBuilder, + final String decoderClassName, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (typeToken.isConstantEncoding()) + { + generateConstPropertyMethods(classBuilder, propertyName, fieldToken, typeToken, indent); + } + else + { + generatePrimitivePropertyMethods( + classBuilder, decoderClassName, propertyName, fieldToken, typeToken, indent); + } + } + + private void generatePrimitivePropertyMethods( + final ClassBuilder classBuilder, + final String decoderClassName, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final int arrayLength = typeToken.arrayLength(); + + if (arrayLength == 1) + { + generateSingleValueProperty(classBuilder, decoderClassName, propertyName, fieldToken, typeToken, indent); + } + else if (arrayLength > 1) + { + generateArrayProperty(classBuilder, decoderClassName, propertyName, fieldToken, typeToken, indent); + } + } + + private void generateArrayProperty( + final ClassBuilder classBuilder, + final String decoderClassName, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String formattedPropertyName = formatPropertyName(propertyName); + final String fieldName = formatFieldName(propertyName); + final String validateMethod = "validate" + toUpperFirstChar(propertyName); + + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + final CharSequence typeName = "String"; + + classBuilder.appendField() + .append(indent).append("private ").append(typeName).append(" ").append(fieldName).append(";\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public ").append(typeName).append(" ") + .append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("void ").append(formattedPropertyName) + .append("(").append(typeName).append(" value)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(validateMethod).append("(value);\n") + .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append("}\n"); + + generateArrayValidateMethod( + classBuilder, + decoderClassName, + indent, + validateMethod, + typeName, + ".length()", + formattedPropertyName); + } + else + { + final String elementTypeName = javaTypeName(typeToken.encoding().primitiveType()); + final String typeName = elementTypeName + "[]"; + + classBuilder.appendField() + .append(indent).append("private ").append(typeName).append(" ").append(fieldName).append(";\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public ").append(typeName).append(" ") + .append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public void ").append(formattedPropertyName).append("(") + .append(typeName).append(" value").append(")\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(validateMethod).append("(value);\n") + .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append("}\n"); + + generateArrayValidateMethod( + classBuilder, + decoderClassName, + indent, + validateMethod, + typeName, + ".length", + formattedPropertyName); + } + } + + private static void generateArrayValidateMethod( + final ClassBuilder classBuilder, + final String decoderClassName, + final String indent, + final String validateMethod, + final CharSequence typeName, + final String lengthAccessor, + final String formattedPropertyName) + { + final StringBuilder validateBuilder = classBuilder.appendPrivate().append("\n") + .append(indent).append("private static void ").append(validateMethod).append("(") + .append(typeName).append(" value)\n") + .append(indent).append("{\n"); + + validateBuilder.append(indent).append(INDENT) + .append("if (value").append(lengthAccessor).append(" > ").append(decoderClassName).append(".") + .append(formattedPropertyName).append("Length())\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("throw new IllegalArgumentException(\"") + .append(formattedPropertyName) + .append(": too many elements: \" + ") + .append("value").append(lengthAccessor).append(");\n") + .append(indent).append(INDENT) + .append("}\n") + .append(indent).append("}\n"); + } + + private void generateSingleValueProperty( + final ClassBuilder classBuilder, + final String decoderClassName, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + final String typeName = javaTypeName(typeToken.encoding().primitiveType()); + final String formattedPropertyName = formatPropertyName(propertyName); + final String fieldName = formatFieldName(propertyName); + final String validateMethod = "validate" + toUpperFirstChar(propertyName); + + final boolean representedWithinJavaType = typeToken.encoding().primitiveType() != PrimitiveType.UINT64; + + final StringBuilder validationCall = new StringBuilder(); + + if (representedWithinJavaType) + { + final StringBuilder validateBuilder = classBuilder.appendPrivate().append("\n") + .append(indent).append("private static void ").append(validateMethod).append("(") + .append(typeName).append(" value)\n") + .append(indent).append("{\n"); + + validateBuilder.append(indent).append(INDENT) + .append("if (value < ") + .append(decoderClassName).append(".").append(formattedPropertyName).append("MinValue() || ") + .append("value").append(" > ") + .append(decoderClassName).append(".").append(formattedPropertyName).append("MaxValue())\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("throw new IllegalArgumentException(\"") + .append(propertyName) + .append(": value is out of allowed range: \" + ") + .append("value").append(");\n") + .append(indent).append(INDENT) + .append("}\n") + .append(indent).append("}\n"); + + validationCall.append(indent).append(INDENT).append(validateMethod).append("(value);\n"); + } + + classBuilder.appendField() + .append(indent).append("private ").append(typeName).append(" ").append(fieldName).append(";\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public ").append(typeName).append(" ") + .append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public void ").append(formattedPropertyName).append("(") + .append(typeName).append(" value)\n") + .append(indent).append("{\n") + .append(validationCall) + .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append("}\n"); + } + + private void generateConstPropertyMethods( + final ClassBuilder classBuilder, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent) + { + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public static String ").append(toLowerFirstChar(propertyName)).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT) + .append("return \"").append(typeToken.encoding().constValue().toString()).append("\";\n") + .append(indent).append("}\n"); + } + else + { + final CharSequence literalValue = + generateLiteral(typeToken.encoding().primitiveType(), typeToken.encoding().constValue().toString()); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public static ") + .append(javaTypeName(typeToken.encoding().primitiveType())) + .append(" ").append(formatPropertyName(propertyName)).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(literalValue).append(";\n") + .append(indent).append("}\n"); + } + } + + private void generateVarData( + final ClassBuilder classBuilder, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token token = tokens.get(i); + if (token.signal() == Signal.BEGIN_VAR_DATA) + { + final String propertyName = token.name(); + final Token varDataToken = Generators.findFirst("varData", tokens, i); + final String characterEncoding = varDataToken.encoding().characterEncoding(); + final String dtoType = characterEncoding == null ? "byte[]" : "String"; + + final String fieldName = formatFieldName(propertyName); + final String formattedPropertyName = formatPropertyName(propertyName); + + classBuilder.appendField() + .append(indent).append("private ").append(dtoType).append(" ").append(fieldName).append(";\n"); + + classBuilder.appendPublic().append("\n") + .append(indent).append("public ").append(dtoType).append(" ") + .append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic().append("\n") + .append(indent).append("public void ").append(formattedPropertyName) + .append("(").append(dtoType).append(" value)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append("}\n"); + } + } + } + + private static String formatDtoClassName(final String name) + { + return formatClassName(name + "Dto"); + } + + private void generateDtosForTypes() throws IOException + { + for (final List tokens : ir.types()) + { + switch (tokens.get(0).signal()) + { + case BEGIN_COMPOSITE: + generateComposite(tokens); + break; + + case BEGIN_SET: + generateChoiceSet(tokens); + break; + + default: + break; + } + } + } + + private void generateComposite(final List tokens) throws IOException + { + final String name = tokens.get(0).applicableTypeName(); + final String className = formatDtoClassName(name); + final String encoderClassName = encoderName(name); + final String decoderClassName = decoderName(name); + + try (Writer out = outputManager.createOutput(className)) + { + final List compositeTokens = tokens.subList(1, tokens.size() - 1); + out.append(generateDtoFileHeader(ir.applicableNamespace())); + out.append("import org.agrona.DirectBuffer;\n"); + out.append("import org.agrona.MutableDirectBuffer;\n"); + out.append("import org.agrona.concurrent.UnsafeBuffer;\n\n"); + out.append(generateDocumentation(BASE_INDENT, tokens.get(0))); + + final ClassBuilder classBuilder = new ClassBuilder(className, BASE_INDENT, "public final"); + + generateCompositePropertyElements(classBuilder, decoderClassName, compositeTokens, + BASE_INDENT + INDENT); + generateCompositeDecodeWith(classBuilder, className, decoderClassName, compositeTokens, + BASE_INDENT + INDENT); + generateCompositeEncodeWith(classBuilder, className, encoderClassName, compositeTokens, + BASE_INDENT + INDENT); + generateDisplay(classBuilder, encoderClassName, encoderClassName + ".ENCODED_LENGTH", + BASE_INDENT + INDENT); + + classBuilder.appendTo(out); + } + } + + private void generateChoiceSet(final List tokens) throws IOException + { + final String name = tokens.get(0).applicableTypeName(); + final String className = formatDtoClassName(name); + final String encoderClassName = encoderName(name); + final String decoderClassName = decoderName(name); + + try (Writer out = outputManager.createOutput(className)) + { + final List setTokens = tokens.subList(1, tokens.size() - 1); + out.append(generateDtoFileHeader(ir.applicableNamespace())); + out.append(generateDocumentation(BASE_INDENT, tokens.get(0))); + + final ClassBuilder classBuilder = new ClassBuilder(className, BASE_INDENT, "public final"); + + generateChoices(classBuilder, className, setTokens, BASE_INDENT + INDENT); + generateChoiceSetDecodeWith(classBuilder, className, decoderClassName, setTokens, BASE_INDENT + INDENT); + generateChoiceSetEncodeWith(classBuilder, className, encoderClassName, setTokens, BASE_INDENT + INDENT); + + classBuilder.appendTo(out); + } + } + + private void generateChoiceSetEncodeWith( + final ClassBuilder classBuilder, + final String dtoClassName, + final String encoderClassName, + final List setTokens, + final String indent) + { + final StringBuilder encodeBuilder = classBuilder.appendPublic() + .append("\n") + .append(indent).append("public static void encodeWith(\n") + .append(indent).append(INDENT).append(encoderClassName).append(" encoder, ") + .append(dtoClassName).append(" dto)\n") + .append(indent).append("{\n"); + + encodeBuilder.append(indent).append(INDENT).append("encoder.clear();\n"); + + for (final Token token : setTokens) + { + if (token.signal() == Signal.CHOICE) + { + final String formattedPropertyName = formatPropertyName(token.name()); + encodeBuilder.append(indent).append(INDENT).append("encoder.").append(formattedPropertyName) + .append("(dto.").append(formattedPropertyName).append("());\n"); + } + } + + encodeBuilder.append(indent).append("}\n"); + } + + private void generateChoiceSetDecodeWith( + final ClassBuilder classBuilder, + final String dtoClassName, + final String decoderClassName, + final List setTokens, + final String indent) + { + final StringBuilder decodeBuilder = classBuilder.appendPublic() + .append("\n") + .append(indent).append("public static void decodeWith(\n") + .append(indent).append(INDENT).append(decoderClassName).append(" decoder, ") + .append(dtoClassName).append(" dto)\n") + .append(indent).append("{\n"); + + for (final Token token : setTokens) + { + if (token.signal() == Signal.CHOICE) + { + final String formattedPropertyName = formatPropertyName(token.name()); + decodeBuilder.append(indent).append(INDENT).append("dto.").append(formattedPropertyName) + .append("(decoder.").append(formattedPropertyName).append("());\n"); + } + } + + decodeBuilder.append(indent).append("}\n"); + } + + private void generateChoices( + final ClassBuilder classBuilder, + final String dtoClassName, + final List setTokens, + final String indent) + { + final List fields = new ArrayList<>(); + + for (final Token token : setTokens) + { + if (token.signal() == Signal.CHOICE) + { + final String fieldName = formatFieldName(token.name()); + final String formattedPropertyName = formatPropertyName(token.name()); + + fields.add(fieldName); + + classBuilder.appendField() + .append(indent).append("boolean ").append(fieldName).append(";\n"); + + classBuilder.appendPublic() + .append("\n") + .append(indent).append("public boolean ").append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + classBuilder.appendPublic() + .append("\n") + .append(indent).append(dtoClassName).append(" ") + .append(formattedPropertyName).append("(boolean value)\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append(INDENT).append("return this;\n") + .append(indent).append("}\n"); + } + } + + final StringBuilder clearBuilder = classBuilder.appendPublic() + .append(indent).append(dtoClassName).append(" clear()\n") + .append(indent).append("{\n"); + + for (final String field : fields) + { + clearBuilder.append(indent).append(INDENT).append(field).append(" = false;\n"); + } + + clearBuilder.append(indent).append(INDENT).append("return this;\n") + .append(indent).append("}\n"); + } + + private void generateCompositePropertyElements( + final ClassBuilder classBuilder, + final String decoderClassName, + final List tokens, + final String indent) + { + for (int i = 0; i < tokens.size(); ) + { + final Token token = tokens.get(i); + final String propertyName = formatPropertyName(token.name()); + + switch (token.signal()) + { + case ENCODING: + generatePrimitiveProperty(classBuilder, decoderClassName, propertyName, token, token, indent); + break; + + case BEGIN_ENUM: + generateEnumProperty(classBuilder, propertyName, token, token, indent); + break; + + case BEGIN_SET: + case BEGIN_COMPOSITE: + generateComplexProperty(classBuilder, propertyName, token, token, indent); + break; + + default: + break; + } + + i += tokens.get(i).componentTokenCount(); + } + } + + private static CharSequence generateDtoFileHeader(final String packageName) + { + final StringBuilder sb = new StringBuilder(); + + sb.append("/* Generated SBE (Simple Binary Encoding) message DTO */\n"); + sb.append("package ").append(packageName).append(";\n\n"); + + return sb; + } + + private static String generateDocumentation(final String indent, final Token token) + { + final String description = token.description(); + if (null == description || description.isEmpty()) + { + return ""; + } + + return + indent + "/**\n" + + indent + " * " + description + "\n" + + indent + " */\n"; + } + + private static String formatFieldName(final String propertyName) + { + return formatPropertyName(propertyName); + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java new file mode 100644 index 0000000000..45eeccff93 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * Copyright (C) 2017 MarketFactory, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import uk.co.real_logic.sbe.generation.CodeGenerator; +import uk.co.real_logic.sbe.generation.TargetCodeGenerator; +import uk.co.real_logic.sbe.ir.Ir; + +/** + * {@link CodeGenerator} factory for Java DTOs. + */ +public class JavaDtos implements TargetCodeGenerator +{ + /** + * {@inheritDoc} + */ + public CodeGenerator newInstance(final Ir ir, final String outputDir) + { + return new JavaDtoGenerator(ir, new JavaOutputManager(outputDir, ir.applicableNamespace())); + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 1a5e17bb20..01cd0cf121 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -303,7 +303,7 @@ private void generateEncoder( if (shouldGenerateGroupOrderAnnotation) { - generateAnnotations(BASE_INDENT, className, groups, out, this::encoderName); + generateAnnotations(BASE_INDENT, className, groups, out, JavaUtil::encoderName); } out.append(generateDeclaration(className, implementsString, msgToken)); @@ -816,7 +816,7 @@ private void generateDecoder( if (shouldGenerateGroupOrderAnnotation) { - generateAnnotations(BASE_INDENT, className, groups, out, this::decoderName); + generateAnnotations(BASE_INDENT, className, groups, out, JavaUtil::decoderName); } out.append(generateDeclaration(className, implementsString, msgToken)); @@ -872,7 +872,7 @@ private void generateDecoderGroups( if (shouldGenerateGroupOrderAnnotation) { - generateAnnotations(indent + INDENT, groupName, groups, sb, this::decoderName); + generateAnnotations(indent + INDENT, groupName, groups, sb, JavaUtil::decoderName); } generateGroupDecoderClassHeader(sb, groupName, outerClassName, fieldPrecedenceModel, groupToken, tokens, groups, index, indent + INDENT); @@ -926,7 +926,7 @@ private void generateEncoderGroups( if (shouldGenerateGroupOrderAnnotation) { - generateAnnotations(indent + INDENT, groupClassName, groups, sb, this::encoderName); + generateAnnotations(indent + INDENT, groupClassName, groups, sb, JavaUtil::encoderName); } generateGroupEncoderClassHeader( sb, groupName, outerClassName, fieldPrecedenceModel, groupToken, @@ -4701,16 +4701,6 @@ private static String validateBufferImplementation( } } - private String encoderName(final String className) - { - return formatClassName(className) + "Encoder"; - } - - private String decoderName(final String className) - { - return formatClassName(className) + "Decoder"; - } - private String implementsInterface(final String interfaceName) { return shouldGenerateInterfaces ? " implements " + interfaceName : ""; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 5bdc6e38b0..2431542d30 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -464,6 +464,16 @@ public static void generateGroupEncodePropertyJavadoc( .append(indent).append(" */"); } + static String encoderName(final String className) + { + return formatClassName(className) + "Encoder"; + } + + static String decoderName(final String className) + { + return formatClassName(className) + "Decoder"; + } + private static void escapeJavadoc(final Appendable out, final String doc) throws IOException { for (int i = 0, length = doc.length(); i < length; i++) @@ -511,4 +521,5 @@ private static void escapeJavadoc(final StringBuilder sb, final String doc) } } } + } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java new file mode 100644 index 0000000000..a28b0ac374 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java @@ -0,0 +1,154 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.generation.java; + +import extension.*; +import org.agrona.ExpandableArrayBuffer; +import org.agrona.MutableDirectBuffer; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +public class DtoTest +{ + @Test + void shouldRoundTripCar1() + { + final ExpandableArrayBuffer inputBuffer = new ExpandableArrayBuffer(); + encodeCar(inputBuffer, 0); + + final CarDecoder decoder = new CarDecoder(); + decoder.wrap(inputBuffer, 0, CarDecoder.BLOCK_LENGTH, CarDecoder.SCHEMA_VERSION); + final String decoderString = decoder.toString(); + + final CarDto dto = new CarDto(); + CarDto.decodeWith(decoder, dto); + + final ExpandableArrayBuffer outputBuffer = new ExpandableArrayBuffer(); + final CarEncoder encoder = new CarEncoder(); + encoder.wrap(outputBuffer, 0); + CarDto.encodeWith(encoder, dto); + + final String dtoString = dto.toString(); + + assertThat(outputBuffer.byteArray(), equalTo(inputBuffer.byteArray())); + assertThat(dtoString, equalTo(decoderString)); + } + + @Test + void shouldRoundTripCar2() + { + final ExpandableArrayBuffer inputBuffer = new ExpandableArrayBuffer(); + final int inputLength = encodeCar(inputBuffer, 0); + + final CarDto dto = + CarDto.decodeFrom(inputBuffer, 0, (short)CarDecoder.BLOCK_LENGTH, (short)CarDecoder.SCHEMA_VERSION); + + final ExpandableArrayBuffer outputBuffer = new ExpandableArrayBuffer(); + final int outputLength = CarDto.encodeWith(dto, outputBuffer, 0); + + assertThat(outputLength, equalTo(inputLength)); + assertThat(outputBuffer.byteArray(), equalTo(inputBuffer.byteArray())); + } + + private static int encodeCar(final MutableDirectBuffer buffer, final int offset) + { + final CarEncoder car = new CarEncoder(); + car.wrap(buffer, offset); + car.serialNumber(1234); + car.modelYear(2013); + car.available(BooleanType.T); + car.code(Model.A); + car.vehicleCode("ABCDEF"); + + for (int i = 0, size = CarEncoder.someNumbersLength(); i < size; i++) + { + car.someNumbers(i, i); + } + + car.extras().cruiseControl(true).sportsPack(true); + + car.cupHolderCount((short)119); + + car.engine().capacity(2000) + .numCylinders((short)4) + .manufacturerCode("ABC") + .efficiency((byte)35) + .boosterEnabled(BooleanType.T) + .booster().boostType(BoostType.NITROUS) + .horsePower((short)200); + + final CarEncoder.FuelFiguresEncoder fuelFigures = car.fuelFiguresCount(3); + fuelFigures.next() + .speed(30) + .mpg(35.9f) + .usageDescription("this is a description"); + + fuelFigures.next() + .speed(55) + .mpg(49.0f) + .usageDescription("this is a description"); + + fuelFigures.next() + .speed(75) + .mpg(40.0f) + .usageDescription("this is a description"); + + final CarEncoder.PerformanceFiguresEncoder perfFigures = car.performanceFiguresCount(2); + + perfFigures.next() + .octaneRating((short)95); + + CarEncoder.PerformanceFiguresEncoder.AccelerationEncoder acceleration = perfFigures.accelerationCount(3); + + acceleration.next() + .mph(30) + .seconds(4.0f); + + acceleration.next() + .mph(60) + .seconds(7.5f); + + acceleration.next() + .mph(100) + .seconds(12.2f); + + perfFigures.next() + .octaneRating((short)99); + + acceleration = perfFigures.accelerationCount(3); + + acceleration.next() + .mph(30) + .seconds(3.8f); + + acceleration.next() + .mph(60) + .seconds(7.1f); + + acceleration.next() + .mph(100) + .seconds(11.8f); + + car.manufacturer("Ford"); + car.model("Fiesta"); + car.activationCode("1234"); + + return car.limit(); + } +} diff --git a/sbe-tool/src/test/resources/example-extension-schema.xml b/sbe-tool/src/test/resources/example-extension-schema.xml new file mode 100644 index 0000000000..3770489b9f --- /dev/null +++ b/sbe-tool/src/test/resources/example-extension-schema.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + T + S + N + K + + + + + + + 9000 + + Petrol + + + + + + 0 + 1 + + + A + B + C + + + 0 + 1 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 41f4b0e27932ef5dfca502b52fe24ff5e86f4f08 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Tue, 14 May 2024 11:57:24 +0100 Subject: [PATCH 1164/1594] [Java] Extend property-based tests to exercise Java DTOs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The added test (non-exhaustively) checks the property: ``` ∀ msg ∈ MessageSchemas, ∀ encoding ∈ EncodingsOf(msg), encoding = dtoEncode(dtoDecode(encoding)) ``` The added test shows some compilation failures, which need to be resolved before enabling it. --- .../sbe/generation/java/JavaGenerator.java | 1 + .../sbe/properties/DtosPropertyTest.java | 112 +++++++++- .../utils/InMemoryOutputManager.java | 207 ++++++++++++++++++ 3 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 01cd0cf121..2d939309b9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -160,6 +160,7 @@ public JavaGenerator( { Verify.notNull(ir, "ir"); Verify.notNull(outputManager, "outputManager"); + Verify.notNull(precedenceChecks, "precedenceChecks"); this.ir = ir; this.shouldSupportTypesPackageNames = shouldSupportTypesPackageNames; diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java index f71e416309..fed7d4c94d 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java @@ -13,28 +13,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties; import net.jqwik.api.*; +import uk.co.real_logic.sbe.generation.common.PrecedenceChecks; import uk.co.real_logic.sbe.generation.cpp.CppDtoGenerator; import uk.co.real_logic.sbe.generation.cpp.CppGenerator; import uk.co.real_logic.sbe.generation.cpp.NamespaceOutputManager; import uk.co.real_logic.sbe.generation.csharp.CSharpDtoGenerator; import uk.co.real_logic.sbe.generation.csharp.CSharpGenerator; import uk.co.real_logic.sbe.generation.csharp.CSharpNamespaceOutputManager; +import uk.co.real_logic.sbe.generation.java.JavaDtoGenerator; +import uk.co.real_logic.sbe.generation.java.JavaGenerator; +import uk.co.real_logic.sbe.ir.generated.MessageHeaderDecoder; import uk.co.real_logic.sbe.properties.arbitraries.SbeArbitraries; +import uk.co.real_logic.sbe.properties.utils.InMemoryOutputManager; +import org.agrona.DirectBuffer; +import org.agrona.ExpandableArrayBuffer; import org.agrona.IoUtil; +import org.agrona.MutableDirectBuffer; +import org.agrona.concurrent.UnsafeBuffer; import org.agrona.io.DirectBufferInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URLClassLoader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; +import static uk.co.real_logic.sbe.SbeTool.JAVA_DEFAULT_DECODING_BUFFER_TYPE; +import static uk.co.real_logic.sbe.SbeTool.JAVA_DEFAULT_ENCODING_BUFFER_TYPE; + @SuppressWarnings("ReadWriteStringCanBeUsed") public class DtosPropertyTest { @@ -44,6 +58,101 @@ public class DtosPropertyTest private static final String CPP_EXECUTABLE = System.getProperty("sbe.tests.cpp.executable", "g++"); private static final boolean KEEP_DIR_ON_FAILURE = Boolean.parseBoolean( System.getProperty("sbe.tests.keep.dir.on.failure", "true")); + private final ExpandableArrayBuffer outputBuffer = new ExpandableArrayBuffer(); + +// @Test +// void oneRun() throws IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, +// IllegalAccessException +// { +// javaDtoEncodeShouldBeTheInverseOfDtoDecode(encodedMessage().sample()); +// } + + @Property + @Disabled + void javaDtoEncodeShouldBeTheInverseOfDtoDecode( + @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage + ) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, + IllegalAccessException + { + final String packageName = encodedMessage.ir().applicableNamespace(); + final InMemoryOutputManager outputManager = new InMemoryOutputManager(packageName); + + boolean success = false; + + try + { + try + { + new JavaGenerator( + encodedMessage.ir(), + JAVA_DEFAULT_ENCODING_BUFFER_TYPE, + JAVA_DEFAULT_DECODING_BUFFER_TYPE, + false, + false, + false, + false, + PrecedenceChecks.newInstance(new PrecedenceChecks.Context()), + outputManager) + .generate(); + + new JavaDtoGenerator(encodedMessage.ir(), outputManager) + .generate(); + } + catch (final Exception generationException) + { + throw new AssertionError( + "Code generation failed.\n\n" + + "SCHEMA:\n" + encodedMessage.schema(), + generationException); + } + + try (URLClassLoader generatedClassLoader = outputManager.compileGeneratedSources()) + { + final Class dtoClass = + generatedClassLoader.loadClass(packageName + ".TestMessageDto"); + + final Method decodeFrom = + dtoClass.getMethod("decodeFrom", DirectBuffer.class, int.class, short.class, short.class); + + final Method encodeWith = + dtoClass.getMethod("encodeWithHeaderWith", dtoClass, MutableDirectBuffer.class, int.class); + + final int inputLength = encodedMessage.length(); + final ExpandableArrayBuffer inputBuffer = encodedMessage.buffer(); + final MessageHeaderDecoder header = new MessageHeaderDecoder().wrap(inputBuffer, 0); + final short blockLength = (short)header.blockLength(); + final short actingVersion = (short)header.version(); + final Object dto = decodeFrom.invoke(null, + encodedMessage.buffer(), MessageHeaderDecoder.ENCODED_LENGTH, blockLength, actingVersion); + outputBuffer.setMemory(0, outputBuffer.capacity(), (byte)0); + final int outputLength = (int)encodeWith.invoke(null, dto, outputBuffer, 0); + if (!areEqual(inputBuffer, inputLength, outputBuffer, outputLength)) + { + throw new AssertionError( + "Input and output differ\n\n" + + "SCHEMA:\n" + encodedMessage.schema()); + } + + success = true; + } + } + finally + { + if (!success) + { + outputManager.dumpSources(); + } + } + } + + private boolean areEqual( + final ExpandableArrayBuffer inputBuffer, + final int inputLength, + final ExpandableArrayBuffer outputBuffer, + final int outputLength) + { + return new UnsafeBuffer(inputBuffer, 0, inputLength).equals(new UnsafeBuffer(outputBuffer, 0, outputLength)); + } @Property void csharpDtoEncodeShouldBeTheInverseOfDtoDecode( @@ -274,4 +383,5 @@ private static void copyResourceToFile( throw new RuntimeException(e); } } + } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java new file mode 100644 index 0000000000..a34669593e --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java @@ -0,0 +1,207 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties.utils; + +import org.agrona.generation.DynamicPackageOutputManager; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.*; +import javax.tools.*; + +/** + * An implementation of {@link DynamicPackageOutputManager} that stores generated source code in memory and compiles it + * on demand. + */ +public class InMemoryOutputManager implements DynamicPackageOutputManager +{ + private final String packageName; + private final Map sourceFiles = new HashMap<>(); + private String packageNameOverride; + + public InMemoryOutputManager(final String packageName) + { + this.packageName = packageName; + } + + @Override + public Writer createOutput(final String name) + { + return new InMemoryWriter(name); + } + + @Override + public void setPackageName(final String packageName) + { + packageNameOverride = packageName; + } + + /** + * Compile the generated sources and return a {@link URLClassLoader} that can be used to load the generated classes. + * + * @return a {@link URLClassLoader} that can be used to load the generated classes + */ + public URLClassLoader compileGeneratedSources() + { + final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + final StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null); + final InMemoryFileManager fileManager = new InMemoryFileManager(standardFileManager); + final JavaCompiler.CompilationTask task = compiler.getTask( + null, + fileManager, + null, + null, + null, + sourceFiles.values() + ); + + if (!task.call()) + { + throw new IllegalStateException("Compilation failed"); + } + + final GeneratedCodeLoader classLoader = new GeneratedCodeLoader(getClass().getClassLoader()); + classLoader.defineClasses(fileManager); + return classLoader; + } + + public void dumpSources() + { + sourceFiles.forEach((qualifiedName, file) -> + { + System.out.println( + System.lineSeparator() + "Source file: " + qualifiedName + + System.lineSeparator() + file.sourceCode + + System.lineSeparator()); + }); + } + + class InMemoryWriter extends StringWriter + { + private final String name; + + InMemoryWriter(final String name) + { + this.name = name; + } + + @Override + public void close() throws IOException + { + super.close(); + final String actingPackageName = packageNameOverride == null ? packageName : packageNameOverride; + packageNameOverride = null; + + final String qualifiedName = actingPackageName + "." + name; + final InMemoryJavaFileObject sourceFile = + new InMemoryJavaFileObject(qualifiedName, getBuffer().toString()); + + final InMemoryJavaFileObject existingFile = sourceFiles.putIfAbsent(qualifiedName, sourceFile); + + if (existingFile != null && !Objects.equals(existingFile.sourceCode, sourceFile.sourceCode)) + { + throw new IllegalStateException("Duplicate (but different) class: " + qualifiedName); + } + } + } + + static class InMemoryFileManager extends ForwardingJavaFileManager + { + private final List outputFiles = new ArrayList<>(); + + InMemoryFileManager(final StandardJavaFileManager fileManager) + { + super(fileManager); + } + + @Override + public JavaFileObject getJavaFileForOutput( + final Location location, + final String className, + final JavaFileObject.Kind kind, + final FileObject sibling) + { + final InMemoryJavaFileObject outputFile = new InMemoryJavaFileObject(className, kind); + outputFiles.add(outputFile); + return outputFile; + } + + public Collection outputFiles() + { + return outputFiles; + } + } + + static class InMemoryJavaFileObject extends SimpleJavaFileObject + { + private final String sourceCode; + private final ByteArrayOutputStream outputStream; + + InMemoryJavaFileObject(final String className, final String sourceCode) + { + super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); + this.sourceCode = sourceCode; + this.outputStream = new ByteArrayOutputStream(); + } + + InMemoryJavaFileObject(final String className, final Kind kind) + { + super(URI.create("mem:///" + className.replace('.', '/') + kind.extension), kind); + this.sourceCode = null; + this.outputStream = new ByteArrayOutputStream(); + } + + @Override + public CharSequence getCharContent(final boolean ignoreEncodingErrors) + { + return sourceCode; + } + + @Override + public ByteArrayOutputStream openOutputStream() + { + return outputStream; + } + + public byte[] getClassBytes() + { + return outputStream.toByteArray(); + } + } + + static class GeneratedCodeLoader extends URLClassLoader + { + GeneratedCodeLoader(final ClassLoader parent) + { + super(new URL[0], parent); + } + + void defineClasses(final InMemoryFileManager fileManager) + { + fileManager.outputFiles().forEach(file -> + { + final byte[] classBytes = file.getClassBytes(); + super.defineClass(file.getName(), classBytes, 0, classBytes.length); + }); + } + } +} From 75df4629c72ea06c1fd73d420709fa3868183f44 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 15 May 2024 11:45:10 +0100 Subject: [PATCH 1165/1594] [Java] Avoid checking parentMessage.actingVersion inside composite. Most not present conditions were already elided via `generateFieldNotPresentCondition(inComposite=true, ...)` but the condition within the wrap method was not. Here's an example of a failing schema found with the DTO property-based tests: ``` ``` And generated code (within a composite without a `parentMessage`): ``` public void wrapMember0OfType0(final DirectBuffer wrapBuffer) { if (parentMessage.actingVersion < 1) { wrapBuffer.wrap(buffer, offset, 0); return; } wrapBuffer.wrap(buffer, offset + 0, 2); } ``` --- .../real_logic/sbe/generation/java/JavaGenerator.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 2d939309b9..0a47fbfe56 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1665,7 +1665,7 @@ private void generateVarDataWrapDecoder( indent + " }\n", propertyName, readOnlyBuffer, - generateWrapFieldNotPresentCondition(token.version(), indent), + generateWrapFieldNotPresentCondition(false, token.version(), indent), accessOrderListenerCall, sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", @@ -2671,9 +2671,12 @@ private CharSequence generatePrimitivePropertyEncode( generatePut(encoding.primitiveType(), "offset + " + offset, "value", byteOrderStr)); } - private CharSequence generateWrapFieldNotPresentCondition(final int sinceVersion, final String indent) + private CharSequence generateWrapFieldNotPresentCondition( + final boolean inComposite, + final int sinceVersion, + final String indent) { - if (0 == sinceVersion) + if (inComposite || 0 == sinceVersion) { return ""; } @@ -2925,7 +2928,7 @@ else if (encoding.primitiveType() == PrimitiveType.UINT8) indent + " }\n", Generators.toUpperFirstChar(propertyName), readOnlyBuffer, - generateWrapFieldNotPresentCondition(propertyToken.version(), indent), + generateWrapFieldNotPresentCondition(inComposite, propertyToken.version(), indent), accessOrderListenerCall, offset, fieldLength); From 60bd11986c5b6186c5a9e6c5bb122ec2676b424c Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 15 May 2024 11:54:55 +0100 Subject: [PATCH 1166/1594] [Java] Fix remaining DTO issues uncovered with PBT. The main issue was around determining when a field might not be present. We were checking `token.version() > 0`, which isn't accurate in composites or groups. In this commit, I've also started to use the `Footnotes` API in JQWIK, which allows useful debug information to be captured _only_ for failing attempts. It then prints out the shrunken footnotes upon a failure. --- .../sbe/generation/java/JavaDtoGenerator.java | 131 ++++++++------ .../sbe/generation/java/JavaGenerator.java | 4 + .../sbe/properties/DtosPropertyTest.java | 161 ++++++++++-------- .../utils/InMemoryOutputManager.java | 14 +- .../resources/example-extension-schema.xml | 4 +- 5 files changed, 184 insertions(+), 130 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java index b5fd05e665..0056ba4703 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -30,6 +30,7 @@ import java.io.Writer; import java.util.ArrayList; import java.util.List; +import java.util.function.Predicate; import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; @@ -43,6 +44,7 @@ */ public class JavaDtoGenerator implements CodeGenerator { + private static final Predicate ALWAYS_FALSE_PREDICATE = ignored -> false; private static final String INDENT = " "; private static final String BASE_INDENT = ""; @@ -97,7 +99,7 @@ public void generate() throws IOException generateVarData(classBuilder, varData, BASE_INDENT + INDENT); generateDecodeWith(classBuilder, dtoClassName, decoderClassName, fields, - groups, varData, BASE_INDENT + INDENT); + groups, varData, BASE_INDENT + INDENT, fieldToken -> fieldToken.version() > msgToken.version()); generateDecodeFrom(classBuilder, dtoClassName, decoderClassName, BASE_INDENT + INDENT); generateEncodeWith(classBuilder, dtoClassName, encoderClassName, fields, groups, varData, BASE_INDENT + INDENT); @@ -196,6 +198,13 @@ private void generateGroups( final String groupClassName = formatDtoClassName(groupName); final String qualifiedDtoClassName = qualifiedParentDtoClassName + "." + groupClassName; + final Token dimToken = tokens.get(i + 1); + if (dimToken.signal() != Signal.BEGIN_COMPOSITE) + { + throw new IllegalStateException("groups must start with BEGIN_COMPOSITE: token=" + dimToken); + } + final int sinceVersion = dimToken.version(); + final String fieldName = formatFieldName(groupName); final String formattedPropertyName = formatPropertyName(groupName); @@ -226,10 +235,22 @@ private void generateGroups( i = collectVarData(tokens, i, varData); generateVarData(groupClassBuilder, varData, indent + INDENT); + final Predicate wasAddedAfterGroup = token -> + { + final boolean addedAfterParent = token.version() > sinceVersion; + + if (addedAfterParent && token.signal() == Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("Cannot extend var data inside a group."); + } + + return addedAfterParent; + }; + generateDecodeListWith( groupClassBuilder, groupClassName, qualifiedDecoderClassName, indent + INDENT); generateDecodeWith(groupClassBuilder, groupClassName, qualifiedDecoderClassName, - fields, groups, varData, indent + INDENT); + fields, groups, varData, indent + INDENT, wasAddedAfterGroup); generateEncodeWith( groupClassBuilder, groupClassName, qualifiedEncoderClassName, fields, groups, varData, indent + INDENT); generateComputeEncodedLength(groupClassBuilder, qualifiedDecoderClassName, @@ -324,8 +345,10 @@ private void generateComputeEncodedLength( .append(qualifiedDecoderClassName).append(".") .append(formatPropertyName(propertyName)).append("HeaderLength();\n"); + final String characterEncoding = varDataToken.encoding().characterEncoding(); + final String lengthAccessor = characterEncoding == null ? ".length" : ".length()"; lengthBuilder.append(indent).append(INDENT).append("encodedLength += ") - .append(fieldName).append(".length()"); + .append(fieldName).append(lengthAccessor); final int elementByteLength = varDataToken.encoding().primitiveType().size(); if (elementByteLength != 1) @@ -358,7 +381,7 @@ private void generateCompositeDecodeWith( final Token token = tokens.get(i); generateFieldDecodeWith( - decodeBuilder, token, token, decoderClassName, indent + INDENT); + decodeBuilder, token, token, decoderClassName, indent + INDENT, ALWAYS_FALSE_PREDICATE); i += tokens.get(i).componentTokenCount(); } @@ -426,16 +449,17 @@ private void generateDecodeWith( final List fields, final List groups, final List varData, - final String indent) + final String indent, + final Predicate wasAddedAfterParent) { final StringBuilder decodeBuilder = classBuilder.appendPublic().append("\n") .append(indent).append("public static void decodeWith(").append(decoderClassName).append(" decoder, ") .append(dtoClassName).append(" dto)\n") .append(indent).append("{\n"); - generateMessageFieldsDecodeWith(decodeBuilder, fields, decoderClassName, indent + INDENT); + generateMessageFieldsDecodeWith(decodeBuilder, fields, decoderClassName, indent + INDENT, wasAddedAfterParent); generateGroupsDecodeWith(decodeBuilder, groups, indent + INDENT); - generateVarDataDecodeWith(decodeBuilder, varData, indent + INDENT); + generateVarDataDecodeWith(decodeBuilder, decoderClassName, varData, indent + INDENT, wasAddedAfterParent); decodeBuilder.append(indent).append("}\n"); } @@ -466,7 +490,8 @@ private void generateMessageFieldsDecodeWith( final StringBuilder sb, final List tokens, final String decoderClassName, - final String indent) + final String indent, + final Predicate wasAddedAfterParent) { for (int i = 0, size = tokens.size(); i < size; i++) { @@ -475,7 +500,7 @@ private void generateMessageFieldsDecodeWith( { final Token encodingToken = tokens.get(i + 1); - generateFieldDecodeWith(sb, signalToken, encodingToken, decoderClassName, indent); + generateFieldDecodeWith(sb, signalToken, encodingToken, decoderClassName, indent, wasAddedAfterParent); } } } @@ -485,17 +510,18 @@ private void generateFieldDecodeWith( final Token fieldToken, final Token typeToken, final String decoderClassName, - final String indent) + final String indent, + final Predicate wasAddedAfterParent) { switch (typeToken.signal()) { case ENCODING: - generatePrimitiveDecodeWith(sb, fieldToken, typeToken, decoderClassName, indent); + generatePrimitiveDecodeWith(sb, fieldToken, typeToken, decoderClassName, indent, wasAddedAfterParent); break; case BEGIN_SET: final String bitSetName = formatDtoClassName(typeToken.applicableTypeName()); - generateBitSetDecodeWith(sb, fieldToken, bitSetName, indent); + generateBitSetDecodeWith(sb, decoderClassName, fieldToken, bitSetName, indent, wasAddedAfterParent); break; case BEGIN_ENUM: @@ -516,7 +542,8 @@ private void generatePrimitiveDecodeWith( final Token fieldToken, final Token typeToken, final String decoderClassName, - final String indent) + final String indent, + final Predicate wasAddedAfterParent) { if (typeToken.isConstantEncoding()) { @@ -543,12 +570,13 @@ private void generatePrimitiveDecodeWith( indent, "decoder.actingVersion() >= " + decoderClassName + "." + formattedPropertyName + "SinceVersion()", "decoder." + formattedPropertyName + "()", - decoderNullValue + decoderNullValue, + wasAddedAfterParent ); } else if (arrayLength > 1) { - generateArrayDecodeWith(sb, decoderClassName, fieldToken, typeToken, indent); + generateArrayDecodeWith(sb, decoderClassName, fieldToken, typeToken, indent, wasAddedAfterParent); } } @@ -557,7 +585,8 @@ private void generateArrayDecodeWith( final String decoderClassName, final Token fieldToken, final Token typeToken, - final String indent) + final String indent, + final Predicate wasAddedAfterParent) { if (fieldToken.isConstantEncoding()) { @@ -566,8 +595,9 @@ private void generateArrayDecodeWith( final String propertyName = fieldToken.name(); final String formattedPropertyName = formatPropertyName(propertyName); + final PrimitiveType primitiveType = typeToken.encoding().primitiveType(); - if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + if (primitiveType == PrimitiveType.CHAR) { generateRecordPropertyAssignment( sb, @@ -575,13 +605,14 @@ private void generateArrayDecodeWith( indent, "decoder.actingVersion() >= " + decoderClassName + "." + formattedPropertyName + "SinceVersion()", "decoder." + formattedPropertyName + "()", - "\"\"" + "\"\"", + wasAddedAfterParent ); } else { final StringBuilder initializerList = new StringBuilder(); - final String elementType = javaTypeName(typeToken.encoding().primitiveType()); + final String elementType = javaTypeName(primitiveType); initializerList.append("new ").append(elementType).append("[] { "); final int arrayLength = typeToken.arrayLength(); for (int i = 0; i < arrayLength; i++) @@ -598,16 +629,19 @@ private void generateArrayDecodeWith( indent, "decoder.actingVersion() >= " + decoderClassName + "." + formattedPropertyName + "SinceVersion()", initializerList, - null + "new " + elementType + "[0]", + wasAddedAfterParent ); } } private void generateBitSetDecodeWith( final StringBuilder sb, + final String decoderClassName, final Token fieldToken, final String dtoTypeName, - final String indent) + final String indent, + final Predicate wasAddedAfterParent) { if (fieldToken.isConstantEncoding()) { @@ -617,11 +651,11 @@ private void generateBitSetDecodeWith( final String propertyName = fieldToken.name(); final String formattedPropertyName = formatPropertyName(propertyName); - if (fieldToken.isOptionalEncoding()) + if (wasAddedAfterParent.test(fieldToken)) { - sb.append(indent).append("if (decoder.").append(formattedPropertyName).append("InActingVersion()"); - - sb.append(")\n") + sb.append(indent).append("if (decoder.actingVersion() >= ") + .append(decoderClassName).append(".") + .append(formattedPropertyName).append("SinceVersion())\n") .append(indent).append("{\n"); sb.append(indent).append(INDENT).append(dtoTypeName).append(".decodeWith(decoder.") @@ -710,8 +744,10 @@ private void generateGroupsDecodeWith( private void generateVarDataDecodeWith( final StringBuilder sb, + final String decoderClassName, final List tokens, - final String indent) + final String indent, + final Predicate wasAddedAfterParent) { for (int i = 0; i < tokens.size(); i++) { @@ -723,7 +759,7 @@ private void generateVarDataDecodeWith( final Token varDataToken = Generators.findFirst("varData", tokens, i); final String characterEncoding = varDataToken.encoding().characterEncoding(); - final boolean isOptional = token.version() > 0; + final boolean isOptional = wasAddedAfterParent.test(token); final String blockIndent = isOptional ? indent + INDENT : indent; final String dataVar = toLowerFirstChar(propertyName) + "Data"; @@ -734,7 +770,7 @@ private void generateVarDataDecodeWith( { decoderValueExtraction.append(blockIndent).append("byte[] ").append(dataVar) .append(" = new byte[decoder.").append(formattedPropertyName).append("Length()];\n") - .append(blockIndent).append("decoder.get").append(formattedPropertyName) + .append(blockIndent).append("decoder.get").append(toUpperFirstChar(formattedPropertyName)) .append("(").append(dataVar).append(", 0, decoder.").append(formattedPropertyName) .append("Length());\n"); } @@ -746,9 +782,9 @@ private void generateVarDataDecodeWith( if (isOptional) { - sb.append(indent).append("if (decoder.").append(formattedPropertyName).append("InActingVersion()"); - - sb.append(")\n") + sb.append(indent).append("if (decoder.actingVersion() >= ") + .append(decoderClassName).append(".") + .append(formattedPropertyName).append("SinceVersion())\n") .append(indent).append("{\n"); sb.append(decoderValueExtraction); @@ -756,7 +792,7 @@ private void generateVarDataDecodeWith( sb.append(indent).append(INDENT).append("dto.").append(formattedPropertyName).append("(") .append(dataVar).append(");\n"); - final String nullDtoValue = "\"\""; + final String nullDtoValue = characterEncoding == null ? "new byte[0]" : "\"\""; sb.append(indent).append("}\n") .append(indent).append("else\n") @@ -782,27 +818,25 @@ private void generateRecordPropertyAssignment( final String indent, final String presenceExpression, final CharSequence getExpression, - final String nullDecoderValueOrNull) + final String nullDecoderValue, + final Predicate wasAddedAfterParent) { final String propertyName = token.name(); final String formattedPropertyName = formatPropertyName(propertyName); - if (token.isOptionalEncoding()) + if (wasAddedAfterParent.test(token)) { - sb.append(indent).append("if (").append(presenceExpression).append(")\n") .append(indent).append("{\n"); sb.append(indent).append(INDENT).append("dto.").append(formattedPropertyName).append("(") .append(getExpression).append(");\n"); - final String nullValue = nullDecoderValueOrNull == null ? "null" : nullDecoderValueOrNull; - sb.append(indent).append("}\n") .append(indent).append("else\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("dto.").append(formattedPropertyName).append("(") - .append(nullValue).append(");\n") + .append(nullDecoderValue).append(");\n") .append(indent).append("}\n"); } else @@ -966,19 +1000,16 @@ private void generateArrayEncodeWith( final String propertyName = fieldToken.name(); final String formattedPropertyName = formatPropertyName(propertyName); - if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + final PrimitiveType primitiveType = typeToken.encoding().primitiveType(); + + if (primitiveType == PrimitiveType.CHAR) { sb.append(indent).append("encoder.").append(toLowerFirstChar(propertyName)).append("(") .append("dto.").append(formattedPropertyName).append("());\n"); } - else if (typeToken.encoding().primitiveType() == PrimitiveType.UINT8) - { - sb.append(indent).append("encoder.put").append(toUpperFirstChar(propertyName)).append("(") - .append("dto.").append(formattedPropertyName).append("());\n"); - } else { - final String javaTypeName = javaTypeName(typeToken.encoding().primitiveType()); + final String javaTypeName = javaTypeName(primitiveType); sb.append(indent).append(javaTypeName).append("[] ").append(formattedPropertyName).append(" = ") .append("dto.").append(formattedPropertyName).append("();\n") .append(indent).append("for (int i = 0; i < ").append(formattedPropertyName).append(".length; i++)\n") @@ -1103,7 +1134,9 @@ private void generateVarDataEncodeWith( if (characterEncoding == null) { sb.append(indent).append("encoder.put").append(toUpperFirstChar(propertyName)).append("(") - .append("dto.").append(formattedPropertyName).append("());\n"); + .append("dto.").append(formattedPropertyName).append("(),") + .append("0,") + .append("dto.").append(formattedPropertyName).append("().length);\n"); } else { @@ -1310,7 +1343,9 @@ private void generateArrayProperty( final String fieldName = formatFieldName(propertyName); final String validateMethod = "validate" + toUpperFirstChar(propertyName); - if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + final PrimitiveType primitiveType = typeToken.encoding().primitiveType(); + + if (primitiveType == PrimitiveType.CHAR) { final CharSequence typeName = "String"; @@ -1345,7 +1380,7 @@ private void generateArrayProperty( } else { - final String elementTypeName = javaTypeName(typeToken.encoding().primitiveType()); + final String elementTypeName = javaTypeName(primitiveType); final String typeName = elementTypeName + "[]"; classBuilder.appendField() diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 0a47fbfe56..7d0d4ba97b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1034,6 +1034,10 @@ private void generateGroupDecoderClassHeader( .append(indent).append(" {\n") .append(indent).append(" return blockLength;\n") .append(indent).append(" }\n\n") + .append(indent).append(" public int actingVersion()\n") + .append(indent).append(" {\n") + .append(indent).append(" return parentMessage.actingVersion;\n") + .append(indent).append(" }\n\n") .append(indent).append(" public int count()\n") .append(indent).append(" {\n") .append(indent).append(" return count;\n") diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java index fed7d4c94d..b21ba27674 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java @@ -16,6 +16,8 @@ package uk.co.real_logic.sbe.properties; import net.jqwik.api.*; +import net.jqwik.api.footnotes.EnableFootnotes; +import net.jqwik.api.footnotes.Footnotes; import uk.co.real_logic.sbe.generation.common.PrecedenceChecks; import uk.co.real_logic.sbe.generation.cpp.CppDtoGenerator; import uk.co.real_logic.sbe.generation.cpp.CppGenerator; @@ -28,10 +30,7 @@ import uk.co.real_logic.sbe.ir.generated.MessageHeaderDecoder; import uk.co.real_logic.sbe.properties.arbitraries.SbeArbitraries; import uk.co.real_logic.sbe.properties.utils.InMemoryOutputManager; -import org.agrona.DirectBuffer; -import org.agrona.ExpandableArrayBuffer; -import org.agrona.IoUtil; -import org.agrona.MutableDirectBuffer; +import org.agrona.*; import org.agrona.concurrent.UnsafeBuffer; import org.agrona.io.DirectBufferInputStream; @@ -45,40 +44,33 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; +import java.util.Base64; +import java.util.stream.Stream; +import static org.junit.jupiter.api.Assertions.fail; import static uk.co.real_logic.sbe.SbeTool.JAVA_DEFAULT_DECODING_BUFFER_TYPE; import static uk.co.real_logic.sbe.SbeTool.JAVA_DEFAULT_ENCODING_BUFFER_TYPE; @SuppressWarnings("ReadWriteStringCanBeUsed") +@EnableFootnotes public class DtosPropertyTest { private static final String DOTNET_EXECUTABLE = System.getProperty("sbe.tests.dotnet.executable", "dotnet"); private static final String SBE_DLL = System.getProperty("sbe.dll", "csharp/sbe-dll/bin/Release/netstandard2.0/SBE.dll"); private static final String CPP_EXECUTABLE = System.getProperty("sbe.tests.cpp.executable", "g++"); - private static final boolean KEEP_DIR_ON_FAILURE = Boolean.parseBoolean( - System.getProperty("sbe.tests.keep.dir.on.failure", "true")); private final ExpandableArrayBuffer outputBuffer = new ExpandableArrayBuffer(); -// @Test -// void oneRun() throws IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, -// IllegalAccessException -// { -// javaDtoEncodeShouldBeTheInverseOfDtoDecode(encodedMessage().sample()); -// } - @Property - @Disabled void javaDtoEncodeShouldBeTheInverseOfDtoDecode( - @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage + @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage, + final Footnotes footnotes ) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { final String packageName = encodedMessage.ir().applicableNamespace(); final InMemoryOutputManager outputManager = new InMemoryOutputManager(packageName); - boolean success = false; - try { try @@ -100,10 +92,7 @@ void javaDtoEncodeShouldBeTheInverseOfDtoDecode( } catch (final Exception generationException) { - throw new AssertionError( - "Code generation failed.\n\n" + - "SCHEMA:\n" + encodedMessage.schema(), - generationException); + fail("Code generation failed.", generationException); } try (URLClassLoader generatedClassLoader = outputManager.compileGeneratedSources()) @@ -128,39 +117,29 @@ void javaDtoEncodeShouldBeTheInverseOfDtoDecode( final int outputLength = (int)encodeWith.invoke(null, dto, outputBuffer, 0); if (!areEqual(inputBuffer, inputLength, outputBuffer, outputLength)) { - throw new AssertionError( - "Input and output differ\n\n" + - "SCHEMA:\n" + encodedMessage.schema()); + fail("Input and output differ"); } - - success = true; } } - finally + catch (final Throwable throwable) { - if (!success) - { - outputManager.dumpSources(); - } - } - } + addInputFootnotes(footnotes, encodedMessage); - private boolean areEqual( - final ExpandableArrayBuffer inputBuffer, - final int inputLength, - final ExpandableArrayBuffer outputBuffer, - final int outputLength) - { - return new UnsafeBuffer(inputBuffer, 0, inputLength).equals(new UnsafeBuffer(outputBuffer, 0, outputLength)); + final StringBuilder generatedSources = new StringBuilder(); + outputManager.dumpSources(generatedSources); + footnotes.addFootnote(generatedSources.toString()); + + throw throwable; + } } @Property void csharpDtoEncodeShouldBeTheInverseOfDtoDecode( - @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage + @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage, + final Footnotes footnotes ) throws IOException, InterruptedException { final Path tempDir = Files.createTempDirectory("sbe-csharp-dto-test"); - boolean success = false; try { @@ -205,34 +184,27 @@ void csharpDtoEncodeShouldBeTheInverseOfDtoDecode( "DIR:" + tempDir + "\n\n" + "SCHEMA:\n" + encodedMessage.schema()); } - success = true; } - finally + catch (final Throwable throwable) { - if (!KEEP_DIR_ON_FAILURE || success) - { - IoUtil.delete(tempDir.toFile(), true); - } - else - { - Files.write( - tempDir.resolve("schema.xml"), - encodedMessage.schema().getBytes(StandardCharsets.UTF_8)); + addInputFootnotes(footnotes, encodedMessage); + addGeneratedSourcesFootnotes(footnotes, tempDir, ".cs"); - Files.write( - tempDir.resolve("encoding.log"), - encodedMessage.encodingLog().getBytes(StandardCharsets.UTF_8)); - } + throw throwable; + } + finally + { + IoUtil.delete(tempDir.toFile(), true); } } @Property(shrinking = ShrinkingMode.OFF) void cppDtoEncodeShouldBeTheInverseOfDtoDecode( - @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage + @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage, + final Footnotes footnotes ) throws IOException, InterruptedException { final Path tempDir = Files.createTempDirectory("sbe-cpp-dto-test"); - boolean success = false; try { @@ -274,24 +246,17 @@ void cppDtoEncodeShouldBeTheInverseOfDtoDecode( "Input and output files differ\n\n" + "SCHEMA:\n" + encodedMessage.schema()); } - success = true; } - finally + catch (final Throwable throwable) { - if (!KEEP_DIR_ON_FAILURE || success) - { - IoUtil.delete(tempDir.toFile(), true); - } - else - { - Files.write( - tempDir.resolve("schema.xml"), - encodedMessage.schema().getBytes(StandardCharsets.UTF_8)); + addInputFootnotes(footnotes, encodedMessage); + addGeneratedSourcesFootnotes(footnotes, tempDir, ".cpp"); - Files.write( - tempDir.resolve("encoding.log"), - encodedMessage.encodingLog().getBytes(StandardCharsets.UTF_8)); - } + throw throwable; + } + finally + { + IoUtil.delete(tempDir.toFile(), true); } } @@ -384,4 +349,52 @@ private static void copyResourceToFile( } } + private boolean areEqual( + final ExpandableArrayBuffer inputBuffer, + final int inputLength, + final ExpandableArrayBuffer outputBuffer, + final int outputLength) + { + return new UnsafeBuffer(inputBuffer, 0, inputLength).equals(new UnsafeBuffer(outputBuffer, 0, outputLength)); + } + + private void addGeneratedSourcesFootnotes( + final Footnotes footnotes, + final Path directory, + final String suffix) + { + try (Stream contents = Files.walk(directory)) + { + contents + .filter(path -> path.toString().endsWith(suffix)) + .forEach(path -> + { + try + { + footnotes.addFootnote(System.lineSeparator() + "File: " + path + + System.lineSeparator() + + new String(Files.readAllBytes(path), StandardCharsets.UTF_8)); + } + catch (final IOException exn) + { + LangUtil.rethrowUnchecked(exn); + } + }); + } + catch (final IOException exn) + { + LangUtil.rethrowUnchecked(exn); + } + } + + public void addInputFootnotes(final Footnotes footnotes, final SbeArbitraries.EncodedMessage encodedMessage) + { + final byte[] messageBytes = new byte[encodedMessage.length()]; + encodedMessage.buffer().getBytes(0, messageBytes); + final byte[] base64EncodedMessageBytes = Base64.getEncoder().encode(messageBytes); + + footnotes.addFootnote("Schema:" + System.lineSeparator() + encodedMessage.schema()); + footnotes.addFootnote("Input Message:" + System.lineSeparator() + + new String(base64EncodedMessageBytes, StandardCharsets.UTF_8)); + } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java index a34669593e..a17f74914e 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java @@ -84,14 +84,16 @@ public URLClassLoader compileGeneratedSources() return classLoader; } - public void dumpSources() + public void dumpSources(final StringBuilder builder) { + builder.append(System.lineSeparator()).append("Generated sources file count: ").append(sourceFiles.size()) + .append(System.lineSeparator()); + sourceFiles.forEach((qualifiedName, file) -> { - System.out.println( - System.lineSeparator() + "Source file: " + qualifiedName + - System.lineSeparator() + file.sourceCode + - System.lineSeparator()); + builder.append(System.lineSeparator()).append("Source file: ").append(qualifiedName) + .append(System.lineSeparator()).append(file.sourceCode) + .append(System.lineSeparator()); }); } @@ -200,7 +202,7 @@ void defineClasses(final InMemoryFileManager fileManager) fileManager.outputFiles().forEach(file -> { final byte[] classBytes = file.getClassBytes(); - super.defineClass(file.getName(), classBytes, 0, classBytes.length); + super.defineClass(null, classBytes, 0, classBytes.length); }); } } diff --git a/sbe-tool/src/test/resources/example-extension-schema.xml b/sbe-tool/src/test/resources/example-extension-schema.xml index 3770489b9f..ab89ba12cc 100644 --- a/sbe-tool/src/test/resources/example-extension-schema.xml +++ b/sbe-tool/src/test/resources/example-extension-schema.xml @@ -2,7 +2,7 @@ @@ -86,7 +86,7 @@ - + From 6e0234b0c9dbd1d585407530c6b453a89fd72ea8 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 15 May 2024 12:02:41 +0100 Subject: [PATCH 1167/1594] [Java] Tidy up spacing. --- .../co/real_logic/sbe/generation/java/JavaDtoGenerator.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java index 0056ba4703..4b8ceb876d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -165,11 +165,8 @@ public void appendTo(final Appendable out) out.append(indent).append(modifiers).append("class ").append(className).append("\n") .append(indent).append("{\n") .append(fieldSb) - .append("\n") .append(privateSb) - .append("\n") .append(publicSb) - .append("\n") .append(indent).append("}\n"); } catch (final IOException exception) @@ -420,7 +417,7 @@ private void generateDecodeListWith( final String indent) { classBuilder.appendPublic().append("\n") - .append(indent).append("static List<").append(dtoClassName).append("> decodeManyWith(") + .append(indent).append("public static List<").append(dtoClassName).append("> decodeManyWith(") .append(decoderClassName).append(" decoder)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("List<").append(dtoClassName) From d93b3370221644866600f0364dcd555695c693a4 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Tue, 25 Jun 2024 17:47:48 +0100 Subject: [PATCH 1168/1594] [C++, C#] Avoid unnecessary validation code. Previously, regardless of whether the min and max values were the min and max values for the host language representation of an SBE type, we would generate a range check. Now, we do not generate the check unless it is meaningful. Also, adjust the property-based test dotnet version to bring inline with other tests. --- .../sbe/generation/cpp/CppDtoGenerator.java | 87 +++++++++++++++---- .../generation/csharp/CSharpDtoGenerator.java | 42 ++++++--- .../SbePropertyTest.csproj | 2 +- 3 files changed, 101 insertions(+), 30 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index 168f6df665..39b59412e5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -20,6 +20,7 @@ import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.generation.CodeGenerator; import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.ir.Encoding; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.ir.Signal; import uk.co.real_logic.sbe.ir.Token; @@ -1489,7 +1490,8 @@ private void generateSingleValueProperty( final Token typeToken, final String indent) { - final String elementTypeName = cppTypeName(typeToken.encoding().primitiveType()); + final Encoding encoding = typeToken.encoding(); + final String elementTypeName = cppTypeName(encoding.primitiveType()); final CharSequence typeName = typeWithFieldOptionality( fieldToken, elementTypeName @@ -1518,6 +1520,31 @@ private void generateSingleValueProperty( .append(indent).append(INDENT).append(fieldName).append(" = value;\n") .append(indent).append("}\n"); + generateSingleValuePropertyValidateMethod( + classBuilder, + codecClassName, + propertyName, + fieldToken, + indent, + validateMethod, + typeName, + formattedPropertyName, + elementTypeName, + encoding); + } + + private static void generateSingleValuePropertyValidateMethod( + final ClassBuilder classBuilder, + final String codecClassName, + final String propertyName, + final Token fieldToken, + final String indent, + final String validateMethod, + final CharSequence typeName, + final String formattedPropertyName, + final String elementTypeName, + final Encoding encoding) + { final StringBuilder validateBuilder = classBuilder.appendPrivate().append("\n") .append(indent).append("static void ").append(validateMethod).append("(") .append(typeName).append(" value)\n") @@ -1525,6 +1552,9 @@ private void generateSingleValueProperty( String value = "value"; + final boolean mustPreventLesser = !encoding.applicableMinValue().equals(encoding.primitiveType().minValue()); + final boolean mustPreventGreater = !encoding.applicableMaxValue().equals(encoding.primitiveType().maxValue()); + if (fieldToken.isOptionalEncoding()) { validateBuilder.append(indent).append(INDENT) @@ -1548,27 +1578,48 @@ private void generateSingleValueProperty( .append(indent).append(INDENT) .append("}\n"); + if (mustPreventLesser || mustPreventGreater) + { + validateBuilder.append(indent).append(INDENT) + .append(elementTypeName).append(" actualValue = value.value();\n"); + + value = "actualValue"; + } + } + + if (mustPreventLesser) + { validateBuilder.append(indent).append(INDENT) - .append(elementTypeName).append(" actualValue = value.value();\n"); + .append("if (").append(value).append(" < ") + .append(codecClassName).append("::").append(formattedPropertyName).append("MinValue())\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("throw std::invalid_argument(\"") + .append(propertyName) + .append(": value is less than allowed minimum: \" + std::to_string(") + .append(value).append("));\n") + .append(indent).append(INDENT) + .append("}\n"); + } - value = "actualValue"; + if (mustPreventGreater) + { + validateBuilder.append(indent).append(INDENT) + .append("if (").append(value).append(" > ") + .append(codecClassName).append("::").append(formattedPropertyName).append("MaxValue())\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("throw std::invalid_argument(\"") + .append(propertyName) + .append(": value is greater than allowed maximum: \" + std::to_string(") + .append(value).append("));\n") + .append(indent).append(INDENT) + .append("}\n"); } - validateBuilder.append(indent).append(INDENT) - .append("if (").append(value).append(" < ") - .append(codecClassName).append("::").append(formattedPropertyName).append("MinValue() || ") - .append(value).append(" > ") - .append(codecClassName).append("::").append(formattedPropertyName).append("MaxValue())\n") - .append(indent).append(INDENT) - .append("{\n") - .append(indent).append(INDENT).append(INDENT) - .append("throw std::invalid_argument(\"") - .append(propertyName) - .append(": value is out of allowed range: \" + std::to_string(") - .append(value).append("));\n") - .append(indent).append(INDENT) - .append("}\n") - .append(indent).append("}\n"); + validateBuilder.append(indent).append("}\n"); } private void generateConstPropertyMethods( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java index e023b8fd95..ad2e3068c7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -20,6 +20,7 @@ import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.generation.CodeGenerator; import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.ir.Encoding; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.ir.Signal; import uk.co.real_logic.sbe.ir.Token; @@ -1194,7 +1195,8 @@ private void generateSingleValueProperty( final String indent) { final String nullableSuffix = fieldToken.isOptionalEncoding() ? "?" : ""; - final String typeName = cSharpTypeName(typeToken.encoding().primitiveType()) + nullableSuffix; + final Encoding encoding = typeToken.encoding(); + final String typeName = cSharpTypeName(encoding.primitiveType()) + nullableSuffix; final String formattedPropertyName = formatPropertyName(propertyName); final String fieldName = "_" + toLowerFirstChar(propertyName); @@ -1242,17 +1244,35 @@ private void generateSingleValueProperty( .append("}\n"); } + final boolean mustPreventLesser = !encoding.applicableMinValue().equals(encoding.primitiveType().minValue()); + if (mustPreventLesser) + { + sb.append(indent).append(INDENT) + .append("if (value < ") + .append(codecClassName).append(".").append(formattedPropertyName).append("MinValue)\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("throw new ArgumentException(\"value is less than minimum allowed: \" + value);\n") + .append(indent).append(INDENT) + .append("}\n"); + } + + final boolean mustPreventGreater = !encoding.applicableMaxValue().equals(encoding.primitiveType().maxValue()); + if (mustPreventGreater) + { + sb.append(indent).append(INDENT) + .append("if (value > ") + .append(codecClassName).append(".").append(formattedPropertyName).append("MaxValue)\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("throw new ArgumentException(\"value is greater than maximum allowed: \" + value);\n") + .append(indent).append(INDENT) + .append("}\n"); + } + sb.append(indent).append(INDENT) - .append("if (value < ") - .append(codecClassName).append(".").append(formattedPropertyName).append("MinValue || value > ") - .append(codecClassName).append(".").append(formattedPropertyName).append("MaxValue)\n") - .append(indent).append(INDENT) - .append("{\n") - .append(indent).append(INDENT).append(INDENT) - .append("throw new ArgumentException(\"value is out of allowed range: \" + value);\n") - .append(indent).append(INDENT) - .append("}\n") - .append(indent).append(INDENT) .append("return value;\n") .append(indent).append("}\n"); } diff --git a/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj index 5da3f76095..ab700af657 100644 --- a/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj +++ b/sbe-tool/src/propertyTest/resources/CSharpDtosPropertyTest/SbePropertyTest.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 From ebd2fd296ee5c829c6825f69e61291705f07a455 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 3 Jul 2024 13:56:24 +0200 Subject: [PATCH 1169/1594] [Java] Upgrade to JUnit 5.10.3. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b661f8b406..8b09e720c3 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' -def junitVersion = '5.10.2' +def junitVersion = '5.10.3' def jqwikVersion = '1.8.1' def jsonVersion = '20230618' def jmhVersion = '1.37' From dbebeb0ca24bdb6aee0517638eee9ac83d3163a6 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 3 Jul 2024 13:57:07 +0200 Subject: [PATCH 1170/1594] [Java] Upgrade to json 20240303. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8b09e720c3..8f31bfba9c 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.10.3' def jqwikVersion = '1.8.1' -def jsonVersion = '20230618' +def jsonVersion = '20240303' def jmhVersion = '1.37' def agronaVersion = '1.21.2' def agronaVersionRange = '[1.21.2,2.0[' // allow any release >= 1.21.2 and < 2.0.0 From b0bfa08b5339c128c9699278c93f10c1fef19172 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 3 Jul 2024 13:57:49 +0200 Subject: [PATCH 1171/1594] [Java] Upgrade to jqwik 1.9.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8f31bfba9c..24898d4bce 100644 --- a/build.gradle +++ b/build.gradle @@ -58,7 +58,7 @@ def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' def mockitoVersion = '4.11.0' def junitVersion = '5.10.3' -def jqwikVersion = '1.8.1' +def jqwikVersion = '1.9.0' def jsonVersion = '20240303' def jmhVersion = '1.37' def agronaVersion = '1.21.2' From 02b0c7a01ec16fdcaf02d7d63578cb65f925cd4c Mon Sep 17 00:00:00 2001 From: James Watson Date: Mon, 8 Jul 2024 18:19:39 +0100 Subject: [PATCH 1172/1594] [Java] Switch JsonPrinter.print to use DirectBuffer instead of UnsafeBuffer. --- .../src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java index 5e58d4f0e7..3071afb6c9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java @@ -15,6 +15,7 @@ */ package uk.co.real_logic.sbe.json; +import org.agrona.DirectBuffer; import org.agrona.concurrent.UnsafeBuffer; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.ir.Token; @@ -62,7 +63,7 @@ public void print(final ByteBuffer encodedMessage, final StringBuilder output) * @param buffer with encoded message and header. * @param offset at which the header begins. */ - public void print(final StringBuilder output, final UnsafeBuffer buffer, final int offset) + public void print(final StringBuilder output, final DirectBuffer buffer, final int offset) { final int blockLength = headerDecoder.getBlockLength(buffer, offset); final int templateId = headerDecoder.getTemplateId(buffer, offset); From cf61f3a5cf4ee93cfc79bcc1fe2aaf877c803745 Mon Sep 17 00:00:00 2001 From: marc-adaptive Date: Wed, 17 Jul 2024 11:10:04 -0400 Subject: [PATCH 1173/1594] [Build] publish OSS artifacts through GitHub workflow --- .github/workflows/ci.yml | 3 +- .github/workflows/codeql.yml | 3 +- .github/workflows/release.yml | 62 +++++++++++++++++++++++++++++++++++ .github/workflows/slow.yml | 3 +- build.gradle | 17 ++++++++++ 5 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6bb6a9736..20b3fd4413 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,7 @@ name: Continuous Integration on: + workflow_call: workflow_dispatch: push: branches: @@ -11,7 +12,7 @@ on: - master concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ci-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 44a604749a..63bb4b11c8 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,6 +1,7 @@ name: "CodeQL" on: + workflow_call: push: branches: - master @@ -10,7 +11,7 @@ on: - master concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: codeql-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..5c5099f479 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,62 @@ +name: Release + +on: + workflow_dispatch: + push: + tags: + - '*.*.*' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +env: + GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail' + +jobs: + ci: + uses: ./.github/workflows/ci.yml + + codeql: + uses: ./.github/workflows/codeql.yml + + slow: + uses: ./.github/workflows/slow.yml + + release: + name: Release java artifacts + permissions: + contents: write + packages: write + needs: [ ci , codeql, slow ] + runs-on: ubuntu-latest + steps: + - name: checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + - name: Create Release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + draft: true + - name: Setup java + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 8 + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=8" >> $GITHUB_ENV + - name: Publish with Gradle + run: ./gradlew publish + env: + ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.ossrhUsername }} + ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.ossrhPassword }} + ORG_GRADLE_PROJECT_signingKey: ${{ secrets.signingKey }} + ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.signingPassword }} diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 9b790d276e..9b4b0c22b0 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -1,6 +1,7 @@ name: Slow checks on: + workflow_call: workflow_dispatch: branches: - '**' @@ -8,7 +9,7 @@ on: - cron: '0 12 * * *' concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: slow-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: diff --git a/build.gradle b/build.gradle index 24898d4bce..c0ce5ee4e9 100644 --- a/build.gradle +++ b/build.gradle @@ -79,6 +79,14 @@ ext { if (!project.hasProperty('ossrhPassword')) { ossrhPassword = '' } + + if (!project.hasProperty('signingKey')) { + signingKey = null + } + + if (!project.hasProperty('signingPassword')) { + signingPassword = null + } } def projectPom = { @@ -404,6 +412,9 @@ project(':sbe-tool') { } signing { + if (signingKey != null) { + useInMemoryPgpKeys(signingKey, signingPassword) + } sign publishing.publications.sbe } } @@ -471,6 +482,9 @@ project(':sbe-all') { } signing { + if (signingKey != null) { + useInMemoryPgpKeys(signingKey, signingPassword) + } sign publishing.publications.sbeAll } } @@ -584,6 +598,9 @@ project(':sbe-samples') { } signing { + if (signingKey != null) { + useInMemoryPgpKeys(signingKey, signingPassword) + } sign publishing.publications.sbeSamples } } From fd81387306fe52d704a65434b0490f334a1ca22c Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Wed, 17 Jul 2024 20:48:57 -0500 Subject: [PATCH 1174/1594] [Java] add #define for template id in C --- .../sbe/generation/c/CGenerator.java | 20 ++++- .../sbe/generation/c/CGeneratorTest.java | 75 +++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/c/CGeneratorTest.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 301532e771..7e597141fd 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1960,6 +1960,8 @@ private CharSequence generateMessageFlyweightFunctions( " return %2$s;\n" + "}\n\n" + + "#define %13$s_SBE_TEMPLATE_ID %4$s\n\n" + + "SBE_ONE_DEF %3$s %10$s_sbe_template_id(void)\n" + "{\n" + " return %4$s;\n" + @@ -2100,7 +2102,23 @@ private CharSequence generateMessageFlyweightFunctions( semanticType, structName, messageHeaderStruct, - semanticVersion); + semanticVersion, + toUppercaseWithUnderscores(structName)); + } + + private String toUppercaseWithUnderscores(final String camelCaseString) + { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < camelCaseString.length(); i++) + { + final char theChar = camelCaseString.charAt(i); + if (Character.isUpperCase(theChar)) + { + sb.append("_"); + } + sb.append(Character.toUpperCase(theChar)); + } + return sb.toString(); } private CharSequence generateFieldFunctions( diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/c/CGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/c/CGeneratorTest.java new file mode 100644 index 0000000000..8b3575e0ab --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/c/CGeneratorTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.cpp; + +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.io.InputStream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +class CppGeneratorTest +{ + @Test + void shouldUseGeneratedLiteralForConstantOneWhenGeneratingBitsetCode() throws Exception + { + try (InputStream in = Tests.getLocalResource("issue827.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + + final CppGenerator generator = new CppGenerator(ir, false, outputManager); + generator.generate(); + + final String source = outputManager.getSource("issue827.FlagsSet").toString(); + assertThat(source, not(containsString("1u << "))); + assertThat(source, containsString("UINT64_C(0x1) << ")); + } + } + + @Test + void shouldUseConstexprWhenInitializingSemanticVersion() throws Exception + { + try (InputStream in = Tests.getLocalResource("code-generation-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + + final CppGenerator generator = new CppGenerator(ir, false, outputManager); + generator.generate(); + + final String source = outputManager.getSource("code.generation.test.Car").toString(); + assertThat(source, containsString("static constexpr const char* SBE_SEMANTIC_VERSION = \"5.2\"")); + } + } +} From d99bf7e27edd57305ca6b169871f2b64f1b92484 Mon Sep 17 00:00:00 2001 From: Nate Bradac <38217740+nbradac@users.noreply.github.com> Date: Wed, 17 Jul 2024 21:56:40 -0400 Subject: [PATCH 1175/1594] remove extra file --- .../sbe/generation/c/CGeneratorTest.java | 75 ------------------- 1 file changed, 75 deletions(-) delete mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/c/CGeneratorTest.java diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/c/CGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/c/CGeneratorTest.java deleted file mode 100644 index 8b3575e0ab..0000000000 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/c/CGeneratorTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2013-2024 Real Logic Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package uk.co.real_logic.sbe.generation.cpp; - -import org.agrona.generation.StringWriterOutputManager; -import org.junit.jupiter.api.Test; -import uk.co.real_logic.sbe.Tests; -import uk.co.real_logic.sbe.ir.Ir; -import uk.co.real_logic.sbe.xml.IrGenerator; -import uk.co.real_logic.sbe.xml.MessageSchema; -import uk.co.real_logic.sbe.xml.ParserOptions; - -import java.io.InputStream; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.not; -import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; - -class CppGeneratorTest -{ - @Test - void shouldUseGeneratedLiteralForConstantOneWhenGeneratingBitsetCode() throws Exception - { - try (InputStream in = Tests.getLocalResource("issue827.xml")) - { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(in, options); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final StringWriterOutputManager outputManager = new StringWriterOutputManager(); - outputManager.setPackageName(ir.applicableNamespace()); - - final CppGenerator generator = new CppGenerator(ir, false, outputManager); - generator.generate(); - - final String source = outputManager.getSource("issue827.FlagsSet").toString(); - assertThat(source, not(containsString("1u << "))); - assertThat(source, containsString("UINT64_C(0x1) << ")); - } - } - - @Test - void shouldUseConstexprWhenInitializingSemanticVersion() throws Exception - { - try (InputStream in = Tests.getLocalResource("code-generation-schema.xml")) - { - final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); - final MessageSchema schema = parse(in, options); - final IrGenerator irg = new IrGenerator(); - final Ir ir = irg.generate(schema); - final StringWriterOutputManager outputManager = new StringWriterOutputManager(); - outputManager.setPackageName(ir.applicableNamespace()); - - final CppGenerator generator = new CppGenerator(ir, false, outputManager); - generator.generate(); - - final String source = outputManager.getSource("code.generation.test.Car").toString(); - assertThat(source, containsString("static constexpr const char* SBE_SEMANTIC_VERSION = \"5.2\"")); - } - } -} From 76bf4d009ec15cf9b1c496c878be069ebb670086 Mon Sep 17 00:00:00 2001 From: marc-adaptive Date: Mon, 22 Jul 2024 06:28:20 -0400 Subject: [PATCH 1176/1594] [Build] Update github release secrets --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5c5099f479..10fbcff404 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,7 +56,7 @@ jobs: - name: Publish with Gradle run: ./gradlew publish env: - ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.ossrhUsername }} - ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.ossrhPassword }} - ORG_GRADLE_PROJECT_signingKey: ${{ secrets.signingKey }} - ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.signingPassword }} + ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.SONATYPE_CENTRAL_USERNAME }} + ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.SONATYPE_CENTRAL_PASSWORD }} + ORG_GRADLE_PROJECT_signingKey: ${{ secrets.GPG_RSA_SIGN_KEY }} + ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.GPG_RSA_SIGN_KEYPASS }} From 0cb82dc2a026877ffcd85d1be60acd13673086d2 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Sat, 27 Jul 2024 20:06:35 +0100 Subject: [PATCH 1177/1594] [Java] Formatting. --- .../sbe/generation/java/JavaGenerator.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 7d0d4ba97b..1d6aa830a4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -274,14 +274,14 @@ public void generate() throws IOException final String decoderClassName = formatClassName(decoderName(msgToken.name())); final String decoderStateClassName = decoderClassName + "#CodecStates"; - final FieldPrecedenceModel decoderPrecedenceModel = - precedenceChecks.createDecoderModel(decoderStateClassName, tokens); + final FieldPrecedenceModel decoderPrecedenceModel = precedenceChecks.createDecoderModel( + decoderStateClassName, tokens); generateDecoder(decoderClassName, msgToken, fields, groups, varData, hasVarData, decoderPrecedenceModel); final String encoderClassName = formatClassName(encoderName(msgToken.name())); final String encoderStateClassName = encoderClassName + "#CodecStates"; - final FieldPrecedenceModel encoderPrecedenceModel = - precedenceChecks.createEncoderModel(encoderStateClassName, tokens); + final FieldPrecedenceModel encoderPrecedenceModel = precedenceChecks.createEncoderModel( + encoderStateClassName, tokens); generateEncoder(encoderClassName, msgToken, fields, groups, varData, hasVarData, encoderPrecedenceModel); } } @@ -839,7 +839,8 @@ private void generateDecoder( private void generateDecoderGroups( final StringBuilder sb, - final FieldPrecedenceModel fieldPrecedenceModel, final String outerClassName, + final FieldPrecedenceModel fieldPrecedenceModel, + final String outerClassName, final List tokens, final String indent, final boolean isSubGroup) throws IOException @@ -993,7 +994,6 @@ private void generateGroupDecoderClassHeader( .append(indent).append(" count = ").append(numInGroupCast).append(numInGroupGet).append(";\n") .append(indent).append(" }\n\n"); - generateAccessOrderListenerMethodForNextGroupElement(sb, fieldPrecedenceModel, indent + " ", groupToken); sb.append(indent).append(" public ").append(className).append(" next()\n") @@ -2345,16 +2345,16 @@ private String interfaceImportLine() } - private CharSequence generateFileHeader(final String packageName, final Set importedTypesPackages, + private CharSequence generateFileHeader( + final String packageName, + final Set importedTypesPackages, final String fqBuffer) { - final StringBuilder importStatements = generateImportStatements(importedTypesPackages, packageName); - return "/* Generated SBE (Simple Binary Encoding) message codec. */\n" + "package " + packageName + ";\n\n" + "import " + fqBuffer + ";\n" + interfaceImportLine() + - importStatements; + generateImportStatements(importedTypesPackages, packageName); } private CharSequence generateMainHeader( @@ -4470,7 +4470,6 @@ private void appendDecoderDisplay( append(sb, indent, groupName + ".index = " + groupName + "OriginalIndex;"); Separator.END_GROUP.appendToGeneratedBuilder(sb, indent); - lengthBeforeLastGeneratedSeparator = sb.length(); Separator.FIELD.appendToGeneratedBuilder(sb, indent); From cc3ea3a8f0b6cff325cf05f6fc912bad58d141a0 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 31 Jul 2024 14:03:50 +0100 Subject: [PATCH 1178/1594] [Java] Style consistency. --- .../common/FieldPrecedenceModel.java | 187 ++++++++---------- 1 file changed, 78 insertions(+), 109 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java index 58a68c17ff..40e5ac7441 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java @@ -136,7 +136,7 @@ public void forEachTerminalEncoderState(final Consumer consumer) public void forEachStateOrderedByStateNumber(final Consumer consumer) { transitionsByState.keySet().stream() - .sorted(Comparator.comparingInt(s -> s.number)) + .sorted(Comparator.comparingInt((s) -> s.number)) .forEach(consumer); } @@ -208,27 +208,31 @@ public void forEachTransitionFrom(final State state, final Consumer - { - transitionsForContext.forEach(transition -> + transitionsByInteraction.values().forEach( + (transitionsForContext) -> { - transition.forEachStartState(startState -> - { - sb.append(indent).append(" ") - .append(startState.name) - .append(" -> ") - .append(transition.endState().name) - .append(" [label=\" ").append(transition.interaction.exampleCode()); - - if (!transition.interaction.exampleConditions().isEmpty()) + transitionsForContext.forEach( + (transition) -> { - sb.append("\\n").append(" where ").append(transition.interaction.exampleConditions()); - } - - sb.append(" \"];\n"); - }); + transition.forEachStartState( + (startState) -> + { + sb.append(indent).append(" ") + .append(startState.name) + .append(" -> ") + .append(transition.endState().name) + .append(" [label=\" ").append(transition.interaction.exampleCode()); + + if (!transition.interaction.exampleConditions().isEmpty()) + { + sb.append("\\n").append(" where ") + .append(transition.interaction.exampleConditions()); + } + + sb.append(" \"];\n"); + }); + }); }); - }); sb.append(indent).append("}\n"); } @@ -244,34 +248,33 @@ private void findTransitions( walkSchemaLevel(new VersionCollector(versions), fields, groups, varData); walkSchemaLevel(new PathCollector(topLevelBlockFields, groupPathsByField), fields, groups, varData); - final IntStream selectedVersions = versionsSelector.apply(versions.stream().mapToInt(i -> i)); - selectedVersions.sorted().forEach(version -> - { - final State versionWrappedState = allocateState("V" + version + "_BLOCK"); + final IntStream selectedVersions = versionsSelector.apply(versions.stream().mapToInt((i) -> i)); + selectedVersions.sorted().forEach( + (version) -> + { + final State versionWrappedState = allocateState("V" + version + "_BLOCK"); - versionWrappedStates.put(version, versionWrappedState); + versionWrappedStates.put(version, versionWrappedState); - final CodecInteraction wrapInteraction = interactionFactory.wrap(version); + final CodecInteraction wrapInteraction = interactionFactory.wrap(version); - allocateTransitions( - wrapInteraction, - Collections.singletonList(notWrappedState), - versionWrappedState - ); + allocateTransitions( + wrapInteraction, + Collections.singletonList(notWrappedState), + versionWrappedState); - final TransitionCollector transitionCollector = new TransitionCollector( - "V" + version + "_", - Collections.singleton(versionWrappedState), - versionWrappedState, - token -> token.version() <= version - ); + final TransitionCollector transitionCollector = new TransitionCollector( + "V" + version + "_", + Collections.singleton(versionWrappedState), + versionWrappedState, + (token) -> token.version() <= version); - walkSchemaLevel(transitionCollector, fields, groups, varData); + walkSchemaLevel(transitionCollector, fields, groups, varData); - // Last writer (highest version) wins when there are multiple versions - encoderWrappedState = versionWrappedState; - terminalEncoderStates = transitionCollector.exitStates(); - }); + // Last writer (highest version) wins when there are multiple versions + encoderWrappedState = versionWrappedState; + terminalEncoderStates = transitionCollector.exitStates(); + }); } private State allocateState(final String name) @@ -287,11 +290,11 @@ private void allocateTransitions( final State to) { final TransitionGroup transitionGroup = new TransitionGroup(interaction, from, to); - final List transitionsForInteraction = - transitionsByInteraction.computeIfAbsent(interaction, ignored -> new ArrayList<>()); + final List transitionsForInteraction = transitionsByInteraction.computeIfAbsent( + interaction, (ignored) -> new ArrayList<>()); final boolean duplicateEndState = - transitionsForInteraction.stream().anyMatch(t -> t.to.number == transitionGroup.to.number); + transitionsForInteraction.stream().anyMatch((t) -> t.to.number == transitionGroup.to.number); if (duplicateEndState) { @@ -299,7 +302,7 @@ private void allocateTransitions( } final Optional conflictingTransition = transitionsForInteraction.stream() - .filter(t -> t.from.stream().anyMatch(transitionGroup.from::contains)) + .filter((t) -> t.from.stream().anyMatch(transitionGroup.from::contains)) .findAny(); if (conflictingTransition.isPresent()) @@ -310,7 +313,7 @@ private void allocateTransitions( transitionsForInteraction.add(transitionGroup); - from.forEach(fromState -> transitionsByState.get(fromState).add(transitionGroup)); + from.forEach((fromState) -> transitionsByState.get(fromState).add(transitionGroup)); } private static void walkSchemaLevel( @@ -394,7 +397,6 @@ public void onBlockField(final Token token) groupPathsByField.put(token, currentGroupPath()); } - @Override public void onEnterRepeatingGroup( final Token token, final List groupFields, @@ -407,7 +409,6 @@ public void onEnterRepeatingGroup( groupPath.removeLast(); } - @Override public void onVarData(final Token token) { groupPathsByField.put(token, currentGroupPath()); @@ -416,15 +417,15 @@ public void onVarData(final Token token) private String currentGroupPath() { final StringBuilder sb = new StringBuilder(); - groupPath.forEach(token -> - { - sb.append(token.name()).append('.'); - }); + groupPath.forEach( + (token) -> + { + sb.append(token.name()).append('.'); + }); return sb.toString(); } } - @SuppressWarnings("ClassCanBeRecord") private static final class VersionCollector implements SchemaConsumer { private final IntHashSet versions; @@ -434,13 +435,11 @@ private static final class VersionCollector implements SchemaConsumer this.versions = versions; } - @Override public void onBlockField(final Token token) { versions.add(token.version()); } - @Override public void onEnterRepeatingGroup( final Token token, final List groupFields, @@ -451,7 +450,6 @@ public void onEnterRepeatingGroup( walkSchemaLevel(this, groupFields, groupGroups, groupVarData); } - @Override public void onVarData(final Token token) { versions.add(token.version()); @@ -479,7 +477,6 @@ private TransitionCollector( currentStates.add(blockState); } - @Override public void onBlockField(final Token token) { if (filter.test(token)) @@ -489,7 +486,6 @@ public void onBlockField(final Token token) } } - @Override public void onEnterRepeatingGroup( final Token token, final List groupFields, @@ -521,8 +517,7 @@ public void onEnterRepeatingGroup( groupPrefix + "N_", currentStates, nRemainingGroupElement, - filter - ); + filter); walkSchemaLevel(nRemainingCollector, groupFields, groupGroups, groupVarData); currentStates.clear(); @@ -548,8 +543,7 @@ public void onEnterRepeatingGroup( groupPrefix + "1_", currentStates, oneRemainingGroupElement, - filter - ); + filter); walkSchemaLevel(oneRemainingCollector, groupFields, groupGroups, groupVarData); final CodecInteraction resetCountToIndexInteraction = interactionFactory.resetCountToIndex(token); @@ -566,16 +560,13 @@ public void onEnterRepeatingGroup( } } - @Override public void onVarData(final Token token) { if (filter.test(token)) { final CodecInteraction lengthAccessInteraction = interactionFactory.accessVarDataLength(token); - currentStates.forEach(state -> - { - allocateTransitions(lengthAccessInteraction, Collections.singleton(state), state); - }); + currentStates.forEach( + (state) -> allocateTransitions(lengthAccessInteraction, Collections.singleton(state), state)); final CodecInteraction codecInteraction = interactionFactory.accessField(token); final State accessedState = allocateState(statePrefix + token.name().toUpperCase() + "_DONE"); @@ -624,7 +615,9 @@ public String name() return name; } - @Override + /** + * {@inheritDoc} + */ public String toString() { return "State{" + @@ -690,7 +683,9 @@ public String exampleCode() return interaction.exampleCode(); } - @Override + /** + * {@inheritDoc} + */ public String toString() { return "Transition{" + @@ -724,7 +719,6 @@ public final boolean isTopLevelBlockFieldAccess() { if (this instanceof AccessField) { - //noinspection PatternVariableCanBeUsed final AccessField accessField = (AccessField)this; return accessField.isTopLevelBlockField(); } @@ -744,19 +738,16 @@ private static final class Wrap extends CodecInteraction this.version = version; } - @Override public String groupQualifiedName() { return "wrap"; } - @Override public String exampleCode() { return "wrap(version=" + version + ")"; } - @Override public String exampleConditions() { return ""; @@ -786,19 +777,16 @@ boolean isTopLevelBlockField() return isTopLevelBlockField; } - @Override public String groupQualifiedName() { return groupPath + token.name(); } - @Override public String exampleCode() { return groupPath + token.name() + "(?)"; } - @Override public String exampleConditions() { return ""; @@ -821,19 +809,16 @@ private DetermineGroupIsEmpty(final String groupPath, final Token token) this.token = token; } - @Override public String groupQualifiedName() { return groupPath + token.name(); } - @Override String exampleCode() { return groupPath + token.name() + "Count(0)"; } - @Override String exampleConditions() { return ""; @@ -856,19 +841,16 @@ private DetermineGroupHasElements(final String groupPath, final Token token) this.token = token; } - @Override public String groupQualifiedName() { return groupPath + token.name(); } - @Override String exampleCode() { return groupPath + token.name() + "Count(>0)"; } - @Override String exampleConditions() { return ""; @@ -892,19 +874,16 @@ private MoveToNextElement(final String groupPath, final Token token) this.token = token; } - @Override public String groupQualifiedName() { return groupPath + token.name(); } - @Override String exampleCode() { return groupPath + token.name() + ".next()"; } - @Override String exampleConditions() { return "count - newIndex > 1"; @@ -928,19 +907,16 @@ private MoveToLastElement(final String groupPath, final Token token) this.token = token; } - @Override public String groupQualifiedName() { return groupPath + token.name(); } - @Override String exampleCode() { return groupPath + token.name() + ".next()"; } - @Override String exampleConditions() { return "count - newIndex == 1"; @@ -963,19 +939,16 @@ private ResetCountToIndex(final String groupPath, final Token token) this.token = token; } - @Override public String groupQualifiedName() { return groupPath + token.name(); } - @Override String exampleCode() { return groupPath + token.name() + ".resetCountToIndex()"; } - @Override String exampleConditions() { return ""; @@ -998,26 +971,22 @@ private AccessVarDataLength(final String groupPath, final Token token) this.token = token; } - @Override public String groupQualifiedName() { return groupPath + token.name(); } - @Override String exampleCode() { return groupPath + token.name() + "Length()"; } - @Override String exampleConditions() { return ""; } } - /** * Factory for creating {@link CodecInteraction} instances. This factory * is used to hash-cons the instances, so that they can be compared by @@ -1068,8 +1037,8 @@ public CodecInteraction wrap(final int version) */ public CodecInteraction accessField(final Token token) { - return accessFieldInteractions.computeIfAbsent(token, - t -> new AccessField(groupPathsByField.get(t), t, topLevelBlockFields.contains(t))); + return accessFieldInteractions.computeIfAbsent( + token, (t) -> new AccessField(groupPathsByField.get(t), t, topLevelBlockFields.contains(t))); } /** @@ -1089,8 +1058,8 @@ public CodecInteraction accessField(final Token token) */ public CodecInteraction determineGroupIsEmpty(final Token token) { - return determineGroupIsEmptyInteractions.computeIfAbsent(token, - t -> new DetermineGroupIsEmpty(groupPathsByField.get(t), t)); + return determineGroupIsEmptyInteractions.computeIfAbsent( + token, (t) -> new DetermineGroupIsEmpty(groupPathsByField.get(t), t)); } /** @@ -1110,8 +1079,8 @@ public CodecInteraction determineGroupIsEmpty(final Token token) */ public CodecInteraction determineGroupHasElements(final Token token) { - return determineGroupHasElementsInteractions.computeIfAbsent(token, - t -> new DetermineGroupHasElements(groupPathsByField.get(t), t)); + return determineGroupHasElementsInteractions.computeIfAbsent( + token, (t) -> new DetermineGroupHasElements(groupPathsByField.get(t), t)); } /** @@ -1128,8 +1097,8 @@ public CodecInteraction determineGroupHasElements(final Token token) */ public CodecInteraction moveToNextElement(final Token token) { - return moveToNextElementInteractions.computeIfAbsent(token, - t -> new MoveToNextElement(groupPathsByField.get(t), t)); + return moveToNextElementInteractions.computeIfAbsent( + token, (t) -> new MoveToNextElement(groupPathsByField.get(t), t)); } /** @@ -1144,8 +1113,8 @@ public CodecInteraction moveToNextElement(final Token token) */ public CodecInteraction moveToLastElement(final Token token) { - return moveToLastElementInteractions.computeIfAbsent(token, - t -> new MoveToLastElement(groupPathsByField.get(t), t)); + return moveToLastElementInteractions.computeIfAbsent( + token, (t) -> new MoveToLastElement(groupPathsByField.get(t), t)); } /** @@ -1162,8 +1131,8 @@ public CodecInteraction moveToLastElement(final Token token) */ public CodecInteraction resetCountToIndex(final Token token) { - return resetCountToIndexInteractions.computeIfAbsent(token, - t -> new ResetCountToIndex(groupPathsByField.get(t), t)); + return resetCountToIndexInteractions.computeIfAbsent( + token, (t) -> new ResetCountToIndex(groupPathsByField.get(t), t)); } /** @@ -1180,8 +1149,8 @@ public CodecInteraction resetCountToIndex(final Token token) */ public CodecInteraction accessVarDataLength(final Token token) { - return accessVarDataLengthInteractions.computeIfAbsent(token, - t -> new AccessVarDataLength(groupPathsByField.get(t), t)); + return accessVarDataLengthInteractions.computeIfAbsent( + token, (t) -> new AccessVarDataLength(groupPathsByField.get(t), t)); } } } From 64ce522f63bdd295fde805a4e49aa88faa53986a Mon Sep 17 00:00:00 2001 From: marc-adaptive Date: Wed, 31 Jul 2024 11:39:42 -0400 Subject: [PATCH 1179/1594] [Build] Add explicit job permissions for on-workflow calls --- .github/workflows/release.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 10fbcff404..9ce363e17c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,12 +16,20 @@ env: jobs: ci: uses: ./.github/workflows/ci.yml - - codeql: - uses: ./.github/workflows/codeql.yml + permissions: + contents: read slow: uses: ./.github/workflows/slow.yml + permissions: + contents: read + + codeql: + uses: ./.github/workflows/codeql.yml + permissions: + actions: read + contents: read + security-events: write release: name: Release java artifacts From 4ddf522c184e4474e7ffe7d929e4eef4f2be1894 Mon Sep 17 00:00:00 2001 From: Ami Bar Date: Wed, 24 Apr 2024 10:59:48 +0300 Subject: [PATCH 1180/1594] [C#] Avoid ToString() affect the message internal state --- csharp/sbe-tests/Issue992Tests.cs | 65 +++++++++++++++++++ .../generation/csharp/CSharpGenerator.java | 20 ++++-- 2 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 csharp/sbe-tests/Issue992Tests.cs diff --git a/csharp/sbe-tests/Issue992Tests.cs b/csharp/sbe-tests/Issue992Tests.cs new file mode 100644 index 0000000000..8a5e47ca3a --- /dev/null +++ b/csharp/sbe-tests/Issue992Tests.cs @@ -0,0 +1,65 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Org.SbeTool.Sbe.Dll; +using Mktdata; + +namespace Org.SbeTool.Sbe.Tests +{ + [TestClass] + public class Issue992Tests + { + private const int Offset = 0; + private DirectBuffer _buffer; + private MessageHeader _messageHeader; + + [TestInitialize] + public void SetUp() + { + var byteArray = new byte[4096]; + _buffer = new DirectBuffer(byteArray); + + _messageHeader = new MessageHeader(); + + _messageHeader.Wrap(_buffer, 0, MessageHeader.SbeSchemaVersion); + _messageHeader.BlockLength = MDIncrementalRefreshBook46.BlockLength; + _messageHeader.SchemaId = MDIncrementalRefreshBook46.SchemaId; + _messageHeader.TemplateId = MDIncrementalRefreshBook46.TemplateId; + _messageHeader.Version = MDIncrementalRefreshBook46.SchemaVersion; + } + + [TestMethod] + public void CheckToStringDontMessWithGroupIteration() + { + var encoder = new MDIncrementalRefreshBook46() + .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); + encoder.TransactTime = (ulong)new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks; + var noMDEntries = encoder.NoMDEntriesCount(2); + noMDEntries.Next(); + noMDEntries.MDEntryPx.Mantissa = 12; + noMDEntries.MDEntrySize = 3; + noMDEntries.Next(); + noMDEntries.MDEntryPx.Mantissa = 15; + noMDEntries.MDEntrySize = 7; + encoder.NoOrderIDEntriesCount(0); + encoder.CheckEncodingIsComplete(); + + var expectedString = "[MDIncrementalRefreshBook46](sbeTemplateId=46|sbeSchemaId=1|sbeSchemaVersion=9|sbeBlockLength=11):TransactTime=630822816000000000|MatchEventIndicator={0}|NoMDEntries=[(MDEntryPx=(Mantissa=12|)|MDEntrySize=3|SecurityID=0|RptSeq=0|NumberOfOrders=0|MDPriceLevel=0|MDUpdateAction=New|MDEntryType=NULL_VALUE),(MDEntryPx=(Mantissa=15|)|MDEntrySize=7|SecurityID=0|RptSeq=0|NumberOfOrders=0|MDPriceLevel=0|MDUpdateAction=New|MDEntryType=NULL_VALUE)]|NoOrderIDEntries=[]"; + + var decoder = new MDIncrementalRefreshBook46() + .WrapForDecodeAndApplyHeader(_buffer, Offset, _messageHeader); + noMDEntries = decoder.NoMDEntries; + Assert.AreEqual(expectedString, decoder.ToString()); + int counter = 0; + while (noMDEntries.HasNext) + { + Assert.AreEqual(expectedString, decoder.ToString()); + ++counter; + noMDEntries.Next(); + Assert.AreEqual(expectedString, decoder.ToString()); + } + + Assert.AreEqual(2, counter); + Assert.AreEqual(expectedString, decoder.ToString()); + } + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 530717c9c4..bfd53ff311 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -181,7 +181,7 @@ public void generate() throws IOException out.append(generateVarData(fieldPrecedenceModel, varData, BASE_INDENT + INDENT)); out.append(generateDisplay(toUpperFirstChar(msgToken.name()), - fields, groups, varData, fieldPrecedenceModel)); + className, fields, groups, varData, fieldPrecedenceModel)); out.append(INDENT + "}\n"); out.append("}\n"); @@ -2406,13 +2406,22 @@ private int writeTokenDisplay( return lengthBeforeFieldSeparator; } - private void appendToString(final StringBuilder sb, final String indent) + private void appendToString(final StringBuilder sb, final String indent, final String className) { sb.append('\n'); append(sb, indent, "public override string ToString()"); append(sb, indent, "{"); append(sb, indent, " var sb = new StringBuilder(100);"); - append(sb, indent, " this.BuildString(sb);"); + if(null != className) + { + append(sb, indent, " var m = new " + className + "();"); + append(sb, indent, " m.WrapForDecode(_buffer, _offset, _actingBlockLength, _actingVersion);"); + append(sb, indent, " m.BuildString(sb);"); + } + else + { + append(sb, indent, " this.BuildString(sb);"); + } append(sb, indent, " return sb.ToString();"); append(sb, indent, "}"); } @@ -2437,6 +2446,7 @@ private CharSequence generateChoiceDisplay(final String enumName) private CharSequence generateDisplay( final String name, + final String className, final List tokens, final List groups, final List varData, @@ -2444,7 +2454,7 @@ private CharSequence generateDisplay( { final StringBuilder sb = new StringBuilder(100); - appendToString(sb, TWO_INDENT); + appendToString(sb, TWO_INDENT, className); sb.append('\n'); append(sb, TWO_INDENT, "internal void BuildString(StringBuilder builder)"); append(sb, TWO_INDENT, "{"); @@ -2502,7 +2512,7 @@ private CharSequence generateCompositeDisplay(final List tokens) { final StringBuilder sb = new StringBuilder(); - appendToString(sb, TWO_INDENT); + appendToString(sb, TWO_INDENT, null); sb.append('\n'); append(sb, TWO_INDENT, "internal void BuildString(StringBuilder builder)"); append(sb, TWO_INDENT, "{"); From 4c8f35bf3efe6f60c395c0bf4262633477ac43ef Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Thu, 1 Aug 2024 12:23:41 +0100 Subject: [PATCH 1181/1594] Use conventions from JavaGenerator in CSharpGenerator where possible. Note that the `BuildString` methods are still unsafe to use during group iteration. --- csharp/sbe-tests/Issue992Tests.cs | 2 +- .../generation/csharp/CSharpGenerator.java | 30 +++++++++++-------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/csharp/sbe-tests/Issue992Tests.cs b/csharp/sbe-tests/Issue992Tests.cs index 8a5e47ca3a..b4bf704565 100644 --- a/csharp/sbe-tests/Issue992Tests.cs +++ b/csharp/sbe-tests/Issue992Tests.cs @@ -28,7 +28,7 @@ public void SetUp() } [TestMethod] - public void CheckToStringDontMessWithGroupIteration() + public void CheckToStringDoesNotBreakGroupIteration() { var encoder = new MDIncrementalRefreshBook46() .WrapForEncodeAndApplyHeader(_buffer, Offset, _messageHeader); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index bfd53ff311..85d2a49855 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -2406,22 +2406,26 @@ private int writeTokenDisplay( return lengthBeforeFieldSeparator; } - private void appendToString(final StringBuilder sb, final String indent, final String className) + private void appendToString(final StringBuilder sb, final String indent) { sb.append('\n'); append(sb, indent, "public override string ToString()"); append(sb, indent, "{"); append(sb, indent, " var sb = new StringBuilder(100);"); - if(null != className) - { - append(sb, indent, " var m = new " + className + "();"); - append(sb, indent, " m.WrapForDecode(_buffer, _offset, _actingBlockLength, _actingVersion);"); - append(sb, indent, " m.BuildString(sb);"); - } - else - { - append(sb, indent, " this.BuildString(sb);"); - } + append(sb, indent, " this.BuildString(sb);"); + append(sb, indent, " return sb.ToString();"); + append(sb, indent, "}"); + } + + private void appendMessageToString(final StringBuilder sb, final String indent, final String className) + { + sb.append('\n'); + append(sb, indent, "public override string ToString()"); + append(sb, indent, "{"); + append(sb, indent, " var sb = new StringBuilder(100);"); + append(sb, indent, " var m = new " + className + "();"); + append(sb, indent, " m.WrapForDecode(_buffer, _offset, _actingBlockLength, _actingVersion);"); + append(sb, indent, " m.BuildString(sb);"); append(sb, indent, " return sb.ToString();"); append(sb, indent, "}"); } @@ -2454,7 +2458,7 @@ private CharSequence generateDisplay( { final StringBuilder sb = new StringBuilder(100); - appendToString(sb, TWO_INDENT, className); + appendMessageToString(sb, TWO_INDENT, className); sb.append('\n'); append(sb, TWO_INDENT, "internal void BuildString(StringBuilder builder)"); append(sb, TWO_INDENT, "{"); @@ -2512,7 +2516,7 @@ private CharSequence generateCompositeDisplay(final List tokens) { final StringBuilder sb = new StringBuilder(); - appendToString(sb, TWO_INDENT, null); + appendToString(sb, TWO_INDENT); sb.append('\n'); append(sb, TWO_INDENT, "internal void BuildString(StringBuilder builder)"); append(sb, TWO_INDENT, "{"); From 156b528289e0ee2d68319f03a2debb7a4978a418 Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Thu, 1 Aug 2024 10:14:50 -0500 Subject: [PATCH 1182/1594] [Java] add keyword suffix check for java enums --- .../sbe/generation/java/JavaGenerator.java | 4 +- .../sbe/generation/java/JavaUtil.java | 22 +++- .../sbe/generation/java/EnumTest.java | 102 ++++++++++++++++++ sbe-tool/src/test/resources/issue1007.xml | 24 +++++ 4 files changed, 145 insertions(+), 7 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java create mode 100644 sbe-tool/src/test/resources/issue1007.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 1d6aa830a4..b47b8839cc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -2238,7 +2238,7 @@ private CharSequence generateEnumValues(final List tokens, final String n final Encoding encoding = token.encoding(); final CharSequence constVal = generateLiteral(encoding.primitiveType(), encoding.constValue().toString()); generateTypeJavadoc(sb, INDENT, token); - sb.append(INDENT).append(token.name()).append('(').append(constVal).append("),\n\n"); + sb.append(INDENT).append(formatForJavaKeyword(token.name())).append('(').append(constVal).append("),\n\n"); } if (shouldDecodeUnknownEnumValues) @@ -2297,7 +2297,7 @@ private CharSequence generateEnumLookupMethod(final List tokens, final St for (final Token token : tokens) { final String constStr = token.encoding().constValue().toString(); - final String name = token.name(); + final String name = formatForJavaKeyword(token.name()); sb.append(" case ").append(constStr).append(": return ").append(name).append(";\n"); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 2431542d30..d5d3ac6693 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -155,22 +155,34 @@ public static String javaTypeName(final PrimitiveType primitiveType) */ public static String formatPropertyName(final String value) { - String formattedValue = Generators.toLowerFirstChar(value); + return formatForJavaKeyword(Generators.toLowerFirstChar(value)); + } - if (ValidationUtil.isJavaKeyword(formattedValue)) + /** + * Format a name for generated code. + *

      + * If the formatted name is a keyword then {@link SbeTool#KEYWORD_APPEND_TOKEN} is appended if set. + * + * @param value to be formatted. + * @return the string formatted as a valid name. + * @throws IllegalStateException if a keyword and {@link SbeTool#KEYWORD_APPEND_TOKEN} is not set. + */ + public static String formatForJavaKeyword(final String value) + { + if (ValidationUtil.isJavaKeyword(value)) { final String keywordAppendToken = System.getProperty(SbeTool.KEYWORD_APPEND_TOKEN); if (null == keywordAppendToken) { throw new IllegalStateException( - "Invalid property name='" + formattedValue + + "Invalid property name='" + value + "' please correct the schema or consider setting system property: " + SbeTool.KEYWORD_APPEND_TOKEN); } - formattedValue += keywordAppendToken; + return value + keywordAppendToken; } - return formattedValue; + return value; } /** diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java new file mode 100644 index 0000000000..6ec55dc56a --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java @@ -0,0 +1,102 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.SbeTool; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; +import uk.co.real_logic.sbe.xml.XmlSchemaParser; + +import java.io.InputStream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.StringContains.containsString; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +class EnumTest +{ + private static final Class BUFFER_CLASS = MutableDirectBuffer.class; + private static final String BUFFER_NAME = BUFFER_CLASS.getName(); + private static final Class READ_ONLY_BUFFER_CLASS = DirectBuffer.class; + private static final String READ_ONLY_BUFFER_NAME = READ_ONLY_BUFFER_CLASS.getName(); + + private StringWriterOutputManager outputManager; + private JavaGenerator generator; + + private void setupGenerator(final InputStream in) throws Exception + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = XmlSchemaParser.parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager); + } + + @SuppressWarnings("checkstyle:LineLength") + @Test + void shouldFailOnKeywordEnumValues() throws Exception + { + try (InputStream in = Tests.getLocalResource("issue1007.xml")) + { + setupGenerator(in); + + try + { + generator.generate(); + } + catch (final IllegalStateException exception) + { + assertEquals( + "Invalid property name='false' please correct the schema or consider setting system property: sbe.keyword.append.token", + exception.getMessage()); + return; + } + + fail("expected IllegalStateException"); + } + } + + @Test + void shouldAddSuffixToEnumValues() throws Exception + { + System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); + + try (InputStream in = Tests.getLocalResource("issue1007.xml")) + { + setupGenerator(in); + + generator.generate(); + final String sources = outputManager.getSources().toString(); + + assertThat(sources, containsString("false_(")); + assertThat(sources, containsString("true_(")); + assertThat(sources, containsString("return false_;")); + assertThat(sources, containsString("return true_;")); + } + } +} diff --git a/sbe-tool/src/test/resources/issue1007.xml b/sbe-tool/src/test/resources/issue1007.xml new file mode 100644 index 0000000000..1ba4ad548c --- /dev/null +++ b/sbe-tool/src/test/resources/issue1007.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + 0 + 1 + + + + + + From 5e0dcfb12d01f2f17bf416dbb9482f6f97af2d24 Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Thu, 1 Aug 2024 14:58:05 -0500 Subject: [PATCH 1183/1594] [Java] add enum keyword check to C++ and C# --- .../sbe/generation/cpp/CppGenerator.java | 14 ++- .../sbe/generation/cpp/CppUtil.java | 19 +++- .../generation/csharp/CSharpGenerator.java | 2 +- .../sbe/generation/csharp/CSharpUtil.java | 26 +++++ .../sbe/generation/cpp/CppEnumTest.java | 102 ++++++++++++++++++ .../sbe/generation/csharp/CSharpEnumTest.java | 97 +++++++++++++++++ .../sbe/generation/java/EnumTest.java | 2 + 7 files changed, 253 insertions(+), 9 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppEnumTest.java create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpEnumTest.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 99f5498e38..cc6921a0bb 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1471,7 +1471,11 @@ private CharSequence generateEnumValues(final List tokens, final Token en { final CharSequence constVal = generateLiteral( token.encoding().primitiveType(), token.encoding().constValue().toString()); - sb.append(" ").append(token.name()).append(" = ").append(constVal).append(",\n"); + sb.append(" ") + .append(formatForCppKeyword(token.name())) + .append(" = ") + .append(constVal) + .append(",\n"); } final CharSequence nullLiteral = generateLiteral( @@ -1505,7 +1509,11 @@ private CharSequence generateEnumLookupMethod(final List tokens, final To final CharSequence constVal = generateLiteral( token.encoding().primitiveType(), token.encoding().constValue().toString()); - sb.append(" case ").append(constVal).append(": return ").append(token.name()).append(";\n"); + sb.append(" case ") + .append(constVal) + .append(": return ") + .append(formatForCppKeyword(token.name())) + .append(";\n"); } final CharSequence nullVal = generateLiteral( @@ -3839,7 +3847,7 @@ private CharSequence generateEnumDisplay(final List tokens, final Token e { new Formatter(sb).format( " case %1$s: return \"%1$s\";\n", - token.name()); + formatForCppKeyword(token.name())); } sb.append(" case NULL_VALUE: return \"NULL_VALUE\";\n").append(" }\n\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index 6ac6d8afa8..534547a7fb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -67,22 +67,31 @@ public static String cppTypeName(final PrimitiveType primitiveType) */ public static String formatPropertyName(final String value) { - String formattedValue = toLowerFirstChar(value); + return formatForCppKeyword(toLowerFirstChar(value)); + } - if (ValidationUtil.isCppKeyword(formattedValue)) + /** + * Format a String with a suffix in case it's a keyword. + * + * @param value to be formatted. + * @return the formatted string. + */ + public static String formatForCppKeyword(final String value) + { + if (ValidationUtil.isCppKeyword(value)) { final String keywordAppendToken = System.getProperty(SbeTool.KEYWORD_APPEND_TOKEN); if (null == keywordAppendToken) { throw new IllegalStateException( - "Invalid property name='" + formattedValue + + "Invalid property name='" + value + "' please correct the schema or consider setting system property: " + SbeTool.KEYWORD_APPEND_TOKEN); } - formattedValue += keywordAppendToken; + return value + keywordAppendToken; } - return formattedValue; + return value; } /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 85d2a49855..8c06689da8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -775,7 +775,7 @@ private CharSequence generateEnumValues(final List tokens, final Token en for (final Token token : tokens) { sb.append(generateDocumentation(INDENT + INDENT, token)) - .append(INDENT).append(INDENT).append(token.name()).append(" = ") + .append(INDENT).append(INDENT).append(formatForCSharpKeyword(token.name())).append(" = ") .append(token.encoding().constValue()).append(",\n"); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index 1fc1cb64b2..31c4444feb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -17,6 +17,8 @@ package uk.co.real_logic.sbe.generation.csharp; import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.SbeTool; +import uk.co.real_logic.sbe.ValidationUtil; import uk.co.real_logic.sbe.generation.Generators; import uk.co.real_logic.sbe.ir.Token; @@ -241,6 +243,30 @@ public static String formatPropertyName(final String str) return toUpperFirstChar(str); } + /** + * Format a String with a suffix in case it's a keyword. + * + * @param value to be formatted. + * @return the formatted string. + */ + public static String formatForCSharpKeyword(final String value) + { + if (ValidationUtil.isCSharpKeyword(value)) + { + final String keywordAppendToken = System.getProperty(SbeTool.KEYWORD_APPEND_TOKEN); + if (null == keywordAppendToken) + { + throw new IllegalStateException( + "Invalid property name='" + value + + "' please correct the schema or consider setting system property: " + SbeTool.KEYWORD_APPEND_TOKEN); + } + + return value + keywordAppendToken; + } + + return value; + } + /** * Format a String as a variable name. * diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppEnumTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppEnumTest.java new file mode 100644 index 0000000000..db69b1cf83 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppEnumTest.java @@ -0,0 +1,102 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.cpp; + +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.SbeTool; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.io.InputStream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +import static org.junit.jupiter.api.Assertions.fail; + +class CppEnumTest +{ + private StringWriterOutputManager outputManager; + private CppGenerator generator; + + private void setupGenerator(final InputStream in) throws Exception + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + generator = new CppGenerator(ir, false, outputManager); + } + + @SuppressWarnings("checkstyle:LineLength") + @Test + void shouldFailOnKeywordEnumValues() throws Exception + { + System.clearProperty(SbeTool.KEYWORD_APPEND_TOKEN); + + try (InputStream in = Tests.getLocalResource("issue1007.xml")) + { + setupGenerator(in); + + try + { + generator.generate(); + } + catch (final IllegalStateException exception) + { + assertEquals( + "Invalid property name='false' please correct the schema or consider setting system property: sbe.keyword.append.token", + exception.getMessage()); + return; + } + + fail("expected IllegalStateException"); + final String source = outputManager.getSources().toString(); + + System.err.println(source); + } + } + + @Test + void shouldAddSuffixToEnumValues() throws Exception + { + System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); + + try (InputStream in = Tests.getLocalResource("issue1007.xml")) + { + setupGenerator(in); + + generator.generate(); + final String sources = outputManager.getSources().toString(); + + assertThat(sources, containsString("false_ = static")); + assertThat(sources, containsString("true_ = static")); + assertThat(sources, containsString("return false_;")); + assertThat(sources, containsString("return true_;")); + assertThat(sources, containsString("case false_:")); + assertThat(sources, containsString("case true_:")); + } + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpEnumTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpEnumTest.java new file mode 100644 index 0000000000..fec4a1bcfd --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpEnumTest.java @@ -0,0 +1,97 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.csharp; + +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.SbeTool; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.io.InputStream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +class CSharpEnumTest +{ + private StringWriterOutputManager outputManager; + private CSharpGenerator generator; + + private void setupGenerator(final InputStream in) throws Exception + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + generator = new CSharpGenerator(ir, outputManager); + } + + @SuppressWarnings("checkstyle:LineLength") + @Test + void shouldFailOnKeywordEnumValues() throws Exception + { + System.clearProperty(SbeTool.KEYWORD_APPEND_TOKEN); + + try (InputStream in = Tests.getLocalResource("issue1007.xml")) + { + setupGenerator(in); + + try + { + generator.generate(); + } + catch (final IllegalStateException exception) + { + assertEquals( + "Invalid property name='false' please correct the schema or consider setting system property: sbe.keyword.append.token", + exception.getMessage()); + return; + } + + fail("expected IllegalStateException"); + final String source = outputManager.getSources().toString(); + + System.err.println(source); + } + } + + @Test + void shouldAddSuffixToEnumValues() throws Exception + { + System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_"); + + try (InputStream in = Tests.getLocalResource("issue1007.xml")) + { + setupGenerator(in); + + generator.generate(); + final String sources = outputManager.getSources().toString(); + + assertThat(sources, containsString("false_ = ")); + assertThat(sources, containsString("true_ = ")); + } + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java index 6ec55dc56a..11c3424e6c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java @@ -61,6 +61,8 @@ private void setupGenerator(final InputStream in) throws Exception @Test void shouldFailOnKeywordEnumValues() throws Exception { + System.clearProperty(SbeTool.KEYWORD_APPEND_TOKEN); + try (InputStream in = Tests.getLocalResource("issue1007.xml")) { setupGenerator(in); From 67a4e410606acff9646002287e4e59f4671500d6 Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Fri, 2 Aug 2024 11:20:50 -0500 Subject: [PATCH 1184/1594] 1.32.0 release --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 365468802a..359c41089a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.32.0-SNAPSHOT \ No newline at end of file +1.32.0 From d419f7fc00ae32fbab40525daafe3ae46260062f Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Fri, 2 Aug 2024 11:21:58 -0500 Subject: [PATCH 1185/1594] 1.33.0 snapshot --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 359c41089a..f1b6e31361 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.32.0 +1.33.0-SNAPSHOT From 49c2b99e04a7c77b504e594ed84415b87040d9a6 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 5 Aug 2024 12:53:06 +0200 Subject: [PATCH 1186/1594] [Java] Upgrade to Agrona 1.22.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index c0ce5ee4e9..438597ba6c 100644 --- a/build.gradle +++ b/build.gradle @@ -61,8 +61,8 @@ def junitVersion = '5.10.3' def jqwikVersion = '1.9.0' def jsonVersion = '20240303' def jmhVersion = '1.37' -def agronaVersion = '1.21.2' -def agronaVersionRange = '[1.21.2,2.0[' // allow any release >= 1.21.2 and < 2.0.0 +def agronaVersion = '1.22.0' +def agronaVersionRange = '[1.22.0,2.0[' // allow any release >= 1.22.0 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 0f9e4100241fb36a48f1bc0814be2ae2170eb6f3 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 5 Aug 2024 12:54:48 +0200 Subject: [PATCH 1187/1594] [Java] Upgrade to Hamcrest 3.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 438597ba6c..613c3dd563 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ def toolchainLauncher = javaToolchains.launcherFor { } def checkstyleVersion = '9.3' -def hamcrestVersion = '2.2' +def hamcrestVersion = '3.0' def mockitoVersion = '4.11.0' def junitVersion = '5.10.3' def jqwikVersion = '1.9.0' From 2a48a285683110020c1198246a7660b72c4c7110 Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Mon, 5 Aug 2024 07:17:10 -0500 Subject: [PATCH 1188/1594] 1.32.1 release --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index f1b6e31361..96cd6ee1e7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.33.0-SNAPSHOT +1.32.1 From 0f49ae57a4fb2fc5b99c8a0e8f08b7f43023b4f9 Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Mon, 5 Aug 2024 07:18:13 -0500 Subject: [PATCH 1189/1594] 1.33.0 snapshot --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 96cd6ee1e7..f1b6e31361 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.32.1 +1.33.0-SNAPSHOT From a5e12d1c0d22e477ca302ee58c352984540e882f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:08:58 +0200 Subject: [PATCH 1190/1594] [Java] Upgrade to JUnit 5.11.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 613c3dd563..c0741e6ab7 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '3.0' def mockitoVersion = '4.11.0' -def junitVersion = '5.10.3' +def junitVersion = '5.11.0' def jqwikVersion = '1.9.0' def jsonVersion = '20240303' def jmhVersion = '1.37' From 7ce24c3f7344fcb2f6e8fb3ca04c162b3f4f5f35 Mon Sep 17 00:00:00 2001 From: Grzegorz Gierlach Date: Fri, 31 May 2024 13:31:10 +0200 Subject: [PATCH 1191/1594] [Rust] Generate imports in alphabetical order. --- .../java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 1 + .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 109d3ba4c5..ad8a62c23e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -73,6 +73,7 @@ void generate() throws IOException .filter((fileName) -> fileName.endsWith(".rs")) .filter((fileName) -> !fileName.equals("lib.rs")) .map((fileName) -> fileName.substring(0, fileName.length() - 3)) + .sorted() .forEach(modules::add); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 1b53987098..734b57d2bc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -152,8 +152,8 @@ public void generate() throws IOException try (Writer out = outputManager.createOutput(codecModName)) { indent(out, 0, "use crate::*;\n\n"); - indent(out, 0, "pub use encoder::%sEncoder;\n", formatStructName(msgToken.name())); - indent(out, 0, "pub use decoder::%sDecoder;\n\n", formatStructName(msgToken.name())); + indent(out, 0, "pub use decoder::%sDecoder;\n", formatStructName(msgToken.name())); + indent(out, 0, "pub use encoder::%sEncoder;\n\n", formatStructName(msgToken.name())); final String blockLengthType = blockLengthType(); final String templateIdType = rustTypeName(ir.headerStructure().templateIdType()); final String schemaIdType = rustTypeName(ir.headerStructure().schemaIdType()); From 80308ae87c198e9fd884a5cad85d35030afd8bd6 Mon Sep 17 00:00:00 2001 From: Grzegorz Gierlach Date: Wed, 22 May 2024 12:33:05 +0200 Subject: [PATCH 1192/1594] [Rust] Make Rust crate version configurable. --- .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 734b57d2bc..c7a33c9cd6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -48,6 +48,7 @@ */ public class RustGenerator implements CodeGenerator { + private static final String CRATE_VERSION = System.getProperty("sbe.rust.crate.version"); static final String WRITE_BUF_TYPE = "WriteBuf"; static final String READ_BUF_TYPE = "ReadBuf"; static final String BUF_LIFETIME = "'a"; @@ -114,10 +115,11 @@ public void generate() throws IOException { namespace = (ir.namespaceName() + "_" + packageName).toLowerCase(); } + final String version = CRATE_VERSION == null ? "0.1.0" : CRATE_VERSION; indent(writer, 0, "[package]\n"); indent(writer, 0, "name = \"%s\"\n", namespace); - indent(writer, 0, "version = \"0.1.0\"\n"); + indent(writer, 0, "version = \"%s\"\n", version); indent(writer, 0, "authors = [\"sbetool\"]\n"); indent(writer, 0, "description = \"%s\"\n", ir.description()); indent(writer, 0, "edition = \"2021\"\n\n"); From 86d0adbc9d2560f703e8106aaadb8a172f14f54d Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Thu, 22 Aug 2024 13:40:56 +0100 Subject: [PATCH 1193/1594] Make new Rust sysprop usage consistent with others. --- .../src/main/java/uk/co/real_logic/sbe/SbeTool.java | 10 ++++++++++ .../sbe/generation/TargetCodeGeneratorLoader.java | 1 + .../real_logic/sbe/generation/rust/RustGenerator.java | 9 ++++++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index d65a6a4601..3d95be6172 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -150,6 +150,16 @@ public class SbeTool */ public static final String CPP_NAMESPACES_COLLAPSE = "sbe.cpp.namespaces.collapse"; + /** + * Version of the Rust crate to generate. + */ + public static final String RUST_CRATE_VERSION = "sbe.rust.crate.version"; + + /** + * The default version of the Rust crate to generate, when not specified via the system property. + */ + public static final String RUST_DEFAULT_CRATE_VERSION = "0.1.0"; + /** * Boolean system property to turn on or off generation of the interface hierarchy. Defaults to false. */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 2b2383dfd2..c031ad60a8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -142,6 +142,7 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) { return new RustGenerator( ir, + System.getProperty(RUST_CRATE_VERSION, RUST_DEFAULT_CRATE_VERSION), new RustOutputManager(outputDir, ir.packageName())); } }; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index c7a33c9cd6..9df137c80a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -48,7 +48,6 @@ */ public class RustGenerator implements CodeGenerator { - private static final String CRATE_VERSION = System.getProperty("sbe.rust.crate.version"); static final String WRITE_BUF_TYPE = "WriteBuf"; static final String READ_BUF_TYPE = "ReadBuf"; static final String BUF_LIFETIME = "'a"; @@ -81,21 +80,26 @@ interface ParentDef private final Ir ir; private final RustOutputManager outputManager; + private final String crateVersion; /** * Create a new Rust language {@link CodeGenerator}. * * @param ir for the messages and types. + * @param crateVersion for the generated crate. * @param outputManager for generating the codecs to. */ public RustGenerator( final Ir ir, + final String crateVersion, final OutputManager outputManager) { Verify.notNull(ir, "ir"); + Verify.notNull(crateVersion, "crateVersion"); Verify.notNull(outputManager, "outputManager"); this.ir = ir; + this.crateVersion = crateVersion; this.outputManager = (RustOutputManager)outputManager; } @@ -115,11 +119,10 @@ public void generate() throws IOException { namespace = (ir.namespaceName() + "_" + packageName).toLowerCase(); } - final String version = CRATE_VERSION == null ? "0.1.0" : CRATE_VERSION; indent(writer, 0, "[package]\n"); indent(writer, 0, "name = \"%s\"\n", namespace); - indent(writer, 0, "version = \"%s\"\n", version); + indent(writer, 0, "version = \"%s\"\n", crateVersion); indent(writer, 0, "authors = [\"sbetool\"]\n"); indent(writer, 0, "description = \"%s\"\n", ir.description()); indent(writer, 0, "edition = \"2021\"\n\n"); From 23e01477d56ef32d4de32b8084fcd2bab19d0fbd Mon Sep 17 00:00:00 2001 From: Nate Bradac <38217740+nbradac@users.noreply.github.com> Date: Thu, 22 Aug 2024 09:20:36 -0400 Subject: [PATCH 1194/1594] [C] fix compliation error in C string view functions (#1010) --- .../co/real_logic/sbe/generation/c/CGenerator.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 7e597141fd..68afbb8283 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -613,7 +613,7 @@ private CharSequence generateVarData( " return ret;\n" + "}\n", propertyName, - generateStringViewNotPresentCondition(token.version()), + generateStringViewNotPresentCondition(token.version(), outermostStruct), lengthOfLengthField, lengthCType, structName, @@ -1032,7 +1032,9 @@ private static CharSequence generateArrayFieldNotPresentCondition(final int sinc sinceVersion); } - private static CharSequence generateStringViewNotPresentCondition(final int sinceVersion) + private static CharSequence generateStringViewNotPresentCondition( + final int sinceVersion, + final String outermostStruct) { if (0 == sinceVersion) { @@ -1042,9 +1044,11 @@ private static CharSequence generateStringViewNotPresentCondition(final int sinc return String.format( " if (codec->acting_version < %1$d)\n" + " {\n" + - " return { NULL, 0 };\n" + + " struct %2$s_string_view ret = { NULL, 0 };\n" + + " return ret;\n" + " }\n\n", - sinceVersion); + sinceVersion, + outermostStruct); } private static CharSequence generateTypeFieldNotPresentCondition(final int sinceVersion) From e7c1c2c20ccba5f56362023f8297a2c2e3785e09 Mon Sep 17 00:00:00 2001 From: Nate Bradac <38217740+nbradac@users.noreply.github.com> Date: Thu, 22 Aug 2024 11:43:05 -0400 Subject: [PATCH 1195/1594] [C] add test to ensure generated C code properly compiles when versions are set (#1011) --- sbe-tool/src/test/c/CComplianceTest.c | 2 +- .../src/test/c/CComplianceWithVersionTest.c | 21 +++++ sbe-tool/src/test/c/CMakeLists.txt | 12 ++- .../code-generation-schema-with-version.xml | 93 +++++++++++++++++++ 4 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 sbe-tool/src/test/c/CComplianceWithVersionTest.c create mode 100644 sbe-tool/src/test/resources/code-generation-schema-with-version.xml diff --git a/sbe-tool/src/test/c/CComplianceTest.c b/sbe-tool/src/test/c/CComplianceTest.c index 9acbb22334..150edec6e5 100644 --- a/sbe-tool/src/test/c/CComplianceTest.c +++ b/sbe-tool/src/test/c/CComplianceTest.c @@ -21,6 +21,6 @@ #include "group_with_data/testMessage3.h" #include "group_with_data/testMessage4.h" -int main() +int main(void) { } diff --git a/sbe-tool/src/test/c/CComplianceWithVersionTest.c b/sbe-tool/src/test/c/CComplianceWithVersionTest.c new file mode 100644 index 0000000000..9156d58ce5 --- /dev/null +++ b/sbe-tool/src/test/c/CComplianceWithVersionTest.c @@ -0,0 +1,21 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "code_generation_test_version/car.h" +#include "code_generation_test_version/messageHeader.h" + +int main(void) +{ +} diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index 52bf553afd..e8ea222cf7 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -34,6 +34,7 @@ endfunction() find_package(Java REQUIRED) set(CODE_GENERATION_SCHEMA ${CODEC_SCHEMA_DIR}/code-generation-schema.xml) +set(CODE_GENERATION_SCHEMA_WITH_VERSION ${CODEC_SCHEMA_DIR}/code-generation-schema-with-version.xml) set(GROUP_WITH_DATA_SCHEMA ${CODEC_SCHEMA_DIR}/group-with-data-schema.xml) set(ISSUE889_SCHEMA ${CODEC_SCHEMA_DIR}/issue889.xml) @@ -43,13 +44,14 @@ set(GENERATED_CODECS add_custom_command( OUTPUT ${GENERATED_CODECS} - DEPENDS sbe-jar ${SBE_JAR} ${CODE_GENERATION_SCHEMA} ${GROUP_WITH_DATA_SCHEMA} ${ISSUE889_SCHEMA} + DEPENDS sbe-jar ${SBE_JAR} ${CODE_GENERATION_SCHEMA} ${CODE_GENERATION_SCHEMA_WITH_VERSION} ${GROUP_WITH_DATA_SCHEMA} ${ISSUE889_SCHEMA} COMMAND ${Java_JAVA_EXECUTABLE} -Dsbe.output.dir=${C_CODEC_TARGET_DIR} -Dsbe.target.language="C" -jar ${SBE_JAR} ${CODE_GENERATION_SCHEMA} + ${CODE_GENERATION_SCHEMA_WITH_VERSION} ${GROUP_WITH_DATA_SCHEMA} ${ISSUE889_SCHEMA} ) @@ -70,3 +72,11 @@ target_include_directories(CComplianceTest ) add_dependencies(CComplianceTest c_codecs) + +add_executable(CComplianceWithVersionTest CComplianceWithVersionTest.c) + +target_include_directories(CComplianceWithVersionTest + PRIVATE ${C_CODEC_TARGET_DIR} +) + +add_dependencies(CComplianceWithVersionTest c_codecs) diff --git a/sbe-tool/src/test/resources/code-generation-schema-with-version.xml b/sbe-tool/src/test/resources/code-generation-schema-with-version.xml new file mode 100644 index 0000000000..1ebd46c77a --- /dev/null +++ b/sbe-tool/src/test/resources/code-generation-schema-with-version.xml @@ -0,0 +1,93 @@ + + + + + + T + S + N + K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 9000 + + Petrol + + + + 0 + 1 + + + A + B + C + + + 0 + 1 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 8d085e4f179bfeddd24758a6a248eb3276113c33 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 10:27:59 +0200 Subject: [PATCH 1196/1594] 1.32.2 release --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index f1b6e31361..c78d39b8ed 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.33.0-SNAPSHOT +1.32.2 From 7c2305838f6c3f2737963b348384d404c2e6ada4 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 10:28:11 +0200 Subject: [PATCH 1197/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index c78d39b8ed..7341032ba0 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.32.2 +1.32.0-SNAPSHOT From 996014f9250456a60b25296f1e2633c4851bf7a8 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:40:24 +0200 Subject: [PATCH 1198/1594] correct snapshot version --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 7341032ba0..f1b6e31361 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.32.0-SNAPSHOT +1.33.0-SNAPSHOT From ccddba964bd8dacaa01af62b8391f722b748ef5b Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:54:45 +0200 Subject: [PATCH 1199/1594] [Java] Upgrade to Gradle 8.10. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 3 ++- gradlew | 27 ++++++++++++++--------- gradlew.bat | 22 +++++++++--------- 5 files changed, 32 insertions(+), 22 deletions(-) diff --git a/build.gradle b/build.gradle index c0741e6ab7..51b968361c 100644 --- a/build.gradle +++ b/build.gradle @@ -959,7 +959,7 @@ tasks.named('dependencyUpdates').configure { } wrapper { - gradleVersion = '8.1.1' + gradleVersion = '8.10' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch literal 43583 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 GZ~q4|mN%#X literal 62076 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8707e8b506..66cd5a0e49 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-all.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index aeb74cbb43..f5feea6d6b 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +134,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 93e3f59f13..9d21a21834 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail From 286f583492071fedc93fe4bf7ab3745311f39561 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:56:32 +0200 Subject: [PATCH 1200/1594] [Java] Upgrade to Shadow 8.3.0. --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 51b968361c..353ada9da2 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ buildscript { plugins { id 'java-library' id 'jvm-test-suite' - id 'com.github.johnrengelman.shadow' version '8.1.1' apply false + id 'com.gradleup.shadow' version '8.3.0' apply false id 'com.github.ben-manes.versions' version '0.51.0' } @@ -422,7 +422,7 @@ project(':sbe-tool') { project(':sbe-all') { apply plugin: 'maven-publish' apply plugin: 'signing' - apply plugin: 'com.github.johnrengelman.shadow' + apply plugin: 'com.gradleup.shadow' dependencies { implementation project(':sbe-tool') @@ -606,7 +606,7 @@ project(':sbe-samples') { } project(':sbe-benchmarks') { - apply plugin: 'com.github.johnrengelman.shadow' + apply plugin: 'com.gradleup.shadow' dependencies { implementation "org.openjdk.jmh:jmh-core:${jmhVersion}" From 81e92929e70adcfbc9ca76a89771d34262e4f2b4 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:57:09 +0200 Subject: [PATCH 1201/1594] [Java] Upgrade to Mockito 5.12.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 353ada9da2..3510266529 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '3.0' -def mockitoVersion = '4.11.0' +def mockitoVersion = '5.12.0' def junitVersion = '5.11.0' def jqwikVersion = '1.9.0' def jsonVersion = '20240303' From 822c8929ba070ed495d030f1227ddce96d9b846f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:59:55 +0200 Subject: [PATCH 1202/1594] [Java] Set `sourceCompatibility = 17` and cleanup warnings. --- build.gradle | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index 3510266529..cb9cf10fe7 100644 --- a/build.gradle +++ b/build.gradle @@ -185,6 +185,7 @@ subprojects { toolchain { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } + sourceCompatibility = 17 } checkstyle.toolVersion = "${checkstyleVersion}" @@ -214,18 +215,13 @@ subprojects { options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' options.links("https://www.javadoc.io/doc/org.agrona/agrona/${agronaVersion}/") - if (buildJavaVersion > 21) { // early access JavaDoc location is different + if (buildJavaVersion >= 23) { // early access JavaDoc location is different options.links("https://download.java.net/java/early_access/jdk${buildJavaVersion}/docs/api/") } - else if (buildJavaVersion >= 11) { - options.links("https://docs.oracle.com/en/java/javase/${buildJavaVersion}/docs/api/") - } else { - options.links("https://docs.oracle.com/javase/${buildJavaVersion}/docs/api/") - } - if (buildJavaVersion >= 10) { - options.addBooleanOption 'html5', true + options.links("https://docs.oracle.com/en/java/javase/${buildJavaVersion}/docs/api/") } + options.addBooleanOption('html5', true) } testing { @@ -274,7 +270,7 @@ project(':sbe-tool') { } } - def generatedDir = 'build/generated-src' + def generatedDir = "${layout.buildDirectory.get()}/generated-src" sourceSets { generated { java.srcDir generatedDir @@ -909,7 +905,7 @@ tasks.register('runJavaBenchmarks', Exec) { } tasks.register('testReport', TestReport) { - destinationDirectory = file("$buildDir/reports/allTests") + destinationDirectory = file("${layout.buildDirectory.get()}/reports/allTests") // Include the results from the `test` task in all sub-projects testResults.setFrom(subprojects*.test) } From c5d5cdfd5f01a289bf9c82eddeb80e30814638ab Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:06:16 +0200 Subject: [PATCH 1203/1594] [CI] Remove JDK 8 + switch to Ubuntu 24.04 and latest compilers. --- .github/workflows/ci.yml | 48 +++++++++++++++++------------------ .github/workflows/codeql.yml | 6 ++--- .github/workflows/release.yml | 4 +-- .github/workflows/slow.yml | 4 +-- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20b3fd4413..588b7bc568 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,8 +29,8 @@ jobs: strategy: fail-fast: false matrix: - java: [ '8', '17', '21' ] - os: [ 'ubuntu-22.04', 'windows-latest' ] + java: [ '17', '21' ] + os: [ 'ubuntu-24.04', 'windows-latest' ] steps: - name: Checkout code uses: actions/checkout@v4 @@ -62,13 +62,13 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - name: Build with Gradle run: ./gradlew csharp-build: name: C# ${{ matrix.dotnet }} - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -97,7 +97,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - name: Cache NuGet dependencies uses: actions/cache@v4 with: @@ -154,17 +154,17 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - name: Build run: ./cppbuild/cppbuild - cpp-gcc-2204-build: - name: C++ GCC ${{ matrix.version }} (Ubuntu 22.04) - runs-on: ubuntu-22.04 + cpp-gcc-2404-build: + name: C++ GCC ${{ matrix.version }} (Ubuntu 24.04) + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: - version: [ '11', '12', '13' ] + version: [ '11', '12', '13', '14' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} @@ -197,7 +197,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - name: Build run: ./cppbuild/cppbuild @@ -242,17 +242,17 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - name: Build run: ./cppbuild/cppbuild - cpp-clang-2204-build: - name: C++ Clang ${{ matrix.version }} (Ubuntu 22.04) - runs-on: ubuntu-22.04 + cpp-clang-2404-build: + name: C++ Clang ${{ matrix.version }} (Ubuntu 24.04) + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: - version: [ '13', '14', '15', '16', '17' ] + version: [ '13', '14', '15', '16', '17', '18' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} @@ -287,7 +287,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - name: Build run: ./cppbuild/cppbuild @@ -297,7 +297,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ 'macos-14' ] + os: [ 'macos-latest' ] env: CC: clang CXX: clang++ @@ -327,7 +327,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - name: Build run: cmake --version && ./cppbuild/cppbuild @@ -368,13 +368,13 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - name: Build run: cppbuild/cppbuild.cmd rust-build: name: Rust ${{ matrix.rust }} - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -406,12 +406,12 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - run: ./gradlew runRustTests golang-build: name: Golang ${{ matrix.version }} - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -441,7 +441,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - name: Generate codecs run: ./gradlew generateGolangCodecs - name: Go diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 63bb4b11c8..c91468d27f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -25,7 +25,7 @@ jobs: java-analyze: name: Java Analyze ${{ matrix.java }} - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: actions: read contents: read @@ -80,7 +80,7 @@ jobs: csharp-analyze: name: C# Analyze ${{ matrix.dotnet }} - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: actions: read contents: read @@ -138,7 +138,7 @@ jobs: cpp-gcc-2204-analyze: name: C++ GCC Analyze ${{ matrix.version }} - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: actions: read contents: read diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9ce363e17c..c34e4a7408 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,7 +37,7 @@ jobs: contents: write packages: write needs: [ ci , codeql, slow ] - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: checkout uses: actions/checkout@v4 @@ -55,7 +55,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION run: | java -Xinternalversion diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 9b4b0c22b0..9fc75825c0 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -21,7 +21,7 @@ permissions: jobs: property-tests: name: Property tests - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: matrix: java: [ '21' ] @@ -46,7 +46,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - name: Setup dotnet uses: actions/setup-dotnet@v2 with: From 97e7b4831ecb710dfb3181bb9eef26464a7c7ee2 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:19:12 +0200 Subject: [PATCH 1204/1594] [CI] Debug. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 588b7bc568..5333c4d700 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: distribution: 'zulu' java-version: 17 - name: Build with Gradle - run: ./gradlew + run: ./gradlew --stacktrace csharp-build: name: C# ${{ matrix.dotnet }} From 12a3ad0cb586e692fb1c38004d3feb4313f1ecd1 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:27:04 +0200 Subject: [PATCH 1205/1594] [Java] Fix Gradle warning. --- settings.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/settings.gradle b/settings.gradle index 72d590e400..19ec0d7679 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,4 @@ include 'sbe-tool', 'sbe-samples', 'sbe-benchmarks', 'sbe-all' rootProject.name = 'sbe' +project(':sbe-all').projectDir.mkdirs() From af090dad060da9157101fd3bc8b3851a85a451da Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:31:00 +0200 Subject: [PATCH 1206/1594] [CI] Add `macos-latest` to the build matrix. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5333c4d700..cf3ce2d344 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: fail-fast: false matrix: java: [ '17', '21' ] - os: [ 'ubuntu-24.04', 'windows-latest' ] + os: [ 'ubuntu-24.04', 'windows-latest', 'macos-latest' ] steps: - name: Checkout code uses: actions/checkout@v4 From 287adb5ece9ed0a51039498214d557605fb532a6 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:31:58 +0200 Subject: [PATCH 1207/1594] [CI] Fix CodeQL build. --- .github/workflows/codeql.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index c91468d27f..757fb40381 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: language: [ 'java' ] - java: [ '8' ] + java: [ '17' ] steps: - name: Checkout code @@ -136,7 +136,7 @@ jobs: with: category: "/language:${{matrix.language}}" - cpp-gcc-2204-analyze: + cpp-gcc-analyze: name: C++ GCC Analyze ${{ matrix.version }} runs-on: ubuntu-24.04 permissions: @@ -147,7 +147,7 @@ jobs: fail-fast: false matrix: language: ['cpp'] - version: [ '12' ] + version: [ '14' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} From 57d73bfd32a9ff859ff64d58f41eab01ee516994 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:39:34 +0200 Subject: [PATCH 1208/1594] [CI] Try CodeQL without version. --- .github/workflows/codeql.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 757fb40381..459f3a29bd 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -34,7 +34,6 @@ jobs: fail-fast: false matrix: language: [ 'java' ] - java: [ '17' ] steps: - name: Checkout code From c7dd79dd22c31a0344e37d9fee8433743bdebcf6 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:43:14 +0200 Subject: [PATCH 1209/1594] [CI] CodeQL java. --- .github/workflows/codeql.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 459f3a29bd..3e6fa7be22 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -56,21 +56,21 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: ${{ matrix.java }} + java-version: 17 - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION run: | java -Xinternalversion echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - + + - name: Build with Gradle + run: ./gradlew + - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml - - - name: Build with Gradle - run: ./gradlew - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 From b5df1f881ddf54504d77b07ded762f82dda9fdda Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:47:19 +0200 Subject: [PATCH 1210/1594] [CI] Move the compilation to the right phase. --- .github/workflows/codeql.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3e6fa7be22..5c2089713a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -63,15 +63,15 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - - name: Build with Gradle - run: ./gradlew - - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml + - name: Build with Gradle + run: ./gradlew + - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: From b713baf7b2e618ebb9516610b367de1e084475a3 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:56:03 +0200 Subject: [PATCH 1211/1594] [CI] Simplify. --- .github/workflows/codeql.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 5c2089713a..8684a7bd54 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -34,6 +34,7 @@ jobs: fail-fast: false matrix: language: [ 'java' ] + java: [ '17' ] steps: - name: Checkout code @@ -56,12 +57,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 - - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION - run: | - java -Xinternalversion - echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV - echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV + java-version: ${{ matrix.java }} - name: Initialize CodeQL uses: github/codeql-action/init@v3 From 4e9689671f3367b3cac627cce3850ea450c25936 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 17:02:37 +0200 Subject: [PATCH 1212/1594] [CI] Try CodeQL workaround. --- .github/workflows/codeql.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 8684a7bd54..b4ddb31dba 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -17,6 +17,7 @@ concurrency: env: GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail' CMAKE_VERSION: '3.14.7' + JAVA_TOOL_OPTIONS: "--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED" permissions: contents: read From ff0b993b8573afbcedfd9ff0bf0de6081c3ffa8c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 17:02:49 +0200 Subject: [PATCH 1213/1594] [Java] Use layout. --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index cb9cf10fe7..0f31db6c71 100644 --- a/build.gradle +++ b/build.gradle @@ -294,7 +294,7 @@ project(':sbe-tool') { suites { test { dependencies { - implementation files('build/classes/java/generated') + implementation files("${layout.buildDirectory.get()}/classes/java/generated") implementation "org.hamcrest:hamcrest:${hamcrestVersion}" implementation "org.mockito:mockito-core:${mockitoVersion}" implementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" @@ -491,7 +491,7 @@ project(':sbe-samples') { dependencies { api project(':sbe-tool') - implementation files('build/classes/java/generated') + implementation files("${layout.buildDirectory.get()}/classes/java/generated") } def generatedDir = 'build/generated-src' @@ -608,7 +608,7 @@ project(':sbe-benchmarks') { implementation "org.openjdk.jmh:jmh-core:${jmhVersion}" annotationProcessor "org.openjdk.jmh:jmh-generator-annprocess:${jmhVersion}" implementation project(':sbe-tool') - implementation files('build/classes/java/generated') + implementation files("${layout.buildDirectory.get()}/classes/java/generated") } sourceSets { From 9bee1597871533c2206172ca32f47974d4d63be2 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 17:09:25 +0200 Subject: [PATCH 1214/1594] [CI] Remove CMake installation step. --- .github/workflows/ci.yml | 44 ++++++++---------------------------- .github/workflows/codeql.yml | 6 +---- .github/workflows/slow.yml | 2 +- 3 files changed, 12 insertions(+), 40 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf3ce2d344..5bc6da223f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,6 @@ concurrency: env: GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail' - CMAKE_VERSION: '3.14.7' permissions: contents: read @@ -58,7 +57,7 @@ jobs: java -Xinternalversion echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - - name: Setup java 8 to run the Gradle script + - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' @@ -93,7 +92,7 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - - name: Setup java 8 to run the Gradle script + - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' @@ -147,10 +146,7 @@ jobs: run: | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ bionic main universe" sudo apt-get install -y g++-${{ matrix.version }} libsparsehash-dev libidn11 - curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH - - name: Setup java 8 to run the Gradle script + - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' @@ -190,10 +186,7 @@ jobs: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install -y g++-${{ matrix.version }} - curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH - - name: Setup java 8 to run the Gradle script + - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' @@ -235,10 +228,7 @@ jobs: echo "deb [signed-by=/etc/apt/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/focal/ llvm-toolchain-focal-${{ matrix.version }} main" | sudo tee /etc/apt/sources.list.d/llvm.list sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev libidn11 - curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH - - name: Setup java 8 to run the Gradle script + - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' @@ -280,10 +270,7 @@ jobs: echo "deb [signed-by=/etc/apt/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${{ matrix.version }} main" | sudo tee /etc/apt/sources.list.d/llvm.list sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} - curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH - - name: Setup java 8 to run the Gradle script + - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' @@ -318,12 +305,7 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - - name: Install CMake - run: | - curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz - tar xf cmake-${CMAKE_VERSION}-Darwin-x86_64.tar.gz - echo "cmake-${CMAKE_VERSION}-Darwin-x86_64/CMake.app/Contents/bin" >> $GITHUB_PATH - - name: Setup java 8 to run the Gradle script + - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' @@ -358,13 +340,7 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - - name: Install CMake - run: | - $client = new-object System.Net.WebClient - $client.DownloadFile("https://github.com/Kitware/CMake/releases/download/v$Env:CMAKE_VERSION/cmake-$Env:CMAKE_VERSION-win64-x64.zip","cmake-$Env:CMAKE_VERSION-win64-x64.zip") - 7z x cmake-$Env:CMAKE_VERSION-win64-x64.zip - echo "cmake-$Env:CMAKE_VERSION-win64-x64/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 - - name: Setup java 8 to run the Gradle script + - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' @@ -402,7 +378,7 @@ jobs: profile: minimal toolchain: ${{ matrix.rust }} override: true - - name: Setup java 8 to run the Gradle script + - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' @@ -437,7 +413,7 @@ jobs: uses: actions/setup-go@v4 with: go-version: ${{ matrix.version }} - - name: Setup java 8 to run the Gradle script + - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b4ddb31dba..5942820cc6 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -16,7 +16,6 @@ concurrency: env: GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail' - CMAKE_VERSION: '3.14.7' JAVA_TOOL_OPTIONS: "--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED" permissions: @@ -167,10 +166,7 @@ jobs: - name: Install compiler run: | sudo apt-get install -y g++-${{ matrix.version }} - curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - tar xf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - echo "cmake-${CMAKE_VERSION}-Linux-x86_64/bin" >> $GITHUB_PATH - + - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 9fc75825c0..e67cd05af7 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -42,7 +42,7 @@ jobs: java -Xinternalversion echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - - name: Setup java 8 to run the Gradle script + - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v3 with: distribution: 'zulu' From 0e99110b6467ae59c87a2ba540fabe0f88bb07ca Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 21:35:06 +0200 Subject: [PATCH 1215/1594] [Java] Use `Set.of` instead of `HashSet<>(Arrays.asList(...))`. --- .../uk/co/real_logic/sbe/ValidationUtil.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index 3ba64ef105..74e58e3f5a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -15,8 +15,6 @@ */ package uk.co.real_logic.sbe; -import java.util.Arrays; -import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; @@ -27,7 +25,7 @@ public class ValidationUtil { private static final Pattern PATTERN = Pattern.compile("\\."); - private static final Set C_KEYWORDS = new HashSet<>(Arrays.asList( + private static final Set C_KEYWORDS = Set.of( "auto", "_Alignas", "_Alignof", "_Atomic", "bool", "_Bool", "break", "case", "_Complex", "char", "const", "continue", "default", @@ -36,7 +34,7 @@ public class ValidationUtil "int", "long", "_Noreturn", "register", "restrict", "return", "short", "signed", "sizeof", "static", "_Static_assert", "struct", "switch", "_Thread_local", "true", "typedef", "union", - "unsigned", "void", "volatile", "wchar_t", "while")); + "unsigned", "void", "volatile", "wchar_t", "while"); /** * Check value for validity of usage as a C identifier. A programmatic variable @@ -114,7 +112,7 @@ private static boolean isSbeCIdentifierPart(final char c) return Character.isLetterOrDigit(c) || c == '_'; } - private static final Set CPP_KEYWORDS = new HashSet<>(Arrays.asList( + private static final Set CPP_KEYWORDS = Set.of( "alignas", "and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case", "catch", "char", "class", "compl", "const", @@ -134,7 +132,7 @@ private static boolean isSbeCIdentifierPart(final char c) // since C++11 "alignof", "constexpr", "decltype", "nullptr", "static_assert", "thread_local", // since C++11 have special meaning, so avoid - "final")); + "final"); /** * Check value for validity of usage as a C++ identifier. A programmatic variable @@ -212,7 +210,7 @@ private static boolean isSbeCppIdentifierPart(final char c) return Character.isLetterOrDigit(c) || c == '_'; } - private static final Set JAVA_KEYWORDS = new HashSet<>(Arrays.asList( + private static final Set JAVA_KEYWORDS = Set.of( "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", @@ -223,7 +221,7 @@ private static boolean isSbeCppIdentifierPart(final char c) "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "try", "void", "volatile", "while", - "null", "true", "false", "_")); + "null", "true", "false", "_"); /** * Check string for validity of usage as a Java identifier. Avoiding keywords. @@ -292,7 +290,7 @@ private static boolean isJavaIdentifier(final String token) } /* https://golang.org/ref/spec#Keywords */ - private static final Set GOLANG_KEYWORDS = new HashSet<>(Arrays.asList( + private static final Set GOLANG_KEYWORDS = Set.of( "break", "default", "func", "interface", "select", "case", "defer", "go", "map", "struct", "chan", "else", "goto", "package", "switch", @@ -310,7 +308,7 @@ private static boolean isJavaIdentifier(final String token) "nil", /* functions */ "append", "cap", "close", "complex", "copy", "delete", "imag", "len", - "make", "new", "panic", "print", "println", "real", "recover")); + "make", "new", "panic", "print", "println", "real", "recover"); /** * "Check" value for validity of usage as a golang identifier. From: @@ -398,7 +396,7 @@ private static boolean isSbeGolangIdentifierPart(final char c) * Note this does not include the contextual keywords * Note "virtual" is no longer but was in early versions of C# */ - private static final Set CSHARP_KEYWORDS = new HashSet<>(Arrays.asList( + private static final Set CSHARP_KEYWORDS = Set.of( "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default", @@ -414,7 +412,7 @@ private static boolean isSbeGolangIdentifierPart(final char c) "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "using static", "virtual", - "void", "volatile", "while")); + "void", "volatile", "while"); /** * "Check" value for validity of usage as a csharp identifier. From 9892b15bb99dbf05ca032e8507aa0e3d1680ee88 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:27:07 +0200 Subject: [PATCH 1216/1594] [Java] Upgrade to Agrona 1.23.0. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 0f31db6c71..16ddc10efe 100644 --- a/build.gradle +++ b/build.gradle @@ -61,8 +61,8 @@ def junitVersion = '5.11.0' def jqwikVersion = '1.9.0' def jsonVersion = '20240303' def jmhVersion = '1.37' -def agronaVersion = '1.22.0' -def agronaVersionRange = '[1.22.0,2.0[' // allow any release >= 1.22.0 and < 2.0.0 +def agronaVersion = '1.23.0' +def agronaVersionRange = '[1.23.0,2.0[' // allow any release >= 1.23.0 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From d0c2fbec8e58da0c91c8685eb890f9d190fdabe8 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:27:29 +0200 Subject: [PATCH 1217/1594] 1.33.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index f1b6e31361..7aa332e416 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.33.0-SNAPSHOT +1.33.0 From 7bf33de90a20ad41862eba538961db25310bf026 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:27:40 +0200 Subject: [PATCH 1218/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 7aa332e416..6214e03b71 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.33.0 +1.34.0-SNAPSHOT From ded4e486b8dd6312eaa20991491cc5872669fae6 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:28:24 +0200 Subject: [PATCH 1219/1594] [Java] Use type-safe version. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 16ddc10efe..48da2f29e0 100644 --- a/build.gradle +++ b/build.gradle @@ -185,7 +185,7 @@ subprojects { toolchain { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } - sourceCompatibility = 17 + sourceCompatibility = JavaVersion.VERSION_17 } checkstyle.toolVersion = "${checkstyleVersion}" From ce67429d152a0ecd7c32f5865771c2945e7e7156 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 23:48:23 +0200 Subject: [PATCH 1220/1594] [CI] Fix publish workflow. --- .github/workflows/release.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c34e4a7408..837f2eaf09 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,11 +56,6 @@ jobs: with: distribution: 'zulu' java-version: 17 - - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION - run: | - java -Xinternalversion - echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV - echo "BUILD_JAVA_VERSION=8" >> $GITHUB_ENV - name: Publish with Gradle run: ./gradlew publish env: From 844bca43ebc87f06e8b8dfa9404c07a3d981ea04 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 23:48:42 +0200 Subject: [PATCH 1221/1594] 1.33.0 released v2. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 6214e03b71..7aa332e416 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.34.0-SNAPSHOT +1.33.0 From f9baab6caff7d424ce3761d993b06e0f96ed4f2d Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 23 Aug 2024 23:48:54 +0200 Subject: [PATCH 1222/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 7aa332e416..6214e03b71 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.33.0 +1.34.0-SNAPSHOT From 95f353bc1887089099c6b6b79ac02e339ccf6892 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 24 Aug 2024 11:56:52 +0200 Subject: [PATCH 1223/1594] [Java] Simplify versioning. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 48da2f29e0..2bc3c8d4e2 100644 --- a/build.gradle +++ b/build.gradle @@ -62,7 +62,7 @@ def jqwikVersion = '1.9.0' def jsonVersion = '20240303' def jmhVersion = '1.37' def agronaVersion = '1.23.0' -def agronaVersionRange = '[1.23.0,2.0[' // allow any release >= 1.23.0 and < 2.0.0 +def agronaVersionRange = "[${agronaVersion},2.0[" def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From 0d13aea3ec9d8cb810bef5bc62dbd402ff845a9a Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 24 Aug 2024 12:02:19 +0200 Subject: [PATCH 1224/1594] [Java] Use JUnit BOM. --- build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2bc3c8d4e2..85d7a38edf 100644 --- a/build.gradle +++ b/build.gradle @@ -297,7 +297,8 @@ project(':sbe-tool') { implementation files("${layout.buildDirectory.get()}/classes/java/generated") implementation "org.hamcrest:hamcrest:${hamcrestVersion}" implementation "org.mockito:mockito-core:${mockitoVersion}" - implementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" + implementation platform("org.junit:junit-bom:${junitVersion}") + implementation "org.junit.jupiter:junit-jupiter-params" } } From 2f5e8ab3d1d5fb024e5d5296fee3a97a7889adf8 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:21:24 +0200 Subject: [PATCH 1225/1594] [Java] Upgrade to Checkstyle 10.18.0. --- build.gradle | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 85d7a38edf..6328a54f99 100644 --- a/build.gradle +++ b/build.gradle @@ -54,7 +54,7 @@ def toolchainLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } -def checkstyleVersion = '9.3' +def checkstyleVersion = '10.18.0' def hamcrestVersion = '3.0' def mockitoVersion = '5.12.0' def junitVersion = '5.11.0' @@ -163,6 +163,11 @@ allprojects { configurations.configureEach { resolutionStrategy { failOnVersionConflict() + // patching conflicting Checkstyle dependencies + force "org.codehaus.plexus:plexus-utils:3.3.0", + "org.apache.commons:commons-lang3:3.8.1", + "org.apache.httpcomponents:httpcore:4.4.14", + "commons-codec:commons-codec:1.15" } } From bb984d44205c77998fd3a8505beadd9e9f02fc3c Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Fri, 30 Aug 2024 11:37:41 +0100 Subject: [PATCH 1226/1594] [Java] Fix #1012 DTO char array setter visibility. Previously, the setter was generated as package-private rather than public. --- .../uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java index 4b8ceb876d..9b22f240f6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -1359,7 +1359,7 @@ private void generateArrayProperty( classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("void ").append(formattedPropertyName) + .append(indent).append("public void ").append(formattedPropertyName) .append("(").append(typeName).append(" value)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append(validateMethod).append("(value);\n") From e0846a80d24f26b5d1ab0b1394285ba45aad14a0 Mon Sep 17 00:00:00 2001 From: Grzegorz Gierlach Date: Sun, 1 Sep 2024 11:56:16 +0200 Subject: [PATCH 1227/1594] [Rust] Indicate the anonymous lifetime in set's Display impl. (#1014) --- .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 9df137c80a..5ed04fc9fb 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1112,7 +1112,7 @@ private static void generateSingleBitSet( indent(writer, 0, "impl core::fmt::Debug for %s {\n", bitSetType); indent(writer, 1, "#[inline]\n"); - indent(writer, 1, "fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {\n"); + indent(writer, 1, "fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n"); indent(writer, 2, "write!(fmt, \"%s[", bitSetType); final StringBuilder builder = new StringBuilder(); From eca18dd4ab61b275927fc9bc68fbe050851ea6a1 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 1 Sep 2024 12:01:41 +0200 Subject: [PATCH 1228/1594] [Java] Upgrade to JUnit 5.13.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6328a54f99..242fbb845b 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '10.18.0' def hamcrestVersion = '3.0' -def mockitoVersion = '5.12.0' +def mockitoVersion = '5.13.0' def junitVersion = '5.11.0' def jqwikVersion = '1.9.0' def jsonVersion = '20240303' From 99db7a8434fbba6dac9d5f7fbb510833cccd1d93 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Mon, 2 Sep 2024 12:03:47 +0100 Subject: [PATCH 1229/1594] [Java] Style consistency and add JavadocVariable Checkstyle test. --- config/checkstyle/checkstyle.xml | 3 ++ config/checkstyle/suppressions.xml | 1 + .../sbe/properties/DtosPropertyTest.java | 17 +++---- .../sbe/properties/JsonPropertyTest.java | 5 +-- .../sbe/properties/ParserPropertyTest.java | 1 - .../arbitraries/SbeArbitraries.java | 7 ++- .../schema/CompositeTypeSchema.java | 2 - .../schema/EncodedDataTypeSchema.java | 7 +-- .../sbe/properties/schema/EnumTypeSchema.java | 2 - .../sbe/properties/schema/FieldSchema.java | 4 +- .../sbe/properties/schema/GroupSchema.java | 2 - .../sbe/properties/schema/MessageSchema.java | 1 - .../sbe/properties/schema/SetSchema.java | 2 - .../schema/TestXmlSchemaWriter.java | 45 +++++++------------ .../sbe/properties/schema/TypeSchema.java | 1 - .../properties/schema/TypeSchemaVisitor.java | 1 - .../sbe/properties/schema/VarDataSchema.java | 1 - .../utils/InMemoryOutputManager.java | 12 +---- 18 files changed, 36 insertions(+), 78 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 4f40d0b3fa..f34d3bd2e5 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -33,6 +33,9 @@ + + + diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml index 2823a9547e..b7a043008b 100644 --- a/config/checkstyle/suppressions.xml +++ b/config/checkstyle/suppressions.xml @@ -7,5 +7,6 @@ + diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java index b21ba27674..93508ad709 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java @@ -64,8 +64,8 @@ public class DtosPropertyTest @Property void javaDtoEncodeShouldBeTheInverseOfDtoDecode( @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage, - final Footnotes footnotes - ) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, + final Footnotes footnotes) + throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { final String packageName = encodedMessage.ir().applicableNamespace(); @@ -136,8 +136,8 @@ void javaDtoEncodeShouldBeTheInverseOfDtoDecode( @Property void csharpDtoEncodeShouldBeTheInverseOfDtoDecode( @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage, - final Footnotes footnotes - ) throws IOException, InterruptedException + final Footnotes footnotes) + throws IOException, InterruptedException { final Path tempDir = Files.createTempDirectory("sbe-csharp-dto-test"); @@ -201,17 +201,14 @@ void csharpDtoEncodeShouldBeTheInverseOfDtoDecode( @Property(shrinking = ShrinkingMode.OFF) void cppDtoEncodeShouldBeTheInverseOfDtoDecode( @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage, - final Footnotes footnotes - ) throws IOException, InterruptedException + final Footnotes footnotes) throws IOException, InterruptedException { final Path tempDir = Files.createTempDirectory("sbe-cpp-dto-test"); try { final NamespaceOutputManager outputManager = new NamespaceOutputManager( - tempDir.toString(), - "sbe_property_test" - ); + tempDir.toString(), "sbe_property_test"); try { @@ -244,7 +241,7 @@ void cppDtoEncodeShouldBeTheInverseOfDtoDecode( { throw new AssertionError( "Input and output files differ\n\n" + - "SCHEMA:\n" + encodedMessage.schema()); + "SCHEMA:\n" + encodedMessage.schema()); } } catch (final Throwable throwable) diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java index a9b8cd0987..f3d49fbbe7 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties; import net.jqwik.api.Arbitrary; @@ -29,9 +28,7 @@ public class JsonPropertyTest { @Property - void shouldGenerateValidJson( - @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage - ) + void shouldGenerateValidJson(@ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage) { final StringBuilder output = new StringBuilder(); final JsonPrinter printer = new JsonPrinter(encodedMessage.ir()); diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java index 1b59dca624..3be05c85ae 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties; import net.jqwik.api.Arbitrary; diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index a47a93eabf..b8543b0abd 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties.arbitraries; import net.jqwik.api.Arbitraries; @@ -268,9 +267,7 @@ private static Arbitrary varDataSchema() (short)0, (short)0, (short)1, - (short)2 - ) - ); + (short)2)); } public static Arbitrary messageSchema() @@ -352,8 +349,10 @@ public static CharacterArbitrary chars(final CharGenerationMode mode) { case UNRESTRICTED: return Arbitraries.chars(); + case JSON_PRINTER_COMPATIBLE: return Arbitraries.chars().alpha(); + default: throw new IllegalArgumentException("Unsupported mode: " + mode); } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java index 06123ffc9f..264a49219d 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties.schema; import java.util.List; @@ -32,7 +31,6 @@ public List fields() return fields; } - @Override public void accept(final TypeSchemaVisitor visitor) { visitor.onComposite(this); diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java index 7abc254e0b..ea9d3228bb 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties.schema; import uk.co.real_logic.sbe.PrimitiveType; @@ -30,8 +29,7 @@ public EncodedDataTypeSchema( final PrimitiveType primitiveType, final int length, final Encoding.Presence presence, - final boolean isEmbedded - ) + final boolean isEmbedded) { this.primitiveType = primitiveType; this.length = length; @@ -54,16 +52,13 @@ public Encoding.Presence presence() return presence; } - @Override public boolean isEmbedded() { return isEmbedded; } - @Override public void accept(final TypeSchemaVisitor visitor) { visitor.onEncoded(this); } - } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java index fa28ef0a3a..b129e54c71 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties.schema; import java.util.List; @@ -41,7 +40,6 @@ public List validValues() return validValues; } - @Override public void accept(final TypeSchemaVisitor visitor) { visitor.onEnum(this); diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java index 9745b042a1..1cf9cc2ccf 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties.schema; import uk.co.real_logic.sbe.ir.Encoding; @@ -27,8 +26,7 @@ public final class FieldSchema public FieldSchema( final TypeSchema type, final Encoding.Presence presence, - final short sinceVersion - ) + final short sinceVersion) { assert sinceVersion == 0 || presence.equals(Encoding.Presence.OPTIONAL); this.type = type; diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java index 2aa3dcd3c3..c0fafb0dbf 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties.schema; import java.util.Comparator; @@ -54,5 +53,4 @@ public List varData() { return varData; } - } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java index d992d6559f..edde5e89b6 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties.schema; import java.util.Comparator; diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java index 5acbc9da40..071f8e7419 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties.schema; import java.util.Set; @@ -41,7 +40,6 @@ public Set choices() return choices; } - @Override public void accept(final TypeSchemaVisitor visitor) { visitor.onSet(this); diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java index b7e3d6f8c1..faeaab331b 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java @@ -13,20 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties.schema; -import uk.co.real_logic.sbe.ir.Encoding; import org.agrona.collections.MutableInteger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; +import uk.co.real_logic.sbe.ir.Encoding; -import java.io.File; -import java.io.StringWriter; -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; @@ -34,6 +28,11 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import java.io.File; +import java.io.StringWriter; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; import static java.util.Objects.requireNonNull; @@ -81,8 +80,7 @@ private static void writeTo( final TypeSchemaConverter typeSchemaConverter = new TypeSchemaConverter( document, topLevelTypes, - typeToName - ); + typeToName); final Set visitedTypes = new HashSet<>(); appendTypes( @@ -197,15 +195,13 @@ private static Element createTypesElement(final Document document) createTypeElement(document, "blockLength", "uint16"), createTypeElement(document, "templateId", "uint16"), createTypeElement(document, "schemaId", "uint16"), - createTypeElement(document, "version", "uint16") - )); + createTypeElement(document, "version", "uint16"))); types.appendChild(createCompositeElement( document, "groupSizeEncoding", createTypeElement(document, "blockLength", "uint16"), - createTypeElement(document, "numInGroup", "uint16") - )); + createTypeElement(document, "numInGroup", "uint16"))); return types; } @@ -256,8 +252,7 @@ private static Element createEnumElement( private static Element createCompositeElement( final Document document, final String name, - final Element... types - ) + final Element... types) { final Element composite = document.createElement("composite"); composite.setAttribute("name", name); @@ -377,10 +372,9 @@ private TypeSchemaConverter( this.document = document; this.topLevelTypes = topLevelTypes; this.typeToName = typeToName; - nextName = ignored -> "Type" + typeToName.size(); + nextName = (ignored) -> "Type" + typeToName.size(); } - @Override public void onEncoded(final EncodedDataTypeSchema type) { result = createTypeElement( @@ -392,7 +386,6 @@ public void onEncoded(final EncodedDataTypeSchema type) ); } - @Override public void onComposite(final CompositeTypeSchema type) { final Element[] members = type.fields().stream() @@ -403,14 +396,13 @@ public void onComposite(final CompositeTypeSchema type) final Element member = members[i]; member.setAttribute("name", "member" + i + "Of" + member.getAttribute("name")); } + result = createCompositeElement( document, typeToName.computeIfAbsent(type, nextName), - members - ); + members); } - @Override public void onEnum(final EnumTypeSchema type) { result = createEnumElement( @@ -421,15 +413,13 @@ public void onEnum(final EnumTypeSchema type) ); } - @Override public void onSet(final SetSchema type) { result = createSetElement( document, typeToName.computeIfAbsent(type, nextName), type.encodingType(), - type.choices() - ); + type.choices()); } private Element embedOrReference(final TypeSchema type) @@ -464,8 +454,8 @@ public Element convert(final TypeSchema type) public Node convert(final VarDataSchema varData) { - final Element lengthElement = createTypeElement(document, "length", - varData.lengthEncoding().primitiveName()); + final Element lengthElement = createTypeElement( + document, "length", varData.lengthEncoding().primitiveName()); if (varData.lengthEncoding().size() >= 4) { @@ -484,8 +474,7 @@ public Node convert(final VarDataSchema varData) document, typeToName.computeIfAbsent(varData, nextName), lengthElement, - varDataElement - ); + varDataElement); } } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java index ca236a0673..4a359fa6be 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties.schema; public interface TypeSchema diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java index 2651febfc7..7dbc69188f 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties.schema; public interface TypeSchemaVisitor diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java index 1bfd64621d..a4298e89e7 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties.schema; import uk.co.real_logic.sbe.PrimitiveType; diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java index a17f74914e..dc8482c525 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package uk.co.real_logic.sbe.properties.utils; import org.agrona.generation.DynamicPackageOutputManager; +import javax.tools.*; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.StringWriter; @@ -26,7 +26,6 @@ import java.net.URL; import java.net.URLClassLoader; import java.util.*; -import javax.tools.*; /** * An implementation of {@link DynamicPackageOutputManager} that stores generated source code in memory and compiles it @@ -43,13 +42,11 @@ public InMemoryOutputManager(final String packageName) this.packageName = packageName; } - @Override public Writer createOutput(final String name) { return new InMemoryWriter(name); } - @Override public void setPackageName(final String packageName) { packageNameOverride = packageName; @@ -71,8 +68,7 @@ public URLClassLoader compileGeneratedSources() null, null, null, - sourceFiles.values() - ); + sourceFiles.values()); if (!task.call()) { @@ -106,7 +102,6 @@ class InMemoryWriter extends StringWriter this.name = name; } - @Override public void close() throws IOException { super.close(); @@ -135,7 +130,6 @@ static class InMemoryFileManager extends ForwardingJavaFileManager Date: Tue, 10 Sep 2024 00:29:04 +0200 Subject: [PATCH 1230/1594] [Java] Upgrade to Gradle 8.10.1. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 242fbb845b..40ea2a3d45 100644 --- a/build.gradle +++ b/build.gradle @@ -961,7 +961,7 @@ tasks.named('dependencyUpdates').configure { } wrapper { - gradleVersion = '8.10' + gradleVersion = '8.10.1' distributionType = 'ALL' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 66cd5a0e49..1ed247ec13 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 159a03f2a2c7e3621d87927ad06869fb569de6f2 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 12 Sep 2024 14:40:39 +0200 Subject: [PATCH 1231/1594] [Java] Upgrade to Shadow 8.3.1. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 40ea2a3d45..d86c838098 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ buildscript { plugins { id 'java-library' id 'jvm-test-suite' - id 'com.gradleup.shadow' version '8.3.0' apply false + id 'com.gradleup.shadow' version '8.3.1' apply false id 'com.github.ben-manes.versions' version '0.51.0' } From 4d4d6e4a6687a5327066e1cfd318e359365202a5 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 13 Sep 2024 13:53:36 +0200 Subject: [PATCH 1232/1594] [Java] Use version catalogs. --- build.gradle | 54 ++++++++++----------------------------- gradle/libs.versions.toml | 18 +++++++++++++ 2 files changed, 32 insertions(+), 40 deletions(-) create mode 100644 gradle/libs.versions.toml diff --git a/build.gradle b/build.gradle index d86c838098..454e2f1e0f 100644 --- a/build.gradle +++ b/build.gradle @@ -18,22 +18,11 @@ import java.nio.file.Files import java.nio.file.StandardOpenOption import java.security.MessageDigest -buildscript { - repositories { - gradlePluginPortal() - mavenCentral() - } - dependencies { - classpath 'org.ow2.asm:asm:9.7' - classpath 'org.ow2.asm:asm-commons:9.7' - } -} - plugins { id 'java-library' id 'jvm-test-suite' - id 'com.gradleup.shadow' version '8.3.1' apply false - id 'com.github.ben-manes.versions' version '0.51.0' + alias(libs.plugins.shadow).apply(false) + alias(libs.plugins.versions) } defaultTasks 'clean', 'build' @@ -54,16 +43,6 @@ def toolchainLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(buildJavaVersion) } -def checkstyleVersion = '10.18.0' -def hamcrestVersion = '3.0' -def mockitoVersion = '5.13.0' -def junitVersion = '5.11.0' -def jqwikVersion = '1.9.0' -def jsonVersion = '20240303' -def jmhVersion = '1.37' -def agronaVersion = '1.23.0' -def agronaVersionRange = "[${agronaVersion},2.0[" - def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() @@ -193,7 +172,7 @@ subprojects { sourceCompatibility = JavaVersion.VERSION_17 } - checkstyle.toolVersion = "${checkstyleVersion}" + checkstyle.toolVersion = libs.versions.checkstyle.get() tasks.withType(Sign).configureEach { onlyIf { @@ -219,7 +198,7 @@ subprojects { options.encoding = 'UTF-8' options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' - options.links("https://www.javadoc.io/doc/org.agrona/agrona/${agronaVersion}/") + options.links("https://www.javadoc.io/doc/org.agrona/agrona/${libs.versions.agrona.get()}/") if (buildJavaVersion >= 23) { // early access JavaDoc location is different options.links("https://download.java.net/java/early_access/jdk${buildJavaVersion}/docs/api/") } @@ -232,7 +211,7 @@ subprojects { testing { suites { test { - useJUnitJupiter junitVersion + useJUnitJupiter libs.versions.junit.get() targets { all { @@ -267,12 +246,7 @@ project(':sbe-tool') { apply plugin: 'signing' dependencies { - api("org.agrona:agrona") { - version { - strictly(agronaVersionRange) - prefer(agronaVersion) - } - } + api libs.agrona } def generatedDir = "${layout.buildDirectory.get()}/generated-src" @@ -300,9 +274,9 @@ project(':sbe-tool') { test { dependencies { implementation files("${layout.buildDirectory.get()}/classes/java/generated") - implementation "org.hamcrest:hamcrest:${hamcrestVersion}" - implementation "org.mockito:mockito-core:${mockitoVersion}" - implementation platform("org.junit:junit-bom:${junitVersion}") + implementation libs.hamcrest + implementation libs.mockito + implementation platform("org.junit:junit-bom:${libs.versions.junit.get()}") implementation "org.junit.jupiter:junit-jupiter-params" } } @@ -310,16 +284,16 @@ project(':sbe-tool') { propertyTest(JvmTestSuite) { // We should be able to use _only_ the JQwik engine, but this issue is outstanding: // https://github.com/gradle/gradle/issues/21299 - useJUnitJupiter junitVersion + useJUnitJupiter libs.versions.junit.get() dependencies { implementation project() - implementation("net.jqwik:jqwik:${jqwikVersion}") { + implementation(libs.jqwik) { // Exclude JUnit 5 dependencies that are already provided due to useJUnitJupiter exclude group: 'org.junit.platform', module: 'junit-platform-commons' exclude group: 'org.junit.platform', module: 'junit-platform-engine' } - implementation "org.json:json:${jsonVersion}" + implementation libs.json } @@ -611,8 +585,8 @@ project(':sbe-benchmarks') { apply plugin: 'com.gradleup.shadow' dependencies { - implementation "org.openjdk.jmh:jmh-core:${jmhVersion}" - annotationProcessor "org.openjdk.jmh:jmh-generator-annprocess:${jmhVersion}" + implementation libs.jmh.core + annotationProcessor libs.jmh.generator.annprocess implementation project(':sbe-tool') implementation files("${layout.buildDirectory.get()}/classes/java/generated") } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000000..7ef3fad716 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,18 @@ +[versions] +agrona = "1.23.0" +checkstyle = "10.18.1" +junit = "5.11.0" +jmh = "1.37" + +[libraries] +agrona = { group = "org.agrona", name = "agrona", version = { strictly = "[1.23, 2.0[", require = "1.23.0" } } +mockito = { group = "org.mockito", name = "mockito-core", version = "5.13.0" } +hamcrest = { group = "org.hamcrest", name = "hamcrest", version = "3.0" } +jqwik = { group = "net.jqwik", name = "jqwik", version = "1.9.0" } +json = { group = "org.json", name = "json", version = "20240303" } +jmh-core = { group = "org.openjdk.jmh", name = "jmh-core", version.ref = "jmh" } +jmh-generator-annprocess = { group = "org.openjdk.jmh", name = "jmh-generator-annprocess", version.ref = "jmh" } + +[plugins] +versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } +shadow = { id = "com.gradleup.shadow", version = "8.3.1" } From 4ba4fcb4ba2c4413e0a153a3667f31a1f98fa923 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:20:08 +0100 Subject: [PATCH 1233/1594] [Java] Upgrade to Shadow 8.3.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7ef3fad716..117d4bbf02 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,4 +15,4 @@ jmh-generator-annprocess = { group = "org.openjdk.jmh", name = "jmh-generator-an [plugins] versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } -shadow = { id = "com.gradleup.shadow", version = "8.3.1" } +shadow = { id = "com.gradleup.shadow", version = "8.3.2" } From 60cfa7a6c6f8aef6f7630d00bfacb11adf72a776 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Sep 2024 13:41:03 +0200 Subject: [PATCH 1234/1594] 1.33.1 released --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 6214e03b71..02261bead1 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.34.0-SNAPSHOT +1.33.1 From c8ff5804190b01ea031c451d8e315911341729f9 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Sep 2024 13:41:17 +0200 Subject: [PATCH 1235/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 02261bead1..6214e03b71 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.33.1 +1.34.0-SNAPSHOT From afc1066821a3cd2b3017561c573b21197d9cf920 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 24 Sep 2024 11:52:39 +0200 Subject: [PATCH 1236/1594] [Java] Upgrade to Gradle 8.10.2. --- build.gradle | 2 +- gradle/libs.versions.toml | 1 + gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 454e2f1e0f..ebfc61a04d 100644 --- a/build.gradle +++ b/build.gradle @@ -935,7 +935,7 @@ tasks.named('dependencyUpdates').configure { } wrapper { - gradleVersion = '8.10.1' + gradleVersion = libs.versions.gradle.get() distributionType = 'ALL' } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 117d4bbf02..3b524b84bd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,6 +3,7 @@ agrona = "1.23.0" checkstyle = "10.18.1" junit = "5.11.0" jmh = "1.37" +gradle = "8.10.2" [libraries] agrona = { group = "org.agrona", name = "agrona", version = { strictly = "[1.23, 2.0[", require = "1.23.0" } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1ed247ec13..79eb9d003f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 0a3fb51a9bd86492adfe5ca1b2dfc1622b4d1de6 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 24 Sep 2024 13:42:57 +0200 Subject: [PATCH 1237/1594] [Gradle] Disable auto detection of JVMs to force a specific JVM for test execution in CI. --- gradle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/gradle.properties b/gradle.properties index 13abd18beb..5d926397cb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,4 @@ +org.gradle.java.installations.auto-detect=false org.gradle.java.installations.auto-download=false org.gradle.java.installations.fromEnv=BUILD_JAVA_HOME From ae8a211065a865cc003516112937a1daeb72fb14 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 25 Sep 2024 13:04:55 +0200 Subject: [PATCH 1238/1594] [Java] Upgrade to JUnit 5.11.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3b524b84bd..d91feb3580 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] agrona = "1.23.0" checkstyle = "10.18.1" -junit = "5.11.0" +junit = "5.11.1" jmh = "1.37" gradle = "8.10.2" From f83f986794cbdba8e0c33d36a9c3bd3fd66abb17 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Thu, 26 Sep 2024 23:33:24 +0100 Subject: [PATCH 1239/1594] [Java] Fix bug in DTO `decodeFrom` signature. It was using `short` for `actingVersion` and `blockLength`, but the inner call to `Decoder#wrap` expects an `int` (in the `uint16` range) for both arguments. There were a bunch of down/narrowing casts in tests, which I should have spotted when doing the port and have now been removed. --- .../co/real_logic/sbe/generation/java/JavaDtoGenerator.java | 2 +- .../uk/co/real_logic/sbe/properties/DtosPropertyTest.java | 6 +++--- .../java/uk/co/real_logic/sbe/generation/java/DtoTest.java | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java index 9b22f240f6..b922bd14ed 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -470,7 +470,7 @@ private static void generateDecodeFrom( .append("\n") .append(indent).append("public static ").append(dtoClassName).append(" decodeFrom(") .append("DirectBuffer buffer, int offset, ") - .append("short actingBlockLength, short actingVersion)\n") + .append("int actingBlockLength, int actingVersion)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append(decoderClassName).append(" decoder = new ") .append(decoderClassName).append("();\n") diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java index 93508ad709..8df61fe2b3 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java @@ -101,7 +101,7 @@ void javaDtoEncodeShouldBeTheInverseOfDtoDecode( generatedClassLoader.loadClass(packageName + ".TestMessageDto"); final Method decodeFrom = - dtoClass.getMethod("decodeFrom", DirectBuffer.class, int.class, short.class, short.class); + dtoClass.getMethod("decodeFrom", DirectBuffer.class, int.class, int.class, int.class); final Method encodeWith = dtoClass.getMethod("encodeWithHeaderWith", dtoClass, MutableDirectBuffer.class, int.class); @@ -109,8 +109,8 @@ void javaDtoEncodeShouldBeTheInverseOfDtoDecode( final int inputLength = encodedMessage.length(); final ExpandableArrayBuffer inputBuffer = encodedMessage.buffer(); final MessageHeaderDecoder header = new MessageHeaderDecoder().wrap(inputBuffer, 0); - final short blockLength = (short)header.blockLength(); - final short actingVersion = (short)header.version(); + final int blockLength = header.blockLength(); + final int actingVersion = header.version(); final Object dto = decodeFrom.invoke(null, encodedMessage.buffer(), MessageHeaderDecoder.ENCODED_LENGTH, blockLength, actingVersion); outputBuffer.setMemory(0, outputBuffer.capacity(), (byte)0); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java index a28b0ac374..68b2fdce83 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java @@ -56,8 +56,7 @@ void shouldRoundTripCar2() final ExpandableArrayBuffer inputBuffer = new ExpandableArrayBuffer(); final int inputLength = encodeCar(inputBuffer, 0); - final CarDto dto = - CarDto.decodeFrom(inputBuffer, 0, (short)CarDecoder.BLOCK_LENGTH, (short)CarDecoder.SCHEMA_VERSION); + final CarDto dto = CarDto.decodeFrom(inputBuffer, 0, CarDecoder.BLOCK_LENGTH, CarDecoder.SCHEMA_VERSION); final ExpandableArrayBuffer outputBuffer = new ExpandableArrayBuffer(); final int outputLength = CarDto.encodeWith(dto, outputBuffer, 0); From edd15cc070be244f9d88af948024df2ab9a57f2f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 28 Sep 2024 13:14:36 +0200 Subject: [PATCH 1240/1594] [Java] Upgrade to Mockito 5.14.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d91feb3580..f2e62a353c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ gradle = "8.10.2" [libraries] agrona = { group = "org.agrona", name = "agrona", version = { strictly = "[1.23, 2.0[", require = "1.23.0" } } -mockito = { group = "org.mockito", name = "mockito-core", version = "5.13.0" } +mockito = { group = "org.mockito", name = "mockito-core", version = "5.14.0" } hamcrest = { group = "org.hamcrest", name = "hamcrest", version = "3.0" } jqwik = { group = "net.jqwik", name = "jqwik", version = "1.9.0" } json = { group = "org.json", name = "json", version = "20240303" } From fa49cc4103ff5d48c0d553e575d20652d243313f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:29:37 +0200 Subject: [PATCH 1241/1594] [Java] Upgrade to Mockito 5.14.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f2e62a353c..ca7ada31f3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ gradle = "8.10.2" [libraries] agrona = { group = "org.agrona", name = "agrona", version = { strictly = "[1.23, 2.0[", require = "1.23.0" } } -mockito = { group = "org.mockito", name = "mockito-core", version = "5.14.0" } +mockito = { group = "org.mockito", name = "mockito-core", version = "5.14.1" } hamcrest = { group = "org.hamcrest", name = "hamcrest", version = "3.0" } jqwik = { group = "net.jqwik", name = "jqwik", version = "1.9.0" } json = { group = "org.json", name = "json", version = "20240303" } From a677d84af6d5c30c77917ea30dc7da124d6c5e57 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 1 Oct 2024 16:57:39 +0200 Subject: [PATCH 1242/1594] [Java] Upgrade to Agrona 1.23.1. --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ca7ada31f3..bc10b558c4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,12 +1,12 @@ [versions] -agrona = "1.23.0" +agrona = "1.23.1" checkstyle = "10.18.1" junit = "5.11.1" jmh = "1.37" gradle = "8.10.2" [libraries] -agrona = { group = "org.agrona", name = "agrona", version = { strictly = "[1.23, 2.0[", require = "1.23.0" } } +agrona = { group = "org.agrona", name = "agrona", version = { strictly = "[1.23.1, 2.0[", require = "1.23.1" } } mockito = { group = "org.mockito", name = "mockito-core", version = "5.14.1" } hamcrest = { group = "org.hamcrest", name = "hamcrest", version = "3.0" } jqwik = { group = "net.jqwik", name = "jqwik", version = "1.9.0" } From 9237d173a115124355739b3c2dcd2c9aa18effc4 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 2 Oct 2024 15:01:05 +0200 Subject: [PATCH 1243/1594] [Java] Upgrade to Shadow 8.3.3. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bc10b558c4..1d8307bd35 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,4 +16,4 @@ jmh-generator-annprocess = { group = "org.openjdk.jmh", name = "jmh-generator-an [plugins] versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } -shadow = { id = "com.gradleup.shadow", version = "8.3.2" } +shadow = { id = "com.gradleup.shadow", version = "8.3.3" } From 153c985f5dfee59fc362e7d57c079e169873d475 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 6 Oct 2024 11:39:32 +0200 Subject: [PATCH 1244/1594] [Java] Upgrade to JUnit 5.11.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1d8307bd35..91ec4ad9f7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] agrona = "1.23.1" checkstyle = "10.18.1" -junit = "5.11.1" +junit = "5.11.2" jmh = "1.37" gradle = "8.10.2" From 338b2746e60d562924cef33fdb594a38a1f9d96f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 17 Oct 2024 22:44:54 +0200 Subject: [PATCH 1245/1594] [Java] Create DTO generator only if enabled. --- .../generation/TargetCodeGeneratorLoader.java | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index c031ad60a8..fbf7a9d0f0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -54,23 +54,23 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) ir, System.getProperty(JAVA_ENCODING_BUFFER_TYPE, JAVA_DEFAULT_ENCODING_BUFFER_TYPE), System.getProperty(JAVA_DECODING_BUFFER_TYPE, JAVA_DEFAULT_DECODING_BUFFER_TYPE), - "true".equals(System.getProperty(JAVA_GROUP_ORDER_ANNOTATION)), - "true".equals(System.getProperty(JAVA_GENERATE_INTERFACES)), - "true".equals(System.getProperty(DECODE_UNKNOWN_ENUM_VALUES)), - "true".equals(System.getProperty(TYPES_PACKAGE_OVERRIDE)), + Boolean.getBoolean(JAVA_GROUP_ORDER_ANNOTATION), + Boolean.getBoolean(JAVA_GENERATE_INTERFACES), + Boolean.getBoolean(DECODE_UNKNOWN_ENUM_VALUES), + Boolean.getBoolean(TYPES_PACKAGE_OVERRIDE), precedenceChecks(), outputManager); - final JavaDtoGenerator dtoGenerator = new JavaDtoGenerator(ir, outputManager); - - final CodeGenerator combinedGenerator = () -> + if (Boolean.getBoolean(JAVA_GENERATE_DTOS)) { - codecGenerator.generate(); - dtoGenerator.generate(); - }; - - final boolean generateDtos = "true".equals(System.getProperty(JAVA_GENERATE_DTOS)); - return generateDtos ? combinedGenerator : codecGenerator; + final JavaDtoGenerator dtoGenerator = new JavaDtoGenerator(ir, outputManager); + return () -> + { + codecGenerator.generate(); + dtoGenerator.generate(); + }; + } + return codecGenerator; } }, @@ -100,19 +100,21 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) { final NamespaceOutputManager outputManager = new NamespaceOutputManager( outputDir, ir.applicableNamespace()); - final boolean decodeUnknownEnumValues = "true".equals(System.getProperty(DECODE_UNKNOWN_ENUM_VALUES)); + final boolean decodeUnknownEnumValues = Boolean.getBoolean(DECODE_UNKNOWN_ENUM_VALUES); final CodeGenerator codecGenerator = new CppGenerator(ir, decodeUnknownEnumValues, precedenceChecks(), outputManager); - final CodeGenerator dtoGenerator = new CppDtoGenerator(ir, outputManager); - final CodeGenerator combinedGenerator = () -> - { - codecGenerator.generate(); - dtoGenerator.generate(); - }; - final boolean generateDtos = "true".equals(System.getProperty(CPP_GENERATE_DTOS)); - return generateDtos ? combinedGenerator : codecGenerator; + if (Boolean.getBoolean(CPP_GENERATE_DTOS)) + { + final CodeGenerator dtoGenerator = new CppDtoGenerator(ir, outputManager); + return () -> + { + codecGenerator.generate(); + dtoGenerator.generate(); + }; + } + return codecGenerator; } }, From 385bffe05f3b7cecf3227c667ac3561a62a0b173 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 21 Oct 2024 21:20:07 +0200 Subject: [PATCH 1246/1594] [Java] Upgrade to JUnit 5.11.3. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 91ec4ad9f7..57cb9ede9d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] agrona = "1.23.1" checkstyle = "10.18.1" -junit = "5.11.2" +junit = "5.11.3" jmh = "1.37" gradle = "8.10.2" From b5df61657818e2d83bcca863fed589464b2b9750 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 21 Oct 2024 21:20:21 +0200 Subject: [PATCH 1247/1594] [Java] Upgrade to Mockito 5.14.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 57cb9ede9d..b9ad02c53a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ gradle = "8.10.2" [libraries] agrona = { group = "org.agrona", name = "agrona", version = { strictly = "[1.23.1, 2.0[", require = "1.23.1" } } -mockito = { group = "org.mockito", name = "mockito-core", version = "5.14.1" } +mockito = { group = "org.mockito", name = "mockito-core", version = "5.14.2" } hamcrest = { group = "org.hamcrest", name = "hamcrest", version = "3.0" } jqwik = { group = "net.jqwik", name = "jqwik", version = "1.9.0" } json = { group = "org.json", name = "json", version = "20240303" } From 956a46b18ac892e7f5efc8bcab55f4cb7ea96c7c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 21 Oct 2024 21:23:25 +0200 Subject: [PATCH 1248/1594] [Java] Upgrade to CheckStyle 10.18.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b9ad02c53a..e8889233da 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "1.23.1" -checkstyle = "10.18.1" +checkstyle = "10.18.2" junit = "5.11.3" jmh = "1.37" gradle = "8.10.2" From e34fc03617d2d42acf90f44db574aeceb11cb71c Mon Sep 17 00:00:00 2001 From: Elvis Wang Date: Fri, 25 Oct 2024 15:45:59 +0800 Subject: [PATCH 1249/1594] Help decoding multiple messages using rust by resolving #987 (#991) * Add new arguments for generated MessageDecoder#header method When decoding multiple messages from a single byte buffer, the second and following message decoder should offset to the new header offset plus header length. * Update code to reflect method signature change in decoder's header method * Add test for introduced changes --------- Co-authored-by: Elvis Wang --- build.gradle | 1 + rust/Cargo.toml | 3 +- rust/benches/car_benchmark.rs | 2 +- rust/benches/md_benchmark.rs | 2 +- rust/car_example_baseline_data.sbe | Bin 0 -> 207 bytes rust/car_example_extension_data.sbe | Bin 0 -> 207 bytes rust/tests/baseline_test.rs | 2 +- rust/tests/big_endian_test.rs | 2 +- rust/tests/extension_test.rs | 2 +- rust/tests/issue_435_test.rs | 2 +- rust/tests/issue_895_test.rs | 6 +- rust/tests/issue_972_test.rs | 2 +- rust/tests/issue_984_test.rs | 2 +- rust/tests/issue_987_test.rs | 71 ++++++++++++++++++ .../sbe/generation/rust/MessageCoderDef.java | 4 +- sbe-tool/src/test/resources/issue987.xml | 25 ++++++ 16 files changed, 112 insertions(+), 14 deletions(-) create mode 100644 rust/car_example_baseline_data.sbe create mode 100644 rust/car_example_extension_data.sbe create mode 100644 rust/tests/issue_987_test.rs create mode 100644 sbe-tool/src/test/resources/issue987.xml diff --git a/build.gradle b/build.gradle index ebfc61a04d..ebc9013168 100644 --- a/build.gradle +++ b/build.gradle @@ -652,6 +652,7 @@ tasks.register('generateRustTestCodecs', JavaExec) { 'sbe-tool/src/test/resources/issue895.xml', 'sbe-tool/src/test/resources/issue972.xml', 'sbe-tool/src/test/resources/issue984.xml', + 'sbe-tool/src/test/resources/issue987.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', 'sbe-tool/src/test/resources/nested-composite-name.xml', ] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 4be04c957b..6b265a3020 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -15,6 +15,7 @@ issue_435 = { path = "../generated/rust/issue435" } issue_895 = { path = "../generated/rust/issue895" } issue_972 = { path = "../generated/rust/issue972" } issue_984 = { path = "../generated/rust/issue984" } +issue_987 = { path = "../generated/rust/issue987" } baseline_bigendian = { path = "../generated/rust/baseline-bigendian" } nested_composite_name = { path = "../generated/rust/nested-composite-name" } @@ -27,4 +28,4 @@ harness = false [[bench]] name = "md_benchmark" -harness = false \ No newline at end of file +harness = false diff --git a/rust/benches/car_benchmark.rs b/rust/benches/car_benchmark.rs index 5f78fff1e4..44ed774c0e 100644 --- a/rust/benches/car_benchmark.rs +++ b/rust/benches/car_benchmark.rs @@ -131,7 +131,7 @@ fn decode(state: &State) -> SbeResult { let buf = ReadBuf::new(state.buffer.as_slice()); let header = MessageHeaderDecoder::default().wrap(buf, 0); - car = car.header(header); + car = car.header(header, 0); // Car... car.serial_number(); diff --git a/rust/benches/md_benchmark.rs b/rust/benches/md_benchmark.rs index 025df09f4f..27c3fa4939 100644 --- a/rust/benches/md_benchmark.rs +++ b/rust/benches/md_benchmark.rs @@ -90,7 +90,7 @@ fn decode_md(state: &State) -> SbeResult { let buf = ReadBuf::new(state.buffer.as_slice()); let header = MessageHeaderDecoder::default().wrap(buf, 0); - market_data = market_data.header(header); + market_data = market_data.header(header, 0); market_data.transact_time(); market_data.event_time_delta(); diff --git a/rust/car_example_baseline_data.sbe b/rust/car_example_baseline_data.sbe new file mode 100644 index 0000000000000000000000000000000000000000..0fd6c7e013786ac15e784a2e80cafadcb6121d21 GIT binary patch literal 207 zcmdO8U<5)2hD$6!0toK1GdhC!OhC*G#313sq~w&;G`0)uEQUtL%8Y&|*nm=U46|nP zJ8=W0LyM9U^AwyblXFtdfm|0SJ|O9wpPQ7Kmzn|*_Xdh6IPn5WkIeLp^2ADrFeA{K zc!*&P3=Ix8K=}_2DGbKO&W_0tVPoTBps=y=W1#TaGd7N_AS3egQW80V4Cl4p!^4i6b55sXUAlSu(5G5P}tb`F;MvI85>7dkP-QLDT$mwhI3|FX0k$9 LNG2PQ192n(19vIr literal 0 HcmV?d00001 diff --git a/rust/tests/baseline_test.rs b/rust/tests/baseline_test.rs index 58a8503d20..ab9eecb1fd 100644 --- a/rust/tests/baseline_test.rs +++ b/rust/tests/baseline_test.rs @@ -44,7 +44,7 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { let buf = ReadBuf::new(buffer); let header = MessageHeaderDecoder::default().wrap(buf, 0); assert_eq!(SBE_TEMPLATE_ID, header.template_id()); - car = car.header(header); + car = car.header(header, 0); // Car... assert_eq!(1234, car.serial_number()); diff --git a/rust/tests/big_endian_test.rs b/rust/tests/big_endian_test.rs index aabea63ce2..1bef7278dd 100644 --- a/rust/tests/big_endian_test.rs +++ b/rust/tests/big_endian_test.rs @@ -43,7 +43,7 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { let buf = ReadBuf::new(buffer); let header = MessageHeaderDecoder::default().wrap(buf, 0); assert_eq!(SBE_TEMPLATE_ID, header.template_id()); - car = car.header(header); + car = car.header(header, 0); // Car... assert_eq!(1234, car.serial_number()); diff --git a/rust/tests/extension_test.rs b/rust/tests/extension_test.rs index 072b9b8baa..d7258bc39b 100644 --- a/rust/tests/extension_test.rs +++ b/rust/tests/extension_test.rs @@ -43,7 +43,7 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> SbeResult<()> { let buf = ReadBuf::new(buffer); let header = MessageHeaderDecoder::default().wrap(buf, 0); assert_eq!(SBE_TEMPLATE_ID, header.template_id()); - car = car.header(header); + car = car.header(header, 0); // Car... assert_eq!(1234, car.serial_number()); diff --git a/rust/tests/issue_435_test.rs b/rust/tests/issue_435_test.rs index 8664be42cd..7b1a9f8ffe 100644 --- a/rust/tests/issue_435_test.rs +++ b/rust/tests/issue_435_test.rs @@ -33,7 +33,7 @@ fn issue_435_ref_test() -> SbeResult<()> { assert_eq!(SBE_SCHEMA_ID, header.schema_id()); assert_eq!(*SetRef::default().set_one(true), header.s()); - let decoder = Issue435Decoder::default().header(header); + let decoder = Issue435Decoder::default().header(header, 0); assert_eq!(EnumRef::Two, decoder.example_decoder().e()); Ok(()) diff --git a/rust/tests/issue_895_test.rs b/rust/tests/issue_895_test.rs index 96968d2459..cb58e82d85 100644 --- a/rust/tests/issue_895_test.rs +++ b/rust/tests/issue_895_test.rs @@ -27,7 +27,7 @@ fn issue_895_both_some() -> SbeResult<()> { assert_eq!(SBE_TEMPLATE_ID, header.template_id()); assert_eq!(SBE_SCHEMA_ID, header.schema_id()); - let decoder = Issue895Decoder::default().header(header); + let decoder = Issue895Decoder::default().header(header, 0); assert_eq!(Some(2.07), decoder.optional_float()); assert_eq!(Some(4.12), decoder.optional_double()); @@ -46,7 +46,7 @@ fn issue_895_float_none() -> SbeResult<()> { let buf = ReadBuf::new(buf.as_slice()); let header = MessageHeaderDecoder::default().wrap(buf, 0); - let decoder = Issue895Decoder::default().header(header); + let decoder = Issue895Decoder::default().header(header, 0); assert_eq!(None, decoder.optional_float()); assert_eq!(Some(4.12), decoder.optional_double()); @@ -65,7 +65,7 @@ fn issue_895_double_none() -> SbeResult<()> { let buf = ReadBuf::new(buffer.as_slice()); let header = MessageHeaderDecoder::default().wrap(buf, 0); - let decoder = Issue895Decoder::default().header(header); + let decoder = Issue895Decoder::default().header(header, 0); assert_eq!(Some(2.07), decoder.optional_float()); assert_eq!(None, decoder.optional_double()); diff --git a/rust/tests/issue_972_test.rs b/rust/tests/issue_972_test.rs index 2cbab324d0..bcf4cd77e8 100644 --- a/rust/tests/issue_972_test.rs +++ b/rust/tests/issue_972_test.rs @@ -26,7 +26,7 @@ fn round_trip() -> SbeResult<()> { assert_eq!(SBE_TEMPLATE_ID, header.template_id()); assert_eq!(SBE_SCHEMA_ID, header.schema_id()); - let decoder = Issue972Decoder::default().header(header); + let decoder = Issue972Decoder::default().header(header, 0); if let Either::Right(composite) = decoder.new_field_decoder() { assert_eq!(2007, composite.f1().unwrap()); assert_eq!(2012, composite.f2().unwrap()); diff --git a/rust/tests/issue_984_test.rs b/rust/tests/issue_984_test.rs index 7ca0dcfc76..74cae2eb07 100644 --- a/rust/tests/issue_984_test.rs +++ b/rust/tests/issue_984_test.rs @@ -34,7 +34,7 @@ fn round_trip() -> SbeResult<()> { assert_eq!(SBE_TEMPLATE_ID, header.template_id()); assert_eq!(SBE_SCHEMA_ID, header.schema_id()); - let simple_msg_decoder = SimpleMessageDecoder::default().header(header); + let simple_msg_decoder = SimpleMessageDecoder::default().header(header, 0); assert_eq!(1985, simple_msg_decoder.id()); let mut grp_decoder = simple_msg_decoder.my_group_decoder(); assert_eq!(1, grp_decoder.count()); diff --git a/rust/tests/issue_987_test.rs b/rust/tests/issue_987_test.rs new file mode 100644 index 0000000000..4462f58b52 --- /dev/null +++ b/rust/tests/issue_987_test.rs @@ -0,0 +1,71 @@ +use issue_987::{ + issue_987_codec::{Issue987Decoder, Issue987Encoder, SBE_BLOCK_LENGTH, SBE_SCHEMA_ID, SBE_SCHEMA_VERSION, SBE_TEMPLATE_ID}, message_header_codec::MessageHeaderDecoder, * +}; + +fn create_encoder(buffer: &mut Vec, off: usize) -> Issue987Encoder { + let encoder = Issue987Encoder::default().wrap( + WriteBuf::new(buffer.as_mut_slice()), + off + message_header_codec::ENCODED_LENGTH, + ); + let mut header = encoder.header(off); + header.parent().unwrap() +} + +#[test] +fn encode_2_messages_and_then_decode() -> SbeResult<()> { + let mut buffer = vec![0u8; 256]; + + let mut off = 0; + + // encode message 1 + let mut encoder = create_encoder(&mut buffer, off); + encoder.old_field(10); + let mut other_encoder = encoder.new_field_encoder(); + other_encoder.f1(11); + other_encoder.f2(12); + let encoder = other_encoder.parent().unwrap(); + + // Update offset + off += message_header_codec::ENCODED_LENGTH + encoder.encoded_length(); + + // encode message 2 + let mut encoder = create_encoder(&mut buffer, off); + encoder.old_field(20); + let mut other_encoder = encoder.new_field_encoder(); + other_encoder.f1(21); + other_encoder.f2(22); + + // decoding ... + off = 0; + + // decode message 1 + let buf = ReadBuf::new(buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, off); + assert_eq!(SBE_BLOCK_LENGTH, header.block_length()); + assert_eq!(SBE_SCHEMA_VERSION, header.version()); + assert_eq!(SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(SBE_SCHEMA_ID, header.schema_id()); + let decoder = Issue987Decoder::default().header(header, off); + assert_eq!(10, decoder.old_field()); + let other_decoder = decoder.new_field_decoder(); + assert_eq!(11, other_decoder.f1()); + assert_eq!(12, other_decoder.f2()); + + // Update offset + off += message_header_codec::ENCODED_LENGTH + decoder.encoded_length(); + + // decode message 2 + let buf = ReadBuf::new(buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, off); + assert_eq!(SBE_BLOCK_LENGTH, header.block_length()); + assert_eq!(SBE_SCHEMA_VERSION, header.version()); + assert_eq!(SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(SBE_SCHEMA_ID, header.schema_id()); + let decoder = Issue987Decoder::default().header(header, off); + assert_eq!(20, decoder.old_field()); + let other_decoder = decoder.new_field_decoder(); + assert_eq!(21, other_decoder.f1()); + assert_eq!(22, other_decoder.f2()); + + Ok(()) +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index 67c37f22fd..8faaa9c451 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -141,13 +141,13 @@ void appendMessageHeaderEncoderFn(final Appendable out) throws IOException void appendMessageHeaderDecoderFn(final Appendable out) throws IOException { - indent(out, 2, "pub fn header(self, mut header: MessageHeaderDecoder>) -> Self {\n"); + indent(out, 2, "pub fn header(self, mut header: MessageHeaderDecoder>, offset: usize) -> Self {\n"); indent(out, 3, "debug_assert_eq!(SBE_TEMPLATE_ID, header.template_id());\n"); indent(out, 3, "let acting_block_length = header.block_length();\n"); indent(out, 3, "let acting_version = header.version();\n\n"); indent(out, 3, "self.wrap(\n"); indent(out, 4, "header.parent().unwrap(),\n"); - indent(out, 4, "message_header_codec::ENCODED_LENGTH,\n"); + indent(out, 4, "offset + message_header_codec::ENCODED_LENGTH,\n"); indent(out, 4, "acting_block_length,\n"); indent(out, 4, "acting_version,\n"); indent(out, 3, ")\n"); diff --git a/sbe-tool/src/test/resources/issue987.xml b/sbe-tool/src/test/resources/issue987.xml new file mode 100644 index 0000000000..4daebc019d --- /dev/null +++ b/sbe-tool/src/test/resources/issue987.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + From da547ccd5a6710f3596771a2cf536cbca0f07380 Mon Sep 17 00:00:00 2001 From: Ethan Date: Tue, 29 Oct 2024 05:40:55 -0400 Subject: [PATCH 1250/1594] [Go] SBE implementation in Go using flyweights (#951) * [Go] SBE implementation in Go using flyweights #765 To generate flyweights instead of structs, set the following flag: ``` sbe.go.generate.generate.flyweights=true ``` * [Go] Checkstyle fix * [Go] Fix null string return value * [Go] Remove spurious type definition for choices * [Go] Fix formatting in WrapForDecode * [Go] Add returning an array by []byte * [Go] Fix array not present in version * [Go] Add ComputeLength methods * [Go] Fix some compiler warnings and remove unused code * [Go] Draft of OTF decoder * [Go] Add OTF Json Printer * [Go] Fix SbeBlockAndHeaderLength and add constants for composite sizes * [Go] Add IrDecoder for runtime types * [Go] Add enum get method * [Go] Fixes for updating component counts in irdecoder * [Go] Run goimports * [Go] Update with latest changes * [Go] Change the file structure for GOPATH * [Go] Fix copywrite year * [Go] Fix tests for otf This generates flyweights in the sbe-tool build for use in the otf library. * [Go] Add helpers for otf PrimitiveValue --- .gitignore | 37 +- README.md | 2 + build.gradle | 100 +- gocode/Makefile | 74 +- gocode/README.md | 10 +- .../src/baseline-bigendian/Car_test.go | 146 + gocode/flyweight/src/baseline/Car_test.go | 138 + .../src/basic/SBE tests/ENUM_test.go | 12 + .../src/basic/SBE tests/Message1_test.go | 29 + .../flyweight/src/basic/SBE tests/SET_test.go | 28 + .../flyweight/src/composite/Composite_test.go | 52 + .../src/composite_elements/Message_test.go | 91 + .../src/example-schema/CarExample_test.go | 572 +++ .../src/group/SBE tests/TestMessage1_test.go | 55 + .../src/group_with_data/TestMessages_test.go | 200 + .../Extension_test.go | 210 + .../flyweight/src/issue435/Issue435_test.go | 48 + .../flyweight/src/issue472/Issue472_test.go | 27 + .../flyweight/src/issue483/Issue483_test.go | 35 + .../flyweight/src/issue488/Issue488_test.go | 9 + .../flyweight/src/issue560/Issue560_test.go | 28 + .../src/issue847/issue847_test.go | 0 .../src/issue848/issue848_test.go | 0 .../src/issue849/issue849_test.go | 0 .../{ => flyweight}/src/mktdata/fixme_test.go | 0 gocode/flyweight/src/otf/go.mod | 10 + gocode/flyweight/src/otf/go.sum | 18 + gocode/flyweight/src/otf/json_test.go | 114 + gocode/flyweight/src/otf/otf_test.go | 159 + gocode/flyweight/src/otf/testlistener.go | 311 ++ gocode/flyweight/src/simple/simple_test.go | 46 + .../since-deprecated/SinceDeprecated_test.go | 23 + .../vardata/SBE tests/TestMessage1_test.go | 27 + gocode/go.mod | 7 + gocode/go.sum | 7 + .../src/baseline-bigendian/Car_test.go | 0 gocode/{ => struct}/src/baseline/Car_test.go | 0 .../src/basic/SBE tests/ENUM_test.go | 0 .../src/basic/SBE tests/Message1_test.go | 0 .../src/basic/SBE tests/SET_test.go | 0 .../src/composite/Composite_test.go | 0 .../src/composite_elements/Message_test.go | 0 .../src/example-schema/CarExample.go | 0 .../src/example-schema/CarExample_test.go | 0 .../clientserver.go | 0 .../src/group/SBE tests/TestMessage1_test.go | 0 .../src/group_with_data/TestMessages_test.go | 0 .../Extension_test.go | 0 .../src/issue435/Issue435_test.go | 0 .../src/issue472/Issue472_test.go | 0 .../src/issue483/Issue483_test.go | 0 .../src/issue488/Issue488_test.go | 0 .../src/issue505/Issue505_test.go | 0 .../src/issue560/Issue560_test.go | 0 gocode/struct/src/issue847/issue847_test.go | 9 + gocode/struct/src/issue848/issue848_test.go | 9 + gocode/struct/src/issue849/issue849_test.go | 9 + gocode/struct/src/mktdata/fixme_test.go | 10 + .../src/mktdata/preallocated_test.go | 0 gocode/{ => struct}/src/simple/simple_test.go | 0 .../since-deprecated/SinceDeprecated_test.go | 0 gocode/{ => struct}/src/test973/EventType.go | 0 .../{ => struct}/src/test973/MessageHeader.go | 0 .../src/test973/SbeMarshalling.go | 0 .../{ => struct}/src/test973/SomeMessage.go | 0 .../{ => struct}/src/test973/test973_test.go | 0 .../vardata/SBE tests/TestMessage1_test.go | 0 sbe-tool/src/main/golang/.gitignore | 1 + sbe-tool/src/main/golang/go.mod | 3 + sbe-tool/src/main/golang/go.sum | 17 + sbe-tool/src/main/golang/json/json_printer.go | 76 + .../main/golang/json/json_token_listener.go | 410 ++ sbe-tool/src/main/golang/main.go | 3 + sbe-tool/src/main/golang/otf/encoding.go | 673 ++++ sbe-tool/src/main/golang/otf/irdecoder.go | 355 ++ .../src/main/golang/otf/otfheaderdecoder.go | 105 + .../src/main/golang/otf/otfmessagedecoder.go | 311 ++ sbe-tool/src/main/golang/otf/token.go | 162 + .../java/uk/co/real_logic/sbe/SbeTool.java | 6 + .../generation/TargetCodeGeneratorLoader.java | 20 +- .../flyweight/GolangFlyweightGenerator.java | 3382 +++++++++++++++++ .../GolangFlyweightOutputManager.java | 72 + .../golang/flyweight/GolangFlyweightUtil.java | 224 ++ .../golang/{ => struct}/GolangGenerator.java | 4 +- .../{ => struct}/GolangOutputManager.java | 2 +- .../golang/{ => struct}/GolangUtil.java | 2 +- ...st.java => GolangStructGeneratorTest.java} | 3 +- 87 files changed, 8428 insertions(+), 65 deletions(-) create mode 100644 gocode/flyweight/src/baseline-bigendian/Car_test.go create mode 100644 gocode/flyweight/src/baseline/Car_test.go create mode 100644 gocode/flyweight/src/basic/SBE tests/ENUM_test.go create mode 100644 gocode/flyweight/src/basic/SBE tests/Message1_test.go create mode 100644 gocode/flyweight/src/basic/SBE tests/SET_test.go create mode 100644 gocode/flyweight/src/composite/Composite_test.go create mode 100644 gocode/flyweight/src/composite_elements/Message_test.go create mode 100644 gocode/flyweight/src/example-schema/CarExample_test.go create mode 100644 gocode/flyweight/src/group/SBE tests/TestMessage1_test.go create mode 100644 gocode/flyweight/src/group_with_data/TestMessages_test.go create mode 100644 gocode/flyweight/src/group_with_data_extension/Extension_test.go create mode 100644 gocode/flyweight/src/issue435/Issue435_test.go create mode 100644 gocode/flyweight/src/issue472/Issue472_test.go create mode 100644 gocode/flyweight/src/issue483/Issue483_test.go create mode 100644 gocode/flyweight/src/issue488/Issue488_test.go create mode 100644 gocode/flyweight/src/issue560/Issue560_test.go rename gocode/{ => flyweight}/src/issue847/issue847_test.go (100%) rename gocode/{ => flyweight}/src/issue848/issue848_test.go (100%) rename gocode/{ => flyweight}/src/issue849/issue849_test.go (100%) rename gocode/{ => flyweight}/src/mktdata/fixme_test.go (100%) create mode 100644 gocode/flyweight/src/otf/go.mod create mode 100644 gocode/flyweight/src/otf/go.sum create mode 100644 gocode/flyweight/src/otf/json_test.go create mode 100644 gocode/flyweight/src/otf/otf_test.go create mode 100644 gocode/flyweight/src/otf/testlistener.go create mode 100644 gocode/flyweight/src/simple/simple_test.go create mode 100644 gocode/flyweight/src/since-deprecated/SinceDeprecated_test.go create mode 100644 gocode/flyweight/src/vardata/SBE tests/TestMessage1_test.go create mode 100644 gocode/go.mod create mode 100644 gocode/go.sum rename gocode/{ => struct}/src/baseline-bigendian/Car_test.go (100%) rename gocode/{ => struct}/src/baseline/Car_test.go (100%) rename gocode/{ => struct}/src/basic/SBE tests/ENUM_test.go (100%) rename gocode/{ => struct}/src/basic/SBE tests/Message1_test.go (100%) rename gocode/{ => struct}/src/basic/SBE tests/SET_test.go (100%) rename gocode/{ => struct}/src/composite/Composite_test.go (100%) rename gocode/{ => struct}/src/composite_elements/Message_test.go (100%) rename gocode/{ => struct}/src/example-schema/CarExample.go (100%) rename gocode/{ => struct}/src/example-schema/CarExample_test.go (100%) rename gocode/{ => struct}/src/example-socket-clientserver/clientserver.go (100%) rename gocode/{ => struct}/src/group/SBE tests/TestMessage1_test.go (100%) rename gocode/{ => struct}/src/group_with_data/TestMessages_test.go (100%) rename gocode/{ => struct}/src/group_with_data_extension/Extension_test.go (100%) rename gocode/{ => struct}/src/issue435/Issue435_test.go (100%) rename gocode/{ => struct}/src/issue472/Issue472_test.go (100%) rename gocode/{ => struct}/src/issue483/Issue483_test.go (100%) rename gocode/{ => struct}/src/issue488/Issue488_test.go (100%) rename gocode/{ => struct}/src/issue505/Issue505_test.go (100%) rename gocode/{ => struct}/src/issue560/Issue560_test.go (100%) create mode 100644 gocode/struct/src/issue847/issue847_test.go create mode 100644 gocode/struct/src/issue848/issue848_test.go create mode 100644 gocode/struct/src/issue849/issue849_test.go create mode 100644 gocode/struct/src/mktdata/fixme_test.go rename gocode/{ => struct}/src/mktdata/preallocated_test.go (100%) rename gocode/{ => struct}/src/simple/simple_test.go (100%) rename gocode/{ => struct}/src/since-deprecated/SinceDeprecated_test.go (100%) rename gocode/{ => struct}/src/test973/EventType.go (100%) rename gocode/{ => struct}/src/test973/MessageHeader.go (100%) rename gocode/{ => struct}/src/test973/SbeMarshalling.go (100%) rename gocode/{ => struct}/src/test973/SomeMessage.go (100%) rename gocode/{ => struct}/src/test973/test973_test.go (100%) rename gocode/{ => struct}/src/vardata/SBE tests/TestMessage1_test.go (100%) create mode 100644 sbe-tool/src/main/golang/.gitignore create mode 100644 sbe-tool/src/main/golang/go.mod create mode 100644 sbe-tool/src/main/golang/go.sum create mode 100644 sbe-tool/src/main/golang/json/json_printer.go create mode 100644 sbe-tool/src/main/golang/json/json_token_listener.go create mode 100644 sbe-tool/src/main/golang/main.go create mode 100644 sbe-tool/src/main/golang/otf/encoding.go create mode 100644 sbe-tool/src/main/golang/otf/irdecoder.go create mode 100644 sbe-tool/src/main/golang/otf/otfheaderdecoder.go create mode 100644 sbe-tool/src/main/golang/otf/otfmessagedecoder.go create mode 100644 sbe-tool/src/main/golang/otf/token.go create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightOutputManager.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java rename sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/{ => struct}/GolangGenerator.java (99%) rename sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/{ => struct}/GolangOutputManager.java (98%) rename sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/{ => struct}/GolangUtil.java (98%) rename sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/{GolangGeneratorTest.java => GolangStructGeneratorTest.java} (99%) diff --git a/.gitignore b/.gitignore index 4ffe2537bc..4e46271843 100644 --- a/.gitignore +++ b/.gitignore @@ -65,31 +65,18 @@ cppbuild/Win32 # golang gocode/pkg -gocode/src/baseline/*.go -!gocode/src/baseline/*_test.go -gocode/src/baseline-bigendian/*.go -!gocode/src/baseline-bigendian/*_test.go -gocode/src/composite/*.go -!gocode/src/composite/*_test.go -gocode/src/composite_elements/*.go -!gocode/src/composite_elements/*_test.go -gocode/src/since-deprecated/*.go -!gocode/src/since-deprecated/*_test.go -gocode/src/group_with_data*/*.go -!gocode/src/group_with_data*/*_test.go -gocode/src/mktdata/*.go -!gocode/src/mktdata/*_test.go -gocode/src/simple/*.go -!gocode/src/simple/*_test.go -gocode/src/issue*/*.go -!gocode/src/issue*/*_test.go -gocode/src/*/*/*.go -!gocode/src/*/*/*_test.go -gocode/src/example-schema/example-schema* -gocode/src/example-schema/cpu.out -gocode/src/example-socket-clientserver/example-socket-clientserver -gocode/src/extension -gocode/src/extension2 +gocode/*/pkg +gocode/struct/src/*/*.go +!gocode/struct/src/*/*_test.go +gocode/struct/src/*/*/*.go +!gocode/struct/src/*/*/*_test.go +gocode/struct/src/example-schema/example-schema* +gocode/struct/src/example-socket-clientserver/example-socket-clientserver +gocode/flyweight/src/*/*.go +!gocode/flyweight/src/*/*_test.go +gocode/flyweight/src/*/*/*.go +!gocode/flyweight/src/*/*/*_test.go +gocode/flyweight/src/otf/code-generation-schema.sbeir # csharp csharp/*/bin diff --git a/README.md b/README.md index c393d2dd26..26efe26f10 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,8 @@ For convenience on Linux, a gnu Makefile is provided that runs some tests and co $ cd gocode # make # test, examples, bench +Go supports both generating Go structs with encode / decode methods, and flyweights like the other languages. Structs are generated by default for compatibility. Set `sbe.go.generate.generate.flyweights=true` to generate flyweights. + Users of golang generated code should see the [user documentation](https://github.com/real-logic/simple-binary-encoding/wiki/Golang-User-Guide). diff --git a/build.gradle b/build.gradle index ebc9013168..40bbbbef9c 100644 --- a/build.gradle +++ b/build.gradle @@ -700,7 +700,7 @@ tasks.register('generateGolangCodecTestComposite', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'gocode/src', + 'sbe.output.dir': 'gocode/struct/src', 'sbe.target.language': 'golang') args = ['sbe-tool/src/test/resources/composite-elements-schema-rc4.xml'] } @@ -709,7 +709,7 @@ tasks.register('generateGolangCodecTestBasic', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'gocode/src/basic', + 'sbe.output.dir': 'gocode/struct/src/basic', 'sbe.target.language': 'golang') args = ['sbe-tool/src/test/resources/basic-types-schema.xml'] } @@ -718,7 +718,7 @@ tasks.register('generateGolangCodecTestGroup', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'gocode/src/group', + 'sbe.output.dir': 'gocode/struct/src/group', 'sbe.target.language': 'golang') args = ['sbe-tool/src/test/resources/basic-group-schema.xml'] } @@ -727,7 +727,7 @@ tasks.register('generateGolangCodecTestVarData', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'gocode/src/vardata', + 'sbe.output.dir': 'gocode/struct/src/vardata', 'sbe.target.language': 'golang') args = ['sbe-tool/src/test/resources/basic-variable-length-schema.xml'] } @@ -736,7 +736,7 @@ tasks.register('generateGolangCodecsWithXIncludes', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'gocode/src', + 'sbe.output.dir': 'gocode/struct/src', 'sbe.target.language': 'golang', 'sbe.xinclude.aware': 'true', 'sbe.validation.xsd': validationXsdPath) @@ -748,7 +748,87 @@ tasks.register('generateGolangCodecsWithXSD', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( - 'sbe.output.dir': 'gocode/src', + 'sbe.output.dir': 'gocode/struct/src', + 'sbe.target.language': 'golang', + 'sbe.xinclude.aware': 'true', + 'sbe.validation.xsd': validationXsdPath) + args = ['sbe-tool/src/test/resources/group-with-data-schema.xml', + 'sbe-tool/src/test/resources/FixBinary.xml', + 'sbe-tool/src/test/resources/issue435.xml', + 'sbe-tool/src/test/resources/issue472.xml', + 'sbe-tool/src/test/resources/issue483.xml', + 'sbe-tool/src/test/resources/issue488.xml', + 'sbe-tool/src/test/resources/issue560.xml', + 'sbe-tool/src/test/resources/issue661.xml', + 'sbe-tool/src/test/resources/issue847.xml', + 'sbe-tool/src/test/resources/issue848.xml', + 'sbe-tool/src/test/resources/issue849.xml', + 'sbe-tool/src/test/resources/since-deprecated-test-schema.xml', + 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', + 'gocode/resources/example-composite.xml', + 'gocode/resources/group-with-data-extension-schema.xml', + 'gocode/resources/simple.xml'] +} + +tasks.register('generateGolangFlyweightCodecTestComposite', JavaExec) { + mainClass.set('uk.co.real_logic.sbe.SbeTool') + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'gocode/flyweight/src', + 'sbe.go.generate.generate.flyweights': 'true', + 'sbe.target.language': 'golang') + args = ['sbe-tool/src/test/resources/composite-elements-schema-rc4.xml'] +} + +tasks.register('generateGolangFlyweightCodecTestBasic', JavaExec) { + mainClass.set('uk.co.real_logic.sbe.SbeTool') + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'gocode/flyweight/src/basic', + 'sbe.go.generate.generate.flyweights': 'true', + 'sbe.target.language': 'golang') + args = ['sbe-tool/src/test/resources/basic-types-schema.xml'] +} + +tasks.register('generateGolangFlyweightCodecTestGroup', JavaExec) { + mainClass.set('uk.co.real_logic.sbe.SbeTool') + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'gocode/flyweight/src/group', + 'sbe.go.generate.generate.flyweights': 'true', + 'sbe.target.language': 'golang') + args = ['sbe-tool/src/test/resources/basic-group-schema.xml'] +} + +tasks.register('generateGolangFlyweightCodecTestVarData', JavaExec) { + mainClass.set('uk.co.real_logic.sbe.SbeTool') + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'gocode/flyweight/src/vardata', + 'sbe.go.generate.generate.flyweights': 'true', + 'sbe.target.language': 'golang') + args = ['sbe-tool/src/test/resources/basic-variable-length-schema.xml'] +} + +tasks.register('generateGolangFlyweightCodecsWithXIncludes', JavaExec) { + mainClass.set('uk.co.real_logic.sbe.SbeTool') + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'gocode/flyweight/src', + 'sbe.go.generate.generate.flyweights': 'true', + 'sbe.target.language': 'golang', + 'sbe.xinclude.aware': 'true', + 'sbe.validation.xsd': validationXsdPath) + args = ['sbe-samples/src/main/resources/example-schema.xml', + 'sbe-samples/src/main/resources/example-extension-schema.xml'] +} + +tasks.register('generateGolangFlyweightCodecsWithXSD', JavaExec) { + mainClass.set('uk.co.real_logic.sbe.SbeTool') + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'gocode/flyweight/src', + 'sbe.go.generate.generate.flyweights': 'true', 'sbe.target.language': 'golang', 'sbe.xinclude.aware': 'true', 'sbe.validation.xsd': validationXsdPath) @@ -780,6 +860,13 @@ tasks.register('generateGolangCodecs') { 'generateGolangCodecTestComposite', 'generateGolangCodecsWithXIncludes', 'generateGolangCodecsWithXSD', + 'generateGolangFlyweightCodecTestVarData', + 'generateGolangFlyweightCodecTestGroup', + 'generateGolangFlyweightCodecTestBasic', + 'generateGolangFlyweightCodecTestComposite', + 'generateGolangFlyweightCodecsWithXIncludes', + 'generateGolangFlyweightCodecsWithXSD', + 'generateIrCodecs', ':sbe-all:jar' } @@ -868,6 +955,7 @@ tasks.register('generateGolangIrCodecs', JavaExec) { systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/golang', 'sbe.target.language': 'golang', + 'sbe.go.generate.generate.flyweights': true, 'sbe.validation.xsd': validationXsdPath) args = ['sbe-tool/src/main/resources/sbe-ir.xml'] } diff --git a/gocode/Makefile b/gocode/Makefile index eebb2b4f38..a635c61f1d 100644 --- a/gocode/Makefile +++ b/gocode/Makefile @@ -19,11 +19,11 @@ all: example test # bench # This target is used to build golang files using parent gradle # script's invocation of sbe-tool in case it needs to be run again. We # use this one output file to check that dependency as it's simple -DEP=src/simple/SbeMarshalling.go +DEP=struct/src/simple/SbeMarshalling.go $(DEP): $(SBE_JAR) (cd ..; ./gradlew generateGolangCodecs) - (export GOPATH=$(GOPATH) && \ - cd src/simple && \ + (export GOPATH=$(GOPATH)/struct && \ + cd struct/src/simple && \ go build && \ $(SAVE_FORMAT) \ go fmt && \ @@ -31,27 +31,27 @@ $(DEP): $(SBE_JAR) # Will regenerate codecs by removing dependencies clean: - rm -f src/*/SbeMarshalling.go src/*/*/SbeMarshalling.go + rm -f struct/src/*/SbeMarshalling.go struct/src/*/*/SbeMarshalling.go -# Example code and benchmarking -example: src/example-schema/example-schema -src/example-schema/example-schema: $(DEP) - (export GOPATH=$(GOPATH) && \ - cd src/example-schema && \ +# Example code and benchmarking +example: struct/src/example-schema/example-schema +struct/src/example-schema/example-schema: $(DEP) + (export GOPATH=$(GOPATH)/struct && \ + cd struct/src/example-schema && \ go build && \ go fmt && \ ./example-schema) bench: $(DEP) - (export GOPATH=$(GOPATH) && \ - cd src/example-schema && \ + (export GOPATH=$(GOPATH)/struct && \ + cd struct/src/example-schema && \ go test --bench . -cpuprofile=cpu.out && \ go tool pprof -text example-schema.test cpu.out) -src/baseline/SbeMarshalling.go: $(DEP) +struct/src/baseline/SbeMarshalling.go: $(DEP) $(GOPATH)/sbe-tool -d src -s $(EXAMPLES_SCHEMA) - (export GOPATH=$(GOPATH) && \ - cd src/baseline && \ + (export GOPATH=$(GOPATH)/struct && \ + cd struct/src/baseline && \ go build && \ go fmt && \ go test && \ @@ -59,29 +59,59 @@ src/baseline/SbeMarshalling.go: $(DEP) # The first set does a make install as there is a test that uses # multiple packages and needs them in GOPATH The second set work in -# src/foo, and the third need a GOPATH addition as for Java and C++ +# struct/src/foo, and the third need a GOPATH addition as for Java and C++ # they generate into the same directory but golang doesn't allow that test: $(DEP) - (export GOPATH=$(GOPATH) && \ + (export GOPATH=$(GOPATH)/struct && \ (for t in baseline extension; do \ - export GOPATH=$(GOPATH) && \ - cd $(GOPATH)/src/$$t && \ + export GOPATH=$(GOPATH)/struct && \ + cd $(GOPATH)/struct/src/$$t && \ go build && \ go fmt && \ go test && \ go install \ ;done)) - (export GOPATH=$(GOPATH) && \ + (export GOPATH=$(GOPATH)/struct && \ (for t in baseline-bigendian mktdata group_with_data group_with_data_extension composite_elements composite since-deprecated simple issue435 issue472 issue483 issue488 issue560 issue847 issue848 issue849 issue505 test973; do \ - cd $(GOPATH)/src/$$t && \ + cd $(GOPATH)/struct/src/$$t && \ go build && \ go fmt && \ go test \ ;done)) (for t in vardata group basic; do \ - export GOPATH=$(GOPATH)/$$t && \ - cd $(GOPATH)/src/$$t/'SBE tests' && \ + export GOPATH=$(GOPATH)/struct/$$t && \ + cd $(GOPATH)/struct/src/$$t/'SBE tests' && \ go build && \ go fmt && \ go test \ ;done) + (export GOPATH=$(GOPATH)/flyweight && \ + (for t in baseline extension; do \ + export GOPATH=$(GOPATH)/flyweight && \ + cd $(GOPATH)/flyweight/src/$$t && \ + go build && \ + go fmt && \ + go test && \ + go install \ + ;done)) + (export GOPATH=$(GOPATH)/flyweight && \ + (for t in baseline-bigendian mktdata group_with_data group_with_data_extension composite_elements composite since-deprecated simple issue435 issue472 issue483 issue488 issue560 issue847 issue848 issue849; do \ + cd $(GOPATH)/flyweight/src/$$t && \ + go build && \ + go fmt && \ + go test \ + ;done)) + (for t in vardata group basic; do \ + export GOPATH=$(GOPATH)/flyweight/$$t && \ + cd $(GOPATH)/flyweight/src/$$t/'SBE tests' && \ + go build && \ + go fmt && \ + go test \ + ;done) + (export SBE_JAR=$(SBE_JAR) && \ + export GO111MODULE=on && \ + (cd $(GOPATH)/flyweight/src/otf && \ + go generate && \ + go build && \ + go fmt && \ + go test)) diff --git a/gocode/README.md b/gocode/README.md index fb8b994539..5740d9dbca 100755 --- a/gocode/README.md +++ b/gocode/README.md @@ -5,10 +5,13 @@ There is now a [user guide](https://github.com/real-logic/simple-binary-encoding/wiki/Golang-User-Guide) and this document is for development of the SBE golang generator. +Go supports both generating Go structs with encode / decode methods, and flyweights like the other languages. +Structs are generated by default for compatibility. Set `sbe.go.generate.generate.flyweights=true` to generate flyweights. + Code Layout ----------- The Java code that performs the generation of golang code is -[here](https://github.com/real-logic/simple-binary-encoding/tree/master/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang). +[here](https://github.com/real-logic/simple-binary-encoding/tree/master/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang). There is both a struct and a flyweight generator. Golang code used for testing resides in the top-level [gocode directory](https://github.com/real-logic/simple-binary-encoding/tree/master/gocode). @@ -24,11 +27,12 @@ the build environment, example and test code are structured into a top level gocode directory hierarchy. Code is generated into this structure with pre-existing test code in place. +There are tests for both the struct and flyweight styles of generated code. For the example, the code is generated into a library and the matching example code lives in it's own directory at the same level. For example, the example-schema generates the baseline library code into -`gocode/src/baseline` and example code lives in `gocode/src/example-schema`. +`gocode/src/struct/baseline` and example code lives in `gocode/src/example-schema`. To use this layout you should `set GOPATH=/path/to/gocode` or use the supplied Makefile which does this for you. For the tests you will need @@ -60,5 +64,3 @@ generator processes. Roadmap ======= * Windows developer support (currently tested on Linux/MacOS) - * Further Unicode support - * Testing/Bug fixes diff --git a/gocode/flyweight/src/baseline-bigendian/Car_test.go b/gocode/flyweight/src/baseline-bigendian/Car_test.go new file mode 100644 index 0000000000..d06ed4102a --- /dev/null +++ b/gocode/flyweight/src/baseline-bigendian/Car_test.go @@ -0,0 +1,146 @@ +package baseline_bigendian + +import ( + _ "fmt" + "testing" +) + +func TestEncodeDecodeCar(t *testing.T) { + var data [256]byte + var in Car + in.WrapForEncode(data[:], 0, uint64(len(data))) + + in.SetSerialNumber(1234). + SetModelYear(2000). + SetAvailable(BooleanType_T). + SetCode(Model_A). + SetVehicleCode("abcdef") + + in.SetSomeNumbersIndex(0, 0) + in.SetSomeNumbersIndex(1, 1) + in.SetSomeNumbersIndex(2, 2) + in.SetSomeNumbersIndex(3, 3) + in.SetSomeNumbersIndex(4, 4) + + in.Extras(). + SetCruiseControl(true). + SetSportsPack(true) + + in.Engine(). + SetCapacity(2000). + SetNumCylinders(4). + SetManufacturerCode("123"). + SetEfficiency(42). + SetBoosterEnabled(BooleanType_T). + Booster(). + SetBoostType(BoostType_NITROUS). + SetHorsePower(200) + + in.FuelFiguresCount(3).Next(). + SetSpeed(30). + SetMpg(35.9). + PutUsageDescription("Urban Cycle").Next(). + SetSpeed(55). + SetMpg(49.0). + PutUsageDescription("Combined Cycle").Next(). + SetSpeed(75). + SetMpg(40.0). + PutUsageDescription("Highway Cycle") + + performanceFigures := in.PerformanceFiguresCount(2) + performanceFigures.SetOctaneRating(95).Next(). + AccelerationCount(3). + SetMph(30). + SetSeconds(3.8).Next(). + SetMph(60). + SetSeconds(7.5).Next(). + SetMph(100). + SetSeconds(12.2) + performanceFigures.Next(). + SetOctaneRating(99). + AccelerationCount(3). + SetMph(30). + SetSeconds(3.8).Next(). + SetMph(60). + SetSeconds(7.5).Next(). + SetMph(100). + SetSeconds(12.2) + + in.PutManufacturer("123"). + PutModel("Civic VTi"). + PutActivationCode("deadbeef") + + var out Car + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeSchemaVersion()), + uint64(in.SbeBlockLength()), + uint64(len(data)), + ) + + if in.SerialNumber() != out.SerialNumber() { + t.Log("in.SerialNumber != out.SerialNumber:\n", in.SerialNumber(), out.SerialNumber()) + t.Fail() + } + if in.ModelYear() != out.ModelYear() { + t.Log("in.ModelYear != out.ModelYear:\n", in.ModelYear(), out.ModelYear()) + t.Fail() + } + if in.Available() != out.Available() { + t.Log("in.Available != out.Available:\n", in.Available(), out.Available()) + t.Fail() + } + if in.Code() != out.Code() { + t.Log("in.Code != out.Code:\n", in.Code(), out.Code()) + t.Fail() + } + for i, l := uint64(0), uint64(in.SomeNumbersLength()); i < l; i++ { + if in.SomeNumbersIndex(i) != out.SomeNumbersIndex(i) { + t.Log("in.SomeNumbers != out.SomeNumbers:\n", in.SomeNumbersIndex(i), out.SomeNumbersIndex(i)) + t.Fail() + } + } + for i, l := uint64(0), uint64(in.VehicleCodeLength()); i < l; i++ { + if in.VehicleCodeIndex(i) != out.VehicleCodeIndex(i) { + t.Log("in.VehicleCode != out.VehicleCode:\n", in.VehicleCodeIndex(i), out.VehicleCodeIndex(i)) + t.Fail() + } + } + if in.Extras().String() != out.Extras().String() { + t.Log("in.Extras != out.Extras:\n", in.Extras(), out.Extras()) + t.Fail() + } + + // DiscountedModel is constant + if Model_C != out.DiscountedModel() { + t.Log("in.DiscountedModel != out.DiscountedModel:\n", in.DiscountedModel(), out.DiscountedModel()) + t.Fail() + } + + if in.Engine().String() != out.Engine().String() { + t.Log("in.Engine != out.Engine:\n", in.Engine().String(), out.Engine().String()) + t.Fail() + } + + return + +} + +func TestDecodeJavaBuffer(t *testing.T) { + // The byte array is from the java example for interop test + // made by editing example-schgema to be bigendian and running + // with the example with -Dsbe.encoding.filename + // and then decoded using od -tu1 + data := []byte{0, 49, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 210, 7, 221, 1, 65, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 97, 98, 99, 100, 101, 102, 6, 7, 208, 4, 49, 50, 51, 35, 1, 78, 200, 0, 6, 0, 3, 0, 30, 66, 15, 153, 154, 0, 0, 0, 11, 85, 114, 98, 97, 110, 32, 67, 121, 99, 108, 101, 0, 55, 66, 68, 0, 0, 0, 0, 0, 14, 67, 111, 109, 98, 105, 110, 101, 100, 32, 67, 121, 99, 108, 101, 0, 75, 66, 32, 0, 0, 0, 0, 0, 13, 72, 105, 103, 104, 119, 97, 121, 32, 67, 121, 99, 108, 101, 0, 1, 0, 2, 95, 0, 6, 0, 3, 0, 30, 64, 128, 0, 0, 0, 60, 64, 240, 0, 0, 0, 100, 65, 67, 51, 51, 99, 0, 6, 0, 3, 0, 30, 64, 115, 51, 51, 0, 60, 64, 227, 51, 51, 0, 100, 65, 60, 204, 205, 0, 0, 0, 5, 72, 111, 110, 100, 97, 0, 0, 0, 9, 67, 105, 118, 105, 99, 32, 86, 84, 105, 0, 0, 0, 6, 97, 98, 99, 100, 101, 102} + + var c Car + c.WrapAndApplyHeader(data, 0, uint64(len(data))) + + expected := `{"Name": "Car", "sbeTemplateId": 1, "serialNumber": "1234", "modelYear": "2013", "available": "T", "code": "A", "someNumbers": [0,1,2,3,4], "vehicleCode": "abcdef", "extras": ["SportsPack","CruiseControl"], "discountedModel": "C", "engine": {"capacity": "2000", "numCylinders": "4", "manufacturerCode": "123", "efficiency": "35", "boosterEnabled": "T", "booster": {"BoostType": "NITROUS", "horsePower": "200"}}, "fuelFigures": [{"speed": "30", "mpg": "35.9", "usageDescription": "Urban Cycle"}, {"speed": "55", "mpg": "49", "usageDescription": "Combined Cycle"}, {"speed": "75", "mpg": "40", "usageDescription": "Highway Cycle"}], "performanceFigures": [{"octaneRating": "95", "acceleration": [{"mph": "30", "seconds": "4"}, {"mph": "60", "seconds": "7.5"}, {"mph": "100", "seconds": "12.2"}]}, {"octaneRating": "99", "acceleration": [{"mph": "30", "seconds": "3.8"}, {"mph": "60", "seconds": "7.1"}, {"mph": "100", "seconds": "11.8"}]}], "manufacturer": "Honda", "model": "Civic VTi", "activationCode": "abcdef"}` + if actual := c.String(); actual != expected { + t.Logf("Failed to decode car, expected %s, got %s", expected, actual) + t.Fail() + } + return +} diff --git a/gocode/flyweight/src/baseline/Car_test.go b/gocode/flyweight/src/baseline/Car_test.go new file mode 100644 index 0000000000..9aa2127b7a --- /dev/null +++ b/gocode/flyweight/src/baseline/Car_test.go @@ -0,0 +1,138 @@ +package baseline + +import ( + _ "fmt" + "testing" +) + +func TestEncodeDecodeCar(t *testing.T) { + var data [256]byte + var in Car + in.WrapForEncode(data[:], 0, uint64(len(data))) + + in.SetSerialNumber(1234). + SetModelYear(2000). + SetAvailable(BooleanType_T). + SetCode(Model_A). + PutSomeNumbersValues(0, 1, 2, 3). + SetVehicleCode("abcdef") + + in.Extras(). + SetCruiseControl(true). + SetSportsPack(true) + + in.Engine(). + SetCapacity(2000). + SetNumCylinders(4). + SetManufacturerCode("123"). + SetEfficiency(42). + SetBoosterEnabled(BooleanType_T). + Booster(). + SetBoostType(BoostType_NITROUS). + SetHorsePower(200) + + in.FuelFiguresCount(3).Next(). + SetSpeed(30). + SetMpg(35.9). + PutUsageDescription("Urban Cycle").Next(). + SetSpeed(55). + SetMpg(49.0). + PutUsageDescription("Combined Cycle").Next(). + SetSpeed(75). + SetMpg(40.0). + PutUsageDescription("Highway Cycle") + + performanceFigures := in.PerformanceFiguresCount(2) + performanceFigures.SetOctaneRating(95).Next(). + AccelerationCount(3). + SetMph(30). + SetSeconds(3.8).Next(). + SetMph(60). + SetSeconds(7.5).Next(). + SetMph(100). + SetSeconds(12.2) + performanceFigures.Next(). + SetOctaneRating(99). + AccelerationCount(3). + SetMph(30). + SetSeconds(3.8).Next(). + SetMph(60). + SetSeconds(7.5).Next(). + SetMph(100). + SetSeconds(12.2) + + in.PutManufacturer("123"). + PutModel("Civic VTi"). + PutActivationCode("deadbeef") + + var out Car + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeSchemaVersion()), + uint64(in.SbeBlockLength()), + uint64(len(data)), + ) + + if in.SerialNumber() != out.SerialNumber() { + t.Log("in.SerialNumber != out.SerialNumber:\n", in.SerialNumber(), out.SerialNumber()) + t.Fail() + } + if in.ModelYear() != out.ModelYear() { + t.Log("in.ModelYear != out.ModelYear:\n", in.ModelYear(), out.ModelYear()) + t.Fail() + } + if in.Available() != out.Available() { + t.Log("in.Available != out.Available:\n", in.Available(), out.Available()) + t.Fail() + } + if in.Code() != out.Code() { + t.Log("in.Code != out.Code:\n", in.Code(), out.Code()) + t.Fail() + } + for i, l := uint64(0), uint64(in.SomeNumbersLength()); i < l; i++ { + if in.SomeNumbersIndex(i) != out.SomeNumbersIndex(i) { + t.Log("in.SomeNumbers != out.SomeNumbers:\n", in.SomeNumbersIndex(i), out.SomeNumbersIndex(i)) + t.Fail() + } + } + for i, l := uint64(0), uint64(in.VehicleCodeLength()); i < l; i++ { + if in.VehicleCodeIndex(i) != out.VehicleCodeIndex(i) { + t.Log("in.VehicleCode != out.VehicleCode:\n", in.VehicleCodeIndex(i), out.VehicleCodeIndex(i)) + t.Fail() + } + } + if in.Extras().String() != out.Extras().String() { + t.Log("in.Extras != out.Extras:\n", in.Extras(), out.Extras()) + t.Fail() + } + + // DiscountedModel is constant + if Model_C != out.DiscountedModel() { + t.Log("in.DiscountedModel != out.DiscountedModel:\n", in.DiscountedModel(), out.DiscountedModel()) + t.Fail() + } + + if in.Engine().String() != out.Engine().String() { + t.Log("in.Engine != out.Engine:\n", in.Engine().String(), out.Engine().String()) + t.Fail() + } + + return + +} + +func TestDecodeJavaBuffer(t *testing.T) { + // See ~gocode/src/example-schema/CarExample.go for how this is generated + data := []byte{45, 0, 1, 0, 1, 0, 0, 0, 210, 4, 0, 0, 0, 0, 0, 0, 221, 7, 1, 65, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 97, 98, 99, 100, 101, 102, 6, 208, 7, 4, 49, 50, 51, 35, 1, 78, 200, 6, 0, 3, 0, 30, 0, 154, 153, 15, 66, 11, 0, 0, 0, 85, 114, 98, 97, 110, 32, 67, 121, 99, 108, 101, 55, 0, 0, 0, 68, 66, 14, 0, 0, 0, 67, 111, 109, 98, 105, 110, 101, 100, 32, 67, 121, 99, 108, 101, 75, 0, 0, 0, 32, 66, 13, 0, 0, 0, 72, 105, 103, 104, 119, 97, 121, 32, 67, 121, 99, 108, 101, 1, 0, 2, 0, 95, 6, 0, 3, 0, 30, 0, 0, 0, 128, 64, 60, 0, 0, 0, 240, 64, 100, 0, 51, 51, 67, 65, 99, 6, 0, 3, 0, 30, 0, 51, 51, 115, 64, 60, 0, 51, 51, 227, 64, 100, 0, 205, 204, 60, 65, 5, 0, 0, 0, 72, 111, 110, 100, 97, 9, 0, 0, 0, 67, 105, 118, 105, 99, 32, 86, 84, 105, 6, 0, 0, 0, 97, 98, 99, 100, 101, 102} + + var c Car + c.WrapAndApplyHeader(data, 0, uint64(len(data))) + + expected := `{"Name": "Car", "sbeTemplateId": 1, "serialNumber": "1234", "modelYear": "2013", "available": "T", "code": "A", "someNumbers": [1,2,3,4], "vehicleCode": "abcdef", "extras": ["SportsPack","CruiseControl"], "discountedModel": "C", "engine": {"capacity": "2000", "numCylinders": "4", "manufacturerCode": "123", "efficiency": "35", "boosterEnabled": "T", "booster": {"BoostType": "NITROUS", "horsePower": "200"}}, "fuelFigures": [{"speed": "30", "mpg": "35.9", "usageDescription": "Urban Cycle"}, {"speed": "55", "mpg": "49", "usageDescription": "Combined Cycle"}, {"speed": "75", "mpg": "40", "usageDescription": "Highway Cycle"}], "performanceFigures": [{"octaneRating": "95", "acceleration": [{"mph": "30", "seconds": "4"}, {"mph": "60", "seconds": "7.5"}, {"mph": "100", "seconds": "12.2"}]}, {"octaneRating": "99", "acceleration": [{"mph": "30", "seconds": "3.8"}, {"mph": "60", "seconds": "7.1"}, {"mph": "100", "seconds": "11.8"}]}], "manufacturer": "Honda", "model": "Civic VTi", "activationCode": "abcdef"}` + if actual := c.String(); actual != expected { + t.Logf("Failed to decode car, expected %s, got %s", expected, actual) + t.Fail() + } + return +} diff --git a/gocode/flyweight/src/basic/SBE tests/ENUM_test.go b/gocode/flyweight/src/basic/SBE tests/ENUM_test.go new file mode 100644 index 0000000000..0a3418592d --- /dev/null +++ b/gocode/flyweight/src/basic/SBE tests/ENUM_test.go @@ -0,0 +1,12 @@ +package sbe_tests + +import ( + "testing" +) + +func TestEnum(t *testing.T) { + e := ENUM_Value1 + if e.String() != "Value1" { + t.Fail() + } +} diff --git a/gocode/flyweight/src/basic/SBE tests/Message1_test.go b/gocode/flyweight/src/basic/SBE tests/Message1_test.go new file mode 100644 index 0000000000..c6963115a2 --- /dev/null +++ b/gocode/flyweight/src/basic/SBE tests/Message1_test.go @@ -0,0 +1,29 @@ +package sbe_tests + +import ( + "testing" +) + +func TestEncodeDecodeMessage1(t *testing.T) { + var data [256]byte + var in Message1 + in.WrapForEncode(data[:], 0, uint64(len(data))) + + in.SetEDTField("abcdefghijklmnopqrst") + in.SetENUMField(ENUM_Value10) + + var out Message1 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + expected := `{"Name": "Message1", "sbeTemplateId": 1, "header": {"blockLength": "0", "templateId": "0", "schemaId": "0", "version": "0"}, "EDTField": "abcdefghijklmnopqrst", "ENUMField": "Value10", "SETField": [], "int64Field": "0"}` + if actual := out.String(); actual != expected { + t.Logf("Failed to decode, expected %s, got %s", expected, actual) + t.Fail() + } +} diff --git a/gocode/flyweight/src/basic/SBE tests/SET_test.go b/gocode/flyweight/src/basic/SBE tests/SET_test.go new file mode 100644 index 0000000000..936730c617 --- /dev/null +++ b/gocode/flyweight/src/basic/SBE tests/SET_test.go @@ -0,0 +1,28 @@ +package sbe_tests + +import ( + "testing" +) + +func TestEncodeDecodeSet(t *testing.T) { + var data [256]byte + var in SET + in.Wrap(data[:], 0, 0, uint64(len(data))) + in.SetBit16(true) + + var out SET + out.Wrap( + data[:], + 0, + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + if out.Bit0() { + t.Fail() + } + + if !out.Bit16() { + t.Fail() + } +} diff --git a/gocode/flyweight/src/composite/Composite_test.go b/gocode/flyweight/src/composite/Composite_test.go new file mode 100644 index 0000000000..20e5c9e757 --- /dev/null +++ b/gocode/flyweight/src/composite/Composite_test.go @@ -0,0 +1,52 @@ +package composite + +import ( + "testing" +) + +func TestEncodeDecode(t *testing.T) { + var data [256]byte + var in Composite + in.WrapForEncode(data[:], 0, uint64(len(data))) + + if in.SbeBlockAndHeaderLength() != 50 { + t.Logf("Failed to encode, expected %d, got %d", + 50, + in.SbeBlockAndHeaderLength(), + ) + t.Fail() + } + + in.Start(). + SetName("start"). + SetD(3.14). + SetI(1). + SetUIndex(0, 66). + SetUIndex(1, 77). + SetTruthval1(BooleanEnum_NULL_VALUE). + SetTruthval2(BooleanEnum_T) + + in.End(). + SetName("end"). + SetD(0.31). + SetI(2). + SetUIndex(0, 77). + SetUIndex(1, 88). + SetTruthval1(BooleanEnum_T). + SetTruthval2(BooleanEnum_F) + + var out Composite + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeSchemaVersion()), + uint64(in.SbeBlockLength()), + uint64(len(data)), + ) + + expected := `{"Name": "Composite", "sbeTemplateId": 1, "start": {"name": "start", "d": "3.14", "i": "1", "u": [66,77], "truthval1": "NULL_VALUE", "truthval2": "T"}, "end": {"name": "end", "d": "0.31", "i": "2", "u": [77,88], "truthval1": "T", "truthval2": "F"}}` + if actual := out.String(); actual != expected { + t.Logf("Failed to decode, expected %s, got %s", expected, actual) + t.Fail() + } +} diff --git a/gocode/flyweight/src/composite_elements/Message_test.go b/gocode/flyweight/src/composite_elements/Message_test.go new file mode 100644 index 0000000000..90dfe20f98 --- /dev/null +++ b/gocode/flyweight/src/composite_elements/Message_test.go @@ -0,0 +1,91 @@ +package composite_elements + +import ( + "testing" +) + +func TestEncodeDecodeMsg(t *testing.T) { + var data [256]byte + var in Msg + in.WrapForEncode(data[:], 0, uint64(len(data))) + + in.Structure(). + SetEnumOne(EnumOne_Value10). + SetZeroth(0) + in.Structure(). + SetOne().SetBit0(true) + in.Structure().Inner(). + SetFirst(1). + SetSecond(2) + + var out Msg + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeSchemaVersion()), + uint64(in.SbeBlockLength()), + uint64(len(data)), + ) + + expected := `{"Name": "Msg", "sbeTemplateId": 1, "structure": {"enumOne": "Value10", "zeroth": "0", "setOne": ["Bit0"], "inner": {"first": "1", "second": "2"}}}` + if actual := out.String(); actual != expected { + t.Logf("Failed to decode, expected %s, got %s", expected, actual) + t.Fail() + } +} + +func TestEncodeDecodeMsg2(t *testing.T) { + var data [256]byte + var in Msg2 + in.WrapForEncode(data[:], 0, uint64(len(data))) + + in.Structure(). + SetEnumOne(EnumOne_Value10). + SetZeroth(0) + in.Structure(). + SetOne().SetBit16(true) + in.Structure().Inner(). + SetFirst(1). + SetSecond(2) + + var out Msg2 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeSchemaVersion()), + uint64(in.SbeBlockLength()), + uint64(len(data)), + ) + + expected := `{"Name": "Msg2", "sbeTemplateId": 2, "structure": {"enumOne": "Value10", "zeroth": "0", "setOne": ["Bit16"], "inner": {"first": "1", "second": "2"}}}` + if actual := out.String(); actual != expected { + t.Logf("Failed to decode, expected %s, got %s", expected, actual) + t.Fail() + } +} + +func TestEncodeDecodeMsg3(t *testing.T) { + var data [256]byte + var in Msg3 + in.WrapForEncode(data[:], 0, uint64(len(data))) + + in.Structure(). + SetMantissa(65). + SetExponent(3). + SetIsSettlement(BooleanEnum_T) + + var out Msg3 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeSchemaVersion()), + uint64(in.SbeBlockLength()), + uint64(len(data)), + ) + + expected := `{"Name": "Msg3", "sbeTemplateId": 3, "structure": {"mantissa": "65", "exponent": "3", "isSettlement": "T"}}` + if actual := out.String(); actual != expected { + t.Logf("Failed to decode, expected %s, got %s", expected, actual) + t.Fail() + } +} diff --git a/gocode/flyweight/src/example-schema/CarExample_test.go b/gocode/flyweight/src/example-schema/CarExample_test.go new file mode 100644 index 0000000000..12b8d3edc8 --- /dev/null +++ b/gocode/flyweight/src/example-schema/CarExample_test.go @@ -0,0 +1,572 @@ +package main + +import ( + "fmt" + "github.com/real-logic/simple-binary-encoding/src/baseline" + "github.com/real-logic/simple-binary-encoding/src/extension" + "io" + "testing" +) + +func TestNoop(t *testing.T) { +} + +func BenchmarkInstantiateCar(b *testing.B) { + var data [256]byte + for i := 0; i < b.N; i++ { + var hdr baseline.MessageHeader + var car baseline.Car + makeCar(&hdr, &car, data[:], 0) + } +} + +func BenchmarkDecodeStrict(b *testing.B) { + var data [256]byte + var hdr baseline.MessageHeader + var car baseline.Car + makeCar(&hdr, &car, data[:], 0) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + var out baseline.Car + out.WrapForDecode( + data[:], + 0, + uint64(car.SbeBlockLength()), + uint64(car.SbeSchemaVersion()), + uint64(len(data)), + ) + } +} + +func BenchmarkPipe(b *testing.B) { + var r, w = io.Pipe() + data := []byte{49, 0, 1, 0, 1, 0, 0, 0, 210, 4, 0, 0, 0, 0, 0, 0, 221, 7, 1, 65, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 97, 98, 99, 100, 101, 102, 6, 208, 7, 4, 49, 50, 51, 35, 1, 78, 200, 6, 0, 3, 0, 30, 0, 154, 153, 15, 66, 11, 0, 0, 0, 85, 114, 98, 97, 110, 32, 67, 121, 99, 108, 101, 55, 0, 0, 0, 68, 66, 14, 0, 0, 0, 67, 111, 109, 98, 105, 110, 101, 100, 32, 67, 121, 99, 108, 101, 75, 0, 0, 0, 32, 66, 13, 0, 0, 0, 72, 105, 103, 104, 119, 97, 121, 32, 67, 121, 99, 108, 101, 1, 0, 2, 0, 95, 6, 0, 3, 0, 30, 0, 0, 0, 128, 64, 60, 0, 0, 0, 240, 64, 100, 0, 51, 51, 67, 65, 99, 6, 0, 3, 0, 30, 0, 51, 51, 115, 64, 60, 0, 51, 51, 227, 64, 100, 0, 205, 204, 60, 65, 5, 0, 0, 0, 72, 111, 110, 100, 97, 9, 0, 0, 0, 67, 105, 118, 105, 99, 32, 86, 84, 105, 6, 0, 0, 0, 97, 98, 99, 100, 101, 102} + writerReady := make(chan bool) + + go func() { + defer w.Close() + writerReady <- true + // By way of test, stream the bytes into the pipe a + // chunk at a time + for looping := true; looping; { + if _, err := w.Write(data); err != nil { + looping = false + } + } + }() + + <-writerReady + b.ResetTimer() + + var buf [1024]byte + for i := 0; i < b.N; i++ { + var hdr baseline.MessageHeader + hdrSize := int(hdr.EncodedLength()) + _, err := io.ReadAtLeast(r, buf[:], hdrSize) + if err != nil { + b.Log("Failed to read", err) + b.Fail() + } + hdr.Wrap(buf[:], 0, 0, uint64(hdrSize)) + + n, err := io.ReadAtLeast(r, buf[:], hdrSize) + if err != nil { + b.Log("Failed to read", err) + b.Fail() + } + + var out baseline.Car + out.WrapForDecode( + buf[hdrSize:], + 0, + uint64(hdr.BlockLength()), + hdr.ActingVersion(), + uint64(n-hdrSize), + ) + } + r.Close() +} + +func BenchmarkPipeBufio(b *testing.B) { + var r, w = io.Pipe() + data := []byte{49, 0, 1, 0, 1, 0, 0, 0, 210, 4, 0, 0, 0, 0, 0, 0, 221, 7, 1, 65, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 97, 98, 99, 100, 101, 102, 6, 208, 7, 4, 49, 50, 51, 35, 1, 78, 200, 6, 0, 3, 0, 30, 0, 154, 153, 15, 66, 11, 0, 0, 0, 85, 114, 98, 97, 110, 32, 67, 121, 99, 108, 101, 55, 0, 0, 0, 68, 66, 14, 0, 0, 0, 67, 111, 109, 98, 105, 110, 101, 100, 32, 67, 121, 99, 108, 101, 75, 0, 0, 0, 32, 66, 13, 0, 0, 0, 72, 105, 103, 104, 119, 97, 121, 32, 67, 121, 99, 108, 101, 1, 0, 2, 0, 95, 6, 0, 3, 0, 30, 0, 0, 0, 128, 64, 60, 0, 0, 0, 240, 64, 100, 0, 51, 51, 67, 65, 99, 6, 0, 3, 0, 30, 0, 51, 51, 115, 64, 60, 0, 51, 51, 227, 64, 100, 0, 205, 204, 60, 65, 5, 0, 0, 0, 72, 111, 110, 100, 97, 9, 0, 0, 0, 67, 105, 118, 105, 99, 32, 86, 84, 105, 6, 0, 0, 0, 97, 98, 99, 100, 101, 102} + + writerReady := make(chan bool) + + go func() { + defer w.Close() + writerReady <- true + // By way of test, stream the bytes into the pipe a + // chunk at a time + for looping := true; looping; { + if _, err := w.Write(data); err != nil { + looping = false + } + } + }() + + <-writerReady + b.ResetTimer() + + var buf [1024]byte + for i := 0; i < b.N; i++ { + var hdr baseline.MessageHeader + hdrSize := int(hdr.EncodedLength()) + _, err := io.ReadAtLeast(r, buf[:], hdrSize) + if err != nil { + b.Log("Failed to read", err) + b.Fail() + } + hdr.Wrap(buf[:], 0, 0, uint64(hdrSize)) + + n, err := io.ReadAtLeast(r, buf[:], hdrSize) + if err != nil { + b.Log("Failed to read", err) + b.Fail() + } + + var out baseline.Car + out.WrapForDecode( + buf[:], + uint64(hdrSize), + uint64(hdr.BlockLength()), + hdr.ActingVersion(), + uint64(n-hdrSize), + ) + } + r.Close() +} + +// String Preallocations which matches what the Java and C++ benchmarks do +var vehicleCode = [6]byte{'a', 'b', 'c', 'd', 'e', 'f'} +var manufacturerCode = [3]byte{'1', '2', '3'} +var manufacturer = []uint8("Honda") +var model = []uint8("Civic VTi") +var activationCode = []uint8("abcdef") + +// Both Java and C++ benchmarks ignore CarFuelFigures.UsageDescription +var urban = []uint8("Urban Cycle") +var combined = []uint8("Combined Cycle") +var highway = []uint8("Highway Cycle") + +func ExampleEncodeDecode() { + var data [256]byte + var hdr baseline.MessageHeader + var in baseline.Car + + makeCar(&hdr, &in, data[:], 0) + in.WrapForDecode( + data[:], + hdr.EncodedLength(), + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data))-hdr.EncodedLength(), + ) + + var out baseline.Car + out.WrapForDecode( + data[:], + hdr.EncodedLength(), + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data))-hdr.EncodedLength(), + ) + + if in.SerialNumber() != out.SerialNumber() { + fmt.Println("in.SerialNumber() != out.SerialNumber():\n", in.SerialNumber(), out.SerialNumber()) + return + } + if in.ModelYear() != out.ModelYear() { + fmt.Println("in.ModelYear() != out.ModelYear():\n", in.ModelYear(), out.ModelYear()) + return + } + if in.Available() != out.Available() { + fmt.Println("in.Available() != out.Available():\n", in.Available(), out.Available()) + return + } + if in.Code() != out.Code() { + fmt.Println("in.Code() != out.Code():\n", in.Code(), out.Code()) + return + } + + if in.SomeNumbersLength() != out.SomeNumbersLength() { + fmt.Println("in.SomeNumbers != out.SomeNumbers:\n", in.SomeNumbersLength(), out.SomeNumbersLength()) + return + } + for i := uint64(0); i < uint64(in.SomeNumbersLength()); i++ { + if in.SomeNumbersIndex(i) != out.SomeNumbersIndex(i) { + fmt.Println("in.SomeNumbers != out.SomeNumbers:\n", in.SomeNumbersIndex(i), out.SomeNumbersIndex(i)) + return + } + } + + if in.GetVehicleCodeAsString() != out.GetVehicleCodeAsString() { + fmt.Println("in.VehicleCode != out.VehicleCode:\n", in.GetVehicleCodeAsString(), out.GetVehicleCodeAsString()) + return + } + if in.Extras().String() != out.Extras().String() { + fmt.Println("in.Extras != out.Extras:\n", in.Extras().String(), out.Extras().String()) + return + } + if baseline.Model_C != out.DiscountedModel() { + fmt.Println("in.DiscountedModel != out.DiscountedModel:\n", in.DiscountedModel(), out.DiscountedModel()) + return + } + if in.Engine().String() != out.Engine().String() { + fmt.Println("in.Engine != out.Engine:\n", in.Engine().String(), "\n", out.Engine().String()) + return + } + // Output: +} + +func ExampleCarToExtension() { + var data [256]byte + var hdr baseline.MessageHeader + var in baseline.Car + + makeCar(&hdr, &in, data[:], 0) + + in.WrapForDecode( + data[:], + hdr.EncodedLength(), + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data))-hdr.EncodedLength(), + ) + + var out extension.Car + out.WrapForDecode( + data[:], + hdr.EncodedLength(), + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data))-hdr.EncodedLength(), + ) + + if in.SerialNumber() != out.SerialNumber() { + fmt.Println("in.SerialNumber() != out.SerialNumber():\n", in.SerialNumber(), out.SerialNumber()) + return + } + if in.ModelYear() != out.ModelYear() { + fmt.Println("in.ModelYear() != out.ModelYear():\n", in.ModelYear(), out.ModelYear()) + return + } + + // Note casts so we can compare + if in.Available() != baseline.BooleanType(out.Available()) { + fmt.Println("in.Available != out.Available:\n", in.Available(), out.Available()) + return + } + if in.Code() != baseline.Model(out.Code()) { + fmt.Println("in.Code != out.Code:\n", in.Code(), out.Code()) + return + } + + if in.SomeNumbersLength() != out.SomeNumbersLength() { + fmt.Println("in.SomeNumbers != out.SomeNumbers:\n", in.SomeNumbersLength(), out.SomeNumbersLength()) + return + } + for i := uint64(0); i < uint64(in.SomeNumbersLength()); i++ { + if in.SomeNumbersIndex(i) != out.SomeNumbersIndex(i) { + fmt.Println("in.SomeNumbers != out.SomeNumbers:\n", in.SomeNumbersIndex(i), out.SomeNumbersIndex(i)) + return + } + } + + if in.GetVehicleCodeAsString() != out.GetVehicleCodeAsString() { + fmt.Println("in.VehicleCode != out.VehicleCode:\n", in.GetVehicleCodeAsString(), out.GetVehicleCodeAsString()) + return + } + if in.Extras().String() != out.Extras().String() { + fmt.Println("in.Extras != out.Extras:\n", in.Extras().String(), out.Extras().String()) + return + } + if extension.Model_C != out.DiscountedModel() { + fmt.Println("in.DiscountedModel != out.DiscountedModel:\n", in.DiscountedModel(), out.DiscountedModel()) + return + } + if in.Engine().String() != out.Engine().String() { + fmt.Println("in.Engine != out.Engine:\n", in.Engine().String(), "\n", out.Engine().String()) + return + } + + // Engine has two constant values which should come back filled in + if in.Engine().MaxRpm() != out.Engine().MaxRpm() { + fmt.Println("in.Engine.MaxRpm != out.Engine/MaxRpm:\n", + in.Engine().MaxRpm(), out.Engine().MaxRpm()) + return + } + + inFuelFigures, outFuelFigures := in.FuelFigures(), out.FuelFigures() + if inFuelFigures.Count() != outFuelFigures.Count() { + fmt.Println("in.FuelFiguresCount() != out.FuelFiguresCount():\n", + inFuelFigures.Count(), outFuelFigures.Count()) + return + } + for i := uint64(0); i < inFuelFigures.Count(); i++ { + inFuelFigures, outFuelFigures = inFuelFigures.Next(), outFuelFigures.Next() + if e, a := inFuelFigures.String(), outFuelFigures.String(); e != a { + fmt.Println("in.FuelFigures != out.FuelFigures:\n", e, a) + return + } + } + + inPerformanceFigures, outPerformanceFigures := in.PerformanceFigures(), out.PerformanceFigures() + if inPerformanceFigures.Count() != outPerformanceFigures.Count() { + fmt.Println("in.PerformanceFiguresCount() != out.PerformanceFiguresCount():\n", + inPerformanceFigures.Count(), outPerformanceFigures.Count()) + return + } + for i := uint64(0); i < inPerformanceFigures.Count(); i++ { + inPerformanceFigures, outPerformanceFigures = inPerformanceFigures.Next(), outPerformanceFigures.Next() + if e, a := inPerformanceFigures.String(), outPerformanceFigures.String(); e != a { + fmt.Println("in.PerformanceFigures != out.PerformanceFigures:\n", e, a) + return + } + } + + if e, a := in.Manufacturer(), out.Manufacturer(); e != a { + fmt.Println("in.Manufacturer != out.Manufacturer:\n", e, a) + return + } + + if e, a := in.Model(), out.Model(); e != a { + fmt.Println("in.Model != out.Model:\n", e, a) + return + } + + if e, a := in.ActivationCode(), out.ActivationCode(); e != a { + fmt.Println("in.ActivationCode != out.ActivationCode:\n", e, a) + return + } + + // Cupholder is not in example-schema and was introduced in + // extension-schema, so it should be NullValue + if out.CupHolderCount() != out.CupHolderCountNullValue() { + fmt.Println("out.cupholderCount not successfully nulled:\n", out.CupHolderCount()) + return + } + // Output: +} + +func ExampleExtensionToCar() { + var data [256]byte + var hdr extension.MessageHeader + var in extension.Car + + makeExtension(&hdr, &in, data[:], 0) + + in.WrapForDecode( + data[:], + hdr.EncodedLength(), + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data))-hdr.EncodedLength(), + ) + + var out baseline.Car + out.WrapForDecode( + data[:], + hdr.EncodedLength(), + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data))-hdr.EncodedLength(), + ) + + if in.SerialNumber() != out.SerialNumber() { + fmt.Println("in.SerialNumber() != out.SerialNumber():\n", in.SerialNumber(), out.SerialNumber()) + return + } + if in.ModelYear() != out.ModelYear() { + fmt.Println("in.ModelYear() != out.ModelYear():\n", in.ModelYear(), out.ModelYear()) + return + } + + // Note casts so we can compare + if in.Available() != extension.BooleanType(out.Available()) { + fmt.Println("in.Available != out.Available:\n", in.Available(), out.Available()) + return + } + if in.Code() != extension.Model(out.Code()) { + fmt.Println("in.Code != out.Code:\n", in.Code(), out.Code()) + return + } + + if in.SomeNumbersLength() != out.SomeNumbersLength() { + fmt.Println("in.SomeNumbers != out.SomeNumbers:\n", in.SomeNumbersLength(), out.SomeNumbersLength()) + return + } + for i := uint64(0); i < uint64(in.SomeNumbersLength()); i++ { + if in.SomeNumbersIndex(i) != out.SomeNumbersIndex(i) { + fmt.Println("in.SomeNumbers != out.SomeNumbers:\n", in.SomeNumbersIndex(i), out.SomeNumbersIndex(i)) + return + } + } + + if in.GetVehicleCodeAsString() != out.GetVehicleCodeAsString() { + fmt.Println("in.VehicleCode != out.VehicleCode:\n", in.GetVehicleCodeAsString(), out.GetVehicleCodeAsString()) + return + } + if in.Extras().String() != out.Extras().String() { + fmt.Println("in.Extras != out.Extras:\n", in.Extras().String(), out.Extras().String()) + return + } + if baseline.Model_C != out.DiscountedModel() { + fmt.Println("in.DiscountedModel != out.DiscountedModel:\n", in.DiscountedModel(), out.DiscountedModel()) + return + } + if in.Engine().String() != out.Engine().String() { + fmt.Println("in.Engine != out.Engine:\n", in.Engine().String(), "\n", out.Engine().String()) + return + } + + inFuelFigures, outFuelFigures := in.FuelFigures(), out.FuelFigures() + if inFuelFigures.Count() != outFuelFigures.Count() { + fmt.Println("in.FuelFiguresCount() != out.FuelFiguresCount():\n", + inFuelFigures.Count(), outFuelFigures.Count()) + return + } + for i := uint64(0); i < inFuelFigures.Count(); i++ { + inFuelFigures, outFuelFigures = inFuelFigures.Next(), outFuelFigures.Next() + if e, a := inFuelFigures.String(), outFuelFigures.String(); e != a { + fmt.Println("in.FuelFigures != out.FuelFigures:\n", e, a) + return + } + } + + inPerformanceFigures, outPerformanceFigures := in.PerformanceFigures(), out.PerformanceFigures() + if inPerformanceFigures.Count() != outPerformanceFigures.Count() { + fmt.Println("in.PerformanceFiguresCount() != out.PerformanceFiguresCount():\n", + inPerformanceFigures.Count(), outPerformanceFigures.Count()) + return + } + for i := uint64(0); i < inPerformanceFigures.Count(); i++ { + inPerformanceFigures, outPerformanceFigures = inPerformanceFigures.Next(), outPerformanceFigures.Next() + if e, a := inPerformanceFigures.String(), outPerformanceFigures.String(); e != a { + fmt.Println("in.PerformanceFigures != out.PerformanceFigures:\n", e, a) + return + } + } + + if e, a := in.ActivationCode(), out.ActivationCode(); e != a { + fmt.Println("in.ActivationCode != out.ActivationCode:\n", e, a) + return + } + // Output: +} + +// Helper to make a Car object as per the Java example +func makeCar(messageHeader *baseline.MessageHeader, car *baseline.Car, buffer []byte, bufferIndex uint64) { + messageHeader.Wrap(buffer, bufferIndex, uint64(messageHeader.SbeSchemaVersion()), uint64(len(buffer))) + + car.WrapAndApplyHeader(buffer, bufferIndex, uint64(len(buffer))-uint64(messageHeader.BlockLength())). + SetSerialNumber(1234). + SetModelYear(2013). + SetAvailable(baseline.BooleanType_T). + SetCode(baseline.Model_A). + PutVehicleCode(vehicleCode[:]) + + size := car.SomeNumbersLength() + for i := 0; i < size; i++ { + car.SetSomeNumbersIndex(uint64(i), uint32(i)) + } + + car.Extras().Clear(). + SetSportsPack(true). + SetSunRoof(true) + + car.Engine(). + SetCapacity(2000). + SetNumCylinders(4). + SetManufacturerCode(string(manufacturerCode[:])). + SetEfficiency(35). + SetBoosterEnabled(baseline.BooleanType_T). + Booster(). + SetBoostType(baseline.BoostType_NITROUS). + SetHorsePower(200) + + car.FuelFiguresCount(3).Next(). + SetSpeed(30).SetMpg(35.9).PutUsageDescription(string(urban[:])).Next(). + SetSpeed(55).SetMpg(49.0).PutUsageDescription(string(combined[:])).Next(). + SetSpeed(75).SetMpg(40.0).PutUsageDescription(string(highway[:])) + + perfFigures := car.PerformanceFiguresCount(2) + perfFigures.Next(). + SetOctaneRating(95). + AccelerationCount(3).Next(). + SetMph(30).SetSeconds(4.0).Next(). + SetMph(60).SetSeconds(7.5).Next(). + SetMph(100).SetSeconds(12.2) + perfFigures.Next(). + SetOctaneRating(99). + AccelerationCount(3).Next(). + SetMph(30).SetSeconds(3.8).Next(). + SetMph(60).SetSeconds(7.1).Next(). + SetMph(100).SetSeconds(11.8) + + car.PutManufacturer(string(manufacturer)) + car.PutModel(string(model)) + car.PutActivationCode(string(activationCode)) +} + +func makeExtension(messageHeader *extension.MessageHeader, car *extension.Car, buffer []byte, bufferIndex uint64) { + // Helper to make an Extension (car with cupholder) object + messageHeader.Wrap(buffer, bufferIndex, uint64(messageHeader.SbeSchemaVersion()), uint64(len(buffer))) + + car.WrapAndApplyHeader(buffer, bufferIndex, uint64(len(buffer))-uint64(messageHeader.BlockLength())). + SetSerialNumber(1234). + SetModelYear(2013). + SetAvailable(extension.BooleanType_T). + SetCode(extension.Model_A). + PutVehicleCode(vehicleCode[:]). + SetUuidIndex(0, 119). + SetUuidIndex(1, 120). + SetCupHolderCount(121) + + size := car.SomeNumbersLength() + for i := 0; i < size; i++ { + car.SetSomeNumbersIndex(uint64(i), uint32(i)) + } + + car.Extras().Clear(). + SetSportsPack(true). + SetSunRoof(true) + + car.Engine(). + SetCapacity(2000). + SetNumCylinders(4). + SetManufacturerCode(string(manufacturerCode[:])). + SetEfficiency(35). + SetBoosterEnabled(extension.BooleanType_T). + Booster(). + SetBoostType(extension.BoostType_NITROUS). + SetHorsePower(200) + + car.FuelFiguresCount(3).Next(). + SetSpeed(30).SetMpg(35.9).PutUsageDescription(string(urban[:])).Next(). + SetSpeed(55).SetMpg(49.0).PutUsageDescription(string(combined[:])).Next(). + SetSpeed(75).SetMpg(40.0).PutUsageDescription(string(highway[:])) + + perfFigures := car.PerformanceFiguresCount(2) + perfFigures.Next(). + SetOctaneRating(95). + AccelerationCount(3).Next(). + SetMph(30).SetSeconds(4.0).Next(). + SetMph(60).SetSeconds(7.5).Next(). + SetMph(100).SetSeconds(12.2) + perfFigures.Next(). + SetOctaneRating(99). + AccelerationCount(3).Next(). + SetMph(30).SetSeconds(3.8).Next(). + SetMph(60).SetSeconds(7.1).Next(). + SetMph(100).SetSeconds(11.8) + + car.PutManufacturer(string(manufacturer)) + car.PutModel(string(model)) + car.PutActivationCode(string(activationCode)) +} + +// The byte array can be made at ~rust/car_example/car_example_data.sbe by running gradlew generateCarExampleDataFile +// This can then be decoded using od -tu1 +var data = []byte{45, 0, 1, 0, 1, 0, 0, 0, 210, 4, 0, 0, 0, 0, 0, 0, 221, 7, 1, 65, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 97, 98, 99, 100, 101, 102, 6, 208, 7, 4, 49, 50, 51, 35, 1, 78, 200, 6, 0, 3, 0, 30, 0, 154, 153, 15, 66, 11, 0, 0, 0, 85, 114, 98, 97, 110, 32, 67, 121, 99, 108, 101, 55, 0, 0, 0, 68, 66, 14, 0, 0, 0, 67, 111, 109, 98, 105, 110, 101, 100, 32, 67, 121, 99, 108, 101, 75, 0, 0, 0, 32, 66, 13, 0, 0, 0, 72, 105, 103, 104, 119, 97, 121, 32, 67, 121, 99, 108, 101, 1, 0, 2, 0, 95, 6, 0, 3, 0, 30, 0, 0, 0, 128, 64, 60, 0, 0, 0, 240, 64, 100, 0, 51, 51, 67, 65, 99, 6, 0, 3, 0, 30, 0, 51, 51, 115, 64, 60, 0, 51, 51, 227, 64, 100, 0, 205, 204, 60, 65, 5, 0, 0, 0, 72, 111, 110, 100, 97, 9, 0, 0, 0, 67, 105, 118, 105, 99, 32, 86, 84, 105, 6, 0, 0, 0, 97, 98, 99, 100, 101, 102} diff --git a/gocode/flyweight/src/group/SBE tests/TestMessage1_test.go b/gocode/flyweight/src/group/SBE tests/TestMessage1_test.go new file mode 100644 index 0000000000..1525462f9f --- /dev/null +++ b/gocode/flyweight/src/group/SBE tests/TestMessage1_test.go @@ -0,0 +1,55 @@ +package sbe_tests + +import ( + "testing" +) + +func TestEncodeDecodeTestMessage1(t *testing.T) { + + var data [256]byte + var in TestMessage1 + in.WrapForEncode(data[:], 0, uint64(len(data))) + + in.SetTag1(44) + in.EntriesCount(1).Next(). + SetTagGroup1("abcdefghijklmnopqrst"). + SetTagGroup2(7) + + in.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + var out TestMessage1 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + if in.Tag1() != out.Tag1() { + t.Log("in != out:\n", in.Tag1(), out.Tag1()) + t.Fail() + } + inEntries, outEntries := in.Entries(), out.Entries() + if inEntries.Count() != outEntries.Count() { + t.Logf("len(in.Entries)(%d) != len(out.Entries)(%d):\n", inEntries.Count(), outEntries.Count()) + t.Fail() + } + for i := uint64(0); i < inEntries.Count(); i++ { + outEntries = outEntries.Next() + inEntries = inEntries.Next() + if inEntries.String() != outEntries.String() { + t.Logf("in.Entries[%d] != out.Entries[%d]: %s %s\n", i, i, inEntries.String(), outEntries.String()) + t.Fail() + } + } + + return + +} diff --git a/gocode/flyweight/src/group_with_data/TestMessages_test.go b/gocode/flyweight/src/group_with_data/TestMessages_test.go new file mode 100644 index 0000000000..73d8066e3f --- /dev/null +++ b/gocode/flyweight/src/group_with_data/TestMessages_test.go @@ -0,0 +1,200 @@ +package group_with_data + +import ( + _ "fmt" + "testing" +) + +func TestEncodeDecodeTestMessage1(t *testing.T) { + var data [256]byte + var in TestMessage1 + in.WrapForEncode(data[:], 0, uint64(len(data))) + + in.SetTag1(1234) + in.EntriesCount(1).Next(). + SetTagGroup1("123456789"). + SetTagGroup2(123456789). + PutVarDataField("abcdef") + + var out TestMessage1 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + expected := `{"Name": "TestMessage1", "sbeTemplateId": 1, "Tag1": "1234", "Entries": [{"TagGroup1": "123456789", "TagGroup2": "123456789", "varDataField": "abcdef"}]}` + if actual := out.String(); actual != expected { + t.Logf("Failed to decode, expected %s, got %s", expected, actual) + t.Fail() + } +} + +func TestEncodeDecodeTestMessage2(t *testing.T) { + var data [256]byte + var in TestMessage2 + in.WrapForEncode(data[:], 0, uint64(len(data))) + + tag1 := uint32(1234) + tagGroup1 := "123456789" + tagGroup2 := int64(123456789) + varDataField1 := "abcdef" + varDataField2 := "ghij" + + in.SetTag1(tag1) + entries := in.EntriesCount(2) + for i := 0; i < 2; i++ { + entry := entries.Next() + entry.SetTagGroup1(tagGroup1). + SetTagGroup2(tagGroup2). + PutVarDataField1(varDataField1). + PutVarDataField2(varDataField2) + } + + var out TestMessage2 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + if out.Tag1() != tag1 { + t.Logf("Tag1 failed, expected %d, got %d", tag1, out.Tag1()) + t.Fail() + } + outEntries := out.Entries() + for i := 0; i < 2; i++ { + entry := outEntries.Next() + if entry.GetTagGroup1AsString() != tagGroup1 { + t.Logf("TagGroup1 failed at index %d, expected %s, got %s", i, tagGroup1, entry.GetTagGroup1AsString()) + t.Fail() + } + if entry.TagGroup2() != tagGroup2 { + t.Logf("TagGroup2 failed at index %d, expected %d, got %d", i, tagGroup2, entry.TagGroup2()) + t.Fail() + } + if entry.VarDataField1() != varDataField1 { + t.Logf("VarDataField1 failed at index %d, expected %s, got %s", i, varDataField1, entry.VarDataField1()) + t.Fail() + } + if entry.VarDataField2() != varDataField2 { + t.Logf("VarDataField2 failed at index %d, expected %s, got %s", i, varDataField2, entry.VarDataField2()) + t.Fail() + } + } +} + +func TestEncodeDecodeTestMessage3(t *testing.T) { + var data [256]byte + var in TestMessage3 + in.WrapForEncode(data[:], 0, uint64(len(data))) + + tag1 := uint32(1234) + tagGroup1 := "123456789" + varDataField := "middle" + tagGroup2Nested := int64(99887766) + varDataFieldNested := "nested" + + in.SetTag1(tag1) + entries := in.EntriesCount(2) + for i := 0; i < 2; i++ { + entry := entries.Next() + entry.SetTagGroup1(tagGroup1). + PutVarDataField(varDataField). + NestedEntriesCount(1).Next(). + SetTagGroup2(tagGroup2Nested). + PutVarDataFieldNested(varDataFieldNested) + } + + in.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + var out TestMessage3 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + if out.Tag1() != tag1 { + t.Logf("Tag1 failed, expected %d, got %d", tag1, out.Tag1()) + t.Fail() + } + outEntries := out.Entries() + for i := 0; i < 2; i++ { + entry := outEntries.Next() + if entry.GetTagGroup1AsString() != tagGroup1 { + t.Logf("TagGroup1 failed at index %d, expected %s, got %s", i, tagGroup1, entry.GetTagGroup1AsString()) + t.Fail() + } + if entry.VarDataField() != varDataField { + t.Logf("VarDataField failed at index %d, expected %s, got %s", i, varDataField, entry.VarDataField()) + t.Fail() + } + nestedEntry := entry.NestedEntries().Next() + if nestedEntry.TagGroup2() != tagGroup2Nested { + t.Logf("TagGroup2Nested failed at index %d, expected %d, got %d", i, tagGroup2Nested, nestedEntry.TagGroup2()) + t.Fail() + } + if nestedEntry.VarDataFieldNested() != varDataFieldNested { + t.Logf("VarDataFieldNested failed at index %d, expected %s, got %s", i, varDataFieldNested, nestedEntry.VarDataFieldNested()) + t.Fail() + } + } +} + +func TestEncodeDecodeTestMessage4(t *testing.T) { + var data [256]byte + var in TestMessage4 + in.WrapForEncode(data[:], 0, uint64(len(data))) + + tag1 := uint32(9876) + varDataField1 := "abcdef" + varDataField2 := "ghij" + + in.SetTag1(tag1) + entries := in.EntriesCount(3) + for i := 0; i < 3; i++ { + entry := entries.Next() + entry.PutVarDataField1(varDataField1). + PutVarDataField2(varDataField2) + } + + var out TestMessage4 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + if out.Tag1() != tag1 { + t.Logf("Tag1 failed, expected %d, got %d", tag1, out.Tag1()) + t.Fail() + } + + outEntries := out.Entries() + for i := 0; i < 3; i++ { + entry := outEntries.Next() + if entry.VarDataField1() != varDataField1 { + t.Logf("VarDataField1 failed at index %d, expected %s, got %s", i, varDataField1, entry.VarDataField1()) + t.Fail() + } + if entry.VarDataField2() != varDataField2 { + t.Logf("VarDataField2 failed at index %d, expected %s, got %s", i, varDataField2, entry.VarDataField2()) + t.Fail() + } + } +} diff --git a/gocode/flyweight/src/group_with_data_extension/Extension_test.go b/gocode/flyweight/src/group_with_data_extension/Extension_test.go new file mode 100644 index 0000000000..2f9547b94a --- /dev/null +++ b/gocode/flyweight/src/group_with_data_extension/Extension_test.go @@ -0,0 +1,210 @@ +package group_with_data_extension + +import ( + "fmt" + "group_with_data" + "math" + "testing" +) + +// Note, this is a copy of group-with-data that we extended to test +// message extensions within a nested group and vardata +func makeTestMessage3Extension() (data []byte, msg *TestMessage3) { + data = make([]byte, 256) + var t TestMessage3 + t.WrapForEncode(data[:], 0, uint64(len(data))) + + t.SetTag1(1234) + + entries := t.EntriesCount(2) // Assuming 2 entries + for i := 0; i < 2; i++ { + entry := entries.Next() + entry.SetTagGroup1("123456789") + + nestedEntries := entry.NestedEntriesCount(1) // Assuming 1 nested entry + nestedEntry := nestedEntries.Next() + nestedEntry.SetTagGroup2(99887766) + nestedEntry.SetInnerExtension(11112222) + nestedEntry.PutVarDataFieldNested("nested") + + entry.PutVarDataField("middle") + } + + return data, &t +} + +func makeTestMessage3Original() (data []byte, msg *group_with_data.TestMessage3) { + data = make([]byte, 256) + var t group_with_data.TestMessage3 + t.WrapForEncode(data[:], 0, uint64(len(data))) + + t.SetTag1(1234) + + entries := t.EntriesCount(2) // Assuming 2 entries + for i := 0; i < 2; i++ { + entry := entries.Next() + entry.SetTagGroup1("123456789") + + nestedEntries := entry.NestedEntriesCount(1) // Assuming 1 nested entry + nestedEntry := nestedEntries.Next() + nestedEntry.SetTagGroup2(99887766) + nestedEntry.PutVarDataFieldNested("") + + entry.PutVarDataField("middle") + } + + return data, &t +} + +// Basic test of new message +func TestEncodeDecodeNewtoNew(t *testing.T) { + data, in := makeTestMessage3Extension() + + var out TestMessage3 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + if in.Tag1() != out.Tag1() { + t.Logf("in.Tag1 != out.Tag1") + t.Fail() + } + + entries := out.Entries() + for i := 0; i < int(entries.Count()); i++ { + entry := entries.Next() + if entry.GetTagGroup1AsString() != "123456789" { + t.Logf("entry.TagGroup1 != out.Entries[0].TagGroup1") + fmt.Printf("%+v\n%+v\n", in, out) + t.Fail() + } + + nestedEntry := entry.NestedEntries().Next() + if nestedEntry.TagGroup2() != 99887766 { + t.Logf("nestedEntry.TagGroup2 != out.Entries[0].NestedEntries[0].TagGroup2") + fmt.Printf("%+v\n%+v\n", in, out) + t.Fail() + } + + if nestedEntry.InnerExtension() != 11112222 { + t.Logf("n.Entries[0].NestedEntries[0].InnerExtension != out.Entries[0].NestedEntries[0].InnerExtension") + fmt.Printf("%+v\n%+v\n", in, out) + t.Fail() + } + + if nestedEntry.VarDataFieldNested() != "nested" { + t.Logf("in.Entries[0].NestedEntries[0].VarDataFieldNested != out.Entries[0].NestedEntries[0].VarDataFieldNested") + fmt.Printf("%+v\n%+v\n", in, out) + t.Fail() + } + + if value := entry.VarDataField(); value != "middle" { + t.Logf("in.Entries[%d].VarDataField (%v) != entry.VarDataField (%v)", i, value, "middle") + t.Fail() + } + } +} + +// Test of New to Old +func TestEncodeDecodeNewToOld(t *testing.T) { + data, in := makeTestMessage3Extension() + + var out group_with_data.TestMessage3 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + if in.Tag1() != out.Tag1() { + t.Logf("in.Tag1 != out.Tag1") + t.Fail() + } + + entries := out.Entries() + for i := 0; i < int(entries.Count()); i++ { + entry := entries.Next() + if value := entry.GetTagGroup1AsString(); value != "123456789" { + t.Logf("entry.TagGroup1 (%s) != out.Entries[0].TagGroup1 (%s)", + value, "123456789") + t.Fail() + } + + nestedEntry := entry.NestedEntries().Next() + if nestedEntry.TagGroup2() != 99887766 { + t.Logf("nestedEntry.TagGroup2 (%d) != out.Entries[0].NestedEntries[0].TagGroup2 (%d)", + nestedEntry.TagGroup2(), 99887766) + t.Fail() + } + + if nestedEntry.VarDataFieldNested() != "nested" { + t.Logf("in.Entries[0].NestedEntries[0].VarDataFieldNested (%s) != out.Entries[0].NestedEntries[0].VarDataFieldNested (%s)", + nestedEntry.VarDataFieldNested(), "nested") + t.Fail() + } + + if value := entry.VarDataField(); value != "middle" { + t.Logf("in.Entries[%d].VarDataField (%v) != entry.VarDataField (%v)", i, value, "middle") + t.Fail() + } + } +} + +// Test of Old to New +func TestEncodeDecodeOldToNew(t *testing.T) { + data, in := makeTestMessage3Original() + + var out TestMessage3 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + if in.Tag1() != out.Tag1() { + t.Logf("in.Tag1 != out.Tag1") + t.Fail() + } + + entries := out.Entries() + for i := 0; i < int(entries.Count()); i++ { + entry := entries.Next() + if entry.GetTagGroup1AsString() != "123456789" { + t.Logf("entry.TagGroup1 != out.Entries[0].TagGroup1") + fmt.Printf("%+v\n%+v\n", in, out) + t.Fail() + } + + nestedEntry := entry.NestedEntries().Next() + if nestedEntry.TagGroup2() != 99887766 { + t.Logf("nestedEntry.TagGroup2 (%d) != out.Entries[0].NestedEntries[0].TagGroup2 (%d)", + nestedEntry.TagGroup2(), 99887766) + t.Fail() + } + + if nestedEntry.InnerExtension() != math.MinInt64 { + t.Logf("n.Entries[0].NestedEntries[0].InnerExtension (%d) != out.Entries[0].NestedEntries[0].InnerExtension (%d)", + nestedEntry.InnerExtension(), math.MinInt64) + t.Fail() + } + + if value := nestedEntry.VarDataFieldNested(); value != "" { + t.Logf("in.Entries[0].NestedEntries[0].VarDataFieldNested (%s) != out.Entries[0].NestedEntries[0].VarDataFieldNested (%s)", + value, "") + t.Fail() + } + + if value := entry.VarDataField(); value != "middle" { + t.Logf("in.Entries[%d].VarDataField (%v) != entry.VarDataField (%v)", i, value, "middle") + t.Fail() + } + } +} diff --git a/gocode/flyweight/src/issue435/Issue435_test.go b/gocode/flyweight/src/issue435/Issue435_test.go new file mode 100644 index 0000000000..170967fc28 --- /dev/null +++ b/gocode/flyweight/src/issue435/Issue435_test.go @@ -0,0 +1,48 @@ +package issue435 + +import ( + "testing" +) + +func TestEncodeDecode(t *testing.T) { + + var data [256]byte + + var in Issue435 + + // Non-standard header so we use the generated one + var hdr MessageHeader + hdr.Wrap(data[:], 0, 0, uint64(len(data))) + hdr.S().SetTwo(true) + + in.WrapForEncode(data[:], hdr.EncodedLength(), uint64(len(data))-hdr.EncodedLength()) + in.Example().SetE(EnumRef_Two) + + var outHdr MessageHeader + outHdr.Wrap(data[:], 0, 0, uint64(len(data))) + + if !outHdr.S().Two() { + t.Logf("Failed to decode, expected Two to be true") + t.Fail() + } + + var out Issue435 + + out.WrapForDecode( + data[:], + hdr.EncodedLength(), + uint64(outHdr.BlockLength()), + outHdr.ActingVersion(), + uint64(len(data))) + + if out.Example().E() != EnumRef_Two { + t.Logf("Failed to decode, expected EnumRef_Two, got %d", out.Example().E()) + t.Fail() + } + + expected := `{"Name": "Issue435", "sbeTemplateId": 1, "example": {"e": "Two"}}` + if actual := out.String(); actual != expected { + t.Logf("Failed to decode, expected %s, got %s", expected, actual) + t.Fail() + } +} diff --git a/gocode/flyweight/src/issue472/Issue472_test.go b/gocode/flyweight/src/issue472/Issue472_test.go new file mode 100644 index 0000000000..151dd62ccc --- /dev/null +++ b/gocode/flyweight/src/issue472/Issue472_test.go @@ -0,0 +1,27 @@ +package issue472 + +import ( + "testing" +) + +func TestEncodeDecode(t *testing.T) { + var data [256]byte + // in contains a single optional field which is not initialized + var in Issue472 + in.WrapForEncode(data[:], 0, uint64(len(data))) + + var out Issue472 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + expected := `{"Name": "Issue472", "sbeTemplateId": 1, "optional": "0"}` + if actual := out.String(); actual != expected { + t.Logf("Failed to decode, expected %s, got %s", expected, actual) + t.Fail() + } +} diff --git a/gocode/flyweight/src/issue483/Issue483_test.go b/gocode/flyweight/src/issue483/Issue483_test.go new file mode 100644 index 0000000000..7af235b396 --- /dev/null +++ b/gocode/flyweight/src/issue483/Issue483_test.go @@ -0,0 +1,35 @@ +package issue483 + +import ( + "testing" +) + +func TestPresence(t *testing.T) { + var issue483 Issue483 + + if issue483.UnsetMetaAttribute("PRESENCE") != "required" { + t.Log("Unset attribute's presence should be 'required'") + t.Fail() + } + + if issue483.RequiredMetaAttribute("PRESENCE") != "required" { + t.Log("Required attribute's presence should be 'required'") + t.Fail() + } + + if issue483.ConstantMetaAttribute("PRESENCE") != "constant" { + t.Log("Constant attribute's presence should be 'constant'") + t.Fail() + } + + // Check contant value is set by init func + if issue483.Constant() != 1 { + t.Log("Constant's value should be 1") + t.Fail() + } + + if issue483.OptionalMetaAttribute("PRESENCE") != "optional" { + t.Log("Optional attribute's presence should be 'optional'") + t.Fail() + } +} diff --git a/gocode/flyweight/src/issue488/Issue488_test.go b/gocode/flyweight/src/issue488/Issue488_test.go new file mode 100644 index 0000000000..5a01a98a15 --- /dev/null +++ b/gocode/flyweight/src/issue488/Issue488_test.go @@ -0,0 +1,9 @@ +package issue488 + +import ( + "testing" +) + +func TestPresence(t *testing.T) { + // placeholder, really just looking for clean builds +} diff --git a/gocode/flyweight/src/issue560/Issue560_test.go b/gocode/flyweight/src/issue560/Issue560_test.go new file mode 100644 index 0000000000..48756aff24 --- /dev/null +++ b/gocode/flyweight/src/issue560/Issue560_test.go @@ -0,0 +1,28 @@ +package issue560 + +import ( + "testing" +) + +func TestEncodeDecode(t *testing.T) { + var data [256]byte + + // in contains a single optional field which is not initialized + var in Issue560 + in.WrapForEncode(data[:], 0, uint64(len(data))) + + var out Issue560 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + expected := `{"Name": "Issue560", "sbeTemplateId": 1, "discountedModel": "C"}` + if actual := out.String(); actual != expected { + t.Logf("Failed to decode, expected %s, got %s", expected, actual) + t.Fail() + } +} diff --git a/gocode/src/issue847/issue847_test.go b/gocode/flyweight/src/issue847/issue847_test.go similarity index 100% rename from gocode/src/issue847/issue847_test.go rename to gocode/flyweight/src/issue847/issue847_test.go diff --git a/gocode/src/issue848/issue848_test.go b/gocode/flyweight/src/issue848/issue848_test.go similarity index 100% rename from gocode/src/issue848/issue848_test.go rename to gocode/flyweight/src/issue848/issue848_test.go diff --git a/gocode/src/issue849/issue849_test.go b/gocode/flyweight/src/issue849/issue849_test.go similarity index 100% rename from gocode/src/issue849/issue849_test.go rename to gocode/flyweight/src/issue849/issue849_test.go diff --git a/gocode/src/mktdata/fixme_test.go b/gocode/flyweight/src/mktdata/fixme_test.go similarity index 100% rename from gocode/src/mktdata/fixme_test.go rename to gocode/flyweight/src/mktdata/fixme_test.go diff --git a/gocode/flyweight/src/otf/go.mod b/gocode/flyweight/src/otf/go.mod new file mode 100644 index 0000000000..fbe2902e53 --- /dev/null +++ b/gocode/flyweight/src/otf/go.mod @@ -0,0 +1,10 @@ +module github.com/real-logic/simple-binary-encoding/otf/test + +require ( + github.com/real-logic/simple-binary-encoding v0.0.0-00010101000000-000000000000 + github.com/stretchr/testify v1.8.4 +) + +replace github.com/real-logic/simple-binary-encoding => ../../../../sbe-tool/src/main/golang + +go 1.12 diff --git a/gocode/flyweight/src/otf/go.sum b/gocode/flyweight/src/otf/go.sum new file mode 100644 index 0000000000..673e9186f2 --- /dev/null +++ b/gocode/flyweight/src/otf/go.sum @@ -0,0 +1,18 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/gocode/flyweight/src/otf/json_test.go b/gocode/flyweight/src/otf/json_test.go new file mode 100644 index 0000000000..7f694d3fbd --- /dev/null +++ b/gocode/flyweight/src/otf/json_test.go @@ -0,0 +1,114 @@ +package otf + +import ( + "github.com/real-logic/simple-binary-encoding/json" + "github.com/real-logic/simple-binary-encoding/otf" + "github.com/real-logic/simple-binary-encoding/otf/test/code_generation_test" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestJson(t *testing.T) { + assert := assert.New(t) + + ir := otf.NewIrDecoder() + if ir.DecodeFile(SchemaFilename) < 0 { + t.Errorf("Error decoding %s", SchemaFilename) + t.Fail() + } + printer, err := json.NewJsonPrinter(ir) + assert.NoErrorf(err, "Error creating JsonPrinter: %v", err) + assert.NotNil(printer) + + var car code_generation_test.Car + buffer := make([]byte, MsgBufferCapacity) + encodeCar(&car, buffer) + + headerDecoder, _ := otf.NewOtfHeaderDecoder(ir.Header()) + bufferOffset := 0 + schemaId, _ := headerDecoder.SchemaId(buffer[bufferOffset:]) + + if uint16(schemaId) != car.SbeSchemaId() { + t.Errorf("Invalid schema id: %d", schemaId) + } + + str, err := printer.PrintJson(buffer) + assert.NoErrorf(err, "Error printing JSON: %v", err) + expected := `{ + "serialNumber": 1234, + "modelYear": 2013, + "available": "T", + "code": "A", + "someNumbers": [0, 1, 2, 3, 4], + "vehicleCode": ["a", "b", "c", "d", "e", "f"], + "extras": { "sunRoof": false, "sportsPack": false, "cruiseControl": false }, + "discountedModel": "C", + "Engine": + { + "capacity": 2000, + "numCylinders": 4, + "maxRpm": "9000", + "manufacturerCode": ["1", "2", "3"], + "fuel": "Petrol", + "booster": + { + "BoostType": "NITROUS", + "horsePower": 200 + } + }, + "fuelFigures": [ + { + "speed": 30, + "mpg": 35.900001525878906, + "usageDescription": "Urban Cycle" + }, + { + "speed": 55, + "mpg": 49, + "usageDescription": "Combined Cycle" + }, + { + "speed": 75, + "mpg": 40, + "usageDescription": "Highway Cycle" + }], + "performanceFigures": [ + { + "octaneRating": 95, + "acceleration": [ + { + "mph": 30, + "seconds": 4 + }, + { + "mph": 60, + "seconds": 7.5 + }, + { + "mph": 100, + "seconds": 12.199999809265137 + }] + }, + { + "octaneRating": 99, + "acceleration": [ + { + "mph": 30, + "seconds": 3.799999952316284 + }, + { + "mph": 60, + "seconds": 7.099999904632568 + }, + { + "mph": 100, + "seconds": 11.800000190734863 + }] + }], + "manufacturer": "Honda", + "model": "Civic VTi", + "activationCode": "abcdef", + "color": "" +}` + assert.EqualValues(expected, str, "Message printer") +} diff --git a/gocode/flyweight/src/otf/otf_test.go b/gocode/flyweight/src/otf/otf_test.go new file mode 100644 index 0000000000..babb370693 --- /dev/null +++ b/gocode/flyweight/src/otf/otf_test.go @@ -0,0 +1,159 @@ +package otf + +import ( + "github.com/real-logic/simple-binary-encoding/otf" + "github.com/real-logic/simple-binary-encoding/otf/test/code_generation_test" + "github.com/stretchr/testify/assert" + "testing" +) + +//go:generate java -Dsbe.output.dir=. -Dsbe.target.language=golang -Dsbe.go.generate.generate.flyweights=true -Dsbe.generate.ir=true -jar ../../../${SBE_JAR} ../../../../sbe-tool/src/test/resources/code-generation-schema.xml + +const SchemaFilename = "code-generation-schema.sbeir" +const MsgBufferCapacity = 4 * 1024 + +func TestOtf(t *testing.T) { + assert := assert.New(t) + + ir := otf.NewIrDecoder() + if ir.DecodeFile(SchemaFilename) < 0 { + t.Errorf("Error decoding %s", SchemaFilename) + } + + var car code_generation_test.Car + buffer := make([]byte, MsgBufferCapacity) + encodedLength := encodeCar(&car, buffer) + + headerDecoder, _ := otf.NewOtfHeaderDecoder(ir.Header()) + bufferOffset := 0 + templateId, _ := headerDecoder.TemplateId(buffer[bufferOffset:]) + schemaId, _ := headerDecoder.SchemaId(buffer[bufferOffset:]) + actingVersion, _ := headerDecoder.SchemaVersion(buffer[bufferOffset:]) + blockLength, _ := headerDecoder.BlockLength(buffer[bufferOffset:]) + + if uint16(schemaId) != car.SbeSchemaId() { + t.Errorf("Invalid schema id: %d", schemaId) + } + + bufferOffset += int(headerDecoder.EncodedLength()) + listener := &TestListener{} + tokens := ir.MessageByID(int32(templateId)) + bufferOffset = otf.Decode( + buffer[bufferOffset:], + actingVersion, + blockLength, + tokens, + listener, + ) + + assert.EqualValues(bufferOffset, encodedLength, "Message not fully decoded") + expected := `Car.serialNumber=1234 +Car.modelYear=2013 +Car.available=T +Car.code=A +Car.someNumbers=01234 +Car.vehicleCode=abcdef +Car.extras: sunRoof=false sportsPack=false cruiseControl=false +Car.discountedModel=C +Car.engine.capacity=2000 +Car.engine.numCylinders=4 +Car.engine.maxRpm=9000 +Car.engine.manufacturerCode=123 +Car.engine.fuel=Petrol +Car.engine.booster.BoostType=NITROUS +Car.engine.booster.horsePower=200 +Car.fuelFigures Group Header : numInGroup=3 +Car.fuelFigures.speed=30 +Car.fuelFigures.mpg=35.900001525878906 +Car.fuelFigures.usageDescription=Urban Cycle +Car.fuelFigures.speed=55 +Car.fuelFigures.mpg=49 +Car.fuelFigures.usageDescription=Combined Cycle +Car.fuelFigures.speed=75 +Car.fuelFigures.mpg=40 +Car.fuelFigures.usageDescription=Highway Cycle +Car.performanceFigures Group Header : numInGroup=2 +Car.performanceFigures.octaneRating=95 +Car.performanceFigures.acceleration Group Header : numInGroup=3 +Car.performanceFigures.acceleration.mph=30 +Car.performanceFigures.acceleration.seconds=4 +Car.performanceFigures.acceleration.mph=60 +Car.performanceFigures.acceleration.seconds=7.5 +Car.performanceFigures.acceleration.mph=100 +Car.performanceFigures.acceleration.seconds=12.199999809265137 +Car.performanceFigures.octaneRating=99 +Car.performanceFigures.acceleration Group Header : numInGroup=3 +Car.performanceFigures.acceleration.mph=30 +Car.performanceFigures.acceleration.seconds=3.799999952316284 +Car.performanceFigures.acceleration.mph=60 +Car.performanceFigures.acceleration.seconds=7.099999904632568 +Car.performanceFigures.acceleration.mph=100 +Car.performanceFigures.acceleration.seconds=11.800000190734863 +Car.manufacturer=Honda +Car.model=Civic VTi +Car.activationCode=abcdef +Car.color= +` + assert.EqualValues(expected, listener.out.String()) +} + +func encodeCar(car *code_generation_test.Car, buffer []byte) int { + const vehicleCode = "abcdef" + const manufacturerCode = "123" + const activationCode = "abcdef" + const manufacturer = "Honda" + const model = "Civic VTi" + + car.WrapAndApplyHeader(buffer, 0, uint64(len(buffer))). + SetSerialNumber(1234). + SetModelYear(2013). + SetAvailable(code_generation_test.BooleanType_T). + SetCode(code_generation_test.Model_A). + SetVehicleCode(vehicleCode) + + // change this to a loop + for i := 0; i < car.SomeNumbersLength(); i++ { + car.SetSomeNumbersIndex(uint64(i), int32(i)) + } + + car.Extras(). + Clear(). + SetCruiseControl(true). + SetSportsPack(true). + SetSunRoof(false) + + car.Engine(). + SetCapacity(2000). + SetNumCylinders(4). + SetManufacturerCode(manufacturerCode). + Booster(). + SetBoostType(code_generation_test.BoostType_NITROUS). + SetHorsePower(200) + + car.FuelFiguresCount(3). + Next().SetSpeed(30).SetMpg(35.9).PutUsageDescription("Urban Cycle"). + Next().SetSpeed(55).SetMpg(49.0).PutUsageDescription("Combined Cycle"). + Next().SetSpeed(75).SetMpg(40.0).PutUsageDescription("Highway Cycle") + + figures := car.PerformanceFiguresCount(2) + figures.Next(). + SetOctaneRating(95). + AccelerationCount(3). + Next().SetMph(30).SetSeconds(4.0). + Next().SetMph(60).SetSeconds(7.5). + Next().SetMph(100).SetSeconds(12.2) + figures.Next(). + SetOctaneRating(99). + AccelerationCount(3). + Next().SetMph(30).SetSeconds(3.8). + Next().SetMph(60).SetSeconds(7.1). + Next().SetMph(100).SetSeconds(11.8) + + car.PutManufacturer(manufacturer). + PutModel(model). + PutActivationCode(activationCode). + PutColor("") + + // var hdr code_generation_test.MessageHeader + return int(car.EncodedLength()) +} diff --git a/gocode/flyweight/src/otf/testlistener.go b/gocode/flyweight/src/otf/testlistener.go new file mode 100644 index 0000000000..18bc73724f --- /dev/null +++ b/gocode/flyweight/src/otf/testlistener.go @@ -0,0 +1,311 @@ +package otf + +import ( + "fmt" + "github.com/real-logic/simple-binary-encoding/otf" + "strconv" + "strings" +) + +type TestListener struct { + out strings.Builder + compositeLevel int + namedScope []string +} + +func (t *TestListener) OnBeginMessage(token otf.Token) { + t.namedScope = append(t.namedScope, token.Name()+".") +} + +func (t *TestListener) OnEndMessage(token otf.Token) { + t.namedScope = t.namedScope[:len(t.namedScope)-1] +} + +func (t *TestListener) OnEncoding(fieldToken otf.Token, buffer []byte, typeToken otf.Token, actingVersion uint64) { + value := t.readEncodingAsString(buffer, fieldToken, typeToken, uint64(fieldToken.TokenVersion()), actingVersion) + + t.printScope() + if t.compositeLevel > 0 { + t.out.WriteString(typeToken.Name()) + } else { + t.out.WriteString(fieldToken.Name()) + } + t.out.WriteString("=") + t.out.WriteString(value) + t.out.WriteString("\n") + +} + +func (t *TestListener) printScope() { + for i := range t.namedScope { + t.out.WriteString(t.namedScope[i]) + } +} + +func (t *TestListener) determineName( + thresholdLevel int, + fieldToken otf.Token, + tokens []otf.Token, + fromIndex int, +) string { + if t.compositeLevel > thresholdLevel { + return tokens[fromIndex].Name() + } else { + return fieldToken.Name() + } +} + +func (t *TestListener) readEncodingAsString( + buffer []byte, + fieldToken otf.Token, + typeToken otf.Token, + fieldVersion uint64, + actingVersion uint64, +) string { + constOrNotPresentValue := t.constOrNotPresentValue(typeToken, fieldVersion, actingVersion) + if constOrNotPresentValue.PrimitiveType != otf.NONE { + encoding := typeToken.Encoding() + characterEncoding := encoding.CharacterEncoding() + if constOrNotPresentValue.Size() == 1 && characterEncoding == "" { + // TODO java uses this + // final byte[] bytes = { (byte)constOrNotPresentValue.longValue() }; + // return new String(bytes, characterEncoding); + return constOrNotPresentValue.String() + } else { + value := constOrNotPresentValue.String() + size := typeToken.ArrayLength() + if size < 2 { + return value + } + sb := strings.Builder{} + more := false + for i := int32(0); i < size; i++ { + if more { + sb.WriteString(", ") + more = true + } + sb.WriteString(value) + } + return sb.String() + } + } + + sb := strings.Builder{} + encoding := typeToken.Encoding() + elementSize := int32(encoding.PrimitiveType().Size()) + + more := false + for i := int32(0); i < typeToken.ArrayLength(); i++ { + if more { + sb.WriteString(", ") + more = true + } + arrayValue := otf.NewPrimitiveValue(encoding.PrimitiveType(), buffer[i*elementSize:(i+1)*elementSize]) + sb.WriteString(arrayValue.String()) + } + return sb.String() +} + +func (t *TestListener) readEncodingAsInt( + buffer []byte, + typeToken otf.Token, + fieldVersion uint64, + actingVersion uint64, +) int64 { + constOrNotPresentValue := t.constOrNotPresentValue(typeToken, fieldVersion, actingVersion) + if constOrNotPresentValue.PrimitiveType != otf.NONE { + return constOrNotPresentValue.AsInt() + } + typeTokenEncoding := typeToken.Encoding() + v, _ := otf.GetAsInt(typeTokenEncoding.PrimitiveType(), typeTokenEncoding.ByteOrder(), buffer) + return v +} + +func (t *TestListener) readEncodingAsUInt( + buffer []byte, + typeToken otf.Token, + fieldVersion uint64, + actingVersion uint64, +) uint64 { + constOrNotPresentValue := t.constOrNotPresentValue(typeToken, fieldVersion, actingVersion) + if constOrNotPresentValue.PrimitiveType != otf.NONE { + return constOrNotPresentValue.AsUInt() + } + typeTokenEncoding := typeToken.Encoding() + v, _ := otf.GetAsUInt(typeTokenEncoding.PrimitiveType(), typeTokenEncoding.ByteOrder(), buffer) + return v +} + +func (t *TestListener) constOrNotPresentValue( + typeToken otf.Token, + fieldVersion uint64, + actingVersion uint64, +) otf.PrimitiveValue { + typeTokenEncoding := typeToken.Encoding() + if typeToken.IsConstantEncoding() { + return typeTokenEncoding.ConstValue() + } else if typeToken.IsOptionalEncoding() && actingVersion < fieldVersion { + return typeTokenEncoding.ApplicableNullValue() + } else { + return otf.PrimitiveValue{} + } +} + +func (t *TestListener) OnEnum( + fieldToken otf.Token, + buffer []byte, + tokens []otf.Token, + fromIndex int, + toIndex int, + actingVersion uint64, +) { + typeToken := tokens[fromIndex+1] + encoding := typeToken.Encoding() + + value := "" + if fieldToken.IsConstantEncoding() { + encoding := fieldToken.Encoding() + refValue := encoding.ConstValue() + indexOfDot := strings.LastIndex(refValue.String(), ".") + if indexOfDot == -1 { + value = refValue.String() + } else { + value = refValue.String()[indexOfDot+1:] + } + } else if encoding.PrimitiveType().IsUnsigned() { + encodedValue := t.readEncodingAsUInt( + buffer, + typeToken, + uint64(fieldToken.TokenVersion()), + actingVersion, + ) + for i := fromIndex + 1; i < toIndex; i++ { + encoding := tokens[i].Encoding() + constValue := encoding.ConstValue() + if constValue.AsUInt() == encodedValue { + value = tokens[i].Name() + break + } + } + } else { + encodedValue := t.readEncodingAsInt( + buffer, + typeToken, + uint64(fieldToken.TokenVersion()), + actingVersion, + ) + for i := fromIndex + 1; i < toIndex; i++ { + encoding := tokens[i].Encoding() + constValue := encoding.ConstValue() + if constValue.AsInt() == encodedValue { + value = tokens[i].Name() + break + } + } + } + + t.printScope() + t.out.WriteString(t.determineName(0, fieldToken, tokens, fromIndex)) + t.out.WriteString("=") + t.out.WriteString(value) + t.out.WriteString("\n") +} + +func (t *TestListener) OnBitSet( + fieldToken otf.Token, + buffer []byte, + tokens []otf.Token, + fromIndex int, + toIndex int, + actingVersion uint64, +) { + typeToken := tokens[fromIndex+1] + encodedValue := t.readEncodingAsInt( + buffer, + typeToken, + uint64(fieldToken.TokenVersion()), + actingVersion, + ) + t.printScope() + t.out.WriteString(t.determineName(0, fieldToken, tokens, fromIndex)) + t.out.WriteString(":") + for i := fromIndex + 1; i < toIndex; i++ { + t.out.WriteString(" ") + t.out.WriteString(tokens[i].Name()) + t.out.WriteString("=") + encoding := tokens[i].Encoding() + constValue := encoding.ConstValue() + bitPosition := constValue.AsInt() + flag := (encodedValue & (1 << uint64(bitPosition))) != 0 + t.out.WriteString(strconv.FormatBool(flag)) + } + t.out.WriteString("\n") +} + +func (t *TestListener) OnBeginComposite( + fieldToken otf.Token, + tokens []otf.Token, + fromIndex int, + toIndex int, +) { + t.compositeLevel++ + t.namedScope = append(t.namedScope, t.determineName(1, fieldToken, tokens, fromIndex)+".") +} + +func (t *TestListener) OnEndComposite( + token otf.Token, + tokens []otf.Token, + fromIndex int, + toIndex int, +) { + t.compositeLevel-- + t.namedScope = t.namedScope[:len(t.namedScope)-1] +} + +func (t *TestListener) OnGroupHeader( + token otf.Token, + numInGroup uint64, +) { + t.printScope() + t.out.WriteString(token.Name()) + t.out.WriteString(" Group Header : numInGroup=") + t.out.WriteString(strconv.FormatUint(numInGroup, 10)) + t.out.WriteString("\n") +} + +func (t *TestListener) OnBeginGroup( + token otf.Token, + groupIndex uint64, + numInGroup uint64, +) { + t.namedScope = append(t.namedScope, token.Name()+".") +} + +func (t *TestListener) OnEndGroup( + token otf.Token, + groupIndex uint64, + numInGroup uint64, +) { + t.namedScope = t.namedScope[:len(t.namedScope)-1] +} + +func (t *TestListener) OnVarData( + fieldToken otf.Token, + buffer []byte, + length uint64, + typeToken otf.Token, +) { + value := "" + typeTokenEncoding := typeToken.Encoding() + if characterEncoding := typeTokenEncoding.CharacterEncoding(); characterEncoding == "" { + value = fmt.Sprintf("%d bytes of raw data", length) + } else { + value = string(buffer[:length]) + } + + t.printScope() + t.out.WriteString(fieldToken.Name()) + t.out.WriteString("=") + t.out.WriteString(value) + t.out.WriteString("\n") +} diff --git a/gocode/flyweight/src/simple/simple_test.go b/gocode/flyweight/src/simple/simple_test.go new file mode 100644 index 0000000000..b15a3c2bad --- /dev/null +++ b/gocode/flyweight/src/simple/simple_test.go @@ -0,0 +1,46 @@ +package simple + +import ( + "testing" +) + +func TestEncodeDecode(t *testing.T) { + var data [256]byte + var in Simple0 + in.WrapForEncode(data[:], 0, uint64(len(data))) + + in.SetU64nv(2863311530) + in.SetU64(2863311530) + in.SetU32(123456) + in.SetU16(7890) + in.SetU8(63) + in.SetS8(-8) + in.SetS16(-16) + in.SetS32(-32) + in.SetS64(-64) + in.SetF32(3.14) + in.SetD64(-3.14e7) + in.SetString6ASCII("abcdef") + in.SetString1ASCII('A') + in.PutInt2Values(254, 255) + + var out Simple0 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + expected := `{"Name": "Simple0", "sbeTemplateId": 11, "U64nv": "2863311530", "U64": "2863311530", "U32": "123456", "U16": "7890", "U8": "63", "S8": "-8", "S16": "-16", "S32": "-32", "S64": "-64", "F32": "3.14", "D64": "-3.14e+07", "String6ASCII": "abcdef", "String1ASCII": "A", "Int2": [254,255]}` + if actual := out.String(); actual != expected { + t.Logf("Failed to decode, expected %s, got %s", expected, actual) + t.Fail() + } + + if in.U64SinceVersion() != 1 { + t.Log("in.U64SinceVersion() should be 1 and is", in.U64SinceVersion()) + t.Fail() + } +} diff --git a/gocode/flyweight/src/since-deprecated/SinceDeprecated_test.go b/gocode/flyweight/src/since-deprecated/SinceDeprecated_test.go new file mode 100644 index 0000000000..1dcf5f416d --- /dev/null +++ b/gocode/flyweight/src/since-deprecated/SinceDeprecated_test.go @@ -0,0 +1,23 @@ +package since_deprecated + +import ( + "testing" +) + +func TestSinceDeprecated(t *testing.T) { + + sv := SinceDeprecated{} + + // V1 has always been there + if sv.V1SinceVersion() != 0 { + t.Fail() + } + // V2 was introduced in version 2 + if sv.V2SinceVersion() != 2 { + t.Fail() + } + // V3 was introduced in version 3 and deprecated in version 4 + if sv.V3SinceVersion() != 3 { + t.Fail() + } +} diff --git a/gocode/flyweight/src/vardata/SBE tests/TestMessage1_test.go b/gocode/flyweight/src/vardata/SBE tests/TestMessage1_test.go new file mode 100644 index 0000000000..237ddb7d5c --- /dev/null +++ b/gocode/flyweight/src/vardata/SBE tests/TestMessage1_test.go @@ -0,0 +1,27 @@ +package sbe_tests + +import ( + "testing" +) + +func TestEncodeDecodeTestMessage1(t *testing.T) { + var data [256]byte + var in TestMessage1 + in.WrapForEncode(data[:], 0, uint64(len(data))) + in.PutEncryptedNewPassword("abcdefghijklmnopqrst") + + var out TestMessage1 + out.WrapForDecode( + data[:], + 0, + uint64(in.SbeBlockLength()), + uint64(in.SbeSchemaVersion()), + uint64(len(data)), + ) + + expected := `{"Name": "TestMessage1", "sbeTemplateId": 1, "encryptedNewPassword": "abcdefghijklmnopqrst"}` + if actual := out.String(); actual != expected { + t.Logf("Failed to decode, expected %s, got %s", expected, actual) + t.Fail() + } +} diff --git a/gocode/go.mod b/gocode/go.mod new file mode 100644 index 0000000000..af460264e6 --- /dev/null +++ b/gocode/go.mod @@ -0,0 +1,7 @@ +module github.com/real-logic/simple-binary-encoding + +go 1.12 + +require ( + github.com/stretchr/testify v1.7.0 +) diff --git a/gocode/go.sum b/gocode/go.sum new file mode 100644 index 0000000000..af7675440c --- /dev/null +++ b/gocode/go.sum @@ -0,0 +1,7 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/gocode/src/baseline-bigendian/Car_test.go b/gocode/struct/src/baseline-bigendian/Car_test.go similarity index 100% rename from gocode/src/baseline-bigendian/Car_test.go rename to gocode/struct/src/baseline-bigendian/Car_test.go diff --git a/gocode/src/baseline/Car_test.go b/gocode/struct/src/baseline/Car_test.go similarity index 100% rename from gocode/src/baseline/Car_test.go rename to gocode/struct/src/baseline/Car_test.go diff --git a/gocode/src/basic/SBE tests/ENUM_test.go b/gocode/struct/src/basic/SBE tests/ENUM_test.go similarity index 100% rename from gocode/src/basic/SBE tests/ENUM_test.go rename to gocode/struct/src/basic/SBE tests/ENUM_test.go diff --git a/gocode/src/basic/SBE tests/Message1_test.go b/gocode/struct/src/basic/SBE tests/Message1_test.go similarity index 100% rename from gocode/src/basic/SBE tests/Message1_test.go rename to gocode/struct/src/basic/SBE tests/Message1_test.go diff --git a/gocode/src/basic/SBE tests/SET_test.go b/gocode/struct/src/basic/SBE tests/SET_test.go similarity index 100% rename from gocode/src/basic/SBE tests/SET_test.go rename to gocode/struct/src/basic/SBE tests/SET_test.go diff --git a/gocode/src/composite/Composite_test.go b/gocode/struct/src/composite/Composite_test.go similarity index 100% rename from gocode/src/composite/Composite_test.go rename to gocode/struct/src/composite/Composite_test.go diff --git a/gocode/src/composite_elements/Message_test.go b/gocode/struct/src/composite_elements/Message_test.go similarity index 100% rename from gocode/src/composite_elements/Message_test.go rename to gocode/struct/src/composite_elements/Message_test.go diff --git a/gocode/src/example-schema/CarExample.go b/gocode/struct/src/example-schema/CarExample.go similarity index 100% rename from gocode/src/example-schema/CarExample.go rename to gocode/struct/src/example-schema/CarExample.go diff --git a/gocode/src/example-schema/CarExample_test.go b/gocode/struct/src/example-schema/CarExample_test.go similarity index 100% rename from gocode/src/example-schema/CarExample_test.go rename to gocode/struct/src/example-schema/CarExample_test.go diff --git a/gocode/src/example-socket-clientserver/clientserver.go b/gocode/struct/src/example-socket-clientserver/clientserver.go similarity index 100% rename from gocode/src/example-socket-clientserver/clientserver.go rename to gocode/struct/src/example-socket-clientserver/clientserver.go diff --git a/gocode/src/group/SBE tests/TestMessage1_test.go b/gocode/struct/src/group/SBE tests/TestMessage1_test.go similarity index 100% rename from gocode/src/group/SBE tests/TestMessage1_test.go rename to gocode/struct/src/group/SBE tests/TestMessage1_test.go diff --git a/gocode/src/group_with_data/TestMessages_test.go b/gocode/struct/src/group_with_data/TestMessages_test.go similarity index 100% rename from gocode/src/group_with_data/TestMessages_test.go rename to gocode/struct/src/group_with_data/TestMessages_test.go diff --git a/gocode/src/group_with_data_extension/Extension_test.go b/gocode/struct/src/group_with_data_extension/Extension_test.go similarity index 100% rename from gocode/src/group_with_data_extension/Extension_test.go rename to gocode/struct/src/group_with_data_extension/Extension_test.go diff --git a/gocode/src/issue435/Issue435_test.go b/gocode/struct/src/issue435/Issue435_test.go similarity index 100% rename from gocode/src/issue435/Issue435_test.go rename to gocode/struct/src/issue435/Issue435_test.go diff --git a/gocode/src/issue472/Issue472_test.go b/gocode/struct/src/issue472/Issue472_test.go similarity index 100% rename from gocode/src/issue472/Issue472_test.go rename to gocode/struct/src/issue472/Issue472_test.go diff --git a/gocode/src/issue483/Issue483_test.go b/gocode/struct/src/issue483/Issue483_test.go similarity index 100% rename from gocode/src/issue483/Issue483_test.go rename to gocode/struct/src/issue483/Issue483_test.go diff --git a/gocode/src/issue488/Issue488_test.go b/gocode/struct/src/issue488/Issue488_test.go similarity index 100% rename from gocode/src/issue488/Issue488_test.go rename to gocode/struct/src/issue488/Issue488_test.go diff --git a/gocode/src/issue505/Issue505_test.go b/gocode/struct/src/issue505/Issue505_test.go similarity index 100% rename from gocode/src/issue505/Issue505_test.go rename to gocode/struct/src/issue505/Issue505_test.go diff --git a/gocode/src/issue560/Issue560_test.go b/gocode/struct/src/issue560/Issue560_test.go similarity index 100% rename from gocode/src/issue560/Issue560_test.go rename to gocode/struct/src/issue560/Issue560_test.go diff --git a/gocode/struct/src/issue847/issue847_test.go b/gocode/struct/src/issue847/issue847_test.go new file mode 100644 index 0000000000..1fb14887ad --- /dev/null +++ b/gocode/struct/src/issue847/issue847_test.go @@ -0,0 +1,9 @@ +package issue847 + +import ( + "testing" +) + +func TestNothing(t *testing.T) { + // placeholder, really just looking for clean builds +} diff --git a/gocode/struct/src/issue848/issue848_test.go b/gocode/struct/src/issue848/issue848_test.go new file mode 100644 index 0000000000..1106e74b01 --- /dev/null +++ b/gocode/struct/src/issue848/issue848_test.go @@ -0,0 +1,9 @@ +package issue848 + +import ( + "testing" +) + +func TestNothing(t *testing.T) { + // placeholder, really just looking for clean builds +} diff --git a/gocode/struct/src/issue849/issue849_test.go b/gocode/struct/src/issue849/issue849_test.go new file mode 100644 index 0000000000..0149615810 --- /dev/null +++ b/gocode/struct/src/issue849/issue849_test.go @@ -0,0 +1,9 @@ +package issue849 + +import ( + "testing" +) + +func TestNothing(t *testing.T) { + // placeholder, really just looking for clean builds +} diff --git a/gocode/struct/src/mktdata/fixme_test.go b/gocode/struct/src/mktdata/fixme_test.go new file mode 100644 index 0000000000..6792aa42e5 --- /dev/null +++ b/gocode/struct/src/mktdata/fixme_test.go @@ -0,0 +1,10 @@ +package mktdata + +import ( + "fmt" + "testing" +) + +func TestFixme(t *testing.T) { + fmt.Println("No tests implemented here") +} diff --git a/gocode/src/mktdata/preallocated_test.go b/gocode/struct/src/mktdata/preallocated_test.go similarity index 100% rename from gocode/src/mktdata/preallocated_test.go rename to gocode/struct/src/mktdata/preallocated_test.go diff --git a/gocode/src/simple/simple_test.go b/gocode/struct/src/simple/simple_test.go similarity index 100% rename from gocode/src/simple/simple_test.go rename to gocode/struct/src/simple/simple_test.go diff --git a/gocode/src/since-deprecated/SinceDeprecated_test.go b/gocode/struct/src/since-deprecated/SinceDeprecated_test.go similarity index 100% rename from gocode/src/since-deprecated/SinceDeprecated_test.go rename to gocode/struct/src/since-deprecated/SinceDeprecated_test.go diff --git a/gocode/src/test973/EventType.go b/gocode/struct/src/test973/EventType.go similarity index 100% rename from gocode/src/test973/EventType.go rename to gocode/struct/src/test973/EventType.go diff --git a/gocode/src/test973/MessageHeader.go b/gocode/struct/src/test973/MessageHeader.go similarity index 100% rename from gocode/src/test973/MessageHeader.go rename to gocode/struct/src/test973/MessageHeader.go diff --git a/gocode/src/test973/SbeMarshalling.go b/gocode/struct/src/test973/SbeMarshalling.go similarity index 100% rename from gocode/src/test973/SbeMarshalling.go rename to gocode/struct/src/test973/SbeMarshalling.go diff --git a/gocode/src/test973/SomeMessage.go b/gocode/struct/src/test973/SomeMessage.go similarity index 100% rename from gocode/src/test973/SomeMessage.go rename to gocode/struct/src/test973/SomeMessage.go diff --git a/gocode/src/test973/test973_test.go b/gocode/struct/src/test973/test973_test.go similarity index 100% rename from gocode/src/test973/test973_test.go rename to gocode/struct/src/test973/test973_test.go diff --git a/gocode/src/vardata/SBE tests/TestMessage1_test.go b/gocode/struct/src/vardata/SBE tests/TestMessage1_test.go similarity index 100% rename from gocode/src/vardata/SBE tests/TestMessage1_test.go rename to gocode/struct/src/vardata/SBE tests/TestMessage1_test.go diff --git a/sbe-tool/src/main/golang/.gitignore b/sbe-tool/src/main/golang/.gitignore new file mode 100644 index 0000000000..aafd6f4184 --- /dev/null +++ b/sbe-tool/src/main/golang/.gitignore @@ -0,0 +1 @@ +uk_co_real_logic_sbe_ir_generated/* diff --git a/sbe-tool/src/main/golang/go.mod b/sbe-tool/src/main/golang/go.mod new file mode 100644 index 0000000000..0a6dd9e719 --- /dev/null +++ b/sbe-tool/src/main/golang/go.mod @@ -0,0 +1,3 @@ +module github.com/real-logic/simple-binary-encoding + +go 1.12 diff --git a/sbe-tool/src/main/golang/go.sum b/sbe-tool/src/main/golang/go.sum new file mode 100644 index 0000000000..479781e603 --- /dev/null +++ b/sbe-tool/src/main/golang/go.sum @@ -0,0 +1,17 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/sbe-tool/src/main/golang/json/json_printer.go b/sbe-tool/src/main/golang/json/json_printer.go new file mode 100644 index 0000000000..d6ec189f7f --- /dev/null +++ b/sbe-tool/src/main/golang/json/json_printer.go @@ -0,0 +1,76 @@ +package json + +import ( + "fmt" + "strings" + + "github.com/real-logic/simple-binary-encoding/otf" +) + +// JsonPrinter pretty prints JSON based upon the given Ir. +type JsonPrinter struct { + headerDecoder *otf.OftHeaderDecoder + ir *otf.IrDecoder +} + +// NewJsonPrinter creates a new JsonPrinter for a given message Ir. +func NewJsonPrinter(ir *otf.IrDecoder) (*JsonPrinter, error) { + d, err := otf.NewOtfHeaderDecoder(ir.Header()) + return &JsonPrinter{ + headerDecoder: d, + ir: ir, + }, err +} + +// Print the encoded message to the output. +func (printer *JsonPrinter) Print(buffer []byte, output *strings.Builder) error { + blockLength, err := printer.headerDecoder.BlockLength(buffer) + if err != nil { + return fmt.Errorf("Error getting blockLength: %s", err) + } + templateId, err := printer.headerDecoder.TemplateId(buffer) + if err != nil { + return fmt.Errorf("Error getting templateId: %s", err) + } + schemaId, err := printer.headerDecoder.SchemaId(buffer) + if err != nil { + return fmt.Errorf("Error getting schemaId: %s", err) + } + actingVersion, err := printer.headerDecoder.SchemaVersion(buffer) + if err != nil { + return fmt.Errorf("Error getting schemaVersion: %s", err) + } + err = printer.validateId(schemaId) + if err != nil { + return err + } + + messageOffset := printer.headerDecoder.EncodedLength() + msgTokens := printer.ir.MessageByID(int32(templateId)) + + otf.Decode( + buffer[messageOffset:], + actingVersion, + blockLength, + msgTokens, + newJsonTokenListener(output), + ) + + return nil +} + +func (printer *JsonPrinter) validateId(schemaId uint64) error { + if schemaId != uint64(printer.ir.Id()) { + return fmt.Errorf("Required schema id %d but was %d", printer.ir.Id(), schemaId) + } + return nil +} + +// PrintJson the encoded message to a String. +func (printer *JsonPrinter) PrintJson(buffer []byte) (string, error) { + sb := strings.Builder{} + if err := printer.Print(buffer, &sb); err != nil { + return "", err + } + return sb.String(), nil +} diff --git a/sbe-tool/src/main/golang/json/json_token_listener.go b/sbe-tool/src/main/golang/json/json_token_listener.go new file mode 100644 index 0000000000..af7c711f64 --- /dev/null +++ b/sbe-tool/src/main/golang/json/json_token_listener.go @@ -0,0 +1,410 @@ +package json + +import ( + "encoding/hex" + "strconv" + "strings" + + "github.com/real-logic/simple-binary-encoding/otf" +) + +// JsonTokenListener dynamically decodes to convert them to JSON for output. +type JsonTokenListener struct { + output *strings.Builder + indentation int + compositeLevel int + more bool +} + +func newJsonTokenListener(output *strings.Builder) *JsonTokenListener { + return &JsonTokenListener{ + output: output, + } +} + +func (t *JsonTokenListener) printScope() { + for i := 0; i < t.compositeLevel; i++ { + t.output.WriteString(" ") + } +} + +func isLastGroup(groupIndex uint64, numInGroup uint64) bool { + return groupIndex == numInGroup-1 +} + +func (t *JsonTokenListener) startObject() { + t.indent() + t.output.WriteString("{\n") + t.indentation++ + t.more = false +} + +func (t *JsonTokenListener) endObject() { + t.output.WriteString("\n") + t.indentation-- + t.indent() + t.output.WriteString("}") + t.more = true +} + +func (t *JsonTokenListener) property(name string) { + t.indent() + t.doubleQuote() + t.output.WriteString(name) + t.output.WriteString("\": ") +} + +func (t *JsonTokenListener) indent() { + for i := 0; i < t.indentation; i++ { + t.output.WriteString(" ") + } +} + +func (t *JsonTokenListener) doubleQuote() { + t.output.WriteString("\"") +} + +func (t *JsonTokenListener) prev() { + if t.more { + t.output.WriteString(",\n") + } +} + +func (t *JsonTokenListener) next() { + t.more = true +} + +func (t *JsonTokenListener) escapePrintableChar(buffer []byte, index int, size int, elementSize int) { + for i := 0; i < size; i++ { + c := buffer[index+i*elementSize] + if c > 0 { + t.escape(rune(c)) + } else { + break + } + } +} + +func (t *JsonTokenListener) escapeString(str string) { + for _, c := range str { + t.escape(c) + } +} + +func (t *JsonTokenListener) escape(c rune) { + if c == '"' || c == '\\' || c == '\b' || c == '\f' || c == '\n' || c == '\r' || c == '\t' { + t.output.WriteString("\\") + } + + t.output.WriteRune(c) +} + +func (t *JsonTokenListener) determineName( + thresholdLevel int, + fieldToken otf.Token, + tokens []otf.Token, + fromIndex int, +) string { + if t.compositeLevel > thresholdLevel { + return tokens[fromIndex].Name() + } else { + return fieldToken.Name() + } + +} + +func (t *JsonTokenListener) OnBeginMessage(token otf.Token) { + t.startObject() +} + +func (t *JsonTokenListener) OnEndMessage(token otf.Token) { + t.endObject() +} + +func (t *JsonTokenListener) OnEncoding(fieldToken otf.Token, buffer []byte, typeToken otf.Token, actingVersion uint64) { + t.prev() + name := fieldToken.Name() + if t.compositeLevel > 0 { + name = fieldToken.Name() + } + t.property(name) + t.appendEncodingAsString(buffer, typeToken, uint64(fieldToken.TokenVersion()), actingVersion) + t.next() +} + +func (t *JsonTokenListener) appendEncodingAsString( + buffer []byte, + typeToken otf.Token, + fieldVersion uint64, + actingVersion uint64, +) { + arrayLength := typeToken.ArrayLength() + encoding := typeToken.Encoding() + constOrNotPresentValue := t.constOrNotPresentValue(typeToken, fieldVersion, actingVersion) + if constOrNotPresentValue.PrimitiveType != otf.NONE { + characterEncoding := encoding.CharacterEncoding() + if characterEncoding == "" { + t.doubleQuote() + t.escapeString(constOrNotPresentValue.String()) + t.doubleQuote() + } else { + if arrayLength < 2 { + t.doubleQuote() + t.escapeString(constOrNotPresentValue.String()) + t.doubleQuote() + } else { + t.output.WriteString("[") + for i := int32(0); i < arrayLength; i++ { + if i > 0 { + t.output.WriteString(", ") + } + t.doubleQuote() + t.escapeString(constOrNotPresentValue.String()) + t.doubleQuote() + } + t.output.WriteString("]") + } + } + } else { + elementSize := encoding.PrimitiveType().Size() + if arrayLength < 1 && encoding.PrimitiveType() == otf.CHAR { + t.doubleQuote() + t.escapePrintableChar(buffer, 0, int(arrayLength), elementSize) + } else { + encoding := typeToken.Encoding() + elementSize := int32(encoding.PrimitiveType().Size()) + if arrayLength == 1 { + otf.AppendPrimitiveValueJson(t.output, otf.NewPrimitiveValue(encoding.PrimitiveType(), buffer)) + } else { + t.output.WriteString("[") + for i := int32(0); i < typeToken.ArrayLength(); i++ { + if i > 0 { + t.output.WriteString(", ") + } + otf.AppendPrimitiveValueJson(t.output, otf.NewPrimitiveValue(encoding.PrimitiveType(), + buffer[i*elementSize:(i+1)*elementSize])) + } + t.output.WriteString("]") + } + } + } +} + +func (t *JsonTokenListener) readEncodingAsInt( + buffer []byte, + typeToken otf.Token, + fieldVersion uint64, + actingVersion uint64, +) int64 { + constOrNotPresentValue := t.constOrNotPresentValue(typeToken, fieldVersion, actingVersion) + if constOrNotPresentValue.PrimitiveType != otf.NONE { + return constOrNotPresentValue.AsInt() + } + typeTokenEncoding := typeToken.Encoding() + v, _ := otf.GetAsInt(typeTokenEncoding.PrimitiveType(), typeTokenEncoding.ByteOrder(), buffer) + return v +} + +func (t *JsonTokenListener) readEncodingAsUInt( + buffer []byte, + typeToken otf.Token, + fieldVersion uint64, + actingVersion uint64, +) uint64 { + constOrNotPresentValue := t.constOrNotPresentValue(typeToken, fieldVersion, actingVersion) + if constOrNotPresentValue.PrimitiveType != otf.NONE { + return constOrNotPresentValue.AsUInt() + } + typeTokenEncoding := typeToken.Encoding() + v, _ := otf.GetAsUInt(typeTokenEncoding.PrimitiveType(), typeTokenEncoding.ByteOrder(), buffer) + return v +} + +func (t *JsonTokenListener) constOrNotPresentValue( + typeToken otf.Token, + fieldVersion uint64, + actingVersion uint64, +) otf.PrimitiveValue { + typeTokenEncoding := typeToken.Encoding() + if typeToken.IsConstantEncoding() { + return typeTokenEncoding.ConstValue() + } else if typeToken.IsOptionalEncoding() && actingVersion < fieldVersion { + return typeTokenEncoding.ApplicableNullValue() + } else { + return otf.PrimitiveValue{} + } +} + +func (t *JsonTokenListener) OnEnum( + fieldToken otf.Token, + buffer []byte, + tokens []otf.Token, + fromIndex int, + toIndex int, + actingVersion uint64, +) { + t.prev() + typeToken := tokens[fromIndex+1] + encoding := typeToken.Encoding() + + value := "" + if fieldToken.IsConstantEncoding() { + encoding := fieldToken.Encoding() + refValue := encoding.ConstValue() + indexOfDot := strings.LastIndex(refValue.String(), ".") + if indexOfDot == -1 { + value = refValue.String() + } else { + value = refValue.String()[indexOfDot+1:] + } + } else if encoding.PrimitiveType().IsUnsigned() { + encodedValue := t.readEncodingAsUInt( + buffer, + typeToken, + uint64(fieldToken.TokenVersion()), + actingVersion, + ) + for i := fromIndex + 1; i < toIndex; i++ { + encoding := tokens[i].Encoding() + constValue := encoding.ConstValue() + if constValue.AsUInt() == encodedValue { + value = tokens[i].Name() + break + } + } + } else { + encodedValue := t.readEncodingAsInt( + buffer, + typeToken, + uint64(fieldToken.TokenVersion()), + actingVersion, + ) + for i := fromIndex + 1; i < toIndex; i++ { + encoding := tokens[i].Encoding() + constValue := encoding.ConstValue() + if constValue.AsInt() == encodedValue { + value = tokens[i].Name() + break + } + } + } + + t.property(t.determineName(0, fieldToken, tokens, fromIndex)) + t.doubleQuote() + t.output.WriteString(value) + t.doubleQuote() + t.next() +} + +func (t *JsonTokenListener) OnBitSet( + fieldToken otf.Token, + buffer []byte, + tokens []otf.Token, + fromIndex int, + toIndex int, + actingVersion uint64, +) { + t.prev() + typeToken := tokens[fromIndex+1] + encodedValue := t.readEncodingAsInt( + buffer, + typeToken, + uint64(fieldToken.TokenVersion()), + actingVersion, + ) + t.property(t.determineName(0, fieldToken, tokens, fromIndex)) + + t.output.WriteString("{ ") + for i := fromIndex + 1; i < toIndex; i++ { + t.output.WriteString(`"`) + t.output.WriteString(tokens[i].Name()) + t.output.WriteString(`": `) + encoding := tokens[i].Encoding() + constValue := encoding.ConstValue() + bitPosition := constValue.AsInt() + flag := (encodedValue & (1 << uint64(bitPosition))) != 0 + t.output.WriteString(strconv.FormatBool(flag)) + if i < toIndex-1 { + t.output.WriteString(", ") + } + } + t.output.WriteString(` }`) + t.next() +} + +func (t *JsonTokenListener) OnBeginComposite( + fieldToken otf.Token, + tokens []otf.Token, + fromIndex int, + toIndex int, +) { + t.prev() + t.compositeLevel++ + t.property(t.determineName(0, fieldToken, tokens, fromIndex)) + t.output.WriteString("\n") + t.startObject() +} + +func (t *JsonTokenListener) OnEndComposite( + token otf.Token, + tokens []otf.Token, + fromIndex int, + toIndex int, +) { + t.compositeLevel-- + t.endObject() +} + +func (t *JsonTokenListener) OnGroupHeader( + token otf.Token, + numInGroup uint64, +) { + t.prev() + t.property(token.Name()) + if numInGroup > 0 { + t.output.WriteString("[\n") + t.more = false + } else { + t.output.WriteString("[]") + } +} + +func (t *JsonTokenListener) OnBeginGroup( + token otf.Token, + groupIndex uint64, + numInGroup uint64, +) { + t.prev() + t.startObject() +} + +func (t *JsonTokenListener) OnEndGroup( + token otf.Token, + groupIndex uint64, + numInGroup uint64, +) { + t.endObject() + if isLastGroup(groupIndex, numInGroup) { + t.output.WriteString("]") + } +} + +func (t *JsonTokenListener) OnVarData( + fieldToken otf.Token, + buffer []byte, + length uint64, + typeToken otf.Token, +) { + t.prev() + t.property(fieldToken.Name()) + t.doubleQuote() + + typeTokenEncoding := typeToken.Encoding() + if characterEncoding := typeTokenEncoding.CharacterEncoding(); characterEncoding == "" { + t.escapeString(hex.EncodeToString(buffer[:length])) + } else { + t.escapeString(string(buffer[:length])) + } + t.doubleQuote() + t.next() +} diff --git a/sbe-tool/src/main/golang/main.go b/sbe-tool/src/main/golang/main.go new file mode 100644 index 0000000000..3b246a530c --- /dev/null +++ b/sbe-tool/src/main/golang/main.go @@ -0,0 +1,3 @@ +package sbe + +//go:generate java -Dsbe.output.dir=. -Dsbe.target.language=golang -Dsbe.go.generate.generate.flyweights=true -jar ${SBE_JAR} ../resources/sbe-ir.xml diff --git a/sbe-tool/src/main/golang/otf/encoding.go b/sbe-tool/src/main/golang/otf/encoding.go new file mode 100644 index 0000000000..a10fef5b2d --- /dev/null +++ b/sbe-tool/src/main/golang/otf/encoding.go @@ -0,0 +1,673 @@ +// Copyright 2013-2024 Real Logic Limited. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package otf + +import ( + "encoding/binary" + "errors" + "fmt" + "math" + "strconv" + "strings" +) + +type ByteOrder int + +const ( + SbeLittleEndian ByteOrder = iota + SbeBigEndian +) + +// String returns the string representation of the ByteOrder. +func (o ByteOrder) String() string { + switch o { + case SbeLittleEndian: + return "SbeLittleEndian" + case SbeBigEndian: + return "SbeBigEndian" + default: + return "Unknown" + } +} + +type PrimitiveType int + +const ( + NONE PrimitiveType = iota + CHAR + INT8 + INT16 + INT32 + INT64 + UINT8 + UINT16 + UINT32 + UINT64 + FLOAT + DOUBLE +) + +func (p PrimitiveType) String() string { + switch p { + case NONE: + return "NONE" + case CHAR: + return "CHAR" + case INT8: + return "INT8" + case INT16: + return "INT16" + case INT32: + return "INT32" + case INT64: + return "INT64" + case UINT8: + return "UINT8" + case UINT16: + return "UINT16" + case UINT32: + return "UINT32" + case UINT64: + return "UINT64" + case FLOAT: + return "FLOAT" + case DOUBLE: + return "DOUBLE" + default: + return "Unknown" + } +} + +func (p PrimitiveType) Size() int { + switch p { + case CHAR, INT8, UINT8: + return 1 + case INT16, UINT16: + return 2 + case INT32, UINT32, FLOAT: + return 4 + case INT64, UINT64, DOUBLE: + return 8 + default: + return 0 + } +} + +// IsUnsigned returns true if the type is unsigned. +func (p PrimitiveType) IsUnsigned() bool { + switch p { + case UINT8, UINT16, UINT32, UINT64: + return true + default: + return false + } +} + +type Presence int + +const ( + SbeRequired Presence = iota + SbeOptional + SbeConstant +) + +func (p Presence) String() string { + switch p { + case SbeRequired: + return "SbeRequired" + case SbeOptional: + return "SbeOptional" + case SbeConstant: + return "SbeConstant" + default: + return "Unknown" + } +} + +type PrimitiveValue struct { + PrimitiveType + size int + asInt int64 + asUInt uint64 + asDouble float64 + arrayValue string +} + +// String returns the string representation of the value. +func (p *PrimitiveValue) String() string { + switch p.PrimitiveType { + case CHAR: + if p.size > 1 { + return p.arrayValue + } + return string(byte(p.asInt)) + case INT8, INT16, INT32, INT64: + return strconv.FormatInt(p.asInt, 10) + case UINT8, UINT16, UINT32, UINT64: + return strconv.FormatUint(p.asUInt, 10) + case FLOAT, DOUBLE: + return strconv.FormatFloat(p.asDouble, 'f', -1, 64) + default: + return "" + } +} + +func AppendPrimitiveValue(sb *strings.Builder, p PrimitiveValue) { + switch p.PrimitiveType { + case CHAR: + if p.size > 1 { + sb.WriteString(p.arrayValue) + return + } + sb.WriteByte(byte(p.asInt)) + case INT8, INT16, INT32, INT64: + sb.WriteString(strconv.FormatInt(p.asInt, 10)) + case UINT8, UINT16, UINT32, UINT64: + sb.WriteString(strconv.FormatUint(p.asUInt, 10)) + case FLOAT, DOUBLE: + sb.WriteString(strconv.FormatFloat(p.asDouble, 'f', -1, 64)) + } +} + +func AppendPrimitiveValueJson(sb *strings.Builder, p PrimitiveValue) { + switch p.PrimitiveType { + case CHAR: + if p.size > 1 { + sb.WriteString(p.arrayValue) + return + } + sb.WriteRune('"') + sb.WriteByte(byte(p.asInt)) + sb.WriteRune('"') + case INT8, INT16, INT32, INT64: + sb.WriteString(strconv.FormatInt(p.asInt, 10)) + case UINT8: + sb.WriteString(strconv.FormatUint(p.asUInt&0xFF, 10)) + case UINT16: + sb.WriteString(strconv.FormatUint(p.asUInt&0xFFFF, 10)) + case UINT32: + sb.WriteString(strconv.FormatUint(p.asUInt&0xFFFFFFFF, 10)) + case UINT64: + sb.WriteString(strconv.FormatUint(p.asUInt, 10)) + case FLOAT, DOUBLE: + sb.WriteString(strconv.FormatFloat(p.asDouble, 'f', -1, 64)) + } +} + +func NewPrimitiveValue(t PrimitiveType, value []byte) PrimitiveValue { + p := PrimitiveValue{PrimitiveType: t} + + if len(value) == 0 { + return p + } + + switch t { + case CHAR: + if len(value) > 1 { + p.arrayValue = string(value) + p.size = len(value) + } else { + p.asInt = int64(value[0]) + p.size = 1 + } + case INT8: + p.asInt = int64(value[0]) + p.size = 1 + case INT16: + p.asInt = int64(binary.LittleEndian.Uint16(value)) + p.size = 2 + case INT32: + p.asInt = int64(binary.LittleEndian.Uint32(value)) + p.size = 4 + case INT64: + p.asInt = int64(binary.LittleEndian.Uint64(value)) + p.size = 8 + case UINT8: + p.asUInt = uint64(value[0]) + p.size = 1 + case UINT16: + p.asUInt = uint64(binary.LittleEndian.Uint16(value)) + p.size = 2 + case UINT32: + p.asUInt = uint64(binary.LittleEndian.Uint32(value)) + p.size = 4 + case UINT64: + p.asUInt = binary.LittleEndian.Uint64(value) + p.size = 8 + case FLOAT: + p.asDouble = float64(math.Float32frombits(binary.LittleEndian.Uint32(value))) + p.size = 4 + case DOUBLE: + p.asDouble = math.Float64frombits(binary.LittleEndian.Uint64(value)) + p.size = 8 + default: + p.PrimitiveType = NONE + p.size = 0 + } + + return p +} + +func ParsePrimitiveValue(t PrimitiveType, value []byte) (PrimitiveValue, error) { + p := PrimitiveValue{PrimitiveType: t} + + var err error + + switch t { + case CHAR: + if len(value) > 1 { + p.arrayValue = string(value) + p.size = len(value) + } else { + p.asInt = int64(value[0]) + p.size = 1 + } + case INT8: + p.asInt, err = strconv.ParseInt(string(value), 10, 8) + p.size = 1 + case INT16: + p.asInt, err = strconv.ParseInt(string(value), 10, 16) + p.size = 2 + case INT32: + p.asInt, err = strconv.ParseInt(string(value), 10, 32) + p.size = 4 + case INT64: + p.asInt, err = strconv.ParseInt(string(value), 10, 64) + p.size = 8 + case UINT8: + p.asUInt, err = strconv.ParseUint(string(value), 10, 8) + p.size = 1 + case UINT16: + p.asUInt, err = strconv.ParseUint(string(value), 10, 16) + p.size = 2 + case UINT32: + p.asUInt, err = strconv.ParseUint(string(value), 10, 32) + p.size = 4 + case UINT64: + p.asUInt, err = strconv.ParseUint(string(value), 10, 64) + p.size = 8 + case FLOAT: + p.asDouble, err = strconv.ParseFloat(string(value), 32) + p.size = 4 + case DOUBLE: + p.asDouble, err = strconv.ParseFloat(string(value), 64) + p.size = 8 + default: + p.PrimitiveType = NONE + p.size = 0 + } + + return p, err +} + +func NewNoneValue() PrimitiveValue { + return PrimitiveValue{} +} + +func NewCharValue(value byte) PrimitiveValue { + return PrimitiveValue{ + PrimitiveType: CHAR, + size: 1, + asInt: int64(value), + } +} + +func NewStringValue(value string) PrimitiveValue { + return PrimitiveValue{ + PrimitiveType: CHAR, + size: len(value), + arrayValue: value, + } +} + +func NewInt8Value(value int8) PrimitiveValue { + return PrimitiveValue{ + PrimitiveType: INT8, + size: 1, + asInt: int64(value), + } +} + +func NewInt16Value(value int16) PrimitiveValue { + return PrimitiveValue{ + PrimitiveType: INT16, + size: 2, + asInt: int64(value), + } +} + +func NewInt32Value(value int32) PrimitiveValue { + return PrimitiveValue{ + PrimitiveType: INT32, + size: 4, + asInt: int64(value), + } +} + +func NewInt64Value(value int64) PrimitiveValue { + return PrimitiveValue{ + PrimitiveType: INT64, + size: 8, + asInt: value, + } +} + +func NewUInt8Value(value uint8) PrimitiveValue { + return PrimitiveValue{ + PrimitiveType: UINT8, + size: 1, + asUInt: uint64(value), + } +} + +func NewUInt16Value(value uint16) PrimitiveValue { + return PrimitiveValue{ + PrimitiveType: UINT16, + size: 2, + asUInt: uint64(value), + } +} + +func NewUInt32Value(value uint32) PrimitiveValue { + return PrimitiveValue{ + PrimitiveType: UINT32, + size: 4, + asUInt: uint64(value), + } +} + +func NewUInt64Value(value uint64) PrimitiveValue { + return PrimitiveValue{ + PrimitiveType: UINT64, + size: 8, + asUInt: value, + } +} + +func NewFloatValue(value float32) PrimitiveValue { + return PrimitiveValue{ + PrimitiveType: FLOAT, + size: 4, + asDouble: float64(value), + } +} + +func NewDoubleValue(value float64) PrimitiveValue { + return PrimitiveValue{ + PrimitiveType: DOUBLE, + size: 8, + asDouble: value, + } +} + +func (p *PrimitiveValue) AsInt() int64 { + return p.asInt +} + +func (p *PrimitiveValue) AsUInt() uint64 { + return p.asUInt +} + +func (p *PrimitiveValue) AsDouble() float64 { + return p.asDouble +} + +func (p *PrimitiveValue) GetArray() string { + return p.arrayValue +} + +func (p *PrimitiveValue) AsString() string { + if p.size <= 1 { + return string(byte(p.asInt)) + } + for i := 0; i < len(p.arrayValue); i++ { + if p.arrayValue[i] == 0 { + return p.arrayValue[:i] + } + } + return p.arrayValue +} + +func (p *PrimitiveValue) Size() int { + return p.size +} + +type Encoding struct { + presence Presence + primitiveType PrimitiveType + byteOrder ByteOrder + minValue PrimitiveValue + maxValue PrimitiveValue + nullValue PrimitiveValue + constValue PrimitiveValue + characterEncoding string + epoch string + timeUnit string + semanticType string +} + +func (e *Encoding) String() string { + return fmt.Sprintf( + "Encoding{presence: %s primitiveType: %s, byteOrder: %s, minValue: %s, maxValue: %s, nullValue: %s, constValue: %s, characterEncoding: %s, epoch: %s, timeUnit: %s, semanticType: %s}", + e.presence, + e.primitiveType, + e.byteOrder, + &e.minValue, + &e.maxValue, + &e.nullValue, + &e.constValue, + e.characterEncoding, + e.epoch, + e.timeUnit, + e.semanticType, + ) +} + +func NewEncoding( + primitiveType PrimitiveType, + presence Presence, + byteOrder ByteOrder, + minValue, maxValue, nullValue, constValue PrimitiveValue, + characterEncoding, epoch, timeUnit, semanticType string) Encoding { + return Encoding{ + presence: presence, + primitiveType: primitiveType, + byteOrder: byteOrder, + minValue: minValue, + maxValue: maxValue, + nullValue: nullValue, + constValue: constValue, + characterEncoding: characterEncoding, + epoch: epoch, + timeUnit: timeUnit, + semanticType: semanticType, + } +} + +func GetChar(buffer []byte) byte { + return buffer[0] +} + +func GetInt8(buffer []byte) int8 { + return int8(buffer[0]) +} + +func GetInt16(buffer []byte, order ByteOrder) int16 { + if order == SbeLittleEndian { + return int16(binary.LittleEndian.Uint16(buffer)) + } + return int16(binary.BigEndian.Uint16(buffer)) +} + +func GetInt32(buffer []byte, order ByteOrder) int32 { + if order == SbeLittleEndian { + return int32(binary.LittleEndian.Uint32(buffer)) + } + return int32(binary.BigEndian.Uint32(buffer)) +} + +func GetInt64(buffer []byte, order ByteOrder) int64 { + if order == SbeLittleEndian { + return int64(binary.LittleEndian.Uint64(buffer)) + } + return int64(binary.BigEndian.Uint64(buffer)) +} + +func GetUInt8(buffer []byte) uint8 { + return buffer[0] +} + +func GetUInt16(buffer []byte, order ByteOrder) uint16 { + if order == SbeLittleEndian { + return binary.LittleEndian.Uint16(buffer) + } + return binary.BigEndian.Uint16(buffer) +} + +func GetUInt32(buffer []byte, order ByteOrder) uint32 { + if order == SbeLittleEndian { + return binary.LittleEndian.Uint32(buffer) + } + return binary.BigEndian.Uint32(buffer) +} + +func GetUInt64(buffer []byte, order ByteOrder) uint64 { + if order == SbeLittleEndian { + return binary.LittleEndian.Uint64(buffer) + } + return binary.BigEndian.Uint64(buffer) +} + +func GetFloat(buffer []byte, order ByteOrder) float32 { + if order == SbeLittleEndian { + return math.Float32frombits(binary.LittleEndian.Uint32(buffer)) + } + return math.Float32frombits(binary.BigEndian.Uint32(buffer)) +} + +func GetDouble(buffer []byte, order ByteOrder) float64 { + if order == SbeLittleEndian { + return math.Float64frombits(binary.LittleEndian.Uint64(buffer)) + } + return math.Float64frombits(binary.BigEndian.Uint64(buffer)) +} + +func GetAsInt(primitiveType PrimitiveType, byteOrder ByteOrder, buffer []byte) (int64, error) { + switch primitiveType { + case CHAR: + return int64(GetChar(buffer)), nil + case INT8: + return int64(GetInt8(buffer)), nil + case INT16: + return int64(GetInt16(buffer, byteOrder)), nil + case INT32: + return int64(GetInt32(buffer, byteOrder)), nil + case INT64: + return GetInt64(buffer, byteOrder), nil + default: + return 0, errors.New("incorrect type for Encoding.GetAsInt") + } +} + +func GetAsUInt(primitiveType PrimitiveType, byteOrder ByteOrder, buffer []byte) (uint64, error) { + switch primitiveType { + case UINT8: + return uint64(GetUInt8(buffer)), nil + case UINT16: + return uint64(GetUInt16(buffer, byteOrder)), nil + case UINT32: + return uint64(GetUInt32(buffer, byteOrder)), nil + case UINT64: + return GetUInt64(buffer, byteOrder), nil + default: + return 0, errors.New("incorrect type for Encoding.GetAsUInt") + } +} + +func GetAsDouble(primitiveType PrimitiveType, byteOrder ByteOrder, buffer []byte) (float64, error) { + switch primitiveType { + case FLOAT: + return float64(GetFloat(buffer, byteOrder)), nil + case DOUBLE: + return GetDouble(buffer, byteOrder), nil + default: + return 0, errors.New("incorrect type for Encoding.GetAsDouble") + } +} + +func (e *Encoding) GetAsInt(buffer []byte) (int64, error) { + return GetAsInt(e.primitiveType, e.byteOrder, buffer) +} + +func (e *Encoding) GetAsUInt(buffer []byte) (uint64, error) { + return GetAsUInt(e.primitiveType, e.byteOrder, buffer) +} + +func (e *Encoding) GetAsDouble(buffer []byte) (float64, error) { + return GetAsDouble(e.primitiveType, e.byteOrder, buffer) +} + +func (e *Encoding) Presence() Presence { + return e.presence +} + +func (e *Encoding) PrimitiveType() PrimitiveType { + return e.primitiveType +} + +func (e *Encoding) ByteOrder() ByteOrder { + return e.byteOrder +} + +func (e *Encoding) MinValue() PrimitiveValue { + return e.minValue +} + +func (e *Encoding) MaxValue() PrimitiveValue { + return e.maxValue +} + +func (e *Encoding) NullValue() PrimitiveValue { + return e.nullValue +} + +func (e *Encoding) ConstValue() PrimitiveValue { + return e.constValue +} + +func (e *Encoding) CharacterEncoding() string { + return e.characterEncoding +} + +func (e *Encoding) Epoch() string { + return e.epoch +} + +func (e *Encoding) TimeUnit() string { + return e.timeUnit +} + +func (e *Encoding) SemanticType() string { + return e.semanticType +} + +func (e *Encoding) ApplicableNullValue() PrimitiveValue { + if e.nullValue.PrimitiveType != NONE { + return e.nullValue + } + return PrimitiveValue{ + PrimitiveType: e.primitiveType, + } +} diff --git a/sbe-tool/src/main/golang/otf/irdecoder.go b/sbe-tool/src/main/golang/otf/irdecoder.go new file mode 100644 index 0000000000..d90876e637 --- /dev/null +++ b/sbe-tool/src/main/golang/otf/irdecoder.go @@ -0,0 +1,355 @@ +package otf + +import ( + "os" + "sort" + "strings" + + ir "github.com/real-logic/simple-binary-encoding/uk_co_real_logic_sbe_ir_generated" +) + +type IrDecoder struct { + headerTokens []Token + messages [][]Token + buffer []byte + length uint64 + id int32 + typesByName map[string][]Token +} + +func NewIrDecoder() *IrDecoder { + return &IrDecoder{ + typesByName: make(map[string][]Token), + } +} + +func (decoder *IrDecoder) Decode(irBuffer []byte) int { + length := uint64(len(irBuffer)) + decoder.length = length + if length == 0 { + return -1 + } + decoder.buffer = make([]byte, length) + copy(decoder.buffer, irBuffer) + return decoder.decodeIr() +} + +func (decoder *IrDecoder) DecodeFile(filename string) int { + fileStat, err := os.Stat(filename) + if err != nil { + return -1 + } + + decoder.length = uint64(fileStat.Size()) + if decoder.length == 0 { + return -1 + } + decoder.buffer = make([]byte, decoder.length) + + if err := readFileIntoBuffer(decoder.buffer, filename, decoder.length); err != nil { + return -1 + } + + return decoder.decodeIr() +} + +func (decoder *IrDecoder) Header() []Token { + return decoder.headerTokens +} + +func (decoder *IrDecoder) Messages() [][]Token { + return decoder.messages +} + +func (decoder *IrDecoder) Message(id int32, version int32) []Token { + for _, tokens := range decoder.messages { + token := &tokens[0] + if token.Signal() == SignalBeginMessage && token.FieldId() == id && token.TokenVersion() == version { + return tokens + } + } + return nil +} + +func (decoder *IrDecoder) MessageByID(id int32) []Token { + for _, tokens := range decoder.messages { + token := &tokens[0] + if token.Signal() == SignalBeginMessage && token.FieldId() == id { + return tokens + } + } + return nil +} + +// TypeByName gets the type representation for a given type name. +func (decoder *IrDecoder) TypeByName(name string) []Token { + return decoder.typesByName[name] +} + +func (decoder *IrDecoder) decodeIr() int { + var frame ir.FrameCodec + offset := uint64(0) + var tmp [256]byte + + frame.WrapForDecode( + decoder.buffer, + offset, + uint64(frame.SbeBlockLength()), + uint64(frame.SbeSchemaVersion()), + decoder.length, + ) + + frame.GetPackageName(tmp[:]) + + if frame.IrVersion() != 0 { + return -1 + } + + frame.GetNamespaceName(tmp[:]) + frame.GetSemanticVersion(tmp[:]) + + offset += frame.EncodedLength() + + decoder.headerTokens = make([]Token, 0) + + headerLength := decoder.readHeader(offset) + + decoder.id = frame.IrId() + + offset += headerLength + + for offset < decoder.length { + offset += decoder.readMessage(offset) + } + + decoder.captureTypes(decoder.headerTokens, 0, len(decoder.headerTokens)-1) + + return 0 +} +func (decoder *IrDecoder) decodeAndAddToken(tokens *[]Token, offset uint64) uint64 { + var tokenCodec ir.TokenCodec + tokenCodec.WrapForDecode( + decoder.buffer, + offset, + uint64(tokenCodec.SbeBlockLength()), + uint64(tokenCodec.SbeSchemaVersion()), + decoder.length, + ) + + signal := Signal(tokenCodec.Signal()) + primitiveType := PrimitiveType(tokenCodec.PrimitiveType()) + presence := Presence(tokenCodec.Presence()) + byteOrder := ByteOrder(tokenCodec.ByteOrder()) + tokenOffset := tokenCodec.TokenOffset() + tokenSize := tokenCodec.TokenSize() + id := tokenCodec.FieldId() + version := tokenCodec.TokenVersion() + componentTokenCount := tokenCodec.ComponentTokenCount() + + name := tokenCodec.GetNameAsString() + + tmpBuffer := [256]byte{} + tmpLength := tokenCodec.GetConstValue(tmpBuffer[:]) + constValue := NewPrimitiveValue(primitiveType, tmpBuffer[:tmpLength]) + tmpLength = tokenCodec.GetMinValue(tmpBuffer[:]) + minValue := NewPrimitiveValue(primitiveType, tmpBuffer[:tmpLength]) + tmpLength = tokenCodec.GetMaxValue(tmpBuffer[:]) + maxValue := NewPrimitiveValue(primitiveType, tmpBuffer[:tmpLength]) + tmpLength = tokenCodec.GetNullValue(tmpBuffer[:]) + nullValue := NewPrimitiveValue(primitiveType, tmpBuffer[:tmpLength]) + + characterEncoding := tokenCodec.GetCharacterEncodingAsString() + epoch := tokenCodec.GetEpochAsString() + timeUnit := tokenCodec.GetTimeUnitAsString() + semanticType := tokenCodec.GetSemanticTypeAsString() + description := tokenCodec.GetDescriptionAsString() + referencedName := tokenCodec.GetReferencedNameAsString() + + encoding := NewEncoding( + primitiveType, + presence, + byteOrder, + minValue, + maxValue, + nullValue, + constValue, + characterEncoding, + epoch, + timeUnit, + semanticType, + ) + + token := Token{ + offset: tokenOffset, + fieldId: id, + version: version, + encodedLength: tokenSize, + componentTokenCount: componentTokenCount, + signal: signal, + name: name, + referencedName: referencedName, + description: description, + encoding: encoding, + } + + *tokens = append(*tokens, token) + + return tokenCodec.EncodedLength() +} + +func (decoder *IrDecoder) readHeader(offset uint64) uint64 { + size := uint64(0) + for offset+size < decoder.length { + size += decoder.decodeAndAddToken(&decoder.headerTokens, offset+size) + token := &decoder.headerTokens[len(decoder.headerTokens)-1] + if token.signal == SignalEndComposite { + break + } + } + return size +} + +func (decoder *IrDecoder) readMessage(offset uint64) uint64 { + size := uint64(0) + tokensForMessage := make([]Token, 0) + for offset+size < decoder.length { + size += decoder.decodeAndAddToken(&tokensForMessage, offset+size) + token := &tokensForMessage[len(tokensForMessage)-1] + if token.signal == SignalEndMessage { + break + } + } + + decoder.captureTypes(tokensForMessage, 0, len(tokensForMessage)-1) + decoder.updateComponentTokenCounts(tokensForMessage) + + decoder.messages = append(decoder.messages, tokensForMessage) + return size +} + +func (decoder *IrDecoder) Id() int32 { + return decoder.id +} + +func readFileIntoBuffer(buffer []byte, filename string, length uint64) error { + f, err := os.Open(filename) + if err != nil { + return err + } + defer f.Close() + + var remaining = length + for remaining > 0 { + bytes := uint(4098) + if remaining < 4098 { + bytes = uint(remaining) + } + sz, err := f.Read(buffer[length-remaining : length-remaining+uint64(bytes)]) + if err != nil { + return err + } + remaining -= uint64(sz) + } + + return nil +} + +func (decoder *IrDecoder) captureTypes(tokens []Token, beginIndex, endIndex int) { + for i := beginIndex; i < endIndex; i++ { + token := tokens[i] + typeBeginIndex := i + switch token.Signal() { + case SignalBeginComposite: + i = decoder.captureType( + tokens, + i, + SignalEndComposite, + token.Name(), + token.ReferencedName(), + ) + decoder.captureTypes(tokens, typeBeginIndex+1, i-1) + case SignalBeginEnum: + i = decoder.captureType( + tokens, + i, + SignalEndEnum, + token.Name(), + token.ReferencedName(), + ) + case SignalBeginSet: + i = decoder.captureType( + tokens, + i, + SignalEndSet, + token.Name(), + token.ReferencedName(), + ) + default: + } + } +} + +func (decoder *IrDecoder) captureType( + tokens []Token, + index int, + endSignal Signal, + name, referencedName string, +) int { + var typeTokens []Token + i := index + token := tokens[i] + typeTokens = append(typeTokens, token) + for { + i++ + token = tokens[i] + typeTokens = append(typeTokens, token) + if token.Signal() == endSignal || name == token.Name() { + break + } + } + + decoder.updateComponentTokenCounts(typeTokens) + + typeName := referencedName + if typeName == "" { + typeName = name + } + decoder.typesByName[typeName] = typeTokens + return i +} + +// updateComponentTokenCounts iterates over a list of Tokens and updates +// their counts of how many tokens make up each component. +func (decoder *IrDecoder) updateComponentTokenCounts(tokens []Token) { + beginIndexMap := make(map[string][]int) + for i, size := 0, len(tokens); i < size; i++ { + token := tokens[i] + signal := token.Signal() + if strings.HasPrefix(signal.String(), "Begin") { + componentType := signal.String()[5:] + beginIndexMap[componentType] = append(beginIndexMap[componentType], i) + } else if strings.HasPrefix(signal.String(), "End") { + componentType := signal.String()[3:] + beginIndices := beginIndexMap[componentType] + last := len(beginIndices) - 1 + beginIndex := beginIndices[last] + beginIndexMap[componentType] = beginIndices[:last] + componentTokenCount := int32((i - beginIndex) + 1) + tokens[beginIndex].componentTokenCount = componentTokenCount + token.componentTokenCount = componentTokenCount + } + } +} + +func (decoder *IrDecoder) Types() [][]Token { + var typeNames []string + for name := range decoder.typesByName { + typeNames = append(typeNames, name) + } + sort.Strings(typeNames) + var types [][]Token + for _, name := range typeNames { + types = append(types, decoder.typesByName[name]) + } + return types +} diff --git a/sbe-tool/src/main/golang/otf/otfheaderdecoder.go b/sbe-tool/src/main/golang/otf/otfheaderdecoder.go new file mode 100644 index 0000000000..5905437fa1 --- /dev/null +++ b/sbe-tool/src/main/golang/otf/otfheaderdecoder.go @@ -0,0 +1,105 @@ +package otf + +import "fmt" + +type OftHeaderDecoder struct { + encodedLength int32 + blockLengthOffset int32 + templateIdOffset int32 + schemaIdOffset int32 + schemaVersionOffset int32 + blockLengthType PrimitiveType + templateIdType PrimitiveType + schemaIdType PrimitiveType + schemaVersionType PrimitiveType + blockLengthByteOrder ByteOrder + templateIdByteOrder ByteOrder + schemaIdByteOrder ByteOrder + schemaVersionByteOrder ByteOrder +} + +func NewOtfHeaderDecoder(tokens []Token) (*OftHeaderDecoder, error) { + decoder := &OftHeaderDecoder{ + encodedLength: tokens[0].EncodedLength(), + } + + var blockLengthToken, + templateIdToken, + schemaIdToken, + versionToken *Token + + for i := range tokens { + token := tokens[i] + name := token.Name() + switch name { + case "blockLength": + blockLengthToken = &token + case "templateId": + templateIdToken = &token + case "schemaId": + schemaIdToken = &token + case "version": + versionToken = &token + } + } + + if blockLengthToken == nil { + return nil, fmt.Errorf("blockLength token not found") + } + + decoder.blockLengthOffset = blockLengthToken.Offset() + encoding := blockLengthToken.Encoding() + decoder.blockLengthType = encoding.PrimitiveType() + decoder.blockLengthByteOrder = encoding.ByteOrder() + + if templateIdToken == nil { + return nil, fmt.Errorf("templateId token not found") + } + + decoder.templateIdOffset = templateIdToken.Offset() + templateIdEncoding := templateIdToken.Encoding() + decoder.templateIdType = templateIdEncoding.PrimitiveType() + decoder.templateIdByteOrder = templateIdEncoding.ByteOrder() + + if schemaIdToken == nil { + return nil, fmt.Errorf("schemaId token not found") + } + + decoder.schemaIdOffset = schemaIdToken.Offset() + schemaIdEncoding := schemaIdToken.Encoding() + decoder.schemaIdType = schemaIdEncoding.PrimitiveType() + decoder.schemaIdByteOrder = schemaIdEncoding.ByteOrder() + + if versionToken == nil { + return nil, fmt.Errorf("version token not found") + } + + decoder.schemaVersionOffset = versionToken.Offset() + versionEncoding := versionToken.Encoding() + decoder.schemaVersionType = versionEncoding.PrimitiveType() + decoder.schemaVersionByteOrder = versionEncoding.ByteOrder() + + return decoder, nil +} + +func (o *OftHeaderDecoder) EncodedLength() int32 { + return o.encodedLength +} + +// All elements must be unsigned integers according to Specification + +func (o *OftHeaderDecoder) TemplateId(headerBuffer []byte) (uint64, error) { + return GetAsUInt(o.templateIdType, o.templateIdByteOrder, headerBuffer[o.templateIdOffset:]) +} + +func (o *OftHeaderDecoder) SchemaId(headerBuffer []byte) (uint64, error) { + return GetAsUInt(o.schemaIdType, o.schemaIdByteOrder, headerBuffer[o.schemaIdOffset:]) +} + +func (o *OftHeaderDecoder) SchemaVersion(headerBuffer []byte) (uint64, error) { + return GetAsUInt(o.schemaVersionType, o.schemaVersionByteOrder, headerBuffer[o.schemaVersionOffset:]) +} + +func (o *OftHeaderDecoder) BlockLength(headerBuffer []byte) (uint64, error) { + return GetAsUInt(o.blockLengthType, o.blockLengthByteOrder, headerBuffer[o.blockLengthOffset:]) +} diff --git a/sbe-tool/src/main/golang/otf/otfmessagedecoder.go b/sbe-tool/src/main/golang/otf/otfmessagedecoder.go new file mode 100644 index 0000000000..09e070e120 --- /dev/null +++ b/sbe-tool/src/main/golang/otf/otfmessagedecoder.go @@ -0,0 +1,311 @@ +package otf + +import "fmt" + +type OnBeginMessage func(token Token) +type OnEndMessage func(token Token) +type OnEncoding func(token Token, buffer []byte, actingVersion uint64) +type OnEnum func(token Token, buffer []byte, tokens []Token, fromIndex int, toIndex int, actingVersion uint64) +type OnBitSet func(token Token, buffer []byte, tokens []Token, fromIndex int, toIndex int, actingVersion uint64) +type OnBeginComposite func(token Token, tokens []Token, fromIndex int, toIndex int) +type OnEndComposite func(token Token, tokens []Token, fromIndex int, toIndex int) +type OnGroupHeader func(token Token, numInGroup uint64) +type OnBeginGroup func(token Token, groupIndex uint64, numInGroup uint64) +type OnEndGroup func(token Token, groupIndex uint64, numInGroup uint64) +type OnVarData func(token Token, buffer []byte, length uint64, typeToken Token) + +type TokenListener interface { + OnBeginMessage(token Token) + OnEndMessage(token Token) + OnEncoding(fieldToken Token, buffer []byte, typeToken Token, actingVersion uint64) + OnEnum(fieldToken Token, buffer []byte, tokens []Token, fromIndex int, toIndex int, actingVersion uint64) + OnBitSet(fieldToken Token, buffer []byte, tokens []Token, fromIndex int, toIndex int, actingVersion uint64) + OnBeginComposite(fieldToken Token, tokens []Token, fromIndex int, toIndex int) + OnEndComposite(fieldToken Token, tokens []Token, fromIndex int, toIndex int) + OnGroupHeader(token Token, numInGroup uint64) + OnBeginGroup(token Token, groupIndex uint64, numInGroup uint64) + OnEndGroup(token Token, groupIndex uint64, numInGroup uint64) + OnVarData(fieldToken Token, buffer []byte, length uint64, typeToken Token) +} + +func DecodeComposite( + fieldToken Token, + buffer []byte, + bufferIndex int, + length uint64, + tokens []Token, + tokenIndex int, + toIndex int, + actingVersion uint64, + listener TokenListener) int { + listener.OnBeginComposite(fieldToken, tokens, tokenIndex, toIndex) + for i := tokenIndex + 1; i < toIndex; { + token := tokens[i] + nextFieldIndex := i + int(token.ComponentTokenCount()) + offset := int(token.Offset()) + switch token.Signal() { + case SignalBeginComposite: + DecodeComposite( + fieldToken, + buffer, + bufferIndex+offset, + length, + tokens, + i, + nextFieldIndex-1, + actingVersion, + listener) + case SignalBeginEnum: + listener.OnEnum( + fieldToken, + buffer[bufferIndex+offset:], + tokens, + i, + nextFieldIndex-1, + actingVersion) + case SignalBeginSet: + listener.OnBitSet( + fieldToken, + buffer[bufferIndex+offset:], + tokens, + i, + nextFieldIndex-1, + actingVersion) + case SignalEncoding: + listener.OnEncoding(token, buffer[bufferIndex+offset:], token, actingVersion) + } + i += int(token.ComponentTokenCount()) + } + listener.OnEndComposite(fieldToken, tokens, tokenIndex, toIndex) + return tokenIndex +} + +func DecodeFields( + buffer []byte, + bufferIndex int, + length uint64, + actingVersion uint64, + tokens []Token, + tokenIndex int, + numTokens int, + listener TokenListener) int { + + for tokenIndex < numTokens { + fieldToken := tokens[tokenIndex] + if SignalBeginField != fieldToken.Signal() { + break + } + nextFieldIndex := tokenIndex + int(fieldToken.ComponentTokenCount()) + tokenIndex++ + + typeToken := tokens[tokenIndex] + offset := bufferIndex + int(typeToken.Offset()) + switch typeToken.Signal() { + case SignalBeginComposite: + DecodeComposite( + fieldToken, + buffer, + offset, + length, + tokens, + tokenIndex, + nextFieldIndex-2, + actingVersion, + listener) + case SignalBeginEnum: + listener.OnEnum( + fieldToken, + buffer[offset:], + tokens, + tokenIndex, + nextFieldIndex-2, + actingVersion) + case SignalBeginSet: + listener.OnBitSet( + fieldToken, + buffer[offset:], + tokens, + tokenIndex, + nextFieldIndex-2, + actingVersion) + case SignalEncoding: + listener.OnEncoding(fieldToken, buffer[offset:], typeToken, actingVersion) + } + tokenIndex = nextFieldIndex + } + + return tokenIndex +} + +func DecodeData( + buffer []byte, + bufferIndex int, + length uint64, + tokens []Token, + tokenIndex int, + numTokens int, + actingVersion uint64, + listener TokenListener) int { + for tokenIndex < numTokens { + token := tokens[tokenIndex] + if SignalBeginVarData != token.Signal() { + break + } + isPresent := token.TokenVersion() <= int32(actingVersion) + lengthToken := tokens[tokenIndex+2] + dataToken := tokens[tokenIndex+3] + if (uint64(bufferIndex) + uint64(dataToken.Offset())) > length { + panic("length too short for data length field") + } + dataLength := uint64(0) + if isPresent { + lengthTokenEncoding := lengthToken.Encoding() + + var err error + dataLength, err = lengthTokenEncoding.GetAsUInt(buffer[bufferIndex+int(lengthToken.Offset()):]) + if err != nil { + panic(fmt.Errorf("invalid length encoding %s", err)) + } + bufferIndex += int(dataToken.Offset()) + } + + if (uint64(bufferIndex) + dataLength) > length { + panic("length too short for data field") + } + listener.OnVarData(token, buffer[bufferIndex:], dataLength, dataToken) + + bufferIndex += int(dataLength) + tokenIndex += int(token.ComponentTokenCount()) + } + return bufferIndex +} + +func DecodeGroups( + buffer []byte, + bufferIndex int, + length uint64, + actingVersion uint64, + tokens []Token, + tokenIndex int, + numTokens int, + listener TokenListener) (int, int) { + for tokenIndex < numTokens { + token := tokens[tokenIndex] + if SignalBeginGroup != token.Signal() { + break + } + isPresent := token.TokenVersion() <= int32(actingVersion) + dimensionsTypeComposite := tokens[tokenIndex+1] + dimensionsLength := int(dimensionsTypeComposite.EncodedLength()) + if (uint64(bufferIndex) + uint64(dimensionsLength)) > length { + panic("length too short for dimensions composite") + } + + blockLengthToken := tokens[tokenIndex+2] + numInGroupToken := tokens[tokenIndex+3] + blockLength := uint64(0) + numInGroup := uint64(0) + if isPresent { + blockLengthTokenEncoding := blockLengthToken.Encoding() + var err error + blockLength, err = blockLengthTokenEncoding.GetAsUInt(buffer[bufferIndex+int(blockLengthToken.Offset()):]) + if err != nil { + panic(fmt.Errorf("invalid block length encoding %s", err)) + } + numInGroupTokenEncoding := numInGroupToken.Encoding() + numInGroup, err = numInGroupTokenEncoding.GetAsUInt(buffer[bufferIndex+int(numInGroupToken.Offset()):]) + if err != nil { + panic(fmt.Errorf("invalid num in group encoding %s", err)) + } + bufferIndex += dimensionsLength + } + + beginFieldsIndex := tokenIndex + int(dimensionsTypeComposite.ComponentTokenCount()) + 1 + listener.OnGroupHeader(token, numInGroup) + for i := uint64(0); i < numInGroup; i++ { + listener.OnBeginGroup(token, i, numInGroup) + if (uint64(bufferIndex) + blockLength) > length { + panic("length too short for group blockLength") + } + afterFieldsIndex := DecodeFields( + buffer, + bufferIndex, + length, + actingVersion, + tokens, + beginFieldsIndex, + numTokens, + listener) + bufferIndex += int(blockLength) + groupIndex, groupNumTokens := DecodeGroups( + buffer, + bufferIndex, + length, + actingVersion, + tokens, + afterFieldsIndex, + numTokens, + listener) + bufferIndex = DecodeData( + buffer, + groupIndex, + length, + tokens, + groupNumTokens, + numTokens, + actingVersion, + listener, + ) + listener.OnEndGroup(token, i, numInGroup) + } + tokenIndex += int(token.ComponentTokenCount()) + } + return bufferIndex, tokenIndex +} + +func Decode( + buffer []byte, + actingVersion uint64, + blockLength uint64, + tokens []Token, + listener TokenListener) int { + listener.OnBeginMessage(tokens[0]) + length := uint64(len(buffer)) + if length < blockLength { + panic("length too short for message blockLength") + } + numTokens := len(tokens) + tokenIndex := DecodeFields( + buffer, + 0, + length, + actingVersion, + tokens, + 1, + numTokens, + listener, + ) + bufferIndex := int(blockLength) + groupIndex, groupNumTokens := DecodeGroups( + buffer, + bufferIndex, + length, + actingVersion, + tokens, + tokenIndex, + numTokens, + listener, + ) + bufferIndex = DecodeData( + buffer, + groupIndex, + length, + tokens, + groupNumTokens, + numTokens, + actingVersion, + listener, + ) + listener.OnEndMessage(tokens[numTokens-1]) + return bufferIndex +} diff --git a/sbe-tool/src/main/golang/otf/token.go b/sbe-tool/src/main/golang/otf/token.go new file mode 100644 index 0000000000..442b6d5d80 --- /dev/null +++ b/sbe-tool/src/main/golang/otf/token.go @@ -0,0 +1,162 @@ +package otf + +import ( + "fmt" +) + +type Signal int + +const ( + SignalBeginMessage Signal = 1 + SignalEndMessage Signal = 2 + SignalBeginComposite Signal = 3 + SignalEndComposite Signal = 4 + SignalBeginField Signal = 5 + SignalEndField Signal = 6 + SignalBeginGroup Signal = 7 + SignalEndGroup Signal = 8 + SignalBeginEnum Signal = 9 + SignalValidValue Signal = 10 + SignalEndEnum Signal = 11 + SignalBeginSet Signal = 12 + SignalChoice Signal = 13 + SignalEndSet Signal = 14 + SignalBeginVarData Signal = 15 + SignalEndVarData Signal = 16 + SignalEncoding Signal = 17 +) + +func (s Signal) String() string { + switch s { + case SignalBeginMessage: + return "BeginMessage" + case SignalEndMessage: + return "EndMessage" + case SignalBeginComposite: + return "BeginComposite" + case SignalEndComposite: + return "EndComposite" + case SignalBeginField: + return "BeginField" + case SignalEndField: + return "EndField" + case SignalBeginGroup: + return "BeginGroup" + case SignalEndGroup: + return "EndGroup" + case SignalBeginEnum: + return "BeginEnum" + case SignalValidValue: + return "ValidValue" + case SignalEndEnum: + return "EndEnum" + case SignalBeginSet: + return "BeginSet" + case SignalChoice: + return "Choice" + case SignalEndSet: + return "EndSet" + case SignalBeginVarData: + return "BeginVarData" + case SignalEndVarData: + return "EndVarData" + case SignalEncoding: + return "Encoding" + default: + return "Unknown" + } +} + +type Token struct { + offset int32 + fieldId int32 + version int32 + encodedLength int32 + componentTokenCount int32 + signal Signal + name string + referencedName string + description string + encoding Encoding +} + +func (token Token) ReferencedName() string { + return token.referencedName +} + +func (token Token) Signal() Signal { + return token.signal +} + +func (token Token) Name() string { + return token.name +} + +func (token Token) Description() string { + return token.description +} + +func (token Token) FieldId() int32 { + return token.fieldId +} + +func (token Token) TokenVersion() int32 { + return token.version +} + +// ApplicableTypeName returns the name of the type that should be applied in context. +func (token Token) ApplicableTypeName() string { + if token.referencedName == "" { + return token.name + } + return token.referencedName +} + +func (token Token) Encoding() Encoding { + return token.encoding +} + +// EncodedLength returns the length of the encoded primitive in bytes. +func (token Token) EncodedLength() int32 { + return token.encodedLength +} + +// ArrayLength returns the number of encoded primitives in this type. +func (token Token) ArrayLength() int32 { + if token.encoding.PrimitiveType() == NONE || token.encodedLength == 0 { + return 0 + } + return token.encodedLength / int32(token.encoding.PrimitiveType().Size()) +} + +func (token Token) Offset() int32 { + return token.offset +} + +func (token Token) ComponentTokenCount() int32 { + return token.componentTokenCount +} + +// IsConstantEncoding returns true if the encoding presence is constant or false if not. +func (token Token) IsConstantEncoding() bool { + return token.encoding.presence == SbeConstant +} + +// IsOptionalEncoding returns true if the encoding presence is optional or false if not. +func (token Token) IsOptionalEncoding() bool { + return token.encoding.presence == SbeOptional +} + +func (token Token) String() string { + return fmt.Sprintf( + "Token{signal: %s, name: %s, description: %s, fieldId: %d, tokenVersion: %d, encoding: %s, encodedLength: %d, offset: %d, componentTokenCount: %d}", + token.signal, + token.name, + token.description, + token.fieldId, + token.version, + &token.encoding, + token.encodedLength, + token.offset, + token.componentTokenCount) +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index 3d95be6172..9c0ab8df4b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -242,6 +242,12 @@ public class SbeTool */ public static final String JAVA_PRECEDENCE_CHECKS_PROPERTY_NAME = "sbe.java.precedence.checks.property.name"; + /** + * Boolean system property to generate flyweights instead of structs in generated Go code. + * Defaults to false + */ + public static final String GO_GENERATE_FLYWEIGHTS = "sbe.go.generate.generate.flyweights"; + /** * Main entry point for the SBE Tool. * diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index fbf7a9d0f0..4edea4f8b4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -21,8 +21,10 @@ import uk.co.real_logic.sbe.generation.cpp.CppDtoGenerator; import uk.co.real_logic.sbe.generation.cpp.CppGenerator; import uk.co.real_logic.sbe.generation.cpp.NamespaceOutputManager; -import uk.co.real_logic.sbe.generation.golang.GolangGenerator; -import uk.co.real_logic.sbe.generation.golang.GolangOutputManager; +import uk.co.real_logic.sbe.generation.golang.struct.GolangGenerator; +import uk.co.real_logic.sbe.generation.golang.struct.GolangOutputManager; +import uk.co.real_logic.sbe.generation.golang.flyweight.GolangFlyweightGenerator; +import uk.co.real_logic.sbe.generation.golang.flyweight.GolangFlyweightOutputManager; import uk.co.real_logic.sbe.generation.java.JavaDtoGenerator; import uk.co.real_logic.sbe.generation.java.JavaGenerator; import uk.co.real_logic.sbe.generation.java.JavaOutputManager; @@ -128,7 +130,19 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { - return new GolangGenerator(ir, new GolangOutputManager(outputDir, ir.applicableNamespace())); + if ("true".equals(System.getProperty(GO_GENERATE_FLYWEIGHTS))) + { + return new GolangFlyweightGenerator( + ir, + "true".equals(System.getProperty(DECODE_UNKNOWN_ENUM_VALUES)), + new GolangFlyweightOutputManager(outputDir, ir.applicableNamespace())); + } + else + { + return new GolangGenerator( + ir, + new GolangOutputManager(outputDir, ir.applicableNamespace())); + } } }, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java new file mode 100644 index 0000000000..de9d86f8cc --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java @@ -0,0 +1,3382 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.golang.flyweight; + +import org.agrona.Strings; +import org.agrona.Verify; +import org.agrona.generation.OutputManager; +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.generation.CodeGenerator; +import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.ir.Encoding; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.ir.Signal; +import uk.co.real_logic.sbe.ir.Token; + +import java.io.IOException; +import java.io.Writer; +import java.nio.ByteOrder; +import java.util.*; + +import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; +import static uk.co.real_logic.sbe.generation.golang.flyweight.GolangFlyweightUtil.*; +import static uk.co.real_logic.sbe.ir.GenerationUtil.*; + +/** + * Codec generator for the Go programming language using flyweights. + */ +@SuppressWarnings("MethodLength") +public class GolangFlyweightGenerator implements CodeGenerator +{ + private static final String BASE_INDENT = ""; + private static final String INDENT = " "; + + private final Ir ir; + private final OutputManager outputManager; + private final boolean shouldDecodeUnknownEnumValues; + + private final Set includes = new TreeSet<>(); + + /** + * Create a new Golang language {@link CodeGenerator}. + * + * @param ir for the messages and types. + * @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding. + * @param outputManager for generating the codecs to. + */ + public GolangFlyweightGenerator( + final Ir ir, + final boolean shouldDecodeUnknownEnumValues, + final OutputManager outputManager) + { + Verify.notNull(ir, "ir"); + Verify.notNull(outputManager, "outputManager"); + + this.ir = ir; + this.shouldDecodeUnknownEnumValues = shouldDecodeUnknownEnumValues; + this.outputManager = outputManager; + } + + private static void generateGroupClassHeader( + final StringBuilder sb, + final String groupClassName, + final List tokens, + final int index, + final String indent, + final List fields, + final List groups) + { + final String dimensionsClassName = formatClassName(tokens.get(index + 1).name()); + final int dimensionHeaderLength = tokens.get(index + 1).encodedLength(); + final int blockLength = tokens.get(index).encodedLength(); + final Token blockLengthToken = Generators.findFirst("blockLength", tokens, index); + final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); + final String golangTypeBlockLength = goTypeName(blockLengthToken.encoding().primitiveType()); + final String golangTypeNumInGroup = goTypeName(numInGroupToken.encoding().primitiveType()); + + new Formatter(sb).format("\n" + + indent + "type %1$s struct {\n" + + indent + " buffer []byte\n" + + indent + " bufferLength uint64\n" + + indent + " initialPosition uint64\n" + + indent + " positionPtr *uint64\n" + + indent + " blockLength uint64\n" + + indent + " count uint64\n" + + indent + " index uint64\n" + + indent + " offset uint64\n" + + indent + " actingVersion uint64\n", + groupClassName); + + for (int i = 0, size = fields.size(); i < size; i++) + { + final Token signalToken = fields.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = fields.get(i + 1); + final String propertyName = formatPropertyName(signalToken.name()); + final String typeName = formatClassName(encodingToken.applicableTypeName()); + + switch (encodingToken.signal()) + { + case BEGIN_SET: + case BEGIN_COMPOSITE: + new Formatter(sb).format(indent + " _%1$s %2$s\n", + propertyName, + typeName); + break; + + default: + break; + } + } + } + + for (int i = 0, size = groups.size(); i < size; ) + { + final Token token = groups.get(i); + if (token.signal() == Signal.BEGIN_GROUP) + { + final String propertyName = formatPropertyName(token.name()); + final String groupName = groupClassName + formatClassName(token.name()); + + new Formatter(sb).format(indent + " _%1$s %2$s\n", + propertyName, + groupName); + i += token.componentTokenCount(); + } + } + + new Formatter(sb).format( + indent + "}\n\n" + + indent + "func (g *%1$s) sbePositionPtr() *uint64 {\n" + + indent + " return g.positionPtr\n" + + indent + "}\n\n", + groupClassName); + + new Formatter(sb).format( + indent + "func (g *%3$s) WrapForDecode(\n" + + indent + " buffer []byte,\n" + + indent + " pos *uint64,\n" + + indent + " actingVersion uint64,\n" + + indent + " bufferLength uint64) {\n" + + indent + " dimensions := %2$s{}\n" + + indent + " dimensions.Wrap(buffer, *pos, actingVersion, bufferLength)\n" + + indent + " g.buffer = buffer\n" + + indent + " g.bufferLength = bufferLength\n" + + indent + " g.blockLength = uint64(dimensions.BlockLength())\n" + + indent + " g.count = uint64(dimensions.NumInGroup())\n" + + indent + " g.index = 0\n" + + indent + " g.actingVersion = actingVersion\n" + + indent + " g.initialPosition = *pos\n" + + indent + " g.positionPtr = pos\n" + + indent + " *g.positionPtr = *g.positionPtr + %1$d\n" + + indent + "}\n", + dimensionHeaderLength, dimensionsClassName, groupClassName); + + final long minCount = numInGroupToken.encoding().applicableMinValue().longValue(); + final String minCheck = minCount > 0 ? "count < " + minCount + " || " : ""; + + new Formatter(sb).format("\n" + + indent + "func (g *%8$s) WrapForEncode(\n" + + indent + " buffer []byte,\n" + + indent + " count %3$s,\n" + + indent + " pos *uint64,\n" + + indent + " actingVersion uint64,\n" + + indent + " bufferLength uint64) {\n" + + indent + " if %5$scount > %6$d {\n" + + indent + " panic(\"count outside of allowed range [E110]\")\n" + + indent + " }\n" + + indent + " g.buffer = buffer\n" + + indent + " g.bufferLength = bufferLength\n" + + indent + " dimensions := %7$s{}\n" + + indent + " dimensions.Wrap(buffer, *pos, actingVersion, bufferLength)\n" + + indent + " dimensions.SetBlockLength(%2$d)\n" + + indent + " dimensions.SetNumInGroup(count)\n" + + indent + " g.index = 0\n" + + indent + " g.count = uint64(count)\n" + + indent + " g.blockLength = %2$d\n" + + indent + " g.actingVersion = actingVersion\n" + + indent + " g.initialPosition = *pos\n" + + indent + " g.positionPtr = pos\n" + + indent + " *g.positionPtr = *g.positionPtr + %4$d\n" + + indent + "}\n", + golangTypeBlockLength, + blockLength, + golangTypeNumInGroup, + dimensionHeaderLength, + minCheck, + numInGroupToken.encoding().applicableMaxValue().longValue(), + dimensionsClassName, + groupClassName); + + new Formatter(sb).format("\n" + + indent + "func (g *%3$s) SbeHeaderSize() uint64 {\n" + + indent + " return %1$d\n" + + indent + "}\n\n" + + + indent + "func (g *%3$s) SbeBlockLength() uint64 {\n" + + indent + " return %2$d\n" + + indent + "}\n\n" + + + indent + "func (g *%3$s) SbePosition() uint64 {\n" + + indent + " return *g.positionPtr\n" + + indent + "}\n\n" + + + indent + "func (g *%3$s) SbeCheckPosition(position uint64) uint64 {\n" + + indent + " if position > g.bufferLength {\n" + + indent + " panic(\"buffer too short [E100]\")\n" + + indent + " }\n" + + indent + " return position\n" + + indent + "}\n\n" + + + indent + "func (g *%3$s) SetSbePosition(position uint64) {\n" + + indent + " *g.positionPtr = g.SbeCheckPosition(position)\n" + + indent + "}\n\n" + + + indent + "func (g *%3$s) Count() uint64 {\n" + + indent + " return g.count\n" + + indent + "}\n\n" + + + indent + "func (g *%3$s) HasNext() bool {\n" + + indent + " return g.index < g.count\n" + + indent + "}\n\n" + + + indent + "func (g *%3$s) Next() *%3$s {\n" + + indent + " if g.index >= g.count {\n" + + indent + " panic(\"index >= count [E108]\")\n" + + indent + " }\n" + + indent + " g.offset = *g.positionPtr\n" + + indent + " if g.offset+g.blockLength > g.bufferLength {\n" + + indent + " panic(\"buffer too short for next group index [E108]\")\n" + + indent + " }\n" + + indent + " *g.positionPtr = g.offset + g.blockLength\n" + + indent + " g.index++\n\n" + + + indent + " return g\n" + + indent + "}\n", + dimensionHeaderLength, + blockLength, + groupClassName); + sb.append("\n") + .append(indent).append("func (g *").append(groupClassName) + .append(") ResetCountToIndex() uint64 {\n") + .append(indent).append(" g.count = g.index\n") + .append(indent).append(" dimensions := ").append(dimensionsClassName).append("{}\n") + .append(indent).append(" dimensions.Wrap") + .append("(g.buffer, g.initialPosition, g.actingVersion, g.bufferLength)\n") + .append(indent) + .append(" dimensions.SetNumInGroup(").append(golangTypeNumInGroup).append("(g.count))\n") + .append(indent).append(" return g.count\n") + .append(indent).append("}\n\n"); + + sb.append("\n") + .append(indent).append("func (g *").append(groupClassName) + .append(") ForEach(fn func(group *").append(groupClassName).append(")) {\n") + .append(indent).append(" for g.HasNext() {\n") + .append(indent).append(" g.Next()\n") + .append(indent).append(" fn(g)\n") + .append(indent).append(" }\n") + .append(indent).append("}\n\n"); + } + + private static void generateGroupProperty( + final StringBuilder sb, + final String groupName, + final String groupClassName, + final String outerClassName, + final Token token, + final String goTypeForNumInGroup, + final String indent) + { + final String propertyName = formatPropertyName(groupName); + + new Formatter(sb).format( + indent + " func (m *%3$s) %1$sId() int {\n" + + indent + " return %2$d\n" + + indent + " }\n", + propertyName, + token.id(), + outerClassName); + + + new Formatter(sb).format("\n" + + indent + "func (m *%1$s) %2$s() *%3$s {\n" + + indent + " m._%2$s.WrapForDecode(m.buffer, m.sbePositionPtr(), m.actingVersion, m.bufferLength)\n" + + indent + " return &m._%2$s\n" + + indent + "}\n", + outerClassName, + propertyName, + groupClassName); + + new Formatter(sb).format("\n" + + indent + "func (m *%1$s) %2$sCount(count %3$s) *%4$s {\n" + + indent + + " m._%2$s.WrapForEncode(m.buffer, count, m.sbePositionPtr(), m.actingVersion, m.bufferLength)\n" + + indent + " return &m._%2$s\n" + + indent + "}\n", + outerClassName, + propertyName, + goTypeForNumInGroup, + groupClassName); + + final int version = token.version(); + final String versionCheck = 0 == version ? + " return true\n" : " return m.actingVersion >= m.%1$sSinceVersion()\n"; + new Formatter(sb).format("\n" + + indent + "func (m *%3$s) %1$sSinceVersion() uint64 {\n" + + indent + " return %2$d\n" + + indent + "}\n\n" + + + indent + "func (m *%3$s) %1$sInActingVersion() bool {\n" + + indent + versionCheck + + indent + "}\n", + propertyName, + version, + outerClassName); + } + + private static CharSequence generateChoiceNotPresentCondition(final int sinceVersion) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + " if m.actingVersion < %1$d {\n" + + " return false\n" + + " }\n\n", + sinceVersion); + } + + private static CharSequence generateArrayFieldNotPresentCondition( + final int sinceVersion, final String indent) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + " if m.actingVersion < %1$d {\n" + + indent + " return nil\n" + + indent + " }\n\n", + sinceVersion); + } + + private static CharSequence generateArrayLengthNotPresentCondition( + final int sinceVersion, final String indent) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + " if m.actingVersion < %1$d {\n" + + indent + " return 0\n" + + indent + " }\n\n", + sinceVersion); + } + + private static CharSequence generateArrayFieldNotPresentConditionWithErr( + final int sinceVersion, final String indent) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + " if m.actingVersion < %1$d {\n" + + indent + " return 0, nil\n" + + indent + " }\n\n", + sinceVersion); + } + + private static CharSequence generateStringNotPresentCondition( + final int sinceVersion, final String indent) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + " if m.actingVersion < %1$d {\n" + + indent + " return \"\"\n" + + indent + " }\n\n", + sinceVersion); + } + + private static CharSequence generateTypeFieldNotPresentCondition( + final int sinceVersion, final String indent) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + " if m.actingVersion < %1$d {\n" + + indent + " return \"\"\n" + + indent + " }\n\n", + sinceVersion); + } + + private static CharSequence generateClassDeclaration(final String className) + { + return + "type " + className + " struct {\n"; + } + + private static CharSequence generateEnumDeclaration(final String name, final Token encodingToken) + { + final Encoding encoding = encodingToken.encoding(); + return "type " + name + " " + goTypeName(encoding.primitiveType()) + "\n"; + } + + private static CharSequence generateConstructorsAndOperators(final String className) + { + return String.format( + " func %1$s() {\n\n" + + + " func %1$s(\n" + + " buffer []byte,\n" + + " offset uint64,\n" + + " bufferLength uint64,\n" + + " actingBlockLength uint64,\n" + + " actingVersion uint64) {\n" + + " m.buffer := buffer\n" + + " m.bufferLength := bufferLength\n" + + " m.offset := offset\n" + + " m.position := sbeCheckPosition(offset + actingBlockLength)\n" + + " m.actingBlockLength := actingBlockLength\n" + + " m.actingVersion := actingVersion\n" + + " }\n\n", + className); + } + + private static void generateFieldMetaAttributeMethod( + final StringBuilder sb, final Token token, final String indent, final String className) + { + final Encoding encoding = token.encoding(); + final String propertyName = toUpperFirstChar(token.name()); + final String epoch = encoding.epoch() == null ? "" : encoding.epoch(); + final String timeUnit = encoding.timeUnit() == null ? "" : encoding.timeUnit(); + final String semanticType = encoding.semanticType() == null ? "" : encoding.semanticType(); + + sb.append("\n") + .append(indent).append("func (m *").append(className) + .append(") ").append(propertyName).append("MetaAttribute(metaAttribute string) string {\n") + .append(indent).append(" switch metaAttribute {\n"); + + if (!Strings.isEmpty(epoch)) + { + sb.append(indent) + .append(" case \"EPOCH\": return \"").append(epoch).append("\"\n"); + } + + if (!Strings.isEmpty(timeUnit)) + { + sb.append(indent) + .append(" case \"TIME_UNIT\": return \"").append(timeUnit).append("\"\n"); + } + + if (!Strings.isEmpty(semanticType)) + { + sb.append(indent) + .append(" case \"SEMANTIC_TYPE\": return \"").append(semanticType) + .append("\"\n"); + } + + sb + .append(indent).append(" case \"PRESENCE\": return \"") + .append(encoding.presence().toString().toLowerCase()).append("\"\n") + .append(indent).append(" default: return \"\"\n") + .append(indent).append(" }\n") + .append(indent).append("}\n"); + } + + private static CharSequence generateEnumFieldNotPresentCondition( + final int sinceVersion, final String enumName, final String indent) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + " if m.actingVersion < %1$d {\n" + + indent + " return %2$s_NULL_VALUE\n" + + indent + " }\n\n", + sinceVersion, + enumName); + } + + private static void generateBitsetProperty( + final StringBuilder sb, + final String propertyName, + final Token token, + final String indent, + final String className) + { + final String bitsetName = formatClassName(token.applicableTypeName()); + final int offset = token.offset(); + + new Formatter(sb).format( + indent + " func (m *%4$s) %2$s() *%1$s {\n" + + indent + " m._%2$s.Wrap(m.buffer, m.offset + %3$d, m.actingVersion, m.bufferLength)\n" + + indent + " return &m._%2$s\n" + + indent + " }\n", + bitsetName, + propertyName, + offset, + className); + + new Formatter(sb).format("\n" + + indent + " func (m *%3$s) %1$sEncodingLength() int {\n" + + indent + " return %2$d\n" + + indent + " }\n", + propertyName, + token.encoding().primitiveType().size(), + className); + } + + private static void generateCompositeProperty( + final StringBuilder sb, + final String propertyName, + final Token token, + final String indent, + final String className) + { + final String compositeName = formatClassName(token.applicableTypeName()); + + new Formatter(sb).format( + indent + " func (m *%4$s) %2$s() *%1$s {\n" + + indent + " m._%2$s.Wrap(m.buffer, m.offset + %3$d, m.actingVersion, m.bufferLength)\n" + + indent + " return &m._%2$s\n" + + indent + " }\n", + compositeName, + propertyName, + token.offset(), + className); + } + + /** + * Generate the composites for dealing with the message header. + * + * @throws IOException if an error is encountered when writing the output. + */ + public void generateMessageHeaderStub() throws IOException + { + generateComposite(ir.headerStructure().tokens()); + } + + private void generateTypeStubs() throws IOException + { + for (final List tokens : ir.types()) + { + switch (tokens.get(0).signal()) + { + case BEGIN_ENUM: + generateEnum(tokens); + break; + + case BEGIN_SET: + generateChoiceSet(tokens); + break; + + case BEGIN_COMPOSITE: + generateComposite(tokens); + break; + + default: + break; + } + } + } + + /** + * {@inheritDoc} + */ + public void generate() throws IOException + { + + generateUtils(ir.namespaces()); + + generateMessageHeaderStub(); + generateTypeStubs(); + + for (final List tokens : ir.messages()) + { + includes.clear(); + + final Token msgToken = tokens.get(0); + final String className = formatClassName(msgToken.name()); + + try (Writer fileOut = outputManager.createOutput(className)) + { + final StringBuilder out = new StringBuilder(); + out.append(generateClassDeclaration(className)); + + final List messageBody = tokens.subList(1, tokens.size() - 1); + int i = 0; + + final List fields = new ArrayList<>(); + i = collectFields(messageBody, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(messageBody, i, groups); + + final List varData = new ArrayList<>(); + collectVarData(messageBody, i, varData); + + out.append(generateMessageFlyweightCode(className, msgToken, fields, groups)); + + final StringBuilder sb = new StringBuilder(); + generateFields(sb, className, fields, BASE_INDENT); + generateGroups(sb, groups, BASE_INDENT, className); + generateVarData(sb, className, varData, BASE_INDENT); + generateDisplay(sb, msgToken.name(), className, fields, groups, varData); + sb.append(generateMessageLength(groups, varData, BASE_INDENT, className)); + out.append(sb); + + fileOut.append(generateFileHeader(ir.namespaces())); + fileOut.append(out); + } + } + } + + private void generateUtils(final String[] namespaces) throws IOException + { + + try (Writer out = outputManager.createOutput("Utils")) + { + out.append("/* Generated SBE (Simple Binary Encoding) message codec */\n"); + + out.append(String.format("// Code generated by SBE. DO NOT EDIT.\n\n" + + + "package %1$s\n\n" + + + "import (\n" + + "\t\"math\"\n" + + "\t\"math/bits\"\n" + + ")\n\n" + + + "// SbeBigEndianEncode16 encodes a 16-bit value into big endian byte order\n" + + "func SbeBigEndianEncode16(v uint16) uint16 {\n" + + "\treturn bits.ReverseBytes16(v)\n" + + "}\n\n" + + + "// SbeBigEndianEncode32 encodes a 32-bit value into big endian byte order\n" + + "func SbeBigEndianEncode32(v uint32) uint32 {\n" + + "\treturn bits.ReverseBytes32(v)\n" + + "}\n\n" + + + "// SbeBigEndianEncode64 encodes a 64-bit value into big endian byte order\n" + + "func SbeBigEndianEncode64(v uint64) uint64 {\n" + + "\treturn bits.ReverseBytes64(v)\n" + + "}\n\n" + + + "// SbeLittleEndianEncode16 encodes a 16-bit value into little endian byte order\n" + + "func SbeLittleEndianEncode16(v uint16) uint16 {\n" + + "\treturn v\n" + + "}\n\n" + + + "// SbeLittleEndianEncode32 encodes a 32-bit value into little endian byte order\n" + + "func SbeLittleEndianEncode32(v uint32) uint32 {\n" + + "\treturn v\n" + + "}\n\n" + + + "// SbeLittleEndianEncode64 encodes a 64-bit value into little endian byte order\n" + + "func SbeLittleEndianEncode64(v uint64) uint64 {\n" + + "\treturn v\n" + + "}\n\n" + + + "// SbeNullValueFloat returns the null value for a float\n" + + "func SbeNullValueFloat() float32 {\n" + + "\treturn float32(math.NaN())\n" + + "}\n\n" + + + "// SbeNullValueDouble returns the null value for a double\n" + + "func SbeNullValueDouble() float64 {\n" + + "\treturn math.NaN()\n" + + "}\n\n" + + + "// SbeNullValueByte returns the null value for a byte\n" + + "func SbeNullValueByte() byte {\n" + + "\treturn byte(math.MaxUint8)\n" + + "}\n\n" + + + "// SbeNullValueInt8 returns the null value for an 8-bit integer\n" + + "func SbeNullValueInt8() int8 {\n" + + "\treturn math.MinInt8\n" + + "}\n\n" + + + "// SbeNullValueInt16 returns the null value for a 16-bit integer\n" + + "func SbeNullValueInt16() int16 {\n" + + "\treturn math.MinInt16\n" + + "}\n\n" + + + "// SbeNullValueInt32 returns the null value for a 32-bit integer\n" + + "func SbeNullValueInt32() int32 {\n" + + "\treturn math.MinInt32\n" + + "}\n\n" + + + "// SbeNullValueInt64 returns the null value for a 64-bit integer\n" + + "func SbeNullValueInt64() int64 {\n" + + "\treturn math.MinInt64\n" + + "}\n\n" + + + "// SbeNullValueUint8 returns the null value for an 8-bit unsigned integer\n" + + "func SbeNullValueUint8() uint8 {\n" + + "\treturn math.MaxUint8\n" + + "}\n\n" + + + "// SbeNullValueUint16 returns the null value for a 16-bit unsigned integer\n" + + "func SbeNullValueUint16() uint16 {\n" + + "\treturn math.MaxUint16\n" + + "}\n\n" + + + "// SbeNullValueUint32 returns the null value for a 32-bit unsigned integer\n" + + "func SbeNullValueUint32() uint32 {\n" + + "\treturn math.MaxUint32\n" + + "}\n\n" + + + "// SbeNullValueUint64 returns the null value for a 64-bit unsigned integer\n" + + "func SbeNullValueUint64() uint64 {\n" + + "\treturn math.MaxUint64\n" + + "}\n\n" + + + "type MetaAttribute int\n" + + "const (\n" + + " EPOCH MetaAttribute = iota\n" + + " TIME_UNIT\n" + + " SEMANTIC_TYPE\n" + + " PRESENCE\n" + + ")\n\n" + + + "var SbeNoBoundsCheck = false\n\n" + + "// LittleEndian\n" + + "\n" + + "func ByteLittleEndian(b []byte) byte {\n" + + "\treturn b[0]\n" + + "}\n" + + "\n" + + "func PutByteLittleEndian(b []byte, v byte) {\n" + + "\tb[0] = v\n" + + "}\n" + + "\n" + + "func Uint8LittleEndian(b []byte) uint8 {\n" + + "\treturn b[0]\n" + + "}\n" + + "\n" + + "func PutUint8LittleEndian(b []byte, v uint8) {\n" + + "\tb[0] = v\n" + + "}\n" + + "\n" + + "func Int8LittleEndian(b []byte) int8 {\n" + + "\treturn int8(Uint8LittleEndian(b))\n" + + "}\n" + + "\n" + + "func PutInt8LittleEndian(b []byte, v int8) {\n" + + "\tPutUint8LittleEndian(b, uint8(v))\n" + + "}\n" + + "\n" + + "func Uint16LittleEndian(b []byte) uint16 {\n" + + "\t_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808\n" + + "\treturn uint16(b[0]) | uint16(b[1])<<8\n" + + "}\n" + + "\n" + + "func PutUint16LittleEndian(b []byte, v uint16) {\n" + + "\t_ = b[1] // early bounds check to guarantee safety of writes below\n" + + "\tb[0] = byte(v)\n" + + "\tb[1] = byte(v >> 8)\n" + + "}\n" + + "\n" + + "func Int16LittleEndian(b []byte) int16 {\n" + + "\treturn int16(Uint16LittleEndian(b))\n" + + "}\n" + + "\n" + + "func PutInt16LittleEndian(b []byte, v int16) {\n" + + "\tPutUint16LittleEndian(b, uint16(v))\n" + + "}\n" + + "\n" + + "func Uint32LittleEndian(b []byte) uint32 {\n" + + "\t_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808\n" + + "\treturn uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24\n" + + "}\n" + + "\n" + + "func PutUint32LittleEndian(b []byte, v uint32) {\n" + + "\t_ = b[3] // early bounds check to guarantee safety of writes below\n" + + "\tb[0] = byte(v)\n" + + "\tb[1] = byte(v >> 8)\n" + + "\tb[2] = byte(v >> 16)\n" + + "\tb[3] = byte(v >> 24)\n" + + "}\n" + + "\n" + + "func Int32LittleEndian(b []byte) int32 {\n" + + "\treturn int32(Uint32LittleEndian(b))\n" + + "}\n" + + "\n" + + "func PutInt32LittleEndian(b []byte, v int32) {\n" + + "\tPutUint32LittleEndian(b, uint32(v))\n" + + "}\n" + + "\n" + + "func Uint64LittleEndian(b []byte) uint64 {\n" + + "\t_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808\n" + + "\treturn uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |\n" + + "\t\tuint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56\n" + + "}\n" + + "\n" + + "func PutUint64LittleEndian(b []byte, v uint64) {\n" + + "\t_ = b[7] // early bounds check to guarantee safety of writes below\n" + + "\tb[0] = byte(v)\n" + + "\tb[1] = byte(v >> 8)\n" + + "\tb[2] = byte(v >> 16)\n" + + "\tb[3] = byte(v >> 24)\n" + + "\tb[4] = byte(v >> 32)\n" + + "\tb[5] = byte(v >> 40)\n" + + "\tb[6] = byte(v >> 48)\n" + + "\tb[7] = byte(v >> 56)\n" + + "}\n" + + "\n" + + "func Int64LittleEndian(b []byte) int64 {\n" + + "\treturn int64(Uint64LittleEndian(b))\n" + + "}\n" + + "\n" + + "func PutInt64LittleEndian(b []byte, v int64) {\n" + + "\tPutUint64LittleEndian(b, uint64(v))\n" + + "}\n" + + "\n" + + "func FloatLittleEndian(b []byte) float32 {\n" + + "\treturn math.Float32frombits(Uint32LittleEndian(b))\n" + + "}\n" + + "\n" + + "func PutFloatLittleEndian(b []byte, v float32) {\n" + + "\tPutUint32LittleEndian(b, math.Float32bits(v))\n" + + "}\n" + + "\n" + + "func DoubleLittleEndian(b []byte) float64 {\n" + + "\treturn math.Float64frombits(Uint64LittleEndian(b))\n" + + "}\n" + + "\n" + + "func PutDoubleLittleEndian(b []byte, v float64) {\n" + + "\tPutUint64LittleEndian(b, math.Float64bits(v))\n" + + "}\n" + + "\n" + + "// BigEndian\n" + + "\n" + + "func ByteBigEndian(b []byte) byte {\n" + + "\treturn b[0]\n" + + "}\n" + + "\n" + + "func PutByteBigEndian(b []byte, v byte) {\n" + + "\tb[0] = v\n" + + "}\n" + + "\n" + + "func Uint8BigEndian(b []byte) uint8 {\n" + + "\treturn b[0]\n" + + "}\n" + + "\n" + + "func PutUint8BigEndian(b []byte, v uint8) {\n" + + "\tb[0] = byte(v)\n" + + "}\n" + + "\n" + + "func Int8BigEndian(b []byte) int8 {\n" + + "\treturn int8(Uint8BigEndian(b))\n" + + "}\n" + + "\n" + + "func PutInt8BigEndian(b []byte, v int8) {\n" + + "\tPutUint8BigEndian(b, uint8(v))\n" + + "}\n" + + "\n" + + "func Uint16BigEndian(b []byte) uint16 {\n" + + "\t_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808\n" + + "\treturn uint16(b[1]) | uint16(b[0])<<8\n" + + "}\n" + + "\n" + + "func PutUint16BigEndian(b []byte, v uint16) {\n" + + "\t_ = b[1] // early bounds check to guarantee safety of writes below\n" + + "\tb[0] = byte(v >> 8)\n" + + "\tb[1] = byte(v)\n" + + "}\n" + + "\n" + + "func Int16BigEndian(b []byte) int16 {\n" + + "\treturn int16(Uint16BigEndian(b))\n" + + "}\n" + + "\n" + + "func PutInt16BigEndian(b []byte, v int16) {\n" + + "\tPutUint16BigEndian(b, uint16(v))\n" + + "}\n" + + "\n" + + "func Uint32BigEndian(b []byte) uint32 {\n" + + "\t_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808\n" + + "\treturn uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24\n" + + "}\n" + + "\n" + + "func PutUint32BigEndian(b []byte, v uint32) {\n" + + "\t_ = b[3] // early bounds check to guarantee safety of writes below\n" + + "\tb[0] = byte(v >> 24)\n" + + "\tb[1] = byte(v >> 16)\n" + + "\tb[2] = byte(v >> 8)\n" + + "\tb[3] = byte(v)\n" + + "}\n" + + "\n" + + "func Int32BigEndian(b []byte) int32 {\n" + + "\treturn int32(Uint32BigEndian(b))\n" + + "}\n" + + "\n" + + "func PutInt32BigEndian(b []byte, v int32) {\n" + + "\tPutUint32BigEndian(b, uint32(v))\n" + + "}\n" + + "\n" + + "func Uint64BigEndian(b []byte) uint64 {\n" + + "\t_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808\n" + + "\treturn uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |\n" + + "\t\tuint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56\n" + + "}\n" + + "\n" + + "func PutUint64BigEndian(b []byte, v uint64) {\n" + + "\t_ = b[7] // early bounds check to guarantee safety of writes below\n" + + "\tb[0] = byte(v >> 56)\n" + + "\tb[1] = byte(v >> 48)\n" + + "\tb[2] = byte(v >> 40)\n" + + "\tb[3] = byte(v >> 32)\n" + + "\tb[4] = byte(v >> 24)\n" + + "\tb[5] = byte(v >> 16)\n" + + "\tb[6] = byte(v >> 8)\n" + + "\tb[7] = byte(v)\n" + + "}\n" + + "\n" + + "func Int64BigEndian(b []byte) int64 {\n" + + "\treturn int64(Uint64BigEndian(b))\n" + + "}\n" + + "\n" + + "func PutInt64BigEndian(b []byte, v int64) {\n" + + "\tPutUint64BigEndian(b, uint64(v))\n" + + "}\n" + + "\n" + + "func FloatBigEndian(b []byte) float32 {\n" + + "\treturn math.Float32frombits(Uint32BigEndian(b))\n" + + "}\n" + + "\n" + + "func PutFloatBigEndian(b []byte, v float32) {\n" + + "\tPutUint32BigEndian(b, math.Float32bits(v))\n" + + "}\n" + + "\n" + + "func DoubleBigEndian(b []byte) float64 {\n" + + "\treturn math.Float64frombits(Uint64BigEndian(b))\n" + + "}\n" + + "\n" + + "func PutDoubleBigEndian(b []byte, v float64) {\n" + + "\tPutUint64BigEndian(b, math.Float64bits(v))\n" + + "}\n", + + namespacesToPackageName(namespaces))); + } + } + + private String formatIncludes(final Set includes) + { + final StringBuilder sb = new StringBuilder(); + + boolean first = true; + for (final String s : includes) + { + if (!first) + { + sb.append("\n"); + } + sb.append('"').append(s).append('"'); + first = false; + } + return sb.toString(); + } + + private void generateGroups( + final StringBuilder sb, + final List tokens, + final String indent, + final String outerClassName) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + final String groupName = groupToken.name(); + final String groupClassName = formatClassName(outerClassName + formatClassName(groupToken.name())); + final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, i); + final String goTypeForNumInGroup = goTypeName(numInGroupToken.encoding().primitiveType()); + + final int groupStart = i; + + ++i; + final int groupHeaderTokenCount = tokens.get(i).componentTokenCount(); + i += groupHeaderTokenCount; + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + generateGroupClassHeader(sb, groupClassName, tokens, groupStart, + indent + INDENT, fields, groups); + + generateFields(sb, groupClassName, fields, indent + INDENT); + generateGroups(sb, groups, indent + INDENT, groupClassName); + + final List varData = new ArrayList<>(); + i = collectVarData(tokens, i, varData); + generateVarData(sb, groupClassName, varData, indent + INDENT); + + sb.append(generateGroupDisplay(groupClassName, fields, groups, varData, indent + INDENT + INDENT)); + sb.append(generateMessageLength(groups, varData, indent + INDENT + INDENT, groupClassName)); + + generateGroupProperty(sb, groupName, groupClassName, outerClassName, groupToken, goTypeForNumInGroup, + indent); + } + } + + private void generateVarData( + final StringBuilder sb, + final String className, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; ) + { + final Token token = tokens.get(i); + if (token.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + token); + } + + final String propertyName = toUpperFirstChar(token.name()); + final Token lengthToken = Generators.findFirst("length", tokens, i); + final Token varDataToken = Generators.findFirst("varData", tokens, i); + final String characterEncoding = varDataToken.encoding().characterEncoding(); + final int lengthOfLengthField = lengthToken.encodedLength(); + final String lengthGoType = goTypeName(lengthToken.encoding().primitiveType()); + final String lengthByteOrderReadStr = formatReadBytes( + lengthToken.encoding().byteOrder(), lengthToken.encoding().primitiveType()); + + generateFieldMetaAttributeMethod(sb, token, indent, className); + + generateVarDataDescriptors( + sb, token, propertyName, characterEncoding, lengthToken, + lengthOfLengthField, lengthGoType, indent, className); + + new Formatter(sb).format("\n" + + indent + " func (m *%5$s) Skip%1$s() uint64 {\n" + + "%2$s" + + indent + " lengthOfLengthField := uint64(%3$d)\n" + + indent + " lengthPosition := m.SbePosition()\n" + + indent + + " dataLength := uint64(%4$s(m.buffer[lengthPosition : lengthPosition+lengthOfLengthField]))\n" + + indent + " m.SetSbePosition(lengthPosition + lengthOfLengthField + dataLength)\n" + + indent + " return dataLength\n" + + indent + " }\n", + propertyName, + generateArrayLengthNotPresentCondition(token.version(), indent), + lengthOfLengthField, + lengthByteOrderReadStr, + className); + + + new Formatter(sb).format("\n" + + indent + "func (m *%6$s) %1$s() string {\n" + + "%2$s" + + indent + " lengthFieldValue := uint64(%4$s(m.buffer[m.SbePosition():m.SbePosition()+%3$d]))\n" + + indent + " m.SetSbePosition(m.SbePosition() + uint64(%3$d))\n" + + indent + " pos := m.SbePosition()\n" + + indent + " m.SetSbePosition(pos + lengthFieldValue)\n" + + indent + " return string(m.buffer[pos:pos+lengthFieldValue])\n" + + indent + "}\n", + formatPropertyName(propertyName), + generateTypeFieldNotPresentCondition(token.version(), indent), + lengthOfLengthField, + lengthByteOrderReadStr, + lengthGoType, + className); + + new Formatter(sb).format("\n" + + indent + "func (m *%5$s) Get%1$s(dst []byte) int {\n" + + "%2$s" + + indent + " lengthOfLengthField := uint64(%3$d)\n" + + indent + " lengthPosition := m.SbePosition()\n" + + indent + " m.SetSbePosition(m.SbePosition() + lengthOfLengthField)\n" + + indent + + " dataLength := uint64(%4$s(m.buffer[lengthPosition:lengthPosition+lengthOfLengthField]))\n" + + indent + " bytesToCopy := dataLength\n" + + indent + " if uint64(len(dst)) < dataLength {\n" + + indent + " bytesToCopy = uint64(len(dst))\n" + + indent + " }\n" + + indent + " pos := m.SbePosition()\n" + + indent + " m.SetSbePosition(pos + dataLength)\n" + + indent + " copy(dst, m.buffer[pos:pos+bytesToCopy])\n" + + indent + " return int(bytesToCopy)\n" + + indent + "}\n", + propertyName, + generateArrayLengthNotPresentCondition(token.version(), indent), + lengthOfLengthField, + lengthByteOrderReadStr, + className); + + final String lengthByteOrderWriteStr = formatWriteBytes( + lengthToken.encoding().byteOrder(), lengthToken.encoding().primitiveType()); + new Formatter(sb).format("\n" + + indent + "func (m *%5$s) Put%1$sLen(src string, length %3$s) *%5$s {\n" + + indent + " lengthOfLengthField := uint64(%2$d)\n" + + indent + " lengthPosition := m.SbePosition()\n" + + indent + " m.SetSbePosition(lengthPosition + lengthOfLengthField)\n" + + indent + " %4$s(m.buffer[lengthPosition:], length)\n" + + indent + " if length != %3$s(0) {\n" + + indent + " pos := m.SbePosition()\n" + + indent + " m.SetSbePosition(pos + uint64(length))\n" + + indent + " copy(m.buffer[pos:], src)\n" + + indent + " }\n" + + indent + " return m\n" + + indent + "}\n", + propertyName, + lengthOfLengthField, + lengthGoType, + lengthByteOrderWriteStr, + className, + lengthByteOrderReadStr); + + new Formatter(sb).format("\n" + + indent + "func (m *%6$s) Get%1$sAsString() string {\n" + + "%2$s" + + indent + " lengthOfLengthField := uint64(%3$d)\n" + + indent + " lengthPosition := m.SbePosition()\n" + + indent + + " dataLength := uint64(%4$s(m.buffer[lengthPosition:lengthPosition+lengthOfLengthField]))\n" + + indent + " m.SetSbePosition(lengthPosition + lengthOfLengthField)\n" + + indent + " pos := m.SbePosition()\n" + + indent + " m.SetSbePosition(pos + dataLength)\n" + + indent + " return string(m.buffer[pos:pos+dataLength])\n" + + indent + "}\n", + propertyName, + generateStringNotPresentCondition(token.version(), indent), + lengthOfLengthField, + lengthByteOrderReadStr, + lengthGoType, + className); + + generateJsonEscapedStringGetter(sb, token, indent, propertyName, className); + + new Formatter(sb).format("\n" + + indent + "func (m *%1$s) Put%2$s(str string) *%1$s {\n" + + indent + " if len(str) > %4$d {\n" + + indent + " panic(\"string too long for length type [E109]\")\n" + + indent + " }\n" + + indent + " return m.Put%2$sLen(str, %3$s(len(str)))\n" + + indent + "}\n", + className, + propertyName, + lengthGoType, + lengthToken.encoding().applicableMaxValue().longValue()); + + i += token.componentTokenCount(); + } + } + + private void generateVarDataDescriptors( + final StringBuilder sb, + final Token token, + final String propertyName, + final String characterEncoding, + final Token lengthToken, + final Integer sizeOfLengthField, + final String lengthGoType, + final String indent, + final String className) + { + new Formatter(sb).format("\n" + + indent + "func (m *%3$s) %1$sCharacterEncoding() string {\n" + + indent + " return \"%2$s\"\n" + + indent + " }\n", + formatPropertyName(propertyName), + characterEncoding, + className); + + final int version = token.version(); + final String versionCheck = 0 == version ? + " return true\n" : " return m.actingVersion >= m.%1$sSinceVersion()\n"; + new Formatter(sb).format("\n" + + indent + "func (m *%4$s) %1$sSinceVersion() uint64 {\n" + + indent + " return %2$d\n" + + indent + " }\n\n" + + + indent + "func (m *%4$s) %1$sInActingVersion() bool {\n" + + indent + versionCheck + + indent + " }\n\n" + + + indent + "func (m *%4$s) %1$sId() uint16 {\n" + + indent + " return %3$d\n" + + indent + " }\n", + formatPropertyName(propertyName), + version, + token.id(), + className); + + + new Formatter(sb).format("\n" + + indent + "func (m *%3$s) %1$sHeaderLength() uint64 {\n" + + indent + " return %2$d\n" + + indent + "}\n", + formatPropertyName(propertyName), + sizeOfLengthField, + className); + + new Formatter(sb).format("\n" + + indent + "func (m *%5$s) %1$sLength() %4$s {\n" + + "%2$s" + + indent + " return %3$s(m.buffer[m.SbePosition():])\n" + + indent + "}\n", + formatPropertyName(propertyName), + generateArrayLengthNotPresentCondition(version, BASE_INDENT), + formatReadBytes(lengthToken.encoding().byteOrder(), lengthToken.encoding().primitiveType()), + lengthGoType, + className); + } + + private void generateChoiceSet(final List tokens) throws IOException + { + final Token token = tokens.get(0); + final String bitSetName = formatClassName(token.applicableTypeName()); + + try (Writer fileOut = outputManager.createOutput(bitSetName)) + { + includes.clear(); + final StringBuilder out = new StringBuilder(); + + out.append(generateClassDeclaration(bitSetName)); + out.append(generateFixedFlyweightCode(bitSetName, token.encodedLength(), tokens)); + + final Encoding encoding = token.encoding(); + new Formatter(out).format("\n" + + " func (bs *%1$s) Clear() *%1$s {\n" + + " %2$s(bs.buffer[bs.offset:], 0)\n" + + " return bs\n" + + " }\n", + bitSetName, + formatWriteBytes(token.encoding().byteOrder(), encoding.primitiveType())); + + new Formatter(out).format("\n" + + " func (bs *%1$s) IsEmpty() bool {\n" + + " return %2$s(bs.buffer[bs.offset:]) == 0\n" + + " }\n", + bitSetName, + formatReadBytes(token.encoding().byteOrder(), encoding.primitiveType())); + + new Formatter(out).format("\n" + + " func (bs *%1$s) RawValue() %2$s {\n" + + " return %2$s(bs.buffer[bs.offset])\n" + + " }\n", + bitSetName, + goTypeName(encoding.primitiveType())); + + out.append(generateChoices(bitSetName, tokens.subList(1, tokens.size() - 1))); + out.append(generateChoicesDisplay(bitSetName, tokens.subList(1, tokens.size() - 1))); + out.append("\n"); + + fileOut.append(generateFileHeader(ir.namespaces())); + fileOut.append(out); + } + } + + private void generateEnum(final List tokens) throws IOException + { + final Token enumToken = tokens.get(0); + final String enumName = formatClassName(tokens.get(0).applicableTypeName()); + + try (Writer fileOut = outputManager.createOutput(enumName)) + { + includes.clear(); + final StringBuilder out = new StringBuilder(); + + out.append(generateEnumDeclaration(enumName, enumToken)); + + out.append(generateEnumValues(tokens.subList(1, tokens.size() - 1), enumName, enumToken)); + + out.append(generateEnumLookupMethod(tokens.subList(1, tokens.size() - 1), enumToken)); + + out.append(generateEnumDisplay(tokens.subList(1, tokens.size() - 1), enumToken)); + + out.append("\n"); + + fileOut.append(generateEnumFileHeader(ir.namespaces())); + fileOut.append(out); + } + } + + private void generateComposite(final List tokens) throws IOException + { + final String compositeName = formatClassName(tokens.get(0).applicableTypeName()); + + try (Writer fileOut = outputManager.createOutput(compositeName)) + { + includes.clear(); + final StringBuilder out = new StringBuilder(); + + out.append(generateClassDeclaration(compositeName)); + out.append(generateFixedFlyweightCode(compositeName, tokens.get(0).encodedLength(), tokens)); + + out.append(generateCompositePropertyElements( + compositeName, tokens.subList(1, tokens.size() - 1), BASE_INDENT)); + + out.append(generateCompositeDisplay( + tokens.get(0).applicableTypeName(), tokens.subList(1, tokens.size() - 1))); + + fileOut.append(generateFileHeader(ir.namespaces())); + fileOut.append(out); + } + } + + private CharSequence generateChoices(final String bitsetClassName, final List tokens) + { + final StringBuilder sb = new StringBuilder(); + + tokens + .stream() + .filter((token) -> token.signal() == Signal.CHOICE) + .forEach((token) -> + { + final String choiceName = formatPropertyName(token.name()); + final PrimitiveType type = token.encoding().primitiveType(); + final String typeName = goTypeName(type); + final String choiceBitPosition = token.encoding().constValue().toString(); + final CharSequence constantOne = generateLiteral(type, "1"); + + new Formatter(sb).format("\n" + + " func (m *%5$s) %1$sValue(bits %2$s) bool {\n" + + " return (bits & (%4$s << %3$s)) != 0\n" + + " }\n", + choiceName, + typeName, + choiceBitPosition, + constantOne, + bitsetClassName); + + new Formatter(sb).format("\n" + + " func (m *%5$s) Set%1$sValue(bits %2$s, value bool) %2$s {\n" + + " if value {\n" + + " return bits | (%4$s << %3$s)\n" + + " }\n" + + " return bits & ^(%4$s << %3$s)\n" + + " }\n", + choiceName, + typeName, + choiceBitPosition, + constantOne, + bitsetClassName); + + + new Formatter(sb).format("\n" + + "func (m *%1$s) %2$s() bool {\n" + + "%3$s" + + " return m.%2$sValue(%4$s(m.buffer[m.offset:]))\n" + + "}\n", + bitsetClassName, + choiceName, + generateChoiceNotPresentCondition(token.version()), + formatReadBytes(token.encoding().byteOrder(), type)); + + new Formatter(sb).format("\n" + + "func (m *%1$s) Set%2$s(value bool) *%1$s{\n" + + " bits := %7$s(m.buffer[m.offset:])\n" + + " if value {\n" + + " bits = %3$s(%3$s(bits) | (%6$s << %5$s))\n" + + " } else {\n" + + " bits = %3$s(%3$s(bits) & ^(%6$s << %5$s))\n" + + " }\n" + + " %4$s(m.buffer[m.offset:], bits)\n" + + " return m\n" + + "}\n", + bitsetClassName, + choiceName, + typeName, + formatWriteBytes(token.encoding().byteOrder(), type), + choiceBitPosition, + constantOne, + formatReadBytes(token.encoding().byteOrder(), type)); + }); + + return sb; + } + + private CharSequence generateEnumValues( + final List tokens, + final String enumName, + final Token encodingToken) + { + final StringBuilder sb = new StringBuilder(); + final Encoding encoding = encodingToken.encoding(); + + sb.append(" const (\n"); + + for (final Token token : tokens) + { + final CharSequence constVal = generateLiteral( + token.encoding().primitiveType(), token.encoding().constValue().toString()); + sb.append(" ").append(enumName).append("_").append(token.name()).append(" ").append(enumName) + .append(" = ").append(enumName).append("(").append(constVal).append(")\n"); + } + + final CharSequence nullLiteral = generateLiteral( + encoding.primitiveType(), encoding.applicableNullValue().toString()); + if (shouldDecodeUnknownEnumValues) + { + sb.append(" ").append(enumName).append("_").append("UNKNOWN") + .append(" ").append(enumName).append(" = ").append(enumName) + .append("(").append(nullLiteral).append(")\n"); + } + + sb.append(" ").append(enumName).append("_").append("NULL_VALUE") + .append(" ").append(enumName) + .append(" = ").append(enumName).append("(") + .append(nullLiteral).append(")\n"); + sb.append("\n )\n\n"); + + return sb; + } + + + private CharSequence generateEnumLookupMethod(final List tokens, final Token encodingToken) + { + final String enumName = formatClassName(encodingToken.applicableTypeName()); + final StringBuilder sb = new StringBuilder(); + final String goTypeName = goTypeName(encodingToken.encoding().primitiveType()); + + addInclude("errors"); + new Formatter(sb).format( + " var %1$sLookupErr = errors.New(\"unknown value for enum %1$s [E103]\")\n" + + " func Lookup%1$s(value %2$s) (%1$s, error) {\n" + + " switch value {\n", + enumName, + goTypeName); + + for (final Token token : tokens) + { + final CharSequence constVal = generateLiteral( + token.encoding().primitiveType(), token.encoding().constValue().toString()); + + sb.append(" case ").append(constVal) + .append(": return ").append(enumName).append("_") + .append(token.name()).append(", nil\n"); + } + + final CharSequence nullVal = generateLiteral( + encodingToken.encoding().primitiveType(), encodingToken.encoding().applicableNullValue().toString()); + + sb.append(" case ").append(nullVal).append(": return ") + .append(enumName).append("_").append("NULL_VALUE, nil\n") + .append(" }\n\n"); + + if (shouldDecodeUnknownEnumValues) + { + + sb.append(" return ").append(enumName).append("_").append("UNKNOWN").append(", nil\n}\n"); + } + else + { + new Formatter(sb).format(" return 0, %1$sLookupErr\n}\n", + enumName); + } + + return sb; + } + + + private CharSequence generateFieldNotPresentCondition( + final int sinceVersion, final Encoding encoding, final String indent) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + " if m.actingVersion < %1$d {\n" + + indent + " return %2$s\n" + + indent + " }\n\n", + sinceVersion, + generateLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString())); + } + + + private String namespacesToPackageName(final CharSequence[] namespaces) + { + return String.join("_", namespaces).toLowerCase().replace('.', '_').replace(' ', '_').replace('-', '_'); + } + + private CharSequence generateFileHeader(final CharSequence[] namespaces) + { + final StringBuilder sb = new StringBuilder(); + + sb.append("/* Generated SBE (Simple Binary Encoding) message codec */\n"); + + + sb.append(String.format( + "// Code generated by SBE. DO NOT EDIT.\n\n" + + + "package %1$s\n\n" + + + "import (\n" + + "%2$s\n" + + ")\n\n", + namespacesToPackageName(namespaces), + formatIncludes(includes))); + + return sb; + } + + private CharSequence generateEnumFileHeader(final CharSequence[] namespaces) + { + final StringBuilder sb = new StringBuilder(); + + sb.append("/* Generated SBE (Simple Binary Encoding) message codec */\n"); + + sb.append(String.format( + "// Code generated by SBE. DO NOT EDIT.\n\n" + + + "package %1$s\n\n" + + + "import (\n" + + "%2$s\n" + + ")\n\n", + namespacesToPackageName(namespaces), + formatIncludes(includes))); + + return sb; + } + + private CharSequence generateCompositePropertyElements( + final String containingClassName, final List tokens, final String indent) + { + final StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < tokens.size(); ) + { + final Token fieldToken = tokens.get(i); + final String propertyName = formatPropertyName(fieldToken.name()); + + generateFieldMetaAttributeMethod(sb, fieldToken, indent, containingClassName); + generateFieldCommonMethods(indent, sb, fieldToken, fieldToken, propertyName, containingClassName); + + switch (fieldToken.signal()) + { + case ENCODING: + generatePrimitiveProperty(sb, containingClassName, propertyName, fieldToken, fieldToken, indent); + break; + + case BEGIN_ENUM: + generateEnumProperty(sb, containingClassName, fieldToken, propertyName, fieldToken, indent); + break; + + case BEGIN_SET: + generateBitsetProperty(sb, propertyName, fieldToken, indent, containingClassName); + break; + + case BEGIN_COMPOSITE: + generateCompositeProperty(sb, propertyName, fieldToken, indent, containingClassName); + break; + + default: + break; + } + + i += tokens.get(i).componentTokenCount(); + } + + return sb; + } + + private void generatePrimitiveProperty( + final StringBuilder sb, + final String containingClassName, + final String propertyName, + final Token propertyToken, + final Token encodingToken, + final String indent) + { + generatePrimitiveFieldMetaData(sb, propertyName, encodingToken, indent, containingClassName); + + if (encodingToken.isConstantEncoding()) + { + generateConstPropertyMethods(sb, containingClassName, propertyName, encodingToken, indent); + } + else + { + generatePrimitivePropertyMethods( + sb, containingClassName, propertyName, propertyToken, encodingToken, indent); + } + } + + private void generatePrimitivePropertyMethods( + final StringBuilder sb, + final String containingClassName, + final String propertyName, + final Token propertyToken, + final Token encodingToken, + final String indent) + { + final int arrayLength = encodingToken.arrayLength(); + if (arrayLength == 1) + { + generateSingleValueProperty(sb, containingClassName, propertyName, propertyToken, encodingToken, indent); + } + else if (arrayLength > 1) + { + generateArrayProperty(sb, containingClassName, propertyName, propertyToken, encodingToken, indent); + } + } + + private void generatePrimitiveFieldMetaData( + final StringBuilder sb, + final String propertyName, + final Token token, + final String indent, + final String className) + { + final Encoding encoding = token.encoding(); + final PrimitiveType primitiveType = encoding.primitiveType(); + final String goTypeName = goTypeName(primitiveType); + final CharSequence nullValueString = generateNullValueLiteral(primitiveType, encoding); + + new Formatter(sb).format("\n" + + indent + " func (m *%4$s) %1$sNullValue() %2$s {\n" + + indent + " return %3$s\n" + + indent + " }\n", + propertyName, + goTypeName, + nullValueString, + className); + + new Formatter(sb).format("\n" + + indent + " func (m *%4$s) %1$sMinValue() %2$s {\n" + + indent + " return %3$s\n" + + indent + " }\n", + propertyName, + goTypeName, + generateLiteral(primitiveType, token.encoding().applicableMinValue().toString()), + className); + + new Formatter(sb).format("\n" + + indent + " func (m *%4$s) %1$sMaxValue() %2$s {\n" + + indent + " return %3$s\n" + + indent + " }\n", + propertyName, + goTypeName, + generateLiteral(primitiveType, token.encoding().applicableMaxValue().toString()), + className); + + new Formatter(sb).format("\n" + + indent + " func (m *%3$s) %1$sEncodingLength() int {\n" + + indent + " return %2$d\n" + + indent + " }\n", + propertyName, + token.encoding().primitiveType().size() * token.arrayLength(), + className); + } + + private CharSequence generateLoadValue( + final PrimitiveType primitiveType, + final String offsetStr, + final ByteOrder byteOrder, + final String indent) + { + final String goTypeName = goTypeName(primitiveType); + final StringBuilder sb = new StringBuilder(); + + new Formatter(sb).format( + indent + " return %3$s(m.buffer[(m.offset + %1$s):])\n", + offsetStr, + goTypeName, + formatReadBytes(byteOrder, primitiveType)); + + return sb; + } + + private CharSequence generateStoreValue( + final PrimitiveType primitiveType, + final String valueSuffix, + final String offsetStr, + final ByteOrder byteOrder, + final String indent) + { + final String goTypeName = goTypeName(primitiveType); + final String goMarshalType = golangMarshalType(primitiveType); + final StringBuilder sb = new StringBuilder(); + + new Formatter(sb).format( + indent + " %3$s(m.buffer[(m.offset + %4$s):], value%2$s)\n", + goTypeName, + valueSuffix, + formatWriteBytes(byteOrder, primitiveType), + offsetStr, + goMarshalType); + + return sb; + } + + private void generateSingleValueProperty( + final StringBuilder sb, + final String containingClassName, + final String propertyName, + final Token propertyToken, + final Token encodingToken, + final String indent) + { + final PrimitiveType primitiveType = encodingToken.encoding().primitiveType(); + final String goTypeName = goTypeName(primitiveType); + final int offset = encodingToken.offset(); + + new Formatter(sb).format("\n" + + indent + " func (m *%1$s) %2$s() %3$s {\n" + + "%4$s" + + "%5$s" + + indent + " }\n", + containingClassName, + propertyName, + goTypeName, + generateFieldNotPresentCondition(propertyToken.version(), encodingToken.encoding(), indent), + generateLoadValue(primitiveType, Integer.toString(offset), encodingToken.encoding().byteOrder(), indent)); + + final CharSequence storeValue = generateStoreValue( + primitiveType, "", Integer.toString(offset), encodingToken.encoding().byteOrder(), indent); + + new Formatter(sb).format("\n" + + indent + " func (m *%1$s) Set%2$s(value %3$s) *%1$s {\n" + + "%4$s" + + indent + " return m\n" + + indent + " }\n", + containingClassName, + propertyName, + goTypeName, + storeValue); + } + + private void generateArrayProperty( + final StringBuilder sb, + final String containingClassName, + final String propertyName, + final Token propertyToken, + final Token encodingToken, + final String indent) + { + final PrimitiveType primitiveType = encodingToken.encoding().primitiveType(); + final String goTypeName = goTypeName(primitiveType); + final int offset = encodingToken.offset(); + + final int arrayLength = encodingToken.arrayLength(); + new Formatter(sb).format("\n" + + indent + " func (m *%3$s) %1$sLength() int {\n" + + indent + " return %2$d\n" + + indent + " }\n", + propertyName, + arrayLength, + formatClassName(containingClassName)); + + new Formatter(sb).format("\n" + + indent + "func (m *%6$s) %2$s() []byte {\n" + + "%4$s" + + indent + " return m.buffer[m.offset+%5$d:m.offset+%5$d+%3$d]\n" + + indent + "}\n", + goTypeName, + toUpperFirstChar(propertyName), + arrayLength, + generateArrayFieldNotPresentCondition(propertyToken.version(), indent), + offset, + formatClassName(containingClassName)); + + final CharSequence loadValue = generateLoadValue( + primitiveType, + String.format("%d + (index * %d)", offset, primitiveType.size()), + encodingToken.encoding().byteOrder(), + indent); + + new Formatter(sb).format("\n" + + indent + " func (m *%6$s) %2$sIndex(index uint64) %1$s {\n" + + indent + " if (index >= %3$d) {\n" + + indent + " panic(\"index out of range for %2$s [E104]\")\n" + + indent + " }\n\n" + + "%4$s" + + "%5$s" + + indent + " }\n", + goTypeName, + propertyName, + arrayLength, + generateFieldNotPresentCondition(propertyToken.version(), encodingToken.encoding(), indent), + loadValue, + formatClassName(containingClassName)); + + final CharSequence storeValue = generateStoreValue( + primitiveType, + "", + String.format("%d + (index * %d)", offset, primitiveType.size()), + encodingToken.encoding().byteOrder(), + indent); + + new Formatter(sb).format("\n" + + indent + " func (m *%6$s) Set%2$sIndex(index uint64, value %3$s) *%6$s {\n" + + indent + " if (index >= %4$d) {\n" + + indent + " panic(\"index out of range for %2$s [E105]\")\n" + + indent + " }\n\n" + + + "%5$s" + + indent + " return m\n" + + indent + " }\n", + containingClassName, + propertyName, + goTypeName, + arrayLength, + storeValue, + formatClassName(containingClassName)); + + + addInclude("fmt"); + new Formatter(sb).format("\n" + + indent + "func (m *%6$s) Get%2$s(dst []byte) (uint64, error) {\n" + + indent + " if len(dst) > %3$d {\n" + + indent + " return 0, fmt.Errorf(\"length too large for get%2$s [E106]\")\n" + + indent + " }\n\n" + + + "%4$s" + + indent + " copy(dst, m.buffer[m.offset+%5$d:])\n" + + indent + " return %3$d, nil\n" + + indent + "}\n", + goTypeName, + toUpperFirstChar(propertyName), + arrayLength, + generateArrayFieldNotPresentConditionWithErr(propertyToken.version(), indent), + offset, + formatClassName(containingClassName)); + + new Formatter(sb).format("\n" + + indent + "func (m *%1$s) Put%2$s(src []byte) *%1$s {\n" + + indent + " copy(m.buffer[(m.offset+%3$d):], src)\n" + + indent + " return m\n" + + indent + "}\n", + formatClassName(containingClassName), + formatPropertyName(propertyName), + offset); + + if (arrayLength > 1 && arrayLength <= 4) + { + sb.append("\n").append(indent).append("func (m *") + .append(formatClassName(containingClassName)).append(") Put") + .append(formatPropertyName(propertyName)) + .append("Values (\n"); + + for (int i = 0; i < arrayLength; i++) + { + sb.append(indent).append(" value").append(i) + .append(" ") + .append(goTypeName); + + if (i < (arrayLength - 1)) + { + sb.append(",\n"); + } + } + + sb.append(")") + .append(" *") + .append(formatClassName(containingClassName)) + .append(" {\n"); + + for (int i = 0; i < arrayLength; i++) + { + sb.append(generateStoreValue( + primitiveType, + Integer.toString(i), + Integer.toString(offset + (i * primitiveType.size())), + encodingToken.encoding().byteOrder(), + indent)); + } + + sb.append("\n"); + sb.append(indent).append(" return m\n"); + sb.append(indent).append("}\n"); + } + + + if (encodingToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + new Formatter(sb).format("\n" + + indent + " func (m *%4$s) Get%1$sAsString() string {\n" + + indent + " offset := m.offset + %2$d\n" + + indent + " length := uint64(0)\n\n" + + indent + " for length < %3$d && m.buffer[offset + length] != '\\x00' {\n" + + indent + " length++\n" + + indent + " }\n" + + indent + " return string(m.buffer[offset:offset + length])\n" + + indent + " }\n", + toUpperFirstChar(propertyName), + offset, + arrayLength, + formatClassName(containingClassName)); + + generateJsonEscapedStringGetter(sb, encodingToken, indent, propertyName, containingClassName); + + new Formatter(sb).format("\n" + + indent + "func (m *%1$s) Set%2$s(src string) *%1$s {\n" + + indent + " copy(m.buffer[(m.offset+%3$d):], []byte(src))\n" + + indent + " return m\n" + + indent + "}\n", + formatClassName(containingClassName), + formatPropertyName(propertyName), + offset); + } + } + + private void generateJsonEscapedStringGetter( + final StringBuilder sb, + final Token token, + final String indent, + final String propertyName, + final String className) + { + addInclude("strings"); + addInclude("fmt"); + new Formatter(sb).format("\n" + + indent + "func (m *%3$s) Get%1$sAsJsonEscapedString() string {\n" + + "%2$s" + + indent + " oss := strings.Builder{}\n" + + indent + " s := m.Get%1$sAsString()\n\n" + + indent + " for _, c := range s {\n" + + indent + " switch c {\n" + + indent + " case '\"': oss.WriteString(\"\\\\\\\"\")\n" + + indent + " case '\\\\': oss.WriteString(\"\\\\\\\\\")\n" + + indent + " case '\\b': oss.WriteString(\"\\\\b\")\n" + + indent + " case '\\f': oss.WriteString(\"\\\\f\")\n" + + indent + " case '\\n': oss.WriteString(\"\\\\n\")\n" + + indent + " case '\\r': oss.WriteString(\"\\\\r\")\n" + + indent + " case '\\t': oss.WriteString(\"\\\\t\")\n\n" + + indent + " default:\n" + + indent + " if '\\x00' <= c && c <= '\\x1f' {\n" + + indent + " fmt.Fprintf(&oss, \"%%x\", c)\n" + + indent + " } else {\n" + + indent + " oss.WriteString(string(c))\n" + + indent + " }\n" + + indent + " }\n" + + indent + " }\n\n" + + indent + " return oss.String()\n" + + indent + "}\n", + toUpperFirstChar(propertyName), + generateStringNotPresentCondition(token.version(), indent), + className); + } + + private void generateConstPropertyMethods( + final StringBuilder sb, + final String className, + final String propertyName, + final Token token, + final String indent) + { + final String goTypeName = goTypeName(token.encoding().primitiveType()); + + if (token.encoding().primitiveType() != PrimitiveType.CHAR) + { + new Formatter(sb).format("\n" + + indent + " func (m *%4$s) %2$s() %1$s {\n" + + indent + " return %3$s\n" + + indent + " }\n", + goTypeName, + propertyName, + generateLiteral(token.encoding().primitiveType(), token.encoding().constValue().toString()), + className); + + return; + } + + final byte[] constantValue = token.encoding().constValue().byteArrayValue(token.encoding().primitiveType()); + final StringBuilder values = new StringBuilder(); + for (final byte b : constantValue) + { + values.append(b).append(", "); + } + + if (values.length() > 0) + { + values.setLength(values.length() - 2); + } + + new Formatter(sb).format("\n" + + indent + " func (m *%3$s) %1$sLength() uint64 {\n" + + indent + " return %2$d\n" + + indent + " }\n", + propertyName, + constantValue.length, + className); + + new Formatter(sb).format("\n" + + indent + " func (m *%3$s) %1$s() string {\n" + + indent + " %1$sValues := []uint8{ %2$s, 0 }\n\n" + + indent + " return string(%1$sValues)\n" + + indent + " }\n", + propertyName, + values, + className); + + sb.append(String.format("\n" + + indent + " func (m *%4$s) %2$sIndex(index uint64) %1$s {\n" + + indent + " %2$sValues := []uint8{ %3$s, 0 }\n\n" + + indent + " return byte(%2$sValues[index])\n" + + indent + " }\n", + goTypeName, + propertyName, + values, + className)); + + new Formatter(sb).format("\n" + + indent + " func (m *%4$s) Get%1$s(dst []byte, length uint64) uint64 {\n" + + indent + " %2$sValues := []uint8{ %3$s }\n" + + indent + " bytesToCopy := uint64(len(%2$sValues))\n" + + indent + " if length < uint64(len(%2$sValues)) {\n" + + indent + " bytesToCopy = length\n" + + indent + " }\n" + + indent + " copy(dst, %2$sValues[:bytesToCopy])\n" + + indent + " return bytesToCopy\n" + + indent + " }\n", + toUpperFirstChar(propertyName), + propertyName, + values, + className); + + new Formatter(sb).format("\n" + + indent + " func (m *%3$s) Get%1$sAsString() string {\n" + + indent + " %1$sValues := []uint8{ %2$s, 0 }\n\n" + + indent + " return string(%1$sValues)\n" + + indent + " }\n", + propertyName, + values, + className); + + generateJsonEscapedStringGetter(sb, token, indent, propertyName, className); + } + + private CharSequence generateFixedFlyweightCode( + final String className, + final int size, + final List fields) + { + final String schemaIdType = goTypeName(ir.headerStructure().schemaIdType()); + final String schemaVersionType = goTypeName(ir.headerStructure().schemaVersionType()); + + final StringBuilder sb = new StringBuilder(); + for (int i = 1, fieldSize = fields.size(); i < fieldSize; ) + { + final Token signalToken = fields.get(i); + final String propertyName = formatPropertyName(signalToken.name()); + final String typeName = formatClassName(signalToken.applicableTypeName()); + + switch (signalToken.signal()) + { + case BEGIN_SET: + case BEGIN_COMPOSITE: + new Formatter(sb).format(" _%1$s %2$s\n", + propertyName, + typeName); + break; + + default: + break; + } + + i += fields.get(i).componentTokenCount(); + } + + String sizeValue = String.format("%1$d", size); + if (size == -1) + { + addInclude("math"); + sizeValue = "math.MaxUint64"; + } + + return String.format( + " buffer []byte\n" + + " bufferLength uint64\n" + + " offset uint64\n" + + " actingVersion uint64\n" + + "%7$s\n" + + "}\n\n" + + + " const (\n" + + " %1$sEncodedLength uint64 = %2$s\n" + + " %1$sSbeSchemaID %3$s = %4$s\n" + + " %1$sSbeSchemaVersion %5$s = %6$s\n" + + " )\n\n" + + + " func (m *%1$s) Wrap(\n" + + " buffer []byte,\n" + + " offset uint64,\n" + + " actingVersion uint64,\n" + + " bufferLength uint64) {\n" + + " m.buffer = buffer\n" + + " m.bufferLength = bufferLength\n" + + " m.offset = offset\n" + + " m.actingVersion = actingVersion\n" + + " if !SbeNoBoundsCheck && ((m.offset + %2$s) > m.bufferLength) {\n" + + " panic(\"buffer too short for flyweight [E107]\")\n" + + " }\n" + + " }\n\n" + + + " func (m *%1$s) EncodedLength() uint64 {\n" + + " return %2$s\n" + + " }\n\n" + + + " func (m *%1$s) Offset() uint64 {\n" + + " return m.offset\n" + + " }\n\n" + + + " func (m *%1$s) Buffer() []byte {\n" + + " return m.buffer\n" + + " }\n\n" + + + " func (m *%1$s) BufferLength() uint64 {\n" + + " return m.bufferLength\n" + + " }\n\n" + + + " func (m *%1$s) ActingVersion() uint64 {\n" + + " return m.actingVersion\n" + + " }\n\n" + + + " func (m *%1$s) SbeSchemaId() %3$s {\n" + + " return %4$s\n" + + " }\n\n" + + + " func (m *%1$s) SbeSchemaVersion() %5$s {\n" + + " return %6$s\n" + + " }\n", + + className, + sizeValue, + schemaIdType, + generateLiteral(ir.headerStructure().schemaIdType(), Integer.toString(ir.id())), + schemaVersionType, + generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), + sb); + } + + private CharSequence generateMessageFlyweightCode( + final String className, + final Token token, + final List fields, + final List groups) + { + final StringBuilder sb = new StringBuilder(); + final String blockLengthType = goTypeName(ir.headerStructure().blockLengthType()); + final String templateIdType = goTypeName(ir.headerStructure().templateIdType()); + final String schemaIdType = goTypeName(ir.headerStructure().schemaIdType()); + final String schemaVersionType = goTypeName(ir.headerStructure().schemaVersionType()); + final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); + final String headerType = ir.headerStructure().tokens().get(0).name(); + final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); + + sb.append(" buffer []byte\n" + + " bufferLength uint64\n" + + " offset uint64\n" + + " position uint64\n" + + " actingBlockLength uint64\n" + + " actingVersion uint64\n"); + + for (int i = 0, size = fields.size(); i < size; i++) + { + final Token signalToken = fields.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = fields.get(i + 1); + final String propertyName = formatPropertyName(signalToken.name()); + final String typeName = formatClassName(encodingToken.applicableTypeName()); + + switch (encodingToken.signal()) + { + case BEGIN_SET: + case BEGIN_COMPOSITE: + new Formatter(sb).format(" _%1$s %2$s\n", + propertyName, + typeName); + break; + + default: + break; + } + } + } + + for (int i = 0, size = groups.size(); i < size; ) + { + final Token groupToken = groups.get(i); + if (groupToken.signal() == Signal.BEGIN_GROUP) + { + final String propertyName = formatPropertyName(groupToken.name()); + final String groupName = className + formatClassName(groupToken.name()); + + new Formatter(sb).format(" _%1$s %2$s\n", + propertyName, + groupName); + + i += groupToken.componentTokenCount(); + } + } + + sb.append("}\n\n"); + + sb.append(String.format( + " func (m *%10$s) sbePositionPtr() *uint64 {\n" + + " return &m.position\n" + + " }\n\n" + + + " const (\n" + + " %10$sSbeBlockLength %1$s = %2$s\n" + + " %10$sSbeTemplateID %3$s = %4$s\n" + + " %10$sSbeSchemaID %5$s = %6$s\n" + + " %10$sSbeSchemaVersion %7$s = %8$s\n" + + " %10$sSbeSemanticVersion string = \"%13$s\"\n" + + " )\n\n" + + + " func (m *%10$s) SbeBlockLength() %1$s {\n" + + " return %2$s\n" + + " }\n\n" + + + " func (m *%10$s) SbeBlockAndHeaderLength() uint64 {\n" + + " return MessageHeaderEncodedLength + uint64(m.SbeBlockLength())\n" + + " }\n\n" + + + " func (m *%10$s) SbeTemplateId() %3$s {\n" + + " return %4$s\n" + + " }\n\n" + + + " func (m *%10$s) SbeSchemaId() %5$s {\n" + + " return %6$s\n" + + " }\n\n" + + + " func (m *%10$s) SbeSchemaVersion() %7$s {\n" + + " return %8$s\n" + + " }\n\n" + + + " func (m *%10$s) SbeSemanticVersion() string {\n" + + " return \"%13$s\"\n" + + " }\n\n" + + + " func (m *%10$s) SbeSemanticType() string {\n" + + " return \"%9$s\"\n" + + " }\n\n" + + + " func (m *%10$s) Offset() uint64 {\n" + + " return m.offset\n" + + " }\n\n" + + + " func (m *%10$s) Wrap(\n" + + " buffer []byte,\n" + + " offset uint64,\n" + + " bufferLength uint64,\n" + + " actingBlockLength uint64,\n" + + " actingVersion uint64) *%10$s {\n" + + " m.buffer = buffer\n" + + " m.bufferLength = bufferLength\n" + + " m.offset = offset\n" + + " m.position = m.SbeCheckPosition(offset + actingBlockLength)\n" + + " m.actingBlockLength = actingBlockLength\n" + + " m.actingVersion = actingVersion\n" + + " return m\n" + + " }\n\n" + + + " func (m *%10$s) WrapForEncode(buffer []byte, offset uint64, bufferLength uint64) *%10$s {\n" + + " return m.Wrap(buffer, offset, bufferLength,\n" + + " uint64(m.SbeBlockLength()), uint64(m.SbeSchemaVersion()))\n" + + " }\n\n" + + + " func (m *%10$s) WrapAndApplyHeader(buffer []byte, offset uint64, bufferLength uint64) *%10$s {\n" + + " var hdr MessageHeader\n" + + " hdr.Wrap(buffer, offset, uint64(m.SbeSchemaVersion()), bufferLength)\n\n" + + + " hdr.SetBlockLength(m.SbeBlockLength()).\n" + + " SetTemplateId(m.SbeTemplateId()).\n" + + " SetSchemaId(m.SbeSchemaId()).\n" + + " SetVersion(m.SbeSchemaVersion())\n\n" + + + " return m.Wrap(\n" + + " buffer,\n" + + " offset + hdr.EncodedLength(),\n" + + " bufferLength,\n" + + " uint64(m.SbeBlockLength()),\n" + + " uint64(m.SbeSchemaVersion()))\n" + + " }\n\n" + + + " func (m *%10$s) WrapForDecode(\n" + + " buffer []byte,\n" + + " offset uint64,\n" + + " actingBlockLength uint64,\n" + + " actingVersion uint64,\n" + + " bufferLength uint64) *%10$s {\n" + + " return m.Wrap(\n" + + " buffer,\n" + + " offset,\n" + + " bufferLength,\n" + + " actingBlockLength,\n" + + " actingVersion)\n" + + " }\n\n" + + + " func (m *%10$s) sbeRewind() *%10$s {\n" + + " return m.WrapForDecode(" + + "m.buffer, m.offset, m.actingBlockLength, m.actingVersion, m.bufferLength)\n" + + " }\n\n" + + + " func (m *%10$s) SbePosition() uint64 {\n" + + " return m.position\n" + + " }\n\n" + + + " func (m *%10$s) SbeCheckPosition(position uint64) uint64 {\n" + + " if !SbeNoBoundsCheck && (position > m.bufferLength) {\n" + + " panic(\"buffer too short [E100]\")\n" + + " }\n" + + " return position\n" + + " }\n\n" + + + " func (m *%10$s) SetSbePosition(position uint64) {\n" + + " m.position = m.SbeCheckPosition(position)\n" + + " }\n\n" + + + " func (m *%10$s) EncodedLength() uint64 {\n" + + " return m.SbePosition() - m.offset\n" + + " }\n\n" + + + " func (m *%10$s) DecodeLength() uint64 {\n" + + " var skipper %10$s\n" + + " skipper.WrapForDecode(m.buffer, m.offset, uint64(m.SbeBlockLength()),\n" + + " uint64(m.ActingVersion()), m.bufferLength)\n" + + " skipper.Skip()\n" + + " return skipper.EncodedLength()\n" + + " }\n\n" + + + " func (m *%10$s) Buffer() []byte {\n" + + " return m.buffer\n" + + " }\n\n" + + + " func (m *%10$s) BufferLength() uint64 {\n" + + " return m.bufferLength\n" + + " }\n\n" + + + " func (m *%10$s) ActingVersion() uint64 {\n" + + " return m.actingVersion\n" + + " }\n", + blockLengthType, + generateLiteral(ir.headerStructure().blockLengthType(), Integer.toString(token.encodedLength())), + templateIdType, + generateLiteral(ir.headerStructure().templateIdType(), Integer.toString(token.id())), + schemaIdType, + generateLiteral(ir.headerStructure().schemaIdType(), Integer.toString(ir.id())), + schemaVersionType, + generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), + semanticType, + className, + generateConstructorsAndOperators(className), + formatClassName(headerType), + semanticVersion)); + return sb.toString(); + } + + private void generateFields( + final StringBuilder sb, + final String containingClassName, + final List tokens, + final String indent) + { + for (int i = 0, size = tokens.size(); i < size; i++) + { + final Token signalToken = tokens.get(i); + if (signalToken.signal() == Signal.BEGIN_FIELD) + { + final Token encodingToken = tokens.get(i + 1); + final String propertyName = formatPropertyName(signalToken.name()); + + generateFieldMetaAttributeMethod(sb, signalToken, indent, containingClassName); + generateFieldCommonMethods(indent, sb, signalToken, encodingToken, propertyName, containingClassName); + + switch (encodingToken.signal()) + { + case ENCODING: + generatePrimitiveProperty( + sb, containingClassName, propertyName, signalToken, encodingToken, indent); + break; + + case BEGIN_ENUM: + generateEnumProperty(sb, containingClassName, signalToken, propertyName, encodingToken, indent); + break; + + case BEGIN_SET: + generateBitsetProperty(sb, propertyName, encodingToken, indent, containingClassName); + break; + + case BEGIN_COMPOSITE: + generateCompositeProperty(sb, propertyName, encodingToken, indent, containingClassName); + break; + + default: + break; + } + } + } + } + + private void generateFieldCommonMethods( + final String indent, + final StringBuilder sb, + final Token fieldToken, + final Token encodingToken, + final String propertyName, + final String className) + { + new Formatter(sb).format("\n" + + indent + " func (m *%3$s) %1$sId() int {\n" + + indent + " return %2$d\n" + + indent + " }\n", + propertyName, + fieldToken.id(), + className); + + final int version = fieldToken.version(); + final String versionCheck = 0 == version ? + " return true\n" : " return m.actingVersion >= m.%1$sSinceVersion()\n"; + new Formatter(sb).format("\n" + + indent + " func (m *%3$s) %1$sSinceVersion() uint64 {\n" + + indent + " return %2$d\n" + + indent + " }\n\n" + + + indent + " func (m *%3$s) %1$sInActingVersion() bool {\n" + + indent + versionCheck + + indent + " }\n", + propertyName, + version, + className); + + new Formatter(sb).format("\n" + + indent + " func (m *%3$s) %1$sEncodingOffset() uint {\n" + + indent + " return %2$d\n" + + indent + " }\n", + propertyName, + encodingToken.offset(), + className); + } + + private void generateEnumProperty( + final StringBuilder sb, + final String containingClassName, + final Token fieldToken, + final String propertyName, + final Token encodingToken, + final String indent) + { + final String enumName = formatClassName(encodingToken.applicableTypeName()); + final PrimitiveType primitiveType = encodingToken.encoding().primitiveType(); + final String typeName = goTypeName(primitiveType); + final int offset = encodingToken.offset(); + + new Formatter(sb).format("\n" + + indent + " func (m *%1$s) %2$sEncodingLength() int {\n" + + indent + " return %3$d\n" + + indent + " }\n", + containingClassName, + propertyName, + fieldToken.encodedLength()); + + if (fieldToken.isConstantEncoding()) + { + final String constValue = fieldToken.encoding().constValue().toString(); + + new Formatter(sb).format("\n" + + indent + " func (m *%1$s) %2$sConstValue() %4$s {\n" + + indent + " return %4$s_%3$s\n" + + indent + " }\n", + containingClassName, + propertyName, + constValue.substring(constValue.indexOf(".") + 1), + enumName); + + new Formatter(sb).format("\n" + + indent + " func (m *%1$s) %2$s() %5$s {\n" + + "%3$s" + + indent + " return %5$s_%4$s\n" + + indent + " }\n", + containingClassName, + propertyName, + generateEnumFieldNotPresentCondition(fieldToken.version(), enumName, indent), + constValue.substring(constValue.indexOf(".") + 1), + enumName); + + new Formatter(sb).format("\n" + + indent + " func (m *%3$s) %2$sRaw() %1$s {\n" + + indent + " return %1$s(%5$s_%4$s)\n" + + indent + " }\n", + typeName, + propertyName, + containingClassName, + constValue.substring(constValue.indexOf(".") + 1), + enumName); + + } + else + { + final String offsetStr = Integer.toString(offset); + new Formatter(sb).format("\n" + + indent + " func (m *%5$s) %2$sRaw() %1$s {\n" + + "%3$s" + + "%4$s" + + indent + " }\n", + typeName, + propertyName, + generateFieldNotPresentCondition(fieldToken.version(), encodingToken.encoding(), indent), + generateLoadValue(primitiveType, offsetStr, encodingToken.encoding().byteOrder(), indent), + containingClassName); + + new Formatter(sb).format("\n" + + indent + " func (m *%1$s) %2$s() %7$s {\n" + + "%3$s" + + indent + " return %7$s(%4$s(m.buffer[(m.offset + %6$d):]))\n" + + indent + " }\n", + containingClassName, + propertyName, + generateEnumFieldNotPresentCondition(fieldToken.version(), enumName, indent), + formatReadBytes(encodingToken.encoding().byteOrder(), primitiveType), + typeName, + offset, + enumName); + + new Formatter(sb).format("\n" + + indent + " func (m *%1$s) Set%2$s(value %3$s) *%1$s {\n" + + indent + " val := %4$s(value)\n" + + indent + " %6$s(m.buffer[(m.offset + %5$d):], val)\n" + + indent + " return m\n" + + indent + " }\n", + formatClassName(containingClassName), + propertyName, + enumName, + typeName, + offset, + formatWriteBytes(encodingToken.encoding().byteOrder(), primitiveType)); + } + } + + private CharSequence generateNullValueLiteral( + final PrimitiveType primitiveType, + final Encoding encoding) + { + // Go does not handle minimum integer values properly + // So null values get special handling + if (null == encoding.nullValue()) + { + switch (primitiveType) + { + case CHAR: + return "SbeNullValueByte()"; + case FLOAT: + return "SbeNullValueFloat()"; + case DOUBLE: + return "SbeNullValueDouble()"; + case INT8: + return "SbeNullValueInt8()"; + case INT16: + return "SbeNullValueInt16()"; + case INT32: + return "SbeNullValueInt32()"; + case INT64: + return "SbeNullValueInt64()"; + case UINT8: + return "SbeNullValueUint8()"; + case UINT16: + return "SbeNullValueUint16()"; + case UINT32: + return "SbeNullValueUint32()"; + case UINT64: + return "SbeNullValueUint64()"; + } + } + + return generateLiteral(primitiveType, encoding.applicableNullValue().toString()); + } + + + private CharSequence generateLiteral(final PrimitiveType type, final String value) + { + String literal = ""; + + switch (type) + { + case CHAR: + literal = "byte(" + value + ")"; + break; + case UINT8: + literal = "uint8(" + value + ")"; + break; + case UINT16: + literal = "uint16(" + value + ")"; + break; + case INT8: + literal = "int8(" + value + ")"; + break; + case INT16: + literal = "int16(" + value + ")"; + break; + + case UINT32: + literal = "uint32(0x" + Integer.toHexString((int)Long.parseLong(value)) + ")"; + break; + + case INT32: + final long intValue = Long.parseLong(value); + if (intValue == Integer.MIN_VALUE) + { + literal = "math.MinInt32"; + addInclude("math"); + } + else + { + literal = "int32(" + value + ")"; + } + break; + + case FLOAT: + if (value.endsWith("NaN")) + { + literal = "math.NaN()"; + } + else + { + literal = value; + } + break; + + case INT64: + final long longValue = Long.parseLong(value); + if (longValue == Long.MIN_VALUE) + { + literal = "math.MinInt64"; + addInclude("math"); + } + else + { + literal = "int64(" + value + ")"; + } + break; + + case UINT64: + literal = "uint64(0x" + Long.toHexString(Long.parseLong(value)) + ")"; + break; + + case DOUBLE: + if (value.endsWith("NaN")) + { + literal = "math.NaN()"; + addInclude("math"); + } + else + { + literal = value; + } + break; + } + + return literal; + } + + private void addInclude(final String name) + { + includes.add(name); + } + + + private void generateDisplay( + final StringBuilder sb, + final String containingClassName, + final String name, + final List fields, + final List groups, + final List varData) + { + addInclude("strings"); + addInclude("fmt"); + new Formatter(sb).format("\n" + + "func (writer *%1$s) String() string {\n" + + " var builder strings.Builder\n" + + " builder.WriteString(\"{\\\"Name\\\": \\\"%1$s\\\", \")\n" + + " builder.WriteString(fmt.Sprintf(\"\\\"sbeTemplateId\\\": %%d\", writer.SbeTemplateId()))\n" + + " builder.WriteString(\", \")\n\n" + + "%2$s" + + " builder.WriteString(\"}\")\n\n" + + " return builder.String()\n" + + "}\n", + formatClassName(name), + appendDisplay(containingClassName, fields, groups, varData, INDENT)); + } + + + private CharSequence generateGroupDisplay( + final String groupClassName, + final List fields, + final List groups, + final List varData, + final String indent) + { + addInclude("strings"); + return String.format("\n" + + indent + "func (writer *%1$s) String() string {\n" + + indent + " builder := strings.Builder{}\n" + + indent + " builder.WriteString(\"{\")\n" + + "%2$s" + + indent + " builder.WriteString(\"}\")\n\n" + + indent + " return builder.String()\n" + + indent + "}\n", + groupClassName, + appendDisplay(groupClassName, fields, groups, varData, indent + INDENT)); + } + + + private CharSequence generateCompositeDisplay(final String name, final List tokens) + { + addInclude("strings"); + return String.format("\n" + + "func (writer *%1$s) String() string {\n" + + " builder := strings.Builder{}\n" + + " builder.WriteString(\"{\")\n" + + "%2$s" + + " builder.WriteString(\"}\")\n\n" + + " return builder.String()\n" + + "}\n\n", + formatClassName(name), + appendDisplay(formatClassName(name), tokens, new ArrayList<>(), new ArrayList<>(), INDENT)); + } + + + private CharSequence appendDisplay( + final String containingClassName, + final List fields, + final List groups, + final List varData, + final String indent) + { + final StringBuilder sb = new StringBuilder(); + final boolean[] atLeastOne = {false}; + + for (int i = 0, size = fields.size(); i < size; ) + { + final Token fieldToken = fields.get(i); + final Token encodingToken = fields.get(fieldToken.signal() == Signal.BEGIN_FIELD ? i + 1 : i); + + writeTokenDisplay(sb, fieldToken.name(), encodingToken, atLeastOne, indent); + i += fieldToken.componentTokenCount(); + } + + for (int i = 0, size = groups.size(); i < size; i++) + { + final Token groupToken = groups.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + if (atLeastOne[0]) + { + sb.append(indent).append("builder.WriteString(\", \")\n"); + } + atLeastOne[0] = true; + + new Formatter(sb).format( + indent + "{\n" + + indent + " atLeastOne := false\n" + + indent + " builder.WriteString(`\"%3$s\": [`)\n" + + indent + " writer.%2$s().ForEach(\n" + + indent + " func(value *%1$s) {\n" + + indent + " if atLeastOne {\n" + + indent + " builder.WriteString(\", \")\n" + + indent + " }\n" + + indent + " atLeastOne = true\n" + + indent + " builder.WriteString(value.String())\n" + + indent + " })\n" + + indent + " builder.WriteString(\"]\")\n" + + indent + "}\n\n", + containingClassName + formatClassName(groupToken.name()), + formatPropertyName(groupToken.name()), + groupToken.name()); + + i = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); + } + + for (int i = 0, size = varData.size(); i < size; ) + { + final Token varDataToken = varData.get(i); + if (varDataToken.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); + } + + if (atLeastOne[0]) + { + sb.append(indent).append("builder.WriteString(\", \")\n"); + } + atLeastOne[0] = true; + + final String characterEncoding = varData.get(i + 3).encoding().characterEncoding(); + sb.append(indent).append("builder.WriteString(`\"").append(varDataToken.name()).append("\": `)\n"); + + if (null == characterEncoding) + { + final String skipFunction = "writer.Skip" + toUpperFirstChar(varDataToken.name()) + "()"; + + sb.append(indent).append("builder.WriteString(`\"`)\n") + .append(indent).append(INDENT).append(skipFunction).append("\n") + .append(INDENT).append("builder.WriteString(\" bytes of raw data\")\n"); + } + else + { + final String getAsStringFunction = + "writer.Get" + toUpperFirstChar(varDataToken.name()) + "AsJsonEscapedString()"; + + sb.append(indent).append("builder.WriteString(`\"` + ") + .append(getAsStringFunction).append(" + `\"`);\n\n"); + } + + i += varDataToken.componentTokenCount(); + } + + return sb; + } + + private void writeTokenDisplay( + final StringBuilder sb, + final String fieldTokenName, + final Token typeToken, + final boolean[] atLeastOne, + final String indent) + { + if (typeToken.encodedLength() <= 0 || typeToken.isConstantEncoding()) + { + return; + } + + if (atLeastOne[0]) + { + sb.append(indent).append("builder.WriteString(\", \")\n"); + } + else + { + atLeastOne[0] = true; + } + + sb.append(indent).append("builder.WriteString(`\"").append(fieldTokenName).append("\": `)\n"); + final String fieldName = "writer." + formatPropertyName(fieldTokenName); + + switch (typeToken.signal()) + { + case ENCODING: + if (typeToken.arrayLength() > 1) + { + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + final String getAsStringFunction = + "writer.Get" + toUpperFirstChar(fieldTokenName) + "AsJsonEscapedString()"; + + sb.append(indent).append("builder.WriteString(`\"` +\n").append(indent).append(INDENT) + .append(getAsStringFunction).append(" + `\"`)\n"); + } + else + { + addInclude("fmt"); + sb.append( + indent + "builder.WriteString(\"[\")\n" + + indent + "for i := 0; i < " + fieldName + "Length(); i++ {\n" + + indent + " if i > 0 {\n" + + indent + " builder.WriteString(\",\")\n" + + indent + " }\n" + + indent + " builder.WriteString(fmt.Sprintf(\"%v\", " + fieldName + + "Index(uint64(i))))\n" + + indent + "}\n" + + indent + "builder.WriteString(\"]\")\n"); + } + } + else + { + addInclude("fmt"); + + if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + sb.append(indent).append("builder.WriteString(fmt.Sprintf(`\"%c\"`, ").append(fieldName) + .append("()))\n"); + } + else + { + sb.append(indent).append("builder.WriteString(fmt.Sprintf(`\"%v\"`, ").append(fieldName) + .append("()))\n"); + } + } + break; + + case BEGIN_ENUM: + addInclude("fmt"); + sb.append(indent).append("builder.WriteString(fmt.Sprintf(`\"%v\"`, ").append(fieldName) + .append("()))\n"); + break; + + case BEGIN_SET: + case BEGIN_COMPOSITE: + if (0 == typeToken.version()) + { + sb.append(indent).append("builder.WriteString(").append(fieldName).append("().String())\n"); + } + else + { + new Formatter(sb).format( + indent + "if (%1$sInActingVersion()) {\n" + + indent + " builder.WriteString(%1$s().String())\n" + + indent + "} else {\n" + + indent + " builder.WriteString(%2$s)\n" + + indent + "}\n", + fieldName, + typeToken.signal() == Signal.BEGIN_SET ? "\"[]\"" : "\"{}\""); + } + break; + + default: + break; + } + + sb.append('\n'); + } + + + private CharSequence generateChoicesDisplay( + final String name, + final List tokens) + { + final String indent = INDENT; + final StringBuilder sb = new StringBuilder(); + final List choiceTokens = new ArrayList<>(); + + collect(Signal.CHOICE, tokens, 0, choiceTokens); + + addInclude("strings"); + new Formatter(sb).format("\n" + + indent + "func (writer %1$s) String() string {\n" + + indent + " builder := strings.Builder{}\n" + + indent + " builder.WriteString(\"[\")\n", + name); + + if (choiceTokens.size() > 1) + { + sb.append(indent + " atLeastOne := false\n"); + } + + for (int i = 0, size = choiceTokens.size(); i < size; i++) + { + final Token token = choiceTokens.get(i); + final String choiceName = "writer." + formatPropertyName(token.name()); + + sb.append(indent + " if ").append(choiceName).append("() {\n"); + + if (i > 0) + { + sb.append( + indent + " if (atLeastOne) {\n" + + indent + " builder.WriteString(\",\")\n" + + indent + " }\n"); + } + sb.append(indent + " builder.WriteString(`\"").append(formatPropertyName(token.name())) + .append("\"`)\n"); + + if (i < (size - 1)) + { + sb.append(indent + " atLeastOne = true\n"); + } + + sb.append(indent + " }\n"); + } + + sb.append( + indent + " builder.WriteString(\"]\")\n" + + indent + " return builder.String()\n" + + indent + "}\n"); + + return sb; + } + + + private CharSequence generateEnumDisplay( + final List tokens, + final Token encodingToken) + { + final String enumName = formatClassName(encodingToken.applicableTypeName()); + final StringBuilder sb = new StringBuilder(); + + new Formatter(sb).format("\n" + + " func (value %1$s) String() string {\n" + + " switch value {\n", + enumName); + + for (final Token token : tokens) + { + new Formatter(sb).format( + " case %2$s_%1$s: return \"%1$s\"\n", + token.name(), + enumName); + } + + sb.append(" case ").append(enumName) + .append("_NULL_VALUE: return \"NULL_VALUE\"\n").append(" }\n\n"); + + if (shouldDecodeUnknownEnumValues) + { + sb.append(" return \"SBE_UNKNOWN\"\n").append(" }\n\n"); + } + else + { + addInclude("fmt"); + new Formatter(sb).format( + " panic(fmt.Sprintf(\"unknown value for enum %1$s [E103]: %%d\", value))\n" + + " }\n\n", + enumName); + } + + return sb; + } + + private Object[] generateMessageLengthArgs( + final List groups, + final List varData, + final String indent, + final boolean inStruct) + { + final StringBuilder sb = new StringBuilder(); + int count = 0; + + for (int i = 0, size = groups.size(); i < size; i++) + { + final Token groupToken = groups.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + final int endSignal = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); + final String groupName = formatPropertyName(groupToken.name()); + + if (count > 0) + { + if (inStruct) + { + sb.append("; ").append(indent); + } + else + { + sb.append(",\n").append(indent); + } + } + + final List thisGroup = groups.subList(i, endSignal + 1); + + if (isMessageConstLength(thisGroup)) + { + sb.append(" ").append(groupName).append("Length ").append("int"); + } + else + { + sb.append(groupName).append("ItemLengths ").append("[]struct{"); + sb.append(generateMessageLengthArgs(thisGroup, indent + INDENT, true)[0]); + sb.append("}"); + } + + count += 1; + + i = endSignal; + } + + for (int i = 0, size = varData.size(); i < size; ) + { + final Token varDataToken = varData.get(i); + if (varDataToken.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); + } + + if (count > 0) + { + if (inStruct) + { + sb.append("; ").append(indent); + } + else + { + sb.append(",\n").append(indent); + } + } + + sb.append(" ").append(formatPropertyName(varDataToken.name())).append("Length").append(" int"); + + count += 1; + + i += varDataToken.componentTokenCount(); + } + + CharSequence result = sb; + if (count > 1) + { + result = "\n" + indent + result; + } + + return new Object[] {result, count}; + } + + + private Object[] generateMessageLengthArgs(final List tokens, final String indent, final boolean inStruct) + { + int i = 0; + + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + ++i; + final int groupHeaderTokenCount = tokens.get(i).componentTokenCount(); + i += groupHeaderTokenCount; + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + final List varData = new ArrayList<>(); + collectVarData(tokens, i, varData); + + return generateMessageLengthArgs(groups, varData, indent, inStruct); + } + + private boolean isMessageConstLength(final List tokens) + { + final Integer count = (Integer)generateMessageLengthArgs(tokens, BASE_INDENT, false)[1]; + + return count == 0; + } + + private String generateMessageLengthCallHelper( + final List groups, + final List varData) + { + final StringBuilder sb = new StringBuilder(); + int count = 0; + + for (int i = 0, size = groups.size(); i < size; i++) + { + final Token groupToken = groups.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + final int endSignal = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); + final String groupName = formatPropertyName(groupToken.name()); + + if (count > 0) + { + sb.append(", "); + } + + final List thisGroup = groups.subList(i, endSignal + 1); + + if (isMessageConstLength(thisGroup)) + { + sb.append("e.").append(groupName).append("Length"); + } + else + { + sb.append("e.").append(groupName).append("ItemLengths"); + } + + count += 1; + + i = endSignal; + } + + for (int i = 0, size = varData.size(); i < size; ) + { + final Token varDataToken = varData.get(i); + if (varDataToken.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); + } + + if (count > 0) + { + sb.append(", "); + } + + sb.append("e.").append(formatPropertyName(varDataToken.name())).append("Length"); + + count += 1; + + i += varDataToken.componentTokenCount(); + } + + return sb.toString(); + } + + private CharSequence generateMessageLengthCallHelper(final List tokens) + { + int i = 0; + + final Token groupToken = tokens.get(i); + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + ++i; + final int groupHeaderTokenCount = tokens.get(i).componentTokenCount(); + i += groupHeaderTokenCount; + + final List fields = new ArrayList<>(); + i = collectFields(tokens, i, fields); + + final List groups = new ArrayList<>(); + i = collectGroups(tokens, i, groups); + + final List varData = new ArrayList<>(); + collectVarData(tokens, i, varData); + + return generateMessageLengthCallHelper(groups, varData); + } + + private CharSequence generateMessageLength( + final List groups, + final List varData, + final String indent, + final String className) + { + final StringBuilder sbEncode = new StringBuilder(); + final StringBuilder sbSkip = new StringBuilder(); + + for (int i = 0, size = groups.size(); i < size; i++) + { + final Token groupToken = groups.get(i); + + if (groupToken.signal() != Signal.BEGIN_GROUP) + { + throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken); + } + + final int endSignal = findEndSignal(groups, i, Signal.END_GROUP, groupToken.name()); + final List thisGroup = groups.subList(i, endSignal + 1); + + final Token numInGroupToken = Generators.findFirst("numInGroup", groups, i); + final long minCount = numInGroupToken.encoding().applicableMinValue().longValue(); + final long maxCount = numInGroupToken.encoding().applicableMaxValue().longValue(); + + final String countName = isMessageConstLength(thisGroup) ? + formatPropertyName(groupToken.name()) + "Length" : + "len(" + formatPropertyName(groupToken.name()) + "ItemLengths)"; + + final String minCheck = minCount > 0 ? countName + " < " + minCount + " || " : ""; + final String maxCheck = countName + " > " + maxCount; + + new Formatter(sbEncode).format("\n" + + indent + " length += m.%1$s().SbeHeaderSize()\n", + formatPropertyName(groupToken.name())); + + if (isMessageConstLength(thisGroup)) + { + addInclude("fmt"); + new Formatter(sbEncode).format( + indent + " if (%3$s%4$s) {\n" + + indent + " panic(fmt.Sprintf(\"%5$s outside of allowed range [E110]\"))\n" + + indent + " }\n" + + indent + " length += uint64(%1$sLength) * m.%1$s().SbeBlockLength()\n", + formatPropertyName(groupToken.name()), + formatClassName(groupToken.name()), + minCheck, + maxCheck, + countName); + } + else + { + new Formatter(sbEncode).format( + indent + " if (%3$s%4$s) {\n" + + indent + " panic(\"%5$s outside of allowed range [E110]\")\n" + + indent + " }\n\n" + + indent + " for _, e := range %1$sItemLengths {\n" + + indent + " l, err := m.%1$s().ComputeLength(%6$s)\n" + + indent + " if err != nil {\n" + + indent + " return 0, err\n" + + indent + " }\n" + + indent + " length += uint64(l)\n" + + indent + " }\n", + formatPropertyName(groupToken.name()), + formatClassName(groupToken.name()), + minCheck, + maxCheck, + countName, + generateMessageLengthCallHelper(thisGroup)); + } + + new Formatter(sbSkip).format( + indent + (" for %1$sGroup := m.%1$s(); %1$sGroup.HasNext(); {\n") + + indent + (" %1$sGroup.Next().Skip()\n") + + indent + (" }\n"), + formatPropertyName(groupToken.name())); + + i = endSignal; + } + for (int i = 0, size = varData.size(); i < size; ) + { + final Token varDataToken = varData.get(i); + + if (varDataToken.signal() != Signal.BEGIN_VAR_DATA) + { + throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken); + } + + final Token lengthToken = Generators.findFirst("length", varData, i); + + addInclude("fmt"); + new Formatter(sbEncode).format("\n" + + indent + " length += m.%1$sHeaderLength()\n" + + indent + " if m.%1$sLength() > %2$d {\n" + + indent + " return 0, fmt.Errorf(\"%1$sLength too long for length type [E109]\")\n" + + indent + " }\n" + + indent + " length += uint64(m.%1$sLength())\n", + formatPropertyName(varDataToken.name()), + lengthToken.encoding().applicableMaxValue().longValue()); + + new Formatter(sbSkip).format( + indent + " m.Skip%1$s()\n", + toUpperFirstChar(varDataToken.name())); + + i += varDataToken.componentTokenCount(); + } + + final StringBuilder sb = new StringBuilder(); + + new Formatter(sb).format("\n" + + indent + "func (m *%2$s) Skip() {\n" + + sbSkip + + indent + "}\n\n" + + + indent + "func (m *%2$s) IsConstLength() bool {\n" + + indent + " return " + (groups.isEmpty() && varData.isEmpty()) + "\n" + + indent + "}\n\n" + + + indent + "func (m *%2$s) ComputeLength(%1$s) (int, error) {\n" + + indent + " length := uint64(m.SbeBlockLength())\n" + + sbEncode + "\n" + + indent + " return int(length), nil\n" + + indent + "}\n", + generateMessageLengthArgs(groups, varData, indent + INDENT, false)[0], + className); + + return sb; + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightOutputManager.java new file mode 100644 index 0000000000..3b9e72b716 --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightOutputManager.java @@ -0,0 +1,72 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.golang.flyweight; + +import org.agrona.generation.OutputManager; +import org.agrona.Verify; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; + +import static java.io.File.separatorChar; + +/** + * {@link OutputManager} for managing the creation of golang source files as the target of code generation. + * The character encoding for the {@link java.io.Writer} is UTF-8. + */ +public class GolangFlyweightOutputManager implements OutputManager +{ + private final File outputDir; + + /** + * Create a new {@link OutputManager} for generating golang source files into a given package. + * + * @param baseDirName for the generated source code. + * @param namespaceName for the generated source code relative to the baseDirName. + */ + public GolangFlyweightOutputManager(final String baseDirName, final String namespaceName) + { + Verify.notNull(baseDirName, "baseDirName"); + Verify.notNull(namespaceName, "applicableNamespace"); + + final String dirName = baseDirName.endsWith("" + separatorChar) ? baseDirName : baseDirName + separatorChar; + final String packageDirName = dirName + namespaceName.replace('.', '_'); + + outputDir = new File(packageDirName); + if (!outputDir.exists() && !outputDir.mkdirs()) + { + throw new IllegalStateException("Unable to create directory: " + packageDirName); + } + } + + /** + * Create a new output which will be a golang source file in the given package. + *

      + * The {@link java.io.Writer} should be closed once the caller has finished with it. The Writer is + * buffered for efficient IO operations. + * + * @param name the name of the golang class. + * @return a {@link java.io.Writer} to which the source code should be written. + * @throws IOException if an issue occurs when creating the file. + */ + public Writer createOutput(final String name) throws IOException + { + final File targetFile = new File(outputDir, name + ".go"); + + return Files.newBufferedWriter(targetFile.toPath(), StandardCharsets.UTF_8); + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java new file mode 100644 index 0000000000..78ac285b6c --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java @@ -0,0 +1,224 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.golang.flyweight; + +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.SbeTool; +import uk.co.real_logic.sbe.ValidationUtil; + +import java.nio.ByteOrder; +import java.util.EnumMap; +import java.util.Map; + +import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; + +/** + * Utilities for mapping between IR and the Golang language. + */ +public class GolangFlyweightUtil +{ + private static final Map PRIMITIVE_TYPE_STRING_ENUM_MAP = new EnumMap<>(PrimitiveType.class); + private static final Map MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP = + new EnumMap<>(PrimitiveType.class); + + static + { + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.CHAR, "byte"); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.INT8, "int8"); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.INT16, "int16"); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.INT32, "int32"); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.INT64, "int64"); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.UINT8, "uint8"); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.UINT16, "uint16"); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.UINT32, "uint32"); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.UINT64, "uint64"); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.FLOAT, "float32"); + PRIMITIVE_TYPE_STRING_ENUM_MAP.put(PrimitiveType.DOUBLE, "float64"); + } + + static + { + MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.CHAR, "Bytes"); + MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.INT8, "Int8"); + MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.INT16, "Int16"); + MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.INT32, "Int32"); + MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.INT64, "Int64"); + MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.UINT8, "Uint8"); + MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.UINT16, "Uint16"); + MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.UINT32, "Uint32"); + MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.UINT64, "Uint64"); + MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.FLOAT, "Float32"); + MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP.put(PrimitiveType.DOUBLE, "Float64"); + } + + /** + * Map the name of a {@link uk.co.real_logic.sbe.PrimitiveType} to a Golang primitive type name. + * + * @param primitiveType to map. + * @return the name of the Java primitive that most closely maps. + */ + public static String goTypeName(final PrimitiveType primitiveType) + { + return PRIMITIVE_TYPE_STRING_ENUM_MAP.get(primitiveType); + } + + /** + * Format a String as a class name. + * + * @param value to be formatted. + * @return the string formatted as a class name. + */ + public static String formatClassName(final String value) + { + return toUpperFirstChar(value); + } + + /** + * Map the name of a {@link uk.co.real_logic.sbe.PrimitiveType} to a Golang marhsalling function name. + * + * @param primitiveType to map. + * @return the name of the Java primitive that most closely maps. + */ + public static String golangMarshalType(final PrimitiveType primitiveType) + { + return MARSHAL_TYPE_BY_PRIMITIVE_TYPE_MAP.get(primitiveType); + } + + /** + * Format a String as a property name. + * + * @param value to be formatted. + * @return the string formatted as a property name. + */ + public static String formatPropertyName(final String value) + { + String formattedValue = toUpperFirstChar(value); + + if (ValidationUtil.isGolangKeyword(formattedValue)) + { + final String keywordAppendToken = System.getProperty(SbeTool.KEYWORD_APPEND_TOKEN); + if (null == keywordAppendToken) + { + throw new IllegalStateException( + "Invalid property name='" + formattedValue + + "' please correct the schema or consider setting system property: " + + SbeTool.KEYWORD_APPEND_TOKEN); + } + + formattedValue += keywordAppendToken; + } + + return formattedValue; + } + + /** + * Generate a count of closing braces, one on each line. + * + * @param count of closing braces. + * @return A string with count of closing braces. + */ + public static String closingBraces(final int count) + { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < count; i++) + { + sb.append("}\n"); + } + + return sb.toString(); + } + + /** + * Return the Golang formatted byte order encoding string to use to read for a given byte order and primitiveType + * + * @param byteOrder of the {@link uk.co.real_logic.sbe.ir.Token} + * @param primitiveType of the {@link uk.co.real_logic.sbe.ir.Token} + * @return the string formatted as the byte ordering encoding + */ + public static String formatReadBytes(final ByteOrder byteOrder, final PrimitiveType primitiveType) + { + final String suffix = (byteOrder == ByteOrder.BIG_ENDIAN ? + "BigEndian" : "LittleEndian"); + + switch (primitiveType) + { + case CHAR: + return "Byte" + suffix; + case FLOAT: + return "Float" + suffix; + case DOUBLE: + return "Double" + suffix; + case INT8: + return "Int8" + suffix; + case INT16: + return "Int16" + suffix; + case INT32: + return "Int32" + suffix; + case INT64: + return "Int64" + suffix; + case UINT8: + return "Uint8" + suffix; + case UINT16: + return "Uint16" + suffix; + case UINT32: + return "Uint32" + suffix; + case UINT64: + return "Uint64" + suffix; + } + return ""; + } + + /** + * Return the Golang formatted byte order encoding string to use to write for a given byte order and primitiveType + * + * @param byteOrder of the {@link uk.co.real_logic.sbe.ir.Token} + * @param primitiveType of the {@link uk.co.real_logic.sbe.ir.Token} + * @return the string formatted as the byte ordering encoding + */ + public static String formatWriteBytes(final ByteOrder byteOrder, final PrimitiveType primitiveType) + { + final String suffix = (byteOrder == ByteOrder.BIG_ENDIAN ? + "BigEndian" : "LittleEndian"); + + switch (primitiveType) + { + case CHAR: + return "PutByte" + suffix; + case FLOAT: + return "PutFloat" + suffix; + case DOUBLE: + return "PutDouble" + suffix; + case INT8: + return "PutInt8" + suffix; + case INT16: + return "PutInt16" + suffix; + case INT32: + return "PutInt32" + suffix; + case INT64: + return "PutInt64" + suffix; + case UINT8: + return "PutUint8" + suffix; + case UINT16: + return "PutUint16" + suffix; + case UINT32: + return "PutUint32" + suffix; + case UINT64: + return "PutUint64" + suffix; + } + return ""; + } + +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java similarity index 99% rename from sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java rename to sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java index 1c1582380a..58c357951d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package uk.co.real_logic.sbe.generation.golang; +package uk.co.real_logic.sbe.generation.golang.struct; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.generation.CodeGenerator; @@ -37,7 +37,7 @@ import static uk.co.real_logic.sbe.PrimitiveType.CHAR; import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; -import static uk.co.real_logic.sbe.generation.golang.GolangUtil.*; +import static uk.co.real_logic.sbe.generation.golang.struct.GolangUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangOutputManager.java similarity index 98% rename from sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java rename to sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangOutputManager.java index 1675d69fed..a584396a09 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangOutputManager.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package uk.co.real_logic.sbe.generation.golang; +package uk.co.real_logic.sbe.generation.golang.struct; import org.agrona.generation.OutputManager; import org.agrona.Verify; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangUtil.java similarity index 98% rename from sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java rename to sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangUtil.java index 0aa379216b..2689da26de 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/GolangUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangUtil.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package uk.co.real_logic.sbe.generation.golang; +package uk.co.real_logic.sbe.generation.golang.struct; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.SbeTool; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangStructGeneratorTest.java similarity index 99% rename from sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java rename to sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangStructGeneratorTest.java index af647727f2..b4d6198680 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangStructGeneratorTest.java @@ -18,6 +18,7 @@ import org.agrona.generation.StringWriterOutputManager; import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.generation.golang.struct.GolangGenerator; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; @@ -28,7 +29,7 @@ import static org.junit.jupiter.api.Assertions.*; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -class GolangGeneratorTest +class GolangStructGeneratorTest { @Test @SuppressWarnings("MethodLength") From 44f225686b1afc22bbe1b8a6a7c47341c228c23d Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 29 Oct 2024 10:53:13 +0100 Subject: [PATCH 1251/1594] [CI] Attempt to fix Rust install. --- .github/workflows/ci.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bc6da223f..833df2a436 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -373,11 +373,8 @@ jobs: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Rust setup - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - override: true + uses: dtolnay/rust-toolchain@stable + toolchain: ${{ matrix.rust }} - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: From 354fb93a06318c3cade850ff265ba2b7d31b4a10 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 29 Oct 2024 10:56:42 +0100 Subject: [PATCH 1252/1594] Revert "[CI] Attempt to fix Rust install." This reverts commit 44f225686b1afc22bbe1b8a6a7c47341c228c23d. --- .github/workflows/ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 833df2a436..5bc6da223f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -373,8 +373,11 @@ jobs: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Rust setup - uses: dtolnay/rust-toolchain@stable - toolchain: ${{ matrix.rust }} + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + override: true - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: From ca86c353f44e2838b350b58f00fb543585c1f424 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 29 Oct 2024 10:57:00 +0100 Subject: [PATCH 1253/1594] Reapply "[CI] Attempt to fix Rust install." This reverts commit 354fb93a06318c3cade850ff265ba2b7d31b4a10. --- .github/workflows/ci.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bc6da223f..833df2a436 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -373,11 +373,8 @@ jobs: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Rust setup - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - override: true + uses: dtolnay/rust-toolchain@stable + toolchain: ${{ matrix.rust }} - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: From d4655418f0bf1f4a588c35a2267cc1b1914492f8 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 29 Oct 2024 11:06:03 +0100 Subject: [PATCH 1254/1594] [Java] Upgrade to Checkstyle 10.19.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e8889233da..d2692936f7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "1.23.1" -checkstyle = "10.18.2" +checkstyle = "10.19.0" junit = "5.11.3" jmh = "1.37" gradle = "8.10.2" From b7bd10409b05361462b57ad75abe835ac8b82e6d Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 29 Oct 2024 11:06:09 +0100 Subject: [PATCH 1255/1594] [Java] Upgrade to Shadow 8.3.4. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d2692936f7..a19bc056c9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,4 +16,4 @@ jmh-generator-annprocess = { group = "org.openjdk.jmh", name = "jmh-generator-an [plugins] versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } -shadow = { id = "com.gradleup.shadow", version = "8.3.3" } +shadow = { id = "com.gradleup.shadow", version = "8.3.4" } From 7a0ac0f63ed15982f14e66fa2c0afe2c7ff85a00 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 29 Oct 2024 12:45:03 +0100 Subject: [PATCH 1256/1594] [CI] Temporarily disable Rust toolchain installation. --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 833df2a436..f1e1f24e61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -372,9 +372,9 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - - name: Rust setup - uses: dtolnay/rust-toolchain@stable - toolchain: ${{ matrix.rust }} +# - name: Rust setup +# uses: dtolnay/rust-toolchain@stable +# toolchain: ${{ matrix.rust }} - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: From cd057964ad589f2c76c007b79065efdb73bbb8bd Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:56:58 +0100 Subject: [PATCH 1257/1594] Revert "[CI] Temporarily disable Rust toolchain installation." This reverts commit 7a0ac0f63ed15982f14e66fa2c0afe2c7ff85a00. --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f1e1f24e61..833df2a436 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -372,9 +372,9 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} -# - name: Rust setup -# uses: dtolnay/rust-toolchain@stable -# toolchain: ${{ matrix.rust }} + - name: Rust setup + uses: dtolnay/rust-toolchain@stable + toolchain: ${{ matrix.rust }} - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: From ae002c29a3378f2c184697465e73e256a96c9ac7 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:58:24 +0100 Subject: [PATCH 1258/1594] [CI] Fix invocation syntax. --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 833df2a436..23be3be93a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -374,7 +374,8 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Rust setup uses: dtolnay/rust-toolchain@stable - toolchain: ${{ matrix.rust }} + with: + toolchain: ${{ matrix.rust }} - name: Setup java 17 to run the Gradle script uses: actions/setup-java@v4 with: From 4d37f331baaf9ee3f7211c6857af3d21e04964e4 Mon Sep 17 00:00:00 2001 From: Nate Bradac <38217740+nbradac@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:59:28 -0500 Subject: [PATCH 1259/1594] [Java] DTOs respect the optional package field in the schema definition (#1022) * [Java] DTOs respect the optional package field in the schema definition * [Java] checkstyle --- .../generation/TargetCodeGeneratorLoader.java | 8 +- .../sbe/generation/cpp/CppDtoGenerator.java | 4 +- .../sbe/generation/java/JavaDtoGenerator.java | 85 ++++++++++++++++--- .../sbe/generation/java/JavaDtos.java | 7 +- .../sbe/properties/DtosPropertyTest.java | 2 +- .../generation/java/JavaGeneratorTest.java | 36 ++++++++ 6 files changed, 126 insertions(+), 16 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index 4edea4f8b4..c09152fabf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -52,6 +52,7 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) { final JavaOutputManager outputManager = new JavaOutputManager(outputDir, ir.applicableNamespace()); + final boolean shouldSupportTypesPackageNames = Boolean.getBoolean(TYPES_PACKAGE_OVERRIDE); final JavaGenerator codecGenerator = new JavaGenerator( ir, System.getProperty(JAVA_ENCODING_BUFFER_TYPE, JAVA_DEFAULT_ENCODING_BUFFER_TYPE), @@ -59,13 +60,16 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) Boolean.getBoolean(JAVA_GROUP_ORDER_ANNOTATION), Boolean.getBoolean(JAVA_GENERATE_INTERFACES), Boolean.getBoolean(DECODE_UNKNOWN_ENUM_VALUES), - Boolean.getBoolean(TYPES_PACKAGE_OVERRIDE), + shouldSupportTypesPackageNames, precedenceChecks(), outputManager); if (Boolean.getBoolean(JAVA_GENERATE_DTOS)) { - final JavaDtoGenerator dtoGenerator = new JavaDtoGenerator(ir, outputManager); + final JavaDtoGenerator dtoGenerator = new JavaDtoGenerator( + ir, + shouldSupportTypesPackageNames, + outputManager); return () -> { codecGenerator.generate(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index 39b59412e5..9c4064dbc9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -41,7 +41,7 @@ import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData; /** - * DTO generator for the CSharp programming language. + * DTO generator for the C++ programming language. */ public class CppDtoGenerator implements CodeGenerator { @@ -52,7 +52,7 @@ public class CppDtoGenerator implements CodeGenerator private final OutputManager outputManager; /** - * Create a new C# DTO {@link CodeGenerator}. + * Create a new C++ DTO {@link CodeGenerator}. * * @param ir for the messages and types. * @param outputManager for generating the DTOs to. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java index b922bd14ed..baf9f70342 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -24,12 +24,14 @@ import uk.co.real_logic.sbe.ir.Token; import org.agrona.LangUtil; import org.agrona.Verify; -import org.agrona.generation.OutputManager; +import org.agrona.generation.DynamicPackageOutputManager; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.function.Predicate; import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; @@ -49,16 +51,23 @@ public class JavaDtoGenerator implements CodeGenerator private static final String BASE_INDENT = ""; private final Ir ir; - private final OutputManager outputManager; + private final DynamicPackageOutputManager outputManager; + private final boolean shouldSupportTypesPackageNames; + private final Set packageNameByTypes = new HashSet<>(); /** - * Create a new C# DTO {@link CodeGenerator}. + * Create a new Java DTO {@link CodeGenerator}. * - * @param ir for the messages and types. - * @param outputManager for generating the DTOs to. + * @param ir for the messages and types. + * @param shouldSupportTypesPackageNames generator support for types in their own package. + * @param outputManager for generating the DTOs to. */ - public JavaDtoGenerator(final Ir ir, final OutputManager outputManager) + public JavaDtoGenerator( + final Ir ir, + final boolean shouldSupportTypesPackageNames, + final DynamicPackageOutputManager outputManager) { + this.shouldSupportTypesPackageNames = shouldSupportTypesPackageNames; Verify.notNull(ir, "ir"); Verify.notNull(outputManager, "outputManager"); @@ -66,6 +75,24 @@ public JavaDtoGenerator(final Ir ir, final OutputManager outputManager) this.outputManager = outputManager; } + /** + * Fetch the type's explicit package - if set and should be supported. + * + * @param token the 0-th token of the type. + * @param ir the intermediate representation. + * @return the overridden package name of the type if set and supported, or {@link Ir#applicableNamespace()}. + */ + private String fetchTypesPackageName(final Token token, final Ir ir) + { + if (shouldSupportTypesPackageNames && token.packageName() != null) + { + outputManager.setPackageName(token.packageName()); + return token.packageName(); + } + + return ir.applicableNamespace(); + } + /** * {@inheritDoc} */ @@ -110,9 +137,10 @@ public void generate() throws IOException generateDisplay(classBuilder, encoderClassName, "computeEncodedLength()", BASE_INDENT + INDENT); + final String packageName = fetchTypesPackageName(msgToken, ir); try (Writer out = outputManager.createOutput(dtoClassName)) { - out.append(generateDtoFileHeader(ir.applicableNamespace())); + out.append(generateDtoFileHeader(packageName)); out.append("import org.agrona.DirectBuffer;\n"); out.append("import org.agrona.MutableDirectBuffer;\n"); out.append("import org.agrona.concurrent.UnsafeBuffer;\n\n"); @@ -1582,6 +1610,19 @@ private static String formatDtoClassName(final String name) private void generateDtosForTypes() throws IOException { + if (shouldSupportTypesPackageNames) + { + for (final List tokens : ir.types()) + { + final String packageName = tokens.get(0).packageName(); + + if (packageName != null) + { + packageNameByTypes.add(packageName); + } + } + } + for (final List tokens : ir.types()) { switch (tokens.get(0).signal()) @@ -1607,10 +1648,11 @@ private void generateComposite(final List tokens) throws IOException final String encoderClassName = encoderName(name); final String decoderClassName = decoderName(name); + final String packageName = fetchTypesPackageName(tokens.get(0), ir); try (Writer out = outputManager.createOutput(className)) { final List compositeTokens = tokens.subList(1, tokens.size() - 1); - out.append(generateDtoFileHeader(ir.applicableNamespace())); + out.append(generateDtoFileHeader(packageName)); out.append("import org.agrona.DirectBuffer;\n"); out.append("import org.agrona.MutableDirectBuffer;\n"); out.append("import org.agrona.concurrent.UnsafeBuffer;\n\n"); @@ -1638,10 +1680,11 @@ private void generateChoiceSet(final List tokens) throws IOException final String encoderClassName = encoderName(name); final String decoderClassName = decoderName(name); + final String packageName = fetchTypesPackageName(tokens.get(0), ir); try (Writer out = outputManager.createOutput(className)) { final List setTokens = tokens.subList(1, tokens.size() - 1); - out.append(generateDtoFileHeader(ir.applicableNamespace())); + out.append(generateDtoFileHeader(packageName)); out.append(generateDocumentation(BASE_INDENT, tokens.get(0))); final ClassBuilder classBuilder = new ClassBuilder(className, BASE_INDENT, "public final"); @@ -1795,13 +1838,35 @@ private void generateCompositePropertyElements( } } - private static CharSequence generateDtoFileHeader(final String packageName) + private static StringBuilder generateImportStatements(final Set packages, final String currentPackage) + { + final StringBuilder importStatements = new StringBuilder(); + + for (final String candidatePackage : packages) + { + if (!candidatePackage.equals(currentPackage)) + { + importStatements.append("import ").append(candidatePackage).append(".*;\n"); + } + } + + if (!importStatements.isEmpty()) + { + importStatements.append("\n\n"); + } + + return importStatements; + } + + private CharSequence generateDtoFileHeader(final String packageName) { final StringBuilder sb = new StringBuilder(); sb.append("/* Generated SBE (Simple Binary Encoding) message DTO */\n"); sb.append("package ").append(packageName).append(";\n\n"); + sb.append(generateImportStatements(packageNameByTypes, packageName)); + return sb; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java index 45eeccff93..3d4dc61482 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java @@ -20,6 +20,8 @@ import uk.co.real_logic.sbe.generation.TargetCodeGenerator; import uk.co.real_logic.sbe.ir.Ir; +import static uk.co.real_logic.sbe.SbeTool.TYPES_PACKAGE_OVERRIDE; + /** * {@link CodeGenerator} factory for Java DTOs. */ @@ -30,6 +32,9 @@ public class JavaDtos implements TargetCodeGenerator */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { - return new JavaDtoGenerator(ir, new JavaOutputManager(outputDir, ir.applicableNamespace())); + return new JavaDtoGenerator( + ir, + Boolean.getBoolean(TYPES_PACKAGE_OVERRIDE), + new JavaOutputManager(outputDir, ir.applicableNamespace())); } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java index 8df61fe2b3..7cb1aa03a1 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java @@ -87,7 +87,7 @@ void javaDtoEncodeShouldBeTheInverseOfDtoDecode( outputManager) .generate(); - new JavaDtoGenerator(encodedMessage.ir(), outputManager) + new JavaDtoGenerator(encodedMessage.ir(), false, outputManager) .generate(); } catch (final Exception generationException) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index e93a7c1eba..68679c15a1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -601,6 +601,42 @@ void shouldCreateTypesInSamePackageIfSupportDisabled() throws Exception } } + @Test + void dtosShouldReferenceTypesInDifferentPackages() throws Exception + { + try (InputStream in = Tests.getLocalResource("explicit-package-test-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + ir = irg.generate(schema); + + outputManager.clear(); + outputManager.setPackageName(ir.applicableNamespace()); + + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, true, outputManager + ); + generator.generate(); + + final JavaDtoGenerator javaDtoGenerator = new JavaDtoGenerator(ir, true, outputManager); + javaDtoGenerator.generate(); + + final Map sources = outputManager.getSources(); + assertNotNull(sources.get("test.message.schema.TestMessageDto")); + assertNotNull(sources.get("test.message.schema.MessageHeaderDto")); + assertNotNull(sources.get("test.message.schema.common.CarDto")); + assertNotNull(sources.get("test.message.schema.common.EngineDto")); + assertNotNull(sources.get("outside.schema.FuelSpecDto")); + assertNotNull(sources.get("outside.schema.DaysDto")); + assertNotNull(sources.get("outside.schema.FuelTypeDto")); + + assertNotNull(compile("test.message.schema.TestMessageDto")); + assertNotNull(compile("test.message.schema.common.CarDto")); + assertNotNull(compile("outside.schema.FuelSpecDto")); + } + } + @ParameterizedTest @CsvSource( { From 879e1ef61c384f1fef9d8434f6d46b2e9de7e6a9 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 6 Nov 2024 14:11:20 +0000 Subject: [PATCH 1260/1594] [CI] Update actions dependencies. --- .github/workflows/slow.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index e67cd05af7..a6700d95b2 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -33,7 +33,7 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - name: Setup java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ matrix.java }} @@ -56,7 +56,7 @@ jobs: - name: Run property tests run: ./gradlew propertyTest - name: Upload test results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: success() || failure() with: name: property-tests From 2f85ccb38b4074ba3d20f8f9869516c77367d962 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:33:39 -0500 Subject: [PATCH 1261/1594] [Java] Upgrade to Shadow 8.3.5. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a19bc056c9..26cd83b807 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,4 +16,4 @@ jmh-generator-annprocess = { group = "org.openjdk.jmh", name = "jmh-generator-an [plugins] versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } -shadow = { id = "com.gradleup.shadow", version = "8.3.4" } +shadow = { id = "com.gradleup.shadow", version = "8.3.5" } From 5ce95bca021e88af58b4c4b48baa698d2caf206d Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:35:57 -0500 Subject: [PATCH 1262/1594] [Java] Upgrade to Checkstyle 1.20.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 26cd83b807..c41a71d0e6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "1.23.1" -checkstyle = "10.19.0" +checkstyle = "10.20.1" junit = "5.11.3" jmh = "1.37" gradle = "8.10.2" From 018664bdf62e61996ad446422e24f5785d4172b8 Mon Sep 17 00:00:00 2001 From: Dan Shearer Date: Fri, 8 Nov 2024 15:23:57 +0000 Subject: [PATCH 1263/1594] 1.33.2 release --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 6214e03b71..80c8c0bd36 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.34.0-SNAPSHOT +1.33.2 From 4484457a485a789cf75071529bf5b7c875a31164 Mon Sep 17 00:00:00 2001 From: Dan Shearer Date: Fri, 8 Nov 2024 15:24:38 +0000 Subject: [PATCH 1264/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 80c8c0bd36..6214e03b71 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.33.2 +1.34.0-SNAPSHOT From 320850d938dfdfa578ea9e67703d0bbd3594d742 Mon Sep 17 00:00:00 2001 From: Elvis Wang Date: Wed, 13 Nov 2024 18:47:48 +0800 Subject: [PATCH 1265/1594] [Rust] Enhance enum supporting fromstr and display and into (#1020) * [Rust] impl FromStr for generated enum items * [Rust] impl Display for generate enum items * [Rust] impl Into for generated enum items * [Rust] reformat code according to checkstyle failure report * [Rust] split code in generateEnum to adress CI checkstyle method too log failure * [Rust] reformat code according to checkstyle failure * [Rust] fix CodeQL warning by removing unused argument * [Rust] fix CodeQL warning by removing unused argument --- rust/tests/baseline_enum_from_str.rs | 21 +++++ rust/tests/baseline_enum_into.rs | 14 +++ rust/tests/baseline_enum_to_str.rs | 14 +++ .../sbe/generation/rust/RustGenerator.java | 88 +++++++++++++++++++ 4 files changed, 137 insertions(+) create mode 100644 rust/tests/baseline_enum_from_str.rs create mode 100644 rust/tests/baseline_enum_into.rs create mode 100644 rust/tests/baseline_enum_to_str.rs diff --git a/rust/tests/baseline_enum_from_str.rs b/rust/tests/baseline_enum_from_str.rs new file mode 100644 index 0000000000..4e52fd4bf9 --- /dev/null +++ b/rust/tests/baseline_enum_from_str.rs @@ -0,0 +1,21 @@ +use examples_baseline::{ + boost_type::BoostType, +}; + +#[test] +fn test_boost_type_from_str() -> Result<(), ()> { + assert_eq!("TURBO".parse::()?, BoostType::TURBO, "Parse \"TURBO\" as BoostType"); + assert_eq!("SUPERCHARGER".parse::()?, BoostType::SUPERCHARGER, "Parse \"SUPERCHARGER\" as BoostType"); + assert_eq!("NITROUS".parse::()?, BoostType::NITROUS, "Parse \"NITROUS\" as BoostType"); + assert_eq!("KERS".parse::()?, BoostType::KERS, "Parse \"KERS\" as BoostType"); + + assert_eq!("Turbo".parse::()?, BoostType::NullVal, "Parse \"Turbo\" as BoostType"); + assert_eq!("Supercharger".parse::()?, BoostType::NullVal, "Parse \"Supercharger\" as BoostType"); + assert_eq!("Nitrous".parse::()?, BoostType::NullVal, "Parse \"Nitrous\" as BoostType"); + assert_eq!("Kers".parse::()?, BoostType::NullVal, "Parse \"Kers\" as BoostType"); + + assert_eq!("AA".parse::()?, BoostType::NullVal, "Parse \"AA\" as BoostType"); + assert_eq!("".parse::().unwrap(), BoostType::NullVal, "Parse \"\" as BoostType"); + + Ok(()) +} diff --git a/rust/tests/baseline_enum_into.rs b/rust/tests/baseline_enum_into.rs new file mode 100644 index 0000000000..9580e51b0d --- /dev/null +++ b/rust/tests/baseline_enum_into.rs @@ -0,0 +1,14 @@ +use examples_baseline::{ + boost_type::BoostType, +}; + +#[test] +fn test_boost_type_from_str() -> Result<(), ()> { + assert_eq!(>::into(BoostType::TURBO), 84_u8, "BoostType::TURBO into value"); + assert_eq!(>::into(BoostType::SUPERCHARGER), 83_u8, "BoostType::SUPERCHARGER into value"); + assert_eq!(>::into(BoostType::NITROUS), 78_u8, "BoostType::NITROUS into value"); + assert_eq!(>::into(BoostType::KERS), 75_u8, "BoostType::KERS into value"); + assert_eq!(>::into(BoostType::NullVal), 0_u8, "BoostType::NullVal into value"); + + Ok(()) +} diff --git a/rust/tests/baseline_enum_to_str.rs b/rust/tests/baseline_enum_to_str.rs new file mode 100644 index 0000000000..93f5206517 --- /dev/null +++ b/rust/tests/baseline_enum_to_str.rs @@ -0,0 +1,14 @@ +use examples_baseline::{ + boost_type::BoostType, +}; + +#[test] +fn test_boost_type_from_str() -> Result<(), ()> { + assert_eq!(format!("{}", BoostType::TURBO), "TURBO", "Display \"TURBO\""); + assert_eq!(format!("{}", BoostType::SUPERCHARGER), "SUPERCHARGER", "Display \"SUPERCHARGER\""); + assert_eq!(format!("{}", BoostType::NITROUS), "NITROUS", "Display \"NITROUS\""); + assert_eq!(format!("{}", BoostType::KERS), "KERS", "Display \"KERS\""); + assert_eq!(format!("{}", BoostType::NullVal), "NullVal", "Display \"NullVal\""); + + Ok(()) +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 5ed04fc9fb..7c2a492ce4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1266,6 +1266,24 @@ private static void generateEnum( indent(writer, 0, "}\n"); // From impl + generateFromImplForEnum(enumRustName, primitiveType, messageBody, writer); + + // Into impl + generateIntoImplForEnum(enumRustName, primitiveType, messageBody, writer); + + // FromStr impl + generateFromStrImplForEnum(enumRustName, primitiveType, messageBody, writer); + + // Display impl + generateDisplayImplForEnum(enumRustName, primitiveType, messageBody, writer); + } + + private static void generateFromImplForEnum( + final String enumRustName, + final String primitiveType, + final List messageBody, + final Appendable writer) throws IOException + { indent(writer, 0, "impl From<%s> for %s {\n", primitiveType, enumRustName); indent(writer, 1, "#[inline]\n"); indent(writer, 1, "fn from(v: %s) -> Self {\n", primitiveType); @@ -1285,6 +1303,76 @@ private static void generateEnum( indent(writer, 0, "}\n"); } + private static void generateIntoImplForEnum( + final String enumRustName, + final String primitiveType, + final List messageBody, + final Appendable writer) throws IOException + { + indent(writer, 0, "impl Into<%s> for %s {\n", primitiveType, enumRustName); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn into(self) -> %s {\n", primitiveType); + indent(writer, 2, "match self {\n"); + for (final Token token : messageBody) + { + final Encoding encoding = token.encoding(); + final String literal = generateRustLiteral(encoding.primitiveType(), encoding.constValue().toString()); + indent(writer, 3, "Self::%s => %s, \n", token.name(), literal); + } + { + final Encoding encoding = messageBody.get(0).encoding(); + final CharSequence nullVal = generateRustLiteral(encoding.primitiveType(), + encoding.applicableNullValue().toString()); + indent(writer, 3, "Self::NullVal => %s,\n", nullVal); + } + indent(writer, 2, "}\n"); + indent(writer, 1, "}\n"); + indent(writer, 0, "}\n"); + } + + private static void generateFromStrImplForEnum( + final String enumRustName, + final String primitiveType, + final List messageBody, + final Appendable writer) throws IOException + { + indent(writer, 0, "impl core::str::FromStr for %s {\n", enumRustName); + indent(writer, 1, "type Err = ();\n\n"); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn from_str(v: &str) -> core::result::Result {\n"); + indent(writer, 2, "match v {\n"); + for (final Token token : messageBody) + { + indent(writer, 3, "\"%1$s\" => core::result::Result::Ok(Self::%1$s), \n", token.name()); + } + // default => NullVal + indent(writer, 3, "_ => core::result::Result::Ok(Self::NullVal),\n"); + indent(writer, 2, "}\n"); + indent(writer, 1, "}\n"); + indent(writer, 0, "}\n"); + } + + private static void generateDisplayImplForEnum( + final String enumRustName, + final String primitiveType, + final List messageBody, + final Appendable writer) throws IOException + { + indent(writer, 0, "impl core::fmt::Display for %s {\n", enumRustName); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n"); + indent(writer, 2, "match self {\n"); + for (final Token token : messageBody) + { + indent(writer, 3, "Self::%1$s => write!(f, \"%1$s\"), \n", token.name()); + } + // default => Err + indent(writer, 3, "Self::NullVal => write!(f, \"NullVal\"),\n"); + indent(writer, 2, "}\n"); + indent(writer, 1, "}\n"); + indent(writer, 0, "}\n"); + } + private static void generateComposites( final String schemaVersionType, final Ir ir, From d38b4bf87717a381992e7c27d999e9eccfc999df Mon Sep 17 00:00:00 2001 From: Elvis Wang Date: Wed, 13 Nov 2024 18:48:24 +0800 Subject: [PATCH 1266/1594] [Rust] generate message schema level info in lib.rs (#1019) * [Rust] generate message schema level info in lib.rs 1. add `SBE_SCHEMA_ID` 2. add `SBE_SCHEMA_VERSION` 3. add `SBE_SEMANTIC_VERSION` * [Rust] use pub use instead of duplicated defines for message schema items in message codec * [Rust] add tests for issue #1018 --- rust/tests/baseline_test.rs | 7 +++++++ .../real_logic/sbe/generation/rust/LibRsDef.java | 16 +++++++++++++++- .../sbe/generation/rust/RustGenerator.java | 15 +++++++-------- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/rust/tests/baseline_test.rs b/rust/tests/baseline_test.rs index ab9eecb1fd..ab711b7c84 100644 --- a/rust/tests/baseline_test.rs +++ b/rust/tests/baseline_test.rs @@ -266,3 +266,10 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { let limit = car.get_limit(); Ok((limit, buffer)) } + +#[test] +fn test_issue_1018() { + assert_eq!(1, examples_baseline::SBE_SCHEMA_ID); + assert_eq!(0, examples_baseline::SBE_SCHEMA_VERSION); + assert_eq!("5.2", examples_baseline::SBE_SEMANTIC_VERSION); +} \ No newline at end of file diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index ad8a62c23e..f62aebe2d0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.stream.Stream; +import uk.co.real_logic.sbe.ir.Ir; import static java.nio.ByteOrder.LITTLE_ENDIAN; import static uk.co.real_logic.sbe.generation.rust.RustGenerator.*; @@ -54,7 +55,7 @@ class LibRsDef this.schemaVersionType = schemaVersionType; } - void generate() throws IOException + void generate(final Ir ir) throws IOException { try (Writer libRs = outputManager.createOutput("lib")) { @@ -84,6 +85,8 @@ void generate() throws IOException } indent(libRs, 0, "\n"); + generateSbeSchemaConsts(libRs, ir); + generateSbeErrorEnum(libRs); generateEitherEnum(libRs); @@ -123,6 +126,17 @@ static void generateDecoderTraits(final String schemaVersionType, final Writer w indent(writer, 0, "}\n\n"); } + static void generateSbeSchemaConsts(final Writer writer, final Ir ir) throws IOException + { + final String schemaIdType = rustTypeName(ir.headerStructure().schemaIdType()); + final String schemaVersionType = rustTypeName(ir.headerStructure().schemaVersionType()); + final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); + + indent(writer, 0, "pub const SBE_SCHEMA_ID: %s = %d;\n", schemaIdType, ir.id()); + indent(writer, 0, "pub const SBE_SCHEMA_VERSION: %s = %d;\n", schemaVersionType, ir.version()); + indent(writer, 0, "pub const SBE_SEMANTIC_VERSION: &str = \"%s\";\n\n", semanticVersion); + } + static void generateSbeErrorEnum(final Writer writer) throws IOException { indent(writer, 0, "pub type SbeResult = core::result::Result;\n\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 7c2a492ce4..29fd0da752 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -159,23 +159,22 @@ public void generate() throws IOException indent(out, 0, "use crate::*;\n\n"); indent(out, 0, "pub use decoder::%sDecoder;\n", formatStructName(msgToken.name())); indent(out, 0, "pub use encoder::%sEncoder;\n\n", formatStructName(msgToken.name())); + + indent(out, 0, "pub use crate::SBE_SCHEMA_ID;\n"); + indent(out, 0, "pub use crate::SBE_SCHEMA_VERSION;\n"); + indent(out, 0, "pub use crate::SBE_SEMANTIC_VERSION;\n\n"); + final String blockLengthType = blockLengthType(); final String templateIdType = rustTypeName(ir.headerStructure().templateIdType()); - final String schemaIdType = rustTypeName(ir.headerStructure().schemaIdType()); - final String schemaVersionType = schemaVersionType(); - final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); indent(out, 0, "pub const SBE_BLOCK_LENGTH: %s = %d;\n", blockLengthType, msgToken.encodedLength()); - indent(out, 0, "pub const SBE_TEMPLATE_ID: %s = %d;\n", templateIdType, msgToken.id()); - indent(out, 0, "pub const SBE_SCHEMA_ID: %s = %d;\n", schemaIdType, ir.id()); - indent(out, 0, "pub const SBE_SCHEMA_VERSION: %s = %d;\n", schemaVersionType, ir.version()); - indent(out, 0, "pub const SBE_SEMANTIC_VERSION: &str = \"%s\";\n\n", semanticVersion); + indent(out, 0, "pub const SBE_TEMPLATE_ID: %s = %d;\n\n", templateIdType, msgToken.id()); MessageCoderDef.generateEncoder(ir, out, msgToken, fields, groups, varData); MessageCoderDef.generateDecoder(ir, out, msgToken, fields, groups, varData); } } - libRsDef.generate(); + libRsDef.generate(ir); } String blockLengthType() From b385e9c794a2e6b1d28f3b335df893af272b0a67 Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Wed, 13 Nov 2024 12:53:45 -0600 Subject: [PATCH 1267/1594] [C++] respect the package override option for C++ codecs and DTOs --- .../generation/TargetCodeGeneratorLoader.java | 12 ++- .../sbe/generation/cpp/CppDtoGenerator.java | 95 +++++++++++++--- .../sbe/generation/cpp/CppDtos.java | 2 +- .../sbe/generation/cpp/CppGenerator.java | 101 +++++++++++++++--- .../main/java/uk/co/real_logic/sbe/ir/Ir.java | 28 +++-- .../sbe/properties/DtosPropertyTest.java | 2 +- .../sbe/generation/cpp/CppGeneratorTest.java | 42 ++++++++ .../csharp/CSharpGeneratorTest.java | 81 ++++++++++++++ 8 files changed, 322 insertions(+), 41 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index c09152fabf..c979bede45 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -107,13 +107,21 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) final NamespaceOutputManager outputManager = new NamespaceOutputManager( outputDir, ir.applicableNamespace()); final boolean decodeUnknownEnumValues = Boolean.getBoolean(DECODE_UNKNOWN_ENUM_VALUES); + final boolean shouldSupportTypesPackageNames = Boolean.getBoolean(TYPES_PACKAGE_OVERRIDE); - final CodeGenerator codecGenerator = new CppGenerator(ir, decodeUnknownEnumValues, precedenceChecks(), + final CodeGenerator codecGenerator = new CppGenerator( + ir, + decodeUnknownEnumValues, + precedenceChecks(), + shouldSupportTypesPackageNames, outputManager); if (Boolean.getBoolean(CPP_GENERATE_DTOS)) { - final CodeGenerator dtoGenerator = new CppDtoGenerator(ir, outputManager); + final CodeGenerator dtoGenerator = new CppDtoGenerator( + ir, + shouldSupportTypesPackageNames, + outputManager); return () -> { codecGenerator.generate(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index 9c4064dbc9..b6f337a837 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -50,27 +50,65 @@ public class CppDtoGenerator implements CodeGenerator private final Ir ir; private final OutputManager outputManager; + private final boolean shouldSupportTypesPackageNames; + private final Map namespaceByType = new HashMap<>(); /** * Create a new C++ DTO {@link CodeGenerator}. * - * @param ir for the messages and types. - * @param outputManager for generating the DTOs to. + * @param ir for the messages and types. + * @param shouldSupportTypesPackageNames generator support for types in their own package. + * @param outputManager for generating the DTOs to. */ - public CppDtoGenerator(final Ir ir, final OutputManager outputManager) + public CppDtoGenerator( + final Ir ir, + final boolean shouldSupportTypesPackageNames, + final OutputManager outputManager) { Verify.notNull(ir, "ir"); Verify.notNull(outputManager, "outputManager"); this.ir = ir; + this.shouldSupportTypesPackageNames = shouldSupportTypesPackageNames; this.outputManager = outputManager; } + private String[] fetchTypesPackageName(final Token token, final Ir ir) + { + if (!shouldSupportTypesPackageNames) + { + return ir.namespaces(); + } + + if (token.packageName() != null) + { + return Ir.getNamespaces(token.packageName()); + } + + return ir.namespaces(); + } + /** * {@inheritDoc} */ public void generate() throws IOException { + namespaceByType.clear(); + + if (shouldSupportTypesPackageNames) + { + for (final List tokens : ir.types()) + { + final Token token = tokens.get(0); + final String packageName = token.packageName(); + + if (packageName != null) + { + namespaceByType.put(token.applicableTypeName(), packageName); + } + } + } + generateDtosForTypes(); for (final List tokens : ir.messages()) @@ -116,13 +154,14 @@ public void generate() throws IOException final Set referencedTypes = generateTypesToIncludes(beginTypeTokensInSchema); referencedTypes.add(codecClassName); + final String[] namespaces = fetchTypesPackageName(msgToken, ir); out.append(generateDtoFileHeader( - ir.namespaces(), + namespaces, className, referencedTypes)); out.append(generateDocumentation(BASE_INDENT, msgToken)); classBuilder.appendTo(out); - out.append(CppUtil.closingBraces(ir.namespaces().length)); + out.append(CppUtil.closingBraces(namespaces.length)); out.append("#endif\n"); } } @@ -1732,7 +1771,8 @@ private void generateDtosForTypes() throws IOException private void generateComposite(final List tokens) throws IOException { - final String name = tokens.get(0).applicableTypeName(); + final Token token = tokens.get(0); + final String name = token.applicableTypeName(); final String className = formatDtoClassName(name); final String codecClassName = formatClassName(name); @@ -1741,8 +1781,9 @@ private void generateComposite(final List tokens) throws IOException final List compositeTokens = tokens.subList(1, tokens.size() - 1); final Set referencedTypes = generateTypesToIncludes(compositeTokens); referencedTypes.add(codecClassName); - out.append(generateDtoFileHeader(ir.namespaces(), className, referencedTypes)); - out.append(generateDocumentation(BASE_INDENT, tokens.get(0))); + final String[] namespaces = fetchTypesPackageName(token, ir); + out.append(generateDtoFileHeader(namespaces, className, referencedTypes)); + out.append(generateDocumentation(BASE_INDENT, token)); final ClassBuilder classBuilder = new ClassBuilder(className, BASE_INDENT); @@ -1754,14 +1795,15 @@ private void generateComposite(final List tokens) throws IOException codecClassName + "::sbeSchemaVersion()", BASE_INDENT + INDENT); classBuilder.appendTo(out); - out.append(CppUtil.closingBraces(ir.namespaces().length)); + out.append(CppUtil.closingBraces(namespaces.length)); out.append("#endif\n"); } } private void generateChoiceSet(final List tokens) throws IOException { - final String name = tokens.get(0).applicableTypeName(); + final Token token = tokens.get(0); + final String name = token.applicableTypeName(); final String className = formatDtoClassName(name); final String codecClassName = formatClassName(name); @@ -1770,7 +1812,8 @@ private void generateChoiceSet(final List tokens) throws IOException final List setTokens = tokens.subList(1, tokens.size() - 1); final Set referencedTypes = generateTypesToIncludes(setTokens); referencedTypes.add(codecClassName); - out.append(generateDtoFileHeader(ir.namespaces(), className, referencedTypes)); + final String[] namespaces = fetchTypesPackageName(token, ir); + out.append(generateDtoFileHeader(namespaces, className, referencedTypes)); out.append(generateDocumentation(BASE_INDENT, tokens.get(0))); final ClassBuilder classBuilder = new ClassBuilder(className, BASE_INDENT); @@ -1780,7 +1823,7 @@ private void generateChoiceSet(final List tokens) throws IOException generateChoiceSetEncodeWith(classBuilder, className, codecClassName, setTokens, BASE_INDENT + INDENT); classBuilder.appendTo(out); - out.append(CppUtil.closingBraces(ir.namespaces().length)); + out.append(CppUtil.closingBraces(namespaces.length)); out.append("#endif\n"); } } @@ -1965,7 +2008,7 @@ private static CharSequence typeWithFieldOptionality( } } - private static CharSequence generateDtoFileHeader( + private CharSequence generateDtoFileHeader( final CharSequence[] namespaces, final String className, final Collection typesToInclude) @@ -2010,6 +2053,32 @@ private static CharSequence generateDtoFileHeader( sb.append(String.join(" {\nnamespace ", namespaces)); sb.append(" {\n\n"); + if (shouldSupportTypesPackageNames && typesToInclude != null && !typesToInclude.isEmpty()) + { + final Set namespacesToUse = namespaceByType + .entrySet() + .stream() + .filter(e -> typesToInclude.contains(e.getKey())) + .map(Map.Entry::getValue) + .collect(Collectors.toSet()); + + // remove the current namespace + namespacesToUse.remove(String.join(".", namespaces)); + + for (final String namespace : namespacesToUse) + { + sb + .append("using namespace ") + .append(namespace.replaceAll("\\.", "::")) + .append(";\n"); + } + + if (!namespacesToUse.isEmpty()) + { + sb.append("\n"); + } + } + return sb; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java index 09dbfb052f..6e59b6dd06 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java @@ -31,6 +31,6 @@ public class CppDtos implements TargetCodeGenerator */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { - return new CppDtoGenerator(ir, new NamespaceOutputManager(outputDir, ir.applicableNamespace())); + return new CppDtoGenerator(ir, false, new NamespaceOutputManager(outputDir, ir.applicableNamespace())); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index cc6921a0bb..8533a4df84 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -33,6 +33,7 @@ import java.io.Writer; import java.nio.ByteOrder; import java.util.*; +import java.util.stream.Collectors; import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; @@ -58,6 +59,8 @@ public class CppGenerator implements CodeGenerator private final boolean shouldDecodeUnknownEnumValues; private final PrecedenceChecks precedenceChecks; private final String precedenceChecksFlagName; + private final boolean shouldSupportTypesPackageNames; + private final Map namespaceByType = new HashMap<>(); /** * Create a new Cpp language {@link CodeGenerator}. @@ -72,6 +75,7 @@ public CppGenerator(final Ir ir, final boolean shouldDecodeUnknownEnumValues, fi ir, shouldDecodeUnknownEnumValues, PrecedenceChecks.newInstance(new PrecedenceChecks.Context()), + false, outputManager ); } @@ -79,15 +83,17 @@ public CppGenerator(final Ir ir, final boolean shouldDecodeUnknownEnumValues, fi /** * Create a new Go language {@link CodeGenerator}. * - * @param ir for the messages and types. - * @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding. - * @param precedenceChecks whether and how to generate field precedence checks. - * @param outputManager for generating the codecs to. + * @param ir for the messages and types. + * @param shouldDecodeUnknownEnumValues generate support for unknown enum values when decoding. + * @param precedenceChecks whether and how to generate field precedence checks. + * @param shouldSupportTypesPackageNames generator support for types in their own package. + * @param outputManager for generating the codecs to. */ public CppGenerator( final Ir ir, final boolean shouldDecodeUnknownEnumValues, final PrecedenceChecks precedenceChecks, + final boolean shouldSupportTypesPackageNames, final OutputManager outputManager) { Verify.notNull(ir, "ir"); @@ -97,6 +103,7 @@ public CppGenerator( this.shouldDecodeUnknownEnumValues = shouldDecodeUnknownEnumValues; this.precedenceChecks = precedenceChecks; this.precedenceChecksFlagName = precedenceChecks.context().precedenceChecksFlagName(); + this.shouldSupportTypesPackageNames = shouldSupportTypesPackageNames; this.outputManager = outputManager; } @@ -140,6 +147,21 @@ private List generateTypeStubs() throws IOException return typesToInclude; } + private String[] fetchTypesPackageName(final Token token, final Ir ir) + { + if (!shouldSupportTypesPackageNames) + { + return ir.namespaces(); + } + + if (token.packageName() != null) + { + return Ir.getNamespaces(token.packageName()); + } + + return ir.namespaces(); + } + private List generateTypesToIncludes(final List tokens) { final List typesToInclude = new ArrayList<>(); @@ -167,6 +189,22 @@ private List generateTypesToIncludes(final List tokens) */ public void generate() throws IOException { + namespaceByType.clear(); + + if (shouldSupportTypesPackageNames) + { + for (final List tokens : ir.types()) + { + final Token token = tokens.get(0); + final String packageName = token.packageName(); + + if (packageName != null) + { + namespaceByType.put(token.applicableTypeName(), packageName); + } + } + } + generateMessageHeaderStub(); final List typesToInclude = generateTypeStubs(); @@ -192,7 +230,8 @@ public void generate() throws IOException final List varData = new ArrayList<>(); collectVarData(messageBody, i, varData); - out.append(generateFileHeader(ir.namespaces(), className, typesToInclude)); + final String[] namespaces = fetchTypesPackageName(msgToken, ir); + out.append(generateFileHeader(namespaces, className, typesToInclude)); out.append(generateClassDeclaration(className)); out.append(generateMessageFlyweightCode(className, msgToken, fieldPrecedenceModel)); out.append(generateFullyEncodedCheck(fieldPrecedenceModel)); @@ -205,7 +244,7 @@ public void generate() throws IOException sb.append(generateMessageLength(groups, varData, BASE_INDENT)); sb.append("};\n"); generateLookupTableDefinitions(sb, className, fieldPrecedenceModel); - sb.append(CppUtil.closingBraces(ir.namespaces().length)).append("#endif\n"); + sb.append(CppUtil.closingBraces(namespaces.length)).append("#endif\n"); out.append(sb); } } @@ -1277,7 +1316,8 @@ private void generateChoiceSet(final List tokens) throws IOException try (Writer out = outputManager.createOutput(bitSetName)) { - out.append(generateFileHeader(ir.namespaces(), bitSetName, null)); + final String[] namespaces = fetchTypesPackageName(token, ir); + out.append(generateFileHeader(namespaces, bitSetName, null)); out.append(generateClassDeclaration(bitSetName)); out.append(generateFixedFlyweightCode(bitSetName, token.encodedLength())); @@ -1322,7 +1362,7 @@ private void generateChoiceSet(final List tokens) throws IOException out.append(generateChoices(bitSetName, tokens.subList(1, tokens.size() - 1))); out.append(generateChoicesDisplay(bitSetName, tokens.subList(1, tokens.size() - 1))); out.append("};\n"); - out.append(CppUtil.closingBraces(ir.namespaces().length)).append("#endif\n"); + out.append(CppUtil.closingBraces(namespaces.length)).append("#endif\n"); } } @@ -1333,7 +1373,8 @@ private void generateEnum(final List tokens) throws IOException try (Writer out = outputManager.createOutput(enumName)) { - out.append(generateEnumFileHeader(ir.namespaces(), enumName)); + final String[] namespaces = fetchTypesPackageName(enumToken, ir); + out.append(generateEnumFileHeader(namespaces, enumName)); out.append(generateEnumDeclaration(enumName)); out.append(generateEnumValues(tokens.subList(1, tokens.size() - 1), enumToken)); @@ -1343,29 +1384,31 @@ private void generateEnum(final List tokens) throws IOException out.append(generateEnumDisplay(tokens.subList(1, tokens.size() - 1), enumToken)); out.append("};\n\n"); - out.append(CppUtil.closingBraces(ir.namespaces().length)).append("\n#endif\n"); + out.append(CppUtil.closingBraces(namespaces.length)).append("\n#endif\n"); } } private void generateComposite(final List tokens) throws IOException { - final String compositeName = formatClassName(tokens.get(0).applicableTypeName()); + final Token token = tokens.get(0); + final String compositeName = formatClassName(token.applicableTypeName()); try (Writer out = outputManager.createOutput(compositeName)) { - out.append(generateFileHeader(ir.namespaces(), compositeName, + final String[] namespaces = fetchTypesPackageName(token, ir); + out.append(generateFileHeader(namespaces, compositeName, generateTypesToIncludes(tokens.subList(1, tokens.size() - 1)))); out.append(generateClassDeclaration(compositeName)); - out.append(generateFixedFlyweightCode(compositeName, tokens.get(0).encodedLength())); + out.append(generateFixedFlyweightCode(compositeName, token.encodedLength())); out.append(generateCompositePropertyElements( compositeName, tokens.subList(1, tokens.size() - 1), BASE_INDENT)); out.append(generateCompositeDisplay( - tokens.get(0).applicableTypeName(), tokens.subList(1, tokens.size() - 1))); + token.applicableTypeName(), tokens.subList(1, tokens.size() - 1))); out.append("};\n\n"); - out.append(CppUtil.closingBraces(ir.namespaces().length)).append("\n#endif\n"); + out.append(CppUtil.closingBraces(namespaces.length)).append("\n#endif\n"); } } @@ -1614,7 +1657,7 @@ private static CharSequence generateTypeFieldNotPresentCondition(final int since sinceVersion); } - private static CharSequence generateFileHeader( + private CharSequence generateFileHeader( final CharSequence[] namespaces, final String className, final List typesToInclude) @@ -1720,6 +1763,32 @@ private static CharSequence generateFileHeader( sb.append(String.join(" {\nnamespace ", namespaces)); sb.append(" {\n\n"); + if (shouldSupportTypesPackageNames && typesToInclude != null && !typesToInclude.isEmpty()) + { + final Set namespacesToUse = namespaceByType + .entrySet() + .stream() + .filter(e -> typesToInclude.contains(e.getKey())) + .map(Map.Entry::getValue) + .collect(Collectors.toSet()); + + // remove the current namespace + namespacesToUse.remove(String.join(".", namespaces)); + + for (final String namespace : namespacesToUse) + { + sb + .append("using namespace ") + .append(namespace.replaceAll("\\.", "::")) + .append(";\n"); + } + + if (!namespacesToUse.isEmpty()) + { + sb.append("\n"); + } + } + return sb; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java index 3587a8a05f..87eba20050 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java @@ -79,14 +79,7 @@ public Ir( captureTypes(headerTokens, 0, headerTokens.size() - 1); - if ("true".equals(System.getProperty(SbeTool.CPP_NAMESPACES_COLLAPSE))) - { - this.namespaces = new String[]{ (namespaceName == null ? packageName : namespaceName).replace(".", "_") }; - } - else - { - this.namespaces = Pattern.compile("\\.").split(namespaceName == null ? packageName : namespaceName); - } + this.namespaces = Ir.getNamespaces(namespaceName == null ? packageName : namespaceName); } /** @@ -280,6 +273,25 @@ else if (signal.name().startsWith("END_")) } } + /** + * Construct an array of namespace strings based on the supplied namespaceName, + * accounting for the CPP_NAMESPACES_COLLAPSE option. + * + * @param namespaceName a namespace name that may contain period-separated nested namespaces + * @return an array of nested namespace strings + */ + public static String[] getNamespaces(final String namespaceName) + { + if ("true".equals(System.getProperty(SbeTool.CPP_NAMESPACES_COLLAPSE))) + { + return new String[]{ namespaceName.replace(".", "_") }; + } + else + { + return Pattern.compile("\\.").split(namespaceName); + } + } + private void captureTypes(final List tokens, final int beginIndex, final int endIndex) { for (int i = beginIndex; i <= endIndex; i++) diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java index 7cb1aa03a1..8517894340 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java @@ -214,7 +214,7 @@ void cppDtoEncodeShouldBeTheInverseOfDtoDecode( { new CppGenerator(encodedMessage.ir(), true, outputManager) .generate(); - new CppDtoGenerator(encodedMessage.ir(), outputManager) + new CppDtoGenerator(encodedMessage.ir(), false, outputManager) .generate(); } catch (final Exception generationException) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index 8b3575e0ab..b8c969c8b8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -18,6 +18,7 @@ import org.agrona.generation.StringWriterOutputManager; import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.generation.common.PrecedenceChecks; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; @@ -28,6 +29,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; class CppGeneratorTest @@ -72,4 +74,44 @@ void shouldUseConstexprWhenInitializingSemanticVersion() throws Exception assertThat(source, containsString("static constexpr const char* SBE_SEMANTIC_VERSION = \"5.2\"")); } } + + @Test + void dtosShouldReferenceTypesInDifferentPackages() throws Exception + { + try (InputStream in = Tests.getLocalResource("explicit-package-test-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + + final CppGenerator generator = new CppGenerator( + ir, + false, + PrecedenceChecks.newInstance(new PrecedenceChecks.Context()), + true, + outputManager); + generator.generate(); + + final CppDtoGenerator dtoGenerator = new CppDtoGenerator(ir, true, outputManager); + dtoGenerator.generate(); + + final java.util.Map sources = outputManager.getSources(); + assertNotNull(sources.get("test.message.schema.TestMessageDto")); + assertNotNull(sources.get("test.message.schema.MessageHeaderDto")); + assertNotNull(sources.get("test.message.schema.CarDto")); + assertNotNull(sources.get("test.message.schema.EngineDto")); + + String source; + + source = sources.get("test.message.schema.TestMessageDto").toString(); + assertThat(source, containsString("using namespace outside::schema;")); + + source = sources.get("test.message.schema.TestMessage").toString(); + assertThat(source, containsString("using namespace outside::schema;")); + assertThat(source, containsString("using namespace test::message::schema::common;")); + } + } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java new file mode 100644 index 0000000000..3cc8fc3635 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2013-2024 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.csharp; + +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.io.InputStream; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +class CSharpGeneratorTest +{ + @Test + void dtosShouldReferenceTypesInDifferentPackages() throws Exception + { + try (InputStream in = Tests.getLocalResource("explicit-package-test-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + + final CSharpGenerator generator = new CSharpGenerator(ir, outputManager); + generator.generate(); + + final CSharpDtoGenerator dtoGenerator = new CSharpDtoGenerator(ir, outputManager); + dtoGenerator.generate(); + + final java.util.Map sources = outputManager.getSources(); + /* + sources.forEach((s, cs) -> + { + System.out.println("----------------"); + System.out.println("FILE :: " + s); + System.out.println("----------------"); + System.out.println(cs); + System.out.println("----------------"); + }); + */ + + assertNotNull(sources.get("test.message.schema.TestMessageDto")); + assertNotNull(sources.get("test.message.schema.MessageHeaderDto")); + //assertNotNull(sources.get("test.message.schema.common.CarDto")); + //assertNotNull(sources.get("test.message.schema.common.EngineDto")); + assertNotNull(sources.get("test.message.schema.CarDto")); + assertNotNull(sources.get("test.message.schema.EngineDto")); + + /* + assertNotNull(sources.get("outside.schema.FuelSpecDto")); + assertNotNull(sources.get("outside.schema.DaysDto")); + assertNotNull(sources.get("outside.schema.FuelTypeDto")); + + assertNotNull(compile("test.message.schema.TestMessageDto")); + assertNotNull(compile("test.message.schema.common.CarDto")); + assertNotNull(compile("outside.schema.FuelSpecDto")); + */ + } + } +} From 4a31cc0b18f95b4de8b340010aa0b0d093459607 Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Wed, 13 Nov 2024 18:21:45 -0600 Subject: [PATCH 1268/1594] [C#] respect the package override option for C# codecs and DTOs --- .../sbe/generation/csharp/CSharp.java | 10 +++- .../generation/csharp/CSharpDtoGenerator.java | 52 ++++++++++++++-- .../sbe/generation/csharp/CSharpDtos.java | 2 +- .../generation/csharp/CSharpGenerator.java | 60 +++++++++++++++---- .../sbe/generation/csharp/CSharpUtil.java | 25 +++++++- .../sbe/properties/DtosPropertyTest.java | 2 +- .../csharp/CSharpGeneratorTest.java | 38 +++++------- 7 files changed, 146 insertions(+), 43 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java index 8a88cbce56..f13b9cfab6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java @@ -21,6 +21,8 @@ import uk.co.real_logic.sbe.generation.TargetCodeGeneratorLoader; import uk.co.real_logic.sbe.ir.Ir; +import static uk.co.real_logic.sbe.SbeTool.TYPES_PACKAGE_OVERRIDE; + /** * {@link CodeGenerator} factory for the CSharp target programming language. */ @@ -33,15 +35,19 @@ public class CSharp implements TargetCodeGenerator */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { + final boolean shouldSupportTypesPackageNames = Boolean.getBoolean(TYPES_PACKAGE_OVERRIDE); final CSharpGenerator flyweightGenerator = new CSharpGenerator( ir, TargetCodeGeneratorLoader.precedenceChecks(), + shouldSupportTypesPackageNames, new CSharpNamespaceOutputManager(outputDir, ir.applicableNamespace())); if (GENERATE_DTOS) { - final CSharpDtoGenerator dtoGenerator = - new CSharpDtoGenerator(ir, new CSharpNamespaceOutputManager(outputDir, ir.applicableNamespace())); + final CSharpDtoGenerator dtoGenerator = new CSharpDtoGenerator( + ir, + shouldSupportTypesPackageNames, + new CSharpNamespaceOutputManager(outputDir, ir.applicableNamespace())); return () -> { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java index ad2e3068c7..b5225caa67 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -30,7 +30,9 @@ import java.io.IOException; import java.io.Writer; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.function.Predicate; import static uk.co.real_logic.sbe.generation.csharp.CSharpUtil.*; @@ -49,27 +51,65 @@ public class CSharpDtoGenerator implements CodeGenerator private final Ir ir; private final OutputManager outputManager; + private final boolean shouldSupportTypesPackageNames; + private final Set packageNameByTypes = new HashSet<>(); /** * Create a new C# DTO {@link CodeGenerator}. * * @param ir for the messages and types. + * @param shouldSupportTypesPackageNames generator support for types in their own package. * @param outputManager for generating the DTOs to. */ - public CSharpDtoGenerator(final Ir ir, final OutputManager outputManager) + public CSharpDtoGenerator( + final Ir ir, + final boolean shouldSupportTypesPackageNames, + final OutputManager outputManager) { Verify.notNull(ir, "ir"); Verify.notNull(outputManager, "outputManager"); this.ir = ir; + this.shouldSupportTypesPackageNames = shouldSupportTypesPackageNames; this.outputManager = outputManager; } + private String fetchTypesPackageName(final Token token, final Ir ir) + { + if (!shouldSupportTypesPackageNames) + { + return ir.applicableNamespace(); + } + + if (token.packageName() != null) + { + return token.packageName(); + } + + return ir.applicableNamespace(); + } + /** * {@inheritDoc} */ public void generate() throws IOException { + packageNameByTypes.clear(); + + if (shouldSupportTypesPackageNames) + { + for (final List tokens : ir.types()) + { + final Token token = tokens.get(0); + final String packageName = token.packageName(); + + if (packageName != null) + { + packageNameByTypes.add(packageName); + } + } + } + generateDtosForTypes(); for (final List tokens : ir.messages()) @@ -110,7 +150,8 @@ public void generate() throws IOException try (Writer out = outputManager.createOutput(dtoClassName)) { out.append(generateFileHeader( - ir.applicableNamespace(), + fetchTypesPackageName(msgToken, ir), + packageNameByTypes, "#nullable enable\n\n", "using System.Collections.Generic;\n", "using System.Linq;\n")); @@ -1360,13 +1401,16 @@ private void generateDtosForTypes() throws IOException private void generateComposite(final List tokens) throws IOException { - final String name = tokens.get(0).applicableTypeName(); + final Token token = tokens.get(0); + final String name = token.applicableTypeName(); final String className = formatDtoClassName(name); final String codecClassName = formatClassName(name); try (Writer out = outputManager.createOutput(className)) { - out.append(generateFileHeader(ir.applicableNamespace(), + out.append(generateFileHeader( + fetchTypesPackageName(token, ir), + packageNameByTypes, "#nullable enable\n", "using System.Collections.Generic;\n", "using System.Linq;\n")); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java index 4fc0cc513f..d924e45b53 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java @@ -30,6 +30,6 @@ public class CSharpDtos implements TargetCodeGenerator */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { - return new CSharpDtoGenerator(ir, new CSharpNamespaceOutputManager(outputDir, ir.applicableNamespace())); + return new CSharpDtoGenerator(ir, false, new CSharpNamespaceOutputManager(outputDir, ir.applicableNamespace())); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 8c06689da8..af9979879a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -60,6 +60,8 @@ public class CSharpGenerator implements CodeGenerator private final OutputManager outputManager; private final PrecedenceChecks precedenceChecks; private final String precedenceChecksFlagName; + private final boolean shouldSupportTypesPackageNames; + private final Set packageNameByTypes = new HashSet<>(); /** * Create a new C# language {@link CodeGenerator}. @@ -72,6 +74,7 @@ public CSharpGenerator(final Ir ir, final OutputManager outputManager) this( ir, PrecedenceChecks.newInstance(new PrecedenceChecks.Context()), + false, outputManager ); } @@ -79,13 +82,15 @@ public CSharpGenerator(final Ir ir, final OutputManager outputManager) /** * Create a new C# language {@link CodeGenerator}. * - * @param ir for the messages and types. - * @param precedenceChecks whether and how to perform field precedence checks. - * @param outputManager for generating the codecs to. + * @param ir for the messages and types. + * @param precedenceChecks whether and how to perform field precedence checks. + * @param shouldSupportTypesPackageNames generator support for types in their own package. + * @param outputManager for generating the codecs to. */ public CSharpGenerator( final Ir ir, final PrecedenceChecks precedenceChecks, + final boolean shouldSupportTypesPackageNames, final OutputManager outputManager) { Verify.notNull(ir, "ir"); @@ -94,6 +99,7 @@ public CSharpGenerator( this.ir = ir; this.precedenceChecks = precedenceChecks; this.precedenceChecksFlagName = precedenceChecks.context().precedenceChecksFlagName(); + this.shouldSupportTypesPackageNames = shouldSupportTypesPackageNames; this.outputManager = outputManager; } @@ -138,11 +144,42 @@ public void generateTypeStubs() throws IOException } } + private String fetchTypesPackageName(final Token token, final Ir ir) + { + if (!shouldSupportTypesPackageNames) + { + return ir.applicableNamespace(); + } + + if (token.packageName() != null) + { + return token.packageName(); + } + + return ir.applicableNamespace(); + } + /** * {@inheritDoc} */ public void generate() throws IOException { + packageNameByTypes.clear(); + + if (shouldSupportTypesPackageNames) + { + for (final List tokens : ir.types()) + { + final Token token = tokens.get(0); + final String packageName = token.packageName(); + + if (packageName != null) + { + packageNameByTypes.add(packageName); + } + } + } + generateMessageHeaderStub(); generateTypeStubs(); @@ -164,7 +201,7 @@ public void generate() throws IOException final List varData = new ArrayList<>(); collectVarData(messageBody, offset, varData); - out.append(generateFileHeader(ir.applicableNamespace())); + out.append(generateFileHeader(fetchTypesPackageName(msgToken, ir), packageNameByTypes)); out.append(generateDocumentation(BASE_INDENT, msgToken)); out.append(generateClassDeclaration(className)); out.append(generateMessageFlyweightCode(className, msgToken, fieldPrecedenceModel, BASE_INDENT)); @@ -662,7 +699,7 @@ private void generateBitSet(final List tokens) throws IOException try (Writer out = outputManager.createOutput(enumName)) { - out.append(generateFileHeader(ir.applicableNamespace())); + out.append(generateFileHeader(fetchTypesPackageName(enumToken, ir), packageNameByTypes)); out.append(generateDocumentation(INDENT, enumToken)); final String enumPrimitiveType = cSharpTypeName(enumToken.encoding().primitiveType()); out.append(generateEnumDeclaration(enumName, enumPrimitiveType, true)); @@ -682,7 +719,7 @@ private void generateEnum(final List tokens) throws IOException try (Writer out = outputManager.createOutput(enumName)) { - out.append(generateFileHeader(ir.applicableNamespace())); + out.append(generateFileHeader(fetchTypesPackageName(enumToken, ir), packageNameByTypes)); out.append(generateDocumentation(INDENT, enumToken)); final String enumPrimitiveType = cSharpTypeName(enumToken.encoding().primitiveType()); out.append(generateEnumDeclaration(enumName, enumPrimitiveType, false)); @@ -696,14 +733,15 @@ private void generateEnum(final List tokens) throws IOException private void generateComposite(final List tokens) throws IOException { - final String compositeName = CSharpUtil.formatClassName(tokens.get(0).applicableTypeName()); + final Token token = tokens.get(0); + final String compositeName = CSharpUtil.formatClassName(token.applicableTypeName()); try (Writer out = outputManager.createOutput(compositeName)) { - out.append(generateFileHeader(ir.applicableNamespace())); - out.append(generateDocumentation(INDENT, tokens.get(0))); + out.append(generateFileHeader(fetchTypesPackageName(token, ir), packageNameByTypes)); + out.append(generateDocumentation(INDENT, token)); out.append(generateClassDeclaration(compositeName)); - out.append(generateFixedFlyweightCode(tokens.get(0).encodedLength())); + out.append(generateFixedFlyweightCode(token.encodedLength())); out.append(generateCompositePropertyElements(tokens.subList(1, tokens.size() - 1), BASE_INDENT)); out.append(generateCompositeDisplay(tokens)); @@ -798,7 +836,7 @@ private void generateMetaAttributeEnum() throws IOException { try (Writer out = outputManager.createOutput(META_ATTRIBUTE_ENUM)) { - out.append(generateFileHeader(ir.applicableNamespace())); + out.append(generateFileHeader(ir.applicableNamespace(), null)); out.append( INDENT + "public enum MetaAttribute\n" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index 31c4444feb..a80ae7a295 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -24,6 +24,7 @@ import java.util.EnumMap; import java.util.Map; +import java.util.Set; /** * Utilities for mapping between IR and the C# language. @@ -87,8 +88,26 @@ static String generateLiteral(final PrimitiveType type, final String value) return literal; } - static CharSequence generateFileHeader(final String packageName, final String... topLevelStatements) + static CharSequence generateFileHeader( + final String packageName, + final Set packageNamesByTypes, + final String... topLevelStatements) { + final StringBuilder additionalUsingBuilder = new StringBuilder(); + if (packageNamesByTypes != null && !packageNamesByTypes.isEmpty()) + { + packageNamesByTypes + .stream() + .filter(p -> !packageName.equals(p)) + .forEach(p -> + additionalUsingBuilder + .append("using ") + .append(formatNamespace(p)) + .append(";\n")); + + additionalUsingBuilder.append("\n"); + } + return String.format( "// \n" + "// Generated SBE (Simple Binary Encoding) message codec\n" + @@ -98,9 +117,11 @@ static CharSequence generateFileHeader(final String packageName, final String... "using System;\n" + "using System.Text;\n" + "using Org.SbeTool.Sbe.Dll;\n\n" + - "namespace %2$s\n" + + "%2$s" + + "namespace %3$s\n" + "{\n", String.join("", topLevelStatements), + additionalUsingBuilder, formatNamespace(packageName)); } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java index 8517894340..a8341e578c 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java @@ -152,7 +152,7 @@ void csharpDtoEncodeShouldBeTheInverseOfDtoDecode( { new CSharpGenerator(encodedMessage.ir(), outputManager) .generate(); - new CSharpDtoGenerator(encodedMessage.ir(), outputManager) + new CSharpDtoGenerator(encodedMessage.ir(), false, outputManager) .generate(); } catch (final Exception generationException) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java index 3cc8fc3635..295ddd293b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java @@ -18,6 +18,7 @@ import org.agrona.generation.StringWriterOutputManager; import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.generation.common.PrecedenceChecks; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; @@ -25,6 +26,8 @@ import java.io.InputStream; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; @@ -42,40 +45,31 @@ void dtosShouldReferenceTypesInDifferentPackages() throws Exception final StringWriterOutputManager outputManager = new StringWriterOutputManager(); outputManager.setPackageName(ir.applicableNamespace()); - final CSharpGenerator generator = new CSharpGenerator(ir, outputManager); + final CSharpGenerator generator = new CSharpGenerator( + ir, + PrecedenceChecks.newInstance(new PrecedenceChecks.Context()), + true, + outputManager); generator.generate(); - final CSharpDtoGenerator dtoGenerator = new CSharpDtoGenerator(ir, outputManager); + final CSharpDtoGenerator dtoGenerator = new CSharpDtoGenerator(ir, true, outputManager); dtoGenerator.generate(); final java.util.Map sources = outputManager.getSources(); - /* - sources.forEach((s, cs) -> - { - System.out.println("----------------"); - System.out.println("FILE :: " + s); - System.out.println("----------------"); - System.out.println(cs); - System.out.println("----------------"); - }); - */ assertNotNull(sources.get("test.message.schema.TestMessageDto")); assertNotNull(sources.get("test.message.schema.MessageHeaderDto")); - //assertNotNull(sources.get("test.message.schema.common.CarDto")); - //assertNotNull(sources.get("test.message.schema.common.EngineDto")); assertNotNull(sources.get("test.message.schema.CarDto")); assertNotNull(sources.get("test.message.schema.EngineDto")); - /* - assertNotNull(sources.get("outside.schema.FuelSpecDto")); - assertNotNull(sources.get("outside.schema.DaysDto")); - assertNotNull(sources.get("outside.schema.FuelTypeDto")); + String source; - assertNotNull(compile("test.message.schema.TestMessageDto")); - assertNotNull(compile("test.message.schema.common.CarDto")); - assertNotNull(compile("outside.schema.FuelSpecDto")); - */ + source = sources.get("test.message.schema.TestMessageDto").toString(); + assertThat(source, containsString("using Outside.Schema;")); + + source = sources.get("test.message.schema.TestMessage").toString(); + assertThat(source, containsString("using Outside.Schema;")); + assertThat(source, containsString("using Test.Message.Schema.Common;")); } } } From ea52edd5aa63ddd6a70498a22331551bfb4e65b1 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Fri, 15 Nov 2024 15:38:43 +0000 Subject: [PATCH 1269/1594] [C#] Test package override support compiles. Co-authored-by: Nate Bradac We've updated the C# generation tasks to include a schema that uses explicit package names on `types` blocks. We found processing this schema produces some build errors (albeit not affecting the exit code): ``` > Task :generateCSharpTestCodecs [Error] explicit-package-test-schema.xml:17:49: cvc-complex-type.3.2.2: Attribute 'package' is not allowed to appear in element 'types'. [Error] explicit-package-test-schema.xml:30:37: cvc-complex-type.3.2.2: Attribute 'package' is not allowed to appear in element 'types'. > Task :generateCSharpTestDtos [Error] explicit-package-test-schema.xml:17:49: cvc-complex-type.3.2.2: Attribute 'package' is not allowed to appear in element 'types'. [Error] explicit-package-test-schema.xml:30:37: cvc-complex-type.3.2.2: Attribute 'package' is not allowed to appear in element 'types'. ``` Therefore, we've put the new generation under tasks that don't validate against an XSD. We considered creating a new version of the XSD that properly describes what we support; however, the licence on the XSD seems prohibitive. --- .gitignore | 1 + build.gradle | 33 +++++++++++++++++-- .../sbe/generation/csharp/CSharpDtos.java | 9 ++++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 4e46271843..fd7d72201b 100644 --- a/.gitignore +++ b/.gitignore @@ -94,6 +94,7 @@ csharp/sbe-generated/since-deprecated csharp/sbe-generated/order_check csharp/sbe-generated/mktdata/*.cs csharp/sbe-generated/uk_co_real_logic_sbe_benchmarks_fix +csharp/sbe-generated/test_message_schema csharp/sbe-tests/*.sbe csharp/nuget/ csharp/csharp.sln.DotSettings.user diff --git a/build.gradle b/build.gradle index 40bbbbef9c..9641c9972f 100644 --- a/build.gradle +++ b/build.gradle @@ -894,7 +894,8 @@ tasks.register('generateCSharpTestCodecs', JavaExec) { 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharp', 'sbe.xinclude.aware': 'true', 'sbe.validation.xsd': validationXsdPath, - 'sbe.generate.precedence.checks': 'true') + 'sbe.generate.precedence.checks': 'true', + 'sbe.types.package.override': 'true') args = ['sbe-tool/src/test/resources/FixBinary.xml', 'sbe-tool/src/test/resources/issue435.xml', 'sbe-tool/src/test/resources/issue483.xml', @@ -912,15 +913,41 @@ tasks.register('generateCSharpTestDtos', JavaExec) { 'sbe.output.dir': 'csharp/sbe-generated', 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharpDtos', 'sbe.xinclude.aware': 'true', - 'sbe.validation.xsd': validationXsdPath) + 'sbe.validation.xsd': validationXsdPath, + 'sbe.types.package.override': 'true') args = ['sbe-samples/src/main/resources/example-extension-schema.xml'] } +tasks.register('generateCSharpExplicitPackageOverrideCodecs', JavaExec) { + mainClass.set('uk.co.real_logic.sbe.SbeTool') + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'csharp/sbe-generated', + 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharp', + 'sbe.xinclude.aware': 'true', + 'sbe.generate.precedence.checks': 'true', + 'sbe.types.package.override': 'true') + args = ['sbe-tool/src/test/resources/explicit-package-test-schema.xml'] +} + +tasks.register('generateCSharpExplicitPackageOverrideDtos', JavaExec) { + mainClass.set('uk.co.real_logic.sbe.SbeTool') + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + systemProperties( + 'sbe.output.dir': 'csharp/sbe-generated', + 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharpDtos', + 'sbe.xinclude.aware': 'true', + 'sbe.types.package.override': 'true') + args = ['sbe-tool/src/test/resources/explicit-package-test-schema.xml'] +} + tasks.register('generateCSharpCodecs') { description = 'Generate csharp codecs' dependsOn 'generateCSharpTestCodecs', 'generateCSharpTestDtos', - 'generateCSharpCodecsWithXIncludes' + 'generateCSharpCodecsWithXIncludes', + 'generateCSharpExplicitPackageOverrideCodecs', + 'generateCSharpExplicitPackageOverrideDtos' } tasks.register('generateJavaIrCodecs', JavaExec) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java index d924e45b53..118b8e8d45 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java @@ -20,6 +20,8 @@ import uk.co.real_logic.sbe.generation.TargetCodeGenerator; import uk.co.real_logic.sbe.ir.Ir; +import static uk.co.real_logic.sbe.SbeTool.TYPES_PACKAGE_OVERRIDE; + /** * {@link CodeGenerator} factory for CSharp DTOs. */ @@ -30,6 +32,11 @@ public class CSharpDtos implements TargetCodeGenerator */ public CodeGenerator newInstance(final Ir ir, final String outputDir) { - return new CSharpDtoGenerator(ir, false, new CSharpNamespaceOutputManager(outputDir, ir.applicableNamespace())); + final boolean shouldSupportTypesPackageNames = Boolean.getBoolean(TYPES_PACKAGE_OVERRIDE); + return new CSharpDtoGenerator( + ir, + shouldSupportTypesPackageNames, + new CSharpNamespaceOutputManager(outputDir, ir.applicableNamespace()) + ); } } From 8596f68decddda4783a592540ad9afc38eaf3069 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:05:30 +0100 Subject: [PATCH 1270/1594] [Java] Upgrade to jqwik 1.9.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c41a71d0e6..6e026b7e16 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ gradle = "8.10.2" agrona = { group = "org.agrona", name = "agrona", version = { strictly = "[1.23.1, 2.0[", require = "1.23.1" } } mockito = { group = "org.mockito", name = "mockito-core", version = "5.14.2" } hamcrest = { group = "org.hamcrest", name = "hamcrest", version = "3.0" } -jqwik = { group = "net.jqwik", name = "jqwik", version = "1.9.0" } +jqwik = { group = "net.jqwik", name = "jqwik", version = "1.9.1" } json = { group = "org.json", name = "json", version = "20240303" } jmh-core = { group = "org.openjdk.jmh", name = "jmh-core", version.ref = "jmh" } jmh-generator-annprocess = { group = "org.openjdk.jmh", name = "jmh-generator-annprocess", version.ref = "jmh" } From b8c7056e96d208a17b4a2756814293b4b63a686b Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:06:31 +0100 Subject: [PATCH 1271/1594] [Java] Upgrade to Gradle 8.11. --- gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6e026b7e16..e0417abadb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ agrona = "1.23.1" checkstyle = "10.20.1" junit = "5.11.3" jmh = "1.37" -gradle = "8.10.2" +gradle = "8.11" [libraries] agrona = { group = "org.agrona", name = "agrona", version = { strictly = "[1.23.1, 2.0[", require = "1.23.1" } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 79eb9d003f..7cf748e743 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 7079133f0e0a7e547b5ce4ed777b393327329fb3 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 26 Nov 2024 10:25:45 +0100 Subject: [PATCH 1272/1594] [Java] Upgrade to Gradle 8.11.1. --- gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e0417abadb..a21be421a2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ agrona = "1.23.1" checkstyle = "10.20.1" junit = "5.11.3" jmh = "1.37" -gradle = "8.11" +gradle = "8.11.1" [libraries] agrona = { group = "org.agrona", name = "agrona", version = { strictly = "[1.23.1, 2.0[", require = "1.23.1" } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7cf748e743..c1d5e01859 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 8af808ca64779bf722e196fa04e29a4180bad845 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 27 Nov 2024 13:07:37 +0000 Subject: [PATCH 1273/1594] [Java] Preserve byte order throughout IR transformations. Previously, the IrDecoder looked at the message header's BEGIN_COMPOSITE token to determine byte order; however, IrEncoder does not write the schema's byte order on tokens like these. Now, the IrDecoder finds the first real ENCODING token and reads the byte order from that. --- .../uk/co/real_logic/sbe/ir/IrDecoder.java | 11 ++++++- .../sbe/ir/BasicXmlIrGenerationTest.java | 30 ++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index b7da2ead1c..4db9e04a99 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -126,7 +126,16 @@ public Ir decode() i = captureHeader(tokens); } - final ByteOrder byteOrder = !tokens.isEmpty() ? tokens.get(0).encoding().byteOrder() : null; + ByteOrder byteOrder = null; + for (int j = 0; j < tokens.size(); j++) + { + if (tokens.get(j).signal() == Signal.ENCODING) + { + byteOrder = tokens.get(j).encoding().byteOrder(); + break; + } + } + final Ir ir = new Ir( irPackageName, irNamespaceName, irId, irVersion, null, semanticVersion, byteOrder, irHeader); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index 7f89f2e18d..f3509f7d97 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -13,15 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package uk.co.real_logic.sbe.ir; -import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; +import org.junit.jupiter.api.Test; import java.io.InputStream; +import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.List; @@ -308,4 +310,30 @@ void shouldGenerateIrForMessageWithVariableLengthFieldWithEmbeddedLength() throw assertThat(tokens.get(dataEncIdx).encoding().primitiveType(), is(PrimitiveType.CHAR)); } } + + @Test + void shouldRegenerateIrWithSameByteOrder() throws Exception + { + try (InputStream in = getLocalResource("example-bigendian-test-schema.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final IrGenerator generator = new IrGenerator(); + final Ir firstIr = generator.generate(schema); + final ByteBuffer firstIrOutputBuffer = ByteBuffer.allocate(8 * 1024); + + final int length; + try (IrEncoder firstIrEncoder = new IrEncoder(firstIrOutputBuffer, firstIr)) + { + length = firstIrEncoder.encode(); + } + + final Ir secondIr; + try (IrDecoder firstIrDecoder = new IrDecoder(firstIrOutputBuffer.slice(0, length))) + { + secondIr = firstIrDecoder.decode(); + } + + assertThat(secondIr.byteOrder(), is(firstIr.byteOrder())); + } + } } From 4547fe6edd6d23d13248e006678288d0e8c8425b Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Thu, 28 Nov 2024 14:13:44 -0600 Subject: [PATCH 1274/1594] [Rust] codegen of primitive enums now implement 'From' instead of 'Into' (#1029) * [Rust] updated LibRsDef.generate() to add "#![allow(clippy::all)]" * [Rust] generating 'From for PRIMITIVE' instead of 'Into for ENUM' to satisfy 'from_over_into' lint * [Rust] removed unused method parameter * fixed formatting --------- Co-authored-by: Michael Ward --- .../sbe/generation/rust/LibRsDef.java | 2 +- .../sbe/generation/rust/RustGenerator.java | 27 ++++++++++--------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index f62aebe2d0..46897829cd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -60,7 +60,7 @@ void generate(final Ir ir) throws IOException try (Writer libRs = outputManager.createOutput("lib")) { indent(libRs, 0, "#![forbid(unsafe_code)]\n"); - indent(libRs, 0, "#![allow(clippy::upper_case_acronyms)]\n"); + indent(libRs, 0, "#![allow(clippy::all)]\n"); indent(libRs, 0, "#![allow(non_camel_case_types)]\n\n"); indent(libRs, 0, "#![allow(ambiguous_glob_reexports)]\n\n"); indent(libRs, 0, "use ::core::{convert::TryInto};\n\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 29fd0da752..0c03766553 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1265,19 +1265,19 @@ private static void generateEnum( indent(writer, 0, "}\n"); // From impl - generateFromImplForEnum(enumRustName, primitiveType, messageBody, writer); + generateFromPrimitiveForEnum(enumRustName, primitiveType, messageBody, writer); // Into impl - generateIntoImplForEnum(enumRustName, primitiveType, messageBody, writer); + generateFromEnumForPrimitive(enumRustName, primitiveType, messageBody, writer); // FromStr impl - generateFromStrImplForEnum(enumRustName, primitiveType, messageBody, writer); + generateFromStrImplForEnum(enumRustName, messageBody, writer); // Display impl generateDisplayImplForEnum(enumRustName, primitiveType, messageBody, writer); } - private static void generateFromImplForEnum( + private static void generateFromPrimitiveForEnum( final String enumRustName, final String primitiveType, final List messageBody, @@ -1302,27 +1302,29 @@ private static void generateFromImplForEnum( indent(writer, 0, "}\n"); } - private static void generateIntoImplForEnum( + private static void generateFromEnumForPrimitive( final String enumRustName, final String primitiveType, final List messageBody, final Appendable writer) throws IOException { - indent(writer, 0, "impl Into<%s> for %s {\n", primitiveType, enumRustName); + indent(writer, 0, "impl From<%s> for %s {\n", enumRustName, primitiveType); indent(writer, 1, "#[inline]\n"); - indent(writer, 1, "fn into(self) -> %s {\n", primitiveType); - indent(writer, 2, "match self {\n"); + indent(writer, 1, "fn from(v: %s) -> Self {\n", enumRustName); + indent(writer, 2, "match v {\n"); + for (final Token token : messageBody) { final Encoding encoding = token.encoding(); final String literal = generateRustLiteral(encoding.primitiveType(), encoding.constValue().toString()); - indent(writer, 3, "Self::%s => %s, \n", token.name(), literal); + indent(writer, 3, "%s::%s => %s, \n", enumRustName, token.name(), literal); } + { final Encoding encoding = messageBody.get(0).encoding(); final CharSequence nullVal = generateRustLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString()); - indent(writer, 3, "Self::NullVal => %s,\n", nullVal); + indent(writer, 3, "%s::NullVal => %s,\n", enumRustName, nullVal); } indent(writer, 2, "}\n"); indent(writer, 1, "}\n"); @@ -1331,7 +1333,6 @@ private static void generateIntoImplForEnum( private static void generateFromStrImplForEnum( final String enumRustName, - final String primitiveType, final List messageBody, final Appendable writer) throws IOException { @@ -1342,10 +1343,10 @@ private static void generateFromStrImplForEnum( indent(writer, 2, "match v {\n"); for (final Token token : messageBody) { - indent(writer, 3, "\"%1$s\" => core::result::Result::Ok(Self::%1$s), \n", token.name()); + indent(writer, 3, "\"%1$s\" => Ok(Self::%1$s), \n", token.name()); } // default => NullVal - indent(writer, 3, "_ => core::result::Result::Ok(Self::NullVal),\n"); + indent(writer, 3, "_ => Ok(Self::NullVal),\n"); indent(writer, 2, "}\n"); indent(writer, 1, "}\n"); indent(writer, 0, "}\n"); From 6784077a8d0d70a7c08abd4e969060a2436cb848 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Tue, 3 Dec 2024 14:01:09 +0000 Subject: [PATCH 1275/1594] Update Checkstyle and JQwik dependencies. --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a21be421a2..5cbe7ecda4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "1.23.1" -checkstyle = "10.20.1" +checkstyle = "10.20.2" junit = "5.11.3" jmh = "1.37" gradle = "8.11.1" @@ -9,7 +9,7 @@ gradle = "8.11.1" agrona = { group = "org.agrona", name = "agrona", version = { strictly = "[1.23.1, 2.0[", require = "1.23.1" } } mockito = { group = "org.mockito", name = "mockito-core", version = "5.14.2" } hamcrest = { group = "org.hamcrest", name = "hamcrest", version = "3.0" } -jqwik = { group = "net.jqwik", name = "jqwik", version = "1.9.1" } +jqwik = { group = "net.jqwik", name = "jqwik", version = "1.9.2" } json = { group = "org.json", name = "json", version = "20240303" } jmh-core = { group = "org.openjdk.jmh", name = "jmh-core", version.ref = "jmh" } jmh-generator-annprocess = { group = "org.openjdk.jmh", name = "jmh-generator-annprocess", version.ref = "jmh" } From 72a8a7742fed2c865feecd7ffe5b525d6004d059 Mon Sep 17 00:00:00 2001 From: marc-adaptive Date: Tue, 3 Dec 2024 21:20:58 -0500 Subject: [PATCH 1276/1594] [Build] Remove draft release notes --- .github/workflows/release.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 837f2eaf09..7d7f62b227 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,14 +43,6 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.ref }} - - name: Create Release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} - draft: true - name: Setup java uses: actions/setup-java@v4 with: From eb24bb02595d4514b6ab5c2885e8fc1049751f23 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 4 Dec 2024 17:35:20 +0000 Subject: [PATCH 1277/1594] Update Checkstyle rules and apply them. --- config/checkstyle/checkstyle.xml | 16 +++++++-- .../uk/co/real_logic/sbe/PrimitiveValue.java | 8 ++--- .../uk/co/real_logic/sbe/ValidationUtil.java | 5 +-- .../co/real_logic/sbe/generation/c/CUtil.java | 8 ++--- .../sbe/generation/cpp/CppUtil.java | 8 ++--- .../sbe/generation/csharp/CSharpUtil.java | 8 ++--- .../golang/flyweight/GolangFlyweightUtil.java | 29 +++++++--------- .../sbe/generation/java/JavaUtil.java | 9 +++-- .../sbe/generation/rust/LibRsDef.java | 16 ++++++--- .../sbe/generation/rust/RustUtil.java | 4 +-- .../java/uk/co/real_logic/sbe/ir/Token.java | 12 +++---- .../real_logic/sbe/xml/EncodedDataType.java | 34 +++++++++---------- .../uk/co/real_logic/sbe/xml/EnumType.java | 16 ++++----- .../uk/co/real_logic/sbe/xml/Message.java | 20 +++++------ .../co/real_logic/sbe/xml/MessageSchema.java | 4 +-- .../uk/co/real_logic/sbe/xml/SetType.java | 18 +++++----- 16 files changed, 114 insertions(+), 101 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index f34d3bd2e5..abb1fc1efe 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -1,11 +1,17 @@ + "https://checkstyle.org/dtds/configuration_1_3.dtd"> + + + + + + @@ -22,8 +28,8 @@ - - + + @@ -33,9 +39,13 @@ + + + + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index 0754d9a485..18b543aef6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -308,7 +308,7 @@ public Representation representation() } /** - * Parse constant value string and set representation based on type + * Parse constant value string and set representation based on type. * * @param value expressed as a String. * @param primitiveType that this is supposed to be. @@ -367,7 +367,7 @@ public static PrimitiveValue parse(final String value, final PrimitiveType primi } /** - * Parse constant value string and set representation based on type + * Parse constant value string and set representation based on type. * * @param value expressed as a String. * @param primitiveType that this is supposed to be. @@ -392,7 +392,7 @@ public static PrimitiveValue parse( } /** - * Parse constant value string and set representation based on type, length, and characterEncoding + * Parse constant value string and set representation based on type, length, and characterEncoding. * * @param value expressed as a String. * @param length of the type. @@ -469,7 +469,7 @@ public byte[] byteArrayValue() } /** - * Return byte array value for this PrimitiveValue given a particular type + * Return byte array value for this PrimitiveValue given a particular type. * * @param type of this value. * @return value expressed as a byte array. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index 74e58e3f5a..a7bb7e0d19 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -19,7 +19,7 @@ import java.util.regex.Pattern; /** - * Various validation utilities used across parser, IR, and generator + * Various validation utilities used across parser, IR, and generator. */ public class ValidationUtil { @@ -228,7 +228,7 @@ private static boolean isSbeCppIdentifierPart(final char c) *

      * Java JLS * - * @param value to check + * @param value to check. * @return true for validity as a Java name. false if not. */ public static boolean isSbeJavaName(final String value) @@ -391,6 +391,7 @@ private static boolean isSbeGolangIdentifierPart(final char c) } /** + * C# keywords. * * C# keywords * Note this does not include the contextual keywords diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java index fa0cbe1f10..518abd80b2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java @@ -108,11 +108,11 @@ public static String formatScopedName(final CharSequence[] scope, final String v } /** - * Return the C99 formatted byte order encoding string to use for a given byte order and primitiveType + * Return the C99 formatted byte order encoding string to use for a given byte order and primitiveType. * - * @param byteOrder of the {@link uk.co.real_logic.sbe.ir.Token} - * @param primitiveType of the {@link uk.co.real_logic.sbe.ir.Token} - * @return the string formatted as the byte ordering encoding + * @param byteOrder of the {@link uk.co.real_logic.sbe.ir.Token}. + * @param primitiveType of the {@link uk.co.real_logic.sbe.ir.Token}. + * @return the string formatted as the byte ordering encoding. */ public static String formatByteOrderEncoding(final ByteOrder byteOrder, final PrimitiveType primitiveType) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index 534547a7fb..469faac27a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -106,11 +106,11 @@ public static String formatClassName(final String value) } /** - * Return the Cpp98 formatted byte order encoding string to use for a given byte order and primitiveType + * Return the Cpp98 formatted byte order encoding string to use for a given byte order and primitiveType. * - * @param byteOrder of the {@link uk.co.real_logic.sbe.ir.Token} - * @param primitiveType of the {@link uk.co.real_logic.sbe.ir.Token} - * @return the string formatted as the byte ordering encoding + * @param byteOrder of the {@link uk.co.real_logic.sbe.ir.Token}. + * @param primitiveType of the {@link uk.co.real_logic.sbe.ir.Token}. + * @return the string formatted as the byte ordering encoding. */ public static String formatByteOrderEncoding(final ByteOrder byteOrder, final PrimitiveType primitiveType) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index a80ae7a295..b4fee26faf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -322,11 +322,11 @@ public static String formatGetterName(final String propertyName) } /** - * Shortcut to append a line of generated code + * Shortcut to append a line of generated code. * - * @param builder string builder to which to append the line - * @param indent current text indentation - * @param line line to be appended + * @param builder string builder to which to append the line. + * @param indent current text indentation. + * @param line line to be appended. */ public static void append(final StringBuilder builder, final String indent, final String line) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java index 78ac285b6c..ba03adbc3b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java @@ -87,7 +87,7 @@ public static String formatClassName(final String value) } /** - * Map the name of a {@link uk.co.real_logic.sbe.PrimitiveType} to a Golang marhsalling function name. + * Map the name of a {@link uk.co.real_logic.sbe.PrimitiveType} to a Golang marshalling function name. * * @param primitiveType to map. * @return the name of the Java primitive that most closely maps. @@ -114,8 +114,8 @@ public static String formatPropertyName(final String value) { throw new IllegalStateException( "Invalid property name='" + formattedValue + - "' please correct the schema or consider setting system property: " + - SbeTool.KEYWORD_APPEND_TOKEN); + "' please correct the schema or consider setting system property: " + + SbeTool.KEYWORD_APPEND_TOKEN); } formattedValue += keywordAppendToken; @@ -142,16 +142,15 @@ public static String closingBraces(final int count) } /** - * Return the Golang formatted byte order encoding string to use to read for a given byte order and primitiveType + * Return the Golang formatted byte order encoding string to use to read for a given byte order and primitiveType. * - * @param byteOrder of the {@link uk.co.real_logic.sbe.ir.Token} - * @param primitiveType of the {@link uk.co.real_logic.sbe.ir.Token} - * @return the string formatted as the byte ordering encoding + * @param byteOrder of the {@link uk.co.real_logic.sbe.ir.Token}. + * @param primitiveType of the {@link uk.co.real_logic.sbe.ir.Token}. + * @return the string formatted as the byte ordering encoding. */ public static String formatReadBytes(final ByteOrder byteOrder, final PrimitiveType primitiveType) { - final String suffix = (byteOrder == ByteOrder.BIG_ENDIAN ? - "BigEndian" : "LittleEndian"); + final String suffix = byteOrder == ByteOrder.BIG_ENDIAN ? "BigEndian" : "LittleEndian"; switch (primitiveType) { @@ -182,16 +181,15 @@ public static String formatReadBytes(final ByteOrder byteOrder, final PrimitiveT } /** - * Return the Golang formatted byte order encoding string to use to write for a given byte order and primitiveType + * Return the Golang formatted byte order encoding string to use to write for a given byte order and primitiveType. * - * @param byteOrder of the {@link uk.co.real_logic.sbe.ir.Token} - * @param primitiveType of the {@link uk.co.real_logic.sbe.ir.Token} - * @return the string formatted as the byte ordering encoding + * @param byteOrder of the {@link uk.co.real_logic.sbe.ir.Token}. + * @param primitiveType of the {@link uk.co.real_logic.sbe.ir.Token}. + * @return the string formatted as the byte ordering encoding. */ public static String formatWriteBytes(final ByteOrder byteOrder, final PrimitiveType primitiveType) { - final String suffix = (byteOrder == ByteOrder.BIG_ENDIAN ? - "BigEndian" : "LittleEndian"); + final String suffix = byteOrder == ByteOrder.BIG_ENDIAN ? "BigEndian" : "LittleEndian"; switch (primitiveType) { @@ -220,5 +218,4 @@ public static String formatWriteBytes(final ByteOrder byteOrder, final Primitive } return ""; } - } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index d5d3ac6693..7f885f673c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -208,11 +208,11 @@ public static String formatClassName(final String className) } /** - * Shortcut to append a line of generated code + * Shortcut to append a line of generated code. * - * @param builder string builder to which to append the line - * @param indent current text indentation - * @param line line to be appended + * @param builder string builder to which to append the line. + * @param indent current text indentation. + * @param line line to be appended. */ public static void append(final StringBuilder builder, final String indent, final String line) { @@ -533,5 +533,4 @@ private static void escapeJavadoc(final StringBuilder sb, final String doc) } } } - } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 46897829cd..ae50c9bef7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -15,6 +15,8 @@ */ package uk.co.real_logic.sbe.generation.rust; +import uk.co.real_logic.sbe.ir.Ir; + import java.io.IOException; import java.io.Writer; import java.nio.ByteOrder; @@ -23,11 +25,15 @@ import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.stream.Stream; -import uk.co.real_logic.sbe.ir.Ir; import static java.nio.ByteOrder.LITTLE_ENDIAN; -import static uk.co.real_logic.sbe.generation.rust.RustGenerator.*; -import static uk.co.real_logic.sbe.generation.rust.RustUtil.*; +import static uk.co.real_logic.sbe.generation.rust.RustGenerator.BUF_LIFETIME; +import static uk.co.real_logic.sbe.generation.rust.RustGenerator.READ_BUF_TYPE; +import static uk.co.real_logic.sbe.generation.rust.RustGenerator.WRITE_BUF_TYPE; +import static uk.co.real_logic.sbe.generation.rust.RustUtil.TYPE_NAME_BY_PRIMITIVE_TYPE_MAP; +import static uk.co.real_logic.sbe.generation.rust.RustUtil.indent; +import static uk.co.real_logic.sbe.generation.rust.RustUtil.rustTypeName; +import static uk.co.real_logic.sbe.generation.rust.RustUtil.toLowerSnakeCase; /** * Generates `lib.rs` specific code. @@ -39,11 +45,11 @@ class LibRsDef private final String schemaVersionType; /** - * Create a new 'lib.rs' for the library being generated + * Create a new 'lib.rs' for the library being generated. * * @param outputManager for generating the codecs to. * @param byteOrder for the Encoding. - * @param schemaVersionType for acting_version type + * @param schemaVersionType for acting_version type. */ LibRsDef( final RustOutputManager outputManager, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index 8f2724759f..43b9c8ba8a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -70,7 +70,7 @@ static String generateRustLiteral(final PrimitiveType type, final String value) Verify.notNull(type, "type"); Verify.notNull(value, "value"); final String typeName = rustTypeName(type); - if (typeName == null) + if (null == typeName) { throw new IllegalArgumentException("Unknown Rust type name found for primitive " + type.primitiveName()); } @@ -178,7 +178,7 @@ static String characterEncoding(final Encoding encoding) /** * Converts to 'snake_case' but will also handle when there are multiple - * upper case characters in a row 'UPPERCase' => 'upper_case' + * upper case characters in a row 'UPPERCase' => 'upper_case'. * * @param value to be formatted * @return the string formatted to 'lower_snake_case' diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index 83ab2d1538..6d97572727 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -71,7 +71,7 @@ public class Token public static final int INVALID_ID = -1; /** - * Length not determined + * Length not determined. */ public static final int VARIABLE_LENGTH = -1; @@ -148,9 +148,9 @@ public Signal signal() } /** - * Return the name of the token + * Return the name of the token. * - * @return name of the token + * @return name of the token. */ public String name() { @@ -158,7 +158,7 @@ public String name() } /** - * Return the packageName of the token + * Return the packageName of the token. * * @return packageName of the token or null, if it was not set explicitly. */ @@ -188,9 +188,9 @@ public String description() } /** - * Return the ID of the token assigned by the specification + * Return the ID of the token assigned by the specification. * - * @return ID of the token assigned by the specification + * @return ID of the token assigned by the specification. */ public int id() { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index 981bcaa8db..78fe6e10a0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -55,7 +55,7 @@ public class EncodedDataType extends Type /** * Construct a new encodedDataType from XML Schema. * - * @param node from the XML Schema Parsing + * @param node from the XML Schema Parsing. */ public EncodedDataType(final Node node) { @@ -258,9 +258,9 @@ public EncodedDataType( } /** - * Return the length attribute of the type + * Return the length attribute of the type. * - * @return length attribute of the type + * @return length attribute of the type. */ public int length() { @@ -268,9 +268,9 @@ public int length() } /** - * Return the variableLength attribute of the type + * Return the variableLength attribute of the type. * - * @return variableLength boolean of the type + * @return variableLength boolean of the type. */ public boolean isVariableLength() { @@ -288,9 +288,9 @@ public void variableLength(final boolean variableLength) } /** - * Return the primitiveType attribute of the type + * Return the primitiveType attribute of the type. * - * @return primitiveType attribute of the type + * @return primitiveType attribute of the type. */ public PrimitiveType primitiveType() { @@ -318,9 +318,9 @@ public int encodedLength() } /** - * The constant value of the type if specified + * The constant value of the type if specified. * - * @return value of the constant for this type + * @return value of the constant for this type. */ public PrimitiveValue constVal() { @@ -333,9 +333,9 @@ public PrimitiveValue constVal() } /** - * The minValue of the type + * The minValue of the type. * - * @return value of the minValue + * @return value of the minValue. */ public PrimitiveValue minValue() { @@ -343,9 +343,9 @@ public PrimitiveValue minValue() } /** - * The maxValue of the type + * The maxValue of the type. * - * @return value of the maxValue + * @return value of the maxValue. */ public PrimitiveValue maxValue() { @@ -353,9 +353,9 @@ public PrimitiveValue maxValue() } /** - * The nullValue of the type + * The nullValue of the type. * - * @return value of the nullValue primitiveType or type + * @return value of the nullValue primitiveType or type. */ public PrimitiveValue nullValue() { @@ -363,9 +363,9 @@ public PrimitiveValue nullValue() } /** - * The character encoding of the type + * The character encoding of the type. * - * @return value representing the encoding + * @return value representing the encoding. */ public String characterEncoding() { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index 60a9cdc66e..b2566ea787 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -174,9 +174,9 @@ public PrimitiveType encodingType() } /** - * The encodedLength (in octets) of the encodingType + * The encodedLength (in octets) of the encodingType. * - * @return encodedLength of the encodingType + * @return encodedLength of the encodingType. */ public int encodedLength() { @@ -191,7 +191,7 @@ public int encodedLength() /** * Get the {@link ValidValue} represented by a {@link PrimitiveValue}. * - * @param value to lookup + * @param value to lookup. * @return the {@link ValidValue} represented by a {@link PrimitiveValue} or null. */ public ValidValue getValidValue(final PrimitiveValue value) @@ -202,7 +202,7 @@ public ValidValue getValidValue(final PrimitiveValue value) /** * Get the {@link ValidValue} represented by a string name. * - * @param name to lookup + * @param name to lookup. * @return the {@link ValidValue} represented by a string name or null. */ public ValidValue getValidValue(final String name) @@ -265,8 +265,8 @@ public static class ValidValue /** * Construct a ValidValue given the XML node and the encodingType. * - * @param node that contains the validValue - * @param encodingType for the enum + * @param node that contains the validValue. + * @param encodingType for the enum. */ public ValidValue(final Node node, final PrimitiveType encodingType) { @@ -310,9 +310,9 @@ public String description() } /** - * The sinceVersion value of the {@link ValidValue} + * The sinceVersion value of the {@link ValidValue}. * - * @return the sinceVersion value of the {@link ValidValue} + * @return the sinceVersion value of the {@link ValidValue}. */ public int sinceVersion() { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java index 3c1e6a78f2..90695b736a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java @@ -98,9 +98,9 @@ public Message(final Node messageNode, final Map typeByNameMap) th } /** - * Return the template schemaId of the message + * Return the template schemaId of the message. * - * @return schemaId of the message + * @return schemaId of the message. */ public int id() { @@ -108,9 +108,9 @@ public int id() } /** - * Return the name of the message + * Return the name of the message. * - * @return name of the message + * @return name of the message. */ public String name() { @@ -118,9 +118,9 @@ public String name() } /** - * The description of the message (if set) or null + * The description of the message (if set) or null. * - * @return description set by the message or null + * @return description set by the message or null. */ public String description() { @@ -128,9 +128,9 @@ public String description() } /** - * The semanticType of the message (if set) or null + * The semanticType of the message (if set) or null. * - * @return the semanticType of the message (if set) or null + * @return the semanticType of the message (if set) or null. */ public String semanticType() { @@ -158,9 +158,9 @@ public int deprecated() } /** - * Return the list of fields in the message + * Return the list of fields in the message. * - * @return {@link java.util.List} of the Field objects in this Message + * @return {@link java.util.List} of the Field objects in this Message. */ public List fields() { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index 46dac06dfd..5203939b4d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -96,7 +96,7 @@ public class MessageSchema /** * The Schema headerType for message headers. This should be a {@link CompositeType}. * - * @return the Schema headerType for message headers + * @return the Schema headerType for message headers. */ public CompositeType messageHeader() { @@ -196,7 +196,7 @@ public Collection types() } /** - * Return the byte order specified by the messageSchema + * Return the byte order specified by the messageSchema. * * @return {@link ByteOrder} of the message encoding. */ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index fb6914774f..ff5b025ae4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -134,9 +134,9 @@ public PrimitiveType encodingType() } /** - * The encodedLength (in octets) of the encodingType + * The encodedLength (in octets) of the encodingType. * - * @return encodedLength of the encodingType + * @return encodedLength of the encodingType. */ public int encodedLength() { @@ -146,7 +146,7 @@ public int encodedLength() /** * Get the {@link Choice} represented by a {@link PrimitiveValue}. * - * @param value to get + * @param value to get. * @return the {@link Choice} represented by a {@link PrimitiveValue} or null if not found. */ public Choice getChoice(final PrimitiveValue value) @@ -157,7 +157,7 @@ public Choice getChoice(final PrimitiveValue value) /** * Get the {@link Choice} represented by a String name. * - * @param name to get + * @param name to get. * @return the {@link Choice} represented by a String name or null if not found. */ public Choice getChoice(final String name) @@ -209,10 +209,10 @@ public static class Choice private final int deprecated; /** - * Construct a Choice given the XML node and the encodingType + * Construct a Choice given the XML node and the encodingType. * - * @param node that contains the validValue - * @param encodingType for the enum + * @param node that contains the validValue. + * @param encodingType for the enum. */ public Choice(final Node node, final PrimitiveType encodingType) { @@ -262,9 +262,9 @@ public String description() } /** - * The sinceVersion value of the {@link Choice} + * The sinceVersion value of the {@link Choice}. * - * @return the sinceVersion value of the {@link Choice} + * @return the sinceVersion value of the {@link Choice}. */ public int sinceVersion() { From 68aeb1a9a5f06b83c07d02c57fec1972ca527dd1 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Fri, 6 Dec 2024 17:46:28 +0000 Subject: [PATCH 1278/1594] [Java] Prevent collision when field name is 'value'. `value` is used as a parameter name in some DTO methods. When an SBE field was named `value` it caused an issue due to a collision. We now make sure to reference fields more explicitly via `this.fieldName`. --- .../sbe/generation/java/JavaDtoGenerator.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java index baf9f70342..8c5bfb8b02 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -291,7 +291,7 @@ private void generateGroups( .append(indent).append("public List<").append(qualifiedDtoClassName).append("> ") .append(formattedPropertyName).append("()\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append(INDENT).append("return this.").append(fieldName).append(";\n") .append(indent).append("}\n"); classBuilder.appendPublic().append("\n") @@ -299,7 +299,7 @@ private void generateGroups( .append(indent).append("public void ").append(formattedPropertyName).append("(") .append("List<").append(qualifiedDtoClassName).append("> value)") .append(indent).append("{\n") - .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append(INDENT).append("this.").append(fieldName).append(" = value;\n") .append(indent).append("}\n"); } } @@ -350,7 +350,7 @@ private void generateComputeEncodedLength( .append(indent).append(INDENT).append("encodedLength += ") .append(groupDecoderClassName).append(".sbeHeaderSize();\n\n") .append(indent).append(INDENT).append("for (").append(groupDtoClassName).append(" group : ") - .append(fieldName).append(")\n") + .append("this.").append(fieldName).append(")\n") .append(indent).append(INDENT).append("{\n") .append(indent).append(INDENT).append(INDENT) .append("encodedLength += group.computeEncodedLength();\n") @@ -373,7 +373,7 @@ private void generateComputeEncodedLength( final String characterEncoding = varDataToken.encoding().characterEncoding(); final String lengthAccessor = characterEncoding == null ? ".length" : ".length()"; lengthBuilder.append(indent).append(INDENT).append("encodedLength += ") - .append(fieldName).append(lengthAccessor); + .append("this.").append(fieldName).append(lengthAccessor); final int elementByteLength = varDataToken.encoding().primitiveType().size(); if (elementByteLength != 1) @@ -1255,7 +1255,7 @@ private void generateComplexProperty( .append(indent).append("public ").append(typeName).append(" ") .append(formattedPropertyName).append("()\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append(INDENT).append("return this.").append(fieldName).append(";\n") .append(indent).append("}\n"); classBuilder.appendPublic().append("\n") @@ -1263,7 +1263,7 @@ private void generateComplexProperty( .append(indent).append("public void ") .append(formattedPropertyName).append("(").append(typeName).append(" value)\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append(INDENT).append("this.").append(fieldName).append(" = value;\n") .append(indent).append("}\n"); } @@ -1304,7 +1304,7 @@ private void generateEnumProperty( .append(indent).append("public ").append(enumName).append(" ") .append(formattedPropertyName).append("()\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append(INDENT).append("return this.").append(fieldName).append(";\n") .append(indent).append("}\n"); classBuilder.appendPublic().append("\n") @@ -1312,7 +1312,7 @@ private void generateEnumProperty( .append(indent).append("public void ").append(formattedPropertyName) .append("(").append(enumName).append(" value)\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append(INDENT).append("this.").append(fieldName).append(" = value;\n") .append(indent).append("}\n"); } } @@ -1382,7 +1382,7 @@ private void generateArrayProperty( .append(indent).append("public ").append(typeName).append(" ") .append(formattedPropertyName).append("()\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append(INDENT).append("return this.").append(fieldName).append(";\n") .append(indent).append("}\n"); classBuilder.appendPublic().append("\n") @@ -1391,7 +1391,7 @@ private void generateArrayProperty( .append("(").append(typeName).append(" value)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append(validateMethod).append("(value);\n") - .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append(INDENT).append("this.").append(fieldName).append(" = value;\n") .append(indent).append("}\n"); generateArrayValidateMethod( @@ -1416,7 +1416,7 @@ private void generateArrayProperty( .append(indent).append("public ").append(typeName).append(" ") .append(formattedPropertyName).append("()\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append(INDENT).append("return this.").append(fieldName).append(";\n") .append(indent).append("}\n"); classBuilder.appendPublic().append("\n") @@ -1425,7 +1425,7 @@ private void generateArrayProperty( .append(typeName).append(" value").append(")\n") .append(indent).append("{\n") .append(indent).append(INDENT).append(validateMethod).append("(value);\n") - .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append(INDENT).append("this.").append(fieldName).append(" = value;\n") .append(indent).append("}\n"); generateArrayValidateMethod( @@ -1519,7 +1519,7 @@ private void generateSingleValueProperty( .append(indent).append("public ").append(typeName).append(" ") .append(formattedPropertyName).append("()\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append(INDENT).append("return this.").append(fieldName).append(";\n") .append(indent).append("}\n"); classBuilder.appendPublic().append("\n") @@ -1528,7 +1528,7 @@ private void generateSingleValueProperty( .append(typeName).append(" value)\n") .append(indent).append("{\n") .append(validationCall) - .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append(INDENT).append("this.").append(fieldName).append(" = value;\n") .append(indent).append("}\n"); } @@ -1590,14 +1590,14 @@ private void generateVarData( .append(indent).append("public ").append(dtoType).append(" ") .append(formattedPropertyName).append("()\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append(INDENT).append("return this.").append(fieldName).append(";\n") .append(indent).append("}\n"); classBuilder.appendPublic().append("\n") .append(indent).append("public void ").append(formattedPropertyName) .append("(").append(dtoType).append(" value)\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append(INDENT).append("this.").append(fieldName).append(" = value;\n") .append(indent).append("}\n"); } } @@ -1777,7 +1777,7 @@ private void generateChoices( .append("\n") .append(indent).append("public boolean ").append(formattedPropertyName).append("()\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") + .append(indent).append(INDENT).append("return this.").append(fieldName).append(";\n") .append(indent).append("}\n"); classBuilder.appendPublic() @@ -1785,7 +1785,7 @@ private void generateChoices( .append(indent).append(dtoClassName).append(" ") .append(formattedPropertyName).append("(boolean value)\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append(fieldName).append(" = value;\n") + .append(indent).append(INDENT).append("this.").append(fieldName).append(" = value;\n") .append(indent).append(INDENT).append("return this;\n") .append(indent).append("}\n"); } From d3f3bf436f822f0a809479f4db8ebeb3146093c7 Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Mon, 9 Dec 2024 15:06:10 -0600 Subject: [PATCH 1279/1594] [C++] use constexpr to define precedence checks lookup tables --- .../sbe/generation/cpp/CppGenerator.java | 28 +++++++------------ .../sbe/generation/cpp/CppGeneratorTest.java | 26 +++++++++++++++++ 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 8533a4df84..65d6a627e6 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -243,7 +243,6 @@ public void generate() throws IOException generateDisplay(sb, msgToken.name(), fields, groups, varData); sb.append(generateMessageLength(groups, varData, BASE_INDENT)); sb.append("};\n"); - generateLookupTableDefinitions(sb, className, fieldPrecedenceModel); sb.append(CppUtil.closingBraces(namespaces.length)).append("#endif\n"); out.append(sb); } @@ -2975,12 +2974,8 @@ private static CharSequence generateLookupTableDeclarations(final FieldPrecedenc } final StringBuilder sb = new StringBuilder(); - sb.append(INDENT).append("static const std::string STATE_NAME_LOOKUP[") - .append(fieldPrecedenceModel.stateCount()) - .append("];\n"); - sb.append(INDENT).append("static const std::string STATE_TRANSITIONS_LOOKUP[") - .append(fieldPrecedenceModel.stateCount()) - .append("];\n\n"); + + generateLookupTableDefinitions(sb, fieldPrecedenceModel); sb.append(INDENT).append("static std::string codecStateName(CodecState state)\n") .append(INDENT).append("{\n") @@ -2997,7 +2992,6 @@ private static CharSequence generateLookupTableDeclarations(final FieldPrecedenc private static void generateLookupTableDefinitions( final StringBuilder sb, - final String className, final FieldPrecedenceModel fieldPrecedenceModel) { if (null == fieldPrecedenceModel) @@ -3005,19 +2999,17 @@ private static void generateLookupTableDefinitions( return; } - sb.append("\n").append("const std::string ").append(className).append("::STATE_NAME_LOOKUP[") - .append(fieldPrecedenceModel.stateCount()).append("] =\n") - .append("{\n"); + sb.append(INDENT).append("static constexpr const char *STATE_NAME_LOOKUP[] =\n") + .append(INDENT).append("{\n"); fieldPrecedenceModel.forEachStateOrderedByStateNumber((state) -> - sb.append(INDENT).append("\"").append(state.name()).append("\",\n")); - sb.append("};\n\n"); + sb.append(INDENT).append(INDENT).append("\"").append(state.name()).append("\",\n")); + sb.append(INDENT).append("};\n\n"); - sb.append("const std::string ").append(className).append("::STATE_TRANSITIONS_LOOKUP[") - .append(fieldPrecedenceModel.stateCount()).append("] =\n") - .append("{\n"); + sb.append(INDENT).append("static constexpr const char *STATE_TRANSITIONS_LOOKUP[] =\n") + .append(INDENT).append("{\n"); fieldPrecedenceModel.forEachStateOrderedByStateNumber((state) -> { - sb.append(INDENT).append("\""); + sb.append(INDENT).append(INDENT).append("\""); final MutableBoolean isFirst = new MutableBoolean(true); final Set transitionDescriptions = new HashSet<>(); fieldPrecedenceModel.forEachTransitionFrom(state, (transitionGroup) -> @@ -3038,7 +3030,7 @@ private static void generateLookupTableDefinitions( }); sb.append("\",\n"); }); - sb.append("};\n\n"); + sb.append(INDENT).append("};\n\n"); } private static CharSequence qualifiedStateCase(final FieldPrecedenceModel.State state) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index b8c969c8b8..79c1651c03 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -114,4 +114,30 @@ void dtosShouldReferenceTypesInDifferentPackages() throws Exception assertThat(source, containsString("using namespace test::message::schema::common;")); } } + + @Test + void shouldUseConstexprWhenDefiningPrecedenceChecksLookupTables() throws Exception + { + try (InputStream in = Tests.getLocalResource("code-generation-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + + final CppGenerator generator = new CppGenerator( + ir, + false, + PrecedenceChecks.newInstance(new PrecedenceChecks.Context().shouldGeneratePrecedenceChecks(true)), + false, + outputManager); + generator.generate(); + + final String source = outputManager.getSource("code.generation.test.Car").toString(); + assertThat(source, containsString("static constexpr const char *STATE_NAME_LOOKUP[] =")); + assertThat(source, containsString("static constexpr const char *STATE_TRANSITIONS_LOOKUP[] =")); + } + } } From daf02836cd7e1e3f6541f861724e3e88ef83b0af Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Tue, 10 Dec 2024 16:37:14 -0600 Subject: [PATCH 1280/1594] [C++] add definitions of constexpr lookup tables --- .../sbe/generation/cpp/CppGenerator.java | 56 +++++++++++-------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 65d6a627e6..e1ae7e16fc 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -243,6 +243,7 @@ public void generate() throws IOException generateDisplay(sb, msgToken.name(), fields, groups, varData); sb.append(generateMessageLength(groups, varData, BASE_INDENT)); sb.append("};\n"); + generateLookupTableDefinitions(sb, className, fieldPrecedenceModel); sb.append(CppUtil.closingBraces(namespaces.length)).append("#endif\n"); out.append(sb); } @@ -2975,30 +2976,6 @@ private static CharSequence generateLookupTableDeclarations(final FieldPrecedenc final StringBuilder sb = new StringBuilder(); - generateLookupTableDefinitions(sb, fieldPrecedenceModel); - - sb.append(INDENT).append("static std::string codecStateName(CodecState state)\n") - .append(INDENT).append("{\n") - .append(TWO_INDENT).append("return STATE_NAME_LOOKUP[static_cast(state)];\n") - .append(INDENT).append("}\n\n"); - - sb.append(INDENT).append("static std::string codecStateTransitions(CodecState state)\n") - .append(INDENT).append("{\n") - .append(TWO_INDENT).append("return STATE_TRANSITIONS_LOOKUP[static_cast(state)];\n") - .append(INDENT).append("}\n\n"); - - return sb; - } - - private static void generateLookupTableDefinitions( - final StringBuilder sb, - final FieldPrecedenceModel fieldPrecedenceModel) - { - if (null == fieldPrecedenceModel) - { - return; - } - sb.append(INDENT).append("static constexpr const char *STATE_NAME_LOOKUP[] =\n") .append(INDENT).append("{\n"); fieldPrecedenceModel.forEachStateOrderedByStateNumber((state) -> @@ -3031,6 +3008,37 @@ private static void generateLookupTableDefinitions( sb.append("\",\n"); }); sb.append(INDENT).append("};\n\n"); + + sb.append(INDENT).append("static std::string codecStateName(CodecState state)\n") + .append(INDENT).append("{\n") + .append(TWO_INDENT).append("return STATE_NAME_LOOKUP[static_cast(state)];\n") + .append(INDENT).append("}\n\n"); + + sb.append(INDENT).append("static std::string codecStateTransitions(CodecState state)\n") + .append(INDENT).append("{\n") + .append(TWO_INDENT).append("return STATE_TRANSITIONS_LOOKUP[static_cast(state)];\n") + .append(INDENT).append("}\n\n"); + + return sb; + } + + private static void generateLookupTableDefinitions( + final StringBuilder sb, + final String className, + final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return; + } + + sb + .append("\nconstexpr const char *") + .append(className) + .append("::STATE_NAME_LOOKUP[];\n") + .append("constexpr const char *") + .append(className) + .append("::STATE_TRANSITIONS_LOOKUP[];\n\n"); } private static CharSequence qualifiedStateCase(final FieldPrecedenceModel.State state) From 0c48ee3f52f4d1b2201db985ea44bab3a5a7af81 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Wed, 11 Dec 2024 10:17:51 +0000 Subject: [PATCH 1281/1594] [C++] Fix field precedence check issue #1031. (#1033) There were a couple of problems here: 1. "wrapping constructors" did not initialize the codec state (for precedence checks) correctly, and 2. the methods returning a JSON encoded string would attempt to transition twice. These problems are now resolved. I have also made a technically breaking change. I have removed an unnecessary constructor that took in the codec state. I think it is highly unlikely that anyone was using this constructor; therefore, it should be okay to make the change. --- .../sbe/generation/cpp/CppGenerator.java | 79 ++++++---------- .../test/cpp/FieldAccessOrderCheckTest.cpp | 93 +++++++++++++++++++ 2 files changed, 120 insertions(+), 52 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index e1ae7e16fc..846a289e11 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1201,7 +1201,7 @@ private void generateVarData( lengthCppType, accessOrderListenerCall); - generateJsonEscapedStringGetter(sb, token, indent, propertyName, accessOrderListenerCall); + generateJsonEscapedStringGetter(sb, token, indent, propertyName); new Formatter(sb).format("\n" + indent + " #if __cplusplus >= 201703L\n" + @@ -2307,7 +2307,7 @@ private void generateArrayProperty( generateStringNotPresentCondition(propertyToken.version(), indent), accessOrderListenerCall); - generateJsonEscapedStringGetter(sb, encodingToken, indent, propertyName, accessOrderListenerCall); + generateJsonEscapedStringGetter(sb, encodingToken, indent, propertyName); new Formatter(sb).format("\n" + indent + " #if __cplusplus >= 201703L\n" + @@ -2381,14 +2381,12 @@ private void generateJsonEscapedStringGetter( final StringBuilder sb, final Token token, final String indent, - final String propertyName, - final CharSequence accessOrderListenerCall) + final String propertyName) { new Formatter(sb).format("\n" + indent + " std::string get%1$sAsJsonEscapedString()\n" + indent + " {\n" + "%2$s" + - "%3$s" + indent + " std::ostringstream oss;\n" + indent + " std::string s = get%1$sAsString();\n\n" + indent + " for (const auto c : s)\n" + @@ -2417,8 +2415,7 @@ private void generateJsonEscapedStringGetter( indent + " return oss.str();\n" + indent + " }\n", toUpperFirstChar(propertyName), - generateStringNotPresentCondition(token.version(), indent), - accessOrderListenerCall); + generateStringNotPresentCondition(token.version(), indent)); } private void generateConstPropertyMethods( @@ -2505,7 +2502,7 @@ private void generateConstPropertyMethods( values, constantValue.length); - generateJsonEscapedStringGetter(sb, token, indent, propertyName, ""); + generateJsonEscapedStringGetter(sb, token, indent, propertyName); } private CharSequence generateFixedFlyweightCode(final String className, final int size) @@ -2654,34 +2651,13 @@ private static String generateHiddenCopyConstructor(final String indent, final S return DISABLE_IMPLICIT_COPYING ? ctorAndCopyAssignmentDeletion : ""; } - private static CharSequence generateConstructorsAndOperators( + private CharSequence generateConstructorsAndOperators( final String className, final FieldPrecedenceModel fieldPrecedenceModel) { - final String constructorWithCodecState = null == fieldPrecedenceModel ? "" : String.format( - " %1$s(\n" + - " char *buffer,\n" + - " const std::uint64_t offset,\n" + - " const std::uint64_t bufferLength,\n" + - " const std::uint64_t actingBlockLength,\n" + - " const std::uint64_t actingVersion,\n" + - " CodecState codecState) :\n" + - " m_buffer(buffer),\n" + - " m_bufferLength(bufferLength),\n" + - " m_offset(offset),\n" + - " m_position(sbeCheckPosition(offset + actingBlockLength)),\n" + - " m_actingBlockLength(actingBlockLength),\n" + - " m_actingVersion(actingVersion),\n" + - " m_codecState(codecState)\n" + - " {\n" + - " }\n\n", - className); - return String.format( " %1$s() = default;\n\n" + - "%2$s" + - " %1$s(\n" + " char *buffer,\n" + " const std::uint64_t offset,\n" + @@ -2695,6 +2671,7 @@ private static CharSequence generateConstructorsAndOperators( " m_actingBlockLength(actingBlockLength),\n" + " m_actingVersion(actingVersion)\n" + " {\n" + + "%2$s" + " }\n\n" + " %1$s(char *buffer, const std::uint64_t bufferLength) :\n" + @@ -2711,7 +2688,7 @@ private static CharSequence generateConstructorsAndOperators( " {\n" + " }\n\n", className, - constructorWithCodecState); + generateCodecStateTransitionForWrapping(fieldPrecedenceModel)); } private CharSequence generateMessageFlyweightCode( @@ -2728,26 +2705,25 @@ private CharSequence generateMessageFlyweightCode( final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); - final String codecStateArgument = null == fieldPrecedenceModel ? "" : ", m_codecState"; - return String.format( "private:\n" + + "%14$s" + "%15$s" + - "%16$s" + " char *m_buffer = nullptr;\n" + " std::uint64_t m_bufferLength = 0;\n" + " std::uint64_t m_offset = 0;\n" + " std::uint64_t m_position = 0;\n" + " std::uint64_t m_actingBlockLength = 0;\n" + " std::uint64_t m_actingVersion = 0;\n" + - "%17$s" + + "%16$s" + " inline std::uint64_t *sbePositionPtr() SBE_NOEXCEPT\n" + " {\n" + " return &m_position;\n" + " }\n\n" + - "%22$s" + + "%19$s" + + "%21$s" + "public:\n" + " static constexpr %1$s SBE_BLOCK_LENGTH = %2$s;\n" + @@ -2775,7 +2751,7 @@ private CharSequence generateMessageFlyweightCode( " using messageHeader = %12$s;\n\n" + - "%18$s" + + "%17$s" + "%11$s" + " SBE_NODISCARD static SBE_CONSTEXPR %1$s sbeBlockLength() SBE_NOEXCEPT\n" + @@ -2826,7 +2802,7 @@ private CharSequence generateMessageFlyweightCode( " m_actingBlockLength = sbeBlockLength();\n" + " m_actingVersion = sbeSchemaVersion();\n" + " m_position = sbeCheckPosition(m_offset + m_actingBlockLength);\n" + - "%19$s" + + "%18$s" + " return *this;\n" + " }\n\n" + @@ -2847,12 +2823,10 @@ private CharSequence generateMessageFlyweightCode( " m_actingBlockLength = sbeBlockLength();\n" + " m_actingVersion = sbeSchemaVersion();\n" + " m_position = sbeCheckPosition(m_offset + m_actingBlockLength);\n" + - "%19$s" + + "%18$s" + " return *this;\n" + " }\n\n" + - "%20$s" + - " %10$s &wrapForDecode(\n" + " char *buffer,\n" + " const std::uint64_t offset,\n" + @@ -2866,7 +2840,7 @@ private CharSequence generateMessageFlyweightCode( " m_actingBlockLength = actingBlockLength;\n" + " m_actingVersion = actingVersion;\n" + " m_position = sbeCheckPosition(m_offset + m_actingBlockLength);\n" + - "%21$s" + + "%20$s" + " return *this;\n" + " }\n\n" + @@ -2903,7 +2877,7 @@ private CharSequence generateMessageFlyweightCode( " SBE_NODISCARD std::uint64_t decodeLength() const\n" + " {\n" + - " %10$s skipper(m_buffer, m_offset, m_bufferLength, sbeBlockLength(), m_actingVersion%14$s);\n" + + " %10$s skipper(m_buffer, m_offset, m_bufferLength, sbeBlockLength(), m_actingVersion);\n" + " skipper.skip();\n" + " return skipper.encodedLength();\n" + " }\n\n" + @@ -2940,14 +2914,13 @@ private CharSequence generateMessageFlyweightCode( generateConstructorsAndOperators(className, fieldPrecedenceModel), formatClassName(headerType), semanticVersion, - codecStateArgument, generateFieldOrderStateEnum(fieldPrecedenceModel), generateLookupTableDeclarations(fieldPrecedenceModel), generateFieldOrderStateMember(fieldPrecedenceModel), generateAccessOrderErrorType(fieldPrecedenceModel), - generateEncoderWrapListener(fieldPrecedenceModel), - generateDecoderWrapListener(fieldPrecedenceModel), - generateDecoderWrapListenerCall(fieldPrecedenceModel), + generateCodecStateTransitionForWrappingLatestVersion(fieldPrecedenceModel), + generateOnWrappedListener(fieldPrecedenceModel), + generateCodecStateTransitionForWrapping(fieldPrecedenceModel), generateHiddenCopyConstructor(" ", className)); } @@ -3118,7 +3091,7 @@ private static CharSequence generateFieldOrderStateMember(final FieldPrecedenceM return sb; } - private static CharSequence generateDecoderWrapListener(final FieldPrecedenceModel fieldPrecedenceModel) + private static CharSequence generateOnWrappedListener(final FieldPrecedenceModel fieldPrecedenceModel) { if (null == fieldPrecedenceModel) { @@ -3131,7 +3104,7 @@ private static CharSequence generateDecoderWrapListener(final FieldPrecedenceMod } final StringBuilder sb = new StringBuilder(); - sb.append(INDENT).append("void onWrapForDecode(std::uint64_t actingVersion)\n") + sb.append(INDENT).append("void onWrapped(std::uint64_t actingVersion)\n") .append(INDENT).append("{\n"); final MutableBoolean actingVersionCanBeTooLowToBeValid = new MutableBoolean(true); @@ -3168,7 +3141,7 @@ private static CharSequence generateDecoderWrapListener(final FieldPrecedenceMod } - private CharSequence generateDecoderWrapListenerCall(final FieldPrecedenceModel fieldPrecedenceModel) + private CharSequence generateCodecStateTransitionForWrapping(final FieldPrecedenceModel fieldPrecedenceModel) { if (null == fieldPrecedenceModel) { @@ -3185,10 +3158,12 @@ private CharSequence generateDecoderWrapListenerCall(final FieldPrecedenceModel return sb; } - return generateAccessOrderListenerCall(fieldPrecedenceModel, TWO_INDENT, "onWrapForDecode", "actingVersion"); + return generateAccessOrderListenerCall(fieldPrecedenceModel, TWO_INDENT, "onWrapped", "actingVersion"); } - private CharSequence generateEncoderWrapListener(final FieldPrecedenceModel fieldPrecedenceModel) + private CharSequence generateCodecStateTransitionForWrappingLatestVersion( + final FieldPrecedenceModel fieldPrecedenceModel + ) { if (null == fieldPrecedenceModel) { diff --git a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp index ef2b58d75c..24ad58c9b8 100644 --- a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp +++ b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include "gtest/gtest.h" #include "gmock/gmock.h" #include "order_check/MultipleVarLength.h" @@ -4955,3 +4956,95 @@ TEST_F(FieldAccessOrderCheckTest, allowsSkippingFutureGroupWhenDecodingFromVersi EXPECT_EQ(decoder.a(), 42); EXPECT_EQ(decoder.getBAsString(), "abc"); } + +TEST_F(FieldAccessOrderCheckTest, worksWithWrappingConstructors1) +{ + MultipleVarLength encoder(m_buffer, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder(m_buffer, BUFFER_LEN); + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.getBAsString(), "abc"); + EXPECT_EQ(decoder.getCAsString(), "def"); +} + +TEST_F(FieldAccessOrderCheckTest, worksWithWrappingConstructors2) +{ + MultipleVarLength encoder( + m_buffer, + BUFFER_LEN, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion() + ); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder( + m_buffer, + BUFFER_LEN, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion() + ); + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.getBAsString(), "abc"); + EXPECT_EQ(decoder.getCAsString(), "def"); +} + +TEST_F(FieldAccessOrderCheckTest, worksWithWrappingConstructors3) +{ + MultipleVarLength encoder( + m_buffer, + OFFSET, + BUFFER_LEN, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion() + ); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder( + m_buffer, + OFFSET, + BUFFER_LEN, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion() + ); + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.getBAsString(), "abc"); + EXPECT_EQ(decoder.getCAsString(), "def"); +} + +TEST_F(FieldAccessOrderCheckTest, worksWithInsertionOperator) +{ + MultipleVarLength encoder( + m_buffer, + OFFSET, + BUFFER_LEN, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion() + ); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder( + m_buffer, + BUFFER_LEN + ); + std::stringstream stream; + stream << decoder; + + const std::string expected = "\"a\": 42, \"b\": \"abc\", \"c\": \"def\""; + EXPECT_THAT(stream.str(), HasSubstr(expected)); + EXPECT_EQ(decoder.a(), 42); + EXPECT_EQ(decoder.getBAsString(), "abc"); + EXPECT_EQ(decoder.getCAsString(), "def"); +} From 91813eafd488ee47f43054f8efcd63ab1ab00249 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 11 Dec 2024 12:02:05 +0000 Subject: [PATCH 1282/1594] Fix warning about used args in GolangFlyweightGenerator. --- .../golang/flyweight/GolangFlyweightGenerator.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java index de9d86f8cc..8d824112fc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java @@ -2236,7 +2236,7 @@ private CharSequence generateMessageFlyweightCode( " %10$sSbeTemplateID %3$s = %4$s\n" + " %10$sSbeSchemaID %5$s = %6$s\n" + " %10$sSbeSchemaVersion %7$s = %8$s\n" + - " %10$sSbeSemanticVersion string = \"%13$s\"\n" + + " %10$sSbeSemanticVersion string = \"%11$s\"\n" + " )\n\n" + " func (m *%10$s) SbeBlockLength() %1$s {\n" + @@ -2260,7 +2260,7 @@ private CharSequence generateMessageFlyweightCode( " }\n\n" + " func (m *%10$s) SbeSemanticVersion() string {\n" + - " return \"%13$s\"\n" + + " return \"%11$s\"\n" + " }\n\n" + " func (m *%10$s) SbeSemanticType() string {\n" + @@ -2375,9 +2375,8 @@ private CharSequence generateMessageFlyweightCode( generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), semanticType, className, - generateConstructorsAndOperators(className), - formatClassName(headerType), - semanticVersion)); + generateConstructorsAndOperators(className))); + return sb.toString(); } From fad6442a3c7627442368277a2489dbfb75c2eb36 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 11 Dec 2024 12:11:44 +0000 Subject: [PATCH 1283/1594] Fix warning about used args in GolangFlyweightGenerator. --- .../generation/golang/flyweight/GolangFlyweightGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java index 8d824112fc..5a44da3e67 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java @@ -2375,7 +2375,7 @@ private CharSequence generateMessageFlyweightCode( generateLiteral(ir.headerStructure().schemaVersionType(), Integer.toString(ir.version())), semanticType, className, - generateConstructorsAndOperators(className))); + semanticVersion)); return sb.toString(); } From bcb2e06b426e9408eba7a2f22fd97c58752dd358 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 11 Dec 2024 12:25:18 +0000 Subject: [PATCH 1284/1594] Fix warning about used variable in GolangFlyweightGenerator. --- .../generation/golang/flyweight/GolangFlyweightGenerator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java index 5a44da3e67..259c461408 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java @@ -2174,7 +2174,6 @@ private CharSequence generateMessageFlyweightCode( final String schemaIdType = goTypeName(ir.headerStructure().schemaIdType()); final String schemaVersionType = goTypeName(ir.headerStructure().schemaVersionType()); final String semanticType = token.encoding().semanticType() == null ? "" : token.encoding().semanticType(); - final String headerType = ir.headerStructure().tokens().get(0).name(); final String semanticVersion = ir.semanticVersion() == null ? "" : ir.semanticVersion(); sb.append(" buffer []byte\n" + From 3199ae72b7077ce862236ea961b5b1657349907b Mon Sep 17 00:00:00 2001 From: Nate Bradac <38217740+nbradac@users.noreply.github.com> Date: Fri, 13 Dec 2024 10:26:42 -0500 Subject: [PATCH 1285/1594] [C++] hide the m_codecStatePtr behind ifdefs to avoid overhead when precedence checking is disabled (#1036) --- .../sbe/generation/cpp/CppGenerator.java | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 846a289e11..99f00e0ffc 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -694,6 +694,7 @@ private void generateGroupClassHeader( if (null != fieldPrecedenceModel) { + sb.append("#if defined(").append(precedenceChecksFlagName).append(")\n"); new Formatter(sb).format( indent + " CodecState *m_codecStatePtr = nullptr;\n\n" + @@ -710,19 +711,38 @@ private void generateGroupClassHeader( indent + " void codecState(CodecState codecState)\n" + indent + " {\n" + indent + " *m_codecStatePtr = codecState;\n" + - indent + " }\n\n" + indent + " }\n" ); + sb.append("#else\n"); + new Formatter(sb).format( + indent + " CodecState codecState() const SBE_NOEXCEPT\n" + + indent + " {\n" + + indent + " return " + qualifiedStateCase(fieldPrecedenceModel.notWrappedState()) + ";\n" + + indent + " }\n\n" + + + indent + " CodecState *codecStatePtr()\n" + + indent + " {\n" + + indent + " return nullptr;\n" + + indent + " }\n\n" + + + indent + " void codecState(CodecState codecState)\n" + + indent + " {\n" + + indent + " }\n" + ); + sb.append("#endif\n\n"); } sb.append(generateHiddenCopyConstructor(indent + " ", groupClassName)); final String codecStateParameter = null == fieldPrecedenceModel ? ")\n" : - ",\n " + indent + " CodecState *codecState)\n"; + ",\n" + indent + " CodecState *codecState)\n"; final String codecStateAssignment = null == fieldPrecedenceModel ? "" : - indent + " m_codecStatePtr = codecState;\n"; + "#if defined(" + precedenceChecksFlagName + ")\n" + + indent + " m_codecStatePtr = codecState;\n" + + "#endif\n"; new Formatter(sb).format( indent + "public:\n" + @@ -802,7 +822,9 @@ private void generateGroupClassHeader( { final String codecStateNullAssignment = null == fieldPrecedenceModel ? "" : - indent + " m_codecStatePtr = nullptr;\n"; + "#if defined(" + precedenceChecksFlagName + ")\n" + + indent + " m_codecStatePtr = nullptr;\n" + + "#endif\n"; new Formatter(sb).format( indent + " inline void notPresent(std::uint64_t actingVersion)\n" + From 75a56d5f262e714eea189533533c73e13e35ed9f Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Fri, 13 Dec 2024 09:44:13 -0600 Subject: [PATCH 1286/1594] [Rust] Updated code generator to resolve Issue #1028 (#1037) * [Rust] updated LibRsDef.generate() to add "#![allow(clippy::all)]" * [Rust] generating 'From for PRIMITIVE' instead of 'Into for ENUM' to satisfy 'from_over_into' lint * [Rust] removed unused method parameter * fixed formatting * [Rust] Updated code generator to resolve Issue #1022 * [Rust] meant issue #1028 not 1022 (renamed files accordingly) --------- Co-authored-by: Michael Ward --- build.gradle | 3 +- rust/Cargo.toml | 1 + .../sbe/generation/rust/RustGenerator.java | 2 +- sbe-tool/src/test/resources/issue1028.xml | 30 +++++++++++++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 sbe-tool/src/test/resources/issue1028.xml diff --git a/build.gradle b/build.gradle index 9641c9972f..6a20ee7201 100644 --- a/build.gradle +++ b/build.gradle @@ -653,6 +653,7 @@ tasks.register('generateRustTestCodecs', JavaExec) { 'sbe-tool/src/test/resources/issue972.xml', 'sbe-tool/src/test/resources/issue984.xml', 'sbe-tool/src/test/resources/issue987.xml', + 'sbe-tool/src/test/resources/issue1028.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', 'sbe-tool/src/test/resources/nested-composite-name.xml', ] @@ -866,7 +867,7 @@ tasks.register('generateGolangCodecs') { 'generateGolangFlyweightCodecTestComposite', 'generateGolangFlyweightCodecsWithXIncludes', 'generateGolangFlyweightCodecsWithXSD', - 'generateIrCodecs', + 'generateIrCodecs', ':sbe-all:jar' } diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 6b265a3020..f15d4d2f6d 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -16,6 +16,7 @@ issue_895 = { path = "../generated/rust/issue895" } issue_972 = { path = "../generated/rust/issue972" } issue_984 = { path = "../generated/rust/issue984" } issue_987 = { path = "../generated/rust/issue987" } +issue_1028 = { path = "../generated/rust/issue1028" } baseline_bigendian = { path = "../generated/rust/baseline-bigendian" } nested_composite_name = { path = "../generated/rust/nested-composite-name" } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 0c03766553..f78899cb4b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1580,7 +1580,7 @@ private static void generateCompositeDecoder( indent(out, 2, "offset: usize,\n"); indent(out, 1, "}\n\n"); - final int version = tokens.stream().findFirst().get().version(); + final int version = tokens.get(1).version(); // skip BEGIN_COMPOSITE appendImplReaderForComposite(schemaVersionType, version, out, 1, decoderName); // impl<'a, P> start diff --git a/sbe-tool/src/test/resources/issue1028.xml b/sbe-tool/src/test/resources/issue1028.xml new file mode 100644 index 0000000000..2a88c59c1b --- /dev/null +++ b/sbe-tool/src/test/resources/issue1028.xml @@ -0,0 +1,30 @@ + + + + 0 + + + + + + + + + + + + + + + + \ No newline at end of file From 1d6e3f1688678ababa7b8119c16c1636c581636f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 13 Dec 2024 17:26:12 +0100 Subject: [PATCH 1287/1594] [Java] Upgrade to Checkstyle 10.21.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5cbe7ecda4..ec0df3ab1c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "1.23.1" -checkstyle = "10.20.2" +checkstyle = "10.21.0" junit = "5.11.3" jmh = "1.37" gradle = "8.11.1" From ec42a79fab4eadc5fc248c06fef453a39258573d Mon Sep 17 00:00:00 2001 From: Nate Bradac <38217740+nbradac@users.noreply.github.com> Date: Mon, 16 Dec 2024 15:09:02 -0500 Subject: [PATCH 1288/1594] Std span (#1038) * [C++] Integrate std::span support for flyweight API The impetus was a bug that we ran into when writing a string-literal to a fixed-width char field: ```c++ flyweight.putFixedChar("hello"); ``` This is unsafe: - If the field size is less than 6, we overrun the buffer and corrupt it. - If the field size is more than 6, we don't zero pad the rest of it. Instead, we build on support for the std::string_view getters and setters, which do length checking. std::span generalizes this to fixed-width fields of all types. Notably, if the size of the std::span is knowable at compile time, we pay no runtime cost for the length checking, and we should get similar performance to the existing API which takes a raw pointer. Further, we add a sbetool option to disable accepting arrays by raw pointer, which should prevent memcpy operation without bounds checking. This is off by default to avoid a breaking change. * [C++] hide USE_SPAN behind ENABLE_SPAN * [C++] add macro guards --------- Co-authored-by: Matt Stern --- .../sbe/generation/cpp/CppGenerator.java | 138 +++++++++++++++++- sbe-tool/src/test/cpp/CMakeLists.txt | 13 +- sbe-tool/src/test/cpp/CodeGenTest.cpp | 62 ++++++++ 3 files changed, 207 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 99f00e0ffc..b8d427241a 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -49,6 +49,8 @@ public class CppGenerator implements CodeGenerator { private static final boolean DISABLE_IMPLICIT_COPYING = Boolean.parseBoolean( System.getProperty("sbe.cpp.disable.implicit.copying", "false")); + private static final boolean DISABLE_RAW_ARRAYS = Boolean.parseBoolean( + System.getProperty("sbe.cpp.disable.raw.arrays", "false")); private static final String BASE_INDENT = ""; private static final String INDENT = " "; private static final String TWO_INDENT = INDENT + INDENT; @@ -1634,6 +1636,23 @@ private static CharSequence generateArrayFieldNotPresentCondition(final int sinc sinceVersion); } + private static CharSequence generateSpanFieldNotPresentCondition( + final int sinceVersion, final String indent, final String cppTypeName) + { + if (0 == sinceVersion) + { + return ""; + } + + return String.format( + indent + " if (m_actingVersion < %1$d)\n" + + indent + " {\n" + + indent + " return std::span();\n" + + indent + " }\n\n", + sinceVersion, + cppTypeName); + } + private static CharSequence generateStringNotPresentCondition(final int sinceVersion, final String indent) { if (0 == sinceVersion) @@ -1703,10 +1722,20 @@ private CharSequence generateFileHeader( "#if __cplusplus >= 201703L\n" + "# include \n" + "# define SBE_NODISCARD [[nodiscard]]\n" + + "# if !defined(SBE_USE_STRING_VIEW)\n" + + "# define SBE_USE_STRING_VIEW 1\n" + + "# endif\n" + "#else\n" + "# define SBE_NODISCARD\n" + "#endif\n\n" + + "#if __cplusplus >= 202002L\n" + + "# include \n" + + "# if !defined(SBE_USE_SPAN)\n" + + "# define SBE_USE_SPAN 1\n" + + "# endif\n" + + "#endif\n\n" + + "#if !defined(__STDC_LIMIT_MACROS)\n" + "# define __STDC_LIMIT_MACROS 1\n" + "#endif\n\n" + @@ -2258,12 +2287,38 @@ private void generateArrayProperty( accessOrderListenerCall); new Formatter(sb).format("\n" + - indent + " %1$s &put%2$s(const char *const src)%7$s\n" + + indent + " #ifdef SBE_USE_SPAN\n" + + indent + " SBE_NODISCARD std::span get%1$sAsSpan() const%7$s\n" + + indent + " {\n" + + "%3$s" + + "%6$s" + + indent + " const char *buffer = m_buffer + m_offset + %4$d;\n" + + indent + " return std::span(reinterpret_cast(buffer), %2$d);\n" + + indent + " }\n" + + indent + " #endif\n", + toUpperFirstChar(propertyName), + arrayLength, + generateSpanFieldNotPresentCondition(propertyToken.version(), indent, cppTypeName), + offset, + cppTypeName, + accessOrderListenerCall, + noexceptDeclaration); + + new Formatter(sb).format("\n" + + indent + " #ifdef SBE_USE_SPAN\n" + + indent + " template \n" + + indent + " %1$s &put%2$s(std::span src)%7$s\n" + indent + " {\n" + + indent + " static_assert(N <= %5$d, \"array too large for put%2$s\");\n\n" + "%6$s" + - indent + " std::memcpy(m_buffer + m_offset + %3$d, src, sizeof(%4$s) * %5$d);\n" + + indent + " std::memcpy(m_buffer + m_offset + %3$d, src.data(), sizeof(%4$s) * N);\n" + + indent + " for (std::size_t start = N; start < %5$d; ++start)\n" + + indent + " {\n" + + indent + " m_buffer[m_offset + %3$d + start] = 0;\n" + + indent + " }\n\n" + indent + " return *this;\n" + - indent + " }\n", + indent + " }\n" + + indent + " #endif\n", containingClassName, toUpperFirstChar(propertyName), offset, @@ -2272,6 +2327,79 @@ private void generateArrayProperty( accessOrderListenerCall, noexceptDeclaration); + if (encodingToken.encoding().primitiveType() != PrimitiveType.CHAR) + { + new Formatter(sb).format("\n" + + indent + " #ifdef SBE_USE_SPAN\n" + + indent + " %1$s &put%2$s(std::span src)\n" + + indent + " {\n" + + indent + " const std::size_t srcLength = src.size();\n" + + indent + " if (srcLength > %5$d)\n" + + indent + " {\n" + + indent + " throw std::runtime_error(\"array too large for put%2$s [E106]\");\n" + + indent + " }\n\n" + + + "%6$s" + + indent + " std::memcpy(m_buffer + m_offset + %3$d, src.data(), sizeof(%4$s) * srcLength);\n" + + indent + " for (std::size_t start = srcLength; start < %5$d; ++start)\n" + + indent + " {\n" + + indent + " m_buffer[m_offset + %3$d + start] = 0;\n" + + indent + " }\n\n" + + indent + " return *this;\n" + + indent + " }\n" + + indent + " #endif\n", + containingClassName, + toUpperFirstChar(propertyName), + offset, + cppTypeName, + arrayLength, + accessOrderListenerCall); + } + + if (!DISABLE_RAW_ARRAYS) + { + new Formatter(sb).format("\n" + + indent + " #ifdef SBE_USE_SPAN\n" + + indent + " template \n" + + // If std::span is available, redirect string literals to the std::span-accepting overload, + // where we can do compile-time bounds checking. + indent + " %1$s &put%2$s(T&& src) %7$s requires\n" + + indent + " (std::is_pointer_v> &&\n" + + indent + " !std::is_array_v>)\n" + + indent + " #else\n" + + indent + " %1$s &put%2$s(const char *const src)%7$s\n" + + indent + " #endif\n" + + indent + " {\n" + + "%6$s" + + indent + " std::memcpy(m_buffer + m_offset + %3$d, src, sizeof(%4$s) * %5$d);\n" + + indent + " return *this;\n" + + indent + " }\n", + containingClassName, + toUpperFirstChar(propertyName), + offset, + cppTypeName, + arrayLength, + accessOrderListenerCall, + noexceptDeclaration); + + } + if (encodingToken.encoding().primitiveType() == PrimitiveType.CHAR) + { + // Resolve ambiguity of string literal arguments, which match both + // std::span and std::string_view overloads. + new Formatter(sb).format("\n" + + indent + " #ifdef SBE_USE_SPAN\n" + + indent + " template \n" + + indent + " %1$s &put%2$s(const char (&src)[N])%3$s\n" + + indent + " {\n" + + indent + " return put%2$s(std::span(src));\n" + + indent + " }\n" + + indent + " #endif\n", + containingClassName, + toUpperFirstChar(propertyName), + noexceptDeclaration); + } + if (arrayLength > 1 && arrayLength <= 4) { sb.append("\n").append(indent).append(" ") @@ -2332,7 +2460,7 @@ private void generateArrayProperty( generateJsonEscapedStringGetter(sb, encodingToken, indent, propertyName); new Formatter(sb).format("\n" + - indent + " #if __cplusplus >= 201703L\n" + + indent + " #ifdef SBE_USE_STRING_VIEW\n" + indent + " SBE_NODISCARD std::string_view get%1$sAsStringView() const%6$s\n" + indent + " {\n" + "%4$s" + @@ -2354,7 +2482,7 @@ private void generateArrayProperty( noexceptDeclaration); new Formatter(sb).format("\n" + - indent + " #if __cplusplus >= 201703L\n" + + indent + " #ifdef SBE_USE_STRING_VIEW\n" + indent + " %1$s &put%2$s(const std::string_view str)\n" + indent + " {\n" + indent + " const std::size_t srcLength = str.length();\n" + diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index 1de7412623..b3271dade0 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -103,6 +103,11 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") sbe_test(DtoTest codecs) target_compile_features(DtoTest PRIVATE cxx_std_17) endif() + + # Check if the GCC version supports C++20 + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "11.0") + target_compile_features(CodeGenTest PRIVATE cxx_std_20) + endif() endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "CLang") @@ -111,12 +116,18 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "CLang") sbe_test(DtoTest codecs) target_compile_features(DtoTest PRIVATE cxx_std_17) endif() + + # Check if CLang version supports C++20 + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "10.0") + target_compile_features(CodeGenTest PRIVATE cxx_std_20) + endif() endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - # Check if MSVC version supports C++17 + # Check if MSVC version supports C++17 / C++20 if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "19.14") sbe_test(DtoTest codecs) target_compile_options(DtoTest PRIVATE /std:c++17) + target_compile_options(CodeGenTest PRIVATE /std:c++20) endif() endif() diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index ea00b8120c..039620a6c1 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -1083,3 +1083,65 @@ TEST_F(CodeGenTest, shouldAllowForMultipleIterations) std::string passFive = walkCar(carDecoder); EXPECT_EQ(passOne, passFive); } + +#ifdef SBE_USE_STRING_VIEW +TEST_F(CodeGenTest, shouldBeAbleToUseStdStringViewMethods) +{ + std::string vehicleCode(VEHICLE_CODE, Car::vehicleCodeLength()); + + char buffer[BUFFER_LEN] = {}; + std::uint64_t baseOffset = MessageHeader::encodedLength(); + Car car; + car.wrapForEncode(buffer, baseOffset, sizeof(buffer)); + car.putVehicleCode(std::string_view(vehicleCode)); + + car.sbeRewind(); + EXPECT_EQ(car.getVehicleCodeAsStringView(), vehicleCode); +} +#endif + +#ifdef SBE_USE_SPAN +TEST_F(CodeGenTest, shouldBeAbleToUseStdSpanViewMethods) +{ + char buffer[BUFFER_LEN] = {}; + + std::uint64_t baseOffset = MessageHeader::encodedLength(); + Car car; + car.wrapForEncode(buffer, baseOffset, sizeof(buffer)); + + { + std::array numbers; + for (std::uint64_t i = 0; i < Car::someNumbersLength(); i++) + { + numbers[i] = static_cast(i); + } + car.putSomeNumbers(numbers); + } + + car.sbeRewind(); + + { + std::span numbers = car.getSomeNumbersAsSpan(); + ASSERT_EQ(numbers.size(), Car::someNumbersLength()); + for (std::uint64_t i = 0; i < numbers.size(); i++) + { + EXPECT_EQ(numbers[i], static_cast(i)); + } + } +} +#endif + +#ifdef SBE_USE_SPAN +TEST_F(CodeGenTest, shouldBeAbleToResolveStringLiterals) +{ + char buffer[BUFFER_LEN] = {}; + + std::uint64_t baseOffset = MessageHeader::encodedLength(); + Car car; + car.wrapForEncode(buffer, baseOffset, sizeof(buffer)); + car.putVehicleCode("ABCDE"); + + car.sbeRewind(); + EXPECT_EQ(car.getVehicleCodeAsStringView(), "ABCDE"); +} +#endif \ No newline at end of file From 658838ed3534dd8f53dd513ca54444d3379748b7 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:11:50 +0100 Subject: [PATCH 1289/1594] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 26efe26f10..b286d72970 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Example for Maven: ```xml     uk.co.real-logic -    sbe-all +    sbe-tool     ${sbe.tool.version} ``` From 633fe63dd569fe0fd5f75e69c16d42c9eed9d265 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 16 Dec 2024 22:28:10 +0100 Subject: [PATCH 1290/1594] [Java] Upgrade to JUnit 5.11.4. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ec0df3ab1c..0f911604c5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] agrona = "1.23.1" checkstyle = "10.21.0" -junit = "5.11.3" +junit = "5.11.4" jmh = "1.37" gradle = "8.11.1" From 268fde019391b01b6915cb469bc66ef0de869bc5 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 17 Dec 2024 14:49:31 +0100 Subject: [PATCH 1291/1594] [Java] Upgrade to Agrona 2.0.0. --- build.gradle | 2 ++ gradle/libs.versions.toml | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 6a20ee7201..dbcc35fdaa 100644 --- a/build.gradle +++ b/build.gradle @@ -217,6 +217,7 @@ subprojects { all { testTask.configure { useJUnitPlatform() + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') testLogging { for (def level : LogLevel.values()) @@ -303,6 +304,7 @@ project(':sbe-tool') { minHeapSize = '2g' maxHeapSize = '2g' + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') javaLauncher.set(toolchainLauncher) systemProperty 'sbe.dll', "${rootProject.projectDir}/csharp/sbe-dll/bin/Release/netstandard2.0/SBE.dll" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0f911604c5..b433f94282 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,12 +1,12 @@ [versions] -agrona = "1.23.1" +agrona = "2.0.0" checkstyle = "10.21.0" junit = "5.11.4" jmh = "1.37" gradle = "8.11.1" [libraries] -agrona = { group = "org.agrona", name = "agrona", version = { strictly = "[1.23.1, 2.0[", require = "1.23.1" } } +agrona = { group = "org.agrona", name = "agrona", version.ref = "agrona" } mockito = { group = "org.mockito", name = "mockito-core", version = "5.14.2" } hamcrest = { group = "org.hamcrest", name = "hamcrest", version = "3.0" } jqwik = { group = "net.jqwik", name = "jqwik", version = "1.9.2" } From c2e9cb4674f4e18d0d2304321215db34b65a8e69 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 17 Dec 2024 14:52:53 +0100 Subject: [PATCH 1292/1594] 1.34.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 6214e03b71..2b17ffd504 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.34.0-SNAPSHOT +1.34.0 From 6b37857c77d1a2a775a932a1242b2c13acca91a8 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 17 Dec 2024 14:53:04 +0100 Subject: [PATCH 1293/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 2b17ffd504..c9c35c012f 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.34.0 +1.35.0-SNAPSHOT From b848b3a670835197afa9d0373794858825e9aab1 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:11:39 +0100 Subject: [PATCH 1294/1594] [Java] Add JVM opts to generator tasks. --- build.gradle | 47 +++++++++++++++++++++++++++++++++++++++-------- version.txt | 2 +- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index dbcc35fdaa..f4c65045ba 100644 --- a/build.gradle +++ b/build.gradle @@ -319,6 +319,7 @@ project(':sbe-tool') { dependsOn 'compileJava' mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': generatedDir, 'sbe.target.language': 'Java', @@ -335,6 +336,7 @@ project(':sbe-tool') { dependsOn 'compileJava' mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': generatedDir, 'sbe.target.language': 'java', @@ -480,7 +482,7 @@ project(':sbe-samples') { sourceSets { generated { java.srcDir generatedDir - compileClasspath += project(':sbe-all').sourceSets.main.runtimeClasspath + compileClasspath += project(':sbe-tool').sourceSets.main.runtimeClasspath } } @@ -489,7 +491,8 @@ project(':sbe-samples') { tasks.register('generateCodecs', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': generatedDir, 'sbe.target.language': 'Java', @@ -505,6 +508,7 @@ project(':sbe-samples') { dependsOn 'compileJava' mainClass.set('uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub') classpath = sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties System.getProperties() } @@ -512,6 +516,7 @@ project(':sbe-samples') { dependsOn 'compileJava' mainClass.set('uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension') classpath = sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties System.getProperties() } @@ -519,6 +524,7 @@ project(':sbe-samples') { dependsOn 'compileJava' mainClass.set('uk.co.real_logic.sbe.examples.OtfExample') classpath = sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') workingDir = 'src/main/resources' } @@ -596,7 +602,7 @@ project(':sbe-benchmarks') { sourceSets { generated { java.srcDir 'build/generated-src' - compileClasspath += project(':sbe-all').sourceSets.main.runtimeClasspath + compileClasspath += project(':sbe-tool').sourceSets.main.runtimeClasspath } } @@ -605,7 +611,8 @@ project(':sbe-benchmarks') { tasks.register('generateCodecs', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'build/generated-src', 'sbe.target.language': 'Java', @@ -629,7 +636,8 @@ project(':sbe-benchmarks') { tasks.register('generateRustExamples', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'generated/rust', 'sbe.xinclude.aware': 'true', @@ -644,7 +652,8 @@ tasks.register('generateRustExamples', JavaExec) { tasks.register('generateRustTestCodecs', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'generated/rust', 'sbe.xinclude.aware': 'true', @@ -664,6 +673,7 @@ tasks.register('generateRustTestCodecs', JavaExec) { tasks.register('generateCarExampleDataFile', JavaExec) { mainClass.set('uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub') classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties('sbe.encoding.filename': 'rust/car_example_baseline_data.sbe') args = [] standardOutput = new ByteArrayOutputStream() @@ -672,6 +682,7 @@ tasks.register('generateCarExampleDataFile', JavaExec) { tasks.register('generateCarExampleExtensionDataFile', JavaExec) { mainClass.set('uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension') classpath = project(':sbe-samples').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties('sbe.encoding.filename': 'rust/car_example_extension_data.sbe') args = [] standardOutput = new ByteArrayOutputStream() @@ -702,6 +713,7 @@ tasks.register('runRustTests', Exec) { tasks.register('generateGolangCodecTestComposite', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'gocode/struct/src', 'sbe.target.language': 'golang') @@ -711,6 +723,7 @@ tasks.register('generateGolangCodecTestComposite', JavaExec) { tasks.register('generateGolangCodecTestBasic', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'gocode/struct/src/basic', 'sbe.target.language': 'golang') @@ -720,6 +733,7 @@ tasks.register('generateGolangCodecTestBasic', JavaExec) { tasks.register('generateGolangCodecTestGroup', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'gocode/struct/src/group', 'sbe.target.language': 'golang') @@ -728,6 +742,7 @@ tasks.register('generateGolangCodecTestGroup', JavaExec) { tasks.register('generateGolangCodecTestVarData', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath systemProperties( 'sbe.output.dir': 'gocode/struct/src/vardata', @@ -738,6 +753,7 @@ tasks.register('generateGolangCodecTestVarData', JavaExec) { tasks.register('generateGolangCodecsWithXIncludes', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'gocode/struct/src', 'sbe.target.language': 'golang', @@ -750,6 +766,7 @@ tasks.register('generateGolangCodecsWithXIncludes', JavaExec) { tasks.register('generateGolangCodecsWithXSD', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'gocode/struct/src', 'sbe.target.language': 'golang', @@ -776,6 +793,7 @@ tasks.register('generateGolangCodecsWithXSD', JavaExec) { tasks.register('generateGolangFlyweightCodecTestComposite', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'gocode/flyweight/src', 'sbe.go.generate.generate.flyweights': 'true', @@ -786,6 +804,7 @@ tasks.register('generateGolangFlyweightCodecTestComposite', JavaExec) { tasks.register('generateGolangFlyweightCodecTestBasic', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'gocode/flyweight/src/basic', 'sbe.go.generate.generate.flyweights': 'true', @@ -796,6 +815,7 @@ tasks.register('generateGolangFlyweightCodecTestBasic', JavaExec) { tasks.register('generateGolangFlyweightCodecTestGroup', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'gocode/flyweight/src/group', 'sbe.go.generate.generate.flyweights': 'true', @@ -806,6 +826,7 @@ tasks.register('generateGolangFlyweightCodecTestGroup', JavaExec) { tasks.register('generateGolangFlyweightCodecTestVarData', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'gocode/flyweight/src/vardata', 'sbe.go.generate.generate.flyweights': 'true', @@ -816,6 +837,7 @@ tasks.register('generateGolangFlyweightCodecTestVarData', JavaExec) { tasks.register('generateGolangFlyweightCodecsWithXIncludes', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'gocode/flyweight/src', 'sbe.go.generate.generate.flyweights': 'true', @@ -829,6 +851,7 @@ tasks.register('generateGolangFlyweightCodecsWithXIncludes', JavaExec) { tasks.register('generateGolangFlyweightCodecsWithXSD', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'gocode/flyweight/src', 'sbe.go.generate.generate.flyweights': 'true', @@ -880,6 +903,7 @@ tasks.register('generateGolangCodecs') { tasks.register('generateCSharpCodecsWithXIncludes', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'csharp/sbe-generated', 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharp', @@ -892,6 +916,7 @@ tasks.register('generateCSharpCodecsWithXIncludes', JavaExec) { tasks.register('generateCSharpTestCodecs', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'csharp/sbe-generated', 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharp', @@ -912,6 +937,7 @@ tasks.register('generateCSharpTestCodecs', JavaExec) { tasks.register('generateCSharpTestDtos', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'csharp/sbe-generated', 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharpDtos', @@ -924,6 +950,7 @@ tasks.register('generateCSharpTestDtos', JavaExec) { tasks.register('generateCSharpExplicitPackageOverrideCodecs', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'csharp/sbe-generated', 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharp', @@ -936,6 +963,7 @@ tasks.register('generateCSharpExplicitPackageOverrideCodecs', JavaExec) { tasks.register('generateCSharpExplicitPackageOverrideDtos', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'csharp/sbe-generated', 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharpDtos', @@ -956,7 +984,8 @@ tasks.register('generateCSharpCodecs') { tasks.register('generateJavaIrCodecs', JavaExec) { dependsOn 'computeOriginalIrHash' mainClass.set('uk.co.real_logic.sbe.SbeTool') - classpath = project(':sbe-all').sourceSets.main.runtimeClasspath + classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/java', 'sbe.target.language': 'Java', @@ -970,6 +999,7 @@ tasks.register('generateJavaIrCodecs', JavaExec) { tasks.register('generateCppIrCodecs', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/cpp', 'sbe.target.language': 'cpp', @@ -982,6 +1012,7 @@ tasks.register('generateCppIrCodecs', JavaExec) { tasks.register('generateGolangIrCodecs', JavaExec) { mainClass.set('uk.co.real_logic.sbe.SbeTool') classpath = project(':sbe-tool').sourceSets.main.runtimeClasspath + jvmArgs('--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED') systemProperties( 'sbe.output.dir': 'sbe-tool/src/main/golang', 'sbe.target.language': 'golang', @@ -999,7 +1030,7 @@ tasks.register('runJavaBenchmarks', Exec) { dependsOn 'sbe-benchmarks:jar' commandLine toolchainLauncher.get().executablePath, '-jar', 'sbe-benchmarks/build/libs/sbe-benchmarks.jar', - '-jvmArgs', '-Dagrona.disable.bounds.checks=true -XX:+UseParallelGC', + '-jvmArgs', '-Dagrona.disable.bounds.checks=true -XX:+UseParallelGC --add-opens java.base/jdk.internal.misc=ALL-UNNAMED', '-w', '1s', '-r', '1s', '-wi', '3', '-i', '5', '-tu', 'ns', '-f', '5' } diff --git a/version.txt b/version.txt index c9c35c012f..6214e03b71 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.35.0-SNAPSHOT +1.34.0-SNAPSHOT From 949d23481c03099acf6682c64707ea5a034a80b3 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:24:42 +0100 Subject: [PATCH 1295/1594] [C] Add missing JVM options to allow generating codes. --- sbe-benchmarks/src/main/cpp/CMakeLists.txt | 2 +- sbe-samples/src/main/cpp/CMakeLists.txt | 2 +- sbe-tool/src/main/cpp/CMakeLists.txt | 2 +- sbe-tool/src/test/c/CMakeLists.txt | 2 +- sbe-tool/src/test/cpp/CMakeLists.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sbe-benchmarks/src/main/cpp/CMakeLists.txt b/sbe-benchmarks/src/main/cpp/CMakeLists.txt index 085e8bf224..055ea4f63a 100644 --- a/sbe-benchmarks/src/main/cpp/CMakeLists.txt +++ b/sbe-benchmarks/src/main/cpp/CMakeLists.txt @@ -39,7 +39,7 @@ set(SBE_MD_SCHEMA ${CODEC_PERF_SCHEMA_DIR}/fix-message-samples.xml) add_custom_command( OUTPUT ${GENERATED_CODECS} DEPENDS ${SBE_CAR_SCHEMA} ${SBE_MD_SCHEMA} sbe-jar ${SBE_JAR} - COMMAND ${Java_JAVA_EXECUTABLE} -Dsbe.output.dir=${CXX_CODEC_TARGET_DIR} -Dsbe.target.language="cpp" -jar ${SBE_JAR} ${SBE_CAR_SCHEMA} ${SBE_MD_SCHEMA} + COMMAND ${Java_JAVA_EXECUTABLE} --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.output.dir=${CXX_CODEC_TARGET_DIR} -Dsbe.target.language="cpp" -jar ${SBE_JAR} ${SBE_CAR_SCHEMA} ${SBE_MD_SCHEMA} ) add_custom_target(perf_codecs DEPENDS ${GENERATED_CODECS}) diff --git a/sbe-samples/src/main/cpp/CMakeLists.txt b/sbe-samples/src/main/cpp/CMakeLists.txt index dd6a5f0b32..2e0a6c8d16 100644 --- a/sbe-samples/src/main/cpp/CMakeLists.txt +++ b/sbe-samples/src/main/cpp/CMakeLists.txt @@ -24,7 +24,7 @@ set(EXAMPLES_SCHEMA ${CODEC_EXAMPLES_SCHEMA_DIR}/example-schema.xml) add_custom_command( OUTPUT ${GENERATED_CODECS} DEPENDS ${EXAMPLES_SCHEMA} sbe-jar ${SBE_JAR} - COMMAND ${Java_JAVA_EXECUTABLE} -Dsbe.output.dir=${CXX_CODEC_TARGET_DIR} -Dsbe.generate.ir=true -Dsbe.target.language=cpp -Dsbe.xinclude.aware=true -jar ${SBE_JAR} ${EXAMPLES_SCHEMA} + COMMAND ${Java_JAVA_EXECUTABLE} --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.output.dir=${CXX_CODEC_TARGET_DIR} -Dsbe.generate.ir=true -Dsbe.target.language=cpp -Dsbe.xinclude.aware=true -jar ${SBE_JAR} ${EXAMPLES_SCHEMA} ) add_custom_target(examples_codecs DEPENDS ${GENERATED_CODECS}) diff --git a/sbe-tool/src/main/cpp/CMakeLists.txt b/sbe-tool/src/main/cpp/CMakeLists.txt index c79be7c58a..abb1f83a49 100644 --- a/sbe-tool/src/main/cpp/CMakeLists.txt +++ b/sbe-tool/src/main/cpp/CMakeLists.txt @@ -28,7 +28,7 @@ find_package(Java REQUIRED) add_custom_command(OUTPUT ${CODECS} COMMAND - ${Java_JAVA_EXECUTABLE} + ${Java_JAVA_EXECUTABLE} --add-opens java.base/jdk.internal.misc=ALL-UNNAMED "-Dsbe.output.dir=${CMAKE_CURRENT_SOURCE_DIR}" "-Dsbe.target.language=CPP" "-jar" "${SBE_JAR}" diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index e8ea222cf7..33169a501d 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -46,7 +46,7 @@ add_custom_command( OUTPUT ${GENERATED_CODECS} DEPENDS sbe-jar ${SBE_JAR} ${CODE_GENERATION_SCHEMA} ${CODE_GENERATION_SCHEMA_WITH_VERSION} ${GROUP_WITH_DATA_SCHEMA} ${ISSUE889_SCHEMA} COMMAND - ${Java_JAVA_EXECUTABLE} + ${Java_JAVA_EXECUTABLE} --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.output.dir=${C_CODEC_TARGET_DIR} -Dsbe.target.language="C" -jar ${SBE_JAR} diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index b3271dade0..ee09f3881e 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -61,7 +61,7 @@ add_custom_command( ${ACCESS_ORDER_SCHEMA} sbe-jar ${SBE_JAR} COMMAND - ${Java_JAVA_EXECUTABLE} + ${Java_JAVA_EXECUTABLE} --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.output.dir=${CXX_CODEC_TARGET_DIR} -Dsbe.generate.ir="true" -Dsbe.target.language="cpp" From 51eeefd317d817515909eac9a7bff8ead4b95136 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:31:03 +0100 Subject: [PATCH 1296/1594] [Go] Fix Go build. --- gocode/sbe-tool | 1 + 1 file changed, 1 insertion(+) diff --git a/gocode/sbe-tool b/gocode/sbe-tool index 61e4c903e1..811e0b6975 100755 --- a/gocode/sbe-tool +++ b/gocode/sbe-tool @@ -35,6 +35,7 @@ shift $(($OPTIND - 1)) [ -f "$SCHEMA" ] || (echo invalid schema "$SCHEMA"; exit 1) java \ +--add-opens java.base/jdk.internal.misc=ALL-UNNAMED \ -Dsbe.output.dir="$OUTPUTDIR" \ -Dsbe.generate.ir="false" \ -Dsbe.target.language="golang" \ From 658fcbd5fc48178b1bad22aec2dbb3191fef54dc Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:54:01 +0100 Subject: [PATCH 1297/1594] [Go] Fix Golang build. --- .github/workflows/ci.yml | 4 +--- gocode/flyweight/src/otf/otf_test.go | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23be3be93a..b0364d208e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -416,7 +416,5 @@ jobs: with: distribution: 'zulu' java-version: 17 - - name: Generate codecs - run: ./gradlew generateGolangCodecs - - name: Go + - name: Test run: cd gocode && make diff --git a/gocode/flyweight/src/otf/otf_test.go b/gocode/flyweight/src/otf/otf_test.go index babb370693..10cc0afd0e 100644 --- a/gocode/flyweight/src/otf/otf_test.go +++ b/gocode/flyweight/src/otf/otf_test.go @@ -7,7 +7,7 @@ import ( "testing" ) -//go:generate java -Dsbe.output.dir=. -Dsbe.target.language=golang -Dsbe.go.generate.generate.flyweights=true -Dsbe.generate.ir=true -jar ../../../${SBE_JAR} ../../../../sbe-tool/src/test/resources/code-generation-schema.xml +//go:generate java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.output.dir=. -Dsbe.target.language=golang -Dsbe.go.generate.generate.flyweights=true -Dsbe.generate.ir=true -jar ../../../${SBE_JAR} ../../../../sbe-tool/src/test/resources/code-generation-schema.xml const SchemaFilename = "code-generation-schema.sbeir" const MsgBufferCapacity = 4 * 1024 From f084da2e94a16bbbf185612b3ffc3ebf037fb6e7 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 17 Dec 2024 16:02:14 +0100 Subject: [PATCH 1298/1594] [Go] Generate Jar for Golang build. --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b0364d208e..81f79e5420 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -416,5 +416,7 @@ jobs: with: distribution: 'zulu' java-version: 17 - - name: Test + - name: Generate jar + run: ./gradlew assemble + - name: Run tests run: cd gocode && make From 4ff6344876366b0272c41e492b1d52757a304bb3 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 17 Dec 2024 16:06:08 +0100 Subject: [PATCH 1299/1594] 1.34.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 6214e03b71..2b17ffd504 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.34.0-SNAPSHOT +1.34.0 From 3ddb76157c30b1a4b3a954bd221992f937dc2067 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 17 Dec 2024 16:06:19 +0100 Subject: [PATCH 1300/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 2b17ffd504..c9c35c012f 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.34.0 +1.35.0-SNAPSHOT From 34f2c32c861417fb6e7d749e6ad9b401b3147c6c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 18 Dec 2024 10:12:08 +0100 Subject: [PATCH 1301/1594] [Doc] Add `--add-opens java.base/jdk.internal.misc=ALL-UNNAMED` to the example execution. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b286d72970..3b2d354d45 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ Jars for the executable, source, and javadoc for the various modules can be foun An example to execute a Jar from command line using the 'all' jar which includes the Agrona dependency: - java -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-${SBE_TOOL_VERSION}.jar my-sbe-messages.xml + java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-${SBE_TOOL_VERSION}.jar my-sbe-messages.xml C++ Build using CMake --------------------- From a1bc244d8136ee1e39d99cf3666839618dd845a6 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Mon, 30 Dec 2024 06:38:32 -0600 Subject: [PATCH 1302/1594] [Rust] encoding primitive arrays now supports slice instead of array (issue #1021) (#1040) * [Rust] codegen now implements: "From<&'a mut WriteBuf<'a>> for &'a mut [u8]" * [Rust] refactored codegen of primitive array encoding to accept slice instead of array * [Rust] updated some tests * [Rust] updated codegen to create additional function for primitive arrays that will accept an "impl Iterator". This allows an arbitrary number of items to be passed in, which will guarantee the correct number of items are encoded (defined 'nullValue' will be used where appropriate) * [Rust] generate at_most_*_items_from_slice setter for fixed sized primitive array in message * [Rust] add padded support for slice setter for primitive array field * [Rust] simplify impl of generated slice aware methods * merging in PR * [Rust] updated generator to create "_from_iter" and "_zero_padded" functions for primitive array * [Rust] updated generator to create "_from_iter" and "_zero_padded" functions for primitive array * fixed formatting issues * removed unused format argument --------- Co-authored-by: Michael Ward Co-authored-by: Elvis Wang --- build.gradle | 1 + rust/Cargo.toml | 1 + rust/tests/baseline_enum_from_str.rs | 21 +- rust/tests/extension_test.rs | 4 +- rust/tests/fixed_sized_primitive_array.rs | 1110 +++++++++++++++++ .../sbe/generation/rust/LibRsDef.java | 7 + .../sbe/generation/rust/RustGenerator.java | 218 +++- .../sbe/generation/rust/RustUtil.java | 6 + .../sbe/generation/rust/RustUtilTest.java | 3 +- .../fixed-sized-primitive-array-types.xml | 73 ++ 10 files changed, 1369 insertions(+), 75 deletions(-) create mode 100644 rust/tests/fixed_sized_primitive_array.rs create mode 100644 sbe-tool/src/test/resources/fixed-sized-primitive-array-types.xml diff --git a/build.gradle b/build.gradle index f4c65045ba..3e3b3b2ee7 100644 --- a/build.gradle +++ b/build.gradle @@ -665,6 +665,7 @@ tasks.register('generateRustTestCodecs', JavaExec) { 'sbe-tool/src/test/resources/issue984.xml', 'sbe-tool/src/test/resources/issue987.xml', 'sbe-tool/src/test/resources/issue1028.xml', + 'sbe-tool/src/test/resources/fixed-sized-primitive-array-types.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', 'sbe-tool/src/test/resources/nested-composite-name.xml', ] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index f15d4d2f6d..2d4f3d4a49 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -19,6 +19,7 @@ issue_987 = { path = "../generated/rust/issue987" } issue_1028 = { path = "../generated/rust/issue1028" } baseline_bigendian = { path = "../generated/rust/baseline-bigendian" } nested_composite_name = { path = "../generated/rust/nested-composite-name" } +fixed_sized_primitive_array = { path = "../generated/rust/fixed_sized_primitive_array" } [dev-dependencies] criterion = "0.5" diff --git a/rust/tests/baseline_enum_from_str.rs b/rust/tests/baseline_enum_from_str.rs index 4e52fd4bf9..a111d28364 100644 --- a/rust/tests/baseline_enum_from_str.rs +++ b/rust/tests/baseline_enum_from_str.rs @@ -1,21 +1,22 @@ +use BoostType::{NullVal, KERS, NITROUS, SUPERCHARGER, TURBO}; use examples_baseline::{ boost_type::BoostType, }; #[test] fn test_boost_type_from_str() -> Result<(), ()> { - assert_eq!("TURBO".parse::()?, BoostType::TURBO, "Parse \"TURBO\" as BoostType"); - assert_eq!("SUPERCHARGER".parse::()?, BoostType::SUPERCHARGER, "Parse \"SUPERCHARGER\" as BoostType"); - assert_eq!("NITROUS".parse::()?, BoostType::NITROUS, "Parse \"NITROUS\" as BoostType"); - assert_eq!("KERS".parse::()?, BoostType::KERS, "Parse \"KERS\" as BoostType"); + assert_eq!("TURBO".parse::()?, TURBO, "Parse \"TURBO\" as BoostType"); + assert_eq!("SUPERCHARGER".parse::()?, SUPERCHARGER, "Parse \"SUPERCHARGER\" as BoostType"); + assert_eq!("NITROUS".parse::()?, NITROUS, "Parse \"NITROUS\" as BoostType"); + assert_eq!("KERS".parse::()?, KERS, "Parse \"KERS\" as BoostType"); - assert_eq!("Turbo".parse::()?, BoostType::NullVal, "Parse \"Turbo\" as BoostType"); - assert_eq!("Supercharger".parse::()?, BoostType::NullVal, "Parse \"Supercharger\" as BoostType"); - assert_eq!("Nitrous".parse::()?, BoostType::NullVal, "Parse \"Nitrous\" as BoostType"); - assert_eq!("Kers".parse::()?, BoostType::NullVal, "Parse \"Kers\" as BoostType"); + assert_eq!("Turbo".parse::()?, NullVal, "Parse \"Turbo\" as BoostType"); + assert_eq!("Supercharger".parse::()?, NullVal, "Parse \"Supercharger\" as BoostType"); + assert_eq!("Nitrous".parse::()?, NullVal, "Parse \"Nitrous\" as BoostType"); + assert_eq!("Kers".parse::()?, NullVal, "Parse \"Kers\" as BoostType"); - assert_eq!("AA".parse::()?, BoostType::NullVal, "Parse \"AA\" as BoostType"); - assert_eq!("".parse::().unwrap(), BoostType::NullVal, "Parse \"\" as BoostType"); + assert_eq!("AA".parse::()?, NullVal, "Parse \"AA\" as BoostType"); + assert_eq!("".parse::().unwrap(), NullVal, "Parse \"\" as BoostType"); Ok(()) } diff --git a/rust/tests/extension_test.rs b/rust/tests/extension_test.rs index d7258bc39b..ab62a7715c 100644 --- a/rust/tests/extension_test.rs +++ b/rust/tests/extension_test.rs @@ -187,7 +187,7 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { car.available(BooleanType::T); car.code(Model::A); car.some_numbers(&[0, 1, 2, 3]); - car.vehicle_code(&[97, 98, 99, 100, 101, 102]); // abcdef + car.vehicle_code_from_iter(b"abcdef_extra_is_ignored".into_iter().copied()); // abcdef extras.set_cruise_control(true); extras.set_sports_pack(true); @@ -197,7 +197,7 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { let mut engine = car.engine_encoder(); engine.capacity(2000); engine.num_cylinders(4); - engine.manufacturer_code(&[49, 50, 51]); // 123 + engine.manufacturer_code(b"123"); engine.efficiency(35); engine.booster_enabled(BooleanType::T); let mut booster = engine.booster_encoder(); diff --git a/rust/tests/fixed_sized_primitive_array.rs b/rust/tests/fixed_sized_primitive_array.rs new file mode 100644 index 0000000000..8542e3d488 --- /dev/null +++ b/rust/tests/fixed_sized_primitive_array.rs @@ -0,0 +1,1110 @@ +use fixed_sized_primitive_array::{ + demo_codec::{DemoDecoder, DemoEncoder}, + message_header_codec::{MessageHeaderDecoder, ENCODED_LENGTH}, + ReadBuf, WriteBuf, +}; + +fn create_encoder(buffer: &mut [u8]) -> DemoEncoder { + let encoder = DemoEncoder::default().wrap(WriteBuf::new(buffer), ENCODED_LENGTH); + let mut header = encoder.header(0); + header.parent().unwrap() +} + +#[test] +fn test_encode_then_decode_u8_slice() { + let uninit = 1u8; + + let test_data = [ + b"" as &[u8], + b"0" as &[u8], + b"01" as &[u8], + b"012" as &[u8], + b"0123" as &[u8], + b"01234" as &[u8], + b"012345" as &[u8], + b"0123456" as &[u8], + b"01234567" as &[u8], + b"012345678" as &[u8], + b"0123456789" as &[u8], + b"0123456789A" as &[u8], + b"0123456789AB" as &[u8], + b"0123456789ABC" as &[u8], + b"0123456789ABCD" as &[u8], + b"0123456789ABCDE" as &[u8], + b"0123456789ABCDEF" as &[u8], + b"0123456789abcdef" as &[u8], + b"0123456789abcdef0" as &[u8], + b"0123456789abcdef01" as &[u8], + b"0123456789abcdef012" as &[u8], + b"0123456789abcdef0123" as &[u8], + b"0123456789abcdef01234" as &[u8], + b"0123456789abcdef012345" as &[u8], + b"0123456789abcdef0123456" as &[u8], + b"0123456789abcdef01234567" as &[u8], + b"0123456789abcdef012345678" as &[u8], + b"0123456789abcdef0123456789" as &[u8], + b"0123456789abcdef0123456789A" as &[u8], + b"0123456789abcdef0123456789AB" as &[u8], + b"0123456789abcdef0123456789ABC" as &[u8], + b"0123456789abcdef0123456789ABCD" as &[u8], + b"0123456789abcdef0123456789ABCDE" as &[u8], + b"0123456789abcdef0123456789ABCDEF" as &[u8], + ]; + + // + // + // + // + // + // + // + // + macro_rules! run_encode_then_decode_for_array_of_u8_len_16 { + ($encode_func:expr, $decode_func:expr, $end_encode_func:expr, $end_decode_func:expr) => { + for each_slice in test_data { + let encode_func = $encode_func; + let decode_func = $decode_func; + let end_encode_func = $end_encode_func; + let end_decode_func = $end_decode_func; + + let cur_len = each_slice.len(); + let effective_len = cur_len.min(16); + + // encode... + let mut buffer = [uninit; 1024]; + let mut encoder = create_encoder(&mut buffer); + + encode_func(&mut encoder, each_slice.into_iter().copied()); + + let end = 1i32; + end_encode_func(&mut encoder, end); + + // decode... + let buf = ReadBuf::new(buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + + let decoder = DemoDecoder::default().header(header, 0); + let decoded = decode_func(&decoder); + for each_idx in 0..effective_len { + assert_eq!( + each_slice[each_idx], decoded[each_idx], + "Item mismatched at {}/{}", + each_idx, cur_len + ); + } + for each_idx in effective_len..16 { + assert_eq!( + decoded[each_idx], uninit, + "Item should not be padded ZERO at {}/{}", + each_idx, cur_len + ); + } + let decoded_end = end_decode_func(&decoder); + assert_eq!(decoded_end, end, "End Item should equal",); + } + }; + } + + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_char_from_iter, + DemoDecoder::fixed_16_char, + DemoEncoder::fixed_16_char_end, + DemoDecoder::fixed_16_char_end + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_ascii_char_from_iter, + DemoDecoder::fixed_16_ascii_char, + DemoEncoder::fixed_16_ascii_char_end, + DemoDecoder::fixed_16_ascii_char_end + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_gb_18030_char_from_iter, + DemoDecoder::fixed_16_gb_18030_char, + DemoEncoder::fixed_16_gb_18030_char_end, + DemoDecoder::fixed_16_gb_18030_char_end + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_utf_8_char_from_iter, + DemoDecoder::fixed_16_utf_8_char, + DemoEncoder::fixed_16_utf_8_char_end, + DemoDecoder::fixed_16_utf_8_char_end + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_u8_from_iter, + DemoDecoder::fixed_16_u8, + DemoEncoder::fixed_16_u8_end, + DemoDecoder::fixed_16_u8_end + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_ascii_u8_from_iter, + DemoDecoder::fixed_16_ascii_u8, + DemoEncoder::fixed_16_ascii_u8_end, + DemoDecoder::fixed_16_ascii_u8_end + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_gb_18030_u8_from_iter, + DemoDecoder::fixed_16_gb_18030_u8, + DemoEncoder::fixed_16_gb_18030_u8_end, + DemoDecoder::fixed_16_gb_18030_u8_end + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_utf_8_u8_from_iter, + DemoDecoder::fixed_16_utf_8_u8, + DemoEncoder::fixed_16_utf_8u_8_end, + DemoDecoder::fixed_16_utf_8u_8_end + ); +} + +#[test] +fn test_encode_then_decode_non_u8_signed_primitive_slice() { + let uninit = 1u8; + + // + // + // + // + macro_rules! run_encode_then_decode_for_array_of_signed_len_16 { + ($encode_func:expr, $decode_func:expr, $end_encode_func:expr, $end_decode_func:expr, $i_type:ty, $existed:expr) => { + let test_data = [ + &[] as &[$i_type], + &[1 as $i_type] as &[$i_type], + &[0 as $i_type] as &[$i_type], + &[-1 as $i_type] as &[$i_type], + &[-1, 1 as $i_type] as &[$i_type], + &[-1, 0, 1 as $i_type] as &[$i_type], + &[-2, -1, 1, 2 as $i_type] as &[$i_type], + &[-2, -1, 0, 1, 2 as $i_type] as &[$i_type], + &[-3, -2, -1, 1, 2, 3 as $i_type] as &[$i_type], + &[-3, -2, -1, 0, 1, 2, 3 as $i_type] as &[$i_type], + &[-4, -3, -2, -1, 1, 2, 3, 4 as $i_type] as &[$i_type], + &[-4, -3, -2, -1, 0, 1, 2, 3, 4 as $i_type] as &[$i_type], + &[-5, -4, -3, -2, -1, 1, 2, 3, 4, 5 as $i_type] as &[$i_type], + &[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 as $i_type] as &[$i_type], + &[-6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6 as $i_type] as &[$i_type], + &[-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6 as $i_type] as &[$i_type], + &[-7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7 as $i_type] as &[$i_type], + &[ + -7, + -6, + -5, + -4, + -3, + -2, + -1, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7 as $i_type, + ] as &[$i_type], + &[ + -8, + -7, + -6, + -5, + -4, + -3, + -2, + -1, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 as $i_type, + ] as &[$i_type], + &[ + -8, + -7, + -6, + -5, + -4, + -3, + -2, + -1, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 as $i_type, + ] as &[$i_type], + &[ + -9, + -8, + -7, + -6, + -5, + -4, + -3, + -2, + -1, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 as $i_type, + ] as &[$i_type], + &[ + -9, + -8, + -7, + -6, + -5, + -4, + -3, + -2, + -1, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 as $i_type, + ] as &[$i_type], + ]; + + let existed = $existed; + + for each_slice in test_data { + let encode_func = $encode_func; + let decode_func = $decode_func; + let end_encode_func = $end_encode_func; + let end_decode_func = $end_decode_func; + + let cur_len = each_slice.len(); + let effective_len = cur_len.min(16); + + // encode... + let mut buffer = [uninit; 1024]; + let mut encoder = create_encoder(&mut buffer); + + encode_func(&mut encoder, each_slice.into_iter().copied()); + + let end = 1i32; + end_encode_func(&mut encoder, end); + + // decode... + let buf = ReadBuf::new(buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + + let decoder = DemoDecoder::default().header(header, 0); + let decoded = decode_func(&decoder); + for each_idx in 0..effective_len { + assert_eq!( + each_slice[each_idx], + decoded[each_idx], + "Item mismatched at {}/{} for {}", + each_idx, + cur_len, + stringify!($i_type) + ); + } + for each_idx in effective_len..16 { + assert_eq!( + decoded[each_idx], + existed, + "Item should not be padded ZERO at {}/{} for {}", + each_idx, + cur_len, + stringify!($i_type) + ); + } + let decoded_end = end_decode_func(&decoder); + assert_eq!(decoded_end, end, "End Item should equal",); + } + }; + } + + run_encode_then_decode_for_array_of_signed_len_16!( + DemoEncoder::fixed_16_i8_from_iter, + DemoDecoder::fixed_16_i8, + DemoEncoder::fixed_16_i8_end, + DemoDecoder::fixed_16_i8_end, + i8, i8::from_le_bytes([uninit]) + ); + run_encode_then_decode_for_array_of_signed_len_16!( + DemoEncoder::fixed_16_i16_from_iter, + DemoDecoder::fixed_16_i16, + DemoEncoder::fixed_16_i16_end, + DemoDecoder::fixed_16_i16_end, + i16, i16::from_le_bytes([uninit, uninit]) + ); + run_encode_then_decode_for_array_of_signed_len_16!( + DemoEncoder::fixed_16_i32_from_iter, + DemoDecoder::fixed_16_i32, + DemoEncoder::fixed_16_i32_end, + DemoDecoder::fixed_16_i32_end, + i32, i32::from_le_bytes([uninit, uninit, uninit, uninit]) + ); + run_encode_then_decode_for_array_of_signed_len_16!( + DemoEncoder::fixed_16_i64_from_iter, + DemoDecoder::fixed_16_i64, + DemoEncoder::fixed_16_i64_end, + DemoDecoder::fixed_16_i64_end, + i64, i64::from_le_bytes([uninit, uninit, uninit, uninit, uninit, uninit, uninit, uninit]) + ); +} + +#[test] +fn test_encode_then_decode_non_u8_unsigned_primitive_slice() { + let uninit = 1u8; + + // + // + macro_rules! run_encode_then_decode_for_array_of_unsigned_len_16 { + ($encode_func:expr, $decode_func:expr, $end_encode_func:expr, $end_decode_func:expr, $i_type:ty, $existed:expr) => { + let test_data = [ + &[] as &[$i_type], + &[1 as $i_type] as &[$i_type], + &[0 as $i_type] as &[$i_type], + &[11 as $i_type] as &[$i_type], + &[11, 1 as $i_type] as &[$i_type], + &[11, 0, 1 as $i_type] as &[$i_type], + &[12, 11, 1, 2 as $i_type] as &[$i_type], + &[12, 11, 0, 1, 2 as $i_type] as &[$i_type], + &[13, 12, 11, 1, 2, 3 as $i_type] as &[$i_type], + &[13, 12, 11, 0, 1, 2, 3 as $i_type] as &[$i_type], + &[14, 13, 12, 11, 1, 2, 3, 4 as $i_type] as &[$i_type], + &[14, 13, 12, 11, 0, 1, 2, 3, 4 as $i_type] as &[$i_type], + &[15, 14, 13, 12, 11, 1, 2, 3, 4, 5 as $i_type] as &[$i_type], + &[15, 14, 13, 12, 11, 0, 1, 2, 3, 4, 5 as $i_type] as &[$i_type], + &[16, 15, 14, 13, 12, 11, 1, 2, 3, 4, 5, 6 as $i_type] as &[$i_type], + &[16, 15, 14, 13, 12, 11, 0, 1, 2, 3, 4, 5, 6 as $i_type] as &[$i_type], + &[17, 16, 15, 14, 13, 12, 11, 1, 2, 3, 4, 5, 6, 7 as $i_type] as &[$i_type], + &[ + 17, + 16, + 15, + 14, + 13, + 12, + 11, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7 as $i_type, + ] as &[$i_type], + &[ + 18, + 17, + 16, + 15, + 14, + 13, + 12, + 11, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 as $i_type, + ] as &[$i_type], + &[ + 18, + 17, + 16, + 15, + 14, + 13, + 12, + 11, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 as $i_type, + ] as &[$i_type], + &[ + 19, + 18, + 17, + 16, + 15, + 14, + 13, + 12, + 11, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 as $i_type, + ] as &[$i_type], + &[ + 19, + 18, + 17, + 16, + 15, + 14, + 13, + 12, + 11, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 as $i_type, + ] as &[$i_type], + ]; + + let existed = $existed; + + for each_slice in test_data { + let encode_func = $encode_func; + let decode_func = $decode_func; + let end_encode_func = $end_encode_func; + let end_decode_func = $end_decode_func; + + let cur_len = each_slice.len(); + let effective_len = cur_len.min(16); + + // encode... + let mut buffer = [uninit; 1024]; + let mut encoder = create_encoder(&mut buffer); + + encode_func(&mut encoder, each_slice.into_iter().copied()); + + let end = 1i32; + end_encode_func(&mut encoder, end); + + // decode... + let buf = ReadBuf::new(buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + + let decoder = DemoDecoder::default().header(header, 0); + let decoded = decode_func(&decoder); + for each_idx in 0..effective_len { + assert_eq!( + each_slice[each_idx], + decoded[each_idx], + "Item mismatched at {}/{} for {}", + each_idx, + cur_len, + stringify!($i_type) + ); + } + + for each_idx in effective_len..16 { + assert_eq!( + decoded[each_idx], + existed, + "Item should not be padded ZERO at {}/{} for {}", + each_idx, + cur_len, + stringify!($i_type) + ); + } + let decoded_end = end_decode_func(&decoder); + assert_eq!(decoded_end, end, "End Item should equal",); + } + }; + } + + run_encode_then_decode_for_array_of_unsigned_len_16!( + DemoEncoder::fixed_16_u16_from_iter, + DemoDecoder::fixed_16_u16, + DemoEncoder::fixed_16_u16_end, + DemoDecoder::fixed_16_u16_end, + u16, + u16::from_le_bytes([uninit, uninit]) + ); + run_encode_then_decode_for_array_of_unsigned_len_16!( + DemoEncoder::fixed_16_u32_from_iter, + DemoDecoder::fixed_16_u32, + DemoEncoder::fixed_16_u32_end, + DemoDecoder::fixed_16_u32_end, + u32, + u32::from_le_bytes([uninit, uninit, uninit, uninit]) + ); + run_encode_then_decode_for_array_of_unsigned_len_16!( + DemoEncoder::fixed_16_u64_from_iter, + DemoDecoder::fixed_16_u64, + DemoEncoder::fixed_16_u64_end, + DemoDecoder::fixed_16_u64_end, + u64, + u64::from_le_bytes([uninit, uninit, uninit, uninit, uninit, uninit, uninit, uninit]) + ); +} + +#[test] +fn test_encode_then_decode_u8_slice_padded() { + let uninit = 1u8; + + let test_data = [ + b"" as &[u8], + b"0" as &[u8], + b"01" as &[u8], + b"012" as &[u8], + b"0123" as &[u8], + b"01234" as &[u8], + b"012345" as &[u8], + b"0123456" as &[u8], + b"01234567" as &[u8], + b"012345678" as &[u8], + b"0123456789" as &[u8], + b"0123456789A" as &[u8], + b"0123456789AB" as &[u8], + b"0123456789ABC" as &[u8], + b"0123456789ABCD" as &[u8], + b"0123456789ABCDE" as &[u8], + b"0123456789ABCDEF" as &[u8], + b"0123456789abcdef" as &[u8], + b"0123456789abcdef0" as &[u8], + b"0123456789abcdef01" as &[u8], + b"0123456789abcdef012" as &[u8], + b"0123456789abcdef0123" as &[u8], + b"0123456789abcdef01234" as &[u8], + b"0123456789abcdef012345" as &[u8], + b"0123456789abcdef0123456" as &[u8], + b"0123456789abcdef01234567" as &[u8], + b"0123456789abcdef012345678" as &[u8], + b"0123456789abcdef0123456789" as &[u8], + b"0123456789abcdef0123456789A" as &[u8], + b"0123456789abcdef0123456789AB" as &[u8], + b"0123456789abcdef0123456789ABC" as &[u8], + b"0123456789abcdef0123456789ABCD" as &[u8], + b"0123456789abcdef0123456789ABCDE" as &[u8], + b"0123456789abcdef0123456789ABCDEF" as &[u8], + ]; + + // + // + // + // + // + // + // + // + macro_rules! run_encode_then_decode_for_array_of_u8_len_16 { + ($encode_func:expr, $decode_func:expr, $end_encode_func:expr, $end_decode_func:expr,) => { + for each_slice in test_data { + let encode_func = $encode_func; + let decode_func = $decode_func; + let end_encode_func = $end_encode_func; + let end_decode_func = $end_decode_func; + + let cur_len = each_slice.len(); + let effective_len = cur_len.min(16); + + // encode... + let mut buffer = [uninit; 1024]; + let mut encoder = create_encoder(&mut buffer); + + encode_func(&mut encoder, each_slice); + + let end = 1i32; + end_encode_func(&mut encoder, end); + + // decode... + let buf = ReadBuf::new(buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + + let decoder = DemoDecoder::default().header(header, 0); + let decoded = decode_func(&decoder); + for each_idx in 0..effective_len { + assert_eq!( + each_slice[each_idx], decoded[each_idx], + "Item mismatched at {}/{}", + each_idx, cur_len + ); + } + for each_idx in effective_len..16 { + assert_eq!( + decoded[each_idx], 0, + "Item should be padded ZERO at {}/{}", + each_idx, cur_len + ); + } + let decoded_end = end_decode_func(&decoder); + assert_eq!(decoded_end, end, "End Item should equal",); + } + }; + } + + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_char_zero_padded, + DemoDecoder::fixed_16_char, + DemoEncoder::fixed_16_char_end, + DemoDecoder::fixed_16_char_end, + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_ascii_char_zero_padded, + DemoDecoder::fixed_16_ascii_char, + DemoEncoder::fixed_16_ascii_char_end, + DemoDecoder::fixed_16_ascii_char_end, + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_gb_18030_char_zero_padded, + DemoDecoder::fixed_16_gb_18030_char, + DemoEncoder::fixed_16_gb_18030_char_end, + DemoDecoder::fixed_16_gb_18030_char_end, + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_utf_8_char_zero_padded, + DemoDecoder::fixed_16_utf_8_char, + DemoEncoder::fixed_16_utf_8_char_end, + DemoDecoder::fixed_16_utf_8_char_end, + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_u8_zero_padded, + DemoDecoder::fixed_16_u8, + DemoEncoder::fixed_16_u8_end, + DemoDecoder::fixed_16_u8_end, + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_ascii_u8_zero_padded, + DemoDecoder::fixed_16_ascii_u8, + DemoEncoder::fixed_16_ascii_u8_end, + DemoDecoder::fixed_16_ascii_u8_end, + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_gb_18030_u8_zero_padded, + DemoDecoder::fixed_16_gb_18030_u8, + DemoEncoder::fixed_16_gb_18030_u8_end, + DemoDecoder::fixed_16_gb_18030_u8_end, + ); + run_encode_then_decode_for_array_of_u8_len_16!( + DemoEncoder::fixed_16_utf_8_u8_zero_padded, + DemoDecoder::fixed_16_utf_8_u8, + DemoEncoder::fixed_16_utf_8u_8_end, + DemoDecoder::fixed_16_utf_8u_8_end, + ); +} + +#[test] +fn test_encode_then_decode_non_u8_signed_primitive_slice_padded() { + let uninit = 1u8; + + // + // + // + // + macro_rules! run_encode_then_decode_for_array_of_signed_len_16 { + ($encode_func:expr, $decode_func:expr, $end_encode_func:expr, $end_decode_func:expr, $i_type:ty,) => { + let test_data = [ + &[] as &[$i_type], + &[1 as $i_type] as &[$i_type], + &[0 as $i_type] as &[$i_type], + &[-1 as $i_type] as &[$i_type], + &[-1, 1 as $i_type] as &[$i_type], + &[-1, 0, 1 as $i_type] as &[$i_type], + &[-2, -1, 1, 2 as $i_type] as &[$i_type], + &[-2, -1, 0, 1, 2 as $i_type] as &[$i_type], + &[-3, -2, -1, 1, 2, 3 as $i_type] as &[$i_type], + &[-3, -2, -1, 0, 1, 2, 3 as $i_type] as &[$i_type], + &[-4, -3, -2, -1, 1, 2, 3, 4 as $i_type] as &[$i_type], + &[-4, -3, -2, -1, 0, 1, 2, 3, 4 as $i_type] as &[$i_type], + &[-5, -4, -3, -2, -1, 1, 2, 3, 4, 5 as $i_type] as &[$i_type], + &[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 as $i_type] as &[$i_type], + &[-6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6 as $i_type] as &[$i_type], + &[-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6 as $i_type] as &[$i_type], + &[-7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7 as $i_type] as &[$i_type], + &[ + -7, + -6, + -5, + -4, + -3, + -2, + -1, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7 as $i_type, + ] as &[$i_type], + &[ + -8, + -7, + -6, + -5, + -4, + -3, + -2, + -1, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 as $i_type, + ] as &[$i_type], + &[ + -8, + -7, + -6, + -5, + -4, + -3, + -2, + -1, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 as $i_type, + ] as &[$i_type], + &[ + -9, + -8, + -7, + -6, + -5, + -4, + -3, + -2, + -1, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 as $i_type, + ] as &[$i_type], + &[ + -9, + -8, + -7, + -6, + -5, + -4, + -3, + -2, + -1, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 as $i_type, + ] as &[$i_type], + ]; + for each_slice in test_data { + let encode_func = $encode_func; + let decode_func = $decode_func; + let end_encode_func = $end_encode_func; + let end_decode_func = $end_decode_func; + + let cur_len = each_slice.len(); + let effective_len = cur_len.min(16); + + // encode... + let mut buffer = [uninit; 1024]; + let mut encoder = create_encoder(&mut buffer); + + encode_func(&mut encoder, each_slice); + + let end = 1i32; + end_encode_func(&mut encoder, end); + + // decode... + let buf = ReadBuf::new(buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + + let decoder = DemoDecoder::default().header(header, 0); + let decoded = decode_func(&decoder); + for each_idx in 0..effective_len { + assert_eq!( + each_slice[each_idx], + decoded[each_idx], + "Item mismatched at {}/{} for {}", + each_idx, + cur_len, + stringify!($i_type) + ); + } + for each_idx in effective_len..16 { + assert_eq!( + decoded[each_idx], + 0, + "Item should be padded ZERO at {}/{} for {}", + each_idx, + cur_len, + stringify!($i_type) + ); + } + let decoded_end = end_decode_func(&decoder); + assert_eq!(decoded_end, end, "End Item should equal",); + } + }; + } + + run_encode_then_decode_for_array_of_signed_len_16!( + DemoEncoder::fixed_16_i8_zero_padded, + DemoDecoder::fixed_16_i8, + DemoEncoder::fixed_16_i8_end, + DemoDecoder::fixed_16_i8_end, + i8, + ); + run_encode_then_decode_for_array_of_signed_len_16!( + DemoEncoder::fixed_16_i16_zero_padded, + DemoDecoder::fixed_16_i16, + DemoEncoder::fixed_16_i16_end, + DemoDecoder::fixed_16_i16_end, + i16, + ); + run_encode_then_decode_for_array_of_signed_len_16!( + DemoEncoder::fixed_16_i32_zero_padded, + DemoDecoder::fixed_16_i32, + DemoEncoder::fixed_16_i32_end, + DemoDecoder::fixed_16_i32_end, + i32, + ); + run_encode_then_decode_for_array_of_signed_len_16!( + DemoEncoder::fixed_16_i64_zero_padded, + DemoDecoder::fixed_16_i64, + DemoEncoder::fixed_16_i64_end, + DemoDecoder::fixed_16_i64_end, + i64, + ); +} + +#[test] +fn test_encode_then_decode_non_u8_unsigned_primitive_slice_padded() { + let uninit = 1u8; + + // + // + // + macro_rules! run_encode_then_decode_for_array_of_unsigned_len_16 { + ($encode_func:expr, $decode_func:expr, $end_encode_func:expr, $end_decode_func:expr, $i_type:ty) => { + let test_data = [ + &[] as &[$i_type], + &[1 as $i_type] as &[$i_type], + &[0 as $i_type] as &[$i_type], + &[11 as $i_type] as &[$i_type], + &[11, 1 as $i_type] as &[$i_type], + &[11, 0, 1 as $i_type] as &[$i_type], + &[12, 11, 1, 2 as $i_type] as &[$i_type], + &[12, 11, 0, 1, 2 as $i_type] as &[$i_type], + &[13, 12, 11, 1, 2, 3 as $i_type] as &[$i_type], + &[13, 12, 11, 0, 1, 2, 3 as $i_type] as &[$i_type], + &[14, 13, 12, 11, 1, 2, 3, 4 as $i_type] as &[$i_type], + &[14, 13, 12, 11, 0, 1, 2, 3, 4 as $i_type] as &[$i_type], + &[15, 14, 13, 12, 11, 1, 2, 3, 4, 5 as $i_type] as &[$i_type], + &[15, 14, 13, 12, 11, 0, 1, 2, 3, 4, 5 as $i_type] as &[$i_type], + &[16, 15, 14, 13, 12, 11, 1, 2, 3, 4, 5, 6 as $i_type] as &[$i_type], + &[16, 15, 14, 13, 12, 11, 0, 1, 2, 3, 4, 5, 6 as $i_type] as &[$i_type], + &[17, 16, 15, 14, 13, 12, 11, 1, 2, 3, 4, 5, 6, 7 as $i_type] as &[$i_type], + &[ + 17, + 16, + 15, + 14, + 13, + 12, + 11, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7 as $i_type, + ] as &[$i_type], + &[ + 18, + 17, + 16, + 15, + 14, + 13, + 12, + 11, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 as $i_type, + ] as &[$i_type], + &[ + 18, + 17, + 16, + 15, + 14, + 13, + 12, + 11, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 as $i_type, + ] as &[$i_type], + &[ + 19, + 18, + 17, + 16, + 15, + 14, + 13, + 12, + 11, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 as $i_type, + ] as &[$i_type], + &[ + 19, + 18, + 17, + 16, + 15, + 14, + 13, + 12, + 11, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 as $i_type, + ] as &[$i_type], + ]; + for each_slice in test_data { + let encode_func = $encode_func; + let decode_func = $decode_func; + let end_encode_func = $end_encode_func; + let end_decode_func = $end_decode_func; + + let cur_len = each_slice.len(); + let effective_len = cur_len.min(16); + + // encode... + let mut buffer = [uninit; 1024]; + let mut encoder = create_encoder(&mut buffer); + + encode_func(&mut encoder, each_slice); + + let end = 1i32; + end_encode_func(&mut encoder, end); + + // decode... + let buf = ReadBuf::new(buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + + let decoder = DemoDecoder::default().header(header, 0); + let decoded = decode_func(&decoder); + for each_idx in 0..effective_len { + assert_eq!( + each_slice[each_idx], + decoded[each_idx], + "Item mismatched at {}/{} for {}", + each_idx, + cur_len, + stringify!($i_type) + ); + } + for each_idx in effective_len..16 { + assert_eq!( + decoded[each_idx], + 0, + "Item should be padded ZERO at {}/{} for {}", + each_idx, + cur_len, + stringify!($i_type) + ); + } + let decoded_end = end_decode_func(&decoder); + assert_eq!(decoded_end, end, "End Item should equal",); + } + }; + } + + run_encode_then_decode_for_array_of_unsigned_len_16!( + DemoEncoder::fixed_16_u16_zero_padded, + DemoDecoder::fixed_16_u16, + DemoEncoder::fixed_16_u16_end, + DemoDecoder::fixed_16_u16_end, + u16 + ); + run_encode_then_decode_for_array_of_unsigned_len_16!( + DemoEncoder::fixed_16_u32_zero_padded, + DemoDecoder::fixed_16_u32, + DemoEncoder::fixed_16_u32_end, + DemoDecoder::fixed_16_u32_end, + u32 + ); + run_encode_then_decode_for_array_of_unsigned_len_16!( + DemoEncoder::fixed_16_u64_zero_padded, + DemoDecoder::fixed_16_u64, + DemoEncoder::fixed_16_u64_end, + DemoDecoder::fixed_16_u64_end, + u64 + ); +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index ae50c9bef7..39a5ed633c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -276,7 +276,14 @@ static void generateWriteBuf(final Writer writer, final ByteOrder byteOrder) thr indent(writer, 2, "dest.clone_from_slice(src);\n"); indent(writer, 2, "len\n"); indent(writer, 1, "}\n"); + indent(writer, 0, "}\n"); + // impl From for &[u8] + indent(writer, 0, "impl<%s> From<&%1$s mut %2$s<%1$s>> for &%1$s mut [u8] {\n", BUF_LIFETIME, WRITE_BUF_TYPE); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn from(buf: &%s mut %2$s<%1$s>) -> &%1$s mut [u8] {\n", BUF_LIFETIME, WRITE_BUF_TYPE); + indent(writer, 2, "buf.data\n"); + indent(writer, 1, "}\n"); indent(writer, 0, "}\n\n"); } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index f78899cb4b..d56c680d28 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -361,7 +361,62 @@ static void generateEncoderVarData( } } - private static void generatePrimitiveEncoder( + private static String rustNullLiteral(final Encoding encoding) + { + return generateRustLiteral(encoding.primitiveType(), encoding.applicableNullValue()); + } + + + private static void generateRustDoc( + final StringBuilder sb, + final int level, + final Token typeToken, + final Encoding encoding) throws IOException + { + indent(sb, level, "/// - min value: %s\n", encoding.applicableMinValue()); + indent(sb, level, "/// - max value: %s\n", encoding.applicableMaxValue()); + indent(sb, level, "/// - null value: %s\n", rustNullLiteral(encoding)); + indent(sb, level, "/// - characterEncoding: %s\n", encoding.characterEncoding()); + indent(sb, level, "/// - semanticType: %s\n", encoding.semanticType()); + indent(sb, level, "/// - encodedOffset: %d\n", typeToken.offset()); + indent(sb, level, "/// - encodedLength: %d\n", typeToken.encodedLength()); + indent(sb, level, "/// - version: %d\n", typeToken.version()); + } + + private static void generatePrimitiveArrayFromIterEncoder( + final StringBuilder sb, + final int level, + final Token typeToken, + final String name) throws IOException + { + final Encoding encoding = typeToken.encoding(); + final PrimitiveType primitiveType = encoding.primitiveType(); + final String rustPrimitiveType = rustTypeName(primitiveType); + + indent(sb, level, "/// primitive array field '%s' from an Iterator\n", name); + generateRustDoc(sb, level, typeToken, encoding); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s_from_iter(&mut self, iter: impl Iterator) {\n", + formatFunctionName(name), rustPrimitiveType); + + indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); + indent(sb, level + 1, "let buf = self.get_buf_mut();\n"); + indent(sb, level + 1, "for (i, v) in iter.enumerate() {\n"); + + if (primitiveType.size() == 1) + { + indent(sb, level + 2, "buf.put_%s_at(offset + i, v);\n", rustPrimitiveType); + } + else + { + indent(sb, level + 2, "buf.put_%s_at(offset + i * %d, v);\n", + rustPrimitiveType, primitiveType.size()); + } + indent(sb, level + 1, "}\n"); + indent(sb, level, "}\n\n"); + } + + private static void generatePrimitiveArrayZeroPaddedEncoder( final StringBuilder sb, final int level, final Token typeToken, @@ -371,34 +426,66 @@ private static void generatePrimitiveEncoder( final PrimitiveType primitiveType = encoding.primitiveType(); final String rustPrimitiveType = rustTypeName(primitiveType); final int arrayLength = typeToken.arrayLength(); - if (arrayLength > 1) + + indent(sb, level, "/// primitive array field '%s' with zero padding\n", name); + generateRustDoc(sb, level, typeToken, encoding); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s_zero_padded(&mut self, value: &[%s]) {\n", + formatFunctionName(name), rustPrimitiveType); + + indent(sb, level + 1, "let iter = value.iter().copied().chain(std::iter::repeat(0_%s)).take(%d);\n", + rustPrimitiveType, arrayLength); + + indent(sb, level + 1, "self.%s_from_iter(iter);\n", formatFunctionName(name)); + indent(sb, level, "}\n\n"); + } + + private static void generatePrimitiveArrayEncoder( + final StringBuilder sb, + final int level, + final Token typeToken, + final String name) throws IOException + { + final Encoding encoding = typeToken.encoding(); + final PrimitiveType primitiveType = encoding.primitiveType(); + final String rustPrimitiveType = rustTypeName(primitiveType); + final int arrayLength = typeToken.arrayLength(); + + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s_at(&mut self, index: usize, value: %s) {\n", + formatFunctionName(name), rustPrimitiveType); + indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); + indent(sb, level + 1, "let buf = self.get_buf_mut();\n"); + + if (primitiveType.size() == 1) { - indent(sb, level, "/// primitive array field '%s'\n", name); - indent(sb, level, "/// - min value: %s\n", encoding.applicableMinValue()); - indent(sb, level, "/// - max value: %s\n", encoding.applicableMaxValue()); - indent(sb, level, "/// - null value: %s\n", encoding.applicableNullValue()); - indent(sb, level, "/// - characterEncoding: %s\n", encoding.characterEncoding()); - indent(sb, level, "/// - semanticType: %s\n", encoding.semanticType()); - indent(sb, level, "/// - encodedOffset: %d\n", typeToken.offset()); - indent(sb, level, "/// - encodedLength: %d\n", typeToken.encodedLength()); - indent(sb, level, "/// - version: %d\n", typeToken.version()); - indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn %s(&mut self, value: &[%s; %d]) {\n", - formatFunctionName(name), - rustPrimitiveType, - arrayLength); + indent(sb, level + 1, "buf.put_%s_at(offset + index, value);\n", rustPrimitiveType); + } + else + { + indent(sb, level + 1, "buf.put_%s_at(offset + index * %d, value);\n", + rustPrimitiveType, primitiveType.size()); + } + indent(sb, level, "}\n\n"); - // NB: must create variable 'offset' before calling mutable self.get_buf_mut() - indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); - indent(sb, level + 1, "let buf = self.get_buf_mut();\n"); + indent(sb, level, "/// primitive array field '%s'\n", name); + generateRustDoc(sb, level, typeToken, encoding); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(&mut self, value: &[%s]) {\n", + formatFunctionName(name), rustPrimitiveType); - if (rustPrimitiveType.equals("u8")) - { - indent(sb, level + 1, "buf.put_bytes_at(offset, value);\n"); - indent(sb, level, "}\n\n"); - return; - } + // NB: must create variable 'offset' before calling mutable self.get_buf_mut() + indent(sb, level + 1, "debug_assert_eq!(%d, value.len());\n", arrayLength); + indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); + indent(sb, level + 1, "let buf = self.get_buf_mut();\n"); + if (rustPrimitiveType.equals("u8")) + { + indent(sb, level + 1, "buf.put_slice_at(offset, value);\n"); + indent(sb, level, "}\n\n"); + } + else + { for (int i = 0; i < arrayLength; i++) { if (i == 0) @@ -416,34 +503,44 @@ private static void generatePrimitiveEncoder( indent(sb, level, "}\n\n"); } - else + + generatePrimitiveArrayFromIterEncoder(sb, level, typeToken, name); + generatePrimitiveArrayZeroPaddedEncoder(sb, level, typeToken, name); + } + + private static void generatePrimitiveEncoder( + final StringBuilder sb, + final int level, + final Token typeToken, + final String name) throws IOException + { + final int arrayLength = typeToken.arrayLength(); + if (arrayLength > 1) { - if (encoding.presence() == Encoding.Presence.CONSTANT) - { - indent(sb, level, "// skipping CONSTANT %s\n\n", name); - } - else - { - indent(sb, level, "/// primitive field '%s'\n", name); - indent(sb, level, "/// - min value: %s\n", encoding.applicableMinValue()); - indent(sb, level, "/// - max value: %s\n", encoding.applicableMaxValue()); - indent(sb, level, "/// - null value: %s\n", encoding.applicableNullValue()); - indent(sb, level, "/// - characterEncoding: %s\n", encoding.characterEncoding()); - indent(sb, level, "/// - semanticType: %s\n", encoding.semanticType()); - indent(sb, level, "/// - encodedOffset: %d\n", typeToken.offset()); - indent(sb, level, "/// - encodedLength: %d\n", typeToken.encodedLength()); - indent(sb, level, "/// - version: %d\n", typeToken.version()); - indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", - formatFunctionName(name), - rustPrimitiveType); - - // NB: must create variable 'offset' before calling mutable self.get_buf_mut() - indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); - indent(sb, level + 1, "self.get_buf_mut().put_%s_at(offset, value);\n", rustPrimitiveType); - indent(sb, level, "}\n\n"); - } + generatePrimitiveArrayEncoder(sb, level, typeToken, name); + return; } + + final Encoding encoding = typeToken.encoding(); + if (encoding.presence() == Encoding.Presence.CONSTANT) + { + indent(sb, level, "// skipping CONSTANT %s\n\n", name); + return; + } + + final PrimitiveType primitiveType = encoding.primitiveType(); + final String rustPrimitiveType = rustTypeName(primitiveType); + + indent(sb, level, "/// primitive field '%s'\n", name); + generateRustDoc(sb, level, typeToken, encoding); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", + formatFunctionName(name), rustPrimitiveType); + + // NB: must create variable 'offset' before calling mutable self.get_buf_mut() + indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); + indent(sb, level + 1, "self.get_buf_mut().put_%s_at(offset, value);\n", rustPrimitiveType); + indent(sb, level, "}\n\n"); } private static void generateEnumEncoder( @@ -679,7 +776,7 @@ private static void generatePrimitiveArrayDecoder( if (fieldToken.version() > 0) { indent(sb, level + 1, "if self.acting_version() < %d {\n", fieldToken.version()); - indent(sb, level + 2, "return [%s; %d];\n", encoding.applicableNullValue(), arrayLength); + indent(sb, level + 2, "return [%s; %d];\n", rustNullLiteral(encoding), arrayLength); indent(sb, level + 1, "}\n\n"); } @@ -772,7 +869,7 @@ private static void generatePrimitiveOptionalDecoder( final String rustPrimitiveType = rustTypeName(primitiveType); final String characterEncoding = encoding.characterEncoding(); indent(sb, level, "/// primitive field - '%s' { null_value: '%s' }\n", - encoding.presence(), encoding.applicableNullValue()); + encoding.presence(), rustNullLiteral(encoding)); if (characterEncoding != null) { @@ -789,14 +886,14 @@ private static void generatePrimitiveOptionalDecoder( rustPrimitiveType, getBufOffset(fieldToken)); - final String literal = generateRustLiteral(primitiveType, encoding.applicableNullValue().toString()); - if (literal.endsWith("::NAN")) + final String nullLiteral = rustNullLiteral(encoding); + if (nullLiteral.endsWith("::NAN")) { indent(sb, level + 1, "if value.is_nan() {\n"); } else { - indent(sb, level + 1, "if value == %s {\n", literal); + indent(sb, level + 1, "if value == %s {\n", nullLiteral); } indent(sb, level + 2, "None\n"); @@ -833,8 +930,7 @@ private static void generatePrimitiveRequiredDecoder( if (fieldToken.version() > 0) { indent(sb, level + 1, "if self.acting_version() < %d {\n", fieldToken.version()); - indent(sb, level + 2, "return %s;\n", - generateRustLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString())); + indent(sb, level + 2, "return %s;\n", rustNullLiteral(encoding)); indent(sb, level + 1, "}\n\n"); } @@ -1257,8 +1353,7 @@ private static void generateEnum( // null value { final Encoding encoding = messageBody.get(0).encoding(); - final CharSequence nullVal = generateRustLiteral(encoding.primitiveType(), - encoding.applicableNullValue().toString()); + final CharSequence nullVal = rustNullLiteral(encoding); indent(writer, 1, "#[default]\n"); indent(writer, 1, "NullVal = %s, \n", nullVal); } @@ -1322,8 +1417,7 @@ private static void generateFromEnumForPrimitive( { final Encoding encoding = messageBody.get(0).encoding(); - final CharSequence nullVal = generateRustLiteral(encoding.primitiveType(), - encoding.applicableNullValue().toString()); + final CharSequence nullVal = rustNullLiteral(encoding); indent(writer, 3, "%s::NullVal => %s,\n", enumRustName, nullVal); } indent(writer, 2, "}\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index 43b9c8ba8a..ae55de1e9e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -17,6 +17,7 @@ import org.agrona.Verify; import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.PrimitiveValue; import uk.co.real_logic.sbe.generation.Generators; import uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType; import uk.co.real_logic.sbe.ir.Encoding; @@ -65,6 +66,11 @@ static String rustTypeName(final PrimitiveType primitiveType) return TYPE_NAME_BY_PRIMITIVE_TYPE_MAP.get(primitiveType); } + static String generateRustLiteral(final PrimitiveType type, final PrimitiveValue value) + { + return generateRustLiteral(type, value.toString()); + } + static String generateRustLiteral(final PrimitiveType type, final String value) { Verify.notNull(type, "type"); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java index d6d7652b83..6092fb5d48 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java @@ -88,6 +88,7 @@ void generateRustLiteralsForUnsignedPrimitiveNulls() assertEquals("0xff_u8", generateRustLiteral(UINT8, UINT8.nullValue().toString())); assertEquals("0xffff_u16", generateRustLiteral(UINT16, UINT16.nullValue().toString())); assertEquals("0xffffffff_u32", generateRustLiteral(UINT32, UINT32.nullValue().toString())); + assertEquals("0xffffffffffffffff_u64", generateRustLiteral(UINT64, UINT64.nullValue())); assertEquals("0xffffffffffffffff_u64", generateRustLiteral(UINT64, UINT64.nullValue().toString())); } @@ -100,7 +101,7 @@ void generateRustLiteralNullPrimitiveTypeParam() @Test void generateRustLiteralNullValueParam() { - assertThrows(NullPointerException.class, () -> generateRustLiteral(INT8, null)); + assertThrows(NullPointerException.class, () -> generateRustLiteral(INT8, (String)null)); } @Test diff --git a/sbe-tool/src/test/resources/fixed-sized-primitive-array-types.xml b/sbe-tool/src/test/resources/fixed-sized-primitive-array-types.xml new file mode 100644 index 0000000000..62f3b9a5b0 --- /dev/null +++ b/sbe-tool/src/test/resources/fixed-sized-primitive-array-types.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 4caa7f4e5db809fa2a411d949db44181e581b329 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jan 2025 22:06:15 +0100 Subject: [PATCH 1303/1594] Update copyright. --- CMakeLists.txt | 2 +- CONTRIBUTING.md | 2 +- README.md | 2 +- build.gradle | 4 ++-- sbe-benchmarks/src/main/cpp/CMakeLists.txt | 2 +- sbe-benchmarks/src/main/cpp/CarBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/CodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/MarketDataBench.cpp | 2 +- sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h | 2 +- sbe-benchmarks/src/main/cpp/benchlet-main.cpp | 2 +- sbe-benchmarks/src/main/cpp/benchlet.h | 2 +- .../src/main/java/uk/co/real_logic/sbe/CarBenchmark.java | 2 +- .../main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/package-info.java | 2 +- sbe-samples/src/main/cpp/CMakeLists.txt | 2 +- sbe-samples/src/main/cpp/GeneratedStubExample.cpp | 2 +- sbe-samples/src/main/cpp/OtfExample.cpp | 2 +- .../uk/co/real_logic/sbe/examples/ExampleTokenListener.java | 2 +- .../co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java | 2 +- .../sbe/examples/ExampleUsingGeneratedStubExtension.java | 2 +- .../main/java/uk/co/real_logic/sbe/examples/OtfExample.java | 2 +- .../main/java/uk/co/real_logic/sbe/examples/package-info.java | 2 +- sbe-tool/src/main/cpp/CMakeLists.txt | 2 +- sbe-tool/src/main/cpp/otf/Encoding.h | 2 +- sbe-tool/src/main/cpp/otf/IrDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h | 2 +- sbe-tool/src/main/cpp/otf/Token.h | 2 +- sbe-tool/src/main/golang/otf/encoding.go | 2 +- .../src/main/java/uk/co/real_logic/sbe/PrimitiveType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ValidationUtil.java | 2 +- .../main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java | 2 +- .../java/uk/co/real_logic/sbe/codec/java/MethodSelector.java | 2 +- .../java/uk/co/real_logic/sbe/codec/java/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/CodeGenerator.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/Generators.java | 2 +- .../uk/co/real_logic/sbe/generation/TargetCodeGenerator.java | 2 +- .../real_logic/sbe/generation/TargetCodeGeneratorLoader.java | 2 +- .../java/uk/co/real_logic/sbe/generation/c/CGenerator.java | 2 +- .../uk/co/real_logic/sbe/generation/c/COutputManager.java | 2 +- .../main/java/uk/co/real_logic/sbe/generation/c/CUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/c/package-info.java | 2 +- .../sbe/generation/common/FieldPrecedenceModel.java | 2 +- .../co/real_logic/sbe/generation/common/PrecedenceChecks.java | 2 +- .../uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java | 2 +- .../uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java | 2 +- .../real_logic/sbe/generation/cpp/NamespaceOutputManager.java | 2 +- .../uk/co/real_logic/sbe/generation/cpp/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/csharp/CSharp.java | 2 +- .../real_logic/sbe/generation/csharp/CSharpDtoGenerator.java | 2 +- .../uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java | 2 +- .../co/real_logic/sbe/generation/csharp/CSharpGenerator.java | 2 +- .../sbe/generation/csharp/CSharpNamespaceOutputManager.java | 2 +- .../uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/csharp/package-info.java | 2 +- .../generation/golang/flyweight/GolangFlyweightGenerator.java | 2 +- .../golang/flyweight/GolangFlyweightOutputManager.java | 2 +- .../sbe/generation/golang/flyweight/GolangFlyweightUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/golang/package-info.java | 2 +- .../sbe/generation/golang/struct/GolangGenerator.java | 2 +- .../sbe/generation/golang/struct/GolangOutputManager.java | 2 +- .../real_logic/sbe/generation/golang/struct/GolangUtil.java | 2 +- .../co/real_logic/sbe/generation/java/JavaDtoGenerator.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/JavaDtos.java | 2 +- .../uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 2 +- .../co/real_logic/sbe/generation/java/JavaOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/JavaUtil.java | 2 +- .../uk/co/real_logic/sbe/generation/java/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 2 +- .../co/real_logic/sbe/generation/rust/RustOutputManager.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/RustUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/rust/SubGroup.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/package-info.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java | 2 +- .../main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/ir/package-info.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java | 2 +- .../java/uk/co/real_logic/sbe/json/JsonTokenListener.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/json/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java | 2 +- .../main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java | 2 +- .../main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/otf/package-info.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java | 2 +- .../uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java | 2 +- .../uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java | 2 +- .../co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java | 2 +- sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java | 2 +- .../main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java | 2 +- .../src/main/java/uk/co/real_logic/sbe/xml/package-info.java | 2 +- .../uk/co/real_logic/sbe/properties/DtosPropertyTest.java | 2 +- .../uk/co/real_logic/sbe/properties/JsonPropertyTest.java | 2 +- .../uk/co/real_logic/sbe/properties/ParserPropertyTest.java | 2 +- .../real_logic/sbe/properties/arbitraries/SbeArbitraries.java | 2 +- .../real_logic/sbe/properties/schema/CompositeTypeSchema.java | 2 +- .../sbe/properties/schema/EncodedDataTypeSchema.java | 2 +- .../co/real_logic/sbe/properties/schema/EnumTypeSchema.java | 2 +- .../uk/co/real_logic/sbe/properties/schema/FieldSchema.java | 2 +- .../uk/co/real_logic/sbe/properties/schema/GroupSchema.java | 2 +- .../uk/co/real_logic/sbe/properties/schema/MessageSchema.java | 2 +- .../uk/co/real_logic/sbe/properties/schema/SetSchema.java | 2 +- .../real_logic/sbe/properties/schema/TestXmlSchemaWriter.java | 2 +- .../uk/co/real_logic/sbe/properties/schema/TypeSchema.java | 2 +- .../real_logic/sbe/properties/schema/TypeSchemaVisitor.java | 2 +- .../uk/co/real_logic/sbe/properties/schema/VarDataSchema.java | 2 +- .../sbe/properties/utils/InMemoryOutputManager.java | 2 +- sbe-tool/src/test/c/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/c/CComplianceTest.c | 2 +- sbe-tool/src/test/c/CComplianceWithVersionTest.c | 2 +- sbe-tool/src/test/c/CMakeLists.txt | 2 +- sbe-tool/src/test/c/CodeGenTest.cpp | 2 +- sbe-tool/src/test/c/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/c/Issue889Test.cpp | 2 +- sbe-tool/src/test/cpp/BoundsCheckTest.cpp | 2 +- sbe-tool/src/test/cpp/CMakeLists.txt | 2 +- sbe-tool/src/test/cpp/CodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeElementsTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp | 2 +- sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp | 2 +- sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp | 2 +- sbe-tool/src/test/cpp/GroupWithDataTest.cpp | 2 +- sbe-tool/src/test/cpp/Issue835Test.cpp | 2 +- sbe-tool/src/test/cpp/Issue889Test.cpp | 2 +- sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp | 2 +- sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp | 2 +- .../test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java | 2 +- .../java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java | 2 +- .../java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/TestTargetLanguage.java | 2 +- sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java | 2 +- .../test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java | 2 +- .../java/uk/co/real_logic/sbe/generation/cpp/CppEnumTest.java | 2 +- .../uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java | 2 +- .../co/real_logic/sbe/generation/csharp/CSharpEnumTest.java | 2 +- .../real_logic/sbe/generation/csharp/CSharpGeneratorTest.java | 2 +- .../sbe/generation/csharp/Issue567GroupSizeTest.java | 2 +- .../sbe/generation/golang/GolangStructGeneratorTest.java | 2 +- .../co/real_logic/sbe/generation/java/CarDecodeTestUtil.java | 2 +- .../real_logic/sbe/generation/java/CharacterEncodingTest.java | 2 +- .../sbe/generation/java/CompositeElementsGenerationTest.java | 2 +- .../real_logic/sbe/generation/java/ConstantCharArrayTest.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/DtoTest.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/EnumTest.java | 2 +- .../sbe/generation/java/FixedSizeDataGeneratorTest.java | 2 +- .../real_logic/sbe/generation/java/GenerateFixBinaryTest.java | 2 +- .../sbe/generation/java/GenerateIlinkBinaryTest.java | 2 +- .../co/real_logic/sbe/generation/java/JavaGeneratorTest.java | 2 +- .../real_logic/sbe/generation/java/JavaOutputManagerTest.java | 2 +- .../co/real_logic/sbe/generation/java/NullEnumTypedTest.java | 2 +- .../sbe/generation/java/PackageOutputManagerTest.java | 2 +- .../co/real_logic/sbe/generation/java/QualifiedYieldTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/ReflectionUtil.java | 2 +- .../java/uk/co/real_logic/sbe/generation/java/RewindTest.java | 2 +- .../real_logic/sbe/generation/java/SchemaExtensionTest.java | 2 +- .../java/SinceVersionTransformedSchemaJavaGenerationTest.java | 2 +- .../sbe/generation/java/SkipAndDecodedLengthTest.java | 2 +- .../uk/co/real_logic/sbe/generation/java/ToStringTest.java | 2 +- .../sbe/generation/java/ValueRefWithLowerCaseEnumTest.java | 2 +- .../real_logic/sbe/generation/java/WarningFormattingTest.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/RustUtilTest.java | 2 +- .../uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java | 2 +- .../java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java | 2 +- .../uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java | 2 +- .../co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java | 2 +- .../test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java | 2 +- .../java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java | 2 +- .../co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java | 2 +- .../src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java | 2 +- .../real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java | 2 +- 212 files changed, 213 insertions(+), 213 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b78278fca..326986a509 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2024 Real Logic Limited. +# Copyright 2013-2025 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 24b6402de5..bac5877c8e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ If you are adding a new file it should have the following header: ``` /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 3b2d354d45..c051584e3b 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ Or run test directly with `Cargo` License (See LICENSE file for full license) ------------------------------------------- -Copyright 2013-2024 Real Logic Limited. +Copyright 2013-2025 Real Logic Limited. Copyright 2017 MarketFactory Inc. Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/build.gradle b/build.gradle index 3e3b3b2ee7..586f2d9c5a 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -194,7 +194,7 @@ subprojects { javadoc { failOnError false title = '

      Simple Binary Encoding (SBE)

      ' - options.bottom = 'Copyright © 2013-2024 Real Logic Limited. All Rights Reserved.' + options.bottom = 'Copyright © 2013-2025 Real Logic Limited. All Rights Reserved.' options.encoding = 'UTF-8' options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' diff --git a/sbe-benchmarks/src/main/cpp/CMakeLists.txt b/sbe-benchmarks/src/main/cpp/CMakeLists.txt index 055ea4f63a..38a1f071b4 100644 --- a/sbe-benchmarks/src/main/cpp/CMakeLists.txt +++ b/sbe-benchmarks/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2024 Real Logic Limited. +# Copyright 2013-2025 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/CarBench.cpp b/sbe-benchmarks/src/main/cpp/CarBench.cpp index 42c757efd2..74e174f016 100644 --- a/sbe-benchmarks/src/main/cpp/CarBench.cpp +++ b/sbe-benchmarks/src/main/cpp/CarBench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/CodecBench.h b/sbe-benchmarks/src/main/cpp/CodecBench.h index 14cf19547e..005cfa0fc4 100644 --- a/sbe-benchmarks/src/main/cpp/CodecBench.h +++ b/sbe-benchmarks/src/main/cpp/CodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp index a320b30ab7..04d00a9cf8 100644 --- a/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp +++ b/sbe-benchmarks/src/main/cpp/MarketDataBench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h index fb044428ae..9f40e6e080 100644 --- a/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeCarCodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h index fbe11e6de0..38f58d6729 100644 --- a/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h +++ b/sbe-benchmarks/src/main/cpp/SbeMarketDataCodecBench.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp index f60927438f..c106879458 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet-main.cpp +++ b/sbe-benchmarks/src/main/cpp/benchlet-main.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/cpp/benchlet.h b/sbe-benchmarks/src/main/cpp/benchlet.h index c883dd0faf..aa3eb621ac 100644 --- a/sbe-benchmarks/src/main/cpp/benchlet.h +++ b/sbe-benchmarks/src/main/cpp/benchlet.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java index 1531933165..dbc37037ff 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/CarBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java index 1125c6ccc3..c97c0f0144 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/MarketDataBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java index 5e8842c2c8..88ae5ee4ba 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/CMakeLists.txt b/sbe-samples/src/main/cpp/CMakeLists.txt index 2e0a6c8d16..dd64470943 100644 --- a/sbe-samples/src/main/cpp/CMakeLists.txt +++ b/sbe-samples/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2024 Real Logic Limited. +# Copyright 2013-2025 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp index 2ee019f9df..a1e4908678 100644 --- a/sbe-samples/src/main/cpp/GeneratedStubExample.cpp +++ b/sbe-samples/src/main/cpp/GeneratedStubExample.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/cpp/OtfExample.cpp b/sbe-samples/src/main/cpp/OtfExample.cpp index ed24a59a6c..89921520ad 100644 --- a/sbe-samples/src/main/cpp/OtfExample.cpp +++ b/sbe-samples/src/main/cpp/OtfExample.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java index fb03fb954e..51302141d0 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java index 16e4617ce3..00ff187351 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java index 02daba6701..f053e7fd39 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java index a45f734aea..2a1c864575 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/OtfExample.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java index a582d13016..1924360927 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/CMakeLists.txt b/sbe-tool/src/main/cpp/CMakeLists.txt index abb1f83a49..bcfdad0e3b 100644 --- a/sbe-tool/src/main/cpp/CMakeLists.txt +++ b/sbe-tool/src/main/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2024 Real Logic Limited. +# Copyright 2013-2025 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/Encoding.h b/sbe-tool/src/main/cpp/otf/Encoding.h index c6464e5ffc..0f265117cc 100644 --- a/sbe-tool/src/main/cpp/otf/Encoding.h +++ b/sbe-tool/src/main/cpp/otf/Encoding.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index b4ed9cefd8..2c497d29ad 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h index 56249a832b..46440d9233 100644 --- a/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfHeaderDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h index edd65bff17..e84e51db3f 100644 --- a/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h +++ b/sbe-tool/src/main/cpp/otf/OtfMessageDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/cpp/otf/Token.h b/sbe-tool/src/main/cpp/otf/Token.h index 69e06224cc..2855c2a86c 100644 --- a/sbe-tool/src/main/cpp/otf/Token.h +++ b/sbe-tool/src/main/cpp/otf/Token.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/golang/otf/encoding.go b/sbe-tool/src/main/golang/otf/encoding.go index a10fef5b2d..b98f336892 100644 --- a/sbe-tool/src/main/golang/otf/encoding.go +++ b/sbe-tool/src/main/golang/otf/encoding.go @@ -1,4 +1,4 @@ -// Copyright 2013-2024 Real Logic Limited. +// Copyright 2013-2025 Real Logic Limited. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java index 92cb21c32d..ed4a263768 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java index 18b543aef6..db90ae0459 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/PrimitiveValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index 9c0ab8df4b..552a9656ab 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index a7bb7e0d19..426e7c4fd1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java index 93e86eee1e..4d60edc6a5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/GroupOrder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java index 7f17222cdc..687a921a0a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/MethodSelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java index f10999cff9..a97ba65c46 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java index 03dcf30090..2afc91a9c8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/CodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java index a6ba5850ea..c2af0d3738 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/Generators.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java index 461cb2bb22..aa8a41fc21 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index c979bede45..db33966a89 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 68afbb8283..427034515d 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java index 0da63b7c09..4459dc09ac 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/COutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java index 518abd80b2..09067240c0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java index 956b86d379..5cba823b2d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java index 40e5ac7441..cad644fedf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/PrecedenceChecks.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/PrecedenceChecks.java index cd5e1856aa..882e4dd66e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/PrecedenceChecks.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/PrecedenceChecks.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index b6f337a837..05d214d751 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java index 6e59b6dd06..1dde335d57 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index b8d427241a..df1140ee22 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index 469faac27a..f076301379 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java index 43c45fa9f7..71f993dc97 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/NamespaceOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java index 4ea7958015..49a0229afc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java index f13b9cfab6..5125f79246 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java index b5225caa67..47bef5a349 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java index 118b8e8d45..ab5b591b48 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index af9979879a..b6fd5d7746 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java index 6ec2505238..841c2fbfb1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpNamespaceOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index b4fee26faf..0fd31feed6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java index 54b9fdd77c..53c5a9418d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java index 259c461408..8b2d65ab62 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightOutputManager.java index 3b9e72b716..541fee82b6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java index ba03adbc3b..2b74309d13 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java index c30d9ed062..a11cc42072 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java index 58c357951d..d764a11eca 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangOutputManager.java index a584396a09..faf3178e3d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangUtil.java index 2689da26de..f2a6343387 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright (C) 2016 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java index 8c5bfb8b02..4d8b3d334c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java index 3d4dc61482..852e6bdd04 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright (C) 2017 MarketFactory, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index b47b8839cc..5f28c17a90 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java index 9bbe32bc86..51817dc04c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 7f885f673c..2290e7f468 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java index cfe10b0723..ee4ebf09fc 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java index 7a6cae1bac..2c9b0501aa 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 39a5ed633c..f361397916 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index 8faaa9c451..da9060b9a2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index d56c680d28..32f1633178 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java index 49f5f6747d..fe8ca08e63 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index ae55de1e9e..a38bea7a7a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index d0b5abc433..5c1981a874 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java index bfaccf83ee..2c817689c3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java index db4e41a9ff..0a7b332130 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java index 318cc3061f..dfae5acb7d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/GenerationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java index 1ca42e82d1..42fa6b9103 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/HeaderStructure.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java index 87eba20050..09e3f33ead 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Ir.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index 4db9e04a99..98e1a9d409 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java index 82ad99d714..c3bf073e5e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java index b72f8b46a0..13694d0579 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java index db6d2cb849..22c21b7735 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Signal.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index 6d97572727..7ea00920c0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java index b4533bccb0..f317c5e7f3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java index 3071afb6c9..efff7fdd93 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonPrinter.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index 9ae537b397..4d81dc47b9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java index a7214788a4..476fe58c1c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java index 3f2e518d31..1422092ba1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java index 7bbe1fb11f..41f79bfba8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfHeaderDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java index f9c243555b..1143379c7d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/OtfMessageDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java index df2782b168..a746798965 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/TokenListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java index 0f8916d55b..d9c64a2a2f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java index d3e1aebfb7..04cf0dddd4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java index 06dfbeb735..fd30d70f78 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index f7d6052df2..37b8b0e808 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index 78fe6e10a0..0239e864ec 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index b2566ea787..bedafa57b3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java index 8d3c48ea3f..ceb020e85b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java index d445da2f92..aa91b6ff31 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java index 49cf4ca722..b79e1d6493 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java index 8f507ca366..3575d38413 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IrGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java index 90695b736a..9fbdfc7789 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java index 5203939b4d..c9dfbec5e5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/MessageSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java index 93aa9c8260..b4569347c6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ParserOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java index 2eee8a20c0..f608e572ec 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Presence.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java index 11bdccbe08..8407385f0d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java index c52ae6feed..7b0e678c88 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index ff5b025ae4..467ac93b80 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java index b96605d860..a5d876baab 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java index 9590c3e756..9b193b6cd9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Type.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java index 008e5a1629..8667d2501c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/XmlSchemaParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright 2017 MarketFactory Inc * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java index c16ea698f3..7c0ead4286 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java index a8341e578c..04e1d8fdae 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java index f3d49fbbe7..ebac19703e 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java index 3be05c85ae..451ea8d0e7 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/ParserPropertyTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index b8543b0abd..c1dc232ee3 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java index 264a49219d..f51e23fd90 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/CompositeTypeSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java index ea9d3228bb..443c594934 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EncodedDataTypeSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java index b129e54c71..284791d38b 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/EnumTypeSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java index 1cf9cc2ccf..9a809642dc 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/FieldSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java index c0fafb0dbf..4046d60ecd 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/GroupSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java index edde5e89b6..a071ee2db9 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/MessageSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java index 071f8e7419..502812a672 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/SetSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java index faeaab331b..5dc4569db2 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java index 4a359fa6be..e03d2f5bf8 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java index 7dbc69188f..9e4cb435b2 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TypeSchemaVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java index a4298e89e7..eb636a7b80 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/VarDataSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java index dc8482c525..065737c57e 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/BoundsCheckTest.cpp b/sbe-tool/src/test/c/BoundsCheckTest.cpp index 047fab85e6..eda469aed9 100644 --- a/sbe-tool/src/test/c/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/c/BoundsCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CComplianceTest.c b/sbe-tool/src/test/c/CComplianceTest.c index 150edec6e5..33f8070605 100644 --- a/sbe-tool/src/test/c/CComplianceTest.c +++ b/sbe-tool/src/test/c/CComplianceTest.c @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CComplianceWithVersionTest.c b/sbe-tool/src/test/c/CComplianceWithVersionTest.c index 9156d58ce5..4de06c4b92 100644 --- a/sbe-tool/src/test/c/CComplianceWithVersionTest.c +++ b/sbe-tool/src/test/c/CComplianceWithVersionTest.c @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index 33169a501d..2ed9136bec 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2024 Real Logic Limited. +# Copyright 2013-2025 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index cda5433609..6f2a195a11 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/GroupWithDataTest.cpp b/sbe-tool/src/test/c/GroupWithDataTest.cpp index f643b2de43..68e34d8bfd 100644 --- a/sbe-tool/src/test/c/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/c/GroupWithDataTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/c/Issue889Test.cpp b/sbe-tool/src/test/c/Issue889Test.cpp index 800065e7da..2c39ea7d7e 100644 --- a/sbe-tool/src/test/c/Issue889Test.cpp +++ b/sbe-tool/src/test/c/Issue889Test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp index aaa6a174a0..9b1763ce0d 100644 --- a/sbe-tool/src/test/cpp/BoundsCheckTest.cpp +++ b/sbe-tool/src/test/cpp/BoundsCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index ee09f3881e..675688cc0c 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2013-2024 Real Logic Limited. +# Copyright 2013-2025 Real Logic Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index 039620a6c1..25c645248f 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp index cede889d68..660333368c 100644 --- a/sbe-tool/src/test/cpp/CompositeElementsTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeElementsTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp index f767072ac6..39383e7659 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsCodeGenTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp index 22ebe9ecc2..468c2a4594 100644 --- a/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp +++ b/sbe-tool/src/test/cpp/CompositeOffsetsIrTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp index 24ad58c9b8..ef59c81d01 100644 --- a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp +++ b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp index 03d35c2dee..e984de02e9 100644 --- a/sbe-tool/src/test/cpp/GroupWithDataTest.cpp +++ b/sbe-tool/src/test/cpp/GroupWithDataTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/Issue835Test.cpp b/sbe-tool/src/test/cpp/Issue835Test.cpp index 9f59ae3fb0..a1fd46f864 100644 --- a/sbe-tool/src/test/cpp/Issue835Test.cpp +++ b/sbe-tool/src/test/cpp/Issue835Test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/Issue889Test.cpp b/sbe-tool/src/test/cpp/Issue889Test.cpp index 2acafb021a..3919c2a889 100644 --- a/sbe-tool/src/test/cpp/Issue889Test.cpp +++ b/sbe-tool/src/test/cpp/Issue889Test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp index 881dd0c020..4d76653fa0 100644 --- a/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp +++ b/sbe-tool/src/test/cpp/MessageBlockLengthTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp index fe8a58e6b1..fc2dabafda 100644 --- a/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp +++ b/sbe-tool/src/test/cpp/Rc3OtfFullIrTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java index 335e3a59b0..d785c2865b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/EncodedCarTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java index 6ac554b8a7..9afc026648 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/FieldAccessOrderCheckTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java index d0a0bdbdeb..8b943f6275 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TargetCodeGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java index 616aa06603..e47bf3a2bf 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/TestTargetLanguage.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java index be6fad4b98..d7b91086b7 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/Tests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java index b09495875d..27886bdb2b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/codec/java/TypesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppEnumTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppEnumTest.java index db69b1cf83..0091dd16f0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppEnumTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppEnumTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index 79c1651c03..6d4990df3b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpEnumTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpEnumTest.java index fec4a1bcfd..b042fc558d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpEnumTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpEnumTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java index 295ddd293b..e78952d1d2 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java index f96c1ee283..dc60b05010 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/Issue567GroupSizeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangStructGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangStructGeneratorTest.java index b4d6198680..aa578e2de9 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangStructGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangStructGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java index 4e063e9b4a..a5d089df1c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CarDecodeTestUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java index 487ce653d3..773ed6e497 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CharacterEncodingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java index ffc38c539f..e44d03263c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/CompositeElementsGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java index e6fe0c252a..e65dda9aa3 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ConstantCharArrayTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java index 68b2fdce83..56d6869199 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java index 11c3424e6c..90eca7fc1c 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java index cd334d9cc1..74d95b309e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/FixedSizeDataGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java index 277404993f..a26048d38d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateFixBinaryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java index babefc9391..3f9b7b024e 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/GenerateIlinkBinaryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 68679c15a1..4b50d633e6 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java index 1eff4fa662..7d6d315744 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaOutputManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java index d949d6dfe8..97f2ac8c3b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/NullEnumTypedTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java index 36e78d2a28..932da0638b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/PackageOutputManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java index c5f0133783..5f0900a9f8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java index 2db082c6fc..acba97facd 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ReflectionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java index de19ed99ed..01a42a1ce5 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/RewindTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java index ee85bc2abe..bf4ebe746d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java index d69fc82a26..39cee1146b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java index a69c9bfadb..4984038080 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SkipAndDecodedLengthTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java index daec79f9ec..13761019a4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ToStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnumTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnumTest.java index 675f99d05e..3d71f72c31 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnumTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/ValueRefWithLowerCaseEnumTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java index 2871b78d54..abf3b96e91 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/WarningFormattingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java index 6092fb5d48..e86e54c438 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index f3509f7d97..97faca7848 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java index c888b3f9c5..f5acaa4544 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeElementsIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java index ee2eef15e9..c5c88e9179 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeOffsetsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java index 0d0416dd5a..4e80cd7b53 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/CompositeRefsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index d534863d86..2111fb1038 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java index 5519bcbf15..d4a31725d1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/GroupWithDataIrTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java index a2223ced19..3c8cfaf4a2 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/SinceVersionValidationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java index b4bdfe9b52..b84abc5b42 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/ValueRefsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java index b5995c4dac..664e45bdee 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/json/JsonPrinterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java index 3d392e0e95..09ff6834e4 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java index a44ee8d4cd..19066eac25 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeElementsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java index 38d399d1e0..ff63651471 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CompositeTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java index b3b3f7ae4e..052d0aa77f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/CyclicReferencesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java index 63495cd586..48515d5dc8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EmbeddedLengthAndCountFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java index a0648b730c..f83abce08b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EncodedDataTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java index 70d8159f9b..9acd1b6c3b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/EnumTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java index bfb2965116..94011259e1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/ErrorHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * Copyright 2017 MarketFactory Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java index 265b088c7d..0aadb1715d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/GroupWithDataTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java index b8c2c130fb..c865dedd33 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/OffsetFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java index 7c134861be..c710b46e04 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java index f4ec8c63db..d92183e2d0 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index 256e832ded..60d09daa15 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java index 32690f6b87..0fd1d90bfd 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 Real Logic Limited. + * Copyright 2013-2025 Real Logic Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From a209a2f9dd0f0fc69d849a5b75b05f40f5d9b27b Mon Sep 17 00:00:00 2001 From: Nate Bradac <38217740+nbradac@users.noreply.github.com> Date: Wed, 8 Jan 2025 13:03:03 -0600 Subject: [PATCH 1304/1594] [C++] use m_actingBlockLength in decodeLength() (#1045) --- .../sbe/generation/cpp/CppGenerator.java | 2 +- sbe-tool/src/test/cpp/CMakeLists.txt | 7 +++ .../src/test/cpp/VersionedMessageTest.cpp | 57 +++++++++++++++++++ .../test/resources/versioned-message-v1.xml | 25 ++++++++ .../test/resources/versioned-message-v2.xml | 28 +++++++++ 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 sbe-tool/src/test/cpp/VersionedMessageTest.cpp create mode 100644 sbe-tool/src/test/resources/versioned-message-v1.xml create mode 100644 sbe-tool/src/test/resources/versioned-message-v2.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index df1140ee22..dd5065dbe2 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -3027,7 +3027,7 @@ private CharSequence generateMessageFlyweightCode( " SBE_NODISCARD std::uint64_t decodeLength() const\n" + " {\n" + - " %10$s skipper(m_buffer, m_offset, m_bufferLength, sbeBlockLength(), m_actingVersion);\n" + + " %10$s skipper(m_buffer, m_offset, m_bufferLength, m_actingBlockLength, m_actingVersion);\n" + " skipper.skip();\n" + " return skipper.encodedLength();\n" + " }\n\n" + diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index 675688cc0c..53bb18f2ef 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -43,6 +43,8 @@ set(DTO_SCHEMA ${CODEC_SCHEMA_DIR}/dto-test-schema.xml) set(ISSUE835_SCHEMA ${CODEC_SCHEMA_DIR}/issue835.xml) set(ISSUE889_SCHEMA ${CODEC_SCHEMA_DIR}/issue889.xml) set(ACCESS_ORDER_SCHEMA ${CODEC_SCHEMA_DIR}/field-order-check-schema.xml) +set(VERSIONED_MESSAGE_V1_SCHEMA ${CODEC_SCHEMA_DIR}/versioned-message-v1.xml) +set(VERSIONED_MESSAGE_V2_SCHEMA ${CODEC_SCHEMA_DIR}/versioned-message-v2.xml) set(GENERATED_CODECS ${CXX_CODEC_TARGET_DIR} @@ -59,6 +61,8 @@ add_custom_command( ${ISSUE835_SCHEMA} ${ISSUE889_SCHEMA} ${ACCESS_ORDER_SCHEMA} + ${VERSIONED_MESSAGE_V1_SCHEMA} + ${VERSIONED_MESSAGE_V2_SCHEMA} sbe-jar ${SBE_JAR} COMMAND ${Java_JAVA_EXECUTABLE} --add-opens java.base/jdk.internal.misc=ALL-UNNAMED @@ -79,6 +83,8 @@ add_custom_command( ${ISSUE835_SCHEMA} ${ISSUE889_SCHEMA} ${ACCESS_ORDER_SCHEMA} + ${VERSIONED_MESSAGE_V1_SCHEMA} + ${VERSIONED_MESSAGE_V2_SCHEMA} ) add_custom_target(codecs DEPENDS ${GENERATED_CODECS}) @@ -96,6 +102,7 @@ sbe_test(Issue835Test codecs) sbe_test(Issue889Test codecs) sbe_test(FieldAccessOrderCheckTest codecs) target_compile_definitions(FieldAccessOrderCheckTest PRIVATE SBE_ENABLE_PRECEDENCE_CHECKS_IN_TESTS) +sbe_test(VersionedMessageTest codecs) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # Check if the GCC version supports C++17 diff --git a/sbe-tool/src/test/cpp/VersionedMessageTest.cpp b/sbe-tool/src/test/cpp/VersionedMessageTest.cpp new file mode 100644 index 0000000000..af4a90c442 --- /dev/null +++ b/sbe-tool/src/test/cpp/VersionedMessageTest.cpp @@ -0,0 +1,57 @@ +/* + * Copyright 2013-2025 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "versmsg/VersionedMessageV1.h" +#include "versmsg/VersionedMessageV2.h" + +using namespace versmsg; + +static const std::size_t BUFFER_LEN = 2048; + +class VersionedMessageTest : public testing::Test +{ +public: + VersionedMessageV2 m_versionedMessageV2 = {}; + VersionedMessageV1 m_versionedMessageV1Decoder = {}; +}; + +TEST_F(VersionedMessageTest, shouldV1DecodeV2Message) +{ + char buffer[BUFFER_LEN] = {}; + + m_versionedMessageV2.wrapForEncode(buffer, 0, sizeof(buffer)); + m_versionedMessageV2.fieldA1(1); + m_versionedMessageV2.fieldB1(2); + m_versionedMessageV2.fieldC2(3); + m_versionedMessageV2.fieldD2(4); + m_versionedMessageV2.fieldE2(5); + m_versionedMessageV2.putString1("asdf", 4); + + m_versionedMessageV1Decoder.wrapForDecode( + buffer, + 0, + VersionedMessageV2::sbeBlockLength(), + VersionedMessageV2::sbeSchemaVersion(), + m_versionedMessageV2.encodedLength()); + + EXPECT_EQ(m_versionedMessageV1Decoder.fieldA1(), (uint32_t)1); + EXPECT_EQ(m_versionedMessageV1Decoder.fieldB1(), (uint32_t)2); + EXPECT_STREQ(m_versionedMessageV1Decoder.string1(), "asdf"); + + EXPECT_EQ(m_versionedMessageV1Decoder.decodeLength(), (uint64_t)26); +} diff --git a/sbe-tool/src/test/resources/versioned-message-v1.xml b/sbe-tool/src/test/resources/versioned-message-v1.xml new file mode 100644 index 0000000000..bd942e82c7 --- /dev/null +++ b/sbe-tool/src/test/resources/versioned-message-v1.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/sbe-tool/src/test/resources/versioned-message-v2.xml b/sbe-tool/src/test/resources/versioned-message-v2.xml new file mode 100644 index 0000000000..3d0de450e5 --- /dev/null +++ b/sbe-tool/src/test/resources/versioned-message-v2.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + From ac0b41a9f7d94ab5e93e7f2d5b70f7c3a04907e2 Mon Sep 17 00:00:00 2001 From: Nate Bradac <38217740+nbradac@users.noreply.github.com> Date: Wed, 8 Jan 2025 14:40:06 -0600 Subject: [PATCH 1305/1594] [C++] check for not wrapped state in decodeLength() when precedence checks are enabled (#1046) --- .../sbe/generation/cpp/CppGenerator.java | 41 ++++++++++++++++++- .../test/cpp/FieldAccessOrderCheckTest.cpp | 40 ++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index dd5065dbe2..566545df2f 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -536,6 +536,18 @@ private static void generateAccessOrderException( .append(fieldPrecedenceModel.generatedRepresentationClassName()).append(".\");\n"); } + private static void generateAccessOrderException( + final StringBuilder sb, + final String indent, + final String action) + { + sb.append(indent).append("throw AccessOrderError(") + .append("std::string(\"Illegal access. \") + \n") + .append(indent).append(INDENT) + .append("\"Cannot call \\\"").append(action) + .append("()\\\" in state: \" + codecStateName(codecState()));\n"); + } + private static void generateAccessOrderListenerMethodForNextGroupElement( final StringBuilder sb, final FieldPrecedenceModel fieldPrecedenceModel, @@ -3027,6 +3039,7 @@ private CharSequence generateMessageFlyweightCode( " SBE_NODISCARD std::uint64_t decodeLength() const\n" + " {\n" + + "%22$s" + " %10$s skipper(m_buffer, m_offset, m_bufferLength, m_actingBlockLength, m_actingVersion);\n" + " skipper.skip();\n" + " return skipper.encodedLength();\n" + @@ -3071,7 +3084,8 @@ private CharSequence generateMessageFlyweightCode( generateCodecStateTransitionForWrappingLatestVersion(fieldPrecedenceModel), generateOnWrappedListener(fieldPrecedenceModel), generateCodecStateTransitionForWrapping(fieldPrecedenceModel), - generateHiddenCopyConstructor(" ", className)); + generateHiddenCopyConstructor(" ", className), + generateCheckForNotWrappedState("decodeLength", fieldPrecedenceModel)); } private CharSequence generateAccessOrderErrorType(final FieldPrecedenceModel fieldPrecedenceModel) @@ -3311,6 +3325,31 @@ private CharSequence generateCodecStateTransitionForWrapping(final FieldPreceden return generateAccessOrderListenerCall(fieldPrecedenceModel, TWO_INDENT, "onWrapped", "actingVersion"); } + private CharSequence generateCheckForNotWrappedState( + final String action, + final FieldPrecedenceModel fieldPrecedenceModel) + { + if (null == fieldPrecedenceModel) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + sb.append("#if defined(").append(precedenceChecksFlagName).append(")\n") + .append(TWO_INDENT) + .append("if (codecState() == ") + .append(qualifiedStateCase(fieldPrecedenceModel.notWrappedState())) + .append(")\n") + .append(TWO_INDENT).append("{\n"); + + generateAccessOrderException(sb, THREE_INDENT, action); + + sb.append(TWO_INDENT).append("}\n") + .append("#endif\n"); + + return sb; + } + private CharSequence generateCodecStateTransitionForWrappingLatestVersion( final FieldPrecedenceModel fieldPrecedenceModel ) diff --git a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp index ef59c81d01..2c0e524dc0 100644 --- a/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp +++ b/sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp @@ -5048,3 +5048,43 @@ TEST_F(FieldAccessOrderCheckTest, worksWithInsertionOperator) EXPECT_EQ(decoder.getBAsString(), "abc"); EXPECT_EQ(decoder.getCAsString(), "def"); } + +TEST_F(FieldAccessOrderCheckTest, shouldThrowExceptionWhenNotWrapped) +{ + MultipleVarLength encoder; + encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN); + encoder.a(42); + encoder.putB("abc"); + encoder.putC("def"); + encoder.checkEncodingIsComplete(); + + MultipleVarLength decoder; + + EXPECT_THROW( + { + try + { + decoder.decodeLength(); + } + catch (const std::exception &e) + { + EXPECT_THAT( + e.what(), + HasSubstr("Illegal access. Cannot call \"decodeLength()\" in state: NOT_WRAPPED") + ); + throw; + } + }, + std::logic_error + ); + + decoder.wrapForDecode( + m_buffer, + OFFSET, + MultipleVarLength::sbeBlockLength(), + MultipleVarLength::sbeSchemaVersion(), + BUFFER_LEN + ); + + decoder.decodeLength(); +} From 28fac12c286b0d30400396331740a819ca314ff5 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 13 Jan 2025 09:54:11 +0100 Subject: [PATCH 1306/1594] [Java] Upgrade to Json 20250107. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b433f94282..f918445ba3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ agrona = { group = "org.agrona", name = "agrona", version.ref = "agrona" } mockito = { group = "org.mockito", name = "mockito-core", version = "5.14.2" } hamcrest = { group = "org.hamcrest", name = "hamcrest", version = "3.0" } jqwik = { group = "net.jqwik", name = "jqwik", version = "1.9.2" } -json = { group = "org.json", name = "json", version = "20240303" } +json = { group = "org.json", name = "json", version = "20250107" } jmh-core = { group = "org.openjdk.jmh", name = "jmh-core", version.ref = "jmh" } jmh-generator-annprocess = { group = "org.openjdk.jmh", name = "jmh-generator-annprocess", version.ref = "jmh" } From d64176dc07e826cd1d7327d9221397d80bcff5c2 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 13 Jan 2025 09:57:02 +0100 Subject: [PATCH 1307/1594] [Java] Upgrade to Mockito 5.15.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f918445ba3..6251b66540 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ gradle = "8.11.1" [libraries] agrona = { group = "org.agrona", name = "agrona", version.ref = "agrona" } -mockito = { group = "org.mockito", name = "mockito-core", version = "5.14.2" } +mockito = { group = "org.mockito", name = "mockito-core", version = "5.15.2" } hamcrest = { group = "org.hamcrest", name = "hamcrest", version = "3.0" } jqwik = { group = "net.jqwik", name = "jqwik", version = "1.9.2" } json = { group = "org.json", name = "json", version = "20250107" } From 59bd78942f4d1d7c6860038a2581639057cdd2a0 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 13 Jan 2025 10:00:20 +0100 Subject: [PATCH 1308/1594] 1.34.1 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index c9c35c012f..a95a46d9fa 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.35.0-SNAPSHOT +1.34.1 From 03dc5e828677670765a975ef5061381dcfb94da3 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 13 Jan 2025 10:00:32 +0100 Subject: [PATCH 1309/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index a95a46d9fa..c9c35c012f 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.34.1 +1.35.0-SNAPSHOT From 98b23b6d998e917b1b573db5c0144bc8e854f6ea Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 13 Jan 2025 10:59:34 +0100 Subject: [PATCH 1310/1594] [Java] Fix Javadoc location. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 586f2d9c5a..942d14a8f3 100644 --- a/build.gradle +++ b/build.gradle @@ -199,7 +199,7 @@ subprojects { options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' options.links("https://www.javadoc.io/doc/org.agrona/agrona/${libs.versions.agrona.get()}/") - if (buildJavaVersion >= 23) { // early access JavaDoc location is different + if (buildJavaVersion > 23) { // early access JavaDoc location is different options.links("https://download.java.net/java/early_access/jdk${buildJavaVersion}/docs/api/") } else { From 4ec602554226e0795f087270270380090f60ae7a Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 13 Jan 2025 11:18:05 +0100 Subject: [PATCH 1311/1594] [Java] Use different URI for early access JDK build. --- build.gradle | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 942d14a8f3..ec29dfe5a4 100644 --- a/build.gradle +++ b/build.gradle @@ -27,8 +27,15 @@ plugins { defaultTasks 'clean', 'build' + +static def rawBuildJavaVersion() +{ + return System.getenv('BUILD_JAVA_VERSION') ?: JavaVersion.current().getMajorVersion() +} +boolean isEarlyAccessJavaVersion = rawBuildJavaVersion().endsWith("-ea") + static def getBuildJavaVersion() { - def buildJavaVersion = System.getenv('BUILD_JAVA_VERSION') ?: JavaVersion.current().getMajorVersion() + def buildJavaVersion = rawBuildJavaVersion() if (buildJavaVersion.indexOf('.') > 0) { buildJavaVersion = buildJavaVersion.substring(0, buildJavaVersion.indexOf('.')) } @@ -199,7 +206,7 @@ subprojects { options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' options.links("https://www.javadoc.io/doc/org.agrona/agrona/${libs.versions.agrona.get()}/") - if (buildJavaVersion > 23) { // early access JavaDoc location is different + if (isEarlyAccessJavaVersion) { options.links("https://download.java.net/java/early_access/jdk${buildJavaVersion}/docs/api/") } else { From 4c07009956e59db622d972a0c5ed64f4575a99ac Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:57:50 +0100 Subject: [PATCH 1312/1594] [Java] Upgrade to Checkstyle 10.21.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6251b66540..259a4f1504 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.0.0" -checkstyle = "10.21.0" +checkstyle = "10.21.1" junit = "5.11.4" jmh = "1.37" gradle = "8.11.1" From 43d4cfa85cdba5625aef2785e457ccf504fe24a4 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:58:10 +0100 Subject: [PATCH 1313/1594] [Java] Upgrade to Agrona 2.0.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 259a4f1504..63dfb168d4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.0.0" +agrona = "2.0.1" checkstyle = "10.21.1" junit = "5.11.4" jmh = "1.37" From 9a9c283e1f943afd389ba283d7ee4d5e70f55652 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 16 Jan 2025 11:36:03 +0100 Subject: [PATCH 1314/1594] [CI] Upload crash logs for failed Java builds. --- .github/workflows/ci.yml | 39 ++++++++++++++++++++++++++++++++++---- .github/workflows/slow.yml | 14 +++++++++++++- build.gradle | 22 +++++++++++++++++++++ 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81f79e5420..a2b568bb73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '17', '21' ] + java: [ '17', '21', '23' ] os: [ 'ubuntu-24.04', 'windows-latest', 'macos-latest' ] steps: - name: Checkout code @@ -52,18 +52,49 @@ jobs: with: distribution: 'zulu' java-version: ${{ matrix.java }} - - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION (Unix) + if: runner.os != 'Windows' run: | java -Xinternalversion echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - - name: Setup java 17 to run the Gradle script + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION (Windows) + if: runner.os == 'Windows' + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=$env:JAVA_HOME" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + echo "BUILD_JAVA_VERSION=${{ matrix.java }}" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + - name: Setup java uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 17 - name: Build with Gradle - run: ./gradlew --stacktrace + run: ./gradlew + - name: Copy test logs (Unix) + id: copy_test_logs + if: failure() && runner.os != 'Windows' + run: | + echo "file=build/distributions/test_logs.tbz2" >> $GITHUB_OUTPUT + ./gradlew tarTestLogs + - name: Upload crash logs (Unix) + if: always() && steps.copy_test_logs.outputs.file == 'build/distributions/test_logs.tbz2' + uses: actions/upload-artifact@v4 + with: + name: crash-logs-${{ matrix.os }}-java-${{ matrix.java }} + path: ${{ steps.copy_test_logs.outputs.file }} + - name: Copy test logs (Windows) + id: copy_test_logs_windows + if: runner.os == 'Windows' && failure() + run: | + echo "file=build/distributions/test_logs.tbz2" | Out-File $env:GITHUB_OUTPUT -Encoding utf8 -Append + ./gradlew tarTestLogs + - name: Upload crash logs (Windows) + if: runner.os == 'Windows' && always() && steps.copy_test_logs_windows.outputs.file == 'build/distributions/test_logs.tbz2' + uses: actions/upload-artifact@v4 + with: + name: crash-logs-${{ matrix.os }}-java-${{ matrix.java }} + path: ${{ steps.copy_test_logs_windows.outputs.file }} csharp-build: name: C# ${{ matrix.dotnet }} diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index a6700d95b2..915a097ec2 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -55,9 +55,21 @@ jobs: run: ./csharp/build.sh - name: Run property tests run: ./gradlew propertyTest + - name: Copy test logs (Unix) + id: copy_test_logs + if: failure() + run: | + echo "file=build/distributions/test_logs.tbz2" >> $GITHUB_OUTPUT + ./gradlew tarTestLogs + - name: Upload crash logs (Unix) + if: always() && steps.copy_test_logs.outputs.file == 'build/distributions/test_logs.tbz2' + uses: actions/upload-artifact@v4 + with: + name: crash-logs-${{ matrix.os }}-property-tests + path: ${{ steps.copy_test_logs.outputs.file }} - name: Upload test results uses: actions/upload-artifact@v4 - if: success() || failure() + if: always() with: name: property-tests path: sbe-tool/build/reports/tests/propertyTest diff --git a/build.gradle b/build.gradle index ec29dfe5a4..03db46371c 100644 --- a/build.gradle +++ b/build.gradle @@ -1079,6 +1079,28 @@ tasks.named('build').configure { dependsOn 'verifyJavaIrCodecsInSync' } +tasks.register('copyTestLogs', Copy) { + from '.' + include '**/build/test-output/**' + include '**/*.hprof' + include '**/*.log' + include '**/*.tlog' + include '**/build/reports/tests/**' + include '**/build/test-results/**/*' + include 'LICENSE' + exclude 'build' + into 'build/test_logs' + + includeEmptyDirs = false +} + +tasks.register('tarTestLogs', Tar) { + dependsOn tasks.named('copyTestLogs') + archiveBaseName.set('test_logs') + from 'build/test_logs' + compression Compression.BZIP2 +} + def isNonStable = { String version -> def stableKeyword = ['RELEASE', 'FINAL', 'GA'].any { it -> version.toUpperCase().contains(it) } def regex = /^[0-9,.v-]+(-r)?$/ From fd46e73d76819c2e0d2727edfc9f9ccfeed26f59 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 16 Jan 2025 11:44:29 +0100 Subject: [PATCH 1315/1594] [CI] Simplify error log upload. --- .github/workflows/ci.yml | 20 ++++---------------- .github/workflows/slow.yml | 8 ++++---- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2b568bb73..83e080689c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,30 +71,18 @@ jobs: java-version: 17 - name: Build with Gradle run: ./gradlew - - name: Copy test logs (Unix) + - name: Copy test logs id: copy_test_logs - if: failure() && runner.os != 'Windows' + if: failure() run: | - echo "file=build/distributions/test_logs.tbz2" >> $GITHUB_OUTPUT + ${{ runner.os == 'Windows' && 'echo "file=build/distributions/test_logs.tbz2" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append' || 'echo "file=build/distributions/test_logs.tbz2" >> $GITHUB_OUTPUT' }} ./gradlew tarTestLogs - - name: Upload crash logs (Unix) + - name: Upload crash logs if: always() && steps.copy_test_logs.outputs.file == 'build/distributions/test_logs.tbz2' uses: actions/upload-artifact@v4 with: name: crash-logs-${{ matrix.os }}-java-${{ matrix.java }} path: ${{ steps.copy_test_logs.outputs.file }} - - name: Copy test logs (Windows) - id: copy_test_logs_windows - if: runner.os == 'Windows' && failure() - run: | - echo "file=build/distributions/test_logs.tbz2" | Out-File $env:GITHUB_OUTPUT -Encoding utf8 -Append - ./gradlew tarTestLogs - - name: Upload crash logs (Windows) - if: runner.os == 'Windows' && always() && steps.copy_test_logs_windows.outputs.file == 'build/distributions/test_logs.tbz2' - uses: actions/upload-artifact@v4 - with: - name: crash-logs-${{ matrix.os }}-java-${{ matrix.java }} - path: ${{ steps.copy_test_logs_windows.outputs.file }} csharp-build: name: C# ${{ matrix.dotnet }} diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 915a097ec2..424e7f3bc8 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -55,17 +55,17 @@ jobs: run: ./csharp/build.sh - name: Run property tests run: ./gradlew propertyTest - - name: Copy test logs (Unix) + - name: Copy test logs id: copy_test_logs if: failure() run: | - echo "file=build/distributions/test_logs.tbz2" >> $GITHUB_OUTPUT + ${{ runner.os == 'Windows' && 'echo "file=build/distributions/test_logs.tbz2" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append' || 'echo "file=build/distributions/test_logs.tbz2" >> $GITHUB_OUTPUT' }} ./gradlew tarTestLogs - - name: Upload crash logs (Unix) + - name: Upload crash logs if: always() && steps.copy_test_logs.outputs.file == 'build/distributions/test_logs.tbz2' uses: actions/upload-artifact@v4 with: - name: crash-logs-${{ matrix.os }}-property-tests + name: crash-logs-${{ matrix.os }}-property-tests-java-${{matrix.java}}-dotnet-${{matrix.dotnet}} path: ${{ steps.copy_test_logs.outputs.file }} - name: Upload test results uses: actions/upload-artifact@v4 From f54c139ba64277302275f1a7b2ec48f22ee8df01 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 16 Jan 2025 21:01:04 +0100 Subject: [PATCH 1316/1594] [CI] Use env to setup base Java. --- .github/workflows/ci.yml | 39 ++++++++++++++++++----------------- .github/workflows/release.yml | 3 ++- .github/workflows/slow.yml | 5 +++-- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83e080689c..695135fe35 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,7 @@ concurrency: env: GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail' + JAVA_VERSION: '17' permissions: contents: read @@ -68,7 +69,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 + java-version: ${{ env.JAVA_VERSION }} - name: Build with Gradle run: ./gradlew - name: Copy test logs @@ -111,11 +112,11 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - - name: Setup java 17 to run the Gradle script + - name: Setup java to run Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 + java-version: ${{ env.JAVA_VERSION }} - name: Cache NuGet dependencies uses: actions/cache@v4 with: @@ -165,11 +166,11 @@ jobs: run: | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ bionic main universe" sudo apt-get install -y g++-${{ matrix.version }} libsparsehash-dev libidn11 - - name: Setup java 17 to run the Gradle script + - name: Setup java to run Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 + java-version: ${{ env.JAVA_VERSION }} - name: Build run: ./cppbuild/cppbuild @@ -205,11 +206,11 @@ jobs: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install -y g++-${{ matrix.version }} - - name: Setup java 17 to run the Gradle script + - name: Setup java to run Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 + java-version: ${{ env.JAVA_VERSION }} - name: Build run: ./cppbuild/cppbuild @@ -247,11 +248,11 @@ jobs: echo "deb [signed-by=/etc/apt/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/focal/ llvm-toolchain-focal-${{ matrix.version }} main" | sudo tee /etc/apt/sources.list.d/llvm.list sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev libidn11 - - name: Setup java 17 to run the Gradle script + - name: Setup java to run Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 + java-version: ${{ env.JAVA_VERSION }} - name: Build run: ./cppbuild/cppbuild @@ -289,11 +290,11 @@ jobs: echo "deb [signed-by=/etc/apt/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${{ matrix.version }} main" | sudo tee /etc/apt/sources.list.d/llvm.list sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} - - name: Setup java 17 to run the Gradle script + - name: Setup java to run Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 + java-version: ${{ env.JAVA_VERSION }} - name: Build run: ./cppbuild/cppbuild @@ -324,11 +325,11 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - - name: Setup java 17 to run the Gradle script + - name: Setup java to run Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 + java-version: ${{ env.JAVA_VERSION }} - name: Build run: cmake --version && ./cppbuild/cppbuild @@ -359,11 +360,11 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - - name: Setup java 17 to run the Gradle script + - name: Setup java to run Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 + java-version: ${{ env.JAVA_VERSION }} - name: Build run: cppbuild/cppbuild.cmd @@ -395,11 +396,11 @@ jobs: uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ matrix.rust }} - - name: Setup java 17 to run the Gradle script + - name: Setup java to run Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 + java-version: ${{ env.JAVA_VERSION }} - run: ./gradlew runRustTests golang-build: @@ -430,11 +431,11 @@ jobs: uses: actions/setup-go@v4 with: go-version: ${{ matrix.version }} - - name: Setup java 17 to run the Gradle script + - name: Setup java to run Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 + java-version: ${{ env.JAVA_VERSION }} - name: Generate jar run: ./gradlew assemble - name: Run tests diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7d7f62b227..db5f85bba4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,6 +12,7 @@ concurrency: env: GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail' + JAVA_VERSION: '17' jobs: ci: @@ -47,7 +48,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 + java-version: ${{ env.JAVA_VERSION }} - name: Publish with Gradle run: ./gradlew publish env: diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 424e7f3bc8..c4bfc7aac8 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -14,6 +14,7 @@ concurrency: env: GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail' + JAVA_VERSION: '17' permissions: contents: read @@ -42,11 +43,11 @@ jobs: java -Xinternalversion echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - - name: Setup java 17 to run the Gradle script + - name: Setup java to run Gradle script uses: actions/setup-java@v3 with: distribution: 'zulu' - java-version: 17 + java-version: ${{ env.JAVA_VERSION }} - name: Setup dotnet uses: actions/setup-dotnet@v2 with: From 16f5f874457bcfcf0865394ac3dde0f624181d46 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 16 Jan 2025 22:13:25 +0100 Subject: [PATCH 1317/1594] [CI] Trigger slow build on PR. --- .github/workflows/ci.yml | 1 + .github/workflows/slow.yml | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 695135fe35..e6bcd429c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,7 @@ on: types: [opened, synchronize] branches: - master + - 'release/**' concurrency: group: ci-${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index c4bfc7aac8..69e4d9bbe0 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -7,6 +7,11 @@ on: - '**' schedule: - cron: '0 12 * * *' + pull_request: + types: [opened, synchronize] + branches: + - master + - 'release/**' concurrency: group: slow-${{ github.workflow }}-${{ github.ref }} From 1b4fd32e9e474bb6e0cb067fda4242c7df72503a Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 17 Jan 2025 15:37:08 +0100 Subject: [PATCH 1318/1594] [CI] Trigger slow build on push to master or release branch. --- .github/workflows/ci.yml | 1 + .github/workflows/slow.yml | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6bcd429c7..1b3540bce4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,7 @@ on: push: branches: - master + - 'release/**' pull_request: types: [opened, synchronize] branches: diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 69e4d9bbe0..6f2a234ce0 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -7,6 +7,10 @@ on: - '**' schedule: - cron: '0 12 * * *' + push: + branches: + - master + - 'release/**' pull_request: types: [opened, synchronize] branches: From ad705a9a5159e2e8e8a3b0667e91f5edc3074abf Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 17 Jan 2025 15:45:32 +0100 Subject: [PATCH 1319/1594] [CI] Do not automatically trigger build when workflow file changes. --- .github/workflows/ci.yml | 2 ++ .github/workflows/slow.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b3540bce4..866dc53e10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,8 @@ on: branches: - master - 'release/**' + paths-ignore: + - '.github/workflows/**' pull_request: types: [opened, synchronize] branches: diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 6f2a234ce0..71ce367082 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -11,6 +11,8 @@ on: branches: - master - 'release/**' + paths-ignore: + - '.github/workflows/**' pull_request: types: [opened, synchronize] branches: From 88b5e8c27f58de36c47051b87e9873d0b31ca014 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 17 Jan 2025 15:47:59 +0100 Subject: [PATCH 1320/1594] Revert "[CI] Do not automatically trigger build when workflow file changes." This reverts commit ad705a9a5159e2e8e8a3b0667e91f5edc3074abf. --- .github/workflows/ci.yml | 2 -- .github/workflows/slow.yml | 2 -- 2 files changed, 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 866dc53e10..1b3540bce4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,8 +7,6 @@ on: branches: - master - 'release/**' - paths-ignore: - - '.github/workflows/**' pull_request: types: [opened, synchronize] branches: diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 71ce367082..6f2a234ce0 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -11,8 +11,6 @@ on: branches: - master - 'release/**' - paths-ignore: - - '.github/workflows/**' pull_request: types: [opened, synchronize] branches: From 0db78b363ada40dec160c7a5d26c92c0f1745b7a Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 21 Jan 2025 13:49:27 +0100 Subject: [PATCH 1321/1594] [Java] Tidy up dependency declarations. --- build.gradle | 10 +++++----- gradle/libs.versions.toml | 31 +++++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/build.gradle b/build.gradle index 03db46371c..988f025c19 100644 --- a/build.gradle +++ b/build.gradle @@ -150,10 +150,10 @@ allprojects { resolutionStrategy { failOnVersionConflict() // patching conflicting Checkstyle dependencies - force "org.codehaus.plexus:plexus-utils:3.3.0", - "org.apache.commons:commons-lang3:3.8.1", - "org.apache.httpcomponents:httpcore:4.4.14", - "commons-codec:commons-codec:1.15" + force libs.commons.codec, + libs.commons.lang3, + libs.httpcore, + libs.plexus.utils } } @@ -284,7 +284,7 @@ project(':sbe-tool') { implementation files("${layout.buildDirectory.get()}/classes/java/generated") implementation libs.hamcrest implementation libs.mockito - implementation platform("org.junit:junit-bom:${libs.versions.junit.get()}") + implementation platform(libs.junit.bom) implementation "org.junit.jupiter:junit-jupiter-params" } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 63dfb168d4..a548837ccd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,19 +1,34 @@ [versions] agrona = "2.0.1" checkstyle = "10.21.1" -junit = "5.11.4" -jmh = "1.37" +commons-codec = "1.15" +commons-lang3 = "3.8.1" gradle = "8.11.1" +hamcrest = "3.0" +httpcore = "4.4.14" +jqwik = "1.9.2" +jmh = "1.37" +json = "20250107" +junit = "5.11.4" +mockito = "5.15.2" +plexus = "3.3.0" +shadow = "8.3.5" +versions = "0.51.0" [libraries] agrona = { group = "org.agrona", name = "agrona", version.ref = "agrona" } -mockito = { group = "org.mockito", name = "mockito-core", version = "5.15.2" } -hamcrest = { group = "org.hamcrest", name = "hamcrest", version = "3.0" } -jqwik = { group = "net.jqwik", name = "jqwik", version = "1.9.2" } -json = { group = "org.json", name = "json", version = "20250107" } +commons-codec = { group = "commons-codec", name = "commons-codec", version.ref = "commons-codec" } +commons-lang3 = { group = "org.apache.commons", name = "commons-lang3", version.ref = "commons-lang3" } +hamcrest = { group = "org.hamcrest", name = "hamcrest", version.ref = "hamcrest" } +httpcore = { group = "org.apache.httpcomponents", name = "httpcore", version.ref = "httpcore" } +jqwik = { group = "net.jqwik", name = "jqwik", version.ref = "jqwik" } +json = { group = "org.json", name = "json", version.ref = "json" } jmh-core = { group = "org.openjdk.jmh", name = "jmh-core", version.ref = "jmh" } jmh-generator-annprocess = { group = "org.openjdk.jmh", name = "jmh-generator-annprocess", version.ref = "jmh" } +junit-bom = { group = "org.junit", name = "junit-bom", version.ref = "junit" } +mockito = { group = "org.mockito", name = "mockito-core", version.ref = "mockito" } +plexus-utils = { group = "org.codehaus.plexus", name = "plexus-utils", version.ref = "plexus" } [plugins] -versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } -shadow = { id = "com.gradleup.shadow", version = "8.3.5" } +shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } +versions = { id = "com.github.ben-manes.versions", version.ref = "versions" } From 1a3957ca67d0df9a84bbbfba638a3193f5f8870a Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 30 Jan 2025 19:29:09 +0100 Subject: [PATCH 1322/1594] Switch project URL to `aeron-io` organization. --- CONTRIBUTING.md | 2 +- README.md | 28 ++++++++++++++-------------- build.gradle | 8 ++++---- csharp/README.md | 12 ++++++------ csharp/sbe-dll/README.txt | 8 ++++---- csharp/sbe-dll/sbe-dll.csproj | 6 +++--- gocode/README.md | 6 +++--- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bac5877c8e..198011b6f8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ When submitting code, please make every effort to follow existing conventions an By contributing your code, you agree to license your contribution under the terms of the APLv2: -https://github.com/real-logic/simple-binary-encoding/blob/master/LICENSE +https://github.com/aeron-io/simple-binary-encoding/blob/master/LICENSE All files are made available under the Apache 2.0 license. diff --git a/README.md b/README.md index c051584e3b..ce55a80bb2 100644 --- a/README.md +++ b/README.md @@ -2,25 +2,25 @@ Simple Binary Encoding (SBE) ============================ [![Javadocs](https://www.javadoc.io/badge/uk.co.real-logic/sbe-tool.svg)](https://www.javadoc.io/doc/uk.co.real-logic/sbe-tool) -[![GitHub](https://img.shields.io/github/license/real-logic/simple-binary-encoding.svg)](https://github.com/real-logic/simple-binary-encoding/blob/master/LICENSE) +[![GitHub](https://img.shields.io/github/license/aeron-io/simple-binary-encoding.svg)](https://github.com/aeron-io/simple-binary-encoding/blob/master/LICENSE) -[![Actions Status](https://github.com/real-logic/simple-binary-encoding/workflows/Continuous%20Integration/badge.svg)](https://github.com/real-logic/simple-binary-encoding/actions) -[![CodeQL Status](https://github.com/real-logic/simple-binary-encoding/workflows/CodeQL/badge.svg)](https://github.com/real-logic/simple-binary-encoding/actions) +[![Actions Status](https://github.com/aeron-io/simple-binary-encoding/workflows/Continuous%20Integration/badge.svg)](https://github.com/aeron-io/simple-binary-encoding/actions) +[![CodeQL Status](https://github.com/aeron-io/simple-binary-encoding/workflows/CodeQL/badge.svg)](https://github.com/aeron-io/simple-binary-encoding/actions) [SBE](https://github.com/FIXTradingCommunity/fix-simple-binary-encoding) is an OSI layer 6 presentation for encoding and decoding binary application messages for low-latency financial applications. This repository contains the reference implementations in Java, C++, Golang, C#, and Rust. -More details on the design and usage of SBE can be found on the [Wiki](https://github.com/real-logic/simple-binary-encoding/wiki). +More details on the design and usage of SBE can be found on the [Wiki](https://github.com/aeron-io/simple-binary-encoding/wiki). An XSD for SBE specs can be found -[here](https://github.com/real-logic/simple-binary-encoding/blob/master/sbe-tool/src/main/resources/fpl/sbe.xsd). Please address questions about the specification to the [SBE FIX community](https://github.com/FIXTradingCommunity/fix-simple-binary-encoding). +[here](https://github.com/aeron-io/simple-binary-encoding/blob/master/sbe-tool/src/main/resources/fpl/sbe.xsd). Please address questions about the specification to the [SBE FIX community](https://github.com/FIXTradingCommunity/fix-simple-binary-encoding). -For the latest version information and changes see the [Change Log](https://github.com/real-logic/simple-binary-encoding/wiki/Change-Log) with **downloads** at [Maven Central](http://search.maven.org/#search%7Cga%7C1%7Csbe). +For the latest version information and changes see the [Change Log](https://github.com/aeron-io/simple-binary-encoding/wiki/Change-Log) with **downloads** at [Maven Central](http://search.maven.org/#search%7Cga%7C1%7Csbe). -The Java and C++ SBE implementations work very efficiently with the [Aeron](https://github.com/real-logic/aeron) +The Java and C++ SBE implementations work very efficiently with the [Aeron](https://github.com/aeron-io/aeron) messaging system for low-latency and high-throughput communications. The Java SBE implementation has a dependency on -[Agrona](https://github.com/real-logic/agrona) for its buffer implementations. Commercial support is available from +[Agrona](https://github.com/aeron-io/agrona) for its buffer implementations. Commercial support is available from [sales@real-logic.co.uk](mailto:sales@real-logic.co.uk?subject=SBE). Binaries @@ -41,7 +41,7 @@ Example for Maven: Build ----- -Build the project with [Gradle](http://gradle.org/) using this [build.gradle](https://github.com/real-logic/simple-binary-encoding/blob/master/build.gradle) file. +Build the project with [Gradle](http://gradle.org/) using this [build.gradle](https://github.com/aeron-io/simple-binary-encoding/blob/master/build.gradle) file. Full clean build: @@ -67,7 +67,7 @@ An example to execute a Jar from command line using the 'all' jar which includes C++ Build using CMake --------------------- NOTE: Linux, Mac OS, and Windows only for the moment. See -[FAQ](https://github.com/real-logic/simple-binary-encoding/wiki/Frequently-Asked-Questions). +[FAQ](https://github.com/aeron-io/simple-binary-encoding/wiki/Frequently-Asked-Questions). Windows builds have been tested with Visual Studio Express 12. For convenience, the `cppbuild` script does a full clean, build, and test of all targets as a Release build. @@ -100,16 +100,16 @@ For convenience on Linux, a gnu Makefile is provided that runs some tests and co Go supports both generating Go structs with encode / decode methods, and flyweights like the other languages. Structs are generated by default for compatibility. Set `sbe.go.generate.generate.flyweights=true` to generate flyweights. Users of golang generated code should see the [user -documentation](https://github.com/real-logic/simple-binary-encoding/wiki/Golang-User-Guide). +documentation](https://github.com/aeron-io/simple-binary-encoding/wiki/Golang-User-Guide). Developers wishing to enhance the golang generator should see the [developer -documentation](https://github.com/real-logic/simple-binary-encoding/blob/master/gocode/README.md) +documentation](https://github.com/aeron-io/simple-binary-encoding/blob/master/gocode/README.md) C# Build -------- -Users of CSharp generated code should see the [user documentation](https://github.com/real-logic/simple-binary-encoding/wiki/Csharp-User-Guide). +Users of CSharp generated code should see the [user documentation](https://github.com/aeron-io/simple-binary-encoding/wiki/Csharp-User-Guide). -Developers wishing to enhance the CSharp generator should see the [developer documentation](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/README.md) +Developers wishing to enhance the CSharp generator should see the [developer documentation](https://github.com/aeron-io/simple-binary-encoding/blob/master/csharp/README.md) Rust Build ------------ diff --git a/build.gradle b/build.gradle index 988f025c19..d9450544ce 100644 --- a/build.gradle +++ b/build.gradle @@ -79,12 +79,12 @@ def projectPom = { name = 'sbe' description = 'FIX/SBE - OSI layer 6 presentation for encoding and decoding application messages' + ' in binary format for low-latency applications.' - url = 'https://github.com/real-logic/simple-binary-encoding' + url = 'https://github.com/aeron-io/simple-binary-encoding' scm { - connection = 'scm:git:github.com/real-logic/simple-binary-encoding.git' - developerConnection = 'scm:git:github.com/real-logic/simple-binary-encoding.git' - url = 'github.com/real-logic/simple-binary-encoding.git' + connection = 'scm:git:github.com/aeron-io/simple-binary-encoding.git' + developerConnection = 'scm:git:github.com/aeron-io/simple-binary-encoding.git' + url = 'github.com/aeron-io/simple-binary-encoding.git' } licenses { diff --git a/csharp/README.md b/csharp/README.md index 686522e03d..95042ca03a 100644 --- a/csharp/README.md +++ b/csharp/README.md @@ -1,7 +1,7 @@ Overview ======== -There is a [user guide](https://github.com/real-logic/simple-binary-encoding/wiki/Csharp-User-Guide) for people who wish +There is a [user guide](https://github.com/aeron-io/simple-binary-encoding/wiki/Csharp-User-Guide) for people who wish to use the C# generator. This document is to assist developers working on the the SBE C# generator itself. @@ -42,13 +42,13 @@ Code Layout ----------- The Java code that performs the generation of C# code is -[here](https://github.com/real-logic/simple-binary-encoding/tree/master/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp). +[here](https://github.com/aeron-io/simple-binary-encoding/tree/master/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp). $ ./gradlew # Will build sbe-tool jar $ ./gradlew generateCSharpCodecs # will generate the test, benchmark, and example C# code The [Visual Studio 2017 Community -solution](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/csharp.sln) provides the projects: +solution](https://github.com/aeron-io/simple-binary-encoding/blob/master/csharp/csharp.sln) provides the projects: * sbe-dll (for common marshalling and DirectBuffer functionality) * sbe-generated (containing C# code generated by sbe-tool) @@ -87,6 +87,6 @@ For now you can: * build the SBE csharp generator using `gradlew` * generate the csharp codecs using `gradlew GenerateCSharpCodecs` - * Use the bash script [build.sh](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/build.sh) to run the tests - * Use the bash script [runtests.sh](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/runtests.sh) to run the tests - * Use the bash script [pack.sh](https://github.com/real-logic/simple-binary-encoding/blob/master/csharp/pack.sh) to create the nuget package + * Use the bash script [build.sh](https://github.com/aeron-io/simple-binary-encoding/blob/master/csharp/build.sh) to run the tests + * Use the bash script [runtests.sh](https://github.com/aeron-io/simple-binary-encoding/blob/master/csharp/runtests.sh) to run the tests + * Use the bash script [pack.sh](https://github.com/aeron-io/simple-binary-encoding/blob/master/csharp/pack.sh) to create the nuget package diff --git a/csharp/sbe-dll/README.txt b/csharp/sbe-dll/README.txt index 7a1cdf0ced..3c92d4d84d 100644 --- a/csharp/sbe-dll/README.txt +++ b/csharp/sbe-dll/README.txt @@ -58,9 +58,9 @@ Next steps This was just a quick sample but hopefully now you have an idea of the overall process you have to go through to use SBE. -To get all the details please refer to our wiki (https://github.com/real-logic/simple-binary-encoding/wiki/) and especially the following sections: - - schema definition: https://github.com/real-logic/simple-binary-encoding/wiki/FIX-SBE-XML-Primer - - SBE Tool command line: https://github.com/real-logic/simple-binary-encoding/wiki/Sbe-Tool-Guide +To get all the details please refer to our wiki (https://github.com/aeron-io/simple-binary-encoding/wiki/) and especially the following sections: + - schema definition: https://github.com/aeron-io/simple-binary-encoding/wiki/FIX-SBE-XML-Primer + - SBE Tool command line: https://github.com/aeron-io/simple-binary-encoding/wiki/Sbe-Tool-Guide -If you face an issue, a suggestion or a question, please use the issue tracker on the main GitHub repo: https://github.com/real-logic/simple-binary-encoding/issues?state=open +If you face an issue, a suggestion or a question, please use the issue tracker on the main GitHub repo: https://github.com/aeron-io/simple-binary-encoding/issues?state=open diff --git a/csharp/sbe-dll/sbe-dll.csproj b/csharp/sbe-dll/sbe-dll.csproj index 747306310d..6db6d56021 100644 --- a/csharp/sbe-dll/sbe-dll.csproj +++ b/csharp/sbe-dll/sbe-dll.csproj @@ -9,13 +9,13 @@ true Bill Segall, MarketFactory Inc, Adaptive Consulting Apache-2.0 - https://github.com/real-logic/simple-binary-encoding - https://github.com/real-logic/simple-binary-encoding + https://github.com/aeron-io/simple-binary-encoding + https://github.com/aeron-io/simple-binary-encoding SBE;Marshaling;Low;Latency;Simple;Binary;Encoding sbe-tool 1.23.1.1 Simple Binary Encoding for .NET - This package contains all you need to define SBE messages and generate C# encoders and decoders. See https://github.com/real-logic/simple-binary-encoding for more detailed instructions + This package contains all you need to define SBE messages and generate C# encoders and decoders. See https://github.com/aeron-io/simple-binary-encoding for more detailed instructions git diff --git a/gocode/README.md b/gocode/README.md index 5740d9dbca..bbfcf1b6cc 100755 --- a/gocode/README.md +++ b/gocode/README.md @@ -2,7 +2,7 @@ Overview ======== There is now a -[user guide](https://github.com/real-logic/simple-binary-encoding/wiki/Golang-User-Guide) +[user guide](https://github.com/aeron-io/simple-binary-encoding/wiki/Golang-User-Guide) and this document is for development of the SBE golang generator. Go supports both generating Go structs with encode / decode methods, and flyweights like the other languages. @@ -11,10 +11,10 @@ Structs are generated by default for compatibility. Set `sbe.go.generate.generat Code Layout ----------- The Java code that performs the generation of golang code is -[here](https://github.com/real-logic/simple-binary-encoding/tree/master/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang). There is both a struct and a flyweight generator. +[here](https://github.com/aeron-io/simple-binary-encoding/tree/master/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang). There is both a struct and a flyweight generator. Golang code used for testing resides in the top-level -[gocode directory](https://github.com/real-logic/simple-binary-encoding/tree/master/gocode). +[gocode directory](https://github.com/aeron-io/simple-binary-encoding/tree/master/gocode). Building and testing -------------------- From b95c1fe69949be609ab871b3d3cf192a624494bf Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 30 Jan 2025 19:43:10 +0100 Subject: [PATCH 1323/1594] [Java] Upgrade to Checkstyle 10.21.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a548837ccd..61b6d52032 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.0.1" -checkstyle = "10.21.1" +checkstyle = "10.21.2" commons-codec = "1.15" commons-lang3 = "3.8.1" gradle = "8.11.1" From 3255cbfad7c708fdd4a13be969421f851904b36b Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 30 Jan 2025 19:43:36 +0100 Subject: [PATCH 1324/1594] [Java] Upgrade to Versions 0.52.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 61b6d52032..72a0148438 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ junit = "5.11.4" mockito = "5.15.2" plexus = "3.3.0" shadow = "8.3.5" -versions = "0.51.0" +versions = "0.52.0" [libraries] agrona = { group = "org.agrona", name = "agrona", version.ref = "agrona" } From 84b8d4a0f90bff84a3433070e48203a7237ceca4 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 30 Jan 2025 19:46:24 +0100 Subject: [PATCH 1325/1594] [Java] Upgrade to Gradle 8.12.1. --- build.gradle | 8 ++++---- gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 3 +-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index d9450544ce..018a53edc1 100644 --- a/build.gradle +++ b/build.gradle @@ -199,7 +199,7 @@ subprojects { } javadoc { - failOnError false + failOnError = false title = '

      Simple Binary Encoding (SBE)

      ' options.bottom = 'Copyright © 2013-2025 Real Logic Limited. All Rights Reserved.' options.encoding = 'UTF-8' @@ -389,7 +389,7 @@ project(':sbe-tool') { repositories { maven { - url(!isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl) + url = !isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl credentials { username = ossrhUsername password = ossrhPassword @@ -459,7 +459,7 @@ project(':sbe-all') { } repositories { maven { - url(!isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl) + url = !isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl credentials { username = ossrhUsername password = ossrhPassword @@ -579,7 +579,7 @@ project(':sbe-samples') { repositories { maven { - url(!isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl) + url = !isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl credentials { username = ossrhUsername password = ossrhPassword diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 72a0148438..73d4e073d7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ agrona = "2.0.1" checkstyle = "10.21.2" commons-codec = "1.15" commons-lang3 = "3.8.1" -gradle = "8.11.1" +gradle = "8.12.1" hamcrest = "3.0" httpcore = "4.4.14" jqwik = "1.9.2" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c1d5e01859..d9fbee2e1d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f5feea6d6b..f3b75f3b0d 100755 --- a/gradlew +++ b/gradlew @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum From 2fff016a5abe2943fbeebe8cb81d2a9b34087f17 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 31 Jan 2025 10:54:28 +0100 Subject: [PATCH 1326/1594] Gradle warning fixes. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 018a53edc1..403c1f8f79 100644 --- a/build.gradle +++ b/build.gradle @@ -1098,7 +1098,7 @@ tasks.register('tarTestLogs', Tar) { dependsOn tasks.named('copyTestLogs') archiveBaseName.set('test_logs') from 'build/test_logs' - compression Compression.BZIP2 + compression = Compression.BZIP2 } def isNonStable = { String version -> From 1942f3d768a963deb71dd1aae2844c41611b00f2 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 31 Jan 2025 11:38:19 +0100 Subject: [PATCH 1327/1594] Update `Implementation-Vendor`. --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 403c1f8f79..3093d9a74e 100644 --- a/build.gradle +++ b/build.gradle @@ -361,7 +361,7 @@ project(':sbe-tool') { 'Specification-Version': '1.0', 'Implementation-Title': 'SBE', 'Implementation-Version': sbeVersion, - 'Implementation-Vendor': 'Real Logic Limited', + 'Implementation-Vendor': 'Adaptive Financial Consulting', 'Automatic-Module-Name': 'uk.co.real_logic.sbe.tool' ) } @@ -423,7 +423,7 @@ project(':sbe-all') { 'Specification-Version': '1.0', 'Implementation-Title': 'SBE', 'Implementation-Version': sbeVersion, - 'Implementation-Vendor': 'Real Logic Limited', + 'Implementation-Vendor': 'Adaptive Financial Consulting', 'Automatic-Module-Name': 'uk.co.real_logic.sbe.all' ) } @@ -548,7 +548,7 @@ project(':sbe-samples') { 'Specification-Version': '1.0', 'Implementation-Title': 'SBE', 'Implementation-Version': sbeVersion, - 'Implementation-Vendor': 'Real Logic Limited', + 'Implementation-Vendor': 'Adaptive Financial Consulting', 'Automatic-Module-Name': 'uk.co.real_logic.sbe.samples' ) } From 0da03ae96cc87ae211883819098dbc976c340b5d Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 31 Jan 2025 11:48:26 +0100 Subject: [PATCH 1328/1594] Update `Implementation-Vendor`. --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 3093d9a74e..b0ac62184a 100644 --- a/build.gradle +++ b/build.gradle @@ -361,7 +361,7 @@ project(':sbe-tool') { 'Specification-Version': '1.0', 'Implementation-Title': 'SBE', 'Implementation-Version': sbeVersion, - 'Implementation-Vendor': 'Adaptive Financial Consulting', + 'Implementation-Vendor': 'Adaptive Financial Consulting Limited', 'Automatic-Module-Name': 'uk.co.real_logic.sbe.tool' ) } @@ -423,7 +423,7 @@ project(':sbe-all') { 'Specification-Version': '1.0', 'Implementation-Title': 'SBE', 'Implementation-Version': sbeVersion, - 'Implementation-Vendor': 'Adaptive Financial Consulting', + 'Implementation-Vendor': 'Adaptive Financial Consulting Limited', 'Automatic-Module-Name': 'uk.co.real_logic.sbe.all' ) } @@ -548,7 +548,7 @@ project(':sbe-samples') { 'Specification-Version': '1.0', 'Implementation-Title': 'SBE', 'Implementation-Version': sbeVersion, - 'Implementation-Vendor': 'Adaptive Financial Consulting', + 'Implementation-Vendor': 'Adaptive Financial Consulting Limited', 'Automatic-Module-Name': 'uk.co.real_logic.sbe.samples' ) } From 3a0fbac9d7022db050cac4e39d8049514a18836d Mon Sep 17 00:00:00 2001 From: Kelly Littlepage Date: Tue, 4 Feb 2025 07:52:49 -0500 Subject: [PATCH 1329/1594] fix: include field 'deprecated' in ir encoding and decoding --- sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java | 1 + sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index 98e1a9d409..63881c0ae7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -240,6 +240,7 @@ private Token decodeToken() .byteOrder(mapByteOrder(tokenDecoder.byteOrder())) .presence(mapPresence(tokenDecoder.presence())); + tokenBuilder.deprecated(tokenDecoder.deprecated()); tokenBuilder.name(tokenDecoder.name()); encBuilder.constValue(get(valBuffer, type, tokenDecoder.getConstValue(valArray, 0, valArray.length))); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java index c3bf073e5e..756f0829ab 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java @@ -192,7 +192,8 @@ private int encodeToken(final Token token) .signal(mapSignal(token.signal())) .primitiveType(mapPrimitiveType(type)) .byteOrder(mapByteOrder(encoding.byteOrder())) - .presence(mapPresence(encoding.presence())); + .presence(mapPresence(encoding.presence())) + .deprecated(token.deprecated()); try { From 127cda953179bc5a7817b3730b9abfe13a68ff78 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 5 Feb 2025 21:15:46 +0100 Subject: [PATCH 1330/1594] [Java] Upgrade to Shadow 8.3.6. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 73d4e073d7..c9f95d9791 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ json = "20250107" junit = "5.11.4" mockito = "5.15.2" plexus = "3.3.0" -shadow = "8.3.5" +shadow = "8.3.6" versions = "0.52.0" [libraries] From a4e4997b70c52617a12894ac541e7d7b6a727432 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 5 Feb 2025 21:43:24 +0100 Subject: [PATCH 1331/1594] [CI] Set build timeout to 60 minutes for normal tests and 3 hours for slow tests. --- .github/workflows/ci.yml | 10 ++++++++++ .github/workflows/slow.yml | 1 + 2 files changed, 11 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b3540bce4..5b5bd11367 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,7 @@ jobs: java-build: name: Java ${{ matrix.java }} (${{ matrix.os }}) runs-on: ${{ matrix.os }} + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -90,6 +91,7 @@ jobs: csharp-build: name: C# ${{ matrix.dotnet }} runs-on: ubuntu-24.04 + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -140,6 +142,7 @@ jobs: cpp-gcc-2004-build: name: C++ GCC ${{ matrix.version }} (Ubuntu 20.04) runs-on: ubuntu-20.04 + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -179,6 +182,7 @@ jobs: cpp-gcc-2404-build: name: C++ GCC ${{ matrix.version }} (Ubuntu 24.04) runs-on: ubuntu-24.04 + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -219,6 +223,7 @@ jobs: cpp-clang-2004-build: name: C++ Clang ${{ matrix.version }} (Ubuntu 20.04) runs-on: ubuntu-20.04 + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -261,6 +266,7 @@ jobs: cpp-clang-2404-build: name: C++ Clang ${{ matrix.version }} (Ubuntu 24.04) runs-on: ubuntu-24.04 + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -303,6 +309,7 @@ jobs: cpp-clang-macos-build: name: C++ Xcode ${{ matrix.version }} (macOS) runs-on: ${{ matrix.os }} + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -338,6 +345,7 @@ jobs: cpp-msvc-build: name: C++ MSVC (Windows) runs-on: ${{ matrix.os }} + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -373,6 +381,7 @@ jobs: rust-build: name: Rust ${{ matrix.rust }} runs-on: ubuntu-24.04 + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -408,6 +417,7 @@ jobs: golang-build: name: Golang ${{ matrix.version }} runs-on: ubuntu-24.04 + timeout-minutes: 60 strategy: fail-fast: false matrix: diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 6f2a234ce0..65510b72f5 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -32,6 +32,7 @@ jobs: property-tests: name: Property tests runs-on: ubuntu-24.04 + timeout-minutes: 180 strategy: matrix: java: [ '21' ] From ee0888f175d0c0b60e7755cf96552e0a1f0fc235 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 5 Feb 2025 21:46:00 +0100 Subject: [PATCH 1332/1594] [CI] Set slow build timeout to 2 hours. --- .github/workflows/slow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 65510b72f5..4b07b30367 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -32,7 +32,7 @@ jobs: property-tests: name: Property tests runs-on: ubuntu-24.04 - timeout-minutes: 180 + timeout-minutes: 120 strategy: matrix: java: [ '21' ] From 6079f116121c4a005ba086af2b9c5c91b2d6c756 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 26 Feb 2025 15:43:39 +0100 Subject: [PATCH 1333/1594] [Java] Upgrade to Checkstyle 10.21.3. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c9f95d9791..9b419e1f18 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.0.1" -checkstyle = "10.21.2" +checkstyle = "10.21.3" commons-codec = "1.15" commons-lang3 = "3.8.1" gradle = "8.12.1" From 4b216d3b7a7a47c436c56eddb2657eb01d794a7f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 26 Feb 2025 15:44:02 +0100 Subject: [PATCH 1334/1594] [Java] Upgrade to JUnit 5.12.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9b419e1f18..91fad866a4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ httpcore = "4.4.14" jqwik = "1.9.2" jmh = "1.37" json = "20250107" -junit = "5.11.4" +junit = "5.12.0" mockito = "5.15.2" plexus = "3.3.0" shadow = "8.3.6" From b1993a8c8e78035427a49bf71fdf129d957f935d Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 26 Feb 2025 15:44:35 +0100 Subject: [PATCH 1335/1594] [Java] Upgrade to Gradle 8.13. --- gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 43583 -> 43705 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 91fad866a4..71c8c1c4b2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ agrona = "2.0.1" checkstyle = "10.21.3" commons-codec = "1.15" commons-lang3 = "3.8.1" -gradle = "8.12.1" +gradle = "8.13" hamcrest = "3.0" httpcore = "4.4.14" jqwik = "1.9.2" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9530d66f5e68d973ea569d8e19de379189..9bbc975c742b298b441bfb90dbc124400a3751b9 100644 GIT binary patch delta 34744 zcmXuJV_+R@)3u$(Y~1X)v28cDZQE*`9qyPrXx!Mg8{4+s*nWFo&-eX5|IMs5>pW(< z=OJ4cAZzeZfy=9lI!r-0aXh8xKdlGq)X)o#ON+mC6t7t0WtgR!HN%?__cvdWdtQC< zrFQ;?l@%CxY55`8y(t7?1P_O7(6pv~(~l!kHB;z2evtUsGHzEDL+y4*no%g#AsI~i zJ%SFMv{j__Yaxnn2NtDK+!1XZX`CB}DGMIT{#8(iAk*`?VagyHx&|p8npkmz=-n!f z3D+^yIjP`D&Lfz500rpq#dJE`vM|-N7=`uN0z86BpiMcCOCS^;6CUG4o1I)W{q6Gv z1vZB6+|7An``GNoG7D!xJGJd_Qv(M-kdVdsIJ?CrXFEH^@Ts83}QX}1%P6KQFNz^-=) z<|qo#qmR!Nonr$p*Uu1Jo2c~KLTrvc*Yw%L+`IL}y|kd+t{NCrXaP=7C00CO?=pgp z!fyr#XFfFXO6z2TP5P1W{H_`$PKzUiGtJd!U52%yAJf}~tgXF`1#}@y`cZl9y{J-A zyUA&-X)+^N?W=2Fm_ce2w$C6>YWp7MgXa{7=kwwy9guBx26=MnPpuSt zB4}vo3{qxa+*{^oHxe7;JMNMp>F`iNv>0!MsFtnb+5eEZ$WI z0M9}rA&cgQ^Q8t_ojofiHaKuhvIB{B9I}3`Dsy3vW8ibigX}Kc912|UZ1uhH?RuHU=i&ePe2w%65)nBkHr7Bx5WwMZj%1B53sUEj0bxI( zEbS%WOUw)3-B0`-m0!{mk7Q%={B#7C^Si>C04@P|qm7$Oxn3ki)G_oNQBTh6CN6d_kt@UKx1Ezdo5)J0Gdf@TcW|{ zdz1V?a>zldA7_5*Pjn6kDj|sbUqt-7X z5+oajeC}*6oi~vxZ#Ac&85cYcC$5OKUnYPv$Y~>H@)mnTtALo*>>5&=0QMr5{5?S; zCDF=RI@94n(!~sa`4Y{JLxgcvRqMM&T!}rRd~Kl#_X4Z&85;})o4W*g>?TaAVXSWB zeY#!8qz^hmC6FERsjTnC)1Xu1UPd7_LfuNvuVqF8(}Jfar=T-K9iChEuZi-FH(P%u zzLrjpq|?}8?g1Vnw^&{eqw~QY0f*9c71&*<5#9f5JlhJmG~IuV*8~nEBLr`KrvOvs zkOLdlZ58K?u>1{vAU0CtT>Il<I{Q8#A!lO7#73V&iN13;oV?Hl?N5xDK63)Rp3%5reb&3n5OQ|9H zDpYEI%JQXcrs^o*SCFY~iYf-VM<`7Tl@+kQS3tfR-fyH_JDaz5SYEMU-bTCLQ=JVG ze?ZPcj95Tci|bVvSZk3^enqQ?pIcZn24V=YT{cf-L|P&{-%%^ql$)^Vu~)Ida=h$bZAMQEi$MM|&b zY8;D;aEba_`W^=VdKfttW)h_zjRA&0A^T*tF*%+}TZQCOvFqKUu=xf1Bx@T?&~S(J zopXniA?s%}Q4p9~F(Ty{8wt$l4oHeT(#U6sAu4>Q+~a;}I>0>??v*wfke}0TwPaeE zj3gWtfNlD{jRgy7;S9PS?su5pnobi%Zoe0LVpw%`<)V=yT~Ht_UUXIna4YUa;p=-T4df6^;bz%;@|$F zK;s9#K@9hqZCST!66N0uPB+FT*kq22%ovtJ%<9ArE%hcX^!(Lz;3?kCZ@Ak*MThjTOKU&t+uJdN*6t$;DDmh zFStdHO>r)8L@qO}K@H~7Z);#f6WU{@Icn7Tc^|IZ`;K^ek9eCWdync`kWCt2s%D-k zE$wyPCui$@gJJ9Q`CtixbMF(GiCCbm`ut(~ce-G|Ji|PZ3~DHlG`Asn;skVhnu0r_ zgGbdmfl|er`87x@uYmd8A+!-3V95GE4&_^9N@hp4SC4 zeFU+Z3Ou&G! zlvZy|iHIIX3X2-Yb7YJ#{SYE9lCoixO+}(|u+H@Z6Rz-l1eZ7{I;vk+Y7kP7ev>hG zv|(I<4?N{EXMSvRgUhbQhDoP1&A;SEUGGep8*!@4u)fNbl3%cts<&=m5<5pi7M-HQ zPS#svbXWu2n&m*K6jL#@xm3VSMJxnxve5J6w1qGv`2>5<6F!uzGVHP1A(_xI7CWlX zm6*wpT@dmQ&pAlm`r~T;)>m5HK^H^cM`pCSoh{;-CE43rMkg<;HnZaCHfMq1LoN0S z%%7|$y~&k6wpiY@rsdCY9ZDh%9W6Pf=2^p=;iv-Ah^ACxwK3VmI}SMNneTa9n%biL z#GoojRHxa}R2zOo!G@<8M-B6vNp?)@_>#mYku#pe{O~t?~}1 zE8`)=BstIRk5W*xZw@2=89@ds?eQ~mxzkrA`y<$oR8bmaUw=rE%lFmzHY&aY8?<-N zp1|bb$(XrOMmiYy{pH#)D1GOmv5aj_?waU~*h~s{VZ&H_PhoXYz`C8Pss{ymY_hPG zt{NY&nPMH#FRvwR+T0(Xo2#T6;=oFmRgA9b-HVY72d|~YF+6v$F%sY0 zS#^LF7sTj>Itvyi!~){Hit*~3imOG*Xh51qLz+!W~`vUBVeZZ5&k34SD%Ha%5#aclSzMfoGWjiq9#rl}j zOf*8NY>VN(`W!DxaBgjBzj3oUAVlLY{R}tiZZ0o>K$vwr?+eggZ!q74m2t?lkvm9z zAmL2=W$jQJL>SSrbIOibe734A(K^B8`M@uao!`E$p+9D!rBea8Oxb|p5r3o4##G8K zMr0I9y&`21{@m=Bi+4tTJ-xy(DB_mG$kYv+qw&VBM(A9^wP9;Yo*6{#5tMpfa;m2FC+%l@ zk_cKXg-d&YUIj3(x{)aNwYGYjSHiOQK2K#yWt$vQomhbnF;Qhkxl`+;i{&+t{PrY` zp5r28&|UvmUK|&Jlv>oX4>XE87Zns?fiE6c;VP7BixT*6n}Zsbv$wd{gXyrE&Sd zhRlv!-{%~xv6yNvx@3^@JEa$={&giRpqZG>`{93 zEjM}YI1i6JSx$DJa&NWcl0M;igxX;est*nz=W16zMfJ0#+s{>Eo>bxmCi)m*43hU1 z;FL43I}nWszjSS%*F1UYt^)4?D6&pDEt1(atK(DKY1pAkNMG`a>_ec;KiT z^xMBBZ9i=;!_hNGlYp^uR0FW^lcBrs_c3ZvhcctW4*T^-DD^OU{{hK8yHahyGyCK& zL0>f0XW|wvi4f`bNTfO+P*Ao^L@8~ezagtl%l z{(2uo71sT3rKTQ-L#Y5Rsy#x)Eo+HQranZmk;r_Hf7WWkRq&QmP{?}do0X=;3U_UYspffJl7v*Y&GnW;M7$C-5ZlL*MU|q*6`Lvx$g^ z6>MRgOZ>~=OyR3>WL0pgh2_ znG)RNd_;ufNwgQ9L6U@`!5=xjzpK_UfYftHOJ)|hrycrpgn-sCKdQ{BY&OEV3`roT|=4I#PT@q`6Lx=Lem2M&k4ghOSjXPH5<%cDd>`!rE} z5;hyRQ|6o>*}@SFEzb7b%5iY}9vOMRGpIQqt%%m)iSpQ@iSAU+A{CmB^&-04fQlV9 z14~oE=?j{b{xE*X^1H)eezKTE27;-=UfNvQZ0kZ+m76{6xqAyTrEB&Oe`Mx{4N;}5 zXp%ojp}JYx6PE}Z`IBO3qWsZEfVPa4EEz0vnsFNkQ!kG8tcec&)k$+s&XmPErROoNxeTh9fATBk)w1g|9*~&S!%r0u6+FTn}dK-qa7cfK~tkJlV zMi{BX!>lQsZhSQUWAf(M6+McPrv>)j<*T&hC!*?qq{@ABJWX z@!~2Y1rhy*Z|x`DZUBuyayz}Kv5Pzrh}1wiHT{9|fh`Wl%ao=lRSwEFl*wy6BZ%vo zrt9Ocbicd1q$a{F6`4#ZQ6vJa@`}IGz+xUr*=6TF^GR?`u{1to&gqJpwf$LN0?G&! zsLNiG+}M+c{*j-Q4I zO!=lj&~{29Os}hgEv`iJ1tU)dx}=ob>DHSHKX|FVu2Y#pO|SsigHRgg4?!FX2>b3W z`m}xI<#_02adGka0TuAIg89kS?>*lKyI)T)Pa)|12XfH;k9}#=dzH6TiciCNO->e9m>!W)l&4B zd74@>_LL9OuJ&v5e0)l7ME@xW)9K@*LUd1RY}Vs_${3YC%+LfSR^H+I=(7Szh2nKB z_8bMoty|M+k9A|hGURVePvMf0XY9NYOiC@h^MLs-X@(8PV4zI7A155!RnZrBE9R1> zuI4E`=JTxyJ#d`!(9_s?T2jxEM*E`){wGI`DBFIz%ouW`Y0cKDfXAGN{};aMpLRvZ zu`PZ-3(+Tsh?UKAr)TQQ;2Jz(kv8{R#!c9Tyeev55@5@Ng*c4-ZQ6vC?o#5>6{;?gVfAIr-+^g>3b$}13U^~?gce6s6k-4ulnzWlFpq}*)2 zd0!wP{2>3U+zYiPaNr+-6O`J;M2Cb`H5hjDXw(1oKK!?dN#Y~ygl{H2|9$( zVg7`gf9*O%Db^Bm6_d808Q!r%K;IUSa(r^hW`w)~)m<)kJ(>{IbCs-LkKJ5Qk~Ujv z|5`OBU>lb7(1IAMvx%~sj+&>%6+_-Pj&OOMzMrkXW}gMmCPOw5zddR}{r9blK&1(w z^6?`m=qMI=B*p~LklFLvlX{LflRXecS#lV$LVwi$+9F8zyE29LgL> zW6R-6z&3x-zL({$nMnbhu|plRO8S_EavN?EKrr+c&Tt;Mk)NC0e|cvyXk%VKb5VIc z;|DN^5)t^}tr&-2q)SbwrF>=k$moYK;yA{Q1!I940KmPvg_Ogb81w$_)i3FgFWG+MS?k=BpkVGk-bRhBF;xJ}wnGN{)?gbry^3=P1@$k^#z9*@tmmB+TZ|L@3#3Z+x z8hJE({GEeEWj#+MnUSN^~c!=G+yW^j=cfN_0!}%(J-f1`G}w^}xi!T8BJDOCri{mGBU? zsKXxeN*=L#<-p_aj6cHtYWMJ+;F`HLeW5cpmeVAhFfy+Y=0rIqqyJ-NRIu-aE*Mvr zVnC-RDR`d1nnQu|^S79I>%9=bPNx1JLOJnB**Y`2WCq zctq<)Cq2^Z%=$*&;QxX30;642;y+=mlMLec6{KA208FQ~_S&tiFQW zp2{C3nyrmgkh+HRmG+$_y19m~0z~b`Mo+m6)Qq82p5)Z6ePn&B=!*twk7Rz%zzm-R z>Qj!PE3XMBY)N-xO(=VpO6=Cky5kpl}fQztM7QzvG#a}5$>2$f5w|}b8=3E)cNQw<%e1xAEwaRHu zhHCGB4Uzs6x3A=7uUBC0({&iNH{!7JgQHVa+ zKfQItwD}sd;587x?M_hzpR|TKtTH^4{`G7*87o_wJrFlmrEjk=jvA z6xBPKYjFB9{0Sj0rBL-z9BuBY_3c||UjVgv2kqw2m<@4#>zfx&8Uhq8u+)q68y+P~ zLT;>P#tv|UD62Nvl`H+UVUXPoFG3>Wt-!sX*=4{XxV|GSC+alg10pP~VaA>^}sRr1I4~ zffa2?H+84k=_w8oc8CQ4Ak-bhjCJIsbX{NQ1Xsi*Ad{!x=^8D6kYup?i~Kr;o`d=$ z*xal=(NL$A?w8d;U8P=`Q;4mh?g@>aqpU}kg5rnx7TExzfX4E=ozb0kFcyc?>p6P# z5=t~3MDR*d{BLI~7ZZG&APgBa4B&r^(9lJO!tGxM7=ng?Py&aN;erj&h``@-V8OA> z=sQ4diM!6K=su^WMbU@R%Tj@%jT5prt8I39 zd3t`Tcw$2G!3;f!#<>>SQ<>g6}Q{xB|sx_%QKm2`NxN|Zl%?Ck6Lu_EMC?*eRxdgS!3zYU#OnO~0&UFei zmP3k9!70^O24j5;G-fH6%T}X{EdO(%*+7ThlNGAh;l?$&{eZ-l`j281o@47x+6Z*DC`R2CkPo{1Behvlt!4${0Q?fBx)iIw$Ky zI#xvxKs1U`uMgeZg5fD>s5AYH*n=+UaRzS?ogn6WwBPK3Gib5@Jj!sZN^tm>M&*r@ zjbBoF7uXJU2MW~JK3%Xa3R}3zsP7qHEqbnC%eKsJ51+% zVAT-eRHwD)0YlfK2&rN549*};CJ8I;dj8rD^PR(>#n?Jccsqx&wF#We;Auv9Vm%-} z3HjpBGp$t5^S$XhJmYAP0q_qM@^#D}NM1FmCCyo;F|wv3_ci@$MA<3An0Aa|>_M&S z%qGjO@w{NI$VKyDF@w5W*6XK~5S`S$@ABWh@uaFIBq~VqOl99dhS}?}3N#JizIfYYt`ZKK0i_e#E;P0)VXh-V!w+qX%^-I0^ok>HAm5)tbBZlYov@XkUL zU}l}NDq{%pc=rmBC>Xi>Y5j9N2WrO58FxmLTZ=$@Fn3>(8~6sbkJ;;Uw!F8zXNoF@ zpW;OS^aL|+aN@xwRNj^&9iX;XxRUuPo`ti>k3Hi3cugt`C(EwuQ&d2lyfO` ze!0fi{eHhU1yN+o%J22|{prPvPOs1S?1eUuGUkR zmzMlCXZtW)ABWasAn53}?BqtPMJ*g>L1i6{$HmoEb@h(kILnMp(2!H!rG?MNH`1V0 zotb`;u#Yz0BZrT1ffVTCV!?{L^z8q11_21ptR0ITbOcaZ!mlWhC_AZb>?2IDV|b_y z9lVt3)0d@W=lNp1ArE;h_;DDQX^_;WtsSIO<;Ly&(#O~Xw$R0~W|xdQk*Y(b2=vLV zt8HX8=;#;$=y}!;Qku2HJbGEzF`2_~&i$&ogHUe5vhx}FLR}K_Mp)J{n*Va2<|pk$ z4tI(7v3A%Z7Z0|ZWw#7%$U#*mv+`Ujlh^N(t63xFt_%*WoJ^oq!U0j+Bx`<>q!J&0sWy4&{@#*BOr-s ztZ68f;l0UT3wf@RRC}_ufMr6rQ69Woa@1sZ50Ww|{yfp8!7rMOh_POTE;|zamq+4OObJ-VeTK|D|h?mfR$^lA{E7pk8DRDz*j&r<&fR>GaG*d zYaJ*q5#n251XIpR6F1o-w>LZ)Cb6Ma^6tCfcOItn1o;$#H?^jqOd(PA)B3HaTlJK zw!~?nh-v-_WBi5*B=IuTZOX2sa{1I!#%VMd5eGe1VcL6 zQ!aDft}>TjlwzEJ9Kr6MWh1MoNNWr$5_?z9BJ=>^_M59+CGj=}Ln)NrZ;Fja%!0oU zAg07?Nw&^fIc9udtYSulVBb-USUpElN!VfpJc>kPV`>B3S$7`SO$B21eH8mymldT} zxRNhSd-uFb&1$^B)%$-O(C$#Ug&+KvM;E9xA=CE*?PIa5wDF_ibV2lMo(Zygl8QK5 zPgH1R(6)1XT9GZ6^ol$p>4UH@5-KV66NF$AH-qOb>-b~+*7)DYsUe&Is0yTx=pn8N zs&2Z4fZ1Wk=dz>AXIfd%>ad=rb-Womi{nVVTfd26+mCx`6ukuQ?gjAROtw&Tuo&w$|&=rEzNzwpuy0 zsqq)r5`=Mst4=HCtEV^^8%+Dv2x+_}4v7qEXSjKf%dOhGh~(FDkBW<~+z&*#4T>r@ z>i7T5TGc96MfD%hr~nK9!%r{Ns9=7fui)N%GN8MvuIrox)(0nNg2{McUIC6nq>dD+ zNvX69vvf=Pw1@x}^K{@%UCL734;&AVta#($&l2E|*VUaKW@h`X*L*;1Kl4tajl}GQ z$K>;*$3y1(<^32Cg8ugi^ZII=I&ina>q@GC&~gQ#Z88(nOj;*j z1{hyEq|R_0v7LZNKB|3jqZPqZOuUG(SuM^Z>0@mzsKqVbRrkTz#TRZ0sTQ|%XiYcE zEE5{9jEB+2Sdga|veYSFZEzOuepHGusAO#pg&R(%Ob@V0Lw;AfQJ{aLUJxnbe`q(m zadg^fXYiWr+mm2akb*J?y`w(!KAL8OfFD!mVWiWrgScgp9^yoh3lNNUxd?YyvgUL z>+!2VXP7Fzq zYQ?(9-r*?N*cJCK&)pbYzuv%R{b;TB_wC1V3nO#12V0ucgp);>!N=;G=l;({KZF>) zNAo=0m|3Zu*PNLa-2v=3r5>-hVI_xYdz0m*f-zUW_=eDqiM3j4MPnS~eIRNdw466? z)yxHI@6d7gL2Qj<_@72W{GDyINBy%X6X&_cF1(##v^}87YGZ87HgfH$&epf>Jlia4 zw53K1M6=Px@YCVTUk!%_MjyBeaWy7c40i47-3B{voi|&|7aXza!(OB~E)U;f>5Wd3&@#UP~gkM*qmK=aeZ zkP}gn%JmKK34}KdEu)4E2~qN)EnAhj>)4dbq&RbLu$BD&kJSoIvr$3A#S%P~l$l1A z!96hNdtFXsta!b+enJ@G;6rv-Rd=IQ_llL#tSGk-mpQi(mhop;lObiTQIARXw~&d> zVuCSG$T&zi?#&PT-fP)`*-d@gc;+tOPDaUA*6>RIrf67& zpZ<1ie#4rJ3HEu>v7sF={4;oXv?_MwEI-^o-Lr@rW%%cd0TR2q`p=rkMOKYzOs&^$ z=xW*e)6p-B(0Ek7w8+!@Cks9>$_#zi44MLyL9X?{sDlihX%V;$%a;wd&RL*XGcb$` zvU}#qxz8wAT)*NQ+lXO>AI`^r7B&IQ3J&{cVNn0aWa)(!fQtV+mm~`vsH24+xI|q{ z4ce$OB1hrqGLn;H#=~Rx%T#b|hN`d6SXt=;Jd=DNX3LO9R8xLX@6p3>SnZO7M+96a z1s=zJKd%qy0#GWLeFgc~?fsCw^$6lG;B*54&@n#>q$#nRSr?2GA4YaSSl5~B2k}R_ zfJE-$C~{O_6Rh6BJbWFuoaeXEI!Q-YSA9EvSG_sjB~-*hf_PM~mJ6BL+IcaF)8$+; z*4A4W&+_Mn6~tF|M8Sz57BxO=W9ZJrNPtdhME>$sS6)etinxj{YkK){@Q${`Vc~dX zLT4UYjwuC>dH8AAjQb{Ji>eMvJ5rH-4a(K{4EyLrCDtta)u#>`V_AvyS?Y(;FRT8L ze`JXZP4s~Quq$m=6NI@}`( z`>o3kbSApxcHP;1Mds3&41!_0r619~@AQr9TW*Swk`Q1JNmIk%nKm(ZbZMHEi z4n%vC0MuAKNz2njKLk~w|6u!|y7FN!SXk5=7>^^p-R4w7R;~G!v<{>H3%SC-?>8jAP&ka=owuQ$sKwU4e8EVyc6V2IpBR56HthbwJ*XdwnwrW4 zcR7oGg7kCmj(q{#ka1d85mRVIo0`1v3+B--4RXv$hGb545y#j7bmu0*>BLnTRZ+mp z29%AP8Id+57Q(6`ep^<tq}GO1dvJ*8~jxjiH0quR*Poy%N3@c8rhlO6YR@LBk%l zux{&bK~LvKYq%d;Tzl|VS=?rkBUD-j$YY-xX)z`zUfH^&($ZYco(Xc1tr|9rwx}=- zk`E2Wwkh*HIVsWej-nJ6HNH)7rWDlB0@`{QG*0)&P+~Ng{m^kG#J*^p`drM(`dnd& z9$U+FH=rXh2py-N$l_0)@|JY;X1hVL`@}qxNi@Zy5hI)@(af%=1cl~L3{fxZWys9G-hLv z*%jvhoba^ePB8YL)`%d%=t6Yh*c5p1S7`+BPjOD*#q4~gv#bn0wOaf_K0SiGC{jp8 zAc_Vk31hKTSUiEU7XNk7`D}S-RUrYb<7%)k+tV0zZ7(}vQN@0C5EI<=$$qW}m7f7I zk>dMLd+kSjN4{OaxBJ^_h?FayJ`Yr)3eC$jdk1@jEzVT=a?{BSjp?&?qPX=xO!ttw zN_s#<#Ve(0i_|cRa=MC2=8MonmoT5)UtF&Wr9-b2ng>>zv{8$*UcIBIXSZ3)x727q zy{r>bdOh?E;ZI(^io=P3`o*tLdsjkjM!rGae!v5QH<3-OBW(XcRhvM!(b)Yas?oK? z$5)Y*YS^_d9H-ZP^_iVooK6EE1(akYvmNkXQGH1`kXg()p94|_F8B@_ABt*7QTmYk z47RyNSjX8nMW&@VZIQ`1WB%-*W4oN#|M}EKDCC_@HQ9!BenOQ{0{i#>IaQkyU-HOT z#8ueeQdKezCP`+p0{|o?!axX6WB@{OJTR;qfs(;uKp@Kjq4Dr)^>R9T+^$ohEYKB= zQx_P+t?e3z}3#W ztf10?br2MbSVn%*3!j2QFu;=K)-ueTmgyYq;%9HjJL_W=dV$#21FIjyv}d3@oIy+c z?IcrTw17F6oYGMQA=66yCh`48DJb}^Q?8r3Lei%QJ!qpxnt5`aP%aJL9ltY7#;qzq)qdoGzpYx=gz7Lz$JJZ4?^Nr`!1MK@k z47M)#_%Bezu?xD<{tFcQ{{@OiDQRGst}MJJdOtp%(wvCymmU}NKvIK%z%RysueJ$h zMe(J;-iblcWW>90Ptma{$`%AUZi8_y>pQy*1GpoiiS>`GK9%)TGXC!$FDO5REO0l^ z&lv``tj^Y#F@DP6&qSkCYO-b8O*XVx^8O@0D}Wv-tbz7`pYOlCS4pVmi!~|4dv-5i^8laoUpk zxH@-rdRED~DyWrZO2290e;bISH8z$=kcmp_ct)+edl012<`vnqx}D^FD$twK8)RpVW@yMvk8CRc&d*ku^a#%~2|u>f%{up2Q6x9Mdt&e&@t?_bEXURy{+@>{ zJjDZB-f~7aGc%-QXc7g4fF1tUfP-hsa@qS*#N2_g3675xMqbzyQnC~pK_jH^3k}w%a6jCW!C?MU zo{9eUxt*=#6(neNmoNf#hiRNdGBu|Q(@9s7|H`J*IMWuCEyE4;3IJtKS-n7f+C1=O z89gY4%6N}DeX%EYz8B!^9f5Sf8V2S}yTJ>r+}=RsLXtADv|&$w!dxTz4oSIuz=8S> ze%G>2|5coCh@K)cA(h6O>kRSfAQt>H_fE#}H@p)v`Tw>aulOfNhyS)7=rI4b9Co$DH=Jd$I?iu%Tq!e%aPW7DXN#iTjDG0TqkpLrhBBzR8`k zD7XbvwV1f*5U7kBxrIxHO}NcgSmCK*P*zt<4FpS5V5@~j2g+wGN-WtIbV``U0-3X< z(0T||f@~2Ebo3UuxzrdG=FuH~6+|7!VsYU$0Z;OEL^Mr^S^zSSbYwE3A~U-vOJDyUDUStXfD%K9;#`BD_z>Zb zYj83mc+8KTgEK6`Y;^Q6ku|@W3|m*M55gt8^^WdrxGslExn_2O8$_a0M&&_Be0KPA zDd|?nYAOvUkTJUXZ7l2Ml&#rK04@AJabu&@g=pIr~b;eo^(8BT(?FunH$AF3j*ZiHB%C({8I)tTa3VRkn) z=9uW|9))}J#GUqRh<&w4yL15QpK%2bM)-YYq2tcqZmh#_)@tYAn7$!Z+6(FhAPs2p z^%a8A6xo5O-hgk)a=r7#iC9Sn=%vgrQsl}WCq)N+4q*=_VT+ac3I+*3lJQ&#epf@`!?G!7S(!aZGWqpGk8(*`ig}*V&iyhzH;xtxA$y_N z>)-lw)z%-mcQ3s#`hcb*fp;U`yikM&{Z0^!k1?*j(d(dK9Vw#6o;HRAhEj6!& zxJ$%z@#hubu+iCATwZBgyl$DO;-%^6*lhP|m`wV*S9e%1oP-d7}LFzNb-nbg&b zLeV~*+>vogxCnjjqMaj6y1jn;s7GQLf{ZSY20O#1YGg;yjg-{KM81iL;0{|;LN@@* z6ST#KrKAJTzEMTb{1d?&eNzE47+;ZFtJ8pB_U~EkOk=`-6MB) zTaU^zm3`7P2kZ;D_=u#Q2t;SHzo8P1xqM5!?7^WSE#u5XoolRV{Q}doTaC)1S08Zy7GJ?pd&8Jjw z`*_`ev(<+Ra2R&CQf7cb97~c^x3voFRhQSEV_1pF(I!QUWEkUh<2Uq?3Cz9FxIKeB|n?CuVkX7tAhr<4Ej#%Cq?uB5e^<(Tu{>54T z!(6b8DmhS=>>S)e9h|J%5}ljxfXIRDVa(%*0*xTQ{+ zUjroY*#_U^>b1Teuc$T-egClH97?IE<0#OhF0Y9ByTKPxej00P`|jMJVCqxQ>44F0 z6StS1JT#Ng(}>CWNb0uNM*qkV5JF(s$Hm`S`+O2LRS#bpUMgwU)x`e2u1#H8woa1YGZIsxydK5$JP$cfI67I1 zBE?jjeY6QO_arp9gg1v9k)(iTssRJl7=WdW!5$tkQ-3&w4c|W=|Bh|HOKy{C>%J3@ zZ|8r+H6nd{{iLE~*`b<}mmrmA{8WRDdlJ%rL%W#To}q01jQ%5ZNy@MC_fzCo_!q8x zb46H1v;|CrZ;mdn-6=g>sqK$5H<)H5rH0*n+c!YnE5YQcu{wHPyVztNP`)K`bv3XO ziFeTQst%KJAd9G3SLmUQ|V9fRRc;+ zPd%sGo1p@XsJh&z8?psQ1@NnY|!@p3%Mm9gi!S*yNThSTSi>xCoEGLx%T*dPC_ zK3J4iwp-OZ&1%b#}32cNRbgvhDTdd7->2vcnO3Mt%o zR22P|KlOg^Lw}@|mzlgUh+KF7hZA-R_k=AFARuTl!02E$Fun#45CtF|+z(y&M--)~ zkX(>sZe#6y_I>oP0}9KH=o`);bPVMO1Tg8k$trp`n2F7Ga^3Z^)#GsOamw&Zg{k!R z#))|f#dP=GU6 zM#KYRBI_eOICiiDR%oBa@n|ggpZJs>v7kQ|)(*x)4xxl6;d76Fl^)QGde*sDZnRit zpWm`UgACR9MH}@~KMp!Y^x#))Vw2>dEk%BKQY#ne{MWqyu__rdoOP0@hS7`G*TR#L zKP;$iLuM2_a){&S^B&D>F@2K;u0F-emkql27M7pe;`+bWflrlI6l9i)&m!9 zKWFwavy<&Bo0Kl4Wl3ARX|f3|khWV=npfMjo3u0yW&5B^b|=Zw-JP&I+cv0p1uCG| z3tkm1a=nURe4rq`*qB%GQMYwPaSWuNfK$rL>_?LeS`IYFZsza~WVW>x%gOxnvRx z*+DI|8n1eKAd%MfOd>si)x&xwi?gu4uHlk~b)mR^xaN%tF_YS3`PXTOwZ^2D9%$Urcby(HWpXn)Q`l!( z7~B_`-0v|36B}x;VwyL(+LqL^S(#KO-+*rJ%orw!fW>yhrco2DwP|GaST2(=ha0EE zZ19qo=BQLbbD5T&9aev)`AlY7yEtL0B7+0ZSiPda4nN~5m_3M9g@G++9U}U;kH`MO+ zQay!Ks-p(j%H||tGzyxHJ2i6Z)>qJ43K#WK*pcaSCRz9rhJS8)X|qkVTTAI)+G?-CUhe%3*J+vM3T=l2Gz?`71c#Z>vkG;A zuZ%vF)I?Bave3%9GUt}zq?{3V&`zQGE16cF8xc#K9>L^p+u?0-go3_WdI?oXJm@Ps6m_FK9%;;epp{iCXIh1z3D?~<4AhPkZ^c-4Z}mO zp@Sa4T#L5>h5BGOn|LS(TA@KB1^r67<@Qp!Vz2yF573JoDBug@iPQ=tr2+7*HcE3(5`Q%{A2 zp%psJG}nJ3lQR>^#z-QI>~|DG_2_261`HHDVmM&*2h2e|uG(OXl?228C|G32{9e%Onc=sVwIVZ=g2{K5s0>v2}V&CZi1_2LA=x)v|&YrWGaH zEe3L=lw}aSiEdWu&2-C5U0O~MpQ2Hj-U8)KQrLg0Wd|XyOt&Gc+g8oC4%@84Q6i;~ zUD^(7ILW`xAcSq1{tW_H3V};43Qpy=%}6HgWDX*C(mPbTgZ`b#A1n`J`|P_^ zx}DxFYEfhc*9DOGsB|m6m#OKsf?;{9-fv{=aPG1$)qI2n`vZ(R8tkySy+d9K1lag&7%F>R(e|_M^wtOmO}n{57Qw z_vv`gm^%s{UN#wnolnujDm_G>W|Bf7g-(AmgR@NtZ2eh!Qb2zWnb$~{NW1qO zOTcT2Y7?BIUmW`dIxST86w{i29$%&}BAXT16@Jl@frJ+a&w-axF1}39sPrZJ3aEbt zugKOG^x537N}*?=(nLD0AKlRpFN5+rz4Uc@PUz|z!k0T|Q|Gq?$bX?pHPS7GG|tpo z&U5}*Zofm%3vR!Q0%370n6-F)0oiLg>VhceaHsY}R>WW2OFytn+z*ke3mBmT0^!HS z{?Ov5rHI*)$%ugasY*W+rL!Vtq)mS`qS@{Gu$O)=8mc?!f0)jjE=p@Ik&KJ_`%4rb z1i-IUdQr3{Zqa|IQA0yz#h--?B>gS@PLTLt6F=3=v*e6s_6w`a%Y2=WmZ&nvqvZtioX0@ykkZ- zm~1cDi>knLm|k~oI5N*eLWoQ&$b|xXCok~ue6B1u&ZPh{SE*bray2(AeBLZMQN#*k zfT&{(5Tr1M2FFltdRtjY)3bk;{gPbHOBtiZ9gNYUs+?A3#)#p@AuY)y3dz(8Dk?cL zCoks}DlcP97juU)dKR8D(GN~9{-WS|ImophC>G;}QVazzTZ6^z91{5<+mRYFhrQeg z|Kn=LOySHXZqU8F1`dXWOJ?NViPE%&FB1@$8!ntuI?)geXh|#JJC1+G^n$h4F)g-P z4WJMPQn{p=fQtw0)}uk;u*&O2z+G5?iW_=1kTy(!AJzj}de{a9WHY+*SqJ7`={VTi)3NK|)*W3PUT#5a$D6oyqH%5zjdO$5 zICHx_V;1Z)4A(rT6aasvZ{{r`HnxK7^fMLS1{;H{o<8j5hz*F@WkKQmDI*Q%Kf$Mo!EpQ)=HV^lsj9KSz->ROVIrXAI0!Q?WUosf8t6CR*rl382^sU3q@($L~E zC(AoyIjS&2(el|I$ za*8oAtqGQs+O~huhBCOFw(^b&bol)FWsp15Sra3v%&#wXz*!kSi!sV>mhe(I=_Zxmz&E1>i6=yB*_X4M#ktdNg7_G}MVRGQ z7^zX=+mQ}1xtg7JN9E(QI&?4}=tP2#z2<7N%zf9rxzynL~!MgNpRvXaU69c*^X2(c?$=h&o~Fvv z06*{JdsM!gF$KALcW(}@Q&Alo`@3h!H3j^@5rFMp8l6-q!cb?1iS$oZfU+}A2< z)&2ZoL34kkSnbf=4>qd%guV7zM1p=amds@nhpkK7mRJlb?9zYI&?4ftd8+RvAYdk~CGE?#q!Bv= zbv1U(iVppMjz8~#Q+|Qzg4qLZ`D&RlZDh_GOr@SyE+h)n%I=lThPD;HsPfbNCEF{k zD;(61l99D=ufxyqS5%Vut1xOqGImJeufdwBLvf7pUVhHb`8`+K+G9 z>llAJ&Yz^XE0;ErC#SR#-@%O3X5^A_t2Kyaba-4~$hvC_#EaAd{YEAr)E*E92q=tk zV;;C}>B}0)oT=NEeZjg^LHx}p zic<&Fy$hApNZFROZbBJ@g_Jp>@Gn*Vg{XhVs!-LSmQL#^6Bh-iT+7Dn)vRT+0ti(1 zYyOQu{Vmgyvx3Tuxk5HG!x2a+(#>q7#Xji%f&ZxT@A*$m8~z`DDl?{&1=gKHThhqt zSBmSpx#kQc$Dh6W76k!dHlhS6V2(R4jj!#3(W?oQfEJB+-dxZOV?gj++sK_7-?qEM1^V z=Sxex)M5X+P{^{c^h3!k*jCU>7pYQ}gsEf>>V^n1+ji40tL#-AxLjHx42bchIx9Z< zz`>51CG4Iboc%m0DAfvd3@b}vv4%oRoYZpZ*dW?+yTcduQlxreAz&6V(Tac9Xw3_` zNotT9g&r{F_{!Xb%hDPJqn`CWqDwai4M@7F4CQ?@C{H~rqxXwD(MFpB4!uljQmH~( zTXJJj3MEVHkt7r8!^R;bp!H=&%-OG&ONKIOgLJtng(VD0u9%2LuXKe7h$?9lQ^#cL zOo}gOx^+ixt2Izmb6{J`u0VexU0j}8Is+?LWLGvQ66Pg0ax4n^G+xW-rwp&fIZ0}l zI?y~wn^6o3{jj*VSEQ}tBVn1#sVTQB(l&Gf(sriC0DKR8#{);Sgb5%k`%l#BfM#W| zfN5C8APnl5w%nrNi{BWrDgudYAZLGEQKTzz^rV(Bst!UI7|8?nB_w}@?_pYX_G?9i zgK?yo0}({MC^6DiO!bB88kijN>+BCQ8v!rg{Y zz$`Hf$tB*WdxSPHMMkJ{&p0(l zyXx|^X_VUQBdh9)?_2P1TViiYqy+91$zg%3%OjzWyY=X^f7I)2-34bDVCEhECAi z^YqS9x@(kD(Bto;VDKfgIo z-)s_q)d2mr4O;DTUTgjOe4f51kd6T9`xa6_AUP*N{jz%!Z0E!Dqq}JlfPZ2EyGN*E zoPHJ^rT;z^0vaI03Z(WcdHTh1suHxs?;>yWLj~GlkAQ#jSWq|nUE}m()bBZ1`Rh^o zO`d+Ar$33kry+En{&JjrML}&gUj3pUFE58(t|p~g@k3p&-uvoFzpGktUMnQ6RxDA& zibYl_A!{@9au^_fB@6;1XHLORS}C(Hi&J8=@>Kw66&QJD@w>_I1XJuBW3_vn?f~bb zTv3_J^W1+E?921QNo!MQiLHISD9?+dP0BsAK+yB?l009uXXMOteoGX;?5I|RG_v#B zf~l?TPy3zGkT`N>WlZRa=k7Vdbz-66IQ979fX!i7Wen@lu-oEcweu$76ZXrc&JWRf z!tLRg2JqNG{;`-H@L` zKHfgY-Lve@vsPT7B0@716|Z$Z-Z{!WV;qGHV!`h!S>b)rZpc`9J))^79ey;7@-=zZ zjys+j=U6maKhDddqZ}XQffIbFYn)R657nRGEG#j`M-Gni4deWVXcr=HoNok4SKTPT zIW&LDw*WrceS&Wj^l1|q_VHWu{Pt**e2;MKxqf%Gt#e^JAKy{jQz4T)LUa6XN40EO zCKLskF@9&B?+PnEe(xB+KN|M<@$&ZP{jM;DemSl!tAG2{Iisge|}6`>*BENm!G2E!s_XsaUit2`a&pfn!ggt)wG<~No zFFD~p(1PRvhIRZaPhi})MXmEm6+(X?Aw+GxB}7gAxHKo)H7d=m&r6ljuG2KX{&D9A zNUe9Q=^7yych#S!-Q!YKbbka8)p==Am-8`N5_Qz~j7dxLQeaeCHYTma$)Fy}ORKS4 z5sf%}(j`4U=~Aq(!-|ZRRXvQijeGJ^%cq3itmW;FI)JsU8k4pNmCazDyH9@=bqwS9 zq)y8?KhH}MpVTd^>?u+Cs!&l|6KH<*pikOqr$wK%YZ7(>z%vWLb^+m&cCQ+h_MDo+ zaXmPW7CD|K$-d&cg$&GVPEi#)hPjGYx|SBxatca)&Ig?*6~uiQKE)tF7l+ci4JvbZ>vQo}1mB?m;{w?j6>1xBD9F+2p#Y zP3U>vfnMicQVHdhK1yDCfacJHG?$*GdGs93XO$LkB~?nFAfNOoRY`xRs9JiG7CM&D zd5!=ra;zY~qn6HhG|^&58(rYoNlP4qwA7KN3mvymz;PR0%5d!IoDF1vxVxNS5wG&fEt`JYIGi>i=Fq;YUc>8aXv_wIKNAm zI$xs8oUc$5M((w)<+NMQ6{7X7iz)2tqz$eebh#@<&91|=(KSq0xZX>fTn|!v{~LlTjaOXR{3kxDZfD5rHpl>gbmAU z@|wOa$t%grx`7}nA|ePPsN0Y)k&2=Mc4?uE@gW0-f>S_2bO;VnKt&W3k$KKdvZh@& z*WWKa@7#~`b#Kuyw9kqd zj%CMuQ9ESPc-)MbM#7}YUL)ZP_L{+siDWcU?e8%n3A4VsFYJpNeLjn2bT>CI3NCJ< zwecm{{XNM@ga#75hHnwEW-M&QOfzo9!Zfi7EH$DX3S}9p>0NY#8jZt#!W_KUc?R>k@Ky-w6=+Da+_s0GJldl zF|P?(31@{B7bweeajQGYky;y%9NZK$oyN7RTWNn&2`?k9Jytjwmk||M(3Z!M&NOYw zT}t~sPOp`iw~(CAw<+U2uUl%xEN7WOyk@N3`M9ikM-q9|HZC|6CJ8jAUA zst!H<<<&6(6Zvbpj!BrzUo!>VHN3A3vo$EF5-6b1Q~ajXENB~lhUA@|>x6=N0u#cf zv&w(qgG`^+5=HoNur`2lvR~b&P zjumO|P8X;=d`c+z1YJlY7&H@Dz-Rts$X0IYE9kSIlqGZ7utSx^+ z2hOEC-eXviWZXQ9;$Va+WlHlU%y|f~w(|)o@(5J0o|3MQ2O@+B<@r*H4*65)(r^JT zq+<*b06XMGclsEElst5dEfFJ;AQfYhRt}O0CVKdGh4Tk3-(^-{kukZb*3oM$ZffpG zMs;jtk2ZjAsn%mND4R~OS73JDbj^Q440{oS&4<@VUYMInc0xxy?FE@$J_^n)b|gY+ zOj;8Pk^)6$w9nbnMms3RSr6q(9wP_)v01|=P}UbkXoS_1#FCl?>&9cjCHOS!yEJqiGd`83Nj00{X6dHFN84%)I^*MZ=*Ihw5FxD0YSJHV{j!9v(DT#k7##q~$ z87Dig!k3EiMO;k|9XhYz8cGVPukGe$N5@yNtQgngIs(U-9QZ2c^1uxg$A}#co1|!Z zzB|+=CrR6lxT%N&|8??u1*Z?CRaGbp6;&#}$uQEzu(M6Tdss;dZl=hPN*%ZG@^9f* zig-F9Wi2cjmjWEC+i?dU`nP`xymRwO$9K3IY`|SvRL^9Jg6|TlJNEL9me$rRD1MJ| z>27?VB1%1i)w5-V-5-nCMyMszfCx0@xjILKpFhA4*}fl9HYZ~jTYYU@{12DS2OXo0 z_u+ot_~UfZNaN>@w4Es$Ye>i&qhgqtxJf9xi6El-@UNPeQ>aXcYVxOUA--x3v1 z3e=7+%#m@}QuMTjN3n--=-{@rNtyYdYS@LJ(G?*np*HILbUeo)+l8N#+F-;^(8w>i z8Q6til8Y^NG7_qa*-n2|4}(k<-HF~R0v*cP7bxlTWNJ1s6#Rz!N zCYesAbm(}4qp%-;B%AF-LyS5Q6@Q|V&Y2ar$uWn(?UstqXy;5$ZOCC_?L$F z@o#dk--?Co{)CGEP^73Kb_^>`G8sAN)M@iNKQLBj>QAcHjIw0!1 zl6{UYd;|bA+CcC#3IGYysWLa4!KA}CsEV#c)JpJcF~NX9mrX2WwItXv+s%I2>x#v) zy%5xDSB`&bU!9COR@6LwbI|OQ&5mf&L^GGZnOXEOLshxOs;Y;ikp^M(l-^>J(o0NIdbt5`(fTq>p%?cG z;%aHXhv=-@!20#xf*q)++kt8IJ5cG{ff?Sy9hfzQIroA8N>Git>3xOUNhe8nUspSV z`GL0DK}<_w!3gRCwOvD~m+Zn6jxTMde<_?egr$S1OySh6XsS!0Wh)wJPX+xd11YQ= zMq7X2tU;U;Xx|ObfO}%y{pchi>ryaM2zAy50_$ltt(ew6h#CF@+U74D#H@hdQ=dX_ z=OChf#oerWnu~l=x>~Mog;wwL7Nl^Iw=e}~8;XZ%co+bp)3O z{Mryc`*3ryyIC*S%Zu;8Y_D3bFAn%8NTYv?y_%Q4zR-DvE(Q*~>ec+JSA76q7D#_w zFR&HI@z>V`9-)xr*ME%7~<$Ykd?U8uZ~EqUe&AlGDqP{uUvna zvy#q%0y2VKf%UxO(ZC2ECkuzLyY#6cJTru6Q`qZQQ+VF1`jr8+bHIwcJg}=iko8FE zDt(bW8pbOr>?{5KLASE=YFFv&(&IM|P6@wK(5#jhxh@Pe7u_QKd{x@L_-HM=1`rX8`BDds3pf+|$)DBqpXrDP>JcOxubC$Dy60;8(mfG^6yXE(+N*UWMW? zA~?H-#B7S@URtmlHC|7dnB!Lqc0vjGi`-tNgQ8uO67%USUuhq}WcpRIpksgNqrx{V z>QkbTfi6_2l0TUk5SXdbPt}D^kwXm^fm04 z^i66Xn0`pLmnhX(P0|TezLiFcQ{E0~v*cmmAR2|PETl7Ls>OakCexUmie^yDw3ccuqd5(wV_6?YM+ zegsV{M=^n{F2a}~qL}DfhDok9nC!X$C9WV!U15~DF2xl0YLvS#K!rPqsqS7(b8m## zZA(3F3H0v&0Z>Z^2u=i$A;aa9-FaPq+e!m55QhI)wY9F+db;s$6+CraswhRp8$lEl zK|$~`-A=dB?15xkFT_5GZ{dXqUibh$lsH=z5gEwL{Q2fjNZvnQ-vDf4Uf{9czi8aM zO&Q!$+;Vr_pzYS&Ac<0?Wu}tYi;@J__n)1+zBq-Wa3ZrY|-n%;+_{BHn|APLH8qfZ}ZXXee!oA>_rzc+m4JD1L)i(VEV-##+;VR(`_BX|7?J@w}DMF>dQQU2}9yj%!XlJ+7xu zIfcB_n#gK7M~}5mjK%ZXMBLy#M!UMUrMK^dti7wUK3mA;FyM@9@onhp=9ppXx^0+a z7(K1q4$i{(u8tiYyW$!Bbn6oV5`vTwt6-<~`;D9~Xq{z`b&lCuCZ~6vv9*bR3El1- zFdbLR<^1FowCbdGTI=6 z$L96-7^dOw5%h5Q7W&>&!&;Mn2Q_!R$8q%hXb#KUj|lRF+m8fk1+7xZPmO|he;<1L zsac`b)EJ~7EpH$ntqD?q8u;tBAStwrzt+K>nq0Mc>(;G;#%f-$?9kmw=}g1wDm#OQM0@K7K=BR+dhUV`*uus`*ND&2x<wG1HL5>74*j@^8Jn_YA_uTKbCF<(bN-6P0vID7dbLE1xY%jjOZPtc z2-(JHfiJCYX>+!y8B2Fm({k0cWxASSs+u_ov64=P?sTYo&rYDDXH?fxvxb>b^|M;q z%}uJ?X5}V30@O1vluQ2hQy*NBwd}kGo8BE>42WYjZn#(~NPFpjeuet!0YO{7M+Et4 zK+vY}8zNGM)1X58C@IM67?0@^Gy_2zq62KcgNW)S%~!UX1LIg~{{L&cVH^pxv&RS8 z7h5Dqhv+b?!UT{rMg#O##tHOouVIW{%W|QnHnAUyjkuZ(R@l7FPsbEG&X{YTZxd6? zGc~wOFg0-e2%mI+LeRc9Mi3vb*?iSmEU7hC;l7%nHAo*ucCtc$edXLFXlD(Sys;Aj z`;iBG;@fw21qcpYFGU6D0@j_)KD&L`tcGuKP_k_u+uZ@Sh<3$bA}GmGrYql z`YBOYe}rLeq-7bVTG?6wpk_57A#-P&*=D9tDbG+8N86Ovlm%$~Fhhg1!#<%uJPW4P+L>rOa{&N2gbFd3Fh-nnA8 zlL@IrHd6K33HFYag|7^pP;EZ&_CU5|tx*P)T5w<3xsYB7C+*ZJvZ7o_)pdFg0Mq37s%lo=)Pp+u-bBo85|bFx@z znXN$P1N#N~1jF)^LHc?61qH?2r$7+}^DzU=b4Sh0ILA`+DkZGwe8`w6RaaLOy2{+; z*G-qRoS@LWVrj2g$m_QBE_9ft8J2%>-hNdge!7N;!t-RmW$Sx$dLFwX06)v6%V+3+ zI_SpK&${J_g&{nfAAf~@mBoJzd1aB-d!go}pMC=xBXEb1?t=6Z2khtQWf04f1vH2D zAzR~Tj#erum;iqZ)uy9mW#IE(g6{gBs0m8`Hho^9SLk>6WYl=|`BSI?aM#~0G0T@g zhZQIE7P486_X7pDDlh!Lpxdh5G=KJg4;1hc2-bl zI9c0tmCMY}Qn=5b(4Vqv{|sKKb)cXA9B?~>}U6*`p`RQ9+ELmfJLHahw z(?8R{AQudS8<=zg^lz2qD}8im+_uhWqYUr=fMT#sIo${8zZfe2N&j7)tPfNL^8Z2} z6)v8;x|<$fDzHr5?L0g@AOmYTwm%3~HQmw+c~!W5LEVM>2|z;BF)jd7U&jQ>xPb5h zeEn5a91wogI=6UL`b7g^&v-q5Y#V}Z4=>PWem5wViJ&4Bv3xeU=0-BSSJgLq4+X0GzB+;^$X5GmqzaR*xhkIN?DGhN6_q3Am7=yuN- zb_|MEpaRpI;Cvp9%i(}%s}RtlP5ojEwsLfL7&QhevV-Nsj0eq<1@D5yAlgMl5n&O9 zX|Vqp%RY4oNyRFF7sWu6%!Dt0yWz|+d4`L7CrbsM*o^`YllRPf2_m#~2I3w7AEh+I zzBIIu%uA#2wR>--P{=o&yasGhV$95c?|JRlO>qdUDA33j5IN=@U7M#9+aa>fFb^X45 z?2QBBpdyCETfk(qrO_G9QH{AF(1{Qg6c9(jWVU>`9kPNV#kqZxKsnG@ z%?+|N3y9-DUAf>)sBX#CYB(Ss;o`eS>0TYtk8(ugt>(!)?E#S%6uC82XIZqAYlIHH zMHZAe8xkWHvSk$;54;FuF~4*RSLzf()!C1J`J>iHkKBN2e70b?Xqa3NOvAB(w2*)%usxAitdXR zXsosCjl0P-*iH$V%MrP>2!E3ZHl@yU_+CN1fffNwny;LnWvPf(q;(3vd z)}hwfgz-(OR5H?(nx==K>;(!(<@t9;uhDT<@L}{HO(kEVmC@_oXQ(0S**-;H@pAPM zql=DME;|u{PV`eSkr1cw8-cy+VdH~Tho_^5PQzI5hn0Vy#^@BR|0?|QZJ6^W2bop9*@$1i0N4&+iqmgc&o1yom5?K6W zxbL!%ch!H^B7N{Ew#U$ikDm9zAzzB|J{M9$Mf%ALP$`-!(j_?i*`%M1k~*I7dLkp< z=!h>iQXd~_`k9coWTEF$u+PukkXqb;1zKnw?ZnMCAU$*2j^CZL_F4f6AMEu3*y|O1 zH*on~MrSW(JZQTj(qC~jzsPRd?74SC6t~&Ho{fJ*H*AMvXXx@p@_Al3UkBY^gXE8Bdj+ z^csKuPu+aSU<4<E+ z*bM#6<ud+wQMn*g0ivOoLF2sMG zMX|YA+;yTTVpqi0qIi@1?JkN$!q*sv^Y<6UyZ3E5ufmiwQi z%d*cc_c?mG&n@>~qR-1dx7`0aeM9!S<^Jm^0J+aC`obd`xi4Gp$3(a6bIbj-cuMM7 zii;+o|1H4kBUC4nix*$<2{av@xW8pXsPUVs;6 zJVT3+(1xAt?9Q3@Iqyu)%%8u%egjy8DR6vr^rrerZ%S*Q{Fc6`FJH6}@8{p6nQo%F$e3uUKnOSQ}Q)_}#>H zIS{p_QQ;x^w&N3pj&F1Hkiv+)I9^?SyjnF{bf|wGg%C(Lf+V!)h2xUId=T2E9mcN1L$QF^ z5g2*u_)h#xV5qoL+7?I^OWPS_a6JtT*$mPcAHy(mJmUtoz)Z1zp0^RJebf|pVGWIs zQB0nO8D@fneP+6d6PT}AA2UVLt7UKlb7PprygKtn-5>!^V1XRwIrG!}4+mn=`W zBk<_rS~lAZls_hOj;GnnAs;L$9u zaRbuj_dhXN_<^afP)`ndO!qW}o+exVj;Uj$zv1Tc32vVWmrHP`CoJ`Zxvp@$E4=rv z{Dp%8tK5(97c5fP{T{ZAA#Omvi%lqOVetgT%V6phEDiQ6oM7cL#+QIm<(v8kP)i30 z>q=X}6rk(Ww~ zN);x^iv)>V)F>R%WhPu8Gn7lW${nB1g?2dLWg6t73{<@%o=iq^d`ejx{msu;S`%=Y z2!BRo(WJ^CT4hqAYqXBuA|4G-hEb5yvQw2Bx7zVRpD;RR2ccOu@PhR3faoc zzJIZ5StRhvJT*c`VV6u>2x;0SlCBHsQ7n>YhA$6iQU$Rd`#A*0pf5UAX^2~Qi`Ky%f6RGsoueIc_WKEcM!=sZzkijF|}LFs~GM=v-1aFc3dl?tifz zSiqvXmL+l|5-?ahOL%3?PG<>&D{-(~{sG3$mZG!I^`lqCHWOSn}?5JWosiW?}R7Hz45Z6M; z|I3ZkC#9f+gJwObwvJ7+lKPKs9)HS$N-3eNAWZc~d`TP=sY$X_md=Li)LwW?#|kR6 zy$#RzQ>|l?27Kf`O2bZM(f5 zT<@B@DC9-<3~{+a6@$%* zbtze+^?#(ya}=}LbSblhT0Q6Rm4>3=gi)o*G!B_6$tq*ItV%e0&U6FU!uj0%!h9}S zX6NEZ9}oimg4WPW?76Hk0#QwuQj$)~3QJw+v|eX=>YZgbHMJs34ZXEzFL($9Pw6>L zDO8nGd&N^$GQH4GKq$+GsmsL%*AWQpwp1!JQ-AyUofV|o;~RKj0^!|%nF=P~ai{JL zHLCol`|FQ7a$D7+PR6Mx&`hnhg>;JWrBjTd0T_>aUBJK||PoA}xw zjpy>>3&$74TY?_p_n~D4+YZ_`VA~C};yEAv@pMP)u1z-biGn_klvcL6s zU`UFOa5WKV3&fLwP#~_QGqNI?vZjX9e_Ddmyv`La8Jre}B_kXk=J63Dn>GS%Nl7ty zD3D2o(^4iZ3mZc%E$ibOHj%F0n#U)zib4~{uoPZTL$0P|m2+KIQ#3oub%T7-d~5T@ z=GJh6j|NV-!5BPIEvv`*E?MCW0ZmUuQo58-cw|hMG8wK%_B(RtIFDydO?RP^e__!P zX;g|RlA4P24jtif(}ij>mC-fQG-YluEa|d!vZky=`ljZ$Ff1r&IZhWinz9xVW74RO zYid$XF*J6~9#4m@lhthw1!$|R%I2dC^$n%=%E!^TkD;QWai13pu*d@!Y6y9c-dw2l zpbj-&crkx2s<6ZhH|C13WnOqNe@}d^VDJ{l;le5kl8?)VY1pm@y|@qed$1aQ;y}@) zL?Jvc0$AuFD-SZv*SVC~K`>q0t1Aq34UJs|`lF_(@D?xDV66bu6ClOSK1t`Q>F~QK z56Cm(MI(a3aT7ypQO-6;vTAZ&m6Uwuwr6=LD-tLFL&h0P zIO1GPDmNp0`#UM72-bPfjP(o)4PIiAp{Ai!ThwhM9u`&DL*e7r45@}qS>??T@1^nnVwqpqQ|k{%dq*L zC>flElRbiyesX2Z>T19VbuXQiV{#@+&4oMF+fTiOA{>-6PSIjcOoKFS6iq+l;13qz z9r6xO;T=vS2R}50ccv2#o=Q|h+CAJH)AW%6InA}KX&=!}FH#s5e>yTlWkaW!*oqO6 z8SU{JVB)Hl0v zvZTX1MRnmt>R(Ase@{zh`Mq(VYx=EF{=B@5S3GzLuQCMxe}@eW>)Mz!MD4@r)31AQ z0&md9FQ^oyd75EqanI>gGg*_2aw+Y?TZJByZ%K~Lw>>z6cc`nDyCqzBkH{8`(LOG~ zi!9q#KEQ__ypNCak(H{r@CidzT+zgq{Y+dopW-YvxkPDIf8F?;VQslqQT}{=AzZ6F zxnZyS=YB7*X}^!B6yLBv)PF1Vi?pQN^vOp4KT@~m?Cor>*}GrNCrA8Eop<;|;99Y} zKl%=)R=@D=O1lzz203Idf@c;Io*aod|N(Ldvd&;<#t}{mYn$t?;DCw($YAa`5v;U*>3p2K6PL7 zys(f}dR3lZQ!YEl$O}x4oh@DO@qatRvqM}Vm)_j>J-94ELt=Krd$CtZ8|QKA>}ys5b|I0wKk~(gw@WTg-gz-E z-n{phQ@gf~i|(7xw!Vj%cOG@#m!2tdzIT#XUxY_=#kr=;#50FJdPiKX;<6g%q5bcD(S^wB;}3Jp@7< zZ8SLqRYg^%-#s)lqC8l`qOsgr%x+u3JE@b!)d9qQ{Pr~%n=KFw@&Ec@m*Rq_0JbiJ-FiiY_(H~OychZCO!23^?kxr zsb6t9-n)(!fBU=h#GNC%a*MbEeJ^QR$1+>KO}iv^@kf((?fv)jjy!#k$T;iB`fx9s zvzxcKJl2e6tM1)!{qv34mp6vCtlhS;y6DDUlXXfveK%ZiQ8{u;>;0mt%BNQ^#D=u4 zTW8me!45Xh8a%S}8iHk*; zc34jqTp|rTRNYt_aaJ*KIuAv!@??P}v9jPJZ-M46271&EMPA8~VY0rX2RK?0r?4_G z=%c8Lbe^oZLUeMavnp62{G3T(ETUTH>k3u~IlNU5tQh%hJ`)sE-+Mq6Yk?H9f)CP} zY_Lp}$-xIK5$7WgHUV@9%T1u`HvwI*i(Pa>H^(8RR7~s8;^31S^uMk^xyMjTmQSU{F9Y?c8LA z6*jEkA*0EOD@2*(y1`E9U7;!i9~1$43N=S==mjf!yh29?-XUURV9-M`*{~m^2y+-k vO&Z*)1cp)oP!FoJdnQj@>B$Ny9`3IcWx78NY!UY=EiM6G;6aIVL4^VU&1=uc delta 34727 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�{ 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 a%EQ2*fnt2> Date: Wed, 26 Feb 2025 19:23:49 +0100 Subject: [PATCH 1336/1594] [Java] Bump `Agrona` to 2.1.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 71c8c1c4b2..bfd6ff5d9b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.0.1" +agrona = "2.1.0" checkstyle = "10.21.3" commons-codec = "1.15" commons-lang3 = "3.8.1" From d53dadb9e1568b84a625a6b44f0cebdff793d0e5 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 3 Mar 2025 15:12:19 +0100 Subject: [PATCH 1337/1594] [CI] Do not cancel an existing build for a scheduled run. --- .github/workflows/slow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 4b07b30367..bdbf452a02 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -19,7 +19,7 @@ on: concurrency: group: slow-${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + cancel-in-progress: ${{ github.event_name != 'schedule' }} env: GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail' From 5bf497fd518734bc4de45d28f585c518f3bb2c3c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 6 Mar 2025 16:16:16 +0100 Subject: [PATCH 1338/1594] [Java] Bump Checkstyle to 10.21.4. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bfd6ff5d9b..5976cd2c73 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.1.0" -checkstyle = "10.21.3" +checkstyle = "10.21.4" commons-codec = "1.15" commons-lang3 = "3.8.1" gradle = "8.13" From 45f9ee3aff6e468973811bc23b0214641cf92f10 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 6 Mar 2025 16:16:37 +0100 Subject: [PATCH 1339/1594] [Java] Bump Mockito to 5.16.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5976cd2c73..b9cbe8078a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ jqwik = "1.9.2" jmh = "1.37" json = "20250107" junit = "5.12.0" -mockito = "5.15.2" +mockito = "5.16.0" plexus = "3.3.0" shadow = "8.3.6" versions = "0.52.0" From 6da9841d57159179f07821f00cc94fdea0b24224 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 17 Mar 2025 10:33:50 +0100 Subject: [PATCH 1340/1594] Bump `Mockito` to 5.16.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b9cbe8078a..9a53023b4a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ jqwik = "1.9.2" jmh = "1.37" json = "20250107" junit = "5.12.0" -mockito = "5.16.0" +mockito = "5.16.1" plexus = "3.3.0" shadow = "8.3.6" versions = "0.52.0" From f426ec0ddb2b3b8e65c428bcc29c3c2f088851a7 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 17 Mar 2025 10:34:00 +0100 Subject: [PATCH 1341/1594] Bump `JUnit` to 5.12.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9a53023b4a..fa6ed4f55e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ httpcore = "4.4.14" jqwik = "1.9.2" jmh = "1.37" json = "20250107" -junit = "5.12.0" +junit = "5.12.1" mockito = "5.16.1" plexus = "3.3.0" shadow = "8.3.6" From 048e3876befa8eb834f59eb1d18e615f29ebfda4 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 18 Mar 2025 17:52:15 +0100 Subject: [PATCH 1342/1594] [CI] Enable JDK 24 GA. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5b5bd11367..81867c8a7c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '17', '21', '23' ] + java: [ '17', '21', '24' ] os: [ 'ubuntu-24.04', 'windows-latest', 'macos-latest' ] steps: - name: Checkout code From 47e4914374197d1d5b064b4bf5af74651879eedf Mon Sep 17 00:00:00 2001 From: Grzegorz Gierlach Date: Fri, 21 Mar 2025 12:15:58 +0100 Subject: [PATCH 1343/1594] [Rust] Elide explicit ActingVersion lifetime. (#1053) --- .../sbe/generation/rust/MessageCoderDef.java | 10 ++++---- .../sbe/generation/rust/RustGenerator.java | 25 +++++++++++++------ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index da9060b9a2..e4e19f4c52 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -26,7 +26,7 @@ import static uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType.Encoder; import static uk.co.real_logic.sbe.generation.rust.RustGenerator.CodecType.Decoder; -import static uk.co.real_logic.sbe.generation.rust.RustGenerator.withLifetime; +import static uk.co.real_logic.sbe.generation.rust.RustGenerator.withBufLifetime; import static uk.co.real_logic.sbe.generation.rust.RustUtil.*; class MessageCoderDef implements RustGenerator.ParentDef @@ -165,8 +165,8 @@ void appendMessageStruct(final Appendable out, final String structName) throws I indent(out, 1, "#[derive(Debug, Default)]\n"); } - indent(out, 1, "pub struct %s {\n", withLifetime(structName)); - indent(out, 2, "buf: %s,\n", withLifetime(this.codecType.bufType())); + indent(out, 1, "pub struct %s {\n", withBufLifetime(structName)); + indent(out, 2, "buf: %s,\n", withBufLifetime(this.codecType.bufType())); indent(out, 2, "initial_offset: usize,\n"); indent(out, 2, "offset: usize,\n"); indent(out, 2, "limit: usize,\n"); @@ -184,7 +184,7 @@ void appendWrapFn(final Appendable out) throws IOException { indent(out, 2, "pub fn wrap(\n"); indent(out, 3, "mut self,\n"); - indent(out, 3, "buf: %s,\n", withLifetime(this.codecType.bufType())); + indent(out, 3, "buf: %s,\n", withBufLifetime(this.codecType.bufType())); indent(out, 3, "offset: usize,\n"); indent(out, 3, "acting_block_length: %s,\n", blockLengthType()); indent(out, 3, "acting_version: %s,\n", schemaVersionType()); @@ -194,7 +194,7 @@ void appendWrapFn(final Appendable out) throws IOException else { indent(out, 2, "pub fn wrap(mut self, buf: %s, offset: usize) -> Self {\n", - withLifetime(this.codecType.bufType())); + withBufLifetime(this.codecType.bufType())); indent(out, 3, "let limit = offset + SBE_BLOCK_LENGTH as usize;\n"); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 32f1633178..99aad88b46 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -50,6 +50,7 @@ public class RustGenerator implements CodeGenerator { static final String WRITE_BUF_TYPE = "WriteBuf"; static final String READ_BUF_TYPE = "ReadBuf"; + static final String ANONYMOUS_LIFETIME = "'_"; static final String BUF_LIFETIME = "'a"; enum CodecType @@ -187,9 +188,19 @@ String schemaVersionType() return rustTypeName(ir.headerStructure().schemaVersionType()); } - static String withLifetime(final String typeName) + static String withAnonymousLifetime(final String typeName) { - return format("%s<%s>", typeName, BUF_LIFETIME); + return withLifetime(typeName, ANONYMOUS_LIFETIME); + } + + static String withBufLifetime(final String typeName) + { + return withLifetime(typeName, BUF_LIFETIME); + } + + private static String withLifetime(final String typeName, final String lifetime) + { + return format("%s<%s>", typeName, lifetime); } static void appendImplWithLifetimeHeader( @@ -1243,14 +1254,14 @@ static void appendImplEncoderTrait( final Appendable out, final String typeName) throws IOException { - indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withLifetime("Writer"), withLifetime(typeName)); + indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withBufLifetime("Writer"), withBufLifetime(typeName)); indent(out, 2, "#[inline]\n"); indent(out, 2, "fn get_buf_mut(&mut self) -> &mut WriteBuf<'a> {\n"); indent(out, 3, "&mut self.buf\n"); indent(out, 2, "}\n"); indent(out, 1, "}\n\n"); - indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withLifetime("Encoder"), withLifetime(typeName)); + indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withBufLifetime("Encoder"), withBufLifetime(typeName)); indent(out, 2, "#[inline]\n"); indent(out, 2, "fn get_limit(&self) -> usize {\n"); indent(out, 3, "self.limit\n"); @@ -1268,21 +1279,21 @@ static void appendImplDecoderTrait( final Appendable out, final String typeName) throws IOException { - indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, "ActingVersion", withLifetime(typeName)); + indent(out, 1, "impl %s for %s {\n", "ActingVersion", withAnonymousLifetime(typeName)); indent(out, 2, "#[inline]\n"); indent(out, 2, "fn acting_version(&self) -> %s {\n", schemaVersionType); indent(out, 3, "self.acting_version\n"); indent(out, 2, "}\n"); indent(out, 1, "}\n\n"); - indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withLifetime("Reader"), withLifetime(typeName)); + indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withBufLifetime("Reader"), withBufLifetime(typeName)); indent(out, 2, "#[inline]\n"); indent(out, 2, "fn get_buf(&self) -> &ReadBuf<'a> {\n"); indent(out, 3, "&self.buf\n"); indent(out, 2, "}\n"); indent(out, 1, "}\n\n"); - indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withLifetime("Decoder"), withLifetime(typeName)); + indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withBufLifetime("Decoder"), withBufLifetime(typeName)); indent(out, 2, "#[inline]\n"); indent(out, 2, "fn get_limit(&self) -> usize {\n"); indent(out, 3, "self.limit\n"); From bdb32557229fa6cd15a13e92cd3d3810481c2d13 Mon Sep 17 00:00:00 2001 From: marc-adaptive Date: Sun, 6 Apr 2025 12:25:14 -0400 Subject: [PATCH 1344/1594] [Java] Adjust Java DTO Choice Set Access (#1064) --- .../real_logic/sbe/generation/java/JavaDtoGenerator.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java index 4d8b3d334c..caf393ef19 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -1771,7 +1771,7 @@ private void generateChoices( fields.add(fieldName); classBuilder.appendField() - .append(indent).append("boolean ").append(fieldName).append(";\n"); + .append(indent).append("private boolean ").append(fieldName).append(";\n"); classBuilder.appendPublic() .append("\n") @@ -1782,7 +1782,7 @@ private void generateChoices( classBuilder.appendPublic() .append("\n") - .append(indent).append(dtoClassName).append(" ") + .append(indent).append("public ").append(dtoClassName).append(" ") .append(formattedPropertyName).append("(boolean value)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("this.").append(fieldName).append(" = value;\n") @@ -1792,7 +1792,8 @@ private void generateChoices( } final StringBuilder clearBuilder = classBuilder.appendPublic() - .append(indent).append(dtoClassName).append(" clear()\n") + .append("\n") + .append(indent).append("public ").append(dtoClassName).append(" clear()\n") .append(indent).append("{\n"); for (final String field : fields) From 2a1ee77d792081e0aabb79107aabc1a7ef70161b Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 7 Apr 2025 14:48:45 +0200 Subject: [PATCH 1345/1594] Bump `Mockito` to 5.17.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fa6ed4f55e..8a7341c0a2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ jqwik = "1.9.2" jmh = "1.37" json = "20250107" junit = "5.12.1" -mockito = "5.16.1" +mockito = "5.17.0" plexus = "3.3.0" shadow = "8.3.6" versions = "0.52.0" From 14d28c5d1347d6a2e182ab8735dc4c9ef62c2f6e Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 7 Apr 2025 14:49:35 +0200 Subject: [PATCH 1346/1594] Bump `Checkstyle` to 10.23.0. --- config/checkstyle/checkstyle.xml | 2 +- gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index abb1fc1efe..b97f363689 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -43,7 +43,7 @@ - + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8a7341c0a2..2464c43cc6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.1.0" -checkstyle = "10.21.4" +checkstyle = "10.23.0" commons-codec = "1.15" commons-lang3 = "3.8.1" gradle = "8.13" From d5ba0f6cc3fb761a29cc0b1710aa74734663473e Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 7 Apr 2025 15:01:46 +0200 Subject: [PATCH 1347/1594] Checkstyle fixes. --- .../java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java | 1 + .../java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java | 1 + .../main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java | 1 + .../java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 1 + .../main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java | 1 + 5 files changed, 5 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index 0fd31feed6..cfba4755e5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -163,6 +163,7 @@ static String generateDocumentation(final String indent, final Token token) indent + "/// \n"; } + @SuppressWarnings("JavadocVariable") enum Separators { BEGIN_GROUP('['), diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 5f28c17a90..3b6e988750 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -49,6 +49,7 @@ public class JavaGenerator implements CodeGenerator static final String MESSAGE_HEADER_ENCODER_TYPE = "MessageHeaderEncoder"; static final String MESSAGE_HEADER_DECODER_TYPE = "MessageHeaderDecoder"; + @SuppressWarnings("JavadocVariable") enum CodecType { DECODER, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index 2290e7f468..e8e6808c01 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -39,6 +39,7 @@ public class JavaUtil /** * Separator symbols for {@link Object#toString()} implementations on codecs. */ + @SuppressWarnings("JavadocVariable") enum Separator { BEGIN_GROUP('['), diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 99aad88b46..16f6e40cb8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -53,6 +53,7 @@ public class RustGenerator implements CodeGenerator static final String ANONYMOUS_LIFETIME = "'_"; static final String BUF_LIFETIME = "'a"; + @SuppressWarnings("JavadocVariable") enum CodecType { Decoder diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index a38bea7a7a..836bab1a7b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -301,6 +301,7 @@ static Appendable indent(final Appendable appendable, final int level, final Str return indent(appendable, level).append(format(f, args)); } + @SuppressWarnings("JavadocVariable") enum ReservedKeyword { Abstract, AlignOf, As, Async, Become, Box, Break, Const, Continue, From 05612b41a2c01c3a0e11d89b39a432a8216233f7 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 9 Apr 2025 14:18:51 +0200 Subject: [PATCH 1348/1594] [CI] Use `gradle/actions/setup-gradle` action for caching Gradle dependencies. --- .github/workflows/ci.yml | 187 ++++++++++++---------------------- .github/workflows/codeql.yml | 78 +++++++------- .github/workflows/release.yml | 7 ++ .github/workflows/slow.yml | 4 +- 4 files changed, 118 insertions(+), 158 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81867c8a7c..81b8ea1546 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,18 +39,6 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v4 - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Setup java uses: actions/setup-java@v4 with: @@ -68,11 +56,13 @@ jobs: java -Xinternalversion echo "BUILD_JAVA_HOME=$env:JAVA_HOME" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append echo "BUILD_JAVA_VERSION=${{ matrix.java }}" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - - name: Setup java + - name: Setup java to run Gradle uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Build with Gradle run: ./gradlew - name: Copy test logs @@ -104,23 +94,18 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v4 - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Setup java to run Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Cache NuGet dependencies uses: actions/cache@v4 with: @@ -155,18 +140,6 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v4 - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ bionic main universe" @@ -176,6 +149,13 @@ jobs: with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Build run: ./cppbuild/cppbuild @@ -195,18 +175,6 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v4 - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test @@ -217,6 +185,13 @@ jobs: with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Build run: ./cppbuild/cppbuild @@ -236,18 +211,6 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v4 - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | sudo mkdir -p /etc/apt/keyrings/ @@ -260,6 +223,13 @@ jobs: with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Build run: ./cppbuild/cppbuild @@ -279,18 +249,6 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v4 - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Install compiler run: | sudo mkdir -p /etc/apt/keyrings/ @@ -303,6 +261,13 @@ jobs: with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Build run: ./cppbuild/cppbuild @@ -322,23 +287,18 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v4 - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Setup java to run Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Build run: cmake --version && ./cppbuild/cppbuild @@ -358,23 +318,18 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v4 - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Setup java to run Gradle script uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=$env:JAVA_HOME" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Build run: cppbuild/cppbuild.cmd @@ -391,18 +346,6 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v4 - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Rust setup uses: dtolnay/rust-toolchain@stable with: @@ -412,6 +355,13 @@ jobs: with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - run: ./gradlew runRustTests golang-build: @@ -427,18 +377,6 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v4 - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} - name: Setup Go uses: actions/setup-go@v4 with: @@ -448,6 +386,13 @@ jobs: with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Generate jar run: ./gradlew assemble - name: Run tests diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 5942820cc6..b072c655ad 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -17,6 +17,7 @@ concurrency: env: GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.warning.mode=fail' JAVA_TOOL_OPTIONS: "--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED" + JAVA_VERSION: '17' permissions: contents: read @@ -41,24 +42,22 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v4 - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + - name: Setup java uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ matrix.java }} + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: @@ -93,18 +92,7 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v4 - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + - name: Cache NuGet dependencies uses: actions/cache@v4 with: @@ -112,6 +100,22 @@ jobs: key: ${{ runner.os }}-nuget-${{ hashFiles('csharp/**/*.sln') }} restore-keys: | ${{ runner.os }}-nuget- + + - name: Setup java + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: ${{ env.JAVA_VERSION }} + + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + - name: Setup dotnet uses: actions/setup-dotnet@v4 with: @@ -151,18 +155,22 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.sha }} - - name: Cache Gradle dependencies - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache Gradle wrappers - uses: actions/cache@v4 + + - name: Setup java + uses: actions/setup-java@v4 with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + distribution: 'zulu' + java-version: ${{ env.JAVA_VERSION }} + + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + - name: Install compiler run: | sudo apt-get install -y g++-${{ matrix.version }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index db5f85bba4..7d843cc7f7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -49,6 +49,13 @@ jobs: with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} + - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION + run: | + java -Xinternalversion + echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV + echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Publish with Gradle run: ./gradlew publish env: diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index bdbf452a02..feb48c79c8 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -3,8 +3,6 @@ name: Slow checks on: workflow_call: workflow_dispatch: - branches: - - '**' schedule: - cron: '0 12 * * *' push: @@ -58,6 +56,8 @@ jobs: with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Setup dotnet uses: actions/setup-dotnet@v2 with: From 72efb6852c21f185b31f96cf72cc80a296449895 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 14 Apr 2025 10:19:50 +0200 Subject: [PATCH 1349/1594] [Java] Bump `JUnit` to 5.12.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2464c43cc6..d8f5ab2680 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ httpcore = "4.4.14" jqwik = "1.9.2" jmh = "1.37" json = "20250107" -junit = "5.12.1" +junit = "5.12.2" mockito = "5.17.0" plexus = "3.3.0" shadow = "8.3.6" From 0f0e58d38f7649f9be5d18ab40df5945896208c3 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 28 Apr 2025 11:27:19 +0200 Subject: [PATCH 1350/1594] [Java] Bump `Gradle` to 8.14. --- build.gradle | 1 - gradle/libs.versions.toml | 1 - gradle/wrapper/gradle-wrapper.jar | Bin 43705 -> 43764 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 4 ++-- gradlew.bat | 4 ++-- 6 files changed, 5 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index b0ac62184a..6859b87b5a 100644 --- a/build.gradle +++ b/build.gradle @@ -1115,7 +1115,6 @@ tasks.named('dependencyUpdates').configure { } wrapper { - gradleVersion = libs.versions.gradle.get() distributionType = 'ALL' } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d8f5ab2680..07a4d2d9dc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,6 @@ agrona = "2.1.0" checkstyle = "10.23.0" commons-codec = "1.15" commons-lang3 = "3.8.1" -gradle = "8.13" hamcrest = "3.0" httpcore = "4.4.14" jqwik = "1.9.2" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 9bbc975c742b298b441bfb90dbc124400a3751b9..1b33c55baabb587c669f562ae36f953de2481846 100644 GIT binary patch delta 642 zcmdmamFde>rVZJA^}0Q$xegf!xPEW^+5YDM%iT2bEgct9o+jH~+sJas#HZ=szO|** z=Pj=X_vx?W&DSwKck|WWn~hffsvnQ+42*W$b7b0$SCcOoZ`{W{^$^pk;4>8-A*-)$ z?n(Po`1$6Jn_u?t-L+tsPyZ2#X}8T6OS8pAU;kdgd+_Hw4z4TW0p9E!T+=f7-c&O% zFic^X{7^$?^Ho04eona9n#mGMxKhA=~8B%JN`M zMhm5wc-2v)$``sY$!Q`9xiU@DhI73ZxiGEKg>yIPs)NmWwMdF-ngLXpZSqV5ez36n zVkxF2rjrjWR+_xr6e6@_u@s~2uv{9vi*1pj2)BjFD+-%@&pRVP1f{O1glxTOp2-62Ph;v z`N1+vCd)9ea)af*Ol1*JCfnp$%Uu}%OuoN7g2}3C@`L5FlP#(sA=|h@iixuZC?qp^ z=L$=v$ZoI}|87Wh=&h7udff{aieKr*l+zDp?pf)_bbRvUf>kn;HCDMXNlgbbo!QRK I1x7am0No)LiU0rr delta 584 zcmexzm1*ZyrVZJAexH5Moc8h7)w{^+t*dqJ%=yhh23L$9JpFV=_k`zJ-?Q4DI*eSe z+ES)HSrVnWLtJ&)lO%hRkV9zl5qqWRt0e;bb zPPo`)y?HTAyZI&u&X<|2$FDHCf4;!v8}p=?Tm`^F0`u(|1ttf~&t$qP3KUSD>@TJQ zRwJ}Pim6NzEc8KA6)e;S6gs8=7IIL8sQL*MYEuRYO;Uj<%3UbMbV&^&!Zvx+LKmjT z8Zch6rYP7Tw?$Hn(UTJwWiS=$f{lB(C=e*%usDV})0AQIK~sat=ND@+Gg*Pyij!rR z*fa02W|%BsV++>4W{DKDGSIUEHd2$P+8ct!RF+CHDowUuTEZOZ%rJSQv*qOXOSPDN zT|sP-$p*_3ncsWB*qoD7JQcyZ9xan%cJP6Tb4-?AZpr*F6v98hoNaPJm@HV`yya5N z))6pqFXn@}P(3T0nEzM8*c_9KtE9o|_pFd&K35GBXP^9Kg(b6GH-z8S4GDzIl~T+b zdLd#meKKHu$5u))8cu$=GKINkGDPOUD)!0$C(BH(U!}!-e;Q0ok8Sc?V1zRO04>ts AA^-pY diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ed4c299adb..6514f919fd 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index faf93008b7..23d15a9367 100755 --- a/gradlew +++ b/gradlew @@ -114,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a21834..db3a6ac207 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell From 43d1253ec661cf76e9c9f646f461b10287a421f3 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 28 Apr 2025 11:29:29 +0200 Subject: [PATCH 1351/1594] [Java] Bump `Checkstyle` to 10.23.1. --- build.gradle | 4 ++-- gradle/libs.versions.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 6859b87b5a..b3770aec71 100644 --- a/build.gradle +++ b/build.gradle @@ -172,6 +172,8 @@ subprojects { group = sbeGroup version = sbeVersion + checkstyle.toolVersion = libs.versions.checkstyle.get() + java { toolchain { languageVersion = JavaLanguageVersion.of(buildJavaVersion) @@ -179,8 +181,6 @@ subprojects { sourceCompatibility = JavaVersion.VERSION_17 } - checkstyle.toolVersion = libs.versions.checkstyle.get() - tasks.withType(Sign).configureEach { onlyIf { isReleaseVersion && gradle.taskGraph.hasTask(tasks.publish) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 07a4d2d9dc..3396ceb3b5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.1.0" -checkstyle = "10.23.0" +checkstyle = "10.23.1" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From 2f8d61e8dd4417ecbbd1bba6f4fd653e774d1f8f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 28 Apr 2025 11:49:55 +0200 Subject: [PATCH 1352/1594] [CI] Remove Ubuntu 20.04 based builds as Github no longer supports that image. --- .github/workflows/ci.yml | 73 ---------------------------------------- 1 file changed, 73 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81b8ea1546..b874215b04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -124,41 +124,6 @@ jobs: - name: Pack run: ./csharp/pack.sh - cpp-gcc-2004-build: - name: C++ GCC ${{ matrix.version }} (Ubuntu 20.04) - runs-on: ubuntu-20.04 - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - version: [ '6', '7', '8', '9', '10' ] - env: - CC: gcc-${{ matrix.version }} - CXX: g++-${{ matrix.version }} - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ github.sha }} - - name: Install compiler - run: | - sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ bionic main universe" - sudo apt-get install -y g++-${{ matrix.version }} libsparsehash-dev libidn11 - - name: Setup java to run Gradle script - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: ${{ env.JAVA_VERSION }} - - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION - run: | - java -Xinternalversion - echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV - echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - - name: Build - run: ./cppbuild/cppbuild - cpp-gcc-2404-build: name: C++ GCC ${{ matrix.version }} (Ubuntu 24.04) runs-on: ubuntu-24.04 @@ -195,44 +160,6 @@ jobs: - name: Build run: ./cppbuild/cppbuild - cpp-clang-2004-build: - name: C++ Clang ${{ matrix.version }} (Ubuntu 20.04) - runs-on: ubuntu-20.04 - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - version: [ '9', '10', '11', '12' ] - env: - CC: clang-${{ matrix.version }} - CXX: clang++-${{ matrix.version }} - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ github.sha }} - - name: Install compiler - run: | - sudo mkdir -p /etc/apt/keyrings/ - curl https://apt.llvm.org/llvm-snapshot.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/llvm-snapshot.gpg - echo "deb [signed-by=/etc/apt/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/focal/ llvm-toolchain-focal-${{ matrix.version }} main" | sudo tee /etc/apt/sources.list.d/llvm.list - sudo apt-get update - sudo apt-get install -y clang-${{ matrix.version }} libsparsehash-dev libidn11 - - name: Setup java to run Gradle script - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: ${{ env.JAVA_VERSION }} - - name: Setup BUILD_JAVA_HOME & BUILD_JAVA_VERSION - run: | - java -Xinternalversion - echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV - echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - - name: Build - run: ./cppbuild/cppbuild - cpp-clang-2404-build: name: C++ Clang ${{ matrix.version }} (Ubuntu 24.04) runs-on: ubuntu-24.04 From e04e61b0ae2b4a32615cae67d761356e075b9d8d Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 28 Apr 2025 11:52:56 +0200 Subject: [PATCH 1353/1594] [CI] Add GCC 15 and Clang 19,20 to the build matrix. --- .github/workflows/ci.yml | 4 ++-- .github/workflows/codeql.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b874215b04..98feaa457d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,7 +131,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '11', '12', '13', '14' ] + version: [ '11', '12', '13', '14', '15' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} @@ -167,7 +167,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '13', '14', '15', '16', '17', '18' ] + version: [ '13', '14', '15', '16', '17', '18', '19', '20' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b072c655ad..4cdfa3e3aa 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -146,7 +146,7 @@ jobs: fail-fast: false matrix: language: ['cpp'] - version: [ '14' ] + version: [ '15' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} From 4c29cf7ad7a26dfa09a643ebf44fa707da448e72 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 28 Apr 2025 12:04:53 +0200 Subject: [PATCH 1354/1594] [CI] Remove GCC 15 as it is not yet available. --- .github/workflows/ci.yml | 2 +- .github/workflows/codeql.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98feaa457d..a9dc9e1f9f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,7 +131,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '11', '12', '13', '14', '15' ] + version: [ '11', '12', '13', '14' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 4cdfa3e3aa..b072c655ad 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -146,7 +146,7 @@ jobs: fail-fast: false matrix: language: ['cpp'] - version: [ '15' ] + version: [ '14' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} From 9383d2429a95c579c814a396df9f2f9753d7b587 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 28 Apr 2025 12:10:03 +0200 Subject: [PATCH 1355/1594] [CI] Bump Go build to use 1.23.x and 1.24.x. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9dc9e1f9f..34d0d20396 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -298,7 +298,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '1.22.x' ] + version: [ '1.23.x', '1.24.x' ] steps: - name: Checkout code uses: actions/checkout@v4 From aab60b04801726ebaea8653e33d4815065f9f81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rcio=20Andrade?= Date: Tue, 29 Apr 2025 06:43:26 -0300 Subject: [PATCH 1356/1594] [Rust] get proper version for composite types. (#1058) Co-authored-by: marcio.andrade --- build.gradle | 1 + rust/Cargo.toml | 1 + .../sbe/generation/rust/RustGenerator.java | 4 ++- sbe-tool/src/test/resources/issue1057.xml | 32 +++++++++++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 sbe-tool/src/test/resources/issue1057.xml diff --git a/build.gradle b/build.gradle index b3770aec71..8ae1c82751 100644 --- a/build.gradle +++ b/build.gradle @@ -672,6 +672,7 @@ tasks.register('generateRustTestCodecs', JavaExec) { 'sbe-tool/src/test/resources/issue984.xml', 'sbe-tool/src/test/resources/issue987.xml', 'sbe-tool/src/test/resources/issue1028.xml', + 'sbe-tool/src/test/resources/issue1057.xml', 'sbe-tool/src/test/resources/fixed-sized-primitive-array-types.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', 'sbe-tool/src/test/resources/nested-composite-name.xml', diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 2d4f3d4a49..e09cacf21c 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -17,6 +17,7 @@ issue_972 = { path = "../generated/rust/issue972" } issue_984 = { path = "../generated/rust/issue984" } issue_987 = { path = "../generated/rust/issue987" } issue_1028 = { path = "../generated/rust/issue1028" } +issue_1057 = { path = "../generated/rust/issue1057" } baseline_bigendian = { path = "../generated/rust/baseline-bigendian" } nested_composite_name = { path = "../generated/rust/nested-composite-name" } fixed_sized_primitive_array = { path = "../generated/rust/fixed_sized_primitive_array" } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 16f6e40cb8..10d0219b33 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1686,7 +1686,9 @@ private static void generateCompositeDecoder( indent(out, 2, "offset: usize,\n"); indent(out, 1, "}\n\n"); - final int version = tokens.get(1).version(); // skip BEGIN_COMPOSITE + // The version of the composite type is the greatest version of its fields. + final int version = tokens.stream().mapToInt(Token::version).max().orElse(0); + appendImplReaderForComposite(schemaVersionType, version, out, 1, decoderName); // impl<'a, P> start diff --git a/sbe-tool/src/test/resources/issue1057.xml b/sbe-tool/src/test/resources/issue1057.xml new file mode 100644 index 0000000000..8e89fcfade --- /dev/null +++ b/sbe-tool/src/test/resources/issue1057.xml @@ -0,0 +1,32 @@ + + + + 0 + + + + + + + + + + + + + + + + + + \ No newline at end of file From e0512f42b24627961250f69eee9f8ed91800eb99 Mon Sep 17 00:00:00 2001 From: Pierre Irrmann Date: Tue, 29 Apr 2025 11:46:51 +0200 Subject: [PATCH 1357/1594] [C#] Read NuGet package version from version file (#1061) Co-authored-by: pierre-irrmann --- csharp/sbe-dll/sbe-dll.csproj | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/csharp/sbe-dll/sbe-dll.csproj b/csharp/sbe-dll/sbe-dll.csproj index 6db6d56021..e4245e5c1b 100644 --- a/csharp/sbe-dll/sbe-dll.csproj +++ b/csharp/sbe-dll/sbe-dll.csproj @@ -13,7 +13,8 @@ https://github.com/aeron-io/simple-binary-encoding SBE;Marshaling;Low;Latency;Simple;Binary;Encoding sbe-tool - 1.23.1.1 + $(MSBuildProjectDirectory)\..\..\version.txt + $([System.IO.File]::ReadAllText($(VersionFile)).TrimEnd()) Simple Binary Encoding for .NET This package contains all you need to define SBE messages and generate C# encoders and decoders. See https://github.com/aeron-io/simple-binary-encoding for more detailed instructions git @@ -31,7 +32,7 @@ true tools/sbe-tool.sh - + true tools/sbe-tool-all.jar From a79ed83d12002550cd56fce0a58e3b85a14c1313 Mon Sep 17 00:00:00 2001 From: pierre-irrmann Date: Fri, 21 Mar 2025 11:17:47 +0100 Subject: [PATCH 1358/1594] [C#] Enable dual build for netstandard2.0 & netstandard2.1 --- csharp/sbe-dll/sbe-dll.csproj | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/csharp/sbe-dll/sbe-dll.csproj b/csharp/sbe-dll/sbe-dll.csproj index e4245e5c1b..ac9e4a8414 100644 --- a/csharp/sbe-dll/sbe-dll.csproj +++ b/csharp/sbe-dll/sbe-dll.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.0;netstandard2.1 True SBE Org.SbeTool.Sbe.Dll @@ -38,9 +38,13 @@ - - - - + + + + + + + + From 2ab62bdbb7e0033fa5d7ec6e407cb32a6cfeacd5 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 21 May 2025 15:16:58 +0200 Subject: [PATCH 1359/1594] [Java] Bump `Mockito` to 5.18.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3396ceb3b5..2376329a1c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ jqwik = "1.9.2" jmh = "1.37" json = "20250107" junit = "5.12.2" -mockito = "5.17.0" +mockito = "5.18.0" plexus = "3.3.0" shadow = "8.3.6" versions = "0.52.0" From 7b1c1524d75652921d38322c099087ff26670548 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 21 May 2025 15:17:21 +0200 Subject: [PATCH 1360/1594] [Java] Bump `Json` to 20250517. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2376329a1c..48b4f4a594 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ hamcrest = "3.0" httpcore = "4.4.14" jqwik = "1.9.2" jmh = "1.37" -json = "20250107" +json = "20250517" junit = "5.12.2" mockito = "5.18.0" plexus = "3.3.0" From 08fadc099868e5b8725704c771080a2b7420a7d0 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 26 May 2025 11:52:34 +0200 Subject: [PATCH 1361/1594] [Java] Bump `Gradle` to 8.14.1. --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6514f919fd..6925085be8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 99cc8c1954402f962407252a5f0f7d7020831239 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 26 May 2025 11:53:02 +0200 Subject: [PATCH 1362/1594] [Java] Bump `Checkstyle` to 10.24.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 48b4f4a594..30ebe716c7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.1.0" -checkstyle = "10.23.1" +checkstyle = "10.24.0" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From 5ee5e5894af127fe5f4cab07b28cd91ee9c5965e Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 26 May 2025 14:29:27 +0200 Subject: [PATCH 1363/1594] [Doc] Add `CHANGELOG.md`. --- CHANGELOG.md | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..c2e8b2fe38 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,74 @@ +# Changelog + +## [1.35.0] - 2025-05-26 +### Changed +* Update `Implementation-Vendor`. +* **Rust:** Elide explicit ActingVersion lifetime. ([#1053](https://github.com/aeron-io/simple-binary-encoding/pull/1053)) +* **CI:** Use `gradle/actions/setup-gradle` action for caching Gradle dependencies. +* **CI:** Enable JDK 24 GA build. +* **CI:** Simplify error log upload. +* **CI:** Remove Ubuntu 20.04 based builds. +* **CI:** Bump Go build to use 1.23.x and 1.24.x. +* Bump `Agrona` to 2.2.0. +* Bump `Gradle` to 8.14.1. +* Bump `Checkstyle` to 10.24.0. +* Bump `json` to 20250517. +* Bump `JUnit` to 5.12.2. +* Bump `Mockito` to 5.18.0. +* Bump `Shadow` to 8.3.6. +* Bump `Versions` to 0.52. + +### Fixed +* **Java:** include field 'deprecated' in ir encoding and decoding. +* **Java:** Adjust Java DTO Choice Set Access. ([#1064](https://github.com/aeron-io/simple-binary-encoding/issues/1064)) +* **Rust:** get proper version for composite types. ([#1058](https://github.com/aeron-io/simple-binary-encoding/pull/1058)) +* **C#:** Read NuGet package version from version file ([#1061](https://github.com/aeron-io/simple-binary-encoding/pull/1061)) +* **C#:** Enable dual build for netstandard2.0 & netstandard2.1. ([#1062](https://github.com/aeron-io/simple-binary-encoding/pull/1062)) + +## [1.34.1] - 2025-01-13 +### Changed +* Bump `json` to 20250107. +* Bump `Mockito` to 5.15.2. + +### Added +* **Doc:** Add `--add-opens java.base/jdk.internal.misc=ALL-UNNAMED` to the example execution. +* **Rust:** encoding primitive arrays now supports slice instead of array (issue [#1021](https://github.com/aeron-io/simple-binary-encoding/issues/)). ([#1040](https://github.com/aeron-io/simple-binary-encoding/pull/1040)) + +### Fixed +* **C++:** check for not wrapped state in `decodeLength()` when precedence checks are enabled. ([#1046](https://github.com/aeron-io/simple-binary-encoding/pull/1046)) +* **C++:** use `m_actingBlockLength` in `decodeLength()`. ([#1045](https://github.com/aeron-io/simple-binary-encoding/pull/1045)) + +## [1.34.0] - 2024-12-17 +### Changed +* **C++:** hide the m_codecStatePtr behind ifdefs to avoid overhead when precedence checking is disabled. ([#1036](https://github.com/aeron-io/simple-binary-encoding/pull/1036)) +* **C++:** use constexpr to define precedence checks lookup tables. +* **Rust:** Enhance enum supporting fromstr and display and into. ([#1020](https://github.com/aeron-io/simple-binary-encoding/pull/1020)) +* **Rust:** codegen of primitive enums now implement 'From' instead of 'Into'. ([#1029](https://github.com/aeron-io/simple-binary-encoding/pull/1029)) +* **Java:** Update Checkstyle rules and apply them. +* **Breaking:** Bump `Agrona` to 2.0.0. + _**Note:** `--add-opens java.base/jdk.internal.misc=ALL-UNNAMED` JVM option must be specified in order to generate codecs or use the generated Java classes. For example:_ + ```shell + $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-${SBE_TOOL_VERSION}.jar my-sbe-messages.xml + ``` +* Bump `Gradle` to 8.11.1. +* Bump `Checkstyle` to 10.21.0. +* Bump `ByteBuddy` to 1.15.11. +* Bump `JUnit` to 5.11.4. +* Bump `jqwik` to 1.9.2. + +### Added +* **C++:** Integrate std::span support for flyweight API. ([#1038](https://github.com/aeron-io/simple-binary-encoding/pull/1038), [#1027](https://github.com/aeron-io/simple-binary-encoding/pull/1027)) +* **Rust:** generate message schema level info in lib.rs. ([#1019](https://github.com/aeron-io/simple-binary-encoding/pull/1019)) + +### Fixed +* **C++:** Fix field precedence check issue [#1031](https://github.com/aeron-io/simple-binary-encoding/issues/1031). ([#1033](https://github.com/aeron-io/simple-binary-encoding/pull/1033)) +* **C++:** respect the package override option for C++ codecs and DTOs. ([#1024](https://github.com/aeron-io/simple-binary-encoding/pull/1024)) +* **C#:** respect the package override option for C# codecs and DTOs. ([#1024](https://github.com/aeron-io/simple-binary-encoding/pull/1024)) +* **Go:** Fix warning about used args in GolangFlyweightGenerator. +* **Rust:** Updated code generator to resolve Issue [#1028](https://github.com/aeron-io/simple-binary-encoding/issues/1028). ([#1037](https://github.com/aeron-io/simple-binary-encoding/pull/1037)) +* **Java:** Prevent collision when field name is 'value'. +* **Java:** Preserve byte order throughout IR transformations. + +[1.35.0]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.0 +[1.34.1]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.34.1 +[1.34.0]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.34.0 From 52f3d6f6b7ef1857c156855453e45b054511d1f9 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 26 May 2025 16:35:39 +0200 Subject: [PATCH 1364/1594] [Java] Bump `Agrona` to 2.2.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 30ebe716c7..20d5d5940a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.1.0" +agrona = "2.2.0" checkstyle = "10.24.0" commons-codec = "1.15" commons-lang3 = "3.8.1" From 29dc5cec8c30135fe19b4121be9d5f5f6ad1ad05 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 26 May 2025 16:36:55 +0200 Subject: [PATCH 1365/1594] 1.35.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index c9c35c012f..a2d87226ac 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.35.0-SNAPSHOT +1.35.0 \ No newline at end of file From 3ebb42547fc3b5565e65067eae932f8cb32a3ad6 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 26 May 2025 16:37:12 +0200 Subject: [PATCH 1366/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index a2d87226ac..aa69911fd7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.35.0 \ No newline at end of file +1.36.0-SNAPSHOT From ff702747e65c687ac3c194e459447efbc3f5e1f6 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 31 May 2025 00:13:09 +0100 Subject: [PATCH 1367/1594] [Java] Bump `JUnit` to 5.13.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 20d5d5940a..b83f161ba6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ httpcore = "4.4.14" jqwik = "1.9.2" jmh = "1.37" json = "20250517" -junit = "5.12.2" +junit = "5.13.0" mockito = "5.18.0" plexus = "3.3.0" shadow = "8.3.6" From 06833056565de381630621adfe6c1339cb2f62fa Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 2 Jun 2025 13:04:48 +0200 Subject: [PATCH 1368/1594] [Java] Bump `Agrona` to 2.2.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b83f161ba6..b472f9f71e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.2.0" +agrona = "2.2.1" checkstyle = "10.24.0" commons-codec = "1.15" commons-lang3 = "3.8.1" From 2541e9e9b7d372a424a4f4e6a3d72125a00a30d4 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 2 Jun 2025 13:04:58 +0200 Subject: [PATCH 1369/1594] [Doc] Add release notes. --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2e8b2fe38..2ea5b58113 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [1.35.1] - 2025-06-02 +### Changed +* Bump `Agrona` to 2.2.1. +* Bump `JUnit` to 5.13.0. + ## [1.35.0] - 2025-05-26 ### Changed * Update `Implementation-Vendor`. @@ -69,6 +74,7 @@ * **Java:** Prevent collision when field name is 'value'. * **Java:** Preserve byte order throughout IR transformations. +[1.35.1]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.1 [1.35.0]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.0 [1.34.1]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.34.1 [1.34.0]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.34.0 From 708e93ce335fbda97342e3633f77c8a698dc59fb Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 2 Jun 2025 13:05:15 +0200 Subject: [PATCH 1370/1594] 1.35.1 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index aa69911fd7..7eee785743 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.36.0-SNAPSHOT +1.35.1 From 5df8522d348bf46dfe8c5b0345f7263721736a38 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 2 Jun 2025 13:05:25 +0200 Subject: [PATCH 1371/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 7eee785743..aa69911fd7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.35.1 +1.36.0-SNAPSHOT From 95c8fd165905caf5f7ae637fa0cb94bc42b1b6d2 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 4 Jun 2025 17:38:34 +0200 Subject: [PATCH 1372/1594] [Java] Bump `Checkstyle` to 1.25.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b472f9f71e..ed61fb694f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.2.1" -checkstyle = "10.24.0" +checkstyle = "10.25.0" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From cf4ee3ef4ea273cc61865675ec216a0f0e755bac Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 6 Jun 2025 14:38:45 +0200 Subject: [PATCH 1373/1594] [Java] Bump `Gradle` 8.14.2. --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6925085be8..be2dc79a8a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From e926d3a6b4fde927087a1aa2f6d57dec1642562c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 6 Jun 2025 14:39:20 +0200 Subject: [PATCH 1374/1594] [Java] Bump `Agrona` to 2.2.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ed61fb694f..4a08456869 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.2.1" +agrona = "2.2.2" checkstyle = "10.25.0" commons-codec = "1.15" commons-lang3 = "3.8.1" From 3c9ee092b9fcd9b6058979e20af9bb8db169be14 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 6 Jun 2025 14:55:25 +0200 Subject: [PATCH 1375/1594] [Java] Publish artifacts to Central Portal using OSSRH Staging API. --- .github/workflows/release.yml | 10 +- .gitignore | 10 +- CHANGELOG.md | 7 + build.gradle | 61 +++-- buildSrc/build.gradle | 19 ++ buildSrc/settings.gradle | 7 + ...typeCentralPortalUploadRepositoryTask.java | 228 ++++++++++++++++++ 7 files changed, 308 insertions(+), 34 deletions(-) create mode 100644 buildSrc/build.gradle create mode 100644 buildSrc/settings.gradle create mode 100644 buildSrc/src/main/java/uk/co/real_logic/sbe/build/SonatypeCentralPortalUploadRepositoryTask.java diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7d843cc7f7..c38dd27632 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -57,9 +57,9 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 - name: Publish with Gradle - run: ./gradlew publish + run: ./gradlew publish uploadArtifactsToCentralPortal env: - ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.SONATYPE_CENTRAL_USERNAME }} - ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.SONATYPE_CENTRAL_PASSWORD }} - ORG_GRADLE_PROJECT_signingKey: ${{ secrets.GPG_RSA_SIGN_KEY }} - ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.GPG_RSA_SIGN_KEYPASS }} + SIGNING_GPG_SECRET_KEY: ${{ secrets.GPG_RSA_SIGN_KEY }} + SIGNING_GPG_PASSWORD: ${{ secrets.GPG_RSA_SIGN_KEYPASS }} + SONATYPE_CENTRAL_PORTAL_USERNAME: ${{ secrets.SONATYPE_CENTRAL_PORTAL_USERNAME }} + SONATYPE_CENTRAL_PORTAL_PASSWORD: ${{ secrets.SONATYPE_CENTRAL_PORTAL_PASSWORD }} diff --git a/.gitignore b/.gitignore index fd7d72201b..c34ba580f9 100644 --- a/.gitignore +++ b/.gitignore @@ -19,14 +19,16 @@ build-local.properties deps */bin -build -.gradle -target +build/ +!buildSrc/ +!buildSrc/src/**/build +.gradle/ +target/ GTAGS GRTAGS GPATH prop -out +out/ .vs/ .vscode diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ea5b58113..d0470654a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [1.35.2] - 2025-06-06 +### Changed +* Publish release artifacts to Central Portal using OSSRH Staging API service. +* Bump `Agrona` to 2.2.2. +* Bump `Checkstyle` to 10.25.0. + ## [1.35.1] - 2025-06-02 ### Changed * Bump `Agrona` to 2.2.1. @@ -74,6 +80,7 @@ * **Java:** Prevent collision when field name is 'value'. * **Java:** Preserve byte order throughout IR transformations. +[1.35.2]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.2 [1.35.1]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.1 [1.35.0]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.0 [1.34.1]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.34.1 diff --git a/build.gradle b/build.gradle index 8ae1c82751..030c4adec8 100644 --- a/build.gradle +++ b/build.gradle @@ -53,26 +53,30 @@ def toolchainLauncher = javaToolchains.launcherFor { def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() -ext { - isReleaseVersion = !sbeVersion.endsWith('-SNAPSHOT') - releasesRepoUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' - snapshotsRepoUrl = 'https://oss.sonatype.org/content/repositories/snapshots/' - - if (!project.hasProperty('ossrhUsername')) { - ossrhUsername = '' +def getConfigProperty(final String projectPropertyName, final String envVarName) { + String value = project.findProperty(projectPropertyName) + if (!value) { + value = System.getenv(envVarName) + if (!value) { + return null + } } - if (!project.hasProperty('ossrhPassword')) { - ossrhPassword = '' - } + value = value.trim() - if (!project.hasProperty('signingKey')) { - signingKey = null - } + return value ? value : null +} - if (!project.hasProperty('signingPassword')) { - signingPassword = null - } +ext { + isReleaseVersion = !sbeVersion.endsWith('-SNAPSHOT') + + sonatypeCentralPortalReleasesRepoUrl = 'https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/' + sonatypeCentralPortalSnapshotsRepoUrl = 'https://central.sonatype.com/repository/maven-snapshots/' + sonatypeCentralPortalUsername = getConfigProperty('sonatypeCentralPortalUsername', 'SONATYPE_CENTRAL_PORTAL_USERNAME') + sonatypeCentralPortalPassword = getConfigProperty('sonatypeCentralPortalPassword', 'SONATYPE_CENTRAL_PORTAL_PASSWORD') + + signingKey = getConfigProperty('signingKey', 'SIGNING_GPG_SECRET_KEY') // NOTE: ASCII armored secret key + signingPassword = getConfigProperty('signingPassword', 'SIGNING_GPG_PASSWORD') // NOTE: Plain text } def projectPom = { @@ -389,10 +393,10 @@ project(':sbe-tool') { repositories { maven { - url = !isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl + url = !isReleaseVersion ? sonatypeCentralPortalSnapshotsRepoUrl : sonatypeCentralPortalReleasesRepoUrl credentials { - username = ossrhUsername - password = ossrhPassword + username = sonatypeCentralPortalUsername + password = sonatypeCentralPortalPassword } } } @@ -459,10 +463,10 @@ project(':sbe-all') { } repositories { maven { - url = !isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl + url = !isReleaseVersion ? sonatypeCentralPortalSnapshotsRepoUrl : sonatypeCentralPortalReleasesRepoUrl credentials { - username = ossrhUsername - password = ossrhPassword + username = sonatypeCentralPortalUsername + password = sonatypeCentralPortalPassword } } } @@ -579,10 +583,10 @@ project(':sbe-samples') { repositories { maven { - url = !isReleaseVersion ? snapshotsRepoUrl : releasesRepoUrl + url = !isReleaseVersion ? sonatypeCentralPortalSnapshotsRepoUrl : sonatypeCentralPortalReleasesRepoUrl credentials { - username = ossrhUsername - password = ossrhPassword + username = sonatypeCentralPortalUsername + password = sonatypeCentralPortalPassword } } } @@ -1115,6 +1119,13 @@ tasks.named('dependencyUpdates').configure { } } +tasks.register('uploadArtifactsToCentralPortal', uk.co.real_logic.sbe.build.SonatypeCentralPortalUploadRepositoryTask) { + portalUsername.set(sonatypeCentralPortalUsername) + portalPassword.set(sonatypeCentralPortalPassword) + groupId.set(aeronGroup) + snapshotRelease.set(!isReleaseVersion) +} + wrapper { distributionType = 'ALL' } diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle new file mode 100644 index 0000000000..a4f559284d --- /dev/null +++ b/buildSrc/build.gradle @@ -0,0 +1,19 @@ +repositories { + mavenCentral() +} + +configurations.configureEach { + resolutionStrategy { + failOnVersionConflict() + } +} + +dependencies { + implementation libs.json +} + +tasks.withType(JavaCompile).configureEach { + configure(options) { + options.compilerArgs << '-Xlint:deprecation' << '-Xlint:unchecked' // examples + } +} diff --git a/buildSrc/settings.gradle b/buildSrc/settings.gradle new file mode 100644 index 0000000000..b5a0fabf66 --- /dev/null +++ b/buildSrc/settings.gradle @@ -0,0 +1,7 @@ +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} diff --git a/buildSrc/src/main/java/uk/co/real_logic/sbe/build/SonatypeCentralPortalUploadRepositoryTask.java b/buildSrc/src/main/java/uk/co/real_logic/sbe/build/SonatypeCentralPortalUploadRepositoryTask.java new file mode 100644 index 0000000000..ba806c5ec0 --- /dev/null +++ b/buildSrc/src/main/java/uk/co/real_logic/sbe/build/SonatypeCentralPortalUploadRepositoryTask.java @@ -0,0 +1,228 @@ +/* + * Copyright 2014-2025 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.build; + +import org.gradle.api.DefaultTask; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.TaskAction; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodySubscribers; +import java.net.http.HttpResponse.ResponseInfo; +import java.time.Duration; +import java.util.Base64; + +import static java.nio.charset.StandardCharsets.US_ASCII; + +/** + * This task performs manual steps to publish artifacts to Central Portal via OSSRH Staging API. + */ +public class SonatypeCentralPortalUploadRepositoryTask extends DefaultTask +{ + private static final String CENTRAL_PORTAL_OSSRH_API_URI = "https://ossrh-staging-api.central.sonatype.com"; + private static final Duration CONNECTION_TIMEOUT = Duration.ofSeconds(30); + + private final Property portalUsername; + private final Property portalPassword; + private final Property groupId; + private final Property snapshotRelease; + + /** + * Create new task instance. + */ + public SonatypeCentralPortalUploadRepositoryTask() + { + portalUsername = getProject().getObjects().property(String.class); + portalPassword = getProject().getObjects().property(String.class); + groupId = getProject().getObjects().property(String.class); + snapshotRelease = getProject().getObjects().property(Boolean.class); + } + + /** + * Return property to set Central Portal username. + * + * @return Central Portal username. + */ + @Input + public Property getPortalUsername() + { + return portalUsername; + } + + /** + * Return property to set Central Portal password. + * + * @return Central Portal password. + */ + @Input + public Property getPortalPassword() + { + return portalPassword; + } + + /** + * Return property to set {@code groupId} of the project. + * + * @return {@code groupId} of the project. + */ + @Input + public Property getGroupId() + { + return groupId; + } + + /** + * Return property to set snapshot release. + * + * @return {@code true} if snapshot release. + */ + @Input + public Property getSnapshotRelease() + { + return snapshotRelease; + } + + /** + * Publish staging repository to the Central Portal. + */ + @TaskAction + public void run() throws IOException, InterruptedException + { + if (!portalUsername.isPresent()) + { + return; // release is not configured + } + + if (snapshotRelease.get()) + { + return; // snapshots are published directly + } + + final HttpClient httpClient = HttpClient.newBuilder() + .connectTimeout(CONNECTION_TIMEOUT) + .build(); + + final String userNameAndPassword = portalUsername.get() + ":" + portalPassword.get(); + final String bearer = new String( + Base64.getEncoder().encode(userNameAndPassword.getBytes(US_ASCII)), US_ASCII); + + final HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() + .header("Authorization", "Bearer " + bearer); + + final URI apiUri = URI.create(CENTRAL_PORTAL_OSSRH_API_URI); + + final String repositoryKey = findOpenRepository(apiUri, httpClient, requestBuilder); + uploadRepositoryToPortal(apiUri, httpClient, requestBuilder, repositoryKey); + dropRepository(apiUri, httpClient, requestBuilder, repositoryKey); + } + + private String findOpenRepository( + final URI apiUri, + final HttpClient httpClient, + final HttpRequest.Builder requestBuilder) throws IOException, InterruptedException + { + final HttpRequest request = requestBuilder + .copy() + .GET() + .uri(apiUri.resolve("/manual/search/repositories?ip=client")) + .build(); + final HttpResponse response = httpClient.send( + request, (ResponseInfo responseInfo) -> BodySubscribers.ofString(US_ASCII)); + + if (200 != response.statusCode()) + { + throw new IllegalStateException("Failed to query repositories: " + + "status=" + response.statusCode() + ", response=" + response.body()); + } + + final JSONArray repositories = new JSONObject(response.body()).getJSONArray("repositories"); + if (repositories.isEmpty()) + { + throw new IllegalStateException("No open repositories found!"); + } + + String repositoryKey = null; + final String group = groupId.get(); + for (int i = 0; i < repositories.length(); i++) + { + final JSONObject repo = (JSONObject)repositories.get(i); + if ("open".equals(repo.getString("state"))) + { + final String key = repo.getString("key"); + if (key.contains(group)) + { + repositoryKey = key; + break; + } + } + } + + if (null == repositoryKey) + { + throw new IllegalStateException("No open repositories found!"); + } + return repositoryKey; + } + + private static void uploadRepositoryToPortal( + final URI apiUri, + final HttpClient httpClient, + final HttpRequest.Builder requestBuilder, + final String repositoryKey) throws IOException, InterruptedException + { + final HttpRequest request = requestBuilder + .copy() + .POST(HttpRequest.BodyPublishers.noBody()) + .uri(apiUri.resolve("/manual/upload/repository/" + repositoryKey + "?publishing_type=automatic")) + .build(); + final HttpResponse response = httpClient.send( + request, (ResponseInfo responseInfo) -> BodySubscribers.ofString(US_ASCII)); + + if (200 != response.statusCode()) + { + throw new IllegalStateException("Failed to upload repository: repository_key=" + repositoryKey + + ", status=" + response.statusCode() + ", response=" + response.body()); + } + } + + private static void dropRepository( + final URI apiUri, + final HttpClient httpClient, + final HttpRequest.Builder requestBuilder, + final String repositoryKey) throws IOException, InterruptedException + { + final HttpRequest request = requestBuilder + .copy() + .DELETE() + .uri(apiUri.resolve("/manual/drop/repository/" + repositoryKey)) + .build(); + final HttpResponse response = httpClient.send( + request, (ResponseInfo responseInfo) -> BodySubscribers.ofString(US_ASCII)); + + if (204 != response.statusCode()) + { + throw new IllegalStateException("Failed to drop repository: repository_key=" + repositoryKey + + ", status=" + response.statusCode() + ", response=" + response.body()); + } + } +} From 0b6f008c766c40d63cc65db7fe6e1fc74e3254e7 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 6 Jun 2025 14:55:46 +0200 Subject: [PATCH 1376/1594] 1.35.2 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index aa69911fd7..0035f2a76b 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.36.0-SNAPSHOT +1.35.2 From 0ab9fff7e2abdefe7112d261bf648105016adcda Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 6 Jun 2025 14:55:58 +0200 Subject: [PATCH 1377/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 0035f2a76b..aa69911fd7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.35.2 +1.36.0-SNAPSHOT From 605a031cef332773b08463953b8a4c275cf76d6e Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 6 Jun 2025 14:57:19 +0200 Subject: [PATCH 1378/1594] Update doc. --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0470654a6..8c0028add3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,10 @@ ## [1.35.2] - 2025-06-06 ### Changed -* Publish release artifacts to Central Portal using OSSRH Staging API service. -* Bump `Agrona` to 2.2.2. -* Bump `Checkstyle` to 10.25.0. +* **Java:** Publish release artifacts to Central Portal using OSSRH Staging API service. +* **Java:** Bump `Agrona` to 2.2.2. +* **Java:** Bump `Checkstyle` to 10.25.0. +* **Java:** Bump `Gradle` to 8.14.2. ## [1.35.1] - 2025-06-02 ### Changed From 4a2e3cd11028262acc862b5553411270ab48ca18 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 6 Jun 2025 15:33:40 +0200 Subject: [PATCH 1379/1594] [Java] Task invocation bug. --- CHANGELOG.md | 4 ++-- build.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c0028add3..da8120cb18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [1.35.2] - 2025-06-06 +## [1.35.3] - 2025-06-06 ### Changed * **Java:** Publish release artifacts to Central Portal using OSSRH Staging API service. * **Java:** Bump `Agrona` to 2.2.2. @@ -81,7 +81,7 @@ * **Java:** Prevent collision when field name is 'value'. * **Java:** Preserve byte order throughout IR transformations. -[1.35.2]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.2 +[1.35.3]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.3 [1.35.1]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.1 [1.35.0]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.0 [1.34.1]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.34.1 diff --git a/build.gradle b/build.gradle index 030c4adec8..a6f9f542b0 100644 --- a/build.gradle +++ b/build.gradle @@ -1122,7 +1122,7 @@ tasks.named('dependencyUpdates').configure { tasks.register('uploadArtifactsToCentralPortal', uk.co.real_logic.sbe.build.SonatypeCentralPortalUploadRepositoryTask) { portalUsername.set(sonatypeCentralPortalUsername) portalPassword.set(sonatypeCentralPortalPassword) - groupId.set(aeronGroup) + groupId.set(sbeGroup) snapshotRelease.set(!isReleaseVersion) } From 37254bf99c132a38ecf5c7047ad1fd3f1a81c39d Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 6 Jun 2025 15:34:57 +0200 Subject: [PATCH 1380/1594] 1.35.3 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index aa69911fd7..0c4fe1942d 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.36.0-SNAPSHOT +1.35.3 From 45ff07209827da348766b0f287da8f22cada7ab2 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 6 Jun 2025 15:35:07 +0200 Subject: [PATCH 1381/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 0c4fe1942d..aa69911fd7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.35.3 +1.36.0-SNAPSHOT From f64751b358fab3dacba82d0ee8ed887542554ba9 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 7 Jun 2025 15:39:50 +0200 Subject: [PATCH 1382/1594] [Java] Bump `JUnit` to 5.13.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4a08456869..5a9fdb63d1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ httpcore = "4.4.14" jqwik = "1.9.2" jmh = "1.37" json = "20250517" -junit = "5.13.0" +junit = "5.13.1" mockito = "5.18.0" plexus = "3.3.0" shadow = "8.3.6" From 4e89da2f4c6806fcf0489c1068b96009b06291e2 Mon Sep 17 00:00:00 2001 From: marc-adaptive Date: Mon, 9 Jun 2025 23:24:48 -0400 Subject: [PATCH 1383/1594] [Java] Adjust Java Dto generateComputeEncodedLength to acount for character encoding (#1072) --- .../sbe/generation/java/JavaDtoGenerator.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java index caf393ef19..65d7bbf6a8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -371,14 +371,20 @@ private void generateComputeEncodedLength( .append(formatPropertyName(propertyName)).append("HeaderLength();\n"); final String characterEncoding = varDataToken.encoding().characterEncoding(); - final String lengthAccessor = characterEncoding == null ? ".length" : ".length()"; - lengthBuilder.append(indent).append(INDENT).append("encodedLength += ") - .append("this.").append(fieldName).append(lengthAccessor); + lengthBuilder.append(indent).append(INDENT).append("encodedLength += "); - final int elementByteLength = varDataToken.encoding().primitiveType().size(); - if (elementByteLength != 1) + if (characterEncoding == null) + { + lengthBuilder.append("this.").append(fieldName).append(".length"); + } + else if (JavaUtil.isAsciiEncoding(characterEncoding)) + { + lengthBuilder.append("this.").append(fieldName).append(".length()"); + } + else { - lengthBuilder.append(" * ").append(elementByteLength); + lengthBuilder.append("this.").append(fieldName) + .append(".getBytes(").append(JavaUtil.charset(characterEncoding)).append(").length"); } lengthBuilder.append(";\n\n"); From 1a656cebf40b00b38a745bbb5fe039df453029d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rcio=20Andrade?= Date: Wed, 11 Jun 2025 07:38:40 -0300 Subject: [PATCH 1384/1594] Return None for optional primite field if its version is less than actingVersion. (#1067) * Fix optional primitive decoder. * Add tests. * Update issue number. --------- Co-authored-by: marcio.andrade Co-authored-by: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> --- build.gradle | 1 + rust/Cargo.toml | 1 + rust/tests/issue_1066_test.rs | 40 +++++++++++++++++++ .../sbe/generation/rust/RustGenerator.java | 7 ++++ sbe-tool/src/test/resources/issue1066.xml | 18 +++++++++ 5 files changed, 67 insertions(+) create mode 100644 rust/tests/issue_1066_test.rs create mode 100644 sbe-tool/src/test/resources/issue1066.xml diff --git a/build.gradle b/build.gradle index a6f9f542b0..b349fe2528 100644 --- a/build.gradle +++ b/build.gradle @@ -677,6 +677,7 @@ tasks.register('generateRustTestCodecs', JavaExec) { 'sbe-tool/src/test/resources/issue987.xml', 'sbe-tool/src/test/resources/issue1028.xml', 'sbe-tool/src/test/resources/issue1057.xml', + 'sbe-tool/src/test/resources/issue1066.xml', 'sbe-tool/src/test/resources/fixed-sized-primitive-array-types.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', 'sbe-tool/src/test/resources/nested-composite-name.xml', diff --git a/rust/Cargo.toml b/rust/Cargo.toml index e09cacf21c..b48fd6ee55 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -18,6 +18,7 @@ issue_984 = { path = "../generated/rust/issue984" } issue_987 = { path = "../generated/rust/issue987" } issue_1028 = { path = "../generated/rust/issue1028" } issue_1057 = { path = "../generated/rust/issue1057" } +issue_1066 = { path = "../generated/rust/issue1066" } baseline_bigendian = { path = "../generated/rust/baseline-bigendian" } nested_composite_name = { path = "../generated/rust/nested-composite-name" } fixed_sized_primitive_array = { path = "../generated/rust/fixed_sized_primitive_array" } diff --git a/rust/tests/issue_1066_test.rs b/rust/tests/issue_1066_test.rs new file mode 100644 index 0000000000..43f7278ebf --- /dev/null +++ b/rust/tests/issue_1066_test.rs @@ -0,0 +1,40 @@ +use issue_1066::{ + issue_1066_codec, + issue_1066_codec::{Issue1066Decoder, Issue1066Encoder}, + *, +}; + +#[test] +fn decode_optional_primitive_field() { + let mut buffer = vec![0u8; 256]; + + // Create a message with `field` set. + let mut encoder = Issue1066Encoder::default().wrap( + WriteBuf::new(&mut buffer), + message_header_codec::ENCODED_LENGTH, + ); + encoder.field(10); + + // Drop encoder to drop the mut reference for the buffer. + drop(encoder); + + // Create a decoder for the message, but stating that the version is 1, instead of 2 + // which is the acting version for `field`. Thus, `field()` must return `None`. + let decoder = Issue1066Decoder::default().wrap( + ReadBuf::new(&mut buffer), + message_header_codec::ENCODED_LENGTH, + issue_1066_codec::SBE_BLOCK_LENGTH, + 1, + ); + assert!(decoder.field().is_none()); + + // Create a decoder for the message, but stating that the version is 1, instead of 2 + // which is the acting version for `field`. Thus, `field()` must return `None`. + let decoder = Issue1066Decoder::default().wrap( + ReadBuf::new(&mut buffer), + message_header_codec::ENCODED_LENGTH, + issue_1066_codec::SBE_BLOCK_LENGTH, + 2, + ); + assert_eq!(decoder.field(), Some(10)); +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 10d0219b33..746f18d022 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -894,6 +894,13 @@ private static void generatePrimitiveOptionalDecoder( formatFunctionName(name), rustPrimitiveType); + if (fieldToken.version() > 0) + { + indent(sb, level + 1, "if self.acting_version() < %d {\n", fieldToken.version()); + indent(sb, level + 2, "return None;\n"); + indent(sb, level + 1, "}\n\n"); + } + indent(sb, level + 1, "let value = self.get_buf().get_%s_at(self.%s);\n", rustPrimitiveType, getBufOffset(fieldToken)); diff --git a/sbe-tool/src/test/resources/issue1066.xml b/sbe-tool/src/test/resources/issue1066.xml new file mode 100644 index 0000000000..a24e45b030 --- /dev/null +++ b/sbe-tool/src/test/resources/issue1066.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + \ No newline at end of file From 777170acde4c2743ebb4641875746441df340fe3 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 11 Jun 2025 14:42:02 +0200 Subject: [PATCH 1385/1594] [CI] Use `macos-15`. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34d0d20396..8d7129e13a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: fail-fast: false matrix: java: [ '17', '21', '24' ] - os: [ 'ubuntu-24.04', 'windows-latest', 'macos-latest' ] + os: [ 'ubuntu-24.04', 'windows-latest', 'macos-15' ] steps: - name: Checkout code uses: actions/checkout@v4 @@ -205,7 +205,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ 'macos-latest' ] + os: [ 'macos-15' ] env: CC: clang CXX: clang++ From cdbc3ec5ef73a6a02d8892dd90767d17b22fbc4d Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 12 Jun 2025 12:57:17 +0200 Subject: [PATCH 1386/1594] [Java] Bump `jqwik` to 1.9.3. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5a9fdb63d1..710f76675a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" httpcore = "4.4.14" -jqwik = "1.9.2" +jqwik = "1.9.3" jmh = "1.37" json = "20250517" junit = "5.13.1" From c11c331e492d9f5d62da4499124efd240555bde4 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 12 Jun 2025 12:58:53 +0200 Subject: [PATCH 1387/1594] [Doc] Release notes. --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da8120cb18..b4e3935a1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.35.4] - 2025-06-12 +### Changed +* **Rust:** Return None for optional primite field if its version is less than actingVersion. ([#1067](https://github.com/aeron-io/simple-binary-encoding/pull/1067)) +* **Java:** Adjust Java Dto generateComputeEncodedLength to acount for character encoding. ([#1072](https://github.com/aeron-io/simple-binary-encoding/pull/1072)) +* **Java:** Bump `JUnit` to 5.13.1. +* **Java:** Bump `jqwik` to 1.9.3. + ## [1.35.3] - 2025-06-06 ### Changed * **Java:** Publish release artifacts to Central Portal using OSSRH Staging API service. @@ -81,6 +88,7 @@ * **Java:** Prevent collision when field name is 'value'. * **Java:** Preserve byte order throughout IR transformations. +[1.35.4]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.4 [1.35.3]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.3 [1.35.1]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.1 [1.35.0]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.0 From f43b14d75732cb0089bf7abb1273f1cbd201bef7 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 12 Jun 2025 12:59:17 +0200 Subject: [PATCH 1388/1594] 1.35.4 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index aa69911fd7..f508d5bf03 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.36.0-SNAPSHOT +1.35.4 From 13f9636fe2b5a63e8c28a0cb367d0f4da6f6a70c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 12 Jun 2025 12:59:34 +0200 Subject: [PATCH 1389/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index f508d5bf03..aa69911fd7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.35.4 +1.36.0-SNAPSHOT From 092c1af104c850e1d17ef77b4edc3b3d91ad5475 Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Fri, 20 Jun 2025 10:42:40 +0100 Subject: [PATCH 1390/1594] [Java/C++/C#] Fix a bug in overzealous DTO validation (#1073) * [Java] Cover null values in PBTs. We had a recent bug report where the generated Java DTOs were not correctly handling null values for optional fields. It turns out the property-based tests were not encoding these values. Now, they do, and they fail with messages like this one: ``` java.lang.IllegalArgumentException: member1: value is out of allowed range: 255 at uk.co.real_logic.sbe.properties.TestMessageDto.validateMember1(TestMessageDto.java:33) at uk.co.real_logic.sbe.properties.TestMessageDto.member1(TestMessageDto.java:55) at uk.co.real_logic.sbe.properties.TestMessageDto.decodeWith(TestMessageDto.java:112) at uk.co.real_logic.sbe.properties.TestMessageDto.decodeFrom(TestMessageDto.java:135) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at uk.co.real_logic.sbe.properties.DtosPropertyTest.javaDtoEncodeShouldBeTheInverseOfDtoDecode(DtosPropertyTest.java:114) at java.base/java.lang.reflect.Method.invoke(Method.java:568) ``` * [Java] Support arbitrary char arrays in PBTs without data after null. I spotted a failure in the DTO round-trip test locally where the DTO's (and flyweight codec's) String-typed accessor would return `""` if the first character in an array was the `null` character. Therefore, it would not round-trip the "hidden bytes" after the `null`. In this commit, I've added a generation mode that disables the generation of strings with this format. Given the representation of char[N] in DTOs it would not be sensible to support round-tripping these "hidden bytes". * [Java,C++,C#] Improve DTO value validation. Previously, in Java, the generated validation methods would not permit the null value, even for fields with optional presence. Now, we do allow these correctly. In this commit, I've also attempted to clean up, centralise, and test the logic that decides when validation for a particular side of a range needs to be included. We omit the validation when the native type cannot represent values outside of the range. There are still some gaps around validation, e.g., we do not validate array values. * [Java] Fix JSON escaping of string characters, delimeters, etc. Previously, there were several problems: - (delimeters) single `char` values were output with single quotes, but this is not valid JSON. - (escaping) escaping was not implemented as per the specification in Section 7 of RFC 8259. For example, special-cased control codes, e.g., `\b` were encoded as `\\` followed by `\b` rather than `\\` followed by `b`. Also, the non-special-cased control characters were not encoded using JSON's mechanism for doing so, e.g., `\u0020`. - (numbers) Section 6 of the specification says "Numeric values that cannot be represented in the grammar below (such as Infinity and NaN) are not permitted." However, these were encoded as expressions of numbers with multiple terms, e.g., `-1/0` for positive infinity. While these are quite logical encodings of such "numbers", it is not valid JSON. Therefore, I have kept the expressions, but enclosed them within quotes. Also, in this commit: - Replaced custom compilation logic with Agrona's CompilerUtil. Note that `CompilerUtil#compileOnDisk` is broken. I attempted to use it to see if I could see classes in IntelliJ rather than just stack frames, but it fails with an NPE. --- .../generation/common/DtoValidationUtil.java | 224 +++++++++++++++ .../sbe/generation/cpp/CppDtoGenerator.java | 10 +- .../generation/csharp/CSharpDtoGenerator.java | 11 +- .../sbe/generation/java/JavaDtoGenerator.java | 168 ++++++++--- .../sbe/json/JsonTokenListener.java | 30 +- .../java/uk/co/real_logic/sbe/otf/Types.java | 105 ++++++- .../sbe/properties/DtosPropertyTest.java | 133 +++++---- .../sbe/properties/JsonPropertyTest.java | 18 +- .../sbe/properties/PropertyTestUtil.java | 43 +++ .../arbitraries/SbeArbitraries.java | 263 +++++++++++++++--- .../schema/TestXmlSchemaWriter.java | 16 +- .../utils/InMemoryOutputManager.java | 132 ++------- .../common/DtoValidationUtilTest.java | 105 +++++++ 13 files changed, 959 insertions(+), 299 deletions(-) create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/DtoValidationUtil.java create mode 100644 sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/PropertyTestUtil.java create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/common/DtoValidationUtilTest.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/DtoValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/DtoValidationUtil.java new file mode 100644 index 0000000000..1e522c232b --- /dev/null +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/DtoValidationUtil.java @@ -0,0 +1,224 @@ +/* + * Copyright 2013-2025 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.common; + +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.PrimitiveValue; +import uk.co.real_logic.sbe.ir.Encoding; +import uk.co.real_logic.sbe.ir.Token; + +/** + * Helpers for generating value validation code. + */ +public final class DtoValidationUtil +{ + private DtoValidationUtil() + { + } + + /** + * What support the target language has for native integer types. + */ + public enum NativeIntegerSupport + { + /** + * The target language supports both signed and unsigned integers natively and the generated code uses + * these to represent the SBE types. + */ + SIGNED_AND_UNSIGNED, + + /** + * The target language only supports signed integers natively and the generated code uses the next biggest + * signed integer type to represent the unsigned SBE types, except for UINT64 which is always represented + * as a signed long. + */ + SIGNED_ONLY + } + + /** + * Checks if the native type can represent values less than the valid range of the SBE type. + * + * @param fieldToken the field token to check if it is optional. + * @param encoding the encoding of the field to check the applicable minimum and null values. + * @param integerSupport the support for native integer types in the target language. + * @return true if the native type can represent values less than the valid range of the SBE type, + * false otherwise. + */ + public static boolean nativeTypeRepresentsValuesLessThanValidRange( + final Token fieldToken, + final Encoding encoding, + final NativeIntegerSupport integerSupport) + { + final PrimitiveType primitiveType = encoding.primitiveType(); + final PrimitiveValue minValue = encoding.applicableMinValue(); + + switch (minValue.representation()) + { + case LONG: + final long nativeMinValue = nativeTypeMinValue(primitiveType, integerSupport); + final PrimitiveValue nullValue = encoding.applicableNullValue(); + final boolean gapBefore = minValue.longValue() > nativeMinValue; + final boolean nullFillsGap = fieldToken.isOptionalEncoding() && + nullValue.longValue() == nativeMinValue && + minValue.longValue() == nativeMinValue + 1L; + return gapBefore && !nullFillsGap; + + case DOUBLE: + switch (primitiveType) + { + case FLOAT: + return minValue.doubleValue() > -Float.MAX_VALUE; + case DOUBLE: + return minValue.doubleValue() > -Double.MAX_VALUE; + default: + throw new IllegalArgumentException( + "Type did not have a double representation: " + primitiveType); + } + + default: + throw new IllegalArgumentException( + "Cannot understand the range of a type with representation: " + minValue.representation()); + } + } + + /** + * Checks if the native type can represent values greater than the valid range of the SBE type. + * + * @param fieldToken the field token to check if it is optional. + * @param encoding the encoding of the field to check the applicable maximum and null values. + * @param integerSupport the support for native integer types in the target language. + * @return true if the native type can represent values greater than the valid range of the SBE type, + * false otherwise. + */ + public static boolean nativeTypeRepresentsValuesGreaterThanValidRange( + final Token fieldToken, + final Encoding encoding, + final NativeIntegerSupport integerSupport) + { + final PrimitiveType primitiveType = encoding.primitiveType(); + final PrimitiveValue maxValue = encoding.applicableMaxValue(); + + switch (maxValue.representation()) + { + case LONG: + final long nativeMaxValue = nativeTypeMaxValue(primitiveType, integerSupport); + final PrimitiveValue nullValue = encoding.applicableNullValue(); + final boolean gapAfter = maxValue.longValue() < nativeMaxValue; + final boolean nullFillsGap = fieldToken.isOptionalEncoding() && + nullValue.longValue() == nativeMaxValue && + maxValue.longValue() + 1L == nativeMaxValue; + return gapAfter && !nullFillsGap; + + case DOUBLE: + switch (primitiveType) + { + case FLOAT: + return maxValue.doubleValue() < Float.MAX_VALUE; + case DOUBLE: + return maxValue.doubleValue() < Double.MAX_VALUE; + default: + throw new IllegalArgumentException( + "Type did not have a double representation: " + primitiveType); + } + + default: + throw new IllegalArgumentException( + "Cannot understand the range of a type with representation: " + maxValue.representation()); + } + } + + private static long nativeTypeMinValue( + final PrimitiveType primitiveType, + final NativeIntegerSupport integerSupport) + { + switch (primitiveType) + { + case CHAR: + return Character.MIN_VALUE; + case INT8: + return Byte.MIN_VALUE; + case INT16: + return Short.MIN_VALUE; + case INT32: + return Integer.MIN_VALUE; + case INT64: + return Long.MIN_VALUE; + case UINT8: + if (integerSupport == NativeIntegerSupport.SIGNED_ONLY) + { + return Short.MIN_VALUE; + } + return 0L; + case UINT16: + if (integerSupport == NativeIntegerSupport.SIGNED_ONLY) + { + return Integer.MIN_VALUE; + } + return 0L; + case UINT32: + if (integerSupport == NativeIntegerSupport.SIGNED_ONLY) + { + return Long.MIN_VALUE; + } + return 0L; + case UINT64: + return 0L; + default: + throw new IllegalArgumentException("Type did not have a long representation: " + primitiveType); + } + } + + private static long nativeTypeMaxValue( + final PrimitiveType primitiveType, + final NativeIntegerSupport integerSupport) + { + switch (primitiveType) + { + case CHAR: + return Character.MAX_VALUE; + case INT8: + return Byte.MAX_VALUE; + case INT16: + return Short.MAX_VALUE; + case INT32: + return Integer.MAX_VALUE; + case INT64: + return Long.MAX_VALUE; + case UINT8: + if (integerSupport == NativeIntegerSupport.SIGNED_ONLY) + { + return Short.MAX_VALUE; + } + return 0xFFL; + case UINT16: + if (integerSupport == NativeIntegerSupport.SIGNED_ONLY) + { + return Integer.MAX_VALUE; + } + return 0xFFFFL; + case UINT32: + if (integerSupport == NativeIntegerSupport.SIGNED_ONLY) + { + return Long.MAX_VALUE; + } + return 0xFFFFFFFFL; + case UINT64: + return 0xFFFFFFFFFFFFFFFFL; + default: + throw new IllegalArgumentException("Type did not have a long representation: " + primitiveType); + } + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index 05d214d751..baf01b639e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -35,6 +35,9 @@ import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; +import static uk.co.real_logic.sbe.generation.common.DtoValidationUtil.NativeIntegerSupport.SIGNED_AND_UNSIGNED; +import static uk.co.real_logic.sbe.generation.common.DtoValidationUtil.nativeTypeRepresentsValuesGreaterThanValidRange; +import static uk.co.real_logic.sbe.generation.common.DtoValidationUtil.nativeTypeRepresentsValuesLessThanValidRange; import static uk.co.real_logic.sbe.generation.cpp.CppUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; @@ -1591,8 +1594,11 @@ private static void generateSingleValuePropertyValidateMethod( String value = "value"; - final boolean mustPreventLesser = !encoding.applicableMinValue().equals(encoding.primitiveType().minValue()); - final boolean mustPreventGreater = !encoding.applicableMaxValue().equals(encoding.primitiveType().maxValue()); + final boolean mustPreventLesser = + nativeTypeRepresentsValuesLessThanValidRange(fieldToken, encoding, SIGNED_AND_UNSIGNED); + + final boolean mustPreventGreater = + nativeTypeRepresentsValuesGreaterThanValidRange(fieldToken, encoding, SIGNED_AND_UNSIGNED); if (fieldToken.isOptionalEncoding()) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java index 47bef5a349..ed55bae37b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -35,6 +35,9 @@ import java.util.Set; import java.util.function.Predicate; +import static uk.co.real_logic.sbe.generation.common.DtoValidationUtil.NativeIntegerSupport.SIGNED_AND_UNSIGNED; +import static uk.co.real_logic.sbe.generation.common.DtoValidationUtil.nativeTypeRepresentsValuesGreaterThanValidRange; +import static uk.co.real_logic.sbe.generation.common.DtoValidationUtil.nativeTypeRepresentsValuesLessThanValidRange; import static uk.co.real_logic.sbe.generation.csharp.CSharpUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; @@ -1285,7 +1288,9 @@ private void generateSingleValueProperty( .append("}\n"); } - final boolean mustPreventLesser = !encoding.applicableMinValue().equals(encoding.primitiveType().minValue()); + final boolean mustPreventLesser = + nativeTypeRepresentsValuesLessThanValidRange(fieldToken, typeToken.encoding(), SIGNED_AND_UNSIGNED); + if (mustPreventLesser) { sb.append(indent).append(INDENT) @@ -1299,7 +1304,9 @@ private void generateSingleValueProperty( .append("}\n"); } - final boolean mustPreventGreater = !encoding.applicableMaxValue().equals(encoding.primitiveType().maxValue()); + final boolean mustPreventGreater = + nativeTypeRepresentsValuesGreaterThanValidRange(fieldToken, typeToken.encoding(), SIGNED_AND_UNSIGNED); + if (mustPreventGreater) { sb.append(indent).append(INDENT) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java index 65d7bbf6a8..bb7da8df34 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -19,6 +19,7 @@ import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.generation.CodeGenerator; import uk.co.real_logic.sbe.generation.Generators; +import uk.co.real_logic.sbe.ir.Encoding; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.ir.Signal; import uk.co.real_logic.sbe.ir.Token; @@ -36,6 +37,9 @@ import static uk.co.real_logic.sbe.generation.Generators.toLowerFirstChar; import static uk.co.real_logic.sbe.generation.Generators.toUpperFirstChar; +import static uk.co.real_logic.sbe.generation.common.DtoValidationUtil.NativeIntegerSupport.SIGNED_ONLY; +import static uk.co.real_logic.sbe.generation.common.DtoValidationUtil.nativeTypeRepresentsValuesGreaterThanValidRange; +import static uk.co.real_logic.sbe.generation.common.DtoValidationUtil.nativeTypeRepresentsValuesLessThanValidRange; import static uk.co.real_logic.sbe.generation.java.JavaUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; @@ -1485,57 +1489,157 @@ private void generateSingleValueProperty( final String typeName = javaTypeName(typeToken.encoding().primitiveType()); final String formattedPropertyName = formatPropertyName(propertyName); final String fieldName = formatFieldName(propertyName); + + final String validateMethod = generateSingleValueValidateMethod( + classBuilder, + decoderClassName, + propertyName, + fieldToken, + typeToken, + indent, + typeName, + formattedPropertyName + ); + + classBuilder.appendField() + .append(indent).append("private ").append(typeName).append(" ").append(fieldName).append(";\n"); + + classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public ").append(typeName).append(" ") + .append(formattedPropertyName).append("()\n") + .append(indent).append("{\n") + .append(indent).append(INDENT).append("return this.").append(fieldName).append(";\n") + .append(indent).append("}\n"); + + final StringBuilder setterBuilder = classBuilder.appendPublic().append("\n") + .append(generateDocumentation(indent, fieldToken)) + .append(indent).append("public void ").append(formattedPropertyName).append("(") + .append(typeName).append(" value)\n") + .append(indent).append("{\n"); + + if (null != validateMethod) + { + setterBuilder.append(indent).append(INDENT).append(validateMethod).append("(value);\n"); + } + + setterBuilder + .append(indent).append(INDENT).append("this.").append(fieldName).append(" = value;\n") + .append(indent).append("}\n"); + } + + private static String generateSingleValueValidateMethod( + final ClassBuilder classBuilder, + final String decoderClassName, + final String propertyName, + final Token fieldToken, + final Token typeToken, + final String indent, + final String typeName, + final String formattedPropertyName) + { + final boolean mustPreventLesser = + nativeTypeRepresentsValuesLessThanValidRange(fieldToken, typeToken.encoding(), SIGNED_ONLY); + + final boolean mustPreventGreater = + nativeTypeRepresentsValuesGreaterThanValidRange(fieldToken, typeToken.encoding(), SIGNED_ONLY); + + if (!mustPreventLesser && !mustPreventGreater) + { + return null; + } + final String validateMethod = "validate" + toUpperFirstChar(propertyName); - final boolean representedWithinJavaType = typeToken.encoding().primitiveType() != PrimitiveType.UINT64; + final StringBuilder validateBuilder = classBuilder.appendPrivate().append("\n") + .append(indent).append("private static void ").append(validateMethod).append("(") + .append(typeName).append(" value)\n") + .append(indent).append("{\n"); - final StringBuilder validationCall = new StringBuilder(); + final boolean allowsNull = fieldToken.isOptionalEncoding(); - if (representedWithinJavaType) + if (allowsNull) { - final StringBuilder validateBuilder = classBuilder.appendPrivate().append("\n") - .append(indent).append("private static void ").append(validateMethod).append("(") - .append(typeName).append(" value)\n") - .append(indent).append("{\n"); + validateBuilder.append(indent).append(INDENT) + .append("if (value == ") + .append(decoderClassName).append(".").append(formattedPropertyName).append("NullValue())\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("return;\n") + .append(indent).append(INDENT) + .append("}\n\n"); + } + if (mustPreventLesser) + { validateBuilder.append(indent).append(INDENT) - .append("if (value < ") - .append(decoderClassName).append(".").append(formattedPropertyName).append("MinValue() || ") - .append("value").append(" > ") - .append(decoderClassName).append(".").append(formattedPropertyName).append("MaxValue())\n") + .append("if ("); + + generateGreaterThanExpression( + validateBuilder, + typeToken.encoding(), + decoderClassName + "." + formattedPropertyName + "MinValue()", + "value" + ); + + validateBuilder + .append(")\n") .append(indent).append(INDENT) .append("{\n") .append(indent).append(INDENT).append(INDENT) .append("throw new IllegalArgumentException(\"") .append(propertyName) - .append(": value is out of allowed range: \" + ") + .append(": value is below allowed minimum: \" + ") .append("value").append(");\n") .append(indent).append(INDENT) - .append("}\n") - .append(indent).append("}\n"); + .append("}\n\n"); + } - validationCall.append(indent).append(INDENT).append(validateMethod).append("(value);\n"); + if (mustPreventGreater) + { + validateBuilder.append(indent).append(INDENT) + .append("if ("); + + generateGreaterThanExpression( + validateBuilder, + typeToken.encoding(), + "value", + decoderClassName + "." + formattedPropertyName + "MaxValue()" + ); + + validateBuilder + .append(")\n") + .append(indent).append(INDENT) + .append("{\n") + .append(indent).append(INDENT).append(INDENT) + .append("throw new IllegalArgumentException(\"") + .append(propertyName) + .append(": value is above allowed maximum: \" + ") + .append("value").append(");\n") + .append(indent).append(INDENT) + .append("}\n\n"); } - classBuilder.appendField() - .append(indent).append("private ").append(typeName).append(" ").append(fieldName).append(";\n"); + validateBuilder.append(indent).append("}\n"); - classBuilder.appendPublic().append("\n") - .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("public ").append(typeName).append(" ") - .append(formattedPropertyName).append("()\n") - .append(indent).append("{\n") - .append(indent).append(INDENT).append("return this.").append(fieldName).append(";\n") - .append(indent).append("}\n"); + return validateMethod; + } - classBuilder.appendPublic().append("\n") - .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("public void ").append(formattedPropertyName).append("(") - .append(typeName).append(" value)\n") - .append(indent).append("{\n") - .append(validationCall) - .append(indent).append(INDENT).append("this.").append(fieldName).append(" = value;\n") - .append(indent).append("}\n"); + private static void generateGreaterThanExpression( + final StringBuilder builder, + final Encoding encoding, + final String lhs, + final String rhs) + { + if (encoding.primitiveType() == PrimitiveType.UINT64) + { + builder.append("Long.compareUnsigned(").append(lhs).append(", ").append(rhs).append(") > 0"); + } + else + { + builder.append(lhs).append(" > ").append(rhs); + } } private void generateConstPropertyMethods( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index 4d81dc47b9..18001ae9fa 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -15,13 +15,13 @@ */ package uk.co.real_logic.sbe.json; -import org.agrona.DirectBuffer; -import org.agrona.PrintBufferUtil; import uk.co.real_logic.sbe.PrimitiveValue; import uk.co.real_logic.sbe.ir.Encoding; import uk.co.real_logic.sbe.ir.Token; import uk.co.real_logic.sbe.otf.TokenListener; import uk.co.real_logic.sbe.otf.Types; +import org.agrona.DirectBuffer; +import org.agrona.PrintBufferUtil; import java.io.UnsupportedEncodingException; import java.util.List; @@ -236,7 +236,7 @@ public void onVarData( final String str = charsetName != null ? new String(tempBuffer, 0, length, charsetName) : PrintBufferUtil.hexDump(tempBuffer); - escape(str); + Types.jsonEscape(str, output); doubleQuote(); next(); @@ -290,7 +290,7 @@ private void appendEncodingAsString( final long longValue = constOrNotPresentValue.longValue(); if (PrimitiveValue.NULL_VALUE_CHAR != longValue) { - escape(new String(new byte[]{ (byte)longValue }, characterEncoding)); + Types.jsonEscape(new String(new byte[] {(byte)longValue}, characterEncoding), output); } } catch (final UnsupportedEncodingException ex) @@ -300,7 +300,7 @@ private void appendEncodingAsString( } else { - escape(constOrNotPresentValue.toString()); + Types.jsonEscape(constOrNotPresentValue.toString(), output); } doubleQuote(); @@ -371,7 +371,7 @@ private void escapePrintableChar(final DirectBuffer buffer, final int index, fin final byte c = buffer.getByte(index + (i * elementSize)); if (c > 0) { - escape((char)c); + Types.jsonEscape((char)c, output); } else { @@ -467,22 +467,4 @@ private static long readEncodingAsLong( return Types.getLong(buffer, bufferIndex, typeToken.encoding()); } - - private void escape(final String str) - { - for (int i = 0, length = str.length(); i < length; i++) - { - escape(str.charAt(i)); - } - } - - private void escape(final char c) - { - if ('"' == c || '\\' == c || '\b' == c || '\f' == c || '\n' == c || '\r' == c || '\t' == c) - { - output.append('\\'); - } - - output.append(c); - } } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java index d9c64a2a2f..2d41cf22ba 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/Types.java @@ -15,10 +15,10 @@ */ package uk.co.real_logic.sbe.otf; -import org.agrona.DirectBuffer; import uk.co.real_logic.sbe.PrimitiveType; import uk.co.real_logic.sbe.PrimitiveValue; import uk.co.real_logic.sbe.ir.Encoding; +import org.agrona.DirectBuffer; import java.nio.ByteOrder; @@ -27,6 +27,11 @@ */ public class Types { + private static final char[] HEX_DIGIT = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + /** * Get an integer value from a buffer at a given index for a {@link PrimitiveType}. * @@ -187,7 +192,9 @@ public static void appendAsJsonString( switch (encoding.primitiveType()) { case CHAR: - sb.append('\'').append((char)buffer.getByte(index)).append('\''); + sb.append('\"'); + jsonEscape((char)buffer.getByte(index), sb); + sb.append('\"'); break; case INT8: @@ -227,15 +234,15 @@ public static void appendAsJsonString( final float value = buffer.getFloat(index, encoding.byteOrder()); if (Float.isNaN(value)) { - sb.append("0/0"); + sb.append("\"0/0\""); } else if (value == Float.POSITIVE_INFINITY) { - sb.append("1/0"); + sb.append("\"1/0\""); } else if (value == Float.NEGATIVE_INFINITY) { - sb.append("-1/0"); + sb.append("\"-1/0\""); } else { @@ -249,15 +256,15 @@ else if (value == Float.NEGATIVE_INFINITY) final double value = buffer.getDouble(index, encoding.byteOrder()); if (Double.isNaN(value)) { - sb.append("0/0"); + sb.append("\"0/0\""); } else if (value == Double.POSITIVE_INFINITY) { - sb.append("1/0"); + sb.append("\"1/0\""); } else if (value == Double.NEGATIVE_INFINITY) { - sb.append("-1/0"); + sb.append("\"-1/0\""); } else { @@ -280,7 +287,9 @@ public static void appendAsJsonString(final StringBuilder sb, final PrimitiveVal switch (encoding.primitiveType()) { case CHAR: - sb.append('\'').append((char)value.longValue()).append('\''); + sb.append('\"'); + jsonEscape((char)value.longValue(), sb); + sb.append('\"'); break; case INT8: @@ -299,15 +308,15 @@ public static void appendAsJsonString(final StringBuilder sb, final PrimitiveVal final float floatValue = (float)value.doubleValue(); if (Float.isNaN(floatValue)) { - sb.append("0/0"); + sb.append("\"0/0\""); } else if (floatValue == Float.POSITIVE_INFINITY) { - sb.append("1/0"); + sb.append("\"1/0\""); } else if (floatValue == Float.NEGATIVE_INFINITY) { - sb.append("-1/0"); + sb.append("\"-1/0\""); } else { @@ -321,15 +330,15 @@ else if (floatValue == Float.NEGATIVE_INFINITY) final double doubleValue = value.doubleValue(); if (Double.isNaN(doubleValue)) { - sb.append("0/0"); + sb.append("\"0/0\""); } else if (doubleValue == Double.POSITIVE_INFINITY) { - sb.append("1/0"); + sb.append("\"1/0\""); } else if (doubleValue == Double.NEGATIVE_INFINITY) { - sb.append("-1/0"); + sb.append("\"-1/0\""); } else { @@ -339,4 +348,70 @@ else if (doubleValue == Double.NEGATIVE_INFINITY) } } } + + /** + * Escape a string for use in a JSON string. + * + * @param str the string to escape + * @param output to append the escaped string to + */ + public static void jsonEscape(final String str, final StringBuilder output) + { + for (int i = 0, length = str.length(); i < length; i++) + { + jsonEscape(str.charAt(i), output); + } + } + + /** + * Escape a character for use in a JSON string. + * + * @param c the character to escape + * @param output to append the escaped character to + */ + public static void jsonEscape(final char c, final StringBuilder output) + { + if ('"' == c || '\\' == c) + { + output.append('\\'); + output.append(c); + } + else if ('\b' == c) + { + output.append("\\b"); + } + else if ('\f' == c) + { + output.append("\\f"); + } + else if ('\n' == c) + { + output.append("\\n"); + } + else if ('\r' == c) + { + output.append("\\r"); + } + else if ('\t' == c) + { + output.append("\\t"); + } + else if (c <= 0x1F || Character.isHighSurrogate(c) || Character.isLowSurrogate(c)) + { + jsonUnicodeEncode(c, output); + } + else + { + output.append(c); + } + } + + private static void jsonUnicodeEncode(final char c, final StringBuilder output) + { + output.append('\\').append('u') + .append(HEX_DIGIT[(c >>> 12) & 0x0F]) + .append(HEX_DIGIT[(c >>> 8) & 0x0F]) + .append(HEX_DIGIT[(c >>> 4) & 0x0F]) + .append(HEX_DIGIT[c & 0x0F]); + } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java index 04e1d8fdae..ba37558242 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/DtosPropertyTest.java @@ -31,25 +31,22 @@ import uk.co.real_logic.sbe.properties.arbitraries.SbeArbitraries; import uk.co.real_logic.sbe.properties.utils.InMemoryOutputManager; import org.agrona.*; -import org.agrona.concurrent.UnsafeBuffer; import org.agrona.io.DirectBufferInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.net.URLClassLoader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; -import java.util.Base64; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.fail; import static uk.co.real_logic.sbe.SbeTool.JAVA_DEFAULT_DECODING_BUFFER_TYPE; import static uk.co.real_logic.sbe.SbeTool.JAVA_DEFAULT_ENCODING_BUFFER_TYPE; +import static uk.co.real_logic.sbe.properties.PropertyTestUtil.addSchemaAndInputMessageFootnotes; @SuppressWarnings("ReadWriteStringCanBeUsed") @EnableFootnotes @@ -65,8 +62,7 @@ public class DtosPropertyTest void javaDtoEncodeShouldBeTheInverseOfDtoDecode( @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage, final Footnotes footnotes) - throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, - IllegalAccessException + throws Exception { final String packageName = encodedMessage.ir().applicableNamespace(); final InMemoryOutputManager outputManager = new InMemoryOutputManager(packageName); @@ -95,39 +91,36 @@ void javaDtoEncodeShouldBeTheInverseOfDtoDecode( fail("Code generation failed.", generationException); } - try (URLClassLoader generatedClassLoader = outputManager.compileGeneratedSources()) - { - final Class dtoClass = - generatedClassLoader.loadClass(packageName + ".TestMessageDto"); - - final Method decodeFrom = - dtoClass.getMethod("decodeFrom", DirectBuffer.class, int.class, int.class, int.class); - - final Method encodeWith = - dtoClass.getMethod("encodeWithHeaderWith", dtoClass, MutableDirectBuffer.class, int.class); - - final int inputLength = encodedMessage.length(); - final ExpandableArrayBuffer inputBuffer = encodedMessage.buffer(); - final MessageHeaderDecoder header = new MessageHeaderDecoder().wrap(inputBuffer, 0); - final int blockLength = header.blockLength(); - final int actingVersion = header.version(); - final Object dto = decodeFrom.invoke(null, - encodedMessage.buffer(), MessageHeaderDecoder.ENCODED_LENGTH, blockLength, actingVersion); - outputBuffer.setMemory(0, outputBuffer.capacity(), (byte)0); - final int outputLength = (int)encodeWith.invoke(null, dto, outputBuffer, 0); - if (!areEqual(inputBuffer, inputLength, outputBuffer, outputLength)) - { - fail("Input and output differ"); - } - } + final Class dtoClass = outputManager.compileAndLoad(packageName + ".TestMessageDto"); + + final Method decodeFrom = + dtoClass.getMethod("decodeFrom", DirectBuffer.class, int.class, int.class, int.class); + + final Method encodeWith = + dtoClass.getMethod("encodeWithHeaderWith", dtoClass, MutableDirectBuffer.class, int.class); + + final int inputLength = encodedMessage.length(); + final DirectBuffer inputBuffer = encodedMessage.buffer(); + final MessageHeaderDecoder header = new MessageHeaderDecoder().wrap(inputBuffer, 0); + final int blockLength = header.blockLength(); + final int actingVersion = header.version(); + final Object dto = decodeFrom.invoke( + null, + encodedMessage.buffer(), MessageHeaderDecoder.ENCODED_LENGTH, blockLength, actingVersion); + outputBuffer.setMemory(0, outputBuffer.capacity(), (byte)0); + final int outputLength = (int)encodeWith.invoke(null, dto, outputBuffer, 0); + assertEqual(inputBuffer, inputLength, outputBuffer, outputLength); } catch (final Throwable throwable) { - addInputFootnotes(footnotes, encodedMessage); + if (null != footnotes) + { + addSchemaAndInputMessageFootnotes(footnotes, encodedMessage); - final StringBuilder generatedSources = new StringBuilder(); - outputManager.dumpSources(generatedSources); - footnotes.addFootnote(generatedSources.toString()); + final StringBuilder generatedSources = new StringBuilder(); + outputManager.dumpSources(generatedSources); + footnotes.addFootnote(generatedSources.toString()); + } throw throwable; } @@ -180,14 +173,12 @@ void csharpDtoEncodeShouldBeTheInverseOfDtoDecode( if (!Arrays.equals(inputBytes, outputBytes)) { throw new AssertionError( - "Input and output files differ\n\n" + - "DIR:" + tempDir + "\n\n" + - "SCHEMA:\n" + encodedMessage.schema()); + "Input and output files differ\n\nDIR:" + tempDir); } } catch (final Throwable throwable) { - addInputFootnotes(footnotes, encodedMessage); + addSchemaAndInputMessageFootnotes(footnotes, encodedMessage); addGeneratedSourcesFootnotes(footnotes, tempDir, ".cs"); throw throwable; @@ -239,14 +230,12 @@ void cppDtoEncodeShouldBeTheInverseOfDtoDecode( final byte[] outputBytes = Files.readAllBytes(tempDir.resolve("output.dat")); if (!Arrays.equals(inputBytes, outputBytes)) { - throw new AssertionError( - "Input and output files differ\n\n" + - "SCHEMA:\n" + encodedMessage.schema()); + throw new AssertionError("Input and output files differ"); } } catch (final Throwable throwable) { - addInputFootnotes(footnotes, encodedMessage); + addSchemaAndInputMessageFootnotes(footnotes, encodedMessage); addGeneratedSourcesFootnotes(footnotes, tempDir, ".cpp"); throw throwable; @@ -319,9 +308,9 @@ private static void execute( @Provide Arbitrary encodedMessage() { - final SbeArbitraries.CharGenerationMode mode = - SbeArbitraries.CharGenerationMode.JSON_PRINTER_COMPATIBLE; - return SbeArbitraries.encodedMessage(mode); + final SbeArbitraries.CharGenerationConfig config = + SbeArbitraries.CharGenerationConfig.firstNullTerminatesCharArray(); + return SbeArbitraries.encodedMessage(config); } private static void copyResourceToFile( @@ -346,13 +335,46 @@ private static void copyResourceToFile( } } - private boolean areEqual( - final ExpandableArrayBuffer inputBuffer, + private static String readResourceFileAsString(final String resourcePath) throws IOException + { + try (InputStream inputStream = DtosPropertyTest.class.getResourceAsStream(resourcePath)) + { + if (inputStream == null) + { + throw new IllegalArgumentException("Resource not found: " + resourcePath); + } + + return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + } + } + + private void assertEqual( + final DirectBuffer inputBuffer, final int inputLength, - final ExpandableArrayBuffer outputBuffer, + final DirectBuffer outputBuffer, final int outputLength) { - return new UnsafeBuffer(inputBuffer, 0, inputLength).equals(new UnsafeBuffer(outputBuffer, 0, outputLength)); + final boolean lengthsDiffer = inputLength != outputLength; + final int minLength = Math.min(inputLength, outputLength); + + for (int i = 0; i < minLength; i++) + { + if (inputBuffer.getByte(i) != outputBuffer.getByte(i)) + { + throw new AssertionError( + "Input and output differ at byte " + i + ".\n" + + "Input length: " + inputLength + ", Output length: " + outputLength + "\n" + + "Input: " + inputBuffer.getByte(i) + ", Output: " + outputBuffer.getByte(i) + + (lengthsDiffer ? "\nLengths differ." : "")); + } + } + + if (lengthsDiffer) + { + throw new AssertionError( + "Input and output differ in length.\n" + + "Input length: " + inputLength + ", Output length: " + outputLength); + } } private void addGeneratedSourcesFootnotes( @@ -383,15 +405,4 @@ private void addGeneratedSourcesFootnotes( LangUtil.rethrowUnchecked(exn); } } - - public void addInputFootnotes(final Footnotes footnotes, final SbeArbitraries.EncodedMessage encodedMessage) - { - final byte[] messageBytes = new byte[encodedMessage.length()]; - encodedMessage.buffer().getBytes(0, messageBytes); - final byte[] base64EncodedMessageBytes = Base64.getEncoder().encode(messageBytes); - - footnotes.addFootnote("Schema:" + System.lineSeparator() + encodedMessage.schema()); - footnotes.addFootnote("Input Message:" + System.lineSeparator() + - new String(base64EncodedMessageBytes, StandardCharsets.UTF_8)); - } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java index ebac19703e..4837d267c7 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/JsonPropertyTest.java @@ -19,16 +19,23 @@ import net.jqwik.api.ForAll; import net.jqwik.api.Property; import net.jqwik.api.Provide; +import net.jqwik.api.footnotes.EnableFootnotes; +import net.jqwik.api.footnotes.Footnotes; import uk.co.real_logic.sbe.json.JsonPrinter; import uk.co.real_logic.sbe.properties.arbitraries.SbeArbitraries; import org.agrona.concurrent.UnsafeBuffer; import org.json.JSONException; import org.json.JSONObject; +import static uk.co.real_logic.sbe.properties.PropertyTestUtil.addSchemaAndInputMessageFootnotes; + public class JsonPropertyTest { @Property - void shouldGenerateValidJson(@ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage) + @EnableFootnotes + void shouldGenerateValidJson( + @ForAll("encodedMessage") final SbeArbitraries.EncodedMessage encodedMessage, + final Footnotes footnotes) { final StringBuilder output = new StringBuilder(); final JsonPrinter printer = new JsonPrinter(encodedMessage.ir()); @@ -39,15 +46,16 @@ void shouldGenerateValidJson(@ForAll("encodedMessage") final SbeArbitraries.Enco } catch (final JSONException e) { - throw new AssertionError("Invalid JSON: " + output + "\n\nSchema:\n" + encodedMessage.schema(), e); + addSchemaAndInputMessageFootnotes(footnotes, encodedMessage); + throw new AssertionError("Invalid JSON: " + output); } } @Provide Arbitrary encodedMessage() { - final SbeArbitraries.CharGenerationMode mode = - SbeArbitraries.CharGenerationMode.JSON_PRINTER_COMPATIBLE; - return SbeArbitraries.encodedMessage(mode); + final SbeArbitraries.CharGenerationConfig config = + SbeArbitraries.CharGenerationConfig.unrestricted(); + return SbeArbitraries.encodedMessage(config); } } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/PropertyTestUtil.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/PropertyTestUtil.java new file mode 100644 index 0000000000..e3c8c4e292 --- /dev/null +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/PropertyTestUtil.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013-2025 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.real_logic.sbe.properties; + +import net.jqwik.api.footnotes.Footnotes; +import uk.co.real_logic.sbe.properties.arbitraries.SbeArbitraries; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +final class PropertyTestUtil +{ + private PropertyTestUtil() + { + } + + static void addSchemaAndInputMessageFootnotes( + final Footnotes footnotes, + final SbeArbitraries.EncodedMessage encodedMessage) + { + final byte[] messageBytes = new byte[encodedMessage.length()]; + encodedMessage.buffer().getBytes(0, messageBytes); + final byte[] base64EncodedMessageBytes = Base64.getEncoder().encode(messageBytes); + + footnotes.addFootnote("Schema:" + System.lineSeparator() + encodedMessage.schema()); + footnotes.addFootnote("Input Message:" + System.lineSeparator() + + new String(base64EncodedMessageBytes, StandardCharsets.UTF_8)); + } +} diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java index c1dc232ee3..74bd2cc1da 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java @@ -29,9 +29,11 @@ import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.ParserOptions; import org.agrona.BitUtil; +import org.agrona.DirectBuffer; import org.agrona.ExpandableArrayBuffer; import org.agrona.MutableDirectBuffer; import org.agrona.collections.MutableInteger; +import org.agrona.concurrent.UnsafeBuffer; import java.io.ByteArrayInputStream; import java.io.InputStream; @@ -114,10 +116,30 @@ private static Arbitrary encodedDataTypeSchema() ).as(EncodedDataTypeSchema::new); } - public enum CharGenerationMode + public static class CharGenerationConfig { - UNRESTRICTED, - JSON_PRINTER_COMPATIBLE + private final boolean nullCharTerminatesData; + + public CharGenerationConfig( + final boolean nullCharTerminatesData) + { + this.nullCharTerminatesData = nullCharTerminatesData; + } + + boolean nullCharTerminatesData() + { + return nullCharTerminatesData; + } + + public static CharGenerationConfig unrestricted() + { + return new CharGenerationConfig(false); + } + + public static CharGenerationConfig firstNullTerminatesCharArray() + { + return new CharGenerationConfig(true); + } } private static Arbitrary enumTypeSchema() @@ -343,24 +365,42 @@ private static Arbitrary combineArbitraryEncoders(final List encodedTypeEncoder( + final Encoding encoding, + final boolean isOptional) + { + final Arbitrary inRangeEncoder = encodedTypeEncoder(encoding); - default: - throw new IllegalArgumentException("Unsupported mode: " + mode); + if (isOptional) + { + final Arbitrary nullEncoder = nullEncoder(encoding); + return Arbitraries.oneOf(inRangeEncoder, nullEncoder); + } + else + { + return inRangeEncoder; } } private static Arbitrary encodedTypeEncoder( - final Encoding encoding, - final CharGenerationMode charGenerationMode) + final Encoding encoding) { final PrimitiveValue minValue = encoding.applicableMinValue(); final PrimitiveValue maxValue = encoding.applicableMaxValue(); @@ -369,7 +409,7 @@ private static Arbitrary encodedTypeEncoder( { case CHAR: assert minValue.longValue() <= maxValue.longValue(); - return chars(charGenerationMode).map(c -> + return chars(encoding).map(c -> (builder, buffer, offset, limit) -> { builder.appendLine().append(c).append(" @ ").append(offset) @@ -458,13 +498,95 @@ private static Arbitrary encodedTypeEncoder( } } + private static Arbitrary nullEncoder(final Encoding encoding) + { + final PrimitiveValue nullValue = encoding.applicableNullValue(); + + switch (encoding.primitiveType()) + { + case CHAR: + return Arbitraries.just((char)nullValue.longValue()).map(c -> + (builder, buffer, offset, limit) -> + { + builder.appendLine().append(c).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_BYTE).append("]"); + buffer.putChar(offset, c, encoding.byteOrder()); + }); + + case UINT8: + case INT8: + return Arbitraries.just((short)nullValue.longValue()) + .map(b -> (builder, buffer, offset, limit) -> + { + builder.appendLine().append((byte)(short)b).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_BYTE).append("]"); + buffer.putByte(offset, (byte)(short)b); + }); + + case UINT16: + case INT16: + return Arbitraries.just((int)nullValue.longValue()) + .map(s -> (builder, buffer, offset, limit) -> + { + builder.appendLine().append((short)(int)s).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_SHORT).append("]"); + buffer.putShort(offset, (short)(int)s, encoding.byteOrder()); + }); + + case UINT32: + case INT32: + return Arbitraries.just(nullValue.longValue()) + .map(i -> (builder, buffer, offset, limit) -> + { + builder.appendLine().append((int)(long)i).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_INT).append("]"); + buffer.putInt(offset, (int)(long)i, encoding.byteOrder()); + }); + + case UINT64: + case INT64: + return Arbitraries.just(nullValue.longValue()) + .map(l -> (builder, buffer, offset, limit) -> + { + builder.appendLine().append(l).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_LONG).append("]"); + buffer.putLong(offset, l, encoding.byteOrder()); + }); + + case FLOAT: + return Arbitraries.just((float)nullValue.doubleValue()) + .map(f -> (builder, buffer, offset, limit) -> + { + builder.appendLine().append(f).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_FLOAT).append("]"); + buffer.putFloat(offset, f, encoding.byteOrder()); + }); + + case DOUBLE: + return Arbitraries.just(nullValue.doubleValue()) + .map(d -> (builder, buffer, offset, limit) -> + { + builder.appendLine().append(d).append(" @ ").append(offset) + .append("[").append(BitUtil.SIZE_OF_DOUBLE).append("]"); + buffer.putDouble(offset, d, encoding.byteOrder()); + }); + + default: + throw new IllegalArgumentException("Unsupported type: " + encoding.primitiveType()); + } + } + private static Arbitrary encodedTypeEncoder( final int offset, + final Token memberToken, final Token typeToken, - final CharGenerationMode charGenerationMode) + final CharGenerationConfig charGenerationConfig) { final Encoding encoding = typeToken.encoding(); - final Arbitrary arbEncoder = encodedTypeEncoder(encoding, charGenerationMode); + final Arbitrary arbEncoder = encodedTypeEncoder( + encoding, + memberToken.isOptionalEncoding() + ); if (typeToken.arrayLength() == 1) { @@ -476,11 +598,28 @@ private static Arbitrary encodedTypeEncoder( return arbEncoder.list().ofSize(typeToken.arrayLength()) .map(encoders -> (builder, buffer, bufferOffset, limit) -> { + boolean hasNullTerminated = false; + for (int i = 0; i < typeToken.arrayLength(); i++) { builder.beginScope("[" + i + "]"); final int elementOffset = bufferOffset + offset + i * encoding.primitiveType().size(); - encoders.get(i).encode(builder, buffer, elementOffset, limit); + if (hasNullTerminated) + { + buffer.putByte(elementOffset, (byte)0); + } + else + { + encoders.get(i).encode(builder, buffer, elementOffset, limit); + } + + if (encoding.primitiveType() == PrimitiveType.CHAR && + charGenerationConfig.nullCharTerminatesData() && + buffer.getByte(elementOffset) == 0) + { + hasNullTerminated = true; + } + builder.endScope(); } }); @@ -548,6 +687,7 @@ private static Encoder integerValueEncoder(final Encoding encoding, final long v private static Arbitrary enumEncoder( final int offset, final List tokens, + final Token memberToken, final Token typeToken, final MutableInteger cursor, final int endIdxInclusive) @@ -569,7 +709,7 @@ private static Arbitrary enumEncoder( encoders.add(caseEncoder); } - if (encoders.isEmpty()) + if (memberToken.isOptionalEncoding() || encoders.isEmpty()) { final Encoder nullEncoder = integerValueEncoder( typeToken.encoding(), @@ -684,7 +824,7 @@ private static Arbitrary fieldsEncoder( final MutableInteger cursor, final int endIdxInclusive, final boolean expectFields, - final CharGenerationMode charGenerationMode) + final CharGenerationConfig charGenerationConfig) { final List> encoders = new ArrayList<>(); while (cursor.get() <= endIdxInclusive) @@ -718,7 +858,7 @@ else if (expectFields) final int endCompositeTokenCount = 1; final int lastMemberIdx = nextFieldIdx - endCompositeTokenCount - endFieldTokenCount - 1; final Arbitrary encoder = fieldsEncoder( - tokens, cursor, lastMemberIdx, false, charGenerationMode); + tokens, cursor, lastMemberIdx, false, charGenerationConfig); fieldEncoder = encoder.map(e -> (builder, buffer, bufferOffset, limit) -> e.encode(builder, buffer, bufferOffset + offset, limit)); @@ -727,7 +867,7 @@ else if (expectFields) case BEGIN_ENUM: final int endEnumTokenCount = 1; final int lastValidValueIdx = nextFieldIdx - endFieldTokenCount - endEnumTokenCount - 1; - fieldEncoder = enumEncoder(offset, tokens, typeToken, cursor, lastValidValueIdx); + fieldEncoder = enumEncoder(offset, tokens, memberToken, typeToken, cursor, lastValidValueIdx); break; case BEGIN_SET: @@ -737,7 +877,7 @@ else if (expectFields) break; case ENCODING: - fieldEncoder = encodedTypeEncoder(offset, typeToken, charGenerationMode); + fieldEncoder = encodedTypeEncoder(offset, memberToken, typeToken, charGenerationConfig); break; default: @@ -766,7 +906,7 @@ private static Arbitrary groupsEncoder( final List tokens, final MutableInteger cursor, final int endIdxInclusive, - final CharGenerationMode charGenerationMode) + final CharGenerationConfig charGenerationConfig) { final List> encoders = new ArrayList<>(); @@ -792,9 +932,9 @@ private static Arbitrary groupsEncoder( final Arbitrary groupElement = Combinators.combine( - fieldsEncoder(tokens, cursor, nextFieldIdx - 1, true, charGenerationMode), - groupsEncoder(tokens, cursor, nextFieldIdx - 1, charGenerationMode), - varDataEncoder(tokens, cursor, nextFieldIdx - 1, charGenerationMode) + fieldsEncoder(tokens, cursor, nextFieldIdx - 1, true, charGenerationConfig), + groupsEncoder(tokens, cursor, nextFieldIdx - 1, charGenerationConfig), + varDataEncoder(tokens, cursor, nextFieldIdx - 1) ).as((fieldsEncoder, groupsEncoder, varDataEncoder) -> (builder, buffer, ignored, limit) -> { @@ -843,8 +983,7 @@ private static Arbitrary groupsEncoder( private static Arbitrary varDataEncoder( final List tokens, final MutableInteger cursor, - final int endIdxInclusive, - final CharGenerationMode charGenerationMode) + final int endIdxInclusive) { final List> encoders = new ArrayList<>(); @@ -867,7 +1006,7 @@ private static Arbitrary varDataEncoder( final String characterEncoding = varDataToken.encoding().characterEncoding(); final Arbitrary arbitraryByte = null == characterEncoding ? Arbitraries.bytes() : - chars(charGenerationMode).map(c -> (byte)c.charValue()); + chars(varDataToken.encoding()).map(c -> (byte)c.charValue()); encoders.add(arbitraryByte.list() .ofMaxSize((int)Math.min(lengthToken.encoding().applicableMaxValue().longValue(), 260L)) .map(bytes -> (builder, buffer, ignored, limit) -> @@ -901,7 +1040,7 @@ private static Arbitrary varDataEncoder( private static Arbitrary messageValueEncoder( final Ir ir, final short messageId, - final CharGenerationMode charGenerationMode) + final CharGenerationConfig charGenerationConfig) { final List tokens = ir.getMessage(messageId); final MutableInteger cursor = new MutableInteger(1); @@ -913,11 +1052,11 @@ private static Arbitrary messageValueEncoder( } final Arbitrary fieldsEncoder = fieldsEncoder( - tokens, cursor, tokens.size() - 1, true, charGenerationMode); + tokens, cursor, tokens.size() - 1, true, charGenerationConfig); final Arbitrary groupsEncoder = groupsEncoder( - tokens, cursor, tokens.size() - 1, charGenerationMode); + tokens, cursor, tokens.size() - 1, charGenerationConfig); final Arbitrary varDataEncoder = varDataEncoder( - tokens, cursor, tokens.size() - 1, charGenerationMode); + tokens, cursor, tokens.size() - 1); return Combinators.combine(fieldsEncoder, groupsEncoder, varDataEncoder) .as((fields, groups, varData) -> (builder, buffer, offset, limit) -> { @@ -941,14 +1080,14 @@ public static final class EncodedMessage { private final String schema; private final Ir ir; - private final ExpandableArrayBuffer buffer; + private final DirectBuffer buffer; private final int length; private final String encodingLog; private EncodedMessage( final String schema, final Ir ir, - final ExpandableArrayBuffer buffer, + final DirectBuffer buffer, final int length, final String encodingLog) { @@ -969,7 +1108,7 @@ public Ir ir() return ir; } - public ExpandableArrayBuffer buffer() + public DirectBuffer buffer() { return buffer; } @@ -979,13 +1118,61 @@ public int length() return length; } + /** + * A log of the steps taken to encode the input message. This information is useful for debugging problems in + * the arbitrary message generator. + * + * @return a log of the steps taken to encode the message + */ + @SuppressWarnings("unused") public String encodingLog() { return encodingLog; } + + /** + * Takes the XML schema and Base64 input message from a (possibly shrunken) example and creates an + * {@link EncodedMessage} instance that can be used to drive property-based test logic. This data is output + * when a test fails. + * + * @param schemaXml the schema to use + * @param inputMessage the input message (as a base64 encoded string) + * @return an encoded message for use with property-based tests + */ + @SuppressWarnings("unused") + public static EncodedMessage fromDebugOutput( + final String schemaXml, + final String inputMessage) + { + try (InputStream in = new ByteArrayInputStream(schemaXml.getBytes(StandardCharsets.UTF_8))) + { + final ParserOptions options = ParserOptions.builder() + .suppressOutput(false) + .warningsFatal(true) + .stopOnError(true) + .build(); + final uk.co.real_logic.sbe.xml.MessageSchema parsedSchema = parse(in, options); + final Ir ir = new IrGenerator().generate(parsedSchema); + + final byte[] messageBytes = Base64.getDecoder().decode(inputMessage); + final UnsafeBuffer buffer = new UnsafeBuffer(messageBytes); + + return new EncodedMessage( + schemaXml, + ir, + buffer, + buffer.capacity(), + "" + ); + } + catch (final Exception exception) + { + throw new RuntimeException(exception); + } + } } - public static Arbitrary encodedMessage(final CharGenerationMode mode) + public static Arbitrary encodedMessage(final CharGenerationConfig charGenerationConfig) { return SbeArbitraries.messageSchema().flatMap(testSchema -> { @@ -999,7 +1186,7 @@ public static Arbitrary encodedMessage(final CharGenerationMode .build(); final uk.co.real_logic.sbe.xml.MessageSchema parsedSchema = parse(in, options); final Ir ir = new IrGenerator().generate(parsedSchema); - return SbeArbitraries.messageValueEncoder(ir, testSchema.templateId(), mode) + return SbeArbitraries.messageValueEncoder(ir, testSchema.templateId(), charGenerationConfig) .map(encoder -> { final EncodingLogger logger = new EncodingLogger(); diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java index 5dc4569db2..141e7e469b 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/schema/TestXmlSchemaWriter.java @@ -15,12 +15,17 @@ */ package uk.co.real_logic.sbe.properties.schema; +import uk.co.real_logic.sbe.ir.Encoding; import org.agrona.collections.MutableInteger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; -import uk.co.real_logic.sbe.ir.Encoding; +import java.io.File; +import java.io.StringWriter; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; @@ -28,11 +33,6 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; -import java.io.File; -import java.io.StringWriter; -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; import static java.util.Objects.requireNonNull; @@ -355,7 +355,6 @@ private static void appendTypes( } } - @SuppressWarnings("EnhancedSwitchMigration") private static final class TypeSchemaConverter implements TypeSchemaVisitor { private final Document document; @@ -465,7 +464,8 @@ public Node convert(final VarDataSchema varData) final Element varDataElement = createTypeElement(document, "varData", "uint8"); varDataElement.setAttribute("length", "0"); - if (varData.dataEncoding().equals(VarDataSchema.Encoding.ASCII)) + final VarDataSchema.Encoding encoding = varData.dataEncoding(); + if (encoding.equals(VarDataSchema.Encoding.ASCII)) { varDataElement.setAttribute("characterEncoding", "US-ASCII"); } diff --git a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java index 065737c57e..403c64b068 100644 --- a/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java +++ b/sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/utils/InMemoryOutputManager.java @@ -15,17 +15,14 @@ */ package uk.co.real_logic.sbe.properties.utils; +import org.agrona.generation.CompilerUtil; import org.agrona.generation.DynamicPackageOutputManager; -import javax.tools.*; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; -import java.net.URI; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.*; +import java.util.HashMap; +import java.util.Map; /** * An implementation of {@link DynamicPackageOutputManager} that stores generated source code in memory and compiles it @@ -34,7 +31,7 @@ public class InMemoryOutputManager implements DynamicPackageOutputManager { private final String packageName; - private final Map sourceFiles = new HashMap<>(); + private final Map sources = new HashMap<>(); private String packageNameOverride; public InMemoryOutputManager(final String packageName) @@ -53,42 +50,32 @@ public void setPackageName(final String packageName) } /** - * Compile the generated sources and return a {@link URLClassLoader} that can be used to load the generated classes. + * Compile the generated sources and return a {@link Class} matching the supplied fully-qualified name. * - * @return a {@link URLClassLoader} that can be used to load the generated classes + * @param fqClassName the fully-qualified class name to compile and load. + * @return a {@link Class} matching the supplied fully-qualified name. */ - public URLClassLoader compileGeneratedSources() + public Class compileAndLoad(final String fqClassName) { - final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - final StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null); - final InMemoryFileManager fileManager = new InMemoryFileManager(standardFileManager); - final JavaCompiler.CompilationTask task = compiler.getTask( - null, - fileManager, - null, - null, - null, - sourceFiles.values()); - - if (!task.call()) + try { - throw new IllegalStateException("Compilation failed"); + return CompilerUtil.compileInMemory(fqClassName, sources); + } + catch (final Exception exception) + { + throw new RuntimeException(exception); } - - final GeneratedCodeLoader classLoader = new GeneratedCodeLoader(getClass().getClassLoader()); - classLoader.defineClasses(fileManager); - return classLoader; } public void dumpSources(final StringBuilder builder) { - builder.append(System.lineSeparator()).append("Generated sources file count: ").append(sourceFiles.size()) + builder.append(System.lineSeparator()).append("Generated sources file count: ").append(sources.size()) .append(System.lineSeparator()); - sourceFiles.forEach((qualifiedName, file) -> + sources.forEach((qualifiedName, source) -> { builder.append(System.lineSeparator()).append("Source file: ").append(qualifiedName) - .append(System.lineSeparator()).append(file.sourceCode) + .append(System.lineSeparator()).append(source) .append(System.lineSeparator()); }); } @@ -109,93 +96,14 @@ public void close() throws IOException packageNameOverride = null; final String qualifiedName = actingPackageName + "." + name; - final InMemoryJavaFileObject sourceFile = - new InMemoryJavaFileObject(qualifiedName, getBuffer().toString()); - final InMemoryJavaFileObject existingFile = sourceFiles.putIfAbsent(qualifiedName, sourceFile); + final String source = getBuffer().toString(); + final CharSequence existingSource = sources.putIfAbsent(qualifiedName, source); - if (existingFile != null && !Objects.equals(existingFile.sourceCode, sourceFile.sourceCode)) + if (null != existingSource && 0 != CharSequence.compare(existingSource, source)) { throw new IllegalStateException("Duplicate (but different) class: " + qualifiedName); } } } - - static class InMemoryFileManager extends ForwardingJavaFileManager - { - private final List outputFiles = new ArrayList<>(); - - InMemoryFileManager(final StandardJavaFileManager fileManager) - { - super(fileManager); - } - - public JavaFileObject getJavaFileForOutput( - final Location location, - final String className, - final JavaFileObject.Kind kind, - final FileObject sibling) - { - final InMemoryJavaFileObject outputFile = new InMemoryJavaFileObject(className, kind); - outputFiles.add(outputFile); - return outputFile; - } - - public Collection outputFiles() - { - return outputFiles; - } - } - - static class InMemoryJavaFileObject extends SimpleJavaFileObject - { - private final String sourceCode; - private final ByteArrayOutputStream outputStream; - - InMemoryJavaFileObject(final String className, final String sourceCode) - { - super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); - this.sourceCode = sourceCode; - this.outputStream = new ByteArrayOutputStream(); - } - - InMemoryJavaFileObject(final String className, final Kind kind) - { - super(URI.create("mem:///" + className.replace('.', '/') + kind.extension), kind); - this.sourceCode = null; - this.outputStream = new ByteArrayOutputStream(); - } - - public CharSequence getCharContent(final boolean ignoreEncodingErrors) - { - return sourceCode; - } - - public ByteArrayOutputStream openOutputStream() - { - return outputStream; - } - - public byte[] getClassBytes() - { - return outputStream.toByteArray(); - } - } - - static class GeneratedCodeLoader extends URLClassLoader - { - GeneratedCodeLoader(final ClassLoader parent) - { - super(new URL[0], parent); - } - - void defineClasses(final InMemoryFileManager fileManager) - { - fileManager.outputFiles().forEach(file -> - { - final byte[] classBytes = file.getClassBytes(); - super.defineClass(null, classBytes, 0, classBytes.length); - }); - } - } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/common/DtoValidationUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/common/DtoValidationUtilTest.java new file mode 100644 index 0000000000..ea6d19e5fa --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/common/DtoValidationUtilTest.java @@ -0,0 +1,105 @@ +/* + * Copyright 2013-2025 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.common; + +import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.PrimitiveValue; +import uk.co.real_logic.sbe.ir.Encoding; +import uk.co.real_logic.sbe.ir.Token; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static uk.co.real_logic.sbe.generation.common.DtoValidationUtil.nativeTypeRepresentsValuesGreaterThanValidRange; +import static uk.co.real_logic.sbe.generation.common.DtoValidationUtil.nativeTypeRepresentsValuesLessThanValidRange; + +public class DtoValidationUtilTest +{ + @ParameterizedTest + @CsvSource({ + "int8,SIGNED_AND_UNSIGNED,false,-128,-127,127,true,false", + "int8,SIGNED_AND_UNSIGNED,true,-128,-127,127,false,false", + "int8,SIGNED_ONLY,false,-128,-127,127,true,false", + "int8,SIGNED_ONLY,true,-128,-127,127,false,false", + + "int8,SIGNED_AND_UNSIGNED,false,127,-128,126,false,true", + "int8,SIGNED_AND_UNSIGNED,true,127,-128,126,false,false", + "int8,SIGNED_ONLY,false,127,-128,126,false,true", + "int8,SIGNED_ONLY,true,127,-128,126,false,false", + + "int8,SIGNED_ONLY,true,-128,-100,127,true,false", + "int8,SIGNED_ONLY,true,127,-128,100,false,true", + + "int8,SIGNED_ONLY,true,0,-128,127,false,false", + "int8,SIGNED_ONLY,true,0,-127,127,true,false", + "int8,SIGNED_ONLY,true,0,-128,126,false,true", + "int8,SIGNED_ONLY,true,0,-127,126,true,true", + + "uint8,SIGNED_AND_UNSIGNED,false,255,0,254,false,true", + "uint8,SIGNED_AND_UNSIGNED,true,255,0,254,false,false", + "uint8,SIGNED_ONLY,false,255,0,254,true,true", + "uint8,SIGNED_ONLY,true,255,0,254,true,true", + + "float,SIGNED_AND_UNSIGNED,false,-2,-1,1,true,true", + "float,SIGNED_AND_UNSIGNED,true,-2,-1,1,true,true", + "float,SIGNED_ONLY,false,-2,-1,1,true,true", + "float,SIGNED_ONLY,true,-2,-1,1,true,true", + + "uint64,SIGNED_AND_UNSIGNED,true,18446744073709551615,0,18446744073709551614,false,false", + "uint64,SIGNED_AND_UNSIGNED,true,18446744073709551615,1,18446744073709551614,true,false", + "uint64,SIGNED_AND_UNSIGNED,true,18446744073709551615,0,18446744073709551613,false,true", + "uint64,SIGNED_AND_UNSIGNED,true,18446744073709551615,1,18446744073709551613,true,true", + "uint64,SIGNED_ONLY,true,18446744073709551615,0,18446744073709551614,false,false", + "uint64,SIGNED_ONLY,true,18446744073709551615,1,18446744073709551614,true,false", + "uint64,SIGNED_ONLY,true,18446744073709551615,0,18446744073709551613,false,true", + "uint64,SIGNED_ONLY,true,18446744073709551615,1,18446744073709551613,true,true", + }) + void shouldGenerateValidationBasedOnNativeRangeVersusSbeTypeRange( + final String type, + final DtoValidationUtil.NativeIntegerSupport integerSupport, + final boolean isOptional, + final String nullValue, + final String minValue, + final String maxValue, + final boolean shouldValidateBelow, + final boolean shouldValidateAbove) + { + final Token fieldToken = mock(Token.class); + when(fieldToken.isOptionalEncoding()).thenReturn(isOptional); + final Encoding encoding = mock(Encoding.class); + final PrimitiveType primitiveType = PrimitiveType.get(type); + when(encoding.primitiveType()).thenReturn(primitiveType); + when(encoding.applicableNullValue()).thenReturn(PrimitiveValue.parse(nullValue, primitiveType)); + when(encoding.applicableMinValue()).thenReturn(PrimitiveValue.parse(minValue, primitiveType)); + when(encoding.applicableMaxValue()).thenReturn(PrimitiveValue.parse(maxValue, primitiveType)); + + final boolean validatesBelow = + nativeTypeRepresentsValuesLessThanValidRange(fieldToken, encoding, integerSupport); + + final boolean validatesAbove = + nativeTypeRepresentsValuesGreaterThanValidRange(fieldToken, encoding, integerSupport); + + assertEquals( + shouldValidateBelow, validatesBelow, + shouldValidateBelow ? "should" : "should not" + " validate below"); + + assertEquals( + shouldValidateAbove, validatesAbove, + shouldValidateAbove ? "should" : "should not" + " validate above"); + } +} From b69c9a596ff33e301c3f991966f77c503e8537b5 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 20 Jun 2025 11:49:22 +0200 Subject: [PATCH 1391/1594] [Doc] Release notes. --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4e3935a1f..50bd456c45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [1.35.5] - 2025-06-20 +### Changed +* **Java/C++/C#:** Fix a bug in overzealous DTO validation. ([#1073](https://github.com/aeron-io/simple-binary-encoding/pull/1073)) +* **Java:** Bump `Agrona` to 2.2.3. + ## [1.35.4] - 2025-06-12 ### Changed * **Rust:** Return None for optional primite field if its version is less than actingVersion. ([#1067](https://github.com/aeron-io/simple-binary-encoding/pull/1067)) @@ -88,6 +93,7 @@ * **Java:** Prevent collision when field name is 'value'. * **Java:** Preserve byte order throughout IR transformations. +[1.35.5]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.5 [1.35.4]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.4 [1.35.3]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.3 [1.35.1]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.1 From 4f62d954c7c9bdbe14e09ed0f38e9da5580679d8 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 20 Jun 2025 11:51:19 +0200 Subject: [PATCH 1392/1594] [Java] Bump `Aeron` to 2.2.3. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 710f76675a..cfc804dd83 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.2.2" +agrona = "2.2.3" checkstyle = "10.25.0" commons-codec = "1.15" commons-lang3 = "3.8.1" From 6349140e35d5de2e580a10932eab47d818c6da7e Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 20 Jun 2025 11:53:07 +0200 Subject: [PATCH 1393/1594] 1.35.5 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index aa69911fd7..00bedd1702 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.36.0-SNAPSHOT +1.35.5 From 0305c5535304cf50588fef3c709d7b354f49a0da Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 20 Jun 2025 11:53:18 +0200 Subject: [PATCH 1394/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 00bedd1702..aa69911fd7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.35.5 +1.36.0-SNAPSHOT From 752febe85ce13360c0f90addf656cd1c99c51ded Mon Sep 17 00:00:00 2001 From: Zach Bray Date: Fri, 20 Jun 2025 15:59:33 +0100 Subject: [PATCH 1395/1594] [Java] Update CHANGELOG. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50bd456c45..8d8faf7862 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [1.35.5] - 2025-06-20 ### Changed * **Java/C++/C#:** Fix a bug in overzealous DTO validation. ([#1073](https://github.com/aeron-io/simple-binary-encoding/pull/1073)) +* **Java:** Improve JsonPrinter's conformance with the JSON specification (e.g., escaping control characters and using correct delimiters). * **Java:** Bump `Agrona` to 2.2.3. ## [1.35.4] - 2025-06-12 From 13a817f2de93ab5b49e43e8d490a7fcfb8d2038c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 24 Jun 2025 13:50:04 +0200 Subject: [PATCH 1396/1594] [Java] Bump `Checkstyle` to 10.25.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cfc804dd83..f756f6bab6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.2.3" -checkstyle = "10.25.0" +checkstyle = "10.25.1" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From ac59f8ef5ab75f8e10f98050bf9aa86dde8478ff Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 24 Jun 2025 13:50:10 +0200 Subject: [PATCH 1397/1594] [Java] Bump `Shadow` to 8.3.7. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f756f6bab6..42006b8ffc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20250517" junit = "5.13.1" mockito = "5.18.0" plexus = "3.3.0" -shadow = "8.3.6" +shadow = "8.3.7" versions = "0.52.0" [libraries] From da6a8b46387bb233947ac5740879dbbd2936d820 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 26 Jun 2025 16:17:01 +0100 Subject: [PATCH 1398/1594] [Java] Bump `Checkstyle` to 10.26.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 42006b8ffc..df856dc33d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.2.3" -checkstyle = "10.25.1" +checkstyle = "10.26.0" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From 3b286f60993e3d8cbddc9857950dcc6c3785d2ec Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 26 Jun 2025 16:17:08 +0100 Subject: [PATCH 1399/1594] [Java] Bump `JUnit` to 5.13.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index df856dc33d..4af934928b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ httpcore = "4.4.14" jqwik = "1.9.3" jmh = "1.37" json = "20250517" -junit = "5.13.1" +junit = "5.13.2" mockito = "5.18.0" plexus = "3.3.0" shadow = "8.3.7" From 4cb504c7c9eb1742913be853f3859173d075c5e8 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 27 Jun 2025 14:55:54 +0100 Subject: [PATCH 1400/1594] [Java] Bump `Agrona` to 2.2.4. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4af934928b..cbfcbd0645 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.2.3" +agrona = "2.2.4" checkstyle = "10.26.0" commons-codec = "1.15" commons-lang3 = "3.8.1" From 041c5bb948676b6d275388d151068f6107f3f658 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 27 Jun 2025 14:56:16 +0100 Subject: [PATCH 1401/1594] 1.35.6 released. --- CHANGELOG.md | 8 ++++++++ version.txt | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d8faf7862..b9e90464f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.35.6] - 2025-06-27 +### Changed +* **Java:** Bump `Agrona` to [2.2.4](https://github.com/aeron-io/agrona/releases/tag/2.2.4). +* **Java:** Bump `JUnit` to 5.13.2. +* **Java:** Bump `Checkstyle` to 10.26.0. +* **Java:** Bump `Shadow` to 8.3.7. + ## [1.35.5] - 2025-06-20 ### Changed * **Java/C++/C#:** Fix a bug in overzealous DTO validation. ([#1073](https://github.com/aeron-io/simple-binary-encoding/pull/1073)) @@ -94,6 +101,7 @@ * **Java:** Prevent collision when field name is 'value'. * **Java:** Preserve byte order throughout IR transformations. +[1.35.6]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.6 [1.35.5]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.5 [1.35.4]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.4 [1.35.3]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.3 diff --git a/version.txt b/version.txt index aa69911fd7..21cbe96c2d 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.36.0-SNAPSHOT +1.35.6 From beea0b2cd0ce83e3a24262ba8f37f9d945be5c72 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 27 Jun 2025 14:56:47 +0100 Subject: [PATCH 1402/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 21cbe96c2d..aa69911fd7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.35.6 +1.36.0-SNAPSHOT From f91958164d86371bf99e3a09d730a4095b58ee45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20L=C3=B6vhall?= Date: Wed, 16 Jul 2025 10:35:34 +0200 Subject: [PATCH 1403/1594] [C++] add getter for schema id on the IrDecoder (#1077) --- sbe-tool/src/main/cpp/otf/IrDecoder.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index 2c497d29ad..947d5c31e3 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -137,6 +137,10 @@ class IrDecoder return result; } + int schemaId() const { + return m_id; + } + protected: // OS specifics static long long getFileSize(const char *filename) From 84193793c901cd6143ae6f9e6d433b5f421b4299 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 18 Jul 2025 10:58:09 +0200 Subject: [PATCH 1404/1594] [Java] Bump `Checkstyle` to 10.26.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cbfcbd0645..66d5b6d2d4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.2.4" -checkstyle = "10.26.0" +checkstyle = "10.26.1" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From 761913ce82241a3bb911d0f24cccf90662e0e6c6 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 18 Jul 2025 10:58:19 +0200 Subject: [PATCH 1405/1594] [Java] Bump `JUnit` to 5.13.3. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 66d5b6d2d4..946d7cd310 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ httpcore = "4.4.14" jqwik = "1.9.3" jmh = "1.37" json = "20250517" -junit = "5.13.2" +junit = "5.13.3" mockito = "5.18.0" plexus = "3.3.0" shadow = "8.3.7" From 7978f394aeffed1e9978cd895747d4b9cc8b77f3 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 18 Jul 2025 10:58:27 +0200 Subject: [PATCH 1406/1594] [Java] Bump `Shadow` to 8.3.8. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 946d7cd310..fb3d1964ae 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20250517" junit = "5.13.3" mockito = "5.18.0" plexus = "3.3.0" -shadow = "8.3.7" +shadow = "8.3.8" versions = "0.52.0" [libraries] From e93cc1a3205496e64769acdc9658af4373242510 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 18 Jul 2025 10:59:01 +0200 Subject: [PATCH 1407/1594] [Java] Bump `Gradle` to 8.14.3. --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index be2dc79a8a..7705927e94 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 66c4dc1153b69e78d284198941848c67b38eb96c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 25 Jul 2025 11:52:55 +0200 Subject: [PATCH 1408/1594] [Java] Bump `JUnit` to 5.13.4. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fb3d1964ae..d892c475d4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ httpcore = "4.4.14" jqwik = "1.9.3" jmh = "1.37" json = "20250517" -junit = "5.13.3" +junit = "5.13.4" mockito = "5.18.0" plexus = "3.3.0" shadow = "8.3.8" From e3d6d4b20ac03a7719c5d52e7ec217b300f5b120 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 9 Aug 2025 13:24:16 +0300 Subject: [PATCH 1409/1594] [Java] Bump `Checkstyle` to 11.0.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d892c475d4..3be9f4f5e3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.2.4" -checkstyle = "10.26.1" +checkstyle = "11.0.0" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From 547d5330786a08b3eead10459bfb85f257fcf1bb Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 9 Aug 2025 13:24:42 +0300 Subject: [PATCH 1410/1594] [Java] Bump `Shadow` to 9.0.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3be9f4f5e3..0e11ed13a6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20250517" junit = "5.13.4" mockito = "5.18.0" plexus = "3.3.0" -shadow = "8.3.8" +shadow = "9.0.1" versions = "0.52.0" [libraries] From 99db50237bf6cc50a5ab5559818871685def2ed7 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 9 Aug 2025 13:25:07 +0300 Subject: [PATCH 1411/1594] [Java] Bump `Gradle` to 9.0.0. --- gradle/wrapper/gradle-wrapper.jar | Bin 43764 -> 45457 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 1b33c55baabb587c669f562ae36f953de2481846..8bdaf60c75ab801e22807dde59e12a8735a34077 100644 GIT binary patch delta 37256 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 delta 35551 zcmYJZV|bna)5V*{Y~1X)L1WvtZQHhXxMQoaZ98df+je97^#6O#xz79h)jhM;%=fb< zejogP5xmysJ1}Y-zK;P#^eNya^!*RyrWsaa*o?`cG4E0x(uI5*J=Ql{I8pVHbrf*&ViJbv&0$Zx^9HzKJYQ+2@eUCip7Q~vv%wZxh=X(hybkQ-d%4h08A3r-BgR1yDQOhGU!yc)KY_R) z<~z-KN~9P>0@{5up2;>ZO7$o~VmdL?8yt&VFrbN!Ax~@SD^gB(*;lok#cYX1yF0ri zTfoNS4~q_qcA&~muAcevb&3QXO?~0wIJt9T@@k%iwWyg|@`P{EtB0FDW2TTpJ449e zuN$b!Af;6128-YK{g=RgMOrWWfwmiBb%I9~ClxAv$Tv$EFuBIYWT39uPZWMY_)u>-6QS>Dpp%(#NEFIeU zjJN#v$j{|sq!va#kM7Uh3#%b(XnIqbX?K%PlWA%C!0rz)hR9!_CvWd*YWqemcDG<_ ztH|`aB23nP=k&Rwy!(xW{j|Wn?pi2hNM1G%1t1en-wK?TTrRDhBR7g@m1Q#C7R_i_ zL3gbJo7pkkx%%3RHtl+`z|2k&Q(IqCA$2glZe)H(AF@Q`UUFJnn$##p$J+Wg29V06 z^$W;@!nT*;@Fm6WWuq~~ZbeD|5ihjEEcv%uhGHE&8e;#tPwF|FJFRb1H*J)HAb-%_ zATZ3|un`ABE3ffkn8#v4L?T+D&Ath57i3+NL7H6VrjcSx00}9XLCoNTea8^xLS$ul zj~YlyyKT+NZn9!<(nGF`y+z)ulWL?2y{qJxmB*f{ug(}O0}n4IaigLNKcqBbBr*t= zAbGz_({CW|vYA*MC0CMUm#7EfqwiX&)Q#eM9U657>_Z_=xQ_KLM zO%6h`rx~)x-7(vp@br}&k(TFMBXDg~(68W~7Id{DO7>I%!1Is@@Z$NA0*S#kM~}+M zO;#+U>;QsYyR6@9itLyZXt?aMAe&1UyFw@2JH?lLl_gE+<6YSM)@Ls;5 zX&SY^f>-?i>qi@tYFRsQFtCPi5dY~o7hMQ=A%`xA!7Ch4v_2OI`%GK?^Fs@VApw2} zQc^|&han&EY+T$iZ))h?oVJ-iFcS2P_&EdlYjyzUIxot79StR&<&wfumAu}Bs9%YpbNZ+1Q6_U5E>>Jo(Gcc?vo73mT|MU zjZUVk4qN7C;+OIaIiiV369ED#h6Bf;tb$G|3w$vB9@Xu`$R4ZvbCmXCj*}^O+=%@F z?=UU%P|G2nihG9%jS$(?h*>v|@=Mlj^g-^oXqx>TK_|sk=2c$Oy!7?DbCN)O^j5Ja zz{rC@_R^7N3(lv$2dGRhkafdoB)-0To|uCK*;$MQWvw&`~J&*b;AnbCAg8}xm^Q^Ypo+fh_OqPzc* zWPK%OH*$E-|C-La5++UiU(+>1{?~KIM86Uve~<&^=M6CY^aS9WD6nq)uraZ1sL^LQ zf3yG5CeC$~Vv=FGYEP}28=rH_Wqf6pxo_YXK*uDxxt$y!H09AXhZG#cTCTkC-a5{_ z%N+N9-9Ij&2NQD)+FiUmcCVLTBwkJp)>R@`@l}*9Yd2O!N_+zuTc;?ak-CRawvt;k z^zi~^YhZmxD>SpY>PBSc3m2?38$48*!Epy=%tQ!zr8U^!w1IVI>7>_GI=Fd7wc{Y# zVCxmr1UiIe5`EI?@3BbcO$i!mIZXkKBc3HkXM5>}@Sv#ulzG$CRGIiCSrXn0jUO%2 z%qFL7?!3E?^5LSxzZ%b9UbO1!=<`B$bqax(RaPih2k`E=37ylvM0v@1i!}hfFH2}w zvN4&MnPa5&YkDRf!YI&JbZMmYxkFo?CzP#){V*K`yvg4bB12^1P-ArAWn@og8pJ7{ zy>T8}r;g02H$f}sj9NjTvesSpv8>v?J?qC)J#KIT40LBAhIPXy_OX~v?1ArOJy zS?%=pXOb4ddE_iQcSy{>LEg!ldXtnK!TlE;VI+vU8O^`&j4kL8atsZ4XSD~#g`Oy7 zGeqF!ev<8TyfzmZbk;|X0~V2gb_O) z_@8OloSoSzC5RX0@CzBks;Dq5iQ0hyOD%F5+l^6>C-0{ET4N;K8!XeeGZ%@J-Dk7enSJ zxiQ``wpU9n8nmzC5P}3s(FoeBXGkf+k{S-V&gy@9;e{_NBv0L=|T!{Qb zcmbg?KO`F&&H99L0;=@mYUbvJw@i%PP!!X7-kRqpAVkrW}Z(P}X7Kut#HlOn0( z9;4KaiG_OrL*-N#+++{f|Fi@p@qK^}0t`$y5e3H*cP^%2H{CvQuOlDf63e=PD_TZ*Er2A}3kqg z;SOi^KKTtFvm~xW?E-yT+S`VA&i2P9?e^Ep;W8N8{ud%WA#Z!l#p6tFI^TdS?E--m zatLuAurYb^6m)i$f<38)L*6!tRLzz7JyexEo#5zHSdQ;Jcr8?=e>Yx%4t=t`t(49O z(Qdt&vg?Iuu4z5uQP{KpX8?1h82cjLX5+DUWdfiQhQMoZTU_7Ogs() z$Y5@4-O?}G&H*$|%Z)z1Qf_vwu{LA8sm4|TOxMcfxlpwYT~GbXSf$v&PVWDfP*~Bf zBjj&*S2=|F_lS8UgH~Ar&gHZS$3gla3sqMKU1XLSYuBq zC|pj}*|05*nI|HNO3`8=>8mw3s@OgK3kzgS-~- zA4}J0_nB-EjHu~K>{aJWO{7RJ@p(q(?Zof=u+?*Q71nl9MNkhA>8$SNiaF>*kfe9-5ZZw9$5s?X_wRv+66j-AiQFTAX9C6boKn)z=SGf_R zs~dTH*P?QqE2LOcv3qjg9_gq)g*=!pQR~e%#vNv(;L4<1^$%3%xsZbL>dFQTTTB7L zYJX{FIgt1AxOn_SE#tU=ueLfv1x8GC!^TY4aWf6AO2AdhCKRXWJ54saLUsu}9e?UIF{9wu)__c$BjVfHHJV;A zhYVV#cIZ5%7iJAy*D|&hb93@El0wF)$Nce4RlU%4s}FbBKDa0lNj0b?i9*!eliscz zodbJd(Id6B#d8UVh-(`Q;ednhCz)^jlD5p2xStUJkK;xI@Xh<>1S@qFad|%OkqbW8 znVl68ZQ*?W*2Pk+^~|laLAs~x#?dbF3&$%-@9lZgq1rG%{)bP1H0d|CU}c!^Dzb*B zmNfDgX?o{Rf5?QfzwnSI21 zkYHzU9R=B?O7mO6gH7q(FltF9hECeLF~*f%HF(3jjpO8j1^k%VLT4%(f70AKl7vuV zemQmc>s02~G!f*z)z$29iJA93EdehD1_jCx^f<^ub{-T7yt-^~5_>@qTbGwMJx7lP6}LNr(_prpAFt zWd~4xIkP1FMzdYf%d;^c2==XPj+g~5Pf#g-& zLgR>80`CNs$QgV}R+hyjnn!Tn^!A|Gzkt^;Sk(-{c6Ie$(>6cGjhBwRj57B;6MV6U zyBD+W@8+8^8|o~h6Ky`hPWl!mg*{7|`$dUGT&_U?A+-lycI%k=(ck3<-YA_u(K+?` z6GhRf$0LMU#JLrFB1u0M2>KU(LKmH?S;g@*4R76n57qV%1 zSR+cm4zfql_dUk+8De}Do~3@VQP8`qqx@vav-B0=e}nJJ|1xs}8VtkQ-oc40NO4+*oMypQV@`FbPBrinn*))GcdlkzS`|6!Qz~ z=|xUIk$K-iz81%pmo}fF5wuA3zU1}IKF-W`zMR(I27;CL8a&tbeC6NBSvxw*k2E)z zr{Px>re&`;;S;Q7v*^^&j$9##Ukl6(>kT!v`N_ zo;v(qg(sg1qnFN$u!z%@WY=leHXC-yQ_d%dU3&h8Ab(Q!4#hKMUu)`vJOzd+1+D~d z1GFL1{z4#D1;d6N!6+}RhlFAD^OKEb=o9wk89C~RJ#*B#{M|a$oWi^ULxBqZwPtYvb9qofWYm z-n-zqIruA~1uuY#RX?v|oB?YR{DRCPM+~$?ob@BF53nk;>w1POhuK5?hCRzHe&qwM zMXV+PsT6T%4z2MHI8V07A{{rfr4j?zBOSz8P3yxlfoavEL2|fI&TorKhD?!WDIw8t z1oMR*Ex3k3vm{4R@^X#CjyxQWdqw(RqYe1?a?AdEt)%|%wIY}}PD%z;v6i1#0Qh~! zO^SBJX8)#`7iec=sslMBIznn8;Xorm`W%w!8meT$?X*TTFoJx;{w#=;DuNF5=O24^ zgE&m7l$G<&e)7zDa@u-)$|39li!uz@y&E0XdM!vle(iREKZ`2ADwR~FUxO(gy zaI5`|_# z0pHNAj-FHF0G+}T$qxU#SCB|GLd_;1Ae6I)axC>LhcSk&!ID55;6I*#p`(v?jrA51j3d%qd;tN)@r8pvbNX_tH_#~N z5tdENu+KVm=kWn;p}ypq)7i}U^BLwI=oNA`1bm-#febi8rK0G<49$NbP#c5ue&Pu7 z3U!x7=M5eWdkTg~)yy$~Vphfo_zx%}xy7tD@1{-JKC=bGXHb2BK| zo-7D9UqX>ZaO6L)B%_lnHJ?-+HR)fpaLFtR?Ren&uh_ZVli996H3AA|AMSWCx z(%F_pOiH)=nDY;2Bnmey!G4Ggjhn&>*HJ`&5JI%GG$*g%HVdXiP=tA+jsfi%t65SQ zq?8j@cE+Bp9a)o|x@%LWY-}k@^@y9xbBTQ@;wq`faHl|ph<=HXT*CvgeQIn9fN?2% zaEpawYPn71V2!CJwB!yHSs!4SG)S#!H4Q&Pi<3cJFx~KaN@k1S5p^P%5s52rhuHTF zak86IyZ%nd?z;0=;0KE<{D*@T%0noMMfj_;lmuARJFca#WQQIk9MRp(lG+~PWB@`V z+4RgO(x)k=C=3^Un!H2>C|fGO=^QV%dxpB7r^@yI{)&PCy-a8-zEqw7u*N0&MhT66 zEMb$K|H3WCKF!$lf`A7eMEnftQ zO|p_WO>P0~mBVF3!B32v0Sid^A&1v~MkGk1t%ND6K=chQUkS3bjKks1iySv-xud>I z@s|o;A+Q&&EYuH-Fa!|#(@Xey=h)N!$kXid^6L}A|9d6Fv$O9KHF|-vj)W!UleoL%#wE7t;Gp<9x6 zlP(A-RpHA9!+c%*&DDaTw7I)w8i(Oxdr~Jc)^YfG{30!>_gJmt$q4t0wN{w4p`(IB zE9;H8xVP*6{uue&OfU8s`uRl2_Ln zkaBW*#cY7M3ei&`b2Ann*n6F<+kn|pSeiChX8Tq>&TAc-^w3$NL zVYFD*2}8aZH2~m2)l9-}UWDObZ~L+RygAsbUt1|x4!X#at|TrttAK*=jZFZsSUB4) zRU%4i@vTj&!83g04C;0fVZ!elG=`UbQfnxws6c^Jj8ERma2K-1GpNYyuvMWm*e_<4 zFZ*8cHFyuU`W+4*NJb}|{D|QjO3g??e)Hd^q|@S#`u*Pk6aGKM8%ZMoRQx|(lM_ip zP*Os9o#jz~mrOQ=!lVEn_$E>$h59q_|I>9$XNCl9GV(4x2hqbHnEL{%AtHr1;=zOu zv!m$k6=vYqhbN>z(sSR=<>O%O>-PF~E1t-i}gF}=)MYQ*u}$xl{BrHy={Y@&GH zY^eOuJu2KnU|P@SAyt3zwtQgH6T~S?epQugU7ciG^Mg|lw?YKCW-QG4LB3p}Sfdg- z27dlz>5oBeYyKrI!6@OcCmIIm#qu2StheP>>R4nu?I zJX#965ONPvine}|{x#GkJ(VXCU&jpZc#1RD;cL%H2Oy@ntD)gkdXIEdy-(nFwKoA& zKEB<=tRiF#E-caJpS+XqIMj!Hk2aSQ6*il?8sOPCYI4A3=o};dsIC0( zl;d>jysNuE)hP4MbRhdd+hu^uS@@}u%YeU6Dti4f~w4u_y-OdV|-qWIxu4wxJi&zm+Z`*e%3g|;(`+{7XM!8 zI>6wx(N55j-A424OTn?gL$aU6?r{&=juA0SF-}bGgQQs&@?vkfyrVB7^;R1P{`ct5 zSYq8F_%0IAw_iq0m+B!tqZQeI@T!PqYd8Zc+YxT-&$81~?80r}3jq-Kw6m5GQFz^8bHe!Tw8p6A5v?|G&v4YC<_OFj`et8(kd3Zy1t&pix4_hUScI5e=LO z3Ip}sB1(fY?x&!wh;-;Ck><+Zp-m*ID!u3X_UZj1y~m;TX06SdGR*2ICyy+)El$_nQ&f5ED0iBF!_aW8}C03bB zAa-+d`AYlG4icGOUBO7x%i_lRnWIgu!D!?Or+Lh*8!JlH-Nhs#---JNS8Lu9xbyp( zi=3)7GVBc|dDnRrjbHs}eT1<4s=@^xP0O3eFoqkj=Gur3C;jZ*^LU-!G zr&*jKRJ`b)QNDABj-aK1i%9+LYQB-*YE`!mR=!E;-HA5HyAYuMj+w$8Vd$bQI+a`% zBNviFF7}{{4kf%^Ngs?MxJFSRickS!an?y$;TN1* znzYVm@a+xh<%(Q71yt=WF6&CM1l2?@r}UrI}22@E%dS9)9y=L2PL;JFofWk(y`JSpqLDX z8`jpc2kNx@96s@MrU8K6%hFvm5_0s8<170FhOtjByI{uf3{v9os)~n=NJAO_0g1Zh zVABd%%;0+$Tz4F}mq9k)JX0wBgj|4%_~q(CJ#F}89%9Yf=qMtvk%2?vD}Q|%b3zGl zuRRj}rUz--cqt4AEj&XE(cdfb_LxcXJCxE9Q>oZ0+TeqGW4`5SteqNH)ie2OE?)C> zGmdGj{J<(1dsjwkSByP8Qi#9nr;(Di{|6(bzlmkanv_1s{ln8=tZ?++&C+cm2V&O5 z5qnmhLjzB9DDMC$&+!g%fZpeQzOuivZ;UL0o8mz8{0y~V;R6+pC9%{iKNB#edaaM4 z0O6a;t(SwW!?E^?-!0{acYzJtJ+Q0c07uB*-=x8?))4$@F7Xvs$dausbVP~M16O-& z|LGHA!}v^{v?uZN2aQN*0yRKy=)_+8Z=3GlecZ=zBgaY!W2hW@i#*L zG3Vt0S*qV2a*$1-J?jyVvkLZtBa%WSA@W;JSQ831TF zHx5%;G(+9{m^RQELa{DUM!OL-xQAyL#DXlSTQTaf>*qxgf3xC_th+-(&IDA-Fu7b#_o*gJKFMg|~NnuNAh zv~7Qb&ksZTx6lS{m$%8YIk%vQr=fd@?-X;5+UIr21qNe-#=m~Wlewu4Wv=M7{m}Lfct-P!JypG))+PpVMO!;aoe!Ey2G4tIji181H9N%Z5*!>P0%&9)kd z^Hs!}Q*DKeliE$PiF>8T%{C7p38Rv)Q*BDz;;HcPC)3LCvY;AN)^sPbtSn?`2W5v9 zbOb1ejHL1uDHlqHfnn|nmmhW*d6qyWiAXM7L>n4^?n0tzyX65Bw9YCtV$MG$u5fnSPCIzPKdidn!{cKt=OInFY<O_65e(4m6jj>(r+GP9S`_g_21ajkkIIA~ZBwyHSPy2z}M zn-v^#)4X19DfwQOA7nVAW-Zhlih~Yps=Z|=$bhoF%G&98-|oR~g+Won(9v#}up5t z5i8fYQVE~dd_2`s{W<2wHGTIVT98YnqTQKJWg6`Rq!VeYU)UsVI>~b$L;jv3yKkg? ztY0kN-oAMgldw=*G!p_#cg_;zApXv~vrQG@4jOG4gih|S%_sE2zmM`D`h**C=B_#! z23%l_d`385|8cZPLsDtzQaCJP~T z9PjnVf7sCGNU)XXpRw%z3uf^XYq`0BlT!TxD4$E^Wlf)rXN$t$^NkQylaxeJdLu(3 z0(Trc(u%FwC0AwPi5~@h5Ri!}p27H%IA}fYm?oYYwkQ5RO%G%FLsTMkMh&x1lJ`(A z`p=Enzmy+ey--Pm)<$&9E#pj38SO{oTn3Ev+XWsZk#yoYdKMFhX0!RDf<(RpA$Uhm z2ng91dQrV?@2-4n7(j5#se(a7MRjuFm2$>r;wJdhM%`_|)@?*$oR?`+*nlxxH4V|! zwYWcOX8R1yOiUP51^w2R_@Y>v2_r04&U)q?nydYlf6jvNMrTG?zH@KFD7A%p2E4?x zKyd~{KdR6>+4ebG9~x_Syayv0lyEJ+r2S+3$JG(=Kd7%2Fg4zWuMFD)F;yxkj19jz zm%>fxU3Xb9TtCM`S)tpmg-hZrvx;RQkRR4oCsUN2y|7}cAgi*_+(>?H<~EQFT}Eo(2^iFDwC9AkZet# z5#q&Qmt?l+QFxYOt6#!xe7#%SG`XV;8*A;Vz`aJ#Yl%X9^HsR^sZ4YeN&bkonEJ*P6MVr|jJh2uo4C4RRoavA zop>D5G0n?cjd0Eq!X>n=8c|MhZ%a!)4Gz)n`cJxU?l5C;mDuGYOX@iWsgO8D9JF@2 z!hD_J@aFY8h}+A;)lYm9L+n$qEIoTc?1;DNB(a z8>2L)>6rAXg-qsq?TKuWs8Q}vEjPw1XyR4qY?8`HMrCKW!+i?^f6$K^!Gi{oMuFB{ z3sLRPcwGu}dw&7)N1aF%m$ezL5SztBv-fTH(|6vo{1|3W-SI*%5-ILg5L4aQ4$!7U zFWMOO_BkIBCS2lSZC~L2ZkEj76ma41B_qwF?sjU z|04y*)sb?(||E&lT#$>pD6CWnNH!Fw((H;ycad1NT?yqe5d^?Y^y0yDtE z1@Eb@=|QUL6Dg-$Rcs|JcWlKk=gF`nLC9LC7#AOCB@v!OPeeZ@VI^XHFg@!30M@Z& zH}`Aem^%G99V1y?$1UANu5|4Oe(cWypx;HrAm~Pm*U&g^mBo$^c&3efTJQYK0nru& zpE`jk7Qkugl9NO>Qir$>7P%}u?1(1X5lzcIM&-KE#iXjeSgf%mz3Fq1anZ<|vZbjM zoq({xgU*zx4JmaG>2YBMSR{BPFm&x~Pr|^^`MfgdSK}J&%#Rb(Tc$kpMDJHEE2@d2 zKSM{yYa+*vvLgdCy-V1U`hULZA+V^by46N3F{#agLYz4` zUG#=hr0u_hMPfT8T*J+se_{RTmzSh|(WqxzM; zSfBs7)+8`1DDJe-GCROPxx#p;_w=>Pl|mSC{~L-(!^0-=PBN&37@ZApI0@R-6gw)KsEY5($Mcyky-?|xirLHS zW9XR{=TXubo?YMKgF6Qrf($ifB(Mq*<UH0{XTb81#ye;beWBetn$eD6e+qycgClN!mf#Dg z%>N&YA5v93>ibvOg8wQjE-D6O9g4$}+-Y~HC8<&WPF#;R@QqaN-*M2Me{19L#REq} zLq%F0=g(Ur9|$bEpN=~a&lDo--@c)xTDrQbx=v0!5$gAR;~3HnK~7Djhq;eeFHOJ56K3EIa+d&YO$3sACzE^b)+nbAM_Ua^30JqT$TiegvS$OGq^n2tqs%Ie17$;kFs;gc zPESj9ydud2g$?iG9m)8BY8uw=dQCF}(PU_iCIVW{_?VYX(_c$DSzoJ+QRC~Gu6opX zdLa`ulUY2;(_Z5CUd*>hHecxHQV9m?M3j{9tQ3D+zRcJ9Z2z*?g+hcpl-w4d7z_7N z>ZJB`lBv#(d5X8=mr0!s&0=l5LssT$ue`Eup}(dt6n1pnVTTf8s6#ddnp~s*&l}HL z@A+c>6^G!z;_!+q02S@$)i6FU=N76QrKNBwRN@v3Xy9ap5rQiNkkmj)XiH^+qVZ&P zxNk#_=PSEwa`7mg*F*i;9)`&4``PhJO15)D=!wl=EEhTu1sPzIDL(%s*m2B#?9&Z= zf4HjwOS$IkcSk0uRKH5IwX=oWW=oZ=FrLa#n>p_wh~4-Dq<;X{R?vZ$zgCzrOAY;1 zL0wtJa2ays6zZM#oBd6$Z20Y$`k{q7Rpio~XW!V_`CZn^9R-S;r)7LfpSzAe?CI-w zQ5Yf6fauLx-)e}}=nsgyPgp?E7NU`5xb;8aY8Buz7IV-{KDM6l^d^*21HImjY{k3`_gibq~f&{L87;FV|hGZfi1^G{_&M|VK1UbXzE^}wXWXvHo@5ZjI(%@UW2 zNVlHFJC-tYoVeidFa;ByulY32ktG+^p7N^s?c1#ab3NtdKwpc9Eq`w^ z*CYoZNaB|IN|2UvK@((bk8)l|*v5M^s4IQH*fryjZRiDrWA9*EkyGl#I1G$|FDE_i zgH1ug8)VFKX&qrm%XAEK^0n3Hn)9{@xrFcUh1QLx-`CR~$)F+V?N@gzv zmuVq-oA4n}1`4|GlBvK0QGm<*(AMYg&zlEw|2E?0$Xx5apBLGKQ=O!~&H)r-dHlxp zedq0_{0#2zDM+4We*9aoQD6Yiti4@qch$SmuOs$k=dPW6kFEm8o+bO`@5Gov2BgZ^ z>Oa+`F*~9#?BN%$e~0<^ZvGs))DbAz;;?e(~n8zm1*Xb`ObOfp6K&Rm}pt}`QLsK%fjbE z^>4p8_`mb*Z_>iRb)|U)4Bb#|X;^jC0bCq~c_Hm@y-uhB#CrY#-wgj=@8Hb|<4PoY zB?Ly15bnV|N5!Nln&IWR48=Na?Cv!VVvh#jwpXnt{oo|kIrlK~R<7_ya zfT<$dX82?Phi!HT$DCLZWiPAG!)a8N$fq&rg!ea4`L5E`Y_gBVu&st<*6)X~weIV6 zERyq-kgLiSa;ac*^+Zvcno7k;gvGTyA~#&!@zSXBi*1=)PV?G&+CPzqkI2qyN%amx zqyuxVjx4~v91TZ7?b2}tRCKwE%P#SGZ#^pY@i%X?_mNnu6I zx|-<)3UwM0D4#ghZ~0u<3wttP?AT}T0g}Vch{Hw}ytK`&SuwQU-O8ncSnZe=t%Eaq z*;!*5YEmY3vVOd6DC+6B&7k*0eq=xs;v|girvzhi4nCc@x^AQE7IiV|B zmDv%?DdMv-99BR?9kaEuwR`d*6}I?=Wg<01qR7k3FR=O@Ngp%^A+9BB3zC$%+k3!s|8zvD=&uc?5seXWIj_r8qqOLD|z5uV7zRkK9=Xj|w4D zUSkg5YzZA7c-i_!!R;_cfH^ZRu)M2xw_thT#I%gB5mp#H<$I;NSw z@(Ybo(*#Duk{I({!QP#Oe1GOYNNE3tb%7`UUoi59dwP8IFBn0E`u~EFL~I<4L}xjA zpgNono+|cNj|n^XrXA60b3jpJ3{hU2+x$99fKZ|y5e!jAAsy|~=;gRs`evG`85>Np z*H1nF2yt3f#ZIb-HP}rSkz6ZFOk|N85z)anK82fnKYKIwO;YQ>@^|C*Julr)-TS`F zZ(GLG{Lc*jt{meI2RpslLlBq{QZB!(fprnZ5hn(szM?Af#S6hkW$iy?&KTufg2-Eq zoV4(iCJbD{#6u@t<|-|4RM5z3Y9t1OB!6M5ghU0%W-N&<+ZJ|-8OHz_vLsM?@st9s z;SRNQ7CG2eXyq1A?S2)8Gv%g-bp7&oexR-7k70QXNp_Ww>B{9jT6Nsq?=|I_^peapI zNvyZH2QoT6n7h^NwAJK-i@WI?^!P>vc)wfbEj77TIC8yV9B+R0BBUDzo(+}?u?9&u zjE+0i-!b`t2txd6MzOVgt>s+l9D&@3n z9E3$+Q`j}IRYN+r5sJkLjx#!v1Z!se;FEZy48OJ+Y=)Xl4Omj8k86Y4+ftjSr=fll z?8_H**ta6|(ID>D0;GQdV+$V*aQn+cCLC`qL$TKD=3(f6AXM4%>G&fIs&n@jC9MZp z@z^>f@UeBX+9E01l__>?KhIDm%tq6}x0WH^@(DMwu9XxjS)QC*j=xZcGCkiqB6|UT zD9ZFLlq6sz>7kY}yh@NNx}O#w_S=O%8ig)Z;mYa77cCpdYOH1ebrma#2=(^ReQ1&JHOs)BKK?l8&dw+`8|qy)nPosH{NTwW{{1YGuFiRZsibY+9*Xv)wRQ&)qmrJhxUU{rctQ`QrP*?8oHl>91P-P(P7?}mpv3Su``@mVTy^(5Zc3cq z?kz^?E^vdSo$+)zZFsbntf=UNUuN`|7|SBz26IM;z2Id`J(^}Olp6Mf>%n0y%2=g# zx*q%714I3L<^{?Idm^@LxtIOiS>WDSLF?b!f;&dZ{EXAhP(g zcAH&IB^6cHz>*E~1SL;(d;1ofH~nmUFwGKf4K)_cMHzx3&@XXwAG$HJlu44b-v?RE z!iNA?DPeqxNM540_3U)WjIz1jgZrpH2Z=ry0Qgs3qSrN1IaIptQ6@#r5`UC;7e_>_ z0ybQ~t8mw7vv!~F0rIg38Xuk0liu!#u?opCWD^+$@Pxo80Y0(Q+8Eyj!1xSlw&~$1 zjgbc9uo3wdKWe5Xfgu^@awCgNn)%ZhfywLo=Yz>EO~#1AgFe&nme?6zNNDHpp?(!D zlS4OJsXNkNkCG+*?oM26hr5eVg%@e$wEEq>Fz6Vg(Bj~fuZVoqQ?3!adu_+%nTp=& znS-{4Kz42diDx|F+3X+41mjLW60Ul&D2dD2@{#A8YTE=rmz>jXPo_MVgQ?e;V;|jH z_`PCq`mS_EDUQ+;p@$*w?InYuqFz8Y?Y!n>!NMy&0A zWPsg>tA!#h6#RISxT>{9K%c6t<~;4HOo@_9!~8GtMn^BHk>z`LrQHt-c7!#ugH0v= zVquYF5f<4RLOPtOB@W4=PvepS*ax1h&bx-ce^AHxbV%QcwKenN4>boXm!JpCb>v#r3gw^ZjH(-u!CnsbT?%7 zg~XQ2Cqg^T?BfCM>p4Gt&K1F}Xt zh)9g&_GHa&Nti>k+l=lM$yOug%U&WvXGmF{pQ%IZd~?q=K|8B^v_uqtA6=6yB&Z9a zDQ*c6B%o}_BOJHYkh>!Jrf!goWU6D_s%t;}c}?BOjY4yBEhK^@=+A;Q>rr(E!5bV2U!P}6@{1@%8Z zpZ<>Te2DLmXlj2DPV5wX#x@~*e*YpTW85X5mK7tGrTbEWj(z6WeMh;R2JXy~wR}bW z;lCp0QTqEO^gHYudx5Duv^>fpI@}L?r?;MzUiQ?Er`cO{6QVNx9`2o6p!PLi^7ME; zjkZlpGAF3OoUo>*3W00L{JI~G++vzTP&*jnpg{Q<&aR&bmtbg9E1#kum6Xqa|*7kYom2Kwr$%sJGPS@cWkqh z?AW$#+qP|WY<29M{=akT+^ktOYt5Tg>tfb;$9M*JV23Ql9vo_KYkASyx6Rtox9l1L zd@8uEkzyY~iq&8-h3lS*qR-m5Zr&mIS9)c|uQvwKzrFv-E_=lXB9LYcVEJomFcPv%WsO|wTLrX#D#BWQ@(!Pl0 z(OC99`(1v*g7REkKN1HziV&8B$32B8J**q~3V2j*Hd|v~`eTI*8my5<8|kJO3!Wl& zlopfFB6)00Q5crg&J}W%w&Z)NN(K*QnIxuR_@;$ed^X<4g48i;Lct>kJ9V|>-ntn* zI0Mvo{#~kk)1>ogX8ye^u9vs=1uBSBY95Df~Hqz8pjD&ak=m$4H>HI4#_CtJ!h!rpbp6mC@l;-t_vUqeyHI=>R_R7d)J}0!> z|J#s$@|M?s3h94hPPNio(t2V)004yZ#y4#iGJj%eOuVAYOkylHmDcIBY=B{iYtd23 z(A;dwY+^?+eb19~qZ(h>&aUIzW(n<&LeKg6b>S_5)oHks-*7e z)*oJd42G4t`OaLIZx}CG`g2u#b?NDaeg%1BAUI=|4 z*-Hp<&2RHtYhMT6lmjx^ z@w2<0!ln%K8+IEkQAVq3wlsOvVoYQX#VZ}OxlKqtE>jb6PEW}p&;XXa$~ikI;U$^M zPPz0)kx{yfbR~GxGUU;gh&PIiH^r5Mnvh9Mu~MR|l4q<;kL>87AOn8-CeIY!r+2Bk zn{@b%o8oqN@|x$lg4)vPl`WvcCKb3&s0|+WrwiQ1qYstQ7AP#Yq^2ywCa26_7$*B- zYvvnmaZRF1cKEn3L)1fj>(PKVKbunIGm9sy3)pf zgzO6StB^#n$_GPPTc4sPYb+MaC9^%7T7k-z82vsB(gz{c@av9Q(VPRoVm+#?#h*D* zYQLa{c~}-Qd|~9ddXi={b19(N572cliB{8csAg8LWCJ7=GlBZ&$lw{4jq*)8vS<1m zR<-^5*PjThmgz^ZwxM9`@TTzKq3Lstu&(~KQG!WJKb1@y<|aB=Pg3@ZvQXUT6!Kr` z(lv7MP-L?R`w#6l_iP=50=ir#OB9Ktm&QiFj=EG}jUH4JL2Dh3DTWAIL~uL4OE+0e#Eq(~z#-O)uKPtE!u z;nDejaT`8BO^FE9T~*WwE7@aPKnHE84*qK8;qcayJ$~4L47TfoaTLItB!_(~r$2$W z&*Op>w5K1bclDB`EJPrK{D#(DeNsHt3Hjra}({;;pkN3_H2ic~7A%JSZ`pYuF zDjc;;OHp2#AdWbZIoDVsp9Lc~3nxzKf|mY+2T7-MG` z^sZ4^qEaaEEvmG0166~k!qFu;hcDs}j$(x8GmqIcK3GD1PMpAO#rZ*6fuFf%38Eyy z3P9Fi{rk2QUudl{N!I8H5N^$Ep@Ic$0odvw(f1llL8a0;^V@_4IrP=4R6?w+rFoj9 z5Stn%9fzB9L-Tc;Pi-$1VIX4qs#K~}=QF-+pLK*4T2_Gp{yPLOgW41NVg``VpoEDu z6Jrg-cRs;C2n%Y~KUIaXM{c(4f#MCe3wu1SvzEvlaZ=S#KledOwdmf1?@Q%0p z!PQIQ^c-&>mCs!Dq!oM&m@mz-z!1znvjmuN{?fMV6`O^#>x~38a->UZ_VD?!Zq0KZ zKz-s+`t(y{$Y4uWs7`hZDZT;@J0A>mZ*=%;ZojlRY(0KF%`v> ze)U$D>dS~*!FLKwo5^I9v1W{qihO&QMJEF9t5x$-ZlbiC2bL;}iJ1=P2E&toGJGn; zy%-!KE!J^$KS0fobx8q(>gULa88DYGiiH*>gUs|Bnh-eS#;6@ zHNN~v4Dx&7=sv+%anI}u=de7^fKhX|V#oo*}Yv zlo=Ig5JpbsfvKh%YHp2^)aVgCAG%$}5}au^Oly%9ea>n6?snX)vtpuQa&%+Cpuee@ zZg0J7=s9PKL0C1*bs3yExahoh=y{ZfV2%CCjNy@sm_r~(mF&E9w51jsfhnH}x-+sk zg~J3<^92=I8m1#*dm|(aju%-clHL090^u3= z+U8>Y#qJ7$9)Z4{i1lb@n`?oi9dfjD;4-&!r+_i$B^&%IebvNl!3nh9mGI1CQMmNuwpfl88ttWh0JF5r68@ z>H}dY`Ms3a>#&jDy!bIUsri>M`S+_8d!Xq|BsLh>zF&92>1FflX6>DzAhFp_VVH2+ zu1NfK22P@^JPv9w&^k7zFzr(uY}n`4E8a{aWqI`B(j>RM65m)&kPE+8$p0LW5L-g9 zY}S9snvosn5r;;YXPls|3t3JOsI@S+&q_7PXUtQ|Xe+gSyNJ_3DoYSk;Z_uL02d(+?X zV55OIw}}SUL2WjA#cqm2!En8*F`H8|u?Qk`bMRZOCzA!D-OJq`v07CNUXXZ`*9P`R zM=R#IM}r9%cY`4#%;I_yvOo5khrG2)Yqk9OVI<-VEYiA~+eYGSp@igJEU}}2o)Wxn z8}=VV$83+i2Lpv#jNx0ejQ8&*RC_i4h&#>6LGLBRWI%W7|0qAUUT!GUrV|U+XS!_*a zaOH|~G#JTYmnN>0r$bsWddlt=KPWcos_5{SViV$<9cl+>Z#C5tUMrcc#8};=_GnLBtooYi|QZ_gkW!1xjoi?a3y~aFr`l6 zbwU|&Ce8GcshcEr2$B~7GeLmKvt=JZB$&oXHb|sL8B`Jieg>WhePs&)&xv+^Qi$%C^~M^G8Lu5L$uX?{{hXgFiik;j~YENafq6g zAu9sgmwZ0l%yuHCEhZBs@CnmHn_e$Z=0sMuYsu)lLuss`_Cai%eobRe7OPw(IjGzO z@jL{Yb<=H;sq#`CzfBiF0w4Cbh?h?At*<{OgW@uWDC?7-hI$#+1)fgUs6IqgHfzc0 zY>jxssdEtPNu}r?;lL1+bv^>PYB3GhE^QTu8%)T2^fIv(G`WBaQJC{6P$0_%g&@^Y z4u9msMy)77SNI&sH!qP1ir6h@rBW^m&~Y+WhNY0bh$lxo8yq1a&wDhLm|Cw*kqu$B z40LIy4W@vXu1O0MuXPEA4x_b1Qyn!qmy2LB?{Jm0tK?8pb2ikOtPuv1>gnbHc){p2 zO*A>FQI9FOoakZS*!3q*OW|vWd8DmUdFS}0GL_+BKkM3BHH)hE$&At`%V}Ea7C2pg zEVz}7fOsQ$kAg`y1;G&0y(=!A`6`B`cW6T_dUwQLpaM*hLBrv(kSAvOoG%uqG3WuIBy|iIT!O1oJ)03*MIhZGB1s3Fr zbadADOCGwu`F2r^zk@iL#U;v|X1O^eJJ0W$ER!}a$SThxZgg(#bxeyI_!K)O%DEIZ zH-TgaOOWmHV`V)cBTbCz9fh{D|F{lkoMhjmg+?BaWYk>=P9e(|%A=rc?3w(m39 z153$)_r?usuh94dxK!v7e>V5b^ZU_67jhzI)FQS6#5wR~EZw~BODiXbTfsMPTxsUy z^RAy?AiK0SM32mzuJzeFsFz3aj}5BdGRS8O0^rI?-}>{-JEw;#E(YZ69aBY^ zn1@Q_v*9CFW zVh|ffv3|fiEhVmZy@Q8eOE)}PuNTU1@;Sb_r9$D|r6evnUrt%x;v%-3`kw_vOiZDA zHI&7GzhZi|JMZVxy_En*eLC`L4SMCl2yqP>5^J`5Cv0M03V2X5bA^5d08JxPr0TE6 zJ9Q8X3~W!czn$YZ;HsDS#?8O8u0c);b(Pa6@3(+xmy`Dc($=cx;nhA})U%O=@)H70 z!gKe36Zj39%nzrWePz*mFUvH7*c9&&mhfv4qV+HkKF^91Iutoe6m(0eY%X2n1oEfx2Syu zr)+`0y|-9KvbitV)g$Kuq!@Q!w&QX|1$P8Twi_>J8Z~tDNJZJuF=|}}cX%cQjPZlv zfA!zcYVY~X+l^^?3KW!66Zo=6-EnxX#PH?do@lWHgk~lS3h{}K{L#G2tg}=>kd||I z>FHTUBoSlo5Dq>|vTE z!a0fUkIj;o$q~}7_A6DKHpn?q)VZcOcm&Uq%~I$Uvgp*-!hBLyxTS^`Y1SZA`m6!g znSK%FUt1lZ1(s24tLo=SGAqlXArV!9Y=|5dTGY z@tM;>6O=!xIx#7HqCaJ02L2^IU~q!1L?`jr>kOC=f$R2q8Uqq#n29=I%3|7c8#1^UYA zTl^7Mhhs$z5Wox};Hltx!_dL9_6E%v0R3 zEEUgfvPN|S?PG)MbNjKE=vIrH{FIe3;3&WygUORaIo`A15ez?Nt)Ps-8`2)3*^z>| z=maa{GXs@Pb!1-L<~-%O;U#$RQRC53xfQuB8NOAyRat!ka9{JXbFl}upmnW5Ks)*Vvm|Rkw5j^@z+1mSAjW75|q*R@;jajWKYd0_I$vf zHc!TMpiq~|CC+`IR+k2rmI1sHFnLqvJYzr@oT`X>3sYv?+2?;r;_2LRH`c18fUt;?rN)Vs#o3wXCbq-q>HD0ZkXnKV= z4~0ZDvDfpN!tuYM{wJ-Ds)LA8V1R&3(EKN+4?3~{5xjNOF~0v4P5<`sdAI0vlYL%x z#dEP;vkNQgj z780N;EaC!$GQ54N#JHH_TF{&GuQdq`(t+y1T!)jbd#~u<}pFG zqBD9ID8YtV@uUg$yW*lU(5-1U0z1ZZ)LWU)WWi%ADotXbXk4Fc5AG?WKRVomUHR&U zg%qZ-r-SJ-64ysC($s~EiwTy|uAuoZ#rmhfxKt1%YIle|O1&Aq&9EGs-S7Z=$9NQ# z6jn5oC3lTcIFpH8MUPrA@*MA_3BN^66KP2w5T1|F4t_LRX~^a>7SG4WtgD_Q#UV<{ zWQP<20yL2eJ2Pq|3Eu|+Hy#hbi^bnUXUiUGuGFyv zs=_dlRSRfv4U2-NCW4bz*a3wN1SZNIiv zc}k*sE^#t)Yf8e%L@I?j5#UC=T2~+nd>$>c{6KrP?ue02n=)X7*y8A_g>U4bE<>fx zn^XNLS)#YV1BM)C=UfB@c!Hu0lr&BNcLU{eR}L>ns!Dld`s;Cz3ndKC%f=8xov)jU zFksRhA)0Z|wYo+3H=@gUb^;!pP>;pH;H-~-Y8&|@q5cqzkusWkzuo=CB?(hPz`cOPUU@{ z45M()PR?OM;zsDv36}4{XVExZD%+_zU}|UTdxQ`agJey^tjDMu8x|PL4zLu$YN#Gg zac^JT1)9~8(h)Q)vlp23<5n>MMWJSj`F4!8;!U>rBliu1XiR19DW*K3>ssz%XzrlZ z>T(ilVxdTbppRZv!VzCpPZu11FculZqk!-oio3sI2PW~mL@}U{#S>!~Cukrhz)*U< zxCP%sG5j&rFpOtuFI$Ed@FG%oFk7y$u$qAmQi%D5op{MqZbv(24&Lx!*2v}}34c;b-T$3oHSoDKtKWgWd49pek zLt5`4Qs$&G#?tYz)%`$9orWSPjDFtp-FZ21nU^{^iD}BF!L^ne!z=uimewXs-5E|? z@OIlw`dih7KMW-Wc!%tnx$FgKC>@Q;%wH}cxmX@_QCM$Z(K28Kqgp?cY-naQc9=nh zh&|$=)|T=u*mLA3QEGFWmidEUg@_(j=Y!nrpQdoI8&} zLX*#V{^7zuO0pT8o48>(q%b$e)P}PbY>*Ji;Kqtt5wWfSR7VPw!`Kerp#>$FSjVD1 zyEn1oWI_Lk*w111nre0&Xwc?3*tPJUG8mY|^^N`$MR&3;3mkI#(&^#pMMFlQ)u%Wa zI|?GWPmHfMb(FZ)UBqjBU#vbRYNJe7C~-OU2rR540+MH5{S=GhMaBRYB+R5^w2rfc z_FbhFTCtA-i&}46Bsk8qZGvSF(5N{7VKe-!ZAbg9lG!Br{tW+#yyfcRYT=Y=hy9X< zq(6p_U(K ztjidkM$kB>?`bO@Z}U57#IO6Bxt+m99z6_(Jkcw%ZE%=mbvf!T(S=1??l_skWfC!6 z<0npNUtLzRE@7FZ^|E+-+1wC1OL7HFdW!S(De8$!WBaormcH_MW=SlK2|2qJHzJ>q zDq5onP)IK=bZ^YF^t~eAnY5$w`{N=FpK4^T$%kvgIr}1H9wbR zZmn7R{e)BH=}nr+*H|{Eeb+A{h8wz(m#j2nfK~?CQ9K$;{65Zemx)n)zz2|bpvTXvK-q%!c}2fB;1?K4va&bR+O*|=0usSt&VXNHWTOV*m^?9ezvJe$rFiV1}DnC2tXn) z1KE;xekCl(%Bgs@|8SUpW0lLtdWPM%vg{2#t=i~&d)x^iC@b6aw|wMNI@|Qe*%=^6 z;|St;_Wzbqif%vi3Eq^Zl6E)H+9z$EWWKo(lD`fh_p$;9TFS&9pihdDCZ83#eg2e4&ym1V(me zr1td8c?L5=B6giGe^hAtfEZv(0d<+`Fh>8bu7VTh$GvbgeBxhGqz3ruTFnDGZ?4bby{>^hk5gC?Yc3$5#XC@0}(3o=(- zyUzILDQMeTTxKDsEcr=eDla3q z838_;pIx}C*~QLY_)yLWyUwN`yw6O^-5D}u6LG8$sKevXS4>Yk(1ddng?WkG(k~7y z&`UzSKchFWBsJ)3yg2HDl#~2mdYSmZahducZ$*^mE7hDzy{sj_0HfBE2Goe)NzjNyqY%)p zN@1sc8>-w#cZ_e7S*RRtPS9s+k@afCPI(}y*Iek{_pB#EW{OB9?=|QeUUH4Tkaz~K z*Igi;-`}|IP`{H)@11rnJxpg6+Qm)cS3M5ZMUu&(x#!c1mHM~Dw&%qC+st+9CiN_t zx^eC%`M305c>y*59R$uk`u{ulo!_Z+Cl~IX+D4a_n&bgGwFtw{m6zbBxhn^{tI$@D z2=Q>pRODU)rHKmt2L!_%rOX#xo?ep0zlw1njkqA~6c8d^!;yB`0YXtjETdtLYZj7@#K9xF=i2+v$$dNTYGsQ!T&38wBw;Nw0khstDzRxOlfbe&PprTCN@8W( zR@S!sxFjEId`Y!k(%BqXN@!!pW{oR!e^s+WzZUawzNLa+kv3MwZPF|`a;IIz#o5A% zs~_q04~8L{=bi2%FDxmO*yr?1REWKyc)XX5Ret=1s(!j?MfT4tbFUW4AgC%=1CEncd;5chU88@|&4Ln&HFSRj$tr>U-(rdEPNy(THTacB4qxv+? zOu%42c&+mmLtftxwUwG$1Lo$hsIv_=vs}L)0BkLE!T-Me&m2Bb>%?e3B_NCk-l(gu z7zlV<0AfOc$!Xncl7&CF6afm2SPMR3gFH$Bx{9RXcuHztfG*6MsT)>;#j4E4m}N|h zC2DDS(umXcii-|aGytZk@aH*3r|V*o3~_sUlBs*J8$)6^~?WvqIGH{l?F&T>**Cj+Wxqo1m)h$_7E5 zu_NZ)DC@trr{~9MM&}*2X~x(B)tiVj11~i(1O%P?IG-*TXg^Q`l7J|chNX}1(OHZZ z*`~3sG3x-zQumzt=5UzpYkXz`&B>#WLyV^LA~(Rrl;yG3iT`|}*T$o2civkT2WQD< zzzUUhmEy$sb^s{OMO1oYQ&e7bGx+=DBC=j-uKWpXj3eNDIZ@#vrqO_n!*im0ITB%U z*;aMZ)r@2X$`0k}8QEz3B1{P>JrvUiR0;P8U^wxco#NQB~W?;3S{_^?2n+>C|3 z3)+kYw}hxx8B>f7a03!~y_aj}FE3#i5i{5m6IH{g_~E`>v=GxYMfI-qXJ_a(dtR(m z2aH(h*ImwSOP|RNo*xcQ2%K%8q$)Rdequ&)rEUs_(7e0J0o~u7G7g}v5L-2`D4^V- z&fGcztMg!CHHa=sHMoBYS##HrAv`I?ajIsDW}Y&NFsL-`;nGX zB^B8avzBcu-c0p$D5a`2)8FSdR zY0*mkKJyKJJNqG`(<2G~YAHNda*Ic*60(>l`c6$Vc7YvxhRO~mf?EJ)(-RnWPBE?7 zk^y$0W%c!K-D!jm)6_T$wSlEWE){ypTsZ(9$0h;xpfLjTU|VYxr9bJEU&2{W6cOE) zfuOP01)NqKMdzJKv(B|gQ=MevXp>{+aQJ}EbrGHG;gUcms$KV9)}}A#(AewA$m5VA zl5lGf1^OIqkz1G}Bz4uJ{dkXu`n|vD?gjyksLLddFQ8Y4;NIXYbP5->Y9DomPi_p& zpQckVEGOoz6U{d1Th?nGgg}zRt-kQ;vEc^^6 zVCJ&NK~2CiFa$Ap(P9#tFAfkz%$8uspk&Q}%l=Hm#ooP|Ss=H*!ya1XnVb)N0Lvo6 z_X6F=DQDsYmwkjhyLv!O`RtEaQRlj5z;1^(4|b<@$?;#{reg71B4r!tG~`|NQWDYu z02`s}8-KjpdButf$=w{O#dP!&AT7ks{fOBk8b%fy9{S`AddI9~qzjPWQ52f#@D^6` zwnSp6zZ2`aqbWjJtvK!A)m2^2&5NzOl;pAQs`i_pmcmLmdOtI^5nfVaw0ZlB$|J;J zK~cBJcCOVPQ0W|kxWLvmNcl#itO*P<0@@at;*o2y z%1LplUjKo=h9*tsm2;r9%XK-*LIQW2)6?UiS-XBN+mvY_s$$C#YU4l02@vd|Pb4}A<}n(yG-)6}xaE>UQ`6mh{ebJYoH7`hFHRr*e9cq$ z7n3EA$5+*|9}cU37+5A#fx@8}R1cU9+A+^y5UsRKA3b@S72E8u-4da@V}vFMJ2Sz(bh8Z;F$$ z-n`oTS+p+LcIkK}6Us4&v((d6oP1z3ZNn@r@o8H@9H^DwSIR36@bB)C7UJ9=I8^9* z;E-Obx6SLBjxN2nvB(?e=%UbKFEJK;AYPga=!1RoA)Swl#a7FVMIrpnx8JWid7f>k zvtDf4Z|QHn>?$NRh`Vo5LJY>7&W=n%1KK*d?JItMequ0do)#f!4UX*vI8XI9ACc|g zcNk&OB^E{y6@yW5;6$6>zuvS@bv1ls-zDBw5A`>3FvD370UNvkJ0zw#GhZ(1l<+)K z^m=cR0lfy+TA8+A6j|gN>V(Ee0-psi=bbBidnU``vWe38ZGa}~0`02wUivev)*l5@ z@>yq73uFjE9fqG<_-+8I6*^LKPCw9FkMm`GvTaq6y+99HV7Xb%UG71c;k}A>s}3pD0Es!IpL3IFo{|(9*-Septi8N<-q3U@qrBYx;PO3e73Hj2JP8 zIqS2Z*Zc*FfUJNLdK7d%S=GFf<~<5y{mWnJoqJO(o*|LHsbnE?)}ld?5}&7j!;m() zK<*QQ5EZiz_OLg_P01GC9%hQil3t^AYZ-FudTzKGfi8A+ZZ)7j;G%HoKYuf)1AY{fKg2R8|= z4to{$D&xO7DK?22Brl-gHRfa-j-?-3gm)s{e8^qBGcs!C&zE-Dn}60UY@DjY4%aNa zO`-}SH2HI;V1`506%k%FSQJUQ6EZBML>5gc0lgg}t|Kumb*yepD{?zttH(Gt;$;*T zGiz@Cx_Ihz;pG-b$79|+sSRirUBeaq6nk0odFaxV+xF(*#rBNfp+5yJ--30H7#X9*$cN&u@Sw^Zk6e0- z=ihx{bP%W(T3Q&YFsOACnw&dwieB|i`*CNRc29YTOD&(?pnSnHoAWMuX?mw`H!-7R zcZ!={9>m2fZ*Q$Do(uCY7tf?~DOXYX1+=t^2=&fMc_S4Ngs@%=1)N_n*01+sB6&u- z)JO>hJ)YG2X5>7$yaK%cUd*aUb`7@{#@pp&=06vsYJC{D-896xFRzgL+)}rU&V|P2 zJol3rMEn)RQV|n>8;4V($)H`J;C^2(%8gFo&AIg=CEGa-W8zdHBC>o-k83r_2cD?Z z&CYJe0k-@g02TySL(`nZ0?wN;f3h2&06$=eE+2oaU0`@~IlSsgm@}F2TXd2x7&x-` zj@fNow!4d=x32f)ME~Tn2{kr9y%WFl)aN#U+BOJ0EXJDX6R%fman$7D&FPlVR4xBh zYSb!HWV^OwzMeTaScM?IZ(l;b0m3hiMm}V+JwU)@G3nslX#ZWURORZ$QB2N$!2MF(_8v6^r|Nbi(jIJ0lYx9OiI4u z)^1>!dpDWvrGFNAE3=XHRo+E1L~C^2jj>m=31jIsi3*%wga4d9T2dl+4Hk`RIt?$e zS6KY>gQQPsQD~P+GO#a!$PV+dxVos4k$`~+oo}8Vl-p9GiaKH>0`VerZOf2x z&&WL@NR!-K#e^XspgZHXQRhcoZG+^ngaqGy#CIt-<50GEeY^ISYXS8y&7qY7kHn8F z#)zK-tJop;&sf9VdOIQ4!eXtccf;hc0bxq+5)T-|pIB$}91|JBvcTK%gY6&Hc)7TO z8j(KVdKX0{y8oX+fO{`Mhv0yPe}w>$eS8 z&Hgge!-^tDPw#^Z9sutm3a3d`8(d5PQQKuZuN1J%TeHDk9}u-&nC&7YxP^(o)UX?T zzv4SSxbnW;ycC|=kG}37VE(tCTQu1)%ka$O)&B2kP%t|w*t+%2 z>m&BRS1zbQ{_VaEkm0s7>0FQgY`t`z{A}`&IoFPeB%{pxX6QR7Q=>{aM6rAbHYw-5 z^Zu`ml!Y`v_Vr&6hzI_E+Jr?s2e7_RlqN+*xGt~Fw>j99L1ID4_?Ohb{z8rw!^1x= zztw4i1huiO!>tkr_ zr0r#_b3amg@^w1jBJ3daM;%Qs!F%=~81_A+7{|jr8W_k1trDAwDD;c$FM%>#1sL7N zcsZBYF%$E;2DMt&iduLYvoG62t~|)i#majmuPp~?!7=vE4{-xw-Q4VY)(q{?X-3TE%R#`451jj5O$j7WB3@xozn}|((q0-a=%-J|?xJ$Sv zR#;3#_@d13!n`i*j2+VGjmF)I(AHccEYBMJy+9Teq(*5Vy8VGu~Xr<|8-|v~nx<7K>hG?US%2io{O1CsLl;#^^8j@TB26 zIz7S@U6$by>qx4f@=@m7f3xpPm=6g4fBAmG|I4?S<3vil@r6!gPND$He-8n~bA{Jc z>Ey-eQk4F&`x5i0A9~j15^cFM>oQjY*P#9~@WT*#gAmDNg%M^2zrOgsPt(7@K7RcG zF+3+(+M=%eNjp+X|0H}Q=+YOklf6t&?uLpL5z+f&nB-0wMCE00h` zCjVb!3J|S`-kHfXDY*Vvolf7TYm7mW+}Q3P654J;4g0me9>w?pc70;12Uu^VO@2GU z&mk&llq#nKZMi{_Py=_SOrKyL!h~e50#Q%+&I3M@$Hc2{8KzT0fxRC?Uo4w|MIXNt zx8)iv_a`2)+gsIR!YpI6C;4lR$%^_@rdgZl6Q7hvW!X8g(U)h#XG<~Jhy$D?Lr?(s%o1P zf*2B4*7ik7!kQJ{3K^b)pOW<-FdZtiQ5{Z%df!&Zs;fl)mxM)d5RyBIVQNT?(2#4NL_kU*= zUW?W(ZPzSOVIOjZuP6$z{^hLvQhk&VHbEe&;$MQjfmF_3RIXmaME*=L?rNz=c!h^2OB71la2QL2`%{ZHxS!+OsSa@rfm4VOdg$N%2AHGvogv5MhPk` zzq+MUrJ*|}*45%Ah~$#M!HPQwFLbTdx@M1Ze*M1vq1$wk2~BZdk_98tZjX&XHOuudfQb#TY!Rkk9O+&)~NYe*^h>!0;i&i}ZZkoDph|&B)$|RncOvF|_0( z)@Ief?%k^RRWh?xmZ2eH8*qd3R$Am@;!;R|S@w&!yzshTO+1nvc~x}mdop^7syHt& z&`hALB}Tq6;VssVa3Vm4CclbU4)`ePEsc*>F5RG(G81yXr0*d+3QOD6jd<+bQ|=qe zEg)^3(vekM&8t~`7_6&u?JvtM4X!Tq3r+Na`9rvL6*>X(g+Y1njA|~Y@O_=r%c=bm zb7xD!z|M_2UDk#KFv!Qz)f(Nub;S_(_ZH5(k2%xZKNg$NI7_gGQMgwEar<7ypmoq@Xyp^l5ENeZnT>EQJPd zGy}S|R<)6>1>6&zOhaVb3!3f&DF7%r9~+wFB?NhX68cj7Wfn&+5X`wTFyxliNA^aE zn)m>|@%5i>tw;H0{{;4rfcgaa{{y*t^-u}*_=(mTSU{aT4dEoJWbomp0ROl++s!?j7<0K zNWbD!X3_wdslzJbS!l9=YDT)HBn}Sk#R>Qm*AiwcW_XSAczSj1vnh)uc*k~8jKJw| zR~qfYM_|#EGkW8?3r%AXK;YyyIiz4WNV#~N9WkADoYuIbN{0LQj0@Q6!0Xn>fH$MI z*~z{n5i;mkz{;HLWqTDfsIq*jN`k^9tgPN?lfJpvdA2DRM>DA`LU*${lLs`o;u()T zjastG?_pI9*6uk)Vd}|{^2uSyRTSvU7ByNnRp9$;Hb&9L0iK5;=-xIk9hUNsW9c;l zM+9|jZq=Vi67F<_8f*bO==TUDG1y8hvDO?xe4gsyTBk&`HUJ;!bn&f&Lix_@z>$kAsnBnnC@W{OA4LQa}zN`~Z8PGRtJX7&;-g92K*81-14G zw?}^c6?#H)6e5ZLkxwUhwrlC`z0l8A^HLDV)P4|&nBzKJivJPMCwR2Wqv^fTPt0Id*@-!WtqVF=%Ao*Ju~%rebC9~ew+)m|AH_Cvt!HR z^K9sS^e~i)h;`sVv49&&^j9LTDQ0URO>Za(Sp)(C7Q1FJ7;&;NLn+AciH`rGkY#d$ z+Dc2acu>bl2QR8n(!=42F)&;l;Bm&+>|~5mHAaY{jntv*D~i>Wm?S&vX{fUEO}GYn z&wE?nj~uT!1jIrrwDn{2D>GD%zA|d>!T*p~6j$j;Qt~j7OJ&8Wk$mEFI^m8rmzQ_X zPXHRtqgbj%P$y(WJRlP6IW7iUu_n)REU=r}G1H$lxHgnj{d_AqZe^yYw%}2~;?8Km zL@{0{i?Oy+QD9+rnKd(1=R(Dz^gGFH?L!Eqf&)SBvhFas66s|{~4NB0J3VH08}LoC;7pt{?To`2Wj z`tA$Q7yTsRX9CqaC80xNomy>AS`%T`+pMI6cSVTSgLo?}Df>TNoq1Ff*B-}XOj#5H z7KjB#mas1ZPY`5_2LiGNN}E7{00o4SO3+{{V1UT>s9_TZ;)W;+h><0c3If6dMB)Mn z0?I>u8huqGgrz7_+&URO!6E0&ADR2f?|1K=$;{k)?tH)VIO}^qHKNAV^sWyPd|vRx z^PQ$DH*BAJ8f5n|)rfn7hV8vB{gNC}QJ((1_2)EGi*HRnd0-?)KQQ(EJ&T>MvFW}_ z)31p-$TQ z?1>6awB;{splC~gq5Mv}yp%dMY?UvWIOX~f7<*m1&T;5+16_AC!1{;paBQb-#5m&l zW0RasrJ9ljtyp7k(;zw}0bLPIb>qJE;Zz>+CrHXus|yyR1{;F!j@aPJ zbEL=tCb_4i^guP{L+C_J!hvF8+5kQHj%}{f9}Q*m7f*;c7Y&@APWtF>u>`$sFKLd7 z9e3ztUaGm~?D?C>^Hr1&i5=({|92Pj%$}9T?>}C>S{UMzs@S{@^NF3WtTa7!%+5n{ zO+41j+K1jdGGJY=UYm9zn$ElhzvB~z5w+L}5?!EJ%dahDUj4(FtI{RiitxOpbiFQgP& zc=l+yxHpdVlEjI>7ixc|;EEwAqcD&3A$|UHwi`8LpV>9iBRzO^+Vz zTkxY!WNb8vsb~{%-jMA)Gput>7QzzH=Vxi>#?cAFxT}Y;uct1l$TQLu3|h(i2Dw7! zE$(@7l(#A+i|t~ju*pcn@aUtypT&QLTe>5(XV4*|I&x{8xQ+C7|9!gNO#SgBi1`g;_u?vqs!SA8IR|x`u}_qz3xPR zbBM3YP)l3xGqZ3xRuTXH;^fIO0VTJwRlrJ~?6PaZx0CoI9)|r>=5uEcru{iF5<$*u zY9i#D+n*{*;?L%O)ay!8ak_PAb(GW?RqETL zj{;dWUW!~gc7_FgEeCJcxC7`u%ws$>UfTz4|3X3PDYDNJ7A&m=KyMX2@JzF+cH-_P zQWA7GYk`CxjS=7>@JOvYu%|)(csNwv3O(@IBFg>L;6UAKcxfO&W>_wdLb)J7RooX) z9%R+o0bd)ux*|YGT2>j1i)@xP@fJ%skR|1&$W=%iEpVTjf#;v zErH)(z@Zzq%E}5ZH~_2OBy0PeYx4z^E92<`GOGcoOOeN>W;^K2bNdFC$Op4{8faH1 zXa^qb;28m{GU036vgi!H;{^aRiE5|~ZiqHS?t}nsNLAbokf|L*5CH*2xPgx@h5|Ch zT?nv70Odq*Q?mvb>1ibG1?^Q?(Y5J*2ZI`LAiq%oq=IPXtq9057=}8j25{=tHzOdaAq04U3WJGF zHb8)Eu@nl0M?mix5VQrHXwn1Vg*{Np7tn@G>2wf+yn)qeO%zHG5k)Z_0swIEkP2L< z)fp=kN*4i!7Ql64mukSEYkgE#5e4TZ8oL`*D!!E(Nx_UaSv j+6D+geLfC^M|+mQ*Ow$yL@ceNaI6S{mE76Panj42;u diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7705927e94..48b43d3506 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 23d15a9367..ef07e0162b 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From e514ca27f77573401f4fcba8195c0cbc69a61f88 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 18 Aug 2025 11:47:10 +0200 Subject: [PATCH 1412/1594] [Java] Bump `Shadow` to 9.0.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0e11ed13a6..90edf96058 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20250517" junit = "5.13.4" mockito = "5.18.0" plexus = "3.3.0" -shadow = "9.0.1" +shadow = "9.0.2" versions = "0.52.0" [libraries] From 3d270481a6a3d011794b652d5c965658520e65a8 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 18 Aug 2025 11:47:21 +0200 Subject: [PATCH 1413/1594] [Java] Bump `Mockito` to 5.19.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 90edf96058..e79e4ccdbf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ jqwik = "1.9.3" jmh = "1.37" json = "20250517" junit = "5.13.4" -mockito = "5.18.0" +mockito = "5.19.0" plexus = "3.3.0" shadow = "9.0.2" versions = "0.52.0" From 7816d6bf376d46096b77bd44b177b552af63b521 Mon Sep 17 00:00:00 2001 From: Peter Veentjer Date: Mon, 25 Aug 2025 13:39:35 +0300 Subject: [PATCH 1414/1594] Replaced empty array creation by Array.Empty (#1080) to prevent creating any objects when not needed. Fixes the following issue: https://github.com/aeron-io/simple-binary-encoding/issues/1079 --- .../co/real_logic/sbe/generation/csharp/CSharpGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index b6fd5d7746..a5dc0b2354 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -1141,7 +1141,7 @@ private CharSequence generateArrayProperty( generateDocumentation(indent, fieldToken), typeName, propName, offset, generateArrayFieldNotPresentCondition(fieldToken.version(), - indent + INDENT + INDENT, "new " + typeName + "[0]"), + indent + INDENT + INDENT, "System.Array.Empty<" + typeName + ">()"), accessOrderListenerCallDoubleIndent)); sb.append(String.format("\n" + @@ -1155,7 +1155,7 @@ private CharSequence generateArrayProperty( generateDocumentation(indent, fieldToken), typeName, propName, offset, generateArrayFieldNotPresentCondition(fieldToken.version(), - indent + INDENT + INDENT, "new " + typeName + "[0]"), + indent + INDENT + INDENT, "System.Array.Empty<" + typeName + ">()"), accessOrderListenerCall)); if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) From 552b4474bee8a226e5f42dd0a0b09682d268967a Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:49:13 +0200 Subject: [PATCH 1415/1594] [Java] Add test showing that DTO generator handles constants correctly. --- build.gradle | 3 +- .../sbe/generation/java/DtoTest.java | 35 +++++++++++- .../src/test/resources/dto-test-schema.xml | 57 +++++++++++++++++++ 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b349fe2528..13cf19ba9b 100644 --- a/build.gradle +++ b/build.gradle @@ -355,8 +355,9 @@ project(':sbe-tool') { 'sbe.validation.xsd': validationXsdPath, 'sbe.generate.precedence.checks': 'true', 'sbe.java.precedence.checks.property.name': 'sbe.enable.test.precedence.checks', + 'sbe.keyword.append.token': 'KeywordSuffix', 'sbe.java.generate.dtos': 'true') - args = ['src/test/resources/example-extension-schema.xml'] + args = ['src/test/resources/example-extension-schema.xml', 'src/test/resources/dto-test-schema.xml'] } jar { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java index 56d6869199..ecc05a9071 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java @@ -16,13 +16,21 @@ package uk.co.real_logic.sbe.generation.java; -import extension.*; +import dto_test.KeywordsDto; +import dto_test.KeywordsEncoder; +import extension.BooleanType; +import extension.BoostType; +import extension.CarDecoder; +import extension.CarDto; +import extension.CarEncoder; +import extension.Model; import org.agrona.ExpandableArrayBuffer; import org.agrona.MutableDirectBuffer; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; public class DtoTest { @@ -65,6 +73,31 @@ void shouldRoundTripCar2() assertThat(outputBuffer.byteArray(), equalTo(inputBuffer.byteArray())); } + @Test + void dtoWithKeywords() + { + final KeywordsDto dto = new KeywordsDto(); + dto.assertKeywordSuffix((short)42); + dto.finalKeywordSuffix((short)7); + final ExpandableArrayBuffer input = new ExpandableArrayBuffer(); + final KeywordsEncoder encoder = new KeywordsEncoder(); + encoder.wrap(input, 0); + + KeywordsDto.encodeWith(encoder, dto); + + final byte[] originalBytes = new byte[encoder.encodedLength()]; + input.getBytes(0, originalBytes); + + final KeywordsDto otherDto = + KeywordsDto.decodeFrom(input, 0, KeywordsEncoder.SCHEMA_VERSION, KeywordsEncoder.BLOCK_LENGTH); + KeywordsDto.encodeWith(encoder, otherDto); + + final byte[] otherBytes = new byte[encoder.encodedLength()]; + input.getBytes(0, otherBytes); + + assertArrayEquals(originalBytes, otherBytes); + } + private static int encodeCar(final MutableDirectBuffer buffer, final int offset) { final CarEncoder car = new CarEncoder(); diff --git a/sbe-tool/src/test/resources/dto-test-schema.xml b/sbe-tool/src/test/resources/dto-test-schema.xml index f6f832e990..fd24bf941d 100644 --- a/sbe-tool/src/test/resources/dto-test-schema.xml +++ b/sbe-tool/src/test/resources/dto-test-schema.xml @@ -107,4 +107,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 46328f70053c11d6360bb6c3b99b67a7635935a6 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 26 Aug 2025 10:36:20 +0200 Subject: [PATCH 1416/1594] [Java] Update the test to use shorter suffix and mixed case characters. --- build.gradle | 2 +- .../sbe/generation/java/DtoTest.java | 7 +- .../src/test/resources/dto-test-schema.xml | 109 +++++++++--------- 3 files changed, 61 insertions(+), 57 deletions(-) diff --git a/build.gradle b/build.gradle index 13cf19ba9b..90102a340e 100644 --- a/build.gradle +++ b/build.gradle @@ -355,7 +355,7 @@ project(':sbe-tool') { 'sbe.validation.xsd': validationXsdPath, 'sbe.generate.precedence.checks': 'true', 'sbe.java.precedence.checks.property.name': 'sbe.enable.test.precedence.checks', - 'sbe.keyword.append.token': 'KeywordSuffix', + 'sbe.keyword.append.token': '$', 'sbe.java.generate.dtos': 'true') args = ['src/test/resources/example-extension-schema.xml', 'src/test/resources/dto-test-schema.xml'] } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java index ecc05a9071..36b32e1b73 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java @@ -77,8 +77,11 @@ void shouldRoundTripCar2() void dtoWithKeywords() { final KeywordsDto dto = new KeywordsDto(); - dto.assertKeywordSuffix((short)42); - dto.finalKeywordSuffix((short)7); + dto.assert$((byte)42); + dto.final$((byte)7); + dto.abstract$((byte)-81); + dto.false$((byte)0); + dto.falsE((byte)1); final ExpandableArrayBuffer input = new ExpandableArrayBuffer(); final KeywordsEncoder encoder = new KeywordsEncoder(); encoder.wrap(input, 0); diff --git a/sbe-tool/src/test/resources/dto-test-schema.xml b/sbe-tool/src/test/resources/dto-test-schema.xml index fd24bf941d..f3ff272e97 100644 --- a/sbe-tool/src/test/resources/dto-test-schema.xml +++ b/sbe-tool/src/test/resources/dto-test-schema.xml @@ -109,59 +109,60 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From cb4eb1fd180594153f30fdf01a2c1489ead4259f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 26 Aug 2025 10:43:47 +0200 Subject: [PATCH 1417/1594] [Java] Fix C++ build by using `X` as a unique suffix for keywords. --- sbe-tool/src/test/cpp/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index 53bb18f2ef..06dab75f9b 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -72,6 +72,7 @@ add_custom_command( -Dsbe.generate.precedence.checks="true" -Dsbe.precedence.checks.flag.name="SBE_ENABLE_PRECEDENCE_CHECKS_IN_TESTS" -Dsbe.cpp.disable.implicit.copying="true" + -Dsbe.keyword.append.token="X" -Dsbe.cpp.generate.dtos="true" -jar ${SBE_JAR} ${CODE_GENERATION_SCHEMA} From fbd3799dfd5e3235d67f5e522d476e46c6a9c28f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 28 Aug 2025 09:41:33 +0200 Subject: [PATCH 1418/1594] [Java] Handle primitive arrays correctly in the generated DTO code. --- .../sbe/generation/java/JavaDtoGenerator.java | 11 ++++++++--- .../uk/co/real_logic/sbe/generation/java/DtoTest.java | 2 ++ sbe-tool/src/test/resources/dto-test-schema.xml | 8 +++++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java index bb7da8df34..335731f290 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -1039,7 +1039,7 @@ private void generateArrayEncodeWith( if (primitiveType == PrimitiveType.CHAR) { - sb.append(indent).append("encoder.").append(toLowerFirstChar(propertyName)).append("(") + sb.append(indent).append("encoder.").append(formattedPropertyName).append("(") .append("dto.").append(formattedPropertyName).append("());\n"); } else @@ -1047,10 +1047,15 @@ private void generateArrayEncodeWith( final String javaTypeName = javaTypeName(primitiveType); sb.append(indent).append(javaTypeName).append("[] ").append(formattedPropertyName).append(" = ") .append("dto.").append(formattedPropertyName).append("();\n") - .append(indent).append("for (int i = 0; i < ").append(formattedPropertyName).append(".length; i++)\n") + .append(indent).append("if (null != ").append(formattedPropertyName).append(")\n") .append(indent).append("{\n") - .append(indent).append(INDENT).append("encoder.").append(formattedPropertyName).append("(") + .append(indent).append(indent).append("for (int i = 0; i < ").append(formattedPropertyName) + .append(".length; i++)\n") + .append(indent).append(indent).append("{\n") + .append(indent).append(indent).append(INDENT).append("encoder.").append(formattedPropertyName) + .append("(") .append("i, ").append(formattedPropertyName).append("[i]);\n") + .append(indent).append(indent).append("}\n") .append(indent).append("}\n"); } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java index 36b32e1b73..24a5093ec8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java @@ -82,6 +82,8 @@ void dtoWithKeywords() dto.abstract$((byte)-81); dto.false$((byte)0); dto.falsE((byte)1); + dto.import$("char nine"); + dto.void$(new int[] {1, 2, 3}); final ExpandableArrayBuffer input = new ExpandableArrayBuffer(); final KeywordsEncoder encoder = new KeywordsEncoder(); encoder.wrap(input, 0); diff --git a/sbe-tool/src/test/resources/dto-test-schema.xml b/sbe-tool/src/test/resources/dto-test-schema.xml index f3ff272e97..38fb39b6c8 100644 --- a/sbe-tool/src/test/resources/dto-test-schema.xml +++ b/sbe-tool/src/test/resources/dto-test-schema.xml @@ -32,6 +32,8 @@ + + T @@ -133,7 +135,7 @@ - + @@ -147,7 +149,7 @@ - + @@ -156,7 +158,7 @@ - + From d39de50ee4fecdd61f74da0f14dcce6cb1de4b2a Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 30 Aug 2025 14:14:11 +0200 Subject: [PATCH 1419/1594] [Java] More tests around arrays in DTOs. --- .../sbe/generation/java/DtoTest.java | 36 +++++++++++++++---- .../src/test/resources/dto-test-schema.xml | 16 +++++++-- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java index 24a5093ec8..b16ca3208d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java @@ -18,6 +18,8 @@ import dto_test.KeywordsDto; import dto_test.KeywordsEncoder; +import dto_test.MessageHeaderDecoder; +import dto_test.MessageHeaderEncoder; import extension.BooleanType; import extension.BoostType; import extension.CarDecoder; @@ -28,6 +30,8 @@ import org.agrona.MutableDirectBuffer; import org.junit.jupiter.api.Test; +import java.util.List; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.junit.jupiter.api.Assertions.assertArrayEquals; @@ -76,6 +80,10 @@ void shouldRoundTripCar2() @Test void dtoWithKeywords() { + final ExpandableArrayBuffer input = new ExpandableArrayBuffer(); + final KeywordsEncoder encoder = new KeywordsEncoder(); + encoder.wrapAndApplyHeader(input, 0, new MessageHeaderEncoder()); + final KeywordsDto dto = new KeywordsDto(); dto.assert$((byte)42); dto.final$((byte)7); @@ -84,20 +92,34 @@ void dtoWithKeywords() dto.falsE((byte)1); dto.import$("char nine"); dto.void$(new int[] {1, 2, 3}); - final ExpandableArrayBuffer input = new ExpandableArrayBuffer(); - final KeywordsEncoder encoder = new KeywordsEncoder(); - encoder.wrap(input, 0); + + final KeywordsDto.DataDto dto1 = new KeywordsDto.DataDto(); + dto1.this$((byte)90); + final KeywordsDto.DataDto.SuperDto superDto = new KeywordsDto.DataDto.SuperDto(); + superDto.try$(0.5f); + dto1.super$(List.of(superDto)); + final KeywordsDto.DataDto dto2 = new KeywordsDto.DataDto(); + dto2.this$((byte)100); + dto.data(List.of(dto1, dto2)); KeywordsDto.encodeWith(encoder, dto); final byte[] originalBytes = new byte[encoder.encodedLength()]; input.getBytes(0, originalBytes); - final KeywordsDto otherDto = - KeywordsDto.decodeFrom(input, 0, KeywordsEncoder.SCHEMA_VERSION, KeywordsEncoder.BLOCK_LENGTH); - KeywordsDto.encodeWith(encoder, otherDto); + final MessageHeaderDecoder messageHeaderDecoder = new MessageHeaderDecoder(); + messageHeaderDecoder.wrap(input, 0); + + final KeywordsDto otherDto = KeywordsDto.decodeFrom( + input, + MessageHeaderDecoder.ENCODED_LENGTH, + messageHeaderDecoder.blockLength(), + messageHeaderDecoder.version()); + final KeywordsEncoder encoder2 = new KeywordsEncoder(); + encoder2.wrapAndApplyHeader(input, 0, new MessageHeaderEncoder()); + KeywordsDto.encodeWith(encoder2, otherDto); - final byte[] otherBytes = new byte[encoder.encodedLength()]; + final byte[] otherBytes = new byte[encoder2.encodedLength()]; input.getBytes(0, otherBytes); assertArrayEquals(originalBytes, otherBytes); diff --git a/sbe-tool/src/test/resources/dto-test-schema.xml b/sbe-tool/src/test/resources/dto-test-schema.xml index 38fb39b6c8..12ef9d6ef7 100644 --- a/sbe-tool/src/test/resources/dto-test-schema.xml +++ b/sbe-tool/src/test/resources/dto-test-schema.xml @@ -33,7 +33,7 @@ - + T @@ -71,6 +71,10 @@ + + + +
      @@ -161,10 +165,16 @@ - - + + + + + + + + From ecb43f4312811c2bc7c4c87838be80d795ca65fc Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 30 Aug 2025 14:14:27 +0200 Subject: [PATCH 1420/1594] [Java] Bump `Shadow` to 9.1.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e79e4ccdbf..b241820484 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20250517" junit = "5.13.4" mockito = "5.19.0" plexus = "3.3.0" -shadow = "9.0.2" +shadow = "9.1.0" versions = "0.52.0" [libraries] From b13d103d38830793eef5649e80e5041295cf0b37 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 30 Aug 2025 14:59:11 +0200 Subject: [PATCH 1421/1594] [C++] Fix property name usage in display code generator. --- .../sbe/generation/cpp/CppGenerator.java | 18 +++-- sbe-tool/src/test/c/CMakeLists.txt | 1 + .../test/resources/code-generation-schema.xml | 75 +++++++++++++++++++ 3 files changed, 86 insertions(+), 8 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 566545df2f..3ee0208cbb 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -290,12 +290,12 @@ private CharSequence generateFullyEncodedCheck(final FieldPrecedenceModel fieldP private static String accessOrderListenerMethodName(final Token token) { - return "on" + Generators.toUpperFirstChar(token.name()) + "Accessed"; + return "on" + Generators.toUpperFirstChar(formatPropertyName(token.name())) + "Accessed"; } private static String accessOrderListenerMethodName(final Token token, final String suffix) { - return "on" + Generators.toUpperFirstChar(token.name()) + suffix + "Accessed"; + return "on" + Generators.toUpperFirstChar(formatPropertyName(token.name())) + suffix + "Accessed"; } private static void generateAccessOrderListenerMethod( @@ -1405,7 +1405,7 @@ private void generateChoiceSet(final List tokens) throws IOException private void generateEnum(final List tokens) throws IOException { final Token enumToken = tokens.get(0); - final String enumName = formatClassName(tokens.get(0).applicableTypeName()); + final String enumName = formatClassName(enumToken.applicableTypeName()); try (Writer out = outputManager.createOutput(enumName)) { @@ -3879,11 +3879,12 @@ private CharSequence appendDisplay( atLeastOne[0] = true; final String characterEncoding = varData.get(i + 3).encoding().characterEncoding(); - sb.append(indent).append("builder << R\"(\"").append(varDataToken.name()).append("\": )\";\n"); + final String propertyName = formatPropertyName(varDataToken.name()); + sb.append(indent).append("builder << R\"(\"").append(propertyName).append("\": )\";\n"); if (null == characterEncoding) { - final String skipFunction = "writer.skip" + toUpperFirstChar(varDataToken.name()) + "()"; + final String skipFunction = "writer.skip" + toUpperFirstChar(propertyName) + "()"; sb.append(indent).append("builder << '\"' <<\n").append(indent).append(INDENT).append(skipFunction) .append(" << \" bytes of raw data\\\"\";\n"); @@ -3891,7 +3892,7 @@ private CharSequence appendDisplay( else { final String getAsStringFunction = - "writer.get" + toUpperFirstChar(varDataToken.name()) + "AsJsonEscapedString().c_str()"; + "writer.get" + toUpperFirstChar(propertyName) + "AsJsonEscapedString().c_str()"; sb.append(indent).append("builder << '\"' <<\n").append(indent).append(INDENT) .append(getAsStringFunction).append(" << '\"';\n\n"); @@ -3925,7 +3926,8 @@ private void writeTokenDisplay( } sb.append(indent).append("builder << R\"(\"").append(fieldTokenName).append("\": )\";\n"); - final String fieldName = "writer." + formatPropertyName(fieldTokenName); + final String propertyName = formatPropertyName(fieldTokenName); + final String fieldName = "writer." + propertyName; switch (typeToken.signal()) { @@ -3935,7 +3937,7 @@ private void writeTokenDisplay( if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { final String getAsStringFunction = - "writer.get" + toUpperFirstChar(fieldTokenName) + "AsJsonEscapedString().c_str()"; + "writer.get" + toUpperFirstChar(propertyName) + "AsJsonEscapedString().c_str()"; sb.append(indent).append("builder << '\"' <<\n").append(indent).append(INDENT) .append(getAsStringFunction).append(" << '\"';\n"); diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index 2ed9136bec..fab918f0b3 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -49,6 +49,7 @@ add_custom_command( ${Java_JAVA_EXECUTABLE} --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.output.dir=${C_CODEC_TARGET_DIR} -Dsbe.target.language="C" + -Dsbe.keyword.append.token="X" -jar ${SBE_JAR} ${CODE_GENERATION_SCHEMA} ${CODE_GENERATION_SCHEMA_WITH_VERSION} diff --git a/sbe-tool/src/test/resources/code-generation-schema.xml b/sbe-tool/src/test/resources/code-generation-schema.xml index 7e1634cd1f..be83536199 100644 --- a/sbe-tool/src/test/resources/code-generation-schema.xml +++ b/sbe-tool/src/test/resources/code-generation-schema.xml @@ -7,6 +7,8 @@ description="Example schema" byteOrder="littleEndian"> + + T @@ -34,6 +36,10 @@ + + + + @@ -57,6 +63,12 @@ B C + + 0 + 1 + 222 + 254 + 0 1 @@ -90,4 +102,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 8985a966eb7343373460198f17c8d9e8528c8ab9 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 30 Aug 2025 15:26:19 +0200 Subject: [PATCH 1422/1594] [Java] Increase buffer capacity. --- .../src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index 2111fb1038..122c0ef41d 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -32,7 +32,7 @@ class EncodedIrTest { - private static final int CAPACITY = 1024 * 16; + private static final int CAPACITY = 1024 * 32; @Test void shouldEncodeIr() throws Exception From 61bf426885fa10c30421d34e924348e84cf02cc1 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 30 Aug 2025 17:57:15 +0200 Subject: [PATCH 1423/1594] [Go] Handle `_` and `String` as keywords + use property name when generating variable data section. --- gocode/flyweight/src/otf/otf_test.go | 2 +- .../uk/co/real_logic/sbe/ValidationUtil.java | 4 +- .../golang/flyweight/GolangFlyweightUtil.java | 21 +-- .../golang/struct/GolangGenerator.java | 2 +- .../test/resources/code-generation-schema.xml | 143 ++++++++++-------- 5 files changed, 88 insertions(+), 84 deletions(-) diff --git a/gocode/flyweight/src/otf/otf_test.go b/gocode/flyweight/src/otf/otf_test.go index 10cc0afd0e..e173da701e 100644 --- a/gocode/flyweight/src/otf/otf_test.go +++ b/gocode/flyweight/src/otf/otf_test.go @@ -7,7 +7,7 @@ import ( "testing" ) -//go:generate java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.output.dir=. -Dsbe.target.language=golang -Dsbe.go.generate.generate.flyweights=true -Dsbe.generate.ir=true -jar ../../../${SBE_JAR} ../../../../sbe-tool/src/test/resources/code-generation-schema.xml +//go:generate java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.output.dir=. -Dsbe.target.language=golang -Dsbe.go.generate.generate.flyweights=true -Dsbe.generate.ir=true -Dsbe.keyword.append.token=X -jar ../../../${SBE_JAR} ../../../../sbe-tool/src/test/resources/code-generation-schema.xml const SchemaFilename = "code-generation-schema.sbeir" const MsgBufferCapacity = 4 * 1024 diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index 426e7c4fd1..92f000cae5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -295,7 +295,7 @@ private static boolean isJavaIdentifier(final String token) "case", "defer", "go", "map", "struct", "chan", "else", "goto", "package", "switch", "const", "fallthrough", "if", "range", "type", - "continue", "for", "import", "return", "var", + "continue", "for", "import", "return", "var", "_", /* https://golang.org/ref/spec#Predeclared_identifiers */ /* types */ @@ -308,7 +308,7 @@ private static boolean isJavaIdentifier(final String token) "nil", /* functions */ "append", "cap", "close", "complex", "copy", "delete", "imag", "len", - "make", "new", "panic", "print", "println", "real", "recover"); + "make", "new", "panic", "print", "println", "real", "recover", "String"); /** * "Check" value for validity of usage as a golang identifier. From: diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java index 2b74309d13..a028aec8dd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightUtil.java @@ -16,8 +16,7 @@ package uk.co.real_logic.sbe.generation.golang.flyweight; import uk.co.real_logic.sbe.PrimitiveType; -import uk.co.real_logic.sbe.SbeTool; -import uk.co.real_logic.sbe.ValidationUtil; +import uk.co.real_logic.sbe.generation.golang.struct.GolangUtil; import java.nio.ByteOrder; import java.util.EnumMap; @@ -105,23 +104,7 @@ public static String golangMarshalType(final PrimitiveType primitiveType) */ public static String formatPropertyName(final String value) { - String formattedValue = toUpperFirstChar(value); - - if (ValidationUtil.isGolangKeyword(formattedValue)) - { - final String keywordAppendToken = System.getProperty(SbeTool.KEYWORD_APPEND_TOKEN); - if (null == keywordAppendToken) - { - throw new IllegalStateException( - "Invalid property name='" + formattedValue + - "' please correct the schema or consider setting system property: " + - SbeTool.KEYWORD_APPEND_TOKEN); - } - - formattedValue += keywordAppendToken; - } - - return formattedValue; + return GolangUtil.formatPropertyName(value); } /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java index d764a11eca..d96f4c8e57 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java @@ -1411,7 +1411,7 @@ private void generateVarData( throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + token); } - final String propertyName = toUpperFirstChar(token.name()); + final String propertyName = formatPropertyName(token.name()); final Token lengthToken = Generators.findFirst("length", tokens, i); final int lengthOfLengthField = lengthToken.encodedLength(); final Token varDataToken = Generators.findFirst("varData", tokens, i); diff --git a/sbe-tool/src/test/resources/code-generation-schema.xml b/sbe-tool/src/test/resources/code-generation-schema.xml index be83536199..c6a6633f8b 100644 --- a/sbe-tool/src/test/resources/code-generation-schema.xml +++ b/sbe-tool/src/test/resources/code-generation-schema.xml @@ -4,7 +4,7 @@ id="6" version="0" semanticVersion="5.2" - description="Example schema" + description="Code generation schema" byteOrder="littleEndian"> @@ -102,67 +102,88 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 7822307729491594c945a1fe4246bff86a0b88aa Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 30 Aug 2025 18:55:22 +0200 Subject: [PATCH 1424/1594] [Java] Handle `null` values when encoding enums, i.e. use `Enum.NULL_VAL` if the value was not assigned. --- .../sbe/generation/java/JavaDtoGenerator.java | 18 +++++++++++++++--- .../sbe/generation/java/DtoTest.java | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java index 335731f290..d8a4d6f245 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -985,7 +985,7 @@ private void generateFieldEncodeWith( break; case BEGIN_ENUM: - generateEnumEncodeWith(sb, fieldToken, indent); + generateEnumEncodeWith(sb, fieldToken, typeToken, indent); break; case BEGIN_SET: @@ -1081,6 +1081,7 @@ private void generatePrimitiveValueEncodeWith( private void generateEnumEncodeWith( final StringBuilder sb, final Token fieldToken, + final Token typeToken, final String indent) { if (fieldToken.isConstantEncoding()) @@ -1088,11 +1089,22 @@ private void generateEnumEncodeWith( return; } + final String enumName = formatClassName(typeToken.applicableTypeName()); final String propertyName = fieldToken.name(); final String formattedPropertyName = formatPropertyName(propertyName); - sb.append(indent).append("encoder.").append(formattedPropertyName).append("(dto.") - .append(formattedPropertyName).append("());\n"); + sb.append(indent).append(enumName).append(" ").append(formattedPropertyName).append(" = ") + .append("dto.").append(formattedPropertyName).append("();\n"); + sb.append(indent).append("if (null != ").append(formattedPropertyName).append(")\n"); + sb.append(indent).append("{\n"); + sb.append(indent).append(indent).append("encoder.").append(formattedPropertyName) + .append("(").append(formattedPropertyName).append(");\n"); + sb.append(indent).append("}\n"); + sb.append(indent).append("else\n"); + sb.append(indent).append("{\n"); + sb.append(indent).append(indent).append("encoder.").append(formattedPropertyName) + .append("(").append(enumName).append(".NULL_VAL);\n"); + sb.append(indent).append("}\n"); } private void generateComplexPropertyEncodeWith( diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java index b16ca3208d..0f9d58f599 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/DtoTest.java @@ -92,6 +92,7 @@ void dtoWithKeywords() dto.falsE((byte)1); dto.import$("char nine"); dto.void$(new int[] {1, 2, 3}); + dto.continue$(dto_test.Model.B); final KeywordsDto.DataDto dto1 = new KeywordsDto.DataDto(); dto1.this$((byte)90); From d9868d2324123c37b66861ed5a310a4f4ba274f1 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 30 Aug 2025 18:58:38 +0200 Subject: [PATCH 1425/1594] [Java] Fix var data and composite code generation to use property name instead of plain name. Also use property name for access order check methods. --- .../sbe/generation/java/JavaGenerator.java | 78 +++++---- .../test/resources/code-generation-schema.xml | 2 + .../src/test/resources/dto-test-schema.xml | 152 +++++++++++------- 3 files changed, 133 insertions(+), 99 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 3b6e988750..4e48e9bd08 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -471,12 +471,12 @@ private void generateFullyEncodedCheck( private static String accessOrderListenerMethodName(final Token token) { - return "on" + Generators.toUpperFirstChar(token.name()) + "Accessed"; + return "on" + Generators.toUpperFirstChar(formatPropertyName(token.name())) + "Accessed"; } private static String accessOrderListenerMethodName(final Token token, final String suffix) { - return "on" + Generators.toUpperFirstChar(token.name()) + suffix + "Accessed"; + return "on" + Generators.toUpperFirstChar(formatPropertyName(token.name())) + suffix + "Accessed"; } private static void generateAccessOrderListenerMethod( @@ -1428,15 +1428,15 @@ private void generateDecoderVarData( { throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + token); } + final String propertyName = formatPropertyName(token.name()); - generateFieldIdMethod(sb, token, indent); - generateFieldSinceVersionMethod(sb, token, indent); + generateFieldIdMethod(sb, token, propertyName, indent); + generateFieldSinceVersionMethod(sb, token, propertyName, indent); final String characterEncoding = tokens.get(i + 3).encoding().characterEncoding(); - generateCharacterEncodingMethod(sb, token.name(), characterEncoding, indent); - generateFieldMetaAttributeMethod(sb, token, indent); + generateCharacterEncodingMethod(sb, propertyName, characterEncoding, indent); + generateFieldMetaAttributeMethod(sb, token, propertyName, indent); - final String propertyName = Generators.toUpperFirstChar(token.name()); final Token lengthToken = tokens.get(i + 2); final int sizeOfLengthField = lengthToken.encodedLength(); final Encoding lengthEncoding = lengthToken.encoding(); @@ -1492,13 +1492,14 @@ private void generateEncoderVarData( throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + token); } - generateFieldIdMethod(sb, token, indent); + final String propertyName = formatPropertyName(token.name()); + + generateFieldIdMethod(sb, token, propertyName, indent); final Token varDataToken = Generators.findFirst("varData", tokens, i); final String characterEncoding = varDataToken.encoding().characterEncoding(); - generateCharacterEncodingMethod(sb, token.name(), characterEncoding, indent); - generateFieldMetaAttributeMethod(sb, token, indent); + generateCharacterEncodingMethod(sb, propertyName, characterEncoding, indent); + generateFieldMetaAttributeMethod(sb, token, propertyName, indent); - final String propertyName = Generators.toUpperFirstChar(token.name()); final Token lengthToken = Generators.findFirst("length", tokens, i); final int sizeOfLengthField = lengthToken.encodedLength(); final Encoding lengthEncoding = lengthToken.encoding(); @@ -1614,7 +1615,7 @@ private void generateDataDecodeMethods( indent + " buffer.getBytes(limit + headerLength, tmp, 0, dataLength);\n\n" + indent + " return new String(tmp, %6$s);\n" + indent + " }\n", - formatPropertyName(propertyName), + propertyName, generateStringNotPresentCondition(false, token.version(), indent), sizeOfLengthField, PrimitiveType.UINT32 == lengthType ? "(int)" : "", @@ -1668,7 +1669,7 @@ private void generateVarDataWrapDecoder( indent + " parentMessage.limit(limit + headerLength + dataLength);\n" + indent + " wrapBuffer.wrap(buffer, limit + headerLength, dataLength);\n" + indent + " }\n", - propertyName, + Generators.toUpperFirstChar(propertyName), readOnlyBuffer, generateWrapFieldNotPresentCondition(false, token.version(), indent), accessOrderListenerCall, @@ -1845,7 +1846,7 @@ private void generateVarDataTypedDecoder( indent + " buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied);\n\n" + indent + " return bytesCopied;\n" + indent + " }\n", - propertyName, + Generators.toUpperFirstChar(propertyName), exchangeType, generateArrayFieldNotPresentCondition(false, token.version(), indent), accessOrderListenerCall, @@ -1884,7 +1885,7 @@ private void generateDataTypedEncoder( indent + " return this;\n" + indent + " }\n", className, - propertyName, + Generators.toUpperFirstChar(propertyName), exchangeType, maxLengthValue, sizeOfLengthField, @@ -2010,7 +2011,7 @@ private void generateComposite(final List tokens) throws IOException final StringBuilder sb = new StringBuilder(); generateEncodingOffsetMethod(sb, propertyName, encodingToken.offset(), BASE_INDENT); generateEncodingLengthMethod(sb, propertyName, encodingToken.encodedLength(), BASE_INDENT); - generateFieldSinceVersionMethod(sb, encodingToken, BASE_INDENT); + generateFieldSinceVersionMethod(sb, encodingToken, propertyName, BASE_INDENT); final String accessOrderListenerCall = ""; switch (encodingToken.signal()) @@ -3239,9 +3240,8 @@ private static void generateCharacterEncodingMethod( { if (null != characterEncoding) { - final String propName = formatPropertyName(propertyName); sb.append("\n") - .append(indent).append(" public static String ").append(propName).append("CharacterEncoding()\n") + .append(indent).append(" public static String ").append(propertyName).append("CharacterEncoding()\n") .append(indent).append(" {\n") .append(indent).append(" return ").append(charsetName(characterEncoding)).append(";\n") .append(indent).append(" }\n"); @@ -3656,11 +3656,11 @@ private void generateEncoderFields( final String propertyName = formatPropertyName(fieldToken.name()); final String typeName = encoderName(typeToken.name()); - generateFieldIdMethod(sb, fieldToken, indent); - generateFieldSinceVersionMethod(sb, fieldToken, indent); + generateFieldIdMethod(sb, fieldToken, propertyName, indent); + generateFieldSinceVersionMethod(sb, fieldToken, propertyName, indent); generateEncodingOffsetMethod(sb, propertyName, fieldToken.offset(), indent); generateEncodingLengthMethod(sb, propertyName, typeToken.encodedLength(), indent); - generateFieldMetaAttributeMethod(sb, fieldToken, indent); + generateFieldMetaAttributeMethod(sb, fieldToken, propertyName, indent); generateAccessOrderListenerMethod(sb, fieldPrecedenceModel, indent + " ", fieldToken); final CharSequence accessOrderListenerCall = generateAccessOrderListenerCall( fieldPrecedenceModel, indent + " ", fieldToken); @@ -3708,11 +3708,11 @@ private void generateDecoderFields( final String propertyName = formatPropertyName(fieldToken.name()); final String typeName = decoderName(typeToken.name()); - generateFieldIdMethod(sb, fieldToken, indent); - generateFieldSinceVersionMethod(sb, fieldToken, indent); + generateFieldIdMethod(sb, fieldToken, propertyName, indent); + generateFieldSinceVersionMethod(sb, fieldToken, propertyName, indent); generateEncodingOffsetMethod(sb, propertyName, fieldToken.offset(), indent); generateEncodingLengthMethod(sb, propertyName, typeToken.encodedLength(), indent); - generateFieldMetaAttributeMethod(sb, fieldToken, indent); + generateFieldMetaAttributeMethod(sb, fieldToken, propertyName, indent); generateAccessOrderListenerMethod(sb, fieldPrecedenceModel, indent + " ", fieldToken); final CharSequence accessOrderListenerCall = generateAccessOrderListenerCall( @@ -3748,9 +3748,9 @@ private void generateDecoderFields( }); } - private static void generateFieldIdMethod(final StringBuilder sb, final Token token, final String indent) + private static void generateFieldIdMethod( + final StringBuilder sb, final Token token, final String propertyName, final String indent) { - final String propertyName = formatPropertyName(token.name()); sb.append("\n") .append(indent).append(" public static int ").append(propertyName).append("Id()\n") .append(indent).append(" {\n") @@ -3759,9 +3759,8 @@ private static void generateFieldIdMethod(final StringBuilder sb, final Token to } private static void generateEncodingOffsetMethod( - final StringBuilder sb, final String name, final int offset, final String indent) + final StringBuilder sb, final String propertyName, final int offset, final String indent) { - final String propertyName = formatPropertyName(name); sb.append("\n") .append(indent).append(" public static int ").append(propertyName).append("EncodingOffset()\n") .append(indent).append(" {\n") @@ -3770,9 +3769,8 @@ private static void generateEncodingOffsetMethod( } private static void generateEncodingLengthMethod( - final StringBuilder sb, final String name, final int length, final String indent) + final StringBuilder sb, final String propertyName, final int length, final String indent) { - final String propertyName = formatPropertyName(name); sb.append("\n") .append(indent).append(" public static int ").append(propertyName).append("EncodingLength()\n") .append(indent).append(" {\n") @@ -3780,9 +3778,9 @@ private static void generateEncodingLengthMethod( .append(indent).append(" }\n"); } - private static void generateFieldSinceVersionMethod(final StringBuilder sb, final Token token, final String indent) + private static void generateFieldSinceVersionMethod( + final StringBuilder sb, final Token token, final String propertyName, final String indent) { - final String propertyName = formatPropertyName(token.name()); sb.append("\n") .append(indent).append(" public static int ").append(propertyName).append("SinceVersion()\n") .append(indent).append(" {\n") @@ -3790,14 +3788,14 @@ private static void generateFieldSinceVersionMethod(final StringBuilder sb, fina .append(indent).append(" }\n"); } - private static void generateFieldMetaAttributeMethod(final StringBuilder sb, final Token token, final String indent) + private static void generateFieldMetaAttributeMethod( + final StringBuilder sb, final Token token, final String propertyName, final String indent) { final Encoding encoding = token.encoding(); final String epoch = encoding.epoch() == null ? "" : encoding.epoch(); final String timeUnit = encoding.timeUnit() == null ? "" : encoding.timeUnit(); final String semanticType = encoding.semanticType() == null ? "" : encoding.semanticType(); final String presence = encoding.presence().toString().toLowerCase(); - final String propertyName = formatPropertyName(token.name()); sb.append("\n") .append(indent).append(" public static String ") @@ -4429,8 +4427,8 @@ private void appendDecoderDisplay( if (fieldToken.signal() == Signal.BEGIN_FIELD) { final Token encodingToken = fields.get(i + 1); - final String fieldName = formatPropertyName(fieldToken.name()); - lengthBeforeLastGeneratedSeparator = writeTokenDisplay(fieldName, encodingToken, sb, indent); + final String propertyName = formatPropertyName(fieldToken.name()); + lengthBeforeLastGeneratedSeparator = writeTokenDisplay(propertyName, encodingToken, sb, indent); i += fieldToken.componentTokenCount(); } @@ -4486,8 +4484,8 @@ private void appendDecoderDisplay( } final String characterEncoding = varData.get(i + 3).encoding().characterEncoding(); - final String varDataName = formatPropertyName(varDataToken.name()); - append(sb, indent, "builder.append(\"" + varDataName + Separator.KEY_VALUE + "\");"); + final String propertyName = formatPropertyName(varDataToken.name()); + append(sb, indent, "builder.append(\"" + propertyName + Separator.KEY_VALUE + "\");"); if (null == characterEncoding) { final String name = Generators.toUpperFirstChar(varDataToken.name()); @@ -4498,12 +4496,12 @@ private void appendDecoderDisplay( if (isAsciiEncoding(characterEncoding)) { append(sb, indent, "builder.append('\\'');"); - append(sb, indent, formatGetterName(varDataToken.name()) + "(builder);"); + append(sb, indent, formatGetterName(propertyName) + "(builder);"); append(sb, indent, "builder.append('\\'');"); } else { - append(sb, indent, "builder.append('\\'').append(" + varDataName + "()).append('\\'');"); + append(sb, indent, "builder.append('\\'').append(" + propertyName + "()).append('\\'');"); } } diff --git a/sbe-tool/src/test/resources/code-generation-schema.xml b/sbe-tool/src/test/resources/code-generation-schema.xml index c6a6633f8b..2e530a3af5 100644 --- a/sbe-tool/src/test/resources/code-generation-schema.xml +++ b/sbe-tool/src/test/resources/code-generation-schema.xml @@ -180,6 +180,8 @@ + + diff --git a/sbe-tool/src/test/resources/dto-test-schema.xml b/sbe-tool/src/test/resources/dto-test-schema.xml index 12ef9d6ef7..dd7bae3f8b 100644 --- a/sbe-tool/src/test/resources/dto-test-schema.xml +++ b/sbe-tool/src/test/resources/dto-test-schema.xml @@ -20,6 +20,10 @@
      + + + + @@ -62,6 +66,12 @@ B C + + 0 + 1 + 222 + 254 + 0 1 @@ -115,66 +125,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 0d3cd0e322a45c83e2461bc51fb9f69d8c4d2c94 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 30 Aug 2025 19:14:50 +0200 Subject: [PATCH 1426/1594] [Java] Format property name for C# code. --- build.gradle | 4 +++- .../sbe/generation/csharp/CSharpGenerator.java | 12 ++++++------ .../src/test/resources/code-generation-schema.xml | 3 +++ sbe-tool/src/test/resources/dto-test-schema.xml | 3 +++ 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index 90102a340e..72af0e9eb9 100644 --- a/build.gradle +++ b/build.gradle @@ -958,8 +958,10 @@ tasks.register('generateCSharpTestDtos', JavaExec) { 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharpDtos', 'sbe.xinclude.aware': 'true', 'sbe.validation.xsd': validationXsdPath, + 'sbe.keyword.append.token': 'X', 'sbe.types.package.override': 'true') - args = ['sbe-samples/src/main/resources/example-extension-schema.xml'] + args = ['sbe-tool/src/test/resources/dto-test-schema.xml', + 'sbe-samples/src/main/resources/example-extension-schema.xml'] } tasks.register('generateCSharpExplicitPackageOverrideCodecs', JavaExec) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index a5dc0b2354..ee123b7ad7 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -534,7 +534,7 @@ private CharSequence generateVarData( if (token.signal() == Signal.BEGIN_VAR_DATA) { generateFieldIdMethod(sb, token, indent); - generateSinceActingDeprecated(sb, indent, CSharpUtil.formatPropertyName(token.name()), token); + generateSinceActingDeprecated(sb, indent, formatPropertyName(token.name()), token); generateOffsetMethod(sb, token, indent); final Token varDataToken = Generators.findFirst("varData", tokens, i); @@ -1608,12 +1608,12 @@ private CharSequence generateFullyEncodedCheck( private static String accessOrderListenerMethodName(final Token token) { - return "On" + Generators.toUpperFirstChar(token.name()) + "Accessed"; + return "On" + Generators.toUpperFirstChar(formatPropertyName(token.name())) + "Accessed"; } private static String accessOrderListenerMethodName(final Token token, final String suffix) { - return "On" + Generators.toUpperFirstChar(token.name()) + suffix + "Accessed"; + return "On" + Generators.toUpperFirstChar(formatPropertyName(token.name())) + suffix + "Accessed"; } private static void generateAccessOrderListenerMethod( @@ -1956,7 +1956,7 @@ private CharSequence generateFields( generateFieldIdMethod(sb, signalToken, indent + INDENT); generateSinceActingDeprecated( - sb, indent + INDENT, CSharpUtil.formatPropertyName(signalToken.name()), signalToken); + sb, indent + INDENT, formatPropertyName(signalToken.name()), signalToken); generateOffsetMethod(sb, signalToken, indent + INDENT); generateFieldMetaAttributeMethod(sb, signalToken, indent + INDENT); @@ -1997,7 +1997,7 @@ private void generateFieldIdMethod(final StringBuilder sb, final Token token, fi { sb.append(String.format("\n" + indent + "public const int %sId = %d;\n", - CSharpUtil.formatPropertyName(token.name()), + formatPropertyName(token.name()), token.id())); } @@ -2005,7 +2005,7 @@ private void generateOffsetMethod(final StringBuilder sb, final Token token, fin { sb.append(String.format("\n" + indent + "public const int %sOffset = %d;\n", - CSharpUtil.formatPropertyName(token.name()), + formatPropertyName(token.name()), token.offset())); } diff --git a/sbe-tool/src/test/resources/code-generation-schema.xml b/sbe-tool/src/test/resources/code-generation-schema.xml index 2e530a3af5..e9b88942a1 100644 --- a/sbe-tool/src/test/resources/code-generation-schema.xml +++ b/sbe-tool/src/test/resources/code-generation-schema.xml @@ -174,6 +174,9 @@ + + + diff --git a/sbe-tool/src/test/resources/dto-test-schema.xml b/sbe-tool/src/test/resources/dto-test-schema.xml index dd7bae3f8b..891e4bef91 100644 --- a/sbe-tool/src/test/resources/dto-test-schema.xml +++ b/sbe-tool/src/test/resources/dto-test-schema.xml @@ -196,6 +196,9 @@ + + + From 6200b472a55f8fdfebf420a48f10fe731d785b6e Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 30 Aug 2025 19:30:09 +0200 Subject: [PATCH 1427/1594] [C++] Fix composite encode generation to use formatted property names, i.e. escape keywords. --- .../sbe/generation/cpp/CppDtoGenerator.java | 62 ++++++++----------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index baf01b639e..8aa13494ad 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -1005,8 +1005,7 @@ private void generateArrayEncodeWith( return; } - final String propertyName = fieldToken.name(); - final String formattedPropertyName = formatPropertyName(propertyName); + final String formattedPropertyName = formatPropertyName(fieldToken.name()); if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) { @@ -1014,13 +1013,13 @@ private void generateArrayEncodeWith( final String value = fieldToken.isOptionalEncoding() ? accessor + ".value_or(" + "\"\"" + ")" : accessor; - sb.append(indent).append("codec.put").append(toUpperFirstChar(propertyName)).append("(") + sb.append(indent).append("codec.put").append(toUpperFirstChar(formattedPropertyName)).append("(") .append(value).append(".c_str());\n"); } else { final String typeName = cppTypeName(typeToken.encoding().primitiveType()); - final String vectorVar = toLowerFirstChar(propertyName) + "Vector"; + final String vectorVar = toLowerFirstChar(formattedPropertyName) + "Vector"; final String accessor = "dto." + formattedPropertyName + "()"; final String value = fieldToken.isOptionalEncoding() ? @@ -1034,7 +1033,7 @@ private void generateArrayEncodeWith( .append(typeToken.arrayLength()).append(")\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("throw std::invalid_argument(\"") - .append(propertyName) + .append(formattedPropertyName) .append(": array length != ") .append(typeToken.arrayLength()) .append("\");\n") @@ -1083,8 +1082,7 @@ private void generateEnumEncodeWith( return; } - final String propertyName = fieldToken.name(); - final String formattedPropertyName = formatPropertyName(propertyName); + final String formattedPropertyName = formatPropertyName(fieldToken.name()); sb.append(indent).append("codec.").append(formattedPropertyName).append("(dto.") .append(formattedPropertyName).append("());\n"); @@ -1096,8 +1094,7 @@ private void generateComplexPropertyEncodeWith( final Token typeToken, final String indent) { - final String propertyName = fieldToken.name(); - final String formattedPropertyName = formatPropertyName(propertyName); + final String formattedPropertyName = formatPropertyName(fieldToken.name()); final String typeName = formatDtoClassName(typeToken.applicableTypeName()); sb.append(indent).append(typeName).append("::encodeWith(codec.") @@ -1225,7 +1222,7 @@ private void generateFields( if (signalToken.signal() == Signal.BEGIN_FIELD) { final Token encodingToken = tokens.get(i + 1); - final String propertyName = signalToken.name(); + final String propertyName = formatPropertyName(signalToken.name()); switch (encodingToken.signal()) { @@ -1258,7 +1255,6 @@ private void generateComplexProperty( final String indent) { final String typeName = formatDtoClassName(typeToken.applicableTypeName()); - final String formattedPropertyName = formatPropertyName(propertyName); final String fieldName = "m_" + toLowerFirstChar(propertyName); classBuilder.appendField() @@ -1267,7 +1263,7 @@ private void generateComplexProperty( classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("[[nodiscard]] const ").append(typeName).append("& ") - .append(formattedPropertyName).append("() const\n") + .append(propertyName).append("() const\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") .append(indent).append("}\n"); @@ -1275,7 +1271,7 @@ private void generateComplexProperty( classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("[[nodiscard]] ").append(typeName).append("& ") - .append(formattedPropertyName).append("()\n") + .append(propertyName).append("()\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") .append(indent).append("}\n"); @@ -1290,8 +1286,6 @@ private void generateEnumProperty( { final String enumName = formatClassName(typeToken.applicableTypeName()) + "::Value"; - final String formattedPropertyName = formatPropertyName(propertyName); - if (fieldToken.isConstantEncoding()) { final String constValue = fieldToken.encoding().constValue().toString(); @@ -1300,7 +1294,7 @@ private void generateEnumProperty( classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("[[nodiscard]] static ").append(enumName).append(" ") - .append(formattedPropertyName).append("()\n") + .append(propertyName).append("()\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("return ").append(enumName).append("::") .append(caseName).append(";\n") @@ -1316,14 +1310,14 @@ private void generateEnumProperty( classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("[[nodiscard]] ").append(enumName).append(" ") - .append(formattedPropertyName).append("() const\n") + .append(propertyName).append("() const\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") .append(indent).append("}\n"); classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("void ").append(formattedPropertyName) + .append(indent).append("void ").append(propertyName) .append("(").append(enumName).append(" value)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append(fieldName).append(" = value;\n") @@ -1378,7 +1372,6 @@ private void generateArrayProperty( final String indent) { final String fieldName = "m_" + toLowerFirstChar(propertyName); - final String formattedPropertyName = formatPropertyName(propertyName); final String validateMethod = "validate" + toUpperFirstChar(propertyName); if (typeToken.encoding().primitiveType() == PrimitiveType.CHAR) @@ -1394,14 +1387,14 @@ private void generateArrayProperty( classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("[[nodiscard]] const ").append(typeName).append("& ") - .append(formattedPropertyName).append("() const\n") + .append(propertyName).append("() const\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") .append(indent).append("}\n"); classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("void ").append(formattedPropertyName) + .append(indent).append("void ").append(propertyName) .append("(const ").append(typeName).append("& borrowedValue)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append(fieldName).append(" = borrowedValue;\n") @@ -1409,7 +1402,7 @@ private void generateArrayProperty( classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("void ").append(formattedPropertyName).append("(") + .append(indent).append("void ").append(propertyName).append("(") .append(typeName).append("&& ownedValue)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append(fieldName).append(" = std::move(ownedValue);\n") @@ -1423,7 +1416,7 @@ private void generateArrayProperty( validateMethod, typeName, "std::string", - formattedPropertyName); + propertyName); } else { @@ -1440,14 +1433,14 @@ private void generateArrayProperty( classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("[[nodiscard]] ").append(typeName).append(" ") - .append(formattedPropertyName).append("() const\n") + .append(propertyName).append("() const\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") .append(indent).append("}\n"); classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("void ").append(formattedPropertyName).append("(") + .append(indent).append("void ").append(propertyName).append("(") .append(typeName).append("& borrowedValue").append(")\n") .append(indent).append("{\n") .append(indent).append(INDENT).append(validateMethod).append("(borrowedValue);\n") @@ -1456,7 +1449,7 @@ private void generateArrayProperty( classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("void ").append(formattedPropertyName).append("(") + .append(indent).append("void ").append(propertyName).append("(") .append(typeName).append("&& ownedValue").append(")\n") .append(indent).append("{\n") .append(indent).append(INDENT).append(validateMethod).append("(ownedValue);\n") @@ -1471,7 +1464,7 @@ private void generateArrayProperty( validateMethod, typeName, vectorTypeName, - formattedPropertyName); + propertyName); } } @@ -1538,7 +1531,6 @@ private void generateSingleValueProperty( fieldToken, elementTypeName ); - final String formattedPropertyName = formatPropertyName(propertyName); final String fieldName = "m_" + toLowerFirstChar(propertyName); final String validateMethod = "validate" + toUpperFirstChar(propertyName); @@ -1548,14 +1540,14 @@ private void generateSingleValueProperty( classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) .append(indent).append("[[nodiscard]] ").append(typeName).append(" ") - .append(formattedPropertyName).append("() const\n") + .append(propertyName).append("() const\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("return ").append(fieldName).append(";\n") .append(indent).append("}\n"); classBuilder.appendPublic().append("\n") .append(generateDocumentation(indent, fieldToken)) - .append(indent).append("void ").append(formattedPropertyName).append("(") + .append(indent).append("void ").append(propertyName).append("(") .append(typeName).append(" value)\n") .append(indent).append("{\n") .append(indent).append(INDENT).append(validateMethod).append("(value);\n") @@ -1570,7 +1562,6 @@ private void generateSingleValueProperty( indent, validateMethod, typeName, - formattedPropertyName, elementTypeName, encoding); } @@ -1583,7 +1574,6 @@ private static void generateSingleValuePropertyValidateMethod( final String indent, final String validateMethod, final CharSequence typeName, - final String formattedPropertyName, final String elementTypeName, final Encoding encoding) { @@ -1613,7 +1603,7 @@ private static void generateSingleValuePropertyValidateMethod( validateBuilder.append(indent).append(INDENT) .append("if (value.value() == ").append(codecClassName).append("::") - .append(formattedPropertyName).append("NullValue())\n") + .append(propertyName).append("NullValue())\n") .append(indent).append(INDENT) .append("{\n") .append(indent).append(INDENT).append(INDENT) @@ -1636,7 +1626,7 @@ private static void generateSingleValuePropertyValidateMethod( { validateBuilder.append(indent).append(INDENT) .append("if (").append(value).append(" < ") - .append(codecClassName).append("::").append(formattedPropertyName).append("MinValue())\n") + .append(codecClassName).append("::").append(propertyName).append("MinValue())\n") .append(indent).append(INDENT) .append("{\n") .append(indent).append(INDENT).append(INDENT) @@ -1652,7 +1642,7 @@ private static void generateSingleValuePropertyValidateMethod( { validateBuilder.append(indent).append(INDENT) .append("if (").append(value).append(" > ") - .append(codecClassName).append("::").append(formattedPropertyName).append("MaxValue())\n") + .append(codecClassName).append("::").append(propertyName).append("MaxValue())\n") .append(indent).append(INDENT) .append("{\n") .append(indent).append(INDENT).append(INDENT) @@ -1693,7 +1683,7 @@ private void generateConstPropertyMethods( .append(generateDocumentation(indent, fieldToken)) .append(indent).append("[[nodiscard]] static ") .append(cppTypeName(typeToken.encoding().primitiveType())) - .append(" ").append(formatPropertyName(propertyName)).append("()\n") + .append(" ").append(propertyName).append("()\n") .append(indent).append("{\n") .append(indent).append(INDENT).append("return ").append(literalValue).append(";\n") .append(indent).append("}\n"); From 988a0e88fb6b6eb71597dcc11a128845bc6d868f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 30 Aug 2025 19:32:53 +0200 Subject: [PATCH 1428/1594] Revert "[Java] Format property name for C# code." This reverts commit 0d3cd0e322a45c83e2461bc51fb9f69d8c4d2c94. --- build.gradle | 4 +--- .../sbe/generation/csharp/CSharpGenerator.java | 12 ++++++------ .../src/test/resources/code-generation-schema.xml | 3 --- sbe-tool/src/test/resources/dto-test-schema.xml | 3 --- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/build.gradle b/build.gradle index 72af0e9eb9..90102a340e 100644 --- a/build.gradle +++ b/build.gradle @@ -958,10 +958,8 @@ tasks.register('generateCSharpTestDtos', JavaExec) { 'sbe.target.language': 'uk.co.real_logic.sbe.generation.csharp.CSharpDtos', 'sbe.xinclude.aware': 'true', 'sbe.validation.xsd': validationXsdPath, - 'sbe.keyword.append.token': 'X', 'sbe.types.package.override': 'true') - args = ['sbe-tool/src/test/resources/dto-test-schema.xml', - 'sbe-samples/src/main/resources/example-extension-schema.xml'] + args = ['sbe-samples/src/main/resources/example-extension-schema.xml'] } tasks.register('generateCSharpExplicitPackageOverrideCodecs', JavaExec) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index ee123b7ad7..a5dc0b2354 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -534,7 +534,7 @@ private CharSequence generateVarData( if (token.signal() == Signal.BEGIN_VAR_DATA) { generateFieldIdMethod(sb, token, indent); - generateSinceActingDeprecated(sb, indent, formatPropertyName(token.name()), token); + generateSinceActingDeprecated(sb, indent, CSharpUtil.formatPropertyName(token.name()), token); generateOffsetMethod(sb, token, indent); final Token varDataToken = Generators.findFirst("varData", tokens, i); @@ -1608,12 +1608,12 @@ private CharSequence generateFullyEncodedCheck( private static String accessOrderListenerMethodName(final Token token) { - return "On" + Generators.toUpperFirstChar(formatPropertyName(token.name())) + "Accessed"; + return "On" + Generators.toUpperFirstChar(token.name()) + "Accessed"; } private static String accessOrderListenerMethodName(final Token token, final String suffix) { - return "On" + Generators.toUpperFirstChar(formatPropertyName(token.name())) + suffix + "Accessed"; + return "On" + Generators.toUpperFirstChar(token.name()) + suffix + "Accessed"; } private static void generateAccessOrderListenerMethod( @@ -1956,7 +1956,7 @@ private CharSequence generateFields( generateFieldIdMethod(sb, signalToken, indent + INDENT); generateSinceActingDeprecated( - sb, indent + INDENT, formatPropertyName(signalToken.name()), signalToken); + sb, indent + INDENT, CSharpUtil.formatPropertyName(signalToken.name()), signalToken); generateOffsetMethod(sb, signalToken, indent + INDENT); generateFieldMetaAttributeMethod(sb, signalToken, indent + INDENT); @@ -1997,7 +1997,7 @@ private void generateFieldIdMethod(final StringBuilder sb, final Token token, fi { sb.append(String.format("\n" + indent + "public const int %sId = %d;\n", - formatPropertyName(token.name()), + CSharpUtil.formatPropertyName(token.name()), token.id())); } @@ -2005,7 +2005,7 @@ private void generateOffsetMethod(final StringBuilder sb, final Token token, fin { sb.append(String.format("\n" + indent + "public const int %sOffset = %d;\n", - formatPropertyName(token.name()), + CSharpUtil.formatPropertyName(token.name()), token.offset())); } diff --git a/sbe-tool/src/test/resources/code-generation-schema.xml b/sbe-tool/src/test/resources/code-generation-schema.xml index e9b88942a1..2e530a3af5 100644 --- a/sbe-tool/src/test/resources/code-generation-schema.xml +++ b/sbe-tool/src/test/resources/code-generation-schema.xml @@ -174,9 +174,6 @@ - - - diff --git a/sbe-tool/src/test/resources/dto-test-schema.xml b/sbe-tool/src/test/resources/dto-test-schema.xml index 891e4bef91..dd7bae3f8b 100644 --- a/sbe-tool/src/test/resources/dto-test-schema.xml +++ b/sbe-tool/src/test/resources/dto-test-schema.xml @@ -196,9 +196,6 @@ - - - From 0130951cd2da5c48107444b6a05a5b3afa814f1a Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 16 Sep 2025 16:42:28 +0200 Subject: [PATCH 1429/1594] [CI] Upgrade `setup-java` and `checkout` actions. --- .github/workflows/ci.yml | 34 +++++++++++++++++----------------- .github/workflows/codeql.yml | 12 ++++++------ .github/workflows/release.yml | 4 ++-- .github/workflows/slow.yml | 2 +- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d7129e13a..ef8d1bc7b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,11 +36,11 @@ jobs: os: [ 'ubuntu-24.04', 'windows-latest', 'macos-15' ] steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.sha }} - name: Setup java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ matrix.java }} @@ -57,7 +57,7 @@ jobs: echo "BUILD_JAVA_HOME=$env:JAVA_HOME" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append echo "BUILD_JAVA_VERSION=${{ matrix.java }}" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Setup java to run Gradle - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -91,11 +91,11 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.sha }} - name: Setup java to run Gradle script - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -137,7 +137,7 @@ jobs: CXX: g++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.sha }} - name: Install compiler @@ -146,7 +146,7 @@ jobs: sudo apt-get update sudo apt-get install -y g++-${{ matrix.version }} - name: Setup java to run Gradle script - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -173,7 +173,7 @@ jobs: CXX: clang++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.sha }} - name: Install compiler @@ -184,7 +184,7 @@ jobs: sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} - name: Setup java to run Gradle script - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -211,11 +211,11 @@ jobs: CXX: clang++ steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.sha }} - name: Setup java to run Gradle script - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -242,11 +242,11 @@ jobs: CXX: cl steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.sha }} - name: Setup java to run Gradle script - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -270,7 +270,7 @@ jobs: rust: [ stable, beta, nightly ] steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.sha }} - name: Rust setup @@ -278,7 +278,7 @@ jobs: with: toolchain: ${{ matrix.rust }} - name: Setup java to run Gradle script - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -301,7 +301,7 @@ jobs: version: [ '1.23.x', '1.24.x' ] steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.sha }} - name: Setup Go @@ -309,7 +309,7 @@ jobs: with: go-version: ${{ matrix.version }} - name: Setup java to run Gradle script - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b072c655ad..4832f66097 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,12 +39,12 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.sha }} - name: Setup java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ matrix.java }} @@ -89,7 +89,7 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.sha }} @@ -102,7 +102,7 @@ jobs: ${{ runner.os }}-nuget- - name: Setup java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -152,12 +152,12 @@ jobs: CXX: g++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.sha }} - name: Setup java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c38dd27632..acbd160259 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,11 +41,11 @@ jobs: runs-on: ubuntu-24.04 steps: - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.ref }} - name: Setup java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index feb48c79c8..29de4d7c2c 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -42,7 +42,7 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - name: Setup java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ matrix.java }} From feea62b27ed064a2203772224693bcba5b8ed7d5 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 16 Sep 2025 16:56:39 +0200 Subject: [PATCH 1430/1594] [CI] JDK 25 GA. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef8d1bc7b1..5037420eba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '17', '21', '24' ] + java: [ '17', '21', '25' ] os: [ 'ubuntu-24.04', 'windows-latest', 'macos-15' ] steps: - name: Checkout code From 3f3bfcd3b056bde13cb5f2cbbb960db93ea2e185 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 16 Sep 2025 17:12:34 +0200 Subject: [PATCH 1431/1594] Revert "[CI] JDK 25 GA." This reverts commit feea62b27ed064a2203772224693bcba5b8ed7d5. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5037420eba..ef8d1bc7b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '17', '21', '25' ] + java: [ '17', '21', '24' ] os: [ 'ubuntu-24.04', 'windows-latest', 'macos-15' ] steps: - name: Checkout code From ef381e4b87485ef522a573fe9f62c990a4afd838 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 11:01:03 +0200 Subject: [PATCH 1432/1594] [CI] Use JDK 25 Zulu build. --- .github/workflows/ci.yml | 2 +- .github/workflows/slow.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef8d1bc7b1..5037420eba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ '17', '21', '24' ] + java: [ '17', '21', '25' ] os: [ 'ubuntu-24.04', 'windows-latest', 'macos-15' ] steps: - name: Checkout code diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 29de4d7c2c..0e40379a1d 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -33,7 +33,7 @@ jobs: timeout-minutes: 120 strategy: matrix: - java: [ '21' ] + java: [ '25' ] dotnet: [ '8.0.x' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true From d001777de1e2a6bad409f72a1c481431af3e1fbc Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 12:40:35 +0200 Subject: [PATCH 1433/1594] [CI] Add `Clang` 21. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5037420eba..b3c08cb75f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -167,7 +167,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '13', '14', '15', '16', '17', '18', '19', '20' ] + version: [ '13', '14', '15', '16', '17', '18', '19', '20', '21' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} From 03852443a6d490c9860b0e62fe52aa1f253cc90f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 12:41:16 +0200 Subject: [PATCH 1434/1594] [CI] Release without running other builds. --- .github/workflows/release.yml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index acbd160259..e643e54186 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,29 +15,11 @@ env: JAVA_VERSION: '17' jobs: - ci: - uses: ./.github/workflows/ci.yml - permissions: - contents: read - - slow: - uses: ./.github/workflows/slow.yml - permissions: - contents: read - - codeql: - uses: ./.github/workflows/codeql.yml - permissions: - actions: read - contents: read - security-events: write - release: name: Release java artifacts permissions: contents: write packages: write - needs: [ ci , codeql, slow ] runs-on: ubuntu-24.04 steps: - name: checkout From bf97e11f66c8402b6930dd9c8f74ffcf25cff5fd Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:00:31 +0200 Subject: [PATCH 1435/1594] [C] Workaround GoogleTest compilation issue on `Clang` 21. --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 326986a509..22c1dd9205 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,11 @@ find_package(Threads) if (UNIX) add_compile_options(-Wall -Wpedantic -Wextra -Wno-unused-parameter) + if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "21.0") + # See gtest: https://github.com/google/googletest/issues/4762 + add_compile_options(-Wno-error=character-conversion) + endif () + if (C_WARNINGS_AS_ERRORS) add_compile_options($<$:-Werror>) endif (C_WARNINGS_AS_ERRORS) From 0bc446c836c9826846d2b8571ba2aba4396c1a8e Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:05:03 +0200 Subject: [PATCH 1436/1594] [CI] Add `GCC` 15. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3c08cb75f..3c9896c369 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,7 +131,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '11', '12', '13', '14' ] + version: [ '11', '12', '13', '14', '15' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} From ee72467ae754e5fbe19c63f345798d39e7b029e7 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:16:18 +0200 Subject: [PATCH 1437/1594] [C] Bump mimium required CMake version to `3.30`. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 22c1dd9205..7d4b2c354a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,8 +14,8 @@ # limitations under the License. # -cmake_minimum_required(VERSION 3.6.1 FATAL_ERROR) -cmake_policy(VERSION 3.6.1) +cmake_minimum_required(VERSION 3.30 FATAL_ERROR) +cmake_policy(VERSION 3.30) file(STRINGS version.txt SBE_VERSION_TXT LIMIT_COUNT 1 REGEX "^[0-9]+(\\.[0-9]+)+") string(REGEX REPLACE "^([0-9]+(\\.[0-9]+)+).*$" "\\1" SBE_VERSION_NUMERIC "${SBE_VERSION_TXT}") From fec7f539b0beb6b456e02c8319be33454937a105 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:29:57 +0200 Subject: [PATCH 1438/1594] Revert "[CI] Add `GCC` 15." This reverts commit 0bc446c836c9826846d2b8571ba2aba4396c1a8e. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c9896c369..b3c08cb75f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,7 +131,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '11', '12', '13', '14', '15' ] + version: [ '11', '12', '13', '14' ] env: CC: gcc-${{ matrix.version }} CXX: g++-${{ matrix.version }} From 76ceb08bcfcb46c433ad508daffcfdefea09a7dc Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 15:16:48 +0200 Subject: [PATCH 1439/1594] [C] Bump `GoogleTest` to 1.14.0. --- CMakeLists.txt | 40 +++++++------------------ cppbuild/googletest-1.14.0.zip | Bin 0 -> 1090859 bytes cppbuild/googletest-release-1.12.1.zip | Bin 1081236 -> 0 bytes sbe-tool/src/test/c/CMakeLists.txt | 7 ++--- sbe-tool/src/test/cpp/CMakeLists.txt | 6 ++-- 5 files changed, 15 insertions(+), 38 deletions(-) create mode 100644 cppbuild/googletest-1.14.0.zip delete mode 100644 cppbuild/googletest-release-1.12.1.zip diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d4b2c354a..32f07dd810 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,13 +16,15 @@ cmake_minimum_required(VERSION 3.30 FATAL_ERROR) cmake_policy(VERSION 3.30) +cmake_policy(SET CMP0003 NEW) +cmake_policy(SET CMP0135 NEW) file(STRINGS version.txt SBE_VERSION_TXT LIMIT_COUNT 1 REGEX "^[0-9]+(\\.[0-9]+)+") string(REGEX REPLACE "^([0-9]+(\\.[0-9]+)+).*$" "\\1" SBE_VERSION_NUMERIC "${SBE_VERSION_TXT}") project("sbe" VERSION "${SBE_VERSION_NUMERIC}") -include(ExternalProject) +include(FetchContent) include(CheckLibraryExists) if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) @@ -63,36 +65,12 @@ if (NOT DEFINED CMAKE_C_EXTENSIONS) endif () if (SBE_TESTS) - set(SBE_THIRDPARTY_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/thirdparty") - - ExternalProject_Add( - gtest - URL ${CMAKE_CURRENT_SOURCE_DIR}/cppbuild/googletest-release-1.12.1.zip - URL_MD5 2648d4138129812611cf6b6b4b497a3b - PREFIX "${SBE_THIRDPARTY_BINARY_DIR}/gtest" - CMAKE_ARGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER};-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} - BUILD_BYPRODUCTS "${SBE_THIRDPARTY_BINARY_DIR}/gtest/src/gtest-build/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX};${SBE_THIRDPARTY_BINARY_DIR}/gtest/src/gtest-build/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock_main${CMAKE_STATIC_LIBRARY_SUFFIX}" - INSTALL_COMMAND "" - LOG_CONFIGURE ON - LOG_BUILD ON - ) - - ExternalProject_Get_Property(gtest source_dir) - set(GTEST_SOURCE_DIR ${source_dir}) - ExternalProject_Get_Property(gtest binary_dir) - set(GTEST_BINARY_DIR ${binary_dir}) - - if (MSVC AND CMAKE_BUILD_TYPE STREQUAL "Debug") - set(GTEST_POSTFIX "d") - else () - set(GTEST_POSTFIX "") - endif () + FetchContent_Declare( + gmock + URL ${CMAKE_CURRENT_SOURCE_DIR}/cppbuild/googletest-1.14.0.zip + URL_MD5 b4911e882c51cba34bebfb5df500a650) - set(GTEST_LIBS - ${GTEST_BINARY_DIR}/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX} - ${GTEST_BINARY_DIR}/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gtest${CMAKE_STATIC_LIBRARY_SUFFIX} - ${GTEST_BINARY_DIR}/lib/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gtest_main${CMAKE_STATIC_LIBRARY_SUFFIX} - ) + FetchContent_MakeAvailable(gmock) endif () find_package(Threads) @@ -132,6 +110,8 @@ elseif (MSVC) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd /Od /Zi /MP") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT /MP") + set(CMAKE_C_FLAGS_DEBUG "/MTd") + set(CMAKE_C_FLAGS_RELEASE "/MT") if (C_WARNINGS_AS_ERRORS) add_compile_options($<$:/WX>) diff --git a/cppbuild/googletest-1.14.0.zip b/cppbuild/googletest-1.14.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..1b1f7034c68dc3c6f2a6bc3150b8379c4b9ff991 GIT binary patch literal 1090859 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
    18. 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Ξ7|y2X}J0h0r;A;_;Y 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%0D)pf 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%0DPa;%l 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�TC53Gu$dA1Q6F5F2)U82wnx-E6+ks2TWIx=TH z$wP(h4nv>;7eA9v+whgxPIEH;wll4Q*H4T6;i-r$7a!8vyV0P|S!dgrQwDG(B58UF zbAWOLdJAAbNJv>JR)(V;7Yd4Ao}pTQsr00UDCRnT$6&$j+?{92(Ong}MyqZz6+3gi zx9pDeZWPg6(&YD2eoRhtLhI2fYdy@LHET=n!#4bh`Hxc;Ci9l5udIEef{FY#uEuG@ zd!?n&9P>|Nr`E{*;Oo8g-9_1AF#>p?OD8=^6vXZI%u&VYnRDBbbt0{5?Y)W)0CR|L zM%LW0@8)rO(SUQ~?s{Dtf}dPaNSfu3LwQUP?pVF_Ds|>5slwr-4z<^&I>o+C;);}< zvP1%^Rp2ecmX!h z+Zp_%1~mMe_HD$7SU0ds;&KWBA(l?eT!NE_YsxX@>qYwo^pW=y%ZjbzRuv@`$~lz zM{^Za3O2oyjdPpz9&3S}b)QD{`h^s#CXw{3s%M2cUwM?dtINlL?Hr8GMv4c(_mZw?Cn9e0^2 zX0yH55A^3csIKlVj2R3a7wgg7vc`a*oI~Yb4?eHei+U(G5YOE_TmB&~xv{SS?imz(m#hpYw?vJN} zG4c0_pG0|+UkF~9BkRsXfO&{^l0@(2hf!B$=?*1Z7s^TZtshr%?H^akgU5|W?lv|R z$KD46xT{(U^9Ov$o9Xe@6KD}Hkn31{r)~iFs7yjbqF?{t((b7hxm=>p!_GCi)0FX@* z`4R#{M_N%!=>&61(l7@a(Nvm}ORal+Ys$A&oF>ZSg!xR_0`2|0 zGI{nS0OR*6Fd`~ZU6$+^YU$FY@BC;md52pP;H)Y?Eh!}z?LkkW!7Wew!3%~-Y>Yep zn6uFtfdVG7g0G{v-QDZj5FJ?`M z4Q-{jm8(*NYJH!prq`{*n22zFS2KZ5SG?-Nw#;b30Ze_)%Q1Z7W) zD1YYcHwb@Tteo#@eR99@`J{6|iZpApq1q?w&iEA6{Y0dHI^G?GlU+m{ve~on$TlNG z0mqh(zOgHU*As<)GYK|oPiY`vr)*j7lE02{PKLLgVUZCiA|JeueLek>F2TB2H+kb- z58tYL!4E$q_s{=>m{p)sSw-Lj0Hiwpe?jC<_9jNOhAtM?#wL#c10uiTwQ|}RP1t#& z9+pXw9Y-|f&q|PzVh_@crwZbkQmb?Uz^Bj zv9tkX=H=!6y2f+&(|cT45=PV6LD|pK?Rx*$!XdeEp%H1obaQ!m6Qzp-?U@rLbIjC{ z1nnJLH|&UbB#Jh*ESgM4B!gy{BaKK(B)_tzJ)fkR9K06PD%E7NjrOAGKs+D)EwchD zq*)quN|hM~QAFD>6PYrZs;D>`qG58T^Vh!zh1~$~CkcQ&cHx7f4efzNQ-p(ZL=r?2 zO(z8F`!W?_Qq;4AF{=!kGWDX`#o{zH|$poC>wlykT4crnCN!PS6A@huth zM18y_%5WPg4=zTh2*5R7_EgS9_^&RWMEh44Z$Q+$(OtwG9+~Zy%FxO(VQ>b{m^8{? zAE7d83@A_92$kO`15KIE)f)=ki`c55-3J{k{5ZN$wU3t}?vOgF?ilM0`aopd3d2cd zus!b7{QC#)!=D{KcIy7#z>Wv;`Z47GXyDGmfpo*yHxY0eN5>ZvMt)Pa|8@Fk&X60v z{f5ZHn-?2)LswRG2hzvliJZQf@7DDoZ+Lq!*%S4%KJ05^VO!(ZuuU(P6wv#H3rqgBuzhQ7zX*tya@_OX3d(W4X0 z{O-<&ae%jZ73l`t`}gJA*?(frHZJr)&@XbM(eDBn5pZmQ4JcC^=3V%ed)5RX>pX_P z8Fh7R7e0*vPB*e>Tk{6wdDT0c%U+0l^;73tr5b7sKP)0GJ;dO*v56VFG`Uk_Rn z7rB_@yw312W5Dtgnw5a(ifMU$^#zz2ke4h3_k(S?W0AZfNlh%evnLJtr z0U$D=N~5@OSPY~p2MAUuPAhQirpOexl3#

      S> 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 z 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 z X&i$0W?x6f^?Ee(J`lkr~GUfP%DL?e%RZSz+bx2+&EA^&L$hwx;1>5iU!m~JEIIW##FTp{& z+FhmJ`*0beM90%@jK%zX3A9VRJ4znVjgN?Qo_b)lFSxX0wLpv+S;?J+r@e+XHmuN$ zYy5~u`mMO*ifYMKEVnyGh;$0f>p%Ay+lrWC&sdb-btGcJ_XR_y%<%|OY1Rxxqug6D zH>CxqvuD-eR~+_8oA0?auV1g`a7iiC#w#?3R2v2qDNmJ(4^W;_f9CHOVrzNScLj5O zHY(R!O)6)&N3UQN$6CvyNQznzsIYMFo47MIPF$K4W=}|gH(C&BW^ek5=>Fy9S*MHmMph5)q&$E4T2=dN zY*_*l)M*bnRbcVT`Qw)G$;-IA_>FI9L1&uKUrAn!wea}9GEZ?eDJ5pjdAgLP?1;cv zOKcY#!Zbsb(PLH74^{PudGLj_n9f1dE9x79x~5>GTjh+}KD}`Kc*o(%CF$irIT#A2 zmI{Y?pRBx>NnWuC`cG1r5tm@s0^kIm1c{KmXA_kk^**XbbZbjkt$TXKDFmVy6eX?F zl}MNfx@nCa*`<*;zE&TYe9-g>`Eo8GeKv%hl>amBi#f9M~B*-s6CXc z*b9|ZMa957O8%ni&vn+MWs&#rgpkQ{5--$yTlBmHeDR)c{nx&I#as18^m6~N4O{o& zWfE6q7xb_$z{eu(~k!)DLHfG=$FIJ zs`>*0ob?K%I%Ha$(mThA#SK@8!0cX{n{BkoZ8bwi;1<>N>9`QC&sWZaVpqz17tb_N5m2 z2e6K_>X6&pytH^+I?Fa}ir{|gNRtN6f;qcv^Jr$?v<$Tf5t$Db&xVXpz&p??l%4`CJx=Y*v zhv|GfwpbwdmI&QLBvY6$oz{f5Yx>G1LO zKn~}aFsYotcqRljd(>%m6{y?M^qz2&3z0`r-{`|?^M!sA=EDgc9gHLLiAYf#8od4t z3`kfAtiJ+X)Bxjbb+G2e6s)e`#A_OzACMPny&M2(% zZhOB03Z{wc7zKMVoqp_;ueqpVRSat2<{3_FAaWF*I|%z3`$Sp7ek;A2Ogoe$jT|te4|8LDf1(>#!2BI_^D#gZ8bv*)~?gX zR9yt?`363#GWqS>0FEz%msfnYPmpAei#SG}%)#RnnR$_*JUeY6yf*_^lk9aMRhyH9XhF zUXtQ>1r|Ya$|oYe5W2y-#dMexr2P9?EY*_wy#hEjNP28?zCv?RX(<8~JCBq7!ZC%E zsJe?Z#eQC09zU~KJgC#|cOo<{WIhgi3|CEY~jA9$V+q7o57#B%Dk@qvM@AQGD0 zX)K)W!o&pfoLAw(Wg|gsLV<*w+}$2vLS+F6Qm+o+X#`!vhY3*SvG@Vxrt&H zKDob#Xr-G0+L(ZjwkIv^`$t0CY&DRZXR-p{tTaDFmPelgK~}b{J`p~>#;u&WM5rxH>??*2#O+miW~TcLo+Y#ukFJDL?;=y0W>6exP=JA@1N~t`;({P(DEtx_ThP1nl+wQ7~B$=2NI9C03wi^%` zJa7R5W^;l3_bY6!yS1F?Ibc>W%Kn_|Pep+Q048Q{B+KOitZ-huY?cUS0Lp&BpK zWX$9--vZ#<)YI1af5%ir@536sqwRb9v-UsbzGa`Ue1R-`d-XMH15Da2S$1`wt9+vC zY4A#^q(vmi$n5I1f%6Vv)Z1GeY+N>zdV3T?)XfD!gn-S)$s5TIvyONO?s#6+_Wp2a zo&6ELFD&x=%WcKuDk|RNPHdAion%r9W^6{at>Z%rl{K$Au3b+u!%gU^1tqcMV?BPu zbm}KNmgLjG`un~RO1RA;85f0Pg=kY>3Ew?D0I@p}aRjb@j|4lfOi`0_is1+6dJiG$ zOs5EE3?4?azH}zY(GB>R+VNiMT1p6#s}UMPM&T}{Q{O*7M^4UFyS=bKB{YTG%xprc zOl3aFsbw9SEFD~+U_6MCFSQa8ZCX|if8?x;1Huw=zjhV#ohiW9D9^G*iHb1Ajg4!M zx;!C84FN3h#^_+i13MPbGDKOiL^}+@{1~hu+te$UQp%HYvi8`EcK&$7T+tFx%X=;| znP}DZ_k`=%#OT#!9Fmmo(Nx}CjO3jU2FU^6!2}5Yz3Q(C2DX4MaHbx7> z-)ImdweKZ1Nnp^zY^;Eii496N zez*t~bo!A%ZvFNDW@aw;k75wElsl-McJ(`8l`WF)O_L>C+%YRSf>|lhbrvDwr6wos zg8q&nTak8eN#WI&z*xca%xLn6b1F&7<+WqVLM4tM)yZTAm^*2x?z-z(i9(+aI zY74z*G9u;O01ZIxPUwk)Ve>nwy9fmb2+B+L4&nMQ@13O$TE{%uvR`L55=>)^vq;g^$wUw2rKdjtf0L@XhmvG~%xZ z*#E&X9~^UFxwLL!OV4*4DXmG713itL4@RN>6|h2ts4^!nXIptbG*p;m{mbW9Yh%8z z7bE4LRJn+B27W$@dqYDnXYC9=X*EMZZ~<~T0^m%pT~g^*)hTg?VluSw&v(&~K9ed1 zy9h#uz7?v(rx8TU@6XphXgiTQ35GU&pgVL;P_U2b9;xTD4+|xQF4pi?-zZ~PoX(+o zQ)vseDdNzTfx7{v<|7&N{DGtSYksIIS4{(foSEk4M9Adb%4XI?iec`YkYpk?6IW#P zWB@%0EMq#YLj`!Oy<3at>BjEo3<4;1zIMmRlpMiOOWXolq1Jv$tanfzIh zcz0VxugPm?82k^f*gr->qCZ{RYPj|WD$B@IcY(ZPFr9AY`DjC88&_>!wKZIGzVkyz z_?=>%m!2s3B))e-)r3f4gl#iHmexup;YQK9=qILgTuPa%oi81OUDWv(*Ir!>`u5s7 z|5sdt%}eo0+!cU46~(k*Bks)Iu5|%?XU={!+HWa(>cc&v9FeUh!c)KE3b{4sM5m^L zL3ayyr~6#~Y5ez>=i9}_H@>Pt>wIsqp)#^ZZw-Okq2YQEkB_XcAcBA*y0dK-cW^q1 z`XE{GFhj4h^DQsX)q;OcOF${1wekn ztqBpyEwCIa=NJxkRNrc@aBo|tzjdxL@mjt9jLlf)C0T53{&6_qb1S=-UV?;&sItt& zLNz>KZVs`#P;Sf2>-Z8POHJQg(VM}A8)Qt-G+%i|CO^`#EQ|5Bab0Vu$ zZONsyQq-R13BlrCVnO%f^H5Y?gZHIZ2;Dx>)A*`;-k5notf)ot67}7u+aJZuZfQ5% zgs(Je)CgQ}B!L|IGxn%2m}P%L^;KJ+H(B$?^0Wn;wi*v_+p2t;TcvPAdbThT%jynf zy$kF&7rWX4rEH7NW{^?2*(X17yR&RBYQCdlFZeuU*URY2bLWr#sLIngt1TjxuxJhc zA2_7=WdgL}>MJBEv!6`Hk7-_^z)50OXj1G&cWBJOBsRf6sv>GJYN>4KIYNpdZBf)O zFs`{&xc6+1Q!#&Ho4cE&>f1(Fgwb9#%_OViYdc@zzGgiwX~tWBlmDGzQktkX^@O*q zS&pB)=b=4y9j#w`wpS))I-BtRe+#_zjdW!=Fd(3INFX4V|DeEguy^|3m0gKyzuf^F zQuhZn#F-&`r&QNz`B<(=WDE3IlC+YfFO^B8T!ciS;5>AY=ubCuQ!vDq*x4>C2 z@JwWvX4ZKWF7v?-V%Rd3sBqYbyg|q#o=5c`k-yYzK1Sfyb$_^#X*^0NsgW;RxCz?X z>A-HqPW&ASijVcCad8F_IQP*85I{pv zpKjeSaxFdNlEM9IwKJ)C%q@0tWEVZMX>a6lXC0dlQA}9X-OCLEE}H+?c}_c}+cJz1 zR4!xpV@QKfR*YpNB&2d)r%K&wR#Oo|9~1rdcqJN{cLKePZ#Ga8A`Pfr1{dd{A(&Tk zBtzXbRa@kw$ABh)Ncl~a5LDYXAfrlJ|Hv;d#2Su{x`xtQ%B<(m97%ej^IOGEFY?vO zFb8J1u|op9%DTRW1oWK#go#?I$LNjKsjs8YPP1HqZlUmXm2OYPofLI((6f`lc#I_n zJ!WFq&Y4c5^iTDRY8VmGI1wR1yBX#v>-j)kxr$8^YL!XvN_x29*n(3) zChcleTM+4HGrmqD!xIQ%+7P<(4B$`GqjR4+T>oPq@JfR-yuElLX*}rB_S;e zTCoCiXTm27pJI=Vr_zs?kU-f>XTue-j$p7oJpN6iYrKiZ9b;mziGFXPuQ5zV%*%Q& zFQr!^cQBBkw@>}!``?IdCN|!tX)pign=GX68T@DO3y}QE#|SBcWc{htXGoXRXz!rB zp4^;~TJ;qFFNZtAco^9O^B4kX94t3bGxx{vu`nOyn}IBGoHa%9?LvFbEsuBjb>lyQ z*9>spwCk95Z)t|s-aqHHiD2&!%Za_ol1@h_ae1+~-Cu88qL@lo;0lkv!$&p4%zSEHrLbG7|_b7g!tZ&%=Q%8bC0F#ja z=fI*u1O&wSpIkEz|E(g~ng1^psawm|d0!0W`&xf)cv*Lsr@sH$j!iC`if|;KJAp%T zm4jY%d_Leec%+0;chBPYKLlyKYZB^msF^yr^usgv`s_N<>g5q_(cvBKttcF9x}rHA zF4K?$3w9Rd(sEn1V{ ze*M)KnQH(LOHS`E%Ht6LjPLBx5T;0;z6tNRLInq+LZ?Sr?2|{{8eoOy`6BX@Aj$<{ z1acfWzMeu7I}G+cj8l@4N0KB>%3ytcTFV;1?cHi-V0(d(HFEUlqd=mgwm9Sam6p)p zhoFW;-oS)S`oS545yzMw_h~1G#$2!7krQ!^V+4grdwTu~n)6~tV_y*ha^|d^7n0CS z(L0?cBa+BIk>wu#f^sAcicF3eb07IfP?`heoTxIK2D4- zucnD4A1dt{>c@w!BZ7`z+>Ab|33h1L$^uJsu->C8gYepJjm54N%%1NT9*v_?u>(?A%SjOD9#=@*-OcGId)R>pRI|lEN`IVuH#^Rd{}5Jr0PHba$HI=2w4ji}2`K1uiL6W15?3 z1iPelX3y{@W2q{=tp?Ukb7u=IG2zm!{o~kDrwd36>{J<@nSCW0;d*q*c#3q6roNe{ z+>&uLtB$|2jVsNp!nM1(J4Rs&vO=?m+7VV>f%DTwXZaCX`_H(4oq8LXl6 zhKA27-fM7_j2TRIqFwn9X4=+Hx<@7kNVC;ucQAIjW{H7h1a(}0geh#cyDj^fAzF+zmK52*0H@i}gO zhf!vnzx?yX&|>_!w06J6L|mzA$q`FpL(PL0_czW`V&V>GGq~)iLPdVsU2fztZAK+^ zIQxWNV;W6gQ*hY{i>VHQK{*gWaryxLHd5B{h<-@}NMU$n3YBUHkZ9$B{92_cl0vWrQObIB)Z9)2e)bwja{B*HjBu@cvFQ~|z^%Anm5%)f4 zdNH5*I)>6Cf#N&8f%a4~165yDSZaO=Y#ztcg$6xh?7j1(oxLfD%0rEgMsSnV{dG&L z6O6$Azr8&hn*!z3^!6vw;@i`iuKS>75Q=~4qu>M(^JFowM^_Iq+i{>JLg^67bI=CF zxfbm!D~>AsFrT_XE{=IAe`KUlXKbg-9Ydx>H)LOuxPVanmg|E#OBpoBM&8v2Njagc zi5h3|oH&QQ*hUrRM{=>)y~Ww37j1R;Oj&rvOr?NO3e;zm%!u7mx^yaUlGU)9VuK|U ztyGDNv$0z%$0bvCZ6I3Br(dFzlCH0m&@^^Pygn#>x?AdaVhpadaaN;nCC55)q698ZO;GD z5M#Z42@C4AJNx^2(@7u@(aL+M9o5=eEPOc0Q&u+Ke;P&=CsQ5c_#&Hj&!goa9+t7S zZJuH!3O$>}SMb2i8sen=s{PV{T8mqMe67@S&PI|nt4C=i_0jcClBACr0>1^OnO03O zhn>|opcYi8b;1z`qk7G?x5*3fAq2x?1=eer8{MbQd_t>A^bQ$EKM4!c#46hQ&cxPr zn_T|_h`!VYL_n|E~lhVHcC}c@#KpFzbNQ1h}nF zS4rK<#kkddqWbsWXBTBD(GRq}D|06fva$n&FGRcdY^`4RWkx6YDfHJm!p)}dL|1`- z3n-!cPbyNre-9|>i=sO`_&Wx7!uCxd*w+j9EZ=1$#1~>j+ZFf~c+w35LEyLh2dXbm z0@OSH3;D-4y2G1|sva)`voF(?h?1 zV<^eoh7^r zFyM=!i1sAG{e#xOX9aF|%%@sAyuumTt0$E%^oE{QR9|o&5Z~KuzKJzC`yA zUGRHjMIa7(RZ9Lf{On7A_aE9Pz?N_Va&!B&E6kBTzktUc_-W8aS{w=eVZuiVeEf2L zU<7`M_uuemmV5bsKsV-ofd6N@GL8Rl-U$>4sQX{*i|Ic~SN>O?Qlh?Lw=RI>`=TzB zoaWjIEJG)oj5N+FS2rQMt0Y>{rkn&*g5%w#d}SxMi(bbJS+Vb`qW#)q+mcEJayJB3$sJ^uu4(mPkrqc6z;{rh%jIDW*;JK)QyY> zhwD2JLcs02r>!k|GkdfnSedep@_QY;`Os}t} za5u9RuwI!xfGS0{5=YT(#sFt1Jz5irA8S;<$BeizC;ZcpAB)POf|9W870=r7TB*Ty zX;%6#lD#8u3{Z@F37B}sHX7*CTeO4tqdPP_BdO9QjUM6;&=etDOOiDV@e45?`TfMC zaS@TU~8n^o^E_+PaPJJr*W)#UM%J8@S0jb~W*o z^~P*kyv#=yx6mw8$?*!Q6lZD+1d`#rx*)$Jb0WnMd%=EDA$7>}0EjXoz!!bnHvuZkoh`mAYzI-2>C%C!Ib;2> zFRvjVbH`&za3t(ds>)Mg{zmcYln13thNX6kOe3L-459o*T#@Y^dCu!M<)Ms0>Q?KnJ73T?-4o-+j%N09S?IHMKph~>} z-eU$h9(oTXVY@=Cfmugh#%X-qy+#HXarAh4oZbY~ZPf+cTo1W9X|D&p(61$C=eISNQZF(5(i^|rhYV1jMq$B$O8OB)Cz@o(*KtOlIz(BnJ zK^Qwbm>Sa>xmwzom^%G`%!z!z)Hfs=PH#TZeKQ`I!T^xiOlySrFPO$CdEiq<%xj$V zH?L6I0eUfqzfGXHvp!mT-%nFJN>XXC$4t!0PquN1UDM7h|9k0oA>|mj;d`mC)LYov z_f|x|2s*I3iq7D(FY9$7U7e}SUPy%49fq}DgXJAmGQ01KI-crI8Pnf}9>@>zIE9`> zQ>2F*r{(H+^q_7>PZD%Rp6^db*NP&|`v-f*DA)x>x}U}3hA3jloknF~Z+kdi$_>%L z*>yvIM%3m2zDL117Azf3-qek7UQrRbMOPyU+V65j;D2n*kYYp}${DaBQPnr6iU1K& zxP1UaZj64~o}^C!4nHJs<5q;)ZV4G+z`$(pr96{GKgOu?Xs6?#7$ecGU@Scha=sfA zK?oONEB}G9ukSEwJ85+CXWmqnAtkVDWD4MmLjo^0VJ&*14 zJsA;gVj%_TT5u-;rH@Nz%IgO=1k3Bez@R%vL_&sI$?H?bPz6_Lhc;4Ya2J3l4^SsMFPI+`&z(`6#Tt+Yy43~z58;e z`IELS_#$xm14G|gxWNDQRQ2*bsNi#okLxl6QRwRgBrhLk-u?Ap_+t}bu)G0!+9h|h zPTm`Jy(2%<5gd4$7rA|Rrii%P4>`R~KB(uefYF^iJ@+PfbLguJ1m`%9Pn1x!?Pw20 z8~(-R%eABYh&b%{QuP4*ZFBPy=QXH*mK@%_2km!V=Py>ImfbQF);;~E_#u;>o0szp zsT=r+`v{R!lnv_rn1GsmBXfYIw-mep-*xy0u{2)0e3?Hu`g-f^_(+4G8GNj}&D*5`OX#3+@vMd_@9qQEBes&9J?+IcxUmPDY zHeey09s+9@7|jMy{|ddTrRj_wq@93Z~hN>Vb?%f z3kIdbc}+lVB4!S!u^C;|9{bgry|wiN6#n(q_=>kT%>4E?;S`&k4^$E-jK_$t?((NI zwt3P$*%kxbfd1w!QAF2kPuEq!f$XIA0v&;;GI2x&awAlWsXs!_FJ&A#ozx}4{!R*QFjw!yBK1D zwGD?dYGx=cHg?5YUq87Y(4p*r?b7IoySXQWuuvOsvCXx>*$(l_2rpv{Ul6Tq!v<%g zUk;jF;}cS#(uw)N3PLZ_H< znG&3`6h#gp213F)AqX_$BB!Y9D(R>s+udwrT@5DdjczPhXgiB`M?pAY#CHc!kSXhdzHBx288aaG~ZTwp^k_(@_ zWg@Or!@!rxIOAx*Qe;dn>w|Jusz_;TKFB|@X<@ip>+;S5JzrDFvCrD0}L9H zEJkAAKyjNPnoi2$(YR3>6zB{|_&k2*q*~-X z4>e!pr@{Gl-LYbu*OkQi$J<-xT#3YJs9@L~R1o?l#D-m`wINcQzU{=H#!ag86ixj2 zs6;KCrCT{&gx+mtME#t($XrS27X&e*S=Gzh$ctT$m2;g&~28 zK?@h^;qW{xaCtLEJg*#5WGF>Ij`386Orfda1Hq9wDSdknWXeFb9wpdC*#sa%BRK;7 zbfFI!;OycQO?c8Ifw|;6eJhKRY>^Jr6b}F3C}l2aKz@J>vqxRaGY$N{=wv~KnoNH z!zhIyE`iIVsA<=ZrXpl6O|%-pHv!bw66Wo=-RNt25!m%Th+?*qH9rjD@_JMkfy(QG zyUr4EvI<6kao^%y0b=Qvh6cKGY`7z+gV0EM%!1!IqxtQ??VD&7U3Y!vB%}9wFBz~) zO_c)pUWRC`q!uI`M@rfpk)ZXIW(cc6<_MYuCDmEXCvOj239DkYYbGlAYVgi0XJ%53}cIcY`IKG3FQ-c}rclkvHO2U7kkgmd;A$@;nrSUIg zPC@)1%FeMl6QJwXv2EL)*fuA)W7{?+oY=N)CwFX{6HIK|I8${_y;V=WU(Qq2|Ddb) z>b<+ywU{X9Q~AVc+VPsxgAOTUkX(O$s12RNYnB$wMaA~}?qqu!j5P(@`@9$}@ev@- zC@H;L3|@&0aNt)JBXucm@gV+6rnZL_@BJN*ZRwDqejHNTwz(5SOv^V|yGE&Tk*m(0 z3L~;6*V)jl#DdJ0{>Gogm01n70YEqbJ4od$-bT>lJ!xnwcKpQ zNNwx|ft*}meoVb(-j+pQ@yBX}R&KomCl+GN0Wo8i{OdA!SkX+HIfwqupG}Ycj-YDj zE1{#>>9Z^jR|$(qL7N)zcAwm5aO%396K$v=qLcc~!GiZSp=lBb5O zZR$kJ80d{0T-2S}qSn_<`zs zMomfv_7Eo|<5+LxbyGDu!LobNpJySqNZlEWI+d90E+xRAzZq3PY78ieo%J4Pc#n|F#!0cQ{C2IqxYx=56fEjv>H#x$ zX>4kxUw)^YHblcmq$V1hkDAAzx`LLn;4r9`uPx2*sU4HtH;ED~zo$cDkz|2-+msoI za0m*PY5yDtmeT-&K;Vxl4x#G@AXawgj$n`};)g?o*BYPy^y_8xX&z;-4gwN4b>LXVRnJyHT}Ht#$QyeiHkDdO7Bx^R9g!oZo*PMbeEUW_5!fTr<&zv6MJcP(m5jm;yZ4H^lBSpbCR~8V)-@Opzp-G~ zRdhyLeq3gWu~=SG%G4rP)Z3#;Wxe4=9xIQmU`diVU7k7dwC-#uHmkOPY~-l0KheMD zvn8p;kQ?t?UB{pZ8AUYej&>11nx}wfV8;GM zVIAm9nLdRp$`HDBE)n_54&_FVyOa$a#tn1r5$oelpEkK&;q2m|-oq%}pEvrxXcw?u z_MSKV)&F@8dvw(MXyhI~S!B+VEzlcq9Wz4h-wi_&=hg~knC$nAMKRMOo^#h&n6yMYWo-4JiCxf&%K$pq| zl!NMtZ@U5Iva-YOPot=2x|wBzKIZR^cf^o&ZHe+XVFhx`sBn%5AK<^#kJGJx2_Q}< zTewVNS6aymToaRa%MyX`(j*K-2>4zzDIcXzddEkLI6d&@aDPD5VhCknBj_}R*ZFnr zS?6$pB*G(dQ~Kg%Z;oYOj%T_J%}%IzAzPSdQzruw%fXmXj(Mz&$Z_k}QrDe>nN!O| zMk_uG(U8?G1Q;#V@Pe+=nrUy%V8q{Q%A8arnvSR{cd{8940>GMq4Day!=cOvK!(rUk_T>?x&<X$jvyHa7pg;X;q31Hq_>Y`}dg7&24I!EURO(;uU?MfOiBuJA~#xjoA69;6)@ z5wD; z+Hn(+k66V4n|=@yX2kFWsZC8ba3QNdWkF9F48WliT~KD{jx^5lfjH&e8PBSp3XvX* zSv-)|E9g|FG*W~xZQT4YslJt2i3|yZtr%U2gQE+U)g4(>ul?T)7{;P+f%q|Eah%CE z=QlrzkaU#5yQP@w_2BRJg{W5C*&!~7uYeS62h@lsWo|?SCYxQdXKCE6OmEu1ayJ;fz0?$#Kt%Et#~2bymH*z?ZdjimD3s#*>ds zH`#~-K?ojTOy=9mich3B2u2!|z=7B~5Uo=MQ<9>A?byR-E*m^ppEDQxr>!nxypBrc z^>V890g(fQ#tZnso-w0$y&GWqcq5=YoFZ9SaN=jaw}QfRuJ}D1gENmok6^2=`aof% zYfm1i3io3QLhw+mIV)8=Tz~OM6-wo(JD8fQV%!Y$%Xd-H)A&2$?M23mxTD-ggolHK zP3Nn%&vCfCEi=|U$Fe?%xVgx`{&`P0*Ap8F2jG8B)$T^<9hhQNzm#8jkWZimSMQ!H zV5E%PTfyW^q{eFGBklbBSRYfiNGS;j-4}0MYY-J|h7Rfh>3|~S!jPaZ>?qU$> zXq1e)fx(SI@qmoLECj<2c1Z27W_Fl{NQg6}u%jF=)=)_ns;$WHd;k8qF_DzjkRy6| zp;awDD7hP`^O3HqlCi@zAS3=+~Ts$`t4@(u^e;|aJM8w8o3%Qr{rUoar#9VVvN z?6NH<&JDRCi59+%dN#gIwy=%D$w10e991|J_p^m~K#+JVYk+!^m_+Gyh27Mr?Cv(c z7XQG$ppR8JO0VLc+!#&ds%&*dJ0CwLz;qG92I?lfT3HR4E6baufb&f6X~+hp`a#Lb zv&-b-#bb`f52l=(n9*uXZn+gw%s1{Bm~Rtt`33H)c;CgdkARgej>xV9nv=G4+c6W( zP=Cn3jf`c%|RszIR|$A0qb+qn>{vlHr1 zQt-XBD=TF^NV+52VN)e!pg9`L%{;61=^^Q9BeSn?^$Ukt#Xil)f4Qc63O2GI#}(_C)+V4RrgR%4>Sh!>D^&A@l5T5jXb?RbJVTW3B9jSI!eYGMtEp6D z0N32=^Y3%0B<`=GR3z(94$&Ps``X=K#`F-lK0ZhF5jlRkx`^mxw4|( z6fN;b^mX>ptlZ+TReirOC8lCSO^F}0^uu}O?w~bKZZs=MK`qH3qNi5_1PKU_^J%aH zZw)2aoHrr4++xGB)McGpNd^rkXJ+2|jn3$BwA5mit?8P%J}(|ksi52UNE9_Kr+jxs z4bWk&z?i|r>KH{2E$}(~MVdAfPHASAnk^rF#Fm{9aq5N&`NBhi`4~yMIYthgdoYeV zCYM(VrOacqO1At>K$2LU$JJcijrPfsBZFMEqIlhe-x=l|C(wV>!s%VeL2_Zv46r_{ zVtexM#_8ddc}jn#BUG7QOugbVNe6t?cT1rn37X=Bo4-ol&&t^v?*E!(-B>}*vz)Ng zZi-jhWR7wrNCSUMI5JjnIArez_|EC}BxVRI%HcyqwQna%VCSkgX-`_JPjWvDRUSgC z&ETVRQDHvPN#Xj-#nI+lW8QFQ!QP^z*nT3>y>fq8t-m%kQTV&}Q2IX%a+g$4!6Lh3 zy@#}0yg;~=q2sw6%j_JNDV^FKl=eiKCkjh2X{pK~>yY@Yxwj}gKu}{Le)_qblr0!j zv#+CX^bTexm3?nJ1f=Cg5BOPkv`SStONTj6&oll_qrl{fuui67B)-bAJnX0psh*U} z*H!zuImE%F!}>?l-;SW5qy@X7o}t|WJ4y+_8pGmB zdY&5*Ur5uq@59BpeLUfSExNw(jvzQhN=DNi*#U!(Gh1FV-)0bgp`r-TQyOjKvXYjYz zw6QD*c@SMQfJc7-bq~|?LSpF)e}pRE@6=BQnf5)9P?G@4r6Uz_QNlXL-|xDuuk>bS4Bz-)6E*iYT53&?cYE_1&0hN91{G0an;KsSivN;jjQy@<)mRvo$Kq-zXFUhOb0kPdg)$DCL;DhGU`h} z;#k<8WYl5D>!2{!vM&11RLG7CQT>b|K5En}DqsPE>tDV77{j+Ie#F}HDHU;ih8X!X z$>-}FroSxw(vZu7ub3fjE8m(fcqJOw%dV8GsO%2=nlL3Z8g^ryGIsPL&yzTwhkqyZ zdhzs*#WZwEk#zQWi!C-pTcbTEGp3L&_bl2N5Lm|`WAJ8T{KXFuG{j-qNF*#8W2!6YgtBf6e|wwsX= z?u3Wwqzn?Oh}{JOMH!V_y>JPHk7!oiFOs-5?!2mNx2;EgX6%u4aO9 zYBfZ*X^q-T)0O>+o|#je2gnNiykxfDIM=nN_O_KBJlHw4UAYZpNMMXUjp-@#tHr$u z`NqjjXg}Ts!A>MTXCvNqG>z7)MYU6|&2W>^k}DFm`|J0_vX$bJLnT`S-1~X1PuXQ_ zhwgm&V~=A@Xi0hYtD-JmtwhW)R3($4#@()rAW-BJ|Ap{?k7gkRncMdzZ`uQ2GAB6h z&C>`}5yOG-$yjdnn=)!!r1&p@LCWAz?NNfN$&6<5N;PSr#iADF)Xqe!E>+qZ+PKul zNL<6;DPX^t5v@P7Z04K`9hk`9Rw4@>*2VKU_8HoIdQ86ZKlQymtwsQ6XScu4aTuSo zX(QsEU=piVWAb_b4iG{8=qwA6YBjJE!+Q~*DZ+%DE;B3sDqs!foq4gTE(}k$Ez3OC zq}=N9E7M>9KE$ErGzyISWZ0JrOr#>nY^A_?%n=vpT^jBl));dpFDf>$Rh^(=D@%V) z|GS}^cwvF%5Kr0zAi4a5QhKU}beGUt2i<#%!3@cXY@?+&k04FmC->7KG!X6Opbwb1 z7{}I#7!Z}9#Zm4U?Tks;^^pS9tAt=e8&GXD zEQ^NJT(ZKAteS1_B_HlwX7~RA_uFVime`NU5spR_ohKVefEjD|Y3#q{RdDTa#EvsgD*@eX1D&i7TZm;V zS(o;t&uq7T!x8na^fV(>@=Vxz2hrQ;;SKP`%-(uue%kVLA@*|dMKxBKfm!^^WfFqh;w6cv8*d};H2i$BqaN!7ai+sy~iNx3N~2h||m$7H5` zU)Bd^uQt^?`?iC>lZhTeDP2A(J(IEfmSLklrcJ-*nd0s&N1yIWe1SGTuSveI3r}|` zzH94q2!>xzf-WK2cKK%In6Y^e1=$SwEf{XOW}NeAPgxwkUc35U+%~ABP^S3Z3OQS> zcs_!eoYhc`5D^P_q#U!`boafy9JQHPkw;<^!&fh@(sFi|IIgDfBR=bfWi%9OfXdAiC7c=@`M{<(`z~wpKyp>n;wgcu8 zqgzWE-U>UgD{KbtvV7HBnGzj#edMOi?MNxG(Nol;-t5gmBL+!o zh4WLnNa5XzGfHOI;kd_tjN8q0+V&5B2X7~|2k(vuI~K#`MzbwaLdbtxqtK}iN8RMOYj z9f)gn2o-{?wXQvMk2Xt}5j~cAwid=0F4IxP^kNzTWg693FeUC#WU5o7Sh1lkmv5&c zjn=LeS6&et!p88PiF0+g;shYDPx@4D-^zYM&$Jw8JDLpA)?rdw_Z_|I=M}S7-kj(Z zVYZC=uBc#<_b!{Aj5<^0P_N(p*$b-is*pL+OQD?}c=?{dziK_PAJ2Wi&KJ=#xicg* zY&+1265Qu6K~plj0l8&+C@HS>v8@PDy;j?jL)+BdslXIOE`ctnSq$#I&Xu}?5Idx_ z3e0#2oiL_h83jDaID4_kqC`uE4 zR3)Sb%f~Y*oXT*;O;tX+rw^6CE>8&Pvz(Pux=3UV+=~mJnn35T^8@x zShyeT^(G6>u0vCR@yffks!r`w9e>qGXzZ9_$>DLZ{uBftONhGt=w?7wNPt~vQ*PWV zs>s!tB(d5S`?xO-rU^x!wc?kVgy#r^#}H{ z&OtYgLiibmfe*jW8;+tvAo=1GVl7V+tbx(#ix$?84x&7~o<4Y+AEcUFzd)zaF;mPU z^(F>eagJ?9dj~qp)Cc~qjCkFBhErxD>#3)@)D6-z=GK}uJi zS%Hl=AViie46hK&Vb_!)5E%f`L>l@|GXv&2A5UQXRI*46oVL`&OlA)Xhp)AcJ6E92b)4yQz)7Z8;d(PcBh z4ud#4UG^6?kD~VbnRALYXI4i4j^Gh537sIWzf1j{zs+Y$Z2LfxEISTHE?T#D@$oUS zt5Gh{`=W*V~D}kx4T7SVe&V0%V!)CnGgSdksUqqn0dlV5jWSyi_ z(=uKEL^{dPtLI+)5&S^3aoW668!p*a$^&8hHw4q(D zfTDH-HdYQF2XwU6&PLBM?a3p9TOs>sW`8e$jtA1bw&>30Rlpzhtzm9a=J1taGJTYG zLcJjAujsSpR74$1Ac%Etrv9@@RZ_1Ly$Jr5`zyljI%){#E>=m9>xbMOL651RPB$m` z-D`O*Z%e(PkLkjzX8`FY7@8;XIb4e5eJ{ZSD$}1?)MO#0yCnL{M*bi&K^ z;zb8ufQJ~2r|vxy`XpkUm90)4b4a{v=f7$?5<>-}AuwwZYEyPq zAf*@9L+%3TjHOa!ojDZxdebzLb3<8*PZTG%f6@#1N8U=}f%iwd}X|l;D1zm#SlavJ;DOinc)5OR@;wK zqRpPDu=<=akQ)8F8}`+&#PM(l>{7_FtV)RKXT0atV6DVYTNB^3R-Kxd5WMYWz`r3V zQalz=io@gG;Lw_qFoIC9p`+CysvQ+8+G2!Zql_04?~T#XKYX`{=-R^KR9Jh7!qf1%w_2jTGChwN)k=E;ixc~0gsS6&?Q?zi>RGNlf@nowmOl7T~`ZRF{qw5*A&N;zk zb!@EtORT>1N)i6}6|7e2bAI$_qErfSE{ZkpkBmHgP3uRuTHfsr1H!5=pY>Z{pI~yn z#%Wa2;r(_;fX|Ig3cmV!eSdhmx^0OfWX%ka4N6&c6noyYKBr1=Z>Ff&H!J98D5XZ& z9|`;o=fgh^@b&QRj!YD~oavYCha^}YS8lp%U|_bie2hc2yhjwyoYtj|PE7tK?xK(i z1*J=`_uN)HzHS(WnN}RH2kDCwG}0-V(1D92SEJ^KwauU{TKSq2qAd$G2X`VX;mM#X z<|M6HuC!hXspTY7m3Eo5D~qQXXQ*hIEGeTey|EhgMs@tM0U2a>FcsRNFi$4MnC0@Q zV}p1qQznL8=-d3OM;Zkgh*&HdBm7(X%U&--{05gCPETPueA9LkfAFFfE ztOrWWIc?LtQj?ilQ0x7Ev20+&-Y!vIOJ(kOkvc{rFF-3VK!^HRO6s4V7JpVkq%I`N zt)bJ+DGoBzv+R8O>1pMuHUHc1`E+r_yAbhGK0-6&R|4S^1&T}X9&bB2r<}MdP242{8qU%MAN02?Uvz_X8*~~_#RESX0G6zJ-w%HeewvL<(0bj8E=2*Xc&`+{7wkR=$F$EL?->sfX*9ZwCEyiZI7pl5s@1& zh|TZK_Kc7G?$3+G*fFe;U#)wFQ8i~+QwV`d^8KBtR7~7th9;}M%uP?@T*j17|1S9V z0~##;dqBTD@W;pPnHvE}8~Bwn_?ON^KZ-UF$c*$-)ctRB$00o2l!CY@k{-nzw1+)| zu6jJBSidp&71J9NSIwpxqk5KcIFY$*WO2m^Z&mAjvq@dea?2(WGy`espbF_T@K!Wu zh$Jw6+Tot_-A~qvA)^5=j0lfG78q=nz;%8ic(ujf{5TJBokd&Y%$G%5{V-q8U2>DY zJvKnI{s1@rftv%9MXKpWClHCK3;}!Y4aEUcC3`n<+hT zwZ@^0baXoxaZ9b0+k-r-9A?UWe$t!@4^Kld@%-pq97I=#8F@6TXLJb=``a{%3M~bt zW1WoJ59AR~xRytq7$zu&z;hoh0P7)%(90&-Q{_quP=uYNn}&JBsbk;yfVz7)*<~rW zVm7dK=FR!ztBk!Corj(NAQmA>)Bn^jk~rHSGLFQ{L+3vByV&d?Jn_zIMO2nqSMC6A zSNaGR{xb1qq$AbK9V33-&+rtdfn*<`Wi8(1jsxKqqkyOCNm*`}ob_|9ljC3e**@(7 zB)r_KwaNvHVOw*I$WPBLHEfJ%EP5T0UhW)%jel+;6ZguM+osFudh8Qm*9yJUQ*V z{J9;9N5yAx3BT}pax7A~5N_uI{M~M1omRfa%hSY0$1NNz6~Q}?Y*%+kwE=DWg4_vT ztR8FGT@{(Jw5)-{@iwze3;P#qo%OfjO)KgUJyVuutRFkIu_eXn|L`(2u6iAuSg9v- zPb2(dZF(A=n;Bx{<5A{4v0Gx4D3DzC0>Cajl&a%Hr}NBY`vES_Wk8Uwz5SF_HM!PI zZQ&HujZ><2$Y}2))SS%9NR_jm;VqDy(P2kvT&UoHnfB)^j`668401Bi$%d(xVDfG~ zDHPyZ_(1n}Z&5_$5otpzcryj)FMnC+S^{~drmVM~o@%#}>0rYuHNP#sF|L9vutFPR0Cq+L!HlEwl1+B_uDW)Lr|DV;rA!mApFh zr4tpvs6wj=^E1<=hfXsCay=f~JE8aBxoJ*01i$GFex{#*nLA}Nerpy|xZK#UQ95`=BKt6iCdj&cNy zND!=SY;ym^W$#3b`smDevfTmRvrN7G$TeFh?~LQ+QdgT^8l4@Ldi^84m-0%Ov_1c^ zSR6ncI6VdEkaBSw$&8&LzvEc#_-A8&BOI>hH=QuiLhyZW2$5I)nc!cf*(K6Oyc4n9 zF254$(3D->*2`ujRfx5?83ate)vHfPK@A2DQejd&()@yWM~YoG5hfW{6qArL0^Vwv zf5@#F08-(5?`hcFVn;nA0tg7pv6q8IBy(z^Sy%VW*I301N+Z1#s(}}(Up+NAzE-RI^bwhM$#r!;-5v<^9Vcm<x+9hj5l}K8o92N-u24YuwB`?)W{9w(zZ$T5hYs3sbt3<$z><2e4lt zze4*3N>TOsJZ->PX%Z{FcX*R%KLomvf?t>21godQh-w43#x1eJ#{0vy8}AiQaw=pC ziGxnX)mMw=W?@EC_qwRWKoH<1qp>I@q-j-=UT}>>(u*C)$=?rtS8nC{cBHD)%%}@N z&~GBuDS}T8xNO_@?&IZJqrnIB?QZfs-+?rQB2DXyM`iPA@Cq5PFK!FHy`l1C zOL0lK+Y-uib}A5qS;_*v5S_faP;#>6GsEedH8p=hVzA&rv$e(EP%$VgdJWqMJCf2) zT2XB4C$(jiu$S|$HA<3^@WOK|p{fR7CzRUCC|$^jnp-{?bx>;H0P0RA0F>=EtF?$$ z$C7&ja~XoN-ubEu<>}d;w2NObjDgQe3VKc)h)mfP>4_K2?Nkco*2E`*W8!pf`%chd zKjMV?PvW7RDiR8!EnmyWa8`t*2K_HA$CB5^FtMGMDzI^-CYt-cCWK_Oiw>F<0tyBr zJY){`L}9Te8ykwyc+0l_m_RdJ26yB}*i<&Ej(N`XNwS8ohoW?ID*)$?ov15f!}>on z@QndByrbDLCIsF;s$XcK1)N9Mp)Pi|h=cFmw}h;|*vJiT^kS7O2d2~=Y6s28*}tcA zL#Zq(h;opV%~E{6>~7XR$6N<*qOE5~+-{@$t}byO)i|rK^j}k?6a0MzN;yqKEbiVjxQ;nvD3f}YBGLf2%Cc}!yV->#G(+7ui17*W>FSO|F1ay5n zc&**#rICN*xj8*aZg_sVjz%oXId_8;km}2x2_+V-e6*knygFCC!bC7wFgN7~by3l@ zS2r;0XQTY`PP@M?j>Bep6&xN>sjTB?6GK#5ug&2-A%1Ie)A#> z2&T_l?a1r$fT_odeb^#`b}{I3n2TzQ7b1Wz4bSqN0Z;-cn2!xE8OmB7ipuetHy%1Fe|9`xgxx#APL8Wuo<1te*F{GXUb+qXY9PxX}c3 zBUkv#Z(Lc+AP086U_Z+lwXe+^W^km}FGN~X7J4}VwWQQx79T;YXb$KVC&G(RTI_8u zFn>0vsLEtbhJdtE0~(E1nqyR%JoSd-A2qTs#%9NwJ8z+~<%1AVNH`f83LpEaZY&kg z8~5GmN*rW-eal5pOFwzd^>}A0c;BH$ugvvd08WjuQ+{3@#iE6q4(}Hk?HtZslHazJCk-rw{T97>;E15AxIr3j)IS|L=n|FtWA%-+pF5zw@35DOqk=udJkq29YJ-B~hr#PU0Yl{srJ5+U#+Ckt0)F zJSjSJ|9M)gj$ukWMlSPwo`Lu2`xTfE+1<@j<;qxaStF)gD?SpUXa7K-G4n{0t;h!$ z2brD_4K@sM$^lmS=l{m7DpjjtFZ!kmf~`AqCJnOwN0RAwA`Rf;{f>es%>k@*oaw9q z@BX2VyO3kB!0k?pmCa1H;jftyVjvuAc4c+xQsSs?YHca!JFLkLKJD*4^0Nt(-N3Us zu~hR6$t(PShCr~Wo zO1K}d9CH?7c`oSN@o|7(+W`wSO}QG8X}YpPPeZow}dGWIsQ_9iuJ3Ypc! z`{6tWbMhPhDLicylE*QRfDdf3w#&VP{ott1=FN`}`pZ2~i8MNo=T_+5L~Ty zo9RO{$Wwr0mC?M06-4~gy_TsS&NwE)!JUpU!acH?10CDl3d=D=R-c@+lM|0-;CbH^ z#zmEPPSSrI0;~<(`Chp@-cPF`uEy=UY?NQnLl=nJ#kamYH2|4-8cM-(Vq13--3$5G z=&>J1sccMfaH|1+bWTfGPS{mvMW`wE$T(&WO}%ip9)Y8Ak~@ETWu)<6`&r%FBl9c? z)vrRSTOJUx*8xgB8un*iZC{B0S;Aoa^4GzjKtK)<{wpGbftlz3u3+lQ4ttU)zm7Gc zxhtTl;Z~nwvgvrtVXJ}^?2>eI|8;o-Pkm8c?(HYZ-&+nV!edTA!DMKb+`kS-@8<62 z(BOB|PZdkZRgu5GUp9yZI#`d4YNWBWdO2|7+w_yzbm&q5heZ>w0$F4!HaaP9J+;lW zG>p!bHDr469Bvu3&qw;$RV?j70*w14X==q18Dy(n<9AeH#g)5)>|eewOu};JUf~REz(NH(`uIu} z@u@$j-Cm}P`p6@+@+EA`!CE@n;L$%61+ZT|jQUMl6(1#2KHIszeTE;w(L&V{_G|W3L}>6;X|0z;aF4=K0n&0fIHRXV z(~av+w-@wL7wTrZ8h^@wJF>Oqg%yl8&j_AAtO-Acce#PLWFnrqQoAh#5vY1w12kjE z$88B+nH21>W#p*C2ax1lh>6nrOo=R!xTTlFe>UAYncFFEy@(>XOIgTxvXm%qc1Z4m z#3S3KSZ~Ur5)f*=ArRmOLPScPsnDzC2XbBfdXffyOp6~V-K=&dt7dHSrkP|wT-Xyx zUM($bMxmWDm+JpxAF(5wh)g+9nE0QKXW%@df`25oV~L2~4rM7CEShECP@$l@aF@uX zfhBmSsrFwHY$Qa7r4!F+<6zeHaRDPNQCeN{uc;bcO~X+3wJ0fzWUvgK+!? zOva}a$s%NhmOqqCaanpaNio!^PMh!; zmmgD?P41u>^BObz(xPandQpNI+yuo3+M6u@M*cEQ_+$D;oaA+w*mQVE1kWJ{I_XRkvOi3Kt7~m4#TJpGHBZctxe} zOD*_5P(o=BG;dUxXY6g!ZaK6c&AQHDg}sS z#pTcgy8El1sdnw32T%_vJf7%l*9gm?^c(@1IWcF2132hrRufq%bYLzWjg#I4Ek=|~ zH@yR{htIM4hML|fmt{oA2mq%wUcnf90fYoqqfJdg5O(L>C@@B9^D-hp#3hZ%BV6Ee zGc-){Tx1k#QMdhpK!E5BQR!Y>qTy4NH#A1>UDZ-!iLqUIQ!okj=&W9WT7u|i*CaT` z*93W7Y}Nyx9iZ)c3&{53zQ_9)zRmVx+^S42Pf+>YB5Hd>RfTD8fB@5mulzHtAUnjO zLkHo8qsdndakOyzh$hzwrOH-<(Btjo68!_7xS+!^4b~%chK7C1vkpDSWgiZzl2dR2 zUFLOW?<9Np+a0F;td`yJrydi6AYc0~DY`D0g)l86K1ggnF#6I5tCq*ojZgJgL*4A9 zNGTh`=x~bU8+r^(g~<3N`_;3-OBDPa0{pZ1v`E9x_5cAAtW9#el7(!*YZ!BF*N>`6 zG@A&eTjV6ODqn6jW>^&iWUGD&SnSYF(>+SU$Cg>M?bD}|KSO+%*OgOq``yzS1i^hJ zRogw4940<*-TV2pu^id;w%e-wc-d8MFYySnk)uC3;ceCpreW{l)}U?k@_KcJjSr<# zD+}5+!Ds0(D6J{dTI&>yAT%?IPJwaGQbL31zHsys0WJy_)V6tt-f|DI0 z3tuc>-XoXAVPS4ECO@08urh2%mmsn-ER2Gx5cnbTP0jQj0SiXRsyo)T7A|WMH{3DI zE8V9u%`jTW5#$AP9lc+02WC&%Ct8Dx2b|GVLJ)M=@5HJ4lM;c zwM%^23IRV?#ZdlG?h9%*YU6-&Ck#d4DF4adqJ%*F*lTh@94ZzBzc`5>+<{@8B51c; z6tG1&%C*@zes$5~uvdYfKVmfr#Be}~WBg(r!-;uB2DEI!k#+s|ZVe5=MTJqQ!gudc zm2M2t)~Rkv$V2>a8pa6s@)YCV`GH)h@BFYd+CtGMkpq7s(5@7Hse^7Q@WOt8%g*dK zob&k(bs@3#mG_l0NRtrp_W0-04}>%YNF?`JRnD1=EuOwc2W6-U5dGjP$d0AQh7^zN ziQ&FY2NI-}!wyDgpKJ-{k6b*%5{Z#}&Wzz22CW(ZpeFYf$vDaOXr%a0hhdedV1q?) zyd`hbB~-5(Uo>t8|Acc!;40r{5B=yzh2R(jZ@*G7wqM#887Q=5RrJJZZurBd2JOXr za)FyM7=XqpFgS3M8z2L(3XN|r7W$4#YlGn;9f_0TlC)@ogZjI;Iueys~*U%swR=iNoz z(Z7AU6%C8}G@5!4*t?h<#hP{CNg>9AgS});rkl@xHbl4J|;)QzHkG8!H41FP~k{Vo#uiE8)DX{r% z_d~3Mdj|B%Ot&oEMa>t62+HTe)=wTuDXSyGd3^6yURrnNv8+d;75iRqzIXb6UYZ46 ziFHnIEjz`|N*~-TiOW9;WDSa)o$_YL@*wz!_~s{*M2+~#HDO2F zCLVAVzYJvOX(V6&3+IV7^1YrQTm59!QD|yJ{qAIS^M7l5K2iC7UzW1;lR58N$^fLt zAfd(>)=KtUsD#$Fb53><@vAellu`CL=m5rU)$W}5KUJa%R&-tLpGqwKYd|>uiy6xQ zsDuHNiOK)S#9#Fd`wdAHzf}zcU6K?uKu;Gy67J`LtbQ^XAhGeREPzY{%O=w1hD?fP z!QncC(r(fz3&WBq@=c`F-C|~n$E83~X?*25jJ5OcimQ|R(|)|U_V!VvX+pGjS()h} zPsVwqETF=@WMdHB-{c5Z>htRGNpL$?U{&Zt{IbqM z$!lF!rm{QlG^Z9C+erML%6vDShn8Md@|9fotP20qM*Bz@m}2gESao}eIJVV@A|@X$ z1t6|->E-&;0#?14D=veQ7tm}|iC27vgUjaLwc^ur_F$MTx~f$e+CD=!0Xl*+nh^ES z)Qs|DeBZWgVt$)CC_t)%p9-wiD)=DR*(jjQ^$Wlhz0@G@ws4`QJQ^p#Cn3OYFS|b6 zLf6Dym;0Lwa*z`I|8VvW&Xvbqw`b6?la4yJZQFKEY}+vpfawej;Cpp^A%pp)ppt+|N>hO{>pK8Zh7%~2cgZ(L=Up6@o zF9_DrAlQzV!8O@cXn#cnzd!cV@6c;ca+iQ#&pqzYWSfs0rDn;cbar@zeo!k8px1+qC(pSg5IwmP2 zi50K#N>-mw?`%nniG!;VSIa+vDff#3d(s`XVJMi~kfz~)EAJFkiEX`ubZxg&ohX;{DzO`zlIVFK&3{t;8YY8dJuSvgP{T>y5@|r=7|NYRs3gX8?fB zUe*^o;}PN!7httdT0<8T`OGObHYdH4nyLNF%QK`04wPpf`W2j;bv8lob-lson_AG} zbyB%AjG3PMug?#z_WW6WZv;`j-c7-2XS>mlO^@ERFd>qtH#$jJ z?m?`Uk^rlY{@LG{)z&7QlQtZ~D76Lli44W6=5jqD&x&|1Gde1T!3(V-(Bn^xa~cm} zB8@y;+!$CxD+Q|r1lDAwZyMy>VnDo>d_vbn*PU5VaV|hTo3G8S5BWOnW_C zj=p*n7Mx+-Ovu=;;rb=I*0FtUwZbSWcx7}tC+&$9aCTeS~# z>c8gk2WS}MByHpiLSu9lu4*ge?0hF2e=m);Mp)k37w89M0Q)~c2Kt3cNnIE4o=hRn zPxB_N2oMv(AFQck&4Iq?ygC?>uy#5F0Q;gkhV;G>7u(cj0E+)h2hFxW+?V>RzFWs{G*KMvEAn`M(Sx8AjHRsp9`A0hfwaJ{dWT>;_7WiKt`WD#(PCo|$5%sv6f zW-k^svVH%h3>>;bRVJbKlX+7Ku-h&@*El9Dc|#Kw05q*pwrMRjmjBfvmoZN}Fb7a^ z*q%$8hqOtv1ke@G(6kVLt&!)ksQf+jP!iuI@Ryv>fX<4gZpa@qZj*+@P*!CL{Ov$v z>9(wbtn`g7u@tZ@XiW7fb5bAs#9FL1+J5L1Avsi5BvWpY#v)Q~woocl1ZMBuwg`wD zZyK%X1$LLvil`^;l8o3lY>QOdN))t*J2{%y@-ye8`&AOLbgUR&dHmyYV+#KoBh<(5 zLP{INY=``vRBr7Mu(W>z?nAGbUA;hJ@%hxV)JI|*g=~2YFX6U>AiJC!M`)E{*UT5&|LfBq~`!5U?y*W}-Av{u#v8<1eU}PWV4C1}k2d zI0|JnKWhAgF=z)sajQ}PU<`~om=`C`9oY(lQtN78Jj#Ag2-1qALAjJ-oQhi9L8Xwf zaE+#7gc@yP}MUg$41qSp@xC=$p;kg&vI+~*~dD!PW z8er{r<$!HB(h=>i!?v$C0%3*0B-2TieZw${c726mHE{z~$=WIGV$!cuK;Kk=7kzO> zZ?HC~-GnI}5xgIj$94P}#n1zGFtFr(xcU&G=l3u~*R{4bCl4I+2i`Wcrgp6k3*OCL z%i;8rtaKvc=09a3yD4^i@_)+2e*<@-YxN@&|Gz3>Ehpj`PqI#mFGVXs@?@ST?j$IT z2C5(%+q1*=13T#;_b5eRtx9u$IJP%o&QLhU(-n1f<(s?F?f#6Lo&V_Aj>lfFh**o9 z?=CTeXI|GEA=|ifWTn_>qmR0Nrsv?3XL53aOy1=0!y8^6CTp=V8%AG$v&TdBa9QAa zWB7U>7$o=HY0I+28Wu0bq~Te&zbPJbd1QYlTiK)EVngYswtL^^>)4Cd;B$%&1c4AC z=KANJKb)i6O@uLeqm$Ou-O$Jv1SKK^hr#6Hc#*UE13a+@=WAOgrSIV9>BTtUewg(Z zgTdVBw)f=H`NxGs%)M}w1X+FskN+|p47`2%Nk<#$R9^pZrEeQr=HAtac|9<|INzOi zd794K34=!mD+};~(<`&5zGfHnV95WY6HWi66A3t+ z+)e+b6E6ux1)OFB@Yr*~je-95`M7;I#ilmdN~Q{KjWjQ)``B!oqc|+so>W0fVAwXQ ziV4+d$N!%?fvKS)LYr9JICx&jj<^o!}w9cx94m9^vcKkZXEBVZYYUT=F)G7Am8H(i9d!1V8F!VAf z!Mjd%>spj?n6wxF5(R`~sgc3wvEn2$^CI{a%GOEA)M>t|_aKOl&N#Jy{-%y|ATw|3Z1s9sdrpchMh`*9zdloc=Y1}OTOC_5AOC|o~DR(i{Q}XRi z+vXys7Kcq2EUS#M;CYHETTIMWigiW>*{FidpiW?^NCDvCo){gkLlP00(0;mlNd|z? zB66lacvR3WaT?ye`$7{4%!C4>*yiY_ha&$U*2&O_%Ma@$UQ0e*SL)dJUX0Jo-6Drv zx0$od*SU|s=W1fCeQ1&X#BhrOgp&SN9jU zzL6^(HZuB~QeYZ)5CWhUu2wr5^xA!eVfI4wa_iO)&Tu5ob?AWye66nwlXT_Q6Qlx; zE-nkFZpG|R2EpUVlM6$pzi?vr%W7i`p14C0s+}e|MwQ=|F=w-{jaCq6qcp! zhWNFo&rl{zp~H$Z?kZi13n+PWJmkqLuatQ+J2tEcE?N6}Jk^*)RM)mGUp!O1=<y6{QbcL zCW=2_AGIWUg8}Y@X;_o&n$-muiGOioG2FRc`cU!ykbX60RSC2zqZ!5iZAhUWm9XG|*?fxss7s(;N2(M9N{yw- zN)63!2xA;r2mnULEafC0hielnh-{}i(2_=qP@ zsJEE|oLErdM?QgnEUgZ)X$Q_2fL_mmAB(U?1buwR#2NEQjaJnf;RANS?bM3MGmhSk zDxwIAZKIok)*zbloW;w4;e{tBsyo>|XNs;1Y+k!<_UUY(qrGwI!F-B^5^*-b%OCnY z*xA}7hVsL_b%FtJfhfO{ae_;imV;lct{wZ8lfOF@g6C-00@$Jg497 z3n9WvgPp`$0GIS!%qxo^T04#3!bsR=`CO!%^f&h{qM(!U3|r8SCT+A_Q_op7xpB#r zTYYt5#07v0{d+H7!a6;Un!5>rrKe-+#t_N?ti0>Rs-eF{UWW|-a+Y5*Mh6!!*M)`6 zjBdQjKq)XS&{%81#Xt(ec8ZN-Vf7&Og6P1=P2_!BkF%mVsA=Jc5MN%geWaRI*s#V? zFWkNwY!z7RBVN7=HqLmivaYR|E0r^8i5x?3F#Y*4dPZ@3HZ*}jXBW+~3!v!q*z&zE z5tqb>mpp162zKuB+kv)3Lchin~a*?C1Dd zHL52%xm?Yh)7-}%ztB;RQXY2^k}0-ACs#U>mv3%CY}hNRbglcWU)DY8W9Psu7vm{Ub-$SiTdpJ-gYn$2Ka^dJySQP z2uTJx(SQ0VfZtp`mmK!UPxxPbwkv?2_dBX|vh;Nj!fyeJXrcS`2Sgv1SSXTsZt-gJ z@cd^NlR$o{I(VY=4*0ll1EJ-^1||-1i-b?3SmS-?Q_Cys-h>AA2kTS2E_Ew^Qm<@5 zr?5B#pZA6RI$YjJ(3u#H86hFl0;#}KNFvyO{4b^f&VL#HmF!}z99!lT+S(EYeE8b2 zUF*^M!kTQHa_P&b(v=(K%`ZAqg+&PgxBlZA2PVGxy^P>A6#p-G<^-PIl63`?n4fnq z4!RLzPIq^T6}{30j)f?^{jY z8g}=aUh`fb(biq|nCaPM$P_xmr?y+y4$Q6%GE@DH$H^<=1L;=+nGU{c+y%JTD)w`xII5W7ZzUk&7&W`$0HvVW z0Y!|fbZhI@@$3162&=pieV|~ePKC+nYv%Nn%YfftahCQstvig1&tFXgPX+~5f~B%~ zU#fyZycq&@cmTx7{I(G$QwTLY3W5F|@}6Fn=422WG~ec#gnX~gT|Gf+qqj8j4f=cm z5ol)upfwa_mxm~FgCZRaggm2P^2CSJ0fwPqyx>EJW^-SUKC z%hfQHQ+@7i64{Idl@FC@q;2z`BKg6eAM2n>k-^m#sAC;9u+ z$m%lLr-FL^d)EacIjyx5|41e3^ZUV6O1&TwrE}OfxEO#fE{4Q!{Un_JzRN0nR$ma} z)Q{4aKtUIG?WU#=h7+w*-++?;Ti_26#P5eorW#!$DE1+cL9}O)n7ad0GP5A!-udNb zx2l>nUIUI+Sig6?TpxGC*8MkOA);tUzK97Mj_>^T?#aZ-GQ4028bGYtf1Xc;Oht3J z`2p-6HUVM?CKjV#DY&;$QpKm*#CvvAJVNHQbATy*6bj`C#z zm!$_&fW_>nsLyd~Pe;rN#LX`C@f2!tP8X1BHrIqB*z+%UR>&Dg#{z=rQ@b>o0S@mN)N5^}(mioT?k^pY-SV^H#W zC82WS1XwG#vvOYqZ_Wk+myp+-&0E1b8Oc7GR<*OG#pgEDsq7#nc|d5ImAX45sLGZM%wD*~Gvta}4 z1m#@fB;}d;9<`}z@F_lX+YW#40dqKqt%EG(B}hI5V@fxr#pu;>)G|eZjrR6xc`t{% zm@?H}_#-u;{cvd9$2r8$vHBp6eq**OL3~MJfx$y8y1lWT2_kOnPQhH7k331(BsL9v zKKUyro!SD*2s0u9L>j!$d!>=OG)0*}Lh-x0XsL?=uY)lC++1&iiFYpowXv|YyA|X9 zR%%la@c!5U#=vY=O_jkr6MM#Qp=0~ha%0r0~^hd#z zM62?5mXFuCH|%KF&ro*zUInZgkXt{}(mO1ZLeS*zpUT}VAGde>=Gc;bit_LUi2K;o znb!%oox34Hjfy>{zU18^>_S;`CN9^{A#96+HsQ+w6s#epgO|Fwh7ulc`dP%)HJ1qU zj;*eT-O>XgUg>H-^Pagf+lckhbW1S*pNq5MmmNp6qm!d*yP&M=A9y!ZiR4Bbj4be5 zVj>CsvFPUkN5?kavFG2mIQR}XXgFb#s-SGa2$pvj=E1nZ`-Q?Nl_Xvw8U3ll?_q&1 zS&RYuNj@qqlA$PUA>l5XuvG-(FtTOXr~<#x{$%zqzmIKaF~76Tm}Ooz2#b%RZ4TLd)(4jr+h~tPZ*F))K4t zdW9cfl$O4JU~ivB>k^^f++((fiX*1fX@EGP)W6a0iP+zdl#bSXAcb5@_anaZu?l4* zL$Sze6R3`TBw9a-SFY21U8cn%Rxhe5 zk7uzotRHOS+oIA&V)FXbSazbieXv3yney)Z2f6R790^NN6rl3q!PvfV{<}a^Nl~s$ zOe*O&9F7*Nl=tkq)mf`PkYwog0B9oFjI6jdX_u~CbWB?Fvyg1oAKGUOh`sqdo06nJ znpg&eja5uLL+`V2+P)aq9v94xCx1qr5825wl3?4~8bnWxYmR4Jd4w>lBg6+PZA6?) za{i!1;l_W)-WW46n=|0!*->}bpQ)@Rn9z1v$9v`)`XTW$03=6 z=yF~`Z^4CIftC6PF`#SzNH^b&K0@xvs;ne^ zReJ&pTzfAb!BZ-llOTkV%a)yAU>_%ZN`AQ_0x-{&8;AvWzX_q?d$kozKNcJg*eZab zD-_6q$6@oDKyq3*D^d9%s>Veu5??eHR9$Yg^9!w#W+@G>d<7|@p#jfILGK`HCq#DiVnXp+A83VRQ8%`@M(0YFmzj1XwbMsmPnM) zx;RQ^G_qECPYP}g)t%A~(;7C;#g@ptHJPN@%_*pRV3Vr}aj)PGu1mbQeNhTQ!mD{Y zV%&BauVxI?0*B&UkadKox7HDR-#sTBJgNL5s|rEKlj#M_`^>dpTo; zniYx24wf@0rIhZS%;k)(x$L(^=)MZKk*_S_7ggJ+p91rek75#LDto!{l;twViq-O< zk|U^2=Re1SCe@b#9SMc2U`xUd$!~+Xr9Mxo>?c*1d2}0LMY)Z@j4M2W2-973s>HF} zrc4iO7ZoW*(5j>BA+jZH%dH#pZA2n8mK2wI*My+p1+=9QG}5)x%-x}kc*LfGQT(y) zXA+)mzwp|AECvhwxoSl|%O%@-Pt^P4Zdxpgq`Gy_6Yo%&9dSF4_%FdTbLpkFWvGFk ze>n47c*MsaA1{2mg*bQ1eq%l=dh?$s0}i`mbV%nvvLOPpHc&%>a}7b(AIGMWyW%}mf5bB6MC^SHQ8 zrPS#H%tE2}FQprq1#!RNwH#8;6EuZ1U5xiv2BoiXP`v%ZWp&vW%sH3zSy$j6NNls1 z>+}RWYLHNPjn})HFm+j0EMe0+;}$N>D9ny@B%N|2aO>sYCGF1=_Nu;I<@XDx^~SPp zH_l@%tE4n=9cyJ!xh!#t_NLj*Q&lPd)O^qMKDgh_epbtyw1 z$@I@Ww=K)=#MH%0 zw$4s=&i@lO{r^Z>HK}Xb?u(=S#CS7haQ)!zJ&w%>Dd*Ys!boTV8&2)0ghrPj+}2jh z#wYdbcs)C1jC%OeFJ_H#g4iojqnBZ)H338U+ES^1KAb^j7CP05pcdxkIukgiCVcQu1pISfeHRZZ{Z#IAWbuYv4<%Xvn z51~EzAfDrV|7z6nvLl?$MN7PmUi((3l*sWhsu$R9?#)`6_ew(Khz?uhpTdo}mXrc64Q5r=Pyz`BY|R(qO|c@`ceicrK? z*k5kl8LiFt**y2uBWc`j&u)vtwRn3tyUcx?DmJ(=t9nUH%d2n00c+@#@H8HsEw|hH zGn6rDm(b|h7j7zyWHTDAsx=o+>Wc}}7%M^hjaG#1CzSEs3ALGW_yLc8E-zfuj` zD)CCCy~--&ZDz*gb1J7RH96} z{MSk}%hf7tRxC!px((q?5sF=777VpTbq_P4mNOv#W?p&UKByGsYGJiJ zDx+>Fa-zmfdZXpM`KJaOB-GgOtx%1ePD2gqbMO6gtop^v7>WkUw^UX|f8WyCO+tGm zUQ`Dxe-Ohg`3Dd4s61{bs$LYua!N-5Wm|-MOo~k6k(FPICUU`OEq2N!3Nm~S@HU2= zFfsD{fT7RWHJ*`&r}sq~K!zH&#GJz2MoRQ?(HEYl7~wWR&WMPaddIN&W6d>~_fPkl zHoUuhRR2207tjeJVrRJyj=3`>)u$Vhp8T`UrkR_rXakcxFzTs+R51i{=`2A-B0vKT zLn1V#kR+n9ie?M=ZqZ{gVz4!GK1hIH|I=jVHNSeNY493r{Qj%|_HU}(7Z~mk5JI;w zApN#nkZ;P%lf}C@OZHab81!21HlWdT9Tb-(`JxT)l*+JF7dyx__Pk3a8w%Vi|tzz0+D_-Xfds?S= zxS>!-og#md9nY3@$qd{<`C4i-(%rW#)@vqf#saHYb)o`PF8nGa>6`r{p1v_49q!-d zhXlcu_~R&&bQo$9g}psMr0;L7(|&V(Z?2$2zooHZF8bJaUes^fVa#0(+(=OI^EU-8 zBSDf40@*B1Aup2~6O8=WBK8y=OA(Q;WGmgp@>qDP4~&_cg%zsd`;U{B2_|y(BGJz7 z7Lg3XM8B-Ui>@j=B-hHY!OhDh9a z@y@pknMf?H#@zQj6|*zgjn;<-ldK2Jk!{5lI+9kjesS(KKmVRs2%()(UL*vYrcSy(gO};N%0W zY#QiD8V=Dwf5Jh6HA}p5cU-;I{gyeyThu84^`3hH})aqj||K@yJ0>0E|3xzA#-_ zjwrUMw0uoY+|xaE3HhpzodiyrBMx>CqKyFxwpu<_VY_0c!;lZaLUvyS&0V10yqC1!MiNoFFL%;N7Lga2qZCo1Sl_()9hA<&%%L!`LfiS;tEm0N9ho)}( z4=(!TpCO6ylTx)$)uHN3wc*sJMxr?^Rz4WzK`we+Wpa4$}O4xXX+C0)BF-g{uvn)>lKHE;h~IhRmU#HhuQULRx7RJr%)JO5*n9R0WDe5PU+u1 zD%POjumnu5WLHtl!0iv1DzO6c#I zQXlycFAq-m?GaOyzRTNB8)#LN9@X{e{i=xnc^2@H8TK+MxS^q+$1CTav86JM<2exm zqlL1MldB+(6OLj0zSR2@5{A@(c+4)~L5xS3W?GZTZEWK2W&(VKT78gcM`5h2b(oA; z1kt#Ol}g+CT;*EB0lxcEXSkEbQvk6Ak;%;8GJ+7jhUZ3K8_F|aFVNt@Zs8uimh}Sx zk55OL8X6*VkZr*2eRaIVsD^01pX$2`FVrv|n#ADWPD{-nZ>qql}jftgOU zAS5xPT6DIRq_@*QYWE2Iwb*_<`-odOrn%5Cx>1^&ksLaPbjlG!v$0u{8_B z@yjS8;gX%RoP)LIp<^6Z$Q5_2#lDcJQ1FMp{{j3Q6<{F@9(`@0s~jU;n6b#v(zlQC zU8uoUy1vx2c*Z#!VQg9*y_=Ucp+ zZu~C({wOf!Q$c`Z2;!>I79l2ayF#|v=KdUs1v4=k5#vcYB7{=N2!maz*|6b2dlB%H3-60aE6>{{Vlyj@1_lFq*KuurgKmdqTtc^w8eF zo$hdFc|pRNPzas&P&Yl6W0VNZ(0hrmg^o^O>>zOpASskrIpFha#^08}^s(obiNRwVsK+hxX* z*j=Q(gS5vD;JX{D{C8&Si7Ww6@M@{<<-u|NeTE?=>fY)Q#43ZgBIR#XCi*nAbmRRk zO3iY6I$zIZXeYkE>4nHuC^#)bRea8Ha_;(P)JUs@nYV7)nc{y=@%sa~m+HEyj6kI* zkt?;z>1oJ|`j#Co>)k>9JdMp^K$w@=jiBYWFmOmLcVY&vNnA1NH@M+T6J90csx7$N z-swC8?vBz(=U~WU?3?Wj5SEmnYLE1ZNE2lnoM#F~hj~hWdn%_Hjtn&$`fKJkuq>+P zb-73e0P(3iC!$`&9y2UmEE9;4GHghcy2cx0O~)TJl?NOZ#Gjj)IltY@(pnJ@DDWd3 zPWBl=-pUWSJdTiWS~^IX;XKc8j`;nf_805zd}l~S*|c+8M{9DJ(yw~Js>fT=5)-6( zk6G*EnN&hU>wLYr?I;HuqSPO$jv?WvRXViU$>B+H#;Wb=5sv(%cFQ-3z_o`WtYsNa zr{Xy+XLGZiCJh9fGmT3X!|0BHL7WJ-&9F~;%zLa z0_#%WLSc6RkFI3zhEGnbbt@~AlY#mW>gz1y#njt{qBZt3Ju2uNCyq5PI0W`qCzWnTfMvwC5vC(E)%%~-hl7JA{r2bVv8u9= zGRMt1l>AsiH9%b<;&x-xf-GN1TwR~4s0q&QWDAHjdYsYJRYZ{C3_MCz<$SmU6U^6Ue7M86QURF<-f`#G7robhUhP zhUab=&2DXGU1V{kH2Tt&rp8lQLDTr~s3k&e)Z7p_TXYtK$he96y8LF9{)kC)+4|ZN zI?ySzNO3o+WzETZ2AJPm7$Y1mih0cWTJ%~T)NauEa-)r0uunQ&4ZQiLUTM^S+sl1> z+_}*kjXH=Y7{e%Ri)F`9qeVo!J>!D@|#lx`DOP0#( zlypt0j|S&CUZfo!0WfIlbT^vM7G@-G^eUQOf&gpEc}-r7@xiU4Kdl6vtM_;<7o3nl zXjeuId&pBAKqFF-n1Cn4&Qm2#vx1fr%JrAwIWCPnn{>e924!wNBln8F4^ei!!;EGTPNqtgtA0=Y7^FQY$Q!F_>nr`qH`YKmz~Vg#ydY{&t+hWSHKKh#Kvnwu|$PO2E#o`VKR*1YhP zH)Y|ds#G}(Mp>m>&N#oxGx%rZiQJirTd5*o&AbZchIzNp+XaO3Tfm}*w;cXKQ)5s)gx=TBU}(AM)QHD| zQ>C&nCoYp=ZYVqK+#U|-b(*MFxe7WMP&~WbKYs=FvTmZ=(anBCk*Epw3xoG>UCNCm zkHCOa5SqZZXNq&4Br*fWu_$8E4WZ6eIVJw%A?&|<$HTl!6>&g?JL@o{IXoF=92*qa zyXCIV?!ugr3&^1qV-Z49*Qoy^4x=#KfjA#VTo=NHOtwg6k_~2|W1cpXS&Wo@t4SMz zO^Bw1CkqvUA|X|DMtN$g-x}~@{I#Zjm18RCWO$BWQ#2QItq>-R9g&we4>W?naKibI z5sm=n&GM?Ve+Dxn(^Z;Y$Os+&yt@wWUv})OUupLKLNBoIa~{J#`_8o-kxYIny7jR$ zoTLL07V%a=ibOEry*#jgIOW)I-s^%;+eft;z%VoJSI^HT$SXrH6NZsYPhT`1k9hTF zb*q2mi(&(U`_)AZl}s8!n#u}kS@Tfot7Rg){K*RDv8cG+m9mNlSnEmT2UwIX3Bzgg zmjOqID+igtE~QINUyLQQWVtPbW}lIY7L<2#iOWl2j^WNGL(%hNe-L$av~yl>OT_IE zAVdiNwxv3^v0#J{%nR`J#j>YE#VELV`4J2-7J3kd3+?tV!UqB$;r4Rr_f#0s$C|K! zS4{Ib84L??X9VSOgikI*r`{8_iqQ({7yKDIF;gBVA^;r;&kHT_{aHV1ASC*_ts1wd zICb(rB6P5ZMSm@n_6^8VbB22Nzv`2NIIpstcR~fVcAf3=>F{yW-{H8I!FeXGG?sEG zFC&W}35s$OM_VlaEb6Lg>FS$lz=Pk)-Kg{q9}CbIZblwO3_v`HG^n`KNMA!Mnbg2S zoK+;4w38yC-D%lzoOSfeN$oe3egKVi%_{1@PvU|fIl_h%CUp>Rki1^CIN@wFSSAe@ z@2$Eqa=HX(hsy~&y0s-(J1XuDVcNj-bWupign1<&Yj2>Gq!&)+!>=ZUnjxln32Ni$ zm{mEt>Trt_)_(z=KBnfAE~4LYT0$+~EX3w*&~lEDR^9;?CZf`kO4pf_?n=k1 z+TDZOGi=Q37OeKo&xe+Dw62h}tj7X}nO+2vHlTV8oHNcUaY7xt(ZYf(sk6$`H^Gl8 zD(CG)`IwFg=<%gNmIn*q@eLHs-994z<(uKZ9y>2aKUuIOs%4%1HC)lCs;N|Cdbzxi znlw&dqd7o>YXkV=7aUi^(xukdHyN>=DOKZ9DkS+iB21L*fEf%NG@a1|#bE-4(t@R+^%ay@^&@;`AU+?JgxA|^%!7@L>9+8HOuWCD?B{V#Ao1xvf@~To4X#Z}Qe(YYseEzMqm?Qjj{` z?+PbAsN~>*7$*er=Ied756LD`10=AR8dE%HpB>xMqq#}g9=y!|jXq*ar?+86rf}Np z8542n^X&Uv5zW|wwOV4cQo26^_bD&1Y^hoAma1>2M$Gb!?Xj;Og2YiwI1prWXsSX{ z!tGocH&RP+OzL8M&YsIF7>LGiR-pIJ?U&9>rPLbW|65J$ZAG2>j33OAkmom9t8dd0 zTPOuiI<~=S@Q8R8Vg{CmG2y8vSW_jn2~`YKM-yq@wKQ3{fo*A#csEwI@h+^d$IJqs z3jHhiI=`~II&P7dK?S5Gd|8|$U$u$K>K{vWTBT%JqPidP_-&E4`Q8V(aQ6uy$M*NB)|wIW@dM7JzIXv(ZkNm|DkjGSXF_Kf zkm!$2xcBY3#+49X8@-igEg6NPUw`@d%IbJ?9Tobwdaoo$ibU z0WljxxO?==ATI1xXY!1L#@&E6fjPM)L)ii>FMWU%2_Kc%17+qHUt1DoB%XfWfy%r; zL>jHY$fugE;(YzQV_R%PtdkS|5BOE2Gv1u?xHkH!EAt@K3A6ZBDmR;a9zk)dPr9Ow zI4>wjJwZH%$?S2V8d#d2&cTR@2fcQkn1VAYBrMe_wBc0$= zM4AeBI5dq+kvy&N){Y;;gnEbsB4B%(4YImd5E`2O8y#&v(Vb(ZVM?-;c{0Jp?`^gf zd4N({gnEE{4LlnqB%(0)QfRELE|ywmT%{HHSB3JAVbU?o5o>P1tt6Tijl%p7vL)ag zB5M|Z5jzK(5;drPz6=NjhkAg+V30Bhj5ZcGS}Y&^3=~yP6%boF6nPGPM2xB>janpa zO(Jm&91f8ZjnM6hyZOk2b^FkC((M}Zj5y7^n-2&2@*a4ir3G$x79G-jBIL_GSaQ(o zI8Ew*@m5&8_M*@_X8G?9qW0VQYONcg8e)3sX;i@5toI@YbmW<9Hxi;?Y!*}33COv3 z6;6C?w9Nrz6SEbE^xrGQXQ0&QI-jGc?5)2{HdkNjWL5{RD~;AmS1+cts5e42 z*>=;#2LBfvjxYT=m)dh}1ja1w>dlos(3i0)xbj;lGABnd8-s zyo0qszs+@@KYEBrhowS)KP^3XcTFQBqGX@C5VEAJY`+=$yjvj$zEr+Jyc>P6air(< z_Se*caD?{drayb3Nd4i^tGNzqKbl{*F;~B!BDHcr+3u{tnJyu`Sz|Ql?OH+ka%8+h zg-#vo$gcKq1g|KcMt)h=>Uk z0rUZv)&0~tS{px|wCONmCK)m7#vnty>|@xwZ=401b*x{8E7hV$Z%@aBi93M^5X5H& z+Mh|Bi`Y>lJfs$H8lI2w)R{O0KM|c8=SYXGVbZ*+k&(37yE^4jJIcuD7|>ytKr4Hk z;l1<0)+pvCXugRhlcuL28MJP7@c})%`0JvuGJYw6}f^>WD5i*3sosOq*h zL>yc;Kw52qJ0)uBsn@rooG=IQW159RO&Vmk2YAAqE@G=#D#kp@&qbgO#u%F5=-yUB z4vP#+AQGH>yv2b+TU~yIBg@U>+4cCT^t54RLSs-mMkB*G@m=FyC8yMd@nej9SHE!~ z;`D&iT(HX2tB7EEI%V)y0^|yI8|`b3u)oTR&MV$xn_()FzgqgtvF6c+VCPp#8dof` zcF~ukRb1!YESROQ2J9L%c=}ghJ<3$Pprk4^^nHRPz=563?I$poiL1dSVCw(A9LXxzh-&q;q$wI z(aEP_!70ETtHE#zFc@HQrVWu!SpaMaKX)nw6|`WgD7dfPIC}#J`fJ3O)Ik?iD?Et` zPA~1r(e_9sY2*qs)B$2u%kchm%Z;F(#yZ>Gn{-QFiy6l{W3eO(zi0HhV=TxK6lil@ z8s0H#iJP`DxVTtPAYW+NQtAP@=BXz7^400#ATuc`OCk%c2Dm&LLRo<|g3aHxwc)d} zY=K_)mn_UFHOoND&%raBt{+$3NxRl^MWnIkI==a;gA!h4C)}3`Fl39NMaj9e>UjeW zIN|w^5zmZTc7xtyPw7iq87k5Z<3i^aL<3g8n@B^VGzn0eC@Gg8HA8O<{UXXXfz z+?eMH3XlsgjR?-tZCbMp*)?qz$sF|u-^y|4xU)s5@7}{(9MNi2v9|ZlYEPS7BNi{H z&eBy`vOEU0S4KZBHfV>QYUozy&_#E{T~=n!>o?80ltP5$mmwv&y>y97LMuVI*w01g zIHTY`(9Asf1UD)Mt{65mgC=pO4V|CGFPL+N>J!AyRKR;L2e5OaQk?EsV8e-3<#JUC zXN2Rz@)7U36?Ft1-RT;dG2?S47H(?~?ITB$t{@D;a{(>{mpVlS4Q>&OcnpSo`9t#P zh^CkVa*`?>G|KXZ^RKhg$LIGhvE7wrR?3a=v%<%#QU0<7QJspJ!&C#$VLF~dFz~t} zbnWN6O1Yqtzh1P1dlUtk-L9m5o{UMTjR4uCL| zmYJ?RWN{&I=?nBTcB8A%PLy!A#`AK0Zf$LNT5|!?9v6-Sj{YI~!mz5Z_8JaZx z#cZihuh6oq-2D+D#Auv4$=iZOqmW6IG&p&C5ZZEz2=9z9p3GNVlw^^tTO^ldk#fXu zmwW|o$ZzQ?EEa24OOHEMZlb+FcxL;1fG?&~p3Nm~=T~t>x1sLr@HVgThAuFpJOO|3D5KrU;>flH0Y*$c7Fe2x>HBWq;UI5~mD zX0ILGnJD%@J6-wI=a%0{k^58@DsXZAvyJsypvOcA?}Nq7vs-}TCkm#H%ycBH2~;V5 z3a%6d@=x4}rY6KI*n0!(XG()XTN|?cW~NnUr5YHQ%W)=&NwLv}+WpeUN*ky}pc=L4 zj3U^Mh-vSn^0KKHTNStY3sfj2$_YpeC6Y#^R!<+^`~yKx?<8z~+$&O)_3km<8agt0PM12};+ZyIllC=J-! z5GQ){>^3zZm@E)1p>*V=yFKN?fSkYw$rmU?Q3EZ8>R?@t%u5Rox`%oqCef0`EUwt1j35D0jHPvh$lndGx%30vc>(@TXjR9askKk^ zKYXbL-suk88*tsEhUkCZXge1He#d!kMTXK_oKHO z2zCs~**KvsJcQX`g-=69ta{20BrZs-5eXUKb!6Z9MF;cKkk{PIjNPCMMjo0u*W&4d z&cNC;0|z#a2~s82^NVDEk2}hZISj+eyVu$bUfpgS7cIx{A~d8;U@VHsnyX>@&I~kM z2(pV0KWIyStUC;}KM&u2*V16BHjeOdN%X2^f8zzhF_~)$zGj^HPQO6Ee;IV}$?ue< zYF$_??2==?1OqSJ2ushhYp=d$vUAE21M=1AG$OPry#J68($10H1O$(ZevQKHG!s(I zlq;JCS$hw+ZZkFOLwCZEH^?iUH-z`Z;72zU4M}<0TpTxbgJxL4Lc6J+;Zqu992Wi@ zc7FidWQ)*CrGQe{N<~rm^Si)b5#@J%$)>@3JK?@+Kw$B6x3UE5=uw9{cSQ^7Q*^e{ zIqUiHU z)fyBfjWC()St+he`Wf|1;f~O9RQYP!UGUApDHOsG=l-c{@%9yQBbH`eM5`J2p1IU( zI=b!KAE(|87Ih~|XE^xi#*(@y<7%ECHUl@!*-&|nk2w)cr_Wv|C;Fq!orAQISX9<9 zz!*Pre}Dnc)Ed5=-4!4wP!e@NOkx|k9BjcVJ{FivqVgp|rzo>gFEe+80cPfpJQ4ik z1tYzss*p7Vs_HL_zU;+0upeqDV-#>~F<*flTPBb7Cq+1SCwuP*g}bZEU1=W_3vrDy zbPema3$+seh|H048zc3Lz)(sdX;UV@ITpvzz>rSsMm_V9RSsZEm$NE!i};~N*=l(X zn=)a9wKYj}}=N9}<+Gx;xmNP|qgCof*) z)tHu&=tY1>Ky)pz-lDp@Yu@`){R+*U$kN^IVBF>6Yp6i*Z`t%yJs9{PCEs@!sxMQ; z=%>iOs?0<kLD0w7UTG56?h-jVHnap?olPhhVlK2;>JBgv^HDbR})JJ?AX zpDozm*LWe%F2WyG&MtU9&pvGZFF96@mp;%5Y@U2wD<6N#Rz?s6=SN`DS^Xjs!yH)>h^OTKRm~)R zvUrA@MKkUbhasUwny61Y7rCU2+S0F9`&=w1H8*FOHeofF8C}Al!!x_lB+oOwax&4S zJ>!IAS{LSsS!n9q7VQ|U6pUy64f0>PC-n>kNuM8!G~)kDi?n|`WObdL%&i=0|Ea#a zSXIV$lO3V^LJej?D6#s&I#L8){ZHPQlVD#;R{{=ODStdhY8f?F0Sei7k1hG%U$QQm zdYGWa+DDQ3i@6gez1XMkE25nv||p=J`;=f^f|n zO94Zo(U9L{=>LnG`aKN7?;R36zL{K+VWnBcrvM(9oS~{-Xpx=lQrkv_f@c3k@9%Ap zzi>@0q_!@}P#V|+c=nm0q|3Hqtm3R!(h~MA{SuK028p4l;@=wa4$Q4uqOb%RI77vc z5G@A(8z3riAS2Xd5O>iPdA)g}J>5>)F>!fIRAp6u#pThSy*mYxWS(97wVr@`_TW@B zW+;r-ww|0k%%ruxt3&pTGb2hkD-J*AmQ~u&okOmW9dIH%ckeP>^L|hhY1gD)94W#e zVR2m;2=28WzeJH3I6e)%jIzr-nFf;$Kq5XSq%O@Y{qFyG^~ z5D~1uO5aeBIbVvHNn~lG1`|VsVvN1gis>^-0%{7(4iRKTJ@NkHUnLSr?DNOrdX&HT zp0w@!_?fKw9*(%`F{bbT8Jgf=UUv&>oPpQ`48; z%*63}2mfguJyWa(hv1+#oDQk#+O&o_1n$*^$ax`-HVvQC$UmsdP=hxI5;# zCh-(0_z`ma4irwdO^jh)Jxsd2b!X+Vro3D z%PyAiw08pTuxO~-BFkIfut$z_)c#Caf zKh4MDocabUaDJ=<=#l+;0pILVFuO5EvUE%^h9d?8H~HG{5;66&r-q#CtrHlZ&+}63 zz}%X;=F7jFgO1aNjn4eWKG8vop~J1aOZTabDi8*r%+_kN#=XL0iRJnR+w+ZtPGD9w zmQDTBr0c36R4$xCF=iOI)R!#Qg)YK*-g$%-WY`qx#bp_8!&2 zb>#u={+9}XVU7QgBhrY+TvBp_b z|4og^iD&i$VYjzvb!lu_vR$N;bB(<}7=HLzbnCBTKQgWIJ=$>~ZCIw1RYZe09-cHt z13l|tat3|roYJvtaS9|4{&piu!*3*)RVQsT0#mq6AdANixv&8ik;-4BhVUlsBK}=$ zg+_MC7;{2s%8FiI)M%JugeWB-1O-3LiVCgRKZqImixsBea-YTAyIJ^b>^5Q;GVJd5 zgw{~^Aj;il$S>5BqEi=SM-WoBxI`LcKC7DuYz6aY{KVfuD*6y@zhmPpJG9ybf|w!8 zf>{bKXuKLfI0!x(w;=<14t;%knJwbIfc8Fe<4$SnJ+|C!|5|>8NKhIr`uGm>Jwp3d$a_(A^efSt-xkFLoD1R8juGTTm~tXFx{zqQVhiKjCfxx0 zv}%NO!hgE%88k`mxb0I}kUsd^7UQ@oo#O3Q!3lx?f_Rh6B^}5hNX%~rK#|b`<#M@q za2j-HjpXyoS-8}{6KJDwOrszItKw@xQYMW?+FA5?_JetWITP(k>)9iHL#CfX`3*=0k6}U!Mc((kHa4XnBHX;6EytZv)aX<3MOnm=y*-!Hg?s0%#)d=Y|-T z3-?9}b@)jMI!cLi>2f z9}r%>8ID<*O13Y-tS~GgwhYtjtVWaG@ZjXzZxg^{Fd)o7{x?-xH)s$VEmL!>`eFC{ zF^HzoV8e^*UX+uM-rLDwxyo?5O zoZS~YnMtd@|1w?J8jD-2;>>_tg8Ol7Ds(%;%vXo%tw&uyRUKKZa^ zUEH1WiSD{o?Iib;KCitVmarMga3U^Urd^T!!Vubk^ApSfS%jJFgmhte4#?h38}w)T zJBN)8Y-*MxH;0BUKzqMEq-O2}&JuZg_ao9+;3fol5(2r!F|xBcrKA-p1otzs0}lm@ zl}q!?(ArMX%9ER|t5nn(VUs}Q69PJz9pvxPG16Qc;?|avKBNqU?H9%FAf2Er-L&c z&<+gQ4df?*gK!=s;53QMZ1PFYD}B@6PI_WXhD8@LM)A?xFG_MKE8^zD>KKUNF970rxxVL)|JErAuza{( z0?BOtNf^!C|NUs%IF}6#kS2V|8@vr{i{1B?t(FeJy)l?kAEwre#O#)a~Bb09&o$PS=lUAXoPYK!=;#^KUXpPwMTXWy~Iyz#WX} zBJ{(uo- zTrz$_bPhLLKxRX8zd^XB^v)?O`rbm)$qKJRtBU;)+8xi2orHg$>J!vC+yV@MZFR$+ z?&E-3$ep_aWt|p4Rp5no^)U2gm#XH-)xR?UQ7URCNT_pR@x|H>Zw$1hN*mpXr|Dva zfDnLzLlK_+R?)Hb;4WaO0ltAAqFD)SLBS}^i%HnKV93#00MsA;p6U_M#!@{T_O}aZ zI0@J_#StElqVq^!OAwsi0eOqw0XtX7%9BqI$V=Z{a-X}olZ4-|C5|8WGFsmsq&2?F zcFSawn;J3rjz?`AP^oMyj}5O@cGy*aP*dVyaci4aZjmTCJd!7_@Ynum13>u&tYbkP zfky&?qG)*0p@>t=!hsM!o73}CTX*0$&MQsA!0{AYZhd$}*(gk2DB;*l!gK3!%O5)L zJIN@r@*S7SaomQ8IcXMmQQwUBP{GQpf0yPa;W8ox9SlF|`2Y)F`)$duN5as29>;f{ z6$tTNHxXtB;ys+wiXWJb7cNnhZ?Y8F3uqoKSc0ZL>I1ApNIf8i>>W0o!bR!~Faj=K zASM*1`D`NTkg0j=a6JdnJ9bW5n=Ud(@pY9KaToKkh;Jiek&O=71gq5m<}K>?9z9C2 z4Mzv^fq1mBcwRufsAnSF;@G7l;k?hFsh8vInt)hwZG>^|Q;A<~Fq2>*3MtUGT|5|R zDxf+?aGfEB=Zf8?)fGh&_qg7Qid?yV=+{nXJ9QuUh~2OJHOahh;-o|k*D*99D?M+k z-1C#mzv*+R_eb?BT|dWw|8)bm4nH_S9>e*5dk@-~;dR-l+d(#$l2>lHIQebUKZGYq z_|boe1e*3nzW?jMu(DpXC5awu@%sTcQ9C9Y&r1CA&-VBxYp}KJ9Vh{%@CkI?m-KdN zeZ)nKg?~``E_JiT$w&|BNv8K(0y8YL%4_9lWMT;=|D2E9=IOgeKsL%yUY~^SIz$+ud=twbt1_ zZXyyGWzh|GPd*E(RTzZNE59;8W!FW36~J=`YEDGLzOZfbXB^4FbW zltYzR>z}1vMinIe&<@B3T=cZklSOq6B~fp4O+IX3vbF`@ez-3qx&-I5fdQ)*PKfB6 z1J}HTM+?mR*VfKeF7S3n$osdD;x88^k{3`oT%?m5~ zv01JdZDY^}caDm%_KJ3(N>wd3p!GP}h|zpn9q%;LeXVd@)6XX%6WMLmz#V&23U$5) z8HEkHoH)wqHifE6M^(E9{$9`Wd5JkL(?HDw&5`T3>C> zD5R7$EgGwwfL$6(n9`T91vOOgo1b~}%=f1Kg_d7lbwN3?Uf2Nt#r?V+or9fS{zgWh zGPA<vN6l~Vv(9pS; zal&iGyqeWR%9Ak^SHa|GdZ|u3Q0cl8su2u&98BCv+H519FB|7n5gi>34B~3;MK6B!dB>ya;69RP zhI;MNqZ*z>IT~2=T)G<(2BHk{&7gsn79}$Bx50^Hg&WEw90Wt(r-`a z$K_Y5)8cWASJC3+hp!@UJop2%4n0q!8uqGXNxqD{kl;yuRIR)RsOQ~?o73Yd>xeD$ zdszIAG8i1icIQX%1-J=o)=YNo!?ZP($^DnQBAgEUO+j0T@@nqu|essr?w#a$Q@g%=4`3jMR-^g|mG0^%;v%HXhvsnyVB!tuQPp;z+O=U3h9B;;k z-4hAFj0TgX@W~aK8s}tmMlFW+9IL8`r$m3PSfGR2L+_1Vla8bII>^kBjI3L7JoV6lr|{IsQmdgtg{-_ZsY@h3dg3HA!m zImj)kh{IDbef<4d?@tdwREX5UN65x413%wc@@loXyXg#R4b1;IKX*N}M6-5oWeqJg z7a?V+kZKd@1ze@`k|&D835!qgTz9uj?+S6JKa1>%mfvuXJQ1`h?yLv!-blhP*1?kQ z%tZjaQ)x8rfBitTk0h8$WQ&I=)Gm22nuH{chgc;9N9;QRn0b{~biI)Lr6mLZ_mSSSwY{N@g|J{m;~~ujQ7~B&Bv2?Q^UP2tlys(( z)R6raQ$S$hFH32}@2+unL=T8r*gc#Qc1~qMGNX~vp@!?gRqGT?V&Gf86!#aji$hyz zr^ENo3p*-V-aa>((|b-zcn1-Qg#tgN(aCrrbbZ4ZmOBo{z!{Lcc#J<;Yz=d!w|iRb z=I@`o>8Ihx?vCt_v%^Oh2VU_c+XWQq!5b)abwJKLcb@ic$=9exrkI#NZZGbzDB^jr zB>t+Fp<^{$U6914@r58$6cLgbN`nyw`6m|AkY;FAOU_FfItdKBNb&uuAE}7H2PMT} z7?IucTxALPaKzpeHnkS7_z5+{ya=_X^HS^?>YeM@-yab=4*I9q9^fEi^eO=)h{T!} za%`Vn)Ym{QU;@NVV_!i%rC5$fJ+>?RolI>a!9UJqWEjpMA&F?$9F=Tg5{@CIij*kd z=FqNcdJqXbck4X6q-fA}z@+Cxpzb?_Y2yH0dbk;-_J+FD;iwXSIZf~VPUnmUO~k`B zQ(VF1BFbHB8h1{1+@s6Lx@7^7l*Z`Ljn(hbbpQlcodxx0uj6ahNQ2Gl{*5u9cTn*q zt@x+wNU`_8+)WgMGF{pNvI~mL>=|)_{B3K>7%AX5 z4huepd|*74GbqkR+X(VshRKLpD1@8gp{f}p9=6^JXk;u%9xnx(&HJGg=pDXCYW_9V zK<(=!hsX^SLUu@a^0)xS(K;^~%eJh=1k~T$)%*c-{_rD76%_3<{M^ImaF@8;w&l?8 zbSq;*F*Ffo)sjlpG{GD*nwcI)j0$#1-U4{2^Q6Q{erR{153?h@=QuTR0j;IySz57e zdhUHm+?}ABzr!0Es8`>={ORfD)8M|_h6K3esa|s&U`6*II#5ulXDGYVfq!+2f6ccx zC2kfWxb%W3`b!Y*?Y{?WvxdR5cfvsQuQvB5aU6DD`xnj(xb)}kGZPLONKnGR&|pH% z2FC@T{1JYpMSP2U86sa1hLN;Xymk=AjG#1+(8v~kZy0y{W=0YMOtHEGBn2^G1TiDN zphqEjuU2yy*$PhAKxsRe2LYu^=^E9zGAc8@%fza z`kX#Hn`A4Eyu7Mh)y-TjeS5KOWIKMkc-3u*0-Fb1-b4eK|JbmSMKNRsN zKq0b0jO!DOK;%4QtR_yOL+z}XRHxuoP?EAeeLHHeq#ii`+Xzzuk~vpqW68^AteSQ7 zpox0k>;g*KRFrJC189+E8<%Hq@$_*1>C|EYZ(!FiSxY;*W_FVfTu`T0dplWSpprG7 z5-6tPNcUXD>kYQt-v*a;8f!)?BNTyFYDajyHmy=^HCPCbJAdS4Q?S;$0*~jZggp4X z1#qr5I<~+Scb_-ph*i$TrJ4gf$H1VfqE5}&fjX6%-=SA1??^|y@dVpk0YJi}hvw?& ztD_>1XOqJ98gTv(1OYje<2!+Tqa6pQu9q_@ZTLQAcpEYfZs%VkZzjj2pfI8H@U_>C>1!uhWyAX5ZeC$k5pcCLjq3Df zzfGV+Fpvyv&6X6eP}Sh?nyK0gXn*TRE=lFcVGGX|`MHvymJ>{fvf`;ZhJVe_&3Y8O z#FXmBoAq(vl9yYHnWR{n^LNxhV}4(|>c=P;pU>vKwPl^&?LdTRA7>`4^_J3v8D^ml zWP*`HSUy6c%uX$IgFhXZ<*WAYdhhu02G8eEaI55Z6tk^u3MuYFp+bmUO(f!+CX3;g zUMA0L{}QxB4k*7{J`EkW`Z!y>yvC#8>fli;-Mv&4p9e4*Z%o$J;Iqtx*V`lrUv`>@ zlp6LGs9wsFbd!q<)2z2Q^+Bvar*1++G-0YK9bNFe22(Nsl0xysz9RQ6vqQqse;l2^ zGh^YAkezY8*VT&I*(K4pPxIKZol?5*&FUy6d+t^W=-!z>AHNMwGqhJL4vdpb;l4XiP5j z%6BJE-uhx@u;7WoAz~Z}3pzF0^jy3yhylVJrlE(4OtE)x<$Hg8&`odwphZXG0^Cyg zA;#{L=s$~vo8TVl8gssvC|OiwK%wUqe{Jo@HWq zaE>TAEjK)+nF=!NgneNld5qCB5VPu{a;C^nAdM!V89J6H;GFbQ94B zq5UE0MK|0UoLfY$MKAHD2+V$^EESuJracIO{PH-O?4;l( zbbk9%Z2q-VX`i&_?TCcV7*ej%lks7Ue2iq(fi<+1d#D_}UFR)E{Y4B+XbWBZ*Cq#< zcJAFBgE6EFKBE}KQ}kqqX`Xec{~zh{GDcwDpTX3+14rCK+Vn&QvpYIyF&-6P2` zHr7x277)O7UPu>aO6TwYfLGIZ$mil>Q~Wm;QYT-oHL*JM2$r*q`v5Fa#;yAU&h`+!Jz z0w)S^0nk!4(lcLnyH>|9LC^G}&*HjEgRRGQFdSU@Fm}Gv3vy&@%kFN+*!bEAF{8B3 zd|0WignSHbfA3IfA=oqIa_868qmae3$<{dVB*fi>i9}O-jux@qlG%zSOFKQ1bg#Nkrc_fN-(! zaZMuBVnbdU>?NNZz42gPghrr1dtT0qe+XxazO)nQ2;GZRg2jERb<{pjpY;BRuAtIMmscP9dr7bg9~T}0`>;z z2rG;mT|Yn-Rz`#g7_8n$nBHv{xw|grS6=$@(7!tZ@k;K0JK}+NUf)0|jU`dIW7DE2 zLTvOB!o@F{`OX|u#8um7rnSiIoMqWt@NB7pV9RS`+1Zuj?3k9z9tw^Yw7M&B=5gp@ zC=b`w4y=+aS?ENZOmRz*v$Y_wz*gjBnc1biFYQ70`#7F|QqUqN=2^M8PzjL-#&Q6A zj&|lHQo)uf0C--aK;CpyMJs1HM4S!{fVv?=T9!C~W8`-q8Iv(-xC2+LX8`D*KarW4 zvMHyLTU@>EBYcUGXHP~U$-Nm4xE+^gK;%cMx47s4Hgyh<9$F;q%=w2v+j+6|Sd*C? z#3X#S<<5*9otaxZv!uQS=t%p6!>9K)3-2Fz_yyO4-Z$gMzU#){@mx}Lwq!Loxzu%)txRfW|<@(zEwl>|6f1nF(fE$!(MHCK4N6!uQ_0#bX_AOcVwP8+GJSGD*BFs4PEF&1WEj1vH>Thd=)ZCq%0q8#`#%V= z{UAj9e}=W`zoA8IXZX+PIL9*B{-6`=>H{hiVkF+JSphQ4oKNBsWUp$(H6$=V%J>_% z;NxXuOtF;Kb>YnOW~Z^FJ>w2H9{H;z;;48it8&%?FU#9Vnm{jPMON(-f5c&+GD;NX zk8`ck8t4`9Sd*>T1H=d{1vmSuI?V~!)>oRHtCF9$b;uRmPD#FY9&X#|yckxt$el>I zGCHNC>K_Q@fYMvMfx%LVg=sLQhm{WAvx1wB15F#O+yS0lZtKhE08eb-ewJ=-sEEd5 z9ga{_BtVBo=hm>bdE5VMAyh2#`ixPn*B4;2*B zkp@>4J6qjn8wk(ZYML~ogjK##z5PK|Y<9RC7DTM4Ri12xufz*-l0}?K@%7C8%wc7?DF1}WWB{(OVJsxWu{$y5HldROS6M=aO z+$8bQzKr3B?HdI-Nmfs8pbsEjsmzJz2*&44Wig0|6r%qPM=Juj@V%eOE1azVd&{SP z+Mnh&PR0&4`d0sM3E4mP>3?q0X-&@`Y7OywH}@b!(UKC8f7C@MV~s{c5DBYCG9YE~ z3^c%ysCDD1a&RYqpdMtFT6Z;x-1@IWLWbYM@I6YC|Pq z(%E*fGtNy*LERyzAyU;6@qR2b-IY++6O%;%l*SiyQ1iBFqW?FZhGp8AhT2tcE(m;m zE0niTH7$o=@9hVPc>y(TnRXY=7sYbBTKDr)(bwdaM(W~4w5wsIX*1ahAd$^3p7f>f zZ+ZvM>*}j50Ci70mMsaOmb#JfFYS|JH_xz4gE>~d<-e#gGbp&s<^6MnsY;!z&SY#? z^~=tl&qqN`;MxJYXgD~7pv!Md#!_qPeNRk2s<-xnHi&N(@=$1g;$!nl+(cyY@FmIEjk5ZC{$8Hul$diHw}sRL2C>M7$eJ}zD8EcRNoY~RH*%l0b!@B)ciZ^Ro}A&m5TI2fWDP;7@mOp2c~h(^^wD;5IT z=&L2LFi{PGu}+#Y}|rweW^Fao_w-oZtZq=Jm+AW6xB1H+z73yLGe zS8Rg^24ckg@n`DeikcqMRs4p-eUhMn! z_WU!F6{jG2GcVG?*W>YN-A~mp)@|iaC`<`Ao#^vi4zX~{1V<#z&WxF3n#N1)$e)$s zJP5Okz;GhnhDiRaF!vr|>aME@XeWtqo*BwJ3=ST&J_?Ij6d69LU(fE2&(|fgye7(& z^Z8l@-0lFsJ-05Ca)9|Rct`8CQW1Dc&<8vZ%Yh@TY_SI1n7YkAPdb`{R$U^AlHS;iqx}1YF+ZI6k>VR$LaLZGKa|!K=)X{Fyk#B z;t@`__qR>kKf5=*B%)cu<3xlbyGe&vM0Rh*U&n}p{Z4wWA==P*lck!Tx5q3#DDbmI z?Diurqw~sIV|`$>7>S#qp|FaXV~g|%8g}|y`WJ?ySRBuG^zJXyBSY-#Jm`Q9p3jw6 z>zHZ$<*W4yMqkKw{9~qj&UnyUNF3m#XRy(S$v8NQb`T9;xFPTENmU|XUlib>NXC1a ztF}76FWa#|jCne75a^64i=UlcLdA8XyS*OTb!NlV;PgmOkl=WP8T9;&xe;#(`asOi zHBtC|h;cW4%5W{EZ~>nUU%b{YMubac9-D|=M_x7`b8AlhLe6UKIk=8kPagPhvsz6o za&&r$USpR1mJP$)2+Mko|%7(l`B%74bQu!Hw8sEd0(GDb16a?3ft;mTTp+&tvE%>-!{4CijTi}cGi#^RdWC%Y0*O7rkL&xWH~IBl ztOk8o6=cUy&dG?2kf3T$)E}-9 zi6xtNt6MwQl$R)#NVDt2lPCUuAV>Ev(h3tX%~hSo|kobWYb!(xJSw5m5_w)d$#f_($&E(po4d{z91ocVo>E^_$QLVCM?dTU76TjS7V> zlcshWKQ9ivH|SCXiI^X8!7{rMISoG3k7=5$8*!9XWV}){yUtN$o(75qLVG*|%va&aV6~$GTs8HQy7FbI+@^OM6aHdCF*m8i zZZe}caiB88X!NIuj?NQJp_|$rPLX+8xDWuoXoaC)Onqo#5K5uNMt$sB#1$jn3jL}9 zB_E!kaXw?!sfEHeQ$4%wdYF|JW8FZYEfuSnRAq&H+M>0gZUGsp^6^mDN_3Lvk7c>x zp?s@!&8_M3p!$Bga`Pvjv0Dm7i=?xCJt`=(@Cy?ljO4Mnsd3L-aqONfM?mDDR(#ng zLSwkwz)b+t`fS2YA4@-tIr*IJK@)DL5I^?4m9PtYpR@V;X=v;d6P%K~Wo#|DFtew~ z+*1I5(=un_MqJYnikW+&9tsXk)ehL78-Gp%%m0 zf#9so%jI)WneGI$)_S)yA&Dj}K)HsdJ2Hj3uMnz`0@| zFC`)vb&J!-oOED1m4=f|27SyZ-iG*4eIXZ?Y!=n~;SD1aivHZS=2#2HQdzeuc;?&T zSt^YVUaLw&;Lh=h;VIPbLAO@#ISw4D(OTlY153>N+_`}iJV`VWr)Ci-ek?|QX98vp z)nH)eS)zVx-i4Z$Z@7*GzLD4;*2i2fRplJq!4}tHY z&lqg1VmC^qtssG-`+CT50Xe}G&I3l>rN9VIh}t(zp0vv-?%+JilqLP9p=a29*WgA| zx^*+0&aH4x@j{=OVTK3-QWKVoN}?Tp<{2-OjN|mVa(Vn`YtTTzGp|n;3W+mhqb_>l znMmO+_&d9@ItphfRh;rjP2!_A4cFg6U-y~{`jFSG_kP(x@wh-|YZ|g;!uv#THh9fi zA(8u+s|N@_Ex86QigE{*e=Dy~rUpb9-<#{N5}Q9i;q%RO|J2mBfyRF0B5cJVy5rJz#AzA-!4IYx& zMMo$9>20yccvrv+Q$#Hz@Sjlr4M|6SdB>rMTJBf5P4MecV^6ia!Yt`+l#JkYO;N~y z7Z^i>rwW(n))=Xmf|(8~<{RZm_~}0MYOpcSI`G>&uSNF|dtwE#K-n4em6-h?K_))) ztbOmwo7>bj>+4US-lTnP-(P3Q`=0vIb5O$m+eM2MN}rHn;ApZyh?Eq2l%09)61x}| zxY`Q1eUY?H?o0b9!!5xvg|VtulSQb=q8C5-v6z6pTMRmO!ZV@rI~fwG);NtFdcOWk zk92ygUx9J=9a&wvDoP4(0B=q0W=sa5mK1&-HRhF>gl>02S~u0?qV}T1rbo$eM^&^r zXvXFt+b%B_?6_rJ$~k@3JIM&rtJOGT3*tM(uorF`Q*)kUliE*-xyRf7vDhPAYmnT1%@ zGGR&&V@T90(l&8!W+VL7V5Qe$OkorK_A|^Q77W7d*Rrsk)Xjov+=wL;5 zkL4sx0?uq^#1Hz${;04{3rJQiOpu2KFH4*NX^Io$DS(dj^VY9X(a=%HbMaWLQAwk< zDPIVVQ)JLt;Z`vrDUoXuDSN7lE!<7_P^v9fgvMGqI_O-DI1Q9hS^Gn2{pz9!CdWV)N zM|r&Ci3td^uV-lCeZA|3jE#m;liNHgF}-3)pE%8De>Q)iME9>$6T1j~Br7W17d@t# z2x`eY&SMCNQd;!aS{1WjGUlb+?+W%bE%DK>8FoWgGrRUD{QEs1?UdDES9;W+6&Fx_Bil0no5iXHZ&oIxTO4=(cUJ54K1Stt4|LdIuwBjn^ z^|0HN@5Rr#8T~$iK@gw**nnnqH{VjPG(7=NdOS{u5L9JR|GM<(Erq*J={c*L81Q{M zC`XSw)S(ARL|Txb`MG*cn;!*;kg18}W|MFQ6!)QUnit@Vl{?ac1aB;GTN|ZghGi{n zZDw&Mq}ALA^(#OOcq~SqB`+G?2o9}gOJE`SKE$ht#?sRO)HHypgTMMxV$UpFuUK6Q z_#{KRmGYW_lK)$8IeZ)*Y4<)l8Dcy-IwMh!)5=hwo+rUw*~oyBJ-IA17udc zOA{)#>@SuHzKeaUB8~2dFSmtbmK|a9)Y8G1+WC{w67tl_d8?N6szD~IosnUKG}8ZM zvHmAtP4utsgORPFborqbBY&=c*);QyK>xG440VbD3WxzEXrH$fqfTMY z4FZ~qt6z{>kkKk&y^F-XGqRPR}5*y*qG|T_ffA{YZ z|M5+u@91dk;AC!VL-XUJ=4|Ce`%mMae;m{fME}h}Esfn7+wS+}cBCVux+*Fd zKGJhLrAiVttZ1vC5OV_Vs>$~|&o&bhP}j_kPVw~z;GkK_?(tcvrzkjhL9MEsx>xVm z@aEuPVGFz3IdA-c%%JSy9{*#4@U0;YW4ZA&!7r>*F=WhP&e?-bqF5Em0A{4%6e8JR zRS`5vy!OaN0#78zWEy8p?vcNOWl`UiL}V0FsKXEJFyf+`AnE@PXYbS`3=?%(mTgx( zW!tuG+qP}nwr$(CZQEwQJrfht(U;#}$cW6yvvTKNC{!6VN8D)%>L!;2vG*i;ARN5J z$HWny(Mw*4mCTVA38f;`5~n&=SU)#*nB^gvX{jNUiG~{I*s>>p)TA2&IiC4qthmHv zDjwLAthi&E#0a8{mzhiEQ`F`#N%*>x)lVKm`SoaNiwN%j{_E&$3;|I-{Z?y@C%!T% z9yFv_;wERi0r)DoCq|yaPt(9A_QY}DrROFFbiuQnjWM3Cl5oeOCdp6%M!eSLJK_m< zvf-ABVNbCr_eF9`yay&rj<*O_kdP0ckV=s+Q^GKSS?r z$AAZ)9Y*e104O5zJIs~+c^D>Q@Zy1wdVANfbEeAn)0M%VLq3YIr>hI4Jr)=!W_#2b zvx0V8#*+oVJ@2N$7m6O`g~aSktBuR}ZJ()hQ;U4aXm=+4f&RYE=@eS)Gf6S4W4BV4v=PTdFv7gxE>AlO|oF+QW&{Tz~o}43YX;@7dpg8#itigk#3tL9&1X zzZ=uq-eFJATX65V?1=&gzi{>SVj&-)-}qk*{m3{6Ugz0t`Q3al17xQIPg%%}6Hn%T zqa!|$W!W{C4VLxM4d+&{Qw1p*Pb7p zcZCxnN@2Pbs&D?C8Rp}Mf(f4R(rmFt4PzBK#TkR>(FtXOFngv(ewl)BxB#glI;8lI z1xbwT+o@}$HSBGgKw9G~p!G7CRfq&&<8Id+!LL6bS5!|9=o2-V1q4%7)8EFKRJz>U zzrE2X=0vB#sgL;woVmOV8++5U?W&~y|v+$qbDrksvs{3hs|7svi)~v@$2c7N%m}5 zBgXT9M^D#_7c+o)i0~&;!oR?|y|u+_MF1(a zAekR9@_A7V!ti|S(eQ46E zz9rVzvrOlJ6iL5)3)ieDO1GTg}qv1>uJ5fC}YWynEV)B;I7}Ab`eM>U+Eo4 zr5~r~Nl-vCRN_xuf40t|J!E1~fO<`oN*rvqHh)_T!t)fuGI`Pq%5`49e_G=`)I+Xd z5)%4Ag-!8GI@}dQ>Y4W~&jK`~6z@ABTheb_+XReLnG;|MZ2%WnrN?bpl^)O^T1jMO zhYhM4^FEgerScNgZQi>a8>O4S14B@WhaVcmFO1^i^9#-AB0rS{L`u=Tf^~-hXHsnN zt+Y0pb#q4CW{Om!V*H{Vd;v1bN`2ZU6hO~8#i0aU)vRl2X6`~f5Q+8em`fCyPFNqy%iE5fOTyAq?z+OHdWs1@D&QjS^60O zi|aIC<4B_zC)7)%-C@YBp^}>kb3;Xg9^VIY-PqH;v)3mGq0O1*rB8V1s*H4zNl>X0 zgO|WGPetPKO@{}TDUP7Y@lRFq@m2+2k>Z`JW<*KktcdinB07f@3XkPkjcxTu8y5eH zme+;bgTH(DIJ5vji6P#2{&^|QCEz6xwSahF=JVYGCD)T@@}4SpOKB?uTTIOA`@f+Vjp6Nwt$?e0MVt;75^sATUSu2Rn^f`d<5jA2)F#`nY^K?n%7s5JD}m3_>6u-kIa%xNU#i#Y zg0_~yu=>eX#1I(v0wpl!R;^w~Q;zMO5pd7E4pP_-*if+T6o{SVe?r$)h9RZGYxg27 z+;s0ceYPoe!zfj2i-xXlme0xUN&UF--(Pq>9NbL8r2aDDZ`2clBT@*@IwRP*;52lF z>fx;+HnHg*#_@Tzf5VP_YBUSkxr@6^JY)xUbG3?394%M=4*Umz6DA*L*6$kI1(m_$ zxJ%&^%tklX<_2SQ*1#prz)`~~+rb@(?j|3oMcd70#lFEI<4en1*SwatAcZFD< zet`{b{JjW%-q8j0hv7hI&=dFIq*|0c`xv}V-ce45+;-Ns)PQzwP8KuK^|T+76(;lg zs-LHtaS#dxK|eA1Y4onR=4pr#idUnQ=L?CpFCdz_*uL{$ic$Ca@bk@}>Urh;+WrE) zJuoW{#7vB?w!{wyq+MrSyqg@C(uef3ZZ_+KI%4e=1_G2DqU%M>Gvlku#R}~y2rW$j zA0bHXlI0x-PE>mEpLYzg`3)>w74!7jhKz%LDy>L1T)Gkq9?Lga!ZU{-4n{seKcRRd zo~lky>vnclo_jZsyGMMGJ8ejCuQBu1fBmu9{%=XfDP}ZW^E5G;EH~)$4`riy(7O*S z)g2)+>?nI>-F;9l9QDr4Qbex@5>98-Qy@abVSGOr)tMwG%a#4S1+k*M8a>ETv)g|C zW`1V2?+s$7GOrW$JVXyMir&e7hDe!EzzSwZpU_2)luM|(pQCxu@cLg zH+G!h25y9s-YeL`={935}1Bh#Z!szHsZ2rNYeOn+t5*_+X*;M zZSpU__MkZI>nbMP}OTvL@^I$VA&oZeXi*1hiIT(Nf_&_n~@A{=r=K| zp>;IVBFLbXyN>HnUAr}$^w&cf@1>H64{w&wFJJax1?rKx`g8kXG8p3RGO}WKAaGL7 z!G-)aDjUe#tu(Lr3|kErQ@GA7sLDLC|Di$zW0+2AIieGq8BZx0W8K5*Invb!ho(cS z(`3dHPpaxT+8Uj-lmm00>FzY-8nKwzRxODxFZ6SE;^Jy3AaSg^NaFoBveuFkbTY^u zmJG5G-Fi0@mUa6F5;e)xE5^7@E{XVcUaP#7<<`utr0Ks^^!Glh>!*hLw1HMoCP5ir zM~jxX(3O#_N_z2H-g5R$#$oH!pBG6Gl48lGijvxXpT^TamP5J8d+H!~N7dqox)APG zq1VY)3mnZep?*-Px5A3 z!lvkUnZ1@PXoJt9$YQqDHCxxoe{zCVE!*9B)wNRQ&7%6E@+i{jkFfQddO@3|TI2=?@k{(Bn7Q0w{90()4#{Jg(8J=H!;IA5jtgYJQ=q)oKcXWF}A(P4Ata#gIHY(}-$C28Os_KKf+ z0^b^Og4i*T=OJAt%WD6A*Gwqx{h5K;o=~hNO_cJidobKTQo-2fxfAq^nXijRg7+TM z%=Z0XHPP^lxEM<)|JfNh0RVXZClimciGi~@&Ht18`Tu8~7Og9{Eq2$x+diP8=V%hK z)THL6TqC(nBB|yXrp9B`5_d;dEzm-IOjwah5DTrWQ@=YOf8yu*oax!iAeyB95ufi{ zVD$Tmh;!m9mr8WE4EMLw89Et<4B{wpNIp0%a5Az&9FaiXe+iUDi(V{4XYZEfrklnU zxu+Sjh6G0$<1t8_XrvQM@(W27u_m2pPsBQzrS9_^IpT_+Imeia8l+4-YX!nsG6YH_ zs+2mH)JjYZl1W}XL3A5A)B9mSoC?X@=k5f9#JLvP#`Z`GiW?OsuzX@#FjxuG(6fWa zrNfMDm=Gxv`xq8e7LIXs)x7bt*~Xm8GVV1o;rW%3WBozTAYlf8weE7nI%G^O^Pz6BM)Jf8it8o4H zVBA1ZBiOq5IE!HtryIb5|4lpTDNu-N^m0V|io(j%>x`q4{!3zNzW9LyBj>F=&mi7? zm~g!BI(1aDe1lSQ&R}eKVZSFU;@YsDI(8W0u6@vQUquCeytuHTfQc0?!0FmWZa2ST z2S2_{&w>0fp@V(B7a#oaXc()=>EbpFxO77awcC5TdbQGMb)l zr5M`bR(9(hfqYwMzH@j!#Uym!3V3N<7%&r7BQjp>k6cH(UgWl;Ls5-&XZgu0~#aRLsJ=a^VU&jbyV{WT&O9|(d)MhJ#tOYQp?C{+y5YBccwUXL&Y1GK46C_;n1AY5h~ zWn;$k)Vjc_z_#je*iW6! zP+A8mlr2p>A~|%k$s|Au8wm8*qb14mf9%U9nXxCy1MBp6>E)EfU#TIdqJnH_{9V=J zl*PHt=<0vT1>DoQyO9&Oq4(=_XGdUd2Js+euQ~tcdHB#_!!8ahDjX z<)RdRX|ex4!43(ITa-jgM-xjGLFjQWtYLx2LWRfM%>iJ1DJW5Tv_&c@ZC&ZPNBad@ z_FmZYy9ZINRMSxf7low-RLONZ*-?!&!Ce%@qI{8oq6TrOQW%;ldr}#tkzG;L4Rgg% zF6&_mCZ`ReNcAd|ae$~1Yup@L6d8UC>iLmx02DJ`zKDW3meJykqQJ3lsZ-5VK)+i< z8k`FZQ-D$tx#aN^luk==>txtNS3t(ONs8ah`Uimh|};aCl+~pJh%VnP=hcGr~t6)5LpJQ zc6J>#7|JNZEjT__OpX2%T~GHH$ZD7q-nK7nkO$S0PZWRxu*4)dyNZ1A+nM?d8h$x# zy>;OL3^7p;7}ZaRob0<%1NcOlikM=$BJY({!iU9Rb_@vUq+c6V1a-MnC{#*^LZ{8X zY%Y@00yIC&gk1Iecq=W}p#X5K0o?n3&n5h$lpxqRovM(u+J_c~5~&VChM?JvVl%tH zQhR{@_WbDt44Aq_&~8S%+M!Ppdg+UoY3#IRj#~Ja=lGBe9=VFR>2Bp(w7SmqwWcR> zBPjSF@G>ABRC}1H2&-pBHP&Wx;@=fAxi`t#k?9y0ih zwc8Q5*M~0ss-Z9l0hL_sLUJ_XjvB8`K1XU~?uy}$NT~OtEFlmeV*~>hEO8JI(c~Ld;}Y6W(b_qj`wN==i8lkF7TqkC`7i zaZKf?4>O1XpH8o2bgA-aJQGmEWJVPiQ9llvpiB7f@v1t@QvVe?X%IQUGJ)v!d zv^YgQFm8)F#QcaMQoe@!XBX38mq7Xf<)Bixg0}|i4U!rp2wv#b^SUK~`1R{aAone&-8Iyt?OF1ju(qEaJV1|4xzkc+HL%H=i zr#Cn8D*PJghYzm@DO{SXwzv2TDmwsjI3jUBh#7_0j9~C{63(7H^X7qi@W{Sgo~c%l z8RfDR2KN$lj>=G{))1wpx$ry_1YjT^gV*i!FLPb)*zHrhXKv@*(q+fSVIhvQH{Oxt zsEK96oCtB(bKu=kFQKx`jJ7Iv!tKu4+sadz%}G@>JtKiRcR}8k*#}Xj2(o{u3e!-U z%}#SbnrGd)tYONSL8=l86?u!Ryb*&oqGDWurb(>s*5ApjN6=#rs>JxehIp?08^`;F zS^Y>ixmdrOSii5s_rF~PfF1Wr{DCJ~&sg4xh^E+5(wadf$?Jqz6%Ey&DL70m4nMkp zu@qwML;ndb|=#cnO z*kOi~LXPAx`i^kN#X`Ddux_w&ap_%(P)T)Ir&K}3i{3&YDwJJSCRkpX_1W$2v`y)Z z`(ucA-ojiF%-xvwr6{g>{?svii10j8C4j1u*b>-P9Od0c(#TFh>4v`<4~#&190qRk zYd3q*(Mp|LTlaOmYcy~nQMfOUB6J3vIRGPkxkwrwWlQ1#t=mZ$+BPgO)!n_rW5C3M z?l6;WoN>{+an|hYQz6C?Cd@6W;xdViA_J)USs+P;TcinRhrcy8zoQz14Q0l3N}If) z9drc(eJ3(3!7zC})()J(nM9i}6oFCxT$sCd$)KL-rZJk91~ZmMcFk4g9&$^4S}CK; zcixY~<^rgT+m_*WVXXd&^;&|Fez#%MP%qai1Z-mzv~x_`$#SgWFft8CMmZ!)8I_XB zi0n*aAetN$qx|SrBgM*B)S>e1N(vn2YW`F^A^`hHEXV#Qlw{GABFXx}X&G7EX_r;X zx!0DD;F~4Vi_A%md8&XgI0l$!-6}3l{{GWkmx53d9K01;Yye{l6sCtvY5m| zMq5ZUluAHEcAhq7*!8t(miTuVTj?C;myQW9YwiHyphr`#i6&G$wZ&n=c%N3Th`E|Z zkFJIQYV{Cx#d$lluDH;5XZ&GVskaXa8Lopu9?Q4=vb}%sJrY67D@*Do$m-m#E(%_!5hM}HH6FW^5ujXy&2^=C;+Tfio1 z;QExiwOZu>-A8>@%nq3}kgn7Y!|0o2M%zX05dsRLa{wn^3Wi>UDTb`d?;y$9q{0h+ z)SHM$>sW5NL1!w*t`7oKe@Xz4-O_UT=W&zFp5m1B5%h_n3jPB~t`Q>a+X#0L!7`@`p-Q*Nu&6_l3XJZ3eo%KJ9)!t9P-hBlmFa4B z%G37C))0lxuJ-cS1qH;?K0$XA8v|`joL2~Z44kGet5f*t+n+zT`>gq~tG8QG4ri42 zTQPUc(LUT$DO*}2)jI4{SrIy}aWRu<7_jbxqFF)WG~)DntiK>N3?!->ROQwJ7VeYx zORa+tRV7I|adaCi!OliRVEj}L2RfmedCS9@r_kK-1*=RgFO`MRLhIe!i!?(Nc!%2p zpkp~KT#MxEuEw0qGO=L|J*|fM_G(WZgI-vzXF+BP%F6P1m%9I8U4R;s`dcA04%nea zK+i5|SRV+MPpP(TRo3*h&q%w1XwTaHifVBz0%xOsYa_>3{%NmvC2L}BR|QXq45;R8 z%2Q~fRGMeks=6bAV8br9-OV?P#m1XFp;@c$J*kHmT~fGjZn?>(q4{=58?*Iz{%<1{TJ~BHE*j*7XxRxdZgo6z_8Hh5sOKR&Sju_O7@t5%VnSf1Z=UiSQx4I+Zlf;`YGim1l!so)({v?> zVvXEDJR)fEpvDT4+M^5fV58qoflvuVT7gv~^g6Wm?})2<`ZBbIXmRtpN5=zPGtif9 zAv17FQ+r#(kN2jg!fN}TVfdSlyj{d4OwN@Rx=y-C!$&Afr*TdyVZTQNM*;VbQ5CfUa~ ze6Q5vFruG9q_GuTrNg@u@KvXU5X--RNj z1IW5}1Xq?(~h_qI|}DsIBSYy{O^ z36lYbC?lJW+&ECu?%r>z{X{PEGEzw(Op&8z>F~=~eUijnoA&mepSl4_WpnENaiqtQ zeA5be{iN8H4j1ogc~!;P#*nVrA1jr-8m#v#Fo!-H1`r!qnb8kdr1{DRN?gRiSqbZE z*|mA{KWQ;T`{z=qFKdX%BPlO#xt@BsXP!Z>X@2nf^#YJKHek+x)_}2H? zn`P!~NKzR}?60{Oq`Os*yvBlD^?IvjUL}vPYf98gP_xfNHS>s!3VdXCIQ+1Ke5&>|1 zYxT4oxOb$Qt5wq;yL^OzqAziPsm z%3rg5X%DYyJ&N$HO9&fjIg--L??14P117lb9EE~^q!yB1`4nu@1t2|Tr&M1odM=Yk zDDV-)tC!z>7$BLbyC9HEMqDGHaIF}HrF}hXqiu;J2do1_myKG|sE=r{^R5M;hn?g- z6@oGZNep?fvM6_}OW0q_gOug$piL2T9Q|ZrpsuOI+tunN?F}Ms%88Hp;1|~tgW@P-xGIwI8t4@d(yKWfipHc z_6@K@DLmrvuH&AZUe*Dp-bfxnj%f54tPX9+hwDgAS>GTF^5I1u^xhdE3Z+S!ndoM)MxoF~HcPgzACp1vE zj4+`>`t}4R@2Dyu8_XgVq^*iNoajJIsX?*?f-qsU%9!wC!Uo}ELUa1iIAL`}D1JsH zd;af%Qiwdt9cwx;B98uYP_9^g(iqV=BRkRrX%AfKJ$~i~<~IR=4CW{dzY{r$Jriu5 zVnh~1!W1?H>z9KPKRwdDlp$+ai2|*PIY`2US3kP`XX_nTkHQl_n|wAfqI&2GAC&+= z2;+5pq1hiTnjP{-pCIYTQdplqiWUno{l*z|98(*?U*N3EUO?P3b;-R^bDaE%Wl0x^ z&(J+7JS1;|__EUq7bN@`cN9G6fXP##U6wLg~>g@J{;GAdkR+Enw%zXpVOl=Jhd?(6{=;5}~ zZ5INiR(Qbwl91TlT*x>cYp}m4F#LiW=}jPxq}0ATA8O`J33z zY&~t~Pt)#gcztdQL+ikjVsiJAQ?TyN{1v)9gl|63nz z+?K}Vk$AtmnFdW;YYh`Pt0@^Y*r3x`YR9{gyFdY-`1Ks(fMHe*wus z(pwAOI2JxDUP{JF=Gf_+vxzhBGwArWPmn#=!(3P+RV-al-BKEDyj@`B4W4XZL& zDU~NR0OW#37?aKI6(87|ofsq4+?<+$%~AS~rRUv25Yuxr;#TR_DuY* zr9R)>d;1mw#t^qJ-^(9=fWiar-hMHr3oEh zbtfHC-}S4sR_j@JbOBTntSFG`*8_I}C@U*|JB5}^vJs@>Pt%6p%z&mngMr*$pQ`x& zMEuo79tGZyC3fNcJYPQ19pJ_DnY@0U9{O;Is6dijFJtJ!%#7ssGTGS?KBLTYBG>+Y zKhLs(Bj@qmg$Uxpq42KW-i>MG)4 zShwqLj}nj%`e5%8X(TLNpRy3)w}IiZ*38w_Y!+2i@Z;s63(t{FOIi4 zL<7RX1B%8Qu&_J3`@qm(@|n9$=q&qT-)W>4Eh{rS!!$}Frr_fwfyB5BDLLSQFCp(- zvW9vr0o<5xel!M;lRx4^0A?|BmPavXv0_QG#afo8A>h7Xjyt28@<0R_6C>+q!Vf5= zpISo##6Opz7<1+`6AO!GPdNh##9@!!Dr*EDmyy+d9=9Q)Hl4N8~*r~4zD zL!$(|Mb^$JNDa67B_%}{k{x7e*wzD7lQWeWzxKN{Xzzp$6ayN9;?GX=7uXhtE<6;q z2c^>>QPC$#w2Qh{RA56pv%-uz=Z*rvl+gL^=c};PCLz_LDqj$?#II!4q@ zKve_^94lYijm=8~Jq1a`r_9V)F=I;(&9f{ZeA`?fwAJkajQYeIQ_ZLNB@dJbT=#Gi zc+>vKF`i(gTwLq{QR|~4q+`KAI#TxL#}Zxsw;Bvexk>qR)|urNWrcoAR|nUOke>tLSRF97~@LF=zi>|3zRTv8j8qbp9W17z1i|g z>Y_D?;@Ahm4-;%GU4T4tRHUKjXcseoz>s~G`IgN|GWipdgo)%R4k)!OCehfS6k5>x zycXom#HU|~7N|l^M2Ol)KtBBBTbsMsrT;{WLZxOrxJifrCg<$K#{`0@ICZrQ;srOo z!^Yo@=^Timfgk9>Yr+lr^(;SToP(Ltc%=!12or8DOLdqq`vX2yiW5i3Nz)^Jutn1$C~r+{}2eX?Z+uL;1i-XGYhiO8$aZ``h|i~ zCmXGwn@b%#uBw*ON;S&ja%TAkwd0 z-SABVV|={7yZ6lk>`TDdokzrP6stD#=t;u(len4qs%8XUVe}L|1Gv`cXJYs}HaG5{ z5#YZQhX}f0COrTU5=2(hZg*Xc1ARowL?@Fxmn|LQKTwzD55*CswTP`7*1P~ORYTD1 zmvq4aRg(jiyNy@ghUJ4Vu{bAD)HZYH6N*fr^5cpez<_9ZFS^uI;tDNq!M$*hzGu$a%S&^50jV$O7l59Z>_2vroruMH-j324|D z1v+d}QI95RK!4N|)JLx}K}^7b;Zsy22=WEIR&CvF`!?~u+6%l-0Ksys;y_tYi-!M| z&F$uQHI~sdQ-*IKW)3OejT=8N{@p~e)W)xKq{p`GXQG+Lh!COd6L8=97GNtSzxAXw z!GNGHK_%yrs30)vrI``c&hWiJQs!!h9Rwi68-XSXlf^}5=+p`b5RNKB{da1rrK$?4 z=>|FLK5NoWyjgm#9=O5jMiwUd4+=L-$6l1G`y9a-tf$p4%2P@Js~rv{5Tb`(f#waA;eH6nW0FB8cQ~UKEviLBJV1EH zwB9h3?V$6Pc2%!=I#LGJ;aO0*>uqs(O5D35E#zGc%wEEIHO4<4@GMBNA{hTfTeM_L zW%hL=;GlK43xuk>d_u{LbY`@psr8C_dNV~y-%TN#+{z+DwTF;Hj5dYDd|TgG>$Mar zI7}n1@r)GuzNNmiI(WFb+EYheM3r?*UGf%0KEzWi0tV_8VAUgN66M6{5XzvPs?LIb zsiI6PgGZdv4p7ZtDjc`iYcu#9A*u&O+7w92y~1PiBmd5*Qo>#ZhzeOPMU~d9OVXPI zyDoGVyV6^4-@~N~w$u)^f>i%0cgfd~9lVM2zlRTlYq`CBLR2*bVL;kqW&tWKeB7qG zx;_HQ;uByFC6Drr2N=PP4-6odyOv2*CleFtQK#sD2Xu}agISRhE8D{1=Q0=>I54!i z6aDWAGZ0WG4%9liWyKP2Ohs0veVq?!r+|9BGm1X1Wmm_U-5yDMRcA~b_8JeU{j7pK zB!qOd^0{G*N$QBTT`?vVbecgsn5TbK+dPwkYYz5IvKF$P$;_&Oqw}LV<Ksa1mw1vAU>ZC~5P6wTtNS$3@1I>}=}6y{VlTNPP*tprVXt(X zE7WU*%8MY*jLcvKD?=au^7l}rnub75Y8OFpJChF6p=O?zeEL2%bEu$%6T&m>M{__V}Rs)nox9{xatDIk~Vk8y26)L4=rsiT`B zn)ga(m5EhI*$2MQk;Eg$?xri!`p+m_I49R?xcmvWE>r6*0R^N^m;@3GLj^F`N zULe;G1DS>$Yg6!+n#O%n-i!JW2a zq&}pRbS!Dkl)O0cTR*M*NkP0?Gu}vJo1r#_P>#&|Q0Zt(nQ$Z>G8xR28&en${@4M% zmD*k$Gw(WF%0+fWFk8MeLS0~XaLO_Gz92NmM>0EkTp6v`sr)cl1jOs!0ZjgVhq>Q)+l8yOq)HNg z<{hV#Ug7xrYPfUPc11&r(G!<`FI1aZ1BxMC=$|Eh{waI&kTZnOT&>cc#{OcjvjTHP z1{HR4gJMtbzLf1{m*4Rl*pfFz%17?WKc`#idU2X~h&U#&>az&36|qs~K|x=nglbH#f}% zYGIhvKP0%%3r)~H>!eA=59HFXL)EeXAmozMwyC}!9&GDRbb6^Pi30t zUeZm23FeO5?Oxe=0Bcz{f0`l;f}8t~x{KOdyK*P->RG;cH8<^I-MD%g@5m+bw7@zP z8JxyOU1?5fYT)-@vBQvFA^D)BftNRw*s_}8YKm1RKOyiJVzA}z-#Th!L7^7NdFt^4C?4tH=D{44mO zKpLV6q0O7ucLAM`T@7l_=2oJNj-x`0@rMe9&}`6ajyATEOr9>!*=}()f@l_=k-2sB zjx-`f4Um|W=71!}9vhmSGnfGsvSv=!*q$u8_H)RxN}V7Vuv#+T;SnvY9SJ5^8V5eibWP?YykEhskE zrE(iw4}sJ)taB`i;UPl3x5r0Q;j>hpj}Y0o-CBZ1S(S4kvKHmS@Hx2;#Jl22H}=XO zEA_v8A)8L};#dZo+q=aqaadVrh*h&d^4_8}Kni@$>y+!h&|H8&?$JP{ey#j$9y!1D zlEiE~yai$_X6gj7Yt~qojT0zm@X}Ed;XGCsMfWsQ2Sd~~RLG0epo8+U{QG)7;T3mH zl)2S%WOzF1d7%92oUHa{4XJGFcm;tRSy=CAH80Pnf35jbr2Bp3(1NEhot}sAw@2M0 zJRH+HaIo$?8r3=SKBKf4$(#OcJe zmjLh-fP*xi;5oIW4@{m!&jM}XoYTvv#}bfVoF?q2>WP>y~5dA>k&G=J?Tygc@Cl+K=vpSiC!`1pjOA{Z-Gs}LeieAM>(u* ze$UrCTo(Vc`3Pr3R=>WctDZnsm+}so_T$*UzlOI^U7Tk2ZF9DtHRYC`%>r~;cuS1! zmFJ>FR?B56c92rMSTrRjN9truV|I-BK+wOSzndR#{f$yIeKj+hY;akJ;P6YmP>k zb=@%Pb6J>KjO}G=rV@T&ujxXahwa~gHA9~KcOD{qvROdBYtnnZi@yiJ{bk-Yjyp-a zOU0zuq4DN+zm+9-A3OD{fQw$&kk7{OhM-&Q%z(3q)d2HQcOmBNHn}EXm)j6i?%|e^ zdF@Hx?sLMeMX_tl21UsJHe4`;)1H44&AVTeS-Ek6=`=J>6JS8O4>WMMk{dcUJo_(U zI>%yhO1f0i78)`sme8K_vqQ)aC#dtyepb;JC+%H24yx;jfCVMv`;!ewm`|5bUMBkr zd*F0-C7VTrFC;uHLQC7*_gxDM$?T{?$1KOFVr7MB&%1i}(2NxQW7;;$Y-Mo*T~B3V zPaa~^YSZnlZr0Ljv%Uzb=H8dzAs9HTbxGZd&u|<}_YjjcQ_QPtD@mIO8(!{h6i%F! zW42{gW)d+6=bvHN`UI2MTxWvsMU&$PXi-zPs&7@Y)g34?Hmtk8cD04@um_C;YliOr^Ksr6yA7{kQBHr&2$~9*L@FUKcgtlyrx)R;`3$ zdgg!%S8017xZSQlLK{bK+0njU5DGm?l}Le(swJE2SU9<9BI6&KbuWxLoCC*x60hRF zKS;NOId0^0mhlx6U<0|iZl%F(Ue-{rZWC3OD5SL5oL4dI>|3y3RD#a!u-bv^JiA#m z>mlU4{D>3x^k8byi4tmAt7H!+rO52!VyqClrrE3wIr?Qf9TVkVkjJXvegLS~n0{wz zT-V>WR2tmSn~qi$W2r@%lPYLV(C)sO-V*t!!ftw1}Ra58Ka^iDF7p zyp^KQ4s@tDvpeb_#X|Sy9!Zy?RNb$?WUql;31s?E^$Zr7w%Q_gAvz68yDb;q=j}s= zu4b`@DrOhq9ngpgrl_Xt0S^dfbQ!&WVWGqPK(_;?!Ui`=nPIdlBjVz%l#PW^_bJ@E z=+pkGs~sG1BA)1jyr4mr`4ZEjYzxfMB(jvXf&MGM5luLyH7K;lJLga;H#Wh55zJ0s z0N?$PP}gGkJdio;e#K40gb66PW(ul>FG1BSD4|2j zkY47Th8~=JS_-Lmy$1yOh6xQXCXhw_{4^_;0|Pt5k2CJx8*38g5EX2Bjl4Cc(@p>?nE z{nYYeh1=2#nTPlnX@SXLnyBqVbw}Av_Mayyg8YGtv!ITK8!{+4p|7}=z#J|dJZT!d zh6~euYQdLx&VCcaI)$r~t78lt^TTx(>9&xFr>h)Dxg!&$Iqp#t30FrX;y&Ioa`v*s zN(&ZnGJfjS>{*NtQ!NUcOcbeWRa59aSmYcPAGVo8(@Ld0#8O*1G%4b9_CPckYWb)K z(ui9VR({lAJyUwOPj6dsaT*n~t6B53?4KQ3+}cFlD_x%W zRt~r~qYs<-voI20LT}GCLk0^CYiXq0lFHKZ^Hxe}9Ne?Bh7GTpcvhFf-J!yzjm@!uo$oVToRQfVJ-kY0CXGe@NVyX+1cwWdK`WF{?1|Gr;hPatSog$w zQ|3~mei$r{R?*+$Vre;VN0(BmH4~X-jMYSF+A6Co5nqAgun0|xav@bT$zLthISx7L z`2^*2lD!RWS99|yw`1@87q~a;?6lIAR|Htjz!ai{3uul@5K;am(|8(MEt)$a$6NK( z6hl|Ze{PkEc8pqjCr zGIoWbuo>OQA*6(eiu4txmo-U;;u{!<78yy@gKF%$25;3*(#WsLEax``ewf!kVuTC1 z+*vWIRZUNtUtk!aq6f6xd3oJWB^~SroN^U{m3-bc@(W)HHX?v7vzwfihO@)AIZ^hV zFo(C5g%D@GnhXQ+WtQjMh~hjXYCTbOR|}xm=62I)z2;Qk(9>}zwe>w8^j_JJTQ%9K z++|XOZKjuqC(>(B-*jhf|5|^NFlN!2eM9 zw?iI?bM5K`5&+D7*a!k-tM+Gd=`P#=jfM20GszY`{wd0E>k|Odjpru@=bgUkoNOf{ zOatGd6>x1EG@!I|;YwaQe!x5(;|`w#I1+1LCbvEJ9y8a&S83G0i|q~*&`7{NDMekv zSzSHn^t`PTrcqv&@8#1Q{}+QKO*hhSZOAYZXRaga6^1>lgd?+|cS=aR!80KJ8^)fk zVmn(DW1dk6IU&noFNWn&uUkO}weR>}oSj2>CV|#&V<%s1+qP}9W3yx19jjw^Y}>YN z+cs~`?4Eyk233=q)KfL6XV<&-djI;?jc>VxH0nM69zD|XW<+;zSHSVFVT_STJ3WR# zZ|>cs?$M`JEW{BsT6>-7sGagu-oe_veASWmWGdcfcHz+MSs`3<23z#_Dja&A+A*Ur zbPY}uwv?<=H@*=nBY;xoiI_7$${D1|CEt#j=q6-hD)++vcc$9#oaLtzbhJ2r_OUB` zS42h|$Yk{(LMW&PmvnpFU_?wvu=`Le|3?5SsQb5IPdg+4-CM&dZEs!7V;J+P! z4vy{Rt(3xUDBz1*4NWJKu`_CF2<^&y#E(0GJ!m#-%44!x)yPZUGO~{0&m5O}GOHU$ znMQJ6pSJe{Us0(`gm@`6O@kr#hGo%(w{@vC1`Z)7r zU(z-+)7Nv;Z`_tCn|@xeen9^XN^GriLBGNOh-iKavAF*yP{P#7$8quddv$2Y}ApmX|0Y1vv8Nf5l&mE|gUi`MDhMqJF#s>kgcc3}(9~*m0=| zzW#$0yh{Xr=v&*i#d?TgqpB|)%_IbOHN6c22tEuaFn+w4lObO(Wi&q`4GJP?tXB@- zu(aKRacu!zD)N-Qp$vqoTf6T*g4bR1t-CqEaKq-I$(SaM?fd);!G!o{X-k%z9Yp}e ziMNOVX4KnPG{=PyE3d{MX<}{^d)9h~F8! zF!$1xB@l`5s8R|Tc=J}zFw4c>uHxtEaTOYlyI+B?TG$WQ zbN=*#{efa1!P^%SR%o7I9k9BTz?8K*5W|t?OFnA?coNsx(DiZ`AiJ+yd^3pwTEYpQ zv|K?RItaR)q8Zv+9O=Fr0*xh?m7K{UaL41E23Q16XOIxrTt-dH%LmzBRE>YyU)8z& z@uPa{SKvRjJ0`&g*$x3@*xB1uZvVdR{f|on((fe*%2WwC2XSEIm?T8%TNY?lsJ6Ap)1L;DSoXleCceSV&0< zt@whYOa^Z~jNdV#E-&bjh77_ksGQc3A1b`?`>PydDyaHUPp*M44{X)(r9ju`Y4l60 zi>p;UR&AD48Y=3a%w(zbE+g<1C0alrmpqy|$}FayHF$BUjB%Arr(FHWOAg^IRqwv#l-1F^E#F@URd_o4|x+OlY;7b*w$+fn1RjGJ4Rk zA`>zxMJ=&ScWA(c>mmcc7a>ueu-mFtl-&f#ukMICMh<#pK<>uU-v)_LwrV$lTYiYe zzWs$CBy9EE#*YmREC9fOSG z(ul6gwzPR5y8Z$}c+(3IQ#-!-@Y{vDXDl!(qA8YY8*U@$;$Us{xGM(MQ1QgS2y@v& zW8kMS@_amnaH2fgs_iTi#%jwmp27~E5*5r}ZtFImM z=ZD~77yFgBMn_e?k;3@%?(n@6zsfTseYyamzelDT!N9p)T*y&gES**=G6#=(u$*-; z!$`r@eP7(EKc{yYx(Ar&$_;eCON_7800tD2=<%Q4Ea9dLBaV#f5bN{5yb>rkU6iw6 zh`;PbpDHjZ;Ngd56fZ74b5;IYeHN~TbqFiWtMjd*_{}n_(D2M4i8XBACLgPMD*g%F zmnj?Voh5S z2n$r;kcH$&vDf>xBiCpuH=59zM}yP{k|=#^maS3aY2c6$3jc__E1-cH zElXGPEAF}Y`^J|=!Tb%`CSruRZq~gh2|6c%ojq}Wp1_yC+f`U_{~a&%z+|fFO-E7{A;iB|5GWb_gfS}COp+o2{R%F0! zj)|A;;^j~M98yfAg&hx$?+c+tH~g&9Ft-j2mzwO6HyShDL4uTeT-H5qQ@X5j+Gmkd z2MSS?+g9-v61({b2YgtgqPV^h@-hv^L(8nJE`Y8`; zwdwKoVa3uH0MS}D4GMShlyUhm*Fy}eJZLT@d?)pqcvXNnS!hVI+_i0KN6sy-V+E~b`S zsYD$tfPH);Y&Xl)!^<2POy-I?J+jHZ`B6|*IpS@_`kX&B3Hh+%bR)(dNlHYT-y1Xy zCYtVFjq5t$B`PXe)JC1uiQFW~Z2~ePh&rHfKM$v?^&MgH2Ep``HR-9_q;sPt$sAc+ z|NU0*{d#?rs^9t80-)rT##-pWVKyB8j_&kI;dw=-@~WOcct0jr7S+a-xffR}`cfO^ zGI;&0Z4ZcbcG#&By(%Evx9BfHk#>Hn+weI*P3^?Qhdv(bL|$1#`u6-2N#%@Yl{A~d zjW0Rb*}e;aY^DzjufBd6avRRTPRX2nSJEDQV)%<4;Km44BG9r!g$^-J8(|R=XH@HF zci-qiq3Z|Dk}~JgC$_|a#6b|Vg(sRTsCsb=ION|-K-^zy^VF7>FjHNH&|^~mK}RV5 zcK2L)G}D}+8jscfb79w0tfEB8fw9}30B;-hCWnl13O7@QY=joJxztE_&+>SZ-Kx4i zzJO24co=}x2XNaShf{!7Nqiqcri@7sGU=|k0uxdW#3zLXE5iQQN* z&PcI4)IldEsXfc!1m;Z9I1}Fr#s2A7GBB3E6Rc(lCe(wDS%-qE_#i`2Jh&9G?lQNa zy8}}Aawf305^2AH7=w4Ka1~@MdLt6VFzHO!swBYBonP{hfUSyu3r_6>0>N=_2g3?0 ztI8*gdQ$E4E(m*p-bwDrQzskJ&r|A{B;S%UwuA%eVB_w+G3Tv9@gk%k&pIYT-84N* zLMUZ3nKA{*%)upZh1H6F0uv(>?NjL_l~DVSF^?7+T=`?m153;ZGX>#5g}(eHtN(yb zlCVr3QFjdV1ivR%Z9!$DHrpIy76X+b=69%y0Z8C$I!m=W^dxK&R<0e-F+8*m{|M>QaHL_>kTf!lZGpi3RH8O1GK?vDqzXJtLPQuFJ`9<|KE1?3_B&`b4x#3gHbyFxs00xSwQmvJInRGL-J+Cd(uCn zaVBzcu19s%3_zT5;gmvgrK)$~HG~B1k`^6b6wZ4W{H}vhsj+;(^2=Kti-O0&jjsE? zQV<9SqTe?NcFB_E-+hM7d`>L*Cn^#>pd_cY_U-NmDULIhvde^hO~P4--jhkYv{Mf_ zZkfP&TleMMNN1EGxxovRX!NV->;{v)`RXmVKvy_~TRf^e2H#@DtYz((CHvg#HjvLc zNAl^!#_I^gQliyohjw^Hq+hx#3A7^?Ev921#oi>)>$|3cq;~8>Br|6QpCZ8pC1ODU z@ZsLMw(1=qK|zy93?N{1+J$7NwG@49p#h=na1kujVYU&R&+w3ohc}Cg#?2V0>qKo2+5M%m?zGDngOqataor6E^{|$%iZyu}!6_!v z48d@VILazZal`Oi_~_36LsEj27$Lb~loDeU z2lqqhK6o{hb>9fIYA`YUzX9rSqhC#8KTZ+I)m4}Z);?&9(s4$F;}S$_Pli0KD1Y!o zVMhPb-gp1fE=lA8asSK8;T{wRZyge_ux&=$JH#S^?1*Vd;U3~=e>h~r4X`sdI*C2C zOf_mC=yk^^>Zl4E0&kD$wMRlCfT+!YrL}}0+zUwqT%~v_(?A9{fHgmnq>iT7{a{`N zljI*Teb2-aOG|WJ?`|l#;=!*M>H>I6?=Tp|0A{|x0;D;sA^Sr4jpbDehzB6lMx_j`Y-Zeo_^P0*{&T0%-6-lwbUcqC}k9#fa9-uPH?&(BO2vt84lpIh^BU zM_06=h05@bLM2v_f8-mJcI}VaVJMW7C=z)9eeU!)#?b6*ecl=$OURn^8s8QXBn||l zgRCk|RQ%;i57!j93v;J#pTh`8Sd=3S6(2Acti9=b9+KQoAn`WBNMcCBsiTS`*Da_y zBgt&|+l>SJ(+!y30Uyx(+6RdcJ`O}L4xq50C8H*53z&&SanEpK&y?dFIrxU@Avwu8 zfBSPZf(J7}Co+=pLA(Eu$81rXQw14=r-f}-D5giPX~xrHPufhil$hS>{|;w5zK5fx zteBr`R4s5xAY1UNV}k5EPQT%D7@m;mOq*$mTWk%WUVvAb$%BeheVo4EOE2|=Eo+5@ zdXJ6GD00P$@R6?MTH(tV!%1IplM}MM0f)ef%2uJx#Xx*uA_av$c@Ds*Um3L`QSs|1 ztMU0=kJ>BeB8~4wBxk8!V%D2-fUA;CT*oxrst7a4gm!d-DUMI59psLb4o3mFa2XTQ z#-%Te;@CL=q#%6`n>^a5jfmJ^xZqdq;=uVQ@(WtyE!-)+FTWv;`8O#NvCf#5FTj@D z8w_)gWo9Zm7#rR5p|xn`)&9k5wSMYw2yjrEA`S+FMg~pYK0pUCwKL={{`uf>?HN`! z9|OrIUv}9 zF7<(a1wJAi}~uz@Klb z6|_<^DN7Hkg${v(Hr}^{U4}3I9uRLDToQs!mYt)bxcoI_Bj}JHPW|F!J*Mm=xCmkm z#YnGv-zD4!vJ3JLofL+o2~?ayG-D7fiY7KG(;mX84i7x}!(ZhWAt@9CtQ1xF$;O*j zOi=q*$^7}>iI5(&oq!J!`K8uP(Ah3Hm4CDYWgK4p-{0(kD@iKDrp!dd5zl@O*XMaj zfwdn&kY{Y(B{*o6~>^w^b^s8NY!==-}(XE$|;FEe^y{FnHt_NEgmLuRG(#fv-cbS0vVGZ-I zkaTH~e6}j64oOauZ{c1yPHF1xY z+M?o_^`1VfN&`d7XQ8ibYP+$OiVrTY>cochHID2UgN3#~0Aw#lU!{?dMWfNZJL^{k zkTOwq3-aK?L$iTRFG*?vbW!0Uz(adhku{icwCII z%Kg^T_z6C!!fgz-qI6Z?&))*lGh9P+=k(ig@N#ehEItHzFekU)zE|eG+O*O#p#EW@ z-l(h*SZdI2F1mjiD1BvP&V)n>=k=gOhE+f7Efht*cKQ*n$6~E}@eJ(?eFc@OC+3CG z4RK!|RxvMoyf7`7?h(Z@7Nz6DHI{Q6)ho*kyE?I+zWImLGZ}07g=k_?Bxw%$f_`pL zP-(FK4#yXk;4VyOELv!sad$5(&$*|r`emJ-ylCRm&kIg|E*`!qDsW7~$J7rmMr?aU|H<8bkIJj7>7nLa2MH?^grB<2CT!Znqqa+`@L1cdl z!x@K5Rqmjc==p_nym)vx)-jM?`ukwCxTr-0&=+Y6pX3r@Uc}#ZtQ32>$nAw0-9K6k zQL$ao#><|PgmW;e?;N5(yhATJTC+T~9-$DR*&d2Ls)}rPU?OTtVmoO@VAM*NUs<;2 z@{%5W@A=V2ipwkR6^N~g3e~rX9?F8*P2IJp5xQTaUVk+8;v$6(F_vPLh;D$3W^u_5 zui+?gog8Ymovp0hFzR7c?>-9wX(g(TR7q6t3o~D8rv=$qn-LGe68kF$?}AdHpK@A$ ztfz+=u^4HJn~(7&DdaRvxyu?EG&4rxyUW)>r~&Ne@)I8`9!n>I%2N12xo~1M?Fy{+ z%^MoI>_nkQ<-yHdo@XA3BZwLF(F68_!Wa3I89}EmSoPe~{9f-U}!T^Mq z>fWYR{!}vBOS~VoHwOJR)wI4(7;&V@13BnN?D{%UkSXzltCGOCE$*nHHCQfoj& zcu7Dz*r^1zZ7P5+7@{HdewkI2;8ZNkZ z-q6HQF1x`6wVNrpu&F6{oC(!CrcEaI<{h(Mh4!k#`d9mo_~=$dyhk89;%q9}aGl>~ za(9<$#<%Rge3-IuUocjR6-^{>tti%huP9bVemL{jlE3O%xMIA9OEyw1z3RmuKA7VQV%1Y@MY1mM zhjC{Ucv&wa@&)lUIiqS5$ z+zhD4Y{R%D&yo=*1GCIJD<^*_m=%$s3TsX)lR{5yO7>;VJLR7Ri0G(wKHR~@=L=rS ztM-v_cv8Lny@Dt#HcUH0#%MMD)4h+l=p49CHp+kgNay2*4(hSoa}Do~Oq^0Qxc906 z^Mg-wr9AmxFw-@fFi7#6enJ6w=Yo%knWx_ni_UTk$Av!Ah-I+Srha8QnN0GtYG9Ci!4xY9aF#v8;#iLzfnTehemI5-?j>(pxuFNXM=8FppkH zgTqAG+kd^Kvm>3oPN|34QP9rIyk&9ZemSGa?H}5$j_Q*|mdYwj{F3H>G_oE#+5$ki z=p{s5fwnNY)hm~v6RnR;Ld{eZv+9^$`F5bJOl-l4A1U&vb*k7JG1{6^oO9XE`b8uZ zr;E{$U@AdW7&`&>49!4sGeNgj4HBsLz& zMW+*XE}AFA8sX|vHx;Q2t_G&mF>Q?`k-ityG`T7_@3YF*selaomp|X<@Wb)2HjZ>* z8sISIp*WRLHh(y$OK(fVIIpe168iokxjn@Gl=*AmRuH@n z{o=yAby5|}P=u8vCG4-?l{SSeC~Cb;SVJ+|NKnogC%443zfA4V08kkoCe#1e0xCd! zWJ9$1#WMX&*Egrq*a!$wdkFXF|Ld941U0Y*LcsOw@BufBu4M<`r`WvrlEg%D<^&m5 zhEO!A4Av73qKQg`*CLTK1M=!8X+4Kl?@)`p(bhvm?^-rWQZY1@lygt$Ox-LmW-$w2 zV`$>yUzCNCSuIzoIq@wGaE8^mC)`yb1q1nqaX|5R_#7%${p>AP@7d5J)Vns4^SI_g zsN3e{iUkE5h1c8LdNnN#^xw-1Bzc@w|n8mw~8|7PTU&>-nL7Do#D6bqqKYK5tAoamr zOd<0C3(CB>WV;TR`MCA|Zd2^XZ{^QTr=5;u|npBC`RoZxu$!H5hwUDckDQZ1zdexy}jvm8jV5lIKEH6Z}|v-Z?(ca z5}%Q!laj)OxNT%m@=2S0_97sC05Mr4Q>rt!Sde2U1zyr-_sO{i;5bGf;h(yQ@$1Tl z^ephPo``2=qNYR%876QZ;g)VlZXmx5vQI2DcYev+|W&%IW>{`-0$1eu4Re zRAS@Zk+WtP1Uu78cJFnW)o$f#2`ZL7OZLztfWG`M$73z6!yQd_)JiYUI~QEMsLuZE zn>_dQmtzaZ?l#vuO^g4K@7N)VNlxzaDDsFa8b8Oqg+|desKBVO(~bO!Ma5@ay%OXV;Y9)8gVVtQv%afK@6<+ z=cA8(Brgn}%@^PQ2dw-kR92y;0s<1q{vQog_Kude&i`$on)Lb9SRaW$x&A=oo8amt z9}+aXmW6<_!($A0gRW_k+UoE+ei>_mTN{aAj(1qm{Cd{V|0L49gFKkp%uE9-xH>C4 zJNwTu_tnK6NfA50bH%S_hk)Q)S_*LR#&|13gFn-Le=kD{iO{34I-~e{=q1?uc>zzM zLh?OJy1C(%p#CFuiT5t)2xv#siLJFlbnj!^77DK~*mb~$g0T7XB1hD&5 z2*kh@v4%^lQ+WtOM0$`46r*>*`-pr=Zz;3#Z^BGUP4)naRXO_pARJ=h5x<(^MJao( zHe)Me&UEyhyII%dzy-D&ss);-GLFwa?QZHyr>g9He>d}cUzEizryNhZO0fNi(N5Kx zH$DBDrgsusv&w+qxA0rC-*^-u&M8Ij>v%j1K9raH+O$i9Bbo z)N+}(aMLz#PKj=6Yqi_qQ|LJn7rrS0opG+IzCdo+x1C>FrJzMr}wUT8yCBFxyRkNx6G9-%ch?Pl%8em z;;~6IwCS22JmHbQp0oR(OiZh1`r3|%&dBh*Y~8xq&aSQUyqtRC6=Mg{V9kH)c;Nh; zrXbC<*kkhxUWi1%g5BzDe3+cqj>IecH@t}iWQ*I9OGa;8k1X-TTzOSG0lhXsx`w%& zwSBaIR|EGXwX9xw5WE&Erz9AhmrTQc0kAErE{3K<)$B#t(jTi#KU<=&IsAj%dE{H7 zrz{`TtL0|IxQgv6fR>qpi{ax~Lj7{}DODMUD(AnwUX71eBbah8e1+~awLg)LsDiNu zywEj`8BV2rk^> ztkPHsE*?_q2yASO?IR)w+i{8_D_bT zl-aER!hsL3L?h`6)l8WbF=y!)36+E&s^|#xYzUJDHb8ZKRH`t-DvI%B=qB>SP&pJO z_MtNc8!?Bt-38nmT(`(26(b~;?aX=B%B^kA-eT4`4yvEpZ;j{(*m_&5S{>+g6?5A~ zEe?}%W_72JaIeht!4QuC3KH0FW(}zMeXPczc?^DgK{x%7jCCHb?8?87)W5>rZDu{Z z4R)VDEVMU_Jzdw}pFki&v@f!&!E)GD;H+_>UiDrDXMbM;_L;lOzoLW#3%~7i3SY#f zAa?`abunzD%lRo24XrHKKeo49*c_&b#l~cVdvQy)ed2wiV7`s{^ra|-$ z$B?n(!A1@Mve6zbj8EL8n$r=Kpsw!jS6Lw=Ny`j%OAtKnA9(VyUa*%0iwkX%l>-v3 z@}-zM&;>-(cu_q8lRqz?t69=vxihiP4*E;pjL5`%8;?I;f*{0caY7)rCMed#QjX9= z$PX8F{}T8_hJ*0cBjdw>u^fkMMbi>4=7iQt$+i!R9+c_dlQ;;)Bhp15^Wk6tMmAz<_vXcV|*vyh?hIiSwy2CSw~_HzF~?S^|FjzYFLJ)gJ7uf-QCs zE=Yl8^#?KFC;!HC+1NYiktca{lhvl$7>uwJ_+$`i^4|lYR)WsEz9j*Wx9%Y8uc%;P zlfXBt!9Eb!Yx`wTSVr0I_E$yRyStl%yUccjYm`}Fn|?k+d_m?17T~^|q@O#b&JgM` z=sa#hrI3C=Yp6Y9$-+u&qM({MU}aTpU}R}>F%VaA};} zYs*UnnvP=Y*f!eYZw)z@SkR;%!CURX(%=@_jL|0&3oUz6QQ{llCfC6Sn4XUFBM#o&n6-E z0FYVS&tw&**3Mz??fqg0BTaA+{v;F^Pbv9WGAj^REwJbnS7n6$BrP{*>*T z%0jll7~`s3(|~^=FSD~kVCnOEiN5N@@e~u62FQW78tJu%@Y-Uh3-x(x_wDYSF=YKy zX+IKa*4?H3<_k9k*R}n|gem4v`4&$=pRs9Hyl#w9x%w{HeY?$JbBD&$8QWP&kX9qt z*25^=6TTF#=YGbE_rCA`cEXR8Nkm?vXZ!X{(Y` z?ClLX>|qfHZn-)|zx1SG=WJ*(n4WpZwRX=rM~c=C?+b6&zKD!lj3iCi=Z*RV!(gli zQ6`NUr-?9u6;B5SOtB(5%m%;}Mx2z`P#wp5d`*2xqTWEP!irO*J-rmigMD8P=S$Nt z1sT2U6?kcJm8dVayIIu&^ZGqn0nY&{3oZd>^I+~)>B{y2E70G>%Ej6(DE(iY2K_;l zA5rkM@9==%R)!#9Xr4IY3!bHKZ=>(7=+i$|^3s1>xCt}+MLbVk;QOn;#OfWki*2Sa z8a?mMz-&0=7e>R^UX71aeKA@<13Y>Z9O9|BXruKzi3QI_jLL46TMSiO_Di{IVlN5V zut?W2F>OZt^+ZKjBFx>M4|Jb>1nMBFP1}Gr)gL{5-d8+kA!B?R0ohG;-&Q7xLLs_j ztBs6#Mgu68l}Oj4bwJh?I}yLMF>9PdYv8_OvcBlwGm8gqpNmwkmGbqi%+qgKt*Z4= zVqcbvD=W#Yr{*6M)3zx*-x?lOTcVdUQYf;TE75R%r+2~E&UJCkodiFGknZSVMQN>B2u`WR*pDwf{Fq;PLEWD zYr(t8@R%%IADA#_sP0T;=Ajz2^5eggr!YHCp{?hA&WiX`>B>sUdF|Mw!ao7d*Gu&! z3O?yrap9=6P&3~Z2BoK#rpk@w;To|M*Xj3f3TADbH1zvv+5=K^EUPhRY!rwSU zU0y4N7(=%jf|2kHu3Qd2fP>&3Xze=eVm9kM2x)^-6CijrP!UOJ>@N4Vv&mkX@)tnC zo`pV)a;L68_02%*`8y~8(E5sr!uo}WS7d9+?w{#;Z4M3TJJ*VnS(HX7QY!-XyOdZq zU|J*heGzy7Wv?9@;}vi31nN3Wy0zoDUXdFA|HT3Zz1)YNAL-5Q59H1!T?MO5t&m_R)Zg_9$ zNNCcgK=e$Go+NkcX@2`Uj~T+lUQB6MLe%T7f5cVp8;6gh!`17r)7&KKUFRd+qRT)P zZ!!XHL8tD;Um#Tj0uxE~5RVcJ4w4q4{k-qlhsjAY^^&Dtk^#x0Z($%Hq>9sTd${=P zbX%;|p#!u#@2ALmS}cStGf&%jHji3EG?>);2&zpAHMO8SjcfdyRa&jhSDY2us7p!P z(b_$S?G>Xzr#Qe@4Z3%Wd6>Bw;OSiJLn~BPBVBgr<}WRWCGUy4@z1@RcrCk(zvxH` zOr}>;Dll8WDd0RpdNtrU&sdZRbo68T)CW?8q_BzQ>%)92j1uD-n{#%_n6q(fJdh#C z>s|{$Vkr{*5d=QGu8DGbENSw(w7J?N|CUrjtPZOftO|xO1+~JiY~6&p8`=)t#e;== zwtlRc8ooAZB}bwe{uQhV_Cfe)O$sLf#XHHjI8xh>-?K|SaD2>tZe9GSL+C=kv+|bd zv~>DK;y4)~lvl(_tSM@IWZ%6)zcxlipFhK{Vv0GvAWeE|s;UJME(U)T;@us@i~?-n zZLq?k;BNUS;t}OSAxNK$NfGI969)y{U0WO-E2H-JRBeAZiKg*24TMK= z!|5Iq1XmHJz2vKCqaHRYVw5apo%SdFx*8EId@N?iIh^^cr`Bi<%KWtv04-1Ao#08N zZZv3!;33!4esk1W=gI@+3b_|}Y>>KQtrRu+2G%@{XYCAx_J@Lec>`hCBp<2JVO&S! zZFV|pY|Dafb19C6QSrc+v&E?ha_3IGx3-y|zr96Os3PIg>_6bDQPvoUPM?| zUViL9Sg3)_OoGLgzCX6uorR79@^{eya+1C}q&CS81u7TuH`W35AbQ2;CHran04e$s zou0M?HxZPO7L|rW)_mB_%B0HoxRLMXTe@Gk6;YP-GdU0B}2PD?l!K7D@0Aq?zbPy3+cl$pkRl&1$251BotTn&5_c+yo*v|D&aR zGKX|MA73;2&D!MUddum_ly0BEztmi+wU@>;IS9gVtPwnn!Fa*C(AY?z(3$LRZcdLb zjx2#&*JRJGMgx7f71CZb ziDp0F^)+MbU6v8Yd4gq!UUX25PNUxGIFT@cytdcz6v!4T?ZSK>B;sdMNvYJ;r>^Of zm+L{8B}`79h$&DAoz3+fba(eE>4HUP#IJ87pR`2k*ZIa*ESoKLZA;WCMq=Jhr(uc} z(&4u-PsL{;;F`#V@X}8Kt;rcD4=!LO-sSs^@ zE&KjmBebcLK>JK>UL)UbL3X@Z(~YKmx~lo>93V{n&nQ|jdpI>n5ll+q-P4$%-?DWB zvm`g!tgqSk|9(;0DH&bmR* zjxp__FK4@-!_MoJoV05b7kFJRPaOx&?dAS{XuXEu;pKGlUOe7cTVRU#H&FFiH`%jP zMQfmT4HMdkFy-ddVAqP&!pif3qU&gOXN%!Fj)iCamg4oOf|*O?+%DUgCu8}`(t^X` zxxLS%`Cm#!-))6QABoN8rn>|mM>h3sk@w2tuLjZ`=@Qe`8b_wIE;BkhVfUgj$JxLo zh^vdsdIuWd`ebRRS)oZ2V7#vn>tH0JntBoAWCi(J;ik!ZAFKrAon%&fR`PlWj3!w62 zYsIvQ$)OTOJrLE3|8MUw9dyu#jf`Vnky^g6K?|zhCqc#9uX*j zJ=KFk;DDhF+dw}=Y)hd*$r>e31{@}(Jpkog6(F$9qX4O3*lYQOmZqn<^nGx3;a}VL)IT?iw`Fn`0 zl|*nEu`EUaJx&x#N$vDX~~BF z>UV`1C{?%0^-0Oo%-}`h{FCYk=M0ys-c)Bf^CVy8A935VB|u+I-174{EULdZFyw5q zskag{!E;XZ+dF*MO8g-ooGlFR{BnX*gyqR#wnR_&>%XYK?DDIiq!Mz`1?usLp$)9m|M=!U^q$#mJ89MdDXPbf2_gjuSVC>#GG`x#>Lz}MH?QTh0?7yk>{;+ zk~ln|3pY8Z`^-lA=dWq8U(X-#bo9vAalr$8HbeO`UOoI~EffKcuMiCaZE~%PQgv&V zUwwa{z|AK1H}zUlntFC*f)x;P&u8@PP1R4(Jb^1h4~r`DhKbf5vrKCfVhsRAAlrut zI9HA?c7XX6@Q{Zl90>P%QhXYuClZ?qk_op`D`-AleTozE0&5fyYd=B?C2P60^njX0 z^5icNF;aLSs}9gE9zFK{Y=vl&?eY>C*4}&czy--va|79nMti%Coaqi?!0#86qEkQUr4#bD0Br1fx+JjBOjY709*kYxX z-xOP=E=3MvabskNcgF(&!F^G!GpJCLayA&m$LS0V8p}?{LUNpgF?1Xt-YgS*3b#RB za%(ETYpfIkxq!m@hv|iX?+41ZjoFpm6zhKp=yQbaTHgY7JYLlGt?v0li*PucLjtCTp7d-2-kXB7XhAd%rl$(gS)@?^o9idE7Vr}$b(EFyv+#?55@`fkiwlJ@)EY_ zCx2Ieck^^E{r#~b#W~jek$2KXop3AO3=AXIp@#q7+!C6gOH)cXM)Ge!Y640hpn-gO z0NKXQgbnC%Ie&p?<$dY`RInS@1Ei@lh!$JvfQQ=rSFxNF(NrF+c5w|G}#c$F2^yHtgA>z3})*atPxc-B6tf zBaqjOH{}b*M<8XsIBha+%Y(01pp&e&k}=~#F`XnxXc!_Z4c9y07xjq>0x0Rq6(T|M z$dLC*O3{$YUW0I9GUiH_^#U85(c;|9;a1!_P4K%6`!8#h5Zn*qWb|yCAOl6rtPLc| zS<``E=9R?d+=^-;`0s>Z#You5%{1y+Ckg{GKhmPyFJ;L>4fI$!3#C12MI(XK=a=%i z^5u2#`8%*@Ie`hrRWK_GJn|?g4X7_!2fE;CSnnVZ>3Z;Fp~tJ~zZ z*K4lLJb@ix*NqY%>v28nlR?F9{hO`JAx^Gz!d7rh{N*+ReoXUfwvAHQ)gi@1@VX+L zGpKWjXL>hY&pjeQT#sxZ)ZUAWjw^u@vtV?43W>`5zRY>yYu8$J?*Ba&mJ)@nsEbB2 zIB4TU12!?=5s6oG+N>1g@>6)+gQUTij0#&F8@ogAF=WgyRc@BseGo6cu2DnpqoD7q zzmPIB=#0#XQvrCld0+1@zMiYk5b}>I*;dP=XzAfRX54fpJN|ll`Eza^G2FXls(w=k z*_S2lpi(E@4`y*mFvQQ_ZJcoXaIyAQW&N8h)C8j+qOZ&S0;ak|=3OyTD+!E6)}nN( zYKC?B9jH15u%ApOPTIj!qH3wa`S1D?W2tGVx}N5Ltclq4ZY~aGTQhJ^fS-T5^l(>!*_23xWW8&0|jeJ%S-^ShfXmn-KQw)YZiG?@-q8L$?R@`ox+b&pVUUMrN2X}6&y0^;(1bP-^Vl6IAP1Ukk0s4H*Cz4)XxR2mgM z&s{pw*!}#%AQe~YYojVDWhvJe1-`F-h5NjcM3XzPhB*tEu#DH&nlY~eGM9`QO?NSO z0Ci*g`j>1iH)85dpYrxX@?ztzi}Rxc-^`o*f#IS5=ky4WiZU}Wf1_d1n zMQ4_2q&b8AMfuTI5oso0m`gX2X>h&7{7nByQ_ERWfD>4w5WhEgZ;gfpxt2D2WjiG7>JhjYmZ4tvzsPn-LXKG{xG?ul> zBCjS<3mYF+a?8dHLCnjZ#ydRI-bQ40C6?&%6hLB~Tpc8I@bFaCodNUw5$t zz%7HYWT5}=ClaX&csR|rl%$B9K7N<}#bGgF6w5m@`Je$vLWMMrh^S9x$D2kwJw~$l z6U8i8oGjTG_R$>l)joW_pj3&Tt*fnB#b4oGy&V|jzxc9Nh|OP2ejBmpv4shjUu)B_ zfhIiSm(E|0&@!PK?Csx%JNH%2O)b^1WZ9J@noFYO)aq5#k-zrZxMYFW^Zvwwovo+C zc-%I1Ij0paMG!I|oBf@+E2o_(I69jw|#_GLVE=_+EG*@mviZtYZ$ix zU>wzBKqRK6?9d)HtE%%9&e9&V=}Fa)q)3mQi?*$FT%*B5d&7abw5K9J^{jf+?@w9W zdCm$~dP}QK-fbx9j-RGOkk-kUCe1&&bH4)-nCf1C;k@rsuasrJRcCiShG+eQFQL*g zSaXtz|Asb2BdRkn-N{|dk_r5hQeAidkeaD9;{A&`C8x)kw-ppzL?aGD#>Fb!$3ei* z!OLy4($L9H*ga9xurYYAmEB=HrS2;dafmD)w}xb=?$$K4WN8)}g}>V09KSvRxIL@n z;~lB7g4DY<@b~SG$|cex6Mgvgd)Ib@NP%0L1XmO*!mz#y44o*Mk-Db=QVRjcz~|~$ z9niN2HDbkA!3nW8OpiAr+Sb@UlDz&dMhiz*cuhs{i|HeKyWs}Kh+<| z(c%O*Bz_m&QGAPYp+dWK%3}ki315T>zS_L}?=A$Gg7P&E*7aWcdZB(mjfFNZp#Qkn zr*6w5Un{dI@8S5Z(3-}=gdsO5J(|kggHGyP3;FbbTWhMZdo>@z9=0dpm(nx`hBXQ$|k&=F_&g}m4fsRJ*edoufDk0Jw{^cjBSq2j-uPfzt| zV=ak>m8IdyQs~~IkX~XjVu2qyoP>B58i_6dwU0Giia+gkQKL6U1t(rHRb4NY8a-{( zQk3V#N&|;UnWKv}C_R3s=g++6O|RC`+)v!zChU;TEU7s^tUXMR&l}J zvEjv0rV}{I{)CS>-^cH|>CvaU&8j|&XDJ=dKc}tnZ8jV;?7Q1;c6_CggmLHK#E*pz z3$d&Ch*|#0IUfoYe`5K@a=*YlWc}5Bn&j&@85C4 ze%gpMGVvNwZtk0to}ef0sokj$$TMgQ>?g#M!28;>XqUda^Vt`Fyb?ma#6-bp#aDYW z8wqBe%7}7mqx{H2-w-Z*ei$kI0U~q(DNUd3Md?(!F`NvClS|B1KF)GWGvQBw8BDrw z5x)}@^*-3SNHYY>>M1Y7rDRt^HuK-RlNxzzPVh&0{WdvLAG+-`CibItGnMGbTS+@U z)+WAUQ@>OFL5f`6Zrlx7lY6j>epltDtwwFx!2H7nKbiIG-M&6h81x2xWzj#kNb0Ab zw!Bui?F>uiOy&8dh;!2&wbV4W$N*$uyk@1^R3FE|;fNW_OQXvcva6G-mWfmOIii7u z<3v+b-dM1ez6KBL6w$J-|DcS?3rwXGxopTnTcrJY#tlhc`%9<#(?7@Rxx|5U&OluC z4QKCCF=t+dUEv$}4R<2612gj7)xS_N$AoTLJMOCbQqSRe zQg37Ds!ntQY%sc%EF<($;WI~(IFIOUQ5!tIe@OGXh8Pb0PuIGLY^+S6&16HriU}}) zTqAvgc-iXmkU~n6iAGPttv?L5@9cIiG>6*cV=rKO5Z`msGR9Ve1;k$Lmo26a@zbC- zCII>N#Dh2E4Zt&#rX$pZ3oA}bpwywKl8%i?l`Ew*yiyxVfEeAlFiT&1tMD^Pp5LZ0 zgXP|@y}+0#g0%^dEB?w6F7K8Bq4CwXX0z&#qy;$F#XJiEX?Q!@N!8g+-EK~i>X;Qm zQMR=IDwGnL_5w^WU~*;IHvT0jFOiR!M^TpuBeiinWyJ|;Dkv75NkU8c5J78a z$NN*m9CH`^Q2Zj?O-&qH*DDcPCeT06=6>V-7%G4u`lj>z$4@DVUsN7gY~zt}Y9I?m zWy1h!ma_kTj^Ap1(>>y~*KCHbs7qe{1?;TYuP=uezPI<=VIzfPziDdo!7ScZ{`;d; z7IGwKXKZKn=l_vN%s#2E{NeuDK$(Gn*!~;HrL%+O{{mcIX<6HEj-!9o>NAalG@w&H zyDbz3Y|#lwH_NJ|p(RRL{R$9BCW(e0LFP#55li@f&h<8zP(;-JvmRY2`Z$2-_;=Pf z*ZW$ctgNsIBi_@Aoo1MU|L1cptzG4uK6P-aFnRQ>!eLS6)|k$z!qkt!*ej19)+GCs zSl%vOw2&FutU<$yDoMtoWtwE-W{X@igFmWb@}!fDAjybaWwvjn@fVddI>izxjHH-! zNCz4$U@o~Zp+V#5oGOTTm$&izALWudNuu?ZV}Ur7F-ei1Gn##QFj5hR+!>I^Qv-!i z{Z^s^wmK?JseUE|LhY(o3@h2FHcG8EYpNDvIxmNe7)sHR5gt07%(y}`=G=dq0Jdyf zj=h!+eM7#l$&p^HMi-g?a*jRri>kSSmgPXD*732ZJvD`&Q3x6^;-RioDUjMhUCg*6 zh%-8mtVvnwA>g!5s3jW>DMgT_Da2qR;u-1-O{ODMS|Cr@V`w2=D4V(g7=*^N=e&*3hDBf8++jZ2hDTDHoE| zg8_XXZZ|fxdm9Z~l)WH374@`@Xk0xcyx>}!Bfaj?y~_=yWX|JMC+XfkOqll(h#3Q_ zu7d!f>(+G>$LEE=#*f+)I2VWeK~J;f3KAY4j>dsNbNlkP{<0pb$L}CsbjNrL@kMU* z4NVYKis0tHu@=m?VdFH0A7dxM`W9TYfRb0M)6Gx((zu4_6pnb~8uZSL2W{SHNaHQK z+jHreZr69X7z7Oce)MLCI`H75wRg8a4u!{Uwn=3%A3NmQkUL8kS9?nzvh;PD`0d7f zKk#DnUjMYI+5Ik zibhlUBY3Re+^$PbRS#=XjPbiV|4BCcTbX&rh_i%4?|G~LDLB$Gp1b4dXIkF>RJN8p zHm{y_;wZ3+h$niHZ21dUP}A+@<&U=g_4usvwec)$j{V#W%Qb8R6*P(mF+iDgEybUtxr^rR$C~r zgH(f**@ZSnk_0>1 z|Jblq5ZjO@u_fq7fCAi5W^H9XLYrPtLX7-Pn~}a(z6g$F7gss^%a90aS<1k32O0#X ze2n)OK7~bmIwn1a3)S|F!%|q4B-*!FK_VUo?_a9m`uPZuYkyb_K;45qtg@-NZ z=W!cOOue%LN(hZ@=`X1il{-C<6C%3 z3wN~$2DLg@OSI1SZ+r9DRL=$EZf-2(L$PXvq7-=MZE%Ts^>Zf|`yJ_@#Ech`q(4Prg}~7vkug=QX6Cffy^Pt{b+9S&};7X$yd!11!yB9J?lci{e~OX zEF%-~E6)IXQlW)RW5$#;eLjtd*`Z|&Jt)nB|BeoIxE zUpcVs6y!-F<`xGET@1WlE)X$ICO~wWmQvj)YAm#QdF8r>0Jf+5_f`U0R$~B(>`+@p zq5^2GkTZKiPhQwa{SD4{z&hOtUp%)I-=iJ8zGCLTXwjJJuS0VxlCbKi^Uy^O>-7%43smjZPt#m zMSn6gmDDJ-ljOb4*NR$<)_c12EFfVDE8j;Qw`*&zDAJz!`TgL+P*X5$(O5&)-@&j8 zzBv$!ba;6?h=@$>7>2E6ej;F?WI!#a$Oq8~`~oMe;@E^tI@)vE(0lw}XFn`dpa$Eczx|C`%W1 zl@~ofHK$Ei1zm0s9?#gV(Mcs_0;32EMI)q^-;FLad>78n*xH>%lbGkv@ z@sQPvvnR>MfK!d3_)W2D2A7=(|4K%j1*7zI*H!bk*3M-gga^JtnV=4&`c#+-Q(M~cS>vGKLdHNGlO#2Fc>mQHF~1aD<;l#-D>xyxHa~eZnk{bqH{tXRlkp8g=f?Wmrd$zvJAmME9bbkIIS)uoDe#orO)#vou?_GU7I@!3kg@_@IIC2qgPk0=!Ip;<`u)!Yuj+c%*WkHx`kA`2*{*;=C4m+y>$mn5?{Ks=+qxbHS2K*r{a%W zDaL+6nab{`0raWT7nNd9)_xHuUQqBOO^ucxml% zkNi6f6s^QwO)^;=YbFo$?3X@@nEgEI!wRdeLTHu}%5(1)A>tdiO0pv%*>=Z)_xx=B zMH*&7vU3~zE34++a%oQo93W%BbnSaA&I8KXt$-MFFvvnobedqNlYbp%*H9g*ZX{Sg zx~~Vr{zI;JRegiYRC}T#vF+x0Zt88v`mTE|GhE*q!H>>QW0JGI@a0^Y=IzEK)k$xX zRzEtg*W-F;Nbh-ImXO8$XLlx6o1>ZT#?+&k{$>pCeUbCA#G}dfX3D`_dB<9|_2-N8 zjRIhpe;A*D_;G#d|NrjHN~r7K51@g7K5>D7c>bGg<6`RULiZ1~=<>f3PK}1G{ec9^ z_iP>Ij6@R>lZjgkMNSexlXH(W4a%VvU{jn-J7y=LAA`F=E@Nl*+_tN{&4vZ~&^i`A z?B?F1&a1jzR<^7@bs{rM2=jh5ljZMrCRO1{JT6(Jck!4~O-j_0txWEe$Qzl__mD(m z1i%Dz>!T}`pp`P!I0-VB=+rbyoHD#H!#9~{R@fxEThc{CDgnOh)WDrJ%Qa?A(3s=t zLjn0E;~0&UA~I7lyc1Z6Bf=Vc@j!W`iq?QxDkV!=0Hrzcj3kF?bBMki~TOkoVKDbP0ckd?gHaBz>Bx9CQX#eCH9XT{(E9BFbdwxYrnZV1K4Q zwWxt@caRgVZpMIEPG1SEGj&ajYO_{EGgMW64lw}?4L04NkO{NQea)e3fBiVzIoom! zE_6i&z!QfatV&gy__RlNi77$Uj#e6;JM|dpOXel$0aA<-#WJQYNEy76R)uKX1JV*p zSlonYroP{&ncwL*&1yD}shMIg8uAJHDJg}{D0XV**5tz?2>DALeth>`iNAFR+rH;P z96txBw*aQQMso#!?pDX_N{js3;eNjxZ=)Ef5B^)NGt<*p?U;?820?`W>2GTn@#j3$ zwPzljuA?oPFoajZ0P9$vvFFaCnD?Qxer#P=XdVmJXTZPFnWN9;la@(>yPDd)Pke>shIA_ZTDNa zzIDb)r<+bP?YZwYw2yiT(2LQ|px7&WZ%Dy&dEJjN*Kq0Xv(OXn@8z~LD;@%iHt*Jt zfwRpWPWZ80x2@%-7G}_?wq_59z{7gbIZWlb1$q~;-mA`~$eS2({NYcGe|ZL@9P-cF zA@b(GJVVgsKArhhP_$68X^p$9>sI%iIdXlw*VC)N3z6th%4TED5PMlw;A|TI&SsCr zQlvfB#0`~ucn2X4D=sE*sj@jM7;ML-liqcCPR4D`|W!6 zr5BCO+2*dSBFCX0Vy+`7FAzqLL@K2QG>iElbTm@&z3J`IAkH{N3X?HiyEC!y6dFa~ z+4H0{yQneE;ifLU*~ZJyNZ$}l^JVsZ&Y!(L;5zRG4FZTFEDX$F3~5t3ZgTzXeHI1Y z7HKc{H|mx?d18TWPq5sP(l1ZUUd7eEt- z>cW&M-Ep1&{%Z68l=`vD$wdm_ol`uiKysW-cta}m9Fa5=jwF<6ynadAYgN^ME zdkvD4Vnq*&+0gaK=A^@C+C`|RU?I^F>P?HXL1N850zoislUu$ zRf`Unz(1tH%k>IyhXkd2`xf{yzN)>VGUhd(#+b2=GWAAPVAu z{rA_@6mGDn zkc6zUF+5)5msF8zVqkv>GUx^LwrY{oRSd&f)wRgJSvB;3VmDvKi(-g{n(u6C(^+Rt z$qU-1^7&E~d66l2WK)g#6hE<7pXXs9vwQ`pz^W7cwOe!6QIR7zLk4^g2k-M^? zs|f@#QU?*LA+Q95@DNl@GvdfH%}eC6`3p`K$5&{TRZH=bPs)^TH#vx5)%d4zUCS ztCnZQQM=zrSKM112Kq{pNsmgPOG3oWR2Z>Ko`Xmi`Ua}fU&FdQL5xqU1@Vr)mMk6t z^4xp6#k$7ZfL!ZTlzIp!qQ5pJD{@qgi4PaXU1q z)j^u>f1~5b9-FIh7LLAL+`gb&K=IK!$QR7zA-+voD9jF;yUM`M`d7DmU@7|yDaI;# zB8$a`fd@B;!B$8UpBQ_E_}~4*A)r`C^1!Qpi0mBtK#4sVg;Jcb7U|CCNds)yIx(O znGPANUYte@%hcWNyJ<&zw6fPQb)w4Y=pMrg8*H8y$~A`oGu`JM)XJJ?Y|Ps9x+D3= z;SY8hqKyEcr;5CXT9*#U0VfM4bBZF7Ep||(>}E6r81h_lqP^J4e@eG&9hiOwRYWnF z#u4XB;)=cQMp(erd^0=qQ}Hf#KXFMRIi15fIjUfmIrU@rXa9{J@ruoV*OwxzQNky8yRA&6b}yS?IrA`@q!a{d z8BvowYV?j4U2ZSYt zASP46R2`=#w4;b2@_=4?#WpM1xHgrQ9j3b$w}{%lsR{gZF=c~#LBrIEej_y&{!++C z$Z0TkWu|RCm*Pz->gG*sRbjXBJWC|H?(_6F{OCIm*OQI!_9)_e?d@cX9m3JRYexKV zCtr=ug+c2y)!fluyy*o~+TVz~wL4QKdEzOg*asLwe`3=Mp2yQiq`$yQl=Fh{llj;3 zN|0^f-oZ9Yw|%D&_4?l*G{@ju zYYZS`$w0N{LI)T9Y8Pbhgw%5K`TP#p@BIH4)r~FeMMsSU1cc1@U!uBQJRM9;{y(aF zTU-A>Riyu1nFZM*{513Q7H^IOTN0?8Q6!K#Hw&gE+0?r1E&O`5ZPLEl!**R|=cZjh z8)Ncj@+>0Q<$quW?+;a0Cx_yz@@iSEUb!ci_IZ3?Ioo6t4?!$62%YAH{LID;25fvY z88a-oy|+j=ha_3yifLsFE;-_o)1MqB7cotgX8%y#pmOe|ikD@$Y|@LStA=%oeCCo; z{>iR!Dru5fGll))IQW0dvTHm#WA3xVZBoe@6ruF*JMxAgA-VpMx^YJ4XeAC92PLuP zh^2ULBv)^}`i2ZflK=;_5<;_S7qsS7bH006mLE$;;DnN{zj8PxiUQpC98(&=k%V#H zCmq{|FsiX=KP@Jf?08B3ZBJp2KuO@%26hBtk}A|cD0lxNqcY6^yC92q*0=p5z8(*j zTWoW7!V~)`sz#m521h^)tP3IAjvQ~nh7$ipCf>?Q0@6EW-VCXj3q4^ZNH58v;Wbo> zcLfQac`pS{zBhHhzMDF^>5QZ zpo?U!)sA4h;p!K_c_?t=#$XRU^Go(Cr|&^7a86Q_5+j@@_A)+uKBW@ffc5yVX2&gidj zWMOsWOmZ{WFxwSvn6&p*AZFye{6%DL^i21P;Kd|JIplXP(HQp@FOCI?xY6&ycr7rx zYIxO8{zPc|0PG2w$`Q{VXWbEBJ8?aF2wbtvbTy~8>q5WbaG7vGfS;U!ja4f+1&XeK z7ZY&99v>%4-7HpXxfzeTh7D7kl$BAb>*jVy`=;`UE$+8^=6rDvBqdH-GLYwB09AaWXv(G(W_~A3!H088@fxV z<_BX4J9N;uB3wX}F4p#0*NcT^q!6{~#0Ta~&!QGagnVOEUDkm1<4YQ(*gdtb+=#)s zXPw>MxaNsAecTVvM>EEqaP z^*2By%v>V{gw+w;=GluLX9_?(SL;As0{ikVL+hJG$`KJbQd0&CwXN;EL1=#OcN5cK z*9MzM%CRn+7T!ZZ{V>^MCj9CRjmRS72<$8fB>`6u{-X1Iz_5zf>)%Ie8uQ9N4_=)M zhTM3J2~f2OnDiI=*x(Z4N8*0O0cOoqGDF*p<%Dj{_;C7A8BOiFBu1ZL#4?x$%{4^< zjo^Vu7)D$KYk@kSMT#z_LcAY=K%+2E;}ZO?1xbL%M-9;!(|p7OMZLYq>(Y7zXGNvv~YM3NmOL9}JRQ zufE6yf_vHmT1!GzK>H;al5~8kh6`cB$w7AwKhqcLZDKzdhb%mdTVSX}!TC?@{O;Z1 z&!O_Bs;(?QG5KqMV`ea~ZQ(E0IfM#sq2tjb&oRrtg@#=y*3ZxYKFS*~Uhq7=hi-+6 zd}R*gj9}0Ov^^M#aoh@UwDt|RQG|=1dsy0!4;-{?XsrvlHIK+fiE3h=1fVph;`DLz z8-;iGQ(7{6rjOK=`+Y6X;9qCdUW=}*Nno_1`9SW_;ETheb|W)-@={Qpk-hs)OdrQ< zSID7+7*(lJXsbC?=^NVTI-#(f>Sf-wHCkfmzF=Ws`)}A{z;`uWTISC7=aBl^jvq>+ zDL3Y+7>+mQ$*jP)8TN4XFnE)_u*Tc}KusU|oa9Jp)ku`VrU8{pNUd)Ghqf33z95%B zLV+sm#3bXs;$>ccndA*0STF?a5(-o@G+T26yKha-Netu;24_2oyCU0V4RLCu6wqPk z20ndThD14XYYqcog1B?z4I(kxNo>T%`&t@Aw8|Q$e{=jEIWVGGcBSe>R|S>%JC~uG z2n56pN$- z)``4A=s!LvT7sfEs&Yd1ra&Ft7?Yx>tlX6kjcKxh5gW~n$nt}3z#p@)R@16P$~}gA zl0K8n7;)je_fkNm4K0vYMWDeIdvh@LG9?_SSsEEvD;Bei8L%G!?=mJ2PFe{fgSP)k zWigBBWH>@YSlNK)Bu!F%N->2V1_ub0PFbn|H#aFf)j~U%dQ>QO=x|CbKyum->#alx zo-_q_JkbAZFGxpQPRSjz47Nc^{13k^%A76eA{>vY0CL5lhbkik8PLdcfrPTvoA>V6 znty;7S$znFTvl%{u|SDl$#T?QGS1-;aGf^$8E|eYu?ehyY?`YEjY1UxM!6t+tY;_} zh>H}jM!YAgGfJ|DDk*RqGl;?-%@#C`1WrOoh6y7u`-NFCm_f}5gU8L9pnh$R+z%<6 z$Gul|Bria|M?+jL1W%rtY+6dHvrE;AlOYf~fE7ev9B+Y5_vr%L@_=-Uq0E5;P$D}1 z0TqenDI3~N7}`=X;tUdlvW4BSvJtg`TB$2{wkKXf3DTB9IMG&~1+l2&ML_{nzK`%RTQsJ$ZW7+!znX)x6HPAO%n|e=(iA=EeKUr)0-59cD6zdtvmIM zlSBxrK#miz%_8T(t?M(2hr4P$^`V)b&yW7sM4y}|DgVE zq?Znrt77VKVX;!TYRy2?lk78GuNDZ zjjEOW_1SJr*J_sOi8RDTj9U{b;pTur-^P&DMYQx5;eMc}Zw=GYiJ-rL&OT`7HpG{V zI%C!*+bdrJSHC7G2AYQIo@qH(Pb!*kAQ>F@VC>;`Hu)3A-TG4e3conSlw{-RrdHjc zPWwc}u)mIw+zLIrSv$wyXW28QR|lm&S?I;vK`w43d~Qv=VT~1?)hP^J7Zt0_)54IY zw13BAdp5Wa8=)!bb?li3KUaT)H>Z3_RC2CMsZps^QY)gNYqOlVW-r>e28sl?(VYq$ zCv8SI0GZnxb6vejVF)GCIa9l#&kg_BTIcNK)M#Y2GA0=p37_E6%gJAEq;$<^g-Nc_ z&wKNZ<_W%&jvG(-Rj|(?bW(P%G@-2mZ}q*x7wwNXk;lb;j!&~J_?_a(##q+!mHBLv zwL=d;2_QV-irSF|No8_!NDjd*7ylJsN`(e8rnFJ|^7UvL`)Gn`okGUa-EliSw}oCB-47V*E%~FuXd(*uSVU9STe(iT=$UTgjd5q z*VPhMdg8jbIgc~Y=7zo`zOWhn6{_|u@r~7EB+h-g#5O^=mN)qcW?d&&sD7`J<&K_C zu~;>VzHZ!0d)DLXS7hN8VoxAlcSh~z#9tCI3WzubvkCv)KxCWF(9pOE!;@MH!0A)= zxuP74TJygvxCZ&u>fI0^UjIAv+H?j#!(H@4TEdKnD&eWRj*^F8#iYAvOR9n!N%dYx zUSp#mu>gY0DJ~Ek;^tVZXN;d#UIrZCK9)i>>SOZ_H zwhiiVu*gpRTqNEyhi{x-W%|+>><*&24uCL(xO!@dHB2M zH~&Uut96sL)U{*K2xwd<1Z$#A;KcycA zXU|%Z)g1OuJ2JDC26%OjT~u{ydMBvS^_-Ke1~=dS;SaZMj#_%PV%t*tke{IbJ#d#Y z+(?KYpS4y#C>5)DOrt4|IXScNvz$^G%Xdt8^bPudyAho(ZS9xpKtRH#z(CCZ#YpRa z4YH1Xt(9>l8&BQ+L=kZfVa4{wW_LIOc`s814MvO%60zondD*>iDgyb^I$O3;GIE~2 zpR?w?9)%I>UtGToAzanXP5<-EOig<|knv2G!g)G6a=`2Kdq0J_Ic6KP9Pu6(_pe8z zF$K+e5Kdi@j~tOt-0z_B4y&R)QqY=sIx^>yXyFT8(59m~Bo_0>|GqJnQm9Mf93u|6 zrpZUSIpj^-1=E)Om_J|(0ZfXHxUj{bitt4|@njBtlBUh>C^P8JloWySQ{R#Vq0K#m{r+sz6{?47v>vg^h&?c1W-wzc*95~Nxjd!r8d4WR z3`sU?GQn!wcU1y21`1=`%3V@~raN`yh)a^pzF{K)!RK;O6ftNn;{0XqAP5AJL$M!} zV3JZ~!;v?9M!P8K4g8Qekj0ZB(!?QO=x7Knj|#zn9Ka1>?oj3^q)&3onmHViHY5_z z<}2=;FbzYXIl0%^9Z*XcRE6~h36Tiy$Q4w^)CiN$JYnY8zYNTV2OQTQI`F$&fI}pn zxGQ&?FO{Y>}dF+Km| z;Z3w{7jc$8Xeaz3nV>%yfu5@@Sg&mt!K)0CB0aok>Cg>`F=(j?7=-i8_Y^+=c&}Pk zSG^BzHZBNpJ39E~w&|hPeG&IlNSELVqHKM8VFSG8&tA7P(<#1At_yw8!&LM`lOKEk z9sct>Bt_0n`1L;h9?%!Wc3x*$aQ;uPv(o`0=6<#>&z0UD*4946O=p1R$+jeBSJ48& zGkqr{C|=sv1yBT(L~b*(!cVvNd~jbNy)Kr@$w7K+z?J)t5A@ZZsl)o)JZBhFYnn17 z`Ptrm;RmoIWYQzU?h|Csz;Qk&Ynx5(hmS-!WUqbJ{KPLAC`wm%pQa4G)ldxC|pTa>Zc&RMSRXHb430W0p+ z-r)y5PoKa&$_kf69G}9C!5&*MeP9MFBlpf;v$xM8_jN9TOTz#*$ou+*dz-<%m#@uy z(QF_|{-!hzx7B(!JUC4dyGv5~F=c1E2sfeb#nAzG+fW&dIqvR;IBRbd z;(#f3RFD}EXG|k3-X0nQi&6hw?;e_g*xUdQtik68WSH)M01V#*Jt*k;O;uWVg%Cy} zpvDuL8W&egO3uy#DrD_#im8n}=xcSq55M|3n(Mh@B)rMwf*4 zGbz}5a_7M2XR(A=B#@*3g~&q$oCQv4AJ;W7wzKzz%^;zn$*9TL%oD~LgI+Ln?U|k~ zVIKfycnc+3ddV$V%kr6G_HyXq5)8KPe8SK^dC$`o@5vo(OF0-BWl$6V5AzDa2_$%Q z2Y)TW1Ko}bc2kJQ7uewmh43FKAXP484b8)&KPbxKCHdPF&kpz^NfU&l3Xe|d1l%tu z;USb)U8fw7u|h^pzB7c*FTru^W?X_LhVPpXheP-2b(&_d{OQSoO+zN!0r!s*@qUBr zBCydca^)A~JG*^8z;H6HzeAphKr%;WdwkS7sLpb8Kn+KaW8O4DsUy@f-IF_{Oycp! ztOc9BgOJ|5zk4A_DK3QxWb??IN2_<&#ym=?t6NvFKU-Vi8v#f-I;_^PC@{V$s|%Wu81Rie9umR}5D&zsK<%F4 zgzu0giRnJzmvVw=hgd|$` zx3PP>;OKt~arI0$IBWtt{|7rj#J`$_`8*A^aY&7~-jsT{LMjN@_-cN015%F^;K1-~ za1C;Np2zhaUBR096lQ5Cttvf`LYu)xaDN+0nPWzubb1ON03HFrJbE zkHAp)f`B44CxDn@)G&4e8d?w)l$4nBf=#9|>e{$Zp&E=^8K}zBIc&R~JLm}826xeT z9vho#^C2!aStF;n45A%urrBoD5|Yc)tv2fGn<%K^9TWOG0wJ&^yT~}6c{CY;iax4P zoB0(6hd`GT8T%of0C*sU-=aKVyCj7jKmHsK*+88}yl-45IW%85*Z30V8T6TQ{~$_% zoKxoHWIRI*GI%-$xrnQPEFdO#6x@unE9iEH>yb?r#+4Qn;0rqVwF?P40V^-K0sAI3 zoI-OU!$9M^o>~lHJ)TU`Vg|iH2SJhCAUoUw1CEKPpjVCNlPPf}uNNFrlA^)NJ1#)P z6$23DYep1yjG~GrlT|v@6%_J!q4ZisJ|fj_W|dJwn{+t*KM954G)rUE z0)(RBY!011Ai;y=+Q=ZJw%WP%=pvj3X|j;6F>ca8R8|Z@eEt041nv7QC*&hi4aFpn zMr^<13;ZfY`r^cYMyz#xHcUFdEhASbcD2aSW(QI_9g8l#Sj2$XjISTn1JXGjM^iHC zlSxdvejE*NX(f=JUe_Ug9pVR%>h*GP^k2d77Iyt1Zs{mPk(P`4n$NEPtGdqFe<19a z1BZfsna(FyC}QF&#{i(;zYbg6FvJ%1qT@EZ2mK%Im}DZr?IH&r0j&stlL02ulO-~- zOA)*>B7>gdqn%f^P;j}TW`2jBsCrzf-FmFuP4ALCOWA1Q&W1VR>`gC&_Eu%hm=OC} z4!Ssw38;f>;2PuzyTDL*Mq_0bx91=u+k_DyM#hgpC}$};$gaiV#Bx3XHc;ncN#!yVZF2sD=lX3>#`u|tCprC?|%zOMWwy{#xcWbF;%fV3QbV#9>CZCR@F9F+56 z)3SwK@IF*fA+-+~j-dDvrT5I>i58!5{HVOFdY+HX$&- zz8+VVB!68^qR+`>ZWb0gXx$-`g2~1sj%CCarBXq4|9bA`F%yl#5$H#^s|=ihLq}F8 zyiaf+Mr957hYUtlw{SDDx)<-#q$Q0=5sE)2?6X#91^H4Vb}Oele~t5ut#fj|-oviB z8yvxR=tJkGs2z&SfhD!IQ0queNLCfpngPRV;U0p`TQC>*aA(>KcvorT6c_U;KI2Vv zI*w-KzZX4=3_Bh#8);!JQ>o~_pB>iyTCUY}JO^kH;AO7p*AMne0T13~tvB_tWiC`)Q&p|Zs za(~XQd*>m}=kpb;HGm!88BUfGov=%^WnC^p5AEM8FY%#zF zhxk7DF#xb{Tv8bC7tlhCLs}#6<1uvkMxGtAd_N}Hjq>aqjOGiP#|u(`Y|}1iw1?;f zz-IdJG^>4lgvLsLJ_LDJ9NfmkPZrEEwmX7Z?t_79p7x1@VCqg#7X-V&g@%7KP91`n z3BOhj%V(J7O?eQ1~bgWJ>rGmOD|LOuB9g#pR2X}nb_MKAhYT6g1_4v!3zJFWs2Eo zZ;zMPGnK)B20xBxZ=Lu1gmCW$l-hW7u1f>=5k#mzhdrcdiJ0mHS5Xm*>wxT!DJn0h zXB6`*dJH=Px%sYQwq~afC~e8d`VkMdSjwT15l16jXl#c){}GrTY|r?4P-LVK!heZs zfF$|>u+e>#r|2MHwY&hMfE}YGq4W4A%17)0e?Y+5JV)zw9Pt*2%gHh$7$gUR8!Q&_ zcJBd&%Wqp-!H=pDy{UW81TQ~+#-HJc>b`mwAnQe-;QY86fWI%s>kG`!7m}J)VPNFW zHJAw?#Bxyhi6FPhl#g2{YMbfYq9y~H{KF84LQ@C2-#yM=`kX`-OvFfN8?ze(_m5#V znI>qNPUtKY#&taxJyD>FJ;jJn|L}tBN80KNw98Z4s}zll4@3)Kq30ECxWNpH z9UUO^|LFF~+m(Y$4~*}!RCr@%Ai6?d_;BW~AnQU%QqVET$(>Ei`AF(2o~ZoH(GTt& zu%P}LC3tq8(rGN2E_U%6of;K?`@H$HLOUm|D9*`$slrg`sRs{G#2j)EZR%{BgSsB9;^rT?t z2cgcM9@ftiFxuH~=D0>lXQgRB+6_p7sRWTJh5xW>o7$&ouu z%?zxcc(kWy@FdInuro|y%6fPKfoSIoeO35r_~MSNK1tS4q3n)d>EewRLH7_L1> z_5-pV&hOqHO_NzDFb`LJeumylWqmSS8PbeRLZ=@D1AO$JG|>q6#vP{2FiLeXp(6=q z*$l|<5jNr5jOYR*16_pr#D&UVk2F#QjDR?27}Nufu$a*ioaHzd@NZvqQh?10wywVs z8I_UU?xSn;p}K@bWB#krv98OnManwZhMFg!eGDIT@3H#~Z9Ao{Xg9coeZ-#`lF{`; zP-SU%jXkRwbKJui@die*4Jx+Sq8=Ifix`A!${r&$z0qhQK`lPr;XKdLIYd)@8x>^C zqj%bP`VCfSUj^@@;t1c1(rhKbBRWEZepzRrU|m1GzkBGf_>_Q|H!AnhEBgH6NkeH# zI2R8m6RtG_+*(LZ85v0aoO-SjIr!V(>WL8;cE|It2)8-1pp0kE#kK7$WOBA>BWRGo z4orZO^iJ#_*AZ#mF}Q`(4xP>A~VD2+l}35a}Y0Ozb|AbDK}` z1NqG2NsLY{^ycC&RR~rT;mG^Dkgp)$$pZ-hNvkOK!q)q-wuyLu z)vckJRpzFS9M0GaJNS~s_X*IdaU8%ZY1cUvXgzJcVWilqM zJciDC2W=hzyMDvuIusX3QiRfJ0x#Y|JLz_RZ;yIg&FMn_P{Qtmd5Cg+|0%Q{D1}kQ zhJU4xsb%W}J9R)oNMWgbvO~{g>%+qw9GOTquQ2s%sxOpVxR{I z)7iP_sXZMOu}~g0A$JwSp2O!~uI}7%G+K%;H$jV{ac8=w3{;Ga8@ezgrVsS8i;Lc2 zmt#whE>90A2$3UwPkyNjK;-B})-BtCdTPiXM-fcMB3tG)Ggr*sWupgjLcJ{UOk3k1 z*z*8*S6G4o(z=+ZmYj#=?ZTsv@ijl8_$ z+JyMOtLZ~klnLJ! z7`2K=UwMxE;Y`Ih`Tq#JJ%>euV264Yb(0QJ$VhS~cX*o>aVjnu+)QvD+NgFVGlilX zUqr4&P|jv34O9vdsR%5&C5>5!^i@qGs0btk%6iNtexkG#z zk7^i`WhLs4{3PVCuJ9@j<)e^30$cKpBS99n-8NHc%#(CJ9>e0Y#>YnvI>cd-lS}AAk>FUfmyhIHDdi*;VPf5ZDwc z$K~@%w}-51=&=5If16+=IBP=~0AaN|)D2#+4a3?(FpZL2eW8csbFFyKjA9EAN@~9N z_hdd?ue$lj^X;M5fZn^^z;A>eTH;pXmB_@6IJSrEGMzE#W`*oAiEo{>NF=NI?AL#<``oa+4JlH0GYSHXLz5X1y?#DX!ubzGEvT{WmPJCXFQF;vuD9~NA#I19#+DmBAiq)ea z&FG-81hMMPTp#oThjF8)xS4O<09$l0fLeuGLyY%=S!Zz-3u#T!wbe;=--b1t2+0nY zL(wV69zgE8u&O9M^&DuIr@fzpc$y7wD`-(;>K6W*Osklc8iX}`hBw7_L=-YFi$snl zXw{GmFk%{nKtlRZ9;G*Ovinj@m8@>v?nvNmqT-MwY&2s4ZPa#ip^~_l?e^*m`DaK^ z|4|FqcCuiSoq@^XufrdY#f`VRDkfGR0z;`Ehd{NXP#vi}24`1pIKQoVA(0QIH#XLx z^unsoD}|jkeq9PVYiwut8ygkY*w_uzTF|T-4%XPT8X;C%pnNyaXb)Dgu#-qy47Yph zH`;$DjDvhH%fzlk(q`4jE;kF+A-D(|Z#Qc|MwrQ=(;1PA#y9LF>K1iI4zD+F zFc<>8-fKY=SO?j{LM86Mf&@c#m|NR0K4#wo5 zcPtM>RO=C^Mx`Cg8gvc_>z=XS*@owQ8imIlGxC%nZyANvFtBV(q?=!3bdSoisbg*5 zqsv$YjOM0cp(NCiJ^2H$`sd0^x1@_AFr zQPtvQa6Ai5-00$Bx7msrg8qH{Nyk+ATZQSxDIk(t$Z;B*E)Ev_C(VZ%ms!E9wRc z03qYapJv47a+EHP9P_Q9OF=XkuJDQP3Q4ETtWHF&>y;ILrBQ200y&c7@wG`fWwd^} z2S*OI8C^`G-CDANd65wqjz_V+c=e&sjh#JX6flezuIs&5gi6_WbtqnKJ5nMpE}TK3q|LZsIrzOL>Kr3Sticg?`UwE_eySfZz3 zH6$6kr-TP8;p#|Mk3y9=RsURMeIMpLfsPv~{Ot7d`QMNuJg8byzcu)4VaQs(d^!n``m^j(~_Vl-ZIMgO_htr60#NU zQs$?H>@>!}i^Uz{hKtP>b%gKB9XM*c39M#0kMqK^9{xwU6+q}dryy)Sc*YoQ>+Vd7 zFiAss7t*^bHZ_gv{Buo60XA(G=(utm=OQzbh*8Z0)50T0rj$NHS%n`pLvFw2+-(`;I?vX^NAgEy9j&M6&~(bQn!F_I!u$x;BF5?^D>9W_aaB z;eyzceH=sm@E~n#7j+e76v^zN;T$@JPGXR0RwO=1#Dh+mDTbDa!G_aX)Ig^SlQequ3X?Ja#_$7+QQ0C#uIb&$#Xc-Kp)GB zZJAYmno*=Q`(AKf)4-8UGzCVs3vELN6Vh2!tvqTF{`Sz;jUFp&^V`y{O6g~Eg|>7M z4XTpWl-_sx;bFHkcu!i(QWv)I?jA*`EI-s-TVD*Z)`{HgTwmK^-Egzov{#jO+qIIT zPjM$5U5K)8wB8NZK~t;LwkzseyFpiK*8p?0gSLatK{kr@YBXK&4RuRZAdb%;I_Qlw zoGK)0gcv^NP{fNdKLVS8{J!&PI2+agEXSYI2N=j0VjN?`H-;bHfhG+a2>-B75;d=C zjgcAJS{u z;|1sw1!X!D;jU4~CM`?eg@%uf+h zn=-;RVbu@#c%#%H>l`yZ9Yxpbe6!IgAB>^)#(-Zc7Gz?3hjsV4%*BI}4(LrU5^SN8 zXDu&Bp)*#~n>8Rgc9?=Hsbp`epzP<4skP)B2R?7K#hOf2q2xz7QxsjYV(Bgry*yZ+tb@|#SoSERVcvzn{p8&)cqV^MOIn`3D! z+EkpA2rTXC`m@ISO^<7R-<1!(Xz;QXQ*8}KhOd%>v&BZGgA9aIxRHo*Re7aAL~h#{ zhv>91o@TzbsqR9x?`*?WVv&P#9I~WC2FtYzr^-{=a5iTNe2{AV=Cp!}@_jIGEUsp} zw-`{(Z6E{7P`tI+pz!ohZ&9zO@Rz??uJ${3mC8pYeZ4;B<*blI0oBM?XRf`k|7o7^ zh3bL59QQBb1UDPrgL9qFOHtu$ppW;*)Wj*50*;%qW1!A%o7MyeEC_{`XxruRx!roe zoj~YCu({cKp#4PPyxKKbh}}%~l7a8A!XB-&%6ASww)^I>Jr2BaZeGQ1rpu*+S=dQ! zA2rO(BG}_-6Kg(WkNT?PSeDnt2E{jHzETV|W6ojh%VX6a8J*6ZEQ~4l&Eq=8-Va`4 z#*1ha-eyC7rOw1%gI9xh@}C;pEt2kEFu2xpa)1neP#1SAYaR zlft|#c-v99sf*hT9RV~F$No1_hHgp@o4OuoUCrrJO=VH%y?$29eC0`~wkbQcS8+2p zIg?Aw))KR3t4{GZvcnryIi88;LF0tc2NU86k{g%izp3N-mhr@_fk=Jiaw9rTQOgcu z4Xgj3%J3eme_$e&INrONPg23CIg*mbkGHl8lA|zDjI~vdFua<6RpOqFPkWYCc9wu` zd~=aLwyo#W%=i&msdjuvbw-#Q+DU`0^Z(U^CTddT6?Q@EW-Q-bTM3@pt3J?L7bXqP z@nh0&_lU*wWYUwJ{SsylbE4ChbANk^v2UQ%I%s7-bHy2tXpR{MN?>XnwAypqVt6*A>4h({WS_Bwg$phwJqZ-n(4Pf zccJ3DNF{gUey~A}3AkZ=tG?+}9^!>DqYee)V}@Ifgz!h~xz*R18E2ezxIYo&^>JD~ zKBSqp>8JMTFF645m13o>he(|q&NLaZL;b`#~ za+l@F4c9zF(s89x*q)p#uX3r#C|V4z+5D(e3QyELDgBy?169hpyR1X&QUM1R3#TFf3=$|5Kw;d{V}5}0b*|F~6b=|N~cVstji z$Go#02cI261{gt3j1U4R4s+7LrCvgKr*6iqbYn+CayA@0I?LNZ?%6HPx)Ii*rA9D%n+O2x6{{w;^jHx*x!ngsOkKBoJ7 z_fq-TWHo{5bzi)~SQr@G{rR9vrR)17&bp>pnVSTzOM-S`T|=EMv;kN0o-ARalUI%S#!b(oC~IpZDcOg!T*ek#?WT& zC2aM&qv|lGV4!vXNvBdrUN2ft*q({Rmd~gVgMMq69W$Y72}>zzx9heOjaMHqEK-2m z+%HK0@|-t}x~JbR8TV>=oXKmh5Eqcj*#l%x*TR|$C|DhUTd0!+$@-JWNr%@&C>Dit z89Lo`^cYU6JD+UgTGH{{VLLkEi*4)k-hSciR^RSYYz>B352K7AJ~Q~C1|;Y?B5UP4 zu??hKNVF0<9Pa11MJh8xSHPpXfY2K74X!IQVC=)250@2ds&mr4+WzIiLAQHII;s2@;9Z4gz}t;*iZy8^v~{33Gw zTQl`0Rn4Zn->#ZUq-o8Xscu+}v|*&xNmw+^CCI$~7Qm;4=6AAS?fo-Wo{!u&TX(Ji zwWisVg}Q3PUqi01hSmzAU6EQ>x(iAT9c%57W&8BPUfWA|U=cE!EmTw^bc2xY55s47 ze6xbI%CMcBu|q5mktS4uiZ#A#uK$~(5thQ75a}* zvs~oXmitSUsFI4)NX}Jtq(%Ts6$t_4s1gg|)u{@r;Z_%6J$A)o6%Q<4NcAoL;IB_r^7OhRV0D4LDBHtu;cN z7&p`6-rSWn%DI-fGey^IXdB_(stj%0z;n)=CoolobFy9cDn z8t+vMdVv6=vL#rkgk4~unQ)Oiat&9;x2s3}at3V_yVe@r1Pfg^!o?q4s^&%!k zWJN02kW9QUKf?0VreiaLacqut-RohQmRIAF8&o4M<%ks|?#QR1aK4-f7q?hd8kKT^ zxM8l8W#iaFJk2zUpMbJjX6`#zd!RoU7F~f8YT&9$i)%^6=5VAiG|!sklKm7H&LOig zoW(&+bEKBDck{4BZ5f!J0`lF5ygqEUzHMXp?0R#BK`cyAL*!YWX^|srxwFI7mblfA zpC@C=EYv)s45&1%0L-fQ>Xfh(y$(u=q&A`oPV*~Jm1dZBl_Ukss?^B?W5Hz+2DJvC zEMO5~?3MUrF^h=wTFxh!`Sk`L;c@O_Hu0KzTynsKq;o#H3M?Cm29rq*dOP*(WHzF` zJh3Ht!-rt=Dc)8uXdFij5NqdQSU|ZV-HM4?RQ391SYBo}0qk*?WOG?X4H$44Su0i&{+4&i(XQX|P!CL~dthYVD(%T%5gR>1 zjQI+VyTM_mdI?^Xr{trWK$j6V6;QOmp+P{)j7H*YE+QurIuKjflNs_{Wc@08aAl&r z#l6Zr(Fv2kaGy3&J_i4h^Yrs%d~9UxD%13h1uKPAl>};+Lq5uv2$9~=keqayv(A96 z=6oQS7lMlw6dD<2#7><8VblywCB|CWI_l0!{ZQrr=kAKt4k#PtI{W6*U@Kp=*Mcq_ z6Wf1L6NXi4P#cf60Eo#Vp*zUJcYAxs@vJ8wabZY~yybd~65X^x$ISxSRL)e9Aow}mm6BUH_{&a8_c!8bw1dG_ z7=GvU4q-pD9MK+~y@j~g$ zR=t$-cP(0p1@TV$DYol640wI{mHW@pa3 zTU5QaRmP8ZgG4iLG(=)A`>kPGESS6n=scrz9wbc7*}MuZSf zz599ZbkMyx?VJR?59cS{58cy2hsyHqXr0f?ez(3fFS>Q;ik8g#hfDYmGzu@e{mYX< zSZDg)XZa_JaiqvLOnyU4!bY7VB!FnD`?j{k!~_PFn!O`okTP902wT!)mNP+U+;%89 zgn+}Ml2}Fx7|X_uw?+-~d7+ykP+YR-XzJ43Ne^evw55%Iy;g4138c_EGmT-wIT85d5IFaB93qq$(-Fb(1)(2h$uJ`v9HW*iVATw(*b?1|!>|ONLK_v6Xs&o0EBP z?~77;e7nQA+MG356QG1gO@^4pR_-PJs$dY*UmGUuD_JY_{#5WycMJRY+ZG$i_wUAkPlDN8Mz%yX& zkd}aQkB}p(GND8E@6&y>5yysnB+%H3XcONzd~V&563p(V3@{foz`Vr^394F?>Duwa z1C4u9`eq;$C@81yqZRQ0YdY2IdKQ)K9Q{Seu?vv$ya`pqdPe7OmDmC~%=d3vJ<%)S z1h8yl{v7wJnfDI5EtgyLPpZs0q8MS$vNCR_jvo7zf+{2^oXUU|T*g!{#<_qcMEPb)uk?STgc!VWE%}jims*-2Jf67tzh~ zUcHa90?X|VKZPhm;&seImqSWLZyWi;t4T);>xnCt8*NI*>wuu0>3LCiIoU6A$J=-{ zPY}7j$~T|M|0f8GATWg}LH>w~%*8hz7cpHx#R!^f$I)oY=?=AKj8knFPwB1f@apT< zm)5npewLQ3B|tUL32xPZ{}zC|W#+0PhTY^C+ZGiz_l0E#H=gDCgY9klz`d-A zzbW}#H3NL@ho!uH=5r(E3yBqH^}z&I$n`-wdoScv;K4+YM>H_qco`NaX)D}Q4;+|x zeBU1eUyKI0Y-mY#RM# z-Xt4?QV9b-_vDKwXg3eFNWpDffAEJ2ek_$!Cs9u5MbaX`ow03d-iOQygw$-nSyy>``u zCp7EhepEo0_lPuO%e~=ym5oUy6Q(+<~)Km&Aq+P?s0Xr zF^dQAC@4yJRu=OWsu7I<#(0mHM@@zpp@t?oA!0T5y@fN&D+b_>i4E~`JYKts#>rp# zYCImvU8{bov?)yZW=xh&fCW=HR)=I92Y5d4suRA!L@ovEvxvJnnVP_Mlfb0-1~5s^ zQ38{PS~y)n!}!uMixc#!*&rtGL$b0*F-Ee-=@6YJtYqQ=7=meGbt-bAno7|?(rJQm zshBVaCCkkmHf&hQv19ma3>LzuP{YTz4ppq}q=Y5cU6N9r*GK9h6xS+hU_VxHpnrNxbFH^uY5Su&iDqnz$R!%tE~>DC|46%AM< z3If3pW$`DunbC)+s2VVli(`f<0VH%Kvf8|XI9A`GfScM%mdbo_R}(I1m^gmq~} ztQWczG%?BLY470dup3NZjjw~yJz^Bj*2f8ccJk3YNwXKYNGY^&3M&cyq>_9|uA}Bs z^oM$Uf!!=c5b>b0x>MA;bgPD?v_WyCTyB;n3S|hAs5qQR5^_eHqhC|1sD}b?G#|!# zIx_r3oQ?W^Pyi33@I07I+5YJMd6%hh3qK3@OC-y!c!5YQDe+3e4s24!JL*l2} z<^)o+1h3qVvuwJ%F#`>JjAM9<>N^!<8N6x-_Q&h}4U?5X{2~r=VlQ|_aK^Vq7=NaC z^>P)%Ra{HC|G7G)Up+&>Yd{;keul6-x!3)RB3weU+-qGoN91^i{~iFx!)h+FRG@ue z0|$W;q^(DOpX2vq{64sj#zkyoFLA&XDc9)pLtbJvq_CRYk1xI>JpvCRspUBSoB#s^ z1sdHr-Jj-D$~D%TQB*JOeVnZ>Itsw$7_I~?QTe3s%zNOsqhn~ppyNG z&X+8tmbPh|)^1w;d`>0D>%RSN$+tu!a%PCb`j)uT7oWee!}f2y1ipl@pq|R~kLLET z#O5{pjajteyWqzk?K8vmW+;6QA8_)_N{gBmy<~v|hS!NlKAP_1w;iJT|O>8~lJYk0Vh8`oh&dnM~5m*T6{9mqIh zLpn;c^kIT`8{%|6(GU()D%8VYBRyneRi%gSv)v4b!4G5<8IW=mL~uo0L4zI>($TpP z-^qNJ+}u!9qIYK2rL@yvBj4Q8-N~zL^g!~vu1*vAcMxSC%B%! zd~Q;fBD47tX-qfk$10FWa)@LI@!~zA5p2I`2ZL>wR_tBU(;)QvvVHX&nm=dp=ytRF zSOPQIFnDhEcCfwQ(i#tqlWZqL98v!Wef#YEE9%>4=U-XjKAYAl+(_kDK3CzR*Xt2g|i=9w&~jgiLT(tO4US!FXkK^bViSvold$*=o_3G*c}iKXUp5;>ujoHsL88S*+*|-htLTQ&?HCINyq7l8hscDNql?W8=3sekU$Z zww3Yg@ZiIF_`Z8`-n|H0*;FC{aPF7<`|k$1T3P`sFr5HvTq?i&o#3_FQXya~^Lo>A zLE}U*W2GEhArrfA*ZilLHEZ*01N%a80gpqc8M7KOCG-{=+m+W2V0wJS6|=AM@4tBy ze+t**x4JZoxS08kWgvw;g=<c|sQ#jABaX!6ek^7?B4 zDM`!XwQIeX0bvdN^P26 zahlD%hdFCjs3>H@;$M^Bc>KHcOH(;rT`PFg!ZD_|O@=Zhs+%xe=osbyoF}8pf@~1n4E?+Tngwo1f<$kZDdOQRn&r>=F{{1%_x>S*bblOB8tH$@Vn)As-rGIjC_)XHz?L zc4o7P>1QU}i47ONi0<)D#hzrBxi7&WFL}_46H+1R9bO3=W%H|Xy!Av|p~f*U=qxyr zIuiV-n(7l`V;UK0g~+V>e}X${UYXs=^33lxDyCa(T< zF0bnV`ayVgR=ao5Cx>^Z-Oj}~G}{kpt)IqGeh$_kA63?zajoeA^4Hwz$H$EzqAQp$ zv^Uq@0Qet^G&wS|KOTXVd~6UBC(No-Llc7`&AW0LM(XWGGpP_;aMGkKkYywGH767< zUEOXfeAy5;cVO=t?V7_*Zd-qo+r5KlZ))31+7;@#P3=9sAo#o2m$@}2=ifN4)4G%W) zfPw;?vABW@imqs-9Kq-g$|)=BK0ZVO@pe^y+`wxkKXE?vc?}Z+G^|#S>xvt@G3*fs zw`Ldt4ZvCg6n-MamV$-fGW9L|T*~`3Tu9DL2vqBJ+op7B!GdP`y_RQL0=VT{uHCP3tT2>&biqNBZa z?~Oz84yu@9z`ng%HU^0?E@dz_E%7o@F`rUm5|S6Bmul3Kq`eZd%B82fB+~M3$MKAM zZf(g$V3UWqu$3dIzMSL|H=t~;bFSLvRL{mM5O|I90&n=XKrsV&KVi=W`q%ldUW$Le z%d#>4{~()Op>z=U_W|Bk&1WXr_}jsL%apxmwm8Z%qMxbt)-+RZfmHh-711^`_jmW$ zR1+YWok8z!(mk$}ZlgN1q4XQvgo~5~f4AS-@TF%X@Af;9rQYbF6Y?l zU-sb7^VV4!4*;+9f-`#g)|>W;Qn&5~qs( zS8VjVf2yeViQiMGsd*yD3Cy~ zNxA~87d*eY#X^?l#K6v+=)z_)mS$+%qKff^&V>AEf7lE!eE~_Ln@%@l8$B{-$> z@;JGUwSrDPt2l_5GzF9j&u+Y^F5_V(FBq7hD$j#(CK_oX1H0mERv3bak@pQbTq?Oz zjv~q_&WcFG8s@mo?Ru2<_B^@@pR?Wg0abuTjU(pk9tmY};Xw7zl!<1jby2Gw^0tMa z{ZB<*Y1)`}7Yiq^tzXi#tv~7~<2MPm|G=rn$jOn8D8WB5JaNtoNjXUJ2HAzKzD!J(k7|KGPL6HbQ0qNfhDWuZYe^!|EJ!$ z$%2AE!q(>I76)k`9)?Gq-pS=f7nfxQBg0-PSzE-(!E|V)ykNXW5jn07ZqBy({GJmc z?V#49DFLGSEW=EVLxN5>ZX~S0O9<{}_oqu8OuK?5r!!#A>or524S}SYqN=)$x#bIc zIG)L?Ivor_9m4#2X1tUg9#AXrjfLh9S_@;N^MjaBZ5U*U-h-usrGO z5py;O2r+Z*@^ZQ`>+AIF^r$oFoahT!Yn)qFR@}l4#r?t=B#UgGquV0EL@JVZiZjvS za8|-9>|r!9bhC?nX5-`vEb#ENHk?oxI*^5K?pvfttj zYD&;lIlEPDW=45eC7UxIgmH>C)bJ$zELW8)33*4&ZW)ER;m&1=Ztu>{PP(1b(0^}cRLJ@{r6d$@!ZKaKSq=^Qg4?398WAGwx9;#p^XsiWS2wzQg^8H%UN@_C-KOupTln3{py|7}3qNb@ z?(M?vjvKq%U-(&Lcl**E`9aO~6LRonxQ#nW6QwdH9oOoS2ID&r6P3 zEvvvkY-&mj%$y}$3NabacF=qIFpUdxd;vS)DFgX`ZsHjyq2wf=6gC7f-#rAI7RV-M z62h}zqYxt)=~FZdjsJ!NIU5Cp zVkt|bTm+Q~`QsneE5NDkfx8o|7o*vc7pFTK-6c{8Myg!YV@}d#%i5`|#tFgiGq?6M1E7U# z*X(OP$f+ZU?rNjV$?2s-M@5Vw$h#tFC4Rcn1HGcRP{m`xRqTWw8Zh1xSkQ)2~Qpo_c;}HQSrOOc5;+uxW@mm^~QSxGZbm=xHc8B*zyn6 zVMj@ThIt-6gct=^dJQ{3PL&agU3`mOyxgLL*@2T!m8`vEkS)==rCqjd+qSjKwr$(C zZCkr++umhsmu*+qIj3*mbGzgF@!jqfkv~>OM&?=(IiDQ!&3BHG1#+0yx1YWPf? zwVKUc96f=3{ZxDa+hpdIsc3H}cW2eEAyWC|^L)#j5$-CzSf3x4R69R9p2!ELR}|Mj zz!%#)!V!xeckp5rebB}d>nT+kI(|50d7-dj?A^r$>&fBw8UWbZ4tbm}Q0 z2Wx%&v&;J*yS#nn^o*oY(VEbhs>otSCTDwT7_-Kki)}6~hF9w1rYF>`_4?l%98@%= zq0!bmp0-bsjINt3Pg7La16A7Sn8>B#IV*^q8UQkq$_Sa&1E=yMr}P1tg31V-x`LTT zRVHxg^QUf;DE{r61MiRMbNDsT1&@=GFad0Nsa>r-G<>9RIb@W=BIR}h=qG8m6aw2T z%8KJ`XWgGbLke6n;(atkmi|~M0FCv{sp>3v<}`2Z&>vfMr}cM^Oi?>>(Kf^erbS3~KbNQMYc%%&LKd?GQ*wuEJNm*&prf)7Z`Z zlulU*KcO*SW7IF&Q%^OE2hP2CS%hId0HETue`fr^OW?Dl9Xu}%ZwGo%WBJbt2K-<> zZ_2Qwi{bJL>5muxlRVZ~k!N`p#)k0p5Km=VX~eD98`eREboBM8O@|}x@GLsFL!9gk zmq~N!?IN}@=S~M2KR##U$$D+d#p4!Eu1*j4Y0Z3G_d}cRFZXZd4y7TjIil8R*dLebRn$ zqb)>)GO~_|Bb0Tt+h!qhmjqQvf;5t4clbbG>);+YmyHnwt9*tuunmRf^==jNoHp1~ z(DyWxixN%eBKOdl(#qnRgPc<4u8H2!h>C@f_tv4<_h~cl=F&!It;wWs{f~_46kk!7rt~_4W zW+PL?qH#%{C2o2XB|ojD^Eu#7MnT#5qu%$-C3nkLWZ>N3$ly_og&?ItT$}z^NklcY zgulvwD0WE8!??yzzH93n|C~4*c!Fx;k#A*2L&Z(S>o0=(>wo!nbFjuK-kclEr^^X8 zP_AWmQbb>|Zt#n>4RYAa6I$=|cj<5Tx|I!<&gj-z?`1*tp zrrzit1HRE_c*9C-EpP^Lx|@%SsxyxB+<(^r+i!Vh6<-}`S`tYZu~Z~z&PRp5$uq?N z^!$P;xspU@QAb6Lucve2#62~Sg$0sHkFQBm?>w%mwAK-=67-z@$LZtvr@WF{SVQ@n zf_j?mMy-|{RGmK6mVkgoqb`Kfw3Pb zk>E?+jDMBZz--S;2;L*ca|hb(FsZD7vrU5kc8|HsU|TtM5D7pLVPtrXYFoI1Wfl&XZ8;wJ828PrsXD5G-#KwLgi2Tt%j0K;Ukdr zB<46Pf+QuZ!OP^U%B7DkwN`z=7i%dpyyO9JbkZfysvFW2`t5nX-Mg@hwnP#<(8Xs>lap0uI*`^lE^c!8dgyrnqK>qAd8V6_7i-Bqu}i&(yr8g6$ACFbu(xH*k|%AQ`P)BAL!q2_DT2gz zKJxxEsL^Te2@E|a$kr-~B4B&^6y?IR5xTJL0IQ38bqgbEym9}Fz%@ay3~!#9&$15m z7}*p``IU$(M(A=%{4uansBp;8B5qJ1mI%R?!cbX=y>0gBKw++s!iUFi-4K~}KLT}d zKsTiy&_b<}Ff+@I&Un!8{8JcI;!o4^RZF7R;l)Efu;k*}kEfSGly^HJEQd9?fqNi% z|DNh(o7}(+#KXg!2PAi}Aq5m_Rx)>S?kbMYq49{jCgiv8F7$WuSD=iuwD1x7>|_4DQY*83RN#f%t-1srrUYIvm#N1PY!bP8 z6NPz-3D$^FUQX@@(nGAdBM1e2Qp&UjkwUXO4Q^xMs_CuOWsYX^=utM4M2a$CGBW1+ z5JM57sdGJaL8ND3DNt#nXVF?#Px&otQehezro@HvlrEz7$v184%68e5!M6Rj)Pk8qjc-?aqFu#yS z%VRX2wCIK~#X(-CHBslV!vSJ8&N$WlShA6>#6!YynwE6|#Df%c%`7Q?7uh!&3Uu&= zZ>6L) z%)G=YDGwou@%W-6(OQo8q({pe8ZF${TqQ|^SlSC@%v$z=W@AvUp2AVP+dqnd!9EgQ zp-BO1%H~Y=y=S-!iybz&oYRdz&oBj9^6GS*d<1qf3j92OZ?$`D)gyJ!&M&zcc4UWf zZC>pc1lXWP-c1GLp~Zt2^qL1N!}I&4 zkM_p=g*lK4`OII`*DcR9)C-uS#IrsETaVh|07?a3`H!b6(|2N>t^ z#WHHQG&?_89wbYls*%acCEzc|s-g~#JW|j-R%ztR)_^)v}52^GZV^55}Yh%fns zlJUBjmh>g}mVfp_Vc!h1(>gRgWr=!5$J}0%O@1Z=lJY}k93i?zlo2Kx>0PAC9Yk7= zziA7Uf)d&_*(3MZbw2@bd1Uvsxypvg8@#ykP9@nW2hT`fwUOfK61QMIcz9J?&r~U$ z%#5z4cBwWmqs4SuD7AXs9^kit8RBa0?coPgPzr%KB+f+R8#?xny`ZL&qP#yCs($l@lQvk{6&`1dOq+;R;~(< zyfF``^H0ldQ)gLBf!K$F&R~d#)y&~@bo7Zs%I=`?oAUx_aMzD8P^}A3jCo!JKk(vr zb-y3lQns2hIIK1=TEwpTWY8&o66h3Ekp z8jP!X_shf2B?r{=T$oUfWP$CVWCe~0&-ptjt>cS_@x?q1(lpgs2=j22gQ`3ka(=vq zuk~B&Z>S*vmG5sCYD>tLu7=IkV~Io5&{Gc>M-?=I_XSgeBd4{bpvP+4vsR0`mr=N? z6XMQy(WsPWwuN#<2N)^Y-Y^oLxW^5lJVPo<%MpVmVtNE7$|f%B=;V%FJu#>i|~=6;AWxoE<;U@QDtacky5_=fnZYr$k<(p7{l-4q8JZT43H$cK6D>DBt^b zb|{ne4gHS9zzaM*b=%`DW}s~E)a#?w0-|vZPV>SFvgbJ0OoM`S^QxuAHS8sbYTj{S zzXiHO-0rk2wYCAT&A!P1fTPD>viY*_4a$9`r=|kV<)sCK~DZ? zf@h}y>#B0#13z7OJI>UZNeCqLxBlwUJ^vK2my_Aag*@h?1KT9z2lH3BX77B;-fX$F zCPXpu{JW8TqG(ax$sXcZZ4gbjtgYsoM~2KtZF9=59ZwKxficrM_m@oHU(5zuHPygz z?@v0QnGq+!gNJ0C)pzW0A^Pr_7T~zf&7_6M94!xtxU7Ac?&Uc@j=x0cS58C$UFx8+ zuQ#fpMOh&D_KgMNzEJ5%%+8tJJR>%GPWWA-z$ucG5C9A)PXVM9l;5F@v3ZJ9RZqQjwnitpW|^S!VS(nqe#$v<8ZCP!HeDINIaONR)75C z5^1h|K{JsGgtTzPdRh-&5qu)KPsdE4jgwQSW{JuYxu;o`&VzG;Qv8TyHQ1Z2xyu{> zno~V%X{m7h$mr5>QEg+R{0NqkI14o{e@xCvk8{U&4d_H$T`B(pYsb z5rtLJXT$nthIxAkg{=NkivJX6C8W)Otg!Qb%AktytqS>p5Slor_KTq8=z})O4y<+?8fTs&pjlt zP+_9flZfq|_4T#h^s z3{2G8@t<7GYsUXxE~cKnqlvMeg^j)Szu5_2YFXLst0R5>B-UMDhX0cGM+b|BzD|n-0_ok`&UOi#3)Hp9u_1UlwVqOjm{fD-*D=_?i^G|Oy`R9^Hi(R#vih7c)32v2UE zLI*1?@xJwJw>6clDQm>1nS|Ce^Iv^Dfhf5DA*@{6NK~TpCA3U^e=Fk_R>%T=!JK= z%vx9AvcLDwf@*5s3#xgtm1$dg!xd#0z;nJi?OR;RN~kymi{MOx?eZS+y4wXz_Jeg9 zW)S!z*p2<9k{kx*?4e&7Nf^Lo{`?EqWiAQ8q)&iZLR_y~NruP55~*rt2jn-jTjX}n zaEW)(lgfR7imQr~z*$G;j0&`{2K&-eIsG{U&Z+RUy#L2}xmYKCm7C--kc~ihzPAz> z8AhvPZ|^DH`1}=kq%2?YRtPpIZHnC+RE3cpcV$hJjN|#G7Pg=W@jDVEQ>diY@O5}p zpzQct5K0tlvYwbb9D4!r&N%NweFr`+jG|XDwVN@wkYThfj1udwQXpQLbB2r1LO-RA z$Xn32%>KR@n2?y$vC^qC1t_2}@|*YRF?mcO7k#P@KCH}2wsM21Yed2(<&h2C5l!s) zS%oW#%rAjLNch-Lkmpt?z75Uq8uPJd^Ll4 zRJPBHS@1PPolVwi-xVbWi#Bq+qt5i^j5Z;3t2g*0a8^4m7_~qkla!C4zludRp{E^P zhQpjwkqju(t}V|)mNHT*aHHs$b5lEskpxblSd0i( zk>vzr64ZnR|LqNxr`R}Zh!DW}NB^g{q;GP7gX}%Ltw-UJqHPl!%I*qk_mF^%qe+;3 zK&I?}3>?Tic0?uWT!ZQ|sAyM*h`e_o06DJ-XWyE>Oz?$;v#+o1W15{nNHR0FT7&1h zR~OvOcvlaj&wgLx&o`3qXwd~mMX-Z&L)B3aC4WYsDzfn$5QMQxR$3#vO_Wa#0TO*4 z&K05R*Mo5sJJ2Gd(9b>{V)D9C?6`|aFEFdixw(6p9&Cp6>=8sjZtT%SEsPztBg@=- ze28A2!=fV9Vo$u3);51voE*@)-60{= zQq2U0zdX7qT#B-?ws^l_7sFI9sRQ+;b!WP65a0x#=pYe3&F zOxcA5X?&|HCu5(FO#ARooP3KgzT%;}aOIx&yD=B1(?N%IyszB25V~XGJ2uy*9WCup zYuFdD;&w&SL>(}Cw0y`Z#KmHnyw$fQQoR=t79g-@pEP(pA~%y7*HGLwsSSfSw+Q&bHw4Uj)^MgW2;*yLImKMf+ah;7k^1Y!0y%7q=V09~Po6!AYimumlZ#UVF% zYAL&9tNmPYu;gUBq1GJ3{i{=n%;`RM2rrqDcZFl2-5XEBAZ@uR-OYOF`k?b@eP}4% z#ue@tCGj%|DHqEen2tB~XLb;EA7JnJH15$SBPFh7*m)hg)NY;4I9`h&VIK(4ublheGsB`Ra|55Vu6I9=Vy{{(dxG9)PhH6h`ohHai~d>c5}`SJOYSlmp+0WGeis)WUYj+XmO zP|-)8!x8rmc<2lUB{q52#^&DYiG?$@cko(WWsrXJf05MJ+xpB|eE~MOKdJB7?o~EB zAtjvj;X7bS;I)2b%kUYpt2n0zPyt={Ni*Wvo;R*r{`i{mZPJK z8~ENWgziQDl5DG7N1+cAqz>jvv#H-zv`xM_6$dwLDWKV`O~vQTHjAiNK+unSO<&_F zUVqEiN-nohg^dYZDGda%f8mn-f{jgwteU;$Wm1LxJTDq9AIm;Y+|wG1UO|(L$=Fyz z!moub=X^0gejkF9K0Mv@l$HhgJe@E>7f>d$3q!j+ahAg%d#sHNMQ{o>xL61=45L|@ z#{e`>nz)b(7w%U(q7(b%G;|^i8y7LhT5X8kl$q~+A#vg46x!Kl+m8Jbb2oMPs6@20 z!au($W3Om$d-N$t{2gG5b`@>9SOeHae@85rN5ns8O|A4f*Thwy?pdGDJ%T=EzJUkT z;u{J{~R@jsk%)+%8gy7Ue@A(4_+`igB&G9PT!{mTo6-%8_H!&~T)4C}Cc}{f_ z1~INl)ef9GvP6agYtxOo2pFXaT|*0jDYWiJ^{!X0n@UWFgfzf9u&o5i`%8tKsLvOI z6vOYKk!~CC*@7l5IRv;=feomAN8K%59W10fe9cmQ$7~m(6 zmwp9MJ517{Pg`)3jUpLEs6!ir(HKiMY4ql+xe=XuF-3K&O0a}TqJ)5e<1|sM)fDt# zzEC|ZnEJTyv;uqxLRgi30OPhdKljg}=+>f}jHFC?62mGr7&HwuPZnv?JU8LvUgAur z$Z1kX<3j~d-CiR7Lj_NJ=((UW!an&TG;8NCv)stTl}OW`kQb;Z|+_MlV6qEVQD*6qh_>)o{zfu3jT ziRWytjLHfL+4X8(-(BInT>@qaqwzUz@gM5(N$}T4%jh-X*7CFw=j?rpX7dCsR^}NB zZW|i@vTM$2@l4LPe1?YI>Sr1N?CtSp$FZ1&Hb!=S3f8g==w=BAohj#w4xl7iu8dB* zLVqvw*OT4aws&?s&At6v8lOKxlzSP@EtvnrIF0Yj1McU&{5U~F&bQT)>m(FWOv!+XXb z`R2Sx@0Nt#e}?qB!~aQu`y%sR@n$RodhTmg;*hJt-um2aE^=n-pAQ6jy~M7LwUYJW z@@;234pwTk|QOce=of zJ}3!gk{L7v^k(VY;vL(uR_}`8*GhD+oGhr18AtC%)fKA?#oCh|)d3O+hQo2EM>e?d z3c=ULk>W-pHXuKCaqKgle612RJTGSrkjHvT$RF+o=q|I~u8^Htee;-r4X>^9^R36n zDy|+xZ0EqYquoExLEYc%|A9gP04!mkpVXcI{ILB0L!pJOvx%dvfi=B~GAIC`sLO=$ z|M#i6|C^^aa&dCDv-v--0P)Ws?-~U=?E?e=@c6@Wk^j3ZD2fV-$cWO}82_(76QeBS zw9bIg{jPQagT9cl;ALBbxC@D2LCdvi{L?%+lFE~q9sKoH6D%PtZsuta@A};BW2c5E zxS&<0^_s<9fy!f9ksU+ii6S2gp}Y{jVBrL05kMV(hMw!=c$`$Qe3ZDZ74Y3$`L}=_ za89<+oFy=17d1382zgm1Hl!CPfV{%x&k1@3+}z!QIW(!_1*mdis-*I>!UHHkBqu4S zNmlk>7Fj%u>HXk3&Vpp)YX4e5$y-(b8sRvbm2g!GH`S7J2%d?Nqu4aL#T&(`5T}7+ zC_hUcw4`T|akjE7)FR_Y4jE>)jT+=k+vNZ%u`V-%=xUKUU3VFZ-LKrpmMlr;9%{09 zXosT@3|gTCR9ZFJ)a`kwY95L!PhviYbE~rHwTAD;N$k$Wu%P2ECcE~G#(LD%4(GDY zeaWl9{0gINZPIQ7Vdv#426JdoBE=kT>&Z!I8T7`|)=}jpte~&Eu{=W{Kra6&V`X=!-W=TuauSU(&4#YYWRePk z9L_PXzy#!+Byvm6{r>j+5po@O%qruLK)>l@x--f$HJ%uWq075)u^oc|{qv03|NMKP zfR((LDP|Kp_ImXxM~|vpRGrIN{+oyLEc6`TH5=e#=CoKk4n)eL7H|Y2o zfTxY$J14YK;sN|WM$*6T^Rr(wNol|U01Ds$0Kfk4?sGF|6DMa{dpk$xf7dU{{kH$m zFYnY~SyJo>`z-?WTgbHYY=9cd5>z#Ep+xhL&{8ZSoPu9H%uNkXwhAb#Z~A|5X0o2Q zVL0=I&*ZLyynHeDR`UE_X#-N8XMaH#+ToerbJiUo8glgM2jS}4NWG&dwzwGJZ2s|Z z?g{I#+ry!0!wckxkBQ-ytEmlh<9I26hU{v;1^qzq`}815o@u?>&CFy#DhG!q=XSQm zv4Jk@@9jWCKak?xPZP~PnD1@>!o=EXjZFk16(!;R;!`M^{d5BXei;OB9BD=CaKcbn zR3|nXsLA`F4k6=*D0?olvJNyr-woFfcF=0K>n#dF%`&>=;^z6_Mx=2+m;^^u-pEbZ zRHFmA`ImS}npkE(o_R9*oNwZM8ZY-zM&F1!Q0%`jt!X~zXwf3=(C1QdSTyDi7KIDOS=_Km zS+9w$KFM<+2~5qjNgIt6H6dOCd4&8Y{eyBuy&m|>tfFn105x1D1A1r>C=yl7KF6P8 zp=&~cgNf+3 zV`+Z1G9@ecLK0ct;6gI(dGW?VyRpx?IL;{QO0H|GWF^2@*5m5LL=-Jp&0(pR_@i}CPi=I&3Pmp z+9t$OCLC2o(|OnFr6Te6FQE3t`8LUWaWbRO;k)p_kv&LldMet&kU|FSib@tCw7mLb zEoX=frm302l?H<8w6#6OONh*m@GWuu&ZD;4vF#HqVs4g>w9E~opT3vqff~<(-74*B z_XI~S0!VXemhb3kNAtd!Dituk|yko&A3-3ao zQ%}e51I_R+`i&v-{X-r81z}Lw9;KclDXzIo-nQd=guH|sfOSpzY!hs}xR!@%yg?9G zKloG96_>K2Za#j4YVfXw7jJbQmaMII;hlA0R)-X)!R9r+uD$oA2lyl_L^4yOuo)Rw^3Yx_&a!^57_?-fnyc;?Ux@2&_MtINc}&7fa5=(;7z;Y z($Hb^-Ro%h15&s*lLWFW?d;qa1rEYir}1UNh~vThWR?%@@3Hydt=!C3+E)4eZ~lcs zG0~8n+Z}4_nI8n%{h%A^Ag#Z{;QApBxbEkCe?c>|>DYKNZ-1vlkagYtl?GXA`9<>F z9|FL4;vET1C_|;Sg5$*;{HEOmUL7`=gZRdkKEIsPi-8XvngwG2drwl^z?w&9S9lA% z&}B(v?7acqNya6ZR|%O43z2k|Xtd7(&8&hj>-3{lB|YwJ9k`!5-|XGt_S{@Hq8#cjLO|@>6MMdsC!1{wnp8TC}A?GsjA=(Htk! zRZa&VR*-3=m7&OpBzg!5SWYVi%$`91QjoSygjBulrHUSu8C#8{l|PXCzJ^1i{7s^V z=+-2n!dwzk!xAQ{@k4^)zds~+L%vfKJ)jyU&WN@^`$G(c6^8i2Q>2gs9su|%{2Oh!OX<_Nh5=g_OB7ny##`lrJbMV!gBEK+gBAh$!z76#=^U-8g5nTA!xOJCC|{{HcS-xVy)^{`zawuqTc)Do#4n5J6y&6QKLMRqIfi z7$j(COMfPCD6ZmQ5z_+a^5Tm_tn}-r;6}hXsmc@D@{oJ-0pjWgetKGc37^wGrG&!0 zA3fk<&Tw*cw0sr1d{It~&bgv}daP9cdT;m^wxwG4!TCFxPVLW`=7`HM5@VzTT zUO-#>aDb&7fcPge!#B`>B@IjJN_Wx^X@q{{hS2{5()>GM{-@IT7hwKfX*mBwX$1UF zrNQ-|O2fvd&I0au+RH99dz#>R^m(4QSLEe&G|zWj|Mc^|KM-U6J!=hSbq|0NN582* zwzj3n2a0l|9pTrrbL0&C91L!DASk=QO<8@j#ql`o^b4F9{}W*lJGx$9-04alQNcrx zlh+DcaDpJSCdYcc8{;}$Y>}S}F5SKq^6ezi%--(K<_*kme6C*-0f|V7F}<>jCr;0} z{Q$n-{nd{-Azvs&k&&=JMUtcOUPbe}AbT);9V=#-P5^Ka;^^}U;b&ah>Qy|fm5tl4 z>j?dRYCXR2{PnBg!yZRM|61oSbabIiW!E0wN7wM_Uw=$j;o}kz-^kYIS;OoZ`B-6s z{zVuQoe8p=f>YZ04lJTWpNJB?HjJ5xQ08oW;Q!Pa1%v<88J_sG*<1aL7xBchgcpng z9OH4j&$lt5W|=e)zcv=M4RVVDuq_Hh@2x`^DD#~gk+7Py(`l7(?7J221W~&DU*Upq z9NX6@>$Ne}#~XGffvcc4e@7$Tum3NdF|6JU{Piy8@LP}y;ar9i0Unw{6|>(3tZ-to z17V2?c*tK83y5-96NAUXI92kS75NZoS^F>b$K+8VifNi8U2sMDrckA`mBC;#qK6I> zXqKi;@sYqARKa~>1S|bj0`M~ES06R7=kUaxR(mjUE2>)Yo+jNCCzHv2qEdTt3qs^^ zsIiVJXJ$CbWVHW7=rPdBKk;(e0I7PvW62XHNU@qpt8f7SeF4WtS&OQN{DYSjC!633 z*szjh(FPr-M*_#1UI9uMrkZ7*1j=-S3ZBAz2X~;Ad(9~0f^rzO%54n7s@c_hTCQMe zOjGo6D~*Js`wRODR}dNBVq4=n9fwUdV>`!~1YE4G$>~Q%ng~-e1N3hBTNBFEt_e=u zc#tO4OuvyMNEvVus#xRzlk?)7%+O86PPCm^r_>H;L%?cxgdsn!xcmHJ7QXQwZ`Oa% zW#}f%<`1&NgKhYOykOLI^7UzAth3ki)hkP>8Odf)3mS^qaAsK%E^k#BL%`OSpzn;! z=dC{dtX%kXxEfX-d{mgNt?icY$wh8v8%_J(I!|u*UfkpU~Mg^#9bd)RE@{YAcgp7Q?d*hiOvYQjeZ0I*;K0Fe7{j{SelF^o+NoXu(fIoIw|af9tiM=yY@vEq=*k*(7wVPk3z$;OFFN>?#5Y3;(E0I8v^R6GTp+j8Xd ziT4PQav|SgWzP6Mbf>+u#rXU(8d)V)hX5V zfu9ySxIui-91Rr5pb2vpL@Ux75j6y2jY-O`2mvpWlYTc2fWsksTXdWidVwU`ULiIL zB9Wp4iuD86mLR>+xs(xlLB38j16@G5AJ8axy6lt|j?$MPn}oJdpviz^LIb7`A++5I z$u=L98;mgyjp+R17YG~6OCchlNB5(W$rKoVF`TS2%vE0Ela5P@bW65#eD#yA0$ql5-ge~AX1R_&^C{uclu zC9(vB9%v<0euFr4KZ%s;9bdA@Ko?9c=IVNU&E(Ssg)-lHpdJn2TpqcJnLP}!FnSvn$$S{ao!3X3nflI>r4YX*sL@6)sG5 z4%~$;*KMwL(Z)-1y!u20oaV#?*9%viH!$Ay0Th#;i>ms(?|R7T;6c@PI_hQuM)wX^ z{_&p3D?I|60i@f9L)hF0 z_v1rO;UP2j)}2>}ju+9PwDGT~_7Dus`Yw6yyjVojif$JP?~sDT{Nh+Pt}eENZs==L z+KutJc=omIY-RnaebPkLrD?F2jR8)k@Lp`P7=-!Mqm5bwJfnkT)fgv+o~%~4{6ZasF)`^_4li<(FFF(PZf&fp9AA3-J}O#NAx@Omx(|)v+hD^ zG^vjObt7L0(EYN1;0NHiW*D**MI@px`$iQE$R$d@KkQ)hIwc`RoLMS^Oy}>_y`k#} z(6YC)5g-Vcy7>ZMfp`l4ay`1T^8tmva#~Ms*THjk5Nlhngs-Gc(7eqVz~DYh(VC3DMR<&wiWb8JU+7At&_YU~%3ypU+T#hyk9m z?8Dlla(160!n4R20;D%p>$J?WXffW1Lx=%IW!B6E3&DQ_c9vA1#b@YWq+1_3OgZ)P z?6+Ebkv{^%5S9>hur*26&H*a5stK|;1s*4 z!DtLDkOnl!jbw_l92P#(XbML?Hbbh<6VsZS;W(>|P$)p8W(sM5KnBPinT)DHJ+K+* ziwRQGbU!udyPu@Okr5(f2*$#^1_uo>j(WR`@b445ijawXo2uLzu|S2#1S=^3KRm&w zAPNE>$%+XLrZore)DyvZD7tvw_+x^=+{XAKxJG9GI_Xh>2&_IWvQQ2*ac6{;$u=pz zq?j{oY=&4Nh?9HD zoNCtV!vkC{$@#LMVlve*ut|8LX%%4zrOR-Kv$ybd58G-(_K3oq4FlL*vaNYcx}X>| zMM953=oq7#DbZw~a4?VtG)=J;5hFZ-n5{Pz~>C8C{yf5?_UQLrWY-tpY@VsGk~*E&fTptZS?)@KAP5 z3KB-s5UD@eGr|veuQE;Ak@B`BZ1UL^V|cP)K}H(>;!TAE7$uq%FoJ{QEF5jsofCbe z<(a|CCZOgw$~wgkvIs-yh+{-5?}Vg$P+tIIoGBKWBa&X3&4YZ!29i?i7eXWbdWQ_b z%eHD@%`4X#kqHzZxctZjr6TE(DDq>ZH_G$&?qkXX#*d?9-P>Xs3POkPe_r5jfoO7r zj{Q#rHtPt^Bh$=1o9}}RnW*QOv4lFZgjrEg`3sAp0@4T@1Zx~5s(2;_K*Tf!dRpkg zHnj(s!!3La8_9$g`Z^wV>?T@kpPSxhV^kOj%DO%52yP8WeUGZi2|_V44qe+h_uL6&( zM43fqj5nV?Sez%$TmdWpQxPD4+DgOMb(&+;E$Ii29#synE1q=_AZWjj8KMS zXp1R$H}8<&W=Fai&;jtQk_=56jh1|s303j5cvZfS1iOwVA#EUUW!a_Y`paf>t@pdp zY-z&+#woWC{+ZT`UG1q%Zd&p>nGiAUhEg#r?jWu*OoG%+!pDFX>{+DIdNFWX0bZZ3 zG};~Kk_(sS8BUe<2B;1ykS6$LC9A0F8Gw~70q}Rdu{}u=CM%JOkWjxizyl)gHb$)iQSzeq^~%|G}tsueN^~3wmfl#{~5E9JR04k;f`hgdq=cKse*=K zdBKxBs?W-?8n#8%-yeU{Wv027_E={Dp3M7dX=Ad21Ddg*o)SzlL23QiKpe6MdXov1 zY7M&80Td-gB|4P)!wWKA;z93m2L5i1q*Qbra-Qu=Dxop1eAm!#pd`I~P@>Z})mF-> z1iEz=Fbh%crNBmy_T6#pbRS}VtnRv+;h|#G&6tL+_hMELo4zb{ZRjOlo$9|KAF%_a-mQN{}abgh+>_%RSHxW79 zd(x4mcd^}yUOUk0EvdN!9%as0I-fd^;#`AI@uf-1U(Gu89qQQ%R5nkRbj1$(ZXhU_ zTFi$5#u7UUYu-AaRN+<`AFcyMrN57Pu}5z7-&(kty%ZH&b9yfUp9ECNV?Z=y*OgH# zwY*44uVTpTmK*qB@ z9ibjf)aS>U;26p*QK`^p9Piu~Iwuf_Juqqy>%mZvE$+g`7CQVdS)zfGFpU39NF=5K z+Hz1EaJJM+PiboAPb8iPu6(&$JS*D;v5F!(Yo?EZb``T2nGCt{Tmsk*QNo|P2Nz;s zts<$Ah}2Ha8${AqQyxS?(Ly%*tt^-)R1WQ`2Bq*AY0wCUl&)IpxL_#+2CgDdPb{Kb zfEpL16fZ84NwjaMJZ)T_;r(hoUq`A!D-o?Ex|9IV=;T-^zJ((Qw92H_U-@K~XJoyQ z;O2Mg75lw>e&1{0cJ`|O`gZe`j|G1wn?=P2B4(4%FhL+WI*WcWcuuv&1fjCSVsj8p z@5Dugpa)c+44$Z8;~nuN?}3tHPFH~gimJ=dpuOgqbxT1<7<5)=AV~^jN(qoA;QrJO ziG>leCi#~v0CRQYR6lIdJWds|RjqZ&WW6R5wCGg5~C{zZ;Dpr&26s!%-oup zE4bm{SpE~U9T#@5$A|jtn5=C%J@?62zsnHFz$>}{=N~?mz)7xJGp^yY33-~i0CTfg z`roYVvG>n61Df;AKH;{fO&v03vlOv*APm6U)(xG7&B#wvh|gTzRL1;AGqK#ba=?`z zzC(11ZlTUw((LIVt~+@F_7j5Vs}*p&ClXmET4hx-{(7`j4NMq#(N5qjoVI1^`#Fz< zHKeOLok*DlsRxNCu@vEyQJj=z=$R~>oNAS7D=)Y>>}Sh}A>V8O&pye46>ZzKocqP) z6GB~}Rip0Qs_=zgAXWd3fO_=syE9_JRY~e~4+NC(4?lp9v&fs6%>$AD*2Q#unc3m$ z%MrhtB4abzvb+XqyF6UKXg1ybb65zdTNY0x@p&2($_s7n@{q;*kcFf@RYt^?bE?< z=-l85pp@J`H%RXBeLcmf))+`GKdB+A8KEwI?F2 z7VQsE8IEbTiS3Hxjm#^9q6F2_BkEU+2%#|1_-=S-SQtZo$^*@`=hR8nxD_%0_V?w~U*D z&P{jHOmOvWeR4SiU0j@St$?gz`Ll7Cw-MlNvaVq*7|boh6LYkQk&F(4{0?xSS`Gct zy6IArf-Bq;>@jy?2yQfRlfb+a-(B3+|YHbu&Z<8dKJNV-E1 z!%bbOFzZTm7f-*mFjJPR%#Nn$<4Jo3HU=2>K2L83S9#)d_-RFXeIb7}gov69cdW?K zdUYMrJDM0e_slSR%z=wny}O*LZYtR(&5JgNd(LxaB4(1g%##c6V8Kw#cr4<6J6ktA|oAN)KbmrwE6A+;2J>jO#$Wd(R`-D}usa=Ku`xKP&!GJbo?rM+JHMQhRC%NnSvF}~4Y7;0EY7`&30|}*5 zyyJKi-VqTAO1Zjn*3Y@@9;&8$ntp(tKFiJPk+aZttE$o2Wo?r+!Ve9*K*AmN#pPS3 zCE%*u@)3N=9cj5%w1cG}Z-Kk>SegI+-`@WQq4X+5!2tjmQT+G&9R5|5F}1KZvHz*d z{97faS<}V|YaH=wrZ#<7nWPMJ0vq&cEe z;%SIM%$F`cLpntB1m}G+{V(Q#=tS~$_hIgYl46p29&4&%6;3;I(2gP(N7g%xg5o^Y_m}YGY@{usywr1KJYVm-$pnO9#r+jEHQe1$ znaYXN?tWfOHFhPluaUZih~Jj+F;uwqoTTyLF1fB1M~%~Fx{?3u?!bN~Kjg{&CmvTO z!Pjr|9KQ3VX4xSa@`|Q9e#MbGC;P@w5i|WPh9ABLdR!4*LsxsR*@vs%k|(XzL7{pl zWr+IUbAc!$mnAZhh3&JgZ@4}!)N<}t3!K*I$0^(+Bjv~T<_()Eub&nVqp|~ggMFk& z`B0`Fw~7yUw)TNH>qXNBp3TGjjn<406Bbu>d!`8!%lA$5d>Cod3!V*Y2gyPSVyn1}Z)d}uzwm`wjhhr6Li1|2 zdYO?7WimL;F}ld5x1oW~V4fJNxae8(wWbAQ-t`<5l zfnJpDABpTYj>mn(IJ>Rz<<%~x4F`^hgvi|r(KIda!mSQTP^d4Y4smj?BgH+tlIVaV zsR-E;998JRc+x~}vYN)RMd+wto`?h!Vh%Xu+t1*d4G`AjylBBBIzXzv^myN9`+R4N zZ7$@d8o8&3Z!Zin!<6ric(qEx)zPQh+dVJ9)`2tl89fozJX4-bEfPf%pM)mtQ=mcr zO2LE06wRZ@je)Xh%cNS3*5QKg9pJO*+h~XmDQO$l@N#J}+BWeidl;+HPyKKl<@@1n zC`V_}Iag~;S38aB>$ZlMF-qfO7~8d&Jv?1>4+9%4`7^g6UMqQzTKZ-A?Q*R4SZ?e= zZJue6@ppWFC~OATLQMGsx?^ZW ztn_72ant2kd0ABqSnH+%q*AtH>ufmv!0j}KjrwVXLoeJ+pVMRJKhra7JO6bC8fWRp zd+7sxIw-@qy~bS}6Zmk4<1_;0@rKpdzbIsGAmLdOyM@#>8WX*8peY>kCb;BNCFK9F<33NS{~?f0UZ05Vc4}Oo$LyUbZAXv8Gso z*zlK-R!JjVj+YgLgHd>2j`B7{*!feVf^vtMR(MRDWJS5Vq}RfyEnLW*X1%PnB_mxbqlbuy>5^c0?dtXsqwPiN6xe9;9d`t-5 z?Bt%r-8>{ZU?n_+nbdgR7RGdpR+@P>xQvK>ldy2G%QeX+^My6jUl1qLt~PM8II0SO zB*)9DV;ota<+w6HGg0e_X|_pra31WrxKMRW0>n+^k`)pX!qu>!J?7e8x!@CWNNo_; zr#G53Lze}G5S92QHzJ)g@zS}C;;@^GSJ>qFDWAMhC7$>eQc{dR!MjzoloG-908&*W z%k)+k&$CwHBFocuV;!|uJMDQfgw%WmxvASOM-sQ85(BLs!3a+xIOuw z`PhU_J+onj>Vm!s^jz%Nwa;l{32a*x?}EB+apE?zh`xzXnopV|OIM zp2j;Cl6kIrWh41(fT^ru$zG$%TCJXU2Q$5o>B<3x-F80BB66BRX<1|kQBglfH(3@J zDm9k|kYz&&0#KANgfFuCFgfFYuMa~}1+iCbYeVz%nY{-PI_5zLu2Ja{u}2u{1Vu|* zblcYsEw~LFQR5s%tF9-Qhq*m@0hAeo^lX+cf@jD%8X2iP z_8vi{ne-@36FSVlHSnENXAG^(R4>+LF;$);T9}{YZ-#*n9gr^{D_+bUv7Pw9tO5n$ zztlmON%pauN#ohL?J}jpMieXV={Nt>^-J;;(=ba82{-2FW12ghs1g>|;MauBhA`Vh z7ADoVQPJcwDUxNK%NBczs6|La6^8q{3u?uBXOUx5;qV#A-S}Rx>?p)E!IH9Wv8n2ZosXO} zeI`)B-|g$ERb*0C;Z3?3O0+wSh@ZzpKB1P-O~o&eq9_?1qhB;H$f>OdM}d6mb&thL z3e;QzI@2|HfXqNR&8UJya&s_5DX7>;9&SXpO=hFAD&1BXGIJyg#=zL&U&H+?Pw`Fj zZZ+!3%|mFRm-qKM&eCuFFBqQ%2faR%d6>DX_fX9{h{F@!h2ota6|MUAqRsV$KFRM2 zPL0BIj|~7t!Pu5q&MRagr%b;3=TR3PsnC(?(LKIJA<|mUw&tDVeR?{ zlMm_hIKB)~JNr|iZ*6?zlUZBjNPew!Y7z>bOs<2)(ir5S3kH5vo`#zpTl!dQR#_I^ zVPC@=H>HTa5v_RDscV@1veM~=yQrC&l=H>XV_mI2wBB4z*7<2NGYt<2jG;zz%!&qR zm)#nPEmpfZ{JMe~J8Ig;UInMcI*~SMWkHvi@*?B=62=x1ODzO8$Y+K`ULt;*kjBzsSJx3cM$7IM#9CuV0ZbpYMUW zrRvVIgAd-Y1I=J9wdYFD1V{$HgIuha!z}IS56lXm9l~6_ajRt*$& zxb8t*i6`(enlp&BIEyuK05L4&7~)a18beff26rtkM_p#OBP^&>;cU+>V=q3}D(DBK zDd+F>ORgg@9z@Q?u4Hzta8Px6OjaIzjmUOBp+asiuoI&3ublU-XJu_LFGg}g3Lm>c zbyoy^1i-Uamg->HaW7gTzAnAYqN9}sria>ZdGAY(m0fFFq^Q|sr5?g)+mfpnD3jY``Rv+{&mE&UrFrH(#?CpgRO zx~L2f=Iw&rpbH*finirz0P;Bh?6N*y<(mC~e`N%#B#;*k_|x-~t^BzKop#hNcfW6O ze=?TR@jijNgP%Fqb(Rs%MMyDp|L!Zk`0E|B^CeDpz7^T`hp`Cl$A;ilZuKf*vj?XUmeuJ`}YA8h;C zX>3X^oO$?*A#%a8GliL2xW8f#;E!euSw!wPOq-rgP2EH3uyKs?BB;`22@Lf=k*n1qA_B@QJd{{--z!n$E_5IvE4i|% zymQOf6u#b)1x8NaDo^8sNn?XA#jr&S9|jt`(l<<2&g}DexSwdr$3Fz>~m z`S`3L83~ZPBbRg2Kb-calVa{zjqXr@*G%dmR-ZwwWBWvIXC#_w$w9iCJXj%xvhK!& zAuxxbUB3%z{f-E*L`%LL;S~H#(FKp`rTvDNfZ1_DHG+L2UUwch9SShS&E@npV~CKFw|qMrW)(ReQdn^;^|04<5?& zPq#k-yOYn zfIa7g>elgGH@>qjTy;)0%5rbIvOusZeV7CZPjeA-fql8!%avA#(=HBV{VZR#Z}(?U zHfOvn?oi#lR{pp)bTvie*J!(~U%_+NR6Uw2=;=SxGkn;E9`am2>6}i_guhtfIR^Nv zeU7?&6nxxfpPt@0BF_wu+INMU)Q4B?v;r@lY(BEPOBC~6KW)?iBhY--fQy2W&e}kg z1J>=`_B;w?a3GeizEx4{zh3}){T_G9x$FY0yZu-+@hXty6>iHmfd8}#q~BF--$E9S zY?f6Xn3!dvFaBMxCS}Vv1Qn0b{Kz+zyX2#)h>8J@ci>+?FO|DQDDIuX?sXn+ zTxYtjRg9+ufx-b+sM`4`H4L4c<|nx?Vz(4vu}=l-LA%6ea(O!kWKQQ3oR;sG^S0>Y~_b8}f(9oC&istEl{4oZ- zd*csu)Dju)t19)?+9@4;5izQ=!0w!{f+<1Zi^!uLQ=qGP9MB}7>pls=?oqv){zL>p zf*JSM&M#UJalTND`QOfL2D<|okF@L%cgGF- z)VEK(er8_>YcS^+p}r|vLgTiHtf(K>UQU%{K}Er!1%e#s3GzHTHGZeG2`J7zF?3fQ zxtI_xpYyap(WDLeTV6Ae zk@*<_QixkfzHY>!|@ek#L2RW|YhqoQOs9d5w1@38@nQ?GGe%h$%wKkqsZ+n9{ z+UF*A%u~L2^(^>`gn7%^L>ROap2~zK3v7 zj9*hrlJxq;Q%i!F1N$wuef=t#Nnp(^G0QBvqKv932CJ!{Js~B+3S6yD1}~MUW8g6$ zWIqfUl84X3{)|&Ju1X5qs!v zAjWUK-sB*X5(<{|63Cx78Pny~fN&GkbI;<3I7SkXRXl)A_gpqIB>O#E(fa+MlKD}&JV5lJGJBM6jqn!6HPD@7b8s+RkT! zKB0o~PynMS(*2$#M2!%sE$mux_2cIv;r*N?A$pDiLCD14VEpkcUGUzw)wTs6orF1mV6A_I z!h0+j^-@aQ0Fs-`yA@E)OBo+hI>klH6-vXy$UIy8aKl&(5Ug<2C9x;u&1xAnc##y0 zvblmr{u7+?9Eq?tVBS2VjR(Qx*I4iWwyd}Gn7%WgH~WpvFRW=#Xe}mi zi31c(*XtB6E7xz^e1eTW|1o~~uiGcyMgZQaJg11Wru?DoiNKlQ04Q|EuAV>wjOA9@ zvEC3=P&w&}a2hzbrou3!2Ls|*kXuCbNKQKRqGCIzcz?&99h7I@+=Wq z?ZV9ntwN77@i0Es_A1@5fx5~3roTXFW~PrZO|{PU-PXS{s@h~O1uqknUF4seiZD;R zP+=yLohr|+oG&G{(8t_S<~Oo7LKZbE-8?d~KN#8{?uKA#Lm;yBn%IqukUdo|$_=kG z3dlj3OqrB+_Buga92GoT@gi}dE2{SHX2M~V`L@Wnvbes(Kkaigh#?lFuc=7kv?hn9 z4S^Us$hdbyo7b&Hmi%z;`2(mZR%S{gn^Vx;V5eZ%aUd@b#*wrZv(|>?MJz$0(ZYBP zjJX!fHP$jc@5Ff$ks;ahTokyVjVU9@qh86D2zAQXJ8J{>XxqR`gptCU4d~EODw?hW zAb#W!>|>kQ3}$zz1WUw2P-ijKWR2fUZ`UY<`#|i~<|ucREE4Bez}#N9#j&S>A5gA; z1H^?O33j`YF*9Omw|-af1vXaP@P2qn?4l3pGlOJ1iDPewx9EUQ%5vZ{3T*1bxG&D&_iJ=K75$6}S}Mtl*Y3dIWX z>%)4KJ7vO06+6P2VT|~Bk-GSAvf=V+Hw|Njun8E{^9=wju}v0O?YDq<IAde;ibj2VD8FZFav2wgj?=4s`u9qOpd_U&KOd`3MkgUD5i}0#csFgPT z4PUx=r_Vjn|Ic?;F@i2)rU8)`bm&{3jAP!Iog5@|-q>4Y3T@a#o*(RV`Y(8x<`$SR zqU^|gjGcy0Hcl+{9!lbRQJnD{6SCtKCDaAh3q^9$OSb_*ueYD$+sEEBB4ilPi=Ob+ zWXR27+b91iEB;ZYFR;PSI~z}V!qux{Z zvY-SxG_pvjQaeFW4J&9Ohx)d;hFT}`O}QJitXf8T+aOb^(nE5BkfV13IHQV{_u!wz zpB_h!yG2*vPAu=|QTAK!CQ{+I=~|waKBBIQj4k7u4IL@u!3>!R`scsk?-mHO0P`wn zqRm9PaK{6XsKzy={Hlv+ZMe&jC!~nqcS%3=hgYwnzO44hkx1UF_ht!b&$((O8XqdV z+4;ZI#Z5x`!SahjF-*xJZQYg@=#VQph2!fZrMaq=L4jn1;C?uNQqs_69Et5Jn{CP- zs#zc_{6!haAGu@j1cnO@lC=V6xu{9%GFjgastScLnyK&@WY`X21DBJ4K256m!AvAu z%bZQl$EsjvA_x-*4D@kSo5n9dC@79m(}-l?4iC~8>&zZg<{iU(A${Kx`=yhw%2Nny zGYk3Z;P|KG4w2D(C@p((CAi(}s>pJ=<0PcYyn^={%hMF~EskGH!IugV{nG6=(wK5=> zxVwL^N0HYV&7V~tlHq1-0t1(4;wq0QPP#avG|o1T63oIM7|7z;7b$E%Jzw)|8uy#hy zppFNU=1t-7(XvTzNeKm|P%<;-knDqybg$CGpGB~L_`gA#9LwdsLUP84arYz@Pe3GK zZU~`az5-iO!Qq;Hpwm`^CE=P$Y63#cxI*)b{@h?$QBE0t&_X~flVY<#D%KjWJ-+T* zkw5LKo%%F_z;WbCBYoH8?|k}4z?T1s6Yx|iSTw$B>XfJUrdo!o|AF;|yyl*dH%FK@ zNs_gF;PjQRCA?K7FqB-7EIP*J)~P-3^95_{^pTegexdh;aQI>)aNUS{uI*_#} z&8#Lx_5qGDwnXwwTi>WuDAp^P(MDEjCago>P)Rn{%e^p-(4lpoe4~`sRUDvvrp98v z+V2|mGRJcGl=V>$y*$Xeo(f#fujD-MfnI`!}VGo9C}-ZCXV$RC~4WH~ixlIwg<8%W3d z8m}1v?^YvcMgo(>rMbz^vJtFSOVl~6MWTwYP5WWUK&AcU@4+&}X6cIp!jui4Roru& z%P&mKL#b~dRKyV{Wgwgg+Z{SUGJY~%a$&jHVh?_(uvA3j1p+na(T4sX;5? z!K}`#hB6r;Xz6;9mX%^;2{91g8eMY z!~=*5y3gz5*G{vbt>}H4_W?i@z}&yyAKcs+jh$d=U$y^>t8iF?&h1fB$0tL;w*|wh zybVN{0SV}bGjw_A5C4g$dtUvZLFxch5vWtq62JfT;MZ(57Soc%Lu90#jvyq18!Q(h zCf)t3`giYNWanmD0I^Hj=7ThK8JJ&d^(@Cok!ay%*%zL#QUy10vx{^UvX>>0DHogN z#MZ>jc3NV0hV)rX_^djW?0Dw66nlT%6F=7b46v>~(po-O)*e_KXLx!@ik3j`;s**g z6iF7ax@Kckp{03ZOb~!BND~9!@qtq2bU(D)8Ac!wQP3R9sRfe8#!ww+vV|2WAhV@> z-i<`xR3?5DOI5TH_U`MA4DBLXQ*Z_;>Pj_@P_vW-iOV6kd8-o38r(>TQi=9@dm(REOujoCr$Gpkm#d#uC|)$ znoi+KqD9#W9SxRln}dr#QtXbWNLhet3{i<2@VgVgD60E8H`V9Xg2Jd1q?u;u7QUk6 zx#ix6n~n?*9E0R9Vk}H1qx_XfX-_r%kd-`PV$W%`&zIsf;dJ0@t!37FrivJ^`|!A- ziNOuf;<~>>3V$&z(cl^^b9kIX3ca9C97(zJ562vWKmEepc{xERnH~)#I?O*cl92|szoDiUHU1#z>oW`F1 zrwxt6i>i!3sO5}3lt;?4pVG2U1YMdul#m~hm$OJ44zPPqk@JNG@K8B}pzz47>x~nW zu>@>TkB}On>JDOcpCgJ`8^lLhm zMs>pK{#b$p$Qru@HaR?N$wI_l{0w9DuTe$HhEd>6X31Z_bd4n z&D*bJr_6mdAA_pT<~-a3hSF-!Gb({e2tQ$gT&9D6;=!)~2kwGozTOA#>&VGYjClE`+(yx z0dqjLp@2p39_rP?qLgu4BUl+~jSV$NA1H5#{XO&Y;LylP1g5a@dh~de8!UZ6w$!?- zgjNLq)1y7lH_<(=GH5HmRKtlQ(a9STvbds6`!P(=rvC#;_eY18r;7ad;2l$5h$Q9Z zJDee3*aAE__UwQjzo%qHNAx$orVvCd$LwjDzhO9=@O5N%nPTFdbb(cJ>=_tb`eQDN z8rO`70Rh(1K>PDG$7U;qFiq`e5StF6vQSox3jyw2v)twf_pPYX>v6Bg>{)UWj(XJhszUB*P4{6-vg#QjPeP%AuEM8^v`Mh zIs+q{$Z6gY*~95g|Fq{mfm4gzh9I!m<9HviE0vyW^{fK7mZ+QSYC9H&zuuuZ8yBns z-?$O7?)S{sqP@f~dxpV+M_hmLs43rOF+yd0j!GFZ%OSoA~SU zTghUH$Up;-ZVyoZPIu(l#msl$3BJ!h!$J){(0QImTI*4+F*B($14D*|31i8mOTzgR z>lLMimyZ)mJ|k6{b!yvm=|ih+;S$FX9*d> z!3He;$?}wwA_i2m-jw_frj2}ze4?#ZtxnM%O7zVHhO>zG1c@IlOy6H0l*LU6H*^kX()(*4 zrPEIN-6-_T2ZMYMgfX5lCeeAwiP4Suejb6dY`yOEeWzO%sY{$?NA-HERF=eDV0{mZEt(EueZTIHeGrKZO}lIe5(;d z>O7yi;Yqi>gF0F6zao4Vg$gGPDw%*`AcBn)XSWN#%-h?gt8-pZc{yxdSJM0*Q8D-v=&xlhAnspOJ=e8o?JhBQ%VnV6*W z4Cy+$0&;G=Sjz?-U5}!6h{5OwleCTqV=WF#dc|;uI&QesjlwwdGY*v(%G^I!? z-VOpd*NaJkR3`gYxgg|I6?uHX|6bsX~dE2zHcb`hwGZ<`Myc5u6 zH+a29W=@7^3e*WpXWZ`?Z0JcCo{=v)YgXbsN)%}=BVb;_@rU0n{&0I<#o1DZ5B{!7 z3ZlJvTS0YV)B?9*4++%KOKxPz(sHs$+03jQv@EY<$RtuC8x5o?2RZ$G>FUW6X+w zm8l>azmMy%JN*g*Xm+gnp_0~f1qL*40}l)rW_a|vq|n#HoVxLdC@X=t&Fs8B^qlr+ z_$DZRAFy*A6sJ14^?Mb<;b!L)L%7&|qs-8?rE5>J-|yP_4ZL#_IF{zwn2wS--YVbt zH31gQ^>a22k}MeWAx07|H6uW<@@6%X>yBPTjR~ z)1T(-iB264m{*D(?5y>yke@F6Xj-1)=wmSx=d=mD%3;@62^X+`P5C3=I)l0XPPYz5 z_T-1)Nkh_`{jJ&fxf$4C4NmgFg~Spx>}>WVrRh30Ml(s~jm!a^KfnE7$__RST{Mcw z{Ii<8?&hJ=wQv0>Z>xu5W#Q_=IHXS)9y8;I8hh8B{U27kHLAkY%Tt2w}I;Mc>xBaIfeZJK1QF*JL8%c zy-0-VY{{d18GKKehRb_;VJXU85`pyAJu*1@#$cOqaI5)?y;G=of1C}P86M%|rm$sr zlJ8_w;Jcw_I5%v$Y)n2IVjoJYs%YiACBE&OPtz@m*-XEF<%)e5&60L^n+8qI%Q3PP znCRoDe$G5Zf4)&|Tw)WMQMhc*%1Z-T_O#EdgDknLJ1}NBv}ZVHo@q~WKE{$UV-MWe z%mOjAp7y!m4Cx^Mt$$3rmsXSgnp*xciMXj;r^;FL7tH|u6pvVUSo5qEOZhEb`O>Sr z0s@e;H%*s3Q1zd#c^Zz&yO*Q&uCy_GQoLzA+1S}iAOA)6#zf8{#?3QM3TLdBM)+nU zvf(P{4>kxuDlunzsWjZ8Xi|tslZ+pb=%|abHcTKU9z~weBS0C(jrQdDfOYJ#2|xdB z$ICkDOF|bZV$=)pCbfBIIs-zQBBxd47bs6}XS&Z4J&?t9Gi zqYIy#j5p<~;#F|D1}ni~F0)z$wM=g()Rt~VE5X$SIh^|m@hOA8Ga|twm48dljV=S_ zymP)Qj=5>>$SM1p=;OXiEuHmg3-4WRpEV1w32kJzu+i)+wW$hi;OmM|eKpM4rD7Sj zGbU@c`7Y_b{w{%~tC-FVR;irFDvFhv`Wj4a4U)$c#p+0vKH z2{?f{H8=jFKHMzn3(zgq#pv!T8UQ%=)`b|~DgAshJn(fA@ta>{IqMyakgIxS%wc?s zDnoKy7!M&vt`E=z`Az(6mWH=4ju|2-t;wI41F1#9Hzm#ktH#FO&=1BJo;IE{UqRbQ z`;RwHuyP6d8VPpljc~|J!Tk7MQhdntlqZq z(785h@`=L47^LCl{hU<)Nub+hWG_L8lQ96cFsaB&R0uV=Lwyey%TLew_)m%h8)?pY zvkOF^6JMShspPc*vP%J*qnccUz=YPKqYrQuB|xe1{gU?D!8SxPS> zNd+2gmS?VcFHIqxq+=a$^hp(}+8Ac*I7!Nht=e7U*<f=As;idO2j38Y!u+!Rak&zo<26&iLcZWqM=^IaGKA+U81YB9EzKu zVE3Sr5-cUUhq8n9)J3^_l@x7x@Ot-=wqErs8bT{U!`vakX@8G;`y%xii+O}X|P5ijGbz$D<6!=;-;!zHL>)=~yzmW71qVMm1 z4wYIAjP+{Gh`?K2Ag0^@EP@T^yZUp9* zlpJrE=#F1Z6bPeaksxKps}C2{eO&{Z^%)bkbJEXKQZAP#HR-h!LjYGHYA^+x07Mys zqaaH@Q)uY7$zVWtoqYyou{%C(Xmv14u6%Mwq&)|hR4AlodxR6KM*M8uN|`N-e@iXB zEA8f9=A~~Y-U4YIo47_j6g7^@lM;y8q_~VuHSlL4l+yE;Qz2w8#02;B6ig9PNV&ux zm7xGiE*FcQBYL|(p|2{A@c}+$UY5Qhlna0AK_+@2_$sfFy}T>ub7Bqgok_C3TiZn% zfdWSk)_9?soE(Ci)=?r9#)OWilj60_##qx^R=Lk5%Lh{JwM78F9?A=O&infPY<^;e z!Qf=W1`WCI;;)a4HoZ-|ufKdNtuV$(MB8@9Jh!`YXP9s(f`bHWg_f1oy(;JI*(B=Y$~ zmxt$_=ET%s&}owEq%J7*uqz6qwmk&cixR`$1T&8nwu*(60UI{&3!jb8J`5j&M~Kg| zbMZ>x>~c(cpoNP&C~3=g7pbOUcIF2=yRAiLC7X+SL~ThzJP1raeI0{MV4I}fW}q27 zUWI6^TzIMU_Q=>rfwf$dlsAV1Q@_2`YkVt@{W52OcT%e16c4chDTrWtzf0~G*<8ti zIBoBy@OWNJ*%Rfp41+hicPUL-e0GtaRc{kNz^CV39;#SjO;+1*-6bBm@ zwNq8DT6d55E{*d;Shu+IibLpLI2&wyg8*Biew2kd2Vqt;*uAGf*0`@_v3@PP?K2hG zgd0QSZ%>&yhi6fY!`2W$R@E)O_N;;W6-8OlM|I#}FHy*)4iaQg8x-E+b9&f3ykTBQ zzn5f;d32ACn$puYhFNs#CC4r%V6F~-bS$Q~3xz{%J@BSVzyrVrHBg*Ez@=&K1&<9D zTd9K@q@A&Qhwx`C8C-u@kf(6fQz6J{#nozu%g%vxuUl@sy#JHJO%dd1zKl?t6a)60 zb~wvi>%p~=`=0YC#IK8vd+1Q{r4nq)Qk+ z)Q~feKIvq2>>DI?jL>r)YJd=YJeo#xK$^tG@g!kOg)ZrXK2REx5bG2C0`3e?(rFp0iYbuF2i6$t~Vy(eDVk@FOS zZJszFN0e^VRDyAT#!CIwaLD28o`6Pt5*ef-Qm=^={142UDKV=_OEumh;(<$i`Riz; zLblinN&(v0-?z0U*tytsYmxnqkQq{LBV2}5t}2HGh<>L1Cr!V8)ao93Ivwk}Xs!cx zj&$nsi#0Ye`YUk!HI4w~oCA_nM#VZil*#QbXNfUBbeR5BX(5Omv@w`~`D+ZUslqk) zBJZGU!V8K2tP`)zWr~G1!NEh&_Pdu3dXDbim*gO$YVDApSfw+;txZ6WM6G)gJ{67Gqehr*9(c?Hh6o z*^Pre*p{xJ9(yVKnvRQg9Fxk-vfGK_*szG;R?WEFrD7N7Y>?3i3<8*Z6NK>j@SN!( z4~k@rYB0CEaC_eFLFDL!l6hai3E;sDR@cdO!_&J{Q(t#^v@_CJ_0tY>`_wcp?u!l6 zVl*2SxXhH8Ds26jB}FQw!m3y*3PxMazTSlR$~X-o?f~UJfTGl_I+qUhj*tTukwr$(CS8Ut9+3mjU{d}taLA6;EV}7Ie zcJGcTHj=L(xF6Gs^0a@Vbk$A$)Kw&%_-|kf-Wt&VZpeS|mQt6I-w4xfdy=LK4Zb)r zK|ivb-z-f>-B<&hWq1!I=CCWaxir@+aS1hO?`e!OGE?FB1RBNbh z!+On*osJNJeTB$6j;3cnziPem$e46M$a||5gg73FsP95@#@DGYv2t!#9m0v|!W&TM z6GC)X3&l&yQxZT)*1?n+gz|KAn88ke5p?rc=_zf^E@!qqi9`O)r6RG=!bCbO_RFo? zrzwxTxFGz;Lxo*~AW3u!BP(&6O**xevI)aKw+}sD*2ASFj8|Q(+4t57IBl(bWfBuO z#8I zSX@R!+YFD99*N-zvB~9x028_udW{g)uNXuU(KJl*{JE@W$*=S|tlHbb0F=R&8-8u# zk?~-Q2oGcNg|BMcVa+$2lsjB32=a>A{`zis#1uE`DYSmYJNT)$@8Lbnr-hqW1ZE~r zWn({m?__DpXkvX5u2rPBNJ>4R*iu@7hL(RJU}C7`Q=mu~l`40pLbBxZm4;a!G+`Ha zFtN5`Ebi|CPcT*o)VKVAWyYa*8^_M1;pOC`Z5Yfaq2K!O{o8=VK3j$2(6e`>x2%yd z9aqszLJ>)y?qwcxn!~r1rr*4t3Ci%5z{!Y#J-qIcw`1r`_pQ1iHSPA&<(RxIo*i(cS@pGg;u76T{!M=1TuG}c+EGc26S*19jVz*;4j^$E z$xW?qUFc4w84r3_L?HhWp-0gJ09wYIEnBrIEUFJ6Mxwq(f=CaAxk zyjurJJo)W=^9)g+ONT(KFs-8`bAlP**~|;~c2P`MCV2)l!(HrZ2%CO8A6C77k?V^% z+2;$%gd+*vrp`z>^Se?kV#v0gyb>s?X9FX$NLZSVfuM@+BpB+PBH1(!(KJ9aBzOPA zrneB>@VoS~+`iF6!!k;pKO;{8=1-C!eZr$I<-b<6GqlW6{DpPZYQpmC<^0Uzvasfa zZ|foVw+EWyHW>6f+~RNn2r*5F)ZBoBfY=A@;sadAk8X#yo2Y&dloQ`Lun>;mId6uQmY>uu3?iWV}L=a zmw!Nxk%t4D#2QxQPv)(aZx3=B#w5Bsf9bn$ToROkcX+F6XQlWe+EuVzwX-6Zog&u^ zFq}WZ_uDyAVs~GEL6q8=jkF?aTJ1{08?*yYRm3`q3~v%uT_fyPA=^&my5nTCP}67C z9|O=+Orwj8nyLyNPB1_?Y}SO5S)kd$tr)Wb7Z{DdN0DUF*UVSkqD_jHDKZ3kM5^}M zH?|eo6*A{?cYg!o{!U{wuf9E6akId5<#U;gnZ%KPz+=tV7YT3H52ybm!~4(R`MiEo zdru#dgu04ovfx5B>5l8!x(k&=0X%Ws7U>HDQPih=-ZuPzU<{kPe-vJBVqXLl$u{1b z4w1SugL50}aiO&t0;&^9sZmqc;8H<4lzg!~8}oVlX~5cIq7qu9DsZYd^rq&u40Chc zPhF^7_rHWXcWiqs;WGpCoi~(Z1QLfb-#ZZa+FMmd`TGWMS9lgw@6pQDw^X)xi+gQQYAzdmmn{JMOi#;a z*~C#jU&T)D-%dkG<_>#!De4CIq_wq9J_dVxRFl1~@+zDc9HStw_ow9V!)qvsQnyYO z`IiV{u8~#34UlP3m!70He#8Tu`V|x8dR*whta~!`u&M5>7TYVhC{+j8S~uUnvs}St z+)(ii8!)vWGK<>@*Z~L9q0ONN3o%TDm!(<)$6a~~M1IbZl(D9+R9aVUTDBLTq^ctq zTY7xWUt7F=?(EeWPssxRs*knYtu)VsH=t7q%{m|lZOP?-DH00f8w9fx+sG-x`BKbM-hF^ie2&sM<{N7y}Akt)GF+%YLIbNT0(n5v9 zQSkP=H2ag!HWA^DYuiD6Xd2z9n2SdxbpSy9i87kR#rgyhG84;1r2#ZaDug#qqxm~& z(NHKoj$S#4-Q*wBKdOm0Jo#V{q>^+=l{kC1ICj#2Se02n5h^id!mPiouRx7MSF6yu zzUko)V|s$f%J5+h1HzxBUWwgl0?ySo z8f_`l(2U-uUcF;M&;VojgQa>3(RC1*gak(VHVL%Z$uZsh%bk~rV`fRg)Wqqd!|9?$ zE^BG=ki~2jPODkovY2x_W=m6vBueVA!ryk;*4EY%&^_6W?d9n;`zqYRw&4bpvd-4p z;%B;zb@We^Yz6!motumU?#{C^Wno}Gh6JMvH>Wkz)6)yGtZvWZ5kY! zOA~G(`c7SNAG?ddX{tWampOg+qw9zzs(hEH%<(Okt8~W$|GYM>wP#!dEW=|RCY8S@ z7l>j+GD>-T9H{bb5iWVHQQn6efkBFLRs{2FDl&-B-M)@*^N@R1rr8haucsLZrJMYT+Y z$Z|zXAN!(ufyBh$gSDYHEXC$`pX{u{*uW_NO4L!&Fcq=Ry5|g6v0(y+4MiWI;R z`dmIxvXp2%V6{KQo2aFJoDLwE8D(SW4}P19fjY}vW{Ti+0o~p(f7rJh3(;08;stF` zw8TTi(e?*pg8~^+bLV(V$uZWWV0*ygIiIS-GxBAed^ymD{Sj&Tw`AA}igK>qeBtt> z!wV-@p68#`-i0Q=qNW@x%fh0*JytDbnyW;sAJPk$kYz#via#}u_)+r96)3;v(N6Q9 zY}n1IiPlS>^Y*m2-?kaJG?}wlvX-G#H~E826PY{dvt-a(=NwNI1_4VqQkWhqeeFQL z0#JGM9<;}8F4Y2X!f^>Z5{fq4ped{nm@)(+JTnYlMRPbeiJ?Ee1Zj~WI4%t>>q`!Euw^ObyC5YbRsT7!;~$F zz6_e{wNg?1x7>Lfg!YD&&u?>=>Z$=drxBa==os_mD-wMWoo!Y#Bzj-m zW;wv;3A9myf{@CicJIrbJ}>`wZ|e&x>frztlC4iv>~G8f?@?#KWy*)j=@04}0A7Tj zjnbTLd6raodvkm?_*`-OF9f4zz?vmQu8#)TY=@&6(Y0z|E=jPN>~1_Kx`@Jh+k+w` z6MmIrRRQGnhD>0nz{Q^a8Fx-@_%{Ae!vT`(tnc8WdjoGV#Lqu^(sh>~n)(@DlvxWwPd`(pJSi$I`h$gJ-9=Cv9q>2Hi7@TPl>vFft zSC>ng_%E*jh`Xw?oe0d9LJ{2=j+eYi)We1%-;aFwc(9B*N}w|U(up~K{o&&a0p5v} zEBvsNA-48Abx*Q==r3e~hrZ{Lmxv>|)QQ-GD)((rMI!_v-fM3Et3Rc&+rCkYj{e)q z?EqBc>;ro3e9f(O{hu!GAK?GhVFcV`6Gf8%0N^A80EqsdbQpH}4*J$K&Q9i5|HWRs z;<2>dm~hznqGE0LgFhN`u$hMs#-~Klv=8HKp&BRSA&2r$A+FEZ3wA%dHhs1HM5taY6TO~Qd7iV>5Wa z2tf)Ug#I#Tu{{*+kzG@CTqx@$1JNIjrh{Bqujzq>pwwOf04p2+*NQQ&Fw?mH{zrCF zT;?C(lo%LEyIa@K7<@HSTIB%ULZ@`Bzyh}1a~x^f$*dOVc$m5JPxsOKamus zRtoyuQ)63nyssWYde|aIS9H7zKyqkR6sQvTnjIWF5PAeC3IR@mSUk-HnGxQ&MuGY; z(;<~vD#75n%14-0<1*lWpPc z=c2GzM+ZB0%!q-VJD4pUS>f&A^q~c_D7`JXq1k831XyZs_+IZXi}0Yn4J-Wi;YkGI zHZO2~*8vG`R2xwzM`trDIQ2vukbdZB8N^>JD0dKYDND<_{K7)Y{z<_LFGiNH|6o_h z4N=yokd`kbQR?#gU^z^+x(zRibnk3>SdX~IR&-VEAiwV}JNRHRQsC9yZ3P%7PnY4- z*^LA7KrS#6+O-YhW`R6|f3TUyxMM${GPfk!mpagVn5au4d zoRC}WQ^p_xSkYc*lC`^AUE4f7l!(UulYWjUhBay2w4%k#`CF!aIAY8lFATYX@o6LS zncA9}u*-wJ)74uic3vcOHABM9X*cn)ELc+DbG$r&y*#kbZ#yQq@SwdTBX+DUExCcp zNw}#u^gIMTPQMjX;fqQs9HxhvTZ>2R08x)QE2rU9IUzSb!F!}-F!2}$`5Pw#wLn_` zG-i4x9eWP$UWnPy)KZ};yI{YbpaXqyQaT*N;5bh37(W|ZvrBe!KWv#*vDEBN=1#&- zaxl~0kg(n=_)mH`k`IJ8Sw4yL7Z)?VSt_)hNM}wW0l-Qh$N(@^`Y`Hv?y3|9NkkN; zO7hU+=z@b@`==2R4f>?pNn5tM?}ETMmvHzC%Kh$AjvNwhO=9RlzyT^O>#JEMspT-n(p`8sxSxEw&o1UAlNT|7N;~kG=fPTU_@8`}?vm@>ic#UtX-f@1Q z(fPoyiZI+d@`6RK51ICmb_X2*pGC%4ez=WV_mJ#syaP;qGoAIs7I>wM0dlCU?sqIL znqOZNvWE4S7 zJrHgEH=Hy&ISYfo&Y5)@Eh9#t-3~||6(G&l?+u93c`+3f#%dD?PRWvnX=qaeyAd^z zM(v`p7Lc~w=QnPJMVQtXgpP!t@`c&S$2{Cc;)Zhr2#{?_sauDf$%~m=8q)Ic{&JD*X=J~{yB zTL{&Sm6)}2?}?08GF}s*s?r&<3uXm3tyKhZYnbpGOj%qJ$1DK|oYb-J4bGa0^~_JI zzd&b*Bg{0YPQ0f-tgnuwfToB=l|aS(J%S~yASW#kGuUL!yXmig@uL%dX%Uq8n!q^q zEQqoKX$DH_k=WBCF`8 zUB#jB%ypqx?0Y8CKc%3RWbWSOT&22CIz|_^G1xTP-@#VZtf(MPc>5hQY;_XxJJH^P z!t9$}kaop638@wq0f!mm3up~hDbYN9JY%Z1%(n!Q1^9E=@SnOZ+$`@BlftR$pRouX z>sH&Qj$a~_y`>!Zu$!5CGOsn4uC_5+HAi2GgJ*rFD~M5A)Rc z1WG3rPnu50Ryy}gKphc`sWx5$qG>Dk<&|Uh`GoZVh5q4dl!Le|tw7%upl15jSmfIs zD$Zi1lE_+8w2|=wymyexBkc=!sU2kV?b|^GQaMQy%XgRFwJJ`Nx7M4YT4F5e-Sxjm zrARGdf=*1Lo@Z?sPtnAS?|v(w9-^&t?TXN52@rnM;pn8>Gua}1eCcz-bF%(1TgEgq z@hasXODk>#%h~!STLb3F>54!Ni>V;r4~4)p1r<`Ts$dUGTYS`+)%M(Uhn=704~Roa zmsm2n$TEr$MO3LLcKicGpM3l=W{itCohOsu9>yMn;W8tM)0K}Tp?ed9T%Z=DN#YO1sPs zv};FSgAYcut{#j4g@G>{u)oWh;&X%`C%eh8ZL+Qi6Q31q4Wg1}k_x^n&;O6Ml=xYP z#G-h7fzTq}I_KVOnOH3!PLLnUaxP&KLLqNjDQVU^9y~}pnJ#Xx=5%D@6htPiw)EA@ zs5@13Pi4KgK4*+ByR?JuB1&)bwYTgUN%|sltM_UxiV9N z$3JwFJ#Q56Yx_njTu-xFRcM&2+HSo=3XL$&Z$1;bo=U1L7LWS5t?K4!j1}gkjsx5O zHkP!sSu~lWT$9|+A{{UMrsOQgremkJrP?+E8So+13%PGHnE4$g&Gm*7WTzPlSOyBL zy4ZJ-yq)WoyY*)F8V+=#f16XJ)Bc9vdAsfJbDu0|#UPXm*`68G3|_2$XABn5IHJ^8 zlf7g#TOYLpdSMg~2O?VPSgP+^iHPBxf)%+TRol0*a?uPB z=(z##BYuL${u6f76a?G=wX{z`u(<3hrwl)?w15*1+rX)#CQV`{NrmD7BX5owFlx8E z;=bs(JVyFg9LG87ivBKm@o>Ts+ipmIS#(2Fgk+-f@(huL@Tz=`pgoPTj^s&-LKSDB zfIN0H_ldj&kHXLw1aJ;Z1t zG)%#+sFamCyAy4EwmTm6lXwa7Jn(1V&vE)vN-@bt6>Nj548&q*1$i z(KWMZM>87M#zH`TN=(v`88QPhWRDD7G2M?5iMo_gF=|sf2_ay?MGWiQT&?j9I;P~x zdAJh2!Za(Updx7->%@3q2-I6oLe!XYu#sBxSX2lYR$oK`DuFI;A>=iUEapo*Tpz@I zP>6+VUd~>p;1ArQhV0k53O~UVC3{k2p7kFts$pw<=`_p^f_#0QPSsF)wY!NRk@A1c zc|V+_4j|DbfS-ol11^hxe>L|iYe<_~3O zwxbu!B$^?3VT7GixVnox)D_w{Q1$9F`eVZw1EF;g~;qUP^ohF5}!g}s>bwQ`W zIRbOah;wO+5cU}j*}=G`zeOq17X1)!*<=j^X!AIB1ywgAl*EZq>#UK(2$CGe`LxIi%dwi+yI+(WT=Y!`;}tS%9ilo__wwbaS}6DOch&Ltb0u+X9K!nj%j!KAZZH{ zIgcc1(aXeQ;&V|95fcHfE~$MGf`B0C%}e~?F>VA1@k57p!FCLdQxrphiz|_7GuB}x z`M82;Aatj0(yWve_e3-T9?-yR^52khYYb$CM>~7&Lwkp3EGeHEapFn*d=v>vM*x)? z!i~=+8Hr94Ep^exTJ0+sOAYCCpEUee79HNj5){!(JNJ=U4N4}8a)vwr$PG5Uok~vgK{d-Ddg8P2cF1F4hl~I)dE4svV58Y>zK&%&V{&-I_U>mB#I>^KY7eZ!nC8Wb9j57<^bGO1rkch05Rcb$Cy5D=vkS3bPkgJd`9E)(uGA_r%`3t^l5Qni&Dpy`W1C#PLnIe{G~;{ z7z$eZLGq<~fPk@si^pPlQ1X&2%qiL^Qwx8F)!l3FmUo{}O#(O`bKG@kwDBZ=?;W{= z`d42jjEpB&UPjZsVG1f%94|2o;7FyKbWZO7rO5tq)FUklszmUr$-N`g$#5U;X%MJA zNxt=2LXg!BE5q;7K2SA=f=qV>_#Hs{Oh}8I>;pm1eutX!YTY91ED57ZrK(V&L<9pH z>DI0XgHrJwQjt{QJ(=smo$fNZ{FLsS0lvO%9xZlun_%qbVWYvdxoWzy5D(8f-68?5 zmOdFDcQ%BiUk?0Aj%w=BIlix1?3qbz9G);^zs;zIiMnW-4i!}<_a+X|5b_kZpPrE7 zj3SV3ULt$LO>6AKG_~^5aj9naC1=<4g}VLM>)^5> z7Uc=CSi=!Z-}oNUaf08m#TONV`U@lf+nqHh;R#8_^9!#2Pty7B?VQnrrUulvi@nUM zzbgztr5iZp?J_fc@g?LRn7Y?6;n&XdVD+_V!{ZCRRemRAx3O&{*nof4L@zi&!I}1B z7hq=1l@!}Y)X^j;xXt|LYfIZ8@-}Zh84`%sCv8zyDdKVF<8Uk*U%xuI-aN_h29b2n z<$7p+$@+dM5x#6f0N6KQ0685*`k{eTFTIcm#dD~*-sTe{m zzAzlJi8&)=TY&6qra6DPaq8=E_zNtTk^}T0So%%v6gwLp68=OrA>i14YC=I=El))h z92n^XMgKV#lRZgj*mRYADRUul^`?RN#PeeEKZ|{qT#Cw=famqA^+a@#NhEaL)nwRT3lZX0mfwYy_33=k z^29w8f@XxpSQ1D6>tuSugknbr7atr8OeP4)NSEyY*L4lhf}@8q)>sFawS zZ40uEw+`I>f!l%Oc9H}mY=1tj0Gnu?Y+{2Y)5n?g>(J(FkC5G(d@wC%{!$%w1GL;y z6zT1BU3Wf#9kytM! zcKt*Pyo70qD{ z7?83Cj&sN@*<%G_>MGk~14HiWXH({$`KMhTJ8-tO5%l0O3B4?hcmT0j|FLteX*j z)HrsPTd^^l)05>)mQRu_>>5^e&Q#ymVBKmd%_VJmlO`KEt^N=obPPd8qsO3whFTb#^tvF-v11HVvY$SslHXCkDz+xdFI_{AUH#o)Q5`JwiHFdr;uJyi z9O@bsLIdLu+}vgD?fbLC!E`>F;ShMU(S;pBzaS1vRgGj4Pd)l|3AGbwz;&W4er)Hu2MX+K#~G1o!!5bf1#$uO*6~&uCXxh zRf#!(?P7Wov;5j-#)rEx+%hrX09-s^lA7$S($(e^ER2Bgfic8Hdd_cHfp-O~X`+U9 z7?aXf{r#iVgZfW1{60tEzG(LvOX~h6?BtVWfcmJD)ufb*ozQse8`tg#$$~tWCB-V} zQ1q7WvHJ*0n4x9?^9?v8sfiQm&#D*uc=8$Eu%8cqB8cAoBkU9W=5SR-&!cCC7lj56 zA>xhaDr8VgH?YSwZ`&PfupKWlmW8A1#4n*Vb=DQACSSy3t!%XDjx`|UT7mT&{}F0T zBmzs(Yf96Wu~3>mv)F|)G9R!M?J{VzjenQXvGITBv`&huJ_F}Y=2tS?;jNY*bdZ#{ z+lrtxMzNf|;JbcRJ5ecm7ND`&-yS>PwIXi7j6@nzn%Xepo@vO@_?-yLu`Qpy-g9xtcMt?6MtaFiEbaos)dRs-I&y1N>@TK3u|TWFiX z^XsUXAl*&Z?cc9q`->U`*p2K}{*CGW@ImuZN@l+#*F~SbJ)_ zi9@YP0*0Q+x+4t)5UV+nL{FvRWJkV)k$gHxAW;hC60<2$cJypWLLWL(_s)ba@m{aP znH};+?>n7nvf3(Im;7srxyJk*I(zImb4cD5+Cq>DEYjV4j_du%q>*LshDpITrFwAz z5A=v<3HJ98_D$%~B11v`o#%!T<%zmGDW)jEn=hXd-K~_X+S7~i#JB|1x2K@6$39ew z2m#xN22SbUh?&yAVzXQqj^*a`P$Xj;;uk2}x{#QSRcQHk5#XrWN!eK8J{SffQsm!iUQrI?@qUWv7d%O21hKANw6{EFl;>=nvJ&P`wCA<&^ znX?t-gemZ9{qm)Z))sySJnKn)onu)94J<;lF&AktK=Dq}m zlp?y3k**_v#{`NhIsF4IXI@W9)&Neaa`NIaEhayREGA^^^9H}th|!} zuo#vBdSZ<_%X+w@F7zH=`7s`-*2M`l)K=TE!j>I%1imFY!|ZSAllG48iuwIF8^>3J zd*sbc+vj`}E7*z19y6oB7erR@ZUO%5LHSCvJ*>s8>tFU$Fy40^54%8Avvo}x=S)it ziK?r``C7O+uoWDyJtKA8f7P#|dg$$=$ynMMJuphKji2|^==r@u8w|<>1|KH=DnM`!#VWvvupcS}KN&$X zLc*ek{}!AIXPH<|oT4okf#f;ZBN!a5tFkD=lnEFdp%9Y! z_X<~2yZ=sMtqY6RG{+k}V=)jjf!D0BCQ=DoXSZGC51@R3#eR)(I>_`#M&R!B$w+$d z(?q%52R;mwlcZIe!(L`2F>V@z3*sQ0ZyVyUheff|N!JYt0)3OgBf>H{8fboVAJa3h z=&ed^MbexkUk21+P}8l#2W|H%1^=9eY2#&iiHcpPp3(6xKnULZ{{#L*Hr>uvHw;`# zlVGyPrZTQxGiJyIFnMme5SzSYI{nV2K8?z1Jd+WT>1c|Z=YS-Q6yPkI*G_U39U1xh z%X5nCcMjv-<<{{hKgrhpq!my1OGe`n9Y>PWN{a=HQ^tqo)BWPi(t();FYT?*+nAG2>TNs47jE6nEep9QlLi_l}@_2tL&lejbp$+sLWO!kJg za5PdWnNJU7bpsf=gsPu4H%8n&o&#&1*g-CUHh+8N`nL|5^E&&swvS^h?)evZ=eoB* z$+G(6#p8Bn+sjk?hx9T;i?QlvEuX45(xjAE`F_bp}nXC7XLY)kY4?dHX@WkpW*vwmGaHCp~rhoh|G-P)cl zBJkHHo>vPao=PWSKJFjfUeZ?ZHiUeY>9;dWYO;OB%s`LB#3XK8fums zd^s9y7#S3h$G@d^X`8`Dru?%j|*f6uSBUXkB1Rmei zWUDdBH_2Zqo>HlB!=z~(Y7ZA>Pue>`94CAbN(*?bx(JN)R^Mztd__IwSKB<`f_*nR;jwIrRIvVBTGY-Hn>6#QwPErLQ!dD(zwUK+h8cFH; zX6p)zE8Xb_>}d%&?~ZV80+(HnR%qD#>Y2yOa*!kc zFiX9qs>702;FQ^0{BpOiM^|>Bu_omJgoKk5Y~=Xi0Ap|fCl@> zjk7FYtX%2uW%15nH*oK>(R@+QG7k=(TzFAHjbgugZZ zUC-^P`7L6f>@9Xs>G|UbamUA(r`o;DGX{7pu34U2{WmXXK8w&(CD;nfb`!d%Gop^H zm3Ivp@JqO_N^0snvNmQp;p3>6FCYQ1;c1?(vM1HwEA3Sriy{BecTcC|9Ogy)-DeEJ zNS~`!JS~Xc5A+9FPb_$PwHToxG(GRtKcX@(h8eNEQ^DRv#W^H3HKqJAMTGYvM4IF^ z?4Ub*v)-=6P+dt| zx3i$r!CcQ1`i}8*JoxguQQsy!foNblaqPF9C;J{ICu0rnN`Y(Zf1 zN8**1H93~gM_HswYE3J@d<0&iT)%h%*G5A+!L09>H#y9VKGC8|AT@x4maQ0?X=@+p zNSm<6CojuqxzK>XJj9Ii@~xUR=e1vCtjUq5ZU6K(vch68-OYjs?UdMlO2c4RPpWU% z3LC6;r(e~=P3wAl7BmL=T%rvFe=+pFe;!aLr{1gB_AI)dqGFZ=?Rr~iSop@)?877jH;hb-9@;sikP{4t$|GEH0;yhYtKvxkz_GiEN zr>kKZG{`M6YP%?3Bf;EQsX7k$@sg_5pt>&kv;a(4aLxL#(+#2LpYA)!!{;|Y$i2aY z);6@LYQ>MVxXN~|y-)I-lP+&u;WLu&9ceRLO|^rs-nJ)KwYg&L9#w)kdG7sanTngI z;R;#czMqMz^IkFA3c6D3^&Fc`4P@Z24fmoUWA9VsHVF$eJ@q6HQ{B$=)(w-$?BAl4 z+QK3{AN@PPpu_@i3P;nzGZ(;9i>u_BA{dn4pkC@|_Ag(O)$Q3TjfD)Z0+c$IX;q;vjC4&S{beFX7 z&oT*7<{&>%+oh3c?OJV_LpDdSHZzg;&&R%0YyMb^*XfQG{2O{z$^Crv9@Syl9Xz5;|7QGF4Z(`{M!bz>OIxY>%NEQU4oZ%LZc4(U_DF*{+A3Qlu~aqr zYIwY$j5zXaXa?F`m!l*2^DecQxdyM)FWs{9s4p+`aStr8(!spU_<=RMFiri0Y|NW! z2g6O<^GPINwOLiTi9kKvKV^2;Au8P6-bu$CGL3pvciyc@6ob9NobEu_-*LNQ4cfAN#x7FOP zrPEw{%h8dvSP^O?xoGd7xz+Io{8vAL zl3uxE{#2&)BptuJ8bzr*0D#?AXin`1XD%^5L56eZ1?&P15}*`+WUru;?xHN0bKDR7 zS7O2E);H3CZ>#}1GC^$UpDEis;|;gUp45t~m}=UQ+3)M@Z?Bss8^Fog_EIMIZ`Q&SvQyCAX^NVJYKYAO;zWv=;B7jq)j6V^$ zLq32u=LV{E*`AI*&dxpz#PR<>S_4~pav%OsdUWul$Nb9OogRd~D7TpX1NgtmFSpp7 zDRM9XfO!M}0FnP&^2^r2iALYS@V}+I#cI~Jnc@iFIl2rM#TDk>5}7@x9;b(2SYLTv{y%gfvzSw?#IbbXB6s3_caqW$FN!5oXw!XEwQo(8YpcWQ1CO{H+Mrt zv$*MO8~33S8pN3xE5^qN&W>YKu)ez8h3i5bTJ%$r%0q@LZ0O5KMMr{gbyL`gEgl5e zMb?eNuk+a}|A^5KtUYTL#hT@h62~?M*T}*l3xsOAuOsxEEutoLo(KZGIDMm|3tALP zPZ~APi6GlXxI{dWD=798+BhW-yMM*GDbb@K^|`=k_Df`AS_0AS2b2EQlnLs>H!1Oa~{*=Wh?x8}NdAy?ncFuWN_>qJZL1uVH%{wnOO~ zbGEvs(pwl&!h9{j2dk-tI0jWR`y3cc%L3}X^{PQ>;|;4nffy13=S}qAtpFGND{BVL zaS3SP=L8I7Kco&)hS|n*;IV_W2^iIG8+}W40WAii^c$N1lDGz|u`NO4J_a9v!aWW| zf6u98m-lLsPZ=Ca+aMbQ`~u=TVFX|?h-t*8-D^W0_m0r#(mHiCns|pJbN&4eubWWh zRiR|iiDAUqcz_hKnn1Y>bU1+q-%YCnl;1SMJSYLvBUWJyJ>NH%dhu0rCx-hm6bkyf zpo9>>a6+rUj5O4j+2G;j+}*YbVp`?RxO$DgC{N-3p?omj7a13n@}ABE%zvv zT)mJu3L(pl!+*&r4;`*;7jlpp_xcs{f#YEZ?Q&-<8iq-5!Rw6y)+|opb%YXZhp=CQLriYTWU5n<KFvemxp4#ti&ommrX<`XO^Wo+CuwU^0d?L=iXcP2Y$u9j3<;InFlLivM-Mf_d zV&yNykfHt#az*D#x&e(aI1V@K8yQF^e3RMw8F1Cm+lJrmAh*5S!cmKEpPUmRPOqiQV3%riOJ;MT5_k6AN}5bOS%#n!ZCv?j zd;*+1aIw91Vav#IjwZ&ti3LI(-P1ldG)b3OW41w1Q|qW_RpaRLv;N1X_Z^3gt>4fS zOQO|`d<6&G8Bsf75Vzx8U+2y0bOcaYFXt_9zNO}py54t!Bcd%@X{2LnUy9hHm!yX) zWl26bgDQMdIJfg4L>hCd*)*%u{f~1?zGp=x{~<6<7ye=f)CH0B#dfQ<5^<3qS+`#$T_cBbe9ZnnV`A=Hgsr=|7obAKWxo7D8 z81zdMLmZH=^yVq~IMb*8JZgeb%A!7*vt!;QF?>hlA+580-^f$jCF?sWT?fo<8_^>o zvTmp6g81`p`@Ij}$EUk)H>wk+Q#aAHJ$P=UpVTlXWVML)(c+HzJyu;xv0bofzl zS`6JyPuE5}DK}265qMJ9?cY1RyhrfdnGWgG&-otjwo5DgpM|Rn-Tz&aDCw^Pb+iBg z>U9AD`2Wvq(tqcWyFXkvL=(tAJHMf#9C$OG$R$tCCF9hOXqD8V5=Veh z82aF9L4dB<5h+d~RxguJO}^_k-_Xazffv^vENL;dw^jtOhZo z5MAk_ui&zynCZk%aR@3pjKgYy{umo6i> zceLFXFh0*7H*})icWc-&UEgoR8u+^c;Ds}K3pdff@SHiGPVO^!omOtYJ=hRr5Qi1M z8@aqAqqTyXNnMXYrJF9c^B#XbuG)9gukqQXBXeKIzH8Y~BF^S*5mV+fSGrkFqMLmO zCkC7s?yMaN-%Xy2$5~G@YYgDWi>K{pFl5`$5=WO~S@b=a9as;dtUw;^8x?rbf9}pJ zgV$y)WM2xkT>a+hI~{()7>63rfYEdwTfCoeZfE^PoQ1iXKrWjf42soN4KT@P5t zYim)sznP??GS?VG@T4d@-Dt9}@uQ-XZag?Sh^vF`Q|sOhYgZJ?M(SiqOH{Isy-a9n~iGIyn zHgmt(e%yV7n3qz&AmAMF>%Jbc`IX`^nj4t(Z0EhaSN(Lboj%v~BLH?^#Cpo8cYR}E zKbAYLA+rd|o1Ui2Vdwz@(rkAH1* zcR`=%eAmIGxAe8=0+;*u*4(L+n#VAU%DxkWcz}Sv(E1&;6g+fifpf%vwTQKj5vG+$ zgot7H5)JGl?_TQLCr{n!>54JnTtbW^DN*N%+0&aY)Wh6L`V-|;*L-8imUo_6BkZIJ z%@QNMUjTWFLEO>zBOLdA!Sv8Qf%J~Mf_%>)*Gn4}EJouT>txwzZ^LMdt& zIYc;BB1o^STGfi;kstHDd#?&qfjD}qE^sK0>7+3&4%LqkZ5C=idlLp|2fCf>MOgeA_^z1+kfZPv_u(27` z3rWRpIqm&;LxQlfYlP4t$nXAj4dzMkb+U1I)ye(X?p&wvw#gC=QMX#~ReJY|m*C%i z&8W>g!(@WQzFstL7qR8MdO3J}TfRZZT<1BG`s(z(-S50|>E6wFJi4+M=y;(QOGHW4 zvq3jfY^t|;yE7REc02PmG_ihPMgwwr`>TV&onoO8&FEL2T{AY~7OrVI)#bR^pZu`` z!oKFQS%*g?fN3cK1w%*g>4ef>gAn1g>1W8;z89r~le6)~p2+EtGxrS^=#dPj7LGjP zUV;%>sYzqhdYHp#(E~{3p~vjInm(bwpf5G_l1k;;oD$Z83Dk3jFO;!6?4zh^K=q9- zU5pgk-h7dO+C;IFp#n-{5E5SlX6})=_D?IOF{xf6FaijZ;YYak!5I9107F2$zcoA| z=4PA#KN%s*65;WV!)cgh!m@b*4F)@wt(7Ir_&5xh8G~ZJu2#_;2p;UBCDAWn^3t?G z51t|=oJN_A%|1h>PG?D&;nbz)fV)sVAY<5aH%2s{6Frty4e-lgH5UlPJt9%L&WVWw zRPYf;q$qMQ1J0bG*z-|*DE5GRS`lz$;Fu?TjvU;9n#BP4INApbV7Za)hV^{GjO3oz z3t&6)RFE)X?~LWW{5}jm1XnPh4{>sJ1PGwTx=E9JJ!Qp?&XHA~KeQFpOJE{_Y+$D! zLLg_?*StN<-Z-IswBmM1U0}q!@T-C-lWMfv?dC2>Ft-tmlV*&AfPMGD3o-{NQQpoO zT+!nK5QPZOV?y($Gxob@!$Hr}KYQK@uWLjbvW#PVdJo=px6FH z*?vTOCAbTsIij##?7sKD+ap$Iymj~C$7#5v!@h9WIb41~q%tKU?!$lUad9zuGwO9t9I@?M&Z`k2v1#__e35X z=s+u0vBqk%G`rLOSZvpCy@5-94oKdu*fVfi z&fx?z{|q!_1K2M(QzcxOnfCXGuqogyE`UJHqEv47RVEkl+Mn5K*=Q0w1HTaJ&^v5Ius1ps- zXC}+pJtD!-6+k)@&G%+D-}&5&t`!-aAt(fW6WyWePdYdv#Q;*8`v`cp%K>bu{-AdP z16Qp69kSU5=s~;LcFrJaL+O2y^RopU(L>ZKA&4a&P81^#fEGmtaX9un!12fy?!P+s z;Lk#X?$58^^#|0T`*3rw7FNGM8FgL{2d8I0<5>mKI*Cu`53j~2g=VLtUJsrknA0>2 zD;ivO-;DbmY5<~R76pX{uLqa@o68X((t}_3->lMEMT?(QN8IW|b!Trn{huy*)^CF7 z!>aiD;_|&9<;}(3Wf3JnvHAU;cNWE~k7}#C4gAjFWHjv4NO);F@hnZE;;7F%U9|$R zb-m%(dtUy%oju zb@WlLl!Y=3hDiPwh=KcX4j+VnXllg@T`kK5#6(0JF=R2UxW1|&^+`4Ys@!>Yq~%Y;?#0tXw*>V>oa6E4F^QMV$h_AKG` z!kG|8n5h;fM=XA<%Oh1Mv)m6$Q9ov@6t)m@MK~^!6M*$pNFsedKw_m30^x-rt0h`1 zSQ7)E!pu%#--RCo)PyPvv?!B|v}71oCJDXw7a%n8c(3b!wIl#^M^*WNlWt; znoF)L)J6sz5ffryd5XoBlbaN9omKeR`ppQz9OZ`xO3Wb zE;+@vF%!CnT&TmyUyge~KYNFo-Q1%si%&$sV<~X7po5Zr7S2k5Y-Q4(7sj^%P`#N^ z7=<6zr)}?q^@p&M*QoZxmEOP$S17F-StwTertAz>PjA*_SUVgfqPs9Fqh*YS-yTnA z&qET4(p^TXc6T;M8#*(74Wr&)t{PdB4$xwivl2c0IGw}Jzbh*#IE0dK)m4xI zzPn$4jT8w6_QJ+(=loUw_2uw#?Dx*bJ^$6&u=`VQA0^4I&4okurtX zMmJVHo{!&lz3#Wq5C7;zn-wnR2QOWuXK-v9KztBQxpCkL=FP1}H@qP1qva;MT|c}> zj7@j~9$sl2WE&-_F!))v4Jndw*IdRCYAu5KMN0Pim!z2mKJOSdz=jc&z74LjxqM6p z$6y})&Da&!f$Gffg9nETI=~J1ynZgj3&!qt6H1o6NTTN7IJI^2E5KU+Q^dn3%#`)| z{@Z@H1R2%eh_V@m*EV1{o&VC@Vh+bt!LoH*ZdiZyGf zfNTNb)8>bSZuo9MHzV0E@E4>@TYXKI#rN+!uloL*tv~8^21comBzF9${yIRDFOVx8 z_b#^n@Lm6;r#2|@K9`fz=ifi7-*dQ_NSPz7s1Fw$?2E^MfP1!o+V6IdBKYgSBYEN> zp5CTOEK4f4?fEJXQBcQ!&XVbe7BCCQ`@-+Ryyd+PbN;&vQb*p{WW9w8$n6CkY!(q} zjF5Ej>Hc!if4?`6KG+(Uy5`?B zy$;%xRwz*z^eF?G!ADU^vZjCbt3VnhnjG4aXUWY?k$XEEzV;hUTElsAlX(ktL%BgV zlU--TF$ad0p{O3^4<32$$sPxglVqIF!Zd9VTg|4ij1~_78hEhFGioPao`Pg>+mEjk z00Ex@X~hTV4-@0`0=~l>82WtVGjzlu=RN`nV$l-BYBRSk{T*^cnx3avuFN#Xui?Eq zu3;{p&GdKpO|mS1LVc$pJd0U;n97&yP95J}?cxXpb+scjD04^1-&KwfQSx~sRHDlb z8cfkgQxH3W-`~OU8-u(~BVGhc6i~>S@`inu0{nx%l5tO>Mc9weqxl^8K+KH2Z3^HXx`}3ZOuZ|3zwUd$<2Q#z0OosIx^E8sd>xE2O}_xd8iP1W)ImTX zCm~Q!j>AwwVCGOF&2gRdEQNY#Yn8`I*T`!r76B zx;lo1P|@vQKt4wBx=mK|8LVp@rs!x87)J@2=#CQYjY}MP_`37%UYuQy@jw5pGkA?a zQ0E+_BwtPg3VzYPEXxFLs5~Myi*j8FGFB;ygY3;JNI}>_|1{-g=A-mR;G4#6b?qq3 z7du~ta~qUDT>{0%|F(u@KG_k?BaQA43g+6+o8Eu_xA&JFue@Oj-MsV;51xN}aCiot zq$!+VR9uMZJ0lAMO7k&3e*P_~Q&3;0b=GZbY=X&`Q=&7s$Iv(69)*A?BaiWx7v@u| zArN1f47HSo%REK@TR(SOMG5+JIgjSiRq+{-V|Zo{1?Chd$E*a_50#kjt7FFlc#T_t zT*NCCs#oDWxwm2Cz)*9gcY;Gr$Acb3^YjihOZ`NKA4|o;FuwUU(v0LBTG}{Z(=`FT3 zF7TVApTdb>Cnp`)XT1R35sWHeI`3UbE+Et=TT?|LdLNar*}iD-TvS-^NmX0-G7Yci zto@=U^)&0G_tx*7clu|3krm#l>j&Z)jt>9O2w<^L&}T*x$ba?r?R56WQmP?VDNe z?>a}O9);D{LVx0OjD>GTSiXCzT6w$JJ<10!`f&g9q-0LD1FGwgxtSb8{bFT35XUOG z)KSSz%3?90P#h8S0~{KoHm{HVDqWxp0Pfp^Zw?MY&I#axQn0>lf73o}7pC{R+x6e# zs^LZ0P$0Z#-tzGgH@tDQNzU`d+(wdT%3) zk)T^uF>*!6qLcm@1NeY>==$$Eqd|Z0dd!;d#jqP5~M*&KvC+9%9x`*CT~hho+|fbC$MJjwZ*Sf~|H z_Z008Ga3;_t&UdfWwG_n;3W(jP->z-(CB?3kiSfp@ATqpd0F6cK6;Hkz|kWE7s-yWp}r! zA$=0GLiiK{+!9%`AM25kEO*t$d=&a|KAWk;pZ@gy<3{?ZJ^YHKd32#Q5}Ek-$i~Zb z2p!UQeS0YG>BWm>l11eCXQD?NsD5pcYX}Gi(|MBNKew|eZNY5-0_;NzH9UE-ak#mWoe*MmH)ZI~k(nsEM%y9v9J@})^S;ZT;pYO?rpM~ga0^)fi{I6AX2jWVcH&Jnc zQU5KnE5qvH4bHwgvZ8b4-0nU;GBmrBWvfN#l|G~pGzA{|t(-xdRR`D> z!7NogA?jjDEz8lrvRP0)mr)pR5l%m=0biV7B^vAJNc+as4CvK0(=JKM1u@ZJ)8gbx^r1vJ9Pec8_fptYLBFrwf#li;9&&*e zSmj5blW6J1PF$L`7ydNwh4)IsIkiii8o!CV9M0@o`WFCMG7@}(-o@R7k z!QYFq!$@sPVS1K*s$C&uDyOQ=h#1DoN4w>{Bu6M5eU$NVjBg~V>2;cc*YI1IUQwK0 zg$!$ax{8QB{?YrBzCuypY19!+(tXvPFQXUp%5DC9IhvF>P-j@rD=%@U$$>fO<$dO2 z(OTbeI9CDK6;?r)Gild|^hny!@W(WnEqX1o6GrHP1C%_agY63Ma$5E+Zvj`tPs2ly z?GNdpGi~iQ_*{ruljOw_F%RZD^KLeCHioYL#)hP-@pk4$HkQWjq9`eFCt;&Oodn6GklA5#9j z=AHH{whw>xn5xd06=wXrq^Ev09G$`T?4rnv^2^s>zrr~AFa-g{#kO+G9#75?SuERE zAd^FbD3K7+12a%T*i%66Ea9sQ*u%DA1F~X}vpqFbbV|6FA!Nn=)$FS#Zshrzk1A1C zYFt$Gvy?^H6FERFpbciL)$^_>DG0+sfQN?%e|-LJ%ez|TMF`V*7{sfk`+XpZ1cJPc z%)$B(}GNL+XceYfHC1COQvSl=lWfsbI*!-Ma?`R=n3L#0T@Zr~S65bj^b0UHvjwBPFXq(dmkWY1jKCM)=SGk7vu@^Pb z40si$cNBEEq1OZZiYjvr7LV)R+9kHLaA8$&KUT(xZP*|5EOj$JXl{Qq4}`Y_MbmlD z+kfP=lxUgMsdQ8@o7;(`0ix)~rx<}U1^Qh41iIi{H<&_)MHAc7W|cV08N3VY5=uvU8u*Us`sn zdU30`vnw{fm5hY=ZH(G9UX*Ib1a?-Ds#9y{GO-vmt$sS{8D=Ci{8*Ot& z6|f4~M2KYJTxvUkP#E(7?h?+0QV_6;rnwGCAa~N@-H>iorQ3RrmqB68<>Vuk}Kr$BM=X=*_ zo=5Ocob1_hkjY1O4Qo&Sq;La%@R$ohsAw*tAtD$%94kS~&d0#N3T8g4CnMmrF}WAU zRFZ}W~0P!}?Xh?VN7o@h$+fEsK)%qKQUd2|+D!1o1?E{h4ay%+A+Jbcgk&LYv z5lcnBjtORcZQCod`?z@j>p~_Xai{74n3~#g&2Xg4$5{OJB(yN_) zlzhI>h5VQgzoK%^@S@W7Q}Mm4sxDn^Rhnr^u^?%2OnRXTjWl~mt-JKXkIQ*9jq>?} zy5|;yj&*)|MB{X5QXO zX%0Ug2v1C@7PLGfq>=T()G!>&K%q?^N3nB&*>XGlH~O&(^9l zQ8=B}QL+6R$+ZWVPWfaX0H-0Q5iR#i?GdR0*<7QBn>LDeOGp#4!E2og$qU7&m_uWN-c>|I z)kT}D;5@saq2W1dn5RLykQ=+w=4TGA_01w$X7wLEKdc~V)~U4sMc@4J{Te`jtUAS< zCbs?z^LtyJx~AFl?V26bGrl$JUrjl9AJ!bL+-OP4=^NYZ2w-_?=8|y+cIa}Ib25l& z9-}&w3ScD0Vq_;psX89j`72*(onKLvT9sbXVT?H>l7c_<{mv4X1W_%>Q^*5JaB&sR zX7ou&0l`_)Qb~IV6-v#7>;dg?TOH7<8A&lpVy%M@`5sl@JWe_+>nzkZ6gAB@njn21 zK2sCq0{cU?(xXa?Q(W^k(qBbmM;81;tw&e2TBx+$HXjLR3**MZP{P#`lXyn~hF-F# zmt-U29R63KooZs4CO2uYFo~ER&+}P|#m&5ktzg{dN8pqPM4YBgX7ro>aNI1xuZ2@c zHOFMvR%us`r~cruXIvGYI(>_&eLPQWbAy}5qd4fb%<>j+{@Hk9!}hLYbLrsdqoEv4 zTrw$j0X|4|0k!qFB^6eNtu6Gc>-k6PL{nC+SxOm+ms+w=KJeqi zA}Z?AVN^4Ib*&FJAt$h$a9s~sCc(_ktZPKppw1=zH9i!@M+D-aDi^FOhp0_rNF zBy8k=fW<&ahXr5j44 zFR^>HV{)+VW&j%qVB?@kUcKJIi(N08MajaJ78D;;4D74{SNlOK^zWT(U8V2`E2 z67Edc7nmXwLHxoxc^&2di@JiW+@lx<40p?SUvoSdnJw_Q5Hl$RQv4-g+j#u9Fikw2 z2TkRR5FyAU6L2N0)H|SkpJ*LvKX<_sSZGojuac0g!AepIcIOayFo74Ij+LBF+c)v5 zouoJT``&l^TyZRG-{yBRzoopRaT&N)3m>GCV820 z9Dqlnk<`2-2gShT1;Hc$D$S`KBE$NI`CL&wO^NM%l>64FD$cGdi(${r4_lvF5p%O# zCyDo?cNL_K=8?m+x=Xr>5q$BIDueXRZt?ww`m7qCrLQ-kQ~X7(WFH(U8hoJ4BTG!1 zcI|P>Af3Rbeoox5;6_G5mwy3_&g9fT9gfaB6D#iMmV<~ab)j@xtWDWEN<5J#vyG4b=tXV131z{$yQ@r zvq!fYg}s9(a-OZjoDfGP#pC#FNZKLJ091@Sl!OID=fwL$`J}KXrqD-8JEM}nz`?MB zW=#w!8PIh`S-Skv8!FLDmCX#n7z0~{T=_FB0GVL;sCuHKD~l;o*AWk#w9nJ^Sr#ZR zb}8X%VI?adRIgVNki8)1W64|VaJh=dB@ z=3=7O%rmTN03*fR@03)JEk_`EXU22VN{K3@&rbe}B*&D)qjHMK%4KTBc<$@6%yJSy zV52adI~u&2-mja#Na^bfR+)NL##0wz zsghJm?r>N{VCyIm9_$nqE@)!$(JO}2K+QRxS6|uTN2;hDTUAfB?_Jq)(0lWR%xYWs z*6yne__*KPv;u5Zu#`(Muqx*ctT<*l6id8ooUChayP8yKvjGJK%s9D!c$y9KL0$Hl zO={vzdfgfwalwY6J;S^;Z7~pU3$?WXDjBXz$HvKp^t>LQWyIAXb)V~!TJ|MQn{9kT zR9Z={#9+Ke(r}LX22`M{Z4Ix>O{GN4QsO7)rznfoqOESa`Z-!az5iMTbBvqj1eK~Z zG;x$FkvCibY~d5N;x7FOlwFTwADi6W;kyk+1hQ@3@2YwVfbQ!nms%;xVF%~s%w2l?Lifz2_{mD3xW*!-9t`1ThP~7)ErIT*njJGAIvKO7$1DzLejY?~A1#Pk_2?tHVJG8+7w?kZGSC6Nb;B4yR z@%ZBe_Mg3zm@VB7BO)!>sAyCHdkhK$rk=ma5G8q}Kn&mEtoY|_dpaT{opHfe=E79v zo#_Wmt;A9$V1Zd5Quz+TdnwSunjoZ96ky0HsU#IU`Xz8c2EDrp^CSCj^eXo$ajNsU z=7}G&zOv#CX7E0;=c+hboGk5tES#nxdnho+ZM)EOc`Ft-Q0`=X85a2CDA<^^s9Z5H z;yO(+rz}cRD)qNqrOPA>?O_4h!+h1J9y%_QsafRZb`-zTF+H9?s~sim0$qoFQuw3zc8F%2sUZl zZiDpMFV1qSHL>sjBZZ~m!eB3Uus}tl1ez19G`$!6i{FsHfBmgeniR2@d%`*;0YSgFfm+}JY|xiGXb3KMtlP-TUzKK>F=SvIc?1HD z`_Ytl-RWvRr{X*nn13yjJNKCeRu zMrEHnXxh1h&B}Y|Q1HNKx+=?=li#Pp&%@2v)7;stAU*ud6_xgQ#~day`+;b^ zN0jwCnA%1_WaXz+@t3M9@W-#bXZuY>eL2YxWo;FEDiS80!-(mQ&U)k4K|v6;rBJpw zjx++K8TL80Q#dI}WQ^HEF_j=CPg4xHkZ1;EMT(N3lJ2n?rCoC*e)TZrZ|P9Tjz$~1 z8WN??hoKYLKpPV+uoA&vIJeRRV{+=lTZZpMlGM==`{UwAp7(e72q`%|9a+UHBvC;c zO5mWAzlcYok39ERd)DQJuZC_gQ#zqdQ!t|tx4MBb zipxx#7F{)8^1RF!(%hMEvn@ffmX6LP?mLBv&?xk5ss?eS6qIWg&3i z<S*%Nb`79m=eupE+5jxrUrwB zv!(o3?!7-hlh7Usf6GC1x)Bq*mQcl$OIblY{XK>3EGhIIuH}!pq@5@a9r2{o=u%B* z4EUyC@cYEr`ZuDZE0gG(IjqOfPLYv)6T^5D(e704LxjP$sf<;dsG}2lsf2`D9!ayx%k66&8Ct{*QNY+?cv|>X!`!n8Z z?^mfv4%_;EE@t%DyGiKwgbgo=c7cTpE7(0XcbDl?Pa7rFn7OP!;!HGU2{@q$x?oW( z9tE`NofKs@7F(!2NTtk{L?|J}|GOR%Lzg2bm1&+}#jY{^+GrZ~NE%_?oui_Nz{9Vd zpHIE$PTkgy&cL(+zIBOpq>}W12IsxOgv!?dF*zBkird;7*!q~%FBIarw?M5PoUt&? zDGgkCH!DYGt?rQ=7ZjrjWGX{K%S3Jb5GTtlQY72ylXOO55c{^;NJz0RU%TN0a-{Ff zv;$Sqo!%2S8cBWWjGA>ug{hS0Ay6W5ywq2V_|&-{-$lus=yc07hb))L?7*u-~3RQ(4<+Q}gH8v+n>hoE6wE_xG zb=)}}V=)wj7sgtU@{w5|O;B!+zBQFcTU3pvGgY7BXd^MP;WHz>eS3$~AQI2pPM65? zcD=8r)*qO23SBtX)%Q_nmN>!E!9(7FlI%Z-!!fJ{8_Y@M*vs+lmLaoG_2i{dMNB@zT_cXeGYGP~12P}-K z#DrmgghBuHH(bAmWTjoiq;w!N^(;i2Fdb&;5k7u@l|p~F)q9L(t?^~Ii{_mMRlp$I zcvEj0zOnEQ=R#F1Dg5Z!jhpVSEUf8QrX?*guOzc43~d*mTi{uN4dc$(XK8n`%V&0% zM>Bb{i-rT>$EA)%rj$%tl>}sAJ`a|vL~**B1H;kCMJY}QLtILYMY781#Eadpzy8w? zmggMp7B23goIJ5(WJqBC2NV%Sfam_{kNS}uve>}F>rYF)uKd5bizdA6g zzJ5~mH5r?dJTwOZt0iz7GcC$bqQesy_q#|~*_Db=NeB__x5OnD4+eT2WD@d$%QvNq zkg8;35SZsIW_t&AE(&LotqDy|-sE^kDp-&@ZxmjWnnYE%P#@C+;-0pG@pAIy*nwk1 zP(GU4pL)VRWGt$ob%z{;bw@gqBP$-SQSY=j>J7R*e=-yo*v5npl^$FrIX2@whWF5P zXIl;g8sR@9uRA=^>=Y8HTelRRSzH(mj|OA^KKnx105G3{zi4Uue8mO`XytKt}2uI@pz z89F&JbxTqs%mYA;(Un?7AiA(5Qc>?oo=>()f$_itJI5Hx81`zEuL6}s95XGWT74E` z`Cww=!jHjJES;o}WXh~7%;4@;n}!;}TmiqiGExSr%!XawctT;vR1BQ`QV^5wYDJk& zIgcyH@}OQTLr4nJ<7GPS9~-W<5B1)_6(6^1cs%#^N~GVv*bDjr0{B3%h< zhT-u^28`8xfR5BxaPj4IEhQcv3${BD@xZuF%2|#^X+jyf>OUAMe=f0ZiaEMosZ>VV zh)JHPa8Co66|NT@9!k5Mb9t3uPQ2MN#U$?-pbUEt&GJ~rbb<0jAs1zeG9vB6* zms_M_LlhBio9r#BP9_;awIw{j97Kw%4P(+csfxaK5f~LKeT`vmXc6h0oK+LMYyLOEwojObZ z@ELx=(>5_`7>a>k5_I0mx;=FxAX|hBI!YGAh}ClMRN}ru9%ctu;t7cKDP6@nK7%sX zQ)LEtJ5?nY4Gy_4Jqodt!Ay>KRp8*4qi5_0g7xRn_ z(iB9QkMI5D`sFJs2qb`kM3beetfbquj=KbrGU7?KD(YH%xm$?Wlk9~>84Z{6#~(eB zYRM{TC7yh#CVJf9dHg{)ZR(Ovdiz)er1&9iEO$7yS!h^~$d)UrPcQZ8QxQw0ussOw zDAM829_Jq|l(tt1x2e3kd^D4<@C!^}Q~ZD!4X4t(d}kHBcZPuDs~>_<7rH~huPTRt zFSZzhtqdk@g@Y4RSy>HiU2zE$g|-D?q#4-~n6%wGs-ds-vO#S?SYZd>{6R*;S!kAK*3*=Ul!a#9B?j2;4?X zNzKUhA*~!*tj>zd*;FfZ=ABiZykWQ{R|zXA9E{|fL+?#zaB|k;`vEiA>I#OWr2ynU zYs2+U9VV#Az_G8WbOZt9LXJiqW)*Pc;p*hNd^o*+b<>Q&VdCyAO37tY@iCFge1L~= zp3u2e;WdaAiDYC6G9;0Xfx$MqhN+ADG`p~{t#DJ>L;Ac__>fW6&)&k6F_&}OlHLeY z9N$Mece4f!vO{a3zBA!XqtNv2Ue~`B59qG{Uy~49Sszy$f*=Pq)14M zGU;6L@fHlqN)G2HO&(0S+tP>}35#JVy%-9a%B|UQ=zW?|X*=!il_7yrIx!&_QLO3% zWmtlh3!P}UWmE*93RO8VWB0?8VdHB5@Zg*8zWLMlhlkAbbr9v~_?e?R>A#q-nj!Er@e2V$CL@%o4m({eA z1;qB0SmBA5q;qsCCOEhU0ECh-YSvsR7Ipg2P<}^r%g>YP2cJS9`PP@%O?=!~tk|8> zGx&muASL6c(>uRSZytOYL&G>J!N6W21hu0phoyjKJfGrJ0#4ydzzXwt7ex7Kk``9g zn$#+e{%aNbID~bx!tvh&tOh=BdH;bZ|4-XutfzhC{Z{2zYGA{O^tA(2IZzh6(tc0| z>ZiL4)zMcxT*H|2osg3YULCCO!72ttu8F8dDL|QQ7;IsYnsuQ#^rIuavO`cGSQ=h! zU)NQsWoqRikw@+TT_I4x?56!9-Kr=hGo_4TuT`avDkfx98Nk;@baMhurqD>8yL(FI z(31F+Q~3KG4551##UD@^WfG$*J;O|_i(DHD3uM8@igQu%OM6ZOLl*#L878(JFcoQE zPVNu;x z(BUTGMiaqYm!hSXjRIjd6(({7G);K-Avhh}NgtS)dtO;0p1 z1V!~z>~o{Zg2DIvxQz+M`L)(H@QH`)WlXcbqXy%T;!4XC%< z-SsTTi)S@Qr@=2J#>!Txk-n*7n>;&iNb9|0+7(AeRV7L+rSE*h;WuV$SF1+nkLcz7n@m{SLDZ*%>Epap#(`dil4v?4KB~l1W*B`FJaKf0=DtQOs3_1 z*YcheyHm~~#pi9sB3LOD6;YAwkB{aRnNa1buFB$(++wwPuaZsyW5*c`eTCOH+a*T$3-Z9qXgG9 z#`G51t7KLmpgml~<<+fsx9c62ovYOz9Jd*~PMC%9e`U^PAmZ*afpC<)pL{6sKE z6&5vC)zh^zPy_!f!YPirDQu^;R1Q1+n_{1>o6?L{52>^%Y_)%R%j_Ljvdi2hZ${pI zRSa%%&-1>auhz4UXHlimx#wI<#=oL47b^K#G#c@dQP6Q*Y8&a%9O<(e zlTB2?WhGI&id+fe-KPZ+w)nOr#jg8YYkaC}93XRE=Gg!Hzjv%TZ_N5sR3_Cm16b!I zhT&rHpwYE{&V=ZTD45nJ{C-qwskMovcFbI~JcX%5Oo9sX!&3`pL3C2;r~TOMYm?D`3W^@@v}$=DPS{Eee?7-Q1SX&uPKf+ftQs@is}PZPfHDYstzx1} zMZZv{p!^N$78lC_@=rdcGvsb*@+7rPfwx9k$j`XojL$A1SE0=cc=OJ=1yT3LM$m%$qG_6ej}KzToU@-a(=)* zI>60QAt#cd&v;>2JV~zKWlaJQb>KC)1~@yaWMR(kQ=}!4!8PTIP~$336&o`~>{wY2 z0L`?6&H~esrF3y=`vy(CQIDbhXS3B}@$hV4#g6j_bl3k~|E_orJnr`2m+{;@A;%Mg zH0|vzr&eyH+hjho=tA2YDlxeQTZ0^Q7#0zx+vw(2yoDqkhV|u zSEb47&>HO^rlv>AKXu+Y$)D^WIq-#zjOoy2WppknJo;_5XNbzbUEU=s4ReR}EgBLGsD#skcJFToFiP$m?nS0yzOe11orz|H=z@3uW zHjtdeF$GL$SQR<^#VeN7NQN1i+^SsJnkOM|4)_Xl+TYhIoC5 zDHD5RqxdRRoGki)p@7AAY$k5Cwlav=eygXAy6dVBINnSY)E6d76J1zwCV^$&&5(n& z?Q~qc!X6GqB7`?VI-7^eKQgoB-s)MDhmJM~Qi)_7;8{Sa@)G{iVuwQbCM=a?2- z*s`>KS}BT~w>6@8_2;rv&x2*=?9BifQe%IjkHvL|1Y=2CZ_HIp*Nw|P0SaPct7Q$Y zUQTHdevDAp3&NT$d+Wtz8xxREE|$RAKQqju&Dt8<1|D&iFd11Q#!DUQJgX3otUgEK z4S-D_O2>v@a8wU5Pncq0?wkEb6}IuvY}j^|OOM*3mWz&7OR-7l`oU2Gp;{F-$$9wpXLiEAFl)+Z;b)h7-K z_ixRzt}{X!jcw@=Gqlkv<`V0qJvCoir&%>o$GqNN>4|JvW%5)|o}mkS%uenb3<5`G zno=;M7UUkw&roRv)xrM)2D1O#%q&$H#T!$t6vkRK7`9kl%D^fKzimq>5`K5rVHXBh z^?T77(%R`a3-%+|ZdBaBe|G?{+uy$y3<1od+A~{k3fQsEywddVl;htdu%q|xz^SEABK@V|A)(z1L_ugNC=gPGW;~GsE+nh!>5k~RTc-qdu4-pwf;D-lQ;~{gV zB5mY3QVjBB3xPVN#ng7xF^o~A6=*q#w{K0GZj+f9C{N`=2dnD zquZTjE=Qq9;b&pG=UAgKz%GVOKa))a{32_VcJ$UL%t#fLL^nj>L&bN6bo|Pnl}n~u zng+p_oq3jwaHKJ~nI~7SXrRVMS!Gd05e6LD^1z}cz@9~+n70v0KoxN-vh+i~xH=mx zhP+wRMgSsssflBKLu+740ghn_tPmmfS>SkovO8_z(sovaSTz}&NM+mH+dTimon0ef zS}(~@R(7g?9pEN?@aYOY;fEHRddjaQL#d@HvEk{+Z938BrmpNmIX+i(!k;UB_TSwh zTh{#wvEapv8nzXMRCVo5o+-yO+Z7ae@L|frH;sw4Gy2xEzbRy8-0r7`W)@Xz;OjEd+=xIrDgghcC=CxQ2GGQAd|DH3&#GVR;fNt&5TQ z8JyC>=n!#&sCgi3-72?Ug@(puimV2-6KUAK;bQa_vl|w1qd!x)V!ozkiJx%eO73SO zkd8`&<36n?C7#B9S7I*eKNODUS;YoYn}xtvgm+p%pB)>w8u_U_70?X?j&+nYU?VW7jK;%hf9tHc>o$>UvTiR`gW)ZuBByJpxH+%eV0F!9pzyW@zAUn>TtHpzW}{jtsqdZP*1j*{ zx4vZw&1-?`lTwZK`g`qhXg66e>MzPIsNtiRN2XV^NDRNJ+}TRYr9?zUXq8h_jQ~U6 zY@A?ygVG|eXlO}{Z2Yo3lYHe}$tH4` zw`z*v8_M4i>qP4Y%JWi%ERB@=QpNa`Nlr!xt=T)D4CQG0ij-YloSv(ZG;0AtkzM~=s?Qck}AzowJHH2LSpt~El9Lv2*(XP_TNV+4-c`0y5DFSl95jIqXSF9=I zr^Vv9AswUzN;p%^#qdNbq`hN%CSbRw85h4YFx+Uv`=EH@p~DIG6m>NQ_a9Nzr5W?fB30Ov1zT(}ime00&k zpitF%01U@e!dm4pG@9nC6*F7JKkT@UFyfVlaH-Buen|NnOhH0CDNW4yBLbGIYV}{i zZRV~W1>TgOmZ(FufFVBrrO@wJCnY5YmSku}2x0rbe`NQ;aWN6XB!7LPg4Vo^P>2G* zBQz;xmoj@wD0@Sts+@+#hp+KwspC(zzLQ8}yaO19VljF`sqoMTZ$^TT@agejY*fz7 zhM)41O$Tp+=iDr>Q!^*k%FSgnnH%~{Xi2@^JyQtR?)Ow0Z4``lSnIS9apZBL^SlDn zn+;9O6B#%A%!f2~9j#VaqSDeFHxa|o3ZiD~8?y6cu{>5Scuevj<=^v;)2C3UW(hG@ zN9;@~B2i%Z8pkx7ky4v1&x|yc1v8tR$UDH;&_(>SE5+aV2~FBh4Y z$vd(k*|xSigoT{4pUkv8ino?bnwlF}Cn!{7Ep2My&Q-+B-dgtSt1qZrFJ=NSINY_y$7 zdI|AR<3XL)`if+i?LrN{Kh$v(&<5z~3%=+HbTnyS1aeYQBCI0mq>VfNb;v{3 zTm6J>L@vgG&pZPk<)f7a_mTT5oXCFHGQq ztT|k^q}(Jv?Nw^fxWu4~`;TAS^| zG?C(oSR7M@)}#)sOM_#i-vs|cX?Sb8W|=i1ka5w>67_8i*qrm$?AZofw0_s`fAJX( zlL*4bawcp=C!({rxW#+sVuwqvzs4P9rzMgV!EPNuevq*usuE*X%1+9c=4*&8NMRP9 z+zXieog&vt`CK);l!%xpr%75}K*C6Rg&Yrqa|}aNq-s175>MiBZX{7uCfSdi>cO~F zX4es62$7_AY856Wh!;@uiFjkA7BpDx#iKE68dJP~kl-&Qz!YroRx(cexXdALbYrUY zF=zRHZA_oG^;iXd)1>_DE=4XTCbBLNDC_=U4G&otJ5!#t9B}A3#GcK}SPVZD5vnTe zGPbwCFp9mKGU_ot3yd?(TpG~43TTW8d)adJKG;!SRd)sm{UkThn2)QPpO z55KqP0i%KhNV3t=Uw^l{?0R(gypCJ%l5A0DF?Gy3i0^B|8u>6q1~6h*?aJ5tD8Hm$ zM`%t^$(nK$pvon_+qsWZXjadY7jnua#-S!SofzRN<-!9!1eaLRjt*f3kJJxYX(;eX zMHb0eRRk+9r&mU)D`F8eMFh$0i7VHDTp{y-WHN-lLxg|FABjyCuHN-|t}O{GlW2RI zc6Y*KKhR8}aPY4#%A?P4X{I}Kas^MPD;Yz~wcXdB9L?|O(55u)YtMGb2E2RY`SbB2^b25k`m}4k-JgsN zv+}*Td8ORk-FqCigEo0_e{Y=ymNj|=>$Q1RT7o9Jd*!HvYwXZ@f6RKm9)w}FxVM52 z0XRNNaMyVJKXdTYu(2Om#m}ZIHhG@Y$uzTeii3boi@p+-AL|#}EY}k1Br&6Qa}J5& z#q|Ev$FW>Irz!AgAo@*Csb>pHlIQbU^*@<{BNLoF29(V?4s!eApsEPNgsl+fddCf z)q~U%#KVcz316s|p3(0aiQ`UIHan-!;RPUwOxIjU2S@Y?KFXODmaAB6NS3Gaez|d< zW-Z^Tr1PbW6=N1;D_VCl@RXX4f86g&a87<#Thbsed|v0&QLS>*KAPKl*$e5v z2H2pxD7z_Ig+0^xJ>g~jn{ZbZb+`tv9DB$TvNhf5VeC`Iwa(zR9x{xB@ISsJ_k4N7YATRPjLn$R9~;Ba*F@m zNtf~_wR?0onM4Sz;`TA?X_(6v@35VB!H|UPU%gL0{_s-Uai24T$n6f z+ETS-B!=a%PynAd$nYVEJ_R=wrR};JKbL+@$`i+fq5{;zLqmo6*e#`HB8VPOYCK%^ zk7l|h@;iM#Rq3K`YbVj1JeksE>bBXp>zW>-9=;K*>Gc=|2E|pY?yF^?i?$KT3w~(% zV-zQD4ZzMb%ajsEP!8`sLJ0l~HgA|^jb3D(i-pcg%ry4Z@`J$QVDC1S?|fTnY@Dc2 zJ7l%gUmcRFiz;P|j!!aTBDyjYEgBymOp9ZZDGjAzCfL>bHBc$K{~0&zMQoE_33@`- zfYdoR9ysntsq{MFDLX{e<@lyKxRqmJ!7?u_KKmNWeo3$f`L|#Uyj;c|qd=#H=`>4B zpJz&ZtqYCz#u1ftoW59BHu!EmG{0MOi>tEBA0W3WppTuFCZ#_RRvYd5Ub&Au{*S1H z(vD-;N$aV7PF|p@TTA2FLM|M(zvZX|VdGughW={7x9@yCPrnoUG3E53`HRum`yes7 zdctHyHucY^6V2_muV~r)Aw_Ul5~3Qrqk9UDWxJ9}K?$8O|7^Z|VY ztJtdQnVJo>6H}Un4)0_*o7+Sc^BuIc%QPi>?sP7`{py@~&l?Lukr5>5^2* z@IKgb6a!0TMuUBM)Cn7%bVXs3`VT*+(b|BE=wb7coGBQprn$GB_9bjuM+A>St<_cz zbneZUWCvII?V7J?U#SlgHA+a7keYO=b{9XsS)2G!iP>@4qE{TNuY#+VqEpX#vgZu7 zn7-7B_Jy}dic*86Vou~7@-*QKwViH^TI(coPl^Va2f-N^Qb}OSyTz`Ulew79;bh5l zb@}zO{#L|w=6)#11gQled6BN+f(5su8>=F>G~ySB_i+gXW`QbN?+&4f*<`=o-s*&e zL9Qz&9A7kp+!w7xLh2pCNvvT4R1zDR_31u@z6fq!WKGY!@`Mg}yu($Q3qc_R1<-iY zm6mkWWGWsvPH2Z0;aF3-xt^AxZ}ev> z?$?-r?|~56Z~L3Z(@#48o4#HhbnIWWM!VMD>jM)CU5iofN(HeZ-bzm}OL?6V0S|f7 zl=nN7;$G?Q^@;1;Xe@w>mGM6&Nb$~p?TmQWE$~*`3Ud*UsfozdE-dtk z)*tI#p*<)8$)zuF_q^i_qbpA5v{FUP@cFT028we$%DgPOz4mdikH+K8xdn!CHSfT$ zvfsOg(dI1G3KA%Yr$1Acc+a5(JVaWN&)$OtjNw1f?TE>>ygr&g$2 zx3hXP?6eSqCG301`j{CsS8|Q23#~;W+>VT(-YYA3|16|5->hsJ!;Vd`t1u3JI=x(d ze3kdwrHkI}Osw&!{b?+;*tR6PAtRxpKA^!7FrOd}Th=YBw-W*`d1dc@*MQ5Htl4vh znNC6;B@`-LKD+^1qK5WzoGNq0Q#*q-^~u)yu9g1k{0y82BxX1%S0eKdZ8pT-f+-bo zbAnT!+T@~tDVVDS`8C7O+gIB9l`Q|Vua;z7(;}_4(teP{3fHJ*C?=Ftp=r5$uySm{RkF8qE)`ayJv0eboMlpb)+$%^F zwrr5V;4918aS9Ae)3yJex;XM8Xz-pGa&zoYV0jrk1y+TQ%CLt~l`)K!$*6KlBkikr zc8_^CFW(dYjo8O;>#Bo2G=LuF6dddIt#kc_P7_HSbVjqelNM5Hcf4V=Z|XZbz;GMF zLJSsofF4Fl)z{Wte=r#06}8F(V$fpLxLkqjMYS8dA7Z2tWEUh;Tk?{-%g0$!))ZKT ztJruO_-VjJlayYRH5f9o3LId##UM{z)PV)_Zcp^%3GN@p+j$V+>k<{cG*}?w$6);g zyH>Kjc3+CkeZlAQv4Q9!I1DcrjZY{#$WV*X=G`%<=e@$7O3;is@w{D)0|!vXs-wvl zOC1QzV}K`BeE0`a0wBl%?T3zdDk%9Ywo>|weD)!akCg?^Pe;GdG>AzTWP&;qZ%=om zEV{Z8n>HKPWM|Vu8Y^S<8Yo0Kr@7*wZN6dZ++?@C$Mh@LVe39^{lR)h`)BY%b%#OT zlBDu-zT&d3k*}!?IFRs@>ET~g+HBZ%PE)%}^km^>YA{J;Sl6Fy8@t7kw&dnO!Gk9Q z`w}bm1Q3~J<2G9@>J{&upCPyz+N>62`cGdeJp^h#S+pH+7at?P%?^9Pf34O zJ=znkjo%+4(oiq^ZThZrj<8am|F!Y!F=6=ShaJh)1OB!ZfzhkX>T|n?`il+WuR!U) zk9M{=`O>GFeq26tR79i0I{fitn#1`hhdfm1$zTw6bYI!r5y_xwXH|14Va0l19<1a^{PwU(x2n=U@@5x4GMfR|k;IvC0q81vC+^ z#d2cmj%?%DJX>0PG14|Lsi{2u6{ z1VD*c$kl&weMH#69A{EW?S-l4iNbqZ?|61>8wnFF1uF-?rZ%-S7BFI!%P*T+@TC79q2 z{>=qm>u4K(#Qkr1ZZ`plWGmA&@>l^#?iNJipF+Kt zz$ctHhfK{(UP%ZjVF3xcgMX^&HtzvHgxix$b=Lf173<&3^1tO6iXTAJQ5krOZwm=0 zn_UDY6B@Rn=QAfM^w&wg9{U>hO{v=dQM(ebcHM{2vPhG!*hV1g+*LozLpxm1;3u|V zVB5R@{Y$XmTiwQ+bO;)JNOcd{4AG~tu@Q@|UP+Y+r=N)U;w5Pq7S)X##lPYlD<(&! z|4uO*P@;khRpL;R1anIbk!aVQ!}mp`6ugK^JVXq)_8CkmJwMb1$g+9XEQe9mYFCeXFUWy3p~&sc6V;@_#*k}?bI<92(k5Px49pX0B%BD z4Sm-Y_{P{vj?WTS=To%Lf1!N7Z+9}7_Dfe@1kI@mi2T&cXN~4;EMlD7HSGLm&>uzH zr5M6^XF#AkSpwK`#Ma}B~9S-_6Tt~>7j4uv?-xaO_3sUP%=C4<^*ev-* zVdR%cWA_!4EV|_^@;RlaFx)Uw%9~(p-m-oa?m>mZ;wZrB#^L8Y4B#q?-SXz6tn(%z zkffwU7n9v}QAhDW$mt}`5#vNX3wJ|ao{f~%oTif^HcDz%7Yku`Wr2Zr*-sl_GS^U-ZCN_rKj(LN5 zdC|K(y;OXq1*CuaaxjTeF7CY_}n{i&qR^u61b zXICpK1mS?+&ol~T_=&3z>oGW?n+e+y%qTPtCpI?E;Sg*Es})b>^QO?2ZXoIMk@j|x z(>l(vix1uh zXbkT6auJW_!du0EopDsnT(4c=Bv>nq?z-g4-h>^g+AP8U8yMG*0DU*?Jl$)$W6)1A z-f@Ll*Zp}6{iHAdP(@`4M6kXs0?B_S&HWz!50d!nU;{Bz4|&C4r`;=fv!yFWX8LJ6 zBJZ5Z7G>MS@J&Up&Rq=HcExY{7-d@@Dob9^W6KDa{ptjYAqV7-n#HbT&d)&Zpy4R` z(tVjY{bt9^ao}NY$RTFOc!Ao#AJV-mw+)^Wn3SveUN!QfcLr;vAX^$o3z^x;^Btnd@GS1JiIpl(xzRB+~S7~BW0O^&^Ud^Y7u}oS-VSl zR~~zw30)TC*rgqEq(%cJ%#6})4Bpc#!AM?1-YzgU1G!^+@yR(w3nQz(4B6P~I<&fp zSlYZc>+})Kn6gtn$W*D?T0WSo4;KltaxeA!nidfsR}B@qyomLn_5Eq|5p7T8yozm< zFyhc3*_gf&bRE$o-RJ3_UiTkhk);_=lCx-thH>?C_-K-}4>U4yiqp)=DQ%lj;DcRPUL?rZfa<5zupG zw|+dPCJYznBD$ETW25re-BcB1Cj_ut-9_*q7~qhY6ZvUpCK<|=!n=*^3z+00!fFx! z$+&WA5&0#!Nf3$o1=ObDfDNWY&D^UBt}6kZv8EMbGUIRu797AK z{#}f5C{xtO+B%cJnZbUY%4XX7E`NWDM0uH2OoIga3nz#;dy}|!>Cc;N z2V1s!*DaD9b9Aur019({U@U2?j~rMF89{K;-xZmA2xoaE^)UYK-oD*dHeo+BbUBzi z@wS(*;bG`jg4V9q4a8M^rSHMmOZnr)KlAO)kNZAU|0aLg&G=^$u2lD{&oZI3x96Da zzgkp5mP&V5&6lgQ!{)-ojs$Y|pA-UjtSci2SsRV9Ug?lWNgt4^r+dzJIR|l?U!^_j zK|C`;jTwNY6d<9qc}D%KAX?G8w76Yj9m<08Gl4&GdBg-Kow$-asCV&z@=R}3j7kG6}+m@UlOR? z=FZZuNT7hmBUziRnYtq5_{bT`Apcz7?>gR(_*(+T$+xeQR=HHR(T#BMYFlES6-)wX zMWZZIjqMSp!~R1n4aePvZS#m0K)Wh2;VS|{J`stxs1IF0PG_KK9nz&v*NUIPpk~q{ z9%pKV5FALD=hiH#0Z}lzlp2!mTx-cdCr@s+1;}$7a&)SmnvrCZrF22i35q+9kj<4T zYf5@0on-s@H{vT*t7gYrXh5{l&QPMmw`wYS$^j!bEjaA$ufD=)T8ZbtvzVt z&{vr|!KSpk=}4G=*$Eq}K;%#lqfZ{6e|kEY^*}F2ypQe7!`my#88~%-0bX$aJM0WW zo%AQ+ji7#HF#-M91mU-)kLmK=sZhFaYja$5UiEg#3ndgHd1gH%_+&1G;qptyI z9DVgw)c6>`$o{A7q|A&m4TJ>(YWk6#|7U(~j&8QbG)|7@|NfiuEK;}nQJzR&Kgx3v z*kvxOvhY)Bgf57BmK9jtUYwGnfCe*MOI?UuVfbe;B;|X{)FcI&WPEfN`!{qK7Z=_1 z1aCu!_j9z!>Jdo{feOjz<>xzK-YJ=fIQ)Y7qGhYAKtDdVzX6=1T<*0X+%>ZV7i~~D zZ8)MlvLVr*Ilo*EwM5BC8J`kMeZV{xFvB>$EF6=)XD_Ty`)#T`s64Z?$(3^>#2Y|%62m1_=3)sF zwU&h&vrx$fG#RvD3xfe%9O467sU3~VR8kJXr2sPmcAvjPBbBiAmF&uTlAKg1=T36r zh+aY|3rR@TVs_+>#_z%+hLzCKaM0|v^|dF!Qyheg+MC1sgnGuiaMnp&oDaQlInj6D zr_#J?hnG@muNll|&757XSC-lEHz!C9$L-A7@eCc$IGzqSGB{`}%n`Mzt;aWP-DQ_* zT%r%#nH@&DyE0a0AVH^W&sLMyi99&dCx)LM+C^vhe|G34NS~@M`R6ho2OiFom^<<{ z$FVkdhIfm2>bg7_+>AXGSzTBhjF#s%XKpWMJsBNOtgkjEwIbNN>n@{71>cvjpLano z;vaj{-4C|l$Pzwn)u%7^7wp-CO% zPLC(UexlvEGR<%w)L;g0n4BsvYv!qhpV}Tw(NzaC1<^w z-cUI2TJ@sv-M8mQ{n+O@zoWd_E+N0quu$tF9DNZIBp98mKk?QFCuIZ zpWc!n9;JzL$YPR@KHd)ASwT5&-H(Eu zQbbJ$7OmN8*@y1k5UY1Jld>asj_eG4?$0jCe9sqQKKm`+J!9<3KGqCU8M#xbwDTbm zLs0z(DQ-Y8+_=&6#?G^9R=>j(chVrjhK`I94nckq`C@ViZ3D8WM7w2kdl|=1_=_kJ zkwM5Rc;mG121r3qY5tD>R<)i()Nd^sEB8&Qqz}Uo#tH&_2xOHg<5s)wqEzJFymF`w ze4>eEh-a3yteeJ)6WKC3e$Lha@>{_HR(g+|U=_$>mU;!z*V`Mfy=DtmBM`ryh?)=- z8WFm{x~#;(rkho)u}w7QA(`Wp*r?6z z+xC*>8UJonZ6F)t9Uw&k4HN4eoGi^fa9gucNs-DWRIp%^TnD1zNVQrx9o)cTiL~1mj4X#mQ6;0=>A@o)h@Iz=Q2}9KbfqAnshXU z&$svN3o9N2W>hZY)w~Uxd?7t^RKEhYPdc>5`ZIw@d3+T5Dx=tZ0wQc6Y6r196*Vu~ z3e(C(R51PhhM1+e{<6j!M0~eI@m7j%>wngHt#6)P+E{Sd!P8JHd3^k!Lse4j@hV~5hcPt<8jW+9pim}` z7m84nuc(|;2s1cL^~Q|pd4?k_tXr2IZRcxfO@z(rA>a`(R8~XtwT_IT71+%0oey&= z^BU>jIcgrepQs@8xQiNG<#O(gd8$0}Qy6{ST1x(`f!TQn-(AfTj>p4twy|TT>=wLI zG6CfH@v9xj+=*A+X+q}BK#n~Fjfk6aiGx?eB}i2ce1) z;gPC$hM$)xf@(2G&Qr1$#4Kx`e_@at8dx|clhWa`7#yET0x?N0>NJrwHxK!HBxKgw zvg%>ar%^Fgi5CecQE|Zh^DwGj*Qlx-zO=2OfFZGnwrIqosp^%Jdw6%7M>idVap<}&-*k2^doA#G>BSJWxWPnLqnNpVn+ zEpx9pF_Q@2CEuh2xDXSPahf0Z<6WhxU`9pmbBR6C64}U~Oc@i1^tLy z<65pb?u#8>p2fT}IxQf@&fQgBC+WfY#6=Aw$aB|j)E$?;wx?6Cu?@8Yp|$^vP|>n| zoq#bA_D$I=z`ZmXvh1&!fradZQKE^YGWUyON{DJf_hh7df5q~Cs4wTvpRI~@{7`Wh z$T@x>M|$<{-rg><5KiE6S~RzJ0!hti(~?;2#R~PQ>MFyP>0v+lDZfkp2Wj1*jJ4oM zhf}X4E&wbBRD!d&80IIatGPl=w~R<#)ZOopHoD%g_uCuKPWLZm^VRm@>OJhZ%nQ8F zF+gq2K*19>wyL`IhOJVDcC7nDK`%FkQIeU?!RO0fYt&D(Mmg)!%|ffa6#gcvCQnzR zZKtp1Qh;cETN-LK$n2og(D{)hYWZji*95VQd)!uWc>07Je7_^9$RJ5se1N+8(JWv3 zRaK~UuEaQRxJcOVD;rx0KGS_*Kn{i_lmJKT`YohR%}XMlf9Av>UO zoTi1|CWRJ6Su6k>AMU7O6h}`aS=RSYvVvLj9G_?8BYJM)LpCB)e#x9#l@SK3KvbX9 zjHte8!U1WXRPx$5GUS7H;#L%hOneTq%$h<%nc6MxNEkx=fDDc0>-8owx7bmcDPm4- zrhSIPm=LiywXWaTeOfUIH?m+(OC&$Uyo>@E)3A}J;suMwH8NiA2Mq6%1%=z}SQhqs ztre(^j27-j==giDPfR({4jauf@2*y64frn3fV99VH9{&l%sP+_x}O-d(a;Q>4Q;N{ z#1^d@eBJ^L$(7B46q0e-*r+^Ek_moUQv;@&04y$EjzI)G1*WueUQ4bFVT>L^ROwF@ zeJ{HRVpjDXByDziy_k*AfK!lDJS^>gxPq~jxwdf6cmV7$*)|ViHT5(p_cZr&15>@I zqjQvaM)1|en!^wVuy$)g+~up0v?yj4M79GfqSmx&DqC{Qpv^=kOBd<;Hq-QzmpzX? zttkqmtL={Zd{5mcKF9p75wCsmK0a_jv31XHl;b&Qz5nulej83Y$eu5{gr~c)$l^dD zYh|UK&e9vZn$n)W&`4L;*?~Jo882Af$Y|@9#@!yd4M7=iYZUde_0_HCTc7v+fVE^? zg-@~Ds3^O%gS)gnoq$k0|7Xy^g>pG^d!gT>&mt=r3KgG#5BkdFak7Kez5+FNSM7mT zY4gn+f=6m@q^)5%u<~l@6kE8v(Lk5RMSOc~>b(PY-&0(79vykned*;K+{~97c8;@q z)NM5qS=qyQ=Xc!Dc8v+0W&YEZ_C#mDYK+L#<^Mz9RO@ck=v;#9pw88NuFb@J zu3tY}Pyvgxk3Vjy)S!kya0VaHjHM+Yg`$Q+Cw+N4fVDoKHwi%ts?E{8DSU^U1CP6p ziw4}{fWk!vzaiB=0`dv9NhTv#(8)olea!WVW;SBv^-s}F(LXArfPQUV5-v_#)NBY$+G%BKPq^#|P* zcTQ3Hh3{U!WJU4aAev#2HgaMVbE0G7hD7?XJ(N3NBpd34hAz)j4Vc~2;~Jlz1Y zLsei?9#6wZRq$EeN^@YGPI_P#unkP7plv-g^N51?PA>4Tsf-b)ki#v9n>EEbz?C=Eck>FTFdL z7Sd$f(-YK=xDs)$8ifAG{)ha#>$)zfPa)Aw2|SHmUo;Vuz5SdC_b|O^$d_ke0KKZ~*Grvd9wvjdilG}_lM(MYjlK2Q znaToWtN37C88~h|q55ORp%f_hmpF0}*lKoye#SLPk%j+x`0(V(^!$y$2o9$e$10yY zezia=&YPHM0C1UeW@qb?vQy44CFwXH-O(2Y1?nf=DNd^V+dTQGJ-%jzMYZ4Rsm8m_ ztEmQR0RuiIxi-+0^1_H`<=+c`a(B(_-6$9eFmsY_qw-(ym z@{KT0UrEJsR_AzelUW2ex^<%S*UK@Oo4~T(#-#5&D{*+Lu>r=i>+|AgRxxq z>HCwYMvGp9cVMBN1`LT=FB&g0v|(6iX)U&ao^XD~9o3~P>}jt@f0xmYNCl9OCE%%q zm-;y{fMpO&L z3WT_lbT!+kj=Njd$iEVUtQWSb_ADU1OKGy5O&^`;N;{P| zQYZ$ksDze-l;Z|G{SLXds^qvMfwmV8wQ;=962Ej#@vg}`<~Q#~d?Kg_>!*yoceyVA zKkYt>fw-qbFd(23XdocE|J9QHf6D*{T0_JCM+g+DNZahQ{_1*Hl~P0vWedI!(up?# zRxh>!i9V39pTjkda1L!6QA$Jx8~l3i&N~yWh%~r7tN#T`O6ZupzK) zXXko%`m1Q!!X-Rc8PYYc2;h>ssqnTv=m#*ELSo76peIZg|O~B@X(=-zJFe#r*IjOx`nO`=^YY80xY`AkM z1Z2wERJU<;ZY^EFA$I?FOyOBYH1@aGtI$l`=0#eSRbJ^oEqHk+grUf+nhU0%sR(^^ zU6W1)aC1`uUJvFzeFFvWtiaGC?Q&6h@V5*YG@|D!ir-p3a2wlCp%yvzvC}V~^>wdiU2)07hWJ4UI^AnuW8zQ(&kHAO*R8=FtV!?odfH z-~D$O`JAe9!QzKNoRPeZ4?2JJg z^`6qNbDVMJOvpQx$dDc1PU0(}M0rlwqx%?pEVAwxp+0Pc!#OcubNX~xnd8N1W5T{j z<1W4+dL-gwPzVVO!bI0#I*@$-1O1ua;=N~*DgA_@UMu>bq5W@XNMV?iuvX)%T4L?! zIVqEIsTtJ&nT ztnso?fnG=hi1w7SlLA-9L(n-gQPJO*bC$>Xei?Mj2ZmgTo=)O2tv=+#Got9DurB^+$sW8{b#; zjK}KUOdgB6sgM}auBWZi3>eVy520aiy+g|hpb0#DgknD8^qnXciwGmkkybQYh5HD= zY;hJMCfad-HYE?_gZ_jyztN8sI; zj;)Ym&!cA8QmSda{mSdR2T+Z@;f%xQTD97B*Px%zfrtkuFrP@(4XLtpCDsm3hd+0K z&_``}c#b=N^%1U>w%=z3ibu6NQ>R~j{K=CB57F3u^(pu-?`j_0y)|=qL$gbTkvrqbr)Tpx#!)viygpC}d2rTw z#@Uzb_}T`NvaIEg61&oYc;d0RwsKc{gORLoe~>dvb~PPL=4o67c#DiN3`+0zhqi9z zt)fiwx$pB%Tw3}-)eSt|&WhEZREwRbdSF83_thOpT2HorNsicDAlSTsnQMakUiS6G zo$xAcrZ2p_`GnUxG^sdw!4-cCxLUKuJ@y!1{NoT}xBLnJpT8YOcxBx=P#_?mpC1qH z|8D9u`+qa1aRqZ6nszs)==~F$=Eb@G7T!(Qcm8lM0R!On8moNju7IDmSd#rAV8X>nKUm}ormwe= zaC->0QZKy>b8$j^g@drMP@KE&r;XAde&ZeoY-WH>I{TvcLhW-mSauf#VLe+}am`PA z%YdO|pWcapRal7-KS#j=dluXST7S(c8Sg(EnrfA9r#lCH-k6={Rs5`xZz7QG8urhK z0UfhsqN!ry6hLn*X8qAH6%6c@ZC(Mz2{tsof;xT&Rs{4-&3xz~;YV8DEX|buPMU%Q z6?L+O!#N05go0%LC9`076LKTa&m@fwCu<_>5M-AOQC$*dKfH<^Tm}NOOqKUH3D#?v z7?Rt@$c>6IyVo;91i`#*RiaMITrJ6Ms0c*G$W_yf;wXu>h%gmVO8+Lr%y1C>g%4*m z$zQ==&Bor(HT7@30Bkk#FX436H1cHV-w>!pq_J9+K_ar+qzsQSadNbJlg90RfPb|1 zc`Xcw0w?}+G!j@j8Y}c=!WxHCeZ}z^3U;|~jCpgJVJy=oBf$3{fWsh&CIh#xZmm9w zYZ%(H;Cp-hsW^&^xMSP$On#COWG zh}e@W(JdZZry>tV24$TE`O`W4xD||z<`L&|<-M@5%97jvV&ISgE3PuQTwp#xUvF~d zn-agE4F#{gQ2F&eN^r~{X6~8qd1|5H<7}6ilXsQ9_Oih9;1q(W9l}NW(8^+47YXVm zi|F=tO9aLw)DP@68FBqBoGR&I8^s|fn9Q-Pb?Px#`>Z7m$hlU1#z;9a$a)Q0zI8$w z!hg56RRm^%rS3^GufcyDIuCHKIXgR=*hY)m|-1D$tmvr8I@mVQtLj8ym!mi zFd`Gq2w{{E=jCM>e)N`-J+@9Mco_eMXxP}>wkjBi?8h8Ah-E+W7@niPZvf|a3T>p4 zCe~T5l#<4a^h`ApVpLirGC)rKVEA?R7MWg(v8N24Y)D#(xC4v(5oORK%S5g`#sN8? zbcAYr4o1e5L+IMPjNL~skTfY6Q#q4Tj$}3{e~e44{}(4Ata%Xh5R%VE)G#6Ubmpn4hf&nY6IKE`d`W}paJSFR zi9RR3dbH$`QQ&OY@k)z>%~>nlJgfFU>+wtuH`4R*i8`&6VuaP0hB|m|DBFoJQ%&ob zi&0x{g4KlgpVkPeVhsP#Q^BQv5!+?h$ugI@yJ$=@lV?wbn`MmEwYt#O>Q><3rZgS| zqqzxZHcw`Zbcl(ADXSBW!MjK^7jDK=0n3>n$g**sZ}zwXIgq0-Y=c#w5v$^JPcaV;&lnV3C=2o;FRBBBrB zIoG&O8o9LIY|U_KL;UcTFr6DyNS8iWx?4yEBQT_}PDY)p5d2L$I(yJ}N1#HpA}(>6 zPe^y$xnz&Cg;FlK7)5iemH;|2p0<~qUISkJA#3lS$(W?3W3tWc1Fs_2_I(7rsZuwO zyHBX(p>ASD?4L&yN3WqR^j-Af(;dKB>O&i!dFvz&rVYKGYgcTzN+Zn+b+U8tz2PPuwi=8z^B)S@%^4f| zN60SI#Rpf!g=5inYPz5`_$D&t#@o)DPhC!SYO|c_|Dfz0y98^KHO$OP+o-f{+qP}n zu4JWc+qP}nwry+jJ-yb<>0W0(^pDur6FcHY_yk;6UIZ~lB7ccpYxM~XQ`Yfk(nmgN zk@-b|b!$Yv-VDL75#Ypu=<`uIee)yLK>bRHkBS{<^^#sc9YeT9--68UQv!_X*koo!J$xLwEW?n_-O>;vjdt5chG}l+y|7g~ zKZ^G-MiOa8kO}R<3pofI89J-uL|y^MSVTM!^&e0<_N^Q4@>>Ru%mR}IWawZ?mSvG` zVtdsZ(Gx;`ef}zIBEq)=%C!27K+>e}NTpIQMM3tFPo_XswpS@RKPQuRkLM9Ht~^VU zv4>O81dfTH;kE3G_4{%T%Rv*wQbM!t)MpiI=;6CuD zx#gVj|9cr-CZ;b-W3p2VI^dt}0dxbK!> z1*%o;>Rmsj*o2hH;fOvJ2A9gyshT2*h{bJz`JsJ6kif{;tT;BbrrF=OdV!H}R?s`0u5WAzI2yjHie2T6)xSXV*YG?_*lz2BC{%*JefTA>@wgtQfO z9n(U;hh=XY#?8|J_?zMNNUyo$tx3*N+k2J>f6++$hrM+Jyc(FKK3XFo+ z$)>C>7{+%FM#)-LX0uGd+1)sy(@!1EqZI4JQG(`drU|gGsk7oH{ES3fJ4@Z>ag>jO zg57MSP%gai3m+9ms_0js)&VW}%ohE?RtQxco;`~_;Q8Kcl;|z61 zf`LqRZb{_XjN}QW492-8%B4;+1hS>ADn*i*$~59=Pt{ct zBI>6~lgb3>`I31t4M~F%iG@<;+9#%odxEXV#NOgNMyXpRp8TOxii1)?sZ?=Pyo+VG z({Nyr7<2a`^+LsQDv9L!O5{28hT*B+CJL8uL!-{6h^rv#zsCTE(5*+^J#tWqNK)k} z)gQK0fPZOvn4cG(6^8_a7Um?98RrU_xI{Gr z0>uKZu{1))}!i0%*3kLm=U7*0Bh z#2NX1CVI#Z8Nvr~jn@a@0tfGu$9j=Z{wwdph7FvbP6OyKvY)~q)T<4@Z^Ct@F{|r1 z_mXz?QR5Tt(^;;EJ^-h3;0zzFw(-c;pe%_*8{z-ubP~vv8WeATfV9pEp7%8ab@jmy z$H7PQn*Av+HCxGwb(KEOw*MZBTL)w9csdqbw6!>6YQMC`5C8U=GP&k;)*mY8uwtBJ zw)YI=8Kmopei#V1iNSLBow0`#!gO=hfw|&#XMK$)_Gx~yU3+CG&eR#UhnF?Pvl%fA zbpA8~#|!4g`xY3qKf+;y@v4&QhxSK>OKyj4qvyEX99azwG=BxI|C9)JC?D3q8xD?N z5pDzM{QNe=+NE_rx*sga#An6K>GW%9*nQ-xQRjXI8=+%4dVLuWajGHc@}e--hY{N5 zLw@@h$`G^-j-cCr2LwSEyu!{1ctED|pK-^e-?=k;N*hxfvT7956ISi}jpq&@^6a7Z z>U?`?>l(ZDgWjNV%4(4svQ}WWa>j7%mo`vjA;U*I&D~ctuL5}_@r1pqjnnOco`Gf> z>?qaa5WKg&mm_=LXsmpa%3)ap`UadmSM}Y%6cFeuX`dGPHc%o&9>|Ne&EF`66g0%3 zDPAqlmJcK6Xo=RMdz|N*ioS*sV}i)ttj>gA+#yF4g1n5%bsLeSiYoW)oq8iHQv;Aj z9)2_llBpO;2@(wl2CPD09N$}MoiW7JDf!I<8Cn!QORkZD-jjpdr5de<#|QUYcP-9u zmPK@8(zdUE-pf!NG{QM}>a5+V>0G~>>)-Q4757QxFGT6r92Lx9wJ44$l9vR^V^^Ex zyP5)^#v_Xw^@!=ECWteA3|_?vO_kiNdB6PR1nWox9P_tlaMXJtwyj5B@j;5o6;z$pt$5g zP$IaQU6|QL+p|4Z;y-?WWlv%dbg!tjIQ!T4hyFTml)e&T{C(#Zi+=%AoY4xG>mysZNTEtT zJljCD7eEx2pBAp8QmBW*XkY!1Oeo%rZRenN-inPSA5&Q4D^EDEV?xrL5)y?HWSK@0 zy?u(NrL4pu%0R({7CP5ar@f{`&yk-lyC>@$8~sG3f@aPGYAtB6&|j)-&I3(`oJd0Z z%DC}7usy5}is?8qC(_LxGs=>7#LCH^VxM@VDN?DbmV6P?ZmS-0or>d=Bht#OBE~YM z*nO4r^g(0z{wSrMH5uyR&&7ayW12l)RLjqVUO@vP`dA5z0WLrPSgCoN>>oR4?|9mB zt^>j_|Js*?%X#4jcem2p;1K4b?BcLxefqU)SbRUud2r8tCoSpv^Ga!R0Bwf;DLi@E zKyZDzgF=-IKyo26Ca#0UY^?;+*O2xda?oxwBb;Y}l%=(* zc0Z*E2xLOnqFk&hz)BIcPnc9#ipKC4P1k;GO>M;Nt8b{M(wr`j0E;n{J*?26n(<$M zJ)?l)YD#m(mc5napEA}5Tbqir*G72Kt_eum{A^0C$^9^J&!wznByZXBHA1_u>epMZ zu%zsORSOQBFvhQI%2-zTsBW%%y?A{1jHY5zc&*FHS?YNUP~v|W1R7jIr! zOYE4xTf-Fb_V-pR1se!=4N+Uhz5Y9!>m_op)+ZTDcxbXq`806Vr=$0@JH3U_SzTXw z7vyxya(XAXXpPu;`lO0vrkk9-h5B-fjpXe;9H24VZI#n(xo0EZaUqX84j4E;OQ;ha zUE%6vFnl9Xk^v^!nS9?2Tje*QQ}c8n+p&L}LW$TM!owg)D}JG{SzH$6BVu^w4L96A8%<-pUU`0OGq+|x2p&jP{_DfE z;Ak=|WN7t}`F6v(EpqLW7w8Zb^|>(e{1g*hfqeQ>fJRU4kLF9ii{^XfnjgN+qfV#^ z(x0(cY+{oS;^8iOoAz>R{&!gDaR)EW<7oy}wbC!PxBr-BNW)ufwSO*Tb3gOUe|aHe z__wW%vb=4+2)y@mHF_cKZ6L>~xR-dE1p3mG1p0=ym_?=xf}gV#oElV;kon^GRw~G_ z)|w^m8Cb`~g!laqihSzjA7z(^JmpDNJ6h z3(@U}B@-e{uw2J%V50qU``4;B#<;4!N}*9aTDX0{!>oZxu26(oSfhz_*Shy-)w_=+ zG8$M`Qw-4|Ln+)KBK@=KWzqESYw$90hAU1-73}WI&->~nVk+Sn))ub(t3+Xq{BWj+ zc{GC14)0=yhgB|G?s^oMW_m(p21k+K)#nJptR;x8{M@2Vj;!yG-!7=?xTc1?<}(US&Y8(4jn0mikp z76XM7jBJAd@xItMghKxu*Mm|cK0p!&O~#uoNo)6-_R4tRYwx#NO9$HO;Jm6Ba@Q6zqEt(S{~o%Y|nh#0y{9lahsD0QS&bew-qy1i!S{J8d0_K zBr!Wt+3}zuD|D#A+JMZfz(^9HZrzOG0X)JCcd}L3;C>ud3rrNYpFUDLCkjmKssnYG zjp?uo+RHDk?a=W1v&|*;7q^iQ> zo7g{SXnIPPFq{v{v~90{>9$dvRb1Fir#&j7>pxe`o=GuC9_OvT>myGR+lFpq`WByq zx@I{Fp?dtcplCs{EYxv31!&kf{vbAbq)IdFfv)mc^YpwauMsXUqt2agPYu(Y3O>#3 z%j`x&@YVX?&*N-t32Y`F_A)89;j|U;bZtw`w2NAVZ!h}$A)1a+#|{jF8+r&vv8=$S zwB(S^HNIz`?0|gSq+-$MUfg)tcx51Pf`L|-!f@Hu+OWp+R$3|S3Kg8bMb|yn--LOX6Y2`)+kvom+%0fU}gUy;zYe|@peP9t_YD| z1O#~%Y26Y}Em!#cczO>p59#U2kM);O{_8(h&dLgb`WPSp0EIt3p8xVP#qhr*c$F&h zw(Bha5R0v%C#@k133)}b-6n>3hy+hEi;NU1s5gd~1Q+~EJwZw7!G-Vj#zX&3{bu?KseIf3trIi&T(@4F(+}ck< zbnAKi4q!CEb~*RTTHvMQb#(6aiEAeBd71j$&>9pgCMqfvl;`<3ReEMbzTU8%2Lz=V ztbXTKl%Xosp)t?1M;19&nJEMZ#XJ(Z(#9sc+P(1aT*|{R*{J_W&YM`c%l~q zYWaS4890sV>zo!@RrNVrqZx0IpUBKw!q|oDTV>}oKn}9STD~E)bCk6DzSH+aT?c?r zdY+LYpx#{FGA~AHeN3=GN#Hkm0IK;+yZgczKe-28x4;}e`&K$mFc-=0eF45~fIR8J zShsY1d&1ht`A1JG7Ys6ECSw< z%G!%1+f@OJI;u-#CGtb9TJ-RQ;_!rCq9`EJcD+&J=TtW^eX0yQs9vnp9!YLA9CP43OYw*Nm7p;FIJ~(yWl9MnkRjXxm+YL$}+tD$d5FQ!Wqg zyWq5){ptpwZ8;d|UXT97b6e(-;qh53<;7_DR5V@JK9$*&PPD$Av9=#tf&2$tMMc+F zG4Iv7{)vr@753E~jElJ7_X3s9_{&N$;v)(qbA>lGPf||Zwn_7cJ0Ldl8s7S7e@{EC z?99IT7{#_DSa`2ODMTBzK{H&PxiMOBQ#Qk09`*SQcTk7d*8yjCdUsQ8>&{RP#+U40 zuk=>_ctL>{3kU6=evT?iHkQh6!@xJHCsL5g9qc8G><5hRd~iw{ikLbDzhX0YtlQBX zSNduuAQk(R=O?)m3YC}>9Y?RQ3w6VI%&{7cbK8po<$pg%J66p9~?+WpT~H?TlEvZXc~ppP1i%8%IPv>C5uYeJfP@hD1dP@z17% zY&i)33ElHb1H`GSu!#$r+Eiaw4?+MAW4@=si|ZZW@)Cd%xCE#;y4+VSZTM z{RlhB-x@mLf%rsfxx6(CmSytTKC#Y<<5{@Sgv0GfL2uRm!FO#gUC0ZmUEX~#CqVWX zx#?-b+2I4H9l1lwHoTUboA6eknkC4vS03NWTxKVIQ(94jz_U~8 z75WsT)V7TjeXm=Msk;1bvsN2dK|3s)06D)ATZnV1+e(rqgj!pCGgRM^tVe+1A$m|s z+)B2PZdDN;jfUo}OEbC`1dIIk^7=Isqk|oD*cQ`ZEe%wR0XR^hxp5v%b+*^*kzg~X zuZmL zsyYf&_~|1*<=Q!3Ws)F|tgh4Kg@D*b6aU~z3qWe?@TV)l)7c=NePqfv=SmL{m-zDh zJMW$(lsrx)qoCq=RP5$yV*K?H)#pPSM<-1#L)NA~L2%;lH;`>ApW=Z$>A&iLI9bj8 z7dCD9H)X0Yt9($p`i1&Dt*(NnFsnYI)NQfP@5#K2skDx;I`;JTFr@XyhMRaQ$RtMI z+(CvP8>`sGHj#vXD(+@LJpE5+K;U)1yU6K6_GDK3xX0eQdrA$Qm+L75u)?ejP*{ExmmB&$3*i{E{I=0jAyr2Q7nu; z({vw^I!zr}R&>n0rVzN8S4Y;0+OXr(>Y@xfscS{rzJC4g>?PBHd*5!O{5?Asc^;b4 zrzKsep2l$2N1?kLcX(C5JN#W>3d*L4Ih(*;UIMMq5*x)YljJ2=8H}1$Cv9$8(`l3B zJjy%LYr>)JO;PRwc~u@3&)$acFSnhu;gHL!I_>7FK~(8xkYOffHK2hxjIWC{u9qWB zi-Ov}C|6^hRk#^x6HP_)Ml2q-;J6#x8&P=dF+P(K<7nRbDv6Pc0~O%-E#v6RyL#V| z0Fn*Ligk6B8(aPkDwSi@uh?ns<{I+K(Ku{JDCn_E8fd@-NLEgSeAgPIq?if^m^hf2 zU4IV)I?Pw(O2}(|vE88^`kXnmD|wL>EuQQ=A18OO74pW2AQpDUB7Lo-ij@~oo#s4 z4MJT=>BPNFnPVN0AtpZ11zW-a;_oI6ArX)4$9U%DV#u}IE^bT4^M#FzgS8-t{O(k9 zE^qOm=B?ajc4r5~fix-bEVZM3{Zh{Kug%6guy$JU!WbGa!j9Q?_bB9K?}~Gl@!v& zBxI(eL*tFW?Q*8;sxpPO|C+VNag`;U<3W8~ld)`PJZaluFLy5@Pw%F_WKFT?Y1q^2 zu?j0=bK5?BffT1iAtB*7>8lTFIUJK%nnKxH+c=Ul1Tpi7925-}W0Fl82TdySpyeG~ ztLGtXFjFh9-pQ(d{_a;{&a zSM&}E$fwoIck(2007rGeTzIjwJ#IoFp{ZX9OltQWJ)iM1-gAhnkgm{(5}YNC`L*aI+Z$bB!^Oulr57jz6sMTc?34 zTfEVRMdi($?nL>jU&-Luar1G!`hk|C9?Z;HTXm3kYAegB_EIOAD)!i6I6;tq`JT3| zZFx#{rS+HV*XtC{Q!cbSNRs>Lw-Cf=s>CJbmJVm*U?LIxUT2}b*K05 zlH)4F?5|&cZfSG73#yiBxw$&;Kp}q80Z!i2d7ZzIZ7I@i1Uh@5V*7u3vrV8!zX=hl zf`0QaPjand@6$CXT+)5Qaw~Fl1o;4hKV#Q7oxed6sd3?W|HZmJd;b<&rh~l~hx+iE z01N@qwm29~5FBRU{Pg@Od(hop$!CImPdxrZPGQqFNsBJR_!+G00G{U&E_o zub0Q?S+VfRn;A-bV1yOg3i?yN;+a;g;eLl^N!_tw@Orf8qw# zlIq>SP^qTo$kb2v9>)3fYEY6fz&j#U0haajL0~d`0s@)UY4<&wG)^kQ&I&T|aoJrU zHG~pr;>f63{gMOp<53#C%-C6%LNiPb)f;A@%aw(CI#=Vdh?LE_#v|G~$n@V5ahR8X zVy?tZ=~bAMA#faZdS(ftqY7*lo^sOJCIc+6ALQp z8gMUeZu_9fZmPST`;>k6nb%%U!4_i4a4Skb7Z)7Q=Qol9Oj{-;Z@wwFkVX5G_T>1P zdmxqjN~E2e=DOnuT(QsNDOG;HEZM8e&5=MJ^qWlkld>GqD>u3{=*?T_=p6qcoe>F< zt4d4(h6fJ=k8dJ(Rj2ZgUYIV9>ZN?Yi;&iRh z0<0MUVO89=WcqLk-?P{yIkJSbF+I}1i1mVGPD0$x_;>L9j>pA!B)~WAOFVrX(Au_M zz}dS+1AG^HPjd&>Fzcs_ToR6XYb>IIjq*jGSs~APf>ra5?AU$@*}^yd3OX^`PvRfTv`JTxT%p#XD(RCp*g4NnW9__eaz0H{X>6 z_cR_7?qY7NoMgL5eJ0Erq)IGvqs;!2ZUz`u0{MAQ>nL8kt?zo*o0U!#SdL;AY29xj zEVhX5sg@jNMjpiiDZq>U{5Q&byuX;7hx1P-8}303#EZV+#K|U2P9YCIyDAK@IK8^y zd%7zgAoIbf#Ec0>d>AP|CY-?fLMCiLXKuyQjIwKnxYpvP{dI9cX026LoNAQ1$f6c4 z46cFc^`V`xIP`4n3eQB!!Ns!#p7CfSXXa@hM?6oTM>>%&ZLlN{DMoZi()DXwD1t<3SZS2T~?5Ec#5mi)Y|@iqHfgf$}j1@uakG&%1a$NCu)7I#S;dFz{2VM18f}y2IqsE^a>IoykIW&0;?L+_ocLIbSy1(5300HfP?|KMmfbJK+cMbTXuC7tH*y)c85RF77lXY^4g3{+ z_QtrXx{1+0D(qNaS76cFj#|T9>$QH?e78eoPZ+B?<(WA7;`}Xz^Ah|EE5weRTMA1o zc2@2<^chn7E>e)DDWbtfs|)u~_%6XnzD-;`NmV596z{7s^rRi&Q_^! zaAJJ+sy+Ogh>7ON|;4r?2CTTdh>-)QOc@crQXKYrI&%T=z}e(X*s$p7{4I^+NO zyI!cOt++0M=yj|*F{xsWw@mN1(ABf41fl6$79mZV7 zf*4~|?sCs}@OlzGzgheT7H)9F3a5O}Mmc;R4)=>59&KnNQ9_6V^9ma$EQbojR#Tq5 zybLUHp2K>Og4RkKCA^3x0#)HSuT}zCLv3CubuUpk*Z7evsYqkpZw2*HA|>pbRa#nM ziG(&um_+<1%vK^avTRBC=hL^MxR*P4DN(H(!UbVBHg5{-LQ0)==TD~6HV`l4xh}8U$hPdm$o6<&{N6=cBF-W8f3KCYxSMY2yPBSeR7=$tk*yULY02odUzMAY&T z^!)cU68zg4J6N2+q&B3giWK31pC3zVo=ggqAT5gI-kzxw9ef0SUR^?fWL7z0&xixF z=4_dD@Ip%~@b(0e*T3Ejv5>Xmj!UAr;K~!#aWU*1PbPoX6LDbA14nl{PAX<>)oQY6!x#O(Fe^K>M*Z&zXU@JXPi@i7av&HH4qqU5cMUXcI< z5gE{8at_#01fD?2@G>B`lRe?mebbH^{YB_ts=Xkd8{gL_cw+hPSURznzC@|n#O4W8 z^Kx1fCWb-W5c{;VWKuGNMoDyb_e4g9L;M&u|0HR$`CZq$Bhm-VGQsS-d1s2$p8^_u zp@8?!0W=RsJX%Tcv~NI|-ok{EaIs+k-99o5cu3taSOE6M0(8o+@q#7-#ABa-pv>PG zAZiE9%Zq`T5S>^i1b~6-B+U4QBoY$lxJ-2^&gfwVpMSV>z_GOvaG>?RND4i@-;V?n z-JSN|MAC4-^>Zils#LKOt8Qu&FO#(~vlUhKVBjSU&FShMB7#K@vr3?3=G=Mf3GR|ilj&}jc;xqIh!k_6eNQp0uPZ2K<5|~&Of7J^2q!WgP zwO}EBrt&%_6MHRRP;D4XXdJkrE11bKRY&z{b4f{*I5Y9b98#!O2U3ZfNelDFOPElh zf)x>B=2X!T?4eGNlRdD2XswxI34ca8shSz%5S$^!o!#$H)L`eKe(--4X-O`!xqT;8 zUX|z%caY+)X~@s8l?d#s=3? z#DzC0k7XLGYMG6t+qPQMgR(co2oMsax&yDc0tH09HUWbzqFd91a7CjsAf#?Ya$=_v zzx2Su{t4HCOz9`Dk7?yAkMGZVPK-lcPTFXNv|w*)nRnWPA;7_!#~Vcr5UpY{Q$Hy~ zHj4Xe6P1w^9>>M^+sY{LYBQk@qk;VJI$l?@hql0Y7(hf(!S?v!Lj7~;jvY**;R4HL zjGA5Jr0_PgPV&|?Ykyw2dMoWXs^_%sfJQ0~Z7_4Z7l+C+Re9);OzY|OS|N9o>=>@o z4_Wk>cplRO-=ohOW4c%Dm_L9e=j=i+Idi*Vm4L{5U_7mifXJ(^CV*Ofvl!ILS$my^ z8QTKr0NFb^MNbZxXRPwKmP(}`lrn}F7~m0r*%d{ur%}Mg)N+&EhG(k|z)vlMXPrkG zMXVJOgcv0NaMhoSyCgO^(PeMw_`ND7DD^9$TVZj8ttyT!>2+rX(YP~o?s*|*{6K$_rk*3L*yM3)gCbN}E*nAlTYEU$g{_G*V6QF^NScdppR z%AEtE!wY-PY|KS64Y8cBd^SHrDEO26emUV*&HMpnZvx-0d<{wyrK0t|CdMvDkrmrP6Txbl+YKHr z_%g@|;hNp;&)G}5g=gT0ui4&GP0p*OD4&|A*yXGzZ(o5jBW6&}ZcqW5TM4(w{;hFe zZht?meVk1eJ`6Ng~F}W7mJj}pzoVBG5Y(xH{*%MJXcDw@Yw>EZrbx2B|F zU>amfgo)rDlartvm-9H_=uo7_V_!eeqjoUc+&1hZWPHK2ORL+QohjWIdp&%`t8807 z{iVfihO$Nvys3oaaXi`yV_n@m`+PXd!urL&WO;aTx_qMM*Gd659>w=YxUFK5lV5|GoS4FgP|_o@iLXm3jB@m6%48NPxC0d3B88OiZ&*k%uMOPt?in$_;5AbqZOV zEBs6(wknpjv!F0n5Z_rT&Aj3G{FLn)28eZ}Na*dg^J!bA?f%|7Q{SEr{%Q7RrB#@Q zPu8a9X$BfFWS8tL%e_7{7Q5d|Yqf_o1>Y0Yqrkwwb9H5296glfg|%`RJ?_xu@URy~ zi{NwE{FT`CDVk7CyR=fApCzk}==>J-&FVGGJL4+!7Uh$7eJWh>F0~@f&D)PQjMap# z`h|T`7xgtadtSJ&8Fhq2I${&D`VRN+R}^_<4{DSjoelecud`wLcb!eI&Hp&jDM4u< zi6WOE!Y+wVQDcbLey-Lu;!FYAFKaqRpQi4SQugg{s?hyNm0CBH+%XC&rmFL+51InDQE4pwqSg;ec zVFauBTxZgIRmQS6&Z`<|YZ#j@f!vm^5F#GGCwIULnH#rG%ZMTXB+B)wt;#bMnJ+5c z=a_j~hUa#J1u}~0r`!JcjyW|JNpfr7iH&LFmdtL$;etQuxrmx1mZCHWUdts=#?tF2 zKOcn(fboJCGs>t^^weDC^3(OPRch) zx%PAUEUCcUjkv6RfZCu;!$sETb7sz>z(6UO!zk8s0voOoiDC<^=?B<#~CriBCV_!l~i+&_c}NUvC*#=k9fO*{$B)Aj#EYeT#<1E zN2d$`1HMe-5JbC{S%xNAAYBjJwgOGQ%t*74-9e67H=gH`G;Uc6t->T9no#L-2V4|! zay>=x=~4`MUi8WGhVI5FNM*p-1#BUZ##RMs~(wUAhWspXUxi`|I zQH_Z&tt$qQ5R4Mx;kD``{G2iab4%o`{DCTrx=~Yt`9u1hTZAG_zpr3f$SHs|kz5;u zP#sh6J4Sv})l)q+Ns`#O4;;V{r9KRy#JMxrrv!I#<>lC?_)XsnIN0LLI+6(0j=Cph z8BSl%;2UA=U9SAeEG%%(z)lLK=8wni!UWu?M9+e%TW&{G3N`W2xAnj` z9uJ^Z$Do%O0Y8b7bcveWk3(#sjY9G>hN{j?3)=8(N4*|qzu5%o@}=uK9QcljzQ=pj z_w4YRJ=^)RVwjTEZF(Q-c7|)Rx-GP{A7%^J1VS61nLpkoj;5jMDcu5dNh!~Y`~=eP zn%7>0ZZRz;TsmIee>iwJ-dbFn!0}0q=q9$QX&Eq+SMqOc$+6>y#-<^1qeusQ#<^te zutKq>-N?0JnN2~7R9{~HKJkuubt{y5VyD&qWZ?jO6 z<#V$`!J^cO3`ccUP<}e&9#qSe%K$jR&cOcNmrQHNjMFdr#On5fqU4Wxi@TrA^BOT) zVrR%a`&GoJQNs{z?`aZGnt#sf{YBzXUb1Yqm(_JWRkXc4ztgzF&i;z_@2C;$v^z)r zL5?=t6lNA zhNdRn+O$Cv_KG3@0Zlq<|Lh@g!P9FzW3()wcW2w17o?;m?lXql_5?|Ca?Hgu{3K4s z(^}_A($grBlclHKkv{m)liV{k^iQK!?|LsY#}!vfmrJ&usrGU4jYS`l8rt_IJa}P! zhg&;T^#Yfnsh`gh%p*z`9yf^`SlH#6lrfLQqs$ySsxr8u2hprugl4R>+F}PB{rKQR565fr3`xidk|ShOcX5isNj4S zgfBmlvht@(uEuyOxkBtWdjhc2FmZd&p1n9M7wB+QPmS_KW?0aMK`W|m^F7l)YQDIO zB&6@zf7E=nUjMkam3&y(AEK+6xK-j*Mr&r&F8xZTy?unZZBmewO4J(W~Jd-oVrkx9pHmoiNu0?P>sH!TX z6PDjJ?amv_*~i&09-mY!y#QGMegrAQs^1y&*YvxETX1ZR<{ar=_Gu=x-hh2p2Sd^6 z$7rnIFjb4+0LiD}kbsFDB6I>sx z)1~d_!>UviI~iizP9N^YT<2e8relLC0x}KmTGBt9byEKR^=BPd8(24z*Y~o&8k;K@ z%i8d%s0y6$Z`rcl+~=%YH748R(<;-;4qW0eZ6uquWp~;YgvB~@5G*?fa!kXwb%97W zZa3jc&y{ZKV$-Z0R)(m2m%vbfHust-WTZE|jA>`7bAbMSjxb$c%hU$*_H18-vu0}k zmFc$>Fp|#eodobA3sBsjeE|Slr!O=#0Ssl9CY-3Y`$fyyBQ?12Se&TD<<3$KS9%^~ zXn$b4%3TSqDrq+99c||Yq4TmIMIJG#gW+0BR=cH&$%I0 z%k5wKwEGK7Nc6G{U{l8)3Q$x@4C*N(o7ZSF*iR#o@CvGo=xLFw6!$mpD&VDXJ!Xq!$Y9G zEA1Y~3!jqm2D7P`1uXJTAOx&WP+ zB0t_Vw913{A|D|MM%yh{KN=e^1k!ysi6n%vHR>)yhGd@^)NjgK`CASt#YXt_6|P_?&jQNS zy`S_5LP2qj+M?7C#0}4q=@f6+J)OMf3pGJTUWQYa&rANCS6^i`TB~kLPjP5xC2?b5zxJ2YTR;n*@6{dt>X*)uJJl_aoLe8j@@aYcnC58~o1Wkl*=> z^={OA{%H@kZX*cYfEyzG$VjI>Pz5xJHR`8BaSHTc+SCJy`M~G7gHWzM2 zf}2|Qr+o8Uha>p*R+l}G8Qy#*%DP@`2oh0izz5qLUTE7l;XwHwTV9;OkD0WJ75xS1 z4>lgEHMOtVo&I=_#aWJmZT-Yw4|8xEdKheb77V{@*1d+`&z`Wq1tLgzIBm{2D<*Q# z9@PGERaW#oA1=7A241n*aoKucw#3^*(Rcd?=a|E_gI%1DrdTz#?n`z2`Agzs$F#P0 zwbt7rdSzVwID*a7u?%-M{^P1N>ZkZKxYCNzsyfwjJ@Xd=aI>{*Uf@P68?}WB>o;Jn zVpHZ{&`mb2{!b?xN2fqeHr63qN8WiMrKcPtm?%G$lE#{&p0Z z<0&JxPUy#6Ul!R_#?Ey^jJGPuhC&0(JS*c5sGtKpY`}J;lqLgI$X1@hJjioB6rA#>nZp@CC)-@WDlnTDDonP1w$ zInNZ3yK@d}1`J zrV_^pTa}G<$g~4xxha7up8a7*FSW)6WX65G5JU4crfbzuN7D&F;F@e0_+gTHvNM2P?)VDDIzP-NQ)TeV<6!Zp-vxt{ zw~*CAY4)4C&n^4+HX#OCvq>=2=pVo<_{ZZaybHIiEim|Q7%^8LhoU*?{|O*|axVqGU}BTBRLSaht_OFQUf-#`cf|Rc&4DFWc6_KjhQV*))hU0B z;3NcIQ9X5bu$Kc%BZB2(OwrwXXc2;cLwrx9Ev2EM7ZQHhu&bO=2soGtq zt9!ry-&yn5c*Zlwxb6#SY8O+A06DzmR?osAgse0oHXk*gPB=`&U}yfQ7v4*)?yfVdFP7xxy3MBTxdv4hZ zB36QFkfydotM#OhXsL}MmQKnFxvdApZ+hs=ZSo5~hNHi66?ylaNUXk1x*b6KVhR+* z0C{|huoB`Cnh(!H;GyH@!D9sgt7YVGRNuVip-HC%H$~F*OgsD91Ki)gxf=(Lr}xNL z6jD9Khr1md0ZSMnR2gC3mYk&8qSYkS!Mqz%ga5QXnFq}PLG;%gR+B_pLNi^Cp-6IX$>gar<;ajxN&+o+)@SKLL` zga^E)p&lYsN?*dAW7Gv(@A((fH zxn%Y^85oWxaYA)@mu%c&zcLS6Wd3r|>+mK&ZXw)NU$SHd8ivCSo>X~iDtD^vQ*ZZC zi%@7USR~>KH$96e`D;cx&2ubq-w-_a@lv|j=4$fhX!AyCx^yh9Ze^z*y?Gv%(LwZD z@VGSUnxLV)8sv|SiM)ru}lZ(P*5o;g6o}zmE$#z%{o2U4T zbb)-5IX$>D_L>Rm1h^Vc(s?^|pz&yT2nVl?g^!j>-h5_P%UWwY!Rrq8txH|fXi)L_ zvb0{nYHX$JI!I?b_~RieuDdh;K#eA4L8aunai2Ub>2AifMA9xFkTM#vpDS*`trRAj zC1p!uYr$i3D*P9bPq1#?=c+7p;;KE_?B+^D$ha&MG*c$A2(<$hlXOYPKpKP zuklhCrip^7WomDWvFFjyYY?+0O?@Kf7?jpUYxPF%OjE9SxkX}>x9+JP512WuNO3vb z5IxBdqjGAc{sO^5!u5_h1r`Z{N?03OpX}^opt84X2MSA#5alE!j-FP8Djf{B_2&7I zsQm6&C(#Ee&ZWwsw(5w?#xs=HIO|@Czftv_%Z6se!YQmAj6vtHol2>Nn~IG2YXU+{ z1kE>_;4~7G!R*$qX=7(g12U)q(3JgsS4=H{vz@+>DKy5;hYsk)p@-p1)Fu?SZ5(LM zNtcG~*><2W0-l_1Eo|uQUi5R7ZO{onqOszHx<`36CWyy;IjwW?r5zKgbM1B5Aq+dm z;+)+y;9t&a-RhuF7Q{Yrjbg7+cwb0d)*AcrQ@pDyP1+(yV&`<|FMOtsxq(X7oWyw4 zFIpFkB^`$kn>0RUHtZ#ycn`hk=??0t0i!|w*|F@29arC^)$d^)3USL`0$bBVGSW$R z{u9dvXJSW`Vul?S$)ApPcoX{X4Ig*Gq|a4fgN%x4C8n=y>tZku%-q&DcH;(rKO382 zz3Fq&a59*^x#4wH-JvwdjaE%j%2bE$7pJ=T%rXq$_3Qr5Qr)EgS(*pkJ_Ewc7*$i` z8o#mNO+i&L?mrCZHIh?{S&-m{${gwj{P#O=g1Ohq7b|LwJOaA|i4ouhSe;s-Oo}QUX;F$KA(U@CMAPnX-wc95&heynAgjzJU&mZ+2DT zVN*XkK07{peoDnR+X%^2yO=$+ObjlzyYT$gsKhfM*)ZH<_jp%!+*fsdU_r_nQ+%u7 zcbBf_LJ?NW60VoRJrx`wMoyRfOOBAbRp2lvV=PBFpQ(D{nAkYTGM3C={87DiP+(Np zZ;CKUa%u{dN?EIXN;&3$66REvoez(9S2*!Qfy-c@TP1LXwMzGeq8c@XGM9d=wF&c7 zKVwe>Y9nV&I+YBV#~%{@ROjIWjj0F5&bnRvKYyq4Tg~^K68@r(iHdC6BVM(FhTp3S zQzbfgU4ug}?a8zGZw6zrsl4$+io19x(-w?gF)Z9qij%Zb$33CG&bY>hB~B<|jw@s;HvL^%g41{VlDeuIJ1-?9Duf z^5FvSa{eQ-b3cIPWA`qtv$3&XNaVgh`s0t?0^PIby5P*BZOiA*iUOMMO#NjrO~!nz zg%>{ks^#KHo8cqLHT*odf^>B}I`hvqXIp-c(?^r7Nat?Db(Hlw5XXQic1&FE`zj1R zM#Q@1n{6RF+U9fM*X=*pk`Ja=RfqR?(wzP;A=YD zj~@M1@2jUSJHQu^$Ki~Sfj-MPu<7e0fA*`1hV%dYkoDHsu4|nb9EMRY>n?wa(Po;; zWd494NW-odjAXO@LCZ!!14}=1f3_-La`DdMhou$jesA>%|D*lk{9}*WT5#ZwzXt!y z(|HTbn(`~E1tV9&;g+1_!{HKNG zfY`V#3Ci#h3fwV6D}TrS2?lwxG#|$BcrHlW>s>VsuXcgW@<7&(Qcv#NCHj$<{{9sY zPHI!JR*lZyEbzR9@raFx9-miTb=?rdwM+(>9GOq3>pbRBT+quZy_};qWi?f03zoP3 zy%+bbjQhCL-sH*V*~y9ZIfY>pF`b}UX%|{wxMd8~eWH5=*}}M7j#2|mhB!+Q1%@?eL1Y{TpD+d&#Cc3i`Bi#9EHGzSz`?fLg@@fhJIJ zcr#ZD2kJnRv;lnvg8Ua|Sq#yR9l?T;{kLCWSNJZ?yBfP12|F3FyzqnJIeE0iMFC}JB+()zXD#;bf~ zJ2oizo+Va>EtMYnAqc&lzb_@{$YhkP948fjC>o3Mg~idSYD7&uLr)NzaKbC4_hk(o zKVHxEAr_WF>#%~jLGW7Z)YPzNd$=z<_en* zm^H@W*~}Xfsv+Htr0MF5!!c@;Q^<8XfRELwbt(MNPKoYW@(H#pm6j;kwC2xQLL@%> zZZ@ftmVa@CVP|{wpKcpsFV;nf-HULuCk@)^S=<3Hwl9J({rZ$ws$~9=K(6*m`yE2{ zDTc9T0tUWkXonc@wt@;jq)J&{0MRxko-$OF_f{#_h7)l*9|_ zPg7=!$kr4x%3Oy&mjcDCW?0d!br77%1lu3j~Rax=}53LE~&DW`#FO)}mtMmt7kdA+GfKvWsu}x8nO| zPA4C7iv#56m8Kcn(bCPX%B$oUrVPP2=69BXdSu}E-9J6kJ;vLnSAwJ1!zYrqG(0Ca za4Wk?s#Psr48lDp9hvcCe+=&TXDS zGu-x%E4pJymxEpf7Pb5R=p-8nnhke@ECt!$E>5+(JHyfL4C>eA`O0nsneNO?**w0s zT*%7g;zoGa`D=_8^OigRop%LLo(#&D{ZjwrWHO1a?vG2`M??GayVy69W7bGfb{-wg zR6eo7j^7dYL}_bP17 zui1k6y*5M}obrvoJdnln<`rvMJ^ix~9u|$oA_6z;FIqr*f>hok0l|;+;ie8gMkhej zhUKf4IR&D?S)rd$PW0rmv$YTEUpq1S9#u=}XX+*X>b+4LB*|v1Zy6dg5E`_X(k>hc0`hHVjJ>+$f<*mFI{TL&_fkDjaYsw%bYG}(7@j(+BjpGbv z@1oEV`TlK2tO3Q0Mis&E?3n5(PA~9U$>cI_g2R*k*Iqs!nFT;jeuH-OQUpZZo==v! zf`mnaCUT<&%}&3k=tzZO^;Q(AIO^Btc&NOdB~M(GRYH#SRZo;os#zEW%bb^&G8Sis zqXe^iDB#C@L==qLA^6p%0u+oe?U+oFUBTRWe!RZ{>t^{`*}A7+IEi&4O0h+9Ml-S8 zK=G@5@z^=kU;#J9Z$q*0$Hf~mI%Y4$xW+K3jT#mV>o^*V9lgE^+j?JA27V*kt&(^L zJzP7?X-=?@N4>gb!zyY65@M@sIc4x{LG|dFMJrG@r?qX{lb*!wyc!?)awPp{ux5@Q z&RFOI&i&D6uKc>8IPV@DMzd#5@vi5&&D$jJkrGg{sBZQ*1{JioPPW@r1{-$u|JuUU7nASJBkzqk-KhYPnMr?MQnig>$WD7tu>|)J{pwpd&6e7o{Up zuv2VI8Ho`jt4?+JF(KDeZ>K!jV?^d6^71x%x-6wFYKkeC8-BhuU;5jvQq~}AhD{-= zMTSSEUX-+irX_4U-KdZyx~(+LvxwTY{$cbfheFRA_z<1X=&j?-lC4ts44o@VlE7w< zntbjXoT+|872E?y$ECtO{hFRwNSK54Cfi_;`ekZUU|e)GAZ50z*KUHyn_fFmo}-mS zGRP&$X$MJaPGn`tx*izMWJ^x~@!WMpY35qA=C(^OjVU&`j*n%?!G>MUMYH4+q)mzpZ&E-kw z-|q@qQc*R=KeI7##Q*rN!1_Pl6$(`?WcEjXyiq!GX;hb_L^7_I7ZtkB#PNT-f+fb4LQU8;g%@PHkmr0l;UauXUn$MI<6D>YoUncmZ%PeN8BcZ4; zrY8T4-oZvf`o#I_OA>@IjohI+#L!XI_!xtQZL1_Ft(CJx7)Py{MM1ioEl9!4O3z2` z)H5lWBxz5z8GPUa2~){jsZuFzjf%v@m^pIvfbe?x({%kF(YYGZ5}-(@!_*3n8H}~{ zbjAXyQsmqwX)09^Zk}%DAjofi?M7Zg_1%v=S7mmc%)ip0fn z_J_6aj7fyfq#_G6JW(5Z7|%R_IT3&9l=x_v&df#H!i)zdb6nl%xt}a8jJ*tzw&7~< z!i@ZkMFZb^d6S;OTANBdars9o+k$E>+FSSs`zmwW?J3dA4}IO{2lRRz>T1#7 z1{9;?hT|v04)OoZRc)gS7wB{OAZRNrKugyX39OfKx}Iw_ApqqY0FpI5>}P=QxFP%U z<%-OawazzX;|tH#Slez>^Q0NodK7i@p`kqKnqsNy=snNDbsl#dMxerSZ4+t--ioj)X_T*k@vL9X8MNk2yUYKDtag030+H7?|5)JB}= zs?J$UY0@ZwU_QviU__EPIn-uV;J*B#nQ9UhynWqbeg?s0A75@46Pc;0C)c4JIP5gs z0<55bL8AHo9e-q}oICEx3z#Q_=;P-k2s(^oNc_LD7)RQx>pgk~u zY8D!Th1`rF;__twnZ`G7GGv9tJsU7#gkYqoh~WYg36%7wB|6fGJ(rD(t9MG7A&Sy3AdG8OmIS$3m2gj@1*^pI)<6%KdAw2+ z-PJCPo?&M&3O9;_!<;324QrL0cQ6?urC5dEXb))v7=Ieo3qeq^CsZQi?Nstyyt@Ug z_sPSlv_-o*^=%bLwuE(;&BN22pCP(x{Cl#X*E2K?lvlEbJQAsC(h9b7L8hnrwuZJ z()ThB^dqaazt?ZgT!GTM=b0Wi%x!P&w^dk;i7`}e;EiUqqZ7^!T%{^S_PSduQWPwG56U3S}pzC zxVAVl=4=oy(y7IHv?#2jZM51!{X!$!TbVn+7Y`vaL%i>Pk0dQb?tf#w;7!5}g~W&? z4@Va<=0~ZSh()h8kJ6749MSIg2U@UQ`SmnCKT`C4{#g3>f+n}$WdyrZ;3(N;0ySv77iG}c`cYbz1&%^RwUBVEuo$|YqjPUDu$bHZ96Yt*-@#_j;A@v`k ziXZ(yKE&DnFNgS#CY}xP>q>`y9r)>@Pb%%fU5j`V7g<9Lgsn*>E`6L#An8Qaml`rJ zVL|1=`~8oAc#|c&l`mA7AW6vmP^yWstGhUGs@2_#ozl$f`?JqXWJ2^`d@>jrj^biN z5{TB0@(~pA0~x|Sr=OS^t!DaEB?$?j!?b6UR>5y@}>Z=BL0>a2K%u z-OH1Y^x48CFA@E1G0Besp`Kipqlpa2WW3eO&wZw#3&r^k3B#I}OV-6F=CK%09{kyOCw!_R!q+N&)yBDm>1mKj&y>7spVaU#0~ zx8BXbjqOADT5TV!?)#6E)pY(}iK$J;17AFlmZcRJ%W9daA7&dS^HwUmCtwIEJ2fJM za~Q0U=hR~MGM=fmh;tohW3PKDk0PxSACiSX6}F5646jwQNLE8J&TrO7ulFb<2E>82WMP3^nI^-kO`#^o-9&0Rzr z=fl@1o_njdRLS7A%dAUpr(aDjV)=iIaaivyD<@{|XlQUXci3ci-p!BL*Mg>2nzdY5 z9y3Qnfz{U$+>j2*9Co#B#?T_tx+cSC_$7vP2 zDj|>6CkSv^3PI7%+dEBnUt%IyMGlmzCZhU{anoTp;YjuHJvfnBt)eW@3~{@-YTqd% zLNPN85V)rl01?!PxlEGK2biX0ZGY7N5-a>tz!jpj*M(;TA*W9jl-~n!WwfgSzF^Qa zD-zei3CIAiDM0ayi|+A97Qe_W0I(HRivhNW6xQeF0L}t{MIjntkfvIwu+nFum#stO z8!-7oE!LCoo0}Gb;PE`YP~HMiT+-J@$5OGuD${lWGJY9~SMdu8x4(P^KP%4N{yc?z3 zekpbU84=gA;wu^=aaKLxRA&b7oTyu3rM?U-UjVrX&;w(n1lVby2q^@W0CVJ^xrK10 z6rSVwXNPm%35Q!pLZL4Jx=4WQXC^7Eqy({#%^VIIA{$yIz7!yPAbV$LKVRbSrOW^= ztHa#QPa1oBt9)q{WNKkm@>NJV(TDre)sCQcx1GZyRp7S8OhS9pmkE~>1b!jTJS;SyJ zXvAwhDly;fZzdjHk)r0(@82!pJLh|Qkn~Qg+EtMIu{d~m&po9S$u&gpIspa9XLAc@ zW&ZT~r(+qQgW~iF4SJ`oY3`Db)RGj^jQJhMZ*)26MnlrYPtnnNw5XR8j71y+cf2iUx#VnI7OL1 zWy0>6ct4a&ZlaDw5C`;Q+)BL3f7}vdwAPfs+^6!Z5@prnB*?5XmWhZrQiYgcrwG2} z#0Y3AV!vM>*anPU=hne)f^S;6#{Ee-O2ZVAl_^_C%S$8m?MH~tphug-SzRC5h@C#5 zldDvwU$>BHK3&2~9+k7vI)ky<$=Je^=w&Z&R~3^_o-z+|ad6$FuP+vHGTo%?oF1T) zA@$kqdhi943~k4N@6}gs+2%gT;E5TWLUIwwn# z$d=hROe%{d&g&s`lC|&n21lnMkO;7cwj5xQKxzkkWr&QNRrGqK0KZEJ=;+d)djj?$ zIoX9@{1tM%aoa(wx%ZXgHIrKDH<;i#H89icot8U=nX}I@VfP=_dzwrcKWqt*YeaZ( z$e~ACW!rYyxmE5g0^F`(TC`M?#C`&Z-+zs(y0*k|nSm873I8?)UzumE6mRT7FE=rB z_8fu>nd8!1>IwBI!6e=o7gmn0*m$BoQ)~0a|6CPRqnM&vB!@BWGu3+ZP5gKx=xN{* z!4s0^m|D4iWuCdaY@IT;Iofep>s)sabZ~F$4FBRYsK;tk=XunCajDR18DmP*Du8M@ zoH+TIX*7DT`q7*Id*fE=qu^=u)3}YH{>P0Q`~TRuHL7aatdIR9W>lw?)ev!pWo$IB zi9xF8Spn4*NXXkoZt>>~CJt(bA-5DL?h}4@niwY|8gYt+H}UDlzS|ieO$g zGQKz=*uF_P^tY?)kUT02KNVDfq#H67pV~7q=iB=MloBc3{}EJSbu5JSthM;tb84aM z7Ek#ULJ_G^?R#ohDk=*%&QI+`V>5zQ=E9--g@+y+Kc*i+35!xvHzpwzj1#B_je`)>&;zm$j>n;s zpaF}ErB<+PK4ll=1p%hni;$SQGPkDQv)+$Io1^QAvc=vd;hOcbPrKEFGxM`xsC5=i z_T1&-g)}$m%4YlNn=uQJpFi{byLfj64!!6SWMw0X-NaGmYMZnR3xw%uv^^90&kmpO zbp-!3Oxr=^TmNYfmX-?yIum9HG{b{+Cp=ZZor+-hhS)w;o73kPjCQ7k%}LNR;oTUN z2=$fu1!If=(lA`-kFw!~DfKPhZU=Fl^~V2e=GJ=iU&@A7oeeqB-bhAl+_WEMLwoFb zJ&csY>0D6J)ZvVgo&IId{igSb@n!ZKK7u%GJ2bN7MpuZ*&0Zh*aQC(PO3$ZLm{UrD zpToIk|IpO*s$cw@!gi<8CZ8BxCp158M(}T~=waa8KenH=+S@R{P1#@rTg-OC7=FGF z33AEuVk_^w+GD!%=dwa-ZD&jK+i-FCO<(u?&;&Ie_?poomi2#eTrRd5neGX;PUbcv z!|k$9QI@cahyXl3Yg(ZR`HIk+nv;dE9%tH}MZA*HA}~&-pf-@$rlDN@$odcv;5kv& zSIuUmHk_Q$r?hT=yQv&Ncez${Yel<)b767w>wFK@ZCm`+voFe9#0*iTy{{zw*bNwk z*uuS%B>=U7%qBPr}b zHIFT8H6#ZZr#LR~9Zo zH6*sB;cXq!h=;K+`Sp}^sa!sn!8bka1|V~Md}Xf1U2A{!>j8Hefm|ItSy&6=r z!emtOp)3p~MziQSiw9=6^8PE;rRkMrp5^a{hXvxlM4Oy*!r(x)WWO$L-S3D)+=lE{ z*-s%gKW(~aCcfHH)thGt#Sc&_P!KcNqY3vPwOjx&<1ORUukKrsTue&&`n+f4YlnI! ze$pHm?TIV5W4U?4e8wY8bk^2*FE9=x>rK1; zpr#>bEjQcBKa@xhKwAiC6tVG~V=pI>@YwNCDaoF=kL(v~M_2m2*leQ^@a5=R%{qTT}zs-DZPvAU|XSLT>h9WQr|6(1(LnlYq9H)%}@l5V3i?m zIznH$WAc@BYCQ^#SuMu<0_m+S`6E$jx*$5+=N8QU2sWVND*EB%ZrQHqJTXviIJ8-W ztNZoW*;&R7zx)Gk38vX?`qdaUX1Mv>%TV5#)MP_gXH4FBhlfXG2R$2)awoTWK7bLP zuCyF1-UGS4@}7rYOj3;GAPRsQCYGbT-Nx3v6H_I|*AgHcMmZ7&FM3xlW|@RFG^5wR z@WspoO}nI5^*1fB@^wmCWN#aAxp}&k*{nu}SFs6v^x!I+b1LJYUWhyme}_*eq#cg{ zoYb*d%n(N6wx9GZSsZ{x+K(&?^64M2QSKQRqa_+K>D+g>qDAac40(2IY^$vW$rmd@0iLnu;YS)P6fbonQPO=`VW6i=L z^jRTdYK1J@v?qmp$#Kjw+pMxkl^z- zZi6#2RisLqn7QW=f`E+kCj>X@SMjw5PM`ISYr~B>#fWJ2;PiIA&Qt>xb;8 z2da(G?`plN%TnqbJ4<~qGfs<1T@3^oVaf9#9v%N1v2$#&Po3n3QCKg0iXx=T*6EeL zAhNFb6>u)m6K(~EkHv0vsTbSiT+Sh;Rc0a8g(=m=AOD9}Au$+H$AZM1S=)?P)fspM z@>nRdTDi&08C`kVt4L3*OT~H>A%j_&a%?P3|De^V$_20NiOr^9qpP%g-j0Clbk!^# z_gs0frOn~)>RxFR4;PQMETGb0+5-!j3Bix!iLAHB3-8|WX5!_OKP6@~7H~x{}`lp>cEg1N?2HywNfAw$x0GI+m zDnBua|NSHQe}*O68_@o@dHBDc1OBh)gbXwcqWwUzsXtIG&HvAHO#bnb(&$-Q{vY(c z{ZD56kImS5LtsBJiQ$ja8j=t{qA|HVsAxNfJh7o3KLRE|!;nw5R!mf4gEQPBpMOoe z%{DhR>JOZD^kMn9KihAk)AfPdJC-sm4S1ct8uE(0R~4Y^tedFtB-Yp z{|ik^E3=eh%uu{OPZmhucSCPbWn0u%({i~|da?Z{EdCs`Dr`Ivb{1r7nM|mmDh=GN zd#w+{^m=IQ4Pi<(q%>Qvy2Pgj9JtKJPDQR9KQaCmQrM{mM&lq<>t810nf}y(ZrOXu zOwg+e%rmNp`32h~jxs!t@zx)aG3}2rn>y+6A2iLKD$FCR4jGm62Zs&2l)hPP3;ZuM z&E;PHMo0;jA8|s8n*N1!WzQ4r;=1w&hb8c}X~GcUlEmNZIFJy@LYDt#L<}RbOc7mrVb#8gNN$g@A05w_qk%%Orm-}TyDJ#`VbjF_Vbjhe zS|#gJY*aY}U{lam{)|h+oU@I4QzzSog=9dK?Y3#E(ivjXG6qX*yYv6Dd6d+m({N%)|(HM@7ml@Vj zhB1x&*e#AB;(hp)NANXC{-M*1u;+*%AwzImv=!sPAl$SW2+FKR!#_}`KLCGX;^~Ep z`OXQ8(}uV7f>sciP7$Pu{6m=gz4-2aE$YV!Z{BrzZnc~TWqSSW2qp6CI;KV!)j~q&v_!%Z#dxJp30Z)LV=$)|6XdyfO*|XfBY1^ zKTE5ToxCQQ_#9uNL5eqt zOI|$bhsHM*DWS%ELm(o5>;6$yU~5P%!Q2PX#Jg;JZExNVjDlEpdi3gC z6B%TzaH^#dsgWrcnF)GbbP^)h$SgQ#iUKzPk;~OB4zp5MqV&_s&7K3nD;qB9qYYwH zD|$BT@>4w)6PG4o#~@bHYFapPm?cv6*LIoE&m>=2G78Eo1OIWUKjdVamQRB19<+%Y zF!x;7T7LavFVR4R~D?jqhohGvD>QSFaqlPMfZ@3}Yq$^MW-BDhZeqY%(QiDl#lTpW%l zz|$X)_r-^RshG7>mZ!`|si8$-S{GoI@-Jb<{;%B>&jfd^%Tl+sDS!K7{WGcuiPBxj zvyzU}$~sGw7>}AA!~z~DYnonwY?Z$5U04TQ_mFgGOCKk)7f*zqJ{KHPV%4mGa&7z< zCTLFrh@*|T6Hn_W>TB2)9je{}5FG%WD$OWYbY4~Mo>XkWXG>Pc7FIk!ecxj+ki9z+ zxEY2U5z>d~tet7y(ZJ50?xlowt`C^WakAiZ^C4Raz)zL5LSy}hy63S_Op`p7U|-eGsE-Je6qe@34O84&ex%bE0-*}%%0r;ymBtu6RsG~LMe`lk z%-TKVbuTK10@s6~rT6D>hIo;iGufZoH|)-srYK2>-nT>EBaNg zrq)$64)EuFi0CX$8~$-sP%K|GWQr8E^_b|gvu3hNkhQ<_opl}t*GgmYvSq(*56t`{bt3dC)EChkDW zb7-=+duhEMojI;4^Nf+>bVz#Aqj!S^3?J%<$CulWk%u&6xvp3H2LAvGiSlDw8^FC6 ziu_0hHe>Wl!nCH!CL3YbYywyc=s*Xs;n-9+0x5FrLf5X^>1$wwy3q-H5-jYOEmqHv z{d(NBLn9kK-JN&7ZPtBPSK<3d#4(Pj*w@dVim3MP{@7J8QzNJMO&!-~&I6~U%d$LX zuGbI1*0ugaBQ=r-p;m0o3_@s~djal;v(W4Pl8P!Bz~5caYoYxFp6}L(l+UxU;oZw# zi78WLnWUda1N_mwSQNdKfL+8T+ESVgoqZ(x^G3!Xosu}z97dUge5Z?Q{mLa}zwe6F z;2u932Q;lF-t9LQwmVSLVN+BQ!K7?$+;>94zDuO{vB>+Z-C5CDCXI+6H``nTT*wIL zn4z^xuWxkWmX~d3)nY{SKyaQoGsjP;a7RndE1fbsM}nSOIxB@(v`cn0&~mm{T#XlQ zAf@vwiLk*(ef}~DM7PO)Bb!A&C;H%=*=GB}Y!TQS1ix%zFpzEZhNtwsmxxzQcs-#o zq#One%e1m8X|p_Ca}F0JzNcwJ>6t&__*UhAmO4GL{(BidT}R}q;0FLeeFOkt`u{J( zhDLghrZoSjl>XA|-33!5>E`;4iemx;13M6J^dLhh_F31@k_ElNH_s3$I}4SmWO!!M znKdqPWqbQ;Q$;P1RzCH5PKoj%X)K9)~Z_P&aN4=%A8wx-oQJ|qrp2Iu;Ki~o#Ro)y>q zX?!{U!ycyz!r*zq>Bg_qMx?<9n+7R_F^)8_aNQ$d^=?TXuTAokb7)(x;@K7PzxSwB_beT%=0{WztyQ`-;5zp zKvPFLO=8#8bvtUz#` zjnSqUf*`IY+q1YJW_^rM7@EjrbPt&hheV$}#Dv3e$2X^AQE^UF6T$3{Lg*U_A^n0@$^Vjo|1mJFp*Y+0v|< zd9E_0?bKIoifclB4|4wck{)-?bAP~|&jpA%4e_voUKBiUqs_o}Iksi8W~$H)zkQYi zr#rgSUv=_r=!ub{(UQ%7J?O7FXh#ZbsXvL?d>DK;u(CV<%7>uY7%UJOapatbg@KdR z-OU00_`1`dD<-*sEAG5~+4Ee(gTbmfPOjniH3M^ZF{>02$Y7k8wqg3h;M;efv1ZB~ zU;gvr88I$VzSMh|(sPz6J!wowOie09onFm&(TVw>^B7$G$C8epH~CYn8Zdo1TQ`6k z1{N8xUwdZ5ZXSSjt%@-{BfX(r`g`Kk(dUBbYYz8BZw~D)_mI;ed;4+Z!sWsRMJMiTFbz%LI$tEijhC8tT#hfjU1sTdd6a{eP4q-Uw)1zvO1;;L`lUeZd79#l4s8e42t z-SU9h{^)(Wyr$K$$v#ITp9aXCDB>7UkYAs>gEB{Zpb{wxizgdv>gTO!v=Rh5eXqD$ z(h)#e zZ~LQL%Phh;Q&D{4F1a67Dz|roR4DgeTy?S79Y&P~(RizIQ5b#bM=Gekd1Qzj0Xg>* zXN@+O(SOwCDM$bf4+;E*>=N-iaWS;UzYP{U3mWJPo%NGFpzXM%WPVAHFL0siHe%=p zc-w6@cuY?mw?VB-8iJTY z(?|DYGK-l)2WiB*We(-PbLm9a{;L8WA3_>(>}(3qF4d@pG*3&S+An_!$!2$19Sma3 zn=zqVH;uQt_P%QT{(A4BnC=0D?0a0}SkSp{o%381x@gF{E&g;mVC%NGS7hy`PaO~Y zB+It4t;5Os6TnDV-3Se4JGUY3nCCl3i6Ai?IeoyrFzkRWGMkn0AG3{o%pmXqelxP@8Pd`T3aJ_))T z#!b^foLBoEz_@dc+!bmCB8?P!&2$lSxYepNEKkW!!4F;QLb0`)Hdo`Ys%*oHA{tWXlz3*&=2MtA<1j@?1)NmJ-tIZ6r>0q2WzpMof2K*5FRLc}vUx z1`!ZEJp4}Xn+$A4=d2ou&6L{|71PweEXBVth-fA}GkieDQe}mEL8CE<2x~u93y5ag z&IYliO~v+1UKMnQ5(*R&IT_@U5h&Y|)%9bsgyvWTbT@s8wbCT#*jN9HRS_FayM`eL zWM=tU4ks`d6cW*_LHLd^*q~xY|Bxm!NNn*!(wS&n${n@I#X4JXHBfd_9SBPtgT&7f zO5*SMH{SQH2{x>l)ln~IbA}waB>yuh#(gJ`P1+6&+c~*;7ooHhZPriiH@xqRNB zE^=XO4TQC@x>T_;Rfes6DzIS!mF}fZ_D*7yytY_bsdT#cq?VSr8e)N-Q7-Z5Z`Ps~M&9*x((+e&Zruqk1qwSp?!iGjMloQ=%MV81Ex1%FbXH@dY)w##noYehhF!^-$b9mUrLv zb@6a4Vs}hSK!WvvK^Q%UKfi=o!vO1oLOFCs8+E27N@0#~Y7R7FLov^agnpk=Z{j=J z!3W@L4ebYFY}Sg(f>~-xG}Eg)VH+lKXBf9V#$u1E{+b75$%mmOFY2wPQ(N6d8O87% zHgq7%hbkdDlf*=}q=AS-wIj<>KsGnLeVx#L-};sIj-MQMNcu1;j0SH(8i2bg%?EAh zb-9@XC|s*ww{l~g>juoUGiAHB1eBCK${$tYI&(vqOHtq{?~Axy8o6+x;=mG)8$&cK z31;(~)KE+pi{yg(Qk-W2v4`R}K+V9m*>rjHM}Np(vimTcC?;mm6bY5EBkZ&;LVS-! zT1#xU6+2~)UQmHtMaV|?Ore}8eQvC zEgTs#3o8JiBh6{2X}D!uX=!S;I=+mZcrX`i%ne^TFVTnH7gc2TMNvmvcYK(a`*HkE z?m;Uu3bessa%-HG?Z)+|?a9T95qNOi(Y<|aJiZM((>hyHBV&5k&7WHBR^L(*(L=G9n5^kO4(De`t4G)$ znd=#N*Yi!UAz!*P=WVn;&Sak|w%Kj@cpm$9-Rlmw9iP(2LBZjlAc`plsBRCpl~=zN z9MVZirH*5EnJ|GgkOCpT_W{4QSGGfTG7!*xG=%l>IXnDppdLur@bFageU$KNi4*dq z^5hd*a>hvj!~kh&V_huoNfB%D_F(haE_XUxgTBP8;@^iHl6oVj$s(=OirOq@oA+a} zDB>r0vjomnKHUV)cf~ktn$xan7`mUDg`wIWrwa{5Rdyny5uo0`D2fEx1y#EfyzdF2e%h!q+pP`ugmlaSUYDg@VrQUp{F zOpVXawk&tLI#d}Kd{tpXA)Cr#WWG9g-X2G;)!Jd=PCV2B*IIYpDX`e@c)iTVefa(m ziYe3?X4hdSa$?m7Se=hMXq~v=zmf*xh0OAnPVch`j`9NsvIAhCwZuTvOV#Frej4J~J9OD-Y6Wh8G00AAU z1kx5_&tOh=z$b3EPD_kdsV;%5fe?)rk8%se84?K$3=K^{*-jBB=EX>GIEj;X7y?W3 zv=G)R8*1E@vk)K+|+em%bLF?Hl^eejl}$f)Wk$#gWX> zeFz+EGK0)dG{pTc#?B#17bQy8W!tuG+qP}nwr$(4I%S*xDciQKQ|S9G2keiHE>sF?l+Bl zI)zjTGXV_N*8jnS1m<*mK6C~_0H=Qa-e^-R zX<;Um8$Zo^UsJ33LYf-*c%)Hfkl;! ztV_dcOu5F~-W8R6unvf}Icf1y_aC#V0Ssv>BZQYeW+?hZk^>1(V)k(vQ@R*?VMuO zl3gWx%vyUF{f^I;t4r-tq9&?AxjJ9q(~8Gzxy%bCH^Nm09#(Bq5p?Q!>3Y+*E=Row$>3mzh*-yDO+undqlAqq0HLv;uzne~m#iFa> zM(nC>MfqL@cAMuUXp8_EO5S2A8bpQ%YqI8?SY*K|rOfeBKdIar1rw~h;vqD+v95(c@|l7;D&&W3sd*%1cxg87H=1@_BfdQ6FeV*>fi(!_AYQR2B0GAcTQJ=BddXV}w0 z)YXyX*@kdo&5(#0DpC9<#&Z}H#qu@zdFq+mjw{nZPm((g7z2fRH3)qXJI#QsNgprv zWd4;4D9H1G2<7jb$vk5b;y|l88m<`GzT+ofDe8wZxa7;_8amMooD^;sx-hj8bTWIdjWC&8Xwez#{%zrIZZ|cs9Oo8YSjK=lXet9K zvKf46gse!14I2SwyE)+8nf@~9fJ@53D&+aSShi8nl@@NAChJ|P4sUOv$!ww5#Z_so zw^oXR#DU`m=c*p&zLMhwHHj0LJUYIb)tivFJzT_|X-t-dM{EIye6WUA{oGI5I+hxyJRxeVV5=Wr9 zH8z|W=>3ydPG17H9@X|_E}x)$odCQ9{pvkm%1ru_G#b?e6$%e8+=}Q zq-qu`_x*gWGBM%AmZI=(Ak!maNhUrQUU#fNEp)`Lnt6ZAlF8>})p`r(m~=?lUQ|mV zW$v0q>bimPl?dmv6UQkYUNVm7P~?Np;;T51Z;8hGyQsYFaXpFt9 zB*^T)Y&~-uVo#c?@UB?VM*W*K`QLD%IjdZXp>0b=!do>Aed%wmQ)1oxoO1j8ae*G% z{rd@?k_n(d_eg7XT*mxlEiw*-?6u(f6-GY2FJ9+)EZE7?WmeH+(-9AKbo_r16VFF? zu^KU$Sx^ys?D(i;;8W_tq#%*LOG!rrf*DR~p^}-`#ntOiU=OOzVZYqTD{Rdf3&kJnok1)Q!CFw}h-{-pXM8Hv6Q0l%%cs5e^Q6UH6*4_ z@#+Pic)l5A(fe4ptV<0OzL(vLVtFh!6bP2Sra6~)dI1xd1hT|f;xm(f;hyi7gwW+&8T<&#YsOI`9ShP&8*l_s96hCgRVCUNpYnM@O*#C$l3bI=56jU$nn+z@p_Jqb~8 zIeEBs@i;fC;U}Ws)A`a=BxAG~wGhQn?3nVrGSNYFYR&>|vS1X0{;}*2EJBCTZRt`T zh^xIuNdx2zyH{Ak;k((5j~T1_XUvmn-AZ>itzj*H0}1=BT8WFtrO$a~&m%L^XjFl6 zUUj;u4-U)5VzUu-+r76LD?^1(|2SDWoUts72qj7){+;~yigsy9B#>{q&Gv#|?j8nbzac>k{tf)Io zDwP*r!Aw!?9l}H40HspPRJs z1DJkU7Ti!g!Y^DOrS8=gnw-9o!E!b&Zdb+^D@Vs(qwsOgNE74GvHYwOtcVzLTC@Mi zA^4$yVP+KaF6{q)WQ(DA{z{4|Py#?9al780o0hY|T&o$b=kli^^p9u>2e#P~>2|~} zr)czGZ26*kT@|HYaVCh&zPpylf3|FLqsW_|eRurODtB(OZ#{5{0x3A{EcS_0s3T5V zS+RGpfaK#b-3GT@A5HDVUvtK9`AFlJF90&@2xGKI}2zG`Gg@WL5xuQpDz;%gDx z-kAZtb^lS_5p4MV5q6x*bLFmO84eN_s&t+xe7lX#@I-FmKa06KlU)fZDc~;FX6EJXnq^YIjA|>m z1_$%8KpT2Z!{10RCR+BGsXO=sM7WQh;ug{KfXwDm-t{WB?x1>9DMor|3YInTxqe~# zFvd<;Guo|*o00|hI9tx{yMY()V1S=^`FEPN{Bmh^R+Kd2>@|SrMmZW67UN+G|35iz zp$9Z*rL5VUswkKmC#WmJOZPtbDpK{`V&zvCx)a}tEQ<)`$IqK3K?I8=v2JIp>1Z`1 z{lJQu(6QgZCIpen(05JBYj>zHXv<65P;S`62~9UhU(`xrSWB8Ph)(_JU}%OZAX5@X zqK=F?|BE$ElKSIVUKE^yN>hX~YYQ9HiOZHm8_R(_9Ja({Qz;i=HZ|^U;Z+7aR5`FW z6g1gd7z#P7lP7Fxdtg%qzfHVp+l7p3e_W~a&-oBhyVJAc-;4Q&Xz!1OM#9T!V~^gX z!Z?x?t0Ia51Vw4~KLg!IkKk<83t^+gBJ3UEy(t!7Rum>Uyq1jeBwESXgo&96jU@#9 z2&cX%3(==yP^+B{rBGsHJOpNWxaKpma`IqmW7E>eEb~j zLqp!Vyiz#zocfRQ6wp>_dUb>oggoRgLRs zdtIw7;W4*AN(AvKv*MZ!5aP~ZGVnUZ+*B3k8tU{RTTkdfT6dPD!n?0raJ!uDYUwa= z9D#LYeUET`d8`JO3dh3E76LBu>VtZq#H2mkmT5v>S9x#vhtRE;Xib8QKrw1!>0n{8 zSeYkX*vx=t4glZEk6)}70j_8>=_ALvoMQ}bpKYc^%|SWqh;>rCew9EHVQeO+EMxO5 zbRk$Vx_fytq@*TEo9gNGA*O^#D9yb!2EtfPu?AAtXh7&SrmQo1?Pk^NZJbHn)$oS_ zSZDR44OiE+Ecv;7wThGXA${C|oA!O|(7SqBq*@oi+gtm-{(j_(!RAwQGjUPrOPWU3 zN_)xd_V`6JLG-ohYj!*KShL<$mTgL3n18 zfh9KH+$5>OON&H+UN3F&ATS|b!sot$>`bBblbF*s>xM=n|FMKg3FAa#Dhs23WFQq{S;{ny8o+bIOlB&}(;>^}`j^@t} z0K7Bs6EW{=0_KuE1R^WSm7^;J{c2F8*kaU&X^WB{V~mvlKAkz5X< zn+$N?4q`@vWpamglw&EnH04Q^AzRrpB$iH8p;A=cFEg8E&RkYRpe2QX{rcTu$tUJF z4j`b>9x4YwGsQh1;SMzp@cHLbV?MVn;Nr^A;o7zkNsbZtmw}H`2~aKH&a1=F#CDZ% zhlg*|l~wj0GhW^-ww}0k09q~8I^C=;qdFc@A<60&-;RcF-qRe|x}Rti*$(7G`I$Vd9E2Li54pXfdV0 z?WQH+&5?Rdb;pUII_{YNG7uLd3#LqErq!2RhFTFEe_5uCCoY~#$z^H9AX+8a9(Uwr z4sx8ee#&UHX%rr0#mc`jR%DWi2a*H&Qd&4QZH`(ptl9Ic2gQAzUj33W39I0*OjV#* zu>F<(E7x}=Td382DCtkSz;midnV&hpI+P!5EWFspok$2X%2?l_{TaMu1K1oTSoht; zhefLm${P$tPI5C2LNS1(-3be7+N*21p*ZRWd^hdR_lnZO3l3noCV7u5t^!oQ2fPRVTPl? zR#kIQYL(2mV{hl*6EPr!RIydP{kd%NFru#-7Y?C`vNfTW#Ma216$%WJQjmkT1M=Je zjf`O*^C0~E+5Fg|tZNz;ho){UutfC_hIBP0Ej9UYB|9b=>=>2Hq*U^u{=_LJ;DT02 z%NMtJaP*#}dhnZ2eI4i&*?H6{I!ws?3{x&k;)A7R_xLDn zfq6xq_iL>pNMM8F-Y2V!)lA$OQ-stoo z#*!3cz{Z*sKk>kG{3_>Q{?Wy=Focm@WgXGUEGHzkM(ki?#N2Q5{H(nv#RZtfunqqg zRht78)*w>1tiWUnKWsaFqO|H8pNgFpUS(L49&HBsLhUV2QZ%TLVz(ynqk~>vPOxbt z3$ClRE|>D;aG*9e?BSJ)nigU?%}V%IUy@wxd~n=j{I;9 zJg>)95Q0L&TI-fynn(6fK@AhJosHNdlZ6T-33L8g@7-(0mAn8`t;^#KzA2)TZ9E86 zBk#yshF_W5z<8P(*k!vf`{{`qCAN0{K3mClq`K~YXW@RR@$u*+z}VibYpcU*+LtEnF>g48)DtheVyR7qHp`hZSxW&|Ita{i$dk?lE>Itm7sNtT7^(% z4Pb2FBjM1}-zp_Mo#8vJFHZ&@V|P4PzpwTKerC9S{lpI7=<-R508K+I@68txzD!EkZ6tz92^bV@jsSjO7(v#jrh(?i4cY3DeF8D&O zSp6`7M`V;nxwfy#%`Gib#tV60S)o?J1#?!223EK_zeTD_NrhG>d|qdT8Pq*DNI}6P zsY-wa6=vFq?6SO)kCCL<8No4^5v($DN#mXq}&1n|Lzz|QME+5l!@B5cQQ`IY0Q@Xm0;#d#h zNgkL${bta#*E3K-f^dXqqn~Gy!oJoQmXeW$bOvWsOWt0oL{B&A?B<^^pep!b80FrK zqGFS0GoCj>X2}#99^H5Dj{iQ z#juVH=9&eQzj$5p4dEx8&(R zPj({~fe9yP!I8f@-5h&YyQI#@t|inVLXgMuCH2wzgX9b9wV6~06fh^*i`W^_Lxvp- znk$@>)6(-_hjfQZnHbpphY4oX(4(SZBEbL^i(lP3Bv2&_%0 z_G!{_V~bUiWT6x2X`-=jd^BA3i_vj#OOKb!t#Rz3GPuf4)F8OHiH!-x*}R+`?P~v0 zu6_6*($q2^qtZu!tX!G3_*)NdNhV}W?m7DidzVjKnThuNTOg3W}`0YyDQ ze$|!hn6L685Jz@ z>K%KEFak?uqnWOyL<7)mKGuD=gAzFvDWGVOLdZgrbLP!B$Oo3w`s{%S#29bdD(t5jqi z$(guvHhB(oI`Rm1ona+G+HB|w)Q>C_3Fh5$6>3oOWw*LJmV9`elm?qX^(JxaRenBvE9T~VxAR6#q(T~Z#qb!jd9m~v+ssR zo}S5{SuZI+Dz9q0(8op8f81bKgHZBKX8SS&!`wDsvr@ASM66szo(m({L=0@$K^(dL zr?~n8F{B@!9sAS73JI6?MxZZuchyh>k@AYR9$_d34xci=9!XX-QjOqTAc7B+4I<%}}nK5~NM&DV}-9S9idJ9g>zWo+L zw3x&}B-;|^2BUheL8fCkIkKQ*Vw-he&>t8xoJ4G&QXyx~ey-j|bN!DmL--r34tp2O z8Li=ju8Odn0)_nfVh50&*sXyE`4?zojDBGDY&KLY8>1Q2M2LsY+61vQbfeduK25lu zyh}Q2(P6^;oHaBY%Y=Cmz$UkUMU?s<=1*V|6xIAr+e}fT$x%i|S8$p${q8x^v1XYw z{iCezldxQYx>nph9Jp3!a-bO1HfKyW71M-5+cP~JjBZ01rw49`+~RxdpNFnx*+RAI z*_l>#%#k{T)>a;KxM-_3WclAlMV;I$kx?(qd?VfZ}%g!2KrXb1batg?x&15MYH zv4V&Nwd;bLm}+*MLg2alj&tME|I^0hA&y6$_3f_nan6h^OOdCNuZ<0JG$$D^QiK$qVkqeVx1RH3kTgN z#&uo8&x`E)h3ufT5vcA=< zf*Pb{oaf)uTG7dq40rK(y&ywZ+~1!yrn>EvQDGY%7G)mVeXD6!~1{K%2AveobK?r74h2Turk< zLo*%J>P{3rbj>`Yc02!}_|rVv=PR8N4*eD0@wjxhXF(0}X$KqZoCrl_dlLBRk zL^XC`Dr)B33SGe4hJ#8d+CQe4BjR&&bUDJH6RyRv?q8VA%znH+7D7fWN`5~FMF*lR zhZ0EB#upA^fu6OY{(JeO8BNX<=Xw0Z=}x9><r6!ITqLD@yof%y!*nDVVmsR z-qYoo?DiXCepp+3x-?7SaCi(C4(ZJ%+W0U{{FgfP-Y{kl9h0v_)!(3buqcDvo;^J3Yrd`|JT{>tfIXSGrj~OI&jUV>>=C)_I!I*XA5h@9-x;q zLR9FF%42phUWws1GT;wyT4`0p4>I7PkpQ6Vx8pEilrYc&dVG=*Vh@|fSmE4EWA0J$ z3tMo>$c>&9Uo#0)Y1IAaEySa-cFU#n_Ge=Px!?m`mIaAgGKpJSaP(a)EF3xxx{-|> z*dgd#&kv%}VP1A)ZIvM{iBg)T1yUC^iJ~KUTrTkm$=iKf6a3ak-w zV39~;3y5<(tu8-AWL{c=82Ts(kC0?^i)?WSJXVpkix@VL64!-i@^*K29*p_`K4_&J3uH%Z>|60W1se&{JrgXefUm}Pt%mAr%=S8?TF z%W<^qPdTH%oYK*ySb8kjz$6*F6_sIB5Su+C>EYN0Z@5}uMI}E#5(A3uqLoS~T~4`o zepoy)76jto4d>kDJ<+8^46ifA3RnA7YnTJfe`sg@2kky2=5wX&yVw9?Ct!G$2Gv;X z45})5u*?~+kKnb&Th2B{JZ~>KGubUM4tU;&jqF4q6i@mLyoUSS!D};N6-Rx{B;z20=Ue$g==WkOBn7>o$=U(lQWQ!S z!UX+^-g|JQ*KdhX<|l;THojZDfeYloc@Wfw9kYN4T`=EpOB!$~?3O4%yZFWFBLh0x zEn>a-U2hTa+sJ-ayjxgDz^z6UA0VEzXXC8Gl5}^I z-GSmFOVqPvVv;~BwiJhMQb6yj5cbpilo)0yVI<0>nR*i<*c{WYk#LRq0E|SQk15Ktx;D_tI9h0yqM-og)lUafU)eBZW6xVH=Msz z*|U~jSWP{X*ZtX8p|;$tF4~RMGIKHeDw;>Br7#gbYOMLAd%w$zSDx~20lcWh0y$#? zYb+M{SBXAgJ3rK|xih_PH&`7yjm2^vvc@R$>wfC`QJc%(Yg=QvjxNJNxekM?0-Afhm(X^qDxtMI%O(9|G)AG|)>gmP_qd zO$WkbVe1yJ=Qy0ersTxVzw!!5Np5V{l{xb7p3x?>RlhyDV_*66aack%JZs3nW$?6x zo8YiKdaDczDIui-Mplv9yV!9H_D&xzJXra$cd1xy(7Y^2!8kbB6e)jO)_S&G0BKPT zkk!Q&(QrhB@?D=G?STmRj~R1`UI*jzxz+*Fj^v!wz?1QmkUei1UWY zGzNVFB)>X^nE`Z~HZ!KCz&Vb*y=z6Mq1YY&1znxtb;_uNpP} z(3*;gOz_Z_Sf2ZdZ7!2}EKxxygL@}f#>aSb$Hu#HH0^0J0}MD>SZI?gGza|6>&6DV z%@~v*JAsA1@v*`AQz+1X;CF$N9C=&5a7{0^4jk^90rV`rZRvJR9Z+*N83KtF(*r_O zW+@~SOPofzf6jU3xM8;>6SZE@(?CHqg4z$k>HgMd+2Xu_cLybnS99V2Jeyn1m~L;V zyvM;iq_4WN;vH=hj>^(Q*K~0g0LT<^3Zl$1u8RaJJ3YLa{Nir!Uvp$%;=2RQs zF-fuW4dC&c)X^+P%2BkFPk$FQ0=j!XI{AZug~`RbYfX3npQV${q%wq;Z60+OWo^$a zSRd%P!rfLOj5Kv$VZ~8`JDY^#u3Ln@=e#89-}jYK`)y9LbQ3pkqdpDaP))lSyg=co zI~ON$6(e6Y2`N!WLNz+e;gw=t&ln#gDAz4YOKp*qOe>n3GVF+S(SwCsZ#L8@yFcJ35pZi{ ztSa8xG|y3pxe#dYaNX1xUhDw1hNh4!9DWd1HiG|(JZ+1B#g|Cu>UwPeapn`2F_7P?0Z!n{vWdbx{dbh}!P+ z?FswTEW(GK_6%*&kWA&P+4jp`Y1x($*NoxhS76;ggsOg)`LCWKF^>wcq10Ji%R+En zPidQlG8urL1(PJ>MdjMZDBG)k$8~tF*3BXpxO@&BN}nPdtCh(zhQ+G$qwmIs512&@ zS1hntDopFQ<)qxjQBErr9edHKBybPu$mXmQm1E{2sfo0-GjYg&ApCie!zr0~{1W6Q zqQ9onhdu1r-zwwVgN%Zdm#o`#;Q6e|lO;Heg>t{8i_(AuaxnYHN~9+b6b(Enu4zdU zd~vzA()_iV&lS{`GWzruQfm7zOgj7^QQN>&&M*-UuknYq$F&&sp6;`Kbmnsp@?mul zcr4Z?Y5n{HNk-$cYJ0Ak`GLCQQ}-jv{=2z$ghP-$d^N{6bRAY7j~SgEcH5f~lK{<{ zCPu}uSOn1PHp~`ZRv|A( z>L1=QwZ&y5k;Fsp%K2@bjB-{@sm)iYroY~W#tN0>7e_}}ga(Rr_!6nW1z%R3N^yk8 zqB2Wss(Af7FN49^X5hsn9yQm>JKmL&!%44cEe{Owx7BMX`-o2PWr_E^oP&mW?5pa? z;j0#gh5_p$b=Fxfg-*MFkHeqtMu`glsRhdRFE|i!5iIn`e~>6B$g! z1N~{`g;r`nqRraju4*Fu_R3zY-qmF0zB)Dv&qND3d)#Ei>wplYk*niM9H0~}KO8)WE!I`scp0yh=Tietam^smCsLKCSTAedG`Ix|i zqbT@u4T`>9eDqI{yR-0yLPkuG1lc?O50&06-~6mpfTZ5x9jrExIwO7(_A~cxOccyV z-O5%Lol%SsqWrpfec_FUVz+Wq@jVz3Z%sp9-8>}7SHO&iemoB%kS0DpIScg?Y@#z@ zuJ*6E>!|)cc#hn@dSiMP0CF~XuQzB+f^1`x?pz8a%psmUcnlMDv;5?tTw6n01xBXW z=DUOGUWL`2gIE^^*q+%M_a)?Uy;W@xW=6CcZ@?9CC5J>imclm9lTIBX8bVT&PA*$4 zE&B1axGNVX z=-LDfo`AkJEeCP#r8XpatqZ(GyqV*& z&(e|whP($=k#?>PGi6Fk$)w%&UtCrSSL*q%TP#ZwOo6p{$a~QCLMg%4T(e+948-Xt zaij#s0G6+T0@jNG9>T=gJY`6zNmPa;QQMDf!m^-NZQi8#ID z6S;I&v^z?a3S%@gJR7ywkQiIC=jW?=EpTPQrnH4Z-zB&vO}b2=*)HNTAKCJTAUY7j}XuQg)=qkz_NO(;QfIj`C}mf9-e zaB=+cBd81nRV>?MocOlBBf!^2{0a`>CwvRM7NXo|)Gm2Xh|&;(&O&}2m5oRVeL?ZM z3w`mRkMbp2YQ6^&0XKi?puR+5)Y1xg1|d9nP5O%Ef6q4opVn24g8!uJ&_t7{F`=*y z6uUbvKF20%E;GVTR;n(9N#nDUO|e75_)OMGV(RZzpHy#EO4N%mBb2y;QL|3y)%9YA zf%lg=RS#iv=vngKz;qYrK#_%sO@JR2IqPxc)*2-3D7h4wOS867Ys6MU@`XqMxS^JL zHoc1N;=h>xC2~+dD4B<NydJUcq)PWIViq0q+;)xp)tIo=FAh!WJsH(Xf6lucR~33O+8~ro;#VRXox73 z#GNMfo}X&qD9ZQh!ZfXIQ8FmmzeUSU1F3MW(vzKg$q*T-A(o(53s1{2F-EoG6aE`j zS&>Z3xv3#dQ0Q!)t}icN>hadVdua?TPcv#Tp?0UbBqS+TVy6ZbJv|oCGz0g(+^~-L z&16YF%>UP>d4v$U?*S*EG`;cT0`B#hVcl(4`h${{- z_>Z3w9TyKXri{k&fHHeXLGABXby4ScvnvDN#`4ygiCsRG?f73x^Nqsi^kF;P%zZUF z@IT4y5Jg(mroiIwzQOM!8Z*Zh?5l?96gHBa;C%k~*x{LLML|TmD8JnX4?5M!wQZP{mDbs&9`- zmLM^?+$=Pm^K=jj*Qu#E%~3_Y&3^i0|G<5oZ+tAzy^2P~K=R&)2=e7hspX}*uS${i zUdR*Al6HL@40)J}Uh&=QK1FGAt3Ws}tIS4+6*e7BJ#H#Ci|l)R5O{pG);2hW(Fxz! zi~iZT&k|o9L;=C36vCK?!Etdzi)9dImD%d*DTP+V>HFH_|4P;YDO~%l!wM_6W*4vF z%5-RmakW0gGI>%#BX$X*O?Bg>mFt5co~u$80W6_u;)mAXCXS4;!3t0*>82K-!qDvX zyCgmz#8O~~6o#fqOQ#mqdhC8{xW7xe_p5og60;dlkzU1u*;@f!o1vT_E0@cxhdT9@ z#x%ibFNl6X$rKEL0=ueafDfL_da(0Eko8Vz+93!=t4*U+4`}suW&n>7I7p{E3O+YR zBT(n7X*p9gw#Vi1{o^L`I8E4uQ(adELq9}_*%u=P%vE1-9Az>n#jwNQ`2EL=?*0kts(=szX?tba=^%=MX+r;^K5YOtCu{eTj$&}6OxUH}k}SBi>Ev>K$$XdvHN zckvq`s9s3ylkjgV>rGecY;M68_gHGR$ht=!+0i>R#dEvGLw=1HWYXdg?i*oY*Ji#* z@#r_AGB~g%*dx-PQcg6`@sX)K z6w*#}#s5vQEK%sBM0NQfSmz0{_dC~;{TayV?5mga`Vy8AH~9MIt$}0T<7nbS@DxkM z#ZN(?*8D2$R7tcuwQs(BP9`5)?eznOR@94CA;U;W+H80*N`yK|T7o65o1M$d`Q~+0 z@#Eu&uj`4O)}=vbwg0h2;ZgXDS(-wn<(Wvq<$yRNau`9Xx0lAw# zy6*FG^keqpe&{2H$^`0C@wz@DjhCK&3e;=z;$xGcx%A_y1FcJXyvu(x@F}Cf0MN42 z_Zjey<1M0hs`nN69urK-c}k6WCv!JI;MW5kbT_phhsJQXsEP)^ttulRq4`4XB74F& zcN<3Sb!IOf@FV^@)xLs$`g=1lNUa+7%-CwiYwvT(^596zsLL)GhfisV`1D&Lz?O&i znmjI)C@4unGb*Fhljfq+>4?=ct_)^_Gj|0QAk z|LJFKytb-aQtf-+v^)hhMxlSCD{iM5z$)-`gKXkwv?#)GRT#8wLNT--Ys?8!rveAg z@*Je=F_W@;)X1{}@&xWQJAC;$pw<+VJza5I-h6$3&zn-2dLOu1K`Xb;U$pk#u;pPf zoQFz%Zx6W?+Brpt&Bo*zjC1@9n5e@wQ4o3w< z=3*7siLB}RB*ZiEOeb*ZK3ScNF?(+Cz})d;3XFDm!2LQ09sN59#oT71gwsRhgx(fQ z^6G6=8Y#R12?+`R3&u+6#;t2F1}8SgVHDSNBkq-`8bb(031vEWfS>gW_5_SIJgzaBKjl7>flML6ZB?SP1W{3mB`yR!>dx4CC z!ba4?I;o-w0?@>9r)~qYy8%nii?oM9hlze69k2ulohavwjpp!HX*SJ?hQ}(Ef>i5@ zP{BC;yIyY1V&^WyFtZ`fve*lmkjU zg1}X@fHE^H$Y#~z&UHIKe^lV$wy+#`bAkzc70e-Z^$?dN$ZcUJ@Z`%*S!sUyakD^R zkoczN9mpzBqzfhX7hS@M`#jBNz6L>XVqg`(KEiHM_*bf2pcls4g@>zJCQO;>&jz&g zGm#uTf!rqQY6E8>rSWPFBnL(&i4SI$j|++_0BQ(FR3q4TN!66`@DIE$RGQ;Io2_Ed z`0C$nU}AWNigD~i1iC*A0y?a&9?Y!kQ)Vn=?YiU7soYF;pd2|`qn)sSiOeFtwF?s< zsRp^UfC~i;v?%_}5pLyk+1oY`l4I_uX1v4M6&HCrLa3w|AKqXAo)C=W1NE(s{5_={)2Ty! zdvlee%V0D=>($IH942Cav+7QG8wDJL%jG$WnJpCQ>u3^|Baw~}nT*7!t!3#$`1W_ZujUN5s%1>-fu+&i1PeDH#=-$5rC@s1SUdoOZK~H&rn_{%J1N)s!#L zJJ8s8__=$fXyeq1+)g)W(jNk6=-#132WK4#}9H!43@&z#+1>Ho!l7awgA0&mvCkzGm%~nE61s?e_ zCl3M4W7d9j?>^n`qdPsG&LqQSTsAFy(;PbpnVZ7=GlZ%~&aoZt7F*2z7asv=C@bzF z3FgAniALg@Ppk-nq-I8A*R(ge8nZ4KzSaR0NXX=Hd$Z{S&qI5P!b6IVYqI{Fk}EUg z)u3&WB>d+Q-Gj|{CNvW-cwF+n(P2`&3B5%Zw^<;UJC`b?HA>nQv9yw*2ZmElh~uDV zl2J~SqIG{iL`iM6%ByjL;EUv`5{+jdg=wd8HEKj=>P6B{_E6uA?=5qch+u{Sv=gtH zZ=&prYti&=Ta-I=i)9?+%M5uFW6f~O*=vDdJMk5UlJ0#MVh5kRo+D8?+&Rz|u)L^j z8@6+~l>&Tlb;}5bQOPtKx0`NQ@e;&9(i{DEvWrTFvw$O09S;!rs>}L;aquz6zo$8~ z5}m89Xf_otbR!fFw*E7#)$}*wxLdRAA}(o<9Xl2wf7B>=FD&8=+<`5j8KHB!kEVgZ z;UhVu`mn=pubNT$)|Ccs!Th+Blq(2{?#=KeZFZs&p5KXoh5^M>*Od@hbUz>d?0Ivn zrgkr|Mg`!n|HSbXj^@su_9lL}|D73N8^AX`JiiC-cHou`w&+rIZ)|p$))Wo(PNA=S z)FGgWTnD!V)-Gb0F&sci@eRTUx3Weq&7e^w+t!YEmjU>5nV78$W<&p#W2Jen^R~`9 z>aO|f?jh1B|AwL3R3rai4+6_^8fC_#kFON#Ws6Tb5&p7)X^2vLE+4gCcVqX@Hc z`%nKX+`K+U{g?P4VfGm(ex6MEwLQkX5x6k*BKCmfZrbiLq3W2FpW;SaNP_ge0TYS< ziV*^G?%g!5FgO_5FuW#xEKU-)tEZ576D;)7*kbu4v3KKE!MZK^+JU_|#=afhe|eh9 zG2DJyk0jwmD~M|_$N86K8>}c=ncUp?c*iTtfud5)=a?i#dwP2|!H$*t3!XkiKzOHp zfRPsTp5cLS-5V9;R$1<+5qO5v-vTY!)#{kF~Tt`~a2p%$pLie}{q$ zptC5oZQ9*J%K?h$d4HkSGBtcMv9ky6Bi*B`)6$(E-X;$JPow6fp3bR8P zKDHm3x1kc)_L;4J_AnMwP-vDH!YKvO(6qKih~&&B_4%h! ztxszz%mEwB+wnkUuBIIOVy^P7hLd3^+)@;U<$d~xqBZ!27dPtF4=3V*O8KE=@>(9R zKOM$7D;umJl2xv1;Wi|6&#G++T8KP5B(XlmDD!wKMYl5ma}XcD`E8JdqTfg z_E+u<(U~AiO)hdQ^UW|=6x&r-_nZC|*zDK*t`-bx;NY(QcPGXBE<>OHcS3{Loc)FK zsIu)WNVXM|*5iZ;4>&q%7Ubor!sp^2Ub>|h;U9^>u>Ya#oW4T=!XqBrwr$(C zabw%Yjcwbu?c~O`ZQD-Mm!7sy?bH4NyJyetd^5k11FPg6g%-%gXFRA|8*W*Sa%Bj-tZi&lh+^;3W&$!1RHANd2YPrHe z{c@$4mQ@6ES-{JejFr0KGTFb4EXK-3rQ@|V>g5dM9bcjzdJKL)&S*+kVudYstRh#mMjzpeN)cQ#oBiAR1>L04rp;zP$GvQxBHmLnXDA%HE-TS&18_XZI(*QDI>4A1C6a5GO1&E!pMxX}i~G z3t!1>lNOLGgHNmGH2yQ|--WKQJUIrS55e8dfM%@*9rNdAuDL*$lNHdOx$>lpYEVZ9 zhkQvnQ*f9aq1n(w9DgUk?LAPOun1=>(>ApG?@o;$lkbZzP=#uJG=OLAouyv~qQw%x z&qNA&)YL>r3yN=CWUpRi;W!P(Kd}PG*%- zQ%aF)(OT7REC zoE)ivsqKVdAp~;#+_SVgSETg}csMFfA)cvAZ6S28y-9r{KfjK~`24=PaJjisA7d&s z`8}Gp`ITmwu1*K8(u|t|qU%s%*qam=u7`4JP=y!$&mJ1i1TUXx0gcuT?5h`2vD~uz zqXxVSow~VZENwGknHP`)YA zR}_>5mW!-KZ-UFE4LjHegd~OeRooCHlPrr>xk?O3ACjV@Qz+{|6Oe#NKFJbS(S^m{ z8)tMIt{$=Sp@6w)ucUilClAG=_Ipj>PcgM>>%qDy3#)x6?$L*w-mb#bWhfnup5B?`u*p)SAI?8vf~LtK&eYYc1Rs~6V7mq!q>4HXLEb^Pw}6ScQWhZu zk9{$yh%h?eY87BIg#X^y8uBkaBv=(w&&lxcU0cgGkr@)s$C&MgtbgP_FyftP?p>t?gg>+Y#eWW^i@s%z~maRKwNo zQO9~#bnOkrq0SwaBy@W!^qh046e+U(><2we4{I+7C3~|`ZV=Ea^e~{=&ck3Ti z{c&@sBIVr>6RBj_MI?TKA#X|mCYNDyLQscx%7AJ->ADYVeyyy7C-$$R-=DgqYmA33 zm38t$+ZKtUS4B6}63<P>W4E{8C-FYsxe>9@oesEmLeOa!O{J|RcSn4^`-TSd|bESJXEZ0-6OyB6} zd}V@aXxkOC3Agd_w4$e{6Q2h^o+EPAL+zPriSJBsLjpWpNKy2Ccc^F5D6_9vGbZsJ z(Gn}%-d)KP)D8l)f^8wBva+hG>hsRmQiy^RNVg49N-;5Vlq6!Tj=5G9RO{JN+fG$} zCPsC-J|NL_bKY{;7@{6C_7+#YRo4B^Ip68pNw-(o6^cCm(H@t-k!QL-#O-m4>iuOG z-vY4E6iL_pC@wY?jQix7mYui&eFyEv5<;xQCez>(vm=>*1BHNnbXCT)edj(@?@5ce z8T!pT4$r;r&c1RrPIu1{r7F18)x!rXN~1@_()=#v-Q71G^LKvpHgnkfv_0c=m_TzQ zwfVI55E0s^Q@&PpL7Z+3h@Snb=war$Enx(u0VjOSx8q(bC~Y@c3Cxopxc~WlC&*os zP2J~uub5uA0x!`0ZG>QhHqXQ@UYoJHLKk1OpRZo?^obn<@0dVM-l~BegJc{^qu^w__r^gZQ&XeehX`0PN}@2V=bBmlE^CMh#UwdjT{K;CubEwTBUP2qgIh%nObI-pCl^Zub}tU z`H0wyV1antZ+?g?VIgAJ&<7sH)JE_V zJW<~Zh%-(R>{zYpFS>myz#Z@`x|Jgw0dh|`A)?i@p$s|%_(p?+t(UrPv~g=@M|B?Awf za+RM~IAIVHx=#qRm!|G~0XzP5!fA{8@5=Ih(;+`EXzTw{&kgN)UjdvhyJT?x6g_O5 z-C{X_CrsMz%p4cKU3r!9$&jIoJg?cm51e{&aI2~(Vj^C{tfCh_P@ufI_;9 z+Ybr=ZJV@H>9}9aU6xLjVCj4?2!HvtuLf*L&xH5cz9{D}F9@?Xh(n5i`xc2bQfEN@ zBr^u^3v}IoOLS|<(V9hP6>kO$cJE0S|u2lah!@EkOC8L23&0+l%H&xWP)uX zrmyy_S@32~c5J*ae6w~V@BX&;CHC>9sLX=1K-na|xI4WU770rx*w3-#FUa=-1n z?ghK(V^TFRp0j%}XSc6Aq1354M8dE-lJR#+2_W&+p6j47(9P|9LA)0(*Z$GcOj{1D zqvA1rgyo|ld+*AxwegD&uqvNnbw^7Om!g;kuZPz zWU-(C-jQfhNFi(&!OS}_KIjI;r_c+aS+}%+sBc$jq=)PPA*SVQwo`gx^#UYckH>wr zKM>O$;Kk|1*)FyzjulaQaEZTqCJN&H1W&p~f%p9`#3iGy4{|DZWsl<288Mp&BpK)l zL5VvEXZa8j?D7&iEMeueq<`Q#f)UQGwqE2D6Y-pJx;cpSu=v5{C4ysT}2*f zAcA2*@{{zf!1+v;=}6A_(lW6w5Jezh;^_ESy-(5nVF-ncCz?xv7y;_ELU?gLEZ90S z`{6Q|h|O8ZkC(5Ub^MnXKvUfyAHTl_zFjv=l={Ao{h;fCW{$2Ojyv z5r)4W1r+ou0BR8l`9af#Ya(B7^0hkzRix3|%pm|iv3=k1WDs$^rp<<%zB~Mi|3X0G z!??^D>9%^Bohk*TY9mrhjH9;qwBZQZa)}%=okyFbj9KfOnN2^@56N zSJ&((17HF939e}%?+cAT=wUHKi}!hm7jGi)#4DQE5j4j|Gm$6k8peD{`2oz!n^vKY z!&H-eboBye8?eUgxHW}U#(ArB#F{W>_%wP8eBto)0`>Q=7pJf{~x)c*-?y?xlPhCQfK zP7K)UuDCw<&awtn6UH^4>_EM@#`zLX0~J{SD}p72@2tyS?6ZJxGQyAv$^iWXI@9zE zr@6!)ClEy9mD-&j5=*TKa`m0uca+ECqrjAAdng>H00&0px&vou>_ z8VC4zU%R5;yH&2eeNitG3nE|;_z> z%`*orDCjPCJjaOHYruA-1T?8ZQT;x+{p9bO#(sLng?G2_`|007<${dg?os_HEaJQH z{tW39g8q{o0oADYTq^^<@w2(Z?}7_+)k3i^u$g=NLoC&fD!orNT3mhP@#t<0KMDptC zgf1S5ybasd18rMNWy9UY19dy5Ous>*i*Qut4PJzEf`<^aa(!=k`|pDx%S}_$RUUF0 zH%l_No8?Z#kR70mEj|aj_YaTzUaDvtS*eilj3x3G@>5aC@oRfiJ<4~NdranS1zY*c zVoCq=bc&$=mqQAJ>TALFgjeZ?7~^GMNyuYx)4VH0tq`Yux0bZDf1vIDvI$*p(sC67 zThk%^Dfi4>LHXXT0e?9m z_V?Eq7+`yTFm(V(vuTZUL{7Yi0 zFoSM99;PYr)QoAa<_as%k*Gf=EA~5IOR&~5N|NW*ieqJODN>$6G^U-Bbbf4tu(En= zI6Y&vXyy*@I%X7AdWvGOvQR^n?*=PhUS9fLJ7lb`|0K(GcStY;K`&n*LJ&wTnxG5| z$}KaTI+@DTU4tMOFJ2BBRIJ`wBXgB@2+CHZ*;yI__twLDrJyXyTOs`euwK78 zo^YH{0~{}@_1SDug%z<9SNj;pYYOxGnEJG^sT?gAFta`>A6Qy&@Z+_PHxl&(O)d>-np?a4xd$h;Lb^}cbVdr;Q8)9v96$*=Pm$}6f*wxwu} zP>zzo3ljazy-u;npzHgl=+p60jaTnv?h$x8xuB(AG%Z$Z!8qN7IN*~UyclMKb1SHKU3%%bk;yjy(}s}^-_^Yc8)Aw?0NqAh9}@W z5mPrih5I9bTU%iKP)uFJXMie@h%U8RHbxc`3nddO@fpCxJE{F{J7e5EY3DQSph)&JYalnK8$92lc6%8lG5v>VIB)9YTP zQT~gr$x}1S;;;}TNt$nRtvbS=SczY2mGuYBCpbPAcBCOln8Bw;*T!f?{R?XSF!Nt9 z2-vK(pdZ6%O(}|n-z3EwnEO4R_l_0+xF6*q50Si0#>7b17^YxA6d%4dib$-YUk;ma zgrm*q+2{65VX*tjqU@zQ5yLat2gqW^Ty4X|>J(8Wot(O3hxs%ko*KVCJEU-qH;xQ_ z*P0hYZ?;EjVP$@UF}n;yJo6=kGkmSmSCyGTb3qcm(0hSKIq6)?XT{qKS3 z6~XW=l3|j`mvWiM{FclIz8WWoG8{*!V(QQ;=&#Zr_=EGY=$rMePkahE3i~pjuz;b%?ANM8EI|Bc_{S7P0&x)c%fh#73A>owEfk z1PWP+kKq>E=gvUg3X}}`;8qc+QT7m3tYV7c#F!_YcnVxt3i1u|frzG1I4A_12hB&( z>_&eAC69SF)I)tHYps*b1BXSb%gc#;1IGnzM7QpkLeiW`p7T`TJI*W)$O+?*?(bAF zxUR4V6)85^;oUNT#4Eyax0XB!hQjs_Vt@5iMN&{zE(cQXd%XneDv8G^ zPkte*VB4c2xu=NoPLomcKhT9X^rpv$oB1kxVBL2R@-Hx9l7T~q1RarlVZ$_tsO<0$dj+L>(%Cnx$2Pw6yKLK)oTl`HS%z%{ zVS8ab`-CwT3pk$3jlDI0&qEu`r@Zz+AbAb(PNF!#+9lsFbbU~8S6T{7h5pr4VAED! z-8W9fSl{LmfnB`ck+<)1Qa2=X2a(@jBB>ZZs5Zn^u~PjEgh@gcF+Wj+IGfuDwOdrl zL-o3#T8ThP4;T!NNs|NrSx%x8NMOEV6G5xpT9Bep%2SkemBEZ?N5nEf=m#yNWMDZCCzSg}pQYsFIN>}f{1COZyJ5Zk7_tc~CQ-sq<|lA* zhhUeg3+wpVWBa*kg&oduv$Gh>M|#^#xETfQ85muT3<_%YD(ap>3&`9RTDFkXEz;(i zh&teefj~%D3jMyWV&;%kj^BM4iX&)VG{#bcf01%s>lSPWab6Ek$s5$73X^Q9XJ6n& z>-jkO;1a);A2~Gx|2%zIxcWx<;%;Q~o>dL8k$VEj;jNw%c)72OM=g~C`o(ZaT{FO0mx&r2sZeY=)f)FeDKp;SWqU&i5*-lk8!Ly6 zi%mU_Zq-1VEy4Y@+fV}rgtWU_B3j`Cm#eW_xbKlze8E7Slk6M&jle>} zN1i4PQ$2ZvTe;;MG($XIJ4CH)K61Jl?pbL0KFG=B)}kQ+1lo7}$F!RGTAnkopiyLY?h{pOit4DsZ6yzK;9QZcq@bfU>1EEYsYKqk7Z^NwMc4XaLWY zbs`As0F>G;kLHaDBcmBbf47HBG&@F5l45$T9-<`mE+CE&-ivQPNS&zk_KHfRv0tB2 zYLQB`a~_21{ouR2ihQ5w@LH&H>U&m&d$wBu}3X!jLQPY9n9XKr8X$0MYuMLjT2Y zx)ipWhs20V4XwVVoNhxcCW=u=gDEZ?Np+hZImtzgUSMs9Tt7=@#0O-uH;Ki{`z@T^CN^npX%|QkbEM;B?j*s7o5_rMJp3 z5um19-W@lh*4UI}%OFuyIwW4-@E-ZL2n~NUor}50Tj>{Z4#tpE$|NdKm$eHAP4KzY z20+^n{?f0Q-cFCuv^l30ZE%F`oS#tS$V2%W&dQvikP32|u}7fCIwlk2L8Jn2&~@o( z9_Zg4uVAAdhy&y(;odl0DNXl91-L0D1n0|xKW`#r_xk&-apimDgBwOyuk-LPxJ*ie z<*z`3xbFv^jkJzoF)}Ab=~Cgq+JWm{vuEJ_8Fh1;i(Om6pIQ+~vcF*L2^etp@8B*jajbmPAyYn9pZxuGBM&yTlgN=&vmNuhwb_Zpg39AntbEi zZO2s)q(^o-Mji^&BaL=(>~x9Qoe=gI{os=s5ZbxgwT&vs#h4^zf5GY#*8w;MfC51l zGnKHTTwx#n2Xz8ib8-2!WGHhZOA57ub0$ptHy;hmguE#Zp*jko8GJn)#{C(?nAxg+ z%nq;^fVpuV=g2@xNSV5MdqhU?VQjhY)n+N(_7fHBBtiWfP;JI}otclJMF7<5BlHOf zMO`=onHNGe8}&w{Oy1dZWzP{A`VSE7&|5rnfc@D88fRJ%Ugu>DmD~)GPUmbr?P_c( zmBawf&81@RaD5Y;P03uV#0AJ~x(aFe*d@!>;DuG(WrI=tNS99On5slMGl{6ah7^CB zwtcu7b(4E!Tmh@|#*AFTuo|bZQ8Bc!9DXv}bR8LgyGuCu0VvYn1uGh8YdWY!^2MW9 zJe_CBIaq|*vqwKh{S(d9<{Y;6(P@jcN>Rv!f39`xrJG>dj%?&smjy=4R*wlq1z0NA z;+-o6((z`IjNe}m48!-ZsUV;0Gkl?I<(2t%8?rD)(viU1cIKjKX zz(1mT7K>0x(je6pHpo0;dCk(43R z>R4@HAqbA|(c?CdMsq_jb-h;Bh9hFAbMzs=6tMgwaUg7mN7TGSkrIFpEm4WaipKy7 zM!Q?b&8OJb_@E#dUCQj5R*syToU0#;BNQTi>bNcQwGIi%uuLJ?Bj{# zm8%>Wf(m7)VHg4wSQ)EQgVtAAtxw zW}^lA$KmUWQDRi+CXsqDp@r?56$kkYgy%hkpS+A7pC||^>*6P?7dssJpxIz==Z3H$ zZOq4mU{0GLPU)uko>L$*O`P8b?ec8BVG|0M%-bjpZ-x9-G1pS}lCeMQjQJ{xR+>T0 zHu24c)(hFl8U1N@a*r^b%~s?O4P?8m85mzH~4Y0nC#)Lr#g1uBVrkkTK=am2rpw z6tZicaLaYHyClxurCwZ6=;`g6X9yNpdhpQofMeP{=qwSOu81PA?PFUj^Z}G$Fu5zK zlvCye3o>+6uo|#O4=AB*4KDbXX}|ZZgyu9EU6+51jvR+bse6r6&$u1$go#{R|NQm9Ev)J6c0$sdz?4rFM_uNp^3 zkW+6Oo4T9rzuk;fgZn}xURO#&i)l4C|LiJVMv7ogo&BYNZx*!?*k6O|drLHJoo8Cq zDl3@^nx2awlubB3w5+PojnX@)aH(PawIM1-(L#o3JID(6L%wSY?=z*>P1A%wp3FyE zOjt(OboL3cP+R-_j3YGbHk%jG(_nri2axol)s!8@JOA(>uqg81;?0Ay?;g}I@NzLT zZz(?=6@RWG{XMExlHnvGrFV`2LaiSk)9@ILb-$7laou>cFWSE41+G3`P2u=vi-^s&k(2`|=#U$BkcP76R1(ad)E(fktS zhW__R_xD8iucfu5stf4x=)Q)(hW`U>zY7{2g+zop=sgf=!w6tk5tL1vpesb z!Kn@`Kg_i6ebMf*br@QNaH{06Q58|2z3!wOuP+nC(&TAZIbVb zjs3jsQKA$^W-7wdzxOK}lA-7p5?)dXybYC{mZ753ESZ9mUBroL(Y;Xe6EN{PZN?9x@}*ruL+rNF%%HtTyVVU28WXo2Ak5*m0X0n@0)lVJStNQKN;;y$_O-SX}&fY{#q(e*X^5z zSv4xu_IZg24kXkMeJB|E04AD8wvdqP-b5CVFhPVDJV6o7^DLN|NPlLq?3!yB0pT(B zm}DKml~``NbN6&`@sNVKbwsEhAO^u&(H$iy6&{?oJb-yI(^@R0G|5s{LeZdSG_j&z zjj6T$LVYH_b&W9E+T}?>Xtsg)(G!tjyz1a z9pj3arTPo46`K;Wn+r1Mk6in2F1UqjrwBSr!AYqgnV0uMiL;X+C*WPG)#i%nVqdR= zPGoVE&Va-rmpT|eCD+m@pk>%h2IL9eWTuzMMS``Zrm>EWIW8@NtC0HH ziGaZGyX1lT&#skPFQT8=ew_$zdl7FUD)*gBC<}C&T*3hj-ZgQRfz66wo)9FY`uWmU zV_dC#+11&#Niq5cYO%lmFtd7Zbi&9ZGg|n+S$y?*hBIM%0(rX;JUn-fe9WA8pBjU- zAY2+H;UhN=#nGj7=^&Cf1XR$f9wG%Q;5tiVT~fbgt1itgASNjmj7&&(SZ z;FV+QDag?km*-M%s9tD&ALirGjP|QXrSF7F%k;TLDj6YmuB#;SQ=CouE6MKT4q~UN z$nlkSzL!UZUJH66*9QwNJe*Byt=s3Uv9+zf*jo$@?6c=PfE(*j80mGr;RaaC({p8? z$#vRnXXXD42(zxsLrtb2AIV@qjdmf~)k`E@rQuMRLD=-&r)G~!HWrt+gOg#|{po5} z*=ZC;-6HRs^Iri7+`?J<2lrcW$cl)!GxSSqv73XfY+AV)Ukd+bLIeNXvfhdPrDu7A zFvx)`g)KnVlbASM|A_koh1hFES>QA9GAya~0ftPT>Djbzi`&Uv5aSxXn*GesrlFWp zFxI!SJsX)DubY>M*hDBn+766%eyUX7>9!6Tbl^OWyjJVGA%Xi@;Lq_|KXJ-M3)o#G zD^oG??_o$Vp@3b*G&J_}&N^mh4E9)f`OLJH`1MJQhVK&Svnl*bW&~;WbJ@i-hI-py zw4;9n=1mq>O6%YcY{uxm%35fifBJ^{X$Fr_9+!s*&x4M2ms zTU1vF9+%}3^M1*dTr(UCxg$wfOU7*d zZjH{g+;S)chJ#AhV1Lqj)F{HqBUVN}L`s>AY88Rd`1#4*?3QmhWzUfhG%%CY}g&0^Q zAK4-kJAOI^0X~}=U^j={ae2n@47;P}!jw08tS;T~z@15G#zDJ7T^}=OGZ1uqA6QDz-10H` zxH$ai<&T$%h+mhO?H^gJR-R_Xld`P9{UR*MJEofcNcMZJvARv;ptv4BNnVTykKtjI z4eCe$u?~UK_QmbmzpZXEy1O4~G$>fhvl-!tnC!*&Ebyb6W`J~Ae0UjlWDm*Odz>)N zbGIw=ind|*_RSa$f%D3dA1r0;r7B33Jl_`;g002;lmMIEA|<$^Y$`Bi@0Je!i2HVx zDopelX)i?p!9#PV-Y~L>#7#lZG@XxW_z9HiK(WLc7Nud5oPEDq8FP*-NU3pSBDGLe zg$p0`Pos}ZZ~*qw-4rYuMwSr)&R5>B>d||hveo|6P&5gdLpzfmvy||-=zxSiai(^} zI&Dqlp8j`y6YJCj@hmajEaw1Br8J-6UL#Gkc)#i27N>H}QS6tH6>*)?Qw7D*c$T1r z4Zjlf^6@qN4R{k(FKeqH#Iy($+JT6^qR=*}7v4tvr4j)*1TLQ}Dv0BhV3*kPuFdH) zmOo=1kLr}Gdk*?gJ`rUjCmdn@$}*g?gpNzYju#BpiW-KUaG zocbgN^Vb;mlE>+!gQ9disFRqJh1V_CG0;$(xYLg6vb=Xm`Mt@ zh+4T+LLAmFwQHOwGw;9?zNi~$)=(Bt>4vLPBM`X4m;>nEqNkM7784FJ+A(_2r*`HP zn$*I;y*e6*45?e!+2EY#y2+*^xnfYaIhLXYW3p8kzkL8U!8?h}(?;8Mgr|2+@I>IA zFY^4UiKbIS3DVTtdl<9RD_BmaIZ>xQ`1GC4sZOho#=x`-crKa^Cp2*6;%cMFm%vmc zsCb%kdD@L|u;M{AlWVCPQb~ZVGMuF~8U#m(Pcp=4CC~;=T(TfP6>Gp zk!=W(MwR`ZzX~F*ed!Igr5i#~jQr>DG5q@rBRkUO7Z8J5P0EoCLBqC4tqVj-n?pxp>d)b^f&2={;OrA)Qj5U}w*BHOesXkSm2GNT43&BxecW-L6B4-Ei)Tu3{Kje0u@|N2UCbZy@egB8N)QlV2FLX;@M;k0yo0agf^A+s zpYyc_o>dpcvV1L{ZReO;aJ=Kg2zJ{m7SuIvFyO5q{HZ^)B|hlnb+Q;okB&{Wf4Sy$ z);(Of7l*vE7=N1znkDqUV+9HSVKCip6uoJ+Z&+JHT{299O9+lb1QXv<&v&PgM0((9 zS}axWiGn(|PUWxPSmJg5$P}_!iA&Iwm2FxEa~RcqqI(nbb+tm)M+MnHwsk|T!;Lux zo8}KbJ#MB0e~CO4X+SbsQi)1auwk{HQ{!r73P??`Zj?rsgnFGeA>S%^FG*9q@xE3e zKF+JY1QLBd@4j(PN_&CW-2O{mmrH!NO{8#^O)OOwo1Y~-LKbWLkK5A>ytQ)t5y(84 zn{3U_;6Nj2IV*SWCJcSoo3lON;EBqoXi5uq{FDK^%QAw36HG(xOI151jVAi~x%vTN zwh-?nLIZzAl96Li#nQ9Y)hqOhy*9_wW4-EIn*~y^y9~D-zXT(R&R~W&ju?yZ3>tna zkI~+8JKqavRa13H$Sr{D9b?x$ZPq(ZeD=3yj7 z2LSW-qm`X&;2%31w&Is?y^zNSgBIqmO(;BZ^k1bdRdw5m_GBffx|_|f&0X0v*j-9CiNiWTr_2y zZv>Fmaj;H+c&k=z`t?Vl9cLr!7ZN_SO**APjS@L$suf!j%BkD1nbV%Q^WL>UEm_sL z3)H8)N;Ary7%ByU_bIgLDu;wcPIGh2)o=E@m84mr=$3HFxm)z^7I0^=;;BU3!m~FE zSOi+J@0P`G<>nC``#@Ddv`(Xear}W1UHdCE^#y(1xu6ajTPYDkLq7hN+82c#1f;b9 z%fH^t$AIBHX3^eHE{fYLT(&4l8-}5kyF3|6MuONZbs|n>zwX=_EO^Dss78>aYfBF# z#b`u=VQzs%G7LL zFEpx0d0O$`uLrTUj?FXleSK#rfdqp3@)S7_tXmf$I*l>x?e%r)iVb6D4#VEF%j&1% zT8HnZ2wa)wXHW3O)vDo43bAv!8MqVvY7ucs;-a1;lS6jx z3+0*q<^X%~(u#tEh~&c_XRsJu1EnT!Hp)t8cfM6;QRM1{cU>|IR;M)QkKDS&vN*_h zXs`Bk+rV6XrT2@OD>~qLA*J47`mU0itN>htaVMQ_=Sw@fy#?UMX$2WY(?=8@(K@en zmG}jLu^6>A*~S#rP27Fnq4GCCTX!md{taF4_MNGej%bLhlY$0;CfQHqS1oc2_ECxl zIOg5gl-8+E992auHt}GP8Kqfbp6%y$c$Q|9dZHTwegn9YbtkFc4aRxL4)X<@^!M7$ zYO}MFpY?~TGNcBeLqV%2pr=KIl#nHfvAbBp%jJ8w$CnmP1f*a*tQ(u3oNcNhEy-#4 zM3FcgvvM=t_jE`|mW)0uD)zr3Gx6%MCJrz#Ahhp1>OE(g$P57H!$xNT6+9KWVaB@}VS;rPtdD%JTR%KO5?$Q&7 zdu$|OhuVTDU{~fGSRmnT_Ly-=cf%+h+y2``Y7ZnkynI=D&Gf;|^U1v(>SFSg|BY4L zYYzYMc%38NS@hw01JvUIUibhEYCaZB#3=FhH<>c;xY2k(UCsf(-aImoLr>DD!-jo9 z^(>>*3FW9xnI499Il=V)hRj~aT&Thspo-mC?0O~%)TS+@!qfzvtp!Zmqo()Pe<&dj z5+S77`HK4>E?>^kB2>agScDug;C?^rCA&O50-`aI=5j}_!5XPFrcU`e3^!+e=5GFJ zHSV2gKRzY`A!r`GZ69{5_AA1MlDTX$pEksFU9+LgPPR&ex;L+tR3PL|b#s=7C^y-4 ziK**=elDo&(*^epmal6E2hUr{k2%hGZ2no(K=md}|9(>su6540TgY@~#lyg#52?Sn zxD?ooMt0lp!(ys2+}AgebnGgSt?Nwg^u!TEn(-F%B;?aABPX)kN+F8DLy66AuN*lQ zG6^ul*W5&hUp{gy!W6A!iQ(lfRk8|{(-GMMw9at|rk?;^eCWyWy5-6RTe$l*{!2F= zvS{LpP|hPO6R;+uXnor36v%#o?HX)!}i`c&> zOk$W=8=1u1Z>cq;*|v~^woKImN&Hb5fxKd)=XPLwcFy5=4;O2NEhBg04b|II8L+X#wmU2F?bvpY8htL1gp{|V>YAgPxXW!LKb`M%ev^T{ zjTJSxPHNXBejL>jHhYlMzSsTz?9opH*XDEG={?KyO1k`_Z}0YN;p)h-T|u&9!1S_7 zB@TWk0*Mq&**wb-cU4DE{tQWMmD-Qb*_Ny9*a9iQ%EQ`*gV~Mo*6$$lzVuJKn4@Ho zH)|T8d_kk zntbngODdp?#iGuQT#Il64Arhy+4U?RV58A0Lp^}&F8bC|J=I{%48zG>3BGAun1Bn1 z7f%6J$0ymAS67Y5?FPOPh%1?#VZ&Gsm^D=CK`=j>ABikZ`l00_w{*~!oOHO((2lOM zoyH(*w1XRKOpmDQ9{1G{(h zlIO>|*}d1ku!gjJ+t|>)BqX>4ajG8CTmDS(omPL;zJP{^Qd0YuN<#8g&e~M!>V0$> z<}UWuYO!kxwt>ktTL{Z^%+c3OWh$@U)elF=Km&d(oD$I>(*DXA}f@QWmeCc+Xejsi53k!1`gpT_hl1lWsGJgQ)GDeL zI!pe8vUBXt1nRPFY};nVwr$(C{lqpZPQ|uu+qP{~%&zWnKiv0Q_n+9~?6cRLE89o_ zPWzW;adU;M_FDH{jgci;fIEEk0ZFkQYhc>BG;;L{67g;K^poJKyM|VKFiXntQmbRN zrC%KsXvNgM>U6mLVVkkpnu!G^pDDpnY^&!@lX|TRwvfX}TRN0m6d(eN$Q=0uBltjs}-J$ByBTRFr|G)mYWDkO77*eP-;L}b+3*6i@NE+X>5qD}M$sSZ9+vA@!-~O<4iGk-s#>u} zlV1aC!?ZawYZG(~Ewd(ZH@$2$ z)JgX>N^9d`J8QPMH!=74ojWnPXT~6HvtIx_Q3Cz$R*uv=MZ*woZZfLA>qX$>MhZNK z_%oxWfw_S05zj}s3cj#f$Agu#+P)sV^+T7}=ia;wy2Xp3`^!Giun!_rZ=anvzmDoT z3Eo>N6xC=8ngcqw&-$U~iLY#X(ObpCQ*CDA+O31=t~=|aNE&U;`8(^8_2EkjA=e)Xp(__+5X1N;L&O6I%qHZVj=OJ*`FiF?nU>Y{~ z;Eebb<0{dFt|LLk!QN6XFcb6{HuFWtlk#J3`8<_KSS(W87v`>E4PnF()R0Jlr$2Wa z@yj3q#BiO*hN&X3+FA6v{^w%V)}nbr(eyaTXVp~x00IlNp+QhBAzcY27CvZde5x|A-y>#oqe|q=!Tvr<%Y`m4|=5V0AxUSnh zj~l7rJL_BQH(m1f<;RX2fht)c5IM%_wn6OC*!Hj}yz#6GBVFd`Pyi$W zvwJY(%~z>eT+bJI`0O~uFRj0w*>c|ex-ux`;J<10F5Q-gbqsJ;cv5m@9ui z`zQ&(_xN!~INmG1Xj0g8$cujpF9!{F_2IwBA-NGuynnmAFXG_JbzRQfuM;sP^pMzn zit9WSStg8&bUZzzCtkEt*jVBf1RfBAe*J#;*&;=GhDf@xboFCDhlhm6`V0FHirom? zz%O`m4DdDIIY*G#CABPqj1^bW>$)EJi=3ENwj%Bv69^bZ?Zje*9x93}{!$CR$@IIG z^Kjf61`z>soyYaSW%TT3!Z=ep>_eWr;(Ee|gm*05=N@lxNfOt1l2`5gtA}`>_RxoT zm{W)N`}Vb3vA4PTDU?ta(*`M_xpF8viBABi9;q#w@4dYfrm)COuW_PV_m!ybaOLUu z6Ro_tpQdNi9mC&Q5+t?PDFEm2gphGsrijq2-bQ@t4s*=SHKkEK(qL? z2ROAT)szK6M6HwuuTz-GDF_z8lc^;NITN!5L9B&wJ z>~NedkLNO6#bbWKj;Hj{1d?-xLLzyJK2qEu!0_=DjFj$_&Up650LU4TN~3qClwVnT zeF#^vc**xUdJihF$^}SkyO$e3+$;v|uCm74>fYGF8ea)rCa5sqOc~mZc(P?`?gXzZ3;@RCGhb4#Dj`Y(2Ht}4+H~jqxwL7|K+W+-sw3QBAz@&JpeDdcer${fkHDk8%vK7NE`mMPGB0iDCM8_Bx=XO@ zVN(ADtnm9SqCop%9sJPp4=9)c)EY*)JPoFsh-ZAow!#XF9v(qzqeU+Vr@zL`pD_=I zS&2RujK16!6o+>00QNHd1E@rG4z7(q0VJ0*GloR+pP?QH-qBk4V~BsKpt6ENZJ~?~&ml3{`?3CNAE7ZVBe|Db|v@4=w;YgiNJo(q4X5?r+NqyGp_C`*)L+<17`R5@T;MP+1v$>BsrHDiMTYwrZ71l-{aQnY1c8>P3@C%@josPo(twM@ z0R~@~n(K+xT9D7tJgFLrae)|Z{N>?q2gv?@vWyNPB#Hn%5SVt5 zZkNKY{$;asgYP?Fa~_xd`=Z;uxqC3i;Pj94tS9bINtrow^h!+@$fLhF3DTqbCF_4n zN}wJ28-6yBhXm_D%$4!|IF@prF2lbN;q`x<9nt*?Ikr4LCHMCxRW*NWN6r0NAc|n4 z1t!$&DTg@qW$bvtja~5Sa2l||$iuL*D%-;^WcjgR7R#Z7iTP~;|J3;84fov3;>B~( z!egSxef%fJvf3D__&KvTilfESH(-TU*qPKRm503^l%=n*4LHr*@*`f7JCk@0r4|+Q zCWRSB{rz2J(69?e!$z6FYJJ8iwgMq@lK~cthh(Le1qC-Ft131lvyBlZ{su4a#Mjge zcWLuTpN@~LQcRXEK6U}hM=Q;PpD!dn?ZQY~u-#&om1GTC^cC_4bZj0h^_{YI>E>^k z)y;b2mg^D&`?-l>+Ly%?=gNTOaxQSJa2@7FK}o?(>*+{y2@ZGRj3dxw4}luh2eaD# zU*kwQWytapCHE#x+0Dg{Ke8BSFx|sUDV9tiv15$1v+>JZ`|0~+ubRe%1* zc}BOv(T04IC_S{=9g3o{E^SeCNmD^rqpeLp?hB!e?3fGZ!{WlPWNU&m&JR#I3H4O) zBy14jn0}{Cpc}>@i46;^I1L22et_pI(<|AAK(809hHYV((Z}ZGyMGjIDsFCyi6e7R zGD>@AhdA^@>3Bjyo_i4W1$LCw%6D_T)@WKtonoD=KmjA+J-A0wq_c-!d z$PD@=E&+}?sN{}0hFf>A3w{Q2AFSiCKdU{k6vRUB$8PGk9v!cAK=QFX4O6q!56p)# z0S#8KCNSTNQvso!jyZ)g>d-m5%l$;T?mnd}hA6!upn-hQVKFubE$=OcTg$O?KoAwc z+ZMHTj8X#51yG&Nd1Kp&)jJ%L9+PuCoz`Y!;bItc{GIOu!Nj*E`x+My0%}^;v1bRq z%zt^GN`2Eh`Ajn{cLs9M^K3kX)0(_56(A1zl7`33;>oNyqRKHz~uum(cW7| z$pxS}2=3r)3`qs_00D))_7nr4AD|GpUVJ&+Pyfw`Z#yfGS+t8p_7>I4lpK6fjO5oa z=7C;FNPGui=f6yRhICLen9#!xu<Wt`LG8@cCVZ|+4=D;Lz^EpOnkxYXW z`I^Gfz7&?bE)Il~4OB$J@#!~z(7xWpyReE=aSGQ zzK8X7iL%7v;iRPCGIiAqBOjy-NIf#ry+`~xzhUCn^`{b*PTgTJsJfQYw4 z=;3(hSdG-5;SXBIIjY3`oH%p549#24BRD*B$uU#r&5kFRmE`vk3#F9&M&OunTB9mW z?G{NAq0We>UHW3qi078Q`n7-GT86lYl@n(+2GkbD77QIl5;?j8*EOY9?XMAoFi>^~ zXL~fq;OeOJRnWO~1FAe@^|ExH#To;7lqN0w=Nf)4D3Q_F51#aAVl;M`xr|kVAU;dT z7=0h?9$`p+GL4i{8T?NbdP?t>ec$WDhKDA!5pFl?Z&-YvCr`s%1erm4=~h^kP*VCR z4^`-B)S=aH&}x0tVY>`hwkTp780_vL4y>uB*>FHq4)9j&lnrjxh9yLV5in4OGDijN zg<@SB>8`gSH@(K3_{$+0+8|ABPq&nnO~vV1+@;ROCt6PB7bqwmH2ZGZTOc(~u$0&N zG@Alo!4nk@0XKo>_S7#VGlBRzd9XoVbv4t0@fFQ65*$9i%1Ye0&{*xHH+PBye{7H@ zLZ3$xtOz;XoI2kPRwH&QQAsmhc`uhCa59}W^u=?$%Eo7cvHz56fjv;2WrKj6e~Wca zun)6KUq5iDUdR*@rVSgjVn{}Uw$SnuBCPs(OZB_^j5L#D>~y&m;0L|s;$qqO^%rh4 zez4dBJE&YX>{l3U#JMeZrjk8^T366`7X-X%pu+9nEJU1IF(l}eS2`C=?q{tdPhe3X z8e{=yl_OfP>qC^sB<~m=L-`2aIQ@}Z-bKZa=d_$Cqv6uw6q3ZogrTRUh8zOC7|fj3 zAhF&U2Q#!QBTuIU@5*e$0t1?F4?I#j0s#EcWR~&5V0)1}+ zPeKhr_W;=yZZT(vKlsfcPy~l?ooyMRA=&V23`Ay7YqQ0xqN;T>7<=0$fPT zG(X?Xllm#DOi2*KMy_zhsPQz*5|>1R4kIcXL46L0j%bqHE=WZ1@{XX7i{gZi%3z{Gp{!%j&s<<*k$<;?w znLDvHmTa`-D+QNM0i~&4Q|W}FWeO(+lkw5YtbOZYZBzaCt;FpqO`tW3pq(~Fkm;42d(Id>27QiJ%3Ui6(6kR`8a~*Ml!P20S|G(hP=2_q8U)~S!2Ub z;^Bbv2wf&2qFkV>5W5@R;9)FD67I!DV}!Tp$G-!@&*_Fs02l)sy9BkV3AEJ}{s!+Kk7@3+CaSFh4!!z}CAd!c5?(yc6U}N@Ju? zToY1ie(|PT$`aoT>1CtYyOM+MHT{pdPaid0Q)!A|BAtZD6vglY*!Bg=js$N+fof*l zX^|cD8a4H%_?vMO;|QbNO10H?;utic5^1uj1UVemD%flSxNYA$0F90Hq2?}q%NMaK zxvEBV2HhvJK`z|J7=3gPVuZdapd+g+R49_6wb;mMEu6+IQvM9CDQ^Ca#Z`Oe)(&RB zo{Q_&f_jOhtUAsoTyZxHRhXN>OoS{L8n9?JOQn8Qw_s5 zuI93yz{LJ0ZJjBcC#!Rv_R-Tk#U2*<130%zcZ5xFI&JA7W%R2$>gGDa#HYX7+4BwZ z*_#m~4=tn#JYgUeAxCE{2E5i=mXyQ{$a4jnw0+YA4uc)P!pZ~kFReHkCVF_0(n5q) z`=e=E@*3Gayp(2@^_83XzD`mo#ucr%rL`#rZ1`P8>3G}AiKOc)g;ai-$tT9Tgj-Ld z$3gE~jc5@OJXE|lOW|_T{*OO7!{YzaM6oANQA7TLJm@0|QPV*>f3B43I93!9*q4vF znLe;~bP)ivyfswb%4Yur3sLyx>rRDvU)KfCMn*J&*@zRmb3ppX8Fk9S`U4vTOLPKg zpTGf>h|tR-PgfbaYxa#2(WC<7FnJ3Th*0?hF@P$ff^V~s`6LNw($C2{8=L01+H4t2 z&3wi$<|A5gf_!$n3$uwN2&jvlIDuWMRw*IAs8toXQ*6Vj2Pfh74szJ z<+re3OI3DFw&oLeu`k)Wt}zb2T2r;cNf(=vp)v9YixjSCuWMH&m|g8$vyhg%E0XDa z)xiB2zmCa48QzQ~yJeA=2l;Rl{?tyC2wy8+%BB^E56StdY^U6k?RU?jm(P*^Q)MHDG>bct#1pFs%#g#eC zc{@(xPGd%xp^zNvTmVcbhwKk+_JfWE*RSs#Z;O(xmf^=1QiSZ{b|qPG;eA85pQ}!z zS{GFX4>US@xm5u^efZ0+C#IOYqRW`sQHyP%QrN2=y*$lVv z8*Thq1?Wb`jpbOO(b$8>kau#$3+ci3qc#vYm7~9SO}MpcNi4vLms-s$nMalZmxbNa?6Ey|hKfJ8F3Bj`($viwYW|WDG2?Sr)Di4Nv z?zv=i|9ab_J-~8 zUBduum!OKo&0<$a+Oc&`cTc5mof6+Ys+s9^vgR?)&wtGx1vh%tO0dUT;STHdv*Eps zkRQOw^^@*%B0Zw^Nyt&BE!a$&SXe2vMp*~AmH|_@Dj;J^Qszo2a0JBj`-67^xXvBs zJRQhe#z$!>D7n!q_tOq#ndm5cU5fiuph=exY+IZY&!VY(MES8QH z4d6tEME}&|xarhAvY-o@k#L~?G9{?gVBEg%!rOyxu(Vm?<9sz+T9#0|xAnYA=sD5s zuszZNv3`>~oaTY9*Yc0^H*(z*RP*s)F`5(%dQi!y7QGs|(YXw&1wp1XgHG|KZVvl+u6@j?R6VDF8 z6_70@dm77JX$1~h9;V=U!E+U_2yBOQwAvQ*`4cQ`yHe>PM874p>LBbWD_- z;bf;R$htrKbeJQb#6nCQiR%nMXTE4a373g>-OLI_MfQB%!II&VOGm7hQ$hzr-#ufpLHBAFfA&zGAErmd71s z-uJm@n0aRrjoA~%P9icV28NOv;lx7Le+^KTim@MIa=_h1R7b2*=`PND#&Glx1~G>b zm68#eOoF-77%;%sxDzc-5GS_XG}mZjZR}Hc!azyj|8jEUIuWx!u7Y3XBGTV$u&XgK5BeZl8i_Ppd` zEIh#TF(AdwFw`O6U43j9zUJNszVr)uLQA_pa21aR$mmcD_>9&0nr&b#kc^}+x5HYC z9txH7cdOr6AGae*H-GTV&|%fxov5+{7(mmk?aT*A@j!7HJYeFRWp9VOfoLDOdlad} zT$uR^IfXYBJQ1< z9%5lqxr#baJ>NH&-=PSDy?4H+3_Mu57OVUsF;yGX!^#f@S6jXhJQN3cp10cim5i{l}3pgY*%u*Sbw z>J{Do0>$f5+|$x=6M*|AJ>bOvpTWTv^S0i>_O0Tyg=*W{1`+8otRUcS^K37q;lrcn zn}QWfUWm@*=54UY_zu&2ixpGa@w5;}QBBsEREVem6iW9P1bH2^)jsH|Y@J|KslG*( zFkul%#Nu{}X@|mzJw&gfQ7o|@H1U~!Hn6g;3Tg~a8r#_#`u#O$)j7W;o{LtNO{v*o ztgxvmp+=@*bnamo1@_f+OdBYH?%Z3`XozL8VBPt$4$EX39F1ot7A6Z zretOD(W&e$D-Z4&sm@ga%3hd%(J|l?w+`usv+dti^}lo_u&lpOM38_S>>%Z(Qv)3S zTu>LUdW%zl<$|kcc`MjrpdHY`|=CXX!gdFi?-VhjYc`4fP9|6BnZNrX)KC z<}R)mT)z|g6xv5hvT4EnDaX$@*O&a^m)YZ9cB}U~uL4v|;mu2Z&{B@7T%$hILb_ZL zvq=b>h95egjwdI2j?!O{yT{5-o<WU2G5^L{Oatj(9UK@w$f>u z%mv1sZhFfR&B;VZIwt<`N_ifF$7lMcEZ$136nrF3GZfCRNk@j|5QHw|XoQ_v?ebCI z{ZsVeA6G77kXN$7Cbz)CfeEbCfIt4oI%zg}?N4gUYT)<7Jox>o>7gTkRdgo-X@5ZJ z5QM8$a8bz(tXLGLV9a3y3zb0}OrN{XWs#qw4E#W>iMR2NSho%GZWv-4(&UvZ>O~68 zf4RC7EgmakNt}k8*bUt0F{M#r|Al2OjS|oacZTS6yFMN2jhWo6i-M~Br>D5KmNR;N zKl{RZHTf>OmDCcxWF7}wxhWX?-h#&~n#Y)YWl5DkBR!rwPqP3zwZnipZm*coam3fP zetazd%v+qG<@6$8+i0EpW^{pjH=Wz;&6sxPEo-8 zm+o8z$4qz)K5<4pd%g%L| zKnK&t=*8Yw_SO2qDzjvA&1-$F5b!th!Q8mE7{rH179^>1UK8Cjw7j_^Q(eD#c1OAq^^P?lUBW@ ztNYt3cqr7elmo}yiA1svc>%xk_@DxvL;0^hTq!|*9s^%ge;AKI;b`TM>8dHcUPQPx zBEqVY&{HnEqF&1M=(oOE8_$oXt4>?pyg31nG0$es>;)dsoSlT2PC%WN4wN zDx!ybMA1;R?`2Y+NgW~LvE}Ze>=hr${GB0{x*0vosY56;W<}9iv*Qr-7MSB{yj${Fw!cCw&)6MoCdbTCU44JroVB)c z0GIffpYu-fm$7?^QMovjJn)q~!CXJg*v(kfge>5!7EMpV3`C$=o3TVF-7-sYR|(JM4Exy!w7AA5~j44Y!6hmDocrqft(U%jz7<|!;_n6 zAQah67+Oc-DV`<3cL+(1|CWBj8O!kz#s#{>J_Qui3(Y8iswT9Y))LhWxX`Vuq|hK4 zIo19oyOW7}XrDKquadC@P7OA%*yeeKHYXvwV^$mCA%{*^L(CG#K!Z4ygwpXR2WAVB zb4ho3zGZgceklnJr2R`gOT2N;nagf2V_{hT5;50RnmJ2uHYWqyQ!^h_vtBK^uz8Xv zG~=vXgZpV^-(OTVA<{^y(7?H(*c=xBsStnZJ(Y)#`6nLi!$&=w2AEH|^Q>}^Iv}6*R{q0T>lgS%6DHP;H~BYvW5zFUdrxoL(DaOVId0{)lB}-4 z7i9ECGY;foY z45QWz$02TN_h%xx5Z|H%_nu~depWG67)3P+;3dpNvqc<9~r|CKBcmIX4<*c)Uc zMeNCPe^5lIkB@ie;Pzz}gPp8&8-FaLUN{2{Jh0!F>~`^OK`b$ZJ+z4hxi5R&h7%hqmeQvjv6FiJMjZ92_V`c7z< zr|T?a2~GgX5o>gFU|ccvZ=xMZ0&#m+g+{z)qB(tF5Xm#zJMLZ42oI4d3k3cB@I)QP z9IjWmv5?tnTG!A;0nWrC9-~eKqR@-AC&bcgj~OlRhg6SDgYw+Dm@lyROt%Lbos^K> zla7^qra#fHC>R$xLe=hi23xj=fjM7O4(5ER#-~71nNQru_(6kjoIuoDGXvHW=uZgq zJJNa-9_f5}?L?X9(; zeZ;=<2n?lI0f^D77K_{d^4@dU@ZQ-=hVosY%LwMke}3}%=*XOP<7&06__#pXE?m+P za9wb&ux{U(2$DY14XyvJqVXUef$Kbd>gSdrPNxf?U#ZSi38^2ez^oC5E7mr)dv+LAPFscI7@pF3is!6WN`b?5pJOW35 z?p#;6_u<-N(%OP!S^V)C5nZ>2tNjaW?Ndk@j>Z{Z<|)FOcy6wg`;B`wuUNG~CX5e~ z$Gp=Qtm1{=UlPfO$yv;paKbgQY9Z-Sgh4mgqb*dh5TCUi?Q3*69`syUH^}r~lf7H4 zu5?WqJZ&s%P8Vg3aZ=k-Vm2WxUpij8M6M3bkuVj|@4XxC(v19AM_uqYO(tuvK$dnK zwh_HCL0MIotz9)^1;Omx)raXN^KsCjmyS@*0QNUBM?VW`84ciY6~Gy^o^+? zSCB+f_V)A?R^KR>z(1hj$3rAS&1K z0&j(4yT{j8KR!MfzF$uTZsHhnZcjC*xCnT%pP|(KT=QeHq+TB3R7;TUYIlJ(NHC9J z@mqz)Ov=MFyTr9imgH-9Gm-|PiJ2JtYr6d5t8YxOATyOq?H$AJ$K(9n;TPRFcY+~$ zHPyG?J0bM>!o{kunR`Aau6ewu$qZP|2miymjP2QwGH=>XfJiQfHo z-RxX^!T)6a+SXTIUbK#8<{s&6^q+>cw+8a(x!b1({!eKuf4{y~G`uzR4Wan$+Aqn- zDx!@`l`4(f&E3T_H`7=Yjtia&u*Q?QS$Wtpj8k0_&0wHoonEH;c}~Ry##bbLQ^?tD zvkR$KVrWGuRqJD(YokD{AIVofbZ*aTS0u&OA0WK^LRFxT0%t&KIH1?&;TsVGOxPv5 zpJWlrX_6OTi2qTIzU~!J+$gueEu02q4jCw9S>K)96Lhh@uuJ!i7PCK`ba7F3ooY!-(>>k?Ipp=W2wFgi zGQ;#~((8swI~+@{b=7)2!933rAh(7PAGovT?WJ58FIPBL=(x1D|0GodXE%1+vPWO;Q3G#V-%|s^NNgIVp&R^DQZH?@%1Hep?QZlt0{fe$!-~8Z($yg( zBiS+&2mY;t)2u%AhVxjZ!Qjl~-yiGW|O zm0b-hdD+r`zJ$zw{uy46!h*;yU3h0T%?VHJ8OFP5x3nAbnM+VMt|)MGey7PI_?ijv zscAfSh-Ej$i3?O9jPz@|&8@SaT#qN~5V$w3XP_2$$B0xR`GC}p(e#cVCW+{-HV$Bc zXCLHvz478eBoj$c#D$81qp&)KXd(}ncoO=;z>4q;835kp-HKU%IoBGchD(FH{ZLd!^wmzq-Ot2!f4wz2zF-qsWh`B$-liX`lM_Zq6FHLlPJF7NM?OD z!Zo574^g^9*(|C!;4TofdYyF<#Jyh&ovu0Ixb7HzZZplpCnvAk5US`Ibs^b-i|^B& zq`S4Z)P9j4N|o~9a8Zpz4z8&Ginbpaw{0u=3MK+G6?(8Ra4#I|^2ukLyLg|QyYnG| zw+l+?r)r$>hhUN}Wl&I$)M08w%^e41W!GmA^i2#e+sHNRCE#J`U~YnqD_WxFsI^!{ z^xFx~8)tScD)Fa?rt=wptIFaY-Wetg{_i$bEO_khTx*sz)vD&viqOyQpEmcXFMTgO(~c$e6S9$Udx z3Op@R4`jK`hDeUk4;9t&tBmVLURL#}HK+AJ8sJOh8&(_9!6IS8346&+B2a*bH8&pV ze$Va>_c)@*Qzbh@dbp6S?=nM#s-Q&_q6OF9Dm-VQZa|H#&i$)1Ln9T&Qt5QP(nlm? zZi*L0!kX~#jTVSu5h6o1#U{;gtH~ObpF#(rcen1dC=-~|hFkBEYfqv3QCrTU2AzmC zPI2%d*niGGK%@tpqoZRPd-v&J6npNLiUd#zgVx|3FPINn6>C_v&$@q>;hQd~$^{b3L4|gHVRa_WlD`2*U0cANa@SrPf^x^@_{ue9)eLj@B%@+9v z4oR1*sShm=;^IdsI|fRT9SHyImrTzsS;ye{b#Dw!10EvSS324lMm&=&b5^n_x_ zl@hy1DgNSgA?03=jav{C1;pNR*$kYjk`qNd2S4t^z_6nUN ze`Ev0(t$;QSf?D^Cpy$-Mjwf^0^Ip!QITLJO0o()tDoTWBs`*6)=_<6d9f#N-G5UI zRbQ*mIj%CpF{LW|p*!B6Z0T?!_eEZucJht84H*nwol)Bk*_bmg;KKlQ>MT0|UaGwL z%vf~(=0{2h5oBe(rI}`jRQHtFa);4ASX~bJiEEckO5d&uh3C*?LzyHOFSp%}MJIo1 z)IF9o<~*G{`5NU0{VM$2_UeE*6o$!-n;qIXXX>zCL@F~ND9pug0(QOVl&Rgq9Y(>} zO=be0qm>YYa|?Q(A%!xzL18BED*fT zTvcL%w{Y`Qll7uH2}x07wti3j%a<0awqzQ&sa6Q>AXGD6+q2nH9&<I)5%K53U-^7rD$PyoIku!3@8G(HP_~ zE{Ctz!JKpVMWt>Xvb%hV0=XhbLGcxAW?RH*Nh@4u-u_Y6q`*zZxG7s^mfs=Xk2omk zju$xLHz)^)HEpE(tH2=krT|T~ud@$qSJ@XIyuK{A*eW+7c^OVOad&s@Ke_ zXA>-B2$G{XbtpMvoC9Yiyd=(lX$N*vbqO*MK{$OG{3n4&bW}x`h5-cRA^CrTksY1? zr=;>fVB~FH8d2?OOBN$cmJ}XW&nVoiv6Cgss7XE{WQiOp>L^Q)1p8C4n5M~# zJgbGD;Lp2Lh$2SMu`K?gAQqcB7`x6!|3D zYH+l$u4uwl8TCK*?iw$M_-`o+%VMi-OT-{lL=;>fmJu%M4+0^y9}(VcJl^rFF>(nzXRk56`!a5arx%zJjzt7K;ju1l=!XyNZGqA-8!|Lk>!6% zO5qbAQgolCKxK7uJ8~kml~BZ7%QdUkiYhs{7Oa0P!q+ z-{PF~i>z4bwaf&LO#IyfCT^~U+#o+dpvBhr$BBEKf08sg{qhT6<6nZveQIInHQ)YD z!1CZ*g36G$St_^&hG9f7?|V^L70K2tdlBC-bo6Cg_~`yM_6flWmfm9M7Vf!yOFXUX z(e%9s8zkq9`BJ2(q=zaa08@>h19L0#byQ(zXs5qCKVQ8af2Rk?3og(dX zpKI`(<9hb~h~-io=I>jeAA1}ELPLn4J(fNLtR2#5g0ukni=A7aQR8XzAtftz=opK( z>67NIgQ!7%>}>YT$8KRHn<+>RbKK~AW|)dmkOG4ITj+76>?}sY&k*GN-Soo6yM7Z{ zUCk&m)F_{mBV;6`IQ0D2q+L6fgPq46=xc6J8L&3sc?beNsJ_YqP%sM)j+;3aAuynk zfLw%e8kBsC9>lu-MLB%Lb{gKQp^KxU1>3OS%eFAee&zWb;9C6y1{EPveOjU+@t@M~ zZ6ggft(DBo3Bmd}Xn}Ar{vkk$P?v%XJDfS^BLV(aVLrQsvwFk>b^Hv}D)NS~qqVaN z%S?-+7xK%6aG3~;kr=HbFmr9{WcOoIQA&>(0FMPM|G3m;JvJa7o8 z1J@M#a+yRyfrx}QS8c5HgN!T~16|{Q0TCl||FYmaQUoVfnqU*=4w@QG2-s_E9Jq^~ z3L{&HKiAOYl@8hQP5YKxI8MD)vEEgDXN3Li3xr*{jjL*UrCqhsXQVyg-CIyWn!l$`JSQz5sNXsp2EdIv- zMcFw-i4tvFHf`IsZQHhO+qQMnH*MRtZQHi9?i+>if3>Qj8@OlpBcF73*xI(Tf=quS;a(^56y@Tdy_ieZPcjz(|9Pyl`d?b*vts33A}kHe=+_t z7WMZQ$6K|E^zp;<>#ZuB2*7Y8$6eENk(J#JDOBij91cg`8AF;XZz+Re1r=9FY+41h zdVu+osVFal)OyY2JQ+Ff>n$OD?tFm5v0OwDg2^J^TX9n~#26=eo`yE3Z#(XEzE0+6 z4QN#3@5`QtsgO6GcdPIlAo30_o^!}kc?YK)C=5a=CVWy35Jm-MC(JVD5aK}%yeM)w z(nmt5w#FKOD}wl#XkqGm&gYml2swa?$uK~@xM&10AsX?0SzwTpseAb&c8o5fN@1!N zW%&X!<)yV@5eHcS(te6Yx1KpEU)VC`m3b(Q9+5p5g&%Fz3EvTzLqpc4gAIh(uzx$(R|AW}$msOtvL z3Ly^=vco3WcyScg35#oE_KT}gK43RtmBc8Ij(dd93RLm33YW<37fnQ8!5<9kp+WZp zZOx-eQOPF8V@&tCP&P`W?L3Koq=LG!w@mnb0`Z|?*Bi{hxI}jr)oGOn$~kXnq<=EX zW+^aRIdo|Dgr{or=TPs-##==BkNs}aokNt;x1GQd!YRxk#NjAXj=c%GIG`96kA;Sg zLCf7H0PA5@pTdHxBc|w>vP4=@IM+Y|B9&MBjr3m7G3=mO;KjFL1^2^2L;e`lsc}F# zEC=&Kz6bqiY&9aGT22qhRt33D##TlBXhmScP6{Vcs*00=x5#!A5JP2k4Xm4jjSu&S zNn(0RS;LkIYgn(XxT@7(HgZv8A7fGD?}1aRTTd7TPhW!%0u|~9G+oWH^r;Aa;@8L8 z303{P-2K3$2JV}yCDpFgQT2WIcph8%PQDy~W}IX0&;A&+Rx5z}ZR@SUV^xRW3d1G* zn#uDV;wE$l>4EjJx=2ghQRPQ=0zdceXEZNOhU}9yW&;d?0m88`G{8oS!LE|(BO^^o zsa8;lEqkzegAfv=V~;j|eIiV(LoQW4(@LD?-vxT?cgn!mlJHf}xnxTnM99qHo;zc~ zgTuN3d6Ik{qrU~%$A-UdFiw(4kWmb!e2Rl870wnq4)tF3ChsD6#Zq<%3nlg>dHbyf z$|oe)c;tV46Te6*OIi(#DuG_Em*9pWyvKp|5R!3&By3~nD|AD6cUt@0ouj#DR}@87 zs6`O##=)jj{1}-ja>=!1G0@{>Ay^{o+bN;I1Y#w~f#Q)_wgGwywSHAA+S!>hZ7#Ih z$0o`6lGm+XJDLf$8wh$X2HAr`_xNr$4Nzzp+GsIQYA~!f8EDlRbXW$e*Y#~S5m0FS z8wMkw(nPS)woz+1s5kXBl!{%6IkA!DP>+OXCa!2hj`@u7qe2b;hQuc6ClzMEp!|jm zuw^ZZvbe@#YJmFsg^+iaK6MxL$yj<)IKmKw0)%Jz#HS$uM1pgE)$I$q;81%{;+{1E zJP)Ojy+s!(%8hZX9oiV06`7eUX&^G1MuO6cQtuEa%9$<)&lyVOBWperSmO>Suu1BQ zMyUjLCe#=VBUWv=S}j)wp;bzWw&-eUrWqRrDn(_4*37Cjc<%M?317UntheLtCt=G( z)B<^5@E{hbqBQ($LLdTy+si8 z_77QpV38SmOaXYoW+*MI0Ib#mCWsuk__n4%-x8gF>ND31Jx*LW`eh)cE{42v>Uvye5xz_-KA7SjZPhk{2>Gu66 z3kG>tER4|=!{x_LQxGP1l&>_1oJE-eD)n1CR;%&{Vn{cl z0B*~OFxZ1krz}v$h0NEC1I=Dqi!GI^kGp~Z)IKts2^|B8Xrc>CVgwX@AU^@zst$?= z9hFN=_(m3GJ;}n_#&AmtkWd9~Aa{$?4@WIoj^I`Zx>+^R{Ew1hNw8;J0w~2ckhj1R z&jSuhs}d^t5e9Qt65uc8vvq9n-V!7d40`cPdIHgrBvQ!0%XAhKvO7FST3zKpzt47U zJ^U`Itdb1=AC~CvOZ}>b-0Cwvk__^dAHJ96lfHVdo?J>!rC_WCkAdor^&=}l?=yvH zGzP0;WR2s$eN&2hWJZM>r!$XjFX-!$3LI;Mz<0I5lO81JS04ELj*Nj=nFWRiieoc% z-zZ75iLj(QYC|o_Jp81sB2e@tPOn3g{awKqPVlO;NaXeH`uFgnB-`eeSkK(wQKmu; zIjUJzuqW3VF7jd+QOFZ&*?(Q$8UV_jdRukb!&5Uq(3pIrDQy=93S7FCwbTvzBrL?0 zM_s9p#o8<2cGTgH+ZAVoj0M75#ivPHrevIFU10MZcz%d$c>7bnfny#M03wJDE1B@% zpL;F88|!zl_ZJ;mrT08=CS9-Wcw;U6+y{zHV#QZp$_qV_?2eRq{u%)fL71^M^77|Q zmkZi$#A!Qzulp4`-MO!|Ykj}nUxy#13`XmwiF*8w4z?8W5M&Q6)`rL4jvlLJq9PtNDjOV~Q+m5g=#gmd3;ndY0hU^O zySqz@=ilKTfMA%1zVtWBJ_SPv@t#f@FzdZ}jEF+}nSH|2u?CWVH>Sl*L=(c%`|tddS;C)hQGp;qcFQy!L-TNRzp~7o9ru3*!#dQHEo3zkPNJ z4?r&4{hr<3ZGR39j(oP>V&nULyZ&zb*`3T9op2vdQ5XhTg7g#P?bTnWU~&)DrJ(Bo zy-9Z76fw6(zl1~L(41oLqOmSJnaQOj7oWM#`D`iXL^?*+%z(@S+(9bwt`CE?H6GPP?v7=z9UR2kboFo)*E~`yw5xsBB=-%6b&@L}ZT9%Z7 zHFZqE0hWAdA=Mr}hrf3g{`A!LDYbj|kc{N9&=GX&l?_-%;cX1tkm!mOAqSOLx{OpxszQ$9-bwN^Iy`FwLi%x@B5cVY2{Rvxb<9l#ZY?S zpATENYk_Q!OqrDAH3>%dV~B}Dof9&j^``Eu0#K%*s_(=dd9q0B_&F|VlyVvV$Nx?W z13B4s{jxaaiWpsgF9`|Z@(0SE!ZgZpIl6w6dG}WeeY2!T9|=9etR=kkh7C)bYIhJz zG`5vhbYy&-d;6#V@HH})Xmm`O+yD|Ru&rIt-SAkKX#T2*w=AO7rxu6u6$7GX4Sq@Q zTq31>8)4*x$G3hkzR)y=ks-*58bz0=*>FO-ui?yQ?DMPONL}wTL6o;H`>)UsR9u|5 z2+o@6=k9zqV(=7fiBAaP0kU<=6usjZB>ADo4jidw{D^160tX~gSeldMqkKC zfZuRs%FfG6ivqC^|0Ig7z0pZKT+XGKclo4X>@WAR_sacmPAiZve0iCZoGvNM7CV%* zp^Z+%r?U;qu=MgnJ(mCl1!ican}9>2kLTN<9fcknHV;Zj1ZK0j@4TWC9o?g# zWRDZE!$JR=AVzRU>!>BL3(a;8ur3cuwQB-id8~VF{vNOc)&P!^KClD^m&bR`*aa^} z=WUYv$t+;+(lK4CP?pLYaN@ophK|?t=SShrKBFP7N1uELri82P9>6r_?kUQ1(8`3k zt=pgV*8TK8pQ%fdEbI+;_kW3-4dc)qLqS7bY!$jrp2lF15j&p;OM505w7ZH-br?ev0k-^zZ=QAvbBg6_D3i>;Isek(5|_TaRP<~9qWYNw7H+{Y~s;2}B|bV^XtU!wNRCFlV9;#sb;4c={J*{5R0c5KNBam7o*$7oz0!8OdrjH z7kB1m5%MfCR2wc=awG#%G;1LQapNypFudS$?{+PY<_GHOkB)1l=hV;9`_A>x)z&(I z3y(3mD+}oDVEe-*w!u*`C%Q{zy>xjyyQC)zgc^_uPB|CD<3Ss&WboCU4RC>BpVo!9 zgF2D}0X`w@f~IaA#Z=Dm1q+XX^jGsD!Som!#a|u8)qHf{8~^BR+q=V^ryShspKS}%r6vhs)PyJU&D2&>G5c_pmYC^|Hnc7-ra}c8 zYc2^VoauC|3Z#rI#Q zd)?!AJAO-Z`{BAjlXe&HYmSz&{(^r>nGnS| z#UG!pd$#dGq)WKv+5W%(@4mGQyYd190O*1T0AT)qC(gN;I=j$182)$cT(P>L{ec+5 z_e?E@;Lfm1n-@qmW(iR52R&BDh_v-FW#xoKQL5DScRNs1r z@8ikzm4~wzRNNZR_?2DpUTI@vZl?q3knT(%s${LJ7nEC0Fk2dd=lC(OyyagRK>0?c zaT~>QnSbk1lq#g*RRKyWO#5D@iKz8HLB$D|4bbr!T7d~4+A2{BD@4<&nn=iE=tkp) zgU4LTQKfZ>2ZYl1g4IT$_&AOaIy`2>xFiJ<%o{2TWU)i4y9$N5t==Hg2$QspB1JeW zs^tunsKmwtap(tuGGg!plpzyHJEG2NLU9Hm^D#O_-c1ZfNu%qTlRK9p3z|-LuT(?bCCirOa1RTCz(DBzm8*1{;AhUh{_ zu^_}R6{Cv1icT2+f*yyFFR8cD7ltJ-DT;1un_4pEUC&2^B76*YSKGF@L*Ljh_Q49@0UIQr zrxW6VLDLdpj6-hdz0}NGOHGGTdXiHDQ-ExDqIs4%f z=4Tn`%UM%TFMM`&t&^CcaUdVUC51FkGaM?=JR10O3*U5=kFCQz3cEYF2H)(^IJay9 z=4Ntv_dhY5`ZGc$q$YYtVEr~&jJuZx)AkC4CRT?xfh!xY6sH~TI{a;<77N1ah0yH8 z=&Qg<>Xl~6ID{3aBC_l-kwzCoZtp>-da>(&E;;Eq-#}ajg<6A$jR`p!aB;YS24`Gu zR9KGwRc?LOXLNOS4TS5!S7Y9={jb6kGG68%IEf4WYMXh{Jxrz<-FCWzBhsSGpky;5 zC2r0=Defisp*-PJ?@4OqDxZbbNIXM{TYO6$j#d0~&f;ZhRPC4T-m;-_sCo4CSyCuq)K30D!H0XBwM3}u=8l^Yy}9V_NSs4AZ`!ja>?(=AHf)E%ARrHBeLYBMgHrT)Bpvij4Gq9DV0XdYMWy7MQt zLS1s8$q8g1j8moBw+eENLFQSO<+@h2$ARMC(MR^Ct}lk#R(${XO2i?)%Nlvknx66= z>`T`q4NE7$E2wz(C?ffJ&eXxfzHq;d@P&L9h-MW)PoUi%Lm1tY%eOG4PxJr=IEFp_69kvM1plOfstt(wrJA>JwCXsoO_dJ6E(WpSSGs zf2DtWs_p$)b?+@)xabiO1hX~0rnLkvFM=5-b$mAW!dH?AiYnf;c-r7ATn@7DZJA@w zQM}ddpZ^MDj!?~nyN2VdLI7LjUNdsQD2H2l7jS6y-0`4P{nm3NOgXUVhOs!xvV-@0 zJ=$iiryC~XoilfloOvgu+$+~U6EwKY4w6at>H}-&-!jIs+}c(+vFaQ2W<~L_`{a4o z;h}izOl?2G)sk`mN2T}!U0#_W9-5XcTI0g|rqIY0q+O!1dB?6Xj)s((N!ML4oH~Hz z@@J)^b6_;|DvWax=2gn)r>cD#_eX_uh)2S-<1fPD5l+GVWTZZwGEhFnxw( z(m7mdZA5MG;LmFH?@D)Qkv)>oEpy&yR7Pjop2iz%t(3-?-ONiW+1*x`ERc*TUSBL> zQ(cGcFyn6d7-k4zm$MXaXBlQucVme;p5Kq22x8vjfNS>tW)4?y|2x38Z1gY3n%Uv4 z?CAF9p-xu+90{P?=Qn);zR^m4sEOk(t8B!pP|d`1KZ8qIJ6Ab6xD8?kY)1sHKPeuS z@oF6Ei?+}>{SdvF!8gmzJhjmGvzJmn{DJDG6`JSFzg*2&ZnqqkW3{tDTn3x$kb66lz|JMxH1KtTC=wGJY{sT(0 z{C{Mcr-P{p?SGQ(zp_+|)pz9&#Sr{v^%>JHDgb&ME|gLCNRlx$DC?Cs1Bq0lV!9zK zov$q1Va2I`UT0$d4w1}xQ^42lWPG1w;d3`;=M2>8^jb9gG~I2k*7gp%YSKAF7D#;l zT~u~>#1Truf+$Y>kTh$OFHkU>(5S|vs+<5yA_|_6PykJDSSUaG3$9A?0g6_vhY6nZ z$2Uajakrr%q=AaLS;0~W1CB&%K`6=6lsxZA|;o} z83M5+w?*0f>^+_!@UhV#4J|Wd<%GuE0@+x4U2^zCq=+mBL@7nJRB^D8DS5zj9VawiRfZ`AH-YFhYC6~2Lv$? zC6{6zZIeu^z2LXAmS>`fAcPU)E;I=6upu@0(DY6MZ-e(XBwyCx2*6(iWC``@5g4q8 zeTIwS5vLEO90|O3yYh$0rVO|s=iQJC0^P@Yng~5_oGeY)4TZ|<0S4>f&|IEp4 za6yRSyblA~j86s37~qKDc4(e5W=A7*S>h-#I97WfPH2#D`FFeh-=pnBlviEy791iY>`+gGp$7Ss(aS(;l~{fSh$UMDJ{oh7hRuQvT?<0q#at7Hx%q?dX_rQjSDA36Lb z7H+#CWNVE7mf_H{qtz7uwQB#j3mB^E2_1Iba|6_H_&!nIGpyIEz`^zgn0JgMp0LD} zrJOOhR7V+4PM2jiP!=S2b2&4Mg?)k$HjyutSf;7c9xNOV-~eQ8je#RRt3+P;uMI;@ z{Q1}I&A0s{Fl~RqVCpKYrmo}#xxKh{$C3fhOHlmOd3+j+K2z@u3o$w^pttC;5TA0 z(0oc#v#6>13!FshsV%|Kn^fVS$qPJ}xeSn;Jl4V4_kyQ|=0~eHk8ZDRzRIv(fK#_5 zH&xZpn}ml5TAy8Ft_|k&bgq~}FfBDkOna^i^M1RDinW`uo;+2Q>eC-}8`j+_tRk;# zZq?e{`g4!z8$3RfyhWuPI}{AgB#yqr{p{oT=EID8Co5ou|4JmP2>&cpdtW-lg{E%=j@@L+4YJhyVKNg9pQVGp?ua)yWXug;ZfY@WvcC zS9Ud!`b(a)UVRO1=MwQdrO!)zCabD>isgZdxI|~?zinc zd}xp^>i_%c_SnZIeJo|^XrJy@_x9dx?rxQIVutP(ts3**-B;55-%vL1L7Uw>|EF!1tj<(kr*QJDj5TIVt6bEE*?& zi#*u^D;79p{w0Xz>BP_r|Jak`{>1WuF|#l2i*0Pb7h!M8Y+M*+*W-{RM?`~iPzr={ zsxt`7&kYK~Opi%5JvLeLY@5CThwBe`0OJ5$O>+F3)LEdz0ZIIbA-0})20O3;#GoB# z4$52*+Gry|2mGQOFVS3{D0(QwlUoD85eprJK;fh4zoOFlF$pI9%^(N-QeJn!y~LjE z#WuKSx>!FAb4V#*a2iD4P4II2BSXOk1P|Peu*jqlQQu})A!Ectj5iu{8_9IuIr%M@ z$WNdgi5`aho@GQ8P}vr_=NY4G04#X`u|qz4C^|&=St9A;7hr}s$K>S6KE^*txagPz zrIX53*B{gWK*GJ)F}wz&ljp;COm~BCZ|Uj%aByDZyV?E2(tK~v4!(2g!R>cryWG)B zN53cYSGoDaN>2+X`?D(NhmR5ZS-gbHw({J&ANjq%b9eM#!i8@S7O=Cs`EdbwEcP1Q z`LLeCZS5WWT)bR)IQ%zX0K(k;7=;K*gB$xHq~ho{mR#CP+#L`8KGVnV^v~{O^`9F& znOi-WFmR2Y$kEYRu6W&grxo_kFI(O&c>BA){}`>k*7=VH@6TJ>JFM{E0Km=Ftp3*f z^F4&!dX<*ixg*XDhd=(1zVzSJyq3VHzwBhc)N@{3-|sc}vkcf}*o*(;g+DaK287*y ziUYsFxtt4^dZqc>L9ZG9^4I3!bUnp+n|HU)jhb}e(xD$-uT}(T$VCcqv z>}*Cy8xwuj`M)3TmGN)A%F&03v{f4BCUD-wdi@___=yz<0TSGd`1j;wI5-5$z1wc9VXqheSn9df&fA1%`c5KYFEv|G^kjji+d1o$;B=E5 zes7zAhF{KB9o~OM2DtCwZJ&m-TOyf_xl&hcYr8y2S8HsZG+bDl-Vx7)p7$|iVND> z@u_*XG(90fBXAU)0!QwbPeX&-Na5dr?+Y^;V#hjr1%`Qs)3$dN^irRWh^(46b)vW| zjgiI>8@wLPNYgOhZ8*FU1Y?&|6lGkRjG)$}=+E&$AI7I}ctM^OSaQgb3#jb5d}MU7 z_$g%-XD?VtwIqg#I8XWPPsHzlQUWj6>gcG=H92idh}j4&N!o$gzg z;~!yg>@&tS<09BHdBHf9(}4ckXY$PO~0=Uu? z4KMtA1$0CTVN~@%NFusCx5+KkZz+j|83xpk#@Mjni&ASu#5zfB-+RT z*3CD;t#7I%>3;=hkzX|SRKx!C$&dRi8I9QyZT`jqcS@1=EKsQ>-tCOf^2hIX3jFx_ z!iDAO`VZ4za00SH(n1(|^3^a+D@{-o2*AcnfZxQLHMbQr6G!t1J946iDgUXfe{jOlp=vT=G z(O4z)C5;5H_Q6+ZtE%p>g-OYGUXISd1J}bSsUf0RADS+}B!OJ_CSXp+nyBeLhn+mI zBl{0V@~^9qRy3%^0KHjP!#n|hwXZit(Y92&QOjfeza15pxjR8@Qq7mswTky@e;J|h z)lxDSKM&e2=ld{yT(IK|KlJGfFe&=$oV#-ev*o%iF^&YxZt>%P@9^yQ5otywSqypC zgB|68?a_DyCD&da3>H_^i^ed}YG7De;A91x(cU+ z;YD0%s~gSTTT13>H>zfVo5Ugxe)YArqhWf>B3G{QNTWIMWnQJ}<&v84W9%pCcfvgV z(F)%8iD-Lqcj!tMHQQ!cNNA zg~BBiq5*-Qiy&={6kMgy9nGOvt1V(qAOZriz;18Sp%3g%LIA$LD&6;34IX1UcZ~f@ zJ0AzWEUq>&n6zR}k$lR!BbrR;0}KObK{1(OAVeMrGpFb1fFcI)=Pa*!%-yJyNu~~L zTgnWB-JF+whsf%~g+ol;oyB`EGHdCfwo~HfqRPB5{9qQzb*SvAw7a5+DH1@LOBn&9 zH)Rb*09<_NHIE)ealR{DY=JHS{dhU@Bbe?YE-nW4uS zelYq^5IomDF^Ui^cUVA_8C~un0FNN=*s5Co*diU*PXROwu=gO$B zSg?)F&@^a)h-rk^joHA6p%?B@9x`r0fG#@PI3zA7>$v+%fWpq(V!?=a z&o9sM19oGB_l=Q|GAU3%x^YTqv*8B?q#n-(KeTO`SSW?$3s5s>sRI_KT$LJa6b;WF zF56FzI7iTny?xP0+@dW0Ai>Lq-q6?AjmG+8&z$hlxo`|Vx&W5RSrU;m+9(oP&2DZF z8{we>PwY$Gw~9V7rW2Ybo{wu~Q6iiD^J#TUIApQi3y^}c)Fzvpuy_J|gPr&4F99d| z{oKtCD*nO{>fe)XWziilt_K8ipg%IaI3QTi@E0LQ`LNn)_=iUsK&IP1^o)l9#Wrjn zgFa`-u;Pz)gBBi2ntsKqtpgj(t=r@T-@TS~zXIYxq)Ywa;IY_JsFIQ^ZqTS*=!CtF zi=&wAb23OZg0kjQDHK>*xyA`-&ki0^kTwdVn5FG|B$^SVo5?GLD!kCRoJykc4g`gD zw`N_%_?|g6F27*G!w%dhvy@z3^iY-Y5S60af1gOgn`umXe{Wdp46`H}ARys@RNZ_p zSnP3E@=`&?t4do!M2S}+Z0~-kRQIn5_dZAJrJ5t&-(>CG?oVYEc9SZLg9>^Hi-SgN zz1+}^3#Wc=?u=68F|93SP4?e!_RM14y;Ek0RThc<1AP5EI)wMhNulI%Q}q4YwJ%pJ zSv#RzhI~rbx?yhELXokE{1QZe8@7tOL%_lQija3%%cGDD)naI1C7mM&6E;G6ny0+; zPl~?1UYgYqGEVig$>ZgB&))_9b6C0k-hB(sc}YEur7$wNywK)zT@hR74fOkJ{BR}h zX5%2XoX>YD00wz|HZ2ay*C^!()05JNFNA4#>*&)($6phNo!7(|zvSVNFggBWpH^## z2QaAIqVaESo!bbq4!Oc^)dtBWAC|p}d27b(kusxZND=kqV}?#yG-jPFWDQ?5%G?dZ zz&peu0^G~}grygBia!LVzQq#A)s3)T`oQ_~Cx!~X?I5n|)R!tiClU)Ik%cyX9F{3F zfo=*4fb&ouxCf~~&mYCS?O~>Sa3{6&MeBLc!xf@im7{>rg(bC9>sB-Zt>V}C?yC$K zuwa6+S2M^0g)P{|OYOdF$9wnor0mtp`9wvq7>#Q)%nq@QI=DxiRsRc;+ zXP7AORoH1xM}gi1m4j!RpvyyeeS`dRW|A8B`V#RAEuF z5v$Caf(|vMuZUK|6UYWjy*!m_o1j2c8HV+2T00*4X|yLEFiDU^m1PqZg4Ze)M6~Mb z5r-8a`4n(g7G5C^U0I=z1h8|7BJI*!Q%TmflG?v_WIi_iQQ66ka*80!`eIO))*vtm z5Ft|7E-b!#eST;FUmuWT10DVUmr2~z4>z0EA z`!D=LqmbRpat8`6^hE_o3W0fs#CR5H1j^vpph0hvs?_@pI!0m^u^H1}R+9%{56+x< zup0e|9l@0Lt#z{lEh{~ii6vt{kD3XGKNY%!UQJbs%E9v?fhHilf(hm$CXW2GJhrHy z7j^YOq@RPd759KQBcN!)1pK7*utaM`D+^ehqH3x)1bbdlTfuD%wG{B^DvlwNx0pFL zp~mS8N6$f>JY12_L6lh57HJ&v$&5D9kk%|xv<-Bh4_7xkb!wANBRe)qvUH?wHc z1HzZA!`UK@&*)7o-wSs&iAsQ2r&ZTnUA-f+Tl$S8KgIJ42R&*Y32jF0h?^@^w%gfb zVbA4-2G3K>IO3+;2mzdR>oDOM?js-~A&N;>5Z|MFetd(bkz9+zVD%Q^UMs1ky4x^4 z-uKeNtN3|(hXnbQb1mG7meeQdY`b1jgv5(pk;qd0i1>n4ZIgJ$tAb`FOp+qBREpN3 zavL-0N&@|CP!k*?Xz&Odz6_AvqB!5MA;3vyLMxtu43TzsHh!TM7@><&WEBgr`8I!r zB&^~KOEjbiEIOTeC*BeAa%LZd-Dt&kazI>)<`}#B=v?=WuSn0Dtot ziE@ATrM)8={F3#M-ljUS{(c3v%=Tj_jBAkkR$XAC{J#8QP=|^oef2{-$Syyd2AJ&F zuCEaAe|buc#H0SC?@`qvsTRk?t)6oV#F3~J0^=IN?8wnu^Z?kyt`_X z1i>bhRk9v!sQe;qB}CgW4qkq3BbR2n7^T&~(bkCHfmPB#CSq{vCjz?F6wnc9V5^sb z=kmA(tL31aGv0^=irXqSwCzRFLV5_=i(N&Zr|rg?CN=y5j|n`T&>wg7cJC=7YI6o} zh#V#^u%*L**geI@Aa>~BPOlpf$*(B$T-Xs_XUEjZ(xDEcWFG zJpHt(RjG=s${)x!?YD=vHSa9oM&l6U)I99&=RO%b^tZH66KBqVKNl#Nu|ewDA}l^J z;Jn4);t4b53nHuJ8B7frJ7klGr>kF`>}#ie!jfJ8_y*ys`nr)kKbjCri`Fx31Y?zq zdaT5CQWpc6Uy-F!l!BNh^~aWzLEWGd>$D>E%SwkQ(1jQ%3jixFDaz-P9vXxxbpBIS z;$9p`;JNN#$d%>^7tRsp$grr&7kb>c`J4+y@%iKkHfc1M{rdG0&aj4V`3i-arkLOX znv!ENew@d?FEN6YP%y45#7Hk157n^NO?CsS8P~%da74QQ;*~(^ehdcisHNB?BZQMooPKkh_^i@x9w1}%3(z+>! zYSKfIS;6;KzTRPOXXe|b%s^XnDW5~B_@d07ib1EUw2x9zMn_5i`;sm2z#eIf0iFqr z5Mm`nV81m_Utn1_+?|3G3IvD20W0?a-43{mowwB!463)z!Rr=HURT62vA_$Cvqes@ zMZ-`y3R9a&v4`nLu&(0LCXGRjlKl>2EGQ&zX-M!?<4K8t9@aRJS z*a;jx_4&bAid==dA3T{%^WOD)edtv0{k*w&TG~_`&h@6(_l2I-+UfOv0icAQo$vga z&;25U-WFanpM!i-L?~pu7ds1Pjt-Z*+R?!Ycc@*?AH0CFsD+n_rq%R9Xj8yF^!eE}83aqF%9E;$HM{?K{Pm$^i z@qqEpl|idpBA9(tY+3g^us+$|A{NKwzTS7GWGOok?|llQe$6l|gr1ky$WKfPFenl58Ypz4)sXpsRe# z);Du*1u~^`<>)TqLRJ`ar1HrJc~vuG+U$bM&M@FzAA-VGDh#|s|2JcMnyP4MClR+ErxB5b((2HlEpaQGW^ zuUJu#y7pReaII(M)*UX_(<3X84yt-(tuC^pX6yQf!HYHzmvx{4M%vK*SOaIYIRh|K z@Idql;irpj+U*V(iNoth=kK8L^C`HVGWrMShwJMci#ms0_(7CBy?R~IF|=eHGIAQd z%jwRdbpGFb^ySxbzC$Zd$GgLA;gzv_5v;R^tBgmvz7{@U-4#o#Io|v#v>f^O|(hPR4A{qDR^2_9 zGn;k$4&6_5$InlKX?n{Mw@zZNv5?=5ICtoC{mBz}IjEF*JJx&BBhboA*&v>~EXTLK zJuevftSypCPZ;rKP%MGpExND8b6}|!Ne*a3lQK}!$r%iwit#+yJjVc8+*Dz}YXS|w z`FC~mXc!PXYY$(Dv{-Rbt^{h`~|k~l)tZK&T`43JoDzR zfVsT~XD~D2#9foy*pcc>cUA!UyY}~7vtW4l<^ma+h+2wq-o;mxVA+m97pn&waLgPs z!we~5O_L^_cy?wBC~3SpK<4AI1rn2i)Utp8|W1*P0(4Q?u4An05UE$*?B2r zN#0wd1d;`_Ud%GQGlLTWrxa@nH4uJ^tbld4Xie7o#4!A!hD|{L*x$0MFVhDRZdF zo{COZUt*22qY2>Q-?qN?RP$s@bwQm5UON- z%sKj4R7MCCYk0BEIm$~`klBiC$=xCc$m8w!&TAkNj&Qt79p6KCgS|5+PZSl~}m{utRt1?Q^pAv`ZRPc38`A&7gfuy)vDPv|fJMY(!ft z%4!r|&fzC{%2w70;dcuvRB`e)qq1zB4Mm#Qks2!{SG!a_J0NaVFc=Dr^HM$6d>vrdjSxT!4?(SAJ> z&1X8xgXx|w%xyiV+I}QOn_hlj6uH(s2dT~*nh|{SFy+;x+hQ-9EqY|YR5vcoP9AVy z%nYkTa{Pj6TjP0N^tTbckZ{Y{W1PEHC#Pyy(e@L&$sj-O;+YcJ=b=P|c{Ivj!o|y2cioyasISjdYSA6fD9jrDn$4 z0~+lefz|EMC%}nQy0ipA+!}y}i&kuhp_+{@>%a@f0>dh7B#aNysH278Vq4n!kg#9f zxP1 z=0-;EeUF?OTi2;i>b*`BTkPDuUs=vmUIR*dQSoJ`FpHGMA&|wSs-&8Bvz#4+Wps;n zgqtW=4%jM*oOmby?y@~4aCA+*`;)6+q)zpEYNT>Wp4`#Se!{6|{w zFK}<2PGf%OXww5$^*7UUY4rM3DG;~^utj-`OwfCCe$Ofg$>fEp2QW0Fc0%S$m$5K5 z-w$G5*_xFHO`#U;zrJd7!L)XEh;G31!FoBRsNVFkk=44BE6-#4pN`yTI{EH5)k-_9 z;{NOAYJ*GEdF^8U%Gpfrq?I0kk0CCQ>YdC!RcwUK9mOTXh>=VD3a)5AId}bMWolum zR_q9>aA1|<(c%y%s1EN@Gk7sI1gZl~3#a5CZs%=6Fil`h>$eBGwrL4=8ECLWFBy7J zt5$8{G*jYsrw|R_mwABLNt?yYi)o;`iR~FCDEZ`)%>(n7)}RRKkEw5=Z^YrFz#Br# z;K>g2C-IJ^V#>jff-B<3?LnHMxlmkjeg*H30lk?H_VwPbt~QldvRfmUPe;=~ofe*( zfAGlg{vx3=kmqeW^*bR0CBNQD9w2d8`@!;NU){4o3}v)n>x!2?Y2|9f~EVk2N%{b`<~C;ofOiZ!f(tABf((dzlIA?FG2`5zC z3IIABKF6+VEE4*I=lrbA!c@3zRS;!>e;ucT2GN0EFBQMc8C1p;N)%3NNP zMdd*^gVx)uTz47tQ#k2*H!g~V*g}2$X^0Sq#lmo_oHYd@7%yRl6kQYIr55 zlZuCH^K{5{x`%pIZN&n$1B$*e&@3uoZlg2~_r4>Y(a0~7Tzzt>PP~cgOTE(I?@l&q{ks(#3R&~PX5?BwaWyxxQ`wmM zF;p?pTRCr=^uiff?a}9%cZ}Q+#%q~s3xP_La-1dD<))tYu!^#~4r@_df?5#SAAkxC zk+FWE;?o^z*;f0i)xUyf%-L4MRDgquqLYOrVb3tV=3#QEzMno`ssPNsjQ0gl-Sd}0 zoc9ghjY%$DV=R>&RXDM=XF*npiB)17b_m0n%UaJ(EZt85n?mYn{J}q&m)lh09Ba(- zBWF<5iJ(;w5&5Mk0x|HBeJYqx;pz3crdT^PW@m(zwaP8LItu3dHGW0f<6S54v`*E< zYvFT+WgSa$la8K@e0**4sht)FS)J1EDxwzq)6LdSpDKw5&(Gpq zWXQb(b_VPYe?V7UbWe7i?Pt>ouI}{Rv0{i@Ms9}CJcXv*mWA=dT5v8TOA4**-y7tL z*AO!*X(+>9qJUkE^82HIEfiI#QH;BgeDeIz@{v&}2daeu;W{@|Y@Rl5=%@;8HWoS7 zPZ}n;Myg4@BN$A?oW*xqs$@%PW_2?u&5^W#Zyg=g(5L-zt-tEVf!NLl+Xsam_EejL zb5Cb!z1HHFAvn4WGTz=E$3Nr(L#L!0NbG*=uH6nLPc}BX-_(h_8n>IHET+!=;LGG+ zk2GsU#YeG~>crR7%-!d+eY(d9x6oAScu*`h^y6z`GorU$Fl3x^w`EdhHM8V&>Pb;V z;dtV@gTTbl*?XSzZnk83uR)ec?jW8##qZhOD8R&1b9dYvHLl#HWXWODCcDwWZc)xBYw?{;)z`p1kEe zo(s*pCxbi^cta0p4LSc2aU(13@dE@k7A1r>EZfoA}?AD=J-Us$~*77D)P&TsJXI?=2kJHDj)QYWDRb$9UQ6=j>ME7 zV}SKt{E3d^cnzd!Q5EC?qaVu_ChP;`Gnbsv(y`UCfV3A$0Xfp4WjZ-PAOt077C=al zGFd>?U#8IcKLA=lrN3``&+M{dqca92^qCpwKDDn)>2;3UM6-NkpFVm{^JdhYr#$rD zGl#iaVl_tPz_iwpVMKKVL1iYo8KJ@?yI6sDkQf?P zDP~=cCRG_X+db0`amUc4kcuh=q*~nLf$vU3F4y)fIDvLou3pSweQ*}Dl|)~?zSZ)G z>V^-b@l~HCqH-q70^Kng^}F6*tkvu<%GFTa;^ZSyvXYromrng6xQmP6(&kI6;xmJ; zQ1f7U2Rgt}ao$wx8||=`mgflw66>X<2fA(IwdMl(ZSB}CtgMFUj93W6j8{3_!U|2k z&wX)x(Y$`~>gDggfA#&h-@j~iNe4!kPBJLWVK?M3cV_CIh{g6kQL&uovX*-Z#rC=l zK2iosI_kn0ZLx|%PcE8r(^SI~?F%&yiAwXA-M^rhfR5nCNAz-^*$L%nRvG+|Zd0JT zgd z$8=br=$78A7lNGDObJ`@vaV}6f_xnx&bn%~N}H|h6`jtWdyS6r`cU4CpP`3VkjJ6S zmSu-ngFGASrA0pL*nqg!vu8FjzbVeVa*Yb@tDycATiq`gDKF==x01uLEe=Wt%)|aWb*Nw;uJT#WFud)n@JQ;)m5R&+#w-8jlXJSu%I+M{4IyI|-ZBA~(4-LUMEpNF zf;6mgE={7T?A|=@WyeHQd7#KbIv1mxp13{(=4}N8KCrw8cn&#xlDI}PE1mw)aHAIKG?K|)t(k=( zouPGKyikD)?xS&){kP_fw=g}6SrEvJNsTocV9Ri|nZ+)qlWzKNF8jSdy}uZok5-i&j(SIb z@-KeuU!I&^d?+M1F~u;O_~87i4+5ZfdGwA05*&*jO01PrTq@HErAnBy<4d}xDsGa4 zSe)q9-3GO}DqZ4sZg5MXdU<1}h?y48t$EzAopRx4A(@s_w%bKnScsHnPQdFzJ@EFf zM8f`0{iCZnHhh^Fg~@ z5e`!h4R-xh4zGkjx4HDT@vya`ygkr*W@0?JF^bTx0_Bkk8S4Q$(ll9noM64T7$L5+ zH5@1NaB>pdh3=qV3bNhqsuIjJ?z>)^22VSJmkOB@DdhZnbj5AL%;;a@$WT%y|LE%S zvVT7ENAFy4^2e&ylabX+RHsgM-$I5pZ-d0^-ahxQ&=jAImvjS!u*wA+$I znTsruUX2?`kEvd_rj*)p%^A(#+_(0XLHErw&z2t|Q+5wIzLSzIg>&~p22a~bmhPbp zj?pk`E&d{$Kjf6u^cV7X(i36W^i5ZgE4_IfTM-OYJQ{K*#JVjw~9M&w{acG4y_t6$h)2 z1DKT=$4Fg)y=XR|xlF^9ld52fDTzfO5f?cb4QHv6bkh#w*a#ZjIOY}J*}$_FEKBtgwX7_fRz#kRbrFV;P9%*t`{mgD&g5idPKQBhMCo8?4v@G@~UFn zo$6SAsMYZ7sK5h^yatCJlbqe>xq)kq)=xngHA zP?pR>IxtIh7~KNw&K5@vE(mfq-zPs1P}Ps_o|4HQ?01QN3(&tsFYUY|&Fu>sWwz?}F?i z4rPDg+#`RXbehbkIAJ?4)-+rcfY5F8FM`0m_$(L|s+y9S)p`5MpW=?p#5UXn5yzUw z9kN|Qoq$%4EZ!)ZAuhH{_k^pF_`z$ul&n}PPWb9dU95yBoo+>1Shd|LyHP5F(!k|l z@tXs4vIwQf8q}9=b=gv+ddcZ^tz9XZmAu|KUw~2~v4>sgR6^~qSP4Ns87JG)at+wkH?^l#uC#-L&y>V(1UTfE#eI9i;f;?=U&B&YYV4qANY#Y%(Xq*a@$(kIVJvZ`bY+6ZdsBy z7kaa-r%tzu$PE``G)We=!6ry5O6?)J@Jcr*LP3~Xnx)>t&XVNLTg;W}W2>YYF1IM? zQ2+o)CF~zU={Co+eo#?jm6Wes8B`)qrV#8eD)57SamCYStqk4SP=@m7OC>3P>gB2I zz16Cvgc7hJtwAJDHBb6YErqRpT)1*1KhiC46&^q@(FCDPD6=k;&k^N@FhfKjZpB`r z!RW=_Ueikpx~F`gx7m`+Y9?ka3=l|3bZe&_eM(%%3jeI+1)i_{pWgS6M*jQD{;_{@ zae3AoecNte_wGP4kWhoVH_Y z;qoOrGSmLxcWnDRb(1;tmC z`-((giP6`h`$|*P?qOw9HWdr|WILl)m5B$oK+6pSJ6kpl$@H=u$AUfQY>|hLr^)yZ z&HQ)GXN-_UgoElTS&lY{++zjbzJj*0it6|<%-8KTjj!9YRaT%13wD`Wx{0qzhm~bX zRpakfOi*v&Q;E=u2LH{OVqH_F?aeR;)Vakaee2wWmN8!s@#cN19`ZHu{+z*IuX|aD z6Ikl$>>R3_R%$F(=rFSe^_@dIb(~Xa?v*KN#qIUk|J!!Vkx@9p7lWzgUw{iDg0m7Q zEW=EaGp)diOMMND_~y|vj8q=vCFtZy9;`W`hOyz_Ml6ok2 z5-L=nZxGKDOpCB7HOqM!HekNB*sd0#%A_VPcF*+78n{c5#T$IWkky!Sfv=2a3Fw-0 zX60=8S{RmKE<1 zuN0k&p`HJfPLpEW`d}g(tdn}v4nJt8V-$A?6Sk<7DwHD_@re~mMMm9tNsuAP$w_FD zJDIyUh*(vpI_Rq$Z__F%hoLuUcgTz4wW=Gc|0i|?^k@pd6C5i#UwRWz9AY^_f>}iO zZ1EK(7F_O6)D}=mP8#~f>ac@{2BT3@OJqD*3KgKC^Hz2I9_GBI^(lFm9t21IPBLfg zK+l#4lwMr{IBH8pb*1({pm}7${4U@6aW$ zTS*T^m*vPe5Y(*&pI%tG<};PrWduJ8cjo933lSUY}t!3-)KuS#p~uaRO_Fq~nph z!1gP<-9rawZ+A1l-l`9i!io(fGOxlRpMnM8j3C*>(fhKeED!H}!iw*!TrZ*-T>>HZ z-#C1jMb~&Z9Y|RQWaUbNPUcA*jXeU=al*~{=lu_-gE#(<{mbFt;+*oJeWP9;on9RM z$v?X|zZhMd500=8d=}5x9Jmy=F*V`kmQ_ISf+te}JqPiWg$DqK-DgK!CLv$uv_yKq z44H#~LK$AeKCs4)Z!sb*UGGBYgNUwrJb8az+>@zZyb!Vl`?}$Q`{b{SENB0c>nCd* z$m^XaM(9inoSL*`5VMNsL}$xkQ{4PpzuhhV=P~P6fz@h;qlTTAl*bc!pN0UBu(X@K z=3SN=S1O7v{bIQ=lqD3|3>c{tFA(_Y&ET|8tAu3d3cRb)$?nVVDTk}NvZwtj*h=0z z9}eUd-CieGSa!^~5AQKHBXb(e2flubYY|@*OT%oA@sL2zBEd!(;ndLzlOMsbmjXlK zq;Wt0+Hv#;3q1-gcaAw=Bc0naiZSpUG>FeTTc_`jJ`6{fLXd8^2Plk^t9<(Md*@I- zfahWaLr-e{siLs*!J3KPL)rAg_y%S^MPY;QO{(D*S-^Cs0IgC~#_tTTU%q+D!%^}9 z`f>#AH;>-?y`%RO&I|#y1$^5?s^ufh4@d8MmpckF#t#V}_~Flm)?o3XOM@G=CNSCs z)RoB`9~Ij9Rpr?fTFG0*o0_>C-YK$`Go=4bY~`@_O183DN3j+$)hIy@Ybv%|;4@$Q zBoJ>|&z3P5j*MmK_9v-nM&CKFP6iU`NygP&~#6}N4M zCNrM}XC>w~R#?wQqR5K)imw{g$4ymokn?cg$oAP zkbKT#eOV=~E-f*R>?N6qMom+52Q6SSS+D(LitE-Csw5(vK&+XJM6EoUBlQzmFlYbk--EJ zXAY+417hXpJKh7$4!M^uvtqqzEC6@VTZTuaGWYQ}2Lg58`qv4@$JE0Fq6*IE+N%0cNX#p?k8-}oA;uVH^1&Fq%0vS8-m_#}bs?8W44aM$Z z_7KdQ44pOUrB|cuC^WGM&oh&B7JaxyZwalCpe!%+1zk!zOAgVTisB){n{C1Pmf|I_ zvvzMd>|c&vusaCnwxH#Nrj0toh|8lw`($(cD*d)E&A`W}gJJqjQe00a9%t%ky} zK4Mr@Q;(%EYUa)<`(8~FWl4>;wO?SF=8Nk9`ode4#oD9?F8Go6$=;Ppf=%Qim7 zWnQl*dNI-Td**3EswCF0UzZjHXu}^H9a7fC9nvA7w`Rtx1$=m$JkUZTQq6*Z-CNrD zZ`bUS_1a#pD|ZE7b+rckiwpG{;~`xApjL$kqtx4!s9xhAEMLtwRqgP)r<6h4frLn0 ze~q)C=e#v829LS)nJ+BZR|m5MG^@1Q$WC#KX)U!PUCEKm^#XNE-e^g_9Wr<|e)(mu z;aYh$>8y+BkQFeOy&FI! zqM=Slr3o)P=ph|N@kKF;w$dS`2-Z|Dvf}&d0V9(D0--OYjp?C8(EGZIGis%3cNA1) z-)f*3=XcAVf}$FLrers%q3ULx(wt|ugrl}|K11}skI3@X6jiOIUMx?4*~8BK{2#pp3fwz zH2UPnSwzMa+{RBPF9Zv6^M9a#SsE6sR}to_i7=x5(>g4vT7{pTJ@{uYw%%V{2zg@Yv%+A{Us8IQ#{ ziYmQ^uls7yRU@8Efr1P*Os#RSHe*;$WEwWHd%#e>u~{)Kyl~|)^;f9SG)?FzuI7Ci<6Ukf@6;YHMPvO4g}a z(gy_O1Lkcmh+nZsGD3xsW@XbSry%PVT+xzNT8ynlRkdeL78`1Z8HbkL=vQU9__VC8 z;u>x>rn|JfHD1@<=B!Zi)x%UlxT0=eHR0$2PBNRQ3@J+ALdVhDMSREcBynF)x2Exs zoGlq_y}(TY?M((~h9K#fk@-UwfJ_Vn60M&uzo*G!PR?1X2nT+^M|8jpwL1tem}Lo@ zQV=ylh7)nB3Sw@^SxAUEhY;ef%w_-nA zwfv?H!W6+?_;$Q#>ALd_GczVJW;SHs53+i`2Sz!K;;>1EP25Knf`7p~9sF0ahF~ef zbey=tvl3T4e=bd#W%OhQ?Jy%*QK^yUzGKrP@pFgCv!k>LK--LfRmVx2!ENt4ZL6*q zno*CJG`G86bI+aTi1dZF=-HBno-c1m>km9a$c3YXfh5dL`$12f)Hbx;i?}tEwtM%+ejBz zlqNKsFsC#+pw2F0_7cNGIwfXoIVd6HMwBs_^1?;gmPDg#{PB<8?rS3(4%_^LO-F~` z^VgPCfS3GBz5U}K8w^M;#$rkqsQrRUNi607<00IG#*MyTQ$RKj(Rm%iJUDD9Z053J zmbr0LcQP7a#JXV=8cj&U2vTmB0~;DKNKf1JR96FyTZD?UM%s{NZ&lTV*CrPx|Lz^25d|acjX%`JE zs64YORHoB`E1Q8O)t)vQ^5RK>V1&1wP{|hWc)>Mp0LV8ofN4E>BF&ovi^L%X_?SkI z%DxCofTRn>F2ekDP~)Nb zB4)S~Y4}C9n8F|BhDJr9$E<@)=^%hff>UNZOEP^{p{^^#-cuUoGn!d2N84@~vyTAO zLs)-JB&9cK7Dfixc2ph@A^S1lP-UsCQIhLFYpKtxfC$4%H%nnQN{T-TZO~xrHA|Tk zl2+3(c&VK%d?7P$qz*kxr%ND-tiw<#{F+-=H=azMo)g$~dAtH)3APg~tBdl5e*es` z$wtOzDI-Y861T5^r1lT4ri6xr2j@{iTqtig?n&7TTN&Wh8lefzG-9UpWh9hO=RK^+ zfJR%75VuMCDgtWKCcRjhOucE%8%K*UdlI)GZcxys;O*{OyAncO>zS<7iJ1}I0e;oN zD~gmEYPS zeLae<*;GS0JaA_PfB0OB%#}_IYswi$=mKhh*%M0?W3r+&2V^H;EJWRc0V(-c2wFxH zQ_dBnk8yQURVXnZ!Zgf_3Yw`X=7$5fmYaB|GM6xht9B7>$pf@CRZ>PNJsin8PM9QE z#bd3L;*-gt)k9!e^GXTyRBk1@6 zkZtkIq-|iE*bX1?ELsN+Il_8)V9Ezjfu;2gB9SnMk3vPrlmJmeSa+>oR18I-!ZVkGh z$Z>o<$%i;GmRXhkV5=B^(a6Yx2eU<-W&53ioAXAs9FeDqzF|E*CT*5S&L|Y}RB(8_ zVn9GMRd^}M)MC?;2s=hB;O%Hm>~ntRX4LooA*Q37+Ggs~9Hs zaZhBQZOSbh3ZCfec(+Oh6oAkKFP5?`G7dCFj)M|*CZ^KCwWI!U{qbNvnDnJnjY5GsyMxWePF{_66$lyHH5LW*YU8)CX&&)Fea?; z6mhwaVjtSEjb9qCR$JrvinUO?A?-0LN(31n1gcz33?%$`snu|vMRfN;83v$kFvU;= zf{(aO)_I#p@idAfUMO}|9|XZ;P^-o!;-u(=nwA`M+sp1bK0Kf(@(VdppBshKDFA`3 z;_S(UC^xdM|DRXAQ+ANP;Y_+F^$`4|h8U2JbDEftoLL0(P+wZRR(@Im(B#R3T_tGG zd6G=j#dijjf*uk{1m*-UL``Q2UGUuHo8_3VXBJM_iT{Pl|1(KQ+ZS?EtZ&jZZE7H2 z=sOjJBu-Sk3N0RCLGElB7z#!)V1a@PE8f(ba6AKA=J}K>%HkkyF)z_NUwr(E9vf`X zy-Mc;G>>1a9&8+zcO*v;c(o6MaD@2-Mrqd)_$A9n97z4_6+gqgoCR<^G4V)?xvCtT z*Mb=$>j!eXgn-jrr|Q)eUoEM~?>fK4*ds$3vyUhObj4a7WL>IAI3q!5rckDUfH!V1 z-6)QX766K>JUuz&Mln8fgCl%otVLtKir@xjFdFG~OC_4{pchfYea->_-0|IoD08MT zvnS3L=&fAnEMa5MWA?$td!TY1LS7zUT)jE%Lm3?ep;0hdE#tqh%6&!NLxN#8uW*tT z#?g#+6_0)QJFMKvOe?qUM5Uk?g{jr%x#dyjc)C}r@2z5(^q9PeB0SoM%}10IcV}hx zwmG}JVNybHEwROOVZ{zdmwDw}T{KtE3KH`*RXA))tI`q+J`oh3{wGsVFC6QUaJ^lk zwKH6kit3)zax&KD%R-Igwqoo3U%cJ^2dg%p*rH!1!qNSl*IRo3nMPmwEV2B01+bgK zGQl#cgKg+27wfM+Dj%pecNcnF>VlkO8ardFvKMYK#Hr0|hLfUW%>iS(|MEfOGG8)q zUwiP@8$j5o58@2(Dd7hCf7N*6(aYxy=XrnmP@cP@D0}(2(=U5fJAm106PF9giojGo z`7*rm`fAOgvd>OGBhwCR3=UyLo%lwn6HecYkYMlvQ7BYeo|lr62NehP?3Fx|-QQ=; z+f{?jWxim*zwV%~H}K0Q?f)u1Feh4MGW=}5sMj28?)fOz$;#W>K{i}m>kt6AwH;)z zLmH|SJGjBsiT(K6PBPVTHo}PoTcuj8IA)H+a5CfAY#Al5RJob})@|@a@k&6);y7+j zz$~}$mJZ8GpaC^HZlz9eAvEMW{LM|ftf`tb+{UG>AXj+0rixX?zA_b5sX`zu^s-Q| z+ESc2MF-dVv=n93siAxpo{lJ&7{aO$$SqNl99oNEF%4aji24 zDdIn-55n@qzYcxF`q}{7Swe4%#f$9Hc1M9w*?c65ON-TIN|wyNST%iEy&9CKEuWQb zR8fuVMpY~L=rd}Tr(}_96_1*d=)qeY zV83waECA3ISZexzTcCyPpa}2>uW^cNQdciVYZ_zz=oIw`LufS$co)_wg5+>lHTnhDmTL61Sk`NMjjx?6RjSr!bx)ZyG=Bg3j&7zT{N~+t81r+bc|Ad@M)z}|Eu{w8P5w8LqsRm6 z0o;s5z9Lb6>nTwP2)YhYDl7iKHFegj`5CnPBJzDUTh)gr{BL8phtKA?hyTxVn^Et} z2>7{7w>rXO^>Il}R)>|w8nV?4vUivL;nnHrzeMjB9s83xInGK$D^;W@gDssmRePzf z>54c@KuNq!3qh&vG$}Q~+wqQKeVNgZ{%A0QQgT%P0k-DJL*^azRdy!OQRkQf%wuOw zE1<0D4eO)i?)o!EQ$p=pva2xI(^ChU$ z`-$XCc?h>*4~{#Cd61E351s7ej-C8Y98~Fk2;FF7Fm$bruS#Hg?0KO4+qgf+A1*GB zy}OfHaFb~_M$S3ypY?~s-rK%^a(Qv)5C1$I_0PP26kiVBo?l$TpK~-95BH0J-z=s> z*d_v%ez*4@--~Ob4pYj+*v^%%7Se_I8!^Ge=r zYvV_k$zh`nJx@cVD4SC^fMv+cK$As|2{1Sw>;`bu7`5>SUgB9y$%wE42%Ymm^-kqS z5Ysa=Id$?~x23_k|N{zyr0@>B{RUGAQq;C5Xuf)_aG*)x>- z2&!qZV4)D+GBlU(c6Z&^>O^6AeeXcWwO=!LMaA_YY2!A0Y&P~D8{TuB-GRyQE_@us zIkKC5MbC;OzrII|_I;6vE4K5!^88$GjnTN;5HyXHMWouCQC2}jU?`hbd5x-GXyjD) z>gcH7KkgqBY1TWm)decoNN%%1K62qCYqYWH8tusiup#OvJz$2fjyE}^SV%A7M=KfC zQ{i|>1?I+RGL*Q82DWKM_|94|kqH0>^X^DGJXIY36Yn=pmhv&AwKnlyz4Wf5JY!Q5 zEEm)g-_+D$!72F)E+*>!7b$;M+p zJjK&JQukxTJV#jP z+9M4&;HHYD7=6pTdcKFPUOj)gcLJXl`ar6Dv}2|d2ctk=`{p2ao7#K)Nj|MYG6K!@ zlAuTv!{BdD)T}-o7UoQ0DXl`GQn|VsV0%rwwdd-}BDs0dUIqg#eD^EswQr&uH4JKl zI0Ho&XAQS#k4Fjb*9Qertz&mW6OK;l=@=Q#{sZwjwDD!E^s46s6kpQtE4$%W<%VBY zH@x@whdtP6+EezKX{C+gh!N5Y-in^=Jsu%Iw?m~50u+dA_wZZ0hu@Za`08u-@Lxx= z{<yK^qA;>E@#rw%aS(;2MFTsz|>1vF|_diA2y6uVp7 zJ9@eSoLYFl6IUf}h82Fi|C-)Y7y}hYL~r$JnU3;BuBt%Wut?tEVKIiqG@)1)8K?@$ zVm9GL=Zs_4bK8b!w=*#4q0jf`?e@2!NqREc3NsU?l=m-WK?Aj90* zO>(DvxhLAO9>QkT7`EK5{{Wg~Q{nxLAhr~=f2dJ3uTW*!dwhwBDO@;R_h-qEOt_zQ zJkFIn(JmC&FAkK-H^yB+a*%Po$kC=ePm_;0^#c+V6lh(tx1ml-SJWv~U&nUq`#N)&~Ysrc=ynu@=pil$x5N&JCX0S)KtmBjYhL?LN;bP z&RikSY&jh$g>I5Cd!|cdldo8R7;u{d*-_3OD;i`OB`3uFdMjK-3p$ctP14$`cI#Fl zg6_t}mC=CZqO`Xy0WKPNt8b1n#8#b{cG6lpNduQ8wnU>ex&fB<@VtRXQCQrntG#nE zePn^_i}@%iQ?Y(l<%+JFvmMaQ?Zt8qV+{cL^QFmywmsUiB zir25IWvv#oZO^&lwyxCGiL2|SE;N7;KS%QFmF{08d6(W;EM9D`zqP!k_+3Z(YA%~6 zS@cNxd=bf`S~D$U-Mn-zm5%R#C_*sM(0l;;B#A|Qc;UmB}{2*%?iRk`6$kNl(2 zpWpX6k@m+ZO=3g^c0XxEN#wANx93+Hk#akR*c{P#bz>fS8{QzHqc?Ss>By`AeAx_JOV!!XwDm7jjOzSD^_*24 zQJSj%7S5_XE>8#NS3hweyy|y;@BH}kVsPAYl`@%n6|H3A^Vo|gX%bD^IL00hGEH^1 z!$_EZZqb4#aRM*sa?&Ek_<=Fh4KsbVDOG@7_$DRR0D!rqWRf%nD8wd-tg84Nc4UgP zoHJjpdf427jy!*^;;Zus^r|YUsq#rB=b*NpJ(D&MbP^nMW^BLMx4mwFL|Hha5Wpf= zmx)T;8bMu2bBYrTgFeQRI;ALfN$AB-)$$HzErxa{Kp0bzg&4sp%%navh|z%yGpZ&Z zz(#RT-OALslZHs;3`o(VPLc(%i%-)s>Z)Q?UzOyZ*oC!eSHK+}SXEk%34VD%0YE}> zWl#nehPG<~TUU?>k|yy6a{wPZXB^8@0+*sOs`2l8uO>CyZLTwj^AG4I`l_ibIwuou zsq>};BYw5KY0Sn+Y{o9A#4@umAmNW8JF|6AIyWe>xr=~V*&|#l73Yj_0)$?kpbcRbY1cqrd?D%kVh)=avbF!V7^6SvGA1yc zsy142y)q^q`7Q}JF2~{xlx!|w4&C619l1zsMz{Jwf7Mz}T%LgR*y@}@g{-9}fO-w_ zwFQk5ev_xPN3Jvu(j{|RTUp7FAfP}}u7f8PVDgt=_8OqxB%(V~E~GLA3%0!qJ1*yI zG@`O_w~B0NP-OQ|x>R+gTO|{*1X^`Lm8k`bKQ9PjcO*RyL(WvCfaK`UmcnXLm1zpS z=9*4|k(M@0J6PPB>@4sd6Jc>~7L&3KwWu8|ry`CkJ1wJuDTj#m`x5GsawBCpJ}l4p zWtE}V008*PhU;$3Ri`Da+$Lmu<0(Is?RX#qPi3zE^lv>0V8HHj8= z3Jja94D$-0shIT@3+PQw$=fkz2;&z@UHz}p)Cgwuy-vcz2 zl)>&AaFqL+&$R4hwtU?58gTo^KRn7|S4Oa99VUngq=)!8x+4t>)e;)`ogl9iZIM|z zYsi}>uvWngVk#C%NaikTP0FoHNQ;UHql%CMv6_tXaxEfO;kN-Dxn>luMa3h~I3;yi zkv&2Gq};}Kcc{3_7nCfzY6!3m2q&;L_P`3E4^zZ3)>y0vDJ*C7b#tuVlz`FI^&lfPTIwgM3^?pW(1N4 zYJDX~@YzJlvnMRDDl}a|!pjg%N}2;JR=CIenIE!EZQbZQF2_5VTE_Yx(PIE)wlf9n z)(SPlXcENf-ossI#-Y%%kp?IrMuJ10T0i^Gc;PiA$bUT@8(wIaU8g3^Ix_sH7D|L96 zt07sE=sT(@4Ian_EC`e2-p@j+(;z&tasw3xhQi-Tr)YfI|AM}MrLM2+d3Cqle(R3f zU9~!j_xJ81&~Yc9-Dlim7Q4J*f6>NN-CfctxkI{VYC1L$_=5V+U6U?9%|oB=jo=$% zXY&*G&_V?dc-NOg$4W`khi30pSto zhXonl;1#Pu(e4_Bmu5s-YtZb1(Aa=-nsgDVY9cso>BDhBP~tVPWJgIi)bgwy~1xHY9nHGKE?&fB~HPyLKK?w?3tjvLU#yw`t4>7&;8|qk?Tt z*C?fQ6dKbJW!1Lr92WiB>8kezs2a43r7A~6>4Q|oI^ow_t)^ST?6L~ad5`6yfDT#4 z&Ri<32;4h9_AwyD)n%U(rZ%+j#Ql^~PYe20OJ;}DV#OZswMoob;MPLl>*}Js)oSzg z6SvB9`n-46_t~qgVQea)AtcOYy_6k>JjZ3co3e%>}1lO#! zZz-$WR>gMTdRMZClhA_~j`iEK9MhZ;R#6U&H4oE8%J#402oq(g8}iE<`<-pIbB=#H z0<>8+{MKYuC!8E~N?fOKu??}(>Nn^GO0Ph&A0cT5(~_w$^V`LKq2#ZoRUL{`YN!G` zje$X~>QYJB*j`$qDvbE8&Q!p+T>0RL3=tz6^oE#V8su~jOLeV^4^Fs@baGQ}kQRK^ zi47_4qF18)yC5UKpaBZYL>NMh|R?$sja+!~aGjnjo)S8h++z?o_` z{4JcRcF!vg?n?bG-8-ug?yMtL9)THr3?FIHUx88OA=tV|S!+rGC3A3FxKWLd^rEJW zgJV2W^)d=F$M+Gbw2askLl5$SE1Ssy!>$}J<2xTKrhYRHA4DxWIqkjmhrJ*Bm%cu> zr5vr)4hH#4(j`rKRG6LgQB}Uf%fA3(lHe6~P87|cgv=#eV8a~FCT(-a9yUJ+;bX)X zgE47@>d`-?ONC?OA+oQ8$YiM%J?1o_*k!wi(c*WR&bYn8j4&zsQsbGCr7yrL7v@*< zrXd9B78CRW{c_j{>=-~9@IAC^X6)FYPrXpFEwj-81)Kwhi3=YJ?Am)U|&DQQ=0Xl(FzDu{)x7 zjL9Fp=}KOp6owh%8SJBVbUpR8qF3TAqTNYKwi{6E(+K^3_~tP6n>aC`?6bElsyPd7 zo`_FM@qD$jjA-T4SjU^k>7RIAwel@3OJ%GFa34ax)({I=yyrw7?i7cC0y#}wcnXXVQ6brANbC_nkP|fIX@D_Hl|%F@ zM-_H9V(F$c&8p=lQ->RLFiaDUOi4HmI2XJ13Zcn#WGSkaDRUEp^W;YE9RR%u+xI6O zKq^fx$H}1bf|mn>P{VwilzZYS%;+LPYUu#`CNC$xQqEP#c{Ux?<`P(sPpuh(K+O=}9$47y9_r_0p=q{$-uu<`!#XgANj8`WEE#A& zLRZ29_}xSGme>Hw_|=YxRz1o*Q~?Q}*Am4hL4D_O4RQKjL415;k6x+Q1jOmI3wG^3 zn`+YKA{?v7xRok4{LMjW1k}z82~?VKav?-+g`>9egJmb9Nx|@-8GP%N;iIk4;d!Jm z)1@g#_Nr;|9$BYV>X>P?MBt@u>Yb*G`#=8SfHek9!0!!a_@+|0G_l%-No_!(z$sM_ zmFnseg{XiPJ0<;50~>|nJV$EBZSvqz(3?k5SWH2)DM0w5zG*C~Uic@N7ca>}1B9Gx z+@5l6i-O}IrjRn&OHg$NB5oWH*u{>kbV3Nxu&Y;s=>gJW*B0HPVQw`$3xtn8&lQ&G|ho=gB~`nN&N@b05W z#r()=!gO`*L|GYDG@FGt!HjcJTV=^0Ta+6{qWdgD3c%WB_ym%G*)%5`Fz|hO4nsGt z7x_v!E1*Dk{+ujumv|jq&z{QQC_+9)ySybQNZ;YJ438JTsfuq&5%#s`wfRo)WI;%v+e;2F5XuJaiKZX>x z#^Exz_)31OYd^Bn|JoAEhAP{C&w;LwUG0)Wd7RzUlIk9Z|91lLsLLuf zhqU&9aF_^ZQ?4&KS*l*q9$YjoqAtgKI4mi~4L!!7`PIH#){1bKx`ZLOsnSJEr%U8> z*j&~DRbSubBx6%$KA-~Qe+bn~%u0E@wcys%$jmI*Di7YAZD-!&?1vnvCP44N)k zhh*mmiK6jcUg6O{4kOSboUCRR;?MxEZMa3ON>!t={Y$2Z4Jd4I@k|opJa@G*lRf0WW6}n{p z{5b_Xu+X%YJw;Qtou(mR!kKpLsEFwNmvbEL6a{@DS`9TwxAYuxbXt}RpxBk$o=%U; zT|L}V0A4_$zp0l9>tT4S88aJzY(kO`rb9)(=4eNZ&}~Jl=BV4<;jwA0ceJ~Xyei~L z>%RlIzMrR0u8U8Tk=Z>o7_hYQeI^8*`V~we7u-FVlr(KP9w9W*bkkkn2LyUdyg>mA zzh3~u0Epczf8xC6hGE)zPNI&m=9J-cl=7@8OqtDD@n6V?^@}F)!>G@JQ%K?EV2hYX zmXZpn>$2E+)|YKdp2#T%WJ!SQCv;~fXJvEn(xg%IO|ce-NTn0QYmy8M=<@2^@135~ z{&5KUD&4{Zb#Oq@^7C+f8%JY0_?#yhpPSGw1e5L3?s*p6Fr;9LX9up~m^8`-#+*Rz zkrd&~L>?Ui?UIZobE(@e?>a!cv7`sbR<<)f6X;S&F0SVA3k-e=|Gf`WiSr_QK98Y9 z-}uD5>@_=`PRrDz!+CRL^|n7MQ?I28tGl(>1Gle1W{z8>u!$LhAL^>QoXZ^-_Y##x z!m*Ge!d6%HhJ?I%7U?|6%$(;1xEp7Iggx8Ck8yF4~XVo4y z){iKH&V7z^X?KgBYcl@I0n?p|m6um9OzyP`h}NKwYJS0@Ph~Oy3una6?W= zTwI?d?TN(x###qAzm-*08n@yNDj{=~ z<*AMfr-42zrIeD%$>%h(l|t7emN)1}$5;J2RSj5#snxERH)-waQ2Rr%F49(QHb7Db z%0q!$v5lw5{i>J7+!9fUFq%43ZzgiyHtt|}U=3x8ahd6`oI4lgwl0XA`PT&{eA33w|=7=b{=kn+|{HCyRHHVFtcs_mO?4;dN9`TsYd^Gs{P$ z?KQ+#q(Sg_|4hpu?9~mCl<${vEO}tZ0_7!zgq=ha3`U0P+m2ne?G&H5I0Ybw>8ntz)htSi8^;rlKdof2n?j9X9 z;IC47(H!YRiO-&XNv2Au|@!d6Q=1K*nsaS0xPR=foOiSL`Q8cfgzD=LNDl|4{k=z zhCd#8FMr?pw)3sm8}`ngkgZb~&MLg(B8eAGSFz%{UT;HpF6i6J=zXpgfJaV^iC= zUE)YW61<5Pwnf$%oUpZ>km2 z5`xVVjrf0y7TzjF#HBz*w-tW48>!F>#YLUaG2|$8T6d!qJq;g{>S($8ODZi*MI4dl zGS*nR!Koi}*Vlog^3b(R`X+$M3n|AFDV!l`NU|oY02F8`;tGYC;7Jboz zVlV4mkm{U^jBk+(slw67+sv=1KrYwGXiLR`IK6o5H~W{D7ndz_C;cRvX-;f9oY=vu z8OrfulRdi&1#e_j-EfyX?!*nu+$C=pW#yK`hVXG7VE9zDeUumKOsid?gkQf8(8YmW z72i`JOcBgKv$QetacrZl*-*jcf-iSO=nb- zMXHWi)WMOsyNGSkmRD#7X7KOr{^0A(Ha$AMrOi*~o8J1$SXM43r9h|c*b7{y>|{nT z*Ht^hLnL4oz6F#=ft=Fp*R<#$hVJD0Zt*H3t4IEi+H!3Szh|QOtBZE* zE5mAhMkfr~j?4PKvE|~k{zsTJ7>NNdun@nKxT4Dp3U71{W85T!yCU-!Uq z1dj*t8O+uwYqknDOneEm9smDK<2(1dhIc!{Z?^X2(0UykYGDi9_MX+6PP$!21Rv`g zZpA&uwq%LMU2>8(bRXP95@o(KC6#Gk-TErpQ*mz<#UGQqu-fp?%n`~KLr1t^K`L2z z(R87vRGncKPYOzAL+k1dN#{utW{4~wIR?CF82=aEnFO(VkLQ%+nKn@#3w7t;Se?%= zkxaXXBv|y+q>DmGzOpAO*(O*%RdC6_=%hoh!`Qqw%rjoYa5nYZmHaXZZFbS#$z}%H zK|?71VA|>Pqh@O}(cnl1G=J05it254%f}W)$M*fT8ZFPrc=C zJ?~wWUkLB~my10$zDiX=UKEvqm#IM6x^00h7kn_%S~0*2uT%)eUi+Pu?%MyVNwwKDFy}3_SFVf5Q3$S)Y3C`kdoe*P2vWCe>R5q` zR)!GK7ix9<5KP|PS`sbfvvA|7{w0X1Ktf9}vqFumg%y|o5~L))$`YKEf-6`NtEtVA zc7qbL0*3SDXC+kmF+wsb^B3TKslh3gdV@Z!LD{c?<2slLQ4`KQkMev&Vty4G+894^ch{=>s#WXq zTdUe_^cD%2E$+!=aZ7WBm~8WF)3uA=!muu7ujM-U1%;QZ=d}r3nxQ|3!P&HVV0GrU z9?_sd(`nvvt8gg84!^3*vtw=>u$Il>bmVmY%g(3qs@K;mP&!j?AnQOqhFp;Bu5FSJrl!sG29-~wVKQJ2YXyci*k5D1VRP(J~K-xRQj^au6SxZXWOBm7ZSyj4}^1w)|njJaQ zc7aAJ&PFf0h_Sah10}wyI&AqvK5Fe=1ceoC_LA+L5NpQ*%rsibvguF#^nXaWvQjp zgzImc0JlimA`s?}>4?Gu(BMKF; z;BQegr_W9c^`7Pwbbp{vOyD9HPtltfox>0t49l~PgOi9);*o*)Ly!x!9uegIbuyf@ z+>PBKS|HZpm z5~uq2AgNE*CICkn!TCPVa%LBM^? z4-_jH(82%XAoR`cWTo5SzBgZ=KSo!uYF;JLfg?d(Uz^z^cYSf^3I}^$+ zmDs|!+;VqU9@lXVLRf4_tsuG}gXU%cbES2F@n~?74_(LNj=^O9?YHm;!tr>mEcW{6 zg=>{sXq2jkewNaYdj9yaG(GBW+079WZrEd5FJ=#yr=o^P$i^!^YO1 zV7-^FkZl_*QC{_T;7U><{JZlcS@|tFQiUKEGU7=5PL8@=B3AwhY&O4(T=~EANV^3C zUdn1e-Q#vdLjObeqezIM4Yg9I8`RYMyAx@cB+W2Efkd z|6+c2HWoJidQIeF@T3s#E612=@=-(?C#miHX_KC*1Hri@3q_T{I>)N%CWe*-49rGF zD&mtCM6%qhw^<<@*0QN6%BhkTsh3!~ylqKj+|`HoMWt&CoqWLss9QOCMr%a9HH!cs>Qk6?l|V8p=+Tbk4O} zo+GJsr3dPl<}=7$sGcig4fAW-Xc@Iq<5{HNcdCf|O_fwa=Z6OWTgdW%i|ElJ+%<<9 z@FW}=SAng&Jb>oZcHEQ{Xne4IML=GEro^QQGB}OZg)M18&Uf{Hk8QQ|0&rxXMc=xO zi#DCAw!C?#TmPKVGRTHgIW)+dkQJvKZaCl;i4KHD(SFLwTy0X< zN*Fo@ytENV=3|;%X`fph2<`e9NPg-L1Pp^&zrisAvk6U4ag`#pgMAW_F3K;5J|dfI zj{cy*x5M`tqdr!YB*%kNVS3zPAl-0TZ&o%JeCmFugaMER25(b)X+VL&GjS4N3(;%{3qmYqPb;hrjC8g56fC3|7N}T1wwf^kC^Cq40r;?4kIBPb(02u1FW@Q@w67@l6<9Trbc@hGmUG?26;+J zs`cVZFukILBeRmaUo~2tY8%6GI{ZMg8_@V=KDlICYmD%vt_HmBSJzUz|*an;+wo5L5q{ccOxLo}WV_i_)$j;8Pt zAZ=vPJM3{0y~$6}CIToPFpb6zf)0x?U3fR+WI`osir5St`57}R+5qeite-~~VMBCK zk)8tW6*Rk2k~OILH#bY9cbb8P6#NeGoXxGyap^l!Y-)C+H3zhoad{`xdl+x{Nd3IW z&0PKU(d)y5?h=Z}C-}iKQg3<(uimvv25FEJ;vuL>Yzj;b%1;hFLpXR03wd{Vya)Gv zJdRAJ$EG-<@OxK?5Rdqfw%@A*TAgFw+4=JDxcln(@a@5#x?b;XRg}Y%ue#)`<8Jq$ zsw|zB3#*NOtDqJ>@1L5porel!Uo}!M(%IqJS&__|ICeM|gGpR`uo^V`4DJn2TY@C1 z(V|mLMCYx%x&WhCQx<&)sdTA4kF`GJJ zrcd(mXh0RhLMn`#%6(fNrAz!>Adw~^Iu{c=7&k>)3$02&Lv-=Mo`xpCfyJ|MX z6P%6cx0<&-QIO_UJm?*qbPxKylOMN&?E>9_+b*#txLy7#sokzc>&w+YuFIBga@OG(_wjp%xH7Yx*pu~(NIf6X5Wwyw7Cg7?p{{l zDpf0Mm!5b3sl@1_DTuVAMm(S84TD*FTN#K%5tt=4s)tshByW`CH_^v_% z0nZY(3khVIBxj9|Tjb+}g-Ot>Xe?|VeF``;9?oKfh2vllg zM_hoNj9bZcqK5r4FVbr?Jaw~=%?1>0ur*d@rBWXcxY>orrXwO{W9(pb?c_PL1z)OZ zx`uxnV7*^>5-q2(flav=N*_`+;&-G}41r_Zk;rT^zrG`h>Gj9i#ym@bE8mgSIL+?d zoZ-#6x`x&#(#=N2yL5KpZG25`E|to00X}VDpe#FlzAo*M`!VegnFdggjC5bPJN0vnMs@h>&MS9Tcy<+5DFAH-LVnK zLTMCWI+`-SM*amBj2Y-36wyYOH%v;@Qwn=drXOSIafffguQ7>8fij1_-V;N`v>(vJ z!rt^dBG}og2%uuTQB$Uk0&Jl-Q8H1jC@zy>8jtP$(*qJAzfJl8yrDHK*AdT3PMd*8 zBqFs?3S&*$xz?&LV>Xb1XEpn`39UZ`aN&V{nwSovrkzy{sNn!*j)uQb9o&aq+gV$q z1-^4~a@>3I7JxO5l@R!H(EPF;ebsW*Zo5SJh!kGsOO!l7&L--ZGYI-0V>HM{@$?+A zan#@FZ`FhcZTQ$YVOiM@Pn9&|%fSSs$88U1{H2m>2K^uVC*3!^h&_>nkFH*!`uC&$ z3ly^lxz@+E;8=1|lOvthDTsP3D_wJrKqW32S;cKQ9C!5Q!FEvGwIa;}Lq&_IA6dnS zV+te2EKQ9fxOs{v4(`Oiv5H5J>g%0@z5T9c+MMPF?^ONSh&-{H{gb`H;oFm=w=g^K zxp96mv1Jz0^m?Y1K~c1Oc+fwDsoaGd@8HGTmoK}=>IU@kP|0Ut!(wPDzGb3_*2mNP z1->T0D%rGl^iY&+dDmY5qPs1t>0FsBY~hs?w_Zn!!Mo1aTIk-t1D6!gGUgHLpGgmi zR$#7}L5VbK1W2IlX^_Oj3!>6DT|ZHSXWB^W)iFBp&tzf}9Aach5d2MQQKF=^o*?@| zL^H6{n*{XJsxnUg%+2TomF5*q@u$EH7mY+{^Hk~NJr@kQSZY>Yo(#=Zw3*=j)33hz z>FL&2UlbE{s+Df8)N*W4c-uR4COR3mYPnwQ=GY++t{AN+x4kp^Oh)IWzn;n1Rwoe! z4IJGQ@j%?zAOQkha?nhVK)m#UYUDURO*n+e33|lB9!w;jkB@)V$!MW(#b%CEL?Wb&DY;J^`~!@9c=o?w)7;LqFaoaK*Ag zfZO)#j(yy$xEV``Sy@s%m${H_HR2NX+iwn;G6afVY;6WC($~I9lGd5mn#EM}z5w~q zn;Z!;XncEta8;8uMUpK`?#zpO5^Rt+^$ygbps&4~2z(ArD34)UphI=U`)jUz;&z5_Vh>JfMtJ$VEHHpq$|J!#pBe*NSU>CF-f_X(3RMA{T#sK2%pw=BJG_A#C2 z87>)&a9BdK9uaWsT%mWXc#(>6upYUVy}>hPZ=mIr&DAHKpdfsTEeU-1P%I6Xh&iyl zMyz?HJ*p+X8yH9U&fvDyD(bDSWo`%B*`T6sJ8esFDNkMRuM!piao2HlX4Z}nIOS-LHXQ@V0__KRCy z_opp##7sdMA?_7+$SfEM=M!AxYAO$`&CMWZ7OLnv6Qym|o*jbx=20E+tmT|y@3Uik zm+EkLY;@ChcIcK&(I0TzIhxy)2aP1KcOBz!mt%_E=a;8W}n$ETWnAFPiED+Q@KB}AzaSL?Qj$1kZ1 zS_G)l78xs8J8FQ&ZBq$jwukIRMWb`D^QJopdBBO$GAMq+)fsg_eMn2t`~dZyKO3zQtJu!h7z7&FarHAx#5d;f@DAN>uSkOTBJ8k^5ZGL{{n}y!` z$MX!8*RVzb&7w3XzAw9N51y4STv985&Kz_)_o$F3c?GSYkD4U5C~#*G8KgXqKMsQHOkt4Jfi`rqDltLso@eKu?hqh3qR0_`;2Ry{rQWR@u^S zUFEqaakcKWii?L>(-i{k-KLiU#r`z&OU(&QFgNsfo#Aqw3#WLM>qPCPu5$xqQ=Ar48G)5mdw(0t%LrmqZrH~i>#rY1 z6!ZzxGQYv_)=uRngN7L_TcQb(l8}ud8KU1g2%MlqJhcA zM+y#}QsxNzJ!Q!y>Nma4A1oSBfkW}{CUx@c6Y4^XwIa*pP_a&yuM#Zht&Jr&qFacL zOO>F%-$edF@@4&*loIDkQ%MC^oy+@{5v#S)f9!1-;9EBUzICz8)YCDz7wGloI=vD4 zUNQ3#$?M2bD=3^j%*_&(xw<7-#YO<>e95}4JS^?1Z4-h%D4fC19v7>xp(#}?*Vn=keoT9GYPf4!S1@Np#y^94r3=d)E8?6R#HGjQKsY z$Y8fwLsDWWTdg|_1uY{w*Ak`Ny7aELAZGT>7hjHaJNb59nr^{p1KW)dJQ~0a8__2H z(r>KJGmt6K^5uI685o9OvVz@qV`8@jr?>@oVVl%qgASj%88>ObO)@+NqYMAkyLj>D z^fWaK(G4x7yD$1pFF`3po|mBMa2bX*Oz`vgabQl|^^I7Efr)!=!#;ys06|`P9|X!f zw~XMz;N5`v193axZ+(3`SaDCtR6+HZdQJ1GcaoNKl{iOfD3yu60EUW+09!9p-Jg2b z_-9`*gUkQO!>^>3xaH}$Kx1*&^RMbWTR}He)9=F90Mz?|`F`@q80J@z*{iLC;+iy# zv(BH;E_f@Y4PW+FP~6ydExN|J(oOw)s*he~0(12n2T>#bRWejkm%Jpr(((B&q}QA&Ax+>K7-EF*7TRomq_z9Cl{ z&7bQSUZUv7!?)4vo$tHg`CyDNAp2B!LC6tkdjnc|37{s~>;vc&B%{FDM?WoW@CN#E zwGn!;twf~watP^$A#jfa!>jZYil;9Gq`4;t>lf2BIjikoz2NJ*?$y;K{^MPJ7w>9^ z%;GaYaI^<&t?7eZrvraFPwXcoc!E~ERM%?$*iVEATPAfUuWTj_;^V@lQE9|pKw#~E zgopMmrZH%us5yzB$6I^V4fH?7XPZ5q>v}I#pB(>jUibr?7nV=Q9efvjb=~chb$4|L zSVc>11moqm$K^)<`#1Z0hW}C`l(0JDt}EbkYAF7rp!ko1;@@0B5$@_TmBfGa0RP+c z0M(4vOGuAb(PPeM!uNckBv5U*f`}E!DVb5yZG;%6zax_xM_>0#Bx~RDOC_6-l$YxV zkjW&Y1=R!)q!x*%{|c2VNt`>EkQk#`YQQ7Yew?Df`{QJsD2Z%IQJUJ_Jey7PaRDCN zc8Cg-_no^!f}a__oM-8q4Q4tg={Mu2NaCyy#Lb#c~p%JINnD-yzM$XPNAv?xX&WS**rb zolfn|_s6I%f=zJ(&Ho$+#bC>7uC=#?sfiPWC&MKDm~i7vs@#tWB%%MNd>}p-O?9*F znWNdRBj@=;(&9sA?yXR{hf#hBbCOTDYmopYQR$1#&7iCRa;HvhX4~J6M6!FQo6kk8 zP@s+)k_J{OX4R(p781oL(F02(P+=VbWl@GQ(GZ=UOgNf=v~It^{AAl6UHB11)I6!y zhzFcLIeHvQY-Y4ZEUoBr(z{`;jMB_$<HM)ZIDh z9uMAhPhKDH4Vs`yYDXuSBFXuAuh~jqUWL&LN;;h7SH}2**$HfI_@MIVy;jrJUJjJ4 z&X$zZtyaXwb8M<@-d1IupQ@X+u(hj~qmrNQJh#AKrwL#$AVMjphWF?D`|feSTVvk; zO!FO@Xhi8$|88v9I^jpoceD{bTQ=u^+m9{EWd@#;hV@kEW(A==!-~jDK0E&MRhsUYk!$Lqu>_x--auwmH}7PW2|P$ z@NOvDAQnCr$Q-lcNneub@Q@F7O5U7In?jzc%SY+{tUY%hq2Ss0+#ZdA5#nPp(5X6O z#5&uuI(7jTx2vW-hlZ#kV7HBac(bqd$<yt7d4sc zv!oxD-5<87GtU+Cz5ep4?2JwpL<78$6vG$-UciZxb2Ly+CQd~F|6qCt*8UU&J0&Tl z9BNx+?UWKjQ2JIHuNbQ`h1P6_2+Ajsi5|$Mgm$R}(m!A*8e~Bp$3tjQYBF5TF2stP zCY+&IZWbAn-Nmk|;g$PTrwUd7wmCV0=%U%CGW!)}xniP(X*PBeM%dg|xHzWCL~)Q& zMXQeSZI6n`xi2c3DXl-MAt`h@x|+gptI@_hVYaKZwNxoYZqNMvv}~kg2DV^Z-1TTj z7>5(BW^(PV++qkvT)owRWbT{^OIu24fwHOJC)4ySO$wVkm8RV`1^o3n*NAp+YvG(+~&NC^!tC#adX4iW$4^iIefc&@ht8W!6vjKFoupB_DFqSZk`N~#lv|P zXa5~zgjSqpI&zTa9Y56x&w-3)8~>cA>hY$2r(MRXnr=?tm-*DnIaQrlO^_F!hMt#U z#mu;g=TRsTrK9}x7d6I}vv4oXzpp04<+V8zXIG`}dxwsWyqO|r%Y?O@CNjhWs&~W}DI*ki}Kc&bFCUp~iNN%uSK*;w3hau&7u?HO=j0xPG;Et!7F&xiF)N&M__{c&_2ym+QnofYt?P8Bxn_3zC z36*r8i+syfaujPhcno$5d0-XIyYJZ0KzqE0DAm}{ww<>wcTOerIs8Z`&gY^J9^x3$`21P#`l=as%`b3?H!m z*t;bM-7m;I-RyjvLasJNf$BY@^Op;z=<7O#KjF@anzBn0M!>hAfOGL#=b6y5wy9cl z9;cxY!@wya)lD~se0FU07*jwL1Sf&u2^PY*bb0#gb8t zAw{Tk<#Cjv&tXy>2$gcPqlXW@6E_G42w3n)$>0tLrg}QjP6p-U zF-G`6j$b@`O^VFt8eRavIW{!UwkO3Im@Cvj5Z%9 ze4aHebD~2US(q)jxrsFlNP1H*(;2ZU?X|WAPae=C@arQUH>0I;i_M|rM7wIat=9h! z-foG7qPwM2<4KSK&TMQge~UB`didAGHBCf%sQ*C5);;3YMtud$=)Ux z`v%QmC_SMfa=WoZ@s35~x!FG(8;Xotjm2e-iE(n#60H&eCjmi?iNW8%{x;xGpctf8 z(yt&fCWqY9QZtmQ8s@2`G%fYD7f8F^=yW=b=juP-JmFW*f1j@x|3I(OY?OXXNAq}G zj)*SI@I2Au!?fuEjz2yTe;3aw!4&dP$($gv57^H{Nm*%;3~?Yq=R&`_41lB6RFPix z1`F&IefqE|pF&tG?rl~oxl(<>F3XA)#S)WV_R}?0XIGAuhAF2}t!a(6aknKs&mMS-ggvJxpI>5Zk zWZHu_{oTR$-Q$+6Yph8PiY8vs9x^Qgq{A$Gk^&{V{_4xY0L`!7^RNG^p3}79-->G} z(w&RvAnU6=1dJ_7(L3K(JcUb?Y)BiOtmZ|+D}XcFuiI}RP+VQM)al5J@dENSZ{T~? zc}^2eS~D{sv&jH*$8HNUrn3|jd2qPjJ2+tljQ(6?7}3#Rlw&=L9?^yR5q&CV5N?&_ zq3fUQ?GE;PF9zKoPM(>8daL>=dr!te<6H*&Uyha9(0Qf=5&Hqi9Bh01@+-99jN&O; zjskQ1&@2^PA2#2t&8Ju@HCc%xtgXRXTu|61gET4`jQ^F*FOYe zfB*XFGY~EmmusVl1fz|&R7LE+^9%^mYqg(4ys-;ay9}~dCIc!oo2T$tQI2{?$juJ;7mD2TbPqW&G%R4-f@5C-(`B(RqVmH(8ESi*@#?92wo)T z=n$}t?~yUGcmcP)Zyx-F{rjn5E(=>*Wrc=L8JQ*5vw@|k2*Fv%586@V=bxX;WZur_ zq3qezl8xtAQ!oZDikldHK2OryH$Ja;SF(0#VCHnPjAjX(bk`VzPAScmDELlEM4 zrsE`Q%KmxCAfg5?riqrW#iiyn>L{H9z8R!hTHsu;#Q&no#iH7S!cS(#8gB9B^M`PA z&##gZR%A0!yh@-)sB)#QSd$$Dqfz6UvXOK#By-B{>+bG922Bf(8ncUw#0=5cyDxTL0hqnP{SdOl{}K+TP^FgGMC|Y=R<~8eq?Nrt695SIMs68^dH0@X_mvZfx zR(fE{>jub`_`IR*^7R)us&90LTD4!tRf}Axdupw6{7@|NdUK^q!MQufNuJKL)r!)1 z!EeJHfLCW~nXN_2XW$rjw>0xK=2csQHuwPPLsLf&t>d7jJ2E>DW}cOg*r zGFKJaviF%edg{4@IgW3uoHcjyge(2r$u+KmTF6&UNJ!;l&mj3bsB~LvAzvNLpRMy7 zG{lBq^YH-FLj604GXyCbV9svqjpAiuxHTuS&9R)sHo>3)mKujri^&LEz5~>)QqZZ| z)=^YZtpTHQo95)Iy?x6pnK}&%B&%Iv;K2vP8F+ZmtYl9?8sjvpD=eTJ=4XEi_h)?lcb z+#Aq9ErUTL#Zg&JM}1e!FM;6}HO^Fbx&9FcW2puADtXoIx)dk8Gk{oEt;2JLtGXa_ zk6NF_mns2-Tj;D+8sO192qomv;J%or22gyLu{>c@VOEC}L=^0uG!aYMbaHT7z;}NsuY%Yf& z-RlL@kS*tPu5-n+s!Q(%j-1+lf7{DiDY;^8sgcy0tKAx?HUYDYPc;&?xkvbT%7KeS z?fa2YqE=1d;~oiO`eAK?SSWR?(Q$;hbV%G6^unnr z9YjR&wah=6wlcQKSmm7b7-}qLq7pJf{ z(8X45l}&MrgChvfU*>|f>tA*vENnvMaj=TUqX?Y^b$hzG|98SFv%V z(8>~ZBovT{3&QEL#EA}P=Bwn@59mG_6E%F7Sn$J^j*e$Ys>}%j^ar3;TJ~i=8M^;V zmqoxTR61D;_h?<=ens)8YqYbMcq!G2mHo4wf+@zL>P7BqSK~RvkeD7so8|6APT|Mf z;){*v0ile!!e={sMQc_(Vpe4twFYOwzP4Wn<-=ub_#Uw~?geS1Ug+53Bf!(nhfD)H zxYagsnJplsU#c<(@MjNgPfG>?eqqc3Vyvt$oG#u`1JxwW-nOq5)Lw8E>On&ShuP`} z8+x&@|F%FH@#7O$G4Tj}*HUIzH8%m)X2}9;vkS3N;V^Jy$6bGYWBmmdstmsoioPWt z14bDonz!t(`8zGAa#Q`r-UL3xh`AbT374a@k~~7V*y>OUtxA`c)zpS(;K_n1u;8jy z%eS1X)kj*r9SG}x^$!n1D6Icg`|DwKtSx{(gf1-sjl4f(!$sJJ(48*qAL;^?(!%_e*kbo z2%m`lZB3kwIhrmy6HcfhdGD zO4W$;21p{{5mFc8?Ht4pUfy{Kr+_8o`dshal`$kc;K!S};q? zCFMT|i0u7)gS+M9aM9mSd;~El;=@6OK*UZ<&|~l4pDqC&n+3|umXyf?WwIq@&H`o5 zmXw(W%1o=u1Odj>45;CY)?L&vO>6%2=`HcRY#Y4rWJCUbpu1`SGgV45A!MdoBkq)r z-H=&wZ%zzrRpgy|*f2P0q?8Lm#M~F~1~R6XyI+0v)&E%uccWs20>)FO{%3~YSo;t3 z#wvB+2lU4O*N{j@X$Jnm&U)&h@TpIyDHKC4VCf!q9~{eNn2Ik;?xcii7=@3<25iJA6iPnT}5G6Kr++k;zCus|rg zhi{JdyC>bfThUoG)%Q8kw`*BtqwcsZR&R}q8zV^|j_=u;^MVg(!8YNzr2Vzk^hO3NRM(-QocW=ef& z7nLuzt-|E$pt7`et+$6~Sy-)u%u)rx5}G~RtXreAENqwrW~o46S>CLALtlZ*(sqc| zphMU!f(~J>7&?-Dtq#HBa*MxPZUG+(w?C;mE(`wkN2L<4#rDsKYJn3L&`k~wPw22+ zaR4jfTEbNZc}fLHOaC9eqa$^2L-Xu09wwna>AyWXI_~!SaMYK+S+Q5Y*SUX-X5G`F zziQPBpj_-`DYb0%v)^Hz^$zuw6fpPi4n#jII~!LWOd&X#KOuTdh)wAt9;!?QXonsF zR+p599iE#zaPY0Y=FqeMsmLFUl%Zx!XepPWYJ^ZQR<2{?)^RRD)w!EOO+ zQG@S%T_q3KQnS?pzF7IN(dsopsUj?K@sWBbZCrhv3(?F#0JGcsTD1j`EP}Nyi(9@$ z)ly-%sIX~RZTV@b+$1`-NOoGeOSjV@iq_Q7BL=Pu%Vi!>MJQa0(fQrUnoj z9Mz!Xz-{ul{I1{?4)&L@O3_c1lu>fFkzVM&I1tdF=yeicRZEaD!Z`&(htEo?qE+EC z>Kr)t4484xkQucOr!Pxkt-tEEyKLi&cw7;deXC=nPF2EMvk=bW?lmnq9O@%ltac<9 z3l4_bxDJcSJCF{tBNC{gj#8`Ey12{rei78g-DmeUSNux!j~X}g8dvkhpa#KH%JS=) z-7dwmyNj&u5m(&hjQjm?G=7IeFL3S9BfkWsL)^Ij9ich`LmD2?PabbF195-Q9_}qS zARu^K=2KmVqH;Xz(mUnn0{yttIsV5YdejphLU6bTi{;e$HLKLHRDEtXQ8K5^@7S4go^!J;DH1*d11e{0AvVyxCII~ z$_|$IfEL1l3zgHi65_({&cUF6a@^f{GdS+{-|nCE2NXtdkqkc+uw~R_YR9@FTHju8 zN9zyaKVPgvE^-Kj5sAt>aA@AB-48T4vw1uhY2z@|8y?_h_ZA+`M-JrxpjW531Yjh$4h=|AM`BXif0MSF(rjSBU{nKgz z8MQY~^BKoLV4h&W(}^IZ^8`he3{iHRSSyT;1-NL)A3CNpaHH(pf$rt ze-;lvKuY6b;%++fVN}0q*on=}x6^SKfT0p6BCrT0Vy7id(I2?Dr#2D0?l6WBn7w5K zvw$;g!LNz|uD^e}zQvCpKQ64LyEW_qP)u#jUle*cCYuKg6%&OE5h& z`zuEx2~vy0p-SygrGsTZxw}!1yB1FZv)IpvACeiwAi`g7;t$Dgo@ET=O@rzB|EllL zMgy=CZ9J2{x}~DS7!qZlChC{5689)8FbSr(@>NqtHxYWjav^rljYp#?SfQf}P`5zG zCds5oX3dBA0I#!fOy*}zd_d!fzjoquaHe`V21dH`a`5(`f7IQj+{h<6c?{E*>K%Rj zD=vBU%hy;XEG!asVPCsH}MMmK@ofetgd6Sv`T#bqn zkJJOz?QxoYP@@96Z4kqIN462L1z7kt?!Xs0q!v|@iH%f-^9Qf^V30CqGFcrILd(}c zhjg|h;2TgtJksO(PIY;4d1sKFVIQ;-y>QF_FXJ5Tvx$GQ1pNln{pF#HmD zq*#258HT(HV_Y#4670+l)W$RSifk^qXVWAx>&h-#!X8lTVFY(uJZ)!i$`%-~rOrBS zl60Ba%Bz~zF^rX1XbTs$-H1qXlO!^|6KQQ*5lOKF0);aCI?@cgEF=XaArgg%#9`5g zGyMdPbS062oV8ZYSzP|A2O`;-`g3#hLwB5xlF`d41Zlj9rytbHAa2v>bUIOk8*;Go zraOSluWX}NvxMO%>KoweQXVK*x4F4HpH9_6v@cM;p2XLKQE~|ZaXLW{$Rq~=bONBJK^P<0BA)D~hFck*y-h>>3%g}ziO(fM+HARa* zyos-EfA-)Z-9qKX9uDS5&!cI4H9+ah62LtH@gtaL0vQ>N=oIp77XYTHgj3wZaKfsc zcR8LHwB*m`86Bz4X<;fE!1-y8jQF$|Z*HQzZU+CM`Sz!$Key#P*g0U4ZH-{V9&s}U z*viP^k~E5MU}E;w-UH{356y=>QMAdu!t&378S&t~%js0<=4|_s{tO%5spsKCvuk~$ zb8(Sh4fI;(3TXUW4lmsqjUY=YZ3||fC_uA7t&S?is$iv2>5en#YKQNT`1sJcQ+x@4IYTgv&rR8&z^qyS4J^#r1G1|X%2~98qIn3AK|?+!Xu<)DLpV z+CbLGTk7|g=)NJVo|oGLzA~~wMaEbZ@WPOUKa>p8h@vkpH={2K)zNn3wt%W>X&+2f z6+GTX`etQ#J5=#WP`u&{JqYZ7E0@F4eeP|#@_WH}w$_|5?BJ~x>(Nqoh}*rr%(ML@ zRtMMlD>V4EZp+J-Z9O}|-UgRNFka~^7vr*;Bo6q3&Ft)5Z!a$yuu?Dgx;rPY2kMjSe@|Ko1%1h5%#}b@x&y{YG+~GFFVb2B$MrEa8p-Q2>Hy)aE4E9A>Td zQ}tYbrqLPu!~8NC9ck)aMI8LhDzFzTzIN`(rlkXDDWbky#%lTT&f2W{U|`)i;HToN z=-bLSn~)`#r>nWEjs2HjJc(SrdHEB{q9o32sGttuFci;?t}g0&~4;Tv^tAb_F->rs^zi zIraaS48FhI#Qyx z`xg&lT09d1A+&5rscH$zNsBo{#aj;0a#$U5pDOsVV7qId@EwL|qxw+`MdFqL zN0@_3Tdb{>pOJ#zeb&^tVbkOi*u!+tgy=@==xd4`^9RCa&x$gAH@hT7vZBCoF#dPf zlktG@cXIJr^y{Z^bN>};Z}cmVo^A40FLu>k+k#<@);X# zkt7*p6l*81*fM?m1t{U>IaYlJ4XKiCv*HYDhoe%}seZjkFZJ=EnCFxooxR%v9^D)im1!Y$V)}9tF^GIhx>>YL7YKLqqf~pnQp|zYvR~PBit%31O~u-AkCCp&R!%I4L_1`jsOYZbB5K(8sLL)iWvwkzwelZq zdmod0Ji`geSa?v~y`-B5;C>~ui+qH-eC`Li#8~SF!;&#A+V-?hkdx?zU$s-WmTXmB zuf58fmdI$(G6%K##?lIQwr-sT45myxxb9;GyS4u>SinC_#;sSEZ_6uN&6o^WU8`$3`$ShH+!h0HI(ai;L9Yht?!ep!;0ibUNw%5^<31@y^E zV!MHvgh#J5C!h=YEYHk)jeHOhs3n@y&?iBzqm*Eb$fK!ul|f;6@&rD7m+*Za3}9r_QWYs#OHDGVq$2c!1i4hpVlWzc zfqP%qMa51NHF$t73{X}P`U)3qVm-u0E_1jWbG9OC7*HVeDdH^&7|wGghZN@kv8pM3g`o2K9+86E z$wbG$sc|JMwCbDt1~$NlB)N>vb2W8`hnfobD3H9*mt02~h7LHYs#MKcb1-;uc)Y)J zu(vxH2wZ>LWo>t$zJd^_E_V90kOcJ?TcortlM-K;LJwsrbAb)F?UTE{DSQ)DJjHxC zRJ-DAK9(-9oi&(bJ7M;#fPZm$+rvONTWT*ZDz;VKC~aM=Zjg*osM(mxA`2RV+oHM^ zRUX&Xji~g|uH6RK_-gMabpWdaXojxL@YNc+OsL0%Ul2{_S*g{w_E`=92Q`{qRYbQt z+E32o;Z3x2)B_eX0++{OjP^P7$pXF*e^fI7+}P999e3Xxe%~GJcVF%7{y1QZZojKY z4VElJ5NYmV6;>~;dKD~OS(PiM9_>X7CNQl?^j>CFu#_6}RFAtXJubG8e|hyTT3yDMwz5(kH$~MFE6}na1$QJy2LpKs>6zcWWr0}LW3;T~ zg7I>j?l)=0cC1=C4;S8>=z6)@Fs(c~HQS}R|Dv;J$pQ+6zAhVw8Yf7Y%LI9h$6fr| zQI3{zI7*N`pJK8HC4ROM`n<5ZOnl1U1D&@Ay&niE9owmu<`SM@fs<)-TZtE#5!_oc;{ zZh#@!G$x8C;4ZFRETu3QrD$HA!aavp=Tp8;Rmz1M(KGb3PxUjRaZ^kLxy?zP+VHB8^ct*g}F0i!2Curxj5F zsOrMqVIy_M`T034OS=+N)uxZ>$Y49_i$Xct#tuU$6t6rGkMu}{J}_m(2UBhq>YaAZ&`x7mYHBi3W6c*a>7&jNe-ss4b=ok?r`ZM? zWNkAZO+hsTJYhkDSgQqUHeY`>i$5gN;L0)sn?A)b*4B)*K{a-j&?$vVvFQx8VaObC z28`SRIx+CMPh!=`uB}Zj^PSO1ylFaLsRmjVw)z7si5^@fuPEQq3>Mfxi2-7qn=KIw z1C)hgNd2j|ifT{6_)iuoO)LDh3SY2BqvhODvnVzOnibSxKSfSCiHFm?P@U+UccPts zzk7T#I5~dXZAaZ7j=H-igYN&^j*{81MVn1AM>V=bwnX9_puYr+{Oy6>V&!)-lVthHFtBN-_*E z`Y~vpnVQPAH^ENqG@y7Avy$8pFKkK-b@5Mb&%%V+18$E z!kPqeJP*9D!qZ^e{K5Lna_ob8?b1M2C6OM)P#88Af_1b|%HE#je#>1bHh0j@_2EGmzj=>U zR)2YXqTQD<{1N)Q2hDu}ErO1{Qx^steVPQEDVzhmZehb==V5X;>?cnMjVH;5dJSA) z*e!{c6eN8Ckf%%;5@oLc{`KJNzm^K6 zU#aJ+keC8ofmp?p^Wji?M90I6R7ob*pqiYWfq1CqN0A0gd76F9KhOnn_7#(hi%GKq ze>Y6mt+(ilx4r$7-hpbx={y~)g${i2Qn$o?YKKm@z2AFva=de-KcB{_y71_S)+orG z+Ea4!nff1Wd(GBOENJvGSNj;ew9!&aTNS)FK+>ZPO@OhM9!j{{A+iHf^IV%ur!no_ z3mCOi#T3qYj+4L;%SsLnik zZXH&)qh|rfUAq)>+g4?|EKc| zrs*_MOh%6?_+mGowYIDyx0W5sR|O5lvFxHi90@lIJ1B{JHC_2R{d!DMgREHED1l%FIvOw1@dyITQG_#D`yqLR!FCXpZDLs> z5P>=m!tbnD1m{qiaC5v8E%~)Kc^x85})lj8Wy zVQD6?t5l6o#uOtOxk25AZ}aFA2@p0e)EVt;4W}S3r5L@_h6$;mVB@r{A6Y2+PjmKh zayCOYh2FQS7xBEHwINp5nmwYCqhT0KC^&NiX`5Z|=)~46@}O$)1q}fiyPSY_7DcL} zGXtSm`Xal4(}^SKTPu&b3*{Ir4jh2vw>atr6e7Q6{i~I-U%Nd$& z?17x030~dw?>Q}fA$Cr0B8Dad6QRVArFysWlI!q!i?-sVe2?-)&QkrLL~sr!M|xGQ z=%y@vvq}^KHVcO_f@}q3BXNC0F*Rd$Y}ZkNG7|bh7MjFw_x_fC4dJNpE$;+L$`zLfOiGC}KiS+fWBl-+z zyg2;9P&qv69>7l2FIvvNdQdS!@jU3k+w+#5 zIzO}#PcfWHnxT0bFZBa`X;jCGQLD5yA^jFh1C9lpfVc>C%=J}F;u7mpH7`(mo^kIq zDWqf|;sCrVCxwk-?Ne=ipjjON8z8_YxUV$_hi^{?Cx?Un$(|Z^d-Zaih|QQTT#VjG z^)e1wfy*Hn)zrplN8hIfSfcy0`6$g{^Qoiy5(3N<$Ycht%s2*`NPc#PXDl9wc}fQ& zkp$w{bCfuU-+|bkC1gw0S58feO)faX5VpczXQ~O%0^p=z`nzER(GxZrArnVmXOx3A zG2%{OoRqvy2d-#sA#xp%ZL%A6&}!zPX=t_A$28`-5<&Y*^@Un*0~3nFFgQ)%5YDF( zeBkNz)Ar)q8vVfOGzQmpQgVVsipM$V*)|2e!8^qPx`Uk;hiYuz^k1pXJ5c;!e{kGA zQjc(BGsY7$)+=210O2`>b82$gSraS7st)Lys+Ets$0xWkkOylmt+1?tE*b91@i;Z( zN$84X@&kV%TsE2hio~Q*0x^b{vwYfOOP+ShSK`(Pu5M;_=xBwjh0z*EWEbQmWA-bG zmN7_Tstm<2WDK;-{UrNeT#(=mor7hp1_N%Q7qSMsZ?inxKq)33g2obLX|p&KL z7?b+_ijaT}D|8^stb!w-rspXrAGnTzs-w!4aIo<_^tl1B@SLnF5NHE_RWh}dk($Y} zp>9Fzh1UO#Z}e@tO6RI)fqDIL;;5sy- zdnN0Cq#v`I+yWuV4M`Z_$%S5otC_ zVFVIfs?c?6=EgJgMft2R z<4KjyzVasl1Fvnf>pnI(N5r}^jY~ichI=v$RFMo|8NwK%r%gb~IF8mKlSKLmUUG_8^UE~DV9UiFA0=M(d)JKXWBRoJ;U*^+pJiHJo9E(9)aAqoMGYCCzX?v_ov@3ncEm?VE4AB+E zm@=Q-;Z+`T&c2<;1?H$iA33AF4|rXmOj%UAT}YA@P8UyZ<8fiF{;N7!xE>bT<)V(0 z1#1LCjuvv5Ie(O{w4AO3pjr|#&cpF-r{Pf~Mvk*8*g1+Xf#ekBV7T&_UQMw@c!Oc% zMwx*+m@lMm63x<l+lCz{PS7x1)yvk`Qrbo@6x>pO-025ant`1lhoUQ6X@L;vl zXQ-_^?9g)rfiaN9^J5>mAjs+tN^ zg3FUp5Ewbjw0DVK_|vl7WJ{O;9G8Vj_Cabe&S#TmI+Y&u4gC%8XXBgXBFnbFlI9_0 z(YEjU=O;$7QBPFDpGzi9K}+gx19=1J!?QFSHP<(FZY`hz?;mW-hHP$T>Y=qoIeU&# z;>2vjb}Qw(YI21D2&%TtQ%HxTuGW$J80v=97ACo>o5i(i^Ei7(%q9&V=hUOW7TCx_ zJI4Ad*Gd0EDj_;n3ah&yFP>2X0|l!O9nJ9mgR&*y0E0Y=f;CcrJE!pS27B#cHogIY zw$SSi#btNZMe!LcKN(pqUq&q>XBv*l$rAO=knl*5fJ@#)Q5vT<4L2#9B+O!}hJK3v zZcZuktgw)E(S+RPVu*zwCT;dUWPXs2)MCzOcr^-as-v8`1ie&q4lTAZvp-8v#d*h&EENy%rHE!$EfD)hy%;UutFBl+1bp^fbz6?oi82i zfh8F{HmXw01V<08UgNR$8X5p{q`G0DuZtQ8JFJv^hJ%Fq_!apjZ|bgC_m;tIpfF3?WHR zgH@p@-Z2}3#gCF$Dl+IetutLTTg{T6ge@!`L5xjQ(01a&r9`GWGn`xsed@+@s2}`r zoMf7q)bOc}@D^D?q%tj|1ZJPMa238x!5iL%L$PblsQ(Dm1Jiw?`Vasv*`1dBVp7m@ z>Sz^s8%S@kPKz6S=(@-2eYA&n`$vZd{oae-e(&T*SY8PVCn4D+rPZp%qj#^n2hqvv zF0L_PxzWyXH##^xiTbbKzI?gg-P0>@XL>$IZSf{Qh{UL41pB6)>I)zIN_~8DnGEpA z+obt$)`n96x(K1<=74Mq7m76seMFK`gMVl0kOTl8zd$WJwOh#I&=&MybEAvaCN znW8;Gj~;=@0YK6GGTh4~o(|x=)5I21g0BmEJPKlB>ANzi1AHYeVB|#Q%}CpQX=Z@z zHX_u*(Tu-TZL~w;e_K+U$wtdI#JA>>8qa6B+|N2f4R;@q8l-2A zQKU0HRiaG>``CR9LTD@KxahMyZ`fKE3c+P80s1WinPgvTL(D>dWYJk%Bz;zvO80^iqUs!UyokKLB#$;pKr`1`H1x;9 zF|Jn3bGsby+}6N=Q(u@f#1K2fL_w1P17Qlrkj|+BI8z(7hLH}gubnOdI$e3&S!pV|(P1$Jqw#rHx{C zGd3wR1K9R{!fC!SHgEgOl- ziJuVIT^;IT_Y$qUQvI_CPrtPzOzKdod^dHhQKOxIbf9wB;Y- zAX#8kr*_1{3Q$DCGc!3yCxW1uLLUz_iEUl_8@qvsR|VjJ35^&7Iw5gfKF#Ptff2## zdcd?$X$5PE$Z?Te#>lzl`4!%8QwZY($>Ur0Gn^(Q2N1CaeAKXCnGDySyv)7gZUW5l zReS?}6gF!&5p+5TP2b3QKL13?cl(q;J zh+M_qvH1$08lagegcr^=N`o5iELY1CW#FM|Qbx)*0P!)DZLOeN0rYd=EH~cV>wXU$ z?^jsZydXfdsDMPOQx-4;xO8Zl;mSgcSA+?VK+POpkAMXMLIXYCiqglA1)o)WRqs+T zTY|O7BD`zFHH@E80@6i3bQKdebXW&sR*3s-fPyIRgFM?Az0QZ$G-gb2z@4VZTBg>F z*eB&l;b>WKwbRA)3|)ED@0$0+8B;n#A3iKOrx0CXhazrH2&Wh&CRGV@fHwScFncbU z{=jB6*Jl<(GM^$3O!RPQXfEQhJ-ye6%NoTZIzJ9CB7te;rz}RmhJ-d}Je(O|eS{sg zWLU|7g|)Lf52Ufv!n03im`@VOr#ExbPy|uqg%~hR*rbnvzeI| zR$*{yDIqbOu+sv$$zQb937%&`*`3fu#(2%RoH zl|F~drC48x1$%Au3n-d2g6a|>R<_m^VNJFv9mfZVr(;~1=}Z79>AY}uGL7a(Yow%P zt`0|av1etYMyL@|zp!W9rAF3jb5SFdR|5-%+WU0)0l-BPb%PeD`8YfpI^Rw2egH|d zte(L5i<;}Mm3Es4u&P`3>%st1oe1xmBpZ%%#^r9f=a9UgMV(G3`qY5XQccALSJc3! z>_{x)AvLfpXd~e(gtgX0nko2Gup$Gr|7iZmxMsUZ`1<-*zcE)RGp9@Mmf+x?f;VA| z?idpEq|8&iAZwwLJV>sETGG9WdihQ&6noxgW1Z}S+7>t6rQLiC;Ri<~Sed{I>N8fNY>yB zeea-mGI(`(_-em9uqkmY86|0YmvCPc1O%W^`7K>JKB-y&?V^o}vthtz(zb z0kMd*&)}G|`Lyv*45QZGYdD-&Q-sJu6)e%KsLNRPsX7ArUnA8XAJWDr0g!3{ZPMB+ zI5cCK#ZkmLk-HoHPC^b8LZo1|BVBl3Yjd(hO~{j9xExLlbE2zq>AyTw+}Nkkjv7}D z5f4R0N>u%wTD?K#Ph%IgScq4PQ^Uq>(#@dJslYx`OW(uAs!)Cm-XCJaq#D!SPn5eLyNVy%TWN&%q*sUN9iu%qV4So0`Eg`txlT((xe#v(f%Q z$E5NW!AzD5>?&>9N1$O6Q)|P4;&EuXL%~?>OC?N;W_r^SjN^x!cVBNe+jobILSrc~NE*-fZLS+2D6BW(6oJMS`cc4ypNW#O) zZrQ8!a!L;*CF+C7wx`YJbRR~vwnzTSHO=ca=7q^tDM~Wdg7H577^T{xmteV0HOBch!DXi@K z{Y-6Ow4E81U0K+a>WTE%%AaMHsaan2KT_q;I{%Q2hc5sfWhVYx( z`@~L-T?|!Zw`=TSq8F@P&~P>YJpRL`TignqMm=W$UL90j_;z+FXiUM*p~L_@6X@`t zQ4SNelH1acS7WrPnHS$-kPH_uN!}!4j0h^dK%`4Nj>-p+Jcw1J+UDdEwU*^_HE{5v zB#A2uM({S@RHYLZHJD-5wKI^>n$g^-;l#!_-TiPP6%N6X#1+yk)39mhS^Cd;f>90HzXoNxb5Lm&5G~5Goi+*ssR_bi zccLA1cxIC{@)(!p$qnI1g~xN$h8$)j9-@9*d`mfr1uc3&+L4h1p2}M4QS^n!Ot+oJ z82nV}GpK{rtijuO4T3^z!(N$;6CsM)+Kr?f^EP$kwsE8Og8fI zh|w3l$E!v=T9b0JtuF3U@=(Wy6)cZa!Y9a?r9FNz99G|3v_FE_85^Meg0C)Sv&&-h z$&+(60`t?(FrPd*N9Sk$2P$}SI?hj@Kqj*%qkLFAiANtHL(!-+!3EZF5QXisXD>^P zw4)&^VF#0=yL2f$PGZzduz~>7I@y7cOsGOi_lE73zM1gzZGcmjeO;BbRfpK7`f%CJ z;NF^E*>d5NTeIQRZqx81#p!`p>|~<@W*c5e8tF38TbhH>xE9~aNik{Sy5z^U(an~< zuXS7-J+z#&~Bx6kTv8?{wGVV2-poF+L9e<(ja4fTa>s7{Y(QHUjiPkEpCei*;3|xWJ#S*fX zL}ZdOQc_1*`@wCLV2WL$Rht=wGmr`0cbDMeY;Qcv(Suo}M0X6&noBzRKq%!k(x>** zFD3W7A;=#=GA z+!y1HqrrGFpIt@3H7CU&D9cIbC>O|AKKazZJX<8ModKs|N_&(Q<__Ou*PuIc6u8^h| z^7MGVU7}Av+A9s(Ec_)L_oPpP6xOx9jl&+I^B!%7=5Y!O@=MQMtz7DhVWW-R5Jew9 zPJKrV3zQ>P3`IOSjz<%lnYZdP0~|Prl2#eEqhn98YOpF!@`6o^7>*(qpfRU|o8c3> zl$&^1H;&}PoA?@IarbFCsnPn|Q|nn@Q;0!^gM+C-=pFIJ2J_sbDB|aNxwSxIOq0P= zO)fHmnG1K*_2{Y|3+vwEEy1GGXa@wnurI0ZmBFo0>!Z9;{W_xPFJO4w1|8pr6IGUG zK0Zyxp0gT-MPNBv*A9S8nJuzYolirsyd*9#*_i3daxswS&N(9%l5jkR?6gMeTRHf`?~ci=H1wf?5A<`G zUI_GgO3V%O7r64L@jdeQ7&hJe<*W*l+qb?*6dqH>TaSRUFO&v+wj-IwFki{VE zryV^MPc%4J%SO$MN?q`?CYR_%kKD07NWOj`XC0omSboQk~9;lD1#ZyUlD0*#lw!ADugg=QGr1-f1OU| z6KS8vqG!{XQ8fTiJ{ykbm|nV^=>?T_)Ox{|N6Dqy9;jTQ^x_cpMe$hn289`Rm|V$R znqRtY;IOeaA=gNNS)!^TkXE6Nbtt;c7f4u&+WB>)0bI5Q@C8@owu(zR|aZ_4elQgSSUV z$K8H^@b=)iyR-WmlT+?OI(JTyF?iA4KYTY(n`1c5+25gHFn!E6qjoTA@G(vKRXhbD zLY)8>3;S0_uil0KzD4hnlY9rGdk~Z7*H5Z>WGdBV*2p!ahaWWYcXi*U0c_a}!sZ#G zBjRV4Zj+@xadGMXu-iR4=^Y;Q*KEv_Awu~mFz5)CgAh6BkjoIbgWw&;Fo@Iq3X`{M zkMEhdYYg+rrMgOiH%OX&po1Sj;DQ=9vyK^AYhM`k2kp>G=ht7cxts&mD;#E3>x+fQ0yH=%`(Q0bnC-4bY{q z(~2n`Fz(DHD*hkQKky;fL@7V;R-&DT)cQWcmyY2;cSJmUgjAgzIh@D_zXkO_o-9-K zOOu{SAGHhs#kobAx-CgS;`->M-ag(IA8bka)Z$wC-q?;;V65#l7_qF@(FBG9wQBMZ zp>NoK2D~ga8)XefV*}w1w^36D<{m`RRCk~Oq439;@{OE_pjd;yWT48K9`&3c74$(N z57|;IpG5JdrNUT?8d8f5KyuEo*MQ=M`p2>zNIpOtF*1Y+g2jD!>JoiK&OC-CO=1z&Er5H2DtM!J=o61c0aW)fXr8w4xht_4ESnLtC)UZVpC|~YCZ0FeDxAZ&NV~{=h9NjVw z_TQlloK)uyx}aAb7qpTE?K0oBc3gDk%|04vd0vv#834S)P6JUILe z@h||;{55mw?j4+Tj}LbCO)sQG-!Mqw4HN=JHU!ZXjKJX!X~1wZjYx!Lpgo*Or(Mo& zcpVpRYRV_QXF#!R98fzoT;2%)UUvs_?o?!SQDTeVS-nI)sIL!c(mhZ}Q z2F(%T2O!#VhILY=Uju+KL?4Cb+w{Ol%yzUuGxobPhBHBp*JVi*V-p!>twaXDtAG*5_X3}it)Cn&K|`Y|0b7zE8LLpk%z z((EG|95D(|RdMNv;9yfs_O>(QP%22ILqvQ;GH!%P7{<|3W>6913l|}AaH5jI$a0Ow zO0~7+#%i$oi|)?DizyvMY6;2A%r#(0a4fa=i1a-r=Am6q)|QsEstHn^NpBOc-ReIO zDf-j1pS7zI%>AXhW`1cK58rHKhnBSbyGGfyhYRnC!V8yJMfu}p<&U+)c)9GWWo2K% z)~qW1+d%<_{109!X-6a^g(V=$gadP>rX$kzKL+3G~^RAOdVzjU^Fwe zOAsVHfY8+FL_g+p;*Y87uqkbRLE)gEaN=D10kA_5 zugeDmy|-x&zS|Rp;0IicEC5}pw9$;Qsuw<@u2%^$9em6sei{9 zXEwf(UJMAiF2j^0B>W|Z_$kR1)Ff*5nVu4|JldHkW}=97u}-x9?YgM|{KWalGsoSQ zro8@W-J|Rj!?f?J>{hhCxvrQbm{ZXU>?*gl)gIc4_@3av!BQ{*S=xf1cPbWU7jbY_ zT9||rr{?*m-NUyBC*kR{Gsm!Uqw&oaZn4-7JDCA(z6VC2uRktq&o8$CT^*D(O>I~w z*9BNI0PZ-w5y*M-J?%&s6K z$ukhNJ%axSeo!m;R8xwHt_h)*ZUu1Yw^ry?4Ghsz9}P4*`iMAbL>a9Xdnbdp^Gv3v z@aTzfkg9b`zNz&WDV{}Yo|@mix=D)fe*EpbS6Pn#fE&$sKekGp>SD0g6W%&>n8EOx zyyI53R2-7&?A0G>%niQ%tW@uziCLmi)5#R-Q^vvwb-MkuM1Btwt62YdMn=VT;`q7L zuaAa=1{XY$aagY>V>POZ#czK1<6iH$yL)nY{3G!A*WbO;q~NbXzk9@Vu$=lFy>{VU zc{jb{gc54W|5yL;AmU{3Y8B;EljfRC#iLZMfA^g>EA<&0r&(ybOoNV;Df_6P5J2YZL_`mK6nA^q+kpBgPL z02IeXLiyGJa5c1Z6+3dSe$wj?h=m8l?FDwiZ+zX2ox~pod8YH$m)ds%$_aY=ym#UKzKpeE0EVn?tiO8Al=LB{TVLJc7iez+(%N+SYIB5X7T_ ztu4r_DElJqZqcx~@OUF+>IE^kO-RKk;`;4W68bbQF4!@IZU>-6KtGmP$&8nfz@e!I zBxZXy5DY#R_V;n<}b`+O~G)xUWZ*at@BfGc+FQ4q()EEQ< z!t7S4MQnn6H%5PIbbXwIKi3A>1zR20S5DWI8`A#ShN=FWcAc_q+qP}nwr$(C`ObYEeYiL;L%3IRf1NpR4tpgX*ITBt8q^H#WIl@0?0bTrO8Jd50mhuoio84<4v`l?3v;X!P z)0g8o+G5)z%OLDGTXtI!pUpy`{*dW3NUe^Lt!6WUEw!u!h$d`hT);dYNj2>EYE|&w zmtT_j!ju>k<83^(soS}rD9xKZB$_t5O{XBet#41@1dufyLR(jmP?pJ=X{+o0rpjbW zo$Ky}S%6iwO<7x$P;t6q7!B@EXy5BJlDc=D)JVmccah3;DcR<1T~UYWe|C|E79wdR z&gh?0%QXdIILpw+>N_|K>Ts?4FcrSlN*pS`MI+Iky!vV+&Y5OtCn{pVsgZ5?SsFA$ z47cefQohLPX7Vl-tP;mQlkBPtv~zP__gFIOeEUeGpGWaaMH_}j7Q%Ty4!G~&B~-_( z@gu5gAZBn~Qw;?QPi4TU=H6EiO>753j>KZw~-QPr@;m&#^;d;kS6tsrgpg}nwRF2ogd?^mv%dGXY&Qx z0)rYM598a##mtjhGF4FI$GchW;l>D%NWQJc)I*dqb!CUlZ!}6qc57v0QELPO+%UL) zB~9(Q>&>Da8h{wvSv*1T6NG8R(+rzTW$F-iVCB&@{D`~0vWFjv+3K8&<}bu>IF%Kc zLT|;$Yx`@wxa4)fWUy|+@wgq){oyJy5PlX1uPYP~P~W+iU-NImA1J%put<11I*rfj zg+!1dN>S)}zcE-VUuu>XB@+P;OUpnLe68uSQGJbn6~yM8!BfJKK>L>ol~OPd0Xj=m z4%6_+|Ml`5-Arf+8j;kT@xl#rwy$<)p`72yAnuzaMB{br>?AQTQS!6Cj@G<}hbU&J zHo#2AA7o4mzkf>q{HAAu($^?`setaS)dy_dST+sCj0A4r0bA{ zNik<(UYv_WFLlzd^6^4^H7JZX#^k-1_gH8;pRqBl*g%eJ}+IUFH_Z(onZi5Zq&YZ@Fz7QkW7Jo~gZz8>@Aw{X^4QgS2a zm5<+|o4B z!1n_E<^46_p-GABs&4rZhxDDuI}mX0rhBA@iQWEno)-JT?ih2H*LusX?K={E@uoLG zx*sSOY~21d)s!dQkV#%&HM@GHIhum3tc*2B zJJo{K(MJ8CHUDv@ef~6*JuKPm7td{a@MAyr(TO6_j<-jw#s`Y(2qkBMr+gPX%?G$j z@z~bu?p6AE&df%ROAn_ccaqap-qeniHPHs3bP` zB$+R=E6*bMY6nvkFAoD2?uF?pRTC#R51L5#a$gn4M$`j>k#kv@≠fzdy~y){59F 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

      U*;Aw`32Zx;Eits#0WA)$op45!!z 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≻lu+CItAZDSv$Kb|%%jmB);sKu|88 zUkQYDC=D&KE1SiHX%s)|aa~3# zT4X|Ok!c%pNNq`x*)sfbLZmQ*e$xC{@{=LJW!P||z?6}?)hzzD3a34TyiY}219^PD zCJkeFv(Rj5(LiCXW?nrP*FW)64zr2tHwd&+u|$aM=kk%xd~!qhUV)}1in7|O z9F01|xtPj}wQIfUsTT+I3V;@p!=Sa~v|@N{e%q)2NMsVlN)hv zIP}%e<>U~{+>`*{%RNIKr#=AwM7b4rNr& zXPtHtq0>Y2xV~4gn@MRTeWcF^TC|d|-QCw6FEZ9uWJtgFgv#w1-~^5c@%Z(GMJy$J zpablZqY#NE-y2c7E^X_sB;KNg{j_l8%OF`s= zCv(qRh#EoQwh^2+0ylq9N({5G)dt~dghS7cuuCrcwoXvJ&jY#g5Gtr`wo>nbZAad# zs*zB1Cv%~;aKUIYRW+PS1Q4{v$hv+M0bpoC*5aFZ-d&s8=*9Ji3dbv_on)@Zz~Rr1 z_wd%k<={Hpmk*@+>r-E6-Nfax${B#S4>Ar89F8_Z^0>B%OkF!XuQ3{w#mW4`L%Aa$ z-1u^!l<46Z@5_`=YhMC4|2jj9VLD;_7X05S(C&S$FPDF)k(Yn`BhmkF3e?%m#nsWp z%-O}+)yl=}zq6o@p8rD|QCD_8{6`yktzV}=42+A{y{o-A9#{uqGqJVakk0HvFlmrt zGof2cN}lSws|yfHviX?jLn>VH`|#bX8$MB7>$#{~tLjLbL2Y4tQRdt&b%!prH{f}` zw>+3SGw^#hs(Kcs59G{7mI&^Iz+|77Chelsiq+Mopf$5CU+q!v3~Z__;6zaam3ZBe z=)|YfbYpB-*_nO2uel~YpZ!|v5l_giTh_3X3A!)5CTnThqP8&uw=2(A3x)morTv)z zrMmW4iyg6HLB5n~LJ0*}+WW|IVQ=nk9D9C?v^utq?ApsjIgUP&9ys0RORO*$8EVP0 znqzUSf<=iGLpVp%uF5^7VZV%FMZvAuza;Qv7LR*Ts8BtASwGY8n>PJt1S}8%hPLOz zy{Yk}QEP1-GBy#xtu!^4#>Uxcn;j-N!=GWFj4pBV1jR-5mJGm?jZ5Ym#r>MfuAtrw zxs*H5$=Hy_#zrL+Y)iA9%0@VDQeGRxHs%7+NRbXituMAp_mXl2` zqs(%g2dCIvP-*n~!o*472tX%`VB@McfG4lp8UcYur%TG+K>` z2!M=fgm=#!Ein#M4bo*IjbMy1{Gd|{mAp$yM+$tVVlQ_)qp#20cH|Rn4fC)wby*G#g0{=dRX(p#(Vk6(P2&Wh(I`&Lt z&M2`wz(J?!*e68p5zK}%*CNDFj11y&7(xW$9RO~{Ll5G9_DE`=p+@7BPbOr0$J-Rl z1tb%nK4Ky4voq89MGKkH>EL^_>o@GcPi&rJ45&#s+s44pABH+7q2xLb1(`MMGoF;7 z$U~a#O}B!uJ`9SxQ_T_wq(+?9C?>lFS9iSzG7|Z*%K;a(6JF=I6xtAc zOFYxj+S)o`-K6RvxCu>NM7ySgMeSw!JmXF`K{r1$WvT9lyQ$mm{vKY2MVN3rHx&Z@ z45Y!sQvk2fq2`W;cQP^VyTh!6Jp;Y)nhn$aiGVFzTx@mGvGLHXv+Sg}HWDa4GyNCx zJ2|o0-qJK;i5%SF5SDjlpmYW!gKOL#WzOg(AMY}(IB@_QK3c^I+U@shOH3n}tgB0( zFFuB*{VfBcl|PBVgSAf!+k8f!;L$8@NhhLGa*k}HssE!XuZ8$sM?LkM?A>kyJomlB zdfW}8wKw;}R_U$THSlMS+H__OKytvyiq{J=&Z}gZ)x6t%cg+inpT&90(fMEPUgysJ zTmL|x-=D!y+gLA7AXAyW>VJB<>AG1$UnWX?3d9xIbR? zs;d8>v;=?GfVIy zZl+24tUP? zo{$82YHY=8 zH_b!u+penSGt}`Lpfvx$^z26-1bB(H!}9DOg4E!9Fulz_MwD@0gk@-zROQ! z*cr=u1CC$6j-X~Vv08J<%Dr={3^^$C_PuCP{`i#HXC4Hc3mvf&?LyKtV;mqH52;1{ z)f(WEN2WuqrRm$0k*=d~r9>kP@U5w24w7z(Y%*SqQ3t5J4+7 zC8}2ii2&5Bh9p77&Sz9UR;2j6PEMdV95C%1?y(_M%5TX(P&$bjr*+1(qeYRiLQJPj zR!FHIMFpQvhd?crvGH&U#i^yc!Opc*uudz%KSYxA%W{;&nm+6gB35pe;7oAHiCPjNGf!3 zC>?9KYA$)7+t6WbL|c0pi+W$H(yaiQ;jhrUh@fFZuxj*Tq&}fUOFC0ci$wGEm3wU$ zh)gD)9FUs(7?z%CxS7MWys`M%SO~jioM+NiY#n2haG_@--`p_Lxk-WxU3wFr)F{*$ zBRNP;z)h$j`Z`Y`#UO|wN1|FA%tqyf1Z|7uyL}Gv{0@S&-Xv_n5BXOPc&Y4R@)h(N z`73={GJPBM7Gl1H1#f#We&}s=_=PbL{bWM`(+>|FwdTLA@Xj1@9cc7xK60KfSChwt zH@-sdOIcX@cdsA@dE}*G;^x>v6!9s=V&_vsq(0y!wT5qT{v8=|#2Hl8*W-J3VzDX-NlieZpGJZRM zO&%OKegpoiN=&WGY_-7v0OT+N0Py_RDq-PjW@huB!_T4Crv3UTqW`jfovcHGi#T&# zDBofzzC~m+pVjj7x%|Kb>|ElFWH!VQl`JInUPCD znA>*d+^@F4BiQo8T zj11~wb?q;!a7^+U$oFhU3aijZHcUGxKCaqs5coM6KX!YEp9jq8S87!;TJh+RS|KoR zU$PB$dwyH*fIu&EmaCpPHOq=j65(+NpkZ>y@49D?R|41sF+8d11Zv7N;Cm24Yg+9r z5d`+8UVCWcmE|x9WSb=7fKi;00aOV9okP=H3jxJ2!EQRF+IS*xw>9tu;tOR&t}I1* z9&mP3(8|RHNovqjD^RiR<5h_+1vVT;NXGplpgA6W)1#57ATUJ}13Kug6^|1Hh6;%R zr;Bllf$yz@HJ(-)5IAT9KmdxbG6Y&lpcHA1`_1^{IU5;`sAI^~P7V-6GsFb3T6 z9+!aX@L8b!q{At%T~IIhcQLz87&#|nwzw+;uK@ZhXRU_WQBG#WmPSW1cBo<08Z@-Q z@{|l$83O0?s!KRH6K3hxX>a0e_sU<+XJ9?4CwZ8zFsHb&vIoWwU$HE(4M&%m)pvw? zvbVT|jmyGV^Zbp`_ALMcN*I6e_BCTZ7t4~XXa~xAP0zF|0IDy)Py)|hJ5&)jEIJ!x zc&v-%N|iTeAP~r=>K$oc7y;u6l69GtVD6#9RG0o90U9+(l5Nz!#6rR8w8C`w0R_%l zAaEuPY3XR!YtfshtB>y?H8@l z&CW~OS{q_tZ6KzLP%?xu*&m_*E56p+}unhn3WvwPBCJ}%BeBpjl zy;jWtb^5Ox5qhJV_Y+RP2PCGETxBs|hyIqZl5Xu+Q%CC!O zFBTV58N$5;k$26%)4MZ=uP^2qp)NW^p`gy&cwPvS!(DXoMbwXxJYqoQ!VJx=?Z5gB zVvRYs40L6hCPvBDLmqXy!@dMU%#dVw0?AzGxcA20*@AaH<9G40L;%l!XBSn6=#uFO zk9Hg-@MMM;wCZa&o zvV?H8P8`yRTML1JZ$Uf0;xiO!L=pI#0s*!Nv|L1bPqIaN8}N-MK8@6mwq6iRked)A zKuHlxVbhS3k4Jz?;ZSNycq@^depuHtmKW6ktnvF^F7JMikDNfSys9!OkLwq!tAvcrJX7|%ylhoyzl0Sd;ryVf$}%z5=4}CC ztXfx~5#nD(axG|9gAY1J%EZ@D;pGBRGk#j+sWLnvCJ-aQ9MUg0JA0YH%khHT8<>FD z&d3f}*_9l)iM=T63Db6eS0qFw3=_kY5)A1V354&6&aa5-CzXvy^hx>t1bzK7l7n|rM^)A>O9C;#GK z*Q_WW<@Q`WYJp-Eta7;KA8QKM;mc`JxXHGSx0e;DDyc)@S?sJ8TBbhL3p@JvT-7P7 z#-G&qnrW6Jn2hTncz}2<8ogfaGMDv~s@!ZQsj1U!`}T+I2wHol-R_#Xa*;ex?evvEl~ha@iO(GTJNG%ogoIT)#gsJ|;BXG-;? zy4BOr!0+pG*93)}Ma+wOrKFtop@*n|rNH&qXSlqBDW9r-FG@?URW);f=Brv1xo~7e zIz?D=WsGvpgD8(x8*6j{E79&^<(>VU)poc8RFpUXtJ8kQ8tNftFT>&@7ut<+lL^^oq4(MD9lab)+e-0 zidY<|;K2C4ddZcxAx*K5-zXm)M|;EjNods`a{&(yoyKAf(a^CdxxA3 zebS2^TNHC+Fv2ceEFi`n+h4Xqh|7O1)bvpV}C}nMC+cyVYY}43Q zOni!s<}Yxr4s;GH4oPNkg`9;dFLY6Z-qWC98IpYXSp;p%VbT?tew3dvk`N&)5W+>F z^YuvD?GiM8e%zeCy-Q^nl#lE0xphO7v9cA- zwyGRyS*qi;N95f8juZ19qR(~(46AeMaM*IcWdk@5qAM2R${0@egRDP>5@)$YB5a)qFIuRtlrwPYf6db!X8)R$zc$1w?=e z@k9zXyc)e{r$*~tE-{s zs8FhXAD4lCr-@_`Kx~e-RFS@tYJZ3ztb{FPHtmeYEH0cg#R}9^KpG#oa`YQj+Gspo zqWtO*U_0Iu7P~6BKkW)djCZGUzh@TfbX@JQrWq`USW(?%^9E#nyn4~Wct)krXq4(j zj{%+%AO$c7>dojf;bu%uihfs-K9(5`-s`ZmYTl2XOi%^K`K}1Z=^ZRQjrH@BB`hY+ zVe-(km!Mc7EXF@hSjf&{vgk1S$JW062#_v7Hiv)V%LK%mt@OKNZEcmKg(CGi2>g$$ z*JwpYuxN~5UPJ@2NVaSDS;LKW^F>Krt4y17!HV^8N}bt^3g(Kf8Ztq?*(tcA5G9l# zBXw^7p!@B>=7Vrbj4aOZ3X_Nr@VQSVs0TEBbnzb1yuB~JzEU-b;P?ixdt)K}1m8ru zX}DerYMb0FT;=6;$B4JB_RB`xWiOLEOLK#9?PpV49IX0e1Y(;u6?&xW0+Pf*yL0p4Pz)MQLU9Z zWvQl0S*o8M(+m}?k)VE2>>RZDjYW}bof1uXB=5?iNviIrVSUqWBd`=Ldz(?`P^~SM z2q~xn4aem0oSCaNy&7Z-sjo`G=1s#K0vN|s9~1csL*uD?CfTZTesCgkTpXCngUpq% zj^eg5^af6U@AXUArj+UZ)mBv*>$V_X6c$#VXDd_5ByHm)+d_kp0y`O=g`8H;+??7G ztyh()SP+R+e7{&^Y@An1p{JSwv_j*;fbP+PryU9|JdPV{7JXCZSmGX}qM!W#4a z;))C6vaGlbd3auTGCScY+5t}_h=WgF>}oQxr5`&8_#>$m*-vIJmN_dYY=Wb&i(V)$ zADd1VB!eqC)4-igOFpbWma}qyTog&riOnF-f=(xr^^OQ31(^>whup2wJCDGz zw%4mZqDVIX!5A?t+LH$O8;G?>Jgj%I&u-?3>xT2F#9ah|kAdZQK+Ra-nH}gZVZplL z$bpNB`& z)>f;$!wP=5h@=&Jx^{40I$tg9mS&jfe)ekGmEC8wuEUBSa#QabenFba5N4J^RsC~! z)|F3FU!F-~^BLGjKS;iEL@rjZaSpEn{bHMEo52Vt%L(yO>HcmHHYEW z(Y|46Jn|b?5<^4Yw7z&!jvIzmrl6p0h(?DQ9v`(DfK_Sf53O7Ftx{dWi)=6oUVOupxx9Yt6vQRRMqsp z=QPAM_F1X4vwd`qtVBx6j#g>R%J}b-(D2p~T62qykooUh?g3p5zx`w31;EJ_@TE>y zx0CSrctklJYlbUC-gBDbyxOkrXEer4K0Ez{4fi+BSh}*|k$I;c99XZ1X#8hJHXPtq z99;xF8q-K|VCLQ#GSkf##!uyJT^+%wjU0zFrPbdf&RM@r!w%&c`7?LPfoJ>X+$_{f zz)DF=yZz@>*^<(L;}ovJ5&5s5oXeN@6Pi6BpF9&&>fyc(roGDY-jZ#ZSVWbCV43jWs1zDR)cuE{|#Q)Eh|v&6#Bd<$OS_v5p#x5N_$JH_wiA4xJ`CradhG4@#hix z@s6#W4Btb0*;H`1Uw_ZF?!Xz9F&w|k|KH59UwcjEEI-S^Uw8ljeE+RE_K)2lt%KqJ zp=!HHQ`dfP6v_8keetlncU+hcUoCS^3J$|4(qM@#dCFHXZZiONU+l{5Cp+TnU9Bk= zaAd_qoE;vpy3hf1AwY8CV0^@tWSofEDW)DEAk03_yhUGR>%M;3&-ZL0fen}{JS)n?B{4BLJNnwcx z0zLm4F$_$v-(Vogm4X!7Ao(Vpp_kq1Q1W90fjsKP8iT&?*b!l#OfU-tDVe>^`r%o7 zOc2ng?s4)MFxZufgha;cgwfDj{v%X`6E_6e8S_m>*pY%jh@pR_1qYn8Wwrp{bN3f% z*M3}HAFp0>oI#^t)HG^0g23)H{i~3KXA0o+0&8?}i|iWaQE(wiU=z6}l2_siVhvK5 z5YS4zA$=<(^j|xm_%2rBmZvC)&#f^PI3ddV(LI z-#dt5edToroLU=(>r!Ln+u49Bd7T9Z76$UqTN?v8F)RWw8Jcu~;iIn8f)Z=X@rRKd z1K8cI+IROC#U9p?lJ`F{aI)?~M`3AIxmp=#&DKxm#+zZMlet=PfGFF&E^o%0o$O$| z4}h0Jx0@NQI~%9_w}!1D#=J5xSw<`H=ytFVDm}Q^CUTWN*W#Rz9fh_IMyHs zGO^u}*NN!B!Sk2mwBfEX{N{hcg)mN@-yn=HSQ>&Q&t`1)bA806vRAA2e_c(o8klGT zi*^{VY)^IX`h?aUQtX+<PrG^{bwyeH;G!l%N*;$6Y$v_$F+{gQLx7}eX}R2NQ`D1ov;r$u|0=#6&o=_)UMdJuGcv|F>F=P>>pR(es43duwBZnXr@eT}#jX zR`zfYg?1-TvXHDUmt<>wSxverH8$M$-dy?+q$$LTBm6C(N+Ck8Bv>gZRP;r-1oCmx z#JaSxYFX)Bs^S6C&LEjjbj4_~^f#@QV$v%|tDTlYUH*b?Sz07^a3m+-&d0@=v{(1`(#{@^y3?xvnl3FkpadPY02vRS*L-xC9)_WbX)Qf^YtjToW@}M`gYN(kNWkywD)<;gajc;~iS}5A{gB%48Qa1;I}BWL^j*~E%vi$IPh@P<2=)dH~}2V1?)H&JbKO2 z?Lj3a{Lj3EJ+CIvAF1gdPvWJ2<`~36R-!5FPG4v2f>J%NNoQzI)iA?Y;Fhs-CFs*Y zuK9zDXe}_Cn6XXu7AGh($${@hF&IU?5{u7ztS2R}bnOR!Vt_gI+}e5l<5Jw(bq^8b zSTC-e_h*nN&HbJZ*2Bs!hwLswAr$WHD&(M@y-MJpcfgz&)T8<_Qs*C$rOWfI`zZ*V zatd>CDsxrFeTi%Jau3p&FRFh`i^m*M$YKoaPhMERGYKpMhO3 zGv~%=AK6y6H5^6<74W&aV?mD^^@xvdgX;0Srm|Aymr*q1SJL!J4Ye1b;HYcbSh6VA z9o>6fSW`0xOv$MvRV)2xD~dz*bULeeP^O%h?=iG_=iCSXUM$xz7J; zQ)!gtkyn8!To7A5EYp^Lua?_PCqBVM)z@%fN~lgQ_?f z!bw==bVLh9)IrBXm39NPmi+S&;O+r0(xB%DD9xAiaTUoP^5Erf6HUkV6Xr{C64v?! zCY$yc;-zG$`v_B{m|9Mo@~qGU&2xs$KtMbA62fKD%JJ*9jd zvH13sI>|_Vfp?6&nq#Nnw*SE7&%|Cq!JD_c?a%Y?J5 zIyd(rVsdy1_wi;S^7D2wg&WPdx?W$wi#iL`P~rPHv%oF2PFgzs1d9Gw4+S5XlP0v& zEup+iKitZm#X`9TK7)L9J@>iNFUsVV#k9zlFai@GJ@t&g@pdk!bYmmOyx)qlq+G*v zH+!On0X2Z{is|e9z_4HzM}SosjUy;(R8>Q?^8Sa2tB%|ZF3)y$aL3a&TunC17%p+n z?}r7^uy;G&$E8o`>x|Ub01v_EPi#Gp@c;TUg)!YF*!kJ(yQ2aCi2m1uiG`EBJFUGP zt(l>vjjPjtuJ4L9e&!Piw4eE8LzWuIEHZhuMK&57n5-`CXFeGdDNH=v3Gx_eO_(4{ z{(SVdTLrsMl(To&l8UJ~+i;%wqab+0?9I@CFmZQXNd`21uA$lS^yzZT$%YsCB=|iXoEx7i*e>R@ z?s;IOFq}Q#jnDe;ceG8;X$k5p&8tG*#?BfRM;_X>jfRZz(Fa*u9D-RG>>Hj8?`E}` z+_$vzY4h$&nGT32-u^v#^mCgyp36V zyI@g>F}+LQ;xbqEy6ei***({A$6TA4Ga{Sj5o{Yi=2t6jq`roV#<_XeYwF!twe!8besriI)xWg<7SxMsWZTsyUQICjMFO5xZH8xI z1YcSava2q$sQu|7;(`;)L#?BGvTR3$Rdw&_XPt<^Ia21KBxi>`R5djj^l(noBf$33UCHxtZw zA(tSlO#X752Oq)&O9gz*#tqHsI~D8JnU2hcMudy@>h)6Ivr${OY6nLlLpBK2M$||$ceKjo9m5P)gkdF2GrrkSDdLJY z0g=AanJ4RZ2rPyK0RU{Sg{@YGu!;e19_f)9wQLXAQO>?bD4ySd#SH<;jcNgDeNydA z&08a}<1+xtFwN;mU#A>8_@+iSeX*qZ79aDPw&6R=`Sj=~vura| z!KwvaTUxAxvtS&q0stv~^Ny`d~Uz){h(JFWu`n z-iza@8l1Y-FUyCBj?ufWLXrB5zlo48tzPZii!)H^NhI^8o3zHN72lqs4HMeU!Bq2g z9*8x&Xf0Sd^&9}Ox`i*)`n#%% zeUc*Y{*GNLpTX5wyPdV|svkal?N68Y*_3o=!``ioaT;QPtDspp=rYrvY08j>aG&q& z+`f}6oDNo6@HOVig%{8KOZ$ASE$A>iIz3FPQGptt*}gB((f}OZC0#W=E$K}hWD*{E& zD+3@E61cG5z-`|+d1o*cdMucCuU_w%vTyNjm7jRr!5ZICGn}i&s))(PiJT5tlm4{O?qjc4b_*xqoen5x)@Iq zsgp#z%yRRSv(JptsjHMrrOH$7d+I@{mQ=JaHk2%t%FI1yF@y&dlirOJxBKLB+_vc-LP2;*v*6jKDm6Mql=w&PRguRswk3oaqXKc;O zIDYj)3YU*ERB)&Yn3`INR&hxTz~Cf?vWx)jYw%Jr*RW^v=$a`usZk!IPFu>gCNY;= zI9HT&!M}L$Bq56Sx%ym(1u^7?^yT105$f_9C?=rG;0bv$M_Ho8gcHS#K89yJ?kniY z?i0jd91X@gybM;ieE~<#BrAv@f)b9ck7)qGg9$Ci7f0YEb+hNf75ncaFpR<*fniQ) zV;Y;|a4bFa$SXO>wh%pty`1Zf)&1DrV?TDc%|Gn!s^UoO;rXn%%>=Rq2PBc8m7e^V z&N^!QAqN1sTIoHx7e-NHcOJh}x_yx6Ziv-zWA{_3fHH4ZG@EHJ?v(r+Be!#gI|3q! zI9#wOvi@WYVRXRKjhntx1L9lDC|`}DeDCwE-jOf=ieLiI1%(YJcL^lfngWgC1&vu* z1emIeM2PDm@`894I3nr|7NoSv*;rj`JPHIjZien(V)IfIpBf>%E=Uu-{GyZB`3M>9 z9K4NM;C$~JM{yAS;9+LGHY_;p_>hy~G&QPIrkq57j)z9p4UmkqM&Q1Z=5*OXfX6I5&FomsKNZ25}vlpoCUvYo4@sY5O$2*=r9h?TzToh<)O*Qv;H(LsQF1yn|>_Hw?$hAd>i5 z;p!?#QFTtc%|xRWU7qD=K1j3d#8UR`;HK?>8ZxA>#H{Rr;2}y@_jLE#C=yV#n{_wU zg?4QB(6=@*(ohxAY*AwSS)=f~Q`DRk&{3%lVZ$BKac9wRQE|!KimR_bN|4GlN$vW?eA#|OqKdd!@7HM>jQ68qi z3&j|g3lJsM?jw^H_T^F$B2JC!9WNh0N??2>9w6YGSbDuZo-gzAX8X5U$oM+eOhBvh z&3z5=sTI3lRWx@Se&L`Z~NoUH&lHBCq(;3~ z;Z<6t%6WNyCVA{p7oRyK3|K-@Zm!EWTSDbLB^Q>1A+ahg9{ug-B|fdt#9Og6;P*fI83Ele&n8Q^^2XJC4fH?4pwhA(ljU0Gp`27#P@u#g^2i)yXjGRznC+8p zQJgssuoC#Ta=x~)6XiC2Gw~>u z3J!H?N*hwl=6s0uLOvXV{xZZKdZdau0;MqX2VQ3~zwY8j@~72FAVnD^MIY(_!M)Vs zmne}4CmAy6%bIZDA`wu;C>cy13YDy6hzX;=6cURrHzGJP43zSxIcILQMJzMHa;~|e z+#?nj-nL=flv!yVS+hI|~ zg1&heaqjEWDM!YPCOFKFvj+qL8G1$F7*hg4s+kobAm;DJcKZ|g;u~tqFh8jOqD-># zEpMujYk(RJiX4tJW|dvUq+1+RqR8SHMNZV67%1Ua=$XPXrxs~Ih0On`>kuHoY}5Ph zkt$J|3!{uUQejF}=n!DEErfgXu*>7fBu+?v;Uy+=iwoRS%VH2W^mhNj%QU$=Te|uw{k&lU2LU(ziGU^{LMN+p#$+9Wj9?KAw!10|Gh(kzeBaN!9i=kbmhakW&d`2D)G<2(|mo z09!WI6lyPgjfJg)evzpm-Z%bO?mFVTic-GS$N7ube#cXURw)u0JlCw3WXR94W z51k&@EXNWiX9+O6pt|A>HtMCJ#?PQ}N2(vTsZLf6X9w>5;jp~nC#_bX`0`oAyt}BT zL|p$gf*B+Giug|Zc%U2Yy!Kolqglujdq?Shg2(Ejd$-Y@TgGDqsVOq6It4x>pVU>& z-JS;*3t%5})nZ*Q-liN!Ou5|+0YqQ_x_l^m`3js?|8MmYYj3lF&SmTFpJ40hh8Df+8*7uU ztGaJ+FzA&x;A{JTweD6QCnEm-U^&V^_T7IC9sZ|k{_Cu*+Gn@V_D?G3G+&Z%B|10i zLNd)FD}bhr1a-MIlxB_%IueG2E3j_Ge;ZS4)k7JDmjyihD8YWqn;B=uETQ#S+CGjP zzQ_OVK^#Q-IIarJ?)=n*Ex6T|Fa-SMG4CCHbCxeO#BOrOyMf<(pGKuQ@IJ3k17oAD z#&u;CTl*26qqQ5G$b^K=Uk75kWwH%22W{717Mm=HcYg7qSQz{|sjJl4 z=ioBFfn6nEf{1X9whrpb6$Gi%p0MifwXoO+5xNlIFbHxt#tz`$Qd7)sXfQMFCEfkr zVOZ6rarMhvSYe8Qy6V()f@si9v7o>@_9C}~%4z*R;eue2b*qrwI+Plyn&TlM9P*Cr z>OnKost}S4?sbC`?u2N^+y?%(AjwEjfIeMg9D9a9h{sXPn1D0Ml`@{)F#wDN^eBNQ zK2xZGB%l{eNr$C&CJ2~K^ga;Ipa5H)CQbqYL`4H~^AC|N>G1iqB% zl4$p=(xsz-_dwo8Z9r{N4HxEZA<8z+WD)~aIvLC+SToFGr$K8e&}kG&kKIzUA|#oj zASCQGyRBmS7*SC}bU*E}?+t^_7$GcrBhrf=-`iIPiAhSetd8Q+CYLHVGk!K`VZy4o*Ou>~7z0p;sed#pv7&sJ=#=|6D zgWJ|3U>=f@xZXz7SvgT*yL_GK-|L)Ee?hwgIDGd8{dwX)30_zD`npY6+xc^3{1}_< zW;h70L=n>9Z(M-{>}G|F8aRv}4E!H&g5)0^`Usu- z#I53$1AZ!iEY~z+=~q0w&RuI9uLN8{`{-HLZ+79jx#n5Ufyt(re-U~6mg}8}_Q+%I z0o9P()<6_Y_82hx6V~5-0Vb&EHeGT|o~V=KU<=~ox3PXji3oTY)(l)vJWlsLQ25>1 zGBGagXE343`xO6}+y1wcglx2$@x34UDEN^N?*F@?>z{`RE}jnmbIxMY z|HmKy0`sZL+W%8F)M4hOl_;JHN{O&R^8Odi_eiNg!bNBm9VS68;qPm1VSah>w6B1V z6DHj4c|GO8lPPfKb{*{N2YEA*PT$kN(RLgQIM=d2X98r?04S*lKkvcZ`77>;l0??r z7vo}qPh(kl!M*kw%m#kzGJI(;hkTuVfV*Ro}>Q=*|1F)-#{|W7NJk&|M9t3E4_9-|S=T3XlVb`b!*a9jT zXOU@Bl2P|;EyaC|G-&0hL(8m^jJ2+mCF&Q3tF6&%G9m( zCu5PQ%9$*`+*Fkcu81C)YARFX&L#$jf&Ru@&q4t@?fCZ(%=fC`@K2a8g;<$winBP{ zikZ-}Tyn`WwIEW0NghH%l?U}lHaMb;oKkTNQNOE(e`F(ub`^(J@2iDdqo^^>M{;8h zNmV`-t$hjS$TU-Q9X0)#=VWjl_Mvy9cE@h^*hB70FHQPAmP`)(I9dH%fc@*}ZWF(o{^poLBzN zz0Ra(q7#<_(rmE82UIjU3N8X8ryEE~RiPUdmQ(cMFJHT35;gQe7!5c2i0@mTr(mR! zr^u(`=)(8?xfAmBmMmVl(RKBOz4K1)^>z=q;c&?hydIrwP`UTzU0?HdYb`#%>}b2) zwclcGrJ91`HSSXZ*1vfD=kG_1XW3rf*1?X8I49}wfAOt^`Jp-_?8*>@@qRYr>c@)Yv+xR*ycX)I z@^~-moQkU&OY^CvKhKqc@EuBu-CW}bjR^WW7cv(2Jmz<_aeDY!zdL}ttLuyZ`&pBn z=lC=m8~^|mI{*OJ|C5INhlCtzpF8i3B7RTnGZNyXxtVG>cch|hxk`bps-c3(A-QF* zQAwc%S8)>}#@5cXIek63Jjdt}^u}+fUG1&i1(}tU;`jJXjb5^yi%yKJ^mIvU9Pf|x z)HhJH!*VbS*Qi>zWa5EL_AB<$(0TaGn7`nJ)9~GkBE7R$495SQ%`i73Wxo<4&rv;b z@V4Cwv-_FcQ|Lj&^1h7WMjO5HYmrKrB2Im@UAIXH8{7TV7L7pjOTNU=?w@S^?h8Md zmfb-I=MqHVec7eGFK{^8Ckl*?K$35dV*T*!8O}49<2js+Hp`|}BQj)^*V)0a>|mec zg`;#O$YGH3iMM9BfJOsgEK=Oy%&w{f<@O3Zr}x-cn})E_n3W!fkl@w^bjGBYATU0b z?Ia*2J*2r)gT^DXvub2pAr4B+pxp==>Bf%Gxiw+H5CQrr(&&e6ldnkhIHBXHR|P=4 z$%#*d{Sc8D6OyEh0=4-Zwd2?W4~f8lH@`_CRtZQIO>rP=0%phtj1LfE3kNI`enXh! z@f5hBFk!4az}tgbdWC4kKtz?Yfy^iAJ)CZ{WcGGB(>YD++qqxC(*5OII3rhWIBU=~ z_p-(`GmY!UhxGtEVfI!FFCQLfnk$o?XiA*fZa1*U6?-~hZT8`7gV{VKhQ>@k42*oz z2bRX?A~Ud*!Fd5o=IiWH!kE_=MhqSaGYP#Am^m#`SjDbhKS$ZYP`SnF^H+W{@Kk3Z zt+a%B@KR13&65`UJk9ut40zLMKav%16-@Z`tz;AX-{FCg&2`7cxR~fhz2pKpQQvHb7Ovp?gI&jE*m9=bQ zQ!G9?13Z|fe$VWT!0@o&Wk8}A@8-rZTf!si3F^QA$##l0p znMTJT$t++ZgLTNUI5FU@QJqp#4r>!#vs|Vwe@mioE54mRHdG%8-!A9kPqnHibN+`Q zRFF}xe$n~vp>6Q7{iGSVn|&1jrmM5iNPQ6bxM=;px`FjQWF0KJ}AQWrQgdy}^1|pvD@zYb)nW;1xfZ8Bj+Ed~YNIF`J~{m2gUH!Q$c4>|hj; z3-5XsJu1>}hL{2*Xj7#SmpQ8i^U#5uUX2hD%_}F;DzX582z=k0hA|L$K~F_MsFAKV zLlazqN4cweCp+lK8TAP(NJJ>1ftoi8Rh54t5U3cMJTCa|%(F!NP50pXA8f|E>l64H zN^jdd2Xn2g hB5ivx*0Ui>SI19`{lPU-_$Qb#^ew`F%;B5&$0VL*^oOBC|h)6@G zpanbP-Ma(LqX08OHxBoIVoqIy1tO)<+j+>eMJL5Fu_bfOTqK?ot;8zyl?%YFH^MtWXi@wkSV$i1f1#~*FgD@!e z+v)oPv5}O&bV}SrJ5SP`F3i1w-0af(K@?3f0CwQ!e>w340{#!u&M8U~Fw54Jwr$&} zv~AnA?W{B_ZQHhO+qP}q?4CP!O;5kftos(R;{C)q```Q9Z5LZGDqd@Bz=km%-`bcV z;UrPH7QcuDp8}}qfBRT{g%fVG_$#GT(u(3^}UWsu4o6xZD*>aKh>7Aef zTgAD@hxsx~sOb%_xa2d3H=;ortr*3x0tzx;_-{<78i-2qSqfa_EH;BV7E(Eu z2F%2A73IGYgu{+zK}{qTCG~I&#bfpuq^W)}F9-@j6G^G5uqP*zaqeSidklE>8kAbpfM}Nd_1*NB5|>u#?vm zChZ`C0`LUtVNxxHPhVJ`B6Ij=#s(!sIQ%ciR0ZoQ*wUrR;1YT;B3a!bvaa$USxr~L z5Vs{0`rB7eZh4s2O+2Q?W97uAqLbh7%Cyo{!XLD)+sF*UN{t36Z&t&AzfgtJ`6fi} zHfdKT3v|}vGxY|iduyA+8Kh>|dl%r2XP-)$h4Gga2cVE!)0xiG=bB>QqaTYZc3q(~ z^yjyuGkQMsDUarxbPO&jDs~wjnjE~6b`2sAVd$E0mG>)QWa*$)@Te2kHnlHtKmmEI zPwSyq{=RXAYhoIIGwT-NQ(TF58-v$wfED=+FsMIkWLofZPNTa(k(< zLn@my699LV)r3I zG(wZp(ZHUvTg;2x9)Dnnvkxxk!2_r2pCWhgLq*E1DYn{D<&Qi=Upf?I#cy(y50Qa| z2$*LbDrK@*8TK$GftvVNHC|3Jan4jM9#P%;NTzugXv;PoT$$m=gso;&Tm-MxJ9s(Dqm+yCXOklB9v_HZVPH*?OxW7`*{ZYX8fH5 z3TzJ4pg8t0eXg8d@!`Iwuj^UlDe2nlI5sZB z7B3XpyUH52OjS0WTB%XK_2-H9ho57p7iB2n_w$d?s*-evL-}9F8@f$}cL|#i}st!?Jbdp=e>s@Mg*T-F#h0XApBf zCh0lvc~Z2j;Z2X1LC*9_Te6oMdG~AW`3~DLOOdbIb6pVyjA*OcbN9%C_s!a!+*p0K z^)D>c;}&mJ?`}%#P+*IEa|agsJw4*5sP?kpR&(o?j0+{M9-Dj86#4glXX``U1=1a& zRDOzEC<1WklpSNiREet5SMQ>M%h+a|az zG;S-H?QSh-UsBf)8x9SWo$Z?^!USEfuss52rC`33? zV3m4XtFcNiIANoVHT@_RMiP8r4!0e`#Bsj?gJy)(8938W+Z~-Q=upp1O)&Dx;mHqkFnznE(p}<)l z3qwT?LwSmF+^z{TIvdL+jSVxAs~ASuaWU5A6x9p0mzc~)jMMHT1@8YyrnLz!62pV5 zjGrj_1E(_Ruw!60pe5ko-OVND%BeXke*Tl!xS9OBG1p6kE)5r{Ci{BbxUf)iwzjzg zZGQE07%2Z1*$Y>7PZxgS3+P{!@mT=SdB>mkMD?HdME3uWv()UrK=`C>|4FI(hp<&= z7oS%w+@{9&4?&!;l{m5D*G!C-L?^fH?6rHw+O> zH;MmDTZT}cSFKrFosSm_w)eR^g+4S;bY7-ATt@YU013tb$XK#b(AG<@Ozv2>)=Hfh zg!R0mLz&LFHCI<`_B(e9o{4H`T;UEJZz!$h43Xb|+U@xv`w zeu&y+37W>PuZ6!uzGK?7WO0^lJ|{VbK)SW3N=S3yrMHVg^tlz?X{Lq-iZ}v;48B@b z9T-`dr4@(CrR7ogTA3tZqmZhm=}!^ z*lQ3oV!=S9Cm)9iD7X{BtYChnFZgmHJ2Y%Vpv>C)jXA26<}SvbM7r;^uN73CWD?8B zNINGsTOn7k1-18vSh~*~$4b}=40b?bPsJ$cfmwKZ?|?zpJs!A+DKlOe`)l4T0a6C7 zOu7KEcDF7nADz(Oh{Fh<8>w~xy$u{0rS$dYSNY&O;5mE&aa$N^$?eDS*-p%!Kp55$ zthf`yoJd+9c-nzGqS3Oz=9t=vYr+u+xT+b#2ytwffJY7=TSbqXk{JeZLMnm;3KP-& z1)!-9SWpjh-xaZ0rm5C_m#a|K5%i=-;5_==rjnjcZ3lm2=;4eU9ZT_e45C4BU(}-l zDQRg&C^c#azG)8UPhkkGtc4D~po0_e9BQr$53?QA@Nb{3seZdQ;$dWx=D1h9rF^^w zt_Il{x-8sE3Gdm-^xP^FZ+ z_{tE~jh^3*T~^+Tcawlj1C8}{+!--mx=l8ntOMFmp8lOp-@s&T%@@|amj*8=RgmjU zWG~RPLxrE9&Ja|Ea#NN^%H2o1gbAw3(ETi*j9*XY01MA9^&n`HzII&bWv`CE@LaDz zf-Kjrk}TD<+}=MxI5N#Dp}eRgR$uG6(WaL>LSZRr*JGtG$~G#w1#Udmsw(MDm@sNm zYe#xp`mSOmvWd zL6X%Av!4K=GY}{=tQ+I3+1`xyqOz{?G7KJG|BPn$`_nyRpilL)ZOc=KX^7umn&_{% z{a?CJJ*EKnx~a|!96Uq5IgI150^2^30_%>wb~K@YpiNMIXs@LEvbfgEH`}|T_p1D8 zTNic^S<}9r@?u&lS;oApMf_ZCdN0sR6S}MVBh+f|TjkcfA$I10FL;7HQTv^%S4=5c zma9U@@Ce5Pef-pzpV+9t&^?|K#7x`~y_ApwN|elU27A_A9@P!V0sLNCbPdu=gT|b{ zz)}&SFGj1B;h|)iar$)_zDqRVx#$BV3BfHag~_!jp%}ylUrE$M6)Or4Q)k0lb7Rpj z(Jyy*!{MlijJmAZdO_W6=(UJJ)o~cdq*EtL!&)sX(8Cg)36|F@?6Fq#@tGY#IH%!m zPF&rL4tPrf!6q7SD2P<~_;Lbl%yJ`7f^Gt#2151`++=sL*kv!&;VV+beS(}= z*fV5t4w%OVdDw77Tjp!-)h1Io0vPwbe|BaM`S z%sKjs6}6SCj^3meLnr+T2yOv%a8k z8GCGk901Ix%1DupRp#x>crP7_+A8*0K{wZNboBBTQW@u+zkRdR6%VBBcMbdM?GG+>!Cj+RS$nLI11li<{y^(98e zNvI;FM(wXfAuHpa6)YXi!}ALfkZBtfY>o)mx@<%{AvQPfvMfn9edj< zapSN+>@O(z5bWWC^^;t37-V_tQ|ihhU%qo9pAW`hXj5fw4H!~nUdy@ZpC!6kVPDRS z46d_x{Cj`3akvCx3_W*JE^s&eK8wdp;(`aeeM2hpU6Qx~)lql*8`tL*kON8}oC4X{ zhWkEHeIC2`s93MVn@AsG;{#*C(&)WcoG+-EF=0m4|&0|oYb`S>9MeTawE%Lj>8*K*`=^6!Z5 zCtMi9+kyk&Gzl~-aU#p?aJ#B8qNCo7p@jRzK#`Q*&%7nzd>ek@a!&)m0VVh$)NYy+ zS)lJf3eva5`1oAhbn>}V-EFFkH{C`{8f;xT?J~Ts_&J_r?jB`VW|K3U01C15-v_h1 zA>Jb9z-nN#B|5?gLEd>okC`Pk4l6^F(_^W@#>~MBv3w1+oGa$}cpVd`qx41r_hR~M zjS5L{%^VpIU@q3;;fyKs3^|6_!_Nyw$8h8T8#{!|h35X*xq+`zFS!+*FU-mO6KD1e zCiG(7JJ|ZC|KL{d&j4f{gBB71$38PCX--0GPwEM3tv}jMT{H0a!9c&QKu3@{@UFYw zcQj4kIE$$$@9C~+E*j>PLBFlOM=VyJbyvQy85O{ch+FSayoc$_c?ak#hS#fs>)t)% zoKJl>Q92BFS^C&U6X$IzzZnduQHx7(L;C!iBn&}YY1f|V{?zelZgR<)`jReF2>9~G zQ~O_}SWW#}xjm7jVZdkEia%RI@BhP}P zT|%+@w;>Tp2ny^s;4{YjL-u&w4{M3cuKCy*22mrV16QJ88g2t-Vj6{p(9QybHVZTf z2w*|g%T_eSCd$mwdlCiIdPJU%vwA~P5tqqyO0ubC*Vo_2%yi- zNUR!`R2trhr)%G7oocsp@Nt$xvd;$%b!|x!)y4%Od`|5x-xXS!p)L(X6uBjubu(A% zAf67TaFJ;luuY3#ogGFk9e;I19XLRqeijOnIYc(CC~jXcx*3AQxW63!eK{MgYI z^KJ1w%Nl`tV)Js4@jKgT^s$Dn|10n%!)wH}pWp!%+zuq)CknFNNMU_U_kwG%+d))S zLRZGCEh1&4DbU)QEa6UpOc%$2$!b|6Lzf!1={NZ-ztv}e7Q$`iGdGR!bdy*OLLn?7 z-44s{C~aR^yT=BV-Kl9SK2{dpO7rzArjQXVH!G{X)rHs%%WAIl?kN4>ACUSqGwmKD zo@~s)OmG_%tC});Y??h>UMf*aXg6># z>%wtoP}(AEkcC>q=s1LUwL$leZ1f+dJc@bD-h8tD1sY=N1qlpX)&wRzZUs%BY#vIB zBEo1>Xdb1-4#VMw;Z;+IQeg=}xkc5MZjNYbuozSu-NG@O7}T93wI{T; z!&M)r&IVKFSp{4QM*A1M?Rd&mK_h+R+5HVHYZy}gkwwPj#k+oFJMrk3a0U`v%m$96 zp}tl`{C(B(jbTkssv1tz(#-7jwR$sWGc4hksrO$>m6^M>p}pdc&@z|?c6Cqz3+01d zYw!u8f0QbHkf7ft8BSOSa&(abd|;qmlI2QOily<{tYLf21;J%31?)5+`Dr=tNeM1% zH=+?iLG(jIa0*fmsXwHVMZ_14=84J0 zQuC0p%1M+YBk(XU+lnFnz0iu|AG4Kq|03T?I}0ykF7y)MPpsa5?p9m;>?uZ8O;`Hx zEGyr#ZKDr5qg-!XWlk!?y?Gc*qitjV1lBf~X%IwW{(B`UrO2B|9I{YTxS~#fIIZ&W zMX3khpj(rxIEuTjl#abvH!u}@4C8#mMqMUpjxa=jVxL>nax`AD5j zev8ANuwZL^j>piE@ z;PMWwkNH;?kl_1y z*?WqQ%5Y5j*Z1P?l+J!8oPncqxsvj1f=P!zn9aB%P8k*Fx?0U$sirXyPK4?y4IuPgZK0;CP|wfMCn8iES_wJny#tRn7GX6rB*3l=2J zO`Cm%`kN|Hy@+=e5RJh9&v3)Yt8&p6Ll_xlN1%%Mwg z)b?Wg_vwAi$O#@(v!?Hrir1Zr+mni;n+lKoY16MunM6Yyt?riW^NfzT5{%BYzh_T) zOTY1!f8(w!Vy`OOTKRkV>K;5}!C&zbTJaEDagkQAlUHo10lmam6yX77M;DKdH}SI2 zUC>IbqUf$XO7x=HULdN7zL*9j4sdo(sC?<|V+=ybQDtxXdP}uE&s5E>Tq%ONPKvr_ zb99umca?9g5QjdTfyG`TcrHrb9$<0s&fD4_b+5HG@+~lPna?ikssvx&(a~Xi)vuz^ zrNf;@t1{S5_+~eK{zUhd2UWSL&)05oVM3CakfK<;*C~0->BWq8VYM@2h$V*UvKL>S z2&73r#(C1*?mvA0^|aWQ_o=w~F#>h}@JX2d=W2S?s)Cvp^XkT6u1(EWG7B}aYItS|S z=L$3Ku}yEV@{aaJI%}rNw6FR?^#+=Db%6I;q!Wd|R|SE0jlb$@gqoMt)jrnFf2wtA ztzlpH8w~KP{?yu+Jys8eK=tDzWGvgMXjMtGNgsGGn#VaW36;G6M!o8Z{8Cc)&8wd> zJTqOfJj0{z^S{E{SX`haFRafGj^|tnhOro+4Fm!WC41Su)c49eO67q1$gw=5;xaAS z#s0DXoY7ntL!Pu~I6~B^m8GlE_dKc~FLN1FP`jWT#UQU|?vywBJI5AEiG}{OMmmzb z79G8Q~0Nn{7h!3%9 z5h$R@i~Yd7<*4=hh3bZ?Z~aZRE(OL&RM`tPQ3*RVR)z#_3nmNz))lOvM*o~iwo28d z*s5^|!laDT#2$V4QPnq4c50vgpUDXI& zgrt1}*F$$qChc@%I(r*aE@Dn}@}~5EEI`mfol8*cn#Nv(cYz2w_<2~gt0+3S$-p}V z|F8hj2wpmwm(XY}-wnG&^<4t$3S{Uw&hhTn;t^-Bk*y?GkUg8C(OnC8dReh$>)<-x zy*jQGj0)777@mV^(Bbf0ke%c1%m)%LED90PL>UXxZAW&`?LQ7FdjjuLZR1I=@4)q# zCuHJ?*1PsFo;YyX8{tDmXtt9y1dY$J(kFu%JnWpt&@ZQ9= z-_S+e{Gc_;Jw)SRQriDSdt)g-A7`ym`%``OAe!R>e*Z!=)7y4S)PmIF@l%w{4c7*d zV%v--+y&EtlVM{c&DzjBoF#IyuD0GGc#Jo31A9=(H6Q)!uWk5$*InP6e)Ud){`v(7 z_dj+d|3jP5)pv9>c5u=)aMv|kyGPkw)x5-ke`k(1PDP`hVKw+8rE+rYrnYl3? zK2+tna7%nXzF4X-a$(5!0-WZX?&k?wXUBb=8O$*0OXH)7)KsR0RScN%%YZ4B^YE=s z?{~v!+Hr?OsyN{}+sw?^CL z_PUX9HQt%J1+4k}_X-Wg(#!3-s+F-Kse0q20jqq`T9pQ6kNAJ!?#jp8sRsocqo_U< zYT}O%y;Um6DI%EnC4=eICCf0GXI_pUk^Tga9m1+B6os=imclEc05Pmbp&jDb{`RWL z%&VvqdaTLB7}Jlm#`dJ0BdghA7~QwZclvh6w{sg9hXv1*w*0ehs1M}H_6-50X^|&2 zUa(b?7w#&~Daa#nVYW7qIH#VG4s^?+zhVS5%zzETs+`(6ITYcRkG>?20Pw6oeS}{g z8Bt+(Bw@Yt=7$=74#uBQ5RP0PE(s#XVq7><8^9>#hoCGbX;p(W9zv14$c-kesBY9m zx!cy)83`rhD2!6o6lqSlb3U60P4O^1`xgzo@1FXGcPtitc94bz1m<(q8lSG3ut6b9*onq}7lp?I&4Dmq^W1?tpQ0V>-S1K(&7Ge( zAt*0VsP=n%_%l# zhZ|}+1S`?^DvUmAh6~a5@EKdkjod5Bj=ak*{V{{c3Ks;zbVoSd7J>pFg5=hf5;CVi zUK|VV|4JSA)ew=f{f7Ym(azJT^{E)Uz8q&4tl28%0)bC z6w5myvYS2H1Ke1VC#h>!x!Qo$zted z8vp%JM8>et`Fe%e9j543I_2cp*IV&?A(tkX_B=eT4k!0X1zvTNDvDm_>h`B|`=b9G zhTyD5@-q^6A|<{!(ArW2HepY(o*O-Uy7glZKp3al&ezU0OlZmkWeNiw4Rd;5&TMwQJW zVEz^O@!cfTSFnBqQRn?UPa8U}rkC&iR_PsRF2aC{cB&F%eo0dt!MPN-LzDWqxZkGu zRa7{(R+O6?R9hcKPOD^XwPhDdEI??KGU@~S`)6hr0aSUEn-${j1^ts#3?l80iNo*) z(lt$TJ%hXa6BsgxXest;CQurO7)$EK)&?n=q!^7 zIZFQ^Ny$3xOi#YVJynix!jbfMN1biw6LM^BsZth8ZhPeb_B1D6aWEg#Sn8?H(Mh#0 zhx&b*`;w$ETN3WpagsA>B(zU7u3+YXU}@J;Y~0?+B6$;&XDCK2kgg5&l|1EM-G8EqXbtIZ{1d}@zRLV(r1{}V2j-HQ|FN0C(d3*0npOK`7w`gt(PUvgMBPtjAPLv z?mlIOU+-US-PJ$TsqZ4l5sk)`M9BlD<%O{FkddX14MMha&sAZH=fU+D8B9RhOnL^Q z##O9RXKIL~r+1RhF`*HuCmkW$f(p4cie@5$3Cg}s}C(U6J$U(LC zL5v0LGkbq0%}N~YHO1MosT>D1^#LfK5P6olQ!zHQTp;}j8GcJbS*sHY;54Ya$VE>j zQWN(J$dTDImDXi*Af7;2MYVRv9Q9c%3kN&5i|M%q01$k!IQPdS0+CZpzB>EvuOkqa zx5v+h$l3j|;5KFV LcW2LgA4SwW6UXlI31QazDRtAYxN7+;mQ`TMip$l=T_L0D z?S^+M4wF-)L}o@`H@D5UUoqLEpW=V3CAK_QNO2Ji)Biqq=p<9nt00aTJe_DBQiY%E`9shSh%{@gpQFaf3^F8x zA;|IN>_^GNjjol%ITPVFTs$E%vtAXSqjzCI_4w}J z4fzLjvC{hGZ|-X z3`POk0QTy9esoW);jEI|UFeX-Mqg(DSO6a@tJQ^>${_f*k(YoT4X$PuDi9lY-o_Tg zdC4mWQo_kcUsgaLU5PJRO-C7{5*(9T3RWt_aK=W~<|$!snz*|*(vm4$m8mV9+S@zZ ze09!n7^UJyN~TY03H~!)=MtE#ha3^6m9!=%lOJi5cSaMB8EvXp%QwfZI{4#>In@>y6BfC_>7%gXY+h66xJr3tHmS&cP<^0VAxA(RFI=c6igEyIHR%?Mk*zVjB`a8 z3HTr?Q~?V^P^1?7%}|Y#-_EOQj5_7FJs=v(5-WbH9${Fnj?ile`%QDS9TfXF5pD{p zlM1XA-LXU7#&Ex4_&}V58NMQtSV9^hig=0L5>$#Cea`*4rU=iCbY`X@+x63|K_BpGKrp|y7S*dkNFGDTfpKJ0 zeeZ*`aP=8MTT;q{Hjc3sihEU_qm6}w5SPH>MKV7awm@^sqz6~$M-l|uP!f7$rjq^m ztJjQ4?7z*KI>nz*3aGA75?|_ns;U8b1ji?aC?2ZZtK>(8l?p+b2ZR}XgFsz?0$d?F zEI6wC)OSFUDr`Xoc!V+~EY*^Lk%+vZP$twf+^IQEvW)8v7i@@_Wg6ve3o}Wu$t7Sm z*OSG~vGlT(uj$FijFTLB3SX``U2Aicb=gu;WZlBHvBYTjCU(?q5_Q^U#A&oSNs9W= z`^QjW5sb#R--cXwQT0R|H zeJf$|ua&4O%_Q`2J?MSd?u^ydgw-H7N((|l~*69n1bF7hU*pAz=6!|maM}`?)af5?gf2U>EkWTlq(czD^)O?tF*P$ z++B<{t_FO&6~E*3R?Aa(4aI4vjMs_!i&G4TuRq|uia^C797|6L3}_n+*2l5Rj$BSG zZ4Y*q2AjJ#XC)ZeuxPVbZj;vZVR{yNoE^-+hmkC;WWY#mYt&~04%1AqLy8uW6pTH{f_$RK)Rcx_YfKK6T2=pmOD`TK7ciq7LVx zDf$s5?%5@b`)Gvp?{)KtLmi#wrzxR`Rz2V9x{*aCb=GN`mMe}FzOT3&u>cc62k(Rv zau7&-B12N18=S6J-przOHECiGurOccGm85>Hw|E*)gz%T8BIqNJ;Tx9ZJQgOCAO>3 ziT<|G^f7oJ=#Zd58{H@z~7gis_tyi1=ht594un|Otb?2o*S(^K>*TS~PE`vNDm>WU&DzCBBxVDM zyEm*S;EEY(WT?8sgLkcmWf>zcq1wR|Qd9wg24>F%py|@gajDPzHa4fN(g=c|WOd7% zsvR~xw9o4i)#R0s?@mAr<)}c_|GYP~Nbk-`yl1uxjHqs4G_7%rwe`F#*O+BQ`I=Uh zF1J-X2on6EoJf(Y_~4p;D$d!`l*Mz?&gaS)m&^E(eK?Wp#_dxZ#ZU``Mj_n-F&I^% zRW$afvX_^ZF_S3|VFQxA7RnP8c&NiYbL?f@{LX^x8nMJDS(QAFUIjRI1@U?WomNSa zl<*?^DHI#K2Ago;DN^OetGFYc0fGyLI$8R~c!kprSWZz*&o{8^qrRxNQcDD!X~JsI zsI^CCUuUQK0M}Jk2{^=C)0V)260sdaL`Qi%jF*3cW# z_wnO|&JdUEmBbCPclzOu_#p-Jv=YD%Xtu154Uvsa(w-e9 zYfnPqtLn6O=pASi0?8yJ!>rn)j|1~_EvzqM zmp1{~RRK1=v5r3Ov^$GmYIeCVZwB$1-6-#mL*;F`)wd*M3SHh?=NJA1K+| zgRe^2vJr42ZMCSO$iADk?4N&EIWxScB%}I~^HM{Ty%|J{$p2zSBLo{>67`$Q$jjM_ zEH86hK67cgtK?xZIw>{{HZBDuKU zX3mCKzAf}Pn0e#<+CKP3C>1JGs@FKv%vj@8KAi1js6l60Gkxc;9@)C-F9%S?Js8bh zM10K66k_Qlw`P$(W8|{`jg!LL_oOXb2Kvn_cG;G-_3PTq$&+asjOaSLz>^~4dkkC8 zCa~?zbVk$9^V)Iudm^lv`n$CRpxQZ}3tyzv(N|3=BwPLZX0LlF%=Of+>}xyxJ!CuW zPROL2=u+CD%kWb+{!tDx(QD%7nNR+4u%lkv-oLxZMXL9pluRm*;an?{bjWQtO~({v zu*JK5p^MFy(D&J*<%_$+%wexU*7LNAEcXa)_|)#Y_zC~Jdv*?Q+S5a{y_k3zde{0;)DPAfbZcvU)Q<-XP&-Uz5MJ&sOgI+F zkWjTA91>+eB5U@TrdEtuX{e@>t0_#V(Xfw0k_u}VX?6Ow6?o}8%2ydBa~m(lg(-ZZ zIfD>TF^nInr^STQN=i&Eb!ZtY51LwOhYwo?hghU4z3jlpAMa66p;Ds^QWKGiOA&{v zCXZ3Sy&opp$A!HPl_^cIX)f0Jb1DN`irX=wL_00~0$>O#sY`IRPZLiPL=9V6)|k*q z1r9RLGNRIX+F}MedxBq00T4C)Ew!!z_*F^cJBkQy!Icr#pmUoi!P3hiiVZ9y(Ii2s zV6zgUc1r#bTC&o~nMQ)g8W#BNWC_!3doM1#!D4&ZYAz{sv zk{^pyH-jhSYNE%)6%F*gRBIKXy}dtU;_d5&$JQ@DAkt;I%0D7C-KR+hnQ<kqx$YEK9+ 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 U;MW{mTNc~aj%DNM=+M{Z|LR>lx&QzG literal 0 HcmV?d00001 diff --git a/cppbuild/googletest-release-1.12.1.zip b/cppbuild/googletest-release-1.12.1.zip deleted file mode 100644 index 2eb158e76041f30a3c12a7264af16000cdce65d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1081236 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%0AZqA34YUClF$j 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

      aP&%S&js%4*AEl1`F0Ww|nQVQN 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 z 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

        qH+f~o$;pW{e9MoD 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

        qGhIl>6Sut+Zra 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≠S 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

        %l{)rihaaG0Z!6$2oVbJWK+oIyd2#Xj++#s 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⪙g8}>o_Eh9(!k5 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

        SwY5tZV^nLW4ARwMF@LjJ5EAq#f9T`%Th z-f#P*tXtEXOzaJAflotxmm{A?UV-whG}#+GTJP`2r8!>dmfaO3_a;mOmU1h51>hW( zMz6$`@e-3p#Zgzw9jy{qr|&_8qHoD4bXU3^A>i#6Hnfz^sOd!zL@Go??*DwwH=GCVxKY zU}@YA#v{O>YCMZyCPAL`I=<-1Ae@!eFJ$`CVrb=NItO^oqn+#NYp#_wvYL)+6)=Xs zqyWtfB9!UU^0OT2BbG+C2`-$bJL;+(Dl>u8Z(&w{e`tye1OTy&l@7Edo&vaEHYM3H zf|Aq-1#r064FL?YQAO=;m}RCNGW(kyg@%GHB15Z-7%ky|O{N2Q$ z316+phvx!G&ZOV^lNjiTa;1IvA;cGP7!7&PIBcht_E3M)Aud2pX`s#CFrq!C zpGvCO4?F}{$Sg#~P|yTYpX$SdV9-Qb#X*6Q&>av*0rQ&7gJJ5a>b+8r2}}iW`c@(t zE`$b|knAZ@M`1j`j?xtv$ypCEp`8|;bwkVv6r+8H5uwo>wF}8%P(e2q`3j+4tOB+e zAQTwjODXK{>t^-628oQEh+!^qE9^^A0})dw#(~vv z1m>By{jVGd+nwUbIi?y76P{Qw4V&=iagQaGty zW=%FkJ~}x1Qgp=3(q?xK3@b$;jy;^249;u;qO!!Efi3qgX9r{PRByrS5;om+(`V0& z?{~u1&8cWrjP{O8+fF)DqZWDLxI0~I=ic&Snti0Gg_?P}{I3emJlvl!ftAMIVhA*0 zc$16T3@ncCSBJ1twgY*LUucOd1e9{5?dO1ruV`(_cyIU~(7&>ccK_pc$l&VuZ6gXUTVaDA=Oq6e;^sZxI!SF75) zfv;7q;PuT{t+2j-4_t7Jf(hN({pU=R#MgH30tNtx2L}L<{(m^r^yvOKyhMrefbAAL zLeD2P*e$6BghNAFh*Kfy<}ZVXN`mxCi9pI(kRJ^;LJ|Sx{WZrRdvwCJE$l;oDf=Mn zbr*&sOW-m zwKTx!4$meC`k%bV7gP9B>+OW=t9(~&gR^ewn5wa$3-7}wCCwN0(rW%hMk z7=*8^!{cAQXrB8&4pcN=q0T-4rTB(s=fCnHz)P*{*XGL!Qi7hqbaw_At>cMh39lLX z*$3hVZoZLW=PVla*)uawq2@HO+H=V&y>e;{*eUamJZVwNy({c8j{UC$PyY}dK+?2g z93z~Ks79`64spsM)1lVW4D3itHBh+Fp$IY?m5o(u*OE47Mq zq(ECD6M9rjtbS67A}1JQA;wd=)7Z!K+M|pdvvCek{nQL|!w3$tS%+ZJ``-K)AB=Pl z!L3<11-c}Jjx|grmwdo=-7QF;%Krq3A&P2mJ z!7Oe4Ny`}`gNZu_r0yx2rEeB)?j$vTB5png!gdYkm2?AJ+sHUf@YT>KH5nJF(?wuW8 zGJBMK9lcKOR!@dZ&swdGm^XgO%MOeWdQT00X#zwq$pFCQ%UxTwb)_BNi9NOpjegTx z*5mDV`i$`2N6>9G3rp|u9YjB$yew4A3_Fk_F1bYXYG#Dg8@#mM;3L+rD_xd2ovQY3 z^3Zldn6sxlG;Lz)uW@0=qT5syJP6TvHW!*WjMNfXU{ANgO6eu?>+(0=)}Q2mq}3cr zZjid^c}_pm$7jv|0RMAZU>hHGyTbqgd@=w42>*|#g}IBVsrCQ4`mAVb*=>oU`L5Na zlTnbguq27Ehy5LdZx-GHF`kf8lnt`xpFb2QlT4rri?*Wq*n7=p?oLW98K!OZte@!c zKJz`DhS~eMr$c?{0_XD{8>+K@&E^(0xU;#V%@Xc9Ti@d*vwr^h=G$;Vu>qQmwl86# zg-DOk3Cz&Gf1`d?&NOnILzlSbD~`YqnTF*_g_`|}kD!QA%hvQy#pY{rL9q)N%>6n} z5Mlg|TLj^6O*pIjPKiQ*ax$8A<=*{}802Yc@v;5J2F0KM1WUoPTmi z?3aKTPI5AY_TytsN2bv{)2<=XkZC6AZgeC6-gEgDh%{YrZ27EQTUgM}f}&oW^74 zgoQw0#Pgh=T;TJMvq`omLj}$~0}R@Cw}!<95UNC2;PeoTo9K>+z||{Y9$>-Gp%MK9 zRU!mQxDht-5@W#lYh3v)OXmzc<#e?FDg8*+@eP#CkwJ6IlRo+wHT@H{q5Oxobf#>c zvrXp6(SlwYT7K6YZQ4gjXY&hr$*+UiWy%mb3A4?O8F(LHZ~3&fKnsfbG-<=pa=H!` z48gj$9?-~i8;cF58667IR?awz+O;Yx3EO>zE+)gkk0??tlt;``4I0^=#kDM>l~H4s zC25CtrYod`8O7F8Jt@O<`%(#&9iURWZ|#h&$+mf;nvS}khIiHl8MHidlFnscsVnNlpRH)_IkKO>oxv|2vN+-xa2%Q!9 zG=oOw8x0fOMSV(YitW0jrs-uQbpNHb5)`C5-)R%~c7OrLFN5D+W@Obwt?3JGThG`pan z_ENSwUL(U{r1_#JVA^bG0Fj2+30raJm`tgA^Qy<==@f6!@v+aT^QI`srObS5 zcW0)65paXGodCMd4ol-Kogq(LT>&pbLPn^PUcMwxb8I`*_Kd#!u2K7Fsl)h(nb~6U zul@<=9(ZJOG|^s|7ohVFSS`Ym6IyrCgDl~y^F{G-EvAZF1H;Uabl0ARpuP@?xa5yR zL_?;z81f>O@UA}F0*QxbLp$3eG;AJEtgoC!L?I8&lT=ExXq-j{{Nshx1=miSDuOML zju6eDD36h_WlAW->Q6#pUt)r2FurfnamS^uvDKfZ&Zt z)mR4zQ|MpL@xl?k+sQ>m^>Pd@uEjt58`l%>$bTQ7=TK&1Y7nRlUWA^O4RWi^|M&Tb z=txwP%~&Mio0p%O_&3iFECn5&o$*l0qKXJ|vPeTAEC^Dx^g!FMav2SYxKbo6K46OC z4)F}YIry%^5dCc;|6g7`U$Xb7Rc2k}a13$)>N)`T_chI(8D==E1o3 zD>j9=P^+wgmvD~q1)FvZ{~R?#%)#e&fo%L&6a7O? zHSzsuH%c@Z7qzSwiTns#VUO0%ACibjEpas{=3Qt;bAsq16+S2M7QU~qAE{gTdbx_| zX#^7AmDt7-OCL*2wi%HjCMlV1{S+_)s7SJ{8Zd`i;0|E(#+4Q#`I^TnobtD1GCPKsEy_L{UK}+)yBx3j)8o!MU3<@-!eZF`z>ehdIK% z!+Y=EKqja{;H@0sfJgpeSAh)!ga;R?4-)XugIh9m5U`N~VF9T838%m8(;2aN&f~B2 z)J7)V(rvDW#lP{=-JhXP<# zi}O%FuNGdu!pMxPh5da9}vkz|x2!3;aOoSIIhX75#n9#`T_ zNUgl8iUJmyYQ9Tb`sagh@Dzy313m7Ecyq9mFlrE$Ue+X8x@@Pr#WFQ*y-JnI4>U|i zWg42B%`&Sma4Pok1eEMbWQO{&ea(cN(VZsmsqF4W(<~mojz)DnH?GZK{$~Z&JB~qb z1eW^Q(rWWH-g}`=vM|Qwu4}yan1XcWL(m;&q4gxj9<>+`T^^$?vYpCn472M78&u1A z0Nobua^IZTt#d@8SeD@yFN{56n^N@VF(_zwQ#Ho{z4D1t_=#9UMXL6YqB_JGBP2Eq z_!!I(_F}|HexM^@zbu5%dievCvL!E%ItN{&l8pTJqSO3N!g3|~wASEiR6E;Obg8Qd zN{$kge&Q}+IaVpRYPP_t^~|s%Pc$Aj24NhuTw*b6a1waDHmRe>%&C5hT9kVFeUZ12 z8dW2pgsbE5@6$#Yy?O@1Qd^Jl-#K|Sm8SeVvq6S@#7t=+e`GO2i3D<|X z{?J7gusonn!SxuXaxxLCm%a&=jY6vNjNmsZG2S*cE?DTr1;L-USkR;}zOUfw7 zft}kURw$VXfjFcF>IGC?_kA``u@Mv?%?1SJf_uB??9N))7XrmKp$t=e%_nu;wvo-! z3NZtf_g5}i;hkzb_iWibS}cBQ8oGw@3bvR|jL|fxShmti;Q9Dd%jC+X`SD-VJxt zr~auwsU&Z&415vtGsEO_e>y2oyiEtTDZah3AQ7;J$o^CniTmhzK|Sq`ERy^FRk&@~ z>?A$k@tP~F1T90sK{r3~O=0uExU6W(GR8XxDx1hh>^Oj6|bf%nSZrO6UGKOD~B%*sl zhRY|2Xubg{I-#g)0B*L~Z#RvD>P_U4X0BNxOu+-%zQd%+MBY)l4;Uo@Vfa~-apX+t zB$D<9vF~7~pcn)0PB2N-lmg>-O8B{?R0`#zTL&#?pSS*vdao+;pGCESje8AKxycvy zNdJ&cIBz|#*fT`$t^{#q!~6>6i`Gys@kOX&4}-m8;}wYe3a4It4}m{5c%vV~9(FmX z*x)SF=}3=ZT}2x;t9}3ILG!d*=L)JLR1Iw-e_-m5^U#LX{|j&ubk9!OQ8~`N^e!lDGk(07G{+Uo>i4nXvxTA z%OVQu@$*h?N@|bk$YSr37P>Z5etL}-LY+-L9kuAj6^qtcRY)Tk3QE))<&K$3$&zO3 zzfP%!3O0#Qekk^j+I_|&$TiLhrri_wWKqSH4pK3BQ-45UFaG9kNR~ymwp1V}r}#4( zk;i>xsMzpgl+CNODgu`?3vu*g6kT=tj0v~bCU z=#Jym3aVz3F%|(XlLB6=doFMHLkK2QDUPSIMU~&UlvGH;;Pjd401QU5-DiSsXDSno+*7!j0kV(VQR2p&#wEUqLR zjKs&S^}d)77lC0M-ViKfLJM<<2@Y)a?`IB*_EHVR4t6&uGDp%wkc$VcQQnRYcmYof zi`$@jXH*9AqBr7fkT}BF*~EAb$D^vdkiEYilG|V$Wv7E_(~>FYQ`I_LV$hBi3w*!FWQ#2|R+srR}i%=wQfKc1tf%_@$pSnzd+ z!x{`-f;9FzqweE~Gg;Z78z?pij59s4L%`ugIBc;?Y^?uQNK8%?m~E@}TG8Rl zd@fJJ$oLPg?W`w{*RmU==|-Gx9b2~rw<)daQN#Lev?7@ zBYU+pE}Lup<{_w}>k8@CD^VgS^mU)+wr4)tiWL`_( z*rRZB&~_I-G-x{eaThYX3s%Rs5h-4SLp%ouy+;d^dmPrsVn@j6Iu8arOpP)I)X{;J zjqf&`20BM%E0lF~j?EDjiHTZK%8i@qE#JyUc27R7dwapNy@wn_YK>pB=uxG>=?(DJ z9#_}%@c8%)*(0m^+r*x$8j=DAUOsoUhD<)*X#$RW7iTP;#aQ%GQ{Rp(=L>z@+hgnY zF#C?q0_~H@q_xP?0C6&topweaUF==$fhZkZ2g@amd~s)Nd{Zz}a*TcH2k5}_0}HO^ zYNcRhq-DK+3o2}hslc)FcjSnAUoXhjYe(^|?Zhu03CVI*fHiCq9v&0)bLgr47sZ!( ze@s>VMiMr*9_he!mtZP1$z61DKZaA^Wq2I4c8$#=OT)0@lMoHG%ppcTD_m{q!(Ao% z@GUv;@kwbPNPp1x^HTk?`inA}who}y z=$EIq$}_$9S9Q`rL!kX4yv7peREBYUUw;0Z=9PKaQpxh`_+{b&0EqriHLw3N{AleB z{x9g|7L8ws&N!0KncDJ6Z~vqaFTQHVf+QSXGQJE7OL;&!=ij z4B*(hvDhDYz|KlJl^iNH)|m~==l4@u$X|GR+Sys(Q23L{aDVi-?$tHSGX+pqF_1Nx z`r{ywCV9e4p!_(Ax1`Cq(fuKS;s8Okz&*=DhNcIU5xqwcsNAYx(3*U$Klx=!S)%+Z zHw1dY9bzb$?x6lqq6-Bnw0_ck8bkjd#}kRKF$D6+H!BSKfink$MKXab6r`j-9ahh; zS`z|*-VJ}JfAu35DiRWD&vQltFS)M}VGi72WGBoIX(0y+0zrns^)?)E(zf|Re2;@n z(w?K(`~e=_)>!>!fyi0ZUIhMwS^9TDagSuc*Cp1dk~W!5%+sJEl7JR+4J6Nmb;LTP zP(h&eI0O22Naz(?ptv4Z;a#SaKklz5(Q-j{ySqdiH)5(UQR0 z>JH=hh9DD+{5bWHdVatI3SJPsaW$&k?nZv=bUBxhPeH2oU@EFvOQ~>fpv~Le3^?}H zd7pV3;QR08*4`{&BY?Iz3YL638GIWj=d-~aRy>SW;16T}D&#dbJF{97E|8^F-0f{u zCZ9)$Q9Y$Cdz^Y}hPyH&-TF_rH-$ddvC_|SX*d}-!PC&xnq1BF%T}uwGozi*i|Jg=SU{A$e&-LPo$fzi zJik3lfe$|aa>j#9F#O0jzQLeX`WcEhQQReM5tG=-Y zut=BD`rb_MfpxJPgemvo` z^4JdWNDFI0debH&&1XV>1bhlCEZ!}Qc3Xt*NT#ea`?&7jj+#)Ccqx=MI=yuC!a5FS zQm+6M8X!-4?83-#1{`JjB)cj|W=_RArNw!c-renOX2NdLPfcC7 z2bq&Y6x#iKi6XLwT$0_bHC3sWl$bD|Co`!Nkd|Oe_OK8C8u@VD(jdja5Ro^bQpms4 z##Uv`HEW8Wl2y-;w)#oDBI}0BWqGug3W@LR?Y5fo4FyX!6{!)}Nl_kW@&~7<8xlVF z7mN8l`(M`+Ql7ngtNVvIYK|Lzn>w`MfZ}x2{AApCo{LeTx)=t=CiV2_?TJ%x1GQBB za0!Pjk!(yAz#X+vR~*~PJMG2s_C7;EApUuGHSp1hVpt>P33gZpel|TugE~VFXG61M zzO3An!|a9jlJ~~}MAmzQZFci$IPh@Pliah2IR5NOg@14`xOH2l zIs;2f`CfSl``(SAzf#h^Uc}1E7Z^l?*P|$GFW%>D15-TiNatuSR53$Y;MTBn#pzQ) zej87UY0WWPn6XWCm!~K*$bp|kFc?LCUGU33t7(Z_9lPP;pe7Do*G?Y4*kspEof8CE z*6UlRqdDYhGvAlvtq!2>D0bDp_bJ&r#2IA23ku{aMX1jELjv= z4sQLq^za49UGuukl?I=}m02FOzZvrm zq>hM#xg{yiF|&&b6A22JxjzwBxq?V}FUDs4u+@|`-}`&7veqZ+O&tqWR@KFcE{mBR z%FQy|a>_78zi@$*3N5M6TG^d6QnWdCu5V7qmr`R|p^#lbnfG)q_5?&OF;lxz-RvKV za?Kf}dl!u!y856AUF^+V(+;rnVd)1P98W11);_S)_$wA-Nd1lqy zl0)12?WX#Tz&P3BF{&WnLP>RBq6Czzzqg0O=bb14P1VUkJ7Z}7#Bor@JV!;oO*y%! zadDj>CWV!9o$VAMzwRYbxYA6j=?)aWsj)zf6n#!I^FL5)r>4^Q**ag)O^luK{8Nx2l4FEvqf4rcWJKDL?+S$^Y z8dzAnIR2mRT#NdG&GtHFiJ3jEla;@dIPpB6m!BLDz*M2IOYM-&DL4;sROH7W<&k57Oxy z={}jnu~l}hIpGq8De;KtwfONG7TUkBcZh7Fj%o#3V-j?1q2looELhr=0LF<5&y(kWpx`IU7kXVRjn zR|y=r2RF-ZHv`*l+VHxw((tWjo)g);34iA@tUT~I=r&%PB4FL_?=qG4TD$Q!mJW=0 z8_U{w0--ZGdA+5ty|%_g_bx8_%R-N%FLoWn+}_OLt|M;vF2aqr@*JBRjvm7or=5Mg z*z?lqW=?OXA7~DbMO*)5r@!>DGWi22OnBCp@_M+P8at*_Z?nfKO`U*bRxI`d$vQDK zu&2wq7ci9Cg_6aVNo0AU31MdRRs;<}vJZiA!=L8X zY&4bio^(EC*l{hyQ3vf^xZ-!b5eYc+FGVB0!^ZH0?bY_U4I>qS-x0$g26m1@2pp_igkchk7vEtxZacdLEEU|-U= z-b8k0{#&6FViv?-Dqu2yTHh4^SIsgm&q)Ju!>Blmz2X_$c9#~Tlqo&q2bTZ`S${h+ zJEQFfA&Thi8>V>4aK_FrvS?=oWcC13EJ+_oD?vSx+>v^RH&_E46sFZ+wa6wNrO*p@ zi~@bNBYWo25LlLE*bGTfQ{Zc9@jNtAxj`U%=_+bI411f!6=BnXN-4g!r|rHhGAg=? zyl8!2{oJ_$jsDe?-LmDPWmcW4DDc_J*B zx6-1YdS2db3sz4q5~l8}8X?UHXD+be5JyBKp}Ti%_>xK0f~$Zj@=)O+oY`L`cfgbaY*y$(h^`oCUcR?AtVA+Rc z@$d8c>Ks&C2+88pDy@}D)4%s}he@s2pdY%s5(*KLkVRk4dC;H!m}T0jVp5vnsOQ5y zqNLyY38_1_rWC59CBkhhUnMqDTiNOU8aoeP27B74w9;@EveHMV4<)(9m|JUGLf7`J zxj^fA@peHumXiL zD3CayEhkjt%9*~@yoY^$?cEx!dR1z) z7fs22Gp##hjNLoU=dI_op%k4rAJSMOD=-7?G4}0f18cpOxK~~6?5ZEsr~!u`a{er` zJFIh`zX$7OdRIXwZDh}zS}k)Bgxwa)2PHfsGm`jddZvKPkQgUXO1ymQLVlI+cdKVNLRXS!+<1 zle9Lx)Z*)c#=3D=_5V3#FMx0DPCQ8k{QF=AZkqHB+hgSR9klh~#@VxB&BV73oqPI# zyZJ|&rw9ARc*8ed7Q`ijCMM`p=JD6&NXXRW<{)VGXG7=fN#dX3HvYkvltCX0*S|35 zKD5^`&FYXQ7Kpch+kyOg0D=0rqZSC~Ui}j>pLkYpaL@nkwYke8WPAEo^&Wu+0FeEE zx` zOI;qZP2^REU$mq*o6XM1*?4k#oc7eZ9BC|tM@R4Da5kDIQX`3Sp6B8t|1&p1r>0yf znIcDZ|tQd-ry+*G<+nqNF#UV(BENVSw)(a6lKLvoUOTB@xAXXD&MqO_^Ev>e^Y zl#zSIVgM7CsJNh+Lann#Rperk>l`Z3BW>wTxqsZTac(H^3znM+qvADAQ1;nSIGXEH z1EFSm!fjeMj#QOV8LHp}G#ZsPJ&j1?x@WWEx19?Cd~yCkM;E>9o|fLMR#qVI%FiLj1EVIbNz_c?oTv)AXVX_V z_BXk)Oo0w>;7bO>zFFEs8XJx&RWQ}Co)%>J5^P3!oRt5CnAarxOm@% z1~TLZ59HuP66)~iE5xHq;|Y2&M_QmnhY>}O{|!t3dnB(bbM#;G_i&8;+i-2i|Hs-p zg;~~ZTbp6qwrwNBMuwGP+g65c+qP}nwr#WG+jUMowa>mff7RW5*1TSQjM;j7Tl)eI zosR!6`Fm6i2p&vu`A7c7iR)s|f-Cgd|G(vL%yCUj0}~vMrH5`g1zVYBq6g8JbM4XE z2>gms3(R-RD=vu3%ED0Wp}F*^%^0$ITO?t>mG0b#j#_G)L0bU08mT?m7e*0c7as3Z zx_yx6E{N4&1D8`t-%<}&G|MS>?u6VMedlwAI|3r{C|s~Gvc7l>A#}jvjho(6UE*7_ zFfX-&T#xgup5ZT_a(@E1dHD?{7jYz+>O8ffd9@iC1enT;fAnwiyl56UBI*qmq@;Nh408lHM2P<+U%^WGKRSOK*ob5(75q3g zo3&#h!6f#d0yqD}?Q*Vp49IG8mO1oed)|8R zc88?p*{DvOVA{koe2XeAP^yR7t$0vwPwQ^*@%Sz6n@?j6!BCthp6tESW(W zzsYC0Qt39LER@TwuTx$4WFE}S+!4CRgU@ijO9Ce%ofVZE>;BU!Q~~ zPgP8{#MfZt#rT+0V1+s?Ze3MU+(x)xp#9w*yeWd`vm)8x60PF6lF1UUSGeD9`l2>0 zZR#|6FLno_(R=memUxUwx5r3)^asS9mQguu@PluxwT%KjBKS;6cL{fI| z;3n;W>Mb$9hx{wDYV^t&2s1KYQ|>025ZX{ZWlwkWZ^El~JfD5_8L zvU0xndG$28j$Mn6bbB*&i!7nIjjxoUXH@+MeL0Yv#W)`EXY26Xh`31ExKA45`P=5U z%Q-IF%RpD8R#kFX^zMe)i_6Jq)$A$AJ}PhkfG6=~Zhm{7`PiN;3&|(D{@uZR?$6s_ zA${jya+AtYl4!Fe)Zh=zu9Q)q0X4bh|M#^ie-l*0*bf`i4G91s`G0zVI9Z!nn>m{4 zS(>>U8U804qw@ctF_36Y(AD*qr7I$EbptCPmZOOW1)P{+BIG|#QPk3lBAspa1RU;k zD-Tn+uz}qUw|irbheJ8lO0z0FN2kIv6RwVx;=uxOyz}gx{0(RAf`MzXREtX5lLrokZM}lZ7es8vXJ6QnMRYP~quV)YrC9sFVm91J>C<_D^c`t!#UnpAN%KK7|zm-?vnQ5v9 z8k6_S!W3MXh=qT9e??{Fy1N)QRzi!sFR2w6IMf*JeB^o?E7F7LmaUytV)d87Ciduu z+?Ocd;*x@FB(-jp8{b8cH01oyF<;eMU+BmHkC_oaTEWDVe#3l~rhLXIAq69R&N3`8?g&M}Tss8tAIP7Z-Ugzdp#K({7fvKim5 zfO=nx-@?+0AWht!${h+CKhy0+PW-Sc$mE{FW{2ddFiX(6P2CpqF{bL1vPN!pbZuk=g-29w~lB99$3(n2bMlCZT(+2HMP~=4H zsexm?b44<^W|vBJsdBSl={SDnV6yFawaFGL%890m$30TT+p!4NUgyBMzS+WMPS_1V zwr3&Q*-!UW1eW)wTpa`Ve&u+(Ks?PP{%#ww5SFQ8wB`b*2`eg1XQ$Yk&V38Y^&5w9nO|yh za|__EnwMMdEbJdRDZQ{IaKATs(*=9@E6b5T`^rbu?Z9_+UK7>+6{trZ+XPs}+)cH& zgr_0v(LHSGLi0PZ;4=Ir*hluKx?9@_!RKAZ!@zx{kW z>6Z+rBT-$hCfu_)f9UJQZJq^qwIYXRBCO8uMfU=Cxz9SV4n#R6)Lq|&b|a}=@}q8| zspr{wkbiBZ!|Ft&!ya?4SU$br)~&*t3;;iQ%y~!OoZ$-$ zu%6iQsOR_Cr%`J9d!N&*hOyCF?X)nAyj1}IuOkcszKYNaq6 zVofuPp8BmNKqpbeJ$6aX2$Q6WfRM1$?6!#NV1$JY(qZY5zSj>pU<9ye4@)h$es5pt z#>Oesu-b`98FD6vl`Al+p^0EwCQI|&28>R}pfX{oN}`Pv)P@PU3k&SufK(k99`p)k zQIiR`{_YsTuQ~b$!5MPphSf&rH0yeTqaKL*L2%?FA)2Uz-u*6Ms|F2&g`bg}JYW>_ zQUzApwMSN&_N9`@Bj8X#8V=)lb#Ge=fO$xUqk0;QW@JT#taG)(v)4JH7D2mwIlT4; ze0ZWi30_zDdbR6*G@k^sNl)Hd|AVq+fA$KX+Dp%}ezObL z#Wlxr4oo)5oJQo~Ri=F+(k+L%2UJaNRSl6h(XGquLs)nB1sJ3Br}2_w;zX4k2U`Fi zzm@eXO!$|pUUmQV_~TUX1BLgU6%*sqehL$soM&Nnq=OCr(HqP*+4leNDP*8kkL~@8 zk-VQVBJ{tzf&I&!;OJ)iUzaW>oqvA#H-JxB#^xU?`CS!ePD+8|DX*9a8zkqy3BE^4 zc@i!{^Y9>Xa&aFo6H}ARi>G~ge4HSmF1PDRTb|TkXU^CDUfz&5 zI2YJPD23HF-JKn{CcR*sT4=pUz`js#*Je1I1)kw4pl)W`N7SwQ1zTVzC7%=8>u9Kx zHf;#dvW!!3GR~d0xWmp7SFm|hFwO#_#yI`1nHq}w2r1Bt5!>b&1!;>vk|GS~(z}P@ z7zTq-FV~4b03W3QO}Q2U9$8Gqj9)p3aO{y2S(qD82%tzQBni4y?ri~Ge9GH!y8M*x zs8L&w&#KaaV72~O>I`UMdLmPoMoG#7QKbV}ZkdrX6v-hqkFa zbkcG555V^-Z~HHRFM(K*ZIZJv+?<)vtxRIcEHN)soJkHsT$u;;XMAvk>Dwpb=%IdB z4*iUe2-;N~R_(85?w>nqlBdMRERwQZB3j!L&XG~7$U18BGtuE0^+93S&|;Vv6XrZk zkr)aKoZODP1~norO5l;gQX-m>T_CH^uizNU{&n?-HX8B!To+eLRS+5P0dta@nw=K< z(XA6KVs4bS)z3{ctkxut+4nrra?V_hbh zd^8thHAl|WlpW^@Fm;twFc~Bl9F58eG+>&Xgou$f)2;SjPma$K+5|n(8!A7|Ds=+P z^YhU<-Np@^qJO-LE9gvhg0PaM3hw?gdRhW8ZO5RtquqqyPvZ`hSc1$80DUmMR_ z1-XpuN0y`ef!QRULrHdy*V8*f_Qzy5;lP;$A$T7*Np8P6?(JfGM1(`h{|sV%b?6w# z*O+G6ABiwep;5=yq>$6uMl@`upWp>2aK*@Ckai8TVmyID`(n&dT;WVDt@z<~_B^8V zSX-HZu+f~58i5pKR{FL^pp(SZ-jiv^#Kqa8xs`*$BeSz=U|%5iicg?f_Ze)%3Rk%@ zVZadm&4U5m4caJP6z6e7$62NFg?O179s%(P}-IzE$6@C9Nyy*{uR|aCnf|22Hnm*;+>&JS_IcQNFMh3 z+(pcGFwSgPj}n(ndVkV*`}y?!V`ak9SHKwOmvJ+jz^QULQUJ5%$eJXmSc0SU)Z=Rn zqJm^*$!}Qn$KU zVtrWgZ*#}TP8*FZ$1@2l7>VZEv26Zai-Szg+d*k=} zR5N&F^wD`bUtY32b}ohoajoxZQARn_wO2YRPdc2BFq)V_M~IeAC?QxuXjkTM2l%qt z_;8)SCf2U+DNev5zUv}5-8lSP0Emg~`U5&`*e&>fsR6#h2&pznSdlWQ5P{z`uRHDZ z|AuYk?A2u%J|P`8M5}XSQr{!-I3(|wwdCH2e4iCkb1kZE{g$eWGlMj;p593oB}`jF zPhw5GAPn;XlikO7K;}`%5w)7{LRqGq=*{;p#1=vsr1+#~-6|vX{Aq2qmugf5agMS; zcnS2~=u#6Nz&x)zJR|e<72o!*jKz`_;6m&T3-E9uG~5Nai=k#ft{#_|P#vLy{0-#~ zK=*9AxDZSi0VU0f*BA|g7J?2V=<+$BclmthHG+cg5&tU_M#pl-(SN2YJXpzj1wWv#7`=zY6D zPQYO}Hl89~{y~1kWWf}($3fc&Tl{(Top3N{ytwfu9jW7nh5>s@7eTa}i#=SV)V7|l zaPQBEdV*?+c z=UX^FkQuXdkF{7yH;$aHFI~HfKWa7`TrWn!mQV6fu3xA@2~p2T3@jnFbYwObzqz@x z`4J9!A*tbr=c-;;gy=ysJU-KSl5SnNf(bsU7%$ft<4MOf;1ft#i8E(P;y8R5D5^D( z9q|SLAmM(b(AC!+fno@Q_z|lBn6N?-xp$XqPs`BA+muj&t7Fx$sE;J$YSu3@>w`J- zRhAiZJ$G&7XC!Xzo{!DhF_;~)&vE3aLHaNFzlI0(94FWJL7x`Fl- zU|0}u>(6N{51q6^=>;Cie*Xo3@$o|w2LWZK*plNMiYq001|?o0E+T*4xZ!-Hb$s$P z&kZDmS8SP4YgW|LDtmVm=v3KIxEr2`KHysz<^nr!q0eguq%MCHasvMkheLmb)k)%W zua{qx4HbO9*(Al-Siy%=4frI2eJ??W4`e9@Ibd)DepxF_-!aOQQ$bIpaLXx?Gd&v! z&}K--y%U&`dn0sUCeLt*fL@AIg}|2LCTKM0(m54Hu`*&QoG2ym8~x66Yxui5w}7NJ ztcFzJDm@Pc0Q-o5*bjl6qzq@YD3vb9i%zT}dD${+X3Z>tmycFXaGM-szO)ZSLOKY? z5r+>XHkJ%x`-?1eQy!!a@J}FLiiruL5M3xXeib^S9FwiKATP^v>qs;tiuuM%lKUT) zO|E3hXgYri)lCqv(ntGw3JzwG4mz!txZj zqIU_msNlj;u$?m0ZR+4F)+fU%8DU6e4aX_F$^f#Pu7cohD<*aK?w{TBuW7t>4^lm>Mu7s*gs}Zhi9BfkQFVDppX zo8#bLia(Wqsc07VtExBzox+~oWQo1diuf7-Tt>bB8m*zPs2iX2?`yx(MDb69*qWkR zzrl&s;R{XwAjUYhwk2=bkS2DPHbw=X8bxD!`x-Y4i09gz31$uUqZ>*iPjwX|gzMux zMIYje%JTV`zjocp0c*H>sb4L61%d`*d?vx`wV6S>J&SQQPxO5%N8}zfx`sQ$D8OB9 z0A8kS?0KhZ>LayySuJwpS6m1kgY66G)Li32Evg zF0tr~>Vt@b%oO;_o#~l^jAKl$n@E)le}D^7+OR`zZuEA^l=Q9^!`!e%8PSP1#NbWX z5VuO>v%rwDJ<$urzf1MIrZ*3wbibU+`7gjkL;>S@-9t~RlK{1S3h$^---50(?6GMpU5Cls~iJV(5!8Tnr#@0omSo~RNZT)7Cw;{RKvylhzt<}_)^r9soY}& zhUn#Q_T#UK2mlJZm3#C^EF=alBOd4N?PYz7=myd4!9b5yp*(k?35!3UkZjnGoErL; z-qF?!OhHaPV@bG23#pPrm6YZMiZepI+Q-?VGmJ>R$A$2SEl(#x2g`2=ZgU6xA>hwH zc$`O0U8(?N?h(d{l{zx*^cBlrM25e#sVIuRep9_fhLoaXUv;XK$r5GSBb5f|lHb>Q zJIBO1GqHO{bs1xt6kTF0Id<}7M4eN1+H7N)lScyXKIk~4|LI=W(;s{cSeajcJ~Xm! zjiJcQ8?!c0#EtBmv**;pd(X_^{`$u0v0|ORzJ#%^26N%Kw+>Ko1P;tL546fq4r!;D zlBK4@yLa$(Fy($>`wJJLWb1reQj6sBx^^@qGB`Br=WbA7d!Pmb=K6^0(D9&foluZ) z7#rsa3~tl=lr0|tz3_~uq7>2^KP38VmGeD%!}58gheE}p7;a7XatpuqhkgK>u=nU1 z|JDI1nX_AeEBkJZXAcaxc77p4{hqsT=KamU-rmH$aS^q6qsZ4^-mqn?wdvlQ(;P4wGtg#O)ufzt`t zViMT#NcXwyrjkRp8mlQf+fWse9;uvQhHlvBuP6Bea>3^Wo4~V3s+Kj1)%iN~xo$~E z_FAjRaifdaVHaT~=6!pC7rKNIU0r*@F=fz^O}o1XTfnyQt(98R;)CkbZAlY4T-o1( z(ZxRBzwvXldszr81C4x#5B%5tu)vpi9SEJc1yFV6fx{CkNR)21iglRUPXH#Mxzx3=^jsawb`ho;Kz z$?db@f{>pG+mkjcMnbV!OD^qyUA&aZxR?bL^atByEmwj`RhT)b5l zMu!Lm&hckT@n;==3(<=O-kzYPa*G9goqh|)<_g)=5|3oM7}Js@g!Yju&r?gb+*Fwob$t0&lKLf0ghqTVBF$`vzx1S_4i# zfZ<7Z0Rxr!JHb&ZFS{yAVGo(zXCG30KRvhUsA>O%MRgu_rpR9Yk4@t&AlSUa&!$oR zXVWO~|HHSb>HjNxPsZk7F;)MlTy?hbdBq}aYQO$b$%$G?5-XndN02fhETn?Oo5jPw zp1p*)8{@6{eIEsiI1bX;qw|N$sl(bY4YoJVS5=bze_kwEDBw61 zRMdZhYu@t&Csbk|zZIazJqkPW8;#XT;A zn}57tf(nRjo`tF}E+(;YAD1?Fffx+YC2xYm;U4H_G~LS>1w*h$Eddxr%uiT-`k^tY zoY$?ceBHeZ$J_`flM|IRZT;O)rGvRi{L#Al#Dl5MtJbV6&&P{}+WXubLmnC^J1^7i zFQfW`frVlKWi2=;>FQ-xCU>k_Yo*T%LVMmZpiO36o2x4}`<*(4&crk{uJBQ2W34PE zH2xtp9k=GRe+W(3e+W&&9u5Kc<;o8+>ntIY*!8u42u&>OmMreF&F3VCU?|u2R7n{w z{PcEl$UfJiJI&OP08s}J(7{*BsslrF)3oAH`LsNmUQ6Qy98@yZG`%UJ$Vn4IG$RKj zpUH%oG<%Ud<0Q!)!oOim#DREmKP{@_hHRKf3>4$A{sniUSQRX<3Q`2No4zu`&xn3Nyf2EOmuVNvla67TF`rMNTvHMaqL8`Am9h2cGOHl?pTGV z_x70N-Qxj!ShC}Vu>kX?2~e`=WikawwYzmu`4~ighFpdOyvVf!7;O+JsHLwr0Of=4 zK<5YrByFK&CAS~PXFD-_f}z+)a1xG;bE0W|5NQW)NQTRTn`3GxE(u3m5UQq#BP6k* zg6=uLI4XKvl}s^75>gQ*QJIPFFMv$E!2^3(`mRV!GflMayIh2;j$kI;1LiU2HkEX> zYdZuQLk?%;>Dh|MW03TN`l22c$jC}FLTJ!B2uyOgO9w&W> zIHqLL{Z-XA8=jWg2}Cq2U2b;jJ!~?&p{B=!>w9&NS6W|Czn7Q6{9S;ntR~p%viY>Z zqdtfDtuN25Rt+Y;9z$tCpi8NC36vqL8$G^%iY>hq?DwDR&?35+$fA!}PO#GJQRn z0WLf{*Mp)<`PlMcl)X9t;JaLb23o9LC0VFxxxRmZa%GxULVMDLufEpvqE9b(guqeK zt;fn-lxF@E)av-06HF<&O0Dh9A6zQeb zL)ySw_YL&# zo4`8}zSZX+2i`r?|2kglUlRV$643Eq4|=v{{~^3J{={qLOCotcSC>pm9~XZi zpKFom?}LoiIsnMAVMWpaWnzH(50b84nEs%KPQYL=aIQ?Vrh7Ag7L|3Bmtpbo`)4$} z-=FT80=%oAZCai>OoIRJrHKK=?E~mQ_m}|Q>!dm@aPbZKoH32u8w2(CNy+R}yq zfi*$@MSmsRm&3DKzS-U#y;l`L-@34c%$oM`_${ubl4ZodS|q^Jruzc3G@-MqH$tQK zzEy6u8*FP9@PaSI7q#EHdc~ZQWw9!Zf`E8D&?i8H^@)Q90@LFmNy5w<-b)1~s6@pg zufJ!-<6hl>;xFK-Mc*K^G-$*P0G^5%eKA_4i~udig4?gn_+6rbz{B7#MFe4PAwr== z1G^c)(v006x)pLrJVE@LNTDmN3nATphjq zh15oQC-5I5wRv)ZG`JXMKqgagwUYsZslDQ7FoIX9Y_~^9TaMgyetp3pPiEK>3O3 zn5alg;Wtw%$-Y^Ky;>lMPgUAPao6$l{Y9~+lwXq!#l#z46N{+dw32t-*|6dL0B9gWy7b0)752@{kA&k%>* z*+?@3uSb|4|EeM5ZD9Rr>5jc^mAtWEAn_9tdI)lN#{OZP><8K2`jon|D3A-Ko&|gmf4A^d)7@ySnf`g4iM9Q4FHNxsMyIjVse1-m|ba%WFHOSC$SMiPe+H{s7 z@00hIjUDyk)6fPYn8dK*;bT-i-yrLEdt!j2QB6)Q2A?KbWc>a%b(=940Ssls2oT)w z{Urby;7u~DUOq^?x|So4n}0`qKjF+6))wRsuSuv`i5pR7i`P|+86EXz1TE4p4u-7s ze&!_!@6!N)$2$!O51jB9v3App*c@a3QHY@}#@qYirt_B@_1&i0c++jPl>XM0<1XXt z%3p_*%-y5x%4`Z2V<2Hpf%_m%SEO5{95@XejzkAoVW>MVm@(6&#$jbB3I=R7xR^Nv zVYaWKmUG2CZ_i_rbkyD`kX|f5tx;h~o|z+~0j$MZeB3c*z9ENTJA`?m=oqdX5F`8G zxsY7nog0KI^^#km`NEt`-#F7}aN!rT-oaMi{)1ax-vOvPMlEDOu6-6TvYdq0p41bx zT0iuix@M5?gMoe~JVLtPW-`!5=j`x5YZOrk*sGzk0*}M4SahJBQ%(Z$lxG5*FBPAY_dB1@G~>9o7uRRfK{6de=`7naV3QWkK0Az7I{xZ_Cb0TD*CvI&!;46L z#V3`r?Zp`(Rf?g;p7}+ur@4Mw&@nT*9JB$mo``mg9_}v#E9r=^ z{zafF=y~oX2R&O)i)1NO>N9ZOEaO@iUUOE2_Y9@=rcO5!WCHzk>Cpv*=q5BRBZGte zj@TjPY^rF>B+aPZn?Z(!&X787B5H^4rwNK(K?x%k-qH=9JmE=*;AH$lOrsbzHxMcV zkA%6mr`PPS7JQBQR1h`hH-gCi_p2k^rI9;f6D0g$wHMk$>=6Ft5C1PKMimJGUki$6 zT@XozL7c2|hZ+`y=GZXM58yB7Sdurv=vX#E%4No(pb;_4-47f%nD11%1PTfKnRtRy zR0T9jBN#c&kW_fwQY)9isLjORvw`=NJ=E()1$BnNM}X?@RN_&al*vh$%Zj^nu=NcVa-Ktc~ml# z+4Ay-=P#f1Do*@2l!J>u8cNn#*>gIbbZ*<2vlSa`Vc9TuXI)XawJg6tG6u`#42Vqr zJJS4u9O)<_t0ko~n)GWuYIi3TMu3erj^oMVP28@}ipii&3PH${1q`?63feQr=&yo; z+iSs4a>qf<=e*8vp;$rQ@nZ>3F}Oq5wT0+m8BaKsIYnzx-MV-4_pEUbdiVH!55oLZ zn9d2eM@#6qBV=q=_;#u6hAFwG^JrZxSUDiVTSX<#&{FPs3j4CX+40{-!K&@kRYlZ= zJ6malEkeYM0SiZDZnvW)p_(?23|IyQHiw+w&RWR3Pp{Z*8=jVL-b0+xj;eMFBUR5o%haGc9o155xVzb?Do8dDOq#F$ktQg|{FR>0 z-;ac+Tg2_6LhW+6>#X=2US}s&M>kdO2Jr-Q<@mx);1|l(1MxP;AJW~usoxssOF+Np zPYOhSV!<(+#=Bb#U#5*!JIwhC__YTc7{C9lJ>lzP>!9mA)Kpjud$8bWOii$_J;;>5 z6!a3r268*v@x@W#cDt(_&j+%k-q639?seY(&j8=;-`*8BKPI8>pFk7t|Gjvkqi1RP zA0HNl|K%+_{>NLGUbUosQF-~_-onI%;$KN80U;z%1sMeYx3jR>6e)*ufaUmhGJSa0 zl`nVzZhC5CGy3N8e0iH#P2FSJe8-EoJ!P8ES`$JKUe@Ch&q?SV1*whE+tJtuC-O4) z44cCpwg}uNx@t+!#O7^`x4*Y-O6Ykp+D>1p)AMSi`D(Q#xxx2Is3pUmvxd0h^OccnkPZjBAAEg!$Oq*icn z;LqhHaUdCgNO5z1sZ)U7ey#}99>??sJO5~3gp+2fZ2PJYbZ>x3R|iC|c{*{}dsQGr z*Z8ZBMu=HiUF~D-{HI!{)*8-rzy5%LYUEmK*<vmx2>HwI zrJiTrQ7RYoM~=lAHIGTjF3yiN=#2Kd80w@&!vV5Rtt?%Qq32NrWtqo_lExXsFa~8k zbEmw~&ndQ0T0G<)#l?a2B~K|ZM%V#UipLXE->wVz=~;z=G8dtTeLaF0pA5mSiX$HJ zhG%pv;kX*trzi{19^{t$Z3 zZNY>-;JSh(^r-KdRI7Adij5kV5Nrzi3hOxPh*O3Uf07i>pv)A=qOCR^4F**tI%d9O z?!U~1ROe2KIiVCx;UVJI>V0;RT?{l-XziwXi5JyKc0cCAtpVza+xhpa9a7RlUF^B2 zq!D{URMkTL8mcgs6}r@xBgl9kL6s3*ElPES_#rB|(^$|*A&{SZ@BcOzDtC-j-%Q!e z5GrBqpR&0AIZ(PUbx|X97MAf2SP$7Tp0w48>FjMxxrjN@&YRNvu?N8fb}m74Y8rVC z-UT4$5aeOgt)gnbnHe5zNqbnB(8A#V5&LBVS3b zAb&PNr@t2T@U-N}*2Z(Vdv#bT7!|BHHaG{@pvUFAAV0_3nGYaYSQI9vjWQCV-;U^> z+kYHV_5j(X-o}?%-+}KjOUT3(&GG896F~|w{EnED~*KF(gF=39OBAeQ3{asNU* z)7y4S+=ATV4(-{;3*QErV$+N-(goXrn_+D&!`{$5oF#g)uD0GGbc{c719wo#Gan5Q zX%qGZ{O_8@dlNwK6c_*i5d8nzz5I_u6?U{T~yiQuV*F zL1|@@SRfJE`7R|{sF}Gj?O$lhabXq&zkbD1hf;_@wHM$v-~7bp(K$KnYtLYX%3K;9 zO{AtWFRWt1j$isusho#xb$Y!UMAMDiCsN0W%-LjS#wH&dHp7}3C3GoLR^O}S%uOh9 zX)Y+MprN2sE{gtEiJ`Q}q-d`j2~*>rsawFF&wsDbP%ORNuB%!ZE0V4^N*b`t7pqli zPpu2 zPsYM`-9Qi6gX0?#TGKpFdc0t(BrnWGf?J4B^1^g&;HR54BOUmbO>e~zc$g6flwCQs zb8;x$H6LT?HzMG(-t-Ycc|>@H?UAI_&f8zKuyb&Mgn}@X@-Qh-c{ZcMky?Ky>A#4| z;!>71xZ}Z;$&0+`a*FDPO;o#WeVq}|vJN7sRZS6QL_6oRi7=E8!?Tg-5PkPFH~eF< z7_)=4Y@o28t5yW`)kJM~QbA~_w3iN+~zfrx+j1TgATw+ zs!fm~J!}zN=f%Tn#O%2;CdBOBSBY10O7UxBLpzcXWktQG+rI8)?uH#{{dQ6L+|lic z@_%Z7X!0rBvETn*YNWXdkObd{qR&|3O?=2B4711W+U|{7FrEPef5g2|6d?wxZW-ER z(XHRw6cO!UMD-U!0~Txz3fFLBUy6h2W7w$$7ZZwuj7UVo1~M}yxPs9G3ApuIRWo9T zWgl|{%V4=JZ;|R>eDHFM&)MRISPa2Q_PvT=jGE#>wmp2t7V@I>igBXsa>{(nAhE*- zf->I`O}7Q3A_OD5cBKT*DNq#0LioMX#C^7`8qY;VkrHr@H! zxu(r)XObGFcXdEJr;;z4Du+{ol5FqxX?u?|A^LKLG_Pbunb#m1OIong{5;bu=lb(@ zv&%{B-&?)k5_WHwaoDJ`IRqlGf-t_DWbz8$uP^4bpXXss&(rksz27Rc1H(h)U(rro zVk97Cf-5wa;(BOY{}#t;LQqAGYhy{Zxk0`4QRKKv-d0<7p~MD^P9>{8u)lw1YVJ>+ zN3~fY;a1Q;ImIa2?vOZ)pf6L?B;PZ*D=>j6i-ewHr)CVTafrF3UTmeGl1YX+%C%H& zW}p&PMjPCA(J-8q@e2v;q0f_Qjn~6BRh{mBt%AFRXacmo&(5W*f8U_o$Q6N%?lo$c z5sbj(!sSlTRQy5xW5aDZ|GNF*i??wQ9R^KwV_=aF{4_YJmY&MaPIx5BHC@ILG1Yz7 zyix0pcL(c-?Nv&d&;Bh;s*OX0D2mIrQg8exLuE-OlVoJ4ZYo*}L%M^9R$F;W0za6# zL$igekHC+>0b$z#0q2{zq$-Zp>Fx8YYJ;Zx(gbJYyiQGz(nlBmtZUoZS>qeI0{;sQ ztsY{ol`eUM<{M1Q;hD0gI+v@|7g<`)ac6q+CGM$md=s9uzdPz|JD-Sab4!(~SZdod z2dJkx@rsM(nASp9b&g)TeL3XsrR{IL@h;}LqAuDC;;O^lAJZ57q z6$sPXFH>Vc>l?mpaQp-Ai4PgBok#F4bPrwAK7+Pgv z^C;+$Wsj3`Zp@R?#p};anjJzeQ1UKJNbOC17*XlCzE~5**|&Gksr%4>7V(GBrz@M= zaW2R14#0f;%bWn)bP7~l;Dp9W6rq$PI?fYrDCmu(Pz53aNts&wcZPbL;&xtDW7ILf?E%S1jzsZO^$62q zb%a4fBTtd@6jjdUJQeG!4~$uRBtz$lnt|9LliV2qzX=^4-6hH5dcl z4TxsfR${s}h{0?0zZ8%n}&EYxxzk-E)TB!1i6sZ#<8r9kQmCGn+xr>YuINASPIkt9NtdzJoD zW2Zt=nnTQQu0KjI!C}1K3X7tUP_UE+O5NT*E8pe$c0R{mUcDYkd|gEo`s_w#&LzQcxL&9uzOH29=4In zS#uN7k^*4F5xuEUY4PO{<%KXe)51K|v-0Zg7*o)@!Favm5-^at-I8@U$s0e^#Jiy9 zB6GZjm2!nDW2p*meU-MBn!Ag+#?wGxyYlxqz189rK|^ucG2?Zj{^AtV{>vAlR}r{4 zm}}`Nff0R!(dsx>*@4HAt?j|qLVt7j=Bxx02M&D}+jY{4Ayn5~m%D?7br{*gQWl)d zrbd0%|1ix&JnQfdObQ#ESl79#)?scZU3S?td+JZ-pE^-Pm}}an?hSap78MD6+^$|L z%uns|GU!}+%ho;7x~RjsXv%&h$$L&oqdr<;y?dQJk`M>S`DrR>;#H5gx^5IPDeZOI zrsawwh3_lgMr@!&u)#Z#gd9Xt?}*@(=LW~?l{eEU9ZlNU18l6<-xa&+l0s*wAFP9(kkq}Rg=yz; z&`ni~5Gg#^+|Am?hbLwOO1L$wC*X-2YGkOoAwYDkhh`a}ETP%L7E)FLfdypG`J?O5 z&hekAQ1Qky`Ba>TE*ag({5o}r|MM~0>e0TY7>>7N+p07xi7r)|;WCj>M2>N6Rfawai9jKhL zn&H>LuDAN4+Da`kNTxBnexueNxm}&D>H~aNStZaAe@$Bg6W=d*LSxd0f@+@1BQtx9 zOs_!LH5Mm4&`Y&TJ1yu*jNB|l;36mF6ULtMc>w2ga+-!Q=ZPu@6`uJ=sNr#Bs&Y1T zY+kaw0ms(K`AQ{H{8$4oB%jBR6M6$Y@>fzU$;)MY<`N6RNKdeoD|hp6mGM_?+Gq*%g>W?3J_Ws0T?%J5trj&D*>|&+<1=cNE5mzAGP)l* zFEupTn?baQJPI=gA=vPesNY;hUd~=*d71O_(RI0 zS4}A-TmAZGuX`xW_0+EHYdicsWIOFn$fTR-Qre-*@KZMaQ4TWEYvShlxBTN^N4>Va ze|M3KRPRA4nN%LbxmG0UklSvWjw#Aui+B4%7rQN?@3TeA7f*+o!(M@`=V=vL?h)GX zsoiz)6aIJi>>S>-wRN?4VY7m^P1T(C3gX-IWw2b zZako-N*uPy+uos^JK>E1e47G7+n z9iIHp{eTqZ$KIb&$J;a%C{`rlG=z9!(qDUvl?o9)K5sc0Mh0E87NiPODvcF-GKs%6 zf5{Z>1w~_u0u;e3v+iqWn8Y3S5Qch}3cvA_fM*uA?1wO~Lhi9i)r7U$zC28Go*8+hI+1X~(Gff$18kC$7uG=e^ z*V+1gx|w?CqatpsoZBlzLGYX@%|QYK4Iha{vE?uZcT$UpV!FmK(t!*~c)NlP_D8-d z)?9JhdlDJ}xmqBuIvwqVY`+cG#uomn}MPTG!wW_ibnOQx9g%I~le{ z#kF*nmnSpq>WU+15+40L&Q2xP+mko4hYvsk6%)X9A}8Y}naL;TZ6&^5*7QY4m?04C zOV?>|6N*#nJbLt}UI;#PXBDE?#7GB$XU)eK`ghuMlVOOg#NG_7 zb{y-27o|Ka!{^MEX!L2l_(^qAuJ+{R9|4hqpfj<#-0P#rE!zHBiBtxrk7`lHU0mjoQVYgk_ zTkUqrW+~$`jiLZ@FT*{L;v+;8m%B7EE@N^$jX1ocW_kwRn}Ml->DL1h)+Cx0{3;L` zvx7uq&i@Sq7vECeH+Dh51g2}P&_y6h2<#HiI_CUozyFe@ucfUWq?OlFBGc`qe&;oL zgLcXt_KD>&ldp+&5%3zu%Ouu9>m>ZAss2QOqYQr4;(Hlb_VBG&UKGR(Bz9YI?ogG4QyramzHQ?Y2->-RZ z(Ek-0{)`&{cOksU2)(d8!iKjOh7oQ5HS6AqP)+`~f{nMl+$il{T!Ci2GDhCoIWpHU z+TdX>SK7zM`!&y8W2ons3$_M7I@oT!;h+#ioOkeaMWO?~C9`_xaffjZF-=ME6E=rF zwudRY{p76?is4A9;|Z;X$idfM9>ow5iISp50Mmu@tybtVVG&}ueLEG395qdUZLc(Z zFNR9n0!nLOdMR0JQNEaAgVvxp&Tc3Tm7Oh`xQ{>qf>1m}nhgAPhlqVUW~?hYqAD{w zb`V8Laf_p=)>so|<@VG5nlT>rYv+7_XZsMoY2+k6>oriNOAb)8lu?FM;gW3Ag3$}D zr+BLyLrHO7lk$9TAbz|sQ-VHvD$OH^?j4BlIfmhQD!v<0#9i(|XR2DI{JTc4U~+oEj9WLQfD6f?DWYnl%f0ulCy2cSId`78G48TYR;*$RVEcMm`l zQU`nSTl3W0*H^;{VUUi1-W%>H*b`w4Zue*qM4r*RwhjPg8p+!??F1%BkBMy)uS%1( zcB~l}6p9s4Tu`Xu0MLv(j{EaH1fXqrj>V#ZvkiaPN!;thTbf!7qt##chPhX48|u&j z?#jtQ9mh+CC;A}UoquO!ouRn_v5 z4d+4BOU1gl!``huDyxqp(rjM(Wnb&Y0 z%6^wu7!>OiG*C$T$ssk z9_VCVC51HfWH7(GziOdICW$+%VX_T8f3lPznRX}ys7#uVGop-ejwCHq(_4rbA%a_D zxQs3og_qA=7w2fWR?a#@#T^)^rWylHmy7UUsPAFz4?bc*A2^zWFq zQ~j_L_DlP1YC?4^XwqtMRnbzc8xJ(qu5K!Kz7B7J$p^3e_VdSj z(8ylR`=-JHc_!g750HY(SN(-+?n^D^2lDlD`8spIFP=mWptDVFJp!p1^vSKzMRCuy zyGWX|csF-xFG5V;&iNN;>#jlKNHtm5c+TK5!9cw7oW92!n`tsCh2N!vATK(eh&&A0 zJkQyz+2?9o-=i1S8+;fw)^nwkloiTiR4LigVl*gQS;YZ6HgPu^IsL1HKLqTT1Vax^+fX_kx;Z+{uTdL9f8TEnFjg|3`wu zg2gE(_A^jV_Hzrx^Z%tu`=7*_xV;}_#6603eaJ)sdde70YA3qppR!14Vs~(|F+(W1 zLA3;uYwGkhU)g3olNIqo2XHWWmGei>YR$`AbOTRrXOrgVoALhsYQYrsc1z})CQO(i z!_YL)zNP>fu1)V*7M^07T+4kg(=1P0D=1@4!E5Fe)Qrn^i4d~sBARw2D{EIfK{o~; zxF)FXrsqJ1n#R?%GU7;rgv{XlE7&1V?f%+&U8yLjZaN+x^8s_rcY`$?rKU<490wd45{@&QC);6qeN?(SVL5AUq7Jq{&gcIkMxZ4&R=x%NJX16p7?%3?WWYk^&ZiQh zJlS}Wq1hmIH2M=;q|)uude-l9!j_bg2(F(y<$(4#)zv+N>ofZo$lR6|_{jVGZ7jXY zN|j^BdOcuFf0#3t|1f7XH}ErdLh3cY1tuL&sqI9y<#l&C1YwrtMH`Q|9Io>IM3-|U zSz8B@_DYK}hP=4M~IAcWFWKrc*!Jlp zRQi3^B1=h(fZPl+9)^ZM2qjQV9l*Px77O>)ufoFv)oCG!jiG7j7mS4vJo3p3@CJb( z-C}=>AZ0l;!cr7#87J7JMc7&DV?Ye<6Gj13L)A`@0L>-aVH6|i)))o;KqG3%k|<*D z$)$Z0B-vjn4gHz5#)BXPi)M+96KG4MTl8uP)vwFZrG?^7WB(k)4Pq~!KncqKRfD6e ziTl*i!?qDXq{+ju==ijCtr4>)Sn+SkC#g#j8&u9kpSa_OXp$t&a+^3HDrkisLWu)m z6fek&#g(67kL-CYh~-urVHyl1PYOR?#aZ$Sf+d&-mnG{x=O&sw-qLSXLt=hKC}Rj* z%-D70e*#@5tP{-htZjqsPcSoqf2u-bWR-l4G-k;ElkrDItB#8rHyOD{(BT4HN)z}} ziTMC^jODX7GbFdIrx>0@HseKi?RvrRYRO$Zal-^8P8vcE3Jlw~H*span}pEkOKr07$Y^KVJz@8Xd152j zwTMZs2lfxJR=grVJ%l`eW4zaSW$)OLhPje;gboO@>l4a_DCss>qHn~-oi@B2WdGEs zpM!wzQ^h)))pcInUngx4QGTKo(jqJHdjQqU>wEf2zp`?Rhy)E6cjgk^Q#`1I$0)}^ zH(8QxI9ca^n@w-RfV&(mwx%&2{X<@F85;@qK)Tg(0^@1;8!{`9`tUkjg|+~47H z4`WI~v_1N}K}@Z15A(?rFYa{uY)T3OyD)0*-j};FR>mY+ZI#EfB=j_#fBCWCV!IpN ztn?!8#zJs@9U#jdI_YxrKUi6=GKu01Keejq=TP|{fGKn>9RGK`tn2J#Zskb(-;R}q z%G-`>BJe)P)hqU#KrNK!oZcrhqfUYB{mwN)B>KxR<|0Y3?}(pzP9aEaliypmaP%wY z@gaBkIL+aBfF?Qz1$`@NUN|R2fYIdwVujnjRo>v*le_q>Cm~V5fuLUSg6R38|Vh9vf zFE^`Plh7=O)M%c}q^+rGP8}2kETT?-ZtKeJD21Bj4-P;VTg}ZM?4Bn(fMzM@Des^_ zR>m@vkDlyF@~b~Tik9Xg08nI8IUWm8#-j8agdbKv--93_o*0)>EyMXBgDK!rFp>od zLdBBv)boDb~%dtsq;M)+~r=BOkx4Z?&eV=J=W$=LWa z(6DMTs9{cLqx2~D9Vx|(knijlk|jV{y#B*7N8|_o+S8%rT?TqfeVGBG$%=lTDT&VE zuhhc74*efiU@!=XRh>%`1sGCC!@z-hpF-_vjS1h_SyO8QoJwaQN80Ry?(O|B@D^70 zNuM@qG}vh1DrAZkOHg$0D5)NG%a*meFX6a^?4X|08(>IQlx+USj@a5l zx9^5*?)n%Mj4ZJ{SpMq71G!am6WfC~FlMvv1aluzzSw`N$1lI`bu83SJ|>4`Z<@5o zX8>eCaDTA@%YARqgSWoDTd(Mnw;7XbFXe!)?royyZarZODcdgfjJc|F$bZum@DN_f zPo^uiWbkR{O8Y1TwCn&iaon_Q_oa=n^&AJx`qZ6Z(~fB?-sFjcl0QTuH>|h#B6$dkUWl7Y~vjG z&e1+#^2)Wur`m74iS^N0@h)`~wj1%`^a{cPxADfMBAXlOf#}6P0LE7^FS0C$Nz;#W zxx1dczBzlf$J>R)dj@cD+D_F^^|eH3lT%qHRsDUs&Hsw@h5oPzc+-!1*$;c>e4O$* zh4Y^2`#+*Y=B^oj`=7#yO9B8O`X4lMR^~tRIJVACcFs<^|7VrxzgNgj4Qt1AF~qN_ z>Jy^FxDLshL$tvu;nhCGq}6y59Q+@*i?BX(-KuboaSvT{;c1*tqs!3`er57OmtrQA3p>S z%4iFI0D}a<3HFHV6*&|OQmi-bu+MYm+kE&9J8%lqosgb<=BE@l|ErA`1QB`eBgl>S zQ5vDzm*_d*sL1?WzB`^|De|2mXi{q2ck#Yp`mlU1-%zyC%JdyDK_-6q&G%gxH+l94 z@vwMA41-Zm1k}&Z26*fcGbN!zVL{OS1Tt_kdj<{03ms8c<^&`^lRolWo}!(SX@cLH zMtK)3*tCIxus;-^VQQ6Z7@*BWbc(*;IsM3j=_3Ab^J+fih|CE@*djWdCi;7*qiem~ zLhOkBE7EEg?SR<~w1`0gCAy&WKugA5GbHo5Tqekhr8e{@t0{WhvMs++OosAO^0!4> zOq7_x@qeMh-csbh^{@}g_u&(PQrU(A8tnFhgUv+d_>1NrWKoh-c@|hRGx^1#~qKQb__KuRkp3Pi5(n;rgoAj$!&(BFiHP}F9 zyI9Y&W32GZ3sBXW2nWVQdHwl$rs`(u#GmTgPL!BvLZr((ik&kcy4RZ5lq=(_p zlW%!m#Bs7NQr#Xk`W1Mgmw`#y3_RIM3y8{+|2!edD5Vw3O@4DKHGE9UK!rXZ3JH~J zxn|7p5GsUNhM{tDb{Rdp)GnPl$0uY8`&afBLz zImkY8!%`4`@9~}*c+%hGsGKVIB&2GII%+rpym!j}X#dTUlrGjSRrU^VPeCGB7VMBJ z_Q+q)B8kLNCRWf{5!QjxvKL*RC(vUY^;4GSNC z_t3E@?T*{$%^3ZL`q^XY_kxPM?KK2T&W%h;*<#Tc2{AD}#SGA}2p_j9;7lgv$3CM! z{*=biq(z{;#}l&+C|;wAn4kQO#(Ehg+P&*h(WZAr>Gmqu(3T)C~q z3Q?1+H3?7XFyksx!F|L+h_sCSC4Su(M>d>49z>~fT>#q^Nx|nU6Eon=2qNOGF$dF% zTWhjel^O1VYpctck6sD}RZ4P{9}TKKdIRzlr|(z&OKkPSL3m8Mf9(kPg?MtU|{;AVBN|^E@MYRE0z*`>Nnb)IculN z#r^B4diV#Y#9HL6$uq~psNVo$CFj_CZTBD z#CyK6F)Zk)P>N=Y9eGrHrA4DFJnVy+i;T@&J=7}aQ{x{ZP@cm%Md`h&-o%G{R;jZW zb5C`&uX*ynfkAte&Qa?OUS#t#_%6*zvUwS{+GgA&{IJ;N)wn?T5@JyYAG^*~Q9Vh@ z>u+BjtCk81WWjEKBZU8?;FY8tboosI3OVn2FFP_dA+@@Y(Q37vlMoV$iTOs#;iw^m zY=Ltji}zLNwf?w8s*N|Lb*!qYTc|)hZLe-6z$$k7MQV>zDSX=d^Io;&snctBA791> z*1^N3S7<%2^sfdVYgkurSDLXH9frEK7~_H`3k(Fy<8KoQR-Cmpj!_pOLW1e*a8|y6 zXx&IK4O$# zg_ESCm$nW}b}h{+S+Hnjccm||tgR55OkHo~_sv^h4PR#;mwcM%aV;NI@3{o-e&ZYs z6eF;l@O(rbeGr|yMeApKlJbdJthdXvPo52rQLejtnN2CMuMj3rZR}wKvc<1#{T3!N zeboe55S7#WIb-Vdh*bk8AW!3er`c!L=l2eo+DJtAcv^1`Lw2S*b*7_XmBmvS6gl6= z1!%YEBLe2IQ0rC(k9UH5hT;!u4@7eF`F?QFDY%tMgtr_uArSY7oTrmSsN28-&g2P^ zn-+)q*h(iErcaD+?U5Niub`46G zP$`z7qB5~J=8}}LkDmQ=W;Ls3#}gpGx)(+BDfjfogiI5;SW9UW7zF>O^AT2JPTxf{di?=%6Mvbp@N(Q z#Y)z%EJ?}Jqo2|Iw=2U=js_HaY%}JZJ$A!oIGkdE*3`)py2J`!wWg(yWWnRxw)wgD zC-pul2 zVvdl8d1&wF83lXW?tNk5)}a15IRNbT(qTrJYQw?{6ShjUBIhp+4OdKUR`v2 z@Sta2Ul*ueLh0~%J<9|#G*n6bl|{CxQVnL4%I?8X>eAA2hYUhniHhk^sALVgXZB^DV87Fg8@+Q5v5@j~xmHqN!}2 ziuA%wziPB$KfumG@l=SzY>C7OTm*eM_5MLeJ%wS^pi^G>c~^jb7lH0wpk}>cXz$8` z;7_~5mnuzQ!#N|1c&EHO%5}(6zdL#Za!nYO@(DW?+`zhD?q7gtPj-tb)gN4+8?G&K zqH}|g+HkwUF-30W21>QDAtgvm7dsfm3WR3(Br|;M zaZ&T6MHrfCoBEuMvcM&rcD*2-BR$K zyhl^*{=D~_AK3d|02uti6Z@5V=SVxN2pTQ@X-y1F#BRE4=dZg7nC-yPOd+cEmSBS% z_*5B`iY37tS!4rVPo4qd5BPX&&ydmfk>Rdg@xzO5*XsgiurHpUcYz>lc~BSQ!ES~E z3QlYbpvZS>(u@hQA}_7%pNAJ8AS{Lj48y>3@DkBMXFUvdGzFtt(M5R6Mc{tkz%h)u zEMDy;fXR=|RJ;@m3k4N$zz_%B$G@Sz^bbPw8X53R0qsLXgD{D>)jC~!2=yPx1>=Py z?4=3XNT!C)Pd)J4?oHJt6jUpXn9VxmyeU04aaDt#f=GL*nYY_<=)2)2_Mow(oh69v z%;k3JPY^4zzL=qVvEn{7Jc7gE00wp%1v%fjX~74xiQgB|TN`PXb~wszgRi_ zh39v!ZCB=d9P^I*Uj9UHkU(+VX z50kGRn;y0+Kv97->?p#d_Eg?5Yil~&h)$nbzI7(5;Cf*sh2R&D+?}2~=#))|PU2Kl zStfpC(L)6bN^XGI#n;IbSc@#Fc7+u96?oS`xhIWOo1=NN=CxIdOq#k$n8~r=sbhsZ zeK1WK5m8)9tE6Duys2_dmPw`_#kP=ISYXQ6eqOI4$w;tHWLV-l%y?4s${oHKeeo*Q`0^&khpSt()NgrO6AliRjQ={Y+Z(=J1jRS?5!zMj{kM6;{c8xXhVqNgwQ zbPHfaBR1eQ)R7Om<_bH-vprRNABN@gwG{i5^Qq0$RIJgUMDZ5&Gi6L;q0Q4M{mj{e zzzyv@H;|ttz1h8eehwy})7ij4faU1N>HC;{wr<=h_%{332d^@f0f5pEPwIA!V{^?G z3Mqv^af&Eb1`7AvGY?b4sRGA0`m{qD&c0RxTWrZ5a5{TG+0qEk5nDPfzknrNO71c{ z9sE38?>Aq~IbjI>UG)uFu(epj>_g)t-M^Q1aZY8+?w_?hx*vA;@Bg5*TkD(K{J%$b zL&N`uH2Oczl>g2B$MrCitrJ@R@uZNHw(z2a3k?ey&%&3Y_Zob6GBwma*~mZ4U|Wgw zyWel6&;D%ZEo5zj-FrOT+!xDs57g8>HO}|Eo1jh}$2#Ez)&%f#@pPOfWhsiCEV1*Y zB+p{43vM>kbN+1SnGWa9?v6&Bp6}woy0EvR(+=VF!tSm|XUWMlv4G7l1R@CXn6aPl z8g(qwWPrV!XmGz6Ufv24$t8+@(44yyX z4!>hzB)xbW?2%RtRD+-#j+7b)c~;yytPaw z-Eb8Q?!Il13pUhVUiSrQ3Kmkhy(>Kbkpm9ZW_w#&B+pMtcFv-;*~?({mq>;HoBlU@ zFPtgdmq0(0G-^w|jae1_^h^&7v;3!XQ${+nT-!gpd0J)Kgy=i&RAZ)Dwa}=Z(2Qc^ zmpV6#8og~3Or*rb!ojjoKf8Gfg|Wc*v0_p_;I#!SK<|cBDG73rJL%R_2yjrL1#%gq z=x%?Hl!qdeq5t7_gA*TPRoxU(?#sPpr^?a(?B=x%`No4xx2}c6NmfBpHd70`S?Z^Q z56)A{0$Wkl()^Rb*ry&rY}Z%?W7p8un5vM+o)b@ZCrYv(R_XaOZ;S_l2o{YJnkvzj zOt$Ei5~?>VhLaMGa+Bh>8dD52z4gf{5kB1lQ>|X3Z1v+CjgqS84h?_1fTbs>_*;i^ zX%LnNDQPK(_m)xD>$My0r4~zlfx1%!*e4qKNhOsKC;UV1w%u`;7ssVO2r>{*(i|M$ zgYfJU42d=OUsb>PhurP#qDJxbL+%c=8K}`@@}eEt+R+ej5p$wbeqOF2PQwV?d=ThW z;n1xmG)byt3xl-0D ziIKJA*n1Cl<(&Txl9zxL^HsoZ{(IkMV~(eFn@>(1>KKJ}G z(S~n@Xe5`1`#}AM_3u>z&m{DA=qLOz{JG=%4+#IdHn#torTf1Z3YGtd@UM^~jT&Cx z4&pJAM{bl_3o#O>iZ^$#0$%~T`R#gfNkZZlZw{42f7Frl*aK_VH%&`qf!99OA*QM;JZ!)!9Y zs^)}MI0OzPqm5OzOT!!<_g#gSwXDkc6s=_mZ(?Z|l_b={Q zJ2jQ!ljfq+V3!$MNr+!zq4jL33RBI<->?x0mdv1cgFrk@ zc23H~ozx69`C_zQTZnJB42jBqkVmsnbM&R_bD$y{hK8(OVZUACsv%E<>Puk)6pAFf{~Axc+k z!=q>uu4gf#v<$}f^BW5^Pd^U!7u2eC1FjU-pux+cXqZHeQ_$u*YD|mwV16szq_H(+ z-R0>&pW5n)63#Xa#ub}kniAxx?1gdbh@ zTa|r1r|V#biJjbcZ+|rBXNgE>B+5H~+X@+?&`&L>DnEV1mWoc`c4Gd%X;zh9@3aF# zdwWp<&_HPe9mCS6r>{(}f_DAGr!?A<&vl_Y?36FZ3^426T|_2zx!d?!2d{fjfM%C<$2RcwdERt{)IJL%ZAL!c^n#?m=A-8cu#2syeOg@sqtiV`K7OIuIAn{WsuQUn zna_3m`Vb(B2Zs}fll6`k!c?cHtQt_pSMZDGRx{TY3%Q!(yGWz|rM+@_%6G=ItpF}t z#5d;ae^?BF4B|QDQ2+pp;Q;}J|AVf|&cWD7*WB99>i=3XFSV@|*Z-Atw`7R7OZ|6n1zOg3$b95j7yr7&vz5^Zpn~ta-f@$vjt(w1CpYqA>ly#KTjW z#aJae7uSYWzaLl^~^@6yO3iwg`d&=RIcXf&;t$nI*2=4WTfN&HtIxlzE zx7!5tgy@+RcXdNs?ZoF0EJsPNFSOR`e$9J88Ua@=dLQ&@15=>>GM@yzpD~VyD`KK1 zXZUrl;hN?;#|wW(|5vgbe$J%8znXocpc5ehGAhNY8nZqaN4~IVLjXV-H@Z&&Vno zE54k-2x?P6RT?Ww`UFq58o5x|l-*xL;3}auIe_B?ZZB8TH-S-Pb<_uZYK~T_HyKed zQ~juiflY_+e?edD_w#uL>qk>>jhPqWy}DCmc+ZR1C^)|$qcAyBwY)OV@OUv#_76Uk z(x+z3ydYJFhm`obm`Ud`Q0uwUdi&c8teL;U8+>)88dssEi^RU2?5hH}PxLr3vD#R% z2)(@=eB8@o_@EI+e(#6*1!bIPI{{rWlM2o`e~B}52xd2&j*7l;a4t_!Pfg9C#J@&dI>(LC?_5@md-JP4Y%hP0ybh zaKzIYT8BG}l|@9epr4++X!UO*Sj#?^x)|s+vTn-&2%#Um!b7ELn~`yPfoU%jU!7?CWuH(u3)< zW+J4=^^QT{TaV1?vU%t7mXY5NBnxx{xovQ}3YXi`-gujj8t!TjByf2<3T7OK*Oq4Z zPU@n)I{R@6O)8~dZv$>5 zDC)22RKSQ{2mp;qYzz`)RMP=|)Y&1gx8ERN@4g`+Gk9ArUK@?g4tr4~XR#N^Mb2=z zs7D-DZR#LYa80yWT)s}{t+FrrXfzDOLW;w6zjr<@e82$tTQb3F?00ExtcIVi@m&Be zdm8B&sH5T9cMCl7f!`|zkN0eolau4irEPu^p2T0SxPj(K;C4?TQi-!r}a`Tun7 zzZipz2XlvifeUlKgB?6;3ISu2fplO7%I-yYj4hnSxzR>P=TWR{#vE?8^A`bT`~Xt7 zpCI05TeR>xJwrgZ`xtV4bG1`QEYVE#pFs)nEnV?~g+*AHZqI_%1Yao$7Q8) z+ZF+THSk@eH{27^J1gw-QqOUYD1GFJzax=*6p$AZc1g2$7m*?-C+1)iQ{%@XBPP$^ z`r1G{t$VKdcNF!I+Cs8nh$)xYCS0@C7_jVXtERN+UP0KN8@8jw?#qdWb-~kdU(BD1;@QI z7*T9lspUPLkgkhV54if>&q)m-%Q-kzh-BzGF0i*jBQyK7(4k8*n`C6$P-br!Ix@3w4Y(2|GxGHK!*nQscmPgAdj1-%8E+YHsJxTl-$ASBx)= zZ!qaZ(INU~hrW8Fb0;Iq>-k+;1d%;2!W<*B=W&3t!d?38NQkpBi~>>#JRTvr2(8A% zuQA>h@HP^pIxPaj_wY-zijr^WgVNM)=)I`G6E7t+Gm?!m) z3}`4wnH2uIkP>y%_4P#>Oee(ckG@zLMNU=UxHxkxg3eamXR^QE9%$iVoky9C8-Pmb zbgucfck#eUyL}GRzty$7OIu-8sU)$B_8{621Xk*9tU01)&_}3b1CTBit?xpqcrGR0 zERD()IEyAlIi3ljkD9K9(_>P#F0z*~(`+P+Em~pg*H~x{nBr8jMUrsr+GhILHSR>D^vz3R$F>w1Rr;<8F;_mj!BSzjM6YDdoCN`U;`{ zB-PPLJK3^-J3BCFHrQsRAQ(M1zbdG88ohK#L+y*U0mYf(ih{>1fFx)sa{IqD!P*~W ze(oO8NXpETJMv>26gDLkhxL{k6t0~$$5Zberj{*Mr*iHgP&F2K_P!{^S(g^{u)op3ESHxqbz74gmG=|^cEM@5tNM3C zjxNs*W=LAh2K zr|^3Aj&x@Um2{RgCdn=9MI0QUV;&15m>-Gq8k>fFS9>ZE|7)6}<5G_<-?}Qx`d-k& zsY$Ys^AJHo;WVwdRiUnfUxSQJO1k>s#YX$iSgn6IpQ|M30$!xS@-68(CM1eO=4me(@8I4y#Sxk5`P#z`TM= zdagxhK%vUI9RaHRECCGBnJCGiQ8QF6?QE2@-+4;*Rfw99dZ$X}cUzdrfE^N#{+e*X zd^gh>pq7n%EI4g7ANQ-M7>IfaY`D8RBlm4SNF%I*W!N7P^dAF{f~ilL{7&pI1OC9u zlq3QIrC^cv)m&0|<_3sx%5O$^4H;~RJrec=kmL%AD%+>Nm-MTf3+id&z~i%D%d`q| z{x3bSyBEw{gOlY+8JKnQKMr&rmPhSr-9nHpf^-wgnYQvpxvW z=;02K?*Vv?9>~!U;df#_kZR!%xS9x}O3LUw7kuxcwjRagk32_FA^B#~Ek62O8XJj5cY`HjO$hWnT zJKhW0D9QZ}0y=cpLi9@`0d}Z65t%Zn;>vPKLaMKrLXO9!*w~6Zo`&(%Jh9F~M&$@G za)}<`$A;DRbi%;iEvM~^^c~T%_~qfin=uo)RBczZQiS!xMnO|i^Qu|xGMpIFPcZ$+ zAj}#1`C`_Eh(BYAN9cgHd%xY=l-Yh!4&`)$mz1_u)axA2bOnHm1qN*`u4)v|{zbnk zAT#5N$#`?s;K85dDnsmLc>=Q>Mo{HXst6c!PJ&kYFyjY_-f&UKLqLW;>{v)GwV;=1 zK955RazRw3&Z%9DXDX;21K5w7x9}GdJkP}+NYL+H_mGGT9z6}gR z!}1?e8J~)M*vF%53jEi{-#%c|g&(_f(oS7-CLzyuhXJ~8zuR*mEws^HdOC1QNkQ(_ zg7A05Jj$hu7IbV45sq#3PRxsa$w7h(OCaQe^CCZ#B;1GZ#M~kMjYx2Ckbh8DT<$oq zsFME(`ZX5UN@s#gK}{VIDPA)lyVRY~*%-c_AjJ^RnAX%QIYutZub|L|Pa)i$xby`@ zYvnIdOgHYTfaq0B&{a-1rTA7H=aH23E7619wpbl^0hOxKfWNVx_q|AH7Sr1Lo1cu1 zabBZ=l0>-NKQ})TXMVmsfxA-zAzJ58)=ksyS8tw_O0*AL*Er*;7USQ9`aR3 z!n!M2Ve(mF>_x|3F!~yWZNwNxf&f8^g211G#EYgd5M0IESHQ=*S3;XGrSD!!OP{=7 z9&|Oiv(JkCRW1!#zQ$a}u_sy4S94cL#5LUFMC$>inIcNUri4C^TU91cv3^8ET&13Z zc{zJ@nyfi2TlUzq2)hRklAuONw71c|aHY49dfa8(Y4hB#PEu8TwkT zWnuK;V1#`ahXYXFx=A{D1dX3zqVZ*>%Ud-)3XTFw=S9RMilvz2sSGVO@qA0sXeb=v zP~2*BqyjyAiKxCvqaITvb1pH9hzVgsSk-jETgcjgy)X+Nl|Ju$8}Nx94M*6Mux0gY z2Bm+3>XcV&yE8sjjCC(VL2kUrZfu5GATU=Xn=@WDN<1KZNnbLR2NifVlnC0ri}AsY z^fL`$ZYGbM-Pt(S$wIy`A+?JK8Ei~y6!MDxkub9Q9CmZ)F-x#&REWUK6s>;NJ4+s( zZiApjVAX@fJJd4RkM)b%Ey49;6_pVB@pa)gQ#F73m2BTH3G95@fxPI9PaL(q1QD_5tyf+S6vV=DAGtzDOEvYT4XdZ*@z`F8G_;X zd6ARAQW6v?-56L~ngma^h&W{O_^@n|GWStxVg!1GWEsMHWsR~|+vlR_>A+S0yxfO{*H<;k4 zs?Nia%34Juxr6Xwst@9-J-NZ@EWbT)y)x%-ulBLR-{oW>!w?@MlHfMO)@?Ffzah=~ z21y7m+YhWd#MR9g#S50v0n(V}J^t!&022y%RQ!?0yrt#wpq`+_Bqw|-m6-DSpQ+RKF2*q?^mah zNpooXiOd8ChIS@v!p>%wX4IbMWg3(cM?IVvK^M{#Qfi8-i=&MVzS;tp^;J`o%Cyu@ zxi5%CtF?!Y>tzNGQ-GGl^wrc2ZP^}}JyK3o55L z#(YLJGxy#I)TON6xqtVy6)I&LhQl$Esr_$lm2b%ZdF-mMy};f9a3xoefPlpRv*oRw zk*k}t8GtKk_3vn`S`9mgy?=R~GL_kb#)v&GIh`vHcEHt1I9lZvB-0X27>&qHNbB=5 z^6$2JoBapKh%ryS37sdediZCjF5WKS#802NQ=ZT9{J-xW5kV=eya{1yg`+NnL|YUj>LN=gSiLk3SmcN#NvKkRvI3=J=+L~6UaGipSZBKT99M@&eaZ`uIu zoHS0P&bz~IWLw?I2Nfoam`KOg(aVA*92juXVnBqD?0IC^fM`%j#wHRY8#nK z8c^luiVe_N?03%cNuXty<<29F=AAnXMC{ny*V;)+6~gkFDdRfGa=YES%kB^7UEVqg z^RDuU2|Yjawf6q6{O+myey1RVX$!o|BGBa)zZpKzjvv|dboL5xg1Cmf{McEyv{xmi z*H~+hI&zL9j>8-CXaU(7z9XMHm(EjuIU8~K8Xojha?8gh!&9zCeU8WRqk(tL9h})& zAJJN%vA~}o-R5nGTYqw=pBBk^XX2)HCyMeIbXj8m^yD%-S2VYFOp5cDwd%wniNZOX zClWi%h~q6s!VZ>8^1i4CpV%eVJWAsp!1EChhm^vh*L4?bBqiJ0Te$E1b%QO7 zH@eW^Gu3-UdXzUbbqna?NjNp6TjXr@X$kHx0;^-hBv?jrUbm?0&V1i!d>?y-Ckai; z{%L1bgP-HfU=zW8MW02%$A$~BA&Y(04OTBcO~%D1>Tu9LJVzc}iMoCW%aJqn61qw% z4uXK)wM%eL>a{@%T$g7eR=6HElP5W}!lt+X>CC~_-9Kumy_~yOf6z$4r=OM(?!Z<% zN9cOihXj)&hqzUhV+D!Jp0rLfB30z7;lLVXQZn|t(lhzhip&{#A&>}_7JHFznq?!p zVE(S21$rMu;+iu}f(5_k+xF7!dfwc>{2O6uQ@%ox?RU7yTK`|iG1RP#Mn$S)2XF-2 zNw8yWl;1NAt9c#6k)@%gUnKoYOd@{p7b%1re}#*xVo z&QR-n3?sm00e;u20ulH?e(l9f2ySdqoM+OA&umczR&ov7`%tpdfyf@F)`8y9;oeXl zRyadg37Pz-yMyBO8njrBq9A@99f6EwPYb7W zvJ_onqDsG{8Z~&WtWBlZo5)gRnmR*asVYz0{El8_@Uk?@6a0Ej16%^Qk64#3NefNE zgc@&~;EZ4Efqa4%VXmX>Gwc2*Nyot=B`=(F&}>lhq(rl6e!rP^b{)nOFn zr!vRtS0q;YY|tX1DZEmW5@k}VCyLRlqv&4n8#i(iWFdbDfqs!^8Xdj)+hR(e(8-d0 zaGPN&Od8&CVU9C-l|-O>)4T&O%AhiQnDS`Vlj<@|rvTDpVM(>~h7TcF$#6s&s)?KY zOjQz1b&U1x!H_ZE*YTuNK*Ck{7zdIJzrJ_OD_%W<`D0aA?YRafIpe+6fW2TQxV2tc zr4x`^==o-I*FdG+PYl1*7x+NLhlZ9pR0W;QhtCN*wI6-@i*yqDa}3mZ?eM3|hb5{H zFJ#3nIR0=oYfiy1@Rv90h%qZ;wqV>)gP2xv7Rvb;EK(xLAI80YPQpo28mewWuI z0hQ{E;;knOOx|8DN&ct&gNK2z47RNhIs;C4eIYrdP@0v_TDj6oqT8dNfFXC7S^vA z$HZ!&>ISr=dW`lR4pax})t#?Dr(l|myO%u3xC{@>Bj>g}ujl?cMV_$dvQ^sX!CBKF z7j8XkeXEdxxyh;GDide4f>-x?^wNBO^uw@aY8S0)RpbqZ)GINochdGS1>arPcy?^v zY!FAkBmAE~(-}Frf@grg%mfhe|4%qfj?NCI|3;UrRhx7^<3id5B>c1FSPp|X=**L9 zV(A6dMvkPNvD8ydVno#p%jl9MBpjSII zoo7{jh3?+Q+X0my7XY*#X5jMxNchLCW_6LoLRHBR{VU7S|AR7Ytt?2c!5ZS!F zZn3x}Vz)jrM=Fs3lKiy%gZ=H}Evyi<+s8zGU3_TwgpcBo)>L-oZ=N5CO8vhQ{@N0j z90*SUtMJg6-F+B_c+GPf_lf<-tSHltU0IkGegNccah zw?Hoq6_>uOjAaQ0Pwq~+>V{woT$y5=-B%ZhP7c2uh~-mj_oni z1MP;@8KEp7;g8z`0KZEf8uo^#@BqN?&H(T`J`NP+$?nCBfXe+t9{82g@*jhU6r?*|$!XNH$H+tw2Vo?Mv5cL< z3TmRn4+aLp%pv5c;~?L$6@2^FsKPTH6Vw|uNJiF1=&-{nEHU6U(v37^pc9OTEaS#~ zrl(lkhPsCBbQ(mMPU(K~8II9zGhl~IvY6#?StE-%~q@Q|41=xgf827o4JioTj43md+YPU~67+(1pvH`{YBG#N@dP zyd%(!MdnH+eu{&ggAe%#-9h{{P8KQlj>73Ol0;)AdrD$Fu+6{aoh|%Es!eOb6=jnRuGe)FHsL{)&Y#a}* zby+(~cJk$QvIlNKyFQH9yaRsYdoLxB!~Ypt-QnlU40T`uYrVOUuf~hGgU*1jyBNwF zxvj5GANf^fbEzw^t{7yjyxX&na(>eUV^bnrGVm#w6S@S0lZTry_UP*tEa%v*(g2lQ z6$fhWpq0O;*H1_q7{sZ{=^4Zt)7x#fJ~}X)_niV;zoeh)P8G8GfSE=bHrZ z$egx|?;E&vMHO2SjX`bRr^LW61P79F7ip4_=))u|XPLsxDlDuJT2vB-9fT5?MG*;< zl1&(EjHNXa^4zk@6?^9YIUQH9KpVabNG+=|Bk=nA?Sa3fL`jL!f^@r~pt3tp5})1| z!FW0)bt@sLfF!Em&qdA&^P?aP1tU3IbZts*fA%y!2wE&9&CLD)I@>}Dra~DKquJg9 zk3K6EK&~C6del>bTveb7WLZ+$;C^tQ8jQE!d2vB5AmjkU#czK30=IGL zo5Wa3^*I%@=fE^Nt3kK~IYtgbS=^8kyWkaS0@f$MimWL-5gF*rzbRv*Ma=6oY=#j6 z>*i$hg7D9#niVc%h(@*jlr;f-j+7)QMGwMeZq|>G z3FS^MHj8$@)|cdBTJ&+Nf2_0BMYwObXv&E-6X_t5W7|+#>8sJX9!83iY?m$@TVU8V0PM&z;Zxq|Q7}u6ubOUJZ(g-^*HnDZ zEy_I=oiON~H>h@Bo%Q5BwAp2PPnx%LY-?04t)$U>| zuU*aFAkYTF=mmRta^{H(oujSfKNIZ~L15jg8=o z~bk}C{=%k=Pa#S=}cE9EaZ%+9O zv#=M6{2TGqk;%aunPd5m?{S2EVo_?Jf->XH=y7wxu$X}G0MblPhi1|l!@>5wR+*rr zu?Bs?EAg4)3D^q?(`*zSJ}hMGZ4BEr@L$ofw!l9D*~Ik)p|<#RGii+VfcEbUTx41G zLuL#rz}bg~Sh~tqOU#{8Cr0|F8s?~Y==~mtT#VYIxNEAq@-BQxPWutkg z=a|bYmMqLxpbC$dF&_RQ6{rdAFl^#A0yxpt?3Z~0B;`dtKCa|f=86i(4{4~d5nX|;%Y z2CcbJMN(6EW%3de!=~;k$tzybMV4F(j`dotCAn)vqie(3_ zj=apMsVm+mkuDhlTVog+WAb!7Nz3v5c8*?4ZilrNo>vcj%~f(>P$#dtZPAVX0DV*l z6tVX*fWy_wvDZpZ)zPQMtMnTkXq|Gmlyl<6-Sn~yR~;wHS;+V8>yX6#?{sXfiVvkY;>ZKu(2AxlB4 zZ`JB1R+GEYl9cQlOmWAlHk+SuAjeJ3TIkzb8cHxgR><^#yQ_npz=haz^IZ~9jUORYL!m@Brz$b*38_Mb$ic`(mj((+7UA6lLS`n zG^ymX;mQPZRWvQ;gP*y!1k|ZqvE{w?%boYiG#-6i!T9ls(}A8?6xhfP$Xh};RIfiA zw@F$DKB+1!x)-l#yG%|8;N&XI%5#!lBLaOmlK84HQepmRLuK1q z0^!KP-v;7fk;wSwTj*{+1LIeb2u~+Dw=heDgJm}H1Epbj)yHBosD@VMp1YJ(UlIX!OjuYnI>@7 zMpH38K*6kYO0SZbzO%nMfCRpNkvOUlwsI*eaO38HvxlLQ5|3XWZ@AO3UMn=xi(F*UZ8|h7=9P--ZW65sy(&dZYhCi>8_ z?3dXH>PhzF*&^-A{*VLNS5X}0>#NLu3s*_9$G@frfK4ryyh}9TMPe&Y(Js~67iTKj zFL_=5*wAg5?B6H`uG&viZt~AfwAf6`r{`fwc0T801Z??>%p|Y!HEU4o0-t8v%tK@&ZF0W|gT* z2i(;<;Y9yNuSdXzulfnhoF}G3!L`1_Dlw4wZ(U<`hXCO9n_Ha1bkf5PReWm+3ToJc zwq(0Od6n6hGj{biItSW5JEvx!!&(8}>@tc!x4M(Aa;oC5ohsCzx6%P83o^9al_471 zaZI=H%n|zZJsYx^lv27OXEhABmb#Y`$RP>MuFtNVlDov-tQhe`@?G%3BS~5ys6Vn< z8ror|DMrPlsChFpaBx!(h&WBXSy+e~|5K0wuQGp`jnZ$Ik5~$pw7+=?Txn_}^W|Q^ zxse!3O5>hc;^6e@!z7I0PR>zufUfmr66gUSC8>?bnqp^yveV^G5Q<;Zq65&m71F4{ z`SWDxcvBVGW5U1Dj~|+%iHWGnO?FaYk!9$Lq6Ed2oH(zPWNt@MMhyXF>+$B2jxY5S zg?zV7NXxQ#&Z(19TI1GQ(AkGxd+3Z}PNXJEU-DM^-t*~YhBQ*DV*Ff!h1dv&KeW;p zswtbL(T1Is#`$oIR@xOI`AE4a^^f@WL;YqWdpb-2xTR$y*>;zp&)~GjXfZl5=)=9U z4=fU4$(b{9jfvlMX{<@Z!I#|o8xzX0iX2*Zz^5W5=typ-sK?Gh*qGLDZm0=Vg@f`+6NUC2rbv(TuT)u3CYS#wM0k!LIQ@@_RS~=gd+p2L7-66_W)WQ=@7w-<3eO$aUs=hhl6{?+!sZO7sq1$q) z#1A7E{5{*rey`ml8XCantA{8d5-h`@TJm6;82S;uDy_x)an8N8U2>D^-ao}Hie+f8 zBSS7IcJ5m78`g%O$rpU8+sWkbi60Wu(LwmiiwRJ58*c6)^~@yFuIjNVFJ8l}eyu=D z?n3@HDF&h|1gO6yqzO+MCl9yF7VhUNK2uQr3GWvC7Z=yI5$-pOVEw}}@Kbc)bnK*T zb@HAW>Hy;&8fQlfm3bMC0y**JM=5Oi=ZL0e!>ZU-4X5Me~~hi(UPCF06N(QSfi=^ zr#kuH3tRsGHB(LLpA!|JusxFkQ7}w$ykZ16Pidp*ioy}d;A=)JsJ>grXwL`JB;T5TDybA(Oe?s0!RT^(Q)`23)q zit}2dmQ1z;LAr7$8Z#H7s_rVWrr?+SDXz18>UP~?Rb-EQQVX&f%HboNWZuro*yR@- zXN3!}uLVO%b}Hm!`1$)v%mlCYHLhif5A?Mo@Els3%Je_3;f=ed0~-MZQ#@|Iiv9vA zhN!N&ZJJj))3LewQQs}aVWHnuBf4k4UpR-L($6UP)}Z5qkpjxK4#1W6uh-W2#eR

        D%Qq!rejiR{fT%$YjB)~gxqLTUjOELSZ{-u~+21d1( zmJL9lfXrTH@v9(#&puji=)ky5A`t?C?R+4UK8#JpfN*8_#69-pJX8_G_fYvaUoCytWgtNccg5;}>k(C(f zj4B=5dt1(=2mDTo34m&X-I(P&hKl$i1GbvZaC~veEJvrla8STj>O|s$89jodB)IRt z2|GQC0ihDw)j2SaT_2lV6oh7&KKCJAew#E&|Q3C_B*qk&hu8$-?NF9^bH<@Dt$irrnweYlVU4cZ zx;tBxKm$rf42kdsV z`EfyyhC?Eapp1nT0pg0uMJ z_E&9U_*K&J$TQ`g;W#SDy({X0jaA3Mt)J8K(QNAy7^zjpHk%J4m&{9FaV;a^q-0vAb$SebM^EF(Bt&c7Zl4SRhIk4mk}-|}Fv2)B+@FeT00s9;#-|!9)MtcfMuP0=H)LrXF3D;nRej1IcOUew0{4h9r~^_ec}k3m@7YIToS99r1}7H^i`1wFe|KyFm93ZT|Oh# znd-PsLnZkp{sIy*`0uutS5X;wBhIHHL z`Ul*b{w2=7unr~d>+_L!6x>VjH{`F%eQRQsHoRhzJ@1~71gjZQHoUnjka(5W(q5!- zE%7gdS#u(*{Fk6B0vYtWdbw#1Y5VoiO6fPz7%$ z=b1oa{}j#G!`J@uQv^~#U#~Z$%;nh!w78NY

        x=@At#P@*q_%W~j^q>HM5SPsO{wLhFU(R&U23Q_zP zi1K$GWGI}eCOB%6ELCo)?@~N<(Eox3|3OjsgfkzXlV5KDg93k6@ku%XkS~ctqRT6L zt=nrci!0Nb@CE*Ct#$i5Bvv_S#TamHgZ{iATnY2<@=4udPioA}>V>g9X~L=l@>b~^ z;;yj_({GoMj6ws@?gx17w5KZ%hw(!p&3g09yhg>&afr5y(dL2>E`PA(P#XesHp{)< zL}~K}3U{<@VeKMMxmS!aVEV}&rducJSE*s&3N;Ck+wQ8A!c!jo!9j4k@EP8ZHE`sX zemwfKJ9Z8OUC~E#p`BUtAuhV=)t$HL`%a&yxDB7WL*ij@)bB5U2zj}fVF}l@)j;D? z(+hV^&yl;%EnBs)p8-PE#<|Juxt7b=r4I2GFUab|l>l8T!M1}`!1_2dup#aO2aW5C zIRK@X|Al%0{fLBqzFcOQdp%+g0iU!8UXu0S=^D%{pZ>L5EV5(FHrD!(ZU;3fK%%+y z!LCxMmXHBvdL0g0^&`=kur$+hP8gtVLvKmGu!%^VatV zHL@xQ@Ic|t%U-+>m?^AED8p91)%5xCOX-%gof;?GE2M~>gUkNT(R-*Y3V>t-LC;&( z!K$PRexRp9eW$-#qEGxRzX=8g#lH{)x{ebKP zZipia@uYH{QbBVbM;uiItyLD8t{*`f)!WZpN{q+n)^f957#1z8R=T9kdQ&{xEQI{7 z*KZthMykIX0M>Yzk_h>>W8WXpoX-Lx0Iv1mkx36zV$dymTtT13vr2>JIlrnRuC~N4 zJM$xgGz^hDmkbA$Z0(CHyrow$pTccN>U|AQzr=E8s>Nw?n=4^3dq0|62XGRTTZn$i-s(~sfZ`h(9Hub%S{sAk0WJvO?lm~a0_ z(m4ia+BI7^p4iUBwr$(CZ97kriEZ1qGqG*kwteRP&X2pgs%!t+Rd-eQ>R#8*kMk{2 zN=X)>i$j(k2k|Dyw~t{FaO=UC&jolBW=B>!@@^5!Czjg9A5^yq$GGp?abA=6 zgxx7t>^NKaBvjO3<_a-6{64Ym`Xuum^K(B9)O#s=X)2M}zHbmGOC$l&2kZ8U@%#2n8@-iHOe z7^^ShjbE9VHmk%66>C@UoocMU_Yst4j0y0h4){7zIqU?AHhT?SWT=kyqSyh}2v)KK zCH3EGe-J6$22?bg4!lU}u&G8|lA3s#^r^8#izc@wuZD`Ag>u&oIiw1CO2Cg1jx;iI zV1GOR?8a4*#A*fA}%|ZcS*}Gat5cuS?{JYoQ1cgVhSwh$U>t$6Ww5?YEDQXS>uc(3Qasr@yRF>L* zy16I1+Ob-ofJ0ni2?9)z1x&EOrXaw`0+7)|McdLhNr;)94`>8BG@6T>o83G$sF&^B zB(1Ak(8=ah>T%ZjDyp}veYa9q%&WI9ONxG+uVoS>$s_==`j6Y*(=Wa!8>#;^*4t5I zktV73oU>~j`_1-eSF|g!LqJ&i>A#vtgp0a@nn>+0IX3gWA~jN&HZIw6qS+*i5*b@( zvfxx8Qcfq^1LQ$aOr)e)Ubhj8xe0Dcn{vtiV?;EP1u9uWC{vDxRE4pSp(c`N zFf258x`zl@puf3fNH(VP6uPTqOdLvSce=C13R^?0`)K7Y@Z4h*uvV({sRS}_>=HYM zG4jT8X>H(XiA1_;Nu&-?Wi!->C4;Lq?x|=EAF|nx_Ku{D1E__Kr#k%3_z+Z;1xl$Z z0;+A~3e>9eG&=_*+y}xY(tjI3ek*HIi0GBf-5S`E>gF#%YYiRZ_SDW>)g`sq#Qt7} z5g3H7Tbb`r(h?SQP#&C8>7crSb825o$XT{#r*8n0`2Z*A~Jq|N=V7XZ$u+EWXpIbEACgO_C%M|f0(m*cGsbyMJBC+$LHmqm~ zJPJ%bi8;lKZS3)~@=C(QC&y$^M(crgCz#1kA|j>B2o_sMW@!f{8sW`~bq1}uG1IoQ z5GiGK1&&!?S=0|9LEq2vX_31yc!Z5a14P6j-yk3eF0p-1jB=xl&fQi3`B#MjUG0B9eegK=pO8UHebj?gSv3K(^F=PjA3gYx25< zRa0i@386Tf=0Zg4$cuxq*GG;U2v-Ir@`yE1ql7}cJw5kgl?D$V(#Kuq<4BDbkfikp z5@Sxf0))w|N?5rflEtE91_sNwRo0_^1?97P(Jq)sk|o9rTM5shDxF*qs$`}=Z}@*_ zi9fzq%KE23s){us136mHO>S#D`#vSp_WgT-~$C-jSEui zfW6HW%bBanN5PV*WDG|w9PclUFvsz!y9dK;J`wyea}~?ZMo=EAinf7;G@-^lV)__VAND25Kb+lCfE@w0 ziF)cPoz$S932OR)R3W;Y68rNS|f0PXr+~d2eGFUl^+BM;w z;u|PkU;S672a)s7e4sZZE*)ycROthmry-sb{-fuS$E@9FfC2$YYoO*oGj4nrdOls4 z6TG`sREfx^tHt)1?Oo$E_2X?i{^S)wpf)|T0u z_mO)pI=kq{ID=Cy>0O3pnehDPM$rcm2rzpFK9|uZ`j8_K0EdbO0AY%Ilz%iA+@~MK zx1891oRuz!_YC-kFwPej(3-4V5&p^h6=e2J*$mJ6JUGeX6`E@M&Ar z5OrDg;y~%`vh10lK!NJJRO~U*X2USAcdMcTo-^$7R=iiH6B2}otsLhJ{tQn?zjww% zyyJ=iQpO`~o;$j<5II%?xc}YO3lV)H8%HaOdIys41B+S27y>OWZ)P))EfrZ2w-4 zdIOa+5#d?WL6cr~+}JcuYs02A>sIYp>}dA$zk*n!0d24Pf54<4keK9?PNxP1KARN;FSl6y{9%k%7PlXi7MzoKP+SvXO&2k znXf}Z9^udfad|{^jv!z)LX6ZD3mxYj%C5&$O`a2!8}PR#1`0HEYbwjI^tt;9#OGjE@^BZLn$SgSD=yZC`-DbfEI>I{uar4=qF z%~@W{iKQRQJ7hA;yu-#mwh^AY(BSWmrV#kr<_UROtgI=+*jNsPctX76^5 zhg4ZLBFPgCdJ38A#t8Nw3qoqNKQ>Z3gj`hJU?Jps`~l&}1h^c#PM_6+{>uE^kjeC_(0`AM6t;s+sC9WEMU@rkPe zVD>8lHU1mgV}9a0iC?Vf@+RqmtcH9wf^g*ui`ytpaXm>gKbly$9)@o$W>v>j55I;j zl0e2Yy+eGn{)y{p^({wzhGF#r1NzE3+{Os5v(j8zr9o!9p7K@xSLHDG>@(|>yD2EX zPDCvQ?pY1tCjmfe^-!xz@-185Gc5QC$R2r6{`z< zsUek7-1n{U_TmXV5)jl|HxB3p%Hb)w!*})5Lv_)$*nlwZsB&6tc3^y;{nmf21$iRn zaO7H}4vTPMLCRVEHNW$Q&(+h5$+!H&|EY15IyXAX9U79B%%o3T^I+6Pyarkdn1Ewk zA9H&KK{)%25CVS~t+7jM7FIG_(@fLAgg?1P!Z*v*SZ+r0d#oOc}qqjzdi$iK_ z5uZCFY^zj)rakn-y{AZI_`HoA|A+NKw_QmpKZT4466i85j;D>nyNiteJ;OLuqkvXh zlN8>hj4aHA)IbcBf*xYj9|ltmC=xAR<3GOFrBpZT-APJ++hcyw4vES@9LIPpeI4Yj z=YQD{8!enf>jBWH43aRBP2Xd}#Oa21wkdM&=h*2utZVNcF%=7`e~t?wux{8#2Ge}N z0Q}N{w9P6giO{J3SbXdV8!*dgMHAfZz;Fr@iS+6|B zV&!P36MN%z8nQL&F<9v$ML1s_TkkO5mg7=}ga*e-i~H(lYtE9=n#DSlk9ArD0_1>L z3&w>lbg+&R$bhc{$SAUO7Ve>Ji)vZmrWH!TY^mfYaCY=yg^C7XNu~@AD_lVkEp?N) ztXHdc0}ACDwVJu)Xy_0CiMq&OhPb8w&VWX=j4W|EGntCWp5oNlgSH@-=>$fUw|6KSL%;vyr!wq3Lj;|8-{>T52E z-}tAkfU*B%tUDkOoS^5bel(t>od>2m)idZ3&NLnN&rN0~uX^<=yT zVDjE5ojUt6N24!aNSF(pkaMpNI9QvsQ7$g`&>ES+S>x87xR9hPR|2>(6dOa1S9;m zxFR3$43SwWR6&F1{;O*%XWv9C?P$M*C3U3EtiemB_HwN5Re#S_kNn&X?7z*Plg|z} zy8&_5;xNl8(HaU`dd92irO&^$C6A9;gb@6v#(!o_{)JB_*95x5_d4{fQKs}YYld`N zo|zYZUXT?a4O;qoz_;`fhL~6aH;>^@tuXTpmp$^1(fF9GdK`70yK?^hi{9Xm8b?tk`HxYmIWB{SKAbv~$u!l^&Tl(^u()?)F`^z_&`I6%J0Mxo$ z<*Y&{1VhyBf8Z?a2c2~H47|^o_ody37Da5O5==<9+ zK(L!~GjJ5=P+MSLb!mni5>NOv6*9io#t5 zTpEOLN}Y%T94vp~^Ob>?qm%?98`_Gr^lf44SBrl zUvrmpT#Io3<}mt8(s$ab?D32Spl!D25E+&T+I|~<-zB zUBP{sO%e3tqdB;cU)tTB(frPIDFOs*=jOeIxt#d-zh;Wb=U^%r$opo>+g=?w6_u&2 zx}P>~ykpL}$8_r_tMWMDTL`8DKwusJ_Qxvgj-oeL$fT2jAq&w|rwFO2AW)g^rTCe8 zxvHh3*>Q?1SK>SSr9E1WjHmE9IZ8iqTH&aeg(3t2F_KqK+B@<|J@m(%w*Z?ess z*W}6rbGVOSI*O=jfaomViyP?7ua?n_JgThAGcwe~IjHorSF?Q2QpnT+Y#*0_tR9IrxZf4<@eW^o1~7_|p|r5`>+XBK{JT2ge zI=n}dvY1XSk|Ku#L~_H+1xg6pq5i@EQq(hd&8SqI|1918P;-Lhl`Lv!Gv%Z28S2>- zYquq9&%b}5>e*F!8~U{4Pz`h*s*#SnEVuR8tFF z=uA+aT9rK2T)8Au%i-vVTNYNP*0^nnuC(D5alN>(SGd>aL%d`!o_1$uZ1NY$o|COt zb^mE8lUHthr?FN2fz_>d5I!Bhv;S`#(aP&c;)f0dq)Yoh56OWuBLK!n+Z62wAi3e4 zX;zzJH-TB01lLhx*;=2BWWc}$v7}_MMPc~ID|NHQour+#eJun*WpEGXXwNzf;g(TF zrI)T+B_wPE3{6B3T=6b|UIa-IDgK>bKY{gXT?o+gxcT6F!hLg-^}zdh&ieserE~?& zuJ5`u%xYi0V>U$B3Q)d#m+-A>?Jnm#Ci|5Ybi`>#mF054wzA;X|8L)e{i9ljW7&R$ zZpI`r{avCqd306w3DkG5h!xR|CH8;nwI{UYf_21+cVjph2Gf_C2e=~l(n*mG_f^q* zTgQN$IYs1!b%wl^9!ksx_xX;Q5G7d0rVW>wy#sPfzYsfMYh^yQWgn{3)O;Nqvu=U* zsyxb^6gg5IlR`PIYir%GnWRcZf8uSUWrJ}>Ah@5=i}ivtJS8nN!gRrs`>46;F0Gl? z5Qo9jAv9Sd%fVP}AK9FM-qtLX@3@UNFtl&usc6rtFr z*7RZ64KD*gY?8Eo@o2iRUI;DCO~zQnjj$ml>Dk?X;m#D9y6`#%k5+}zv5=K?P^~J# z9<}1lR8_X^LZjarBTWx&1Ybd|7_&|QQkGEbDG2tUpHEG4}M*-Ccgb4OD zrs?DvYj13jBeE-nV}YoX8N@MJu_V0;$37ezqlq#zTo#g#L{M@Jb{L2c63?LxBZ@@R zpq!U0xSP5@B2%MI%gHQ--Zw$2gSAGD$z=&VD6&`)6(JmxCLf3@D%^ZbUawCDbL3hc zzs3Tntc*dX5-cC3PAjE}8n4(+w1roh>l=7}30BQ$ySMZQmMi!7a{i4|qcJm2i=RkO z^o3h6o3++toZ1@#UnL6;>9!uh0pY-~SK+vG#ba{7Yo0>Mxgb09e;_5~cI<0onsYTB zZcKz=n|F50c=A9>=}kzQEIfNY{#hDHD$k)Yq!Uvq z((RXGgc1hTPIm!qh%*o^%ce=jJe-(C=`Hp^8Nf6Lezq8D@xe5f!3(LUH8f>HWu&uw zB2ulJqi(IVcPf>2ONZl7DQT*3ebS~@Z*?Yu&8|{)=T#Y#B&Rlp~k9Q0Fo+m~rR!SNO0iG1a6$C%_#|xLmVV zx|H_crcfv7Dy`_C{m=o5k!G2J6X_1%&kOX{N1DI^8p|y(#KN7;aIY!EG_JXjw_*0U zFCubs*ti1lLHQ~aJ-<8+$cXFa)uf9 z&1N~;Wjg3DqW;y;RRWa0NkuZ5F`|BoS_7_o9k9oBM@`G~v(eXQMG^yse&G*?97mUW zjk|jZat)e2^&}N^C3(APZRz56aHnWyEpvWjIXgEfE)%&-@@(kTZlCYySRY}^QoVn? zAWUdfqx;Zhz-RV{SohDN^qmA?JLVrkhqI7AH~dRvo(<+1UM=&zd_(Sz3H*+BlU}D= z)*iK)i+W?jy7cN*Y-7IqhC52jv6h!Lj#i~)|GCd-g9cMY$Y{4SF-Z2MC=|p4aYvbA z=dY!(M|3zo1xpN4%57RhB`;irPs`kt|8GV}*O^e&L!B#bcK9XvcBUXX{5j@v(1 z!G>nftnHpTof>{Od_Q{0NQ&qC!4W6(ec^iglj0SIt9WXPY~Ph~rSc+qTy=zdNqtMkdWK``BF)S;6d@57A5$OMFJ4RYjukNc4q`Nk$Wod=x)l9{R@7alzr|^GjVfnhVMLvV$o}E-cSBvm&0`^YXAT zQsbHHCinAt?d%eAOjob^UlwOLjg&Kz>!dANNDAgs#JnXM(w82(mKT*5r0i0=i7VbH z*j^A7(KEJGb4PcgfE?C3NtPo9;@}46%uTaIFdrg7;VaFKKvnz+H6#YBSgRde^3}km z=?6oPB|du4i=kne4?a5FURx&tz*!;o;NfJlI7#yQ`vOP2j%0m~BkYZn2Dh)l!ua1N zBTENQsOnPnXX*f@Fo!K7j1z}5f*SoqzAZwArx_gprhwB1Q%wBvub>X*6;D`1*SF@x zwHP}f-Da$BoN#*!Gun=nmGamf-pH^hYJ}+Mj|OVA3d_;#4sV#r;B9LLT6MDF)K(Si z3&AWZeDYBoT=GfXg_#Q6K}A?Q##Nv`Zgg5Gh4o{59B1IxoP+`7%C&vlb9KhB+Cv9(4ii{o1yr08EbqIG>-F&n?K_E4 zj-b#C7F8A_3%3vsj!^HR&KERJK14?Gro}ic=pdMU$P>!cR0Sq@mr+P~k=F5W;W;D# zj|5!k?bmr|=r7)fe%HauS z;B{rogLLFjwL7a~bzpVR(bn0sO)MS2BI6oUCeXC6r-Kw7GVWdQjg59mRjJ6_Ij&9Z zWF==SD!&rPMOAvtZ0lq-hi5W~l)WDkhP1Eb`!vA&xK>E`Ck9h7Qj)zWWj33iv`>&F zh{|d)9I5eA4|7hUnBT-@ZY!CyIjYa6!kOOep;Z8r_GD!9w$5sb68ndTk@???13ri& z!Q&BjR5#^{rE;TDCBvqi%`Mvcc^rMg*?ZjLi|LB(aKctwzW3R&w$WA#=07Th({x~| z9~$8}uX=5mFT06Zf5Er=9JO`{#8m=zh6&;D`vp|H42wQZx*zPtT3t zzwimXBluqs+@WWoQ@Abl1`4nV>`D!(4UR^m8( z&VQ$DSu4Kq>zEjX2TZ3jIwv{n_X@P@aj5^eKmA-mgyMilHAKiu_F~6C4`7-`=OzsI zvKD!vHNsu0S?y7Hi!LpGN{}#pE!;6TX&t+euv;c5m#lmugT6%VuTzHWAS>pViYcT(rdGm+*BUa(PbU+{tbU7)od@(A!n1602M|(S6ZQxP ztF}!k(AM_KQ#l@E!nH!H#Pz1wHAUGbCEJBfJmAppwJExtGCiMx5Q2YlR9?HRA~`gIwbYLG=EPptl*FE^!$1I1{3-QrX8srf&ck`o2j~Vdg4&xj=wHo zLJE`-HRMO5Sxely%XTw5ur=nN?cJ*{ngBW?kDx7TVZoBcnJ|4hc=gvEtqy8mFv6~I zxOoK;(J!azw})(gLeC!$Ur>dSz+UBA_c;#-dlLt7$AvA|KPlR-e@LW~Q_`i3=%q6L z-}!FeQv4Li2JYU1qUqjB+FV?b2?)_6QI?0}Ie*fsZW*Yu{G4p%(rPr=nBUk>*;g16 z5gQ_`)MZMUG3u&s?^?UfSaii7Apny~l^g+cDPn=DA|ZPeCeFSyuQ0)XJ!EP_HxP-f-B^Eegs8<(vMnAtz7hnsJIa|w7#rw@%1{9DXMC8IUN{Og^)~t8Drv)KvKa=rHxi<2J8v@ zk*c&&-p{}~4xy?iXYJ8&{Fb@rn%N?P{w?77_5KdNfa5!<@{#5Z0byZip!f>*U$5x0 z)68V`Z`bMM-}gUeZen|&D8NU1$@53yc&Kx`5}O>8=LTkr2BHdj9N>?1%qQs2|@u2d_&nJ+C}Sx^&mb0GIb1Z-~~dHJ+;C z*t0ho=K@aN`OUd3HfM0+%C&zilatA)n74wQC06N?{WPoeS` z;5iRD>OnZlgZl|~`)wa^kI0RR4{@nA8nP-z+HR<#9DLUM4n3Cp!Zh9*4BD*VH{0w~ zSG!2_$Ac;NUlNee0J!vGBdwn4(epq$rpQ9wLQ&eprOx3Na$ENBy{WyN>n3!`>!OFykOZoAkt3VJeXP#Wv=BT{L6XVT2x<5}u zUm{%E4N(V5wK*pZ)-pBZJ=0Ih``Td7Ml(hA1f-qAFi?YuInvsx{IR1`YiRYFq^VSfE}HqzLa#|+h_ z%ZSah#f`hir$q{xd1Rd04be90x#?3N!2&JC3MvW;GiaCLBt=kGW#@#Pp72&K3Opi= z=U~?8%vB)M)%Mo>JR8`C>k^q7kyC*w)0)bNtBV}OfR0j)#lv)HTR25_?~ds@H%w6r zGj#HPmtg07FuF2R|L>BP!%dF$X^ftPn*A?<6nw8ElJ-0O-#A)wpW3c&cT4rBhZ<0@u^DEp&C7Qs%w-_$;T)ebA=3dOR`F|ISwn?P8HFw@J92l-kJpw^iXr1&<& zfnI0fc<-jPTOce@i$xkVygF1^F2ifKMlB`&a7QU-5A+Fy^=%^4zOj6ES>`b7@=wx( z0!lc=))2SEW<5-+-M-$0#zG)Y zoc7X;du=L_lNXK{y?`55p+s1?HmlpG1mKVCio7<9zAleQY+d75V;N~SoKAiblH;=0 z@=Ei|svPI=MRj7j7vg}@tYVjWS&*-b1LRieRSuJMkrHR_Y27andilqz@DI$z29jJ% z&h)mlc>eM0Uvma7DkXkDIW;DH*L?T11Dds6H8%X`Wgiv%hLT}Sxo>;TXz7M=?~D)_ zrJtp5pvy%?)n5&Ux#St*mM?r=HB((VvVEv{mwv=L_6@S0x*~m4HuQ>0wB`O{0^lHK zr^03WEsrhq1STOkJi%(4wU}J!tPDI>(&Pt|4H5ka4tK?;Ol4ZdOkxn8he4E?EH@u( zKTtlZKinTSLAlCs*HjL4AeRGbemAreR0 zHB1t0`@<=;}tA9y zma)wQ%1L34=N4J$!Y`H^+{#jFq)W>}Z0nn2aexS%c5CzHv-{Q!DD81LadETsc736J z?c|DcRcrl-MdasB=0Z4jg?aLUNMb11t+#Ov4KR59aY(HN^Wt(uGOW>3G1h?oGe8=3SA(xbwjUqM%NlhIdaczd@o`Os``9yip-1t@QXi&w0l+n8$FI#N`mCe}xWlmu6fbFF;w;GLl*84ovNdiEbbee zK7g+=h~bD#^jZbBlrCl zZI1;l4;uB4?WP!E)CyysQ?5pkWmB&Q$%UJjP5$fHh1*I1pwADBKa$WCzrkwTZF^~A zef@;Rte+m$Ll12AtGA%G(Vvf=;M~6+m$jUO0KE|F-M_VrCEHNunR3FrA{=hrwDK{L@$1{Ury zYGp+%?~98lU^n2raSHU$7Zu6f> zY!cSUlsFCYWn%K(p`}Vqv5wN9d4JR^)Z%oq4y*LwAVQbHVk6KESo;|WAU56c0()+Q zv!NVC3D`&qgTNz9gZ@TGPF%!0E3poNGNKNG@%bx3fD7^I)^j`QZ~H=U?-Nc^5u1OA zB%{JM*ph%x$3_nu{_$8%p#sz|!+KF0IH6KI6|}4aJl?52+XFvk9YSOp(3=-hB`n$l zr=TI#>G`E4>=E}i;AW3$-Wpf0V!@Rs-&-Gz#{w8s-h$Z79#5?iEs-k|5#3({<&X?$ z{aEZC0E+IZ_%65iLqZg+wu)~VGei%98XIi}@$fAlaGr*gXepFc2kH4Ul_9=m$HF$p zWqhnztBc=?!eItH*c^V@EN^QVSfng^?&z64D6$KXwaa|9tVj+r{hwye}w(e z68B45;E5rTqW7FVeS!lfGH})}+)s(MD6Q4c0KU#G2cO!5if#|pjX!OVJ!nN?hKr|G zzrrv|bsOG?9TauDb=P&+0kS!Sl!ML{$qODV`CO12n35N6F32!M0VhCH&k1kw# zu+TZ}gtfqkYP;Eb#-5o7W|LXkWSxbYarrB4fq_vxoz%PqfSTqIVxrI76O^w89rGlj z0H7DJQm?;Or0_SY(Vm$R3^G~n-*c4gH0Z~%D#W3bcBv4$K~M+Pd4F_eV+^&T6ax@a zXO)nRKo%ixy%}p_N@8Rb2ROBIu+s`kPMMpSo?%6~a`KnVi*Eijh0wXNg{#*M#n#iI z(=K!fo31-#2$`2#8zj_(C!aMe_D&q;0;)a zfhclp#zucIa6=f5>{Z7KUJ|Ee1Hg7Nfrd9$m4Wr+T(BLx#xG#AYu*0JY%{|dn^X3j z{6N*mO?8lOnBqGsOH$x3Ak$FO$m!2DnRmf6Pzh zBiO&dr8${f%wgj7gQgl%GW7zn@MbEnQ&$p4){}P`#lg9Eg?&2^hU>w*{&kKsgV~>7dQq5X%}zI?bj;9eR+U--z86t+98`CC{zqxO_Y8kkf3nd4V{UB?w-Xl z^~=3WH~_ln!x~*0+6p+I8DKo`TGt5~fKVr&8rN#}$HjT&5~UbFRlphl^A#}$fVLy( z2i9)rEzloiVXXqf8MB8qeB(8vYHd_^j~(K}(qhJp2uR7{mF1gJCdcS2*#S90kvA-j zbJv&2c_|ajr>sB64TE*Uxai-LWKZPri^-8Lb{i;|Nj-Dt5Ys=#1n`E(?qERHt|)oG zGUSoymGJXO1IYed&dARxwfyMgWmNgtCcwK7&dgm*zKKN$vWV_Py_THbj6c3W*>}0a zH}T0zSI)j)n;dc9B}JCD-U1q&ZUj)tyIi{qWp=m+_)p@egxaKPS=OC6Ye-aMrWUD2 z*w(2=s86jpuZwh@05bD>obdBVoOt<#3>@(xb-RvHGMp)=f}HpEwO~`Fho=G*6C4`- z`ERCY%O|U)shpg$^u|3>Ke;P* zAqDjyc0CY{dB2>OtX;U-9Qb+|mmO359LSo*ksAU{|3r|DWk%koQq%OJm5rJ*U&pxg- zVqTR@>)H2e?LqV0Q-^ld?CZEOFKZ%Sxk(y)CF0T>0sAEl96lM()n(d9HuqbABJMKR z1Lc7cCr1(tpI2s7J;jy7uAjYyCZ_H{@~7+F1)+h(h>ix#XfQ4w*|6lBhM?s^y0 z#^qK;%qle+DdUXY8S?r4LqUm|RCo zqRq}jKpQm|sa#fV@+UGlhi-1v>njX&7aFhp1tMHY8mc6xAG!eL{8qwo{8{Ij-aDQJ zUJu+miLcx|57UEM4FM~vq50F|OLAjQkOkE;0 zsVuQFwdfcB9o#bNEb=t*QurPBFSkPi5c@CL8rk_@kdLq*^&a0OfYnk9IJX!IB1+*j zHPAu2;HZcP(lSX5L4$vCtQhtJ*KdZoh6s}wCrxM6I&2_fn@(tpIL}h06SJr^Z}IN> zo0HZ^XI9OwR_559nC+H-ylUxM-;jddPTjDhxOpWf3)d?Yq z(|)S^r?(9i)fGar^LDZ0)fPNv$Bq2dW1s$}F{ssjc<#I+w5;Bq};$?%w9T#pJjOWO& zUQA+)e$_HXna@3N57BdkgY*{2IW@P2%r*Dvha6^3<{dxZH|V?|){uk3Lh~bbt8AQ) ze%msfiu%f$vXGP4lquo~XVwvG$azph7(8e#n|lRjKt}&6f-$)YyIVVM1lkfiYv@PD z(mh3T#L&KO1l+&(UF~c(NP=W*suyYU0tpg^_}iA|LP1ua+8?5kt>62pK|5 zrXoRwd75nc7%sp|>>&Oc!hEUr`s#yuEiua?QAjXE-P{S+Y;3YVkw5Voiat{7mq8+E8VX5vP#4qLI_o!_odl`y4+1i6Aq#6lSTVXIej z#u$<-bKaJT+G8UQrF@u@=5fuIsCl8T0>SmO}#dy{) zZYA@Z_zgHURo+1rf~l&77GMySCaQD6Pz;}F$xLi}JRI52jr<{3o+}|-dPbnAlmgGr z4euV82Q1TqD^@)4*$?Fe@bn=+pDgS-ioekv+JsX3)&|!laEhP!>iHj?4;)WJQ~Mv8 zUF&~zzAQ$BM0-id#Ge!b04O8kF!^(BbA&GlX{lO=ZWV8pDi{(ERD{sY!letlEn6qa zh8N-oL3c2D-=F^^ROPupC~2`bsrF=t4;NpcKw@>|yQW>;u{npROMx~tBT7>y`V~CX zO?^ryY@_#SY1~XfIj>Bj_+?3p{q)TABg`y0?+p@xu#o~kmzdFjkbyl)bKOUFer@c5 z-cropjii|t(uYm5X*HvsevzIm99SZPGSqLIV1#*3arD^**0vJ8hSv!Uj+i*m__*lc z?YHm~kMrK+B_TSX6(G+iZT+)(vi%!pSt@J(9scj_EggRm9cH`UpiX%@y;~Ef1Xvlf;dTK{D|O#n@g{`#)fK+rmMT+x zpNFlTUHjXiwiyRW|27tDS+nVGpAV<*F2K*nQ7sTzUEl5D-azrBdp*d?a~ND3 z4c0oDo#DVkO8dK^gXWZ z<}zF#Vr!OD$K`DS;d~~1tL3&@30fsYZfi@nl9$hkKM=A* zCCD)$zjlw?77IeOWL*b*3zkr^xr zaMc?rYrsFkFU$PYe%fKW$(R0wGf*AvFJU1rB?G|0S9yqlj==>Jot`Pn8k6uSJJUM9g1HyDrg+)Tsz@3b4eNlxXe32+y3kGF zV8-Cnx0?P+iA!8*kckli36X&r`GImppiTfl<}zp9%dUfYNuGcUgMlJOc=Ux&qh@R^3;XeNj^O&{XO;@e>@Nn zp&v>}SaBbVnPP!Nxl!=ib=v|Bw}ZS^YWXwof5fA8x42|#DZCP2{M5Ot4$}`s(nK$h zn0ORx5sJtQONTo=D~Y|EDgsxUBj6d+ZO(lcL#|H%HEb-SB>oEKJq#;g^D@20@Y?Zf2G!R+)H-cO-fi*rZ03m{85FmW z=RiMB2gM^ zOek^uuGAiZ^8{z`JZG^32vhd>cbIH(xQ|QTJ|fyTl4dz7=*b3ys%T+`Bigx=&?ioNFZi zfQHL^gHoveNsK@4o+L8kJ)}JBF{$~8B8r_?tf>Ni$jY{%#c$LF^AJsUi6&4t=T29CL)}3R!)h0w*izEDP|P#(E$+O>$f$T#HH#=M$!zGp>1G|>%cNRZzi;R+tCMF9x&)_9!fs3p zN^9@&P}2T9!G~k|3*KL9ZFAC|ynV?j^f{7IyOt+?e0(CYo(U6V1Wy2p&)(m$s9jSn zy*6fjKW7mmsr@X{s2r=f0lgP8rXon*<>g%6f2KZdZ7y=2rP%6N^|b&{eqc}jc6C2! zOW+IyxpJB5bzy`i^|H{sHcb`Px_D|;zJRVZG#jn-si(s{JEKaT1EWZ(UZ7O(k-<>R zOKx3D__%mub6?}F)t8clz5)?OM@QEB=+F5tBdhb*$(u{VqL9<$7BPTPg7?g^1Bm4Q z!)Ln;2JwBbjpdUEmpJi%D&WaO6TvvT$LJUabRCPMS0F6-mX>eX|DBZ-Xm76`EN|8R zVu>VPrloP3`gwNttXZw09pb)1F@}&%CxuGg2K!lsKE~vIAO@u%(ckjEl_g-YwG)Wr zLPuwJx-Ck7%}bi%lfhiNHEpPvbmV<}=YF@Cvod~%nG~$=D5D>5rb(8(hM1ZIj6OtR zylPqobN|rxF(FD=bLvYI%*N65NN1x$qO7N@3n>go&yG!<2}md@nudu3hSm;46{ZQf z)T>k1YK6h>06!UB~WW(bb_~GDJB%%db+jiyyt$#;Mz;d5>6R zO;`mgm^{F1YPXO*L+B8?K4@uoG)<)g&dMxw97wlsmnIi(a z$h>BMtiGLX_gvIwxh7#9t^uE_Cvb6`;q~;wcH$2Y^;; zOM(yXfHjBQkLf1Um>Trs@^*f2>cGLky8R^v@YB|j8JG`*fSAzgxbtCUgRy70T&NF< z5Hp9|VVP%J`S|&${rcG|(+*RbW4_O|eHy+^1*GvP1e(V|=jn#~ItyfBJne%tzEukg zU3utYcvchnMt?)i46bb8X2<0x1Mg{XYeEPW>8rVE=X($I10_3_>sFqsmi|1K!qeT< zaX1q2dEc4cI}oJ#N;tr3FD6=2U2y*N!l}*b=_%b;9k{s zV=CaTWnQ0W4`*=`ElPeN#a8ODV`!%=tcm|)Bch;*H#Ua01Ajg=#cwKJ%Py;awr$4_ z9b@n@A@b#VfBjfcQDM9J#q*A*DrNpI{(6|F+_!<^-kj+hjo;0k_Qtuo?;+h@pK&wo zov-4;;yC$J=HS9<$L7jc|5Vf_rBT0Ux!Wzgn#tQZ5we%D?$4v7Y_NHK#z$0RSta<^ z_t@d4#C87zN-FZD^G9(Gxx{^`UBR%&HX+7fGj)&MPpya{O37fIlw|#h3wvCNqIP4p zslsxX$9;50Td*IFy(%`omYAzT{p{KmCZ?FR$~;dXccA-|7WV}}8t`xQ;<{JNoMS#^rG4j(z? z@X~#C9J#B5NmG}rJ!>%%-aS?-^ZBVwc&8_ylj>3bo7rxQ@C)=up7uuqOpjgB88gy( z))rj6h$a3!GETSPaBf88JXey4ic=T&?h6dL+$(#iaAiEoGBZP*=U7hTgr*MK@Ais; zW<$+%0l{IpbOzWn3}EwR$&EZTuGA*8O7at<;fLi!PgJfM@nrt@wqDY{JxZ=jy!;dY zuA6JBB6kW4Hn{||ntU`I*1cP%EBjkBEd^mSZr6R@dOgHeWjwlR+Lvl6YO=GuK?G@n z#Ofy|RhLv%OD{uBJ|(9-DQ6gtwgMXRNH>kWIiQJInxEQ-1|Hb~@`8s&%)Q$dV=w;E za(+gNu!?ip-#wvRTRwo;O&dn6y0jo{Q30*`TJ!Nry^V(uElV|=yhA45cY9=d-J(sj zLV4qEy)e#DQk|9Zjlie*Nem2$#3f9AO}}&1C%ayEvP15XW?a=rAi+zGD=5bx(Pblw z_DzM*J6v?ZPcXAbmpqv{t#k%;?Be87373I>VS3uyQ6*A-biShyzPZTRV%nw;Nr-vo zU0B-2{0i68(DK!GQQ*(Jk8UqCjxh|uq@beBlGZ6M2|m(#5yZUS5tV>}lq#&TV-!4A zkvC^lHDV#}Iwz4su$wRuRcPPsOTxitT*&BBr`C<*@L^-if6%+vjbV;rHA$^?oWgT0 zhMqaAn9PIM8Es{GDnVhdP1Guis+M~V{m$GbT+HXZHx{Tm9cUV2E*WyCg*4bDV>LzV zgD@JmdPJ7a8Q0|ks)a?+bxUav;9cPb=(SE`B49+Z=fvw=(QyFsDHl2E=a}kN0ACS& zr}04ukh@<3Fey?K{R^{h};{q=35=e&H=&U30LMO#|I8wAsipaR{(O z!f=a1ZrhVWAnft(1LR_R)V3QY1fsvdF+9;VK)e>vOzKOzh=Hzg5hLYqXD9&{=!>!LZ898_i=%G>uh|4$`&sUG=b&$ z);?@|eEgSe2e_zuoGgzDz=8_rpkM(QRRXw9krMu`!w(L@K4(W91PI09SV`O#d z*(NchyG03s%KayVwEaAQ(2F8)%}T0Nrv7=dU)i%jIwmsy{1oR=Eu7-#t+5k-NfJkYL1N z)(&m2@IfGAY$IfZv%oVIXw>f|8Sp@fvOyflEa-8C6zccF1DId-lch3+1#PCHSVOWZ z4KR{B=xeUX7VStX3k*+}WPw``j`QG=vfTCG^mJshz_!XGoWHK*%}O{2@*ZoWT$SQ3 JWd7DQ`9Hc?h(rJY diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4eac4a84cc..4f32b203e1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 445395ee3e073d657d92e67c20611c174edc6232 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 30 Jan 2026 13:29:12 +0100 Subject: [PATCH 1509/1594] [Java] Upgrade to `Gradle` 9.3.1. --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4f32b203e1..5f38436fc6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 79e460ff56e76d1d0be02a0ce455a7482c97d420 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Wed, 18 Feb 2026 15:02:58 -0600 Subject: [PATCH 1510/1594] [Rust] updated generator to correctly limit length of var data written (#1096) * [Rust] updated how Cargo.toml package name is cleaned * [Rust] fixed RustGenerator::generateEncoderVarData() to cap slice len to primitive type size * [Rust] updated test imports * [Rust] updated issue1066.xml * [Rust] updated rust tests --------- Co-authored-by: Michael Ward --- build.gradle | 3 +- rust/Cargo.toml | 9 +-- rust/tests/baseline_enum_from_str.rs | 64 +++++++++++++++---- rust/tests/baseline_enum_into.rs | 34 +++++++--- rust/tests/baseline_enum_to_str.rs | 28 ++++++-- rust/tests/baseline_test.rs | 2 +- .../basic_variable_length_schema_test.rs | 43 +++++++++++++ rust/tests/big_endian_test.rs | 6 +- rust/tests/fixed_sized_primitive_array.rs | 12 ++-- rust/tests/issue_1066_test.rs | 2 +- rust/tests/issue_987_test.rs | 7 +- .../sbe/generation/rust/RustGenerator.java | 7 +- .../generation/rust/RustOutputManager.java | 2 +- .../basic-variable-length-schema.xml | 45 +++++++------ sbe-tool/src/test/resources/issue1066.xml | 42 ++++++------ 15 files changed, 219 insertions(+), 87 deletions(-) create mode 100644 rust/tests/basic_variable_length_schema_test.rs diff --git a/build.gradle b/build.gradle index 90102a340e..3d6461d6e7 100644 --- a/build.gradle +++ b/build.gradle @@ -679,8 +679,9 @@ tasks.register('generateRustTestCodecs', JavaExec) { 'sbe-tool/src/test/resources/issue1028.xml', 'sbe-tool/src/test/resources/issue1057.xml', 'sbe-tool/src/test/resources/issue1066.xml', - 'sbe-tool/src/test/resources/fixed-sized-primitive-array-types.xml', + 'sbe-tool/src/test/resources/basic-variable-length-schema.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', + 'sbe-tool/src/test/resources/fixed-sized-primitive-array-types.xml', 'sbe-tool/src/test/resources/nested-composite-name.xml', ] } diff --git a/rust/Cargo.toml b/rust/Cargo.toml index b48fd6ee55..76119b11b7 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -2,7 +2,7 @@ name = "sbe_rust_example" version = "0.1.0" authors = [] -edition = "2018" +edition = "2021" publish = false [dependencies] @@ -19,12 +19,13 @@ issue_987 = { path = "../generated/rust/issue987" } issue_1028 = { path = "../generated/rust/issue1028" } issue_1057 = { path = "../generated/rust/issue1057" } issue_1066 = { path = "../generated/rust/issue1066" } -baseline_bigendian = { path = "../generated/rust/baseline-bigendian" } -nested_composite_name = { path = "../generated/rust/nested-composite-name" } +baseline_bigendian = { path = "../generated/rust/baseline_bigendian" } +nested_composite_name = { path = "../generated/rust/nested_composite_name" } +sbe_tests = { path = "../generated/rust/sbe_tests" } fixed_sized_primitive_array = { path = "../generated/rust/fixed_sized_primitive_array" } [dev-dependencies] -criterion = "0.5" +criterion = "0.7" [[bench]] name = "car_benchmark" diff --git a/rust/tests/baseline_enum_from_str.rs b/rust/tests/baseline_enum_from_str.rs index a111d28364..26cf7a9102 100644 --- a/rust/tests/baseline_enum_from_str.rs +++ b/rust/tests/baseline_enum_from_str.rs @@ -1,22 +1,60 @@ +use examples_baseline::boost_type::BoostType; use BoostType::{NullVal, KERS, NITROUS, SUPERCHARGER, TURBO}; -use examples_baseline::{ - boost_type::BoostType, -}; #[test] fn test_boost_type_from_str() -> Result<(), ()> { - assert_eq!("TURBO".parse::()?, TURBO, "Parse \"TURBO\" as BoostType"); - assert_eq!("SUPERCHARGER".parse::()?, SUPERCHARGER, "Parse \"SUPERCHARGER\" as BoostType"); - assert_eq!("NITROUS".parse::()?, NITROUS, "Parse \"NITROUS\" as BoostType"); - assert_eq!("KERS".parse::()?, KERS, "Parse \"KERS\" as BoostType"); + assert_eq!( + "TURBO".parse::()?, + TURBO, + "Parse \"TURBO\" as BoostType" + ); + assert_eq!( + "SUPERCHARGER".parse::()?, + SUPERCHARGER, + "Parse \"SUPERCHARGER\" as BoostType" + ); + assert_eq!( + "NITROUS".parse::()?, + NITROUS, + "Parse \"NITROUS\" as BoostType" + ); + assert_eq!( + "KERS".parse::()?, + KERS, + "Parse \"KERS\" as BoostType" + ); - assert_eq!("Turbo".parse::()?, NullVal, "Parse \"Turbo\" as BoostType"); - assert_eq!("Supercharger".parse::()?, NullVal, "Parse \"Supercharger\" as BoostType"); - assert_eq!("Nitrous".parse::()?, NullVal, "Parse \"Nitrous\" as BoostType"); - assert_eq!("Kers".parse::()?, NullVal, "Parse \"Kers\" as BoostType"); + assert_eq!( + "Turbo".parse::()?, + NullVal, + "Parse \"Turbo\" as BoostType" + ); + assert_eq!( + "Supercharger".parse::()?, + NullVal, + "Parse \"Supercharger\" as BoostType" + ); + assert_eq!( + "Nitrous".parse::()?, + NullVal, + "Parse \"Nitrous\" as BoostType" + ); + assert_eq!( + "Kers".parse::()?, + NullVal, + "Parse \"Kers\" as BoostType" + ); - assert_eq!("AA".parse::()?, NullVal, "Parse \"AA\" as BoostType"); - assert_eq!("".parse::().unwrap(), NullVal, "Parse \"\" as BoostType"); + assert_eq!( + "AA".parse::()?, + NullVal, + "Parse \"AA\" as BoostType" + ); + assert_eq!( + "".parse::().unwrap(), + NullVal, + "Parse \"\" as BoostType" + ); Ok(()) } diff --git a/rust/tests/baseline_enum_into.rs b/rust/tests/baseline_enum_into.rs index 9580e51b0d..0af9b0a585 100644 --- a/rust/tests/baseline_enum_into.rs +++ b/rust/tests/baseline_enum_into.rs @@ -1,14 +1,32 @@ -use examples_baseline::{ - boost_type::BoostType, -}; +use examples_baseline::boost_type::BoostType; #[test] fn test_boost_type_from_str() -> Result<(), ()> { - assert_eq!(>::into(BoostType::TURBO), 84_u8, "BoostType::TURBO into value"); - assert_eq!(>::into(BoostType::SUPERCHARGER), 83_u8, "BoostType::SUPERCHARGER into value"); - assert_eq!(>::into(BoostType::NITROUS), 78_u8, "BoostType::NITROUS into value"); - assert_eq!(>::into(BoostType::KERS), 75_u8, "BoostType::KERS into value"); - assert_eq!(>::into(BoostType::NullVal), 0_u8, "BoostType::NullVal into value"); + assert_eq!( + >::into(BoostType::TURBO), + 84_u8, + "BoostType::TURBO into value" + ); + assert_eq!( + >::into(BoostType::SUPERCHARGER), + 83_u8, + "BoostType::SUPERCHARGER into value" + ); + assert_eq!( + >::into(BoostType::NITROUS), + 78_u8, + "BoostType::NITROUS into value" + ); + assert_eq!( + >::into(BoostType::KERS), + 75_u8, + "BoostType::KERS into value" + ); + assert_eq!( + >::into(BoostType::NullVal), + 0_u8, + "BoostType::NullVal into value" + ); Ok(()) } diff --git a/rust/tests/baseline_enum_to_str.rs b/rust/tests/baseline_enum_to_str.rs index 93f5206517..8739d6ec9d 100644 --- a/rust/tests/baseline_enum_to_str.rs +++ b/rust/tests/baseline_enum_to_str.rs @@ -1,14 +1,28 @@ -use examples_baseline::{ - boost_type::BoostType, -}; +use examples_baseline::boost_type::BoostType; #[test] fn test_boost_type_from_str() -> Result<(), ()> { - assert_eq!(format!("{}", BoostType::TURBO), "TURBO", "Display \"TURBO\""); - assert_eq!(format!("{}", BoostType::SUPERCHARGER), "SUPERCHARGER", "Display \"SUPERCHARGER\""); - assert_eq!(format!("{}", BoostType::NITROUS), "NITROUS", "Display \"NITROUS\""); + assert_eq!( + format!("{}", BoostType::TURBO), + "TURBO", + "Display \"TURBO\"" + ); + assert_eq!( + format!("{}", BoostType::SUPERCHARGER), + "SUPERCHARGER", + "Display \"SUPERCHARGER\"" + ); + assert_eq!( + format!("{}", BoostType::NITROUS), + "NITROUS", + "Display \"NITROUS\"" + ); assert_eq!(format!("{}", BoostType::KERS), "KERS", "Display \"KERS\""); - assert_eq!(format!("{}", BoostType::NullVal), "NullVal", "Display \"NullVal\""); + assert_eq!( + format!("{}", BoostType::NullVal), + "NullVal", + "Display \"NullVal\"" + ); Ok(()) } diff --git a/rust/tests/baseline_test.rs b/rust/tests/baseline_test.rs index ab711b7c84..49486795a2 100644 --- a/rust/tests/baseline_test.rs +++ b/rust/tests/baseline_test.rs @@ -272,4 +272,4 @@ fn test_issue_1018() { assert_eq!(1, examples_baseline::SBE_SCHEMA_ID); assert_eq!(0, examples_baseline::SBE_SCHEMA_VERSION); assert_eq!("5.2", examples_baseline::SBE_SEMANTIC_VERSION); -} \ No newline at end of file +} diff --git a/rust/tests/basic_variable_length_schema_test.rs b/rust/tests/basic_variable_length_schema_test.rs new file mode 100644 index 0000000000..c8b4eed86f --- /dev/null +++ b/rust/tests/basic_variable_length_schema_test.rs @@ -0,0 +1,43 @@ +use sbe_tests::{ + message_header_codec::MessageHeaderDecoder, + test_message_1_codec::{ + TestMessage1Decoder, SBE_BLOCK_LENGTH, SBE_SCHEMA_ID, SBE_SCHEMA_VERSION, SBE_TEMPLATE_ID, + }, +}; +use sbe_tests::{ + WriteBuf, + {message_header_codec, test_message_1_codec::TestMessage1Encoder, Encoder, ReadBuf}, +}; + +#[test] +fn should_limit_var_data_length() { + // encode... + let mut buffer = vec![0u8; 1024]; + let mut encoder = TestMessage1Encoder::default(); + encoder = encoder.wrap( + WriteBuf::new(buffer.as_mut_slice()), + message_header_codec::ENCODED_LENGTH, + ); + encoder = encoder.header(0).parent().unwrap(); + + let password: String = (0..1024).map(|_| 'x' as char).collect(); + encoder.encrypted_new_password(password.as_bytes()); + assert_eq!(263, encoder.get_limit()); + + // decode... + let buf = ReadBuf::new(buffer.as_slice()); + let header = MessageHeaderDecoder::default().wrap(buf, 0); + assert_eq!(SBE_BLOCK_LENGTH, header.block_length()); + assert_eq!(SBE_SCHEMA_VERSION, header.version()); + assert_eq!(SBE_TEMPLATE_ID, header.template_id()); + assert_eq!(SBE_SCHEMA_ID, header.schema_id()); + + let mut decoder = TestMessage1Decoder::default().header(header, 0); + let coord = decoder.encrypted_new_password_decoder(); + let password = String::from_utf8_lossy(decoder.encrypted_new_password_slice(coord)); + assert_eq!(254, password.len()); + password + .as_bytes() + .iter() + .for_each(|x| assert_eq!(b'x', *x)); +} diff --git a/rust/tests/big_endian_test.rs b/rust/tests/big_endian_test.rs index 1bef7278dd..248a367d52 100644 --- a/rust/tests/big_endian_test.rs +++ b/rust/tests/big_endian_test.rs @@ -1,10 +1,8 @@ +use baseline_bigendian::car_codec::{CarDecoder, CarEncoder, SBE_TEMPLATE_ID}; use baseline_bigendian::{ boolean_type::BooleanType, boost_type::BoostType, - car_codec::{ - encoder::{AccelerationEncoder, FuelFiguresEncoder, PerformanceFiguresEncoder}, - *, - }, + car_codec::encoder::{AccelerationEncoder, FuelFiguresEncoder, PerformanceFiguresEncoder}, message_header_codec, message_header_codec::MessageHeaderDecoder, model::Model, diff --git a/rust/tests/fixed_sized_primitive_array.rs b/rust/tests/fixed_sized_primitive_array.rs index 8542e3d488..59e6df84d6 100644 --- a/rust/tests/fixed_sized_primitive_array.rs +++ b/rust/tests/fixed_sized_primitive_array.rs @@ -337,28 +337,32 @@ fn test_encode_then_decode_non_u8_signed_primitive_slice() { DemoDecoder::fixed_16_i8, DemoEncoder::fixed_16_i8_end, DemoDecoder::fixed_16_i8_end, - i8, i8::from_le_bytes([uninit]) + i8, + i8::from_le_bytes([uninit]) ); run_encode_then_decode_for_array_of_signed_len_16!( DemoEncoder::fixed_16_i16_from_iter, DemoDecoder::fixed_16_i16, DemoEncoder::fixed_16_i16_end, DemoDecoder::fixed_16_i16_end, - i16, i16::from_le_bytes([uninit, uninit]) + i16, + i16::from_le_bytes([uninit, uninit]) ); run_encode_then_decode_for_array_of_signed_len_16!( DemoEncoder::fixed_16_i32_from_iter, DemoDecoder::fixed_16_i32, DemoEncoder::fixed_16_i32_end, DemoDecoder::fixed_16_i32_end, - i32, i32::from_le_bytes([uninit, uninit, uninit, uninit]) + i32, + i32::from_le_bytes([uninit, uninit, uninit, uninit]) ); run_encode_then_decode_for_array_of_signed_len_16!( DemoEncoder::fixed_16_i64_from_iter, DemoDecoder::fixed_16_i64, DemoEncoder::fixed_16_i64_end, DemoDecoder::fixed_16_i64_end, - i64, i64::from_le_bytes([uninit, uninit, uninit, uninit, uninit, uninit, uninit, uninit]) + i64, + i64::from_le_bytes([uninit, uninit, uninit, uninit, uninit, uninit, uninit, uninit]) ); } diff --git a/rust/tests/issue_1066_test.rs b/rust/tests/issue_1066_test.rs index 43f7278ebf..2c22c0f44b 100644 --- a/rust/tests/issue_1066_test.rs +++ b/rust/tests/issue_1066_test.rs @@ -1,7 +1,7 @@ use issue_1066::{ issue_1066_codec, issue_1066_codec::{Issue1066Decoder, Issue1066Encoder}, - *, + message_header_codec, ReadBuf, WriteBuf, }; #[test] diff --git a/rust/tests/issue_987_test.rs b/rust/tests/issue_987_test.rs index 4462f58b52..bd496ee801 100644 --- a/rust/tests/issue_987_test.rs +++ b/rust/tests/issue_987_test.rs @@ -1,5 +1,10 @@ use issue_987::{ - issue_987_codec::{Issue987Decoder, Issue987Encoder, SBE_BLOCK_LENGTH, SBE_SCHEMA_ID, SBE_SCHEMA_VERSION, SBE_TEMPLATE_ID}, message_header_codec::MessageHeaderDecoder, * + issue_987_codec::{ + Issue987Decoder, Issue987Encoder, SBE_BLOCK_LENGTH, SBE_SCHEMA_ID, SBE_SCHEMA_VERSION, + SBE_TEMPLATE_ID, + }, + message_header_codec::MessageHeaderDecoder, + *, }; fn create_encoder(buffer: &mut Vec, off: usize) -> Issue987Encoder { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 746f18d022..94491b0a15 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -111,7 +111,7 @@ public void generate() throws IOException // create Cargo.toml try (Writer writer = outputManager.createCargoToml()) { - final String packageName = toLowerSnakeCase(ir.packageName()).replaceAll("[.-]", "_"); + final String packageName = toLowerSnakeCase(ir.packageName().replaceAll("[\\s.-]", "_")); final String namespace; if (ir.namespaceName() == null || ir.namespaceName().equalsIgnoreCase(packageName)) { @@ -356,14 +356,15 @@ static void generateEncoderVarData( indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", propertyName, varDataType); indent(sb, level + 1, "let limit = self.get_limit();\n"); - indent(sb, level + 1, "let data_length = value.len();\n"); + indent(sb, level + 1, "let data_length = value.len().min((%s::MAX - 1) as usize);\n", + rustTypeName(lengthType)); indent(sb, level + 1, "self.set_limit(limit + %d + data_length);\n", lengthType.size()); indent(sb, level + 1, "self.get_buf_mut().put_%s_at(limit, data_length as %1$s);\n", rustTypeName(lengthType)); - indent(sb, level + 1, "self.get_buf_mut().put_slice_at(limit + %d, value%s);\n", + indent(sb, level + 1, "self.get_buf_mut().put_slice_at(limit + %d, &value[0..data_length]%s);\n", lengthType.size(), toBytesFn); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java index fe8ca08e63..26ee4ca98f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustOutputManager.java @@ -60,7 +60,7 @@ public RustOutputManager(final String baseDirName, final String packageName) Verify.notNull(packageName, "packageName"); String dirName = baseDirName.endsWith("" + separatorChar) ? baseDirName : baseDirName + separatorChar; - dirName += packageName.replaceAll("\\.", "_").toLowerCase() + separatorChar; + dirName += packageName.replaceAll("[\\s.-]", "_").toLowerCase() + separatorChar; final String libDirName = dirName; rootDir = new File(libDirName); diff --git a/sbe-tool/src/test/resources/basic-variable-length-schema.xml b/sbe-tool/src/test/resources/basic-variable-length-schema.xml index bd5dee2de9..39d681b989 100644 --- a/sbe-tool/src/test/resources/basic-variable-length-schema.xml +++ b/sbe-tool/src/test/resources/basic-variable-length-schema.xml @@ -1,22 +1,25 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/sbe-tool/src/test/resources/issue1066.xml b/sbe-tool/src/test/resources/issue1066.xml index a24e45b030..270926cc70 100644 --- a/sbe-tool/src/test/resources/issue1066.xml +++ b/sbe-tool/src/test/resources/issue1066.xml @@ -1,18 +1,24 @@ - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + \ No newline at end of file From fa33cfc13ddb741a093e0d4bf5bcd4b35620e01f Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Wed, 18 Feb 2026 15:03:20 -0600 Subject: [PATCH 1511/1594] [Rust] updated some function to "const" (#1098) Co-authored-by: Michael Ward --- .../uk/co/real_logic/sbe/generation/rust/LibRsDef.java | 8 ++++---- .../real_logic/sbe/generation/rust/MessageCoderDef.java | 2 +- .../uk/co/real_logic/sbe/generation/rust/SubGroup.java | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index f361397916..1de9357f3a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -189,7 +189,7 @@ static void generateReadBuf(final Appendable writer, final ByteOrder byteOrder) indent(writer, 0, "#[allow(dead_code)]\n"); indent(writer, 0, "impl<%s> %s<%s> {\n", BUF_LIFETIME, READ_BUF_TYPE, BUF_LIFETIME); indent(writer, 1, "#[inline]\n"); - indent(writer, 1, "pub fn new(data: &%s [u8]) -> Self {\n", BUF_LIFETIME); + indent(writer, 1, "pub const fn new(data: &%s [u8]) -> Self {\n", BUF_LIFETIME); indent(writer, 2, "Self { data }\n"); indent(writer, 1, "}\n\n"); @@ -205,7 +205,7 @@ static void generateReadBuf(final Appendable writer, final ByteOrder byteOrder) uniquePrimitiveTypes.remove("u8"); indent(writer, 0, "\n"); indent(writer, 1, "#[inline]\n"); - indent(writer, 1, "pub fn get_u8_at(&self, index: usize) -> u8 {\n"); + indent(writer, 1, "pub const fn get_u8_at(&self, index: usize) -> u8 {\n"); indent(writer, 2, "self.data[index]\n"); indent(writer, 1, "}\n"); @@ -238,7 +238,7 @@ static void generateWriteBuf(final Writer writer, final ByteOrder byteOrder) thr indent(writer, 0, "}\n"); indent(writer, 0, "impl<%s> %s<%s> {\n", BUF_LIFETIME, WRITE_BUF_TYPE, BUF_LIFETIME); - indent(writer, 1, "pub fn new(data: &%s mut [u8]) -> Self {\n", BUF_LIFETIME); + indent(writer, 1, "pub const fn new(data: &%s mut [u8]) -> Self {\n", BUF_LIFETIME); indent(writer, 2, "Self { data }\n"); indent(writer, 1, "}\n\n"); @@ -255,7 +255,7 @@ static void generateWriteBuf(final Writer writer, final ByteOrder byteOrder) thr uniquePrimitiveTypes.remove("u8"); indent(writer, 1, "#[inline]\n"); - indent(writer, 1, "pub fn put_u8_at(&mut self, index: usize, value: u8) {\n"); + indent(writer, 1, "pub const fn put_u8_at(&mut self, index: usize, value: u8) {\n"); indent(writer, 2, "self.data[index] = value;\n"); indent(writer, 1, "}\n\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index e4e19f4c52..1979de7b86 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -83,7 +83,7 @@ void generate( appendWrapFn(sb); indent(sb, 2, "#[inline]\n"); - indent(sb, 2, "pub fn encoded_length(&self) -> usize {\n"); + indent(sb, 2, "pub const fn encoded_length(&self) -> usize {\n"); indent(sb, 3, "self.limit - self.offset\n"); indent(sb, 2, "}\n\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index 5c1981a874..e96c11c20a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -103,7 +103,7 @@ void generateEncoder( // block_length function indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn block_length() -> %s {\n", rustTypeName(blockLengthPrimitiveType)); + indent(sb, level, "pub const fn block_length() -> %s {\n", rustTypeName(blockLengthPrimitiveType)); indent(sb, level + 1, "%d\n", this.groupToken.encodedLength()); indent(sb, level, "}\n\n"); From 8327dcdf49c3c131094630acafb2ca50dd60c081 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Wed, 18 Feb 2026 15:09:18 -0600 Subject: [PATCH 1512/1594] [Rust] generated encoders now produce fluent interface (#1097) Co-authored-by: Michael Ward Co-authored-by: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> --- rust/tests/baseline_test.rs | 83 +++++++++---------- rust/tests/big_endian_test.rs | 72 ++++++++-------- rust/tests/extension_test.rs | 80 +++++++++--------- .../sbe/generation/rust/RustGenerator.java | 24 ++++-- 4 files changed, 131 insertions(+), 128 deletions(-) diff --git a/rust/tests/baseline_test.rs b/rust/tests/baseline_test.rs index 49486795a2..5ec352b7d0 100644 --- a/rust/tests/baseline_test.rs +++ b/rust/tests/baseline_test.rs @@ -181,24 +181,26 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { ); car = car.header(0).parent()?; - car.serial_number(1234); - car.model_year(2013); - car.available(BooleanType::T); - car.code(Model::A); - car.some_numbers(&[1, 2, 3, 4]); - car.vehicle_code(&[97, 98, 99, 100, 101, 102]); // abcdef - - extras.set_cruise_control(true); - extras.set_sports_pack(true); - extras.set_sun_roof(false); + car.serial_number(1234) + .model_year(2013) + .available(BooleanType::T) + .code(Model::A) + .some_numbers(&[1, 2, 3, 4]) + .vehicle_code(&[97, 98, 99, 100, 101, 102]); // abcdef + + extras + .set_cruise_control(true) + .set_sports_pack(true) + .set_sun_roof(false); car.extras(extras); let mut engine = car.engine_encoder(); - engine.capacity(2000); - engine.num_cylinders(4); - engine.manufacturer_code(&[49, 50, 51]); // 123 - engine.efficiency(35); - engine.booster_enabled(BooleanType::T); + engine + .capacity(2000) + .num_cylinders(4) + .manufacturer_code(&[49, 50, 51]) // 123 + .efficiency(35) + .booster_enabled(BooleanType::T); let mut booster = engine.booster_encoder(); booster.boost_type(BoostType::NITROUS); booster.horse_power(200); @@ -207,19 +209,22 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { car = engine.parent()?; fuel_figures = car.fuel_figures_encoder(3, fuel_figures); assert_eq!(Some(0), fuel_figures.advance()?); - fuel_figures.speed(30); - fuel_figures.mpg(35.9); - fuel_figures.usage_description(b"Urban Cycle"); + fuel_figures + .speed(30) + .mpg(35.9) + .usage_description(b"Urban Cycle"); assert_eq!(Some(1), fuel_figures.advance()?); - fuel_figures.speed(55); - fuel_figures.mpg(49.0); - fuel_figures.usage_description(b"Combined Cycle"); + fuel_figures + .speed(55) + .mpg(49.0) + .usage_description(b"Combined Cycle"); assert_eq!(Some(2), fuel_figures.advance()?); - fuel_figures.speed(75); - fuel_figures.mpg(40.0); - fuel_figures.usage_description(b"Highway Cycle"); + fuel_figures + .speed(75) + .mpg(40.0) + .usage_description(b"Highway Cycle"); car = fuel_figures.parent()?; performance_figures = car.performance_figures_encoder(2, performance_figures); @@ -228,16 +233,13 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { acceleration = performance_figures.acceleration_encoder(3, acceleration); assert_eq!(Some(0), acceleration.advance()?); - acceleration.mph(30); - acceleration.seconds(4.0); + acceleration.mph(30).seconds(4.0); assert_eq!(Some(1), acceleration.advance()?); - acceleration.mph(60); - acceleration.seconds(7.5); + acceleration.mph(60).seconds(7.5); assert_eq!(Some(2), acceleration.advance()?); - acceleration.mph(100); - acceleration.seconds(12.2); + acceleration.mph(100).seconds(12.2); performance_figures = acceleration.parent()?; assert_eq!(Some(1), performance_figures.advance()?); @@ -245,23 +247,20 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { acceleration = performance_figures.acceleration_encoder(3, acceleration); assert_eq!(Some(0), acceleration.advance()?); - acceleration.mph(30); - acceleration.seconds(3.8); + acceleration.mph(30).seconds(3.8); assert_eq!(Some(1), acceleration.advance()?); - acceleration.mph(60); - acceleration.seconds(7.1); + acceleration.mph(60).seconds(7.1); assert_eq!(Some(2), acceleration.advance()?); - acceleration.mph(100); - acceleration.seconds(11.8); + acceleration.mph(100).seconds(11.8); performance_figures = acceleration.parent()?; car = performance_figures.parent()?; - car.manufacturer("Honda"); - car.model("Civic VTi"); - car.activation_code(b"abcdef"); + car.manufacturer("Honda") + .model("Civic VTi") + .activation_code(b"abcdef"); let limit = car.get_limit(); Ok((limit, buffer)) @@ -269,7 +268,7 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { #[test] fn test_issue_1018() { - assert_eq!(1, examples_baseline::SBE_SCHEMA_ID); - assert_eq!(0, examples_baseline::SBE_SCHEMA_VERSION); - assert_eq!("5.2", examples_baseline::SBE_SEMANTIC_VERSION); + assert_eq!(1, SBE_SCHEMA_ID); + assert_eq!(0, SBE_SCHEMA_VERSION); + assert_eq!("5.2", SBE_SEMANTIC_VERSION); } diff --git a/rust/tests/big_endian_test.rs b/rust/tests/big_endian_test.rs index 248a367d52..a759ff7443 100644 --- a/rust/tests/big_endian_test.rs +++ b/rust/tests/big_endian_test.rs @@ -175,12 +175,12 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { ); car = car.header(0).parent()?; - car.serial_number(1234); - car.model_year(2013); - car.available(BooleanType::T); - car.code(Model::A); - car.some_numbers(&[0, 1, 2, 3, 4]); - car.vehicle_code(b"abcdef"); + car.serial_number(1234) + .model_year(2013) + .available(BooleanType::T) + .code(Model::A) + .some_numbers(&[0, 1, 2, 3, 4]) + .vehicle_code(b"abcdef"); extras.set_cruise_control(true); extras.set_sports_pack(true); @@ -188,32 +188,36 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { car.extras(extras); let mut engine = car.engine_encoder(); - engine.capacity(2000); - engine.num_cylinders(4); - engine.manufacturer_code(b"123"); - engine.efficiency(35); - engine.booster_enabled(BooleanType::T); + engine + .capacity(2000) + .num_cylinders(4) + .manufacturer_code(b"123") + .efficiency(35) + .booster_enabled(BooleanType::T); + let mut booster = engine.booster_encoder(); - booster.boost_type(BoostType::NITROUS); - booster.horse_power(200); + booster.boost_type(BoostType::NITROUS).horse_power(200); engine = booster.parent()?; car = engine.parent()?; fuel_figures = car.fuel_figures_encoder(3, fuel_figures); assert_eq!(Some(0), fuel_figures.advance()?); - fuel_figures.speed(30); - fuel_figures.mpg(35.9); - fuel_figures.usage_description("Urban Cycle"); + fuel_figures + .speed(30) + .mpg(35.9) + .usage_description("Urban Cycle"); assert_eq!(Some(1), fuel_figures.advance()?); - fuel_figures.speed(55); - fuel_figures.mpg(49.0); - fuel_figures.usage_description("Combined Cycle"); + fuel_figures + .speed(55) + .mpg(49.0) + .usage_description("Combined Cycle"); assert_eq!(Some(2), fuel_figures.advance()?); - fuel_figures.speed(75); - fuel_figures.mpg(40.0); - fuel_figures.usage_description("Highway Cycle"); + fuel_figures + .speed(75) + .mpg(40.0) + .usage_description("Highway Cycle"); car = fuel_figures.parent()?; performance_figures = car.performance_figures_encoder(2, performance_figures); @@ -222,16 +226,13 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { acceleration = performance_figures.acceleration_encoder(3, acceleration); assert_eq!(Some(0), acceleration.advance()?); - acceleration.mph(30); - acceleration.seconds(4.0); + acceleration.mph(30).seconds(4.0); assert_eq!(Some(1), acceleration.advance()?); - acceleration.mph(60); - acceleration.seconds(7.5); + acceleration.mph(60).seconds(7.5); assert_eq!(Some(2), acceleration.advance()?); - acceleration.mph(100); - acceleration.seconds(12.2); + acceleration.mph(100).seconds(12.2); performance_figures = acceleration.parent()?; assert_eq!(Some(1), performance_figures.advance()?); @@ -239,23 +240,20 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { acceleration = performance_figures.acceleration_encoder(3, acceleration); assert_eq!(Some(0), acceleration.advance()?); - acceleration.mph(30); - acceleration.seconds(3.8); + acceleration.mph(30).seconds(3.8); assert_eq!(Some(1), acceleration.advance()?); - acceleration.mph(60); - acceleration.seconds(7.1); + acceleration.mph(60).seconds(7.1); assert_eq!(Some(2), acceleration.advance()?); - acceleration.mph(100); - acceleration.seconds(11.8); + acceleration.mph(100).seconds(11.8); performance_figures = acceleration.parent()?; car = performance_figures.parent()?; - car.manufacturer("Honda"); - car.model("Civic VTi"); - car.activation_code("abcdef"); + car.manufacturer("Honda") + .model("Civic VTi") + .activation_code("abcdef"); let limit = car.get_limit(); Ok((limit, buffer)) diff --git a/rust/tests/extension_test.rs b/rust/tests/extension_test.rs index ab62a7715c..665d8f92b4 100644 --- a/rust/tests/extension_test.rs +++ b/rust/tests/extension_test.rs @@ -182,45 +182,49 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { ); car = car.header(0).parent()?; - car.serial_number(1234); - car.model_year(2013); - car.available(BooleanType::T); - car.code(Model::A); - car.some_numbers(&[0, 1, 2, 3]); - car.vehicle_code_from_iter(b"abcdef_extra_is_ignored".into_iter().copied()); // abcdef - - extras.set_cruise_control(true); - extras.set_sports_pack(true); - extras.set_sun_roof(false); + car.serial_number(1234) + .model_year(2013) + .available(BooleanType::T) + .code(Model::A) + .some_numbers(&[0, 1, 2, 3]) + .vehicle_code_from_iter(b"abcdef_extra_is_ignored".into_iter().copied()); // abcdef + + extras + .set_cruise_control(true) + .set_sports_pack(true) + .set_sun_roof(false); car.extras(extras); let mut engine = car.engine_encoder(); - engine.capacity(2000); - engine.num_cylinders(4); - engine.manufacturer_code(b"123"); - engine.efficiency(35); - engine.booster_enabled(BooleanType::T); + engine + .capacity(2000) + .num_cylinders(4) + .manufacturer_code(b"123") + .efficiency(35) + .booster_enabled(BooleanType::T); let mut booster = engine.booster_encoder(); - booster.boost_type(BoostType::NITROUS); - booster.horse_power(200); + booster.boost_type(BoostType::NITROUS).horse_power(200); engine = booster.parent()?; car = engine.parent()?; fuel_figures = car.fuel_figures_encoder(3, fuel_figures); assert_eq!(Some(0), fuel_figures.advance()?); - fuel_figures.speed(30); - fuel_figures.mpg(35.9); - fuel_figures.usage_description(b"Urban Cycle"); + fuel_figures + .speed(30) + .mpg(35.9) + .usage_description(b"Urban Cycle"); assert_eq!(Some(1), fuel_figures.advance()?); - fuel_figures.speed(55); - fuel_figures.mpg(49.0); - fuel_figures.usage_description(b"Combined Cycle"); + fuel_figures + .speed(55) + .mpg(49.0) + .usage_description(b"Combined Cycle"); assert_eq!(Some(2), fuel_figures.advance()?); - fuel_figures.speed(75); - fuel_figures.mpg(40.0); - fuel_figures.usage_description(b"Highway Cycle"); + fuel_figures + .speed(75) + .mpg(40.0) + .usage_description(b"Highway Cycle"); car = fuel_figures.parent()?; performance_figures = car.performance_figures_encoder(2, performance_figures); @@ -229,16 +233,13 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { acceleration = performance_figures.acceleration_encoder(3, acceleration); assert_eq!(Some(0), acceleration.advance()?); - acceleration.mph(30); - acceleration.seconds(4.0); + acceleration.mph(30).seconds(4.0); assert_eq!(Some(1), acceleration.advance()?); - acceleration.mph(60); - acceleration.seconds(7.5); + acceleration.mph(60).seconds(7.5); assert_eq!(Some(2), acceleration.advance()?); - acceleration.mph(100); - acceleration.seconds(12.2); + acceleration.mph(100).seconds(12.2); performance_figures = acceleration.parent()?; assert_eq!(Some(1), performance_figures.advance()?); @@ -246,23 +247,20 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { acceleration = performance_figures.acceleration_encoder(3, acceleration); assert_eq!(Some(0), acceleration.advance()?); - acceleration.mph(30); - acceleration.seconds(3.8); + acceleration.mph(30).seconds(3.8); assert_eq!(Some(1), acceleration.advance()?); - acceleration.mph(60); - acceleration.seconds(7.1); + acceleration.mph(60).seconds(7.1); assert_eq!(Some(2), acceleration.advance()?); - acceleration.mph(100); - acceleration.seconds(11.8); + acceleration.mph(100).seconds(11.8); performance_figures = acceleration.parent()?; car = performance_figures.parent()?; - car.manufacturer("Honda"); - car.model("Civic VTi"); - car.activation_code(b"abcdef"); + car.manufacturer("Honda") + .model("Civic VTi") + .activation_code(b"abcdef"); let limit = car.get_limit(); Ok((limit, buffer)) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 94491b0a15..683d81da44 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -353,7 +353,7 @@ static void generateEncoderVarData( // function to write slice ... todo - handle character encoding ? indent(sb, level, "/// VAR_DATA ENCODER - character encoding: '%s'\n", characterEncoding); indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", propertyName, varDataType); + indent(sb, level, "pub fn %s(&mut self, value: %s) -> &mut Self {\n", propertyName, varDataType); indent(sb, level + 1, "let limit = self.get_limit();\n"); indent(sb, level + 1, "let data_length = value.len().min((%s::MAX - 1) as usize);\n", @@ -368,6 +368,7 @@ static void generateEncoderVarData( lengthType.size(), toBytesFn); + indent(sb, level + 1, "self\n"); indent(sb, level, "}\n\n"); i += varDataToken.componentTokenCount(); @@ -409,7 +410,7 @@ private static void generatePrimitiveArrayFromIterEncoder( indent(sb, level, "/// primitive array field '%s' from an Iterator\n", name); generateRustDoc(sb, level, typeToken, encoding); indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn %s_from_iter(&mut self, iter: impl Iterator) {\n", + indent(sb, level, "pub fn %s_from_iter(&mut self, iter: impl Iterator) -> &mut Self {\n", formatFunctionName(name), rustPrimitiveType); indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); @@ -426,6 +427,7 @@ private static void generatePrimitiveArrayFromIterEncoder( rustPrimitiveType, primitiveType.size()); } indent(sb, level + 1, "}\n"); + indent(sb, level + 1, "self\n"); indent(sb, level, "}\n\n"); } @@ -443,13 +445,14 @@ private static void generatePrimitiveArrayZeroPaddedEncoder( indent(sb, level, "/// primitive array field '%s' with zero padding\n", name); generateRustDoc(sb, level, typeToken, encoding); indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn %s_zero_padded(&mut self, value: &[%s]) {\n", + indent(sb, level, "pub fn %s_zero_padded(&mut self, value: &[%s]) -> &mut Self {\n", formatFunctionName(name), rustPrimitiveType); indent(sb, level + 1, "let iter = value.iter().copied().chain(std::iter::repeat(0_%s)).take(%d);\n", rustPrimitiveType, arrayLength); indent(sb, level + 1, "self.%s_from_iter(iter);\n", formatFunctionName(name)); + indent(sb, level + 1, "self\n"); indent(sb, level, "}\n\n"); } @@ -465,7 +468,7 @@ private static void generatePrimitiveArrayEncoder( final int arrayLength = typeToken.arrayLength(); indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn %s_at(&mut self, index: usize, value: %s) {\n", + indent(sb, level, "pub fn %s_at(&mut self, index: usize, value: %s) -> &mut Self {\n", formatFunctionName(name), rustPrimitiveType); indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); indent(sb, level + 1, "let buf = self.get_buf_mut();\n"); @@ -479,12 +482,13 @@ private static void generatePrimitiveArrayEncoder( indent(sb, level + 1, "buf.put_%s_at(offset + index * %d, value);\n", rustPrimitiveType, primitiveType.size()); } + indent(sb, level + 1, "self\n"); indent(sb, level, "}\n\n"); indent(sb, level, "/// primitive array field '%s'\n", name); generateRustDoc(sb, level, typeToken, encoding); indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn %s(&mut self, value: &[%s]) {\n", + indent(sb, level, "pub fn %s(&mut self, value: &[%s]) -> &mut Self {\n", formatFunctionName(name), rustPrimitiveType); // NB: must create variable 'offset' before calling mutable self.get_buf_mut() @@ -495,6 +499,7 @@ private static void generatePrimitiveArrayEncoder( if (rustPrimitiveType.equals("u8")) { indent(sb, level + 1, "buf.put_slice_at(offset, value);\n"); + indent(sb, level + 1, "self\n"); indent(sb, level, "}\n\n"); } else @@ -514,6 +519,7 @@ private static void generatePrimitiveArrayEncoder( } } + indent(sb, level + 1, "self\n"); indent(sb, level, "}\n\n"); } @@ -547,12 +553,13 @@ private static void generatePrimitiveEncoder( indent(sb, level, "/// primitive field '%s'\n", name); generateRustDoc(sb, level, typeToken, encoding); indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", + indent(sb, level, "pub fn %s(&mut self, value: %s) -> &mut Self {\n", formatFunctionName(name), rustPrimitiveType); // NB: must create variable 'offset' before calling mutable self.get_buf_mut() indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); indent(sb, level + 1, "self.get_buf_mut().put_%s_at(offset, value);\n", rustPrimitiveType); + indent(sb, level + 1, "self\n"); indent(sb, level, "}\n\n"); } @@ -579,11 +586,12 @@ private static void generateEnumEncoder( indent(sb, level, "/// REQUIRED enum\n"); indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", formatFunctionName(name), enumType); + indent(sb, level, "pub fn %s(&mut self, value: %s) -> &mut Self {\n", formatFunctionName(name), enumType); // NB: must create variable 'offset' before calling mutable self.get_buf_mut() indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken)); - indent(sb, level + 1, "self.get_buf_mut().put_%s_at(offset, value as %1$s)\n", rustPrimitiveType); + indent(sb, level + 1, "self.get_buf_mut().put_%s_at(offset, value as %1$s);\n", rustPrimitiveType); + indent(sb, level + 1, "self\n"); indent(sb, level, "}\n\n"); } } From f3b0e79c0a7e4d49e20779823b78ebf9dd876935 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 18 Feb 2026 22:23:57 +0100 Subject: [PATCH 1513/1594] [Doc] Update release notes. --- CHANGELOG.adoc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 897cda1814..5ae8575833 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,5 +1,11 @@ = Changelog +== 1.38.0 (unreleased) + +* **[Rust]** Generated encoders now produce fluent interface. (https://github.com/aeron-io/simple-binary-encoding/pull/1097[#1097]) +* **[Rust]** Updated some function to `const`. (https://github.com/aeron-io/simple-binary-encoding/pull/1098[#1098]) +* **[Rust]** Updated generator to correctly limit length of var data written. (https://github.com/aeron-io/simple-binary-encoding/pull/1096[#1096]) + == 1.37.1 (2026-01-13) * **[Java]** Ensure Java code generation for precedence checks always produces the same code without re-orderings. * **[Java]** Upgrade to `Shadow` 9.3.1. From 239829837522a578f918d68d5a5302b188a95a22 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Feb 2026 14:08:00 +0100 Subject: [PATCH 1514/1594] [Java] Upgrade to `JUnit` 6.0.3. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f5fc18e4e6..4d776a4008 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ httpcore = "4.4.14" jqwik = "1.9.3" jmh = "1.37" json = "20251224" -junit = "6.0.2" +junit = "6.0.3" mockito = "5.21.0" plexus = "3.3.0" shadow = "9.3.1" From 61d6409c2bf3691d9c21b26cba9852586f503e95 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 23 Feb 2026 14:08:15 +0100 Subject: [PATCH 1515/1594] [Java] Upgrade to `Checkstyle` 12.3.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4d776a4008..33f839c213 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.4.0" -checkstyle = "12.3.0" +checkstyle = "12.3.1" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From 4eaf7f29660835819dd7936cf6286ab50ab3d786 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 2 Mar 2026 11:32:26 +0100 Subject: [PATCH 1516/1594] [Java] Upgrade to `Mockito` 5.22.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 33f839c213..b14b840259 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ jqwik = "1.9.3" jmh = "1.37" json = "20251224" junit = "6.0.3" -mockito = "5.21.0" +mockito = "5.22.0" plexus = "3.3.0" shadow = "9.3.1" versions = "0.53.0" From b5d28bade3e17bd01f1baa23b265b7bf023b6371 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 2 Mar 2026 12:19:33 +0100 Subject: [PATCH 1517/1594] [Java] Upgrade to `Shadow` 9.3.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b14b840259..bbe626a7ef 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20251224" junit = "6.0.3" mockito = "5.22.0" plexus = "3.3.0" -shadow = "9.3.1" +shadow = "9.3.2" versions = "0.53.0" [libraries] From 712779a05b6ea7d2a35d7dc648a933c133747879 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:26:26 +0100 Subject: [PATCH 1518/1594] [Java] Upgrade to `Gradle` 9.4.0. --- gradle/wrapper/gradle-wrapper.jar | Bin 46175 -> 48966 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 61285a659d17295f1de7c53e24fdf13ad755c379..d997cfc60f4cff0e7451d19d49a82fa986695d07 100644 GIT binary patch delta 39855 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

        SdO`o?U^bCPz6Ehh!k z$iWoy5;(rkuX8fgr;aa6Ctk;PqW79jwVr`$<8zxzba{NypJ@$l z5=}YGNTKY^CVPMFv|izZt(=n~ZASUrdGcrj2!jR42b+d`u4%~U9RMHcYj6;slDq%v#!)Pb zb~FxQVGheju_D^oGmIvUuFT<>>Q?^C;kaR(FoZ=poVf?pDinENSf?1hjyip!#r zz%VYqx3z!D-x{n9)>eHUhlb4B;Hqe3mR7nd6bSL_Bi)w<)$XyULxG4HGVjDS3i*#u zD(u41^0iB`Z7(A~>VLC1BoyeW{_HSrp_zGKW7E%=rA73;mL@Z!!JT+#Mq5aaad(Y7Vc|`7A-P* zs-LDsBltrOf2w}|fLXteeaC6R(?huUu)j*dUr7e_*<-* z-Clo^2&zi9qmeQRaP>$O? zd!qgt73?ajQM0?sTPt#EUTsBB*RVP$rxr48a%#ygWW*7j;)aM3;!=I}!#(ubqalNi z7*$J2H>{S?ollZr9~wdxHR{NSS#}SMXrzDAA2Pb=?#i56!C*esxf^r&TO^ED@?(B@ zM78D=jen7t85S7chr>c;MK_iA)TrYpWkyruikw>8tuIiV;O(8^+eg*OQMnDnYTbSE zosVseYSU-`RHIHU1eg0*g=_d;cn9vn&78ai-o|lS;1EYtf#1b`4Ije88vcRLx#Xt*_H{}a0437VjmMIokn22I!?nA)kY1IYEV6mr__b&3JtGRS7~^)x>3WM z)QE<6t4B3_R6VAi1=JJj=Nf-jJulFAmG650Y}KM+K!trb`97y{fr8)S`;x{53Vy3^ zkH!TGKH?kIxIn@0_1&*=fr3Ba+oykVfr3Bi`<2E83jVb3IgJYx`~}}j8W$+|%f44M zE>Q6Q`YSXpkhs6vzd&#eiNmK(W7)kNb^pUT29_DaaM8!Sicc`!mw;8JCHTX#-&K#%VR)Go<*wT%b@r|<54RLvX;}sk> z#tvP^K3yQ>NGac)`BXZvp{Qdw-`rkcEBdGc@OC>Sew-$4Jn=sdR9_IOCsP^@v#&<5=K#u+X1C$Ums% z`1RP~|36Sm2MA9re$SKMfM|bLYdzg~w+f!RF5;=Ecq52{A}9!6rn}Q^Gl=U#%m_R_Je)V~+@=g}C<)yiH)y$aH%Q}5 zX_>1u@!~Wj)(vTrmUy!*trxT@xUrqsx;rhYE!EvD@?x2Js_@usZpnXeYnxfq_?d5Y zv}VD!rMJc{C6P*qj7lO_yJRe%#d>3PeYN3*)OGKNAOtEGX~zU~s5A*Iq$ctsBSTI8 zt&v$q#y?JMF14Qj&IiTC%IFsuzm{F;Ynep;S@W8Lyo^Ei`x-w=WA+<6=`kwx3;$gf zT2kqbp;NL}Modhc{JLmdO9u#)3d59>tb$U1d|TCd|4#I{lB_&z$4Nv2xv^tnOO~C4#tsTE#|hwA zd0^*(NJ_YtuI)=CU7>pw$Giq>*gDwO(XzEkS73C^Y-L@ufgGAbVC#Ug(XM-UV{{ws z9xYuvwr+zBy#IIZl`T6mbX|V=>D=#}?|kPw-}nC>$FIEi#pj6VL*h<(z&Lfl{(TZX%}Om`1>i(4!EM@rc&Caf_nz6qqBA2ss2UNrKfm_4o+Eu4k< zt(}*3ZjER3VhsZi=$nmMJ7qspFp|?VfAzDuL zVG7gYAo*xTm;w~!uT^0RQ5}C>1b1q3*ZPecHwqf9c|q5q+mh0mhS|l3xs-J6kj<#s z*8V=5*SljM!<2o0JF44#S|?*}rM%vD^WYXm8VwUcibrtQ>PN4?Z1 z=$7lGchn4+ipFq>Eun5`wKk|3Q@7N-X{%{7Z)-+g)$$Wyb96Fvt5e;1q5wkAsJ5w& z82OB^?1o}PwpK){Siec34~OVxMpye> zo8+||=L?&&P7N5}!Y65hc6~5b_;{_zSDitPT4NXPn-;VJHN_a2sN}>xw_pj{QUfI) z>_h;3==$FH<}KX;8bv9QES8=w6%Bi$Yd3Nl(%=qbROfIo5MnU5L`yyme{ZUBrt62= zGGLm2W0Vcitptr%R%_RvFO+PE(6yXGCMSov$~$m znwB1>pX91CP9K4sjJyy|LKfQ|ru*opSjbO*SFTlMlI8 z>&(x>wzhe_e!|&v0i0d?42e^8NEi+rPb*}4S`Zbo&LX%>V{~+VuNXzC;HAiYih&rMHDw%by z`PO_2{Z&n#oHn73X~%VSSl9Eat>qB=NHpVyJ=WQp?=$lwMlq+_W15X0UENTS zqzsjE8`MJ4#728UMYvAzSxz>IyV<0F(_Ke4Q@Phr4GYm-H_x7f)S+fjX)1I27YZM87#%2AW1V%pV{&u4vXl>1!I-B2r=CoMY(RGtiaGJF*h3Hw%dWxR6xjqVt%;~ar=1V!f zDBTX_&eQYE|H2%3RV)hq9zqSTo!w?p-YW^gh0w;_6s{tn%xES)o}g1Xw0wM|#K%-p($`@BKl zV%L5fUa57ULjMT3jic;;!r=eRRqdbXJN)wz-i4wSl2GInkqy%q=^P{U`_)x+Z&e`u zD_#P9W(i@+O^V#92I${7qa%X69Q^_M4?zM!`Cl-?f{!|d-r@es91YX|a0LE0y^HEG zh-|`XDnQdv47PC_g)m;nfXcmM5vI`s9K|4C$HOG2L}6pW&A9LlzqsmdE0qc zFKcU`*O&>vP~dqHVD|%yzRm*rynv_!#&%St;(%C;X6Sw1qKa4wbTcdu6wwx4(l$?< zxnx+>i-wR`CK~4z+yz_rs)8$;U~;iS(E1_0h}ckzx?L*fk<_o>zkeSntANys{A*@( zm{Y8(Joenv6@dqTs?RnL3?{2g;w&bi+8S|jNURo@%-xn$1YV6xP{g<<=AGvrQt!O| zvulvlELuWhomh{YiWgUJ2~`2v*{Mgf{d2`A3&}y$h)cx=HW!|q4Zv!;lts&Sz|xDo zqmURDQ6L1%F(8Cz<8nG6;+14{flx(sL6oK2gJ?w1w(WC&t2drS3%1Sks)yJlHiyJU zaT%-v`Qv8s*nU(VvxFQe`om(2=ng`s9$X&hxJS=$c-y$u6qkzx%fQopiBv|*xEx_| zrL%NZrM&SSu16W3caLkFHfhlHdLNt~7TeJPieAyjeP4~Pu^LP}8BEv0a4KR;g>Z%p z-iU8;P_LbTIeExL@~x;pn-m1zhAZ0^OiyArUjgr{WuwvrHr$eQnpClmb=)X!nDh4q zblExw(-49e?*$HBXKH@kab|(B1L9yv>=%cy!LYb{E*47#bU0y=LQ==dO+Mm(%ZP9i z`i4;ih{ex&J%7QUvF1nh`W^a+R?6BHdf&Y5IR9pUag^PB%iO;!{a*zsVi@JQ(){7E zX_u_NFo}ASl5CCoT{bOV1iR2VIaU3WT1D=kdhHIl|Y1hCxN~V$`Iz@XY>673B zw7rj1vmLmAtq}D*L#ajdJhfoHC6!7>8xBv=5h#0#+G6tjb+L1FGb?x$^l&QqA}x)7 zJ?DLtf-%qLN%D%9s*lKAaKvIsLrNGf8;l4k!?X z!~NK}53^$sb{yXN7{oq|*-7xd0bsm;g+0^Y3zAMFu2*@Tq4U*_m&kjjVeBmB_nf0b zD&dVykyXEpz7$CKB3^dc9jR{r!_*Lu_&iPiGX2CP+)bZo@-KRX{r-A9;w{t3GJO>L z@5lZrdcf1|Yx2dPdyG2cO}@+OY5MN7^k6E1%@4ugbrJ8fjb-}OA&AG+rw^Tf^Z^lH z?_fEPr1o8%1yGw?u*ZWHcXxLS?nQ&U6)jfWic5h&(L&J_mtw`;rO-lfw*sZO6ewP_ zSYP12x%crhlgZ4^Z+Fi*^L?3on{)R6VYgOClQo5HdPC|5zEXHcl4#Pgf4=PUd_uL= z05!G4RczFp+a!clc&B+xg>wuFujYxXsxI|9hT_LbyLF!hb#cOxgi+o^B^n_Co7yy6 z(jP1a)bPV>o73*~IDFfy)v9JzAm;9US#Q!?BPqL~G*8NXF0jn%-TpM=X5|9S(xSkn z+-^VP#3Hif^QaB8E}w)INtb!51R(9NIAxlC9`VsD)1y{*H4Oci(1iHDS*K^~<5PUa zgWG<;H|gfjj8_A0mG%jKAI1!xatW~TGwOF>CQ7@Qn+l7s*(CLkP1cvrxEP$Z^4@Xv z@2F4|FrSt!_>y7*fz3z;^{EQC^?c$|@Wbmmy% zs7(sdcd}mJ@ZQOG8y{sOS87a8p*3`hiQHxT4)soFUP+1sj!O|RcldP{sIG`XCASkt zWm<;3?Hjh-O_a(gGE4R1oM$-uhj-aT4hv1)Ri|ExV1cJ_MX2%$fWnCpHLGs#RYg*E z;6#2Od81}%3{Hk+{8J<7p;#-_lNmO(1cS6|J_kA;HU zAzNPL#$HVj?8mx6`TM9Om>$uOGJhovF9Lk^NhBvp&0OFE7Y(_pwwa&>0Q1J>ceMG%3duGQp|?bP6GzT*7V@B+NZ@8A$6 z18q;%T}|j%IvSeLf~$k1&vNojaaT_Bn>oA-t1609skdIudc-X&*XldQ@fuk~?~#Ed zXX04m+;uGH{)C{Iiz%)6^t<<@vc+_uf&<9`9qk;?+B>>(%xj9d){hbfE@-7~#-hoG z*N?&W3(fg1pqfFSmBgIf*-#Bk>fzo*ljFQ`O<#~H}qrsL~6W4p~8Efb}BsKLsM3oLat7L1;nm+(AIJ_OHsu(PEb zmw7c?nX;x?T*?=#wG6J_tKhFKGxnQKvburS0~$ApS-J$8`*+#Ch-FJ2>pA((loN(qT60_48pE z`-PoIDMMkRoBmdHIB}QJvbE6fm4BlFGYmY${lPFwKOMRr46|L!^U%R;;7+wgR@i5d zOn~gN&d+BS6Lt0_ar&w(mgzdr`Uq>|3dm4%L4x)MYns%>$`u+L<^Eku09>V320r;1 z6aAh(5xf^#+4V!cD9-2m-qopd_@}eIS?7KB4i#Q?(_FfgVg+3Kvr}|FpbN3+_9Z2| z!$5I6v9e;?xelxar}w9#b2Rq!sY`FR2k7+2xot~fJD_q_y(KXf!9p}ImQYS56{$Y( za0_YeWBtD6ekh#8F?v>F;sO9;G>`ww3w;m(!wt!>esIU)X6usxH(cVEAX^R%^z_H>BN=8YFBaPC?%iQcR2e$Xfg| z@Lu~OR&Ua;%nWGYXcCo=Bj_dfa>0DA=g?7KlbX!@>H^yx+FXMPE&Q;6k_3UYVyhxI z=ZYbhy_Z`_Cndm2QNKeN*i!@(pCsi5dhxA#8ShlXAKuVSu;>tb43bpPf8TYJeKU=z~RPxWQ@Sp>{~%uSFSJFGHCQl zEQ-YmJrgu|0~65)=@^jKp>$V)q#G8MLlewza~2E~NRS?1o~?8z+LU6+PghYaUD@tv zsX&P+))C-)9~8|5Ys~=Gc^5Q~G(}6I7bUNP>L??UPaB>1eKiS@YhPn(jlB>BJ9m!c znuXo!Y>MlqUy4Exs`h8~=fcW~Whu3}20k>GoV3PPjZK4RMM($>yXd^ULe*)ZuLbf$ z@1t(U8AlSTCTIgF!~}4&SOzrX34s_>nTcw}Z<2ET(4c4Ec3jaU_=8`qZP~uJk+j&C z*o1TmGcE9-AEbG%(f7qA-Ubg_#i*GihhPkI4pWoR+EC3cj2LAOHl*bdd2E2zDBnpG z&uA3pO*edGVO5FDbdIFEwgYT%Mq2Cw#pdJ=x#N%Ivi;6-d^g))BsyE}e$ksiq9bly zydi(M*mxPxH;iF|P)3kk21=L!)IVo`|E9n?9w{S8+k)W)4fFNbKsy!3QLyNlUGS^P?J7uIvJS{#VAD#5H35gxAmN=f7ZX7Y-5eBk_-W6%C`q zy}8T$7(908u=gD-l!jJvjy%oPkT)Gd1av|zF*_m7MaFE>Lw)W%zu7rj)o*0wOz~Oz z@?1zW1hXXY@!T|hbm=HPtW%}K<8fg7G&OKvE{Tjxg|mIwOQ%FMK`BN9)sEG{O$O4m zk@p@Ubu(2LUDT7$cdX2A2o~z}Z&ovp?w^4}x%&bmRN#9)89MTMTx|VFJw3R)S>ZN= zYl-rTV8*86unCGHY-wT|v2>y$T!oX`G%n{X4ut@RJK~WGIW-uj= zQ>j(VA#DeyC=vGh?-%2cgl5zSDBw4H$^v^hi?g`IKHEi|ML?a6g?Gi`K-?O{RSoHD zOstehlo(6p0olcvE-BOK;d*&~Xrf?J_2lr>AD$9g&c3`^F}4VfOUf!~gNfM%N4xU= zaX%m!i8dYZ$$2_HK2r|y@ryAuZ@CC9C~S8euhb1Aq!UX8Uq}ndD(X7BLU2gc`>>JU zWeGU14Ex2c>LGz$2kj!! zFickTd7?ZpC?k4fFl@=>)$T(M#G(d)vKamRPn?rdM9z0wP!d_9EP4_QZU%)bL4^?Zgec^OeyZ&&*o9)fcz8LTS-yu%j4v%$ZC71%Xh87Kr{R%3Ra|*L)Nz?Dun$D3CC!i zR>D6tIj)O}Uw|N17Oo~4{(jSQvH6RX{HU_iaaJOevC+T+cR@wU#>;J>Q9f=Pnar-) zAuz2n8VxSn1$4*?0qTJNPX0wO)I4znGRW!O<3jN`>8y8l3zH^Wk4hg&1;<2o|#XZ2ukL>ycB@tCZxXmb8>%nIkpS*M;zxxy5 zjqd7V1(X!Z7-4S0sa#tkTVCl?yuTnC@ZCq^;vHc$TcwZaPs;_zmt*|-L*{a(`VDx~ za&H^m*$x#L*EwIhewT z&T_W{rVZxo4pG+JhgaN*7YY^TfXP+LUK}dzU$P`vW7sDi$1b4?Q{+1sbM{D$>?B$f z)e|Ed+$Plp2&#ENkUE&%t3f3&O_YxX$;9D@qLk>{<6RMTrdO)83&&BN_I8R35f|Xc zW&%K)@t=_8te4T9OD(v2qMl)?Vg_1H=g`a-^9{$~_tcPr> zAAkej_4%bx^nPnTFFemu!gQUq3Y*GD@&Mi(_os2Pc@~z>tB%FRFeqM=d&+5k`dY z&;y-6XxU~%n|pfj_m|3}V?7ea-ASW3`NP-;-101=_m$56G!p_s+%*~5#$Ae106pWp6B-@GARIlSOK?cJWMt%Vac zq}=#D2;#G?VgGi3>`B-Q9%MD{lh?Opf^M$`8ciq1C@%KxA}?Hx5qFx$+k@#&$#7pv zZpJTOAdOyxP}Zip(OpRO4D7{SSdQ0p<@*V&#~dBY#?pGeHoZygLkHU2E3C&*pYV68 z1vt~Jx87cLpCFy2=Lw^0z+^99&Q(|p_nQrTuAK88X4Bh5q365n>@~kaGy=U@x*d%zjSyQ()Bw9ra2AD*8TRFvnATpY>wlWhho?NqJWhTUeiHz)-o3 z9?fPPT?Otv^^chT+@;5rnMD+7&6h*Vj%3#L7@~yV4fIVleAQAc;_zbMgO=jO| zs3jsRC*=Mvi`G^*hlFoaCWQQ*>0yh#qy{nPQUZ9@I;~lQDjC15VhhhW^5Ud{G4Gu! zAx1VoXLu%t(1oZdNJR@D0dl%W@>93Lq}anm4WxmR&Yv;WmZIm5;oQO3KYg%6fEg(Z zXH;z$?ZpkPn>BiKzG3%caMj-V2kBRekyBZjgoL?WweA4P3|tJFU~-#0T%l*HP>z#E z8UR?*CZ-yM5%NozVNq53_g%DodfZ+Yz@@7)h(kI}Skp^H2bDV*<>&R_&;f=JiOHC_ z6i{}>q6A~K(z%218j@0S+y+QlSBEo@52k2-_A1mdW%%ebZ|;a9z&Q%7{{X{OPehD@ zHKP|(O@BCDEGIcHUoq1Oe75KkM5Cuf$9|OrE1?2}W zC1N{;6uM|i4qS_s%Ur)03D$D8U&o}lTagvo*E?ME5dZZhTxN7VVp!gi^FEP<`1*)$ zte473PaSU0rnx-mvYK!kjo}`kf@vZxU=}z_gHv?!IDK8zFV867>5Xj{qN(&?NH-G4rC>uj@ct zBQbrbyD8sBD@|`tfy8pjUu!f>U6U2w+ik-l+v z{mgt_TViVEb*7Ea(ac`{y|h2p_>CI|H&E^`c+Z(y@QlYV>N@(z*Z3PZ0&bo~-6aqI z2AN4Zj?`1Um!)S3?keti)z@zD)mkqqeN+^ELkEa@CZ1P)E$0x^U+(@9^!c67kXMOb z;xU!1mC?7}lshRC!J`dmMiN-9h<=U!S5W$b`^_;bH2d6N@hK|{vqAyfz>X~V)%-?KHR z4KBN@Ilp8@3y!T^!gFx5hw?W?52dLOQYatR}#@;3ZxZ`;r5fh}kig)nN#ouF6Ewf?AaE_U{Ddv~f zuK(`fH?t9JH)y(a0#>~ow={O(Bzj2a+x5WJ_h;U@TJX3rt!H3Tb6k$MsWyKd;+qt# zCTE0YQYW&M&*KZW;9bCN!QsR;^L@_L>%+eMIT`o#CQk4^^L7XIxCP_Mf}*mf3>7g4 zjcy-f4=0$CsMwT@Wda#6doKK)7@YSpB$U?=r`B^O@EJa-XwUXNC-)=QSg3J&|6SOV zOz6_Id-B62Z=vp&VhK`zrspBVRvW&5hD4M(-^N}MMNY<6jtK{Y`?KA!<+HSUrESH- zHpZ^-?qU+9#XlNPypHX8h8l|}p`R88{c8?aOTu~zisfm{Skxy3%~s!H6!9r=hOC|ShnFP4mPD34EOxBot;zk7m}{G%C&hD@~g zbI-V8B0DF?@)QdmSpD2zrZ{QYj`z%3%vvI@x*Dgh%WVVBF$Cw1U-~(Smw!qpZU{gWOQ(G{0WvGw)GRsrOl1{nXT-?l zd0l;@Rn(XCp)ZRI`{nZgCK!zQqk@Jg^vPELJjx5404-bdAiTw;h^yDCa*&ncS4b8W z;RkUL#S#O`SruC4hezTjn7jlZ0QEsu=YL<}_y9;Az62zp1P2Kh2$9ofXt{_Cn=K9BKSRq9DuX-v> zN}B13Zv@W+MGN@~D=a+B=RYaL|4)uVP%34R9+mtc8kL0bRbmj-N;=4!5=O)a5i3Y- zB@u$91OO5s@won!|4Adk`b0m;c_{Nhk-}3jo=^xN0E7xei~fJKlprA` z)Rg}zPXGYVpLobCKX@oU%!A@V03jZ>T2!#r;(kIUt3tYJ2q6O10*H@2-Ce4Q;G@+a zZ9z3C5U>*WV}So!Tmu07PXefE{|l4X@KXHWetfh~z)rpY1(_)xnzwz24W|w^9L^_@ zjRg!+r1-aK84P;54h2>)fE+?&ijDy5_6DITp{MxoU=RSn_9PmD^&>1*%ZB*4m(Hb@ z2>xf_<1jL7StuU1d^x}}Y{TA9hk+3D2oZAD*;$VUcWLcPH1AXg2weU~n44Bl!5M w7PgL>&;I`;?us74{(3&7f4)He))T^OmOUET88lJokpk8iEZ0%Y};;}6WeLhG)ceS&-?w@`}e-CJ+s!V zSu^$txpxNH=!yz#X{~D|!Rqmyk#lN~X&X|PN-VC(*S{l4u_MT_%(!w!9}$Uk0n6R( zL%pgVFwqG>LG8`I2L|;5AqL>R@p~M3nvbIPkUGU1UNfg*ZauQPW^~muS7cbUWCOm& zP{?3pP$V2-95b*Q&5a|Od0agz$|zeVRaw(<6XfTiP7(r>_dccUn9+Z$OIAQHIvk>h z-e>>h2IYFA7XUz^RO%fk^G>D!fyWjAhD)3jY%kZDE?g1Q*iyD{vH)#Q_EPC(p+ZDo z$G6l>EuZ$n!Tme2S}Diy_50eVaJN?#7YR``jmssIO%c}!MG@dX0H^-IbZ zDWa4@c9N7UL2RIv#+LfBDwa`1TUZ--NgTb$yk{XDga}iYdLMp2q=-Jw!N%7|lq^9Y zo1&b|ArSu_@%g>sA`&2Q_>u}xtYqFt#F9;%Ym}2ZQt90lzAoLHBd92%Vhg~=HI%8;6Z;I*t=r~oAQ^(Ce z$tFjU=&C6`fx|6I?f?taoq*2Q@%?a>ww_4Q%-Uj_?EQkM+vm_GPu8pe6lveXxY+Y^ zlaZ3m!a!*IQDy5e_qY)(ho2=cabN$zhJa)pbf5?==6-{4l`i3tma zC?Z6zT;g(>&7Vg8BP}62RGt^}eAThhTWwBoT}c6txFgn+IJoQ(LR26eSprJFghhedF~s`k_<91{q-vf($kZLm;kO5CyrANi2N;X+hK}}o z@as!OVxzbXf$(^yWI|Y`sN^Ir zB?!|V2r1K0hJ}7-BqX-ERHDXKwUS8|6(t8X#!w!>zSVv0=Gwk~WmGdVfqKvTDu$UV zi3$8JI>i@APR3=|qu_0AlW$|~?fvVefV3Z?mSX(w{O-=`K2+^+tuL{y$y(Qo(nU9T z&sCVDGnngR0LM~i2vZ2_X#2Rx?i$fS)bXtd*ra`GO!pu?%pSPQw&M-hGB)~l=NjHv z?K{-KE1UoTv+&+7Ys-$OiPPx_SUMqKtF!#T&Cp4YDQDIn8)s*O?Zx0qqt5TlH)Vr5 z#v&SZQo&-HXLf|{n=dmemu2lh49_-ckP&y{-VBc*0O3DC(Hp5n`BHJka!}Q3z=x^< zMQ{tD+ULXQ*<(e#%Ls+dbSD5Hn|6E<=X~>)+?njf0$ctF-ho@JX$blCV`z4vyXJ~8 z+^}bP&$vO)zS}t#gIc#u*%ivLFWKM0>!-nIvwYTjbA_%i^IV|0S6i~n*6oZz!EeE} zX4zs-HBP1tuo-@B6V3`YUNifMI~HU>UZ`(NITas%uRt*V2`qLk7*;~QCjrYuM|l~S z1M&Q`t12hy5_>J}0M3dxR$gv<=$g;jJl?Dt^=s%L+F@IuGen!c|4_6oL~`bMNPKsP z3{U~F7nSYof-?>~AW8A4y2-+_G`)}f z1N+(~`BOnyHQJJp3+vDJqY~JCzFii6h-!+s#~}p#b!7&& zX&rh-Hq%+v(=yR%uD;Pl9zN;=|I9wt1j2yp*=&rKOkiZ1qaSKXdzZP6@c+|V3SWUFj zbA~b-Z08Y|k=kf$IU;60v1;)3x`0jkyh||%oLyWCw;JbSB zl72>_X$Ofz_Y(ZmoReF7cxu265&|)RIB4e%)WBA$;N~1X(r5M)1WW<%>I!|3QHIs{ z`;Ojg!Q`D?4B4n+P4H1m4B3I4$IIc3M5A-eoE*>T_m22ewptA*QPmBEVq?caEAk`x zM2R%lVcLr<7;pIMv@tf^3!c)zF$h@vWVbC@zVU^_F#m6lqEgCuuoUA;du$#rojSk) zLMa&ByKlI2he)74iD`^JOWOv70y9sSLdLWT@fUif2r`(Aq*ONqiSaS~W3eF}ENosS zo6DwNGeHCIFn@rf(jdHa=!80evnguFroVx69AEjI^tVjQDcD&(QLGIZBOq&mCZk2S zCJ_L2?UYy9$B%Ef@Ov^~(|fLto7wD-Ptb}KV|WUn7jBx&EZVFxEyYry*E%`Was_*G zB{C!XY~)GgaHo%H;l32z%&q#*4EjUAXdkvd6HGJRROTQuXppi;ve;#6;xH#AHh)wF z%Qqe@^$ytZd5ULL8TkV&knbV0AZf?PK;pWy6Ijgd6N9@(Z-8#@re!mB*2e~e;NNWX z<(>%4djki3OMp(M|L#9VegX;JZ;d=8l zCvX*q zDD9}o*=x1@x#$CdQ;{`YhT`ABub?5TqiTH1Y088SNJa_&E0*V1NMXQgA0%kuFWR$J zWH(EvJQL+X)`C2=Tq^I8_&FiABP94Q zg?%_$KWR%~Tg|-+V#zK>Vf)WN|dg1*vZR zruO6PApbS-j0Ley-b$GrdREN}OQG*@p$s49m0a_tqzxv>$8%;KAe zFp)wNc!nz{AG0}th**_<$wcuFInbJ*0*;33gL*Qq`HD}Dj0hJ36reY-d}tZpN0}a^ znx#cdZDGLKH3sCiTKbVD{vw6ERQDQJLnM4fq9hjf=h142pDhXN&?>cv25>F4~^fGjosOWWFOpM zRyS`dHg!A$EoHM-cj%=Km6z6p?b~JQ2Q>iQ>!4228bX40>HwO^il&G$=O{7>iOwEj zBrVTX=(OPM$pxoLH0G^eK5WtqT&`v=$*>w(_DNrNv=8-1Ypi8FHr_hF+ZBzFJ?3Oj zVkojNPXG~+vYwZ%ciz)XIUOGbALw%jjy(Z6P9`aoU=K|*p8m{LCzAFVK4A&V05RLYLVdC_ z_&I`_Hhma2z5bMj1HU=?D7ODFJgbqDarCj+G6Q{+%%-d1n-qNYQX|Ws@l#96PcXuv z(#_Bq+&-d6-f8-@B3$;jxKfBe_*o9I*)0k0ck~Sh`wpIdQGLW*!U1SOKR`9hnnrf$ zGFitw{g>>&D683bj@vHuQ}>KU2_9>685SlFb?z;`9CO=)o=-7?m_0&3EB)4#^;ngKmEq&zYmHag;poGfezAyQxDr<@NE} z`Q(oN~pfBiw+6ZiBaIRuEhXf!WycIyB{pQ(^9C0i}&J3ac0rR(u^OFqE$B5RZ~b=p{LF3&V(FlYCKdBV+}3 zvxgn25^#6N({f%h0x>1biUXOmhZWlI@(^SF@%q+thF{LxUp5A`TCjm%dEW1oG);y- zIXZJ#Pv(5Uv`uRUuQ05dHF(PAzt+Wmul^1!COkn~g+ zeN6(URji*!bk}krVu$QbR(R%`!5xQNpZE^HO7Cw1tr3H;1A%926u~={s}VTO2vT!i z5oyX*D@;LI*3jnsI{EpcslSl_wP6-*2{KbS2nYdG2nbaLs1#T!+?026bs$t%hO(&u z`rZQKW|Nl&sO$S8-Qo!JVC3LLd-ty;t<9~nYuVT&(gT;fP#OVD(O0NmJq~)-v-aty;i#BD*gp9785RSy#rV(L^^ES_fXwtaNF)u!=8C# z)wkaa^&Lu|a^Z^LPxATAWRnSZ_?{zzd-3mO>F}&7i6@2G=q+;1wt*^|c=Tf+VIV7X!8c|X05xc89 z)|(5dg|H-$1V+EcGg}&#(h>=&fpgEb`VBj!09{n$DP4VmNleQ;QJp#O+~UNdSf|7* zmr0?e3Xk3wgvDtYgJi$rsU~zr zmqIjT#^pbVtsIjbDgGO;GX8J8>ZURTiWzK{8I~D_X@-EH6`&+TfD@iRx;WnLmfkUF zl&A-suM)@^l9;3e5ghqWVx81GO4dGok9oI-Co{LAqCsEq#)XDY4-Z#oWLgKFg~0?D zE!8eH^jfR}f6`|IYtHPI7tz8L%#dynIBr~3mVLtdPSc1~@^(+!Xw@(Js`vwdCe4t@ z!+4~Gd3codGlp+28ICy+E)fotE!g#To#L|7+z7&GOC`EtHlQ&O$3LrQMFrUukko1} zcX7~ag#?-`=2|X40x>UjIhEl?#}6A>WTieB`icK)xPs%i5q14HMgQK$MYP9P*UD@7 zw!+DE@s}QO@qir6vC~1pIjjo2z121Tdq;d_0EYZkd#wLSG@Rq><@bCS<)bFKfG16S z!@e?>0ZA5}4v#fbZ2Ogut(Con@4b?&QuSPiU~B>1WcL_O$jM_}vElb%=M2>@C*A!w z)*@tTLf3+KXLT%3%u%q&Y$)z1l&ADUsIk4#;w<)#!o7}9luq62#Wz)8^IP?5Ltz3q zpYMr!UcUJVe*LAgQT{C1W#hay_1$*k;XR8^QwaGG;SGQDhK$a44DA5qR>H{`ZdCMV zC5!GrR`QN0w4JkCD=GvlTyL_0weG0ReWN|b;P=(r+kt(2(I0s~^~{6Bi-$mRBY8LY zb2cu3i9-N26if*Kx%>`@>v*G<=5#-j#xzZa5NkmZ!ro)LP|YLQt)#{XcS1kG2H4J? z?51UjK8G*=N~_uZRVS~ApY2#)S!}|~xDjTjS0MXqA#9T=d~muhTSZvdz(jx4T1LyI z6f?Oc$@aElelfpi{MrirWO1C7&;Z8tVChzP*nzY1auPO^YLy?C&~tySz|tc zVK#lPBx)_|n>#LQ_0Ih(s2=oDY?L>^GBhnFtYRDn8t>T61(T8Xc7rV^(V?an8xp)w zd(m01$h~k$*zT(MP~Asab2NE$&t)nw!$s1vNldkZ!lCmksw^%XB{xb))>*vCeoYB-`MJ{F;9c7_&Rr;o7KQOPy^=MNbH>&9i< zU%QTnT2RE<~unJT#U+vWgSJVjEk2Ly+F&^<5opYJQ6I@uuPC&6qmTUWmE4 z*9~JRrYk9<=kzBx!E~J#-U0smu!1y~Uq$~6@W5m#;*


        Xdyd*p!l1Y@nCA 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5f38436fc6..5be30bbeb2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index adff685a03..0262dcbd52 100755 --- a/gradlew +++ b/gradlew @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. From ff34cee9d6a1a110aa0283a555a0985535fbe8cd Mon Sep 17 00:00:00 2001 From: Leonardo Arcari Date: Thu, 12 Feb 2026 14:54:33 +0100 Subject: [PATCH 1519/1594] fix: clippy warnings --- rust/tests/extension_test.rs | 2 +- rust/tests/fixed_sized_primitive_array.rs | 2 +- rust/tests/issue_1066_test.rs | 19 +++++++++---------- rust/tests/issue_435_test.rs | 2 +- rust/tests/issue_895_test.rs | 2 +- rust/tests/issue_972_test.rs | 2 +- rust/tests/issue_984_test.rs | 2 +- rust/tests/issue_987_test.rs | 2 +- 8 files changed, 16 insertions(+), 17 deletions(-) diff --git a/rust/tests/extension_test.rs b/rust/tests/extension_test.rs index 665d8f92b4..984eeb61d8 100644 --- a/rust/tests/extension_test.rs +++ b/rust/tests/extension_test.rs @@ -187,7 +187,7 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec)> { .available(BooleanType::T) .code(Model::A) .some_numbers(&[0, 1, 2, 3]) - .vehicle_code_from_iter(b"abcdef_extra_is_ignored".into_iter().copied()); // abcdef + .vehicle_code_from_iter(b"abcdef_extra_is_ignored".iter().copied()); // abcdef extras .set_cruise_control(true) diff --git a/rust/tests/fixed_sized_primitive_array.rs b/rust/tests/fixed_sized_primitive_array.rs index 59e6df84d6..a071e537b3 100644 --- a/rust/tests/fixed_sized_primitive_array.rs +++ b/rust/tests/fixed_sized_primitive_array.rs @@ -4,7 +4,7 @@ use fixed_sized_primitive_array::{ ReadBuf, WriteBuf, }; -fn create_encoder(buffer: &mut [u8]) -> DemoEncoder { +fn create_encoder(buffer: &mut [u8]) -> DemoEncoder<'_> { let encoder = DemoEncoder::default().wrap(WriteBuf::new(buffer), ENCODED_LENGTH); let mut header = encoder.header(0); header.parent().unwrap() diff --git a/rust/tests/issue_1066_test.rs b/rust/tests/issue_1066_test.rs index 2c22c0f44b..95ba97cc1f 100644 --- a/rust/tests/issue_1066_test.rs +++ b/rust/tests/issue_1066_test.rs @@ -9,19 +9,18 @@ fn decode_optional_primitive_field() { let mut buffer = vec![0u8; 256]; // Create a message with `field` set. - let mut encoder = Issue1066Encoder::default().wrap( - WriteBuf::new(&mut buffer), - message_header_codec::ENCODED_LENGTH, - ); - encoder.field(10); - - // Drop encoder to drop the mut reference for the buffer. - drop(encoder); + { + let mut encoder = Issue1066Encoder::default().wrap( + WriteBuf::new(&mut buffer), + message_header_codec::ENCODED_LENGTH, + ); + encoder.field(10); + } // Create a decoder for the message, but stating that the version is 1, instead of 2 // which is the acting version for `field`. Thus, `field()` must return `None`. let decoder = Issue1066Decoder::default().wrap( - ReadBuf::new(&mut buffer), + ReadBuf::new(&buffer), message_header_codec::ENCODED_LENGTH, issue_1066_codec::SBE_BLOCK_LENGTH, 1, @@ -31,7 +30,7 @@ fn decode_optional_primitive_field() { // Create a decoder for the message, but stating that the version is 1, instead of 2 // which is the acting version for `field`. Thus, `field()` must return `None`. let decoder = Issue1066Decoder::default().wrap( - ReadBuf::new(&mut buffer), + ReadBuf::new(&buffer), message_header_codec::ENCODED_LENGTH, issue_1066_codec::SBE_BLOCK_LENGTH, 2, diff --git a/rust/tests/issue_435_test.rs b/rust/tests/issue_435_test.rs index 7b1a9f8ffe..80ca723642 100644 --- a/rust/tests/issue_435_test.rs +++ b/rust/tests/issue_435_test.rs @@ -3,7 +3,7 @@ use issue_435::{ set_ref::SetRef, *, }; -fn create_encoder(buffer: &mut Vec) -> Issue435Encoder { +fn create_encoder(buffer: &mut Vec) -> Issue435Encoder<'_> { let issue_435 = Issue435Encoder::default().wrap( WriteBuf::new(buffer.as_mut_slice()), message_header_codec::ENCODED_LENGTH, diff --git a/rust/tests/issue_895_test.rs b/rust/tests/issue_895_test.rs index cb58e82d85..35db43541c 100644 --- a/rust/tests/issue_895_test.rs +++ b/rust/tests/issue_895_test.rs @@ -1,6 +1,6 @@ use issue_895::{issue_895_codec::*, message_header_codec::*, *}; -fn create_encoder(buffer: &mut Vec) -> Issue895Encoder { +fn create_encoder(buffer: &mut Vec) -> Issue895Encoder<'_> { let issue_895 = Issue895Encoder::default().wrap(WriteBuf::new(buffer.as_mut_slice()), ENCODED_LENGTH); let mut header = issue_895.header(0); diff --git a/rust/tests/issue_972_test.rs b/rust/tests/issue_972_test.rs index bcf4cd77e8..c90fd452df 100644 --- a/rust/tests/issue_972_test.rs +++ b/rust/tests/issue_972_test.rs @@ -1,6 +1,6 @@ use issue_972::{issue_972_codec::*, message_header_codec::MessageHeaderDecoder, *}; -fn create_encoder(buffer: &mut Vec) -> Issue972Encoder { +fn create_encoder(buffer: &mut Vec) -> Issue972Encoder<'_> { let issue_972 = Issue972Encoder::default().wrap( WriteBuf::new(buffer.as_mut_slice()), message_header_codec::ENCODED_LENGTH, diff --git a/rust/tests/issue_984_test.rs b/rust/tests/issue_984_test.rs index 74cae2eb07..a378d39105 100644 --- a/rust/tests/issue_984_test.rs +++ b/rust/tests/issue_984_test.rs @@ -4,7 +4,7 @@ use issue_984::{ *, }; -fn create_encoder(buffer: &mut Vec) -> SimpleMessageEncoder { +fn create_encoder(buffer: &mut Vec) -> SimpleMessageEncoder<'_> { let simple_msg = SimpleMessageEncoder::default().wrap( WriteBuf::new(buffer.as_mut_slice()), message_header_codec::ENCODED_LENGTH, diff --git a/rust/tests/issue_987_test.rs b/rust/tests/issue_987_test.rs index bd496ee801..bca123f2ba 100644 --- a/rust/tests/issue_987_test.rs +++ b/rust/tests/issue_987_test.rs @@ -7,7 +7,7 @@ use issue_987::{ *, }; -fn create_encoder(buffer: &mut Vec, off: usize) -> Issue987Encoder { +fn create_encoder(buffer: &mut Vec, off: usize) -> Issue987Encoder<'_> { let encoder = Issue987Encoder::default().wrap( WriteBuf::new(buffer.as_mut_slice()), off + message_header_codec::ENCODED_LENGTH, From 271699bed8cdd2620cbca3404cdad4ab881ef293 Mon Sep 17 00:00:00 2001 From: Leonardo Arcari Date: Thu, 12 Feb 2026 14:57:29 +0100 Subject: [PATCH 1520/1594] feat(rust): generate setters for optional primitive fields --- rust/tests/optional_field_nullify_test.rs | 354 ++++++++++++++++++ .../sbe/generation/rust/MessageCoderDef.java | 3 +- .../sbe/generation/rust/RustGenerator.java | 80 +++- .../sbe/generation/rust/SubGroup.java | 3 +- 4 files changed, 437 insertions(+), 3 deletions(-) create mode 100644 rust/tests/optional_field_nullify_test.rs diff --git a/rust/tests/optional_field_nullify_test.rs b/rust/tests/optional_field_nullify_test.rs new file mode 100644 index 0000000000..188eca4cb6 --- /dev/null +++ b/rust/tests/optional_field_nullify_test.rs @@ -0,0 +1,354 @@ +use examples_extension as ext; +use examples_uk_co_real_logic_sbe_benchmarks_fix as mqfix; +use issue_895 as i895; +use issue_972 as i972; + +use ext::{ + boolean_type::BooleanType as ExtBooleanType, + boost_type::BoostType as ExtBoostType, + car_codec::{ + encoder::FuelFiguresEncoder as ExtFuelFiguresEncoder, CarDecoder as ExtCarDecoder, + CarEncoder as ExtCarEncoder, + }, + message_header_codec::{self as ext_header, MessageHeaderDecoder as ExtHeaderDecoder}, + model::Model as ExtModel, + optional_extras::OptionalExtras as ExtOptionalExtras, + ReadBuf as ExtReadBuf, + SbeResult as ExtSbeResult, + WriteBuf as ExtWriteBuf, +}; +use i895::{ + issue_895_codec::{Issue895Decoder, Issue895Encoder}, + message_header_codec::{self as i895_header, MessageHeaderDecoder as I895HeaderDecoder}, + ReadBuf as I895ReadBuf, WriteBuf as I895WriteBuf, +}; +use i972::{ + issue_972_codec::{Issue972Decoder, Issue972Encoder}, + message_header_codec::{self as i972_header, MessageHeaderDecoder as I972HeaderDecoder}, + Either as I972Either, ReadBuf as I972ReadBuf, WriteBuf as I972WriteBuf, +}; +use mqfix::{ + mass_quote_codec::{ + encoder::{QuoteEntriesEncoder, QuoteSetsEncoder}, + MassQuoteDecoder, MassQuoteEncoder, + }, + message_header_codec::{self as mqfix_header, MessageHeaderDecoder as MassQuoteHeaderDecoder}, + ReadBuf as MassQuoteReadBuf, WriteBuf as MassQuoteWriteBuf, +}; + +type TestResult = Result<(), Box>; + +macro_rules! create_encoder_with_header_parent { + ($buffer:expr, $encoder_ty:ty, $write_buf_ty:ty, $encoded_len:expr) => {{ + let encoder = <$encoder_ty>::default().wrap( + <$write_buf_ty>::new($buffer.as_mut_slice()), + $encoded_len, + ); + let mut header = encoder.header(0); + header.parent().unwrap() + }}; +} + +fn create_issue_895_encoder(buffer: &mut Vec) -> Issue895Encoder<'_> { + create_encoder_with_header_parent!( + buffer, + Issue895Encoder<'_>, + I895WriteBuf<'_>, + i895_header::ENCODED_LENGTH + ) +} + +fn create_issue_972_encoder(buffer: &mut Vec) -> Issue972Encoder<'_> { + create_encoder_with_header_parent!( + buffer, + Issue972Encoder<'_>, + I972WriteBuf<'_>, + i972_header::ENCODED_LENGTH + ) +} + +fn create_mass_quote_encoder(buffer: &mut Vec) -> MassQuoteEncoder<'_> { + create_encoder_with_header_parent!( + buffer, + MassQuoteEncoder<'_>, + MassQuoteWriteBuf<'_>, + mqfix_header::ENCODED_LENGTH + ) +} + +fn decode_issue_895(buffer: &[u8]) -> Issue895Decoder<'_> { + let buf = I895ReadBuf::new(buffer); + let header = I895HeaderDecoder::default().wrap(buf, 0); + Issue895Decoder::default().header(header, 0) +} + +fn decode_issue_972(buffer: &[u8]) -> Issue972Decoder<'_> { + let buf = I972ReadBuf::new(buffer); + let header = I972HeaderDecoder::default().wrap(buf, 0); + Issue972Decoder::default().header(header, 0) +} + +fn encode_extension_car_for_optional_field_test( + cup_holder_count: Option, + nullify: bool, +) -> ExtSbeResult> { + let mut buffer = vec![0u8; 256]; + let mut car = ExtCarEncoder::default(); + let mut extras = ExtOptionalExtras::default(); + + car = car.wrap( + ExtWriteBuf::new(buffer.as_mut_slice()), + ext_header::ENCODED_LENGTH, + ); + car = car.header(0).parent()?; + + car.cup_holder_count_opt(cup_holder_count); + if nullify { + // When enabled, tests expect optional message fields to be encoded as "absent". + car.nullify_optional_fields(); + } + car.serial_number(1234); + car.model_year(2013); + car.available(ExtBooleanType::T); + car.code(ExtModel::A); + car.some_numbers(&[0, 1, 2, 3]); + car.vehicle_code(b"abcdef"); + + extras.set_cruise_control(true); + extras.set_sports_pack(true); + extras.set_sun_roof(false); + car.extras(extras); + + let mut engine = car.engine_encoder(); + engine.capacity(2000); + engine.num_cylinders(4); + engine.manufacturer_code(b"123"); + engine.efficiency(35); + engine.booster_enabled(ExtBooleanType::T); + let mut booster = engine.booster_encoder(); + booster.boost_type(ExtBoostType::NITROUS); + booster.horse_power(200); + engine = booster.parent()?; + let _car = engine.parent()?; + + Ok(buffer) +} + +macro_rules! with_decoded_extension_car { + ($buffer:expr, $car:ident, $body:block) => {{ + let buf = ExtReadBuf::new($buffer); + let header = ExtHeaderDecoder::default().wrap(buf, 0); + let $car = ExtCarDecoder::default().header(header, 0); + $body + }}; +} + +#[test] +fn extension_encoder_cup_holder_count_opt_sets_some_and_none() -> TestResult { + let buffer = encode_extension_car_for_optional_field_test(Some(7), false)?; + with_decoded_extension_car!(buffer.as_slice(), car, { + assert_eq!(Some(7), car.cup_holder_count()); + }); + + let buffer = encode_extension_car_for_optional_field_test(None, false)?; + with_decoded_extension_car!(buffer.as_slice(), car, { + assert_eq!(None, car.cup_holder_count()); + }); + + Ok(()) +} + +#[test] +fn extension_encoder_nullify_optional_fields_sets_cup_holder_count_to_none() -> TestResult { + // Control: without nullify, the explicit optional value should remain present. + let buffer = encode_extension_car_for_optional_field_test(Some(7), false)?; + with_decoded_extension_car!(buffer.as_slice(), car, { + assert_eq!(Some(7), car.cup_holder_count()); + }); + + // Contract under test: nullify marks optional fields as absent in the encoded payload. + let buffer = encode_extension_car_for_optional_field_test(Some(7), true)?; + with_decoded_extension_car!(buffer.as_slice(), car, { + assert_eq!(None, car.cup_holder_count()); + }); + + Ok(()) +} + +#[test] +fn nullify_on_composite_and_group_without_optional_fields_has_no_effect() -> TestResult { + let mut buffer = vec![0u8; 256]; + let mut car = ExtCarEncoder::default(); + let mut fuel_figures = ExtFuelFiguresEncoder::default(); + let mut extras = ExtOptionalExtras::default(); + + car = car.wrap( + ExtWriteBuf::new(buffer.as_mut_slice()), + ext_header::ENCODED_LENGTH, + ); + car = car.header(0).parent()?; + + car.serial_number(1234); + car.model_year(2013); + car.available(ExtBooleanType::T); + car.code(ExtModel::A); + car.some_numbers(&[0, 1, 2, 3]); + car.vehicle_code(b"abcdef"); + + extras.set_cruise_control(true); + extras.set_sports_pack(true); + extras.set_sun_roof(false); + car.extras(extras); + + let mut engine = car.engine_encoder(); + engine.capacity(2000); + engine.num_cylinders(4); + engine.manufacturer_code(b"123"); + engine.efficiency(35); + engine.booster_enabled(ExtBooleanType::T); + // Engine has no optional primitive scalar fields, so nullify must be a no-op. + engine.nullify_optional_fields(); + let mut booster = engine.booster_encoder(); + booster.boost_type(ExtBoostType::NITROUS); + booster.horse_power(200); + engine = booster.parent()?; + car = engine.parent()?; + + fuel_figures = car.fuel_figures_encoder(1, fuel_figures); + assert_eq!(Some(0), fuel_figures.advance()?); + fuel_figures.speed(77); + fuel_figures.mpg(12.5); + // FuelFigures group also has no optional primitive scalar fields; expect no change. + fuel_figures.nullify_optional_fields(); + let _car = fuel_figures.parent()?; + + with_decoded_extension_car!(buffer.as_slice(), car, { + let mut engine = car.engine_decoder(); + assert_eq!(2000, engine.capacity()); + assert_eq!(4, engine.num_cylinders()); + assert_eq!(35, engine.efficiency()); + + let mut fuel_figures = engine.parent().unwrap().fuel_figures_decoder(); + assert_eq!(Some(0), fuel_figures.advance().unwrap()); + assert_eq!(77, fuel_figures.speed()); + assert_eq!(12.5, fuel_figures.mpg()); + }); + + Ok(()) +} + +#[test] +fn opt_setters_work_as_expected() -> TestResult { + let mut some_buf = vec![0u8; 256]; + let mut encoder = create_issue_895_encoder(&mut some_buf); + encoder.optional_float_opt(Some(2.07)); + encoder.optional_double_opt(Some(4.12)); + + let decoder = decode_issue_895(some_buf.as_slice()); + assert_eq!(Some(2.07), decoder.optional_float()); + assert_eq!(Some(4.12), decoder.optional_double()); + + let mut none_buf = vec![0u8; 256]; + let mut encoder = create_issue_895_encoder(&mut none_buf); + encoder.optional_float_opt(None); + encoder.optional_double_opt(None); + + let decoder = decode_issue_895(none_buf.as_slice()); + assert_eq!(None, decoder.optional_float()); + assert_eq!(None, decoder.optional_double()); + + Ok(()) +} + +#[test] +fn nullify_optional_fields_sets_all_to_none() -> TestResult { + let mut buf = vec![0u8; 256]; + let mut encoder = create_issue_895_encoder(&mut buf); + encoder.optional_float_opt(Some(2.07)); + encoder.optional_double_opt(Some(4.12)); + // Message-level nullify should clear every optional primitive scalar field. + encoder.nullify_optional_fields(); + + let decoder = decode_issue_895(buf.as_slice()); + // Both optional fields are expected to decode as absent after nullify. + assert_eq!(None, decoder.optional_float()); + assert_eq!(None, decoder.optional_double()); + + Ok(()) +} + +#[test] +fn composite_nullify_optional_fields_sets_fields_to_none() -> TestResult { + let mut buffer = vec![0u8; 256]; + let mut encoder = create_issue_972_encoder(&mut buffer); + encoder.old_field(777); + let mut new_composite_encoder = encoder.new_field_encoder(); + new_composite_encoder.f1(2007); + new_composite_encoder.f2(2012); + // Composite-level nullify should clear composite optional primitive fields. + new_composite_encoder.nullify_optional_fields(); + let _encoder = new_composite_encoder.parent()?; + + let decoder = decode_issue_972(buffer.as_slice()); + match decoder.new_field_decoder() { + I972Either::Right(composite) => { + assert_eq!(None, composite.f1()); + assert_eq!(None, composite.f2()); + } + I972Either::Left(_) => panic!("expected new_field_decoder to return Right(composite)"), + } + + Ok(()) +} + +#[test] +fn message_nullify_without_optional_primitive_fields_has_no_effect() -> TestResult { + let mut buffer = vec![0u8; 256]; + let mut encoder = create_issue_972_encoder(&mut buffer); + encoder.old_field(42); + // Issue972 message has no optional primitive scalar fields; nullify should be a no-op. + encoder.nullify_optional_fields(); + + let decoder = decode_issue_972(buffer.as_slice()); + assert_eq!(42, decoder.old_field()); + + Ok(()) +} + +#[test] +fn group_nullify_optional_fields_sets_optional_fields_to_none() -> TestResult { + let mut buffer = vec![0u8; 1024]; + let mass_quote = create_mass_quote_encoder(&mut buffer); + let mut quote_sets = QuoteSetsEncoder::default(); + let mut quote_entries = QuoteEntriesEncoder::default(); + + quote_sets = mass_quote.quote_sets_encoder(1, quote_sets); + assert_eq!(Some(0), quote_sets.advance()?); + quote_sets.tot_quote_entries(1); + + quote_entries = quote_sets.quote_entries_encoder(1, quote_entries); + assert_eq!(Some(0), quote_entries.advance()?); + quote_entries.security_id_opt(Some(111)); + quote_entries.bid_size_opt(Some(222)); + quote_entries.offer_size_opt(Some(333)); + // Group-level nullify should clear all optional primitive scalar fields in the entry. + quote_entries.nullify_optional_fields(); + + quote_sets = quote_entries.parent()?; + let _mass_quote = quote_sets.parent()?; + + let buf = MassQuoteReadBuf::new(buffer.as_slice()); + let header = MassQuoteHeaderDecoder::default().wrap(buf, 0); + let decoder = MassQuoteDecoder::default().header(header, 0); + + let mut quote_sets = decoder.quote_sets_decoder(); + assert_eq!(Some(0), quote_sets.advance()?); + let mut quote_entries = quote_sets.quote_entries_decoder(); + assert_eq!(Some(0), quote_entries.advance()?); + // Optional fields must decode as absent once group nullify has been applied. + assert_eq!(None, quote_entries.security_id()); + assert_eq!(None, quote_entries.bid_size()); + assert_eq!(None, quote_entries.offer_size()); + + Ok(()) +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index 1979de7b86..1fd81d51b2 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -99,7 +99,8 @@ void generate( { appendMessageHeaderEncoderFn(sb); - RustGenerator.generateEncoderFields(sb, fields, 2); + final List optionalPrimitiveFields = RustGenerator.generateEncoderFields(sb, fields, 2); + RustGenerator.generateNullifyOptionalFieldsMethod(sb, 2, optionalPrimitiveFields); RustGenerator.generateEncoderGroups(sb, groups, 2, this); RustGenerator.generateEncoderVarData(sb, varData, 2); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 683d81da44..1e239ee527 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -222,11 +222,13 @@ static String getBufOffset(final Token token) return "offset"; } - static void generateEncoderFields( + static List generateEncoderFields( final StringBuilder sb, final List tokens, final int level) { + final List optionalPrimitiveFields = new ArrayList<>(); + Generators.forEachField( tokens, (fieldToken, typeToken) -> @@ -238,6 +240,11 @@ static void generateEncoderFields( { case ENCODING: generatePrimitiveEncoder(sb, level, typeToken, name); + if (isOptionalPrimitiveScalar(typeToken)) + { + generateOptionalPrimitiveEncoder(sb, level, typeToken, name, typeToken.encoding()); + optionalPrimitiveFields.add(formatFunctionName(name)); + } break; case BEGIN_ENUM: generateEnumEncoder(sb, level, fieldToken, typeToken, name); @@ -257,6 +264,35 @@ static void generateEncoderFields( throw new UncheckedIOException(ex); } }); + + return optionalPrimitiveFields; + } + + static void generateNullifyOptionalFieldsMethod( + final Appendable out, + final int level, + final List optionalPrimitiveFields) throws IOException + { + indent(out, level, "/// Set all optional primitive scalar fields to their null values.\n"); + indent(out, level, "#[inline]\n"); + indent(out, level, "pub fn nullify_optional_fields(&mut self) {\n"); + if (optionalPrimitiveFields.isEmpty()) + { + indent(out, level + 1, "// No optional primitive scalar fields exist; nothing to do.\n"); + } + else + { + for (final String field : optionalPrimitiveFields) + { + indent(out, level + 1, "self.%s_opt(None);\n", field); + } + } + indent(out, level, "}\n\n"); + } + + private static boolean isOptionalPrimitiveScalar(final Token typeToken) + { + return typeToken.arrayLength() == 1 && typeToken.encoding().presence() == Encoding.Presence.OPTIONAL; } static void generateEncoderGroups( @@ -547,6 +583,16 @@ private static void generatePrimitiveEncoder( return; } + generatePrimitiveSetterEncoder(sb, level, typeToken, name, encoding); + } + + private static void generatePrimitiveSetterEncoder( + final StringBuilder sb, + final int level, + final Token typeToken, + final String name, + final Encoding encoding) throws IOException + { final PrimitiveType primitiveType = encoding.primitiveType(); final String rustPrimitiveType = rustTypeName(primitiveType); @@ -563,6 +609,30 @@ private static void generatePrimitiveEncoder( indent(sb, level, "}\n\n"); } + private static void generateOptionalPrimitiveEncoder( + final StringBuilder sb, + final int level, + final Token typeToken, + final String name, + final Encoding encoding) throws IOException + { + final PrimitiveType primitiveType = encoding.primitiveType(); + final String rustPrimitiveType = rustTypeName(primitiveType); + final String functionName = formatFunctionName(name); + final String nullLiteral = rustNullLiteral(encoding); + + indent(sb, level, "/// optional primitive field '%s'\n", name); + generateRustDoc(sb, level, typeToken, encoding); + indent(sb, level, "/// Set to `None` to encode the field null value.\n"); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s_opt(&mut self, value: Option<%s>) {\n", functionName, rustPrimitiveType); + indent(sb, level + 1, "match value {\n"); + indent(sb, level + 2, "Some(value) => self.%s(value),\n", functionName); + indent(sb, level + 2, "None => self.%s(%s),\n", functionName, nullLiteral); + indent(sb, level + 1, "}\n"); + indent(sb, level, "}\n\n"); + } + private static void generateEnumEncoder( final StringBuilder sb, final int level, @@ -1656,6 +1726,7 @@ private static void generateCompositeEncoder( indent(out, 3, "self.parent.take().ok_or(SbeErr::ParentNotSet)\n"); indent(out, 2, "}\n\n"); + final List optionalPrimitiveFields = new ArrayList<>(); for (int i = 1, end = tokens.size() - 1; i < end; ) { final Token encodingToken = tokens.get(i); @@ -1665,6 +1736,12 @@ private static void generateCompositeEncoder( { case ENCODING: generatePrimitiveEncoder(sb, 2, encodingToken, encodingToken.name()); + if (isOptionalPrimitiveScalar(encodingToken)) + { + generateOptionalPrimitiveEncoder(sb, 2, encodingToken, encodingToken.name(), + encodingToken.encoding()); + optionalPrimitiveFields.add(formatFunctionName(encodingToken.name())); + } break; case BEGIN_ENUM: generateEnumEncoder(sb, 2, encodingToken, encodingToken, encodingToken.name()); @@ -1683,6 +1760,7 @@ private static void generateCompositeEncoder( i += encodingToken.componentTokenCount(); } + generateNullifyOptionalFieldsMethod(out, 2, optionalPrimitiveFields); indent(out, 1, "}\n"); // end impl indent(out, 0, "} // end encoder mod \n"); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index e96c11c20a..1d9a0e4056 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -132,7 +132,8 @@ void generateEncoder( indent(sb, level + 1, "}\n"); indent(sb, level, "}\n\n"); - RustGenerator.generateEncoderFields(sb, fields, level); + final List optionalPrimitiveFields = RustGenerator.generateEncoderFields(sb, fields, level); + RustGenerator.generateNullifyOptionalFieldsMethod(sb, level, optionalPrimitiveFields); RustGenerator.generateEncoderGroups(sb, groups, level, this); RustGenerator.generateEncoderVarData(sb, varData, level); From bd0ade78b73d94b501c5869fdc6cda777ebaf500 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Sun, 15 Feb 2026 14:26:53 -0600 Subject: [PATCH 1521/1594] [Rust] updated Encoder trait to include "nullify_optional_fields()" --- rust/tests/optional_field_nullify_test.rs | 6 +- .../sbe/generation/rust/LibRsDef.java | 3 + .../sbe/generation/rust/MessageCoderDef.java | 6 +- .../sbe/generation/rust/RustGenerator.java | 79 ++++++++++++++----- .../sbe/generation/rust/SubGroup.java | 7 +- 5 files changed, 76 insertions(+), 25 deletions(-) diff --git a/rust/tests/optional_field_nullify_test.rs b/rust/tests/optional_field_nullify_test.rs index 188eca4cb6..44318570b1 100644 --- a/rust/tests/optional_field_nullify_test.rs +++ b/rust/tests/optional_field_nullify_test.rs @@ -2,7 +2,6 @@ use examples_extension as ext; use examples_uk_co_real_logic_sbe_benchmarks_fix as mqfix; use issue_895 as i895; use issue_972 as i972; - use ext::{ boolean_type::BooleanType as ExtBooleanType, boost_type::BoostType as ExtBoostType, @@ -92,6 +91,7 @@ fn encode_extension_car_for_optional_field_test( cup_holder_count: Option, nullify: bool, ) -> ExtSbeResult> { + use examples_extension::Encoder; let mut buffer = vec![0u8; 256]; let mut car = ExtCarEncoder::default(); let mut extras = ExtOptionalExtras::default(); @@ -177,6 +177,7 @@ fn extension_encoder_nullify_optional_fields_sets_cup_holder_count_to_none() -> #[test] fn nullify_on_composite_and_group_without_optional_fields_has_no_effect() -> TestResult { + use examples_extension::Encoder; let mut buffer = vec![0u8; 256]; let mut car = ExtCarEncoder::default(); let mut fuel_figures = ExtFuelFiguresEncoder::default(); @@ -262,6 +263,7 @@ fn opt_setters_work_as_expected() -> TestResult { #[test] fn nullify_optional_fields_sets_all_to_none() -> TestResult { + use issue_895::Encoder; let mut buf = vec![0u8; 256]; let mut encoder = create_issue_895_encoder(&mut buf); encoder.optional_float_opt(Some(2.07)); @@ -303,6 +305,7 @@ fn composite_nullify_optional_fields_sets_fields_to_none() -> TestResult { #[test] fn message_nullify_without_optional_primitive_fields_has_no_effect() -> TestResult { + use issue_972::Encoder; let mut buffer = vec![0u8; 256]; let mut encoder = create_issue_972_encoder(&mut buffer); encoder.old_field(42); @@ -317,6 +320,7 @@ fn message_nullify_without_optional_primitive_fields_has_no_effect() -> TestResu #[test] fn group_nullify_optional_fields_sets_optional_fields_to_none() -> TestResult { + use examples_uk_co_real_logic_sbe_benchmarks_fix::Encoder; let mut buffer = vec![0u8; 1024]; let mass_quote = create_mass_quote_encoder(&mut buffer); let mut quote_sets = QuoteSetsEncoder::default(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 1de9357f3a..898977b57e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -113,6 +113,9 @@ static void generateEncoderTraits(final Writer writer) throws IOException indent(writer, 0, "pub trait Encoder<'a>: Writer<'a> {\n"); indent(writer, 1, "fn get_limit(&self) -> usize;\n"); indent(writer, 1, "fn set_limit(&mut self, limit: usize);\n"); + indent(writer, 1, "fn nullify_optional_fields(&mut self) -> &mut Self {\n"); + indent(writer, 2, "self\n"); + indent(writer, 1, "}\n"); indent(writer, 0, "}\n\n"); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index 1fd81d51b2..cd3e5a8ce0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -72,7 +72,8 @@ void generate( if (codecType == Encoder) { - RustGenerator.appendImplEncoderTrait(sb, msgTypeName); + final List optionalPrimitiveFields = RustGenerator.getOptionalPrimitiveFields(fields); + RustGenerator.appendImplEncoderTrait(sb, msgTypeName, optionalPrimitiveFields); } else { @@ -99,8 +100,7 @@ void generate( { appendMessageHeaderEncoderFn(sb); - final List optionalPrimitiveFields = RustGenerator.generateEncoderFields(sb, fields, 2); - RustGenerator.generateNullifyOptionalFieldsMethod(sb, 2, optionalPrimitiveFields); + RustGenerator.generateEncoderFields(sb, fields, 2); RustGenerator.generateEncoderGroups(sb, groups, 2, this); RustGenerator.generateEncoderVarData(sb, varData, 2); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 1e239ee527..858198902a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -33,9 +33,11 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import static java.lang.String.format; +import static java.lang.System.out; import static uk.co.real_logic.sbe.generation.rust.RustUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; @@ -222,13 +224,30 @@ static String getBufOffset(final Token token) return "offset"; } - static List generateEncoderFields( + static List getOptionalPrimitiveFields(final List tokens) + { + final List optionalPrimitiveFields = new ArrayList<>(); + Generators.forEachField( + tokens, + (fieldToken, typeToken) -> + { + final String name = fieldToken.name(); + if (Objects.requireNonNull(typeToken.signal()) == Signal.ENCODING) + { + if (isOptionalPrimitiveScalar(typeToken)) + { + optionalPrimitiveFields.add(formatFunctionName(name)); + } + } + }); + return optionalPrimitiveFields; + } + + static void generateEncoderFields( final StringBuilder sb, final List tokens, final int level) { - final List optionalPrimitiveFields = new ArrayList<>(); - Generators.forEachField( tokens, (fieldToken, typeToken) -> @@ -243,7 +262,6 @@ static List generateEncoderFields( if (isOptionalPrimitiveScalar(typeToken)) { generateOptionalPrimitiveEncoder(sb, level, typeToken, name, typeToken.encoding()); - optionalPrimitiveFields.add(formatFunctionName(name)); } break; case BEGIN_ENUM: @@ -264,8 +282,6 @@ static List generateEncoderFields( throw new UncheckedIOException(ex); } }); - - return optionalPrimitiveFields; } static void generateNullifyOptionalFieldsMethod( @@ -275,18 +291,12 @@ static void generateNullifyOptionalFieldsMethod( { indent(out, level, "/// Set all optional primitive scalar fields to their null values.\n"); indent(out, level, "#[inline]\n"); - indent(out, level, "pub fn nullify_optional_fields(&mut self) {\n"); - if (optionalPrimitiveFields.isEmpty()) + indent(out, level, "pub fn nullify_optional_fields(&mut self) -> &mut Self {\n"); + for (final String field : optionalPrimitiveFields) { - indent(out, level + 1, "// No optional primitive scalar fields exist; nothing to do.\n"); - } - else - { - for (final String field : optionalPrimitiveFields) - { - indent(out, level + 1, "self.%s_opt(None);\n", field); - } + indent(out, level + 1, "self.%s_opt(None);\n", field); } + indent(out, level + 1, "self\n"); indent(out, level, "}\n\n"); } @@ -1339,7 +1349,8 @@ private static void generateSingleBitSet( static void appendImplEncoderTrait( final Appendable out, - final String typeName) throws IOException + final String typeName, + final List optionalPrimitiveFields) throws IOException { indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withBufLifetime("Writer"), withBufLifetime(typeName)); indent(out, 2, "#[inline]\n"); @@ -1358,6 +1369,21 @@ static void appendImplEncoderTrait( indent(out, 2, "fn set_limit(&mut self, limit: usize) {\n"); indent(out, 3, "self.limit = limit;\n"); indent(out, 2, "}\n"); + + if (!optionalPrimitiveFields.isEmpty()) + { + indent(out, 0, "\n"); + indent(out, 2, "/// xxx Set all optional primitive scalar fields to their 'null' values.\n"); + indent(out, 2, "#[inline]\n"); + indent(out, 2, "fn nullify_optional_fields(&mut self) -> &mut Self {\n"); + for (final String field : optionalPrimitiveFields) + { + indent(out, 3, "self.%s_opt(None);\n", field); + } + indent(out, 3, "self\n"); + indent(out, 2, "}\n"); + } + indent(out, 1, "}\n\n"); } @@ -1628,7 +1654,8 @@ static void appendImplWriterForComposite( static void appendImplEncoderForComposite( final Appendable out, final int level, - final String name) throws IOException + final String name, + final List optionalPrimitiveFields) throws IOException { appendImplWriterForComposite(out, level, name); @@ -1643,6 +1670,21 @@ static void appendImplEncoderForComposite( indent(out, level + 1, "fn set_limit(&mut self, limit: usize) {\n"); indent(out, level + 2, "self.parent.as_mut().expect(\"parent missing\").set_limit(limit);\n"); indent(out, level + 1, "}\n"); + + if (!optionalPrimitiveFields.isEmpty()) + { + indent(out, 0, "\n"); + indent(out, 2, "/// Set all optional primitive scalar fields to their 'null' values.\n"); + indent(out, 2, "#[inline]\n"); + indent(out, 2, "fn nullify_optional_fields(&mut self) -> &mut Self {\n"); + for (final String field : optionalPrimitiveFields) + { + indent(out, 3, "self.%s_opt(None);\n", field); + } + indent(out, 3, "self\n"); + indent(out, 2, "}\n"); + } + indent(out, level, "}\n\n"); } @@ -1721,6 +1763,7 @@ private static void generateCompositeEncoder( indent(out, 2, "}\n\n"); // parent fn... + indent(out, 2, "/// parent fns\n"); indent(out, 2, "#[inline]\n"); indent(out, 2, "pub fn parent(&mut self) -> SbeResult

        {\n"); indent(out, 3, "self.parent.take().ok_or(SbeErr::ParentNotSet)\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index 1d9a0e4056..96d2b07d2e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -72,7 +72,8 @@ void generateEncoder( indent(sb, level, "initial_limit: usize,\n"); indent(sb, level - 1, "}\n\n"); - RustGenerator.appendImplEncoderForComposite(sb, level - 1, name); + final List optionalPrimitiveFields = RustGenerator.getOptionalPrimitiveFields(fields); + RustGenerator.appendImplEncoderForComposite(sb, level - 1, name, optionalPrimitiveFields); // define impl... indent(sb, level - 1, "impl<'a, P> %s

        where P: Encoder<'a> + Default {\n", name); @@ -132,8 +133,8 @@ void generateEncoder( indent(sb, level + 1, "}\n"); indent(sb, level, "}\n\n"); - final List optionalPrimitiveFields = RustGenerator.generateEncoderFields(sb, fields, level); - RustGenerator.generateNullifyOptionalFieldsMethod(sb, level, optionalPrimitiveFields); + RustGenerator.generateEncoderFields(sb, fields, level); +// RustGenerator.generateNullifyOptionalFieldsMethod(sb, level, optionalPrimitiveFields); RustGenerator.generateEncoderGroups(sb, groups, level, this); RustGenerator.generateEncoderVarData(sb, varData, level); From ccc8fcc58c275eaacce4ee31e45b942076bfff37 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Sun, 15 Feb 2026 14:35:11 -0600 Subject: [PATCH 1522/1594] [Rust] minor edit --- .../uk/co/real_logic/sbe/generation/rust/RustGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 858198902a..15f383a0a6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1373,7 +1373,7 @@ static void appendImplEncoderTrait( if (!optionalPrimitiveFields.isEmpty()) { indent(out, 0, "\n"); - indent(out, 2, "/// xxx Set all optional primitive scalar fields to their 'null' values.\n"); + indent(out, 2, "/// Set all optional primitive scalar fields to their 'null' values.\n"); indent(out, 2, "#[inline]\n"); indent(out, 2, "fn nullify_optional_fields(&mut self) -> &mut Self {\n"); for (final String field : optionalPrimitiveFields) From 1ccfd4a0f791a35cb8db94c17dedc029b7453d04 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Sun, 15 Feb 2026 15:06:45 -0600 Subject: [PATCH 1523/1594] Update sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java Co-authored-by: Leonardo Arcari --- .../main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java | 1 - 1 file changed, 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index 96d2b07d2e..5012cda52c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -134,7 +134,6 @@ void generateEncoder( indent(sb, level, "}\n\n"); RustGenerator.generateEncoderFields(sb, fields, level); -// RustGenerator.generateNullifyOptionalFieldsMethod(sb, level, optionalPrimitiveFields); RustGenerator.generateEncoderGroups(sb, groups, level, this); RustGenerator.generateEncoderVarData(sb, varData, level); From 0388477e97680d18fa271bba21d18e825d9c29dc Mon Sep 17 00:00:00 2001 From: Leonardo Arcari Date: Wed, 18 Feb 2026 17:22:14 +0100 Subject: [PATCH 1524/1594] feat(rust): generate setters for optional enum fields too --- build.gradle | 1 + rust/Cargo.toml | 1 + rust/tests/optional_field_nullify_test.rs | 87 +++++++++++++++-- .../sbe/generation/rust/MessageCoderDef.java | 4 +- .../sbe/generation/rust/RustGenerator.java | 93 ++++++++++++++----- .../sbe/generation/rust/SubGroup.java | 4 +- .../test/resources/optional_enum_nullify.xml | 31 +++++++ 7 files changed, 184 insertions(+), 37 deletions(-) create mode 100644 sbe-tool/src/test/resources/optional_enum_nullify.xml diff --git a/build.gradle b/build.gradle index 3d6461d6e7..df2554c746 100644 --- a/build.gradle +++ b/build.gradle @@ -679,6 +679,7 @@ tasks.register('generateRustTestCodecs', JavaExec) { 'sbe-tool/src/test/resources/issue1028.xml', 'sbe-tool/src/test/resources/issue1057.xml', 'sbe-tool/src/test/resources/issue1066.xml', + 'sbe-tool/src/test/resources/optional_enum_nullify.xml', 'sbe-tool/src/test/resources/basic-variable-length-schema.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', 'sbe-tool/src/test/resources/fixed-sized-primitive-array-types.xml', diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 76119b11b7..df19774eb3 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -22,6 +22,7 @@ issue_1066 = { path = "../generated/rust/issue1066" } baseline_bigendian = { path = "../generated/rust/baseline_bigendian" } nested_composite_name = { path = "../generated/rust/nested_composite_name" } sbe_tests = { path = "../generated/rust/sbe_tests" } +optional_enum_nullify = { path = "../generated/rust/optional_enum_nullify" } fixed_sized_primitive_array = { path = "../generated/rust/fixed_sized_primitive_array" } [dev-dependencies] diff --git a/rust/tests/optional_field_nullify_test.rs b/rust/tests/optional_field_nullify_test.rs index 44318570b1..2f9555a413 100644 --- a/rust/tests/optional_field_nullify_test.rs +++ b/rust/tests/optional_field_nullify_test.rs @@ -1,7 +1,5 @@ use examples_extension as ext; use examples_uk_co_real_logic_sbe_benchmarks_fix as mqfix; -use issue_895 as i895; -use issue_972 as i972; use ext::{ boolean_type::BooleanType as ExtBooleanType, boost_type::BoostType as ExtBoostType, @@ -12,9 +10,7 @@ use ext::{ message_header_codec::{self as ext_header, MessageHeaderDecoder as ExtHeaderDecoder}, model::Model as ExtModel, optional_extras::OptionalExtras as ExtOptionalExtras, - ReadBuf as ExtReadBuf, - SbeResult as ExtSbeResult, - WriteBuf as ExtWriteBuf, + ReadBuf as ExtReadBuf, SbeResult as ExtSbeResult, WriteBuf as ExtWriteBuf, }; use i895::{ issue_895_codec::{Issue895Decoder, Issue895Encoder}, @@ -26,6 +22,8 @@ use i972::{ message_header_codec::{self as i972_header, MessageHeaderDecoder as I972HeaderDecoder}, Either as I972Either, ReadBuf as I972ReadBuf, WriteBuf as I972WriteBuf, }; +use issue_895 as i895; +use issue_972 as i972; use mqfix::{ mass_quote_codec::{ encoder::{QuoteEntriesEncoder, QuoteSetsEncoder}, @@ -34,15 +32,23 @@ use mqfix::{ message_header_codec::{self as mqfix_header, MessageHeaderDecoder as MassQuoteHeaderDecoder}, ReadBuf as MassQuoteReadBuf, WriteBuf as MassQuoteWriteBuf, }; +use oen::{ + enum_type::EnumType as OenEnumType, + message_header_codec::{ + self as oen_header, MessageHeaderDecoder as OptionalEnumNullifyHeaderDecoder, + }, + optional_encoding_enum_type::OptionalEncodingEnumType as OenOptionalEncodingEnumType, + optional_enum_nullify_codec::{OptionalEnumNullifyDecoder, OptionalEnumNullifyEncoder}, + ReadBuf as OenReadBuf, WriteBuf as OenWriteBuf, +}; +use optional_enum_nullify as oen; type TestResult = Result<(), Box>; macro_rules! create_encoder_with_header_parent { ($buffer:expr, $encoder_ty:ty, $write_buf_ty:ty, $encoded_len:expr) => {{ - let encoder = <$encoder_ty>::default().wrap( - <$write_buf_ty>::new($buffer.as_mut_slice()), - $encoded_len, - ); + let encoder = <$encoder_ty>::default() + .wrap(<$write_buf_ty>::new($buffer.as_mut_slice()), $encoded_len); let mut header = encoder.header(0); header.parent().unwrap() }}; @@ -66,6 +72,15 @@ fn create_issue_972_encoder(buffer: &mut Vec) -> Issue972Encoder<'_> { ) } +fn create_optional_enum_nullify_encoder(buffer: &mut Vec) -> OptionalEnumNullifyEncoder<'_> { + create_encoder_with_header_parent!( + buffer, + OptionalEnumNullifyEncoder<'_>, + OenWriteBuf<'_>, + oen_header::ENCODED_LENGTH + ) +} + fn create_mass_quote_encoder(buffer: &mut Vec) -> MassQuoteEncoder<'_> { create_encoder_with_header_parent!( buffer, @@ -87,6 +102,12 @@ fn decode_issue_972(buffer: &[u8]) -> Issue972Decoder<'_> { Issue972Decoder::default().header(header, 0) } +fn decode_optional_enum_nullify(buffer: &[u8]) -> OptionalEnumNullifyDecoder<'_> { + let buf = OenReadBuf::new(buffer); + let header = OptionalEnumNullifyHeaderDecoder::default().wrap(buf, 0); + OptionalEnumNullifyDecoder::default().header(header, 0) +} + fn encode_extension_car_for_optional_field_test( cup_holder_count: Option, nullify: bool, @@ -356,3 +377,51 @@ fn group_nullify_optional_fields_sets_optional_fields_to_none() -> TestResult { Ok(()) } + +#[test] +fn nullify_optional_fields_sets_optional_enum_field_to_null_value() -> TestResult { + use oen::Encoder; + let mut control_buffer = vec![0u8; 256]; + let mut control_encoder = create_optional_enum_nullify_encoder(&mut control_buffer); + // Optionality is declared on the field, matching IR optional enum semantics. + control_encoder.optional_enum_opt(Some(OenEnumType::One)); + // This field is required, even if its enum type encoding is optional. + control_encoder.required_enum_from_optional_type(OenOptionalEncodingEnumType::Alpha); + + let control_decoder = decode_optional_enum_nullify(control_buffer.as_slice()); + assert_eq!(OenEnumType::One, control_decoder.optional_enum()); + assert_eq!( + OenOptionalEncodingEnumType::Alpha, + control_decoder.required_enum_from_optional_type() + ); + + let mut none_buffer = vec![0u8; 256]; + let mut none_encoder = create_optional_enum_nullify_encoder(&mut none_buffer); + none_encoder.optional_enum_opt(None); + none_encoder.required_enum_from_optional_type(OenOptionalEncodingEnumType::Beta); + + let none_decoder = decode_optional_enum_nullify(none_buffer.as_slice()); + assert_eq!(OenEnumType::NullVal, none_decoder.optional_enum()); + assert_eq!( + OenOptionalEncodingEnumType::Beta, + none_decoder.required_enum_from_optional_type() + ); + + let mut nullified_buffer = vec![0u8; 256]; + let mut nullified_encoder = create_optional_enum_nullify_encoder(&mut nullified_buffer); + nullified_encoder.optional_enum_opt(Some(OenEnumType::Two)); + nullified_encoder.required_enum_from_optional_type(OenOptionalEncodingEnumType::Beta); + // This is the behavior under test: nullify should route through *_opt(None) + // only for field-optional members, so `optional_enum` becomes NullVal while + // the required field remains unchanged even if its enum type encoding is optional. + nullified_encoder.nullify_optional_fields(); + + let nullified_decoder = decode_optional_enum_nullify(nullified_buffer.as_slice()); + assert_eq!(OenEnumType::NullVal, nullified_decoder.optional_enum()); + assert_eq!( + OenOptionalEncodingEnumType::Beta, + nullified_decoder.required_enum_from_optional_type() + ); + + Ok(()) +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index cd3e5a8ce0..0f51975b7a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -72,8 +72,8 @@ void generate( if (codecType == Encoder) { - final List optionalPrimitiveFields = RustGenerator.getOptionalPrimitiveFields(fields); - RustGenerator.appendImplEncoderTrait(sb, msgTypeName, optionalPrimitiveFields); + final List optionalFields = RustGenerator.getNullifyOptionalFields(fields); + RustGenerator.appendImplEncoderTrait(sb, msgTypeName, optionalFields); } else { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 15f383a0a6..b19cba2762 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -224,23 +224,29 @@ static String getBufOffset(final Token token) return "offset"; } - static List getOptionalPrimitiveFields(final List tokens) + static List getNullifyOptionalFields(final List tokens) { - final List optionalPrimitiveFields = new ArrayList<>(); + final List optionalFields = new ArrayList<>(); Generators.forEachField( tokens, (fieldToken, typeToken) -> { - final String name = fieldToken.name(); - if (Objects.requireNonNull(typeToken.signal()) == Signal.ENCODING) + final String fieldName = formatFunctionName(fieldToken.name()); + final Signal signal = Objects.requireNonNull(typeToken.signal()); + if (signal == Signal.ENCODING) { if (isOptionalPrimitiveScalar(typeToken)) { - optionalPrimitiveFields.add(formatFunctionName(name)); + optionalFields.add(fieldName); } } + else if (signal == BEGIN_ENUM && + isOptionalEnum(typeToken, fieldToken)) + { + optionalFields.add(fieldName); + } }); - return optionalPrimitiveFields; + return optionalFields; } static void generateEncoderFields( @@ -266,6 +272,10 @@ static void generateEncoderFields( break; case BEGIN_ENUM: generateEnumEncoder(sb, level, fieldToken, typeToken, name); + if (isOptionalEnum(typeToken, fieldToken)) + { + generateOptionalEnumEncoder(sb, level, typeToken, name); + } break; case BEGIN_SET: generateBitSetEncoder(sb, level, typeToken, name); @@ -287,12 +297,12 @@ static void generateEncoderFields( static void generateNullifyOptionalFieldsMethod( final Appendable out, final int level, - final List optionalPrimitiveFields) throws IOException + final List optionalFields) throws IOException { - indent(out, level, "/// Set all optional primitive scalar fields to their null values.\n"); + indent(out, level, "/// Set all optional fields to their null values.\n"); indent(out, level, "#[inline]\n"); indent(out, level, "pub fn nullify_optional_fields(&mut self) -> &mut Self {\n"); - for (final String field : optionalPrimitiveFields) + for (final String field : optionalFields) { indent(out, level + 1, "self.%s_opt(None);\n", field); } @@ -305,6 +315,18 @@ private static boolean isOptionalPrimitiveScalar(final Token typeToken) return typeToken.arrayLength() == 1 && typeToken.encoding().presence() == Encoding.Presence.OPTIONAL; } + private static boolean isOptionalEnum(final Token typeToken, final Token fieldToken) + { + return typeToken.signal() == BEGIN_ENUM && fieldToken.isOptionalEncoding(); + } + + private static String rustEnumType(final Token typeToken) + { + final String referencedName = typeToken.referencedName(); + final String enumTypeName = referencedName == null ? typeToken.name() : referencedName; + return format("%s::%s", toLowerSnakeCase(enumTypeName), formatStructName(enumTypeName)); + } + static void generateEncoderGroups( final StringBuilder sb, final List tokens, @@ -650,10 +672,7 @@ private static void generateEnumEncoder( final Token typeToken, final String name) throws IOException { - final String referencedName = typeToken.referencedName(); - final String enumType = format("%s::%s", - toLowerSnakeCase(referencedName == null ? typeToken.name() : referencedName), - formatStructName(referencedName == null ? typeToken.name() : referencedName)); + final String enumType = rustEnumType(typeToken); if (fieldToken.isConstantEncoding()) { @@ -676,6 +695,27 @@ private static void generateEnumEncoder( } } + private static void generateOptionalEnumEncoder( + final StringBuilder sb, + final int level, + final Token typeToken, + final String name) throws IOException + { + final String functionName = formatFunctionName(name); + final String enumType = rustEnumType(typeToken); + + indent(sb, level, "/// optional enum field '%s'\n", name); + generateRustDoc(sb, level, typeToken, typeToken.encoding()); + indent(sb, level, "/// Set to `None` to encode the field null value.\n"); + indent(sb, level, "#[inline]\n"); + indent(sb, level, "pub fn %s_opt(&mut self, value: Option<%s>) {\n", functionName, enumType); + indent(sb, level + 1, "match value {\n"); + indent(sb, level + 2, "Some(value) => self.%s(value),\n", functionName); + indent(sb, level + 2, "None => self.%s(%s::NullVal),\n", functionName, enumType); + indent(sb, level + 1, "}\n"); + indent(sb, level, "}\n\n"); + } + private static void generateBitSetEncoder( final StringBuilder sb, final int level, @@ -1350,7 +1390,7 @@ private static void generateSingleBitSet( static void appendImplEncoderTrait( final Appendable out, final String typeName, - final List optionalPrimitiveFields) throws IOException + final List optionalFields) throws IOException { indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withBufLifetime("Writer"), withBufLifetime(typeName)); indent(out, 2, "#[inline]\n"); @@ -1370,13 +1410,13 @@ static void appendImplEncoderTrait( indent(out, 3, "self.limit = limit;\n"); indent(out, 2, "}\n"); - if (!optionalPrimitiveFields.isEmpty()) + if (!optionalFields.isEmpty()) { indent(out, 0, "\n"); - indent(out, 2, "/// Set all optional primitive scalar fields to their 'null' values.\n"); + indent(out, 2, "/// Set all optional fields to their 'null' values.\n"); indent(out, 2, "#[inline]\n"); indent(out, 2, "fn nullify_optional_fields(&mut self) -> &mut Self {\n"); - for (final String field : optionalPrimitiveFields) + for (final String field : optionalFields) { indent(out, 3, "self.%s_opt(None);\n", field); } @@ -1655,7 +1695,7 @@ static void appendImplEncoderForComposite( final Appendable out, final int level, final String name, - final List optionalPrimitiveFields) throws IOException + final List optionalFields) throws IOException { appendImplWriterForComposite(out, level, name); @@ -1671,13 +1711,13 @@ static void appendImplEncoderForComposite( indent(out, level + 2, "self.parent.as_mut().expect(\"parent missing\").set_limit(limit);\n"); indent(out, level + 1, "}\n"); - if (!optionalPrimitiveFields.isEmpty()) + if (!optionalFields.isEmpty()) { indent(out, 0, "\n"); - indent(out, 2, "/// Set all optional primitive scalar fields to their 'null' values.\n"); + indent(out, 2, "/// Set all optional fields to their 'null' values.\n"); indent(out, 2, "#[inline]\n"); indent(out, 2, "fn nullify_optional_fields(&mut self) -> &mut Self {\n"); - for (final String field : optionalPrimitiveFields) + for (final String field : optionalFields) { indent(out, 3, "self.%s_opt(None);\n", field); } @@ -1769,7 +1809,7 @@ private static void generateCompositeEncoder( indent(out, 3, "self.parent.take().ok_or(SbeErr::ParentNotSet)\n"); indent(out, 2, "}\n\n"); - final List optionalPrimitiveFields = new ArrayList<>(); + final List optionalFields = new ArrayList<>(); for (int i = 1, end = tokens.size() - 1; i < end; ) { final Token encodingToken = tokens.get(i); @@ -1783,11 +1823,16 @@ private static void generateCompositeEncoder( { generateOptionalPrimitiveEncoder(sb, 2, encodingToken, encodingToken.name(), encodingToken.encoding()); - optionalPrimitiveFields.add(formatFunctionName(encodingToken.name())); + optionalFields.add(formatFunctionName(encodingToken.name())); } break; case BEGIN_ENUM: generateEnumEncoder(sb, 2, encodingToken, encodingToken, encodingToken.name()); + if (isOptionalEnum(encodingToken, encodingToken)) + { + generateOptionalEnumEncoder(sb, 2, encodingToken, encodingToken.name()); + optionalFields.add(formatFunctionName(encodingToken.name())); + } break; case BEGIN_SET: generateBitSetEncoder(sb, 2, encodingToken, encodingToken.name()); @@ -1803,7 +1848,7 @@ private static void generateCompositeEncoder( i += encodingToken.componentTokenCount(); } - generateNullifyOptionalFieldsMethod(out, 2, optionalPrimitiveFields); + generateNullifyOptionalFieldsMethod(out, 2, optionalFields); indent(out, 1, "}\n"); // end impl indent(out, 0, "} // end encoder mod \n"); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index 5012cda52c..b465cee680 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -72,8 +72,8 @@ void generateEncoder( indent(sb, level, "initial_limit: usize,\n"); indent(sb, level - 1, "}\n\n"); - final List optionalPrimitiveFields = RustGenerator.getOptionalPrimitiveFields(fields); - RustGenerator.appendImplEncoderForComposite(sb, level - 1, name, optionalPrimitiveFields); + final List optionalFields = RustGenerator.getNullifyOptionalFields(fields); + RustGenerator.appendImplEncoderForComposite(sb, level - 1, name, optionalFields); // define impl... indent(sb, level - 1, "impl<'a, P> %s

        where P: Encoder<'a> + Default {\n", name); diff --git a/sbe-tool/src/test/resources/optional_enum_nullify.xml b/sbe-tool/src/test/resources/optional_enum_nullify.xml new file mode 100644 index 0000000000..22478f92e3 --- /dev/null +++ b/sbe-tool/src/test/resources/optional_enum_nullify.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + 1 + 2 + + + + 3 + 4 + + + + + + + From f6b2b7a9460824ec7a3e9432f47ddc55421b0d0f Mon Sep 17 00:00:00 2001 From: Leonardo Arcari Date: Thu, 19 Feb 2026 18:24:24 +0100 Subject: [PATCH 1525/1594] feat(rust): recursively call nullify_optional_fields on composites --- rust/tests/optional_field_nullify_test.rs | 19 ++- .../sbe/generation/rust/MessageCoderDef.java | 4 +- .../sbe/generation/rust/RustGenerator.java | 117 +++++++++++------- .../sbe/generation/rust/SubGroup.java | 4 +- .../test/resources/optional_enum_nullify.xml | 4 + 5 files changed, 100 insertions(+), 48 deletions(-) diff --git a/rust/tests/optional_field_nullify_test.rs b/rust/tests/optional_field_nullify_test.rs index 2f9555a413..fe2f5fc0d6 100644 --- a/rust/tests/optional_field_nullify_test.rs +++ b/rust/tests/optional_field_nullify_test.rs @@ -387,6 +387,9 @@ fn nullify_optional_fields_sets_optional_enum_field_to_null_value() -> TestResul control_encoder.optional_enum_opt(Some(OenEnumType::One)); // This field is required, even if its enum type encoding is optional. control_encoder.required_enum_from_optional_type(OenOptionalEncodingEnumType::Alpha); + let mut control_composite = control_encoder.optional_composite_encoder(); + control_composite.optional_counter_opt(Some(77)); + let _control_encoder = control_composite.parent()?; let control_decoder = decode_optional_enum_nullify(control_buffer.as_slice()); assert_eq!(OenEnumType::One, control_decoder.optional_enum()); @@ -394,11 +397,16 @@ fn nullify_optional_fields_sets_optional_enum_field_to_null_value() -> TestResul OenOptionalEncodingEnumType::Alpha, control_decoder.required_enum_from_optional_type() ); + let control_composite = control_decoder.optional_composite_decoder(); + assert_eq!(Some(77), control_composite.optional_counter()); let mut none_buffer = vec![0u8; 256]; let mut none_encoder = create_optional_enum_nullify_encoder(&mut none_buffer); none_encoder.optional_enum_opt(None); none_encoder.required_enum_from_optional_type(OenOptionalEncodingEnumType::Beta); + let mut none_composite = none_encoder.optional_composite_encoder(); + none_composite.optional_counter_opt(None); + let _none_encoder = none_composite.parent()?; let none_decoder = decode_optional_enum_nullify(none_buffer.as_slice()); assert_eq!(OenEnumType::NullVal, none_decoder.optional_enum()); @@ -406,14 +414,19 @@ fn nullify_optional_fields_sets_optional_enum_field_to_null_value() -> TestResul OenOptionalEncodingEnumType::Beta, none_decoder.required_enum_from_optional_type() ); + let none_composite = none_decoder.optional_composite_decoder(); + assert_eq!(None, none_composite.optional_counter()); let mut nullified_buffer = vec![0u8; 256]; let mut nullified_encoder = create_optional_enum_nullify_encoder(&mut nullified_buffer); nullified_encoder.optional_enum_opt(Some(OenEnumType::Two)); nullified_encoder.required_enum_from_optional_type(OenOptionalEncodingEnumType::Beta); + let mut nullified_composite = nullified_encoder.optional_composite_encoder(); + nullified_composite.optional_counter_opt(Some(88)); + nullified_encoder = nullified_composite.parent()?; // This is the behavior under test: nullify should route through *_opt(None) - // only for field-optional members, so `optional_enum` becomes NullVal while - // the required field remains unchanged even if its enum type encoding is optional. + // and recurse into composite fields, so `optional_enum` and composite optional + // members become null while required fields remain unchanged. nullified_encoder.nullify_optional_fields(); let nullified_decoder = decode_optional_enum_nullify(nullified_buffer.as_slice()); @@ -422,6 +435,8 @@ fn nullify_optional_fields_sets_optional_enum_field_to_null_value() -> TestResul OenOptionalEncodingEnumType::Beta, nullified_decoder.required_enum_from_optional_type() ); + let nullified_composite = nullified_decoder.optional_composite_decoder(); + assert_eq!(None, nullified_composite.optional_counter()); Ok(()) } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index 0f51975b7a..58416f17bd 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -72,8 +72,8 @@ void generate( if (codecType == Encoder) { - final List optionalFields = RustGenerator.getNullifyOptionalFields(fields); - RustGenerator.appendImplEncoderTrait(sb, msgTypeName, optionalFields); + final RustGenerator.NullifyTargets nullifyTargets = RustGenerator.getNullifyTargets(fields); + RustGenerator.appendImplEncoderTrait(sb, msgTypeName, nullifyTargets); } else { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index b19cba2762..13edc8f67b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -82,6 +82,17 @@ interface ParentDef SubGroup addSubGroup(String name, int level, Token groupToken); } + static final class NullifyTargets + { + final List optionalFields = new ArrayList<>(); + final List compositeFieldEncoders = new ArrayList<>(); + + boolean isEmpty() + { + return optionalFields.isEmpty() && compositeFieldEncoders.isEmpty(); + } + } + private final Ir ir; private final RustOutputManager outputManager; private final String crateVersion; @@ -224,9 +235,9 @@ static String getBufOffset(final Token token) return "offset"; } - static List getNullifyOptionalFields(final List tokens) + static NullifyTargets getNullifyTargets(final List tokens) { - final List optionalFields = new ArrayList<>(); + final NullifyTargets targets = new NullifyTargets(); Generators.forEachField( tokens, (fieldToken, typeToken) -> @@ -237,16 +248,20 @@ static List getNullifyOptionalFields(final List tokens) { if (isOptionalPrimitiveScalar(typeToken)) { - optionalFields.add(fieldName); + targets.optionalFields.add(fieldName); } } else if (signal == BEGIN_ENUM && isOptionalEnum(typeToken, fieldToken)) { - optionalFields.add(fieldName); + targets.optionalFields.add(fieldName); + } + else if (signal == Signal.BEGIN_COMPOSITE) + { + targets.compositeFieldEncoders.add(compositeEncoderAccessorName(fieldToken.name())); } }); - return optionalFields; + return targets; } static void generateEncoderFields( @@ -297,17 +312,53 @@ static void generateEncoderFields( static void generateNullifyOptionalFieldsMethod( final Appendable out, final int level, - final List optionalFields) throws IOException + final NullifyTargets targets) throws IOException { indent(out, level, "/// Set all optional fields to their null values.\n"); indent(out, level, "#[inline]\n"); indent(out, level, "pub fn nullify_optional_fields(&mut self) -> &mut Self {\n"); - for (final String field : optionalFields) + appendNullifyOptionalFieldsBody(out, level + 1, targets); + indent(out, level + 1, "self\n"); + indent(out, level, "}\n\n"); + } + + private static void appendNullifyOptionalFieldsBody( + final Appendable out, + final int level, + final NullifyTargets targets) throws IOException + { + for (final String field : targets.optionalFields) { - indent(out, level + 1, "self.%s_opt(None);\n", field); + indent(out, level, "self.%s_opt(None);\n", field); } + + for (final String compositeFieldEncoder : targets.compositeFieldEncoders) + { + indent(out, level, "{\n"); + indent(out, level + 1, "let mut composite_encoder = core::mem::take(self).%s();\n", compositeFieldEncoder); + indent(out, level + 1, "composite_encoder.nullify_optional_fields();\n"); + indent(out, level + 1, "*self = composite_encoder.parent().expect(\"parent missing\");\n"); + indent(out, level, "}\n"); + } + } + + private static void appendTraitNullifyOptionalFieldsMethod( + final Appendable out, + final int level, + final NullifyTargets targets) throws IOException + { + if (targets.isEmpty()) + { + return; + } + + indent(out, 0, "\n"); + indent(out, level, "/// Set all optional fields to their 'null' values.\n"); + indent(out, level, "#[inline]\n"); + indent(out, level, "fn nullify_optional_fields(&mut self) -> &mut Self {\n"); + appendNullifyOptionalFieldsBody(out, level + 1, targets); indent(out, level + 1, "self\n"); - indent(out, level, "}\n\n"); + indent(out, level, "}\n"); } private static boolean isOptionalPrimitiveScalar(final Token typeToken) @@ -327,6 +378,11 @@ private static String rustEnumType(final Token typeToken) return format("%s::%s", toLowerSnakeCase(enumTypeName), formatStructName(enumTypeName)); } + private static String compositeEncoderAccessorName(final String name) + { + return toLowerSnakeCase(encoderName(name)); + } + static void generateEncoderGroups( final StringBuilder sb, final List tokens, @@ -743,7 +799,7 @@ private static void generateCompositeEncoder( final Token typeToken, final String name) throws IOException { - final String encoderName = toLowerSnakeCase(encoderName(name)); + final String encoderName = compositeEncoderAccessorName(name); final String encoderTypeName = format("%s::%s", codecModName(typeToken.referencedName() == null ? typeToken.name() : typeToken.referencedName()), encoderName(formatStructName(typeToken.applicableTypeName()))); @@ -1390,7 +1446,7 @@ private static void generateSingleBitSet( static void appendImplEncoderTrait( final Appendable out, final String typeName, - final List optionalFields) throws IOException + final NullifyTargets targets) throws IOException { indent(out, 1, "impl<%s> %s for %s {\n", BUF_LIFETIME, withBufLifetime("Writer"), withBufLifetime(typeName)); indent(out, 2, "#[inline]\n"); @@ -1410,19 +1466,7 @@ static void appendImplEncoderTrait( indent(out, 3, "self.limit = limit;\n"); indent(out, 2, "}\n"); - if (!optionalFields.isEmpty()) - { - indent(out, 0, "\n"); - indent(out, 2, "/// Set all optional fields to their 'null' values.\n"); - indent(out, 2, "#[inline]\n"); - indent(out, 2, "fn nullify_optional_fields(&mut self) -> &mut Self {\n"); - for (final String field : optionalFields) - { - indent(out, 3, "self.%s_opt(None);\n", field); - } - indent(out, 3, "self\n"); - indent(out, 2, "}\n"); - } + appendTraitNullifyOptionalFieldsMethod(out, 2, targets); indent(out, 1, "}\n\n"); } @@ -1695,7 +1739,7 @@ static void appendImplEncoderForComposite( final Appendable out, final int level, final String name, - final List optionalFields) throws IOException + final NullifyTargets targets) throws IOException { appendImplWriterForComposite(out, level, name); @@ -1711,19 +1755,7 @@ static void appendImplEncoderForComposite( indent(out, level + 2, "self.parent.as_mut().expect(\"parent missing\").set_limit(limit);\n"); indent(out, level + 1, "}\n"); - if (!optionalFields.isEmpty()) - { - indent(out, 0, "\n"); - indent(out, 2, "/// Set all optional fields to their 'null' values.\n"); - indent(out, 2, "#[inline]\n"); - indent(out, 2, "fn nullify_optional_fields(&mut self) -> &mut Self {\n"); - for (final String field : optionalFields) - { - indent(out, 3, "self.%s_opt(None);\n", field); - } - indent(out, 3, "self\n"); - indent(out, 2, "}\n"); - } + appendTraitNullifyOptionalFieldsMethod(out, 2, targets); indent(out, level, "}\n\n"); } @@ -1809,7 +1841,7 @@ private static void generateCompositeEncoder( indent(out, 3, "self.parent.take().ok_or(SbeErr::ParentNotSet)\n"); indent(out, 2, "}\n\n"); - final List optionalFields = new ArrayList<>(); + final NullifyTargets nullifyTargets = new NullifyTargets(); for (int i = 1, end = tokens.size() - 1; i < end; ) { final Token encodingToken = tokens.get(i); @@ -1823,7 +1855,7 @@ private static void generateCompositeEncoder( { generateOptionalPrimitiveEncoder(sb, 2, encodingToken, encodingToken.name(), encodingToken.encoding()); - optionalFields.add(formatFunctionName(encodingToken.name())); + nullifyTargets.optionalFields.add(formatFunctionName(encodingToken.name())); } break; case BEGIN_ENUM: @@ -1831,7 +1863,7 @@ private static void generateCompositeEncoder( if (isOptionalEnum(encodingToken, encodingToken)) { generateOptionalEnumEncoder(sb, 2, encodingToken, encodingToken.name()); - optionalFields.add(formatFunctionName(encodingToken.name())); + nullifyTargets.optionalFields.add(formatFunctionName(encodingToken.name())); } break; case BEGIN_SET: @@ -1839,6 +1871,7 @@ private static void generateCompositeEncoder( break; case BEGIN_COMPOSITE: generateCompositeEncoder(sb, 2, encodingToken, encodingToken.name()); + nullifyTargets.compositeFieldEncoders.add(compositeEncoderAccessorName(encodingToken.name())); break; default: break; @@ -1848,7 +1881,7 @@ private static void generateCompositeEncoder( i += encodingToken.componentTokenCount(); } - generateNullifyOptionalFieldsMethod(out, 2, optionalFields); + generateNullifyOptionalFieldsMethod(out, 2, nullifyTargets); indent(out, 1, "}\n"); // end impl indent(out, 0, "} // end encoder mod \n"); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index b465cee680..cae8e37546 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -72,8 +72,8 @@ void generateEncoder( indent(sb, level, "initial_limit: usize,\n"); indent(sb, level - 1, "}\n\n"); - final List optionalFields = RustGenerator.getNullifyOptionalFields(fields); - RustGenerator.appendImplEncoderForComposite(sb, level - 1, name, optionalFields); + final RustGenerator.NullifyTargets nullifyTargets = RustGenerator.getNullifyTargets(fields); + RustGenerator.appendImplEncoderForComposite(sb, level - 1, name, nullifyTargets); // define impl... indent(sb, level - 1, "impl<'a, P> %s

        where P: Encoder<'a> + Default {\n", name); diff --git a/sbe-tool/src/test/resources/optional_enum_nullify.xml b/sbe-tool/src/test/resources/optional_enum_nullify.xml index 22478f92e3..81a20568fd 100644 --- a/sbe-tool/src/test/resources/optional_enum_nullify.xml +++ b/sbe-tool/src/test/resources/optional_enum_nullify.xml @@ -23,9 +23,13 @@ 3 4 + + + + From e73b2680bcf63c8e81cf3fe46fa78ec70017dbad Mon Sep 17 00:00:00 2001 From: Leonardo Arcari Date: Thu, 19 Feb 2026 18:41:28 +0100 Subject: [PATCH 1526/1594] fix(rust): make optional setters fluent --- .../sbe/generation/rust/RustGenerator.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 13edc8f67b..106941bda6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -37,7 +37,6 @@ import java.util.Set; import static java.lang.String.format; -import static java.lang.System.out; import static uk.co.real_logic.sbe.generation.rust.RustUtil.*; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields; import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups; @@ -713,11 +712,13 @@ private static void generateOptionalPrimitiveEncoder( generateRustDoc(sb, level, typeToken, encoding); indent(sb, level, "/// Set to `None` to encode the field null value.\n"); indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn %s_opt(&mut self, value: Option<%s>) {\n", functionName, rustPrimitiveType); + indent(sb, level, "pub fn %s_opt(&mut self, value: Option<%s>) -> &mut Self {\n", + functionName, rustPrimitiveType); indent(sb, level + 1, "match value {\n"); indent(sb, level + 2, "Some(value) => self.%s(value),\n", functionName); indent(sb, level + 2, "None => self.%s(%s),\n", functionName, nullLiteral); - indent(sb, level + 1, "}\n"); + indent(sb, level + 1, "};\n"); + indent(sb, level + 1, "self\n"); indent(sb, level, "}\n\n"); } @@ -764,11 +765,12 @@ private static void generateOptionalEnumEncoder( generateRustDoc(sb, level, typeToken, typeToken.encoding()); indent(sb, level, "/// Set to `None` to encode the field null value.\n"); indent(sb, level, "#[inline]\n"); - indent(sb, level, "pub fn %s_opt(&mut self, value: Option<%s>) {\n", functionName, enumType); + indent(sb, level, "pub fn %s_opt(&mut self, value: Option<%s>) -> &mut Self {\n", functionName, enumType); indent(sb, level + 1, "match value {\n"); indent(sb, level + 2, "Some(value) => self.%s(value),\n", functionName); indent(sb, level + 2, "None => self.%s(%s::NullVal),\n", functionName, enumType); - indent(sb, level + 1, "}\n"); + indent(sb, level + 1, "};\n"); + indent(sb, level + 1, "self\n"); indent(sb, level, "}\n\n"); } From 9459cebfe41750faf8242de04993b5f69439bcf4 Mon Sep 17 00:00:00 2001 From: Leonardo Arcari Date: Thu, 19 Feb 2026 18:44:40 +0100 Subject: [PATCH 1527/1594] refactor(rust): use fluent API in unit test --- rust/tests/optional_field_nullify_test.rs | 119 ++++++++++++---------- 1 file changed, 64 insertions(+), 55 deletions(-) diff --git a/rust/tests/optional_field_nullify_test.rs b/rust/tests/optional_field_nullify_test.rs index fe2f5fc0d6..6963236a6e 100644 --- a/rust/tests/optional_field_nullify_test.rs +++ b/rust/tests/optional_field_nullify_test.rs @@ -123,32 +123,37 @@ fn encode_extension_car_for_optional_field_test( ); car = car.header(0).parent()?; - car.cup_holder_count_opt(cup_holder_count); if nullify { // When enabled, tests expect optional message fields to be encoded as "absent". - car.nullify_optional_fields(); + car.cup_holder_count_opt(cup_holder_count) + .nullify_optional_fields(); } - car.serial_number(1234); - car.model_year(2013); - car.available(ExtBooleanType::T); - car.code(ExtModel::A); - car.some_numbers(&[0, 1, 2, 3]); - car.vehicle_code(b"abcdef"); - - extras.set_cruise_control(true); - extras.set_sports_pack(true); - extras.set_sun_roof(false); + else + { + car.cup_holder_count_opt(cup_holder_count); + } + car.serial_number(1234) + .model_year(2013) + .available(ExtBooleanType::T) + .code(ExtModel::A) + .some_numbers(&[0, 1, 2, 3]) + .vehicle_code(b"abcdef"); + + extras + .set_cruise_control(true) + .set_sports_pack(true) + .set_sun_roof(false); car.extras(extras); let mut engine = car.engine_encoder(); - engine.capacity(2000); - engine.num_cylinders(4); - engine.manufacturer_code(b"123"); - engine.efficiency(35); - engine.booster_enabled(ExtBooleanType::T); + engine + .capacity(2000) + .num_cylinders(4) + .manufacturer_code(b"123") + .efficiency(35) + .booster_enabled(ExtBooleanType::T); let mut booster = engine.booster_encoder(); - booster.boost_type(ExtBoostType::NITROUS); - booster.horse_power(200); + booster.boost_type(ExtBoostType::NITROUS).horse_power(200); engine = booster.parent()?; let _car = engine.parent()?; @@ -210,36 +215,36 @@ fn nullify_on_composite_and_group_without_optional_fields_has_no_effect() -> Tes ); car = car.header(0).parent()?; - car.serial_number(1234); - car.model_year(2013); - car.available(ExtBooleanType::T); - car.code(ExtModel::A); - car.some_numbers(&[0, 1, 2, 3]); - car.vehicle_code(b"abcdef"); - - extras.set_cruise_control(true); - extras.set_sports_pack(true); - extras.set_sun_roof(false); + car.serial_number(1234) + .model_year(2013) + .available(ExtBooleanType::T) + .code(ExtModel::A) + .some_numbers(&[0, 1, 2, 3]) + .vehicle_code(b"abcdef"); + + extras + .set_cruise_control(true) + .set_sports_pack(true) + .set_sun_roof(false); car.extras(extras); let mut engine = car.engine_encoder(); - engine.capacity(2000); - engine.num_cylinders(4); - engine.manufacturer_code(b"123"); - engine.efficiency(35); - engine.booster_enabled(ExtBooleanType::T); + engine + .capacity(2000) + .num_cylinders(4) + .manufacturer_code(b"123") + .efficiency(35) + .booster_enabled(ExtBooleanType::T); // Engine has no optional primitive scalar fields, so nullify must be a no-op. engine.nullify_optional_fields(); let mut booster = engine.booster_encoder(); - booster.boost_type(ExtBoostType::NITROUS); - booster.horse_power(200); + booster.boost_type(ExtBoostType::NITROUS).horse_power(200); engine = booster.parent()?; car = engine.parent()?; fuel_figures = car.fuel_figures_encoder(1, fuel_figures); assert_eq!(Some(0), fuel_figures.advance()?); - fuel_figures.speed(77); - fuel_figures.mpg(12.5); + fuel_figures.speed(77).mpg(12.5); // FuelFigures group also has no optional primitive scalar fields; expect no change. fuel_figures.nullify_optional_fields(); let _car = fuel_figures.parent()?; @@ -263,8 +268,9 @@ fn nullify_on_composite_and_group_without_optional_fields_has_no_effect() -> Tes fn opt_setters_work_as_expected() -> TestResult { let mut some_buf = vec![0u8; 256]; let mut encoder = create_issue_895_encoder(&mut some_buf); - encoder.optional_float_opt(Some(2.07)); - encoder.optional_double_opt(Some(4.12)); + encoder + .optional_float_opt(Some(2.07)) + .optional_double_opt(Some(4.12)); let decoder = decode_issue_895(some_buf.as_slice()); assert_eq!(Some(2.07), decoder.optional_float()); @@ -272,8 +278,7 @@ fn opt_setters_work_as_expected() -> TestResult { let mut none_buf = vec![0u8; 256]; let mut encoder = create_issue_895_encoder(&mut none_buf); - encoder.optional_float_opt(None); - encoder.optional_double_opt(None); + encoder.optional_float_opt(None).optional_double_opt(None); let decoder = decode_issue_895(none_buf.as_slice()); assert_eq!(None, decoder.optional_float()); @@ -287,8 +292,9 @@ fn nullify_optional_fields_sets_all_to_none() -> TestResult { use issue_895::Encoder; let mut buf = vec![0u8; 256]; let mut encoder = create_issue_895_encoder(&mut buf); - encoder.optional_float_opt(Some(2.07)); - encoder.optional_double_opt(Some(4.12)); + encoder + .optional_float_opt(Some(2.07)) + .optional_double_opt(Some(4.12)); // Message-level nullify should clear every optional primitive scalar field. encoder.nullify_optional_fields(); @@ -306,8 +312,7 @@ fn composite_nullify_optional_fields_sets_fields_to_none() -> TestResult { let mut encoder = create_issue_972_encoder(&mut buffer); encoder.old_field(777); let mut new_composite_encoder = encoder.new_field_encoder(); - new_composite_encoder.f1(2007); - new_composite_encoder.f2(2012); + new_composite_encoder.f1(2007).f2(2012); // Composite-level nullify should clear composite optional primitive fields. new_composite_encoder.nullify_optional_fields(); let _encoder = new_composite_encoder.parent()?; @@ -353,9 +358,10 @@ fn group_nullify_optional_fields_sets_optional_fields_to_none() -> TestResult { quote_entries = quote_sets.quote_entries_encoder(1, quote_entries); assert_eq!(Some(0), quote_entries.advance()?); - quote_entries.security_id_opt(Some(111)); - quote_entries.bid_size_opt(Some(222)); - quote_entries.offer_size_opt(Some(333)); + quote_entries + .security_id_opt(Some(111)) + .bid_size_opt(Some(222)) + .offer_size_opt(Some(333)); // Group-level nullify should clear all optional primitive scalar fields in the entry. quote_entries.nullify_optional_fields(); @@ -384,9 +390,10 @@ fn nullify_optional_fields_sets_optional_enum_field_to_null_value() -> TestResul let mut control_buffer = vec![0u8; 256]; let mut control_encoder = create_optional_enum_nullify_encoder(&mut control_buffer); // Optionality is declared on the field, matching IR optional enum semantics. - control_encoder.optional_enum_opt(Some(OenEnumType::One)); // This field is required, even if its enum type encoding is optional. - control_encoder.required_enum_from_optional_type(OenOptionalEncodingEnumType::Alpha); + control_encoder + .optional_enum_opt(Some(OenEnumType::One)) + .required_enum_from_optional_type(OenOptionalEncodingEnumType::Alpha); let mut control_composite = control_encoder.optional_composite_encoder(); control_composite.optional_counter_opt(Some(77)); let _control_encoder = control_composite.parent()?; @@ -402,8 +409,9 @@ fn nullify_optional_fields_sets_optional_enum_field_to_null_value() -> TestResul let mut none_buffer = vec![0u8; 256]; let mut none_encoder = create_optional_enum_nullify_encoder(&mut none_buffer); - none_encoder.optional_enum_opt(None); - none_encoder.required_enum_from_optional_type(OenOptionalEncodingEnumType::Beta); + none_encoder + .optional_enum_opt(None) + .required_enum_from_optional_type(OenOptionalEncodingEnumType::Beta); let mut none_composite = none_encoder.optional_composite_encoder(); none_composite.optional_counter_opt(None); let _none_encoder = none_composite.parent()?; @@ -419,8 +427,9 @@ fn nullify_optional_fields_sets_optional_enum_field_to_null_value() -> TestResul let mut nullified_buffer = vec![0u8; 256]; let mut nullified_encoder = create_optional_enum_nullify_encoder(&mut nullified_buffer); - nullified_encoder.optional_enum_opt(Some(OenEnumType::Two)); - nullified_encoder.required_enum_from_optional_type(OenOptionalEncodingEnumType::Beta); + nullified_encoder + .optional_enum_opt(Some(OenEnumType::Two)) + .required_enum_from_optional_type(OenOptionalEncodingEnumType::Beta); let mut nullified_composite = nullified_encoder.optional_composite_encoder(); nullified_composite.optional_counter_opt(Some(88)); nullified_encoder = nullified_composite.parent()?; From f40acbb504ee956079c1324afe8050d317448b25 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 12 Mar 2026 10:59:34 +0000 Subject: [PATCH 1528/1594] [Java] Add a test for custom message header type. --- .../co/real_logic/sbe/ir/EncodedIrTest.java | 24 +++++++++++++++++++ .../src/test/resources/custom-header-type.xml | 19 +++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 sbe-tool/src/test/resources/custom-header-type.xml diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index c353a02d31..a8daf9bd2a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -17,6 +17,7 @@ import org.junit.jupiter.api.Test; import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.xml.CompositeType; import uk.co.real_logic.sbe.xml.IrGenerator; import uk.co.real_logic.sbe.xml.MessageSchema; import uk.co.real_logic.sbe.xml.ParserOptions; @@ -28,6 +29,8 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.core.Is.is; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; class EncodedIrTest @@ -175,6 +178,27 @@ void shouldPreservePackageNames() throws Exception testDecodeTypes("explicit-package-test-schema.xml"); } + @Test + void shouldUseCustomHeaderType() throws Exception + { + try (InputStream in = Tests.getLocalResource("custom-header-type.xml")) + { + final MessageSchema schema = parse(in, ParserOptions.DEFAULT); + final CompositeType messageHeader = schema.messageHeader(); + assertNotNull(messageHeader); + assertEquals("foo", messageHeader.name()); + + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final ByteBuffer buffer = ByteBuffer.allocate(CAPACITY); + try (IrEncoder irEncoder = new IrEncoder(buffer, ir)) + { + irEncoder.encode(); + assertThat(buffer.position(), greaterThan(0)); + } + } + } + private void testDecodeTypes(final String name1) throws Exception { try (InputStream in = Tests.getLocalResource(name1)) diff --git a/sbe-tool/src/test/resources/custom-header-type.xml b/sbe-tool/src/test/resources/custom-header-type.xml new file mode 100644 index 0000000000..689d60c055 --- /dev/null +++ b/sbe-tool/src/test/resources/custom-header-type.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + From fe703f59307ea5cefa1422e62ca8572bc00ca038 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 12 Mar 2026 13:36:00 +0000 Subject: [PATCH 1529/1594] [Java] Upgrade to `Mockito` 5.23.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bbe626a7ef..d65f565d3e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ jqwik = "1.9.3" jmh = "1.37" json = "20251224" junit = "6.0.3" -mockito = "5.22.0" +mockito = "5.23.0" plexus = "3.3.0" shadow = "9.3.2" versions = "0.53.0" From 489a9443e0dc064485cf8d499a3b4d8e3b9c3219 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 16 Mar 2026 22:03:12 +0100 Subject: [PATCH 1530/1594] [Java] Upgrade to `Shadow` 9.4.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d65f565d3e..9c6d37c733 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20251224" junit = "6.0.3" mockito = "5.23.0" plexus = "3.3.0" -shadow = "9.3.2" +shadow = "9.4.0" versions = "0.53.0" [libraries] From 6e771ab8c299c1abcc9eb29c5ce82b21c16ca9eb Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 20 Mar 2026 11:02:20 +0100 Subject: [PATCH 1531/1594] [Java] Upgrade to `Gradle` 9.4.1. --- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5be30bbeb2..c82ad3ff01 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 0262dcbd52..739907dfd1 100755 --- a/gradlew +++ b/gradlew @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. From 3eb1ac3c73a8a69548e4b5cb5508757dce695161 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 27 Mar 2026 14:51:13 +0100 Subject: [PATCH 1532/1594] [Java] Upgrade to `Shadow` 9.4.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9c6d37c733..f4d2b11457 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20251224" junit = "6.0.3" mockito = "5.23.0" plexus = "3.3.0" -shadow = "9.4.0" +shadow = "9.4.1" versions = "0.53.0" [libraries] From 5cc53ab21fa1d9cbf01488453d8dd6fdb04a3272 Mon Sep 17 00:00:00 2001 From: Andrew Schwartz Date: Sat, 28 Mar 2026 07:27:32 -0700 Subject: [PATCH 1533/1594] [C++] mark a generated function SBE_CONSTEXPR (#1055) (#1083) * [C++] gate constexpr char-constant accessor on c++14 * [C++] initialize test buffer before manufacturer code read --- .../sbe/generation/cpp/CppGenerator.java | 11 ++++++-- sbe-tool/src/test/c/CodeGenTest.cpp | 2 ++ .../sbe/generation/cpp/CppGeneratorTest.java | 27 +++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 3ee0208cbb..ae795aeaeb 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2630,12 +2630,19 @@ private void generateConstPropertyMethods( values); sb.append(String.format("\n" + + indent + " #if __cplusplus >= 201402L\n" + + indent + " SBE_NODISCARD static SBE_CONSTEXPR %1$s %2$s(const std::uint64_t index) SBE_NOEXCEPT\n" + + indent + " {\n" + + indent + " const std::uint8_t %2$sValues[] = { %3$s, 0 };\n\n" + + indent + " return (char)%2$sValues[index];\n" + + indent + " }\n" + + indent + " #else\n" + indent + " SBE_NODISCARD %1$s %2$s(const std::uint64_t index) const\n" + indent + " {\n" + indent + " static const std::uint8_t %2$sValues[] = { %3$s, 0 };\n\n" + - indent + " return (char)%2$sValues[index];\n" + - indent + " }\n", + indent + " }\n" + + indent + " #endif\n", cppTypeName, propertyName, values)); diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index 4135804ad3..474915d769 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -253,6 +253,7 @@ class CodeGenTest : public testing::Test output << static_cast(CGT(car_discountedModel(&car))) << ';'; char code_buf[4]; + memset(code_buf, 0, sizeof(code_buf)); CGT(engine) engine = {}; if (CGT(car_engine)(&car, &engine)) { @@ -354,6 +355,7 @@ class CodeGenTest : public testing::Test } char code_buf[4]; + memset(code_buf, 0, sizeof(code_buf)); CGT(engine) engine = {}; if (CGT(car_engine)(&car, &engine)) { diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index 2cdb37ecce..8d0b3995fa 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -75,6 +75,33 @@ void shouldUseConstexprWhenInitializingSemanticVersion() throws Exception } } + @Test + void shouldGenerateConstexprConstantCharAccessorOnlyForCpp14AndLater() throws Exception + { + try (InputStream in = Tests.getLocalResource("code-generation-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + + final CppGenerator generator = new CppGenerator(ir, false, outputManager); + generator.generate(); + + final String source = outputManager.getSource("code.generation.test.Engine").toString(); + assertThat(source, containsString("#if __cplusplus >= 201402L")); + assertThat(source, containsString( + "SBE_NODISCARD static SBE_CONSTEXPR char fuel(const std::uint64_t index) SBE_NOEXCEPT")); + assertThat(source, containsString("const std::uint8_t fuelValues[] = { 80, 101, 116, 114, 111, 108, 0 };")); + assertThat(source, containsString("#else")); + assertThat(source, containsString("SBE_NODISCARD char fuel(const std::uint64_t index) const")); + assertThat(source, containsString( + "static const std::uint8_t fuelValues[] = { 80, 101, 116, 114, 111, 108, 0 };")); + } + } + @Test void dtosShouldReferenceTypesInDifferentPackages() throws Exception { From b0b7826cb7006c1faea7cdfe3b0b1e5a66df295f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 29 Mar 2026 15:43:05 +0200 Subject: [PATCH 1534/1594] [C++] Protect against a segfault when dealing with empty `std::span` and `std::view`. Fixes #1100 --- .../sbe/generation/cpp/CppGenerator.java | 24 +++++---- sbe-tool/src/test/cpp/CodeGenTest.cpp | 53 ++++++++++++++++++- 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index ae795aeaeb..14c01a981a 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1240,7 +1240,7 @@ private void generateVarData( generateJsonEscapedStringGetter(sb, token, indent, propertyName); new Formatter(sb).format("\n" + - indent + " #if __cplusplus >= 201703L\n" + + indent + " #ifdef SBE_USE_STRING_VIEW\n" + indent + " std::string_view get%1$sAsStringView()\n" + indent + " {\n" + "%2$s" + @@ -1279,7 +1279,7 @@ private void generateVarData( lengthToken.encoding().applicableMaxValue().longValue()); new Formatter(sb).format("\n" + - indent + " #if __cplusplus >= 201703L\n" + + indent + " #ifdef SBE_USE_STRING_VIEW\n" + indent + " %1$s &put%2$s(const std::string_view str)\n" + indent + " {\n" + indent + " if (str.length() > %4$d)\n" + @@ -2323,7 +2323,10 @@ private void generateArrayProperty( indent + " {\n" + indent + " static_assert(N <= %5$d, \"array too large for put%2$s\");\n\n" + "%6$s" + - indent + " std::memcpy(m_buffer + m_offset + %3$d, src.data(), sizeof(%4$s) * N);\n" + + indent + " if (N > 0)\n" + + indent + " {\n" + + indent + " std::memcpy(m_buffer + m_offset + %3$d, src.data(), sizeof(%4$s) * N);\n" + + indent + " }\n\n" + indent + " for (std::size_t start = N; start < %5$d; ++start)\n" + indent + " {\n" + indent + " m_buffer[m_offset + %3$d + start] = 0;\n" + @@ -2350,9 +2353,11 @@ private void generateArrayProperty( indent + " {\n" + indent + " throw std::runtime_error(\"array too large for put%2$s [E106]\");\n" + indent + " }\n\n" + - "%6$s" + - indent + " std::memcpy(m_buffer + m_offset + %3$d, src.data(), sizeof(%4$s) * srcLength);\n" + + indent + " if (srcLength > 0)\n" + + indent + " {\n" + + indent + " std::memcpy(m_buffer + m_offset + %3$d, src.data(), sizeof(%4$s) * srcLength);\n" + + indent + " }\n\n" + indent + " for (std::size_t start = srcLength; start < %5$d; ++start)\n" + indent + " {\n" + indent + " m_buffer[m_offset + %3$d + start] = 0;\n" + @@ -2502,14 +2507,15 @@ private void generateArrayProperty( indent + " {\n" + indent + " throw std::runtime_error(\"string too large for put%2$s [E106]\");\n" + indent + " }\n\n" + - "%5$s" + - indent + " std::memcpy(m_buffer + m_offset + %3$d, str.data(), srcLength);\n" + + indent + " if (srcLength > 0)\n" + + indent + " {\n" + + indent + " std::memcpy(m_buffer + m_offset + %3$d, str.data(), srcLength);\n" + + indent + " }\n\n" + indent + " for (std::size_t start = srcLength; start < %4$d; ++start)\n" + indent + " {\n" + indent + " m_buffer[m_offset + %3$d + start] = 0;\n" + indent + " }\n\n" + - indent + " return *this;\n" + indent + " }\n" + indent + " #else\n" + @@ -2520,14 +2526,12 @@ private void generateArrayProperty( indent + " {\n" + indent + " throw std::runtime_error(\"string too large for put%2$s [E106]\");\n" + indent + " }\n\n" + - "%5$s" + indent + " std::memcpy(m_buffer + m_offset + %3$d, str.c_str(), srcLength);\n" + indent + " for (std::size_t start = srcLength; start < %4$d; ++start)\n" + indent + " {\n" + indent + " m_buffer[m_offset + %3$d + start] = 0;\n" + indent + " }\n\n" + - indent + " return *this;\n" + indent + " }\n" + indent + " #endif\n", diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index 991e1f96f3..c8a831d368 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -1101,6 +1101,21 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringViewMethods) } #endif +#ifdef SBE_USE_STRING_VIEW +TEST_F(CodeGenTest, shouldHandleEmptyStringView) +{ + char buffer[BUFFER_LEN] = {}; + + std::uint64_t baseOffset = MessageHeader::encodedLength(); + Car car; + car.wrapForEncode(buffer, baseOffset, sizeof(buffer)); + car.putVehicleCode(std::string_view{}); + + car.sbeRewind(); + EXPECT_EQ(car.getVehicleCodeAsStringView(), ""); +} +#endif + #ifdef SBE_USE_SPAN TEST_F(CodeGenTest, shouldBeAbleToUseStdSpanViewMethods) { @@ -1133,7 +1148,7 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdSpanViewMethods) #endif #ifdef SBE_USE_SPAN -TEST_F(CodeGenTest, shouldBeAbleToResolveStringLiterals) +TEST_F(CodeGenTest, shouldBeAbleToUseStringLiteralsWhenSpanIsEnabled) { char buffer[BUFFER_LEN] = {}; @@ -1144,6 +1159,42 @@ TEST_F(CodeGenTest, shouldBeAbleToResolveStringLiterals) car.sbeRewind(); EXPECT_EQ(car.getVehicleCodeAsStringView(), "ABCDE"); + auto res = car.getVehicleCodeAsSpan(); + EXPECT_EQ(6, res.size()); +} +#endif + +#ifdef SBE_USE_SPAN +TEST_F(CodeGenTest, shouldBeAbleToUseSpanToEncodeCharData) +{ + char buffer[BUFFER_LEN] = {}; + + std::uint64_t baseOffset = MessageHeader::encodedLength(); + Car car; + car.wrapForEncode(buffer, baseOffset, sizeof(buffer)); + car.putVehicleCode(std::span("ABCDE")); + + car.sbeRewind(); + EXPECT_EQ(car.getVehicleCodeAsStringView(), "ABCDE"); + auto res = car.getVehicleCodeAsSpan(); + EXPECT_EQ(6, res.size()); +} +#endif + +#ifdef SBE_USE_SPAN +TEST_F(CodeGenTest, shouldBeAbleToHandleEmptySpan) +{ + char buffer[BUFFER_LEN] = {}; + + std::uint64_t baseOffset = MessageHeader::encodedLength(); + Car car; + car.wrapForEncode(buffer, baseOffset, sizeof(buffer)); + car.putVehicleCode(std::span{}); + + car.sbeRewind(); + EXPECT_EQ(car.getVehicleCodeAsStringView(), ""); + auto res = car.getVehicleCodeAsSpan(); + EXPECT_EQ(0, res.size()); } #endif From 08ed6a986f5e104a6cf920a3f75cdde949e8aaeb Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 29 Mar 2026 15:46:37 +0200 Subject: [PATCH 1535/1594] [Java] Checkstyle fixes. --- .../java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 14c01a981a..5d3762c274 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -2356,7 +2356,8 @@ private void generateArrayProperty( "%6$s" + indent + " if (srcLength > 0)\n" + indent + " {\n" + - indent + " std::memcpy(m_buffer + m_offset + %3$d, src.data(), sizeof(%4$s) * srcLength);\n" + + indent + " std::memcpy(m_buffer + m_offset + %3$d, src.data(), sizeof(%4$s) * srcLength);" + + "\n" + indent + " }\n\n" + indent + " for (std::size_t start = srcLength; start < %5$d; ++start)\n" + indent + " {\n" + From 7932dd65081243384fac3f2366780239f13e25d2 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 29 Mar 2026 15:50:24 +0200 Subject: [PATCH 1536/1594] [C/C++] Upgrade to `CMake` 4.3.0. --- cppbuild/cppbuild | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppbuild/cppbuild b/cppbuild/cppbuild index 26a8d8a345..fe14587073 100755 --- a/cppbuild/cppbuild +++ b/cppbuild/cppbuild @@ -5,7 +5,7 @@ BUILD_DIR="${SOURCE_DIR}/cppbuild/Release" EXTRA_CMAKE_ARGS="" BUILD_DELETE_CMAKE=false -BUILD_CMAKE_VERSION=4.2.1 +BUILD_CMAKE_VERSION=4.3.0 BUILD_CMAKE_DIR="${SOURCE_DIR}/cppbuild/cmake" ncpus=1 From 8452826d59421695a52cd0ddeeff10d2eb7a94e1 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 29 Mar 2026 15:57:12 +0200 Subject: [PATCH 1537/1594] [C++] Fix test assertion. --- sbe-tool/src/test/cpp/CodeGenTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index c8a831d368..40f769919b 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -1155,10 +1155,10 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStringLiteralsWhenSpanIsEnabled) std::uint64_t baseOffset = MessageHeader::encodedLength(); Car car; car.wrapForEncode(buffer, baseOffset, sizeof(buffer)); - car.putVehicleCode("ABCDE"); + car.putVehicleCode("ABC"); car.sbeRewind(); - EXPECT_EQ(car.getVehicleCodeAsStringView(), "ABCDE"); + EXPECT_EQ(car.getVehicleCodeAsStringView(), "ABC"); auto res = car.getVehicleCodeAsSpan(); EXPECT_EQ(6, res.size()); } @@ -1194,7 +1194,7 @@ TEST_F(CodeGenTest, shouldBeAbleToHandleEmptySpan) car.sbeRewind(); EXPECT_EQ(car.getVehicleCodeAsStringView(), ""); auto res = car.getVehicleCodeAsSpan(); - EXPECT_EQ(0, res.size()); + EXPECT_EQ(6, res.size()); } #endif From 6a81d98a01663934ba6400d967a4e7bca6860bfb Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 29 Mar 2026 16:01:57 +0200 Subject: [PATCH 1538/1594] [CI] Add Clang 22 and remove version older than 17. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c71672ec1..731426c973 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -173,7 +173,7 @@ jobs: strategy: fail-fast: false matrix: - version: [ '13', '14', '15', '16', '17', '18', '19', '20', '21' ] + version: [ '17', '18', '19', '20', '21', '22' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} @@ -186,7 +186,7 @@ jobs: run: | sudo mkdir -p /etc/apt/keyrings/ curl https://apt.llvm.org/llvm-snapshot.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/llvm-snapshot.gpg - echo "deb [signed-by=/etc/apt/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${{ matrix.version }} main" | sudo tee /etc/apt/sources.list.d/llvm.list + echo "deb [signed-by=/etc/apt/keyrings/llvm-snapshot.gpg] https://apt.llvm.org/noble/ llvm-toolchain-noble-${{ matrix.version }} main" | sudo tee /etc/apt/sources.list.d/llvm.list sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} - name: Setup java to run Gradle script From a96e8689190d20079f0efdcfba9bd48bd8e63345 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sun, 29 Mar 2026 16:03:20 +0200 Subject: [PATCH 1539/1594] [Doc] Add `C` to the list of supported languages. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ce55a80bb2..5a819bd1fe 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Simple Binary Encoding (SBE) [SBE](https://github.com/FIXTradingCommunity/fix-simple-binary-encoding) is an OSI layer 6 presentation for encoding and decoding binary application messages for low-latency financial applications. This repository contains -the reference implementations in Java, C++, Golang, C#, and Rust. +the reference implementations in Java, C, C++, C#, Golang and Rust. More details on the design and usage of SBE can be found on the [Wiki](https://github.com/aeron-io/simple-binary-encoding/wiki). From fa98b3d89876d8e2495f09ffc681d5d4f3a4ba8e Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 7 Apr 2026 14:41:16 +0200 Subject: [PATCH 1540/1594] [CI] Upgrade to Github Actions: - `actions/checkout@v6` - `gradle/actions/setup-gradle@v6` - `actions/upload-artifact@v7` diff --git c/.github/workflows/ci.yml i/.github/workflows/ci.yml index 731426c9..36d7f5db 100644 --- c/.github/workflows/ci.yml +++ i/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: echo "TMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append echo "TEMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Setup java @@ -67,7 +67,7 @@ jobs: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Build with Gradle run: ./gradlew - name: Copy test logs @@ -78,7 +78,7 @@ jobs: ./gradlew tarTestLogs - name: Upload crash logs if: always() && steps.copy_test_logs.outputs.file == 'build/distributions/test_logs.tbz2' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 with: name: crash-logs-${{ matrix.os }}-java-${{ matrix.java }} path: ${{ steps.copy_test_logs.outputs.file }} @@ -96,7 +96,7 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Setup java to run Gradle script @@ -110,7 +110,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Cache NuGet dependencies uses: actions/cache@v4 with: @@ -143,7 +143,7 @@ jobs: CXX: g++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Install compiler @@ -162,7 +162,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Build run: ./cppbuild/cppbuild @@ -173,13 +173,13 @@ jobs: strategy: fail-fast: false matrix: - version: [ '17', '18', '19', '20', '21', '22' ] + version: [ '13', '14', '15', '16', '17', '18', '19', '20', '21', '22' ] env: CC: clang-${{ matrix.version }} CXX: clang++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Install compiler @@ -200,7 +200,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Build run: ./cppbuild/cppbuild @@ -217,7 +217,7 @@ jobs: CXX: clang++ steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Setup java to run Gradle script @@ -231,7 +231,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Build run: cmake --version && ./cppbuild/cppbuild @@ -252,7 +252,7 @@ jobs: echo "TMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append echo "TEMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Setup java to run Gradle script @@ -266,7 +266,7 @@ jobs: echo "BUILD_JAVA_HOME=$env:JAVA_HOME" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Build run: cppbuild/cppbuild.cmd @@ -280,7 +280,7 @@ jobs: rust: [ stable, beta, nightly ] steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Rust setup @@ -298,7 +298,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - run: ./gradlew runRustTests golang-build: @@ -311,7 +311,7 @@ jobs: version: [ '1.23.x', '1.24.x' ] steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Setup Go @@ -329,7 +329,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Generate jar run: ./gradlew assemble - name: Run tests diff --git c/.github/workflows/codeql.yml i/.github/workflows/codeql.yml index b7e916b4..b763dfaf 100644 --- c/.github/workflows/codeql.yml +++ i/.github/workflows/codeql.yml @@ -39,7 +39,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} @@ -56,7 +56,7 @@ jobs: echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Initialize CodeQL uses: github/codeql-action/init@v4 @@ -89,7 +89,7 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} @@ -114,7 +114,7 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Setup dotnet uses: actions/setup-dotnet@v5 @@ -152,7 +152,7 @@ jobs: CXX: g++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} @@ -169,7 +169,7 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Install compiler run: | diff --git c/.github/workflows/release.yml i/.github/workflows/release.yml index b33cf0c6..e49b419b 100644 --- c/.github/workflows/release.yml +++ i/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.ref }} - name: Setup java @@ -37,7 +37,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Publish with Gradle run: ./gradlew publish uploadArtifactsToCentralPortal env: diff --git c/.github/workflows/slow.yml i/.github/workflows/slow.yml index 0961c7a9..ed6585eb 100644 --- c/.github/workflows/slow.yml +++ i/.github/workflows/slow.yml @@ -40,7 +40,7 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Setup java uses: actions/setup-java@v5 with: @@ -57,7 +57,7 @@ jobs: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Setup dotnet uses: actions/setup-dotnet@v5 with: @@ -74,12 +74,12 @@ jobs: ./gradlew tarTestLogs - name: Upload crash logs if: always() && steps.copy_test_logs.outputs.file == 'build/distributions/test_logs.tbz2' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 with: name: crash-logs-${{ matrix.os }}-property-tests-java-${{matrix.java}}-dotnet-${{matrix.dotnet}} path: ${{ steps.copy_test_logs.outputs.file }} - name: Upload test results - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 if: always() with: name: property-tests --- .github/workflows/ci.yml | 34 +++++++++++++++++----------------- .github/workflows/codeql.yml | 12 ++++++------ .github/workflows/release.yml | 4 ++-- .github/workflows/slow.yml | 8 ++++---- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 731426c973..defe4986ad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: echo "TMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append echo "TEMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Setup java @@ -67,7 +67,7 @@ jobs: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Build with Gradle run: ./gradlew - name: Copy test logs @@ -78,7 +78,7 @@ jobs: ./gradlew tarTestLogs - name: Upload crash logs if: always() && steps.copy_test_logs.outputs.file == 'build/distributions/test_logs.tbz2' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 with: name: crash-logs-${{ matrix.os }}-java-${{ matrix.java }} path: ${{ steps.copy_test_logs.outputs.file }} @@ -96,7 +96,7 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Setup java to run Gradle script @@ -110,7 +110,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Cache NuGet dependencies uses: actions/cache@v4 with: @@ -143,7 +143,7 @@ jobs: CXX: g++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Install compiler @@ -162,7 +162,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Build run: ./cppbuild/cppbuild @@ -179,7 +179,7 @@ jobs: CXX: clang++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Install compiler @@ -200,7 +200,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Build run: ./cppbuild/cppbuild @@ -217,7 +217,7 @@ jobs: CXX: clang++ steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Setup java to run Gradle script @@ -231,7 +231,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Build run: cmake --version && ./cppbuild/cppbuild @@ -252,7 +252,7 @@ jobs: echo "TMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append echo "TEMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Setup java to run Gradle script @@ -266,7 +266,7 @@ jobs: echo "BUILD_JAVA_HOME=$env:JAVA_HOME" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Build run: cppbuild/cppbuild.cmd @@ -280,7 +280,7 @@ jobs: rust: [ stable, beta, nightly ] steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Rust setup @@ -298,7 +298,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - run: ./gradlew runRustTests golang-build: @@ -311,7 +311,7 @@ jobs: version: [ '1.23.x', '1.24.x' ] steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} - name: Setup Go @@ -329,7 +329,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Generate jar run: ./gradlew assemble - name: Run tests diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b7e916b4fc..b763dfafcd 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,7 +39,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} @@ -56,7 +56,7 @@ jobs: echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Initialize CodeQL uses: github/codeql-action/init@v4 @@ -89,7 +89,7 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} @@ -114,7 +114,7 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Setup dotnet uses: actions/setup-dotnet@v5 @@ -152,7 +152,7 @@ jobs: CXX: g++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.sha }} @@ -169,7 +169,7 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Install compiler run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b33cf0c690..e49b419b17 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.ref }} - name: Setup java @@ -37,7 +37,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Publish with Gradle run: ./gradlew publish uploadArtifactsToCentralPortal env: diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 0961c7a9ef..ed6585eb3b 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -40,7 +40,7 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Setup java uses: actions/setup-java@v5 with: @@ -57,7 +57,7 @@ jobs: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 + uses: gradle/actions/setup-gradle@v6 - name: Setup dotnet uses: actions/setup-dotnet@v5 with: @@ -74,12 +74,12 @@ jobs: ./gradlew tarTestLogs - name: Upload crash logs if: always() && steps.copy_test_logs.outputs.file == 'build/distributions/test_logs.tbz2' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 with: name: crash-logs-${{ matrix.os }}-property-tests-java-${{matrix.java}}-dotnet-${{matrix.dotnet}} path: ${{ steps.copy_test_logs.outputs.file }} - name: Upload test results - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 if: always() with: name: property-tests From 989b40553f15d9299a74d4e8c2603ad2be900729 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 16 Apr 2026 15:38:02 +0200 Subject: [PATCH 1541/1594] [Checkstyle] Allow inline return tags in the Javadoc comments + align with Aeron Checkstyle config. --- config/checkstyle/checkstyle.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index b97f363689..a0ad3423a9 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -41,7 +41,9 @@ - + + + @@ -50,9 +52,7 @@ - - - + @@ -80,7 +80,9 @@ - + + + @@ -192,7 +194,5 @@ - - From a06614ef6fd1b32015b3fe618a3b8b572b7aa011 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Wed, 22 Apr 2026 09:58:13 +1200 Subject: [PATCH 1542/1594] 1.38.0 release --- CHANGELOG.adoc | 11 ++++++++++- version.txt | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 5ae8575833..5675c0ddea 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,10 +1,19 @@ = Changelog -== 1.38.0 (unreleased) +== 1.38.0 (2026-04-22) +* **[Rust]** Recursively call nullify_optional_fields on composites +* **[Rust]** Generate setters for optional enum fields too. * **[Rust]** Generated encoders now produce fluent interface. (https://github.com/aeron-io/simple-binary-encoding/pull/1097[#1097]) * **[Rust]** Updated some function to `const`. (https://github.com/aeron-io/simple-binary-encoding/pull/1098[#1098]) * **[Rust]** Updated generator to correctly limit length of var data written. (https://github.com/aeron-io/simple-binary-encoding/pull/1096[#1096]) +* **[C++]** Protect against a segfault when dealing with empty `std::span` and `std::view`. +* **[C++]** mark a generated function SBE_CONSTEXPR (#1055) (#1083) +* Upgrade to `CMake` 4.3.0. +* Upgrade to `Shadow` 9.4.1. +* Upgrade to `Gradle` 9.4.1. +* Upgrade to `Shadow` 9.4.0. +* Upgrade to `Mockito` 5.23.0. == 1.37.1 (2026-01-13) * **[Java]** Ensure Java code generation for precedence checks always produces the same code without re-orderings. diff --git a/version.txt b/version.txt index 860bd0396d..ebeef2f2d6 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.38.0-SNAPSHOT +1.38.0 From 60ae2904b61388cc7b70d16ae3bd85c822799ff0 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Wed, 22 Apr 2026 10:45:40 +1200 Subject: [PATCH 1543/1594] 1.39.0 snapshot --- CHANGELOG.adoc | 2 ++ version.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 5675c0ddea..b6fe598b0b 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,5 +1,7 @@ = Changelog +== 1.39.0 (unreleased) + == 1.38.0 (2026-04-22) * **[Rust]** Recursively call nullify_optional_fields on composites diff --git a/version.txt b/version.txt index ebeef2f2d6..40c214a46c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.38.0 +1.39.0-SNAPSHOT From e2e46fbab894331d1ac7a0d4f35336fce00a31bd Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 23 Apr 2026 15:24:16 +0200 Subject: [PATCH 1544/1594] [Java] Upgrade to `Versions` 0.54.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f4d2b11457..9ef7516f81 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ junit = "6.0.3" mockito = "5.23.0" plexus = "3.3.0" shadow = "9.4.1" -versions = "0.53.0" +versions = "0.54.0" [libraries] agrona = { group = "org.agrona", name = "agrona", version.ref = "agrona" } From 13daf4fa32a2fb31b89eac26ed05a656a604d63f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 23 Apr 2026 15:24:41 +0200 Subject: [PATCH 1545/1594] [Java] Upgrade to `Agrona` 2.4.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9ef7516f81..b365a2f26b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.4.0" +agrona = "2.4.1" checkstyle = "12.3.1" commons-codec = "1.15" commons-lang3 = "3.8.1" From 9ee637410cb6028ea37c1ed2ff03db420d090e7c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 23 Apr 2026 15:27:25 +0200 Subject: [PATCH 1546/1594] [Doc] Changelog update. --- CHANGELOG.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index b6fe598b0b..1092b157be 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -2,6 +2,9 @@ == 1.39.0 (unreleased) +* Upgrade to `Agrona` 2.4.1. +* Upgrade to `Versions` 0.54.0. + == 1.38.0 (2026-04-22) * **[Rust]** Recursively call nullify_optional_fields on composites From 06fdf3cb1a14b0ecbc66727c69a1150964f0962b Mon Sep 17 00:00:00 2001 From: Victor Leyva <118840902+vleyva@users.noreply.github.com> Date: Fri, 24 Apr 2026 11:14:12 -0400 Subject: [PATCH 1547/1594] Update README to remove sales contact details (#1104) Removed commercial support contact information from README. --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 5a819bd1fe..bef8bbff07 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,7 @@ For the latest version information and changes see the [Change Log](https://gith The Java and C++ SBE implementations work very efficiently with the [Aeron](https://github.com/aeron-io/aeron) messaging system for low-latency and high-throughput communications. The Java SBE implementation has a dependency on -[Agrona](https://github.com/aeron-io/agrona) for its buffer implementations. Commercial support is available from -[sales@real-logic.co.uk](mailto:sales@real-logic.co.uk?subject=SBE). +[Agrona](https://github.com/aeron-io/agrona) for its buffer implementations. Binaries -------- From 95f4e5c2e932c6befa2da58d19564ecf17670851 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Tue, 28 Apr 2026 05:55:58 +1200 Subject: [PATCH 1548/1594] 1.38.1 release --- CHANGELOG.adoc | 2 +- version.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 1092b157be..0c25154a18 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,6 +1,6 @@ = Changelog -== 1.39.0 (unreleased) +== 1.38.1 (2026-04-28) * Upgrade to `Agrona` 2.4.1. * Upgrade to `Versions` 0.54.0. diff --git a/version.txt b/version.txt index 40c214a46c..11a36de972 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.39.0-SNAPSHOT +1.38.1 From e31f65007897844097e7933cd7e9f035ac65584e Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Tue, 28 Apr 2026 05:57:29 +1200 Subject: [PATCH 1549/1594] 1.39.0-SNAPSHOT --- CHANGELOG.adoc | 2 ++ version.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 0c25154a18..d43bd10cc2 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,5 +1,7 @@ = Changelog +== 1.39.0 (unreleased) + == 1.38.1 (2026-04-28) * Upgrade to `Agrona` 2.4.1. diff --git a/version.txt b/version.txt index 11a36de972..40c214a46c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.38.1 +1.39.0-SNAPSHOT From a4a03a873f27645a9203c8af7477057482c3a2da Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 28 Apr 2026 18:16:42 +0200 Subject: [PATCH 1550/1594] [Java] Upgrade to `Gradle` 9.5.0. --- CHANGELOG.adoc | 2 ++ gradle/wrapper/gradle-wrapper.jar | Bin 48966 -> 48462 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++- gradlew | 2 +- gradlew.bat | 31 ++++++++--------------- 5 files changed, 16 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index d43bd10cc2..de3e542650 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -2,6 +2,8 @@ == 1.39.0 (unreleased) +* Upgrade to `Gradle` 9.5.0. + == 1.38.1 (2026-04-28) * Upgrade to `Agrona` 2.4.1. diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d997cfc60f4cff0e7451d19d49a82fa986695d07..b1b8ef56b44f16b14dc800fa8103a6d89abb526f 100644 GIT binary patch delta 39760 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 e(*aw}>J`&Ep$5$o2mVP)i30-M3~u@DBh0 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 delta 40115 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 e{Sg5G5zENPNVU~b5#<2@M#Os+0czL&{q{eZe&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,7 +65,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line @@ -73,21 +73,10 @@ goto fail @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% From 3d19ac22e9d379f9ad893dbf92c07e66703b30c2 Mon Sep 17 00:00:00 2001 From: swadaptive <268603322+swadaptive@users.noreply.github.com> Date: Tue, 5 May 2026 11:29:33 +0100 Subject: [PATCH 1551/1594] (chore): Pin github actions to specific commit hashes (#1105) * Pin GitHub actions versions to hashes * Move to rust setup action that support Dependabot-friendly versioning --- .github/workflows/ci.yml | 60 +++++++++++++++++------------------ .github/workflows/codeql.yml | 38 +++++++++++----------- .github/workflows/release.yml | 6 ++-- .github/workflows/slow.yml | 14 ++++---- 4 files changed, 59 insertions(+), 59 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index defe4986ad..34d31eec0b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,11 +41,11 @@ jobs: echo "TMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append echo "TEMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.sha }} - name: Setup java - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ matrix.java }} @@ -62,12 +62,12 @@ jobs: echo "BUILD_JAVA_HOME=$env:JAVA_HOME" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append echo "BUILD_JAVA_VERSION=${{ matrix.java }}" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Setup java to run Gradle - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Build with Gradle run: ./gradlew - name: Copy test logs @@ -78,7 +78,7 @@ jobs: ./gradlew tarTestLogs - name: Upload crash logs if: always() && steps.copy_test_logs.outputs.file == 'build/distributions/test_logs.tbz2' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: crash-logs-${{ matrix.os }}-java-${{ matrix.java }} path: ${{ steps.copy_test_logs.outputs.file }} @@ -96,11 +96,11 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.sha }} - name: Setup java to run Gradle script - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -110,16 +110,16 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Cache NuGet dependencies - uses: actions/cache@v4 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ~/.nuget/packages key: ${{ runner.os }}-nuget-${{ hashFiles('csharp/**/*.sln') }} restore-keys: | ${{ runner.os }}-nuget- - name: Setup dotnet - uses: actions/setup-dotnet@v5 + uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0 with: dotnet-version: ${{ matrix.dotnet }} dotnet-quality: 'ga' @@ -143,7 +143,7 @@ jobs: CXX: g++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.sha }} - name: Install compiler @@ -152,7 +152,7 @@ jobs: sudo apt-get update sudo apt-get install -y g++-${{ matrix.version }} - name: Setup java to run Gradle script - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -162,7 +162,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Build run: ./cppbuild/cppbuild @@ -179,7 +179,7 @@ jobs: CXX: clang++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.sha }} - name: Install compiler @@ -190,7 +190,7 @@ jobs: sudo apt-get update sudo apt-get install -y clang-${{ matrix.version }} - name: Setup java to run Gradle script - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -200,7 +200,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Build run: ./cppbuild/cppbuild @@ -217,11 +217,11 @@ jobs: CXX: clang++ steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.sha }} - name: Setup java to run Gradle script - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -231,7 +231,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Build run: cmake --version && ./cppbuild/cppbuild @@ -252,11 +252,11 @@ jobs: echo "TMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append echo "TEMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.sha }} - name: Setup java to run Gradle script - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -266,7 +266,7 @@ jobs: echo "BUILD_JAVA_HOME=$env:JAVA_HOME" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Build run: cppbuild/cppbuild.cmd @@ -280,15 +280,15 @@ jobs: rust: [ stable, beta, nightly ] steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.sha }} - name: Rust setup - uses: dtolnay/rust-toolchain@stable + uses: actions-rust-lang/setup-rust-toolchain@2b1f5e9b395427c92ee4e3331786ca3c37afe2d7 # v1.16.0 with: toolchain: ${{ matrix.rust }} - name: Setup java to run Gradle script - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -298,7 +298,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - run: ./gradlew runRustTests golang-build: @@ -311,15 +311,15 @@ jobs: version: [ '1.23.x', '1.24.x' ] steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.sha }} - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version: ${{ matrix.version }} - name: Setup java to run Gradle script - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -329,7 +329,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Generate jar run: ./gradlew assemble - name: Run tests diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b763dfafcd..8892163a36 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,12 +39,12 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.sha }} - name: Setup java - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ matrix.java }} @@ -56,10 +56,10 @@ jobs: echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Initialize CodeQL - uses: github/codeql-action/init@v4 + uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml @@ -68,7 +68,7 @@ jobs: run: ./gradlew - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 with: category: "/language:${{matrix.language}}" @@ -89,12 +89,12 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.sha }} - name: Cache NuGet dependencies - uses: actions/cache@v4 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ~/.nuget/packages key: ${{ runner.os }}-nuget-${{ hashFiles('csharp/**/*.sln') }} @@ -102,7 +102,7 @@ jobs: ${{ runner.os }}-nuget- - name: Setup java - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -114,15 +114,15 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Setup dotnet - uses: actions/setup-dotnet@v5 + uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0 with: dotnet-version: ${{ matrix.dotnet }} - name: Initialize CodeQL - uses: github/codeql-action/init@v4 + uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml @@ -131,7 +131,7 @@ jobs: run: ./csharp/build.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 with: category: "/language:${{matrix.language}}" @@ -152,12 +152,12 @@ jobs: CXX: g++-${{ matrix.version }} steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.sha }} - name: Setup java - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -169,14 +169,14 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Install compiler run: | sudo apt-get install -y g++-${{ matrix.version }} - name: Initialize CodeQL - uses: github/codeql-action/init@v4 + uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml @@ -185,14 +185,14 @@ jobs: run: ./cppbuild/cppbuild - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 with: category: "/language:${{ matrix.language }}" upload: false output: sarif-results - name: filter-sarif - uses: advanced-security/filter-sarif@v1 + uses: advanced-security/filter-sarif@2da736ff05ef065cb2894ac6892e47b5eac2c3c0 # v1.1 with: patterns: | -**/thirdparty/** @@ -200,6 +200,6 @@ jobs: output: sarif-results/${{ matrix.language }}.sarif - name: Upload SARIF - uses: github/codeql-action/upload-sarif@v4 + uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 with: sarif_file: sarif-results/${{ matrix.language }}.sarif diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e49b419b17..2808d09f66 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,11 +23,11 @@ jobs: runs-on: ubuntu-24.04 steps: - name: checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.ref }} - name: Setup java - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} @@ -37,7 +37,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Publish with Gradle run: ./gradlew publish uploadArtifactsToCentralPortal env: diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index ed6585eb3b..e30649fbe6 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -40,9 +40,9 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup java - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ matrix.java }} @@ -52,14 +52,14 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - name: Setup java to run Gradle script - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Setup dotnet - uses: actions/setup-dotnet@v5 + uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0 with: dotnet-version: ${{ matrix.dotnet }} - name: Build .NET library @@ -74,12 +74,12 @@ jobs: ./gradlew tarTestLogs - name: Upload crash logs if: always() && steps.copy_test_logs.outputs.file == 'build/distributions/test_logs.tbz2' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: crash-logs-${{ matrix.os }}-property-tests-java-${{matrix.java}}-dotnet-${{matrix.dotnet}} path: ${{ steps.copy_test_logs.outputs.file }} - name: Upload test results - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: always() with: name: property-tests From 430afa6a541273a4fa7aa177bb49c675794236f4 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 5 May 2026 17:07:04 +0200 Subject: [PATCH 1552/1594] trigger CI --- CHANGELOG.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index de3e542650..da3c662e72 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -3,6 +3,7 @@ == 1.39.0 (unreleased) * Upgrade to `Gradle` 9.5.0. +* == 1.38.1 (2026-04-28) From 3cce26a26e6fb06c0989d7867bd721d5387f43f1 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 20 May 2026 15:12:12 +0200 Subject: [PATCH 1553/1594] [Java] Upgrade to `JUnit` 6.1.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b365a2f26b..1f37604fc3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ httpcore = "4.4.14" jqwik = "1.9.3" jmh = "1.37" json = "20251224" -junit = "6.0.3" +junit = "6.1.0" mockito = "5.23.0" plexus = "3.3.0" shadow = "9.4.1" From 36f87da67d0b3340d5b58a95baa6dd862b3f5b87 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 20 May 2026 15:12:25 +0200 Subject: [PATCH 1554/1594] [Java] Upgrade to `Gradle` 9.5.1. --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f193d72905..e74c8700b2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-all.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From 69906a12a046bb4208b20d9a078af1539f4d826d Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 20 May 2026 15:15:13 +0200 Subject: [PATCH 1555/1594] [Doc] Release notes. --- CHANGELOG.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index da3c662e72..34004f61dd 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -2,8 +2,8 @@ == 1.39.0 (unreleased) -* Upgrade to `Gradle` 9.5.0. -* +* Upgrade to `Gradle` 9.5.1. +* Upgrade to `JUnit` 6.1.0. == 1.38.1 (2026-04-28) From 2941e218b47885a0b6cd04b168dfad7eb4b2d399 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 22 May 2026 16:23:28 +0200 Subject: [PATCH 1556/1594] [CI] Use `cache-provider: basic` with `setup-gradle` action. --- .github/workflows/ci.yml | 16 ++++++++++++++++ .github/workflows/codeql.yml | 6 ++++++ .github/workflows/release.yml | 2 ++ .github/workflows/slow.yml | 2 ++ 4 files changed, 26 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34d31eec0b..0597a21e9c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,6 +68,8 @@ jobs: java-version: ${{ env.JAVA_VERSION }} - name: Setup Gradle uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 + with: + cache-provider: basic - name: Build with Gradle run: ./gradlew - name: Copy test logs @@ -111,6 +113,8 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 + with: + cache-provider: basic - name: Cache NuGet dependencies uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: @@ -163,6 +167,8 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 + with: + cache-provider: basic - name: Build run: ./cppbuild/cppbuild @@ -201,6 +207,8 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 + with: + cache-provider: basic - name: Build run: ./cppbuild/cppbuild @@ -232,6 +240,8 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 + with: + cache-provider: basic - name: Build run: cmake --version && ./cppbuild/cppbuild @@ -267,6 +277,8 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Setup Gradle uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 + with: + cache-provider: basic - name: Build run: cppbuild/cppbuild.cmd @@ -299,6 +311,8 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 + with: + cache-provider: basic - run: ./gradlew runRustTests golang-build: @@ -330,6 +344,8 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 + with: + cache-provider: basic - name: Generate jar run: ./gradlew assemble - name: Run tests diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 8892163a36..327473dcf4 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -57,6 +57,8 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 + with: + cache-provider: basic - name: Initialize CodeQL uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 @@ -115,6 +117,8 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 + with: + cache-provider: basic - name: Setup dotnet uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0 @@ -170,6 +174,8 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 + with: + cache-provider: basic - name: Install compiler run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2808d09f66..782735172f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,6 +38,8 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 + with: + cache-provider: basic - name: Publish with Gradle run: ./gradlew publish uploadArtifactsToCentralPortal env: diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index e30649fbe6..b0c7af5a5e 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -58,6 +58,8 @@ jobs: java-version: ${{ env.JAVA_VERSION }} - name: Setup Gradle uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 + with: + cache-provider: basic - name: Setup dotnet uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0 with: From b0dd9b279d3611f9d49ad99817ac2e074e20007f Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Fri, 22 May 2026 15:11:47 -0500 Subject: [PATCH 1557/1594] add element descriptions to rust comments --- .../sbe/generation/rust/RustGenerator.java | 133 +++++++++---- .../rust/RustGeneratorDescriptionTest.java | 186 ++++++++++++++++++ .../rust-description-test-schema.xml | 48 +++++ .../rust-no-description-test-schema.xml | 47 +++++ 4 files changed, 380 insertions(+), 34 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorDescriptionTest.java create mode 100644 sbe-tool/src/test/resources/rust-description-test-schema.xml create mode 100644 sbe-tool/src/test/resources/rust-no-description-test-schema.xml diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 106941bda6..628055a3e3 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -278,24 +278,25 @@ static void generateEncoderFields( switch (typeToken.signal()) { case ENCODING: - generatePrimitiveEncoder(sb, level, typeToken, name); + generatePrimitiveEncoder(sb, level, typeToken, name, fieldToken.description()); if (isOptionalPrimitiveScalar(typeToken)) { - generateOptionalPrimitiveEncoder(sb, level, typeToken, name, typeToken.encoding()); + generateOptionalPrimitiveEncoder(sb, level, typeToken, name, typeToken.encoding(), + fieldToken.description()); } break; case BEGIN_ENUM: generateEnumEncoder(sb, level, fieldToken, typeToken, name); if (isOptionalEnum(typeToken, fieldToken)) { - generateOptionalEnumEncoder(sb, level, typeToken, name); + generateOptionalEnumEncoder(sb, level, typeToken, name, fieldToken.description()); } break; case BEGIN_SET: - generateBitSetEncoder(sb, level, typeToken, name); + generateBitSetEncoder(sb, level, typeToken, name, fieldToken.description()); break; case BEGIN_COMPOSITE: - generateCompositeEncoder(sb, level, typeToken, name); + generateCompositeEncoder(sb, level, typeToken, name, fieldToken.description()); break; default: break; @@ -475,6 +476,7 @@ static void generateEncoderVarData( // function to write slice ... todo - handle character encoding ? indent(sb, level, "/// VAR_DATA ENCODER - character encoding: '%s'\n", characterEncoding); + appendFieldDocDescription(sb, level, varDataToken.description()); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&mut self, value: %s) -> &mut Self {\n", propertyName, varDataType); @@ -503,13 +505,38 @@ private static String rustNullLiteral(final Encoding encoding) return generateRustLiteral(encoding.primitiveType(), encoding.applicableNullValue()); } + private static void appendDocDescription( + final Appendable writer, + final int level, + final String description) throws IOException + { + if (Strings.isEmpty(description)) + { + return; + } + indent(writer, level, "/// %s\n", description); + } + + private static void appendFieldDocDescription( + final Appendable writer, + final int level, + final String description) throws IOException + { + if (Strings.isEmpty(description)) + { + return; + } + indent(writer, level, "/// - description: %s\n", description); + } private static void generateRustDoc( final StringBuilder sb, final int level, + final String fieldDescription, final Token typeToken, final Encoding encoding) throws IOException { + appendFieldDocDescription(sb, level, fieldDescription); indent(sb, level, "/// - min value: %s\n", encoding.applicableMinValue()); indent(sb, level, "/// - max value: %s\n", encoding.applicableMaxValue()); indent(sb, level, "/// - null value: %s\n", rustNullLiteral(encoding)); @@ -524,14 +551,15 @@ private static void generatePrimitiveArrayFromIterEncoder( final StringBuilder sb, final int level, final Token typeToken, - final String name) throws IOException + final String name, + final String fieldDescription) throws IOException { final Encoding encoding = typeToken.encoding(); final PrimitiveType primitiveType = encoding.primitiveType(); final String rustPrimitiveType = rustTypeName(primitiveType); indent(sb, level, "/// primitive array field '%s' from an Iterator\n", name); - generateRustDoc(sb, level, typeToken, encoding); + generateRustDoc(sb, level, fieldDescription, typeToken, encoding); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s_from_iter(&mut self, iter: impl Iterator) -> &mut Self {\n", formatFunctionName(name), rustPrimitiveType); @@ -558,7 +586,8 @@ private static void generatePrimitiveArrayZeroPaddedEncoder( final StringBuilder sb, final int level, final Token typeToken, - final String name) throws IOException + final String name, + final String fieldDescription) throws IOException { final Encoding encoding = typeToken.encoding(); final PrimitiveType primitiveType = encoding.primitiveType(); @@ -566,7 +595,7 @@ private static void generatePrimitiveArrayZeroPaddedEncoder( final int arrayLength = typeToken.arrayLength(); indent(sb, level, "/// primitive array field '%s' with zero padding\n", name); - generateRustDoc(sb, level, typeToken, encoding); + generateRustDoc(sb, level, fieldDescription, typeToken, encoding); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s_zero_padded(&mut self, value: &[%s]) -> &mut Self {\n", formatFunctionName(name), rustPrimitiveType); @@ -583,7 +612,8 @@ private static void generatePrimitiveArrayEncoder( final StringBuilder sb, final int level, final Token typeToken, - final String name) throws IOException + final String name, + final String fieldDescription) throws IOException { final Encoding encoding = typeToken.encoding(); final PrimitiveType primitiveType = encoding.primitiveType(); @@ -609,7 +639,7 @@ private static void generatePrimitiveArrayEncoder( indent(sb, level, "}\n\n"); indent(sb, level, "/// primitive array field '%s'\n", name); - generateRustDoc(sb, level, typeToken, encoding); + generateRustDoc(sb, level, fieldDescription, typeToken, encoding); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&mut self, value: &[%s]) -> &mut Self {\n", formatFunctionName(name), rustPrimitiveType); @@ -646,20 +676,21 @@ private static void generatePrimitiveArrayEncoder( indent(sb, level, "}\n\n"); } - generatePrimitiveArrayFromIterEncoder(sb, level, typeToken, name); - generatePrimitiveArrayZeroPaddedEncoder(sb, level, typeToken, name); + generatePrimitiveArrayFromIterEncoder(sb, level, typeToken, name, fieldDescription); + generatePrimitiveArrayZeroPaddedEncoder(sb, level, typeToken, name, fieldDescription); } private static void generatePrimitiveEncoder( final StringBuilder sb, final int level, final Token typeToken, - final String name) throws IOException + final String name, + final String fieldDescription) throws IOException { final int arrayLength = typeToken.arrayLength(); if (arrayLength > 1) { - generatePrimitiveArrayEncoder(sb, level, typeToken, name); + generatePrimitiveArrayEncoder(sb, level, typeToken, name, fieldDescription); return; } @@ -670,7 +701,7 @@ private static void generatePrimitiveEncoder( return; } - generatePrimitiveSetterEncoder(sb, level, typeToken, name, encoding); + generatePrimitiveSetterEncoder(sb, level, typeToken, name, encoding, fieldDescription); } private static void generatePrimitiveSetterEncoder( @@ -678,13 +709,14 @@ private static void generatePrimitiveSetterEncoder( final int level, final Token typeToken, final String name, - final Encoding encoding) throws IOException + final Encoding encoding, + final String fieldDescription) throws IOException { final PrimitiveType primitiveType = encoding.primitiveType(); final String rustPrimitiveType = rustTypeName(primitiveType); indent(sb, level, "/// primitive field '%s'\n", name); - generateRustDoc(sb, level, typeToken, encoding); + generateRustDoc(sb, level, fieldDescription, typeToken, encoding); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&mut self, value: %s) -> &mut Self {\n", formatFunctionName(name), rustPrimitiveType); @@ -701,7 +733,8 @@ private static void generateOptionalPrimitiveEncoder( final int level, final Token typeToken, final String name, - final Encoding encoding) throws IOException + final Encoding encoding, + final String fieldDescription) throws IOException { final PrimitiveType primitiveType = encoding.primitiveType(); final String rustPrimitiveType = rustTypeName(primitiveType); @@ -709,7 +742,7 @@ private static void generateOptionalPrimitiveEncoder( final String nullLiteral = rustNullLiteral(encoding); indent(sb, level, "/// optional primitive field '%s'\n", name); - generateRustDoc(sb, level, typeToken, encoding); + generateRustDoc(sb, level, fieldDescription, typeToken, encoding); indent(sb, level, "/// Set to `None` to encode the field null value.\n"); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s_opt(&mut self, value: Option<%s>) -> &mut Self {\n", @@ -741,6 +774,7 @@ private static void generateEnumEncoder( final String rustPrimitiveType = rustTypeName(encoding.primitiveType()); indent(sb, level, "/// REQUIRED enum\n"); + appendFieldDocDescription(sb, level, fieldToken.description()); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&mut self, value: %s) -> &mut Self {\n", formatFunctionName(name), enumType); @@ -756,13 +790,14 @@ private static void generateOptionalEnumEncoder( final StringBuilder sb, final int level, final Token typeToken, - final String name) throws IOException + final String name, + final String fieldDescription) throws IOException { final String functionName = formatFunctionName(name); final String enumType = rustEnumType(typeToken); indent(sb, level, "/// optional enum field '%s'\n", name); - generateRustDoc(sb, level, typeToken, typeToken.encoding()); + generateRustDoc(sb, level, fieldDescription, typeToken, typeToken.encoding()); indent(sb, level, "/// Set to `None` to encode the field null value.\n"); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s_opt(&mut self, value: Option<%s>) -> &mut Self {\n", functionName, enumType); @@ -778,7 +813,8 @@ private static void generateBitSetEncoder( final StringBuilder sb, final int level, final Token bitsetToken, - final String name) throws IOException + final String name, + final String fieldDescription) throws IOException { final Encoding encoding = bitsetToken.encoding(); final String rustPrimitiveType = rustTypeName(encoding.primitiveType()); @@ -786,6 +822,7 @@ private static void generateBitSetEncoder( final String structTypeName = format("%s::%s", toLowerSnakeCase(referencedName == null ? bitsetToken.name() : referencedName), formatStructName(bitsetToken.applicableTypeName())); + appendFieldDocDescription(sb, level, fieldDescription); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&mut self, value: %s) {\n", formatFunctionName(name), structTypeName); @@ -799,13 +836,15 @@ private static void generateCompositeEncoder( final StringBuilder sb, final int level, final Token typeToken, - final String name) throws IOException + final String name, + final String fieldDescription) throws IOException { final String encoderName = compositeEncoderAccessorName(name); final String encoderTypeName = format("%s::%s", codecModName(typeToken.referencedName() == null ? typeToken.name() : typeToken.referencedName()), encoderName(formatStructName(typeToken.applicableTypeName()))); indent(sb, level, "/// COMPOSITE ENCODER\n"); + appendFieldDocDescription(sb, level, fieldDescription); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(self) -> %2$s {\n", encoderName, @@ -840,7 +879,7 @@ static void generateDecoderFields( generateEnumDecoder(sb, level, fieldToken, typeToken, name); break; case BEGIN_SET: - generateBitSetDecoder(sb, level, typeToken, name); + generateBitSetDecoder(sb, level, typeToken, name, fieldToken.description()); break; case BEGIN_COMPOSITE: generateCompositeDecoder(sb, level, fieldToken, typeToken, name); @@ -869,6 +908,7 @@ private static void generateCompositeDecoder( codecModName(referencedName == null ? typeToken.name() : referencedName), decoderName(formatStructName(typeToken.applicableTypeName()))); indent(sb, level, "/// COMPOSITE DECODER\n"); + appendFieldDocDescription(sb, level, fieldToken.description()); indent(sb, level, "#[inline]\n"); if (fieldToken.version() > 0) { @@ -900,7 +940,8 @@ private static void generateBitSetDecoder( final StringBuilder sb, final int level, final Token bitsetToken, - final String name) throws IOException + final String name, + final String fieldDescription) throws IOException { final Encoding encoding = bitsetToken.encoding(); final String rustPrimitiveType = rustTypeName(encoding.primitiveType()); @@ -909,6 +950,7 @@ private static void generateBitSetDecoder( toLowerSnakeCase(referencedName == null ? bitsetToken.name() : referencedName), formatStructName(bitsetToken.applicableTypeName())); indent(sb, level, "/// BIT SET DECODER\n"); + appendFieldDocDescription(sb, level, fieldDescription); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&self) -> %s {\n", formatFunctionName(name), structTypeName); @@ -940,7 +982,7 @@ private static void generatePrimitiveDecoder( } else if (encoding.presence() == Encoding.Presence.CONSTANT) { - generatePrimitiveConstantDecoder(sb, level, name, encoding); + generatePrimitiveConstantDecoder(sb, level, name, encoding, fieldToken.description()); } else if (encoding.presence() == Encoding.Presence.OPTIONAL) { @@ -966,6 +1008,7 @@ private static void generatePrimitiveArrayDecoder( final int arrayLength = typeToken.arrayLength(); assert arrayLength > 1; + appendFieldDocDescription(sb, level, fieldToken.description()); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&self) -> [%s; %d] {\n", formatFunctionName(name), @@ -1013,7 +1056,8 @@ private static void generatePrimitiveConstantDecoder( final StringBuilder sb, final int level, final String name, - final Encoding encoding) throws IOException + final Encoding encoding, + final String fieldDescription) throws IOException { assert encoding.presence() == Encoding.Presence.CONSTANT; final PrimitiveType primitiveType = encoding.primitiveType(); @@ -1021,6 +1065,7 @@ private static void generatePrimitiveConstantDecoder( final String characterEncoding = encoding.characterEncoding(); indent(sb, level, "/// CONSTANT \n"); + appendFieldDocDescription(sb, level, fieldDescription); final String rawConstValue = encoding.constValue().toString(); if (characterEncoding != null) { @@ -1070,6 +1115,8 @@ private static void generatePrimitiveOptionalDecoder( indent(sb, level, "/// primitive field - '%s' { null_value: '%s' }\n", encoding.presence(), rustNullLiteral(encoding)); + appendFieldDocDescription(sb, level, fieldToken.description()); + if (characterEncoding != null) { // ASCII and UTF-8 @@ -1122,6 +1169,8 @@ private static void generatePrimitiveRequiredDecoder( final String characterEncoding = encoding.characterEncoding(); indent(sb, level, "/// primitive field - '%s'\n", encoding.presence()); + appendFieldDocDescription(sb, level, fieldToken.description()); + if (characterEncoding != null) { // ASCII and UTF-8 @@ -1178,6 +1227,7 @@ private static void generateEnumDecoder( final String rustPrimitiveType = rustTypeName(encoding.primitiveType()); indent(sb, level, "/// REQUIRED enum\n"); + appendFieldDocDescription(sb, level, fieldToken.description()); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(&self) -> %s {\n", formatFunctionName(name), enumType); @@ -1285,6 +1335,7 @@ static void generateDecoderVarData( final PrimitiveType lengthType = lengthEncoding.primitiveType(); indent(sb, level, "/// VAR_DATA DECODER - character encoding: '%s'\n", characterEncoding); + appendFieldDocDescription(sb, level, varDataToken.description()); indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s_decoder(&mut self) -> (usize, usize) {\n", propertyName); @@ -1368,6 +1419,7 @@ private static void generateSingleBitSet( { final Token beginToken = tokens.get(0); final String rustPrimitiveType = rustTypeName(beginToken.encoding().primitiveType()); + appendDocDescription(writer, 0, beginToken.description()); indent(writer, 0, "#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]\n"); indent(writer, 0, "pub struct %s(pub %s);\n", bitSetType, rustPrimitiveType); indent(writer, 0, "impl %s {\n", bitSetType); @@ -1394,6 +1446,7 @@ private static void generateSingleBitSet( final String choiceBitIndex = encoding.constValue().toString(); indent(writer, 0, "\n"); + appendDocDescription(writer, 1, token.description()); indent(writer, 1, "#[inline]\n"); indent(writer, 1, "pub fn get_%s(&self) -> bool {\n", choiceName); indent(writer, 2, "0 != self.0 & (1 << %s)\n", choiceBitIndex); @@ -1548,6 +1601,7 @@ private static void generateEnum( throw new IllegalArgumentException("No valid values provided for enum " + originalEnumName); } + appendDocDescription(writer, 0, enumTokens.get(0).description()); indent(writer, 0, "#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]\n"); final String primitiveType = rustTypeName(messageBody.get(0).encoding().primitiveType()); indent(writer, 0, "#[repr(%s)]\n", primitiveType); @@ -1557,6 +1611,7 @@ private static void generateEnum( { final Encoding encoding = token.encoding(); final String literal = generateRustLiteral(encoding.primitiveType(), encoding.constValue().toString()); + appendDocDescription(writer, 1, token.description()); indent(writer, 1, "%s = %s, \n", token.name(), literal); } @@ -1702,6 +1757,11 @@ private static void generateComposite( try (Writer out = outputManager.createOutput(compositeModName)) { + final String compositeDescription = token.description(); + if (!Strings.isEmpty(compositeDescription)) + { + indent(out, 0, "//! %s\n\n", compositeDescription); + } indent(out, 0, "use crate::*;\n\n"); indent(out, 0, "pub use encoder::%sEncoder;\n", formatStructName(compositeName)); @@ -1852,11 +1912,12 @@ private static void generateCompositeEncoder( switch (encodingToken.signal()) { case ENCODING: - generatePrimitiveEncoder(sb, 2, encodingToken, encodingToken.name()); + generatePrimitiveEncoder(sb, 2, encodingToken, encodingToken.name(), + encodingToken.description()); if (isOptionalPrimitiveScalar(encodingToken)) { generateOptionalPrimitiveEncoder(sb, 2, encodingToken, encodingToken.name(), - encodingToken.encoding()); + encodingToken.encoding(), encodingToken.description()); nullifyTargets.optionalFields.add(formatFunctionName(encodingToken.name())); } break; @@ -1864,15 +1925,18 @@ private static void generateCompositeEncoder( generateEnumEncoder(sb, 2, encodingToken, encodingToken, encodingToken.name()); if (isOptionalEnum(encodingToken, encodingToken)) { - generateOptionalEnumEncoder(sb, 2, encodingToken, encodingToken.name()); + generateOptionalEnumEncoder(sb, 2, encodingToken, encodingToken.name(), + encodingToken.description()); nullifyTargets.optionalFields.add(formatFunctionName(encodingToken.name())); } break; case BEGIN_SET: - generateBitSetEncoder(sb, 2, encodingToken, encodingToken.name()); + generateBitSetEncoder(sb, 2, encodingToken, encodingToken.name(), + encodingToken.description()); break; case BEGIN_COMPOSITE: - generateCompositeEncoder(sb, 2, encodingToken, encodingToken.name()); + generateCompositeEncoder(sb, 2, encodingToken, encodingToken.name(), + encodingToken.description()); nullifyTargets.compositeFieldEncoders.add(compositeEncoderAccessorName(encodingToken.name())); break; default: @@ -1938,7 +2002,8 @@ private static void generateCompositeDecoder( generateEnumDecoder(sb, 2, encodingToken, encodingToken, encodingToken.name()); break; case BEGIN_SET: - generateBitSetDecoder(sb, 2, encodingToken, encodingToken.name()); + generateBitSetDecoder(sb, 2, encodingToken, encodingToken.name(), + encodingToken.description()); break; case BEGIN_COMPOSITE: generateCompositeDecoder(sb, 2, encodingToken, encodingToken, encodingToken.name()); diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorDescriptionTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorDescriptionTest.java new file mode 100644 index 0000000000..e96f9bf45c --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustGeneratorDescriptionTest.java @@ -0,0 +1,186 @@ +/* + * Copyright 2013-2025 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.rust; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +class RustGeneratorDescriptionTest +{ + @TempDir + Path tempDir; + + private Path generatedSrcDir; + + @BeforeEach + void generate() throws Exception + { + try (InputStream in = Tests.getLocalResource("rust-description-test-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + final RustOutputManager outputManager = new RustOutputManager( + tempDir.toString(), ir.applicableNamespace()); + final RustGenerator generator = new RustGenerator(ir, "0.1.0", outputManager); + generator.generate(); + + generatedSrcDir = tempDir.resolve("description_test").resolve("src"); + } + } + + @Test + void enumTypeDescriptionAppearsAsDocComment() throws Exception + { + final String source = readGeneratedFile("colour.rs"); + assertThat(source, containsString("/// The colour of the vehicle")); + } + + @Test + void enumVariantDescriptionsAppearAsDocComments() throws Exception + { + final String source = readGeneratedFile("colour.rs"); + assertThat(source, containsString("/// Red colour")); + assertThat(source, containsString("/// Green colour")); + assertThat(source, containsString("/// Blue colour")); + } + + @Test + void bitsetTypeDescriptionAppearsAsDocComment() throws Exception + { + final String source = readGeneratedFile("features.rs"); + assertThat(source, containsString("/// Optional features fitted to the vehicle")); + } + + @Test + void bitsetChoiceDescriptionsAppearAsDocComments() throws Exception + { + final String source = readGeneratedFile("features.rs"); + assertThat(source, containsString("/// Panoramic sun roof")); + assertThat(source, containsString("/// Sports handling pack")); + } + + @Test + void compositeDescriptionAppearsAsModuleDocComment() throws Exception + { + final String source = readGeneratedFile("engine_codec.rs"); + assertThat(source, containsString("//! Internal combustion engine specification")); + } + + @Test + void primitiveFieldDescriptionAppearsInDocComment() throws Exception + { + final String source = readGeneratedFile("vehicle_codec.rs"); + assertThat(source, containsString("/// - description: Unique serial number of the vehicle")); + } + + @Test + void enumFieldDescriptionAppearsInDocComment() throws Exception + { + final String source = readGeneratedFile("vehicle_codec.rs"); + assertThat(source, containsString("/// - description: Exterior colour of the vehicle")); + } + + @Test + void bitsetFieldDescriptionAppearsInDocComment() throws Exception + { + final String source = readGeneratedFile("vehicle_codec.rs"); + assertThat(source, containsString("/// - description: Bitset of optional features fitted")); + } + + @Test + void compositeFieldDescriptionAppearsInDocComment() throws Exception + { + final String source = readGeneratedFile("vehicle_codec.rs"); + assertThat(source, containsString("/// - description: Engine specification composite")); + } + + @Test + void groupDescriptionAppearsOnEncoderAndDecoder() throws Exception + { + final String source = readGeneratedFile("vehicle_codec.rs"); + assertThat(source, containsString( + "/// GROUP ENCODER (id=5, description='Passengers currently in the vehicle')")); + assertThat(source, containsString( + "/// GROUP DECODER (id=5, description='Passengers currently in the vehicle')")); + } + + @Test + void groupFieldDescriptionAppearsInDocComment() throws Exception + { + final String source = readGeneratedFile("vehicle_codec.rs"); + assertThat(source, containsString("/// - description: Age of the passenger in years")); + } + + @Test + void varDataDescriptionAppearsInDocComment() throws Exception + { + final String source = readGeneratedFile("vehicle_codec.rs"); + assertThat(source, containsString("/// - description: Full model name of the vehicle")); + } + + @Test + void generatorSucceedsAndProducesNoDescriptionCommentsWhenSchemaHasNoDescriptions() throws Exception + { + try (InputStream in = Tests.getLocalResource("rust-no-description-test-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + final RustOutputManager outputManager = new RustOutputManager( + tempDir.toString(), ir.applicableNamespace()); + final RustGenerator generator = new RustGenerator(ir, "0.1.0", outputManager); + + assertDoesNotThrow(generator::generate); + + final Path srcDir = tempDir.resolve("no_description_test").resolve("src"); + final String enumSource = Files.readString(srcDir.resolve("colour.rs")); + final String bitsetSource = Files.readString(srcDir.resolve("features.rs")); + final String compositeSource = Files.readString(srcDir.resolve("engine_codec.rs")); + final String messageSource = Files.readString(srcDir.resolve("vehicle_codec.rs")); + + assertThat(enumSource, not(containsString("/// -"))); + assertThat(bitsetSource, not(containsString("/// -"))); + assertThat(compositeSource, not(containsString("//!"))); + assertThat(messageSource, not(containsString("/// - description:"))); + } + } + + private String readGeneratedFile(final String fileName) throws Exception + { + return Files.readString(generatedSrcDir.resolve(fileName)); + } +} diff --git a/sbe-tool/src/test/resources/rust-description-test-schema.xml b/sbe-tool/src/test/resources/rust-description-test-schema.xml new file mode 100644 index 0000000000..2b3c32d0fe --- /dev/null +++ b/sbe-tool/src/test/resources/rust-description-test-schema.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + 2 + + + 0 + 1 + + + + + + + + + + + + + diff --git a/sbe-tool/src/test/resources/rust-no-description-test-schema.xml b/sbe-tool/src/test/resources/rust-no-description-test-schema.xml new file mode 100644 index 0000000000..e445474b1a --- /dev/null +++ b/sbe-tool/src/test/resources/rust-no-description-test-schema.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + 2 + + + 0 + 1 + + + + + + + + + + + + + From c386066955329291cd79d5d2ce1d38ea058e5cae Mon Sep 17 00:00:00 2001 From: Nikolay Zdravkov Date: Tue, 2 Jun 2026 17:46:36 +0300 Subject: [PATCH 1558/1594] refactor: seal PrimitiveValue and PrimitiveType, make ThrowHelper static --- csharp/sbe-dll/PrimitiveType.cs | 2 +- csharp/sbe-dll/PrimitiveValue.cs | 27 +++++++++++---------------- csharp/sbe-dll/ThrowHelper.cs | 2 +- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/csharp/sbe-dll/PrimitiveType.cs b/csharp/sbe-dll/PrimitiveType.cs index d0d183eabc..3e54de6d54 100644 --- a/csharp/sbe-dll/PrimitiveType.cs +++ b/csharp/sbe-dll/PrimitiveType.cs @@ -71,7 +71,7 @@ /// /// /// - public class PrimitiveType + public sealed class PrimitiveType { ///

        /// Primitive type representation for SBE type CHAR diff --git a/csharp/sbe-dll/PrimitiveValue.cs b/csharp/sbe-dll/PrimitiveValue.cs index a579baa158..39be34975c 100644 --- a/csharp/sbe-dll/PrimitiveValue.cs +++ b/csharp/sbe-dll/PrimitiveValue.cs @@ -74,7 +74,7 @@ namespace Org.SbeTool.Sbe.Dll /// /// /// - public class PrimitiveValue + public sealed class PrimitiveValue { private enum Representation { @@ -485,26 +485,21 @@ public override string ToString() /// equivalence of values public override bool Equals(object value) { - if (null != value && this.GetType().Equals(value.GetType())) + if (value is PrimitiveValue rhs && _representation == rhs._representation) { - var rhs = (PrimitiveValue) value; - - if (_representation == rhs._representation) + switch (_representation) { - switch (_representation) - { - case Representation.Long: - return _longValue == rhs._longValue; + case Representation.Long: + return _longValue == rhs._longValue; - case Representation.ULong: - return _unsignedLongValue == rhs._unsignedLongValue; + case Representation.ULong: + return _unsignedLongValue == rhs._unsignedLongValue; - case Representation.Double: - return BitConverter.DoubleToInt64Bits(_doubleValue) == BitConverter.DoubleToInt64Bits(rhs._doubleValue); + case Representation.Double: + return BitConverter.DoubleToInt64Bits(_doubleValue) == BitConverter.DoubleToInt64Bits(rhs._doubleValue); - case Representation.ByteArray: - return _byteArrayValue.SequenceEqual(rhs._byteArrayValue); - } + case Representation.ByteArray: + return _byteArrayValue.SequenceEqual(rhs._byteArrayValue); } } diff --git a/csharp/sbe-dll/ThrowHelper.cs b/csharp/sbe-dll/ThrowHelper.cs index 30ca008c9c..9c1ffe4630 100644 --- a/csharp/sbe-dll/ThrowHelper.cs +++ b/csharp/sbe-dll/ThrowHelper.cs @@ -6,7 +6,7 @@ namespace Org.SbeTool.Sbe.Dll /// Helper class that provides non-returning methods that throw common exception /// from the generated C# code /// - public class ThrowHelper + public static class ThrowHelper { /// /// Throws a when the "count" parameter is out of range From e1e156934f9ab9357a3b5b3690d225685f997919 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 4 Jun 2026 13:19:07 +0200 Subject: [PATCH 1559/1594] [Java] Upgrade to `Shadow` 9.4.2. --- CHANGELOG.adoc | 1 + gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 34004f61dd..5b4358588d 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -4,6 +4,7 @@ * Upgrade to `Gradle` 9.5.1. * Upgrade to `JUnit` 6.1.0. +* Upgrade to `Shadow` 9.4.2. == 1.38.1 (2026-04-28) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1f37604fc3..54618c5f17 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20251224" junit = "6.1.0" mockito = "5.23.0" plexus = "3.3.0" -shadow = "9.4.1" +shadow = "9.4.2" versions = "0.54.0" [libraries] From b9cf706d10b2c4e35f4331030303b8cc1d976e69 Mon Sep 17 00:00:00 2001 From: sunlei Date: Fri, 12 Jun 2026 22:04:21 +0800 Subject: [PATCH 1560/1594] [Rust] Inline generated header methods (#1110) --- .../uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java index 58416f17bd..6e1b317615 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/MessageCoderDef.java @@ -130,6 +130,7 @@ public SubGroup addSubGroup(final String name, final int level, final Token grou void appendMessageHeaderEncoderFn(final Appendable out) throws IOException { + indent(out, 2, "#[inline]\n"); indent(out, 2, "pub fn header(self, offset: usize) -> MessageHeaderEncoder {\n"); indent(out, 3, "let mut header = MessageHeaderEncoder::default().wrap(self, offset);\n"); indent(out, 3, "header.block_length(SBE_BLOCK_LENGTH);\n"); @@ -142,6 +143,7 @@ void appendMessageHeaderEncoderFn(final Appendable out) throws IOException void appendMessageHeaderDecoderFn(final Appendable out) throws IOException { + indent(out, 2, "#[inline]\n"); indent(out, 2, "pub fn header(self, mut header: MessageHeaderDecoder>, offset: usize) -> Self {\n"); indent(out, 3, "debug_assert_eq!(SBE_TEMPLATE_ID, header.template_id());\n"); indent(out, 3, "let acting_block_length = header.block_length();\n"); From 17bb431112c44c122bc3d5dde64245f983dbcf4c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 12 Jun 2026 16:10:36 +0200 Subject: [PATCH 1561/1594] [Java] Upgrade to `jqwik` 1.10.1. --- CHANGELOG.adoc | 3 ++- gradle/libs.versions.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 5b4358588d..0060e94a3a 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -5,6 +5,7 @@ * Upgrade to `Gradle` 9.5.1. * Upgrade to `JUnit` 6.1.0. * Upgrade to `Shadow` 9.4.2. +* Upgrade to `jqwik` 1.10.1. == 1.38.1 (2026-04-28) @@ -13,7 +14,7 @@ == 1.38.0 (2026-04-22) -* **[Rust]** Recursively call nullify_optional_fields on composites +* **[Rust]** Recursively call nullify_optional_fields on composites. * **[Rust]** Generate setters for optional enum fields too. * **[Rust]** Generated encoders now produce fluent interface. (https://github.com/aeron-io/simple-binary-encoding/pull/1097[#1097]) * **[Rust]** Updated some function to `const`. (https://github.com/aeron-io/simple-binary-encoding/pull/1098[#1098]) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 54618c5f17..482bafd9ea 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" httpcore = "4.4.14" -jqwik = "1.9.3" +jqwik = "1.10.1" jmh = "1.37" json = "20251224" junit = "6.1.0" From 4b0ef7702a9e1b24d9bf54dcfb2071c7293f1263 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 12 Jun 2026 16:11:00 +0200 Subject: [PATCH 1562/1594] [Java] Upgrade to `json` 20260522. --- CHANGELOG.adoc | 1 + gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 0060e94a3a..cc7f956585 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -6,6 +6,7 @@ * Upgrade to `JUnit` 6.1.0. * Upgrade to `Shadow` 9.4.2. * Upgrade to `jqwik` 1.10.1. +* Upgrade to `json` 20260522. == 1.38.1 (2026-04-28) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 482bafd9ea..d6ffc9f7ac 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ hamcrest = "3.0" httpcore = "4.4.14" jqwik = "1.10.1" jmh = "1.37" -json = "20251224" +json = "20260522" junit = "6.1.0" mockito = "5.23.0" plexus = "3.3.0" From effad488929942455590f9f5bedf598cab427550 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 12 Jun 2026 16:15:18 +0200 Subject: [PATCH 1563/1594] [Doc] Release notes. --- CHANGELOG.adoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index cc7f956585..f4b9ddd8a1 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -2,6 +2,9 @@ == 1.39.0 (unreleased) +* **[Rust]** Inline generated header methods. (https://github.com/aeron-io/simple-binary-encoding/pull/1110[#1110]) +* **[Rust]** Add element descriptions to comments. +* **[C#]** Seal `PrimitiveValue` and `PrimitiveType`, make `ThrowHelper` static. (https://github.com/aeron-io/simple-binary-encoding/pull/1109[#1109]) * Upgrade to `Gradle` 9.5.1. * Upgrade to `JUnit` 6.1.0. * Upgrade to `Shadow` 9.4.2. @@ -25,7 +28,6 @@ * Upgrade to `CMake` 4.3.0. * Upgrade to `Shadow` 9.4.1. * Upgrade to `Gradle` 9.4.1. -* Upgrade to `Shadow` 9.4.0. * Upgrade to `Mockito` 5.23.0. == 1.37.1 (2026-01-13) From b48c2700a7a8315f4fb20dd268bce002834d29c3 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Jun 2026 12:15:05 +0200 Subject: [PATCH 1564/1594] [Java] Upgrade to `Gradle` 9.6.0. --- CHANGELOG.adoc | 2 +- build.gradle | 19 ++++++++----------- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 4 ++-- gradlew.bat | 4 ++-- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index f4b9ddd8a1..e73ab0ef10 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -5,7 +5,7 @@ * **[Rust]** Inline generated header methods. (https://github.com/aeron-io/simple-binary-encoding/pull/1110[#1110]) * **[Rust]** Add element descriptions to comments. * **[C#]** Seal `PrimitiveValue` and `PrimitiveType`, make `ThrowHelper` static. (https://github.com/aeron-io/simple-binary-encoding/pull/1109[#1109]) -* Upgrade to `Gradle` 9.5.1. +* Upgrade to `Gradle` 9.6.0. * Upgrade to `JUnit` 6.1.0. * Upgrade to `Shadow` 9.4.2. * Upgrade to `jqwik` 1.10.1. diff --git a/build.gradle b/build.gradle index df2554c746..9a5a9b57d8 100644 --- a/build.gradle +++ b/build.gradle @@ -67,17 +67,14 @@ def getConfigProperty(final String projectPropertyName, final String envVarName) return value ? value : null } -ext { - isReleaseVersion = !sbeVersion.endsWith('-SNAPSHOT') - - sonatypeCentralPortalReleasesRepoUrl = 'https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/' - sonatypeCentralPortalSnapshotsRepoUrl = 'https://central.sonatype.com/repository/maven-snapshots/' - sonatypeCentralPortalUsername = getConfigProperty('sonatypeCentralPortalUsername', 'SONATYPE_CENTRAL_PORTAL_USERNAME') - sonatypeCentralPortalPassword = getConfigProperty('sonatypeCentralPortalPassword', 'SONATYPE_CENTRAL_PORTAL_PASSWORD') - - signingKey = getConfigProperty('signingKey', 'SIGNING_GPG_SECRET_KEY') // NOTE: ASCII armored secret key - signingPassword = getConfigProperty('signingPassword', 'SIGNING_GPG_PASSWORD') // NOTE: Plain text -} +def isReleaseVersion = !sbeVersion.endsWith('-SNAPSHOT') +def sonatypeCentralPortalReleasesRepoUrl = 'https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/' +def sonatypeCentralPortalSnapshotsRepoUrl = 'https://central.sonatype.com/repository/maven-snapshots/' +def sonatypeCentralPortalUsername = getConfigProperty('sonatypeCentralPortalUsername', 'SONATYPE_CENTRAL_PORTAL_USERNAME') +def sonatypeCentralPortalPassword = getConfigProperty('sonatypeCentralPortalPassword', 'SONATYPE_CENTRAL_PORTAL_PASSWORD') +def signingKey = getConfigProperty('signingKey', 'SIGNING_GPG_SECRET_KEY') // NOTE: ASCII armored secret key +def signingPassword = getConfigProperty('signingPassword', 'SIGNING_GPG_PASSWORD') // NOTE: Plain text +def libs = rootProject.libs def projectPom = { name = 'sbe' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e74c8700b2..11cae1e003 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-all.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/gradlew b/gradlew index b9bb139f79..249efbb032 100755 --- a/gradlew +++ b/gradlew @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: diff --git a/gradlew.bat b/gradlew.bat index 24c62d56f2..a51ec4f588 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -19,7 +19,7 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## @@ -72,7 +72,7 @@ echo location of your Java installation. 1>&2 -@rem Execute Gradle +@rem Execute gradlew @rem endlocal doesn't take effect until after the line is parsed and variables are expanded @rem which allows us to clear the local environment before executing the java command endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel From 1a8ed757cd4d6d2e7a6c355de49aec350b17e3ae Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Jun 2026 10:02:04 +0200 Subject: [PATCH 1565/1594] [Java] Upgrade to `Gradle` 9.6.1. --- CHANGELOG.adoc | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index e73ab0ef10..93549d2c56 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -5,7 +5,7 @@ * **[Rust]** Inline generated header methods. (https://github.com/aeron-io/simple-binary-encoding/pull/1110[#1110]) * **[Rust]** Add element descriptions to comments. * **[C#]** Seal `PrimitiveValue` and `PrimitiveType`, make `ThrowHelper` static. (https://github.com/aeron-io/simple-binary-encoding/pull/1109[#1109]) -* Upgrade to `Gradle` 9.6.0. +* Upgrade to `Gradle` 9.6.1. * Upgrade to `JUnit` 6.1.0. * Upgrade to `Shadow` 9.4.2. * Upgrade to `jqwik` 1.10.1. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 11cae1e003..8747320212 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-all.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From 5e62b099f57e5cde3690d34144cc789ae46a52a4 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Jun 2026 10:02:23 +0200 Subject: [PATCH 1566/1594] [Java] Upgrade to `JUint` 6.1.1. --- CHANGELOG.adoc | 2 +- gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 93549d2c56..35c3eff295 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -6,7 +6,7 @@ * **[Rust]** Add element descriptions to comments. * **[C#]** Seal `PrimitiveValue` and `PrimitiveType`, make `ThrowHelper` static. (https://github.com/aeron-io/simple-binary-encoding/pull/1109[#1109]) * Upgrade to `Gradle` 9.6.1. -* Upgrade to `JUnit` 6.1.0. +* Upgrade to `JUnit` 6.1.1. * Upgrade to `Shadow` 9.4.2. * Upgrade to `jqwik` 1.10.1. * Upgrade to `json` 20260522. diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d6ffc9f7ac..706e8a1c2b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ httpcore = "4.4.14" jqwik = "1.10.1" jmh = "1.37" json = "20260522" -junit = "6.1.0" +junit = "6.1.1" mockito = "5.23.0" plexus = "3.3.0" shadow = "9.4.2" From 722d4e32a20e4350137c0e69f5e87e8ac8ad0a6b Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Jun 2026 10:02:45 +0200 Subject: [PATCH 1567/1594] [Java] Upgrade to `Shadow` 9.4.3. --- CHANGELOG.adoc | 2 +- gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 35c3eff295..2be155bbef 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -7,7 +7,7 @@ * **[C#]** Seal `PrimitiveValue` and `PrimitiveType`, make `ThrowHelper` static. (https://github.com/aeron-io/simple-binary-encoding/pull/1109[#1109]) * Upgrade to `Gradle` 9.6.1. * Upgrade to `JUnit` 6.1.1. -* Upgrade to `Shadow` 9.4.2. +* Upgrade to `Shadow` 9.4.3. * Upgrade to `jqwik` 1.10.1. * Upgrade to `json` 20260522. diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 706e8a1c2b..ee44af3ea9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20260522" junit = "6.1.1" mockito = "5.23.0" plexus = "3.3.0" -shadow = "9.4.2" +shadow = "9.4.3" versions = "0.54.0" [libraries] From 625ccbbce4e4b9ec1b275aeb8060c84f1ee1baac Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jul 2026 15:30:28 +0200 Subject: [PATCH 1568/1594] [Java] Upgrade to `Agrona` 2.5.0. --- CHANGELOG.adoc | 23 ++++++++++++----------- gradle/libs.versions.toml | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 2be155bbef..f986ef19dd 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -5,16 +5,17 @@ * **[Rust]** Inline generated header methods. (https://github.com/aeron-io/simple-binary-encoding/pull/1110[#1110]) * **[Rust]** Add element descriptions to comments. * **[C#]** Seal `PrimitiveValue` and `PrimitiveType`, make `ThrowHelper` static. (https://github.com/aeron-io/simple-binary-encoding/pull/1109[#1109]) -* Upgrade to `Gradle` 9.6.1. -* Upgrade to `JUnit` 6.1.1. -* Upgrade to `Shadow` 9.4.3. -* Upgrade to `jqwik` 1.10.1. -* Upgrade to `json` 20260522. +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.5.0[Agrona 2.5.0]. +* **[Java]** Upgrade to `Gradle` 9.6.1. +* **[Java]** Upgrade to `JUnit` 6.1.1. +* **[Java]** Upgrade to `Shadow` 9.4.3. +* **[Java]** Upgrade to `jqwik` 1.10.1. +* **[Java]** Upgrade to `json` 20260522. == 1.38.1 (2026-04-28) -* Upgrade to `Agrona` 2.4.1. -* Upgrade to `Versions` 0.54.0. +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.4.1[Agrona 2.4.1]. +* **[Java]** Upgrade to `Versions` 0.54.0. == 1.38.0 (2026-04-22) @@ -25,10 +26,10 @@ * **[Rust]** Updated generator to correctly limit length of var data written. (https://github.com/aeron-io/simple-binary-encoding/pull/1096[#1096]) * **[C++]** Protect against a segfault when dealing with empty `std::span` and `std::view`. * **[C++]** mark a generated function SBE_CONSTEXPR (#1055) (#1083) -* Upgrade to `CMake` 4.3.0. -* Upgrade to `Shadow` 9.4.1. -* Upgrade to `Gradle` 9.4.1. -* Upgrade to `Mockito` 5.23.0. +* **[Java]** Upgrade to `CMake` 4.3.0. +* **[Java]** Upgrade to `Shadow` 9.4.1. +* **[Java]** Upgrade to `Gradle` 9.4.1. +* **[Java]** Upgrade to `Mockito` 5.23.0. == 1.37.1 (2026-01-13) * **[Java]** Ensure Java code generation for precedence checks always produces the same code without re-orderings. diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ee44af3ea9..da86c24cd3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.4.1" +agrona = "2.5.0" checkstyle = "12.3.1" commons-codec = "1.15" commons-lang3 = "3.8.1" From e773b57cac6b2008ce30dd219a33de49766c6013 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jul 2026 15:32:54 +0200 Subject: [PATCH 1569/1594] 1.39.0 released. --- CHANGELOG.adoc | 2 +- version.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index f986ef19dd..195b640ec8 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,6 +1,6 @@ = Changelog -== 1.39.0 (unreleased) +== 1.39.0 (2026-07-03) * **[Rust]** Inline generated header methods. (https://github.com/aeron-io/simple-binary-encoding/pull/1110[#1110]) * **[Rust]** Add element descriptions to comments. diff --git a/version.txt b/version.txt index 40c214a46c..5edffce6d5 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.39.0-SNAPSHOT +1.39.0 From 4f4deee2463c102a7212bd228366a1b601950679 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 3 Jul 2026 15:33:08 +0200 Subject: [PATCH 1570/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 5edffce6d5..69670a655a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.39.0 +1.40.0-SNAPSHOT From f40cdde6b60745cee572f688ac786cb90074e772 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 6 Jul 2026 11:09:41 +0200 Subject: [PATCH 1571/1594] [Java] Upgrade to `Shadow` 9.5.0. --- CHANGELOG.adoc | 4 ++++ gradle/libs.versions.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 195b640ec8..03b9f3f2de 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,5 +1,9 @@ = Changelog +== 1.40.0 (unreleased) + +* **[Java]** Upgrade to `Shadow` 9.5.0. + == 1.39.0 (2026-07-03) * **[Rust]** Inline generated header methods. (https://github.com/aeron-io/simple-binary-encoding/pull/1110[#1110]) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index da86c24cd3..ae2ec8e9d8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20260522" junit = "6.1.1" mockito = "5.23.0" plexus = "3.3.0" -shadow = "9.4.3" +shadow = "9.5.0" versions = "0.54.0" [libraries] From 15f2b9c2380b9814d1d0f5ec2ef42e6baf01d78e Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 6 Jul 2026 16:30:53 +0200 Subject: [PATCH 1572/1594] [Java] Upgrade to `Shadow` 9.5.1. --- CHANGELOG.adoc | 2 +- gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 03b9f3f2de..01b178c5da 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -2,7 +2,7 @@ == 1.40.0 (unreleased) -* **[Java]** Upgrade to `Shadow` 9.5.0. +* **[Java]** Upgrade to `Shadow` 9.5.1. == 1.39.0 (2026-07-03) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ae2ec8e9d8..273db3db0f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20260522" junit = "6.1.1" mockito = "5.23.0" plexus = "3.3.0" -shadow = "9.5.0" +shadow = "9.5.1" versions = "0.54.0" [libraries] From 10dd521cb195ba60e960c84997a3df41961725fb Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 9 Jul 2026 13:15:00 +0200 Subject: [PATCH 1573/1594] [Java] Fix links to `javadoc.io` to avoid build warnings/failures. --- README.md | 2 +- build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bef8bbff07..bdb0e51ba5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Simple Binary Encoding (SBE) ============================ -[![Javadocs](https://www.javadoc.io/badge/uk.co.real-logic/sbe-tool.svg)](https://www.javadoc.io/doc/uk.co.real-logic/sbe-tool) +[![Javadocs](https://www.javadoc.io/badge/uk.co.real-logic/sbe-tool.svg)](https://www.javadoc.io/static/uk.co.real-logic/sbe-tool) [![GitHub](https://img.shields.io/github/license/aeron-io/simple-binary-encoding.svg)](https://github.com/aeron-io/simple-binary-encoding/blob/master/LICENSE) [![Actions Status](https://github.com/aeron-io/simple-binary-encoding/workflows/Continuous%20Integration/badge.svg)](https://github.com/aeron-io/simple-binary-encoding/actions) diff --git a/build.gradle b/build.gradle index 9a5a9b57d8..4d18230ac7 100644 --- a/build.gradle +++ b/build.gradle @@ -206,7 +206,7 @@ subprojects { options.encoding = 'UTF-8' options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' - options.links("https://www.javadoc.io/doc/org.agrona/agrona/${libs.versions.agrona.get()}/") + options.links("https://www.javadoc.io/static/org.agrona/agrona/${libs.versions.agrona.get()}/") if (isEarlyAccessJavaVersion) { options.links("https://download.java.net/java/early_access/jdk${buildJavaVersion}/docs/api/") } From 9e48af34bfdefb502f66244f40fe8ef5fb82d051 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 16 Jul 2026 15:15:55 +0200 Subject: [PATCH 1574/1594] [Java] Upgrade to `Shadow` 9.6.0. --- CHANGELOG.adoc | 2 +- gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 01b178c5da..c5e9614fb1 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -2,7 +2,7 @@ == 1.40.0 (unreleased) -* **[Java]** Upgrade to `Shadow` 9.5.1. +* **[Java]** Upgrade to `Shadow` 9.6.0. == 1.39.0 (2026-07-03) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 273db3db0f..06d742df4f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20260522" junit = "6.1.1" mockito = "5.23.0" plexus = "3.3.0" -shadow = "9.5.1" +shadow = "9.6.0" versions = "0.54.0" [libraries] From 71c10ebc5a701c35c80e5b23d681248e84072dee Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 16 Jul 2026 15:16:27 +0200 Subject: [PATCH 1575/1594] [Java] Apply same `Shadow` config across all projects. --- build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle b/build.gradle index 4d18230ac7..e63452a9ef 100644 --- a/build.gradle +++ b/build.gradle @@ -428,6 +428,12 @@ project(':sbe-all') { 'Implementation-Vendor': 'Adaptive Financial Consulting Limited', 'Automatic-Module-Name': 'uk.co.real_logic.sbe.all' ) + + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + mergeServiceFiles() + filesMatching('META-INF/services/**') { + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } } jar.finalizedBy shadowJar From 4d9fb7a3b6031a594e7c33da2e791848b8c86dfa Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 16 Jul 2026 15:17:19 +0200 Subject: [PATCH 1576/1594] [Java] Upgrade to `JUnit` 6.1.2. --- CHANGELOG.adoc | 1 + gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index c5e9614fb1..4707ae6a8a 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -2,6 +2,7 @@ == 1.40.0 (unreleased) +* **[Java]** Upgrade to `JUnit` 6.1.2. * **[Java]** Upgrade to `Shadow` 9.6.0. == 1.39.0 (2026-07-03) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 06d742df4f..055ffc156c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ httpcore = "4.4.14" jqwik = "1.10.1" jmh = "1.37" json = "20260522" -junit = "6.1.1" +junit = "6.1.2" mockito = "5.23.0" plexus = "3.3.0" shadow = "9.6.0" From 44b04492d67aff2cd1fab19da77f365860b1e8c8 Mon Sep 17 00:00:00 2001 From: "amir.langer" Date: Mon, 27 Jul 2026 09:23:05 +0100 Subject: [PATCH 1577/1594] New agreed Aeron checkstyle and fixes (MissingOverride and NewLineAtEndOfFile). --- config/checkstyle/checkstyle.xml | 11 ++++++++++- .../main/java/uk/co/real_logic/sbe/package-info.java | 2 +- .../real_logic/sbe/examples/ExampleTokenListener.java | 11 +++++++++++ .../uk/co/real_logic/sbe/examples/package-info.java | 2 +- .../uk/co/real_logic/sbe/codec/java/package-info.java | 2 +- .../sbe/generation/TargetCodeGeneratorLoader.java | 5 +++++ .../uk/co/real_logic/sbe/generation/c/CGenerator.java | 1 + .../co/real_logic/sbe/generation/c/package-info.java | 2 +- .../sbe/generation/common/FieldPrecedenceModel.java | 3 +++ .../sbe/generation/cpp/CppDtoGenerator.java | 1 + .../uk/co/real_logic/sbe/generation/cpp/CppDtos.java | 1 + .../real_logic/sbe/generation/cpp/CppGenerator.java | 1 + .../real_logic/sbe/generation/cpp/package-info.java | 2 +- .../co/real_logic/sbe/generation/csharp/CSharp.java | 1 + .../sbe/generation/csharp/CSharpDtoGenerator.java | 1 + .../real_logic/sbe/generation/csharp/CSharpDtos.java | 1 + .../sbe/generation/csharp/CSharpGenerator.java | 1 + .../sbe/generation/csharp/package-info.java | 2 +- .../golang/flyweight/GolangFlyweightGenerator.java | 1 + .../sbe/generation/golang/package-info.java | 2 +- .../sbe/generation/golang/struct/GolangGenerator.java | 1 + .../sbe/generation/java/JavaDtoGenerator.java | 1 + .../co/real_logic/sbe/generation/java/JavaDtos.java | 1 + .../real_logic/sbe/generation/java/JavaGenerator.java | 1 + .../sbe/generation/java/JavaOutputManager.java | 2 ++ .../co/real_logic/sbe/generation/java/JavaUtil.java | 1 + .../real_logic/sbe/generation/java/package-info.java | 2 +- .../uk/co/real_logic/sbe/generation/package-info.java | 2 +- .../real_logic/sbe/generation/rust/package-info.java | 2 +- .../main/java/uk/co/real_logic/sbe/ir/Encoding.java | 1 + .../main/java/uk/co/real_logic/sbe/ir/IrDecoder.java | 1 + .../main/java/uk/co/real_logic/sbe/ir/IrEncoder.java | 1 + .../src/main/java/uk/co/real_logic/sbe/ir/Token.java | 1 + .../java/uk/co/real_logic/sbe/ir/package-info.java | 2 +- .../uk/co/real_logic/sbe/json/JsonTokenListener.java | 11 +++++++++++ .../java/uk/co/real_logic/sbe/json/package-info.java | 2 +- .../co/real_logic/sbe/otf/AbstractTokenListener.java | 11 +++++++++++ .../java/uk/co/real_logic/sbe/otf/package-info.java | 2 +- .../main/java/uk/co/real_logic/sbe/package-info.java | 2 +- .../java/uk/co/real_logic/sbe/xml/CompositeType.java | 2 ++ .../uk/co/real_logic/sbe/xml/EncodedDataType.java | 1 + .../main/java/uk/co/real_logic/sbe/xml/EnumType.java | 3 +++ .../java/uk/co/real_logic/sbe/xml/ErrorHandler.java | 1 + .../src/main/java/uk/co/real_logic/sbe/xml/Field.java | 1 + .../main/java/uk/co/real_logic/sbe/xml/Message.java | 1 + .../real_logic/sbe/xml/SchemaTransformerFactory.java | 1 + .../main/java/uk/co/real_logic/sbe/xml/SetType.java | 3 +++ .../sbe/xml/SinceVersionSchemaTransformer.java | 1 + .../java/uk/co/real_logic/sbe/xml/package-info.java | 2 +- .../uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java | 2 +- .../co/real_logic/sbe/xml/RelativeXIncludeTest.java | 2 +- .../sbe/xml/SchemaTransformerFactoryTest.java | 2 +- 52 files changed, 103 insertions(+), 19 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index a0ad3423a9..355c4ee478 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -25,7 +25,7 @@ - + @@ -33,12 +33,16 @@ + + + + @@ -194,5 +198,10 @@ + + + + + diff --git a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java index 88ae5ee4ba..503fb61954 100644 --- a/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java +++ b/sbe-benchmarks/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -16,4 +16,4 @@ /** * Basic benchmarks for encoding and decoding of messages with SBE. */ -package uk.co.real_logic.sbe; \ No newline at end of file +package uk.co.real_logic.sbe; diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java index 51302141d0..d5ff41086d 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java @@ -52,6 +52,7 @@ public ExampleTokenListener(final PrintWriter out) /** * {@inheritDoc} */ + @Override public void onBeginMessage(final Token token) { namedScope.push(token.name() + "."); @@ -60,6 +61,7 @@ public void onBeginMessage(final Token token) /** * {@inheritDoc} */ + @Override public void onEndMessage(final Token token) { namedScope.pop(); @@ -68,6 +70,7 @@ public void onEndMessage(final Token token) /** * {@inheritDoc} */ + @Override public void onEncoding( final Token fieldToken, final DirectBuffer buffer, @@ -87,6 +90,7 @@ public void onEncoding( /** * {@inheritDoc} */ + @Override public void onEnum( final Token fieldToken, final DirectBuffer buffer, @@ -129,6 +133,7 @@ public void onEnum( /** * {@inheritDoc} */ + @Override public void onBitSet( final Token fieldToken, final DirectBuffer buffer, @@ -161,6 +166,7 @@ public void onBitSet( /** * {@inheritDoc} */ + @Override public void onBeginComposite( final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { @@ -171,6 +177,7 @@ public void onBeginComposite( /** * {@inheritDoc} */ + @Override public void onEndComposite(final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { --compositeLevel; @@ -180,6 +187,7 @@ public void onEndComposite(final Token fieldToken, final List tokens, fin /** * {@inheritDoc} */ + @Override public void onGroupHeader(final Token token, final int numInGroup) { printScope(); @@ -192,6 +200,7 @@ public void onGroupHeader(final Token token, final int numInGroup) /** * {@inheritDoc} */ + @Override public void onBeginGroup(final Token token, final int groupIndex, final int numInGroup) { namedScope.push(token.name() + "."); @@ -200,6 +209,7 @@ public void onBeginGroup(final Token token, final int groupIndex, final int numI /** * {@inheritDoc} */ + @Override public void onEndGroup(final Token token, final int groupIndex, final int numInGroup) { namedScope.pop(); @@ -208,6 +218,7 @@ public void onEndGroup(final Token token, final int groupIndex, final int numInG /** * {@inheritDoc} */ + @Override public void onVarData( final Token fieldToken, final DirectBuffer buffer, diff --git a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java index 1924360927..b1fc7c8247 100644 --- a/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java +++ b/sbe-samples/src/main/java/uk/co/real_logic/sbe/examples/package-info.java @@ -16,4 +16,4 @@ /** * Samples showing usage of generated codecs and On-The-Fly (OTF) decoding. */ -package uk.co.real_logic.sbe.examples; \ No newline at end of file +package uk.co.real_logic.sbe.examples; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java index a97ba65c46..8c0e70a225 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/codec/java/package-info.java @@ -16,4 +16,4 @@ /** * Annotation for marking the order of groups in generated code to provide metadata. */ -package uk.co.real_logic.sbe.codec.java; \ No newline at end of file +package uk.co.real_logic.sbe.codec.java; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java index db33966a89..4a119a3d6a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/TargetCodeGeneratorLoader.java @@ -48,6 +48,7 @@ public enum TargetCodeGeneratorLoader implements TargetCodeGenerator /** * {@inheritDoc} */ + @Override public CodeGenerator newInstance(final Ir ir, final String outputDir) { final JavaOutputManager outputManager = new JavaOutputManager(outputDir, ir.applicableNamespace()); @@ -88,6 +89,7 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) /** * {@inheritDoc} */ + @Override public CodeGenerator newInstance(final Ir ir, final String outputDir) { return new CGenerator(ir, new COutputManager(outputDir, ir.applicableNamespace())); @@ -102,6 +104,7 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) /** * {@inheritDoc} */ + @Override public CodeGenerator newInstance(final Ir ir, final String outputDir) { final NamespaceOutputManager outputManager = new NamespaceOutputManager( @@ -140,6 +143,7 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) /** * {@inheritDoc} */ + @Override public CodeGenerator newInstance(final Ir ir, final String outputDir) { if ("true".equals(System.getProperty(GO_GENERATE_FLYWEIGHTS))) @@ -166,6 +170,7 @@ public CodeGenerator newInstance(final Ir ir, final String outputDir) /** * {@inheritDoc} */ + @Override public CodeGenerator newInstance(final Ir ir, final String outputDir) { return new RustGenerator( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java index 427034515d..b6dd9639f3 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java @@ -125,6 +125,7 @@ List generateTypesToIncludes(final List tokens) /** * {@inheritDoc} */ + @Override public void generate() throws IOException { generateMessageHeaderStub(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java index 5cba823b2d..291771f60b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/package-info.java @@ -16,4 +16,4 @@ /** * Generation of codecs for the C programming language. */ -package uk.co.real_logic.sbe.generation.c; \ No newline at end of file +package uk.co.real_logic.sbe.generation.c; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java index e9c8dcc1f9..fc52813d89 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java @@ -616,6 +616,7 @@ public String name() /** * {@inheritDoc}. */ + @Override public int compareTo(final State other) { final int result = Integer.compare(number, other.number); @@ -629,6 +630,7 @@ public int compareTo(final State other) /** * {@inheritDoc} */ + @Override public String toString() { return "State{" + @@ -697,6 +699,7 @@ public String exampleCode() /** * {@inheritDoc} */ + @Override public String toString() { return "Transition{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java index 8aa13494ad..ca2d09f568 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtoGenerator.java @@ -94,6 +94,7 @@ private String[] fetchTypesPackageName(final Token token, final Ir ir) /** * {@inheritDoc} */ + @Override public void generate() throws IOException { namespaceByType.clear(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java index 1dde335d57..3cd8d2659b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppDtos.java @@ -29,6 +29,7 @@ public class CppDtos implements TargetCodeGenerator /** * {@inheritDoc} */ + @Override public CodeGenerator newInstance(final Ir ir, final String outputDir) { return new CppDtoGenerator(ir, false, new NamespaceOutputManager(outputDir, ir.applicableNamespace())); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 5d3762c274..f6dbcced9a 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -189,6 +189,7 @@ private List generateTypesToIncludes(final List tokens) /** * {@inheritDoc} */ + @Override public void generate() throws IOException { namespaceByType.clear(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java index 49a0229afc..4c5df2f938 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/package-info.java @@ -16,4 +16,4 @@ /** * Generation of codecs for the C++ programming language. */ -package uk.co.real_logic.sbe.generation.cpp; \ No newline at end of file +package uk.co.real_logic.sbe.generation.cpp; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java index 5125f79246..3be301705e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharp.java @@ -33,6 +33,7 @@ public class CSharp implements TargetCodeGenerator /** * {@inheritDoc} */ + @Override public CodeGenerator newInstance(final Ir ir, final String outputDir) { final boolean shouldSupportTypesPackageNames = Boolean.getBoolean(TYPES_PACKAGE_OVERRIDE); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java index ed55bae37b..0bfcb7763b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtoGenerator.java @@ -95,6 +95,7 @@ private String fetchTypesPackageName(final Token token, final Ir ir) /** * {@inheritDoc} */ + @Override public void generate() throws IOException { packageNameByTypes.clear(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java index ab5b591b48..ee526328b5 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpDtos.java @@ -30,6 +30,7 @@ public class CSharpDtos implements TargetCodeGenerator /** * {@inheritDoc} */ + @Override public CodeGenerator newInstance(final Ir ir, final String outputDir) { final boolean shouldSupportTypesPackageNames = Boolean.getBoolean(TYPES_PACKAGE_OVERRIDE); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index d3b063631a..414b68e2a9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -162,6 +162,7 @@ private String fetchTypesPackageName(final Token token, final Ir ir) /** * {@inheritDoc} */ + @Override public void generate() throws IOException { packageNameByTypes.clear(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java index 53c5a9418d..1adec5c7a8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/package-info.java @@ -16,4 +16,4 @@ /** * Generation of codecs for the C# programming language. */ -package uk.co.real_logic.sbe.generation.csharp; \ No newline at end of file +package uk.co.real_logic.sbe.generation.csharp; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java index 8b2d65ab62..30db48127e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java @@ -593,6 +593,7 @@ private void generateTypeStubs() throws IOException /** * {@inheritDoc} */ + @Override public void generate() throws IOException { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java index a11cc42072..5973b8464e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/package-info.java @@ -16,4 +16,4 @@ /** * Generation of codecs for the Go Lang programming language. */ -package uk.co.real_logic.sbe.generation.golang; \ No newline at end of file +package uk.co.real_logic.sbe.generation.golang; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java index d96f4c8e57..b0b33e5c7e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java @@ -146,6 +146,7 @@ public void generateMessageHeaderStub() throws IOException /** * {@inheritDoc} */ + @Override public void generate() throws IOException { // Add the Marshalling from the big or little endian diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java index d8a4d6f245..dc7ce730f1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtoGenerator.java @@ -100,6 +100,7 @@ private String fetchTypesPackageName(final Token token, final Ir ir) /** * {@inheritDoc} */ + @Override public void generate() throws IOException { generateDtosForTypes(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java index 852e6bdd04..a1df9d2e8b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaDtos.java @@ -30,6 +30,7 @@ public class JavaDtos implements TargetCodeGenerator /** * {@inheritDoc} */ + @Override public CodeGenerator newInstance(final Ir ir, final String outputDir) { return new JavaDtoGenerator( diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java index 4e48e9bd08..7c14607d6a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java @@ -250,6 +250,7 @@ private String registerTypesPackageName(final Token token, final Ir ir) /** * {@inheritDoc} */ + @Override public void generate() throws IOException { packageNameByTypes.clear(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java index 51817dc04c..029bccdfb6 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaOutputManager.java @@ -51,6 +51,7 @@ public JavaOutputManager(final String baseDirName, final String packageName) /** * {@inheritDoc} */ + @Override public void setPackageName(final String packageName) { actingPackageOutputManager = outputManagerByPackageName.get(packageName); @@ -69,6 +70,7 @@ private void resetPackage() /** * {@inheritDoc} */ + @Override public Writer createOutput(final String name) throws IOException { return new FilterWriter(actingPackageOutputManager.createOutput(name)) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java index e8e6808c01..680bc02c76 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaUtil.java @@ -69,6 +69,7 @@ void appendToGeneratedBuilder(final StringBuilder builder, final String indent) /** * {@inheritDoc} */ + @Override public String toString() { return String.valueOf(symbol); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java index ee4ebf09fc..a53e241dd0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/package-info.java @@ -16,4 +16,4 @@ /** * Generation of codecs for the Java programming language. */ -package uk.co.real_logic.sbe.generation.java; \ No newline at end of file +package uk.co.real_logic.sbe.generation.java; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java index 2c9b0501aa..bbb33505cf 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/package-info.java @@ -16,4 +16,4 @@ /** * Codec generators for various programming languages which take {@link uk.co.real_logic.sbe.ir.Ir} as input. */ -package uk.co.real_logic.sbe.generation; \ No newline at end of file +package uk.co.real_logic.sbe.generation; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java index 2c817689c3..399b4c1db1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/package-info.java @@ -16,4 +16,4 @@ /** * Generation of codecs for the Rust programming language. */ -package uk.co.real_logic.sbe.generation.rust; \ No newline at end of file +package uk.co.real_logic.sbe.generation.rust; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java index 0a7b332130..7817b11694 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Encoding.java @@ -271,6 +271,7 @@ public String semanticType() /** * {@inheritDoc} */ + @Override public String toString() { return diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index 7bd1ed693d..72ff961276 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -100,6 +100,7 @@ public IrDecoder(final ByteBuffer buffer) /** * {@inheritDoc} */ + @Override public void close() { CloseHelper.quietClose(channel); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java index ad5888b95a..ba3a2bfa2b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java @@ -95,6 +95,7 @@ public IrEncoder(final ByteBuffer buffer, final Ir ir) /** * {@inheritDoc} */ + @Override public void close() { CloseHelper.quietClose(channel); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java index 7ea00920c0..8fb58cf703 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/Token.java @@ -352,6 +352,7 @@ public boolean isOptionalEncoding() /** * {@inheritDoc} */ + @Override public String toString() { return "Token{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java index f317c5e7f3..691b15ef2f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/package-info.java @@ -17,4 +17,4 @@ * Intermediate Representation for the parsed XML message schema which can be used for generating codecs or * performing OTF decoding. */ -package uk.co.real_logic.sbe.ir; \ No newline at end of file +package uk.co.real_logic.sbe.ir; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java index 18001ae9fa..cb7c87e1c0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/JsonTokenListener.java @@ -50,6 +50,7 @@ public JsonTokenListener(final StringBuilder output) /** * {@inheritDoc} */ + @Override public void onBeginMessage(final Token token) { startObject(); @@ -58,6 +59,7 @@ public void onBeginMessage(final Token token) /** * {@inheritDoc} */ + @Override public void onEndMessage(final Token token) { endObject(); @@ -66,6 +68,7 @@ public void onEndMessage(final Token token) /** * {@inheritDoc} */ + @Override public void onEncoding( final Token fieldToken, final DirectBuffer buffer, @@ -81,6 +84,7 @@ public void onEncoding( /** * {@inheritDoc} */ + @Override public void onEnum( final Token fieldToken, final DirectBuffer buffer, @@ -122,6 +126,7 @@ public void onEnum( /** * {@inheritDoc} */ + @Override public void onBitSet( final Token fieldToken, final DirectBuffer buffer, @@ -158,6 +163,7 @@ public void onBitSet( /** * {@inheritDoc} */ + @Override public void onBeginComposite( final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { @@ -170,6 +176,7 @@ public void onBeginComposite( /** * {@inheritDoc} */ + @Override public void onEndComposite( final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { @@ -180,6 +187,7 @@ public void onEndComposite( /** * {@inheritDoc} */ + @Override public void onGroupHeader(final Token token, final int numInGroup) { property(token.name()); @@ -196,6 +204,7 @@ public void onGroupHeader(final Token token, final int numInGroup) /** * {@inheritDoc} */ + @Override public void onBeginGroup(final Token token, final int groupIndex, final int numInGroup) { startObject(); @@ -204,6 +213,7 @@ public void onBeginGroup(final Token token, final int groupIndex, final int numI /** * {@inheritDoc} */ + @Override public void onEndGroup(final Token token, final int groupIndex, final int numInGroup) { endObject(); @@ -217,6 +227,7 @@ public void onEndGroup(final Token token, final int groupIndex, final int numInG /** * {@inheritDoc} */ + @Override public void onVarData( final Token fieldToken, final DirectBuffer buffer, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java index 476fe58c1c..c007499288 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/json/package-info.java @@ -16,4 +16,4 @@ /** * An OTF decoder for decoding and printing messages in JSON format. */ -package uk.co.real_logic.sbe.json; \ No newline at end of file +package uk.co.real_logic.sbe.json; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java index 1422092ba1..bb45ad2a88 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/AbstractTokenListener.java @@ -31,6 +31,7 @@ public abstract class AbstractTokenListener implements TokenListener /** * {@inheritDoc} */ + @Override public void onBeginMessage(final Token token) { // no op @@ -39,6 +40,7 @@ public void onBeginMessage(final Token token) /** * {@inheritDoc} */ + @Override public void onEndMessage(final Token token) { // no op @@ -47,6 +49,7 @@ public void onEndMessage(final Token token) /** * {@inheritDoc} */ + @Override public void onEncoding( final Token fieldToken, final DirectBuffer buffer, @@ -60,6 +63,7 @@ public void onEncoding( /** * {@inheritDoc} */ + @Override public void onEnum( final Token fieldToken, final DirectBuffer buffer, @@ -75,6 +79,7 @@ public void onEnum( /** * {@inheritDoc} */ + @Override public void onBitSet( final Token fieldToken, final DirectBuffer buffer, @@ -90,6 +95,7 @@ public void onBitSet( /** * {@inheritDoc} */ + @Override public void onBeginComposite( final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { @@ -99,6 +105,7 @@ public void onBeginComposite( /** * {@inheritDoc} */ + @Override public void onEndComposite( final Token fieldToken, final List tokens, final int fromIndex, final int toIndex) { @@ -108,6 +115,7 @@ public void onEndComposite( /** * {@inheritDoc} */ + @Override public void onGroupHeader(final Token token, final int numInGroup) { // no op @@ -116,6 +124,7 @@ public void onGroupHeader(final Token token, final int numInGroup) /** * {@inheritDoc} */ + @Override public void onBeginGroup(final Token token, final int groupIndex, final int numInGroup) { // no op @@ -124,6 +133,7 @@ public void onBeginGroup(final Token token, final int groupIndex, final int numI /** * {@inheritDoc} */ + @Override public void onEndGroup(final Token token, final int groupIndex, final int numInGroup) { // no op @@ -132,6 +142,7 @@ public void onEndGroup(final Token token, final int groupIndex, final int numInG /** * {@inheritDoc} */ + @Override public void onVarData( final Token fieldToken, final DirectBuffer buffer, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java index 04cf0dddd4..7515e0baee 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/otf/package-info.java @@ -16,4 +16,4 @@ /** * On-The-Fly (OTF) decoding of messages based on {@link uk.co.real_logic.sbe.ir.Ir} using a visitor pattern. */ -package uk.co.real_logic.sbe.otf; \ No newline at end of file +package uk.co.real_logic.sbe.otf; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java index fd30d70f78..0663eec56a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/package-info.java @@ -16,4 +16,4 @@ /** * SBE Tool for generating encoders and decoders in multiple languages. */ -package uk.co.real_logic.sbe; \ No newline at end of file +package uk.co.real_logic.sbe; diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java index 37b8b0e808..9fc1b478f0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java @@ -388,6 +388,7 @@ public void checkForValidOffsets(final Node node) /** * {@inheritDoc} */ + @Override public boolean isVariableLength() { return false; @@ -499,6 +500,7 @@ private Type addType(final Node subTypeNode, final String name, final Type type) /** * {@inheritDoc} */ + @Override public String toString() { return "CompositeType{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java index 0239e864ec..e0f0443bc8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java @@ -422,6 +422,7 @@ private PrimitiveValue processConstantChar(final Node node, final String lengthA /** * {@inheritDoc} */ + @Override public String toString() { return "EncodedDataType{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java index bedafa57b3..045801a669 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EnumType.java @@ -233,6 +233,7 @@ public Collection validValues() /** * {@inheritDoc} */ + @Override public boolean isVariableLength() { return false; @@ -241,6 +242,7 @@ public boolean isVariableLength() /** * {@inheritDoc} */ + @Override public String toString() { return "EnumType{" + @@ -332,6 +334,7 @@ public int deprecated() /** * {@inheritDoc} */ + @Override public String toString() { return "ValidValue{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java index ceb020e85b..f0fa5b0d1f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/ErrorHandler.java @@ -135,6 +135,7 @@ public int warningCount() /** * {@inheritDoc} */ + @Override public String toString() { return "ErrorHandler{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java index aa91b6ff31..7382646a5f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java @@ -380,6 +380,7 @@ public String timeUnit() /** * {@inheritDoc} */ + @Override public String toString() { return "Field{name='" + name + '\'' + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java index 9fbdfc7789..0a3886a435 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java @@ -479,6 +479,7 @@ private static void validateBlockLength( /** * {@inheritDoc} */ + @Override public String toString() { return "Message{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java index 7b0e678c88..7ae28dfa5d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java @@ -41,6 +41,7 @@ public SchemaTransformerFactory(final String schemaTransformConfig) /** * {@inheritDoc} */ + @Override public MessageSchema transform(final MessageSchema originalSchema) { return transformer.transform(originalSchema); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index 467ac93b80..9c2763ffae 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -180,6 +180,7 @@ public Collection choices() *

        * {@inheritDoc} */ + @Override public boolean isVariableLength() { return false; @@ -188,6 +189,7 @@ public boolean isVariableLength() /** * {@inheritDoc} */ + @Override public String toString() { return "SetType{" + @@ -284,6 +286,7 @@ public int deprecated() /** * {@inheritDoc} */ + @Override public String toString() { return "Choice{" + diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java index a5d876baab..ae161c164b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java @@ -29,6 +29,7 @@ class SinceVersionSchemaTransformer implements SchemaTransformer /** * {@inheritDoc} */ + @Override public MessageSchema transform(final MessageSchema originalSchema) { final Collection types = originalSchema.types(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java index 7c0ead4286..1b7bcb8c2c 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/package-info.java @@ -16,4 +16,4 @@ /** * Parser and types for the XML based messages schemas. */ -package uk.co.real_logic.sbe.xml; \ No newline at end of file +package uk.co.real_logic.sbe.xml; diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java index 09ff6834e4..992ba63e8f 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/BasicSchemaFileTest.java @@ -78,4 +78,4 @@ void shouldHandleBasicAllTypes() throws Exception assertThat(fields.get(4).name(), is("int64Field")); } } -} \ No newline at end of file +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java index c710b46e04..4643bbd9da 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/RelativeXIncludeTest.java @@ -39,4 +39,4 @@ void shouldParseFileInSubDir() throws Exception assertNotNull(messageSchema.getType("Symbol")); } -} \ No newline at end of file +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java index d92183e2d0..efab1bc608 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java @@ -64,4 +64,4 @@ void shouldHandleMultiSchemaTransformation() (SinceVersionSchemaTransformer)transformer.lookupTransformer(89732465); assertEquals(5, schemaTransformerDefault.sinceVersion()); } -} \ No newline at end of file +} From 5d5ff493e054b96bed6ce1c2c0ea9fdafdd00d68 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:25:55 +0200 Subject: [PATCH 1578/1594] [Java] Upgrade to `Versions` 0.61.0. --- CHANGELOG.adoc | 6 ++++-- gradle/libs.versions.toml | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 4707ae6a8a..bef7f6f04f 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -2,8 +2,10 @@ == 1.40.0 (unreleased) -* **[Java]** Upgrade to `JUnit` 6.1.2. -* **[Java]** Upgrade to `Shadow` 9.6.0. +* **[Java]** Upgrade to `Gradle` 9.7.0. +* **[Java]** Upgrade to `JUnit` 6.1.3. +* **[Java]** Upgrade to `Shadow` 9.6.1. +* **[Java]** Upgrade to `Versions` 0.61.0. == 1.39.0 (2026-07-03) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 055ffc156c..3961afd42e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ junit = "6.1.2" mockito = "5.23.0" plexus = "3.3.0" shadow = "9.6.0" -versions = "0.54.0" +versions = "0.61.0" [libraries] agrona = { group = "org.agrona", name = "agrona", version.ref = "agrona" } @@ -30,4 +30,4 @@ plexus-utils = { group = "org.codehaus.plexus", name = "plexus-utils", version.r [plugins] shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } -versions = { id = "com.github.ben-manes.versions", version.ref = "versions" } +versions = { id = "io.github.ben-manes.versions", version.ref = "versions" } From a6eba5471404f2a7538c56bfe031743088e8f1bc Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:26:12 +0200 Subject: [PATCH 1579/1594] [Java] Upgrade to `JUnit` 6.1.3. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3961afd42e..9139c8245f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ httpcore = "4.4.14" jqwik = "1.10.1" jmh = "1.37" json = "20260522" -junit = "6.1.2" +junit = "6.1.3" mockito = "5.23.0" plexus = "3.3.0" shadow = "9.6.0" From 205808ab8a05144a5c00c330fb9bdf59b73287da Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:26:28 +0200 Subject: [PATCH 1580/1594] [Java] Upgrade to `Shadow` 9.6.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9139c8245f..f7f892363b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20260522" junit = "6.1.3" mockito = "5.23.0" plexus = "3.3.0" -shadow = "9.6.0" +shadow = "9.6.1" versions = "0.61.0" [libraries] From 0c0a474f1ae34295873b304dde46672bde8ee38c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:26:49 +0200 Subject: [PATCH 1581/1594] [Java] Upgrade to `Gradle` 9.7.0. --- gradle/wrapper/gradle-wrapper.jar | Bin 48462 -> 47505 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index b1b8ef56b44f16b14dc800fa8103a6d89abb526f..eddabd2eef8d94a5437d6168ff9c87a78ff725b3 100644 GIT binary patch delta 39079 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 F{Rc_uT_ykk delta 40101 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8747320212..c6f915a79d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.0-all.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From 7f828bc934a08a49597383815baf0cdea6beab05 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:27:53 +0200 Subject: [PATCH 1582/1594] [Java] Upgrade to `json` 20260814. --- CHANGELOG.adoc | 1 + gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index bef7f6f04f..fe6c691165 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -3,6 +3,7 @@ == 1.40.0 (unreleased) * **[Java]** Upgrade to `Gradle` 9.7.0. +* **[Java]** Upgrade to `json` 20260814. * **[Java]** Upgrade to `JUnit` 6.1.3. * **[Java]** Upgrade to `Shadow` 9.6.1. * **[Java]** Upgrade to `Versions` 0.61.0. diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f7f892363b..1b9d098da7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ hamcrest = "3.0" httpcore = "4.4.14" jqwik = "1.10.1" jmh = "1.37" -json = "20260522" +json = "20260814" junit = "6.1.3" mockito = "5.23.0" plexus = "3.3.0" From c30680a3bb0ad59f22a7387612ddda19548130f5 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 20 Aug 2026 16:03:13 +0200 Subject: [PATCH 1583/1594] [Java] Upgrade to `Gradle` 9.7.1. --- CHANGELOG.adoc | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index fe6c691165..47aa8e26c1 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -2,7 +2,7 @@ == 1.40.0 (unreleased) -* **[Java]** Upgrade to `Gradle` 9.7.0. +* **[Java]** Upgrade to `Gradle` 9.7.1. * **[Java]** Upgrade to `json` 20260814. * **[Java]** Upgrade to `JUnit` 6.1.3. * **[Java]** Upgrade to `Shadow` 9.6.1. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c6f915a79d..8c15739002 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-all.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From 73101496c1f050ca7af6cc04a81cb1e80f5525a3 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 20 Aug 2026 16:03:51 +0200 Subject: [PATCH 1584/1594] [Java] Upgrade to `Agrona` 2.6.0. --- CHANGELOG.adoc | 1 + gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 47aa8e26c1..106cde87ff 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -2,6 +2,7 @@ == 1.40.0 (unreleased) +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.6.0[Agrona 2.6.0]. * **[Java]** Upgrade to `Gradle` 9.7.1. * **[Java]** Upgrade to `json` 20260814. * **[Java]** Upgrade to `JUnit` 6.1.3. diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1b9d098da7..dc7d6adc01 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.5.0" +agrona = "2.6.0" checkstyle = "12.3.1" commons-codec = "1.15" commons-lang3 = "3.8.1" From 4f8d88f77baf8fb31c68b01829a05921ade35a98 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Fri, 21 Aug 2026 13:43:41 +1200 Subject: [PATCH 1585/1594] 1.40.0 release --- CHANGELOG.adoc | 2 +- version.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 106cde87ff..19e60b33ac 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,6 +1,6 @@ = Changelog -== 1.40.0 (unreleased) +== 1.40.0 (2026-08-21) * **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.6.0[Agrona 2.6.0]. * **[Java]** Upgrade to `Gradle` 9.7.1. diff --git a/version.txt b/version.txt index 69670a655a..32b7211cb6 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.40.0-SNAPSHOT +1.40.0 From aeeb8d41ce3eaf796092adca1661e278c5a24c13 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Fri, 21 Aug 2026 13:46:06 +1200 Subject: [PATCH 1586/1594] 1.41.0 snapshot --- CHANGELOG.adoc | 2 ++ version.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 19e60b33ac..43cc78a1e9 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,5 +1,7 @@ = Changelog +== 1.41.0 (unreleased) + == 1.40.0 (2026-08-21) * **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.6.0[Agrona 2.6.0]. diff --git a/version.txt b/version.txt index 32b7211cb6..263ee2cdaa 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.40.0 +1.41.0-SNAPSHOT From b18882a6db7ebd46d0c17eeeec6e5af0f8dbb40f Mon Sep 17 00:00:00 2001 From: raphaelroshan <49832307+raphaelroshan@users.noreply.github.com> Date: Fri, 21 Aug 2026 21:36:37 +0800 Subject: [PATCH 1587/1594] [Java] Reject negative choice values in SetType. (#1112) A value is a bit position and must be in [0, size * 8). The bounds check only guarded the upper limit, so a negative value passed validation and was later emitted as a shift amount in generated code, where 1 << -1 is silently masked to 1 << 31 -- producing wrong encode/decode masking for an invalid schema. Reject negative values too. --- .../java/uk/co/real_logic/sbe/xml/SetType.java | 2 +- .../uk/co/real_logic/sbe/xml/SetTypeTest.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java index 9c2763ffae..b3249e3bb1 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SetType.java @@ -225,7 +225,7 @@ public Choice(final Node node, final PrimitiveType encodingType) deprecated = Integer.parseInt(getAttributeValue(node, "deprecated", "0")); // choice values are bit positions (0, 1, 2, 3, 4, etc.) from LSB to MSB - if (value.longValue() >= (encodingType.size() * 8L)) + if (value.longValue() < 0 || value.longValue() >= (encodingType.size() * 8L)) { throw new IllegalArgumentException("Choice value out of bounds: " + value.longValue()); } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java index 60d09daa15..fcaf2a020b 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SetTypeTest.java @@ -175,6 +175,21 @@ void shouldThrowExceptionWhenValueOutOfBoundsSpecified() parseTestXmlWithMap("/types/set", testXmlString)); } + @Test + void shouldThrowExceptionWhenNegativeValueSpecified() + { + final String testXmlString = + "" + + "" + + " 0" + + " -1" + + "" + + ""; + + assertThrows(IllegalArgumentException.class, () -> + parseTestXmlWithMap("/types/set", testXmlString)); + } + @Test void shouldHandleEncodingTypesWithNamedTypes() throws Exception { From b91a783ee697ec3c6a92e415ecb9faeb2b557e6c Mon Sep 17 00:00:00 2001 From: be0hhh Date: Fri, 21 Aug 2026 13:38:20 +0000 Subject: [PATCH 1588/1594] [C++] expose schema version from IrDecoder (#1117) --- sbe-tool/src/main/cpp/otf/IrDecoder.h | 6 ++++++ sbe-tool/src/test/cpp/VersionedMessageTest.cpp | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index fb077cb30c..289f5b985e 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -141,6 +141,10 @@ class IrDecoder return m_id; } + int schemaVersion() const { + return m_version; + } + protected: // OS specifics static long long getFileSize(const char *filename) @@ -188,6 +192,7 @@ class IrDecoder std::unique_ptr m_buffer; std::uint64_t m_length = 0; int m_id = 0; + int m_version = 0; int decodeIr() { @@ -221,6 +226,7 @@ class IrDecoder std::uint64_t headerLength = readHeader(offset); m_id = frame.irId(); + m_version = frame.schemaVersion(); offset += headerLength; diff --git a/sbe-tool/src/test/cpp/VersionedMessageTest.cpp b/sbe-tool/src/test/cpp/VersionedMessageTest.cpp index af4a90c442..ceed72059c 100644 --- a/sbe-tool/src/test/cpp/VersionedMessageTest.cpp +++ b/sbe-tool/src/test/cpp/VersionedMessageTest.cpp @@ -16,6 +16,7 @@ #include +#include "otf/IrDecoder.h" #include "versmsg/VersionedMessageV1.h" #include "versmsg/VersionedMessageV2.h" @@ -55,3 +56,12 @@ TEST_F(VersionedMessageTest, shouldV1DecodeV2Message) EXPECT_EQ(m_versionedMessageV1Decoder.decodeLength(), (uint64_t)26); } + +TEST_F(VersionedMessageTest, shouldExposeSchemaVersionFromIr) +{ + IrDecoder irDecoder = {}; + + ASSERT_GE(irDecoder.decode("versioned-message-v2.sbeir"), 0); + EXPECT_EQ(irDecoder.schemaId(), 1); + EXPECT_EQ(irDecoder.schemaVersion(), 2); +} From 3e8f1c0dcbc164e029e665e0bc7c5152d77bbbfc Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:42:56 +0200 Subject: [PATCH 1589/1594] [Doc] 1.40.1 release notes. --- CHANGELOG.adoc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 43cc78a1e9..0500ac85da 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -2,8 +2,14 @@ == 1.41.0 (unreleased) +== 1.40.1 (2026-08-21) + +* **[Java]** Reject negative choice values in `SetType`. (https://github.com/aeron-io/simple-binary-encoding/pull/1112[#1112]) +* **[C{plus}{plus}]** Expose schema version from `IrDecoder`. (https://github.com/aeron-io/simple-binary-encoding/pull/1117[#1117]). + == 1.40.0 (2026-08-21) +* **[Java]** New agreed Aeron checkstyle and fixes (`MissingOverride` and `NewLineAtEndOfFile`). * **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.6.0[Agrona 2.6.0]. * **[Java]** Upgrade to `Gradle` 9.7.1. * **[Java]** Upgrade to `json` 20260814. @@ -35,8 +41,8 @@ * **[Rust]** Generated encoders now produce fluent interface. (https://github.com/aeron-io/simple-binary-encoding/pull/1097[#1097]) * **[Rust]** Updated some function to `const`. (https://github.com/aeron-io/simple-binary-encoding/pull/1098[#1098]) * **[Rust]** Updated generator to correctly limit length of var data written. (https://github.com/aeron-io/simple-binary-encoding/pull/1096[#1096]) -* **[C++]** Protect against a segfault when dealing with empty `std::span` and `std::view`. -* **[C++]** mark a generated function SBE_CONSTEXPR (#1055) (#1083) +* **[C{plus}{plus}]** Protect against a segfault when dealing with empty `std::span` and `std::view`. +* **[C{plus}{plus}]** mark a generated function SBE_CONSTEXPR (#1055) (#1083) * **[Java]** Upgrade to `CMake` 4.3.0. * **[Java]** Upgrade to `Shadow` 9.4.1. * **[Java]** Upgrade to `Gradle` 9.4.1. From b8855ade64d66482b25724c2084855c6a75e3a85 Mon Sep 17 00:00:00 2001 From: Sebastian Klose Date: Fri, 21 Aug 2026 06:52:25 -0700 Subject: [PATCH 1590/1594] match fixed length string behavior of java/c++ in go (#1119) Co-authored-by: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> --- CHANGELOG.adoc | 9 +- .../flyweight/src/composite/Composite_test.go | 122 ++++++++++++++++++ gocode/struct/src/baseline/Car_test.go | 99 ++++++++++++++ .../flyweight/GolangFlyweightGenerator.java | 79 +++++++++--- .../golang/struct/GolangGenerator.java | 18 ++- 5 files changed, 309 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 0500ac85da..f5a49cc44e 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -6,6 +6,13 @@ * **[Java]** Reject negative choice values in `SetType`. (https://github.com/aeron-io/simple-binary-encoding/pull/1112[#1112]) * **[C{plus}{plus}]** Expose schema version from `IrDecoder`. (https://github.com/aeron-io/simple-binary-encoding/pull/1117[#1117]). +* **[Go]** Fix padding on fixed length character arrays so they are null padded in the Go flyweight codec, matching +the Java and C{plus}{plus} codecs. Setters now also reject values longer than the field rather than overrunning into +the following field. (https://github.com/aeron-io/simple-binary-encoding/pull/1119[#1119]) +* **[Go]** `RangeCheck` in the Go struct codec no longer rejects null padded fixed length character arrays. `NullValue` +for `char` is `0`, which sits below `MinValue` of `0x20`, so null padding written by any codec previously failed +validation, including when decoding a buffer produced by the Java or C{plus}{plus} codec. +(https://github.com/aeron-io/simple-binary-encoding/pull/1119[#1119]) == 1.40.0 (2026-08-21) @@ -1231,4 +1238,4 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru * Project structure updated to be a Gradle modular build. * RC4 features are available for testing if appropriate RC4 XSD schema is provided or schema validation is turned off. * Generated code is marked with the @Generated annotation. -* C{plus}{plus} updated to C{plus}{plus} 11. \ No newline at end of file +* C{plus}{plus} updated to C{plus}{plus} 11. diff --git a/gocode/flyweight/src/composite/Composite_test.go b/gocode/flyweight/src/composite/Composite_test.go index 20e5c9e757..d7bf75235f 100644 --- a/gocode/flyweight/src/composite/Composite_test.go +++ b/gocode/flyweight/src/composite/Composite_test.go @@ -1,6 +1,7 @@ package composite import ( + "bytes" "testing" ) @@ -50,3 +51,124 @@ func TestEncodeDecode(t *testing.T) { t.Fail() } } + +// wrapDirtyComposite wraps a buffer pre-filled with a non-zero sentinel, so that a setter which fails to pad +// cannot pass by accident on a freshly zeroed buffer. +func wrapDirtyComposite(t *testing.T, data []byte) *Composite { + t.Helper() + + for i := range data { + data[i] = 0xFF + } + + var in Composite + in.WrapForEncode(data, 0, uint64(len(data))) + + return &in +} + +// name is a char[5], so every value shorter than 5 bytes must leave the remainder of the field NUL filled. +func TestSetNamePadsShortStringWithNul(t *testing.T) { + tests := []struct { + value string + expected []byte + }{ + {"start", []byte{'s', 't', 'a', 'r', 't'}}, + {"end", []byte{'e', 'n', 'd', 0, 0}}, + {"a", []byte{'a', 0, 0, 0, 0}}, + {"", []byte{0, 0, 0, 0, 0}}, + } + + for _, test := range tests { + var data [256]byte + point := wrapDirtyComposite(t, data[:]).Start() + + point.SetName(test.value) + + if actual := point.Name(); !bytes.Equal(actual, test.expected) { + t.Errorf("SetName(%q) encoded %v, expected %v", test.value, actual, test.expected) + } + if actual := point.GetNameAsString(); actual != test.value { + t.Errorf("SetName(%q) decoded as %q", test.value, actual) + } + } +} + +// Overwriting a longer value with a shorter one must not leave the tail of the previous value behind. +func TestSetNameOverwriteDoesNotLeakPreviousValue(t *testing.T) { + var data [256]byte + point := wrapDirtyComposite(t, data[:]).Start() + + point.SetName("start") + point.SetName("end") + + if actual := point.GetNameAsString(); actual != "end" { + t.Errorf("expected \"end\" after overwrite, got %q", actual) + } + if actual := point.Name(); !bytes.Equal(actual, []byte{'e', 'n', 'd', 0, 0}) { + t.Errorf("stale bytes left after overwrite: %v", actual) + } +} + +// PutName shares the padding contract with SetName so the invariant holds whichever setter is used. +func TestPutNamePadsShortValueWithNul(t *testing.T) { + var data [256]byte + point := wrapDirtyComposite(t, data[:]).Start() + + point.PutName([]byte("start")) + point.PutName([]byte("end")) + + if actual := point.Name(); !bytes.Equal(actual, []byte{'e', 'n', 'd', 0, 0}) { + t.Errorf("PutName left stale bytes: %v", actual) + } +} + +// A value longer than the field must be rejected rather than overrun into the following field, matching the +// Java and C++ codecs which throw. +func TestSetNameTooLongPanics(t *testing.T) { + var data [256]byte + point := wrapDirtyComposite(t, data[:]).Start() + + defer func() { + if recover() == nil { + t.Error("expected SetName to panic for a value longer than the field") + } + }() + + point.SetName("toolong") +} + +func TestPutNameTooLongPanics(t *testing.T) { + var data [256]byte + point := wrapDirtyComposite(t, data[:]).Start() + + defer func() { + if recover() == nil { + t.Error("expected PutName to panic for a value longer than the field") + } + }() + + point.PutName([]byte("toolong")) +} + +// The padding must stop at the end of the field and not spill into whatever follows it. +func TestSetNamePaddingDoesNotDisturbAdjacentFields(t *testing.T) { + var data [256]byte + in := wrapDirtyComposite(t, data[:]) + + in.Start().SetName("end").SetD(3.14).SetI(7) + in.End().SetName("x") + + if actual := in.Start().GetNameAsString(); actual != "end" { + t.Errorf("start.name corrupted: %q", actual) + } + if actual := in.Start().D(); actual != 3.14 { + t.Errorf("start.d corrupted by name setter: %v", actual) + } + if actual := in.Start().I(); actual != 7 { + t.Errorf("start.i corrupted by name setter: %v", actual) + } + if actual := in.End().GetNameAsString(); actual != "x" { + t.Errorf("end.name corrupted: %q", actual) + } +} diff --git a/gocode/struct/src/baseline/Car_test.go b/gocode/struct/src/baseline/Car_test.go index f0e601dd21..61f368620a 100644 --- a/gocode/struct/src/baseline/Car_test.go +++ b/gocode/struct/src/baseline/Car_test.go @@ -137,3 +137,102 @@ func TestDecodeJavaBuffer(t *testing.T) { // fmt.Println(c) return } + +// newRangeCheckableCar builds a Car that passes RangeCheck, so that tests below can vary a single +// character array and attribute any failure to that field alone. +func newRangeCheckableCar(vehicleCode [6]byte, manufacturerCode [3]byte) Car { + var optionalExtras [8]bool + optionalExtras[OptionalExtrasChoice.CruiseControl] = true + + engine := Engine{2000, 4, 0, manufacturerCode, [6]byte{}, 42, BooleanType.T, + EngineBooster{BoostType.NITROUS, 200}} + + fuel := []CarFuelFigures{{30, 35.9, []uint8("Urban Cycle")}} + acceleration := []CarPerformanceFiguresAcceleration{{30, 3.8}} + performance := []CarPerformanceFigures{{95, acceleration}} + + return Car{1234, 2013, BooleanType.T, Model.A, [4]uint32{0, 1, 2, 3}, vehicleCode, + optionalExtras, Model.A, engine, fuel, performance, + []uint8("Honda"), []uint8("Civic VTi"), []uint8("deadbeef")} +} + +func makeVehicleCode(value string) [6]byte { + var code [6]byte + copy(code[:], value) + + return code +} + +// vehicleCode is a char[6]. NUL is the pad byte written by the Java, C++ and Go flyweight codecs, and is +// also what the idiomatic `copy` into a zeroed Go array leaves behind, so RangeCheck has to accept it. +// Space padding must keep working, and genuinely out of range bytes must still be rejected. +func TestRangeCheckAcceptsPaddedCharArrays(t *testing.T) { + var manufacturerCode [3]byte + copy(manufacturerCode[:], "123") + + tests := []struct { + name string + code [6]byte + wantError bool + }{ + {"exact length", makeVehicleCode("abcdef"), false}, + {"NUL padded", makeVehicleCode("abc"), false}, + {"space padded", makeVehicleCode("abc "), false}, + {"all NUL", makeVehicleCode(""), false}, + {"all space", makeVehicleCode(" "), false}, + {"below range", [6]byte{'a', 'b', 'c', 0x01, 0, 0}, true}, + {"above range", [6]byte{'a', 'b', 'c', 0x7F, 0, 0}, true}, + } + + for _, test := range tests { + c := newRangeCheckableCar(test.code, manufacturerCode) + err := c.RangeCheck(c.SbeSchemaVersion(), c.SbeSchemaVersion()) + + if test.wantError && err == nil { + t.Errorf("%s (%q): expected RangeCheck to fail, got nil", test.name, test.code) + } + if !test.wantError && err != nil { + t.Errorf("%s (%q): expected RangeCheck to pass, got %v", test.name, test.code, err) + } + } +} + +// A NUL padded char array must survive a round trip with range checking enabled at both ends. +func TestEncodeDecodeNulPaddedCharArray(t *testing.T) { + var manufacturerCode [3]byte + copy(manufacturerCode[:], "12") + + in := newRangeCheckableCar(makeVehicleCode("abc"), manufacturerCode) + + m := NewSbeGoMarshaller() + buf := new(bytes.Buffer) + if err := in.Encode(m, buf, true); err != nil { + t.Fatalf("Encode with range check failed: %v", err) + } + + var out Car + if err := out.Decode(m, buf, in.SbeSchemaVersion(), in.SbeBlockLength(), true); err != nil { + t.Fatalf("Decode with range check failed: %v", err) + } + + if in.VehicleCode != out.VehicleCode { + t.Errorf("VehicleCode round trip: encoded %q, decoded %q", in.VehicleCode, out.VehicleCode) + } + if in.Engine.ManufacturerCode != out.Engine.ManufacturerCode { + t.Errorf("ManufacturerCode round trip: encoded %q, decoded %q", + in.Engine.ManufacturerCode, out.Engine.ManufacturerCode) + } +} + +// The NullValue escape must apply only to character arrays; numeric arrays keep strict range checking. +func TestRangeCheckStillStrictForNumericArrays(t *testing.T) { + var manufacturerCode [3]byte + copy(manufacturerCode[:], "123") + + c := newRangeCheckableCar(makeVehicleCode("abcdef"), manufacturerCode) + c.SomeNumbers[2] = c.SomeNumbersMaxValue() + 1 + + if err := c.RangeCheck(c.SbeSchemaVersion(), c.SbeSchemaVersion()); err == nil { + t.Error("expected RangeCheck to reject an out of range uint32 array element, got nil") + } +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java index 30db48127e..0d12e794af 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java @@ -1855,14 +1855,22 @@ private void generateArrayProperty( offset, formatClassName(containingClassName)); - new Formatter(sb).format("\n" + - indent + "func (m *%1$s) Put%2$s(src []byte) *%1$s {\n" + - indent + " copy(m.buffer[(m.offset+%3$d):], src)\n" + - indent + " return m\n" + - indent + "}\n", - formatClassName(containingClassName), - formatPropertyName(propertyName), - offset); + if (primitiveType == PrimitiveType.CHAR) + { + generateNullPaddedSetter( + sb, containingClassName, "Put", propertyName, "[]byte", offset, arrayLength, indent); + } + else + { + new Formatter(sb).format("\n" + + indent + "func (m *%1$s) Put%2$s(src []byte) *%1$s {\n" + + indent + " copy(m.buffer[(m.offset+%3$d):], src)\n" + + indent + " return m\n" + + indent + "}\n", + formatClassName(containingClassName), + formatPropertyName(propertyName), + offset); + } if (arrayLength > 1 && arrayLength <= 4) { @@ -1922,17 +1930,56 @@ private void generateArrayProperty( generateJsonEscapedStringGetter(sb, encodingToken, indent, propertyName, containingClassName); - new Formatter(sb).format("\n" + - indent + "func (m *%1$s) Set%2$s(src string) *%1$s {\n" + - indent + " copy(m.buffer[(m.offset+%3$d):], []byte(src))\n" + - indent + " return m\n" + - indent + "}\n", - formatClassName(containingClassName), - formatPropertyName(propertyName), - offset); + generateNullPaddedSetter( + sb, containingClassName, "Set", propertyName, "string", offset, arrayLength, indent); } } + /** + * Generate a setter for a fixed length character array which pads any unused trailing bytes with NUL, matching + * the Java and C{plus}{plus} codecs. The field is therefore fully defined after the call regardless of what the + * buffer previously held, which is what {@code Get<name>AsString} relies on when it trims at the first NUL. + * + * @param sb to append the generated code to. + * @param containingClassName of the flyweight the setter belongs to. + * @param methodPrefix of the generated method, either {@code Set} or {@code Put}. + * @param propertyName of the field being set. + * @param srcGoType Go type of the source parameter, either {@code string} or {@code []byte}. + * @param offset of the field within the containing block. + * @param arrayLength declared length of the character array. + * @param indent for the generated code. + */ + private void generateNullPaddedSetter( + final StringBuilder sb, + final String containingClassName, + final String methodPrefix, + final String propertyName, + final String srcGoType, + final int offset, + final int arrayLength, + final String indent) + { + new Formatter(sb).format("\n" + + indent + "func (m *%1$s) %2$s%3$s(src %4$s) *%1$s {\n" + + indent + " length := uint64(len(src))\n" + + indent + " if length > %6$d {\n" + + indent + " panic(\"src too large for %2$s%3$s [E106]\")\n" + + indent + " }\n\n" + + indent + " start := m.offset + %5$d\n" + + indent + " copy(m.buffer[start:start+%6$d], src)\n" + + indent + " for i := length; i < %6$d; i++ {\n" + + indent + " m.buffer[start+i] = 0\n" + + indent + " }\n\n" + + indent + " return m\n" + + indent + "}\n", + formatClassName(containingClassName), + methodPrefix, + formatPropertyName(propertyName), + srcGoType, + offset, + arrayLength); + } + private void generateJsonEscapedStringGetter( final StringBuilder sb, final Token token, diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java index b0b33e5c7e..32f61dec82 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/struct/GolangGenerator.java @@ -477,10 +477,26 @@ private void generateRangeCheckPrimitive( imports.peek().add("fmt"); if (token.arrayLength() > 1) { + // A character array holding a value shorter than its declared length is NUL padded by the Java, + // C++ and Go flyweight codecs, and NullValue for CHAR (0) sits below MinValue (0x20), so the pad + // bytes have to be accepted here too. Space padded values are unaffected either way because the + // pad character is itself within Min->Max. + // Structured this way for go fmt sanity on both cases. + final String elementCheck; + if (token.encoding().primitiveType() == PrimitiveType.CHAR) + { + elementCheck = "\t\t\tif %1$s[idx] != %1$sNullValue() && " + + "(%1$s[idx] < %1$sMinValue() || %1$s[idx] > %1$sMaxValue()) {\n"; + } + else + { + elementCheck = "\t\t\tif %1$s[idx] < %1$sMinValue() || %1$s[idx] > %1$sMaxValue() {\n"; + } + sb.append(String.format( "\tif %1$sInActingVersion(actingVersion) {\n" + "\t\tfor idx := 0; idx < %2$s; idx++ {\n" + - "\t\t\tif %1$s[idx] < %1$sMinValue() || %1$s[idx] > %1$sMaxValue() {\n" + + elementCheck + "\t\t\t\treturn fmt.Errorf(\"Range check failed on %1$s[%%d] " + "(%%v < %%v > %%v)\", idx, %1$sMinValue(), %1$s[idx], %1$sMaxValue())\n" + "\t\t\t}\n" + From 2f1c1d3a0b54f1b4f7ac7017346d331882b66bc1 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:55:18 +0200 Subject: [PATCH 1591/1594] Tidy up after #1119. --- .../flyweight/GolangFlyweightGenerator.java | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java index 0d12e794af..036ffbf7ae 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/golang/flyweight/GolangFlyweightGenerator.java @@ -1935,20 +1935,6 @@ private void generateArrayProperty( } } - /** - * Generate a setter for a fixed length character array which pads any unused trailing bytes with NUL, matching - * the Java and C{plus}{plus} codecs. The field is therefore fully defined after the call regardless of what the - * buffer previously held, which is what {@code Get<name>AsString} relies on when it trims at the first NUL. - * - * @param sb to append the generated code to. - * @param containingClassName of the flyweight the setter belongs to. - * @param methodPrefix of the generated method, either {@code Set} or {@code Put}. - * @param propertyName of the field being set. - * @param srcGoType Go type of the source parameter, either {@code string} or {@code []byte}. - * @param offset of the field within the containing block. - * @param arrayLength declared length of the character array. - * @param indent for the generated code. - */ private void generateNullPaddedSetter( final StringBuilder sb, final String containingClassName, @@ -1959,6 +1945,8 @@ private void generateNullPaddedSetter( final int arrayLength, final String indent) { + // Generate a setter for a fixed length character array which pads any unused trailing bytes with NUL, + // matching the Java and C++ codecs new Formatter(sb).format("\n" + indent + "func (m *%1$s) %2$s%3$s(src %4$s) *%1$s {\n" + indent + " length := uint64(len(src))\n" + From ac796a16fcf7f0b1ab3aeedb94668ac8f34ac6d2 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:56:09 +0200 Subject: [PATCH 1592/1594] 1.40.1 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 263ee2cdaa..53a714f1dd 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.41.0-SNAPSHOT +1.40.1 From d908f362fee24f6e751df965865ae4b2ab6dc345 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:56:21 +0200 Subject: [PATCH 1593/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 53a714f1dd..263ee2cdaa 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.40.1 +1.41.0-SNAPSHOT From 7373f23c4c59a178827752d094fc31a90857de8e Mon Sep 17 00:00:00 2001 From: s1amese2003 Date: Sat, 22 Aug 2026 10:42:57 +0000 Subject: [PATCH 1594/1594] [Rust] Use the schema's null value when generating enums (#1120) The Rust generator emitted the primitive type's default null value for an enum instead of the one declared in the schema, so a uint8 enum encoding that declares nullValue="254" generated NullVal = 0xff_u8. Java, C++ and Go generate 254 for the same schema, so a Rust encoder wrote a null value a peer in another language does not recognise. IrGenerator records the null value on the enum's BEGIN_ENUM token, while the VALID_VALUE tokens carry only byteOrder, primitiveType and constValue. generateEnum read it from messageBody.get(0), a valid value token, so applicableNullValue() fell back to primitiveType.nullValue(). JavaGenerator reads it from tokens.get(0), which is why Java is unaffected. The same mistake appeared in the enum discriminant and in From for . Resolve the null value once and pass it down so the two cannot disagree. optional_enum_nullify.xml already covers an enum with a declared null value, but declares 255, which is also the uint8 default, so it passes either way. The new issue1116 schema declares 254 to separate the two. Resolves #1116 --- build.gradle | 1 + rust/Cargo.toml | 1 + rust/tests/issue_1116_test.rs | 44 +++++++++++++++++++ .../sbe/generation/rust/RustGenerator.java | 16 +++---- sbe-tool/src/test/resources/issue1116.xml | 25 +++++++++++ 5 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 rust/tests/issue_1116_test.rs create mode 100644 sbe-tool/src/test/resources/issue1116.xml diff --git a/build.gradle b/build.gradle index e63452a9ef..28e6d6f3dc 100644 --- a/build.gradle +++ b/build.gradle @@ -682,6 +682,7 @@ tasks.register('generateRustTestCodecs', JavaExec) { 'sbe-tool/src/test/resources/issue1028.xml', 'sbe-tool/src/test/resources/issue1057.xml', 'sbe-tool/src/test/resources/issue1066.xml', + 'sbe-tool/src/test/resources/issue1116.xml', 'sbe-tool/src/test/resources/optional_enum_nullify.xml', 'sbe-tool/src/test/resources/basic-variable-length-schema.xml', 'sbe-tool/src/test/resources/example-bigendian-test-schema.xml', diff --git a/rust/Cargo.toml b/rust/Cargo.toml index df19774eb3..1853a174fc 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -19,6 +19,7 @@ issue_987 = { path = "../generated/rust/issue987" } issue_1028 = { path = "../generated/rust/issue1028" } issue_1057 = { path = "../generated/rust/issue1057" } issue_1066 = { path = "../generated/rust/issue1066" } +issue_1116 = { path = "../generated/rust/issue1116" } baseline_bigendian = { path = "../generated/rust/baseline_bigendian" } nested_composite_name = { path = "../generated/rust/nested_composite_name" } sbe_tests = { path = "../generated/rust/sbe_tests" } diff --git a/rust/tests/issue_1116_test.rs b/rust/tests/issue_1116_test.rs new file mode 100644 index 0000000000..41e08bba2f --- /dev/null +++ b/rust/tests/issue_1116_test.rs @@ -0,0 +1,44 @@ +use issue_1116::{ + foo_bar::FooBar, + issue_1116_codec::{self, Issue1116Decoder, Issue1116Encoder}, + message_header_codec, ReadBuf, WriteBuf, +}; + +/// The schema declares `nullValue="254"` on the type `FooBar` encodes to, so the generated null +/// value has to be 254 rather than the uint8 default of 255. The Java, C++ and Go generators all +/// emit 254 for this schema. +#[test] +fn enum_null_value_comes_from_the_schema() { + // The discriminant, which is what the encoder writes. + assert_eq!(FooBar::NullVal as u8, 254); + + // The `From` conversion, which is generated separately from the discriminant. + assert_eq!(u8::from(FooBar::NullVal), 254); + + assert_eq!(FooBar::from(254), FooBar::NullVal); +} + +/// A peer decoding this message in another language reads the schema's null value off the wire, so +/// that is the byte the Rust encoder has to write. +#[test] +fn encodes_and_decodes_the_schema_null_value() { + let mut buffer = vec![0u8; 256]; + + { + let mut encoder = Issue1116Encoder::default().wrap( + WriteBuf::new(&mut buffer), + message_header_codec::ENCODED_LENGTH, + ); + encoder.foo_bar(FooBar::NullVal); + } + + assert_eq!(buffer[message_header_codec::ENCODED_LENGTH], 254); + + let decoder = Issue1116Decoder::default().wrap( + ReadBuf::new(&buffer), + message_header_codec::ENCODED_LENGTH, + issue_1116_codec::SBE_BLOCK_LENGTH, + 0, + ); + assert_eq!(decoder.foo_bar(), FooBar::NullVal); +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 628055a3e3..2d6b310e62 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1615,10 +1615,13 @@ private static void generateEnum( indent(writer, 1, "%s = %s, \n", token.name(), literal); } + // The null value is declared on the enum itself, or on the type it encodes to, so it + // has to be read from the enum token. A valid value token never carries one, which makes + // applicableNullValue() fall back to the primitive type default instead of the schema one. + final CharSequence nullVal = rustNullLiteral(enumTokens.get(0).encoding()); + // null value { - final Encoding encoding = messageBody.get(0).encoding(); - final CharSequence nullVal = rustNullLiteral(encoding); indent(writer, 1, "#[default]\n"); indent(writer, 1, "NullVal = %s, \n", nullVal); } @@ -1628,7 +1631,7 @@ private static void generateEnum( generateFromPrimitiveForEnum(enumRustName, primitiveType, messageBody, writer); // Into impl - generateFromEnumForPrimitive(enumRustName, primitiveType, messageBody, writer); + generateFromEnumForPrimitive(enumRustName, primitiveType, messageBody, nullVal, writer); // FromStr impl generateFromStrImplForEnum(enumRustName, messageBody, writer); @@ -1666,6 +1669,7 @@ private static void generateFromEnumForPrimitive( final String enumRustName, final String primitiveType, final List messageBody, + final CharSequence nullVal, final Appendable writer) throws IOException { indent(writer, 0, "impl From<%s> for %s {\n", enumRustName, primitiveType); @@ -1680,11 +1684,7 @@ private static void generateFromEnumForPrimitive( indent(writer, 3, "%s::%s => %s, \n", enumRustName, token.name(), literal); } - { - final Encoding encoding = messageBody.get(0).encoding(); - final CharSequence nullVal = rustNullLiteral(encoding); - indent(writer, 3, "%s::NullVal => %s,\n", enumRustName, nullVal); - } + indent(writer, 3, "%s::NullVal => %s,\n", enumRustName, nullVal); indent(writer, 2, "}\n"); indent(writer, 1, "}\n"); indent(writer, 0, "}\n"); diff --git a/sbe-tool/src/test/resources/issue1116.xml b/sbe-tool/src/test/resources/issue1116.xml new file mode 100644 index 0000000000..229a76fada --- /dev/null +++ b/sbe-tool/src/test/resources/issue1116.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + 0 + 1 + + + + + +

        eiA2GR@p!BxfkB$9OMKXKst*+I> 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 AyZ`_I diff --git a/sbe-tool/src/test/c/CMakeLists.txt b/sbe-tool/src/test/c/CMakeLists.txt index fab918f0b3..646b9e43c9 100644 --- a/sbe-tool/src/test/c/CMakeLists.txt +++ b/sbe-tool/src/test/c/CMakeLists.txt @@ -16,16 +16,15 @@ function(sbe_test name) add_executable("C${name}" "${name}.cpp") + add_dependencies(C${name} gmock) target_include_directories("C${name}" - PRIVATE ${GTEST_SOURCE_DIR}/googletest/include - PRIVATE ${C_CODEC_TARGET_DIR} + PRIVATE ${C_CODEC_TARGET_DIR} ) target_compile_options("C${name}" PRIVATE $<$:-Werror>) target_compile_options("C${name}" PRIVATE $<$:-Werror>) target_compile_options("C${name}" PRIVATE $<$:-Werror -Wno-maybe-uninitialized>) - target_link_libraries("C${name}" ${GTEST_LIBS} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries("C${name}" gmock_main ${CMAKE_THREAD_LIBS_INIT}) add_test(NAME C${name} COMMAND C${name} WORKING_DIRECTORY ${C_CODEC_TARGET_DIR}) - add_dependencies(C${name} gtest) if (${ARGC} GREATER 1) add_dependencies(C${name} ${ARGV1}) endif () diff --git a/sbe-tool/src/test/cpp/CMakeLists.txt b/sbe-tool/src/test/cpp/CMakeLists.txt index 06dab75f9b..0137b6de35 100644 --- a/sbe-tool/src/test/cpp/CMakeLists.txt +++ b/sbe-tool/src/test/cpp/CMakeLists.txt @@ -16,17 +16,15 @@ function(sbe_test name) add_executable("${name}" "${name}.cpp") + add_dependencies(${name} gmock) target_include_directories("${name}" - PRIVATE ${GTEST_SOURCE_DIR}/googletest/include - PRIVATE ${GTEST_SOURCE_DIR}/googlemock/include PRIVATE ${CXX_CODEC_TARGET_DIR} ) target_compile_options("${name}" PRIVATE $<$:-Werror>) target_compile_options("${name}" PRIVATE $<$:-Werror>) target_compile_options("${name}" PRIVATE $<$:-Werror>) - target_link_libraries("${name}" sbe ${GTEST_LIBS} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries("${name}" sbe gmock_main ${CMAKE_THREAD_LIBS_INIT}) add_test(NAME ${name} COMMAND ${name} WORKING_DIRECTORY ${CXX_CODEC_TARGET_DIR}) - add_dependencies(${name} gtest) if (${ARGC} GREATER 1) add_dependencies(${name} ${ARGV1}) endif () From 9296871ab1fa2f95acf0b1e361ec32c0cdcfa6b1 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 15:21:30 +0200 Subject: [PATCH 1440/1594] [CI] Add `C#` 9 through 13 to the build matrix. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3c08cb75f..f0c40b4609 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,7 +85,7 @@ jobs: strategy: fail-fast: false matrix: - dotnet: [ '8.0.x' ] + dotnet: [ '8.0.x', '9.0.x', '10.0.x', '11.0.x', '12.0.x', '13.0.x' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 From 473904db59080fc7ba9dd2381f69f5d90db0e360 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 15:22:34 +0200 Subject: [PATCH 1441/1594] [CI] Bump `setup-dotnet` to v5. --- .github/workflows/ci.yml | 2 +- .github/workflows/codeql.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f0c40b4609..4b960d8b1b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -114,7 +114,7 @@ jobs: restore-keys: | ${{ runner.os }}-nuget- - name: Setup dotnet - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v5 with: dotnet-version: ${{ matrix.dotnet }} - name: Build diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 4832f66097..05a2b98aa4 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -117,7 +117,7 @@ jobs: uses: gradle/actions/setup-gradle@v4 - name: Setup dotnet - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v5 with: dotnet-version: ${{ matrix.dotnet }} From 2429e586a87be8c9b4df079765d19e6711d8e1f6 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 15:25:54 +0200 Subject: [PATCH 1442/1594] [CI] Simplify `setup-dotnet` version specification. --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b960d8b1b..4164ffee03 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,7 +85,7 @@ jobs: strategy: fail-fast: false matrix: - dotnet: [ '8.0.x', '9.0.x', '10.0.x', '11.0.x', '12.0.x', '13.0.x' ] + dotnet: [ '8', '9', '10', '11', '12', '13' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -117,6 +117,7 @@ jobs: uses: actions/setup-dotnet@v5 with: dotnet-version: ${{ matrix.dotnet }} + dotnet-quality: 'ga' - name: Build run: ./csharp/build.sh - name: Run tests From 6c7f2bb42d3b5dfb46e0d4baa00b6875eb8235a1 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 15:31:56 +0200 Subject: [PATCH 1443/1594] [CI] Remove non-installable .NET versions. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4164ffee03..7560413329 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,7 +85,7 @@ jobs: strategy: fail-fast: false matrix: - dotnet: [ '8', '9', '10', '11', '12', '13' ] + dotnet: [ '8', '9', '10' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 From c398c8a966f7690d23fa0c7b47baa8b438cc7a2a Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 15:43:36 +0200 Subject: [PATCH 1444/1594] [CI] Run slow tests using .NET 10. --- .github/workflows/slow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 0e40379a1d..7ff980090d 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -34,7 +34,7 @@ jobs: strategy: matrix: java: [ '25' ] - dotnet: [ '8.0.x' ] + dotnet: [ '10' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 From 8c5c57858eacf5676f6769a08c63620a5b8b4383 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Wed, 17 Sep 2025 15:49:53 +0200 Subject: [PATCH 1445/1594] [CI] Update actions in the slow build. --- .github/workflows/codeql.yml | 2 +- .github/workflows/slow.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 05a2b98aa4..e4951b67f8 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -83,7 +83,7 @@ jobs: fail-fast: false matrix: language: [ 'csharp' ] - dotnet: [ '8.0.x' ] + dotnet: [ '10' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index 7ff980090d..ae634eb04b 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -40,7 +40,7 @@ jobs: DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v5 - name: Setup java uses: actions/setup-java@v5 with: @@ -52,14 +52,14 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - name: Setup java to run Gradle script - uses: actions/setup-java@v3 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 - name: Setup dotnet - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@v5 with: dotnet-version: ${{ matrix.dotnet }} - name: Build .NET library From d78946a08925a11d8db31531668c1700d053d4b8 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 22 Sep 2025 10:18:07 +0200 Subject: [PATCH 1446/1594] [Java] Bump `Gradle` to 9.1.0. --- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 3 --- gradlew.bat | 3 +-- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 48b43d3506..a35649f5fc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index ef07e0162b..adff685a03 100755 --- a/gradlew +++ b/gradlew @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -172,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -212,7 +210,6 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" diff --git a/gradlew.bat b/gradlew.bat index db3a6ac207..c4bdd3ab8e 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell From 21ee4a2301d11c2d4b7f509ca36620f8cba75b02 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 22 Sep 2025 10:18:25 +0200 Subject: [PATCH 1447/1594] [Java] Bump `Mockito` to 5.20.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b241820484..3ab54e41ae 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ jqwik = "1.9.3" jmh = "1.37" json = "20250517" junit = "5.13.4" -mockito = "5.19.0" +mockito = "5.20.0" plexus = "3.3.0" shadow = "9.1.0" versions = "0.52.0" From 7122a817522dfc90ed4a552b2467020a79d669ac Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 11:45:25 +0200 Subject: [PATCH 1448/1594] [Java] Bump `Versions` to 0.53.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3ab54e41ae..f5bfc0788f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ junit = "5.13.4" mockito = "5.20.0" plexus = "3.3.0" shadow = "9.1.0" -versions = "0.52.0" +versions = "0.53.0" [libraries] agrona = { group = "org.agrona", name = "agrona", version.ref = "agrona" } From 6aaa314e3e45af9f198f2e6721df901bfa573b17 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 11:45:40 +0200 Subject: [PATCH 1449/1594] [Java] Bump `Shadow` to 9.2.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f5bfc0788f..00c6ac6232 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20250517" junit = "5.13.4" mockito = "5.20.0" plexus = "3.3.0" -shadow = "9.1.0" +shadow = "9.2.2" versions = "0.53.0" [libraries] From 08f0a6be9d0fe84d4c0eddb104095457332d20c2 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 11:46:02 +0200 Subject: [PATCH 1450/1594] [Java] Bump `Checkstyle` to 11.1.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 00c6ac6232..14662e3f55 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.2.4" -checkstyle = "11.0.0" +checkstyle = "11.1.0" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From d6e38b3d0d3d3e8cb340e5527e7aee204e222917 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 11:46:14 +0200 Subject: [PATCH 1451/1594] [Java] Bump `Agrona` to 2.3.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 14662e3f55..559965ee68 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.2.4" +agrona = "2.3.0" checkstyle = "11.1.0" commons-codec = "1.15" commons-lang3 = "3.8.1" From 553afe1a927591a625ac40924d0137237614e1bb Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 12:12:39 +0200 Subject: [PATCH 1452/1594] [Doc] Migrate to AsciiDoc. --- CHANGELOG.adoc | 96 ++++++++++++++++++++++++++++++++++++++++++ CHANGELOG.md | 111 ------------------------------------------------- 2 files changed, 96 insertions(+), 111 deletions(-) create mode 100644 CHANGELOG.adoc delete mode 100644 CHANGELOG.md diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc new file mode 100644 index 0000000000..8b41172297 --- /dev/null +++ b/CHANGELOG.adoc @@ -0,0 +1,96 @@ += Changelog + +== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.6[1.35.6] - 2025-06-27 + +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.4[Agrona 2.2.4]. +* **[Java]** Upgrade to `JUnit` 5.13.2. +* **[Java]** Upgrade to `Checkstyle` 10.26.0. +* **[Java]** Upgrade to `Shadow` 8.3.7. + +== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.5[1.35.5] - 2025-06-20 + +* **[Java/C{plus}{plus}/C#]** Fix a bug in overzealous DTO validation. (https://github.com/aeron-io/simple-binary-encoding/pull/1073[#1073]) +* **[Java]** Improve JsonPrinter's conformance with the JSON specification (e.g., escaping control characters and using correct delimiters). +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.3[Agrona 2.2.3]. + +== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.4[1.35.4] - 2025-06-12 + +* **[Rust]** Return None for optional primite field if its version is less than actingVersion. (https://github.com/aeron-io/simple-binary-encoding/pull/1067[#1067]) +* **[Java]** Adjust Java Dto generateComputeEncodedLength to acount for character encoding. (https://github.com/aeron-io/simple-binary-encoding/pull/1072[#1072]) +* **[Java]** Upgrade to `JUnit` 5.13.1. +* **[Java]** Upgrade to `jqwik` 1.9.3. + +== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.3[1.35.3] - 2025-06-06 + +* **[Java]** Publish release artifacts to Central Portal using OSSRH Staging API service. +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.2[Agrona 2.2.2]. +* **[Java]** Upgrade to `Checkstyle` 10.25.0. +* **[Java]** Upgrade to `Gradle` 8.14.2. + +== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.1[1.35.1] - 2025-06-02 + +* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.1[Agrona 2.2.1]. +* Upgrade to `JUnit` 5.13.0. + +== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.0[1.35.0] - 2025-05-26 + +* **[Java]** include field 'deprecated' in ir encoding and decoding. +* **[Java]** Adjust Java DTO Choice Set Access. (https://github.com/aeron-io/simple-binary-encoding/issues/1064[#1064]) +* **[Rust]** get proper version for composite types. (https://github.com/aeron-io/simple-binary-encoding/pull/1058[#1058]) +* **[C#]** Read NuGet package version from version file (https://github.com/aeron-io/simple-binary-encoding/pull/1061[#1061]) +* **[C#]** Enable dual build for netstandard2.0 & netstandard2.1. (https://github.com/aeron-io/simple-binary-encoding/pull/1062[#1062]) +* Update `Implementation-Vendor`. +* **[Rust]** Elide explicit ActingVersion lifetime. (https://github.com/aeron-io/simple-binary-encoding/pull/1053[#1053]) +* **[CI]** Use `gradle/actions/setup-gradle` action for caching Gradle dependencies. +* **[CI]** Enable JDK 24 GA build. +* **[CI]** Simplify error log upload. +* **[CI]** Remove Ubuntu 20.04 based builds. +* **[CI]** Bump Go build to use 1.23.x and 1.24.x. +* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.0[Agrona 2.2.0]. +* Upgrade to `Gradle` 8.14.1. +* Upgrade to `Checkstyle` 10.24.0. +* Bump `json` to 20250517. +* Upgrade to `JUnit` 5.12.2. +* Upgrade to `Mockito` 5.18.0. +* Upgrade to `Shadow` 8.3.6. +* Bump `Versions` to 0.52. + +== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.34.1[1.34.1] - 2025-01-13 + +* *Doc:* Add `--add-opens java.base/jdk.internal.misc=ALL-UNNAMED` to the example execution. +* **[Rust]** encoding primitive arrays now supports slice instead of array (issue https://github.com/aeron-io/simple-binary-encoding/issues/[#1021]). (https://github.com/aeron-io/simple-binary-encoding/pull/1040[#1040]) +* **[C{plus}{plus}]** check for not wrapped state in `decodeLength()` when precedence checks are enabled. (https://github.com/aeron-io/simple-binary-encoding/pull/1046[#1046]) +* **[C{plus}{plus}]** use `m_actingBlockLength` in `decodeLength()`. (https://github.com/aeron-io/simple-binary-encoding/pull/1045[#1045]) +* Bump `json` to 20250107. +* Upgrade to `Mockito` 5.15.2. + +== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.34.0[1.34.0] - 2024-12-17 + +* **[C{plus}{plus}]** hide the m_codecStatePtr behind ifdefs to avoid overhead when precedence checking is disabled. (https://github.com/aeron-io/simple-binary-encoding/pull/1036[#1036]) +* **[C{plus}{plus}]** use constexpr to define precedence checks lookup tables. +* **[Rust]** Enhance enum supporting fromstr and display and into. (https://github.com/aeron-io/simple-binary-encoding/pull/1020[#1020]) +* **[Rust]** codegen of primitive enums now implement 'From' instead of 'Into'. (https://github.com/aeron-io/simple-binary-encoding/pull/1029[#1029]) +* **[Java]** Update Checkstyle rules and apply them. +* *Breaking:* Upgrade to `Agrona` 2.0.0. ++ +_**Note:** `--add-opens java.base/jdk.internal.misc=ALL-UNNAMED` JVM option must be specified in order to generate codecs or use the generated Java classes. For example:_ ++ +[source,shell] +---- +$ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-${SBE_TOOL_VERSION}.jar my-sbe-messages.xml +---- + +* **[C{plus}{plus}]** Fix field precedence check issue https://github.com/aeron-io/simple-binary-encoding/issues/1031[#1031]. (https://github.com/aeron-io/simple-binary-encoding/pull/1033[#1033]) +* **[C{plus}{plus}]** respect the package override option for C{plus}{plus} codecs and DTOs. (https://github.com/aeron-io/simple-binary-encoding/pull/1024[#1024]) +* **[C#]** respect the package override option for C# codecs and DTOs. (https://github.com/aeron-io/simple-binary-encoding/pull/1024[#1024]) +* **[Go]** Fix warning about used args in GolangFlyweightGenerator. +* **[Rust]** Updated code generator to resolve Issue https://github.com/aeron-io/simple-binary-encoding/issues/1028[#1028]. (https://github.com/aeron-io/simple-binary-encoding/pull/1037[#1037]) +* **[Java]** Prevent collision when field name is 'value'. +* **[Java]** Preserve byte order throughout IR transformations. +* **[C{plus}{plus}]** Integrate std::span support for flyweight API. (https://github.com/aeron-io/simple-binary-encoding/pull/1038[#1038], https://github.com/aeron-io/simple-binary-encoding/pull/1027[#1027]) +* **[Rust]** generate message schema level info in lib.rs. (https://github.com/aeron-io/simple-binary-encoding/pull/1019[#1019]) +* Upgrade to `Gradle` 8.11.1. +* Upgrade to `Checkstyle` 10.21.0. +* Upgrade to `ByteBuddy` 1.15.11. +* Upgrade to `JUnit` 5.11.4. +* Upgrade to `jqwik` 1.9.2. diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index b9e90464f5..0000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,111 +0,0 @@ -# Changelog - -## [1.35.6] - 2025-06-27 -### Changed -* **Java:** Bump `Agrona` to [2.2.4](https://github.com/aeron-io/agrona/releases/tag/2.2.4). -* **Java:** Bump `JUnit` to 5.13.2. -* **Java:** Bump `Checkstyle` to 10.26.0. -* **Java:** Bump `Shadow` to 8.3.7. - -## [1.35.5] - 2025-06-20 -### Changed -* **Java/C++/C#:** Fix a bug in overzealous DTO validation. ([#1073](https://github.com/aeron-io/simple-binary-encoding/pull/1073)) -* **Java:** Improve JsonPrinter's conformance with the JSON specification (e.g., escaping control characters and using correct delimiters). -* **Java:** Bump `Agrona` to 2.2.3. - -## [1.35.4] - 2025-06-12 -### Changed -* **Rust:** Return None for optional primite field if its version is less than actingVersion. ([#1067](https://github.com/aeron-io/simple-binary-encoding/pull/1067)) -* **Java:** Adjust Java Dto generateComputeEncodedLength to acount for character encoding. ([#1072](https://github.com/aeron-io/simple-binary-encoding/pull/1072)) -* **Java:** Bump `JUnit` to 5.13.1. -* **Java:** Bump `jqwik` to 1.9.3. - -## [1.35.3] - 2025-06-06 -### Changed -* **Java:** Publish release artifacts to Central Portal using OSSRH Staging API service. -* **Java:** Bump `Agrona` to 2.2.2. -* **Java:** Bump `Checkstyle` to 10.25.0. -* **Java:** Bump `Gradle` to 8.14.2. - -## [1.35.1] - 2025-06-02 -### Changed -* Bump `Agrona` to 2.2.1. -* Bump `JUnit` to 5.13.0. - -## [1.35.0] - 2025-05-26 -### Changed -* Update `Implementation-Vendor`. -* **Rust:** Elide explicit ActingVersion lifetime. ([#1053](https://github.com/aeron-io/simple-binary-encoding/pull/1053)) -* **CI:** Use `gradle/actions/setup-gradle` action for caching Gradle dependencies. -* **CI:** Enable JDK 24 GA build. -* **CI:** Simplify error log upload. -* **CI:** Remove Ubuntu 20.04 based builds. -* **CI:** Bump Go build to use 1.23.x and 1.24.x. -* Bump `Agrona` to 2.2.0. -* Bump `Gradle` to 8.14.1. -* Bump `Checkstyle` to 10.24.0. -* Bump `json` to 20250517. -* Bump `JUnit` to 5.12.2. -* Bump `Mockito` to 5.18.0. -* Bump `Shadow` to 8.3.6. -* Bump `Versions` to 0.52. - -### Fixed -* **Java:** include field 'deprecated' in ir encoding and decoding. -* **Java:** Adjust Java DTO Choice Set Access. ([#1064](https://github.com/aeron-io/simple-binary-encoding/issues/1064)) -* **Rust:** get proper version for composite types. ([#1058](https://github.com/aeron-io/simple-binary-encoding/pull/1058)) -* **C#:** Read NuGet package version from version file ([#1061](https://github.com/aeron-io/simple-binary-encoding/pull/1061)) -* **C#:** Enable dual build for netstandard2.0 & netstandard2.1. ([#1062](https://github.com/aeron-io/simple-binary-encoding/pull/1062)) - -## [1.34.1] - 2025-01-13 -### Changed -* Bump `json` to 20250107. -* Bump `Mockito` to 5.15.2. - -### Added -* **Doc:** Add `--add-opens java.base/jdk.internal.misc=ALL-UNNAMED` to the example execution. -* **Rust:** encoding primitive arrays now supports slice instead of array (issue [#1021](https://github.com/aeron-io/simple-binary-encoding/issues/)). ([#1040](https://github.com/aeron-io/simple-binary-encoding/pull/1040)) - -### Fixed -* **C++:** check for not wrapped state in `decodeLength()` when precedence checks are enabled. ([#1046](https://github.com/aeron-io/simple-binary-encoding/pull/1046)) -* **C++:** use `m_actingBlockLength` in `decodeLength()`. ([#1045](https://github.com/aeron-io/simple-binary-encoding/pull/1045)) - -## [1.34.0] - 2024-12-17 -### Changed -* **C++:** hide the m_codecStatePtr behind ifdefs to avoid overhead when precedence checking is disabled. ([#1036](https://github.com/aeron-io/simple-binary-encoding/pull/1036)) -* **C++:** use constexpr to define precedence checks lookup tables. -* **Rust:** Enhance enum supporting fromstr and display and into. ([#1020](https://github.com/aeron-io/simple-binary-encoding/pull/1020)) -* **Rust:** codegen of primitive enums now implement 'From' instead of 'Into'. ([#1029](https://github.com/aeron-io/simple-binary-encoding/pull/1029)) -* **Java:** Update Checkstyle rules and apply them. -* **Breaking:** Bump `Agrona` to 2.0.0. - _**Note:** `--add-opens java.base/jdk.internal.misc=ALL-UNNAMED` JVM option must be specified in order to generate codecs or use the generated Java classes. For example:_ - ```shell - $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-${SBE_TOOL_VERSION}.jar my-sbe-messages.xml - ``` -* Bump `Gradle` to 8.11.1. -* Bump `Checkstyle` to 10.21.0. -* Bump `ByteBuddy` to 1.15.11. -* Bump `JUnit` to 5.11.4. -* Bump `jqwik` to 1.9.2. - -### Added -* **C++:** Integrate std::span support for flyweight API. ([#1038](https://github.com/aeron-io/simple-binary-encoding/pull/1038), [#1027](https://github.com/aeron-io/simple-binary-encoding/pull/1027)) -* **Rust:** generate message schema level info in lib.rs. ([#1019](https://github.com/aeron-io/simple-binary-encoding/pull/1019)) - -### Fixed -* **C++:** Fix field precedence check issue [#1031](https://github.com/aeron-io/simple-binary-encoding/issues/1031). ([#1033](https://github.com/aeron-io/simple-binary-encoding/pull/1033)) -* **C++:** respect the package override option for C++ codecs and DTOs. ([#1024](https://github.com/aeron-io/simple-binary-encoding/pull/1024)) -* **C#:** respect the package override option for C# codecs and DTOs. ([#1024](https://github.com/aeron-io/simple-binary-encoding/pull/1024)) -* **Go:** Fix warning about used args in GolangFlyweightGenerator. -* **Rust:** Updated code generator to resolve Issue [#1028](https://github.com/aeron-io/simple-binary-encoding/issues/1028). ([#1037](https://github.com/aeron-io/simple-binary-encoding/pull/1037)) -* **Java:** Prevent collision when field name is 'value'. -* **Java:** Preserve byte order throughout IR transformations. - -[1.35.6]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.6 -[1.35.5]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.5 -[1.35.4]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.4 -[1.35.3]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.3 -[1.35.1]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.1 -[1.35.0]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.0 -[1.34.1]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.34.1 -[1.34.0]: https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.34.0 From 71a8ada4de2801156c3fedfaed145a7f98af1222 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 12:31:13 +0200 Subject: [PATCH 1453/1594] [Doc] Add release notes. --- CHANGELOG.adoc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 8b41172297..f0fc9cc19c 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,5 +1,26 @@ = Changelog +== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.36.0[1.36.0] - 2025-09-29 + +* **[C{plus}{plus}]** Fix composite encode generation to use formatted property names, i.e. escape keywords. +* **[C{plus}{plus}]** Fix property name usage in display code generator. +* **[C{plus}{plus}]** Add getter for schema id on the `IrDecoder` (https://github.com/aeron-io/simple-binary-encoding/pull/1077[#1077]) +* **[Java]** Fix var data and composite code generation to use property name instead of plain name. Also use property name for access order check methods. (https://github.com/aeron-io/simple-binary-encoding/issues/1081[#1081]) +* **[Java]** Handle `null` values when encoding enums, i.e. use `Enum.NULL_VAL` if the value was not assigned. +* **[Java]** Handle primitive arrays correctly in the generated DTO code. +* **[Go]** Handle `_` and `String` as keywords and use property name when generating variable data section. +* **[C#]** Replaced empty array creation by `Array.Empty`, issue (https://github.com/aeron-io/simple-binary-encoding/issues/1079[#1079]). (https://github.com/aeron-io/simple-binary-encoding/pull/1080[#1080]) +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.3.0[Agrona 2.3.0]. +* **[Java]** Upgrade to `JUnit` 5.13.4. +* **[Java]** Upgrade to `Mockito` 5.20.0. +* **[Java]** Upgrade to `Checkstyle` 11.1.0. +* **[Java]** Upgrade to `Shadow` 9.2.2. +* **[Java]** Upgrade to `Version` 0.53.0. +* **[C]** Upgrade to `GoogleTest` to 1.14.0. +* **[C]** Bump minimium required CMake version to `3.30`. +* **[CI]** Add `Clang` 21 to the build matrix. +* **[CI]** Add `Java` 25 to the build matrix. + == https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.6[1.35.6] - 2025-06-27 * **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.4[Agrona 2.2.4]. From 1f6ec0e59e17f105dd666f76a6d6dcfcf883af14 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 12:54:51 +0200 Subject: [PATCH 1454/1594] [Java] Preserve `packageName` in the IR. Fixes #1089. --- .../uk/co/real_logic/sbe/ir/IrDecoder.java | 3 + .../uk/co/real_logic/sbe/ir/IrEncoder.java | 3 + .../sbe/ir/generated/TokenCodecDecoder.java | 167 ++++++++++++++++++ .../sbe/ir/generated/TokenCodecEncoder.java | 113 +++++++++++- sbe-tool/src/main/resources/sbe-ir.xml | 1 + .../sbe/ir/BasicXmlIrGenerationTest.java | 2 +- .../co/real_logic/sbe/ir/EncodedIrTest.java | 14 +- 7 files changed, 300 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java index 63881c0ae7..7bd1ed693d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrDecoder.java @@ -266,6 +266,9 @@ private Token decodeToken() final String referencedName = tokenDecoder.referencedName(); tokenBuilder.referencedName(referencedName.isEmpty() ? null : referencedName); + final String packageName = tokenDecoder.packageName(); + tokenBuilder.packageName(packageName.isEmpty() ? null : packageName); + offset += tokenDecoder.encodedLength(); return tokenBuilder.encoding(encBuilder.build()).build(); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java index 756f0829ab..ad5888b95a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/IrEncoder.java @@ -223,6 +223,9 @@ private int encodeToken(final Token token) final byte[] referencedNameBytes = getBytes(token.referencedName(), referencedNameCharacterEncoding()); tokenEncoder.putReferencedName(referencedNameBytes, 0, referencedNameBytes.length); + + final byte[] packageNameBytes = getBytes(token.packageName(), packageNameCharacterEncoding()); + tokenEncoder.putPackageName(packageNameBytes, 0, packageNameBytes.length); } catch (final UnsupportedEncodingException ex) { diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java index 7b2e69831b..ea9144e0b8 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecDecoder.java @@ -59,6 +59,8 @@ public final class TokenCodecDecoder * V0_SEMANTICTYPE_DONE -> V0_DESCRIPTION_DONE [label=" description(?) "]; * V0_DESCRIPTION_DONE -> V0_DESCRIPTION_DONE [label=" referencedNameLength() "]; * V0_DESCRIPTION_DONE -> V0_REFERENCEDNAME_DONE [label=" referencedName(?) "]; + * V0_REFERENCEDNAME_DONE -> V0_REFERENCEDNAME_DONE [label=" packageNameLength() "]; + * V0_REFERENCEDNAME_DONE -> V0_PACKAGENAME_DONE [label=" packageName(?) "]; * } * } */ @@ -77,6 +79,7 @@ private static class CodecStates private static final int V0_SEMANTICTYPE_DONE = 10; private static final int V0_DESCRIPTION_DONE = 11; private static final int V0_REFERENCEDNAME_DONE = 12; + private static final int V0_PACKAGENAME_DONE = 13; private static final String[] STATE_NAME_LOOKUP = { @@ -93,6 +96,7 @@ private static class CodecStates "V0_SEMANTICTYPE_DONE", "V0_DESCRIPTION_DONE", "V0_REFERENCEDNAME_DONE", + "V0_PACKAGENAME_DONE", }; private static final String[] STATE_TRANSITIONS_LOOKUP = @@ -109,6 +113,7 @@ private static class CodecStates "\"semanticTypeLength()\", \"semanticType(?)\"", "\"descriptionLength()\", \"description(?)\"", "\"referencedNameLength()\", \"referencedName(?)\"", + "\"packageNameLength()\", \"packageName(?)\"", "", }; @@ -2667,6 +2672,164 @@ public String referencedName() return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); } + public static int packageNameId() + { + return 22; + } + + public static int packageNameSinceVersion() + { + return 0; + } + + public static String packageNameCharacterEncoding() + { + return java.nio.charset.StandardCharsets.UTF_8.name(); + } + + public static String packageNameMetaAttribute(final MetaAttribute metaAttribute) + { + if (MetaAttribute.PRESENCE == metaAttribute) + { + return "required"; + } + + return ""; + } + + public static int packageNameHeaderLength() + { + return 2; + } + + void onPackageNameLengthAccessed() + { + switch (codecState()) + { + case CodecStates.V0_REFERENCEDNAME_DONE: + codecState(CodecStates.V0_REFERENCEDNAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot decode length of var data \"packageName\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + + private void onPackageNameAccessed() + { + switch (codecState()) + { + case CodecStates.V0_REFERENCEDNAME_DONE: + codecState(CodecStates.V0_PACKAGENAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"packageName\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecDecoder#CodecStates."); + } + } + + public int packageNameLength() + { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameLengthAccessed(); + } + + final int limit = parentMessage.limit(); + return (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); + } + + public int skipPackageName() + { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); + final int dataOffset = limit + headerLength; + parentMessage.limit(dataOffset + dataLength); + + return dataLength; + } + + public int getPackageName(final MutableDirectBuffer dst, final int dstOffset, final int length) + { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); + final int bytesCopied = Math.min(length, dataLength); + parentMessage.limit(limit + headerLength + dataLength); + buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); + + return bytesCopied; + } + + public int getPackageName(final byte[] dst, final int dstOffset, final int length) + { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); + final int bytesCopied = Math.min(length, dataLength); + parentMessage.limit(limit + headerLength + dataLength); + buffer.getBytes(limit + headerLength, dst, dstOffset, bytesCopied); + + return bytesCopied; + } + + public void wrapPackageName(final DirectBuffer wrapBuffer) + { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); + parentMessage.limit(limit + headerLength + dataLength); + wrapBuffer.wrap(buffer, limit + headerLength, dataLength); + } + + public String packageName() + { + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + + final int headerLength = 2; + final int limit = parentMessage.limit(); + final int dataLength = (buffer.getShort(limit, BYTE_ORDER) & 0xFFFF); + parentMessage.limit(limit + headerLength + dataLength); + + if (0 == dataLength) + { + return ""; + } + + final byte[] tmp = new byte[dataLength]; + buffer.getBytes(limit + headerLength, tmp, 0, dataLength); + + return new String(tmp, java.nio.charset.StandardCharsets.UTF_8); + } + public String toString() { if (null == buffer) @@ -2770,6 +2933,9 @@ public StringBuilder appendTo(final StringBuilder builder) builder.append('|'); builder.append("referencedName="); builder.append('\'').append(referencedName()).append('\''); + builder.append('|'); + builder.append("packageName="); + builder.append('\'').append(packageName()).append('\''); limit(originalLimit); @@ -2790,6 +2956,7 @@ public TokenCodecDecoder sbeSkip() skipSemanticType(); skipDescription(); skipReferencedName(); + skipPackageName(); return this; } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java index 9e201cbf52..057e7f129d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java @@ -59,6 +59,8 @@ public final class TokenCodecEncoder * V0_SEMANTICTYPE_DONE -> V0_DESCRIPTION_DONE [label=" description(?) "]; * V0_DESCRIPTION_DONE -> V0_DESCRIPTION_DONE [label=" referencedNameLength() "]; * V0_DESCRIPTION_DONE -> V0_REFERENCEDNAME_DONE [label=" referencedName(?) "]; + * V0_REFERENCEDNAME_DONE -> V0_REFERENCEDNAME_DONE [label=" packageNameLength() "]; + * V0_REFERENCEDNAME_DONE -> V0_PACKAGENAME_DONE [label=" packageName(?) "]; * } * } */ @@ -77,6 +79,7 @@ private static class CodecStates private static final int V0_SEMANTICTYPE_DONE = 10; private static final int V0_DESCRIPTION_DONE = 11; private static final int V0_REFERENCEDNAME_DONE = 12; + private static final int V0_PACKAGENAME_DONE = 13; private static final String[] STATE_NAME_LOOKUP = { @@ -93,6 +96,7 @@ private static class CodecStates "V0_SEMANTICTYPE_DONE", "V0_DESCRIPTION_DONE", "V0_REFERENCEDNAME_DONE", + "V0_PACKAGENAME_DONE", }; private static final String[] STATE_TRANSITIONS_LOOKUP = @@ -109,6 +113,7 @@ private static class CodecStates "\"semanticTypeLength()\", \"semanticType(?)\"", "\"descriptionLength()\", \"description(?)\"", "\"referencedNameLength()\", \"referencedName(?)\"", + "\"packageNameLength()\", \"packageName(?)\"", "", }; @@ -2009,6 +2014,112 @@ public TokenCodecEncoder referencedName(final String value) return this; } + public static int packageNameId() + { + return 22; + } + + public static String packageNameCharacterEncoding() + { + return java.nio.charset.StandardCharsets.UTF_8.name(); + } + + public static String packageNameMetaAttribute(final MetaAttribute metaAttribute) + { + if (MetaAttribute.PRESENCE == metaAttribute) + { + return "required"; + } + + return ""; + } + + public static int packageNameHeaderLength() + { + return 2; + } + + private void onPackageNameAccessed() + { + switch (codecState()) + { + case CodecStates.V0_REFERENCEDNAME_DONE: + codecState(CodecStates.V0_PACKAGENAME_DONE); + break; + default: + throw new IllegalStateException("Illegal field access order. " + + "Cannot access field \"packageName\" in state: " + CodecStates.name(codecState()) + + ". Expected one of these transitions: [" + CodecStates.transitions(codecState()) + + "]. Please see the diagram in the Javadoc of the class TokenCodecEncoder#CodecStates."); + } + } + + public TokenCodecEncoder putPackageName(final DirectBuffer src, final int srcOffset, final int length) + { + if (length > 65534) + { + throw new IllegalStateException("length > maxValue for type: " + length); + } + + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + + final int headerLength = 2; + final int limit = parentMessage.limit(); + parentMessage.limit(limit + headerLength + length); + buffer.putShort(limit, (short)length, BYTE_ORDER); + buffer.putBytes(limit + headerLength, src, srcOffset, length); + + return this; + } + + public TokenCodecEncoder putPackageName(final byte[] src, final int srcOffset, final int length) + { + if (length > 65534) + { + throw new IllegalStateException("length > maxValue for type: " + length); + } + + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + + final int headerLength = 2; + final int limit = parentMessage.limit(); + parentMessage.limit(limit + headerLength + length); + buffer.putShort(limit, (short)length, BYTE_ORDER); + buffer.putBytes(limit + headerLength, src, srcOffset, length); + + return this; + } + + public TokenCodecEncoder packageName(final String value) + { + final byte[] bytes = (null == value || value.isEmpty()) ? org.agrona.collections.ArrayUtil.EMPTY_BYTE_ARRAY : value.getBytes(java.nio.charset.StandardCharsets.UTF_8); + + final int length = bytes.length; + if (length > 65534) + { + throw new IllegalStateException("length > maxValue for type: " + length); + } + + if (SBE_ENABLE_IR_PRECEDENCE_CHECKS) + { + onPackageNameAccessed(); + } + + final int headerLength = 2; + final int limit = parentMessage.limit(); + parentMessage.limit(limit + headerLength + length); + buffer.putShort(limit, (short)length, BYTE_ORDER); + buffer.putBytes(limit + headerLength, bytes, 0, length); + + return this; + } + public String toString() { if (null == buffer) @@ -2038,7 +2149,7 @@ public void checkEncodingIsComplete() { switch (codecState) { - case CodecStates.V0_REFERENCEDNAME_DONE: + case CodecStates.V0_PACKAGENAME_DONE: return; default: throw new IllegalStateException("Not fully encoded, current state: " + diff --git a/sbe-tool/src/main/resources/sbe-ir.xml b/sbe-tool/src/main/resources/sbe-ir.xml index 4b55318f53..d2941ca3bf 100644 --- a/sbe-tool/src/main/resources/sbe-ir.xml +++ b/sbe-tool/src/main/resources/sbe-ir.xml @@ -96,5 +96,6 @@ + diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java index 97faca7848..0d2edc2173 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/BasicXmlIrGenerationTest.java @@ -319,7 +319,7 @@ void shouldRegenerateIrWithSameByteOrder() throws Exception final MessageSchema schema = parse(in, ParserOptions.DEFAULT); final IrGenerator generator = new IrGenerator(); final Ir firstIr = generator.generate(schema); - final ByteBuffer firstIrOutputBuffer = ByteBuffer.allocate(8 * 1024); + final ByteBuffer firstIrOutputBuffer = ByteBuffer.allocate(16 * 1024); final int length; try (IrEncoder firstIrEncoder = new IrEncoder(firstIrOutputBuffer, firstIr)) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java index 122c0ef41d..c353a02d31 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/ir/EncodedIrTest.java @@ -166,7 +166,18 @@ void shouldDecodeHeader() throws Exception @Test void shouldDecodeMessagesAndTypes() throws Exception { - try (InputStream in = Tests.getLocalResource("code-generation-schema.xml")) + testDecodeTypes("code-generation-schema.xml"); + } + + @Test + void shouldPreservePackageNames() throws Exception + { + testDecodeTypes("explicit-package-test-schema.xml"); + } + + private void testDecodeTypes(final String name1) throws Exception + { + try (InputStream in = Tests.getLocalResource(name1)) { final MessageSchema schema = parse(in, ParserOptions.DEFAULT); final IrGenerator irg = new IrGenerator(); @@ -216,6 +227,7 @@ void shouldDecodeMessagesAndTypes() throws Exception private void assertEqual(final Token lhs, final Token rhs) { assertThat(lhs.name(), is(rhs.name())); + assertThat(lhs.packageName(), is(rhs.packageName())); assertThat(lhs.version(), is(rhs.version())); assertThat(lhs.offset(), is(rhs.offset())); assertThat((long)lhs.id(), is((long)rhs.id())); From 67bb9be306598794bb75e7050f6d7aea614b3830 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 13:10:52 +0200 Subject: [PATCH 1455/1594] [C++] Add `referencedName` and `packageName` to the `Token` definition. --- sbe-tool/src/main/cpp/otf/IrDecoder.h | 5 ++++- sbe-tool/src/main/cpp/otf/Token.h | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/cpp/otf/IrDecoder.h b/sbe-tool/src/main/cpp/otf/IrDecoder.h index 947d5c31e3..fb077cb30c 100644 --- a/sbe-tool/src/main/cpp/otf/IrDecoder.h +++ b/sbe-tool/src/main/cpp/otf/IrDecoder.h @@ -289,6 +289,9 @@ class IrDecoder tmpLen = tokenCodec.getReferencedName(tmpBuffer, sizeof(tmpBuffer)); std::string referencedName(tmpBuffer, tmpLen); + tmpLen = tokenCodec.getPackageName(tmpBuffer, sizeof(tmpBuffer)); + std::string packageName(tmpBuffer, tmpLen); + Encoding encoding( type, presence, @@ -302,7 +305,7 @@ class IrDecoder timeUnit, semanticType); - Token token(tokenOffset, id, version, tokenSize, componentTokenCount, signal, name, description, encoding); + Token token(tokenOffset, id, version, tokenSize, componentTokenCount, signal, name, description, encoding, referencedName, packageName); tokens->push_back(token); diff --git a/sbe-tool/src/main/cpp/otf/Token.h b/sbe-tool/src/main/cpp/otf/Token.h index 2855c2a86c..f5ba05e511 100644 --- a/sbe-tool/src/main/cpp/otf/Token.h +++ b/sbe-tool/src/main/cpp/otf/Token.h @@ -77,7 +77,10 @@ class Token Signal signal, std::string name, std::string description, - Encoding encoding) : + Encoding encoding, + std::string referencedName = "", + std::string packageName = "" + ) : m_offset(offset), m_fieldId(fieldId), m_version(version), @@ -86,7 +89,9 @@ class Token m_signal(signal), m_name(std::move(name)), m_description(std::move(description)), - m_encoding(std::move(encoding)) + m_encoding(std::move(encoding)), + m_referencedName(std::move(referencedName)), + m_packageName(std::move(packageName)) { } @@ -105,6 +110,16 @@ class Token return m_description; } + inline const std::string &referencedName() const + { + return m_referencedName; + } + + inline const std::string &packageName() const + { + return m_packageName; + } + inline std::int32_t fieldId() const { return m_fieldId; @@ -150,6 +165,8 @@ class Token const std::string m_name; const std::string m_description; const Encoding m_encoding; + const std::string m_referencedName; + const std::string m_packageName; }; }} From 04ea6358535a344fc29e0f69fd864b46877b5c9f Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 13:18:42 +0200 Subject: [PATCH 1456/1594] [C#] Fix typo. --- sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index 92f000cae5..7ba93c7bd0 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -412,7 +412,7 @@ private static boolean isSbeGolangIdentifierPart(final char c) "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", - "unsafe", "ushort", "using", "using static", "virtual", + "unsafe", "ushort", "using", "virtual", "void", "volatile", "while"); /** From a4c1ca1b557f7b53d9fcf9d53769c617978287f2 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 13:29:42 +0200 Subject: [PATCH 1457/1594] [Go] Add `packageName` to the `Token` definition. --- sbe-tool/src/main/golang/otf/irdecoder.go | 2 ++ sbe-tool/src/main/golang/otf/token.go | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/main/golang/otf/irdecoder.go b/sbe-tool/src/main/golang/otf/irdecoder.go index d90876e637..24a9e5efb7 100644 --- a/sbe-tool/src/main/golang/otf/irdecoder.go +++ b/sbe-tool/src/main/golang/otf/irdecoder.go @@ -164,6 +164,7 @@ func (decoder *IrDecoder) decodeAndAddToken(tokens *[]Token, offset uint64) uint semanticType := tokenCodec.GetSemanticTypeAsString() description := tokenCodec.GetDescriptionAsString() referencedName := tokenCodec.GetReferencedNameAsString() + packageName := tokenCodec.GetPackageNameAsString() encoding := NewEncoding( primitiveType, @@ -188,6 +189,7 @@ func (decoder *IrDecoder) decodeAndAddToken(tokens *[]Token, offset uint64) uint signal: signal, name: name, referencedName: referencedName, + packageName: packageName, description: description, encoding: encoding, } diff --git a/sbe-tool/src/main/golang/otf/token.go b/sbe-tool/src/main/golang/otf/token.go index 442b6d5d80..b2ef627d84 100644 --- a/sbe-tool/src/main/golang/otf/token.go +++ b/sbe-tool/src/main/golang/otf/token.go @@ -76,10 +76,15 @@ type Token struct { signal Signal name string referencedName string + packageName string description string encoding Encoding } +func (token Token) PackageName() string { + return token.packageName +} + func (token Token) ReferencedName() string { return token.referencedName } @@ -149,9 +154,11 @@ func (token Token) IsOptionalEncoding() bool { func (token Token) String() string { return fmt.Sprintf( - "Token{signal: %s, name: %s, description: %s, fieldId: %d, tokenVersion: %d, encoding: %s, encodedLength: %d, offset: %d, componentTokenCount: %d}", + "Token{signal: %s, name: %s, referencedName: %s, packageName: %s, description: %s, fieldId: %d, tokenVersion: %d, encoding: %s, encodedLength: %d, offset: %d, componentTokenCount: %d}", token.signal, token.name, + token.referencedName, + token.packageName, token.description, token.fieldId, token.version, From cd4841ababc93fb0d1369539f296f5c49582affc Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 13:34:37 +0200 Subject: [PATCH 1458/1594] [C/C++] Allow overriding Gradle wrapper location. Fixes #1091. --- CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 32f07dd810..ce164c285b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,8 +137,16 @@ file(GLOB_RECURSE SBE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/sbe-tool/src/main/java/*.java" ) +if (NOT DEFINED GRADLE_WRAPPER) + if (MSVC) + set(GRADLE_WRAPPER "gradlew.bat" CACHE INTERNAL "Location of the Gradle wrapper script") + else () + set(GRADLE_WRAPPER "./gradlew" CACHE INTERNAL "Location of the Gradle wrapper script") + endif () +endif () + add_custom_command(OUTPUT ${SBE_JAR} - COMMAND ./gradlew assemble -x javadoc --console=plain + COMMAND ${GRADLE_WRAPPER} assemble -x javadoc --console=plain DEPENDS ${SBE_SOURCES} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating SBE jar" From 8b49cf5dbc15a31d25aefae76de64544a3a92957 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 13:38:49 +0200 Subject: [PATCH 1459/1594] [Doc] Update release notes. --- CHANGELOG.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index f0fc9cc19c..7062e70ebb 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -10,6 +10,8 @@ * **[Java]** Handle primitive arrays correctly in the generated DTO code. * **[Go]** Handle `_` and `String` as keywords and use property name when generating variable data section. * **[C#]** Replaced empty array creation by `Array.Empty`, issue (https://github.com/aeron-io/simple-binary-encoding/issues/1079[#1079]). (https://github.com/aeron-io/simple-binary-encoding/pull/1080[#1080]) +* **[C/C{plus}{plus}]** Allow overriding Gradle wrapper location. (https://github.com/aeron-io/simple-binary-encoding/issues/1091[#1091]). +* **[Java/C{plus}{plus}/Go]** Preserve `packageName` in the IR. (https://github.com/aeron-io/simple-binary-encoding/issues/1089[#1089]) * **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.3.0[Agrona 2.3.0]. * **[Java]** Upgrade to `JUnit` 5.13.4. * **[Java]** Upgrade to `Mockito` 5.20.0. From 88e2c7533140a7021b94f87398e1f59a493e923c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 13:39:05 +0200 Subject: [PATCH 1460/1594] 1.36.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index aa69911fd7..39fc130ef8 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.36.0-SNAPSHOT +1.36.0 From d93e0a5057f2220d7ca5f9bdfe3dab08a8c16aa1 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 29 Sep 2025 13:39:16 +0200 Subject: [PATCH 1461/1594] post release bump. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 39fc130ef8..7991f09416 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.36.0 +1.37.0-SNAPSHOT From 34b27b599bab1a433c20984868378cf4e1ef68cf Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 30 Sep 2025 14:55:21 +0200 Subject: [PATCH 1462/1594] [Java] Bump `JUnit` to 6.0.0. --- gradle/libs.versions.toml | 2 +- .../co/real_logic/sbe/generation/java/QualifiedYieldTest.java | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 559965ee68..c8d66da919 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ httpcore = "4.4.14" jqwik = "1.9.3" jmh = "1.37" json = "20250517" -junit = "5.13.4" +junit = "6.0.0" mockito = "5.20.0" plexus = "3.3.0" shadow = "9.2.2" diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java index 5f0900a9f8..8906748ac8 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/QualifiedYieldTest.java @@ -20,8 +20,6 @@ import org.agrona.generation.CompilerUtil; import org.agrona.generation.StringWriterOutputManager; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledForJreRange; -import org.junit.jupiter.api.condition.JRE; import uk.co.real_logic.sbe.Tests; import uk.co.real_logic.sbe.ir.Ir; import uk.co.real_logic.sbe.xml.IrGenerator; @@ -44,7 +42,6 @@ public class QualifiedYieldTest private final StringWriterOutputManager outputManager = new StringWriterOutputManager(); @Test - @EnabledForJreRange(min = JRE.JAVA_17) void shouldGenerateValidJava() throws Exception { try (InputStream in = Tests.getLocalResource("issue910.xml")) From a972a5e78e3a1fe9c1ab29c31a5f13acb6af60ff Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 30 Sep 2025 15:17:42 +0200 Subject: [PATCH 1463/1594] [C++] Use common buffer size. --- sbe-tool/src/test/c/CodeGenTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index 6f2a195a11..4d33156149 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -1093,7 +1093,7 @@ void testUsageDescription(CGT(car_fuelFigures) *const fuelFigures, const std::st TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) { - char buffer[2048] = {}; + char buffer[BUFFER_LEN] = {}; CGT(car) carEncoder; CGT(car_reset)(&carEncoder, buffer, 0, sizeof(buffer), CGT(car_sbe_block_length)(), CGT(car_sbe_schema_version)()); @@ -1185,7 +1185,7 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) TEST_F(CodeGenTest, shouldAllowForMultipleIterations2) { - char buffer[2048] = {}; + char buffer[BUFFER_LEN] = {}; std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer)); std::uint64_t carEncodedLength = encodeCar( From f40270a516560e4d7b1015f3dfef3edd5eb24141 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 20 Oct 2025 17:37:05 +0200 Subject: [PATCH 1464/1594] [Java] Upgrade `Checkstyle` to 12.1.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c8d66da919..90aaac3a53 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.3.0" -checkstyle = "11.1.0" +checkstyle = "12.1.0" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From 8b2052e00c71b0cb90ec7e5f5e5fd2caf906261e Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 27 Oct 2025 21:07:07 +0100 Subject: [PATCH 1465/1594] [CI] Use temporary storage driver on Windows to speed up build. --- .github/workflows/ci.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7560413329..a2706d0b1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,6 +35,25 @@ jobs: java: [ '17', '21', '25' ] os: [ 'ubuntu-24.04', 'windows-latest', 'macos-15' ] steps: + - name: Use faster temporary storage (Windows) + if: runner.os == 'Windows' + run: | + $fast_dir = "D:\fast-dir" + New-Item -ItemType Directory -Path "$fast_dir" + New-Item -ItemType Directory -Path "$fast_dir\temp" + New-Item -ItemType Directory -Path "$fast_dir\.m2" + New-Item -ItemType Directory -Path "$fast_dir\.gradle" + + if (Test-Path "$env:userprofile\.m2") + { + Remove-Item "$env:userprofile\.m2" -Recurse + } + New-Item -ItemType SymbolicLink -Path "$env:userprofile\.m2" -Target "$fast_dir\.m2" + + echo "TMP=$fast_dir\temp" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + echo "TEMP=$fast_dir\temp" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + echo "M2_HOME=$fast_dir\.m2" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + echo "GRADLE_USER_HOME=$fast_dir\.gradle" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Checkout code uses: actions/checkout@v5 with: @@ -242,6 +261,24 @@ jobs: CC: cl CXX: cl steps: + - name: Use faster temporary storage (Windows) + run: | + $fast_dir = "D:\fast-dir" + New-Item -ItemType Directory -Path "$fast_dir" + New-Item -ItemType Directory -Path "$fast_dir\temp" + New-Item -ItemType Directory -Path "$fast_dir\.m2" + New-Item -ItemType Directory -Path "$fast_dir\.gradle" + + if (Test-Path "$env:userprofile\.m2") + { + Remove-Item "$env:userprofile\.m2" -Recurse + } + New-Item -ItemType SymbolicLink -Path "$env:userprofile\.m2" -Target "$fast_dir\.m2" + + echo "TMP=$fast_dir\temp" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + echo "TEMP=$fast_dir\temp" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + echo "M2_HOME=$fast_dir\.m2" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + echo "GRADLE_USER_HOME=$fast_dir\.gradle" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Checkout code uses: actions/checkout@v5 with: From edebd1dce2d8905897fa001a76905f6507b8bdc6 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 27 Oct 2025 21:21:37 +0100 Subject: [PATCH 1466/1594] [Java] Upgrade `Checkstyle` to 12.1.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 90aaac3a53..b757f613f2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.3.0" -checkstyle = "12.1.0" +checkstyle = "12.1.1" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From 6663c18cfdeb0e6f9d373c463102c9455ef80b07 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 27 Oct 2025 21:32:43 +0100 Subject: [PATCH 1467/1594] [CI] Upgrade to `setup-gradle` and `upload-artifact` to v5. --- .github/workflows/ci.yml | 18 +++++++++--------- .github/workflows/codeql.yml | 6 +++--- .github/workflows/release.yml | 2 +- .github/workflows/slow.yml | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2706d0b1e..ef58311b57 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,7 +81,7 @@ jobs: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Build with Gradle run: ./gradlew - name: Copy test logs @@ -92,7 +92,7 @@ jobs: ./gradlew tarTestLogs - name: Upload crash logs if: always() && steps.copy_test_logs.outputs.file == 'build/distributions/test_logs.tbz2' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: crash-logs-${{ matrix.os }}-java-${{ matrix.java }} path: ${{ steps.copy_test_logs.outputs.file }} @@ -124,7 +124,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Cache NuGet dependencies uses: actions/cache@v4 with: @@ -176,7 +176,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Build run: ./cppbuild/cppbuild @@ -214,7 +214,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Build run: ./cppbuild/cppbuild @@ -245,7 +245,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Build run: cmake --version && ./cppbuild/cppbuild @@ -294,7 +294,7 @@ jobs: echo "BUILD_JAVA_HOME=$env:JAVA_HOME" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Build run: cppbuild/cppbuild.cmd @@ -326,7 +326,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - run: ./gradlew runRustTests golang-build: @@ -357,7 +357,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Generate jar run: ./gradlew assemble - name: Run tests diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e4951b67f8..2efa60259b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -56,7 +56,7 @@ jobs: echo "BUILD_JAVA_VERSION=${{ matrix.java }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Initialize CodeQL uses: github/codeql-action/init@v3 @@ -114,7 +114,7 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Setup dotnet uses: actions/setup-dotnet@v5 @@ -169,7 +169,7 @@ jobs: echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Install compiler run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e643e54186..b33cf0c690 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,7 +37,7 @@ jobs: echo "BUILD_JAVA_HOME=${JAVA_HOME}" >> $GITHUB_ENV echo "BUILD_JAVA_VERSION=${{ env.JAVA_VERSION }}" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Publish with Gradle run: ./gradlew publish uploadArtifactsToCentralPortal env: diff --git a/.github/workflows/slow.yml b/.github/workflows/slow.yml index ae634eb04b..0961c7a9ef 100644 --- a/.github/workflows/slow.yml +++ b/.github/workflows/slow.yml @@ -57,7 +57,7 @@ jobs: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Setup dotnet uses: actions/setup-dotnet@v5 with: @@ -74,12 +74,12 @@ jobs: ./gradlew tarTestLogs - name: Upload crash logs if: always() && steps.copy_test_logs.outputs.file == 'build/distributions/test_logs.tbz2' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: crash-logs-${{ matrix.os }}-property-tests-java-${{matrix.java}}-dotnet-${{matrix.dotnet}} path: ${{ steps.copy_test_logs.outputs.file }} - name: Upload test results - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 if: always() with: name: property-tests From f472113efc7ffdf28b3364b93c894fb8de18ced4 Mon Sep 17 00:00:00 2001 From: Dmitry Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 28 Oct 2025 10:16:17 +0100 Subject: [PATCH 1468/1594] [CI] Simplify Windows `D:` drive usage. --- .github/workflows/ci.yml | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef58311b57..6c71672ec1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,22 +38,8 @@ jobs: - name: Use faster temporary storage (Windows) if: runner.os == 'Windows' run: | - $fast_dir = "D:\fast-dir" - New-Item -ItemType Directory -Path "$fast_dir" - New-Item -ItemType Directory -Path "$fast_dir\temp" - New-Item -ItemType Directory -Path "$fast_dir\.m2" - New-Item -ItemType Directory -Path "$fast_dir\.gradle" - - if (Test-Path "$env:userprofile\.m2") - { - Remove-Item "$env:userprofile\.m2" -Recurse - } - New-Item -ItemType SymbolicLink -Path "$env:userprofile\.m2" -Target "$fast_dir\.m2" - - echo "TMP=$fast_dir\temp" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - echo "TEMP=$fast_dir\temp" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - echo "M2_HOME=$fast_dir\.m2" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - echo "GRADLE_USER_HOME=$fast_dir\.gradle" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + echo "TMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + echo "TEMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Checkout code uses: actions/checkout@v5 with: @@ -263,22 +249,8 @@ jobs: steps: - name: Use faster temporary storage (Windows) run: | - $fast_dir = "D:\fast-dir" - New-Item -ItemType Directory -Path "$fast_dir" - New-Item -ItemType Directory -Path "$fast_dir\temp" - New-Item -ItemType Directory -Path "$fast_dir\.m2" - New-Item -ItemType Directory -Path "$fast_dir\.gradle" - - if (Test-Path "$env:userprofile\.m2") - { - Remove-Item "$env:userprofile\.m2" -Recurse - } - New-Item -ItemType SymbolicLink -Path "$env:userprofile\.m2" -Target "$fast_dir\.m2" - - echo "TMP=$fast_dir\temp" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - echo "TEMP=$fast_dir\temp" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - echo "M2_HOME=$fast_dir\.m2" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - echo "GRADLE_USER_HOME=$fast_dir\.gradle" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + echo "TMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + echo "TEMP=$env:RUNNER_TEMP" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - name: Checkout code uses: actions/checkout@v5 with: From f6914c26347709225c447a30d4fdd0e8433e35c4 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 28 Oct 2025 10:45:21 +0100 Subject: [PATCH 1469/1594] [CI] Use .NET 9 in codeql. --- .github/workflows/codeql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 2efa60259b..b5c633b1f1 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -83,7 +83,7 @@ jobs: fail-fast: false matrix: language: [ 'csharp' ] - dotnet: [ '10' ] + dotnet: [ '9' ] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 From 9367f9d608a62556a97cae9ca1fad0e936618518 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 3 Nov 2025 15:06:26 +0100 Subject: [PATCH 1470/1594] [Java] Upgrade to `JUnit` 6.0.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b757f613f2..96fc0881bb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ httpcore = "4.4.14" jqwik = "1.9.3" jmh = "1.37" json = "20250517" -junit = "6.0.0" +junit = "6.0.1" mockito = "5.20.0" plexus = "3.3.0" shadow = "9.2.2" From d0ae48ac4dc4e8dd6486eedb4507a0c23d6c0db2 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 3 Nov 2025 15:06:37 +0100 Subject: [PATCH 1471/1594] [Java] Upgrade to `Agrona` 2.3.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 96fc0881bb..41e68f43fb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.3.0" +agrona = "2.3.1" checkstyle = "12.1.1" commons-codec = "1.15" commons-lang3 = "3.8.1" From 582af43aaefef8fb8ac3be8b11b6f7303bab066f Mon Sep 17 00:00:00 2001 From: Nikolay Zdravkov Date: Mon, 3 Nov 2025 16:14:35 +0200 Subject: [PATCH 1472/1594] [C#] fix: handle case when valueRef is with enum type prefix (#1092) --- .../sbe/generation/csharp/CSharpGenerator.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index a5dc0b2354..81f323ef39 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -2069,6 +2069,18 @@ private CharSequence generateEnumProperty( if (fieldToken.isConstantEncoding()) { final String constValue = fieldToken.encoding().constValue().toString(); + + // If constValue already contains the type prefix (e.g., "filterType.TrailingDelta"), + // extract just the enum value name + final String enumValue; + if (constValue.contains(".")) + { + enumValue = constValue.substring(constValue.lastIndexOf('.') + 1); + } + else + { + enumValue = constValue; + } return String.format("\n" + "%1$s" + @@ -2076,13 +2088,14 @@ private CharSequence generateEnumProperty( indent + INDENT + "{\n" + indent + INDENT + INDENT + "get\n" + indent + INDENT + INDENT + "{\n" + - indent + INDENT + INDENT + INDENT + "return %4$s;\n" + + indent + INDENT + INDENT + INDENT + "return %4$s.%5$s;\n" + indent + INDENT + INDENT + "}\n" + indent + INDENT + "}\n\n", generateDocumentation(indent + INDENT, fieldToken), enumName, toUpperFirstChar(propertyName), - constValue); + enumName, + enumValue); } else { From 8c7c43fdd8939b5a011050cf41c5eac1e1e59a85 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 3 Nov 2025 15:30:40 +0100 Subject: [PATCH 1473/1594] [Java] Tidy up after #1092. --- .../sbe/generation/csharp/CSharpGenerator.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 81f323ef39..d3b063631a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -2069,18 +2069,10 @@ private CharSequence generateEnumProperty( if (fieldToken.isConstantEncoding()) { final String constValue = fieldToken.encoding().constValue().toString(); - + final int lastDotIndex = constValue.lastIndexOf('.'); // If constValue already contains the type prefix (e.g., "filterType.TrailingDelta"), // extract just the enum value name - final String enumValue; - if (constValue.contains(".")) - { - enumValue = constValue.substring(constValue.lastIndexOf('.') + 1); - } - else - { - enumValue = constValue; - } + final String enumValue = -1 == lastDotIndex ? constValue : constValue.substring(lastDotIndex + 1); return String.format("\n" + "%1$s" + From 1428382a03aada1f9f58a5bd426be4caa9d56b3a Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 3 Nov 2025 15:55:51 +0100 Subject: [PATCH 1474/1594] [C#] Exclude generated sources. --- .gitignore | 14 ++------------ csharp/sbe-generated/mktdata/README.txt | 4 ---- 2 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 csharp/sbe-generated/mktdata/README.txt diff --git a/.gitignore b/.gitignore index c34ba580f9..554fcc27e0 100644 --- a/.gitignore +++ b/.gitignore @@ -85,18 +85,8 @@ csharp/*/bin csharp/*/obj csharp/.vs csharp/TestResults -csharp/sbe-generated/baseline -csharp/sbe-generated/baseline-bigendian -csharp/sbe-generated/extension -csharp/sbe-generated/issue435 -csharp/sbe-generated/issue483 -csharp/sbe-generated/issue560 -csharp/sbe-generated/issue661 -csharp/sbe-generated/since-deprecated -csharp/sbe-generated/order_check -csharp/sbe-generated/mktdata/*.cs -csharp/sbe-generated/uk_co_real_logic_sbe_benchmarks_fix -csharp/sbe-generated/test_message_schema +csharp/sbe-generated/ +!csharp/sbe-generated/sbe-generated.csproj csharp/sbe-tests/*.sbe csharp/nuget/ csharp/csharp.sln.DotSettings.user diff --git a/csharp/sbe-generated/mktdata/README.txt b/csharp/sbe-generated/mktdata/README.txt deleted file mode 100644 index 606c4c5376..0000000000 --- a/csharp/sbe-generated/mktdata/README.txt +++ /dev/null @@ -1,4 +0,0 @@ -The csharp code can be regenerated via the top level gradle environment. - -The FixBinary specification is from: ftp://ftp.cmegroup.com/SBEFix/NRCert/Templates/ and is -kept locally ~sbe-tool/src/test/resources/FixBinary.xml From f270f66d2d28634b8488bf42d9f38abec986edae Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 3 Nov 2025 17:31:03 +0100 Subject: [PATCH 1475/1594] [C#] Add tests for #1092. --- .../sbe/generation/cpp/CppGeneratorTest.java | 31 +++++++++++++++++ .../csharp/CSharpGeneratorTest.java | 33 +++++++++++++++++++ ...atorTest.java => GolangGeneratorTest.java} | 33 +++++++++++++++++-- .../generation/java/JavaGeneratorTest.java | 15 +++++++++ .../test/resources/code-generation-schema.xml | 7 ++++ 5 files changed, 117 insertions(+), 2 deletions(-) rename sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/{GolangStructGeneratorTest.java => GolangGeneratorTest.java} (93%) diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java index 6d4990df3b..2cdb37ecce 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppGeneratorTest.java @@ -140,4 +140,35 @@ void shouldUseConstexprWhenDefiningPrecedenceChecksLookupTables() throws Excepti assertThat(source, containsString("static constexpr const char *STATE_TRANSITIONS_LOOKUP[] =")); } } + + @Test + void shouldHandleLowerCaseEnumValueReference() throws Exception + { + try (InputStream in = Tests.getLocalResource("code-generation-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + + final CppGenerator generator = new CppGenerator( + ir, + false, + PrecedenceChecks.newInstance(new PrecedenceChecks.Context().shouldGeneratePrecedenceChecks(true)), + false, + outputManager); + generator.generate(); + + final java.util.Map sources = outputManager.getSources(); + final String source = sources.get("code.generation.test.LowerCaseValueRef").toString(); + assertThat(source, containsString(""" + SBE_NODISCARD LowerCaseEnum::Value x() const + { + return LowerCaseEnum::Value::TwO; + } + """)); + } + } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java index e78952d1d2..d19639b2fd 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpGeneratorTest.java @@ -72,4 +72,37 @@ void dtosShouldReferenceTypesInDifferentPackages() throws Exception assertThat(source, containsString("using Test.Message.Schema.Common;")); } } + + @Test + void shouldGenerateValidCode() throws Exception + { + try (InputStream in = Tests.getLocalResource("code-generation-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + + final CSharpGenerator generator = new CSharpGenerator( + ir, + PrecedenceChecks.newInstance(new PrecedenceChecks.Context()), + true, + outputManager); + generator.generate(); + + final java.util.Map sources = outputManager.getSources(); + final String source = sources.get("code.generation.test.LowerCaseValueRef").toString(); + assertThat(source, containsString(""" + public LowerCaseEnum X + { + get + { + return LowerCaseEnum.TwO; + } + } + """)); + } + } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangStructGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java similarity index 93% rename from sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangStructGeneratorTest.java rename to sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java index aa578e2de9..f622f8081a 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangStructGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/golang/GolangGeneratorTest.java @@ -26,10 +26,12 @@ import java.io.InputStream; -import static org.junit.jupiter.api.Assertions.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertEquals; import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; -class GolangStructGeneratorTest +class GolangGeneratorTest { @Test @SuppressWarnings("MethodLength") @@ -485,4 +487,31 @@ void shouldUseUpperCaseTypeNamesWhenReferencingBitSet() throws Exception "}\n", messageSource); } } + + @Test + @SuppressWarnings("MethodLength") + void shouldHandleLowerCaseEnumValueReference() throws Exception + { + try (InputStream in = Tests.getLocalResource("code-generation-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + + final GolangGenerator generator = new GolangGenerator(ir, outputManager); + generator.generate(); + + final java.util.Map sources = outputManager.getSources(); + final String source = sources.get("code.generation.test.LowerCaseValueRef").toString(); + assertThat(source, containsString(""" + func LowerCaseValueRefInit(l *LowerCaseValueRef) { + \tl.X = LowerCaseEnum.TwO + \treturn + } + """)); + } + } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java index 4b50d633e6..e5d4a1f5a1 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorTest.java @@ -740,6 +740,21 @@ void shouldValidateNotImplementedReadOnlyBufferClass() () -> new JavaGenerator(ir, BUFFER_NAME, "java.nio.ByteBuffer", false, false, false, outputManager)); } + @Test + void shouldHandleLowerCaseEnumValueReference() throws Exception + { + generator().generate(); + + final java.util.Map sources = outputManager.getSources(); + final String source = sources.get("code.generation.test.LowerCaseValueRefDecoder").toString(); + assertThat(source, containsString(""" + public LowerCaseEnum x() + { + return LowerCaseEnum.TwO; + } + """)); + } + private Class compileCarEncoder() throws Exception { final String className = "CarEncoder"; diff --git a/sbe-tool/src/test/resources/code-generation-schema.xml b/sbe-tool/src/test/resources/code-generation-schema.xml index 2e530a3af5..b07106ba4d 100644 --- a/sbe-tool/src/test/resources/code-generation-schema.xml +++ b/sbe-tool/src/test/resources/code-generation-schema.xml @@ -74,6 +74,10 @@ 1 2 + + 0 + 5 + @@ -188,4 +192,7 @@ + + + From d8cd23580a28a8882fdfe1c67371051c1f168172 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 3 Nov 2025 17:41:24 +0100 Subject: [PATCH 1476/1594] [Doc] Format release notes. --- CHANGELOG.adoc | 142 ++++++++++++++++++++++++------------------------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 7062e70ebb..d5932da0a9 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,74 +1,74 @@ = Changelog -== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.36.0[1.36.0] - 2025-09-29 - -* **[C{plus}{plus}]** Fix composite encode generation to use formatted property names, i.e. escape keywords. -* **[C{plus}{plus}]** Fix property name usage in display code generator. -* **[C{plus}{plus}]** Add getter for schema id on the `IrDecoder` (https://github.com/aeron-io/simple-binary-encoding/pull/1077[#1077]) -* **[Java]** Fix var data and composite code generation to use property name instead of plain name. Also use property name for access order check methods. (https://github.com/aeron-io/simple-binary-encoding/issues/1081[#1081]) -* **[Java]** Handle `null` values when encoding enums, i.e. use `Enum.NULL_VAL` if the value was not assigned. -* **[Java]** Handle primitive arrays correctly in the generated DTO code. -* **[Go]** Handle `_` and `String` as keywords and use property name when generating variable data section. +== 1.36.0 (2025-09-29) + +* *[C{plus}{plus}]* Fix composite encode generation to use formatted property names, i.e. escape keywords. +* *[C{plus}{plus}]* Fix property name usage in display code generator. +* *[C{plus}{plus}]* Add getter for schema id on the `IrDecoder` (https://github.com/aeron-io/simple-binary-encoding/pull/1077[#1077]) +* *[Java]* Fix var data and composite code generation to use property name instead of plain name. Also use property name for access order check methods. (https://github.com/aeron-io/simple-binary-encoding/issues/1081[#1081]) +* *[Java]* Handle `null` values when encoding enums, i.e. use `Enum.NULL_VAL` if the value was not assigned. +* *[Java]* Handle primitive arrays correctly in the generated DTO code. +* *[Go]* Handle `_` and `String` as keywords and use property name when generating variable data section. * **[C#]** Replaced empty array creation by `Array.Empty`, issue (https://github.com/aeron-io/simple-binary-encoding/issues/1079[#1079]). (https://github.com/aeron-io/simple-binary-encoding/pull/1080[#1080]) -* **[C/C{plus}{plus}]** Allow overriding Gradle wrapper location. (https://github.com/aeron-io/simple-binary-encoding/issues/1091[#1091]). -* **[Java/C{plus}{plus}/Go]** Preserve `packageName` in the IR. (https://github.com/aeron-io/simple-binary-encoding/issues/1089[#1089]) -* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.3.0[Agrona 2.3.0]. -* **[Java]** Upgrade to `JUnit` 5.13.4. -* **[Java]** Upgrade to `Mockito` 5.20.0. -* **[Java]** Upgrade to `Checkstyle` 11.1.0. -* **[Java]** Upgrade to `Shadow` 9.2.2. -* **[Java]** Upgrade to `Version` 0.53.0. -* **[C]** Upgrade to `GoogleTest` to 1.14.0. -* **[C]** Bump minimium required CMake version to `3.30`. -* **[CI]** Add `Clang` 21 to the build matrix. -* **[CI]** Add `Java` 25 to the build matrix. - -== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.6[1.35.6] - 2025-06-27 - -* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.4[Agrona 2.2.4]. -* **[Java]** Upgrade to `JUnit` 5.13.2. -* **[Java]** Upgrade to `Checkstyle` 10.26.0. -* **[Java]** Upgrade to `Shadow` 8.3.7. - -== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.5[1.35.5] - 2025-06-20 +* *[C/C{plus}{plus}]* Allow overriding Gradle wrapper location. (https://github.com/aeron-io/simple-binary-encoding/issues/1091[#1091]). +* *[Java/C{plus}{plus}/Go]* Preserve `packageName` in the IR. (https://github.com/aeron-io/simple-binary-encoding/issues/1089[#1089]) +* *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.3.0[Agrona 2.3.0]. +* *[Java]* Upgrade to `JUnit` 5.13.4. +* *[Java]* Upgrade to `Mockito` 5.20.0. +* *[Java]* Upgrade to `Checkstyle` 11.1.0. +* *[Java]* Upgrade to `Shadow` 9.2.2. +* *[Java]* Upgrade to `Version` 0.53.0. +* *[C]* Upgrade to `GoogleTest` to 1.14.0. +* *[C]* Bump minimium required CMake version to `3.30`. +* *[CI]* Add `Clang` 21 to the build matrix. +* *[CI]* Add `Java` 25 to the build matrix. + +== 1.35.6 (2025-06-27) + +* *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.4[Agrona 2.2.4]. +* *[Java]* Upgrade to `JUnit` 5.13.2. +* *[Java]* Upgrade to `Checkstyle` 10.26.0. +* *[Java]* Upgrade to `Shadow` 8.3.7. + +== 1.35.5 (2025-06-20) * **[Java/C{plus}{plus}/C#]** Fix a bug in overzealous DTO validation. (https://github.com/aeron-io/simple-binary-encoding/pull/1073[#1073]) -* **[Java]** Improve JsonPrinter's conformance with the JSON specification (e.g., escaping control characters and using correct delimiters). -* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.3[Agrona 2.2.3]. +* *[Java]* Improve JsonPrinter's conformance with the JSON specification (e.g., escaping control characters and using correct delimiters). +* *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.3[Agrona 2.2.3]. -== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.4[1.35.4] - 2025-06-12 +== 1.35.4 (2025-06-12) -* **[Rust]** Return None for optional primite field if its version is less than actingVersion. (https://github.com/aeron-io/simple-binary-encoding/pull/1067[#1067]) -* **[Java]** Adjust Java Dto generateComputeEncodedLength to acount for character encoding. (https://github.com/aeron-io/simple-binary-encoding/pull/1072[#1072]) -* **[Java]** Upgrade to `JUnit` 5.13.1. -* **[Java]** Upgrade to `jqwik` 1.9.3. +* *[Rust]* Return None for optional primite field if its version is less than actingVersion. (https://github.com/aeron-io/simple-binary-encoding/pull/1067[#1067]) +* *[Java]* Adjust Java Dto generateComputeEncodedLength to account for character encoding. (https://github.com/aeron-io/simple-binary-encoding/pull/1072[#1072]) +* *[Java]* Upgrade to `JUnit` 5.13.1. +* *[Java]* Upgrade to `jqwik` 1.9.3. -== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.3[1.35.3] - 2025-06-06 +== 1.35.3 (2025-06-06) -* **[Java]** Publish release artifacts to Central Portal using OSSRH Staging API service. -* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.2[Agrona 2.2.2]. -* **[Java]** Upgrade to `Checkstyle` 10.25.0. -* **[Java]** Upgrade to `Gradle` 8.14.2. +* *[Java]* Publish release artifacts to Central Portal using OSSRH Staging API service. +* *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.2[Agrona 2.2.2]. +* *[Java]* Upgrade to `Checkstyle` 10.25.0. +* *[Java]* Upgrade to `Gradle` 8.14.2. -== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.1[1.35.1] - 2025-06-02 +== 1.35.1 (2025-06-02) * Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.1[Agrona 2.2.1]. * Upgrade to `JUnit` 5.13.0. -== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.35.0[1.35.0] - 2025-05-26 +== 1.35.0 (2025-05-26) -* **[Java]** include field 'deprecated' in ir encoding and decoding. -* **[Java]** Adjust Java DTO Choice Set Access. (https://github.com/aeron-io/simple-binary-encoding/issues/1064[#1064]) -* **[Rust]** get proper version for composite types. (https://github.com/aeron-io/simple-binary-encoding/pull/1058[#1058]) +* *[Java]* include field 'deprecated' in ir encoding and decoding. +* *[Java]* Adjust Java DTO Choice Set Access. (https://github.com/aeron-io/simple-binary-encoding/issues/1064[#1064]) +* *[Rust]* get proper version for composite types. (https://github.com/aeron-io/simple-binary-encoding/pull/1058[#1058]) * **[C#]** Read NuGet package version from version file (https://github.com/aeron-io/simple-binary-encoding/pull/1061[#1061]) * **[C#]** Enable dual build for netstandard2.0 & netstandard2.1. (https://github.com/aeron-io/simple-binary-encoding/pull/1062[#1062]) * Update `Implementation-Vendor`. -* **[Rust]** Elide explicit ActingVersion lifetime. (https://github.com/aeron-io/simple-binary-encoding/pull/1053[#1053]) -* **[CI]** Use `gradle/actions/setup-gradle` action for caching Gradle dependencies. -* **[CI]** Enable JDK 24 GA build. -* **[CI]** Simplify error log upload. -* **[CI]** Remove Ubuntu 20.04 based builds. -* **[CI]** Bump Go build to use 1.23.x and 1.24.x. +* *[Rust]* Elide explicit ActingVersion lifetime. (https://github.com/aeron-io/simple-binary-encoding/pull/1053[#1053]) +* *[CI]* Use `gradle/actions/setup-gradle` action for caching Gradle dependencies. +* *[CI]* Enable JDK 24 GA build. +* *[CI]* Simplify error log upload. +* *[CI]* Remove Ubuntu 20.04 based builds. +* *[CI]* Bump Go build to use 1.23.x and 1.24.x. * Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.0[Agrona 2.2.0]. * Upgrade to `Gradle` 8.14.1. * Upgrade to `Checkstyle` 10.24.0. @@ -78,22 +78,22 @@ * Upgrade to `Shadow` 8.3.6. * Bump `Versions` to 0.52. -== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.34.1[1.34.1] - 2025-01-13 +== 1.34.1 (2025-01-13) * *Doc:* Add `--add-opens java.base/jdk.internal.misc=ALL-UNNAMED` to the example execution. -* **[Rust]** encoding primitive arrays now supports slice instead of array (issue https://github.com/aeron-io/simple-binary-encoding/issues/[#1021]). (https://github.com/aeron-io/simple-binary-encoding/pull/1040[#1040]) -* **[C{plus}{plus}]** check for not wrapped state in `decodeLength()` when precedence checks are enabled. (https://github.com/aeron-io/simple-binary-encoding/pull/1046[#1046]) -* **[C{plus}{plus}]** use `m_actingBlockLength` in `decodeLength()`. (https://github.com/aeron-io/simple-binary-encoding/pull/1045[#1045]) +* *[Rust]* encoding primitive arrays now supports slice instead of array (issue https://github.com/aeron-io/simple-binary-encoding/issues/[#1021]). (https://github.com/aeron-io/simple-binary-encoding/pull/1040[#1040]) +* *[C{plus}{plus}]* check for not wrapped state in `decodeLength()` when precedence checks are enabled. (https://github.com/aeron-io/simple-binary-encoding/pull/1046[#1046]) +* *[C{plus}{plus}]* use `m_actingBlockLength` in `decodeLength()`. (https://github.com/aeron-io/simple-binary-encoding/pull/1045[#1045]) * Bump `json` to 20250107. * Upgrade to `Mockito` 5.15.2. -== https://github.com/aeron-io/simple-binary-encoding/releases/tag/1.34.0[1.34.0] - 2024-12-17 +== 1.34.0 (2024-12-17) -* **[C{plus}{plus}]** hide the m_codecStatePtr behind ifdefs to avoid overhead when precedence checking is disabled. (https://github.com/aeron-io/simple-binary-encoding/pull/1036[#1036]) -* **[C{plus}{plus}]** use constexpr to define precedence checks lookup tables. -* **[Rust]** Enhance enum supporting fromstr and display and into. (https://github.com/aeron-io/simple-binary-encoding/pull/1020[#1020]) -* **[Rust]** codegen of primitive enums now implement 'From' instead of 'Into'. (https://github.com/aeron-io/simple-binary-encoding/pull/1029[#1029]) -* **[Java]** Update Checkstyle rules and apply them. +* *[C{plus}{plus}]* hide the m_codecStatePtr behind ifdefs to avoid overhead when precedence checking is disabled. (https://github.com/aeron-io/simple-binary-encoding/pull/1036[#1036]) +* *[C{plus}{plus}]* use constexpr to define precedence checks lookup tables. +* *[Rust]* Enhance enum supporting fromstr and display and into. (https://github.com/aeron-io/simple-binary-encoding/pull/1020[#1020]) +* *[Rust]* codegen of primitive enums now implement 'From' instead of 'Into'. (https://github.com/aeron-io/simple-binary-encoding/pull/1029[#1029]) +* *[Java]* Update Checkstyle rules and apply them. * *Breaking:* Upgrade to `Agrona` 2.0.0. + _**Note:** `--add-opens java.base/jdk.internal.misc=ALL-UNNAMED` JVM option must be specified in order to generate codecs or use the generated Java classes. For example:_ @@ -103,15 +103,15 @@ _**Note:** `--add-opens java.base/jdk.internal.misc=ALL-UNNAMED` JVM option must $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-${SBE_TOOL_VERSION}.jar my-sbe-messages.xml ---- -* **[C{plus}{plus}]** Fix field precedence check issue https://github.com/aeron-io/simple-binary-encoding/issues/1031[#1031]. (https://github.com/aeron-io/simple-binary-encoding/pull/1033[#1033]) -* **[C{plus}{plus}]** respect the package override option for C{plus}{plus} codecs and DTOs. (https://github.com/aeron-io/simple-binary-encoding/pull/1024[#1024]) +* *[C{plus}{plus}]* Fix field precedence check issue https://github.com/aeron-io/simple-binary-encoding/issues/1031[#1031]. (https://github.com/aeron-io/simple-binary-encoding/pull/1033[#1033]) +* *[C{plus}{plus}]* respect the package override option for C{plus}{plus} codecs and DTOs. (https://github.com/aeron-io/simple-binary-encoding/pull/1024[#1024]) * **[C#]** respect the package override option for C# codecs and DTOs. (https://github.com/aeron-io/simple-binary-encoding/pull/1024[#1024]) -* **[Go]** Fix warning about used args in GolangFlyweightGenerator. -* **[Rust]** Updated code generator to resolve Issue https://github.com/aeron-io/simple-binary-encoding/issues/1028[#1028]. (https://github.com/aeron-io/simple-binary-encoding/pull/1037[#1037]) -* **[Java]** Prevent collision when field name is 'value'. -* **[Java]** Preserve byte order throughout IR transformations. -* **[C{plus}{plus}]** Integrate std::span support for flyweight API. (https://github.com/aeron-io/simple-binary-encoding/pull/1038[#1038], https://github.com/aeron-io/simple-binary-encoding/pull/1027[#1027]) -* **[Rust]** generate message schema level info in lib.rs. (https://github.com/aeron-io/simple-binary-encoding/pull/1019[#1019]) +* *[Go]* Fix warning about used args in GolangFlyweightGenerator. +* *[Rust]* Updated code generator to resolve Issue https://github.com/aeron-io/simple-binary-encoding/issues/1028[#1028]. (https://github.com/aeron-io/simple-binary-encoding/pull/1037[#1037]) +* *[Java]* Prevent collision when field name is 'value'. +* *[Java]* Preserve byte order throughout IR transformations. +* *[C{plus}{plus}]* Integrate std::span support for flyweight API. (https://github.com/aeron-io/simple-binary-encoding/pull/1038[#1038], https://github.com/aeron-io/simple-binary-encoding/pull/1027[#1027]) +* *[Rust]* generate message schema level info in lib.rs. (https://github.com/aeron-io/simple-binary-encoding/pull/1019[#1019]) * Upgrade to `Gradle` 8.11.1. * Upgrade to `Checkstyle` 10.21.0. * Upgrade to `ByteBuddy` 1.15.11. From 02f5a68bd54750d9a373ac10f9f0fc6bd38bcfdc Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 3 Nov 2025 17:58:50 +0100 Subject: [PATCH 1477/1594] [Doc] Complete release since the beginning of time. --- CHANGELOG.adoc | 1056 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1051 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index d5932da0a9..aac63dd520 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,5 +1,12 @@ = Changelog +== 1.36.1 (2025-11-03) + +* *[C#]* Handle case when `valueRef` is with enum type prefix. (https://github.com/aeron-io/simple-binary-encoding/pull/1092[#1092]) +* *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.3.1[Agrona 2.3.1]. +* *[Java]* Upgrade to `JUnit` 6.0.1. +* *[Java]* Upgrade to `Checkstyle` 12.1.1. + == 1.36.0 (2025-09-29) * *[C{plus}{plus}]* Fix composite encode generation to use formatted property names, i.e. escape keywords. @@ -9,7 +16,7 @@ * *[Java]* Handle `null` values when encoding enums, i.e. use `Enum.NULL_VAL` if the value was not assigned. * *[Java]* Handle primitive arrays correctly in the generated DTO code. * *[Go]* Handle `_` and `String` as keywords and use property name when generating variable data section. -* **[C#]** Replaced empty array creation by `Array.Empty`, issue (https://github.com/aeron-io/simple-binary-encoding/issues/1079[#1079]). (https://github.com/aeron-io/simple-binary-encoding/pull/1080[#1080]) +* *[C#]* Replaced empty array creation by `Array.Empty`, issue (https://github.com/aeron-io/simple-binary-encoding/issues/1079[#1079]). (https://github.com/aeron-io/simple-binary-encoding/pull/1080[#1080]) * *[C/C{plus}{plus}]* Allow overriding Gradle wrapper location. (https://github.com/aeron-io/simple-binary-encoding/issues/1091[#1091]). * *[Java/C{plus}{plus}/Go]* Preserve `packageName` in the IR. (https://github.com/aeron-io/simple-binary-encoding/issues/1089[#1089]) * *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.3.0[Agrona 2.3.0]. @@ -32,7 +39,7 @@ == 1.35.5 (2025-06-20) -* **[Java/C{plus}{plus}/C#]** Fix a bug in overzealous DTO validation. (https://github.com/aeron-io/simple-binary-encoding/pull/1073[#1073]) +* *[Java/C{plus}{plus}/C#]* Fix a bug in overzealous DTO validation. (https://github.com/aeron-io/simple-binary-encoding/pull/1073[#1073]) * *[Java]* Improve JsonPrinter's conformance with the JSON specification (e.g., escaping control characters and using correct delimiters). * *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.3[Agrona 2.2.3]. @@ -60,8 +67,8 @@ * *[Java]* include field 'deprecated' in ir encoding and decoding. * *[Java]* Adjust Java DTO Choice Set Access. (https://github.com/aeron-io/simple-binary-encoding/issues/1064[#1064]) * *[Rust]* get proper version for composite types. (https://github.com/aeron-io/simple-binary-encoding/pull/1058[#1058]) -* **[C#]** Read NuGet package version from version file (https://github.com/aeron-io/simple-binary-encoding/pull/1061[#1061]) -* **[C#]** Enable dual build for netstandard2.0 & netstandard2.1. (https://github.com/aeron-io/simple-binary-encoding/pull/1062[#1062]) +* *[C#]* Read NuGet package version from version file (https://github.com/aeron-io/simple-binary-encoding/pull/1061[#1061]) +* *[C#]* Enable dual build for netstandard2.0 & netstandard2.1. (https://github.com/aeron-io/simple-binary-encoding/pull/1062[#1062]) * Update `Implementation-Vendor`. * *[Rust]* Elide explicit ActingVersion lifetime. (https://github.com/aeron-io/simple-binary-encoding/pull/1053[#1053]) * *[CI]* Use `gradle/actions/setup-gradle` action for caching Gradle dependencies. @@ -105,7 +112,7 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru * *[C{plus}{plus}]* Fix field precedence check issue https://github.com/aeron-io/simple-binary-encoding/issues/1031[#1031]. (https://github.com/aeron-io/simple-binary-encoding/pull/1033[#1033]) * *[C{plus}{plus}]* respect the package override option for C{plus}{plus} codecs and DTOs. (https://github.com/aeron-io/simple-binary-encoding/pull/1024[#1024]) -* **[C#]** respect the package override option for C# codecs and DTOs. (https://github.com/aeron-io/simple-binary-encoding/pull/1024[#1024]) +* *[C#]* respect the package override option for C# codecs and DTOs. (https://github.com/aeron-io/simple-binary-encoding/pull/1024[#1024]) * *[Go]* Fix warning about used args in GolangFlyweightGenerator. * *[Rust]* Updated code generator to resolve Issue https://github.com/aeron-io/simple-binary-encoding/issues/1028[#1028]. (https://github.com/aeron-io/simple-binary-encoding/pull/1037[#1037]) * *[Java]* Prevent collision when field name is 'value'. @@ -117,3 +124,1042 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru * Upgrade to `ByteBuddy` 1.15.11. * Upgrade to `JUnit` 5.11.4. * Upgrade to `jqwik` 1.9.2. + +== 1.33.2 (2024-11-08) + +* *[Rust]* Help decoding multiple messages using rust by resolving https://github.com/aeron-io/simple-binary-encoding/issues/987[#987]. +* *[Go]* SBE implementation in Go using flyweights. +* *[Java]* DTOs respect the optional package field in the schema definition. +* *[Java]* Fix bug in DTO `decodeFrom` signature. + +== 1.33.1 (2024-09-23) + +* *[Java]* Fix #1012 DTO char array setter visibility. +* *[Rust]* Indicate the anonymous lifetime in set's Display impl (https://github.com/aeron-io/simple-binary-encoding/pull/1014[#1014]). +* *[Java]* Style consistency and add JavadocVariable Checkstyle test. +* *[Java]* Use version catalogs. +* *[Java]* Upgrade to JUnit 5.13.0. +* *[Java]* Upgrade to Gradle 8.10.1. +* *[Java]* Upgrade to Shadow 8.3.2. +* *[Java]* Upgrade to Checkstyle 10.18.1. + +== 1.33.0 (2024-08-24) + +=== Breaking changes + +* *JDK 17 is required for compiling and running!* + +=== Changelog + +* *[CI]* Execute tests using `ubuntu-24.04` and `macos-latest`. +* *[Java]* Upgrade to Agrona 1.23.0. +* *[Java]* Upgrade to Gradle 8.10. +* *[Java]* Upgrade to Shadow 8.3.0. +* *[Java]* Upgrade to Mockito 5.12.0. + +== 1.32.2 (2024-08-23) + +* *[Rust]* Generate imports in alphabetical order. #997 +* *[Rust]* Make Rust crate version configurable. #996 +* *[C]* fix compilation error in C string view functions. #1010 +* *[Java]* Upgrade to JUnit 5.11.0. + +== 1.32.1 (2024-08-05) + +* *[Java]* Upgrade to Agrona 1.22.0. +* *[Java]* Upgrade to Hamcrest 3.0. + +== 1.32.0 (2024-08-02) + +* [C#,C{plus}{plus},Java] Generate DTOs for non-perf-sensitive usecases. #957 +* [C{plus}{plus}, C#] Only generate range validation code when specifying a range smaller than the associate type. +* *[C#]* Fix ToString() to avoid state changes on message. #992 +* *[C]* Add a #define for each template id. #1006 +* [Java, C#, C{plus}{plus}] Check enum value for language specific keywords and apply `sbe.keyword.append.token` when appropriate. #1009 #1008 + +== 1.31.0 (2024-04-03) + +* *[Java]* Remove unused initialOffset member from generated codecs. +* *[Java]* Check for being in a composite when generating array access methods based on version. +* *[Java]* Captured types in IR should be for the minimum version used in a schema. https://github.com/aeron-io/simple-binary-encoding/pull/967[#967]. +* *[C{plus}{plus}]* Provide access to acting block length of repeating group via the sbeActingBlockLength() method. Issue #968. +* *[C{plus}{plus}]* message header members constexpr https://github.com/aeron-io/simple-binary-encoding/pull/971[#971]. +* *[C{plus}{plus}]* Code tidy up and address Issue #970. +* *[Java]* Cope with optional sets not being present when pretty printing decoders for debugging. https://github.com/aeron-io/simple-binary-encoding/pull/977[#977]. +* *[C{plus}{plus}]* small test fix https://github.com/aeron-io/simple-binary-encoding/pull/980[#980]. +* *[Rust]* Updated RustGenerator.generatePrimitiveOptionalDecoder() https://github.com/aeron-io/simple-binary-encoding/pull/981[#981]. +* *[Rust]* Take slices by reference https://github.com/aeron-io/simple-binary-encoding/pull/979[#979]. +* *[Rust]* updated code generator to prevent rust warning for "ambiguous glob re-exports" https://github.com/aeron-io/simple-binary-encoding/pull/982[#982]. +* *[Go]* Handle mixed case enums and BitSets. Fixes #983. +* *[Java]* Use `BYTE_ORDER` constant instead of accessing `java.nio.ByteOrder` directly. +* Upgrade .NET SDK to 8.0.201 (https://github.com/aeron-io/simple-binary-encoding/pull/978[#978]). +* *[Java]* Upgrade to Agrona 1.21.1. +* *[Java]* Upgrade to ASM 9.7. +* *[Java]* Upgrade to JUnit 5.10.2. +* *[Java]* Upgrade to Versions 0.51.0. + +== 1.30.0 (2023-12-06) + +* [Java, C{plus}{plus}, C#] Add support to https://github.com/aeron-io/simple-binary-encoding/wiki/Safe-Flyweight-Usage[check the safe usage of flyweights (w.r.t. field access order)]. https://github.com/aeron-io/simple-binary-encoding/pull/948[#948]. +* *[C#]* Fix invalid code generated when using some length types for var data https://github.com/aeron-io/simple-binary-encoding/issues/955[#955] +* *[Java]* Support valueRef with camelCase enum type identifiers https://github.com/aeron-io/simple-binary-encoding/pull/963[#963] +* *[Rust]* update how "use declarations" are generated, now deriving Defaults for enums https://github.com/aeron-io/simple-binary-encoding/pull/952[#952] +* *[C{plus}{plus}]* Rely on NAN from limits rather than pulling in cmath (https://github.com/aeron-io/simple-binary-encoding/issues/956) +* *[Java]* Fix javadoc link for JDK 21 GA +* *[Java]* Expose actingVersion https://github.com/aeron-io/simple-binary-encoding/pull/953[#953] +* Upgrade Agrona to 1.20.0 +* Upgrade to ASM 9.6 +* Upgrade to JMH 1.27 +* Upgrade to JUnit 5.10.1 +* Upgrade Versions to 0.50.0 + +== 1.29.0 (2023-07-21) + +* *[Rust]* Add derive Copy Clone traits for decoders (PR #940). +* *[Rust]* Fix clippy lint (PR #941). +* *[Rust]* Fix array syntax error (PR #946). +* *[Rust]* Improve rust performance (PR #944). +* JsonPrinter remove trailing garbage after non-printable char (PR #950). +* Upgrade to Agrona 1.19.0. +* Upgrade to versions 0.47.0. + +== 1.28.3 (2023-06-08) + +* CppGenerator: operator<< take messages as const-ref (PR #939) +* JDK 21-ea warning fixes. +* Upgrade to Agrona 1.18.2. +* Upgrade to JUnit 5.9.3. +* Upgrade to ASM 9.5 for JDK 21-ea support. +* Upgrade to Shadow 8.1.1. +* Upgrade to Gradle 8.1.1. + +== 1.28.2 (2023-04-17) + +* Upgrade to Agrona 1.18.1. + +== 1.28.1 (2023-03-29) + +* Fix SBE_SEMANTIC_VERSION field generation for C{plus}{plus}. + +== 1.28.0 (2023-03-29) + +* Added semantic version as a static public member. PR #931. +* *[Rust]* Nested composite name should not be based on field name. PR #922. +* *[C/C{plus}{plus}]* Prevent clashing defines in C/C{plus}{plus} codecs when multiple generated schemas are used. Issue #884. +* *[C#]* Compare `PrimitiveValue` with doubles in the same way as Java by the raw bits, so NaN and Infinity are correctly handled. +* Add CodeQL workflow. +* *[C#]* Add `ToString` for `PrimitiveType` +* *[C{plus}{plus}]* Pass by reference rather than value when streaming to a string. +* *[C{plus}{plus}]* Address duplicate guard issues. +* *[Java]* More efficient attribute parsing in XML with a more precise error message. +* *[Java]* Validate IR file for decoding is not greater than Integer.MAX_VALUE. +* *[C/C{plus}{plus}]* Move check for existing `SBE_BOUNDS_CHECK_EXPECT` define to outer condition to capture all platforms. +* *[Java]* Print warnings for undersize header fields. +* Upgrade to Agrona 1.18.0. +* Upgrade to Mockito 4.11.0. +* Upgrade to Junit 5.9.2. +* Upgrade to JMH 1.36. +* Upgrade to versions plugin 0.45.0. +* Upgrade to Gradle 7.6. + +== 1.27.0 (2022-10-11) + +* *[Java]* Add preview support for package override on types from SBE 2.0. https://github.com/aeron-io/simple-binary-encoding/pull/904[#904], https://github.com/aeron-io/simple-binary-encoding/pull/915[#915]. +* Add support for transforming a schema to generate code for older versions when checking compatibility. +* *[Java]* Support binary var data in `JsonPrinter`. https://github.com/aeron-io/simple-binary-encoding/pull/914[#914]. +* *[Java]* Qualify methods with name `yield` to avoid warning in Java 17. https://github.com/aeron-io/simple-binary-encoding/pull/910[#910]. +* Carry down the the `sinceVersion` value into composite types to make parsing OTF easier. https://github.com/aeron-io/simple-binary-encoding/issues/908[Issue #908]. +* Set the size for constant encoded data type to be zero in IR. +* Upgrade to Google Test 1.21.1. +* Upgrade to Mockito 4.7.0. +* Upgrade to JUnit 5.9.1. +* Upgrade to Gradle 7.5.1. +* Upgrade to Agrona 1.17.1. + +== 1.26.0 (2022-07-11) + +* *[Java]* Provide raw access to type for bitset. https://github.com/aeron-io/simple-binary-encoding/issues/893[Issue #893]. +* *[C{plus}{plus}]* Generate `skip` function with loop rather than lambda to avoid compilation errors on some compilers. https://github.com/aeron-io/simple-binary-encoding/issues/903[Issue #903]. +* Check `sinceVersion` is valid on elements against schema version. https://github.com/aeron-io/simple-binary-encoding/issues/902[Issue #902]. +* *[Rust]* Fix generated comparator when value is `NaN`. https://github.com/aeron-io/simple-binary-encoding/pull/896[#896]. +* *[Rust]* Fix resource leak in Rust generator running in Java SBE compiler. +* *[Java]* Generate `@SuppressWarnings` annotation on enums types. https://github.com/aeron-io/simple-binary-encoding/issues/894[Issue #894]. +* Upgrade to Mockito 4.6.1. +* Upgrade to Agrona 1.16.0. + +== 1.25.3 (2022-04-14) + +* Set correct version range for Agrona dependency check. +* Upgrade to Gradle 7.4.2. +* Upgrade to JMH 1.35. +* Upgrade to Agrona 1.15.1. + +== 1.25.2 (2022-03-18) + +* *[Java]* Calling `toString()` on decoder should not disturb repeating group. https://github.com/aeron-io/simple-binary-encoding/pull/892[#892]. +* *[All]* Generate `NULL_VALUE` for enums based on correct type. https://github.com/aeron-io/simple-binary-encoding/issues/889[Issue #889]. +* *[C{plus}{plus}]* Check for version before outputting to stream for composites and bitsets. https://github.com/aeron-io/simple-binary-encoding/pull/888[#888]. +* *[Java]* Charset handling improvements for more efficient string decoding. https://github.com/aeron-io/simple-binary-encoding/pull/887[#887]. +* Add descriptions to schema for IR. +* Set warnings as errors in build and clean up existing warnings. +* Add ability to set the error stream in `ParserOptions`. +* Remove some unnecessary checks in `XmlSchemaParser` to improve generation performance. +* Upgrade to Versions 0.42.0. +* Upgrade to Checkstyle 9.3. +* Upgrade to JMH 1.34. +* Upgrade to Mockito 4.4.0. +* Upgrade to Shadow 7.1.2. +* Upgrade to JUnit 5.8.2. +* Upgrade to Gradle 7.4.1. +* Upgrade to Agrona 1.15.0. + +== 1.25.1 (2021-11-24) + +* Upgrade to Mockito 4.1.0. +* Upgrade to Agrona 1.14.0. + +== 1.25.0 (2021-11-17) + +* *[C#]* Add support for wrapping `ArraySegment` in `DirectBuffer`. https://github.com/aeron-io/simple-binary-encoding/pull/878[#878]. +* *[Java]* Add `@Deprecated` annotation to message codecs that have been marked as deprecated in SBE schema. https://github.com/aeron-io/simple-binary-encoding/pull/876[#876]. +* *[C{plus}{plus}]* Only generate necessary macros and includes for enum types. +* *[Rust]* Reinstate improved Rust codec generation. +* *[Java]* Add `sbeSkip` and `sbeDecodedLength` methods to codecs. https://github.com/aeron-io/simple-binary-encoding/pull/865[#865]. +* Upgrade to JUnit 5.8.1. +* Upgrade to Shadow 7.1.0. +* Upgrade to Mockito 4.0.0. +* Upgrade to Checkstyle 9.1. +* Upgrade to JMH 1.33. +* Upgrade to Gradle 7.2. +* Upgrade to Agrona 1.13.0. + +== 1.24.0 (2021-08-06) + +* *[Java]* Improve efficiency of encoding `CharSequence` when ASCII character encoding is used. +* *[Java]* Check that IR codecs are regenerated on codec change. +* *[Java/C{plus}{plus}/C]* Add `sbeRewind` to decoders so they can rewind to the beginning of a message and begin decoding again. +* Upgrade to Google Test 1.11.0 +* Upgrade to ByteBuddy 1.11.3 +* Upgrade to Mockito 3.11.2. +* Upgrade to Gradle 7.1.1. +* Upgrade to Agrona 1.12.0. + +== 1.23.0 (2021-06-13) + +* *[C#]* Add `ToString()` method to generated codecs. https://github.com/aeron-io/simple-binary-encoding/pull/853[#853]. +* *[C#]* Add more string read and write methods to codecs. https://github.com/aeron-io/simple-binary-encoding/pull/845[#845]. +* *[Go]* Fix tokens passed when generating composites. https://github.com/aeron-io/simple-binary-encoding/pull/850[#850]. +* *[C/C{plus}{plus}]* Add Clang 12 to the matrix build. +* Upgrade to Versions 0.39.0. +* Upgrade to JUnit 5.7.2. +* Upgrade to Mockito 3.11.1. +* Upgrade to ByteBuddy 1.11.2. +* Upgrade to JMH 1.32. +* Upgrade to Shadow 7.0.0. +* Upgrade to Gradle 7.0.2. +* Upgrade to Agrona 1.11.0. + +== 1.22.0 (2021-04-16) + +* *[C#]* Convert benchmarks to use DotNetBenchmark. https://github.com/aeron-io/agrona/pull/841[#841]. +* *[C#]* Help compiler to inline `DirectBuffer.CheckLimit` for better performance. https://github.com/aeron-io/simple-binary-encoding/pull/840[#840]. +* Add Java 17-ea to the build matrix. +* Test with CME FixBinary version 9. +* *[C{plus}{plus}]* Capture `actingBlockLength` and use it for prettying printing output in version aware codecs. https://github.com/aeron-io/simple-binary-encoding/issues/839[Issue #839]. +* *[C{plus}{plus}]* Remove invalid use of `noexcept` on `resetCountToIndex`. https://github.com/aeron-io/simple-binary-encoding/issues/838[Issue #838]. +* *[Java]* Generate a `wrapAndApplyHeader` method for decoders to verify template then apply acting version and offset. +* *[C{plus}{plus}]* Clean up and improve samples. +* *[C{plus}{plus}]* Pass elements by reference rather than value in `forEach` for more efficient skip operations. +* Upgrade to Version 0.38.0. +* Upgrade to JMH 1.29. +* Upgrade to JUnit 5.7.1. +* Upgrade to Mockito 3.9.0. +* Upgrade to Gradle 6.8.3. +* Upgrade to Agrona 1.10.0. + +== 1.21.0 (2021-01-15) + +* *[Java]* Generate metadata methods to groups for min and max count values. https://github.com/aeron-io/simple-binary-encoding/pull/834[#834]. +* *[Java]* Declare generated classes as final to allow for better optimisation and increased performance. +* *[C{plus}{plus}]* Null terminate constant char arrays to avoid warnings. https://github.com/aeron-io/simple-binary-encoding/issues/832[Issue #832]. +* *[C{plus}{plus}]* Add support for decoding unknown enum values from later versions by enabling `sbe.decode.unknown.enum.values` and provide access to raw values. +* Clean up warnings in bash scripts. +* Upgrade to Checkstyle 8.39. +* Upgrade to Mockito 3.7.0. + +== 1.20.4 (2020-12-22) + +* Add parsing of CME iLink order protocol to tests. +* *[C{plus}{plus}]* Generate literal marked up for correct type when shifting for bitsets using `uint64`. https://github.com/aeron-io/simple-binary-encoding/pull/829[#829]. +* *[Java]* Generate `@return` in javadoc for bitset values. https://github.com/aeron-io/simple-binary-encoding/issues/828[Issue #828]. +* *[Java]* Escape basic HTML characters for javadoc. https://github.com/aeron-io/simple-binary-encoding/issues/826[Issue #826]. +* *[Go]* Fix decoding into struct with pre-allocated slices. https://github.com/aeron-io/simple-binary-encoding/pull/825[#825]. +* *[C{plus}{plus}]* Fix spelling of `_cplusplus` macro. https://github.com/aeron-io/simple-binary-encoding/issues/823[Issue #821]. +* *[C#]* Fix repeating group encode overflow. https://github.com/aeron-io/simple-binary-encoding/pull/823[#823]. +* *[C]* Fix argument order for wrap_and_apply_header methods. https://github.com/aeron-io/simple-binary-encoding/pull/821[#821]. +* *[Java]* Generate bulk methods for fixed length `uint8` arrays. https://github.com/aeron-io/simple-binary-encoding/pull/819[#819]. +* Add Java 16 EA to the build matrix. +* Upgrade to JMH 1.27. +* Upgrade to Checkstyle 8.38. +* Upgrade to Versions 0.36.0. +* Upgrade to Mockito 3.6.28. +* Upgrade to Gradle 6.7.1. +* Upgrade to Agrona 1.9.0. + +== 1.20.3 (2020-10-13) + +* Fix generation of `GroupOrder` annotations on Java codecs. +* Java codecs have a new method `MessageDecoderFlyweight.appendTo(StringBuilder)` for the interface. https://github.com/aeron-io/agrona/pull/220[#220]. +* Reduce scope of some fields in Java codecs which were protected and should have been package or private. +* Add GCC 10 and Clang 10 to build mix. +* Add Java 15 to build mix. +* Upgrade to JMH 1.26. +* Upgrade to Checkstyle 8.36.2. +* Upgrade to Mockito 3.5.13. +* Upgrade to Agrona 1.8.0. + +== 1.20.2 (2020-09-18) + +* Indicate files are auto-generated for C# so they can be ignored by VS. https://github.com/aeron-io/simple-binary-encoding/pull/814[#814]. +* Fix CMake install on MacOS. +* Support CMake 3.6.1 as a minimum version. +* Upgrade to Versions 0.33.0. +* Upgrade to JUnit 5.7.0. +* Upgrade to Agrona 1.7.2. + +== 1.20.1 (2020-09-12) + +* Validate enum values are in the range for type considering min and max value, excluding null value. +* Upgrade to Versions 0.31.0. +* Upgrade to Checkstyle 8.36. +* Upgrade to Mockito 3.5.10. +* Upgrade to JMH 1.25.2. +* Upgrade to Agrona 1.7.1. + +== 1.20.0 (2020-08-29) + +* Improve validation and error messages when parsing invalid SBE schemas. +* Generate SBE header constants in C{plus}{plus} codecs so they can be used more easily in switch statements. +* Generate C{plus}{plus} style casts rather than C style casts in C{plus}{plus} codecs. +* Generate enum literals beyond `int` range correctly for C and C{plus}{plus}. +* Enum get methods for C{plus}{plus} codecs should not be `noexcept`. https://github.com/aeron-io/simple-binary-encoding/pull/806[#806]. +* Improve javadoc. +* Update Gradle build script so IDEA can more easily get the dependencies correct for generated code. +* Upgrade to Gradle 6.6.1. +* Upgrade to Mockito 3.5.7. +* Upgrade to JMH 1.25.1. +* Upgrade to Checkstyle 8.35. +* Upgrade to Version 0.29.0. +* Upgrade to Agrona 1.7.0. + +== 1.19.0 (2020-07-14) + +* Improve edge case generation for `JsonPrinter` when groups have num in group of zero. https://github.com/aeron-io/simple-binary-encoding/issues/800[Issue #800]. +* Improve edge case generation for `JsonPrinter` when messages are empty. https://github.com/aeron-io/simple-binary-encoding/issues/799[Issue #799]. +* Fix case of generated variables in C{plus}{plus} `computeLength` method which could cause compilation errors. https://github.com/aeron-io/simple-binary-encoding/issues/796[Issue #796]. +* Enable Java 14 build in CI. +* Improve Javadoc. +* Remove use of `constexpr` from `computeLength` generated methods in C{plus}{plus} codecs to address compilation errors. +* Validate usage of group and var data types within composite elements when XSDs are not used. +* Improve C# samples. +* Improve C{plus}{plus} samples. +* Reduce warnings in C{plus}{plus} build on Windows. +* Upgrade to .net core 3.1 LTS for for CI. +* Upgrade to Mockito 3.4.0. +* Upgrade to Checkstyle 8.34. +* Upgrade to Shadow 6.0.0. +* Upgrade to Gradle 6.5.1. +* Upgrade to Agrona 1.6.0. + +== 1.18.2 (2020-05-27) + +* Fix SbeMarshalling.go file generation based on template. https://github.com/aeron-io/simple-binary-encoding/issues/789[Issue #789]. +* Fix numerous MSVC warnings about C and C{plus}{plus} codec generation and testing. + +== 1.18.1 (2020-05-23) + +* Fix case of importing buffers when var data is used in nested groups for Java codecs. + +== 1.18.0 (2020-05-23) + +* Only generate imports for Java codecs when required to address warnings. +* Access fixed length arrays as Spans in C# codecs. https://github.com/aeron-io/simple-binary-encoding/pull/780[#780]. +* Add `SbeSchemaId` and `SbeSchemaVersion` as constants in fixed flyweights for C# codecs. +* Generate source docs from schema descriptions for C# codecs. https://github.com/aeron-io/simple-binary-encoding/pull/778[#778]. +* Add offset and wrap methods to C# codecs for ease of use. https://github.com/aeron-io/simple-binary-encoding/pull/777[#777]. +* Support non-standard message headers form the C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/pull/775[#775]. +* Fix version support for enums in C codecs. https://github.com/aeron-io/simple-binary-encoding/issues/773[Issue #773]. +* Improve formatting of generated C codecs. +* Require a strict dependency on Agrona. +* Upgrade to Agrona 1.5.0. +* Upgrade to javadoc-links 5.1.0. +* Upgrade to JUnit 5.6.2. +* Upgrade to Gradle 6.4.1. + +== 1.17.0 (2020-03-28) + +* Remove redundant generated casts from Java codecs. https://github.com/aeron-io/simple-binary-encoding/issues/766[Issue #766]. +* Add ability to compute the length of an encoded message before encoding for C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/pull/761[#761]. +* Remove Rust support due to lack of community support. +* Use `sinceVersion` from field which overrides type in C# codecs. https://github.com/aeron-io/simple-binary-encoding/issues/763[Issue #763]. +* Upgrade to JUnit 5.6.1. +* Upgrade to Gradle 6.3. +* Upgrade to Agrona 1.4.1. + +== 1.16.3 (2020-02-28) + +* Re-generate Java IR codecs. +* Make Java codec `toString()` methods version aware so the wrapped `actingVersion` and `actingBlockLength` are accounted for. + +== 1.16.2 (2020-02-27) + +* Variable data string improvements in C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/pull/758[#758]. +* Short circuit `toString` and `appendTo` in Java codes when buffer is null to avoid debugging issues. +* CLang Tidy fixes for C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/pull/757[#757]. +* Eliminate allocation when calling `appendTo` on set based fields in Java codecs. https://github.com/aeron-io/simple-binary-encoding/pull/755[#755]. +* Support optional groups which is a non-standard feature. https://github.com/aeron-io/simple-binary-encoding/issues/754[Issue #754]. +* Fix issue with populating optional arrays in Go codecs. https://github.com/aeron-io/simple-binary-encoding/pull/750[#750]. +* Migrate to maven-publish plugin for Gradle. +* C{plus}{plus} codec `sbePosition()` method should be SBE_NOEXCEPT. +* Upgrade to Versions 0.28.0. +* Upgrade to Mockito 3.3.0. +* Upgrade to Agrona 1.4.0. +* Upgrade to Gradle 6.2.1. +* Upgrade to JMH 1.23. + +== 1.16.1 (2020-01-21) + +* Simplify the generation of `MetaAttribute` lookup on fields in C{plus}{plus} codecs to reduce code size. +* Allow setting a count for groups and then later setting it to the value of index. This allows for streaming operations when the count is not known but can be limited and then later set to index for what is encoded. Applied to Java, C{plus}{plus}, and C# codecs. https://github.com/aeron-io/simple-binary-encoding/pull/746[#746]. +* Fix generation of Java Decoder names when message names start with lowercase. https://github.com/aeron-io/simple-binary-encoding/issues/745[Issue #745]. +* Upgrade to Agrona 1.3.0. +* Upgrade to JUnit 5.6.0. + +== 1.16.0 (2020-01-10) + +* Generate simpler `MetaAttribute` lookup in Java Codecs which avoids the generation of a synthetic class. +* Don't default timeunit and epoch for var data fields when parsing. This results in more compact IR. +* Move CI build to GitHub Actions. +* Track `initialOffset` on Java codecs so `toString()` can be called on the decoder at any time during decoding. This allows SBE decoding to be debugged. +* Use skip methods to avoid unused warning in C{plus}{plus} codecs. +* Upgrade to Agrona 1.2.0. +* Upgrade to Checkstyle 8.28. +* Upgrade to JUnit 5.6.0-RC1. +* Upgrade to javadoc-links 4.1.6. +* Upgrade to Mockito 3.2.4. +* Upgrade to Gradle 6.0.1. +* Upgrade to gtest 1.10.0. + +== 1.15.0 (2019-11-21) + +* Add skip methods for var data fields in C{plus}{plus} and Java codecs. +* Handle encoding of Nan, Infinity, and -Infinity for floating point values in Java `JsonPrinter`. +* Fix handling of `sinceVersion` in IR, Java codecs, and C{plus}{plus} codecs so that the max value is taken from type in field. +* Set javadoc encoding to UTF-8. +* Upgrade to javadoc-links 4.1.4. +* Upgrade to Hamcrest 2.2. +* Upgrade to Checkstyle 8.26. +* Upgrade to Shadow 5.2.0. +* Upgrade to Agrona 1.1.0. + +== 1.14.1 (2019-11-06) + +* Regenerate the Java IR Codecs to benefit for less allocation when pretty printing. +* Add null enum value lookup into the switch for Java codecs. https://github.com/aeron-io/simple-binary-encoding/pull/732[#732]. +* Upgrade to JMH 1.22. +* Upgrade to Agrona 1.0.11. + +== 1.14.0 (2019-10-27) + +* Provide consistent API for constant char arrays to be compatible with mutable char arrays. +* Cast length type for memcpy to address warning. https://github.com/aeron-io/simple-binary-encoding/pull/730[#730]. +* Reduce string copying to improve performance of C{plus}{plus} codec generators. +* Provide property accessor methods for getting string values Json escaped in C{plus}{plus} codecs. +* Escape Json string in C{plus}{plus} codec pretty printing. https://github.com/aeron-io/simple-binary-encoding/issues/718[Issue #718]. +* Escape Json strings in Java `JsonTokenListener`. +* Upgrade to javadoc-links 4.1.3. +* Upgrade to Checkstyle 8.25. +* Upgrade to Gradle 5.6.3. +* Upgrade to Agrona 1.0.9. + +== 1.13.3 (2019-10-08) + +* Fix type conversion warnings in C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/pull/725[#725]. +* Allow setting of raw value for bit sets in C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/pull/724[#724]. +* Fix initialisation of C{plus}{plus} codecs samples for printing as JSON. +* Print non-printable char in C{plus}{plus} codecs as int. https://github.com/aeron-io/simple-binary-encoding/pull/716[#716]. +* Fix unsigned conversation warning and use better default value for group index initialisation in C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/issues/714[Issue #714]. +* Declare primitive accessors as `noexcept` for C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/pull/709[#709]. +* Upgrade to Checkstyle 8.24. +* Upgrade to javadoc-links 4.1.2. +* Upgrade to Mockito 3.1.0. +* Upgrade to Gradle 5.6.2. +* Upgrade to Agrona 1.0.8. + +== 1.13.2 (2019-08-16) + +* Cope with optional composite values being pretty printed in Java codecs. https://github.com/aeron-io/simple-binary-encoding/issues/708[Issue #708]. + +== 1.13.1 (2019-08-14) + +* Reduce allocation and copying in Java codec generator to make stub generation more efficient. +* Update C# README. +* Generate package-info.java for codec Javadoc. https://github.com/aeron-io/simple-binary-encoding/issues/703[Issue #703]. +* Upgrade to javadoc-links 3.8.4. +* Upgrade to Agrona 1.0.7. + +== 1.13.0 (2019-08-02) + +* *[C#]* Add system property to allow squashing of namespace generation. https://github.com/aeron-io/simple-binary-encoding/pull/702[#702]. +* *[C{plus}{plus}]* Use `*[nodiscard]*` attribute where applicable. https://github.com/aeron-io/simple-binary-encoding/pull/700[#700]. +* *[C#]* Use ThrowHelper and simplify bounds checks to improve inlining. https://github.com/aeron-io/simple-binary-encoding/pull/695[#695]. +* *[Java]* Javadoc to `MetaAttribute` generation. +* Upgrade to Agrona 1.0.6. +* Upgrade to javadoc-links 3.8.1. +* Upgrade to Checkstyle 8.23. +* Upgrade to Mockito 2.30.0. +* Upgrade to Gradle 5.5.1. + +== 1.12.8 (2019-07-12) + +* More efficient approach for truncating an existing file when generating IR. +* Improve Javadoc for IR. +* More efficient implementation for appending to an `Appendable` for var-data in Java codecs. +* Use raw string literals in C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/pull/688[#685]. +* Enhancements to Rust codecs. https://github.com/aeron-io/simple-binary-encoding/pull/688[#685]. +* Generate pretty printers for encoded data inspection for C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/pull/683[#683]. +* Test C{plus}{plus} codecs with a greater range of compilers. +* Upgrade to javadoc-links 3.7.5. +* Upgrade to Shadow 5.1.0. +* Upgrade to Checkstyle 8.22. +* Upgrade to Mockito 2.28.2. +* Upgrade to Agrona 1.0.3. + +== 1.12.7 (2019-05-26) + +* Truncate existing serialised IR file when generating to avoid garbage at the end when new IR is shorter. https://github.com/aeron-io/simple-binary-encoding/issues/682[Issue #682]. + +== 1.12.6 (2019-05-25) + +* Remove the need for dimensions member in C codecs. https://github.com/aeron-io/simple-binary-encoding/pull/681[#681]. +* Improve Rust codec generator. https://github.com/aeron-io/simple-binary-encoding/pull/679[#679]. +* Upgrade to javadoc-links 3.6.4 to allow for offline builds. +* Upgrade to hamcrest 2.1. +* Upgrade to Agrona 1.0.1. + +== 1.12.5 (2019-05-03) + +* Fix warnings in generated Rust codecs. https://github.com/aeron-io/simple-binary-encoding/pull/676[#676]. +* Generate null values for enums in Rust codecs. https://github.com/aeron-io/simple-binary-encoding/pull/675[#675]. +* Reduce footprint of repeating group by replacing field with stack allocated object for dimensions in C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/pull/674[#674]. +* Don't generate an encode method for a constant enum in Java codecs. https://github.com/aeron-io/simple-binary-encoding/issues/670[Issue #670]. +* Remove redundant code for put string methods on arrays in C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/issues/668[Issue #668]. +* Generate overload with a 2-4 arg methods for setting array values to support the likes of UUIDs and cryptographic hashes efficiently for Java and C{plus}{plus} codecs. +* Add missing storage class specifier for C codecs. https://github.com/aeron-io/simple-binary-encoding/pull/666[#666]. +* Create a executable binary for C# benchmarks. https://github.com/aeron-io/simple-binary-encoding/pull/664[#664]. +* Always return a value bit set type in C# codec. https://github.com/aeron-io/simple-binary-encoding/pull/663[#663]. +* Add the ability to query length of var data from C# codecs. https://github.com/aeron-io/simple-binary-encoding/pull/622[#622]. +* Provide output on failure for ctest. +* Upgrade to io.freefair.javadoc-links 3.2.1. +* Upgrade to Checkstyle 8.20. +* Upgrade to Mockito 2.27.0. +* Upgrade to Gradle 5.4.1. +* Upgrade to Agrona 1.0.0. + +== 1.12.4 (2019-03-28) + +* Reduce module warnings when using Java 11. +* Fix incremental build due to annotation processor directory clash with generated code directory. +* Various clean ups to C and C{plus}{plus} codecs. +* Cast Java message header flyweight returns to int if interfaces are used. https://github.com/aeron-io/simple-binary-encoding/pull/635[#635]. +* Add a C codec generator. https://github.com/aeron-io/simple-binary-encoding/pull/638[#638]. +* Improve C{plus}{plus} generated codecs to use member initialisation lists for cleaner and easier to optimise code. https://github.com/aeron-io/simple-binary-encoding/pull/650[#650]. +* Fix Javadoc links so they use HTTPS and work with OpenJDK and Java 11. +* Upgrade Checkstyle DTD and apply checkstyle to method Javadoc. +* Upgrade to Agrona 0.9.35. +* Upgrade to Mockito 2.25.1. +* Upgrade to Gradle 5.3.1. + +== 1.12.3 (2019-03-10) + +* Include links when generating Javadoc. +* Update examples so they use relative path for XInclude. +* Set `systemId` for message schemas so that XInclude can have a relative path. https://github.com/aeron-io/simple-binary-encoding/pull/649[#649]. +* Fix generated Java codec for optional fixed length character arrays. https://github.com/aeron-io/simple-binary-encoding/pull/648[#648]. +* Trim strings decoded from fixed length character arrays for C{plus}{plus} codec. https://github.com/aeron-io/simple-binary-encoding/issues/646[Issue #646]. +* Fix padding on fixed length character arrays so they are null padded in C{plus}{plus} codec. https://github.com/aeron-io/simple-binary-encoding/issues/646[Issue #646]. +* Fix generated include files. https://github.com/aeron-io/simple-binary-encoding/pull/644[#644]. +* Upgrade to Checkstyle 8.18. +* Upgrade to Mockito 2.25.0. +* Upgrade to Gradle 5.2.1. +* Upgrade to Shadow 5.0.0. +* Upgrade to Agrona 0.9.34. + +== 1.12.2 (2019-02-16) + +* Add `wrapAndAppyHeader` method for ease of use for C{plus}{plus} codecs. +* Generate `sbe.h` for C{plus}{plus} client to avoid namespace clash and dependencies. https://github.com/aeron-io/simple-binary-encoding/issues/626[Issue #626]. +* Make C{plus}{plus} IR decode use params. https://github.com/aeron-io/simple-binary-encoding/issues/643[Issue #]. +* Upgrade to Agrona 0.9.33. + +== 1.12.1 (2019-02-05) + +* Don't generate id methods for members of a composite. https://github.com/aeron-io/simple-binary-encoding/issues/641[Issue #641]. +* Fix broken code generation that resulted from merging https://github.com/aeron-io/simple-binary-encoding/pull/631[#631]. +* Add ability to get var data members as a `string_view` to remove copy with C{plus}{plus}17. https://github.com/aeron-io/simple-binary-encoding/issues/550[Issue #550]. +* Add `Automatic-Module-Name` to help support modular Java systems that include SBE. +* Update C{plus}{plus} build to be more inline with Aeron. https://github.com/aeron-io/simple-binary-encoding/pull/635[#635]. +* Upgrade to Mockito 2.24.0. +* Upgrade to Agrona 0.9.32. + +== 1.12.0 (2019-01-30) + +* Fixes and improves to CMake build. https://github.com/aeron-io/simple-binary-encoding/pull/632[#632]. +* Add support for getting and setting a `string_view` on char array fields when C{plus}{plus}17. https://github.com/aeron-io/simple-binary-encoding/pull/631[#631]. +* Simplify C{plus}{plus} generator and modernise for C{plus}{plus}11. https://github.com/aeron-io/simple-binary-encoding/pull/630[#630]. +* Allow other types than `UINT16` for message header fields but issue a warning. https://github.com/aeron-io/simple-binary-encoding/pull/629[#629]. +* Change Golang codecs to no longer assume ordering of fields in group header. https://github.com/aeron-io/simple-binary-encoding/pull/627[#627]. +* Upgrade to Google Test 1.8.0. +* Upgrade to Checkstyle 8.17. +* Upgrade to Agrona 0.9.31. + +== 1.11.0 (2019-01-21) + +* Better handing of null passed for string encoding to Java codecs. +* Provide a fluent API for encoding array elements in Java and C{plus}{plus} codecs. +* Add support for XInclude so common definitions can be included into a schema and update samples to reflect usage. https://github.com/aeron-io/simple-binary-encoding/issues/624[Issue #624]. +* Upgrade to Shadow 4.0.4. +* Upgrade to Agrona 0.9.30. + +== 1.10.2 (2019-01-06) + +* Only generate lower bounds check in C{plus}{plus} codecs when necessary to add compile warning. +* Improve C{plus}{plus} OTF code to be more strict and eliminate build warnings. +* Improve build for optional build and include JAR dependency. https://github.com/aeron-io/simple-binary-encoding/pull/623[#623]. +* Upgrade to Checkstyle 8.15. +* Upgrade to Agrona 0.9.29. + +== 1.10.1 (2018-12-16) + +* Warnings clean up in code base. +* Add OS X to Travis for native build. +* Fix golang generated codec for metadata attributes. https://github.com/aeron-io/simple-binary-encoding/issues/620[Issue #620]. +* Add `Span` support to generated C# codecs. https://github.com/aeron-io/simple-binary-encoding/pull/589[#589]. +* Upgrade to Checkstyle 8.15. +* Upgrade to Gradle 4.10.3. +* Upgrade to Agrona 0.9.28. + +== 1.10.0 (2018-11-25) + +* Add support for `Span` in C# codecs. https://github.com/aeron-io/simple-binary-encoding/pull/589[#589]. +* Check when wrapping the same buffer in all types to avoid Java GC write barrier where possible. +* Set `parentMessage` on construction of group codecs and remove need for dimensions composite to reduce footprint and improve performance. +* Allow signed `numInGroup` and issue warning to support `int32` type. https://github.com/aeron-io/simple-binary-encoding/pull/617[#617]. +* Allow flexibility on group header member ordering in codecs. https://github.com/aeron-io/simple-binary-encoding/pull/614[#614]. +* Fix Golang return type bug. https://github.com/aeron-io/simple-binary-encoding/pull/611[#611]. +* Allow `uint32` for `blockLength` in Java codecs but issue warning. https://github.com/aeron-io/simple-binary-encoding/issues/609[Issue #609]. +* Add non-const buffer access method to C{plus}{plus} codecs. +* Upgrade to Mockito 2.23.4. +* Upgrade to Shadow 4.0.3. +* Upgrade to Agrona 0.9.27. + +== 1.9.0 (2018-10-29) + +* This is the first release that supports building and running on Java 11. +* Add a `wrap(DirectBuffer)` to Java codecs for more efficient consumption of strings. +* Return `const char *` from `buffer()` method in C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/issues/601[Issue #601]. +* Support constant members in message header Java codecs. https://github.com/aeron-io/simple-binary-encoding/issues/602[#602]. +* Generate static constexpr methods for C{plus}{plus} codecs for constant enums. https://github.com/aeron-io/simple-binary-encoding/issues/591[Issue #591]. +* Added encoding offset and other metadata to C{plus}{plus} composite codecs. https://github.com/aeron-io/simple-binary-encoding/issues/594[Issue #594]. +* Fix length encoding on arrays for C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/issues/595[Issue #595]. +* Add methods to access schema id and version for all fixed flyweights for Java and C{plus}{plus}. https://github.com/aeron-io/simple-binary-encoding/issues/593[Issue #593]. +* Detect duplication ids in message fields. https://github.com/aeron-io/simple-binary-encoding/issues/597[Issue #597]. +* Add Travis build matrix for Java 8 and 11 for OpenJDK and Oracle JDK. +* Upgrade to Checkstyle 8.14. +* Upgrade to Mockito 0.23.0. +* Upgrade to Agrona 0.9.26. + +== 1.8.9 (2018-10-05) + +* Fix string format warnings in Rust and Golang generators. +* Add Travis build. +* Upgrade to Shadow 4.0.0. +* Upgrade to Gradle 4.10.1. +* Upgrade to Agrona 0.9.25. + +== 1.8.8 (2018-09-12) + +* Fix initialisation of encoding type with length is zero for C{plus}{plus}. https://github.com/aeron-io/simple-binary-encoding/issues/583[Issue #583]. +* Fix formatting of property access methods for Java within composites. https://github.com/aeron-io/simple-binary-encoding/issues/582[Issue #582]. +* Upgrade to Mockito 2.22.0. +* Upgrade to Gradle 4.10. +* Upgrade to Agrona 0.9.24. + +== 1.8.7 (2018-08-18) + +* Use find package to discover java executable when building C{plus}{plus} codecs tests. +* Use pointers in golang codecs to improve efficiency. https://github.com/aeron-io/simple-binary-encoding/pull/578[#578]. +* Upgrade to Checkstyle 8.12. +* Upgrade to Mockito 2.21.0. +* Upgrade to Agrona 0.9.23. + +== 1.8.6 (2018-07-30) + +* Provide the ability to query for an empty bit set in Java and C{plus}{plus} codecs for simplicity. https://github.com/aeron-io/simple-binary-encoding/pull/575[#575]. +* Upgrade to Mockito 2.20.1. +* Upgrade to Gradle 4.9. +* Upgrade to Agrona 0.9.22. + +== 1.8.5 (2018-07-19) + +* Invalid Java generated for codec with an extension string field that is appendable. https://github.com/aeron-io/simple-binary-encoding/pull/574[#574]. + +== 1.8.4 (2018-07-16) + +* Upgrade to Mockito 2.19.1. +* Upgrade to Agrona 0.9.21. + +== 1.8.3 (2018-07-07) + +* Regenerate IR Codecs to quote strings when printing. +* Upgrade to Checkstyle 8.11. +* Upgrade to Gradle 4.8.1. +* Upgrade to Agrona 0.9.20. + +== 1.8.2 (2018-07-03) + +* Update to latest CME fix binary market template for testing. +* Allow, with warning, `numInGroup` type to use `uint32` for repeating groups. +* Add support to C# codecs for constant presence enums. +* Fix issue with loss of IR data on encoding the IR for constant presence enums. https://github.com/aeron-io/simple-binary-encoding/issues/560[Issue #560]. +* Complete functionality for `JsonPrinter` so that an SBE message can be transformed to JSON for debugging. https://github.com/aeron-io/simple-binary-encoding/issues/560[Issue #560]. +* Remove debugging output from C{plus}{plus} IR decoder. https://github.com/aeron-io/simple-binary-encoding/issues/559[Issue #559]. +* Make `HEADER_SIZE` a public constant in Java codecs for repeating groups. +* Allow Java decoders to use an `Appendable` for ASCII strings. https://github.com/aeron-io/simple-binary-encoding/pull/557[#557]. +* Upgrade to Mockito 2.19.0. +* Upgrade to Checkstyle 8.10.1. +* Upgrade to Agrona 0.9.19. +* Upgrade to GSON 2.8.5. + +== 1.8.1 (2018-05-04) + +* Upgrade to JMH 1.21. +* Upgrade to Checkstyle 8.10. +* Upgrade to Shadow 2.0.4. +* Upgrade to Agrona 0.9.18. + +== 1.8.0 (2018-04-29) + +* Use `Constructor` to dynamically create new instances to avoid deprecated warning in Java 10. +* Remove use of `javax.annotation.Generated` so that the generated codecs compile and and run on Java 10. +* Rename `position` methods in C{plus}{plus} generated codecs to `sbePosition` to avoid clash with Aeron codecs for the archive and clustering. *Note:* this is a breaking change for those who have used these methods. +* Upgrade to Gradle 4.7. +* Upgrade to Agrona 0.9.17. + +== 1.7.10 (2018-04-23) + +* Return `NULL_VAL` for unknown `enum` value so it can be used in a Java switch. https://github.com/aeron-io/simple-binary-encoding/pull/548[#548] +* Improve C{plus}{plus} Unit tests. https://github.com/aeron-io/simple-binary-encoding/pull/549[#459]. +* Use since version from field rather than type in Java codecs. https://github.com/aeron-io/simple-binary-encoding/pull/548[#548]. +* Generate put `CharSequence` methods for ASCII encoded fields in Java. https://github.com/aeron-io/simple-binary-encoding/pull/547[#547] +* Cleaning up unit tests' global namespaces for C{plus}{plus}. https://github.com/aeron-io/simple-binary-encoding/pull/545[#545] +* Generates invalid CSharp code when using sinceVersion attribute inside groups. https://github.com/aeron-io/simple-binary-encoding/pull/555[#555]. +* Add support for netstandard2.0 removing support for 1.3 for .NET. +* Upgrade to Shadow 2.0.3. +* Upgrade to Mockito 2.18.3. +* Upgrade to Gradle 4.6. +* Upgrade to Checkstyle 8.9. +* Upgrade to Agrona 0.9.16. + +== 1.7.9 (2018-03-09) + +* Remove redundant throws clause from Java `TargetCodeGenerator`. +* Removed the using of namespace in generated C{plus}{plus} headers. Issue https://github.com/aeron-io/simple-binary-encoding/pull/544[#544]. +* Fix generated C# code for version checking of fields. Issue https://github.com/aeron-io/simple-binary-encoding/issues/543[#543]. +* Upgrade to Agrona 0.9.15. + +== 1.7.8 (2018-02-23) + +* Advance toString() operation on Java decoders when raw bytes for var data is encountered. Issue https://github.com/aeron-io/simple-binary-encoding/issues/542[#542]. +* Add C{plus}{plus} classes for OTF and header include to the sources jar. Issue https://github.com/aeron-io/simple-binary-encoding/issues/540[#540]. +* Upgrade to Agrona 0.9.14. + +== 1.7.7 (2018-02-23) + +* Regenerate IR codecs. +* Provide `ByteOrder` as a constant available in the generated Java codecs. +* Do not allocate when putting or getting an empty string in Java codecs. +* Apply strict indentation code style. +* Upgrade to JMH 1.20.0. +* Upgrade to Gradle 4.5.1. +* Upgrade to Checkstyle 8.8. +* Reduce Hamcrest dependency from all to library. +* Upgrade to Mockito 2.15.0. +* Upgrade to Agrona 0.9.13. + +== 1.7.6 (2017-12-15) + +* Fix build of golang code due to failing test. Issue https://github.com/aeron-io/simple-binary-encoding/issues/532[#532]. +* Generate getters for constant properties in Java decoders. Issue https://github.com/aeron-io/simple-binary-encoding/issues/531[#531]. +* Rework C{plus}{plus} OTF to support unaligned access. +* Generate field accessors in C{plus}{plus} to use `memcpy` to support platforms requiring aligned access and X86 when the XMM registers are used. Issue https://github.com/aeron-io/simple-binary-encoding/issues/506[#506]. +* Rework C{plus}{plus} generated code for options sets to work with Visual Studio. +* Upgrade to Mockito 2.13.0. +* Upgrade to Checkstyle 8.5. +* Upgrade to JShadow 2.0.1. +* Upgrade to Gradle 4.4. +* Upgrade to Agrona 0.9.12. + +== 1.7.5 (2017-11-15) + +* Support lookup of an enum value to be used as the value for a constant primitive type in a composite or message. Issue https://github.com/aeron-io/simple-binary-encoding/issues/529[#529]. +* Take account of constant fields when computing block length. Issue https://github.com/aeron-io/simple-binary-encoding/issues/528[#528]. +* Validate the type is correct in a `valueRef` attribute. +* Update to Mockito 2.12.0. +* Update to Checkstyle 8.4. +* Update to Agrona 0.9.11. + +== 1.7.4 (2017-11-01) + +* Generate Javadocs for major types in codecs based on descriptions. Simple fields to come later. +* Take the max of type and field version rather than just having the field take precedence. +* Expose a `JsonPrinter` method that takes an `UnsafeBuffer` rather than a `ByteBuffer`. +* Update to Mockito 2.11.0. + +== 1.7.3 (2017-10-16) + +* Fix the generated group name for arrays within groups for c++ codecs. https://github.com/aeron-io/simple-binary-encoding/pull/521[#521]. +* Upgrade to Agrona 0.9.9. + +== 1.7.2 (2017-10-11) + +* Fix move constructors and assignment operators for c++ 11 code generation. +* Add bit twiddling methods to codecs for bitsets. Issue https://github.com/aeron-io/simple-binary-encoding/issues/489[#489]. +* Remove old SBE typedefs from C{plus}{plus} codecs. +* Handle case of constant array of char with length of 1. Issue https://github.com/aeron-io/simple-binary-encoding/issues/505[#505]. +* Capture types by `ref` name for support refs in refs. Issuehttps://github.com/aeron-io/simple-binary-encoding/issues/496[#496]. +* Improvements to efficiency of introducing c++ 11 functionality. +* Initial support for Rust language. +* Upgrade to GSON 2.8.2. +* Upgrade to Checkstyle 8.3. +* Upgrade to Mockito 2.10.0. +* Upgrade to Agrona 0.9.8. + +== 1.7.1 (2017-08-21) + +* Add accessors for buffer length on C{plus}{plus} codecs. https://github.com/aeron-io/simple-binary-encoding/issues/479[Issue #479]. +* Add the ability to lookup message tokens when decoding IR by template id for C{plus}{plus}. https://github.com/aeron-io/simple-binary-encoding/issues/484[Issue #484]. +* Don't dereference a null character encoding. https://github.com/aeron-io/simple-binary-encoding/pull/491[Issue #491]. +* Add metadata attribute for presence. https://github.com/aeron-io/simple-binary-encoding/issues/483[Issue #483]. +* Add `noexcept` specifier for C{plus}{plus} https://github.com/aeron-io/simple-binary-encoding/pull/480[#480] +* Capture referenced name when dealing with simple types for refs. https://github.com/aeron-io/simple-binary-encoding/issues/477[Issue #477]. +* Handle `presence=optional` better in Golang generator. https://github.com/aeron-io/simple-binary-encoding/pull/475[#475]. +* Validate message names and field names are unique in a given context. https://github.com/aeron-io/simple-binary-encoding/issues/470[Issue #470] +* Copy elements of correct size in C{plus}{plus} fix arrays. https://github.com/aeron-io/simple-binary-encoding/issues/402[Issue #402]. +* Generate a field accessor as a `char` for constant Java char arrays exactly 1 in length. +* Generate a field accessor as a `String` for constant Java char arrays greater than 1 in length. +* Generate garbage free settors for Java strings and char arrays when the encoding is US_ASCII. +* Use compiler detections to guard pragmas to suppress excessive warnings. https://github.com/aeron-io/simple-binary-encoding/issues/437[Issue #437]. +* Provide dotnet core support. https://github.com/aeron-io/simple-binary-encoding/pull/456[#456]. +* Correct defaults for `UINT32` type as per specification. *Note:* this maybe breaking for those relying on hardcoded references for the values. https://github.com/aeron-io/simple-binary-encoding/issues/455[Issue #455]. +* Upgrade to Mockito 2.8.47. +* Upgrade to JMH 1.19 for Java benchmarks. +* Upgrade to sevntu-checks:1.24.1. +* Upgrade to Checkstyle 8.1. +* Upgrade to Gradle 4.1. +* Upgrade to Agrona 0.9.7. + +== 1.7.0 (2017-04-14) + +* Use compiler detections to guard pragmas to suppress excessive warnings in C{plus}{plus} #454 +* Reinstate C# support but consider it beta. +* Fix min/max macro conflicts on Windows for C{plus}{plus}. +* Remove `sinceVersion=1` from `deprecated` attribute in IR as the base IR has no message header. +* Support generation of var-data methods for raw data which do not have a `characterEncoding`. +* Default to `US-ASCII` rather than `UTF-8` for `char` type as per specification. +* Generate `wrapAndApplyHeader()` method to Java encoders for convenience. +* Upgrade to Agrona 0.9.6. +* Upgrade to Checkstyle 7.7. + +== 1.6.2 (2017-04-12) + +* Upgrade to Agrona 0.9.5. +* Upgrade to Gradle 3.5. +* Upgrade to Mockito 2.7.22. + +== 1.6.1 (2017-04-06) + +* Share some test code with Golang. +* Upgrade to Checkstyle 7.6.1. +* Upgrade to Agrona 0.9.4. +* Upgrade to Gradle 3.4.1. +* Upgrade to Mockito 2.7.21. + +== 1.6.0 (2017-02-22) + +* Allow complex types to be included in the `messageHeader` for a schema. +* Fixed bug https://github.com/aeron-io/simple-binary-encoding/issues/435[#435] so that the name is correctly picked up for ref types in composites. +* Add `referencedName` to the IR so that is can be used with ref types. +* Code clean ups for C{plus}{plus}. +* Go lang support beta complete. +* Upgrade to Agrona 0.9.3. +* Upgrade to Gradle 3.4. +* Upgrade to Mockito 2.7.9. + +== 1.5.7 (2017-02-08) + +* Make name clash with language keywords a warning rather than error. Issue https://github.com/aeron-io/simple-binary-encoding/issues/433[#433]. +* Capture byte order as a field in the IR for convenience. +* Add missing accessor methods for C{plus}{plus} OTF `Token` and `Encoding`. +* Golang additions in preparation for beta launch. +* Upgrade to Checkstyle 7.5.1. + +== 1.5.6 (2017-01-23) + +* Fix bug with generating composites within composites. +* Fix bug with message `sinceVersion` being over written by schema version id. +* Add `deprecated` version information from the XML to the IR. +* Add Golang support to generator. +* Upgrade to Agrona 0.9.2. +* Upgrade to JMH 1.17.4. +* Upgrade to Checkstyle 7.4. +* Upgrade to sevntu-checks 1.23.0. +* Upgrade to Mockito 2.6.8. +* Upgrade to Gradle 3.3. + +== 1.5.5 (2016-12-20) + +* Correct issues with message extension on types other than basic encoded types. +* Removed unneeded fields from the Java codecs to reduce footprint. +* Capture `sinceVersion` and `description` attributes for all types in the XML schema and store in the IR. +* Expose the buffer and offset as accessor methods in the Java stubs. +* Generate encoding offset and length as static methods for fields in the codec stubs. +* Upgrade to JMH 1.17.3. +* Upgrade to Checkstyle 7.3. +* Upgrade to sevntu-checks 1.22.0. +* Upgrade to Mockito 2.2.29. +* Upgrade to Agrona 0.9.1. +* Upgrade to Gradle 3.2.1. + +== 1.5.4 (2016-11-17) + +* Added optional support for decoding unknown extended enums. +* Upgrade to JMH 1.16. +* Upgrade to sevntu-checks 1.21.1. +* Upgrade to Mockito 2.2.16. +* Upgrade to Agrona 0.9.0. +* Upgrade to Gradle 3.2. + +== 1.5.3 (2016-11-03) + +* Add String convenience accessors to Java generated stubs for char array types. +* Upgrade to Mockito 2.2.9. +* Upgrade to Agrona 0.5.6. +* Upgrade to Checkstyle 7.2. + +== 1.5.2 (2016-10-15) + +* Added checks for extension var data and repeating groups in OTF for Java and C{plus}{plus}. +* Added `sinceVerion` and `inActingVersion` to repeating groups for C{plus}{plus}. +* Added acting version guard to repeating groups and var data for extensions. +* Added `sinceVersion` metadata methods for all field types in Java generated stubs. +* Expose buffer and offset in fixed flyweights for C{plus}{plus}. +* Use static constexpr for C{plus}{plus} constants. +* Upgrade to Agrona 0.5.5. +* Upgrade to Checkstyle 7.1.2. +* Upgrade to JMH 1.15. +* Upgrade to Gradle 3.1. + +== 1.5.1 (2016-08-24) + +* Target CMake 3.0.2 minimum. +* Correctly encode int64 min value in C{plus}{plus}. +* Apply constexpr's where possible in C{plus}{plus}. +* Upgrade to Agrona 0.5.4. +* Upgrade to Gradle 2.14.1. + +== 1.5.0 (2016-07-22) + +* Reference the 1.0 final SBE schema XSD. +* Generate a `toString()` method for the Java codecs stubs to help with debugging. +* Update to Agrona 0.5.3. +* Update to Checkstyle 7.0. + +== 1.4.2-RC2 2016-06-29 + +* Added `sbe.cpp.namespaces.collapse` system property so c++ nested namespaces are collapsed to a single namespace, separated by underscores, which defaults to false. +* Move generated interfaces for flyweights to https://github.com/aeron-io/Agrona[Agrona]* and allow configuration via `sbe.java.generate.interfaces` system property which defaults to false. +* Update to Agrona 0.5.2. +* Update to Checkstyle 6.19. +* Update to Gradle 2.14. + +== 1.4.1-RC4 2016-05-23 + +* Update to Agrona 0.5.1. +* Update to Checkstyle 6.18. +* Update to Gradle 2.13. + +== 1.4.0-RC4 2016-04-22 + +* Correct examples for illustration of how to do message extension. +* Update On-The-Fly decoding to assign contextual names for types within composites. +* Add feature support for the https://github.com/FIXTradingCommunity/fix-simple-binary-encoding/tree/master/v1-0-RC4[RC4 Specification] which adds offsets and refs in composites, plus restricted ranges on repeating groups. +* Upgrade to Agrona 0.5 to bring in support for encoding into expandable buffers. +* Upgrade to Checkstyle 6.17. +* Upgrade to JMH 1.12. + +== 1.3.5-RC3 2016-04-01 + +* Performance improvements to C{plus}{plus} generated stub by using move constructors where possible. +* Add a check for string length to avoid truncation in C{plus}{plus} generated stubs. +* Validate that number of items as a repeat count is within range for groups in Java generated stubs. +* Use UINT16, rather than UINT8, for number of times a group repeats in the examples. +* Use UINT32 length strings in the examples. +* Support for UINT32 length var-data strings as fields. Previously allowed UINT8 and UINT16 length strings. +* Fix bug with UINT32 type in Java not treating the most significant bit correctly. + +== 1.3.4-RC3 2016-03-24 + +* Generate MessageEncoder and MessageDecoder interfaces to common message methods. +* Fix up code for Agrona changes to org.agrona package structure. +* Update to Checkstyle 6.16.1. +* Update to Gradle 2.12. +* Update to Agrona 0.4.13. + +== 1.3.3-RC3 2016-03-01 + +* Validate length of encoded var data strings against length type of var data in schema. +* Update var data length type in IR and examples to be uint16 to support larger strings. +* Added the ability to append a token to property names that have keyword clashes. +* Added fluent API support for putting strings into var data fields. +* Update to Checkstyle 6.15. +* Update to Gradle 2.11. +* Update to Agrona 0.4.11. + +== 1.3.2-RC3 2016-02-06 + +* Warn that optional presence is not allowed on var data fields. +* Bring C{plus}{plus} inline with Java features. +* Update to Agrona 0.4.11. +* Constant values for enums need to be in US-ASCII rather than default encoding. +* Code quality changes to reduce number of Sonar warnings. + +== 1.3.1-RC3 2016-01-18 + +* Add Checkstyle for indentation and fix violations. +* Update to JMH 1.11.3 +* Check for keywords class on formatted property field. +* Update to Agrona 0.4.10. +* Fix publishing of sbe-all JAR to Maven Central. + +== 1.3-RC3 2016-01-06 + +* Updated implementation to reflect the https://github.com/FIXTradingCommunity/fix-simple-binary-encoding/tree/master/v1-0-RC3/doc[RC3 Specification]. RC3 is more generally useful with support added for var data in repeating groups and composites that can contain other types than just primitive encodings. +* Significant rewrite of Java and C{plus}{plus} OTF implementation to be more efficient with no back or re-scanning of the IR, plus they are now similar in usage and API. +* Java generated stubs are no longer dependent on CodecUtil and one level less for better inlining by the optimiser. +* IR updated to carry the description and count of tokens per component. +* Other language implementations have been removed until ports for RC3 are available. +* Project structure updated to be a Gradle modular build. +* RC4 features are available for testing if appropriate RC4 XSD schema is provided or schema validation is turned off. +* Generated code is marked with the @Generated annotation. +* C{plus}{plus} updated to C{plus}{plus} 11. \ No newline at end of file From ee188a9e482346f3a1a965d397a8d64603040498 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:00:25 +0100 Subject: [PATCH 1478/1594] 1.36.1 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 7991f09416..f107550c29 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.37.0-SNAPSHOT +1.36.1 From 8d371375d09dc036eae29fd7cd8b03698a8c5f16 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:00:37 +0100 Subject: [PATCH 1479/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index f107550c29..7991f09416 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.36.1 +1.37.0-SNAPSHOT From 3dc0f60c584a30c10c8134f1a412b73252171ef3 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 8 Nov 2025 10:51:41 +0100 Subject: [PATCH 1480/1594] [Java] Upgrade to `Agrona` 2.3.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 41e68f43fb..6e10340b5d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.3.1" +agrona = "2.3.2" checkstyle = "12.1.1" commons-codec = "1.15" commons-lang3 = "3.8.1" From a84f9b70da28d55ad1103972769e3b3afc7cba3a Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 8 Nov 2025 10:52:20 +0100 Subject: [PATCH 1481/1594] [Doc] Release notes. --- CHANGELOG.adoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index aac63dd520..d798f2bd60 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,5 +1,9 @@ = Changelog +== 1.36.2 (2025-11-08) + +* *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.3.2[Agrona 2.3.2]. + == 1.36.1 (2025-11-03) * *[C#]* Handle case when `valueRef` is with enum type prefix. (https://github.com/aeron-io/simple-binary-encoding/pull/1092[#1092]) From bc3be5f22625120c5b58d2cbfd3a5701f1de814d Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 8 Nov 2025 10:53:19 +0100 Subject: [PATCH 1482/1594] 1.36.2 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 7991f09416..c6a567b8eb 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.37.0-SNAPSHOT +1.36.2 From 0d6fcba0a160c90c4b01e77a8203371bc0b32a65 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Sat, 8 Nov 2025 10:53:31 +0100 Subject: [PATCH 1483/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index c6a567b8eb..7991f09416 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.36.2 +1.37.0-SNAPSHOT From 6232181bbffa23091b5b15dc9680f64f6a00e03c Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 25 Nov 2025 13:55:15 +0100 Subject: [PATCH 1484/1594] [Java] Upgrade to `Checkstyle` 12.1.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6e10340b5d..aa2e4500b5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.3.2" -checkstyle = "12.1.1" +checkstyle = "12.1.2" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From d296042a5f34a1198d22f589371f0cd84defd6b9 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 28 Nov 2025 10:01:22 +0100 Subject: [PATCH 1485/1594] [Java] Upgrade to `Gradle` 9.2.1. --- gradle/wrapper/gradle-wrapper.jar | Bin 45457 -> 45633 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 8bdaf60c75ab801e22807dde59e12a8735a34077..f8e1ee3125fe0768e9a76ee977ac089eb657005e 100644 GIT binary patch delta 36466 zcmXVXQ)4CEwrnG|ZQHhO+qRvo*j}-1c5K_WZL@>Z-@f-{{(%~(8dWpl;8)+_uR3dZ zfZQ)egq&Z$i11kM_Up+}Q({I9MU9QZb2tR|yWGN*EITsYQsXf^5qA245#ac}VN7sh zh0J3lJ2M}?KHXivdw;lL^3<*X4-B$3ia;m37Kqtw&i zS44bg*-wcSL! z3SdD4tBX;ArwHhPVinq?S0M$-NDOHL41GA}u(Mv5lJs<>n1t_H{9Dx+iP^!|OZQjg z?r?7~D`^kTzf9h>O*8A}exIMuzXc$pU~b^ya#D9FHgvX-Q%Yzk&SMjmRXXNaWUeur zlkHbC@;ZrS`g8^HFE*ztUGuNoszWPjE*%z7Ig86rushQM?7yOw$~9=Fm8+HQUTzv? zfJk=PC+3tWDRvq{9HGU^Zu%T_j*8tp%>TiVuoXOEUm?=ke1bF@YIBp42=^no_&WYdKw$ss1@Y-se*rkpi&K6u}~U$255Np z?7GN0p@Jp>xLr#KDJ@^^k}45a;HG1THPWPxvaJ=yARI7bHIW%7`oU5K?Zzz`nW5_D zr@AaO1KtwBXLQ3AdtS+tV8RsHYw?WXA}~magC2%dki?8d@kw)G7AS~1Mi{5@cB`Re zhFOH2-A^`}!>EIWtoSO%}~`k7X@ z@Qd#Q?2$C1GC6$WnOnF6&3iLUKO?&*=wT=QJA;RTu^aiHh9T1=UUCc}c#wz@jeYns zvk<0}xrpSWOn(w+ngAey!wL-gr}+QXrU%HlghdPxfNTZ$C0<*Mf_SUTBlzydqQ-|} zB@;h5SoD)PGJxL9yM-6-`Z=S^IvL}Q@C%IJA~4ZnAO2Pxvy>hrm@LM9Z2EHYVRCYM z`s?fA0Nvm85Q7gFw~GeAV71AGFwdq2TWN;^Lw$=~GeXQBUxL3Hcq!!(7#5i2&BId7 zYls^x%g+K(yV!&l?X%!0nZYjEh^X(>p-NVRs2nf-@LG5nMYwi+AhZo}(V+}>Di&T& zQ6M}b^7cHNQ(9{jop|K{8_u%_l{JkpuOY{n6yOvUcicc0op6r22)J>!RHvMWt`W*V zUO7)t$c%B@%MUdS?H7=G8Z8DQ@60bBMWS zjK>B9@LWwT`0;-9+`>2qK`lE(5t43;N7ho7oqWH$L4in9EWoHQ03@#V=2&?;3QW|*ThDm+^W_8PLz=_P?p z7PHSz5MvfwXE@_RYBaN8kHQF*AamlbM=mnH---W3jWF;?Q)W zT?E3Ih|JH}0OS_q`et(vywK<3Y-o&4lySM=>7Bx(T$#uizd|^`c)8!He?5*a1iA-5 za!4*i@&~W#|5sz8{LcJZzkd8^1_2^s;Q&tvNr6#lWB^>XPN7WTZK@5 z8ojIux!<+(H17=O3EubL9sSy$G6!G-3*_?GXnu;+Iy)$Cs@cjafZTlN@%m>du}^ zD4bg?P7|@FjvehnIoA#=$k(Tds}4Fw9Xa||Y5=VZBqW$rV_S9XfbAjM>*n~x8DGNu zp!|Va?Cn!gFjvxP*@V@HP}^5%n3ds!GkhkY*7i8{EDhz^h#EQ{FwuZ$J4_@mOfQ^F zB9~7JyU?e* zHb(HP_@|SQp?06V-{H?Zo3c<$qi%}emH?RjGN>W1aQnQ^YUCw$a$;C6{`9yFy7s0L zQk(B_`F4w9hMC!KLrfAG=IBPJM4R#z8K?N@cB1t5-C{CsM(5sFU467ukNNOAjwRn` zh&T9H`w%qgKAcDwHj7V2Io1eisR&TJ%U%5yxf}bCnQ{n*_(k!ywLHM-^;gfUTzL_f58`f7`3{e;7jHS zS-!BrUgGH%7EF#6z0gy0ZVW53^gTlCC)hWd=68=Cb6@Sy`8(GJlt#7Y{$TFwdg6(> z$6QM`b`8n27K;!=+cQQ7qex-G{?sY8j((iIh-z%iPgQ|Q?1M;9Lb1&$V{UAh!$G66 z5&rxAU&9UP-?1tIVX$lg7y39$n0{a>Ff>4sQP@NawoGiA4g(0)Uo5B$Rwe-~2&cm; zxNh(ahHmD}%+P|?M)vC!U2D|K%X$UnthR+miKDgEx$pTq8-TpeRsP;(D&Of#IvWFJ zp`OXChn$!D&K2jc`?0?Okl8>{&|2MYpOUAw-Eh2IgmRHOS`2&uY-o@pbvm2O7HgFX zi6tq>Su;b(H3VMlg&YYV-9EA$*%`=&nCk-Ko`Dxl;^G40z{1@8{N|=lR;Qb_o*#>G z1_{T3*C9m<5vy5Ia9zwIMmezG%_8b?dDu9nIw3d>hEE+%Gyu>$zUp`vZU_Ymul204 zkXB7DGl#++Q(_08PG3}xpkU2jwiRCm_f}d~soZHQzuRu}9@nNkJ>swCbr4tb=tkr~)d!U2G(jN>q^N6a<5W0DM zNl>jM`Mhz2Nix9+)n&<)*y6mrzC;J&oINA9*NahEal~uUSq;2&LB>lpV9!q3J}4H}MDBui-h@YN0*Dm+l?*gvBH5EC58CVimf z@T8=3Vm$AhDx_gS-GbucQvR7B)3FfX1MyqA9a#dfv0RjZ5Yby^3huOp&REVJZ@bx> zAUvHg?3869Gn%-Vesdst|0$B-Uv)HpOMwSW;Ax@?eXF<||1%OtCxVJ|(fvC|pdU$& zz_jhBdM?6G-lj|BglERPKgg~dSIDV4!x8~j9OT6}dVJ}nGyBn#3;u!N%Tv;|dmMu) zv_e*Z3D}W_tWkGfbUS<1vx7Q(;a8meSjZQ~EltZ3i`*xG2?c{`>p?)U!+!Ig;s%cs zXO2RhwQE`jQ)oIubL7n5I}$hNOEd_oGP;zO()@`UEJMuGGZuSk(1Ze80JyPAf`9z8 z7-w3fN)(ivcANE4ZN`z8MSZd7` zXQkbz+t(QLa&8&ulu+&;BnelNVH4VPLghCuaZ5-s5)}%_-IF2R?wvUkj|^T)?#Noy->*3IRu&vevo)O` zxYU4M`Q!Mplrev2^k&V!oj@_J$-n(MjIve23po1(>v=jb{D`e@5uML4;n+!bpX2tJ zsr(@+^>_kg&y+pQ;yKYhx;UmzjyUv*l&>=Ze?olQ-K4sxqzB?4Hj4|Q(vtv^?N69$ zUKMsLr1+3K`SBsQbLBy9X2?TE#vqKad)V8oOI$F&!-VS}PNdQ6oDo^;b3iX4r}nl( zIWM7S3;`x^;8woQ9FKInmR!-qoNuWVy8Yj6voy~$ME7_ZJ0j8pJX+=osF71jV?11; zCwH?kqAo+DO|>I0;5;}{DWL$c3Vh4fh!OPJzokUxpKr`o^nJ8`?D>Z~5Z8Twb<_vM zL86goRFdY!@g1{=BXDX6=TW}kQTNx!rn(+5vI3gJ^EE7f)?*Vw+OC0w{L1;tew5Zy z@T?0t?Ap9~De!?acVgr6AhWfhZp?qL=~MUe)hwhEROc=7(E21fZc+n`y@;qOOA=FN z{vcH=vvk0`Iv^Y-*YfRdkr6AE2dj82|EbTNj(%rSHPzx@YK9osl>CXA+|<4P$1@t1 zeXu`a^;&C(C-HZiM5vL>XaL2Kxnq6myf17+8q~}|8@$62S$DsE6}!m#3Q>c{8(Oz= zpdtLg3zylQ@7FWWRYxRX7-#exzdJ;BrLI=u+U&k7HYjK=}gBZa1LT_&?FEsD8b%+OIO{}KDC*c zQOqyArw=~kROVy%KV2m+Z9YpQXaV%T=Jm}v$;xrQp3&a{{3shRc&+RCF1VAkc63%B zZEh||$E_|%&)I0e#aqu|(W#{!y@3|L6__2NgNJFLp4`g20b7>}18@hFS@2Fcc+S)r z$9Q$ARc;Yi?O@z<`;HKb&mIlaazR zcH2jiHxpxAdvvQd`E0w1EV*2sx1Y4@G-nn)X8jGgMbBLm6iCeMqIeSTZbH3RpujLM z!x`gcfFz!Ze>Or51$aG3TnqLJLsbs;*h_Q!^g5{XM+i7(8tMSFHq{bBGC~3=QGuf- z3;~v*ofA9FAcCI`%wx`K_T78lo#zggsxAFx&6PvAV4?sFl$fJ?5;^1>{qR7|z*e53 z95AY5h0%SQX+{~(d-}I*#CzgjIaL}>2Ms7XMQ^txg5I$Z082i*^KZmY2OZSZ`uHJI z9Ysex^a3Jl7*2UR52x1+>%t1JP6o#emKb04QH3E_8c{}j1?K(Bu*s1>Q}Oc$!?g?5 zhH0^z*uE{KAE}*35R(cIsO=rmZYzDY2O$Zsur?9(|R^k;-51>qsU8@GwA!@I<)FwtTEAaH_&4uF=D;zY^* zQ_&IB)-u&ed0bS2)Iy>TfgtfcOr~YvPhAITgLd%06I^Z|zEvwp#_JEhq&pkv@nT7L z;9B;L&k1)b=fmHbIQ<`F^}V-mhbFwAic`+M`W&FHVoUCeMHT2*zZdp%G+kIaG!TNN z4I!_gn691F7u-X-Z&Ga3vjJ;+Db$JQ0r_hm0?ZRwK;Xf_!NOqj8TEH|qAB9;wUcdh zb3dbuID{n^SbmsLJ4)2;}VMx+)t4j!u4)3k=w9oE6(%Nk+ISL47B5St22MYts**7K3IbfVNfT_zt)+{Bz zZ-aHKZ;tAcd(Y=N>nv@XXCPC<*6Zr_&K)s$4n>Gp3nQ@J6hAzV76x<<0t@k878k~r zjei=NO2sQVl+k5K?fI2ZUUQRC2|EWs*Kqd&BW2SUV@(_(wn^NxfdbkkQr{;2uq)<( zzh(HCpR1+r@<;SU3h<%IdY6H!&kt|4EKvQ93d7JCPAq>P%_7z8z>^A98BFI{k~}Uk z7N;(=k{Kf~1Vq3yj?XWI66{kB{Xvgn=W52w7r5IntP-&ex zQMqrKl`3F9c@>X{P{SIiNp0)ZuF4`As|3QGA-m&=hU_$$wPNFL5LToHKco=9{l5{YH3W0}7Fot_Y6`aEj&W$nDbqSLm30heN<=az}u~ z0s@7td{-3*3F?HJ_l3F9v7cZ&p!+t3{%&&xi{@e0)nGt1l}g@t z-s;CZmU{l-_LE9NT=VbFdVH73-LkcF{~hA^KcC0i8NQD$Ti7A#(lhZbJ3-z$RaErF=hM9 z-~2_+o};ZfaRhMI)?3TppNYLJ?dVq~4RaOqpeQyZq1xH>Jw4FWg7W_Y)F89Ko z3V_>`R)FN<*41Ct7L{r(OTSDBiQreU@NM>$ZDUwjUyVXdHJZ0-C+U0{p8==;j@rN! zvW(Z?AByK&A;a(tK$+>RwwFzA^XnIU{qCO@1;e*{hlipU)ysRs2@W0WC1#I}6=oi> z_G>(iJnHV9H3WK4+W&T(X)bvC9Qv>#gTpV|2EfRbfC}r*BJTBtTGgBl8&*sh3bi)+ zTUUTBGU8*KUv6waE3G<&WgA)jh!B`c)T`Q+V0E$kQ2jF<>~Q?r3)nn@JgqjvX%5Rp z$)T?HBJ4(my?5-u)-@a@?+FuvlkH5L*ET${E+{k1L)b^!itTmAQ`dApgAgcXC`l@r zFu?ER<%q&GituO%2?S5G29?iDgI;!6mg(qsB5g9fijElDZ%}oWB1Y~g=`{5O%zPeU zu17IU80g~rMmVJQoZ+P&tsakARwfdNHkcrFwN-PCta+`srbtp6a|c{@jL7e8eoPHF zbqUaxFCbpet{WJ2t1y|vPH7v#MQMnf0>Jo=7PV3%isZUNqt_^S855(ca+0Az7P&8e z3*PcH$MKu=MkJRT-S^3(7 zEr$89!koefY#*h9AC84V7{WqTE@1*ato02~TEBk2rgIE^CO^A?VX%u(3SSXtfjXK0 zOy2Q~>PnMD4NxEuPI=fMM<6<1m>fNj*z=DJfkPZ~lwc73+g)bA|91wAq7ej4$sI5t zjEp2TD^MieAg5Zu(^`c$ZwLpVf+I*spc1t2_fAQcl=szBlUD~L@Icu2L0ZD|{D2R^ z2)id$B~s$S|Gu-oynC4VCjVj4j}`Q{qoZLt=HOu$O7+x+TX3bEJ0SM2(7lSq(J+_D zICjz~GD-aiGW)5aLo&?%;Mz67DcxY}Ox$krZ_Oyilv&~2YJt{**Uk>Egk(g~$kq-@ zL1eHHi;!p%Zh>SO`jK`ffKA&jT=>Kd3L{8K9A3shOo%9`oh<cCXmlAJttBvb%DEYlq*hNFxDFEJmN_%PuLU8Ft&3`mSETTBB{igdMa$X6 zE<=uX{m;khOxxco2l~4hqFCljh!p6j7|!&X~B!0N^^)&?HS9iMCTy zm%e6)9w-p39obfe)Nr&wrguNSd0~siw zr`<~2bP2ZOXzo7mpnI95V(i-e*Wu4iEjMpBT~A&lpCrwQ_X_ll*fGjdom0#T1391zQ{(bnp+_& z{?wh4x*Nn|n3cgW2hxlYA3DICpqWox%_1%$6zD?QxWdo{!11+e{Qyq6%^^SC&R9mc zIHe4AOkNrs#+bYqJOApGTIoJcl^Y@zb#mX0-);|XKq3s<@~{9f$P$sK`{89PkFn?E zr!Dx?8S_xF$h2yn+Xy34q>6PjBfi#S3UPFvV*W7$`EZVIbVAHKlGZlD2C4`{_>p$b zGIUzkeZJ`;4^cA241tgo0NJCxdKAK}ZP% zBwzolw?sVS5n5D*YQe*7Q=5@5mpe;*Ywu>u|tqpGWpERNwf48lIB zL0ZOwW|}Dl84wTENc4(ItOi9Qp@2O%Z|E+e#@6BJJ|JGL=i#;G+_^Zh?XjT--JG+o z_fo=N&{J4^bA7K0k#n4NIo?81qAHb2Q*%yKeX7M}twyz}FcNMVsNGyg0)h#E+c|*dsdg?*nx5H4jwCkZ z7k2hDvLeaN95WpbGbdwGRvrLyhOVZ8*KlU!G>b^m6qC0eKulm1;Fh+^X4ODEqfQ++ zv@2k)+J*|7Ej8%r(Q#bELUhEOV6{vfbe=Og=(3~RV?2bmSsZ@y!u*}F3_aE{fFR+r z7ju9J8;A$Y4$d}42@5%6h|i)3f`DVs`5VLJJG;2%?#?dDHgIuL6AnAbpf;O9vNr7b z^zF$_J;!$7_IX>t9&pHsAPoOZ{S%YV>Ugrh;$8vI)UH^`leLXgY<5k?E$oq-ZwjAI z;?qm;b|&;wigdVH=e`N^d{cQJV*Sn#qjVNg5F!Rp!<R+~wS>p60@z zmlis}I)H~d0VCeRePliuUnv5`ThnS8X-O5l@GXh+%>wD06wo|CJJMaud4#KjO^3KL z@=78D>KZy&<`7mfV05|>JC)L=itu9HuONaeIs7S0GNuXBo(Quv=YvbK_i@bV27X`+Z%<)bsWg?-6lAR&h0+b9MiI@lQo5FK^{7pc%|WP9fH;wf`Y`6u7Oy$unp=&D z+@<1kCGBbsJJmb#K@&qOgbDh75ThH0F6{(J?74iBg^ggY-*2#4HcGaDsHd8$PAck^ zgN!S)u1JbQuI#L*++S3nv;CQXHXr`;%A|S$n;5xaoFS{!ME;C6ym8nsk)r*|6P-zs z$RCki*-f!vD6#>m>3ae}#h{ZVNn5E!yeg3W z%g-ChR%t8jXqm$jVRGI*e2>6Y*fdA$B57l$JfvN5e2J=||DML8fR1Etg)uyBBgub& zu|+wtc+9r{(ad8c6Wl^%Dl>;QBl{6>EWo0vBl^f1iz2S>$nu7)<>&twdT&eC2K(7_ z_1IznN)8Oa#~&xAM`#~3k?$3F;1d=*qM5iNA!UG=d;h%%*rTQP>&E*ESOQBkPF8f6mca0dFJyP%yvEAREN0HWN1~W&=+0a&@rcqEwSyh6{@=>K-cG*w zXs4c#^E(y>Hn6_iAri-adBvu%w5#O#g8d|Qp=KbR5oC%^^PMrlA?(9Mp96!>w2}{l z3kUaNFKzFk>VWU~O?|t79{_R}uUeK^F8KkUCN=6u` z_w(gM%gopFG(Eugo7mqH1tW*Y&xicW)Iogg(wP@K3);-7PlCZ1C9VN2ShKJ4*MhRH+Me<`ix4Akmlv&jH|j(D7W{3z1K> zt0>Zfp_%BQs4;o_&td61RnKHADq(pbe`2PFh||9ZZ=r(4Svf1$!zvTtS^N7ml;pk` zVXTOhAc6rd+#!u&km}8XYDUYiyU`6ryby$v`l`9l8=h8SV+uzZJ4r9ev@&;QpRJHd zWEge+(nl`Z?xZjh(*e|{A6B}q?WyXvk?Hr-k}dU)Ge%X95`sZ1$~6j*_6w^~8?Dw; zJaKO#L%TyH1d*PB@(p z{$)}VUHV!76u6Bs6Hrqn?N9}wE`eg#AqHn)ab4bHOBSWZODvdKZK{KEPnrmheVETg2hAyQzeF5O)=$qkeG8yPlT0)52svXin;$dobPo1p zS`Al&rRoVOV2v8$d?5s*Yb6%fSohL;`{Xn+}Gk8I!8r50Vsm&JXAzi z`WMD)^8v&@kCz}5r~yOZsllqp{^bU;99@_cc(O<8Abuda_a*I z1W5c*<3MFkx=$y&}%5Bp@45bE*w^;_cu1MzpoBUS>r z*;5}foXw9f{(d40z*GOCKe$u9J=`9<4VWM0br=ZfxC+%wq^5;VF4jvF9c(9*okz+P zw(N3{*bAaXzQBViYHqwbu1_7^R9*nY>eX&sT{|y>08YS*muXh>AKlWGuqu;A%UH}@ zMTYO`mV>gpvU{T}4*ApxLC#k+Erqz0GeDM^k^j~wB#`khj`t)DE4gHlM#vQMz33kH zsJk&x&vvE~pIN65e+_N%hJ*xp2D~LKl4=GleJ#>M7k?rf9~$eg?Z^KXr&84(suwUd zekcjxLOXYuML7Kcy4R_UFk!)}C{`N6(FUw3`_XI3;CvbPg?CXR_1N-oPcADMf;6_+ zk!yVP-e0|eOjWZt>IYc1_dA0n|1Yss!0_^<@GnhR^}jS>9x^--qLLBds%-7NAcn$= zohiY1T%7WlAQVDCf>^JTsE`F-+n&!exzLD9q0e@&g?4J_wgQP6`VsdI|7aZs9~zMV zIUQ%@MH&hjr^1|~ezNU--PU2g)9L#L?+>bDjA3KDRm1PN>~X75WNSVK$u(VtY$8b? z*%te!F~!7Iuob0#S4sg;H=#;<8o8T)PCl-Aeyb6oS&F`lv|T9*I?~_2xw%PnH2(hg zU5-B%QbAXbTQZjjwonBEvzRddLWt^I)MG32<-Dm`!#yX%047;&IW?daV<<2`Wo#Cn z)PAHtPKnlJ+_*=W@SAL9i#zdzhsW-4KbS?qZ1vl})|vm<@^lBF;Z5+%)*var!bAL! zb;VPtbEGtL!;&^TN-O6L=RN!i*DSB!K*Wmm>`XRv{&BL4s$x~S&+gLHpgZD|C3s%P z>dE_`CrL%9x^oJDhNfawQa8Fz2 z5N0PK_OIuaVMQ@OnD$-Gu;+kZNO7hRPTX?u#1aT9Bvo4Wlo)}TL7}WCrER=FI3oNn z*M#(&HFPU~mfdt2S;<~)&$#LrJb&lR^##Rqre?3Pp+T(KThovMD}M~F`dCQmFhd-E zgrfPBjqoVgn$2GszRB%9nTj%F#$4+N6?+j&?hOSpHH<94)#8LBjS!xGydghgxt=dh zxSpNuZ*$Dfa!FQG@o_n3TW4)Z%CQYm8JXF%1RHY)m^H0X&#ME+*p#$a7(@mas#K^M0VZ4buZ z443qp7a%Ku5IQ)z2O8`?%n*j`6QgE!g}Gn+6fl8nwDTjt8W&@K_s5IQMWvDBL{m5B z{_KxJfZ=#kH-0~+!BA5y>TahsExbE2nS2 z5NG#^TEk7-l+6^^y+P|z}0Tv$#*eBo!=(Af8K=9olaRm-H<||zDH7V*=5(?#uN|Xg6qXrf@ZQGDd zvt2YbS&OTL`$6#cwvmH?$Kt$F7}%gX8o)Pj-*kC0XMDb0Y`Fh0=0SLM@%=QrC(Mv) zBH@mTC1#C-BT6<8Vf(Y#7SrG(7R}8>!pqne&!+~hB&~1C$CV=uI5;Dqn&$wDR$<58 zd9YydnpJ0hROkLn>FuI3@$DzsRL~|Yu$j7uPCL^NlZU~>lix+F&5gi91Z;ciaf;G6 z5(WS_izUwwClv~8C8wo;lj%}2H7Pd9Jb+r6qo)c=j}jD509m!n7^nrbjsAGDOti^S zd1g3uNG8Ri+!>Np!ac>_e~qKevj`vOdgp0?!nxg z-DlTI${yhmuKfUXhu#o0(66Ggkt*WTZ=P@%)-n00B}#y{`Hv?d?X-otP#_6d>%gn?5_p zCciPbXh6C-mD+QgK=}v!XE!wZgXpB8;I5HK^O*Bh!`#vR`i={FRBINnHcRz=EhEU3 z?pAtRhEhcr^;*JMw@QXZ9rXHpXSOx}LNv)i*kGN^Cg?;|?$P(JL3gxg z@koGLPQiudVyi*+#Lok>Ci)yia8>lG5V5kz7fsD6+%x>${Q{ zfZgg_uD$y=sd0+Ly0V|maeS&ED?&|fk^k$%`OEs**nc45{SPEwabrO6I$11XQQzRK zkZ=NyjPel0s1hmH8g4DS=1u$GJp$FEd2Dbwo!uWJISCmEO-dWe39sZIzvUWlXcXq5 z5IW{NZ+IRiJMm{G7tnjY;0*AjVP5RFw5q=hs+^sbJyPl|(rk@~89wc196b+T_1Z49 z18)Ud|3$>nxOr$YaSZ`>p^oeJFs5w_2LLjl`$m{5W67>+Z(>XcSDYSF!emEfieu4Pmr0xGXfC|mPUq$8KO`)dJ z{(18xqR@6|?^!cbZJa8SIb!$d^(DKz5dbj|iY(TT91zJO>=p!g@fYMDQW1@SHJ*tjqyG(1NQ4K$>O-E;uI>WJ4uUPT^cJ1BO_R`MpFB+r3b*&2jg!` z$A3J&f@3=GxeYrinT=Gj3?2LXWYGmhVeyty3MOn@vmp}mJXVB9>aU6645y0BEXvME zKeMQ*KnB!uv*`;xp{sC z8kJSE+Ta&zXk>4aE)d%w-v z7GYQjGhQc!!dq~zHUlERoML$au$3obvQT}vge92!Q zN07SGw7PubZR3lBjQys_?y`S% z$VJWB-bD*~oL41+JwX|-Kxv%vFzzHtH*2-8{PHpIo_w6s6#QX@a(4!!{T{obdfs^P zYgB%#D~wQb2awacVp_MH+!IfERO)s+L|oyFG$K0JABaL)Z|=ZZKcOLO0~E7-*&`z5 z4S3v%e@QFX@Cb;8BF)D0l@_@JMWk}hSj9eExRUise*d3QszvFXAPwA=vIB@h zQ9moHR(!d zN#=_>m`{98vTm~8%mANX@36fDWSHAFHj^cKXHlCvh;nN9%TuIX`s`ambAQ_G+vGZT z%|O?R>p)*XI3G5nGCd7zJc{ttm%TMyT*mt39n4GJv^G(@H9Dw%GK=JDAd?19_~Y z4l@pi3gX8)t}~1~cs96+w^A>RN%`qNX~A#f)_m4to*u?>jCGk!0c|L$yu{$T*0ZT6D`_Vx|VF!d2w?fjm_&lq_Ql zI50BZ9ai1Uy;Z%sscapmY4{`|$mv4$kXUG#?56FzL{oFn>`PKqFs;+WUm+Ztp{@1& zOJA2AcPb>I-2|fiWAutJCQZALm|}s1mmS;&u&KYvz-ky8RmOz+Q~`;gPeR63Roq>z zG%`IE*ENy@tUC53e?5ZC)F!0*5C#%(vAm@qgBAsqI;LhH@G&V{g@I37E;$p7ly6+Z zU5LIZ%M788r~?uUB=8tB4Ue%kH{}>ZzOc3y@Nn0JA*E+R$_vhXzRYDip4}GE_w4c5 z28{*W0+n1^l@=u@#(;I#+3whFE1HG~V&7cEH~-xgG?VS2PElT=$CP>|F24OmZkiz` z(=1vb9zWq9P~wFbALKcv{VPeYB*t6NaxR|{2eWhVP@|?iZPvVqTniig^woZgP^rx; z^39-^dRZQ?o++QeoUO9IK_?KDEE&6T{1!iz%Q}7_u3u9>qQm{SUj`wj^1*)p_#p`T zKQGu>P5}C+R&IWPOJX{uZ6B~(j)tx=5}K-vf{N<;Z(t;7#K|^0P%g3ldBN}PxZC-f z_aw)A8Zgb<64&MO9rQzu8Hgb-25_y?>vB38XKh@zqnv<8`=e>ZA?)>NL)4beC^Kz4 zFp1!vwgGn~`jN6)p&`vO6?Rdp*oW~8veKaRRg8E7Q?B7shR68gj3zE_)r)WD>eb77 za8k=lD#W43hpT@Owmp!SRiM*$CZK%t=I|*zPGVysTv!L#Qf3ePo<0mLM(jI-*d~7X5gy zk5NH#Z#ZfdB;nmY!mC~R!`qlJ#qAK1=4omv<{lR40Z4AqdO>io4A=n4Pa2V7o+LgN z)1EmzB@l%1^66LZc4W(n4O_VDiSX=ZA3W|TgHU@XVKi%hKMkEjnSo}f9%ah%Qt37$qc{g4bM4GONOpDYWv~5Jg>i2=zUC9JavY-HHm4qTZ<7bEYBS}?G=lGMU1KLoyOJL@1DTTfIdZiNxWufy z=ol$8y}qPNOLpmGZT@J9TukfSCRHvHGe6nm?*V5YdRvaCNK%y^+`4?s1Fba%CJRJU zJD9yO`x#}ZLS%wGTBOGfQKphP{Z7c+v?`l2Z`-SWmmxQZ(DtbOCm!V_Ha865)dbrY z#q)nLKA2jmt_d<8Ahyu)2eW@R?g_)J*lKqamlm1>mv3fE){ncp^<=%Y zG6C0CQw7`_3$jxTxH$#$Ma3nZ)VH~Ggkr>mwm_G%l#&b!?BAgEWF=4IHIm_+V7M~W zGPY^q<*yLJul&n0p!md#$~R00BB+|5j+>~xdOih6J_`hSyLM7!juaDYHHqd*ca-}}(Br64mu;i%tv|Dr@x1_B<*T)A0`_Gbzz<4Z9W@6^41RVm!Dw^L$ec?1=* zvT@kn+j|a`MgkD5z-YNkJD3%eK@U_Fn3qPrki|uA_4D}JvwNjMiTCEc(e}YhrFj3HLyq?J(pqM+ z3&jM`z-XmO+^jdovCf3c>w5daCS#!dr@;~jT^ugYdhF*TisPAIIKa6cG$QeFN(8b+ zha=#tXjWm+G`p%Y{Ax?|vNJC{KusU9b4hT{+*5KD{W;8fq~2Tq1frvVA(>qdaX`VyB!Y5PZjbS~JH_=Z#-R=ojNI1=}5ppvv`Wk1XBeK<0&>9iY z5;7**_D_6j1g=6O~;>eb|QAzP@Mx)Fer3!9)1 zPX?^+o)tmNh4-yL{)t1e?@-DAXetO85_kDS_Sgi%IN&F?AcZK8pe`w9J^d8ctvmRF z_U1nSh-^Y=+he7@ivFG-?^~jjk}LwCi${_k|K&}NZy(Dd%6kyy;nssbpX*JS9aZVb zyG1MyEVWBGsBRUGb>Fw+ye97nzf-K(aklVDtf;}r9cFg&L7N$yixS0O{67GzKvcgM zu;E1k=r+RpA^}?k_efMv;&RkTh~G#o0RqB)4g6Cq`SF05c=`z9lQLrkAtSq(l3V=O zP=7D&WRuwQ@G%mmDE|VhOE9_>0SVF@1jslVuDiO zp$5}h6Q7#P?sU6!zjAlCh8X!F{tIJ*MiYO4Kgu{=G)D2kmwRW<%$Yee_kR2S`73}1 zRs`N1A9tE>^aE*)D6sVn-5TiYx)u77>&e6o1H%t(VqB3&GA0fVWo%eOvPN<0$NI)V zdNHl*kz@EWGJo8xMx#-$*B^4OYX0I6QqN-`9!ldryA(KXK&0HjVRTF?=3b09YY%Eo z!=|zRR)Y{IcEeOzwBvdtuo^1IbdoJf;Qa59L^z zo(vpw|KO0UB#&8vrR~}Hl*#yOOVn8SI2Ldw!=L)NC@!XK)-M{z=a9v1~l z4kgc3$nzve0xQ+CO4iOoWn9ALA{Ma7jVH?pYysoHxIZ;>i7U7|5xUHinzhr_YPil` z5}u|CEL2qg+59GMO_;aK&`>B~26qIepYmh#?q`ta4<@)e$1+Pp5hcFwvA2pTwt(d? zn0xgR^OedcES=z5(NwV;+CHkS-D`c_ zm)B>l-R!2M|8wq4l1U~=e~(}E-h0mXedpVkGhe^($YVsbO1Ylt?i+91x%PDx?MCE? zndqnpRzx~0sw*N^yeEGeGtyBj5r|tICf1W?%rsIaHoJ{fAku9{j-)d2R7J4Uh^5Tx zik_}O+~^5JC5=_9R<2yR4zS6!dHl{yEQW;td)xlip@!k`Z%LG-fg_vXWi3T}h)OX4W1{8a;nKX0mp({M>7QwHVQa zN=~M!*BeKT+L)2(s@>jxy%|ZXF}fLc zX%98gCY^ukXtQmT9Y)ejq&?Iu2-MM5n`o;MH$4=x*IGdIK+W|=a*;;c;XO4yNehvc zj+!ZrUIV_8W>3rz5t&RurE80vTZEHh9?(X+gxPj8Ex9xzQk=bl$!qOsvBePz^3Xn7 zCwBHT`A21mNGytYh{ugYM+o@_2q_c#JqVAewCR5x(&;)n3}YFwn00J-;z+_eme}4S zq6IF;aIbcXlmMm!UtJn?!ss^fKnAn|-BujV+YPN*J$8t#DVknF6LV#s28~=#M+7&q zi^^a_tAvw0MzSjthYEJ}_P`mZg~sGBknEuwO30!ln7=_I7|eA;CTgZNI*OG>jgG^_ zsosB7+KdN;p*4Cf(_~2|la9t}L(vpc=j$OAbm(qU;I!0+!rME+QBNVn6scwj?(mPNRY^$c~ zdu>+XD4{~g7NZBpy_4Q0oaEi(2w_{L|AGKgA#kZ#m7}?BuwpU05`f4Z^j@7#(w$7c z%HlA#&)%ie?Q}{Mvd}oLb0F{6={CBDY4xiG!=ie#(@NUm+?Hw2?W^=brp=WXaaw;H zd;M65amvl{^I@GnL?6j#RB5~Bw3#&8MRNNnlNJ?UX)7tD8m*w_+&a|rar#6leT@2; zs$W$q`_Yy*(xCsT{J8}bRr)mYAG(=V^LSb&1O)qM=z&tYpB_Y6O33BH@|E*94}Fdv z5^$e~zs8N;b`vKh)7x_%UNjkl_!)o7>U1CVGbw?9Mh`OuUR98~POzKHM=A}90Jv10 zKdRFg=rPC`2<*RZ!@(+z9>+)ANTV{RJoF{OO%;6^r6HARPvzXZyt27yw*D%e6VOi} z^IC}lY4=@X33ydeZGxjLhhx7+Ul%I-Z>E+1IlfBYKsL*2pKPGL60sl|~aC=JD;Q3{EJo*+bu@?+IOfU-)wKMC$yZ0QnI* zTq{wROXE!S#XRRf<@U$)oZ$9hhSmF6DnWI{j9Z&eDjLNTZ8QZ8Lj4^gGdwouvO`nmJaK`b;#| zA?ok%QG5^pf6(a#(VDnL^PWI~4HOlB0y2>FPxNO&;xEV_Y0KX9&`Y9`d4c{0W1&Yt zTFk50L;s)$gl7IJwGK7*#LP5$hnH>hz5-5S7);XLG8@257_6{yD;psdh-*p!Ps60z&pUBnIi^-<) z9Js&+jpt2}EkzXZ0-=9=3>c&_h6+bdW^BWmOUDy71O+*p7cm^;BxB@ogH&A%eU^80 z1r?PXnUgDdsm^m5qsQc)q?v-}4EKX$i@zwi9P%nTo#F^e|=#v9M-b-W@J9D|wxOz&NpBROx?2L(pZ!WWYBakC-`Y zVYHZIv+74#^T#u>bQCV`w_A@IjW_DNK?K}_98`y8ru+#j4e+C;-$?Y@pn$AHS3cpi zy&HL83;N!WWgW@%sEk2mR%6qqy4|5&hc@r5YYa6V+TGT)^U#*` zt`UuMjclBGi#>m!<~*Ypu6ao*07~D=+eB=HKz8hz8n?p6AZsR$dU%Hoh}mUY?)*_B z4Yx5ZtSp@2CKx?zhKOnOUL-3hxhS* zox^+p&0vx9LRMFoIN&-_boSZ&9oG2}8)9HSjtGPcMnr$Qt79bAiXtR(cP358%}7SH zL);0k7infmQGJZfPWG8moxAvYoC(M8jH0?0?#(;m!N*>u2jhmK88r7~|Bzi!yu>V-(#i;3ap`TXepO--;HbBPv?U_Ke*uP9AfO z#Bbxb3$xq?Bh_krJJJCr*L1VpQF-`Xb`ii_#mIk3n4{E`(P{2ZMw#YMaGNts`VM}t zP%y@+NolLDt)aO&*COy;@&bi1LOEI*uhjVc@W8@Lv=%d!GP=yhXqPF9*$3=2C5@60 zmvbv7PE*BcfS(WXhjsoSV+wNZ-nA*PR%0>vfNXtlT6o`#Vl?;Hd-&u0384fOQ+KAP z137;m6e{=Ei(2(5zE9BnbiU4_yYH^8k9IXD(xyxhp8-;bD7lnYy zgb}lE=3-Xl2-H>EG$A_l{{%l-0;l{M)7*&zZqW*rF>NF-8cc`exw6qyobMM=Y7l{rBQ!$ z`AKvVRub*U5AAgf9kWL$?#v|8$djYmh#zA{YOpe~4%r$+k|sRP-y`qZ{2h5}{!T0D z7i#wl1Nb$@xG@D>*R`jtSSD@Smi?)`ROFxO{G8}Jw1kncL{^p!_Er!7l7A&?^RHbb z{!OXB#zFj@$MaJM)V&jx)Qa1dlsA8&jKN~w@U?8D+ejqLSW23u!TwPB_jv)wfrP-Y z%74HBo;;@UA9a3S6m(r^+XiF0ta8+~a54JO{$Kd70`(<0aXQ&6h>CPH5uVrw(%<HLa91@nK%u5OsM zLsb-{l2ptzdqj5F3UI}#xOBy#xbuB|9^5)6FKZMHkP*1HN73maxT{hME#!V3@+gxq z{P2s)WEeOWZP%2k=m?60K)q$9ku8iK@r#Wd&oRZWP!+GPl!>%c5<@Z(vLgVN7KUQN zhzqTxMWxw4=JH)BS7yN9l$n3|;WPJJhK!mJ$`|yf_{2T2Klj^4$fL{^zke)L#3V8% z&hi)wkX?tnxKTUeo^D)l+FRh|GNnRS{K`TPHQR5Cg)I9Ee}0(&TV?}giLT66Dp9^r zP(<|EMjLx4Wv}AEWlEK>Tr~tqiJy|-S;x}_?9Q&7_&lXXsTJtU;mUuoSWT{1jv1Lm zq#OOZ-TDiAY064rAzg!tS*2Vl^srjPKqr5XXfe~>76iJc2!Z|M2#h9~ zG&{weXst~FwAU#?ol2GU1veIjP^z*4Niv!^Y8^oWT32L{ocLO(TD)GbVm^Gvyt*tv!EUoBpkJJN?l_etC51^eVj72V|M%}I`t>^-j?M$_PxET2E z@EMSIRp-jCe`NZzOPA31$RsRhCme*q zYGVVEIF>pvNG9Xagz1k6KkPwelk(@1nSZO1^mit$xIbcbnC%ccZ^Fa*wldc#wDl&^ z#_>_|wu{@Ji|~KmA$W(cI>m3g$OFifks}x&b_p2NTX9v>nu)iYNx6a)?;=%}Qp6W& z_>Yw?qDhDGR!XFmdtF(YlBM!2&B@Yb;ZT;Ac$a3W_LTZ;)c{@jFd=?IedOIcNOj?s zsw_43)0XPcva0;|HvHG>-QnGtr9J%=&e8$Ggv()R`=#tda?34u@d&a0f62&o}o7l(Ax&-ws6onNVkUrr|CUe zdS5@?-A^AFqz{FIu7JoX;iRPcuCZ(m^##1E=`oKGpk( z5R;}2(ieY#D^Sn&4V}mO7qj%0Q{)4h3gtZMQx9e7e3qUGy84Fh$NqQZevR0lx*BTJCZlmTymH=_dl|7?6G@k^BP5IRffa-6LQ-9-?2~O|t;}YYFV`qtZe8 zZMdKQ_iO-YfDCGo+NWjd`BOAq&=T)?-lhg}w1a;o0;)tpy~*bqq!+@zl0)7X`{|Ea z`fHZ{F80nt=q&x~6qV%#wb{7vH6K1M1YNGxTDj&^v#i{E;f&8!t~n12Ny{}UYEYA8 zwF0s>GZ%sY@o7O2=o>l=N&*eNHgN+5k^(9i)@syq~9d zd$S|#J*YZ-rpp4hwhG}nrS zm8Yo92M4SRy1ZRj4+q_nhbx`82%oS&);d2*GlkpX%aP^vUpA^yw^rTV~;Ki-?m0x$u$lwMr7- z9md9XxHZc^xSLi4ggt2z9?!~@;veMa!UDJYP#OP3gdYDqkN1nS+{!`c0RLt>|2AI6 zzdK>9adA-fsZY@E-0BS19rw_dL4H0g1ObmxG=_?t#g zo)}PIPkozDZSCW7q^MTdcj&X*`WVr7j=o=&RXlJXXhE3*3~{`|k5gU97PYEOnI;4h zLM*M8LR3@_DrMo8er0-fR+$xUIY(2gA9H?~^lHb-mOgTEOZ7Qw8&qb84}<_QC#%eF zaXw1(!j6CHwgF{PR=K=iSvsHuaPo>W<%+Db2D_!q<*TruVqsYuyozC)GNnb@=66|TN13uy7`dcChXG0^0N5rV%9MS}`jvxcM{$2#4UP}xIUXa4kzbd{!0bFr)6pV4Qm%ClIM2!FdFPMB(>>ii$9%%`D}N0%jeDR6KWlvC*1Fr@F(4OilG)Psh#o}Rc{tg zQWSq+J4{+N1ojk_HmJ0aSf#6nXmaiwWQXV@q}m_y?>d!kQ|UgH?k9SgR;yICVAbVA z<|C@jDP_#!-qXj2iOr}98UXsb#lqQPRnf%J*??LPrDa{?g9Zv*%*#_13` zJNNK5*_$@jC|&Sexp7jGeT9|_2LDd;hiHF~P=-E4I=RL`6J0j%Wh%w@5cLgnz&EL! zg7zh(5b~d-zf99v=%P4`*)^7AUc;8gj={BAuuWdX}Ci2pqgzfwwu$X$T*qK$v^ zd>%(5mqZb?atMz6>G@?Eb;h0%FMU}!E_B*PN`7~y z^-5{@->}!{^6c z!SQ=w@_TUz8dv%hDBcg#K8SdHnx=oyGc=WTn#Nx8DxaY;7^ykN~&~L(^BUuTIO6sRn9u9c3w*X=RvA*MyS?#f|ff!Mk}0sw9@$?UEyo|5v_8* zL{~chMXOy*Yg~(Htt&w5T+1owYNqwB?R1qZP8(cDX``!`u6Er;*SH>}I`?#{cdwxa z_np+}zMGodKcr3SCfcmNgSMzoQ?vRkZB_paU9oUO=*sbLP)i30w>@zreii@#T`iLl z8XS|uaY=u%l@VYtItJBJVBIKTgL;?Tws$1CCAry#4^+hA3+3T!h!5~FR8+t&tyG4H z+XNLvK?PCqfiFZ6Q4x{)KVOnH?bfdHUDFnLQY&vFda1yq{LO0#l(wDa43A<%y+8P+J(=F|(jAtbh zi&uXbC{vid-P&QbB&<|l%lX^3+cD2Tg~BmW+e%4!zQTX&cQT8Y)A-2_6|5J!)0~v!tyM@jjMsZI ztf<~}EMK>dOD_sy4yr3rj@lpssFJUFK?L((p&({prhFY8#4OB~uVWPa4RWpq#|B`a zPN9shr~i&>SlTf$hO{nNYJ`Es3N!j_?*dB#nUB`&;=!V&L7adS16YCvg?VEvyF7o% zxwEoPB5tP*GzPFt#2aMSX(jE68sy2zER1Gh)n7=d^CclWalyDU(RF3Uvy%ok z(sOp2_qz75+80nukGk4ck{WEn=1O$oBHr;{%SmL@_IdP!)yI^no-AQ5MpS>KUBXH+ z2}1*0nRElPkYGiqoh+3YN-!x(1)_Grbnd>CU)9)__kVP!HDF)nHKB2}=_ zE4Qm}a;HspnGHBprnIVc^;;`fw{~TdL0m2tZAYSb9Sc>&Kx({4wfY7I=>A?;inr~> z`W23yG_8xJNUTjGBSH3Pt-XJXI%I;_k+*gywHhnpZEhmLbfr_|nsyG5I?GoiDoH#-9zGAB%x(1*?7!F|Zd!6BB_v4D|53x|xe zcg5_1{GIzozW?M)@kri|Z*r|Uqc5L{{Y26>3-%6HoBFBSPVs*-1@SH1FI>J&ZxppU zE8E*^r|tMg+tRJ?JB(U!uRS%8EmWrB_Q7J?EErTmV&J=zgiZIPhXQyI-%}{xylF#t zjfo#9G>#FL@R+izJrckn{7_2T;bVD~3j03_-~fKi3qvmP4i1q)JT5LffS*uoEa7Ij z@-vw$4&aI6jn#i*N<9AaaT}ZZ)9%jvDEJFHrOnMI;&mz4tLv4@RmVHkU&l(uoc|Rs z%_Ny#Of>_)W~4G!ue~|VLb|A7LXDdkrQhOr0sIEfOqeB#MPu4o;tz83{-~guP5hbe zpp!CgDncdyB7M*H3hgO~zlwW)iN8@bH`AQrlw;!W92{Z_imz9MUuhA2v^;-Lj6Xi07VGJJNoGmPR41@`^y*!O z(m@fz;P^hb&dE@p zI=(EOcpck`-fK41dIqYE&uuEvZkG~{zlLq6{S_()%aqxdY}K&+AHD+qrVHAc5?4VCS~+-3VPziA&9g!f@# zsC*w54dJ-EAb)dEkK^;_%%zk`?*8i=N3bN?(Kv|tIV>H)vS?$^5Slc)Jcm`)t^Ak6 zDML7I5DRiRa}QQ8%b{%#nt5g}e+!~HY#2sI^t?e_80|cWioO0>%kD-unQY0y$|2s} z7>$2!B{eDLcMf7RTR<%3uhjZ`${(BD0XWW?~dniZ{;Va?sFHTNLU6b_Z;kPVgR zuuXExU#k=jfTp5qW&5c>?*5KGrP)LD{^X1ZADMlkUA=- z<}+<_YSA8K#1Wn1hKLd3QhoKqJ@nb5A%l(>QHx18q?XW~KPACIG=wT@)QJ(Z>|Pkr zNTokybkW_FIkk+ze5!LVX7jf|7%k_=-0-k!%_$oHJTWsYFnkclh02O_ z;pu9lhDkM`p2kz^3iTch-=}}B)9`xr2@P*i!y0~5J*wfO>M`{UpnjsB(D*azS%JRm zd>`@8R4p0?RM>Zm?=u<~DEO_u&ud(u;J5qsXXx)1lNC%IDG0HmfdSn z_di@@V2Odwmoamcb6>zfxn4L||9AEO?FNS%1&p$aPf5TUjtavVWsRSb#=teCdKI$` z>{e>wD0@ZK)ci;!GX2x>GqhUfbR;)vl2fMF{1OBAjN;lUiChvj1~O8M^0r_$jKMZNjiJ3UQwV37GgxS7JF~=7} zwXY8~zN>JQzYDeg%P`j;$2`A-`Thh#{sAq=ug4Dm{{c`-2MAY7nUlqnzkXeR%Sr<= z6o&s;wOU7Oy=~l$g13%?wTpVejUWn&pdh%6)6;1*b0L}5h1du2EnF1Ag%99EiD#-J zA_sEL`SYDWA$k9JeFIR(g1}R+chPuoZ)9*sans#(gO*!$gCt6omYGUoFG`xkx*<){ z5^uJp^@279ceWE*cef?ArK+2MhF&C7PYpck^;)gA!>noi%(psPvtZlO+v1kuP{l+> z#UZO*GM3L`y|KBy+3=dwbsxtd1WK1l#{_hwGzqLECiFuio0|N4Bh!?Oe-hhFYQ6lO z5A%x^F)T2BE4$LyG7kOon_CL9B1YNoYy3Eg*l+4|z^KH}{r6aCNu@h~hR(=Z88R_* z`s;F;<+o*ObYI0PI}lh}{cG?aUb_+~tgc--a4=Ou5oHHs7$3(7Dh^7R$g5d_;X{5U zRJbYf&kS+J6jzm;;Vd{DO!7L<-69GcKzaT8`UTS)eauw*n0p2WXklPc_ykZ(2MBcE zwK8e}008F!002-+0|XS4nSe)s)p`F;^th6&JZ#5FL;|_7V`58|odgmGg_rFFaI8GA z^FSmeTuayXC6cbty^3RAgEi~{+d5jdHt7nCj+w2jYc`NWQwVGwP&V3i?{184quryW zYsc1Yuz~jf&b_i_$A)gpFF&38o%5aVeCPZA-{bhz_rLf&5nV3s5_I~1o_hwj-Pt^> zrH|?POmm_+J<{CKoHla>BdghlnUCkpjE?!Dp4Bx=$Kse~#nWSY`j}P9SDdY0XH*em21$c|ws{2Pu*(@fkF)h9cq@Eu&^15C$@}rnNt`{wwh52or zmvwH7XY}LEcLzua3JsZmrD9sY&dBP5E;5UwU86-UlhwP%i&~+e7rXlNmaS#83V8)B zyG=W;b!D~uXxHB1+w`=pkYA8LYmScUMM0~R^XyN`#qELu8FM_JHMNYOi|1q9;Vy&q zBK<@wLTDPp-T3(Z1F8a;gtg zm=*`gM=Qb6YN+ZVIe89hbWl7* zG3o?s7Bj2@&aH22KRnwSVcJNWSc}bqmd;sI5ZKf>Bf6)5Sk&a13T+KhH+#CyuyzV{TpgPJjQOU;|Mnl|&cX5>{ZKLIvJCquV7)tx5_AoPrCo9c*> zwdEp2CiC)7>Td=s4k+6n)Rn8ln1lU~twAxaL6s9u9c84fQdjxqc;|^USsXt8n=tefwAVPgXL%H^`UxLA4eht*th-d z7g{7t2k8*2aufKn#&CdcW<)^W_IZraYnnFH)C#+Qq1ceE6_F~|Z&K(ZA-aXp)jr!M zc`e8J!se_q4~%c+lQcoQJ{&82yjJ9^PNPPhXBY097PJC2#Tc2W=EOd?UeH3ys@WBuYWY)Fj zTk|ROSM&1ZvW13QLt`2u zWvG%_g0H?mDuW%DskaScvW-r!Lfl3~y1jB2;tZ7zUHa zx!cu|qM1V)u!|*&)1W20#ZJE1j@ru{C}tCCtA$xtj+!(b6FJkQtCS>ku&G)2j zIHYD;br%jAmSL-7wq39iU2cl(xMZe9kd>R>Jo^^%FVfq4{ z386PUi`-Gl-(eI4t(~`~&g8d$SuGZJblq$eoM!DyA$pFpo}%Y%u8)Euv%0LE`BF|V zO1DF~^YjAqzc@=?4U0m*i%`RBXSZ3@cV_h*q#`nZkK3Cs(@V%hdHsa#F3gSX>B{;F zeTCUyMMb(m>zz<@LZLr^#)#-WD3oFPDo65b^fhFh1^aQ1`Ta$WUrm~S(~NLt{5qOf zOB<0Hfn^E0^he5BQ1XxIPeSxZ^rw6>`apl~7`g}C^)H;1^9|(5suOxkBO{y$_Ll6L zO7d5NR@J&`_Ud1U=neKuWX7|#3@+yWCPc5(-=e#erE_{!P*+=We$!PiGrO+gK5x>u z*tOq=SLQoVp??6}#!+^EVeo(As`iic9sc?s3MjE-3-eEMYKhiw9V0G zHW?Q6q9G)fiN-kvcfr=Zrr?Sum|Uz7w0=l0A~w{bZkLLAB=sBi@81W?Dj>BY|C$*c z<`k={k3IKvMc{#d>a)!QgUK3`IEzWBwnkhW605}}v$rJ`fmh=a6fv%edFQ!@)H`SY z%o-#$iRnF4Y)f&flxB<0z&ONSmdZj_v^?mSsSoER`6g{Gko4I@` z6~Y-ecqqPq&5^x!`s5)K8MvzcOlA;xAg*j%Fh_~qd<8tRmW@gi*lIh&}!=(QA3DeJQ_HDovFFS$C(At4v2#xv0og*2E*bOx>zg~(B_0i3Yi@%H~WbH zEhEB7XdXrpB^JNw_51~Y%bFY7>v!lQS}AK+>3ws5w&VO;#8Gzht+W5Q^uHCPh+)*| zY6plHr(Lr8#&A(xzFc#BrcV zj05X`3`+P1*GeDTtrhk&4`7=#^7@`qZdfnM8LCGKQs62Nz5*1)S3Un-O^#t&j8TCP zm(WrYVgl3#@Ov??j;4-GQNuY}o*I~bc*&) z(kH3ODdI&HXNR!BT)7fwZ-K5>tg5V7FO^m=;2g< z@+Ddtd*1sP1!JDgljIdI*B+6%;E2VNhzby~FTg~L#2xs(lNMKCY7bkwou~p!dGOid zQg!4}XiIf%G5J6#)D0Sinj#hWgW0=X2Epu#!`^yng?gB7ap-ID^$xAAz&DF9lY~d^ zgaT1G+>ed>Fgpfe$KkDyLF^-#odn;1n*he!*i!*tkaQYxy~^thov(JhOx`mMV`nM9 z=NuJM32$tQtomj2r9i?L@v_VAOl|c)LJjeV&(q{D(~nKU-Smkj|Ds3P?{CB--ZGsm z(@$al1K2-B4|=xxntbu+AE(ZElkc*6s@!vy9!e#!`C%BmF5+Fbu}q&j1o4=E`t+fb zJ|N=j9W3Y3)SfauehMnZQe}DqXnQiLuvbz?5?)Vq$Qv8-bqx9ALk+(k@j5PgDg_7q z=6R{bd03!{E`rGk2yT&MJASuJJM7~W^1V+h6uM2Jf=UIQmq2qL{P+-#e-+MCC%tvPqfFmB!$0Sd%|f_JuQb|nIj$sCj?L66 z$2Qt3$1CV+Iqsxga!k^HUO5iZ5jh^AqcAv;hOppqj7&L}=s`L1Z?6Q+r{w5BD9bol z!lC(P>DK4irDkv68V7`k-lbI)+{!BjU|!02m;5`b z;0Qrp2HUXqYeLmHbp-~_#nU<{sTW9 z?)N+RL7bK8eU~+U6pc0W3eWV?c^pQ7gde%X!47iFbqc6@;T1mTc<;l~5hUK}h^A!L z9f*}h&^aDipe#ZV*eJq|Sc#M;4!Ngx;M65J^{iN47Ava?t=_}lMv)OgMpL7RB)lTw z6A8cMTboKKjI2a|fT0DDev?rpT2p`-FvR~;9l(`nFN=;w(Rs8iE`M5VD~l`T?=>%q zo>R0d;(I~#l*NwJRrU1BW1P&o&(Yf{)@sdBMk`EleWU1y+7ZQ3Zc6MrKM(maR$8vEb7kv0L6kbu+xuvJWYs|@3MsMy6)g) z0GAp);t~TL!AvgmW6j?bZ7=3Jafc zX(HUa0bIC zXdb@}`Xqf$(mXQ#c`8eqN2Xt-S0v3N(_g_a(>yZ$Lp*_*=8@_5#3D)a2wHfApJ_QV zy+kaRG>=TL7V9L=T*Bt|5E%_Gydi@PMvBhyccZ^(Pf+#n2E zR)Okh#e^c3Ib~p65$iarkpNm`lZF)z^>M1kdIev#3+@JpNXjLdFH&&=|zLTAHq2}0Wb+NLR7P%|3-%;G{PC|3<<3Za|I}N$+ zbR2>5dZ+wAd?Xq9Fu5~K?cIIP#aUJldq8@f0?!j(N=b{o7s2H^PV#~Gv9uF z`3j(fHHPD(qi5weYMmSV!fmJgPzS?c` z6$bqx;q+F6IZ&BlOn?0Rp{;YK|C`f~4>gpz)LWa>= ze?$lU5%-@LO?<$WV_JFbvb1kxi$2GC=bbM(L~3-!%GY0LjA3&lsQk zgo*c%PX?37c4C$~G3mlbOdKQm0hgCga8(8}thOzGV2qeWTo!i^4k+ z`%bB!NJFRTAW>454mUdvcaWd~Otu|HFQvo$!U=MJd3-18%%i{Mk?&o_+zD3xTLoPp za*@mZzX4E72M7foSXo;F003G9lMxymlh8H~lka{AlQ5JZe*-ZP#wYf#wTgWLC8t)p zU93Hd6xD)kEXPvKWM8U0E40B<=Qhaln3y{1DQ8{uH$Ph%!@#E)9J3{xXiMa@O_;98d47v|G&mVVK};+8+yo(@ z^^h-}qHAqPz+vu^FmV_g3LhO71-bAJ%k6}#AfVzPC zxwg8z5OC1F`3dMe+-yDj?|Ksfm2Pj+h9`;gjkB2LNB&R1sk9e zET&%YWO9-WOlHQpKv`;6eeg%L5Bk{GK83cdWgmR=-QVDE@Wr^#a7lo;G;2*}&c1y6 za=yKP|NG^y04A`(@Z{mcrObD+0@v1sS&U7_v{Eb?)2ynk8{E?^GgY;Ug5-`c1a}1~ zE8Ifje=>f*X#Q6C56|!|Q`~D^0Fi7B5cI8zp0Zp-yVwc*KdA)XDabt^4l zrbc#;zNZ`Md2UZJM4I&qREAF7-A$`KK5{>T2)a~+agw30;X7>^21TaYTm{_>AyKux zEka~C9X}c*f*zbvaT>i0y$w|(PX%Ww>{Z>=z3V~Pdl8(&fQo*cXXtOvaL%-SFXuUe zR~5W}A)_5BFmQcS#UL&)bQl&dGMsA|HTeg&7ZH8Jy;(-^z2j~jpePpOwlLXX%;(gR6iV)@`rlj3f%D}Uz1H{myw!2cY zy^b3y6nw}Kb`Ll;7Q(GV?AtY0@Db73^|<4?E4o)9p2Ux1N+#XL$0}wp%kY}(7u>xR z`r>mfbNB>zq;-~hZO~LnU}DBx1PfS{io0|!%NrPuA1}9M2bPeN*Ro8GL;{9P3&;O| z33U%Ek_ewOobpZD1bRv51w#Y_5RD(<|M7Xak1ymrd`V+_K+MIN2b!?uNGbSwUlBxI zt~l1Fgjetl!}*3{$u~W{Dw-S%`{UBo%Uix~6y@%qNf?@O9LtGrR)iUqvq9>peK3d7 z5{=Nc5K8}Yhrw)BR0!yFD{@bngqiw(kNzLZf{I^rj~JF{5h>fE_`UG93Ju>9 z*{5m$(tzbWTJhA?Wobj#k)`#!;8zR62_&>HPY{#kk7$PwJq#`##?VO`;Fm-Vr=CE0 zj=pC*=+Eb~+jxBkgZcTKN15Sqa^)|6gA{mp4NX$JjYkhvQH6868fth zX!#w8d}6hyyp6RQ%o?oGZ8)ze$zCGu_gKXMqQN_gAv~hghcFzRAK|Cq-3E`OH_;ic z(+X-=FruJep_#{DxKT$3m_my%oc>npXqWmhb!JcsxYV|hfOG`m({qwc$e2R3;Ya$W zp&@A-+W!GiO9u#Kvf8dOlMtF+f9p;YK@`W&K%u2BrCUIds>mYt0;N(4mWvl|DhY~d z1p^@=Lp$9rYi3vrX zu`5Dc&oU^cFqY9w>1Bc{yhq30tg@vc4e2Xkc3J?>A3+(QkN5csrmo zi{PbXd!IzpqXsXnY#Ukw-n*gipjzDG2*gtNI9Ttqu%V31ZX1=?H*5fFTSqf#3i7ot z3UJV+q+R-gcd-p@uIPJ#RWwQ9y zO7ab?x!PovZ(n-Xzy~(UPZu-2ZRm%y{4C@V^n4^GOws+##KRIqFlgl#5PgO?*=HX~VUXGPYG|^p4tWVft zj#GiPMQ5o6_qHo(>&kFKGQ927+q6%(GKFd}g zTQ{cO&~ea$)LDR)ZK^x04x&eowO8DOlcxu4m8sGQDi2-ydys2$UI}X#omgic^#&`tsS!|Ywo?&C!|o7@uZ8(ddXr{1eeXUHckc4ZKLrd zk{C2DLwR>Pg$Ot%{?G@+Y|;@*n#;>}qWLeO1 zV6Paiz&+^s)s0La~v zAOt%&sD#Q|bv#|hi&d(t+EG5u%{iOZ8rs8eA1y=UvRm-s64$|WSfLN`q$#hE3@e4%5jP|M$Iv24-qU zuE3|~0i&r{v`x)Jbk5B7|bIGkisJN<7f+KPrrBcxfg--!@xBuewf|aF`*I0>;j(& zVSvJ4sh+I6+1=K-y;`Fo;nh0fNB1_RI*j{p=oM)2aHv_`3~zLIES?Bch|CQjJP_&T zL-E+S^w>0WibmH&+{eqb_{MbSY;t(cV7UG$ta(Uzq)QkOfVqk^%~$I|GWUtLQ+B-` zB~E?D+~bluCV)kdngcO<_O?AdMv0z*dcY8VI_3O1vXp@2H+|N539B@|67dq3z(j$T z#99M#O7(uAjnbOpr?uajMP`dI(_|W7gStoS;Pa&n9SE-5SFR7UvyRR|PvL^%!>g0d zMpOBTUcOaS(hSnn_>nVYG$=6hY~t3J{+2)zO4zv-OpYx%sNZx-#-YH?^>x_ zd!$tH_n8c?o~F*j(SYA%S6=^6h}sL`AS)hp+z}PQ1-r#lpCtB=6<7r%W#T=A?s`AC z@HJ4dv2O2T`lHJNi+J(6jY5-pOnxBUh9v5}e#ysN&G1i|Q1I>ThihxBH(RKErw-Or zwA|fy8|r&jwZ}{c-LxbP5H9pV%bKXMvWpqE5{I3_yQDdq_&zkki<`I;_=@gg=H>|`Dwpz#Y}0uC^Np2TBu0*x!`@cI{CcMc)Hg96QmP`|PS}S5f$` z)ooqNs#DZW*t=7X&pp@25Nw@vs)|glv&Fl}p3w@aPmgROyDsp$C>;+>$ODihF~Sph z@z^94G2emUu#5fD2TRt*Vl9a|Vq6;ejpJ(CsDSHh`f3d|GsQT^m5Nz_bHrek9MrHf z`AL2{p?d6@sBwY=DXSpi@k|`{j1K)ofMFP>Pb%u#Q|GUZTvYbVCbI{GhejiJXkHhP zg=StSi@vt^x@!fla3Z3I2_g&Xqy zjR)ba%QaB$mnOb9`=t6k;!M=Txs$FvHO`S&nv?L4GRO)LA9{HxDP>|cJNdF-UOjfA zQ|7K(Qq>0_#YdSvBws((Z9A6wMG@COQuS{4#Gl0OwKPLE=RJ7AqVY;g7{+ez_`AD}>9VN!`hGFOoWSm*rCfO~; zPf|C^i`4&4F=!~G3S;aP3rm#a&VR2IwMe=O^Jw{B<<(z}4RNN|Ito#A_4f`=wPY=zhb1)7Nq5ilDbf zgOz52O~cHOgeAA)hr6Y$rl|vv-p21)CCg`w>k5J2?v_F~EhW9h0f8b9#FZ{%uVnDw zX9OgRL_t8lq@5oTxLKr&G|;}J?Ficc1a)wZG1+7H0ck}@;PF0jpx_=KwB-z4#R||V zhOrnQ_-WV!TrE~c{!_DAi>U=}p&j5tu?q5+_AUgX$pjn~+W~TkANk%L;=6w7FzA;l z6aryx^)^5&ae)5N&EzG+SUyTJD)UH5ey@o9rIPsXfWAuq1abq9$r4D08XvfC?E!mH zVsa;5cE=s6tPmr5hLjp`suaeOEw^J#Dpf=NUqfgB6joy%-zdeOK(_QU5yW>vj~H-_ zt^R}S05r;Up$t_DAgT<;LdF1?GI5}`Oaj3m-UlbH`ahH71bi*CK<==;gCXcJh42y! zY?dK_$Z{RT4qrG3I>7{*1>TlBB6g^%LAyMYT?05(VFvv{yjxfSW05lg`0v30Duo?z zHj-zI_Aee%2t=8wGTn3sENaHMgpmKF>=I)FyPy0CmP9i6p1^6j54v-d36y@C0jfKF zm@y@cuW$ftC5)xVkzw$yRDk|SXe$H@DS=?2Ffddpiuh-?6?2o_0N*_m*lFo2}kOpG_cg{q>K$x$J2N?{YLI#onWbA*y+4TfP z&*hj}JeJ7-W>A%pzgCd{9+FNX1LQ*6lTMR`{1-ocl`eV0~V3w delta 36287 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 TbTtHgKIb=}#OPPBcmMwnM9LS( diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a35649f5fc..4eac4a84cc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From e7c1bbd0d8311d2a3991019bcb039194f06ac74d Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 2 Dec 2025 11:39:46 +0100 Subject: [PATCH 1486/1594] [Java] Upgrade to `Checkstyle` 12.2.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index aa2e4500b5..722f599e87 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.3.2" -checkstyle = "12.1.2" +checkstyle = "12.2.0" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From e22b6c226fdb1dcefe942b395745f83ccb121cdd Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 2 Dec 2025 12:39:21 +0100 Subject: [PATCH 1487/1594] [C] Handle fields in the correct order and use all declared fields. --- sbe-tool/src/test/c/CodeGenTest.cpp | 61 ++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/sbe-tool/src/test/c/CodeGenTest.cpp b/sbe-tool/src/test/c/CodeGenTest.cpp index 4d33156149..4135804ad3 100644 --- a/sbe-tool/src/test/c/CodeGenTest.cpp +++ b/sbe-tool/src/test/c/CodeGenTest.cpp @@ -46,6 +46,7 @@ static const char FUEL_FIGURES_3_USAGE_DESCRIPTION[] = "Highway Cycle"; static const char MANUFACTURER[] = "Honda"; static const char MODEL[] = "Civic VTi"; static const char ACTIVATION_CODE[] = "deadbeef"; +static const char COLOR[] = "silver/white"; static const std::size_t VEHICLE_CODE_LENGTH = sizeof(VEHICLE_CODE); static const std::size_t MANUFACTURER_CODE_LENGTH = sizeof(MANUFACTURER_CODE); @@ -55,12 +56,13 @@ static const std::size_t FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH = strlen(FUEL_F static const std::size_t MANUFACTURER_LENGTH = strlen(MANUFACTURER); static const std::size_t MODEL_LENGTH = strlen(MODEL); static const std::size_t ACTIVATION_CODE_LENGTH = strlen(ACTIVATION_CODE); +static const std::size_t COLOR_LENGTH = strlen(COLOR); static const std::uint8_t PERFORMANCE_FIGURES_COUNT = 2; static const std::uint8_t FUEL_FIGURES_COUNT = 3; static const std::uint8_t ACCELERATION_COUNT = 3; static const std::uint64_t expectedHeaderSize = 8; -static const std::uint64_t expectedCarEncodedLength = 191; +static const std::uint64_t expectedCarEncodedLength = 207; static const std::uint16_t fuel1Speed = 30; static const float fuel1Mpg = 35.9f; @@ -107,13 +109,14 @@ class CodeGenTest : public testing::Test CGT(car_set_modelYear)(&car, MODEL_YEAR); CGT(car_set_available)(&car, AVAILABLE); CGT(car_set_code)(&car, CODE); - CGT(car_put_vehicleCode)(&car, VEHICLE_CODE); for (std::uint64_t i = 0; i < CGT(car_someNumbers_length)(); i++) { CGT(car_set_someNumbers_unsafe)(&car, i, static_cast(i)); } + CGT(car_put_vehicleCode)(&car, VEHICLE_CODE); + CGT(optionalExtras) extras; if (!CGT(car_extras)(&car, &extras)) { @@ -213,9 +216,10 @@ class CodeGenTest : public testing::Test CGT(car_performanceFigures_acceleration_set_mph)(&acc, perf2cMph); CGT(car_performanceFigures_acceleration_set_seconds)(&acc, perf2cSeconds); - CGT(car_put_manufacturer)(&car, MANUFACTURER, static_cast(strlen(MANUFACTURER))); - CGT(car_put_model)(&car, MODEL, static_cast(strlen(MODEL))); - CGT(car_put_activationCode)(&car, ACTIVATION_CODE, static_cast(strlen(ACTIVATION_CODE))); + CGT(car_put_manufacturer)(&car, MANUFACTURER, MANUFACTURER_LENGTH); + CGT(car_put_model)(&car, MODEL, MODEL_LENGTH); + CGT(car_put_activationCode)(&car, ACTIVATION_CODE, ACTIVATION_CODE_LENGTH); + CGT(car_put_color)(&car, COLOR, COLOR_LENGTH); return CGT(car_encoded_length)(&car); } @@ -246,6 +250,8 @@ class CodeGenTest : public testing::Test CGT(optionalExtras_cruiseControl)(&extras) << ';'; } + output << static_cast(CGT(car_discountedModel(&car))) << ';'; + char code_buf[4]; CGT(engine) engine = {}; if (CGT(car_engine)(&car, &engine)) @@ -307,6 +313,16 @@ class CodeGenTest : public testing::Test { output << std::string(model.data, model.length) << ';'; } + CGT(car_string_view) activationCode = CGT(car_get_activationCode_as_string_view(&car)); + if (nullptr != activationCode.data) + { + output << std::string(activationCode.data, activationCode.length) << ';'; + } + CGT(car_string_view) color = CGT(car_get_color_as_string_view(&car)); + if (nullptr != color.data) + { + output << std::string(color.data, color.length) << ';'; + } return output.str(); } @@ -653,6 +669,10 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeCarCorrectly) offset += sizeof(std::uint16_t); EXPECT_EQ(std::string(bp + offset, ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); offset += ACTIVATION_CODE_LENGTH; + EXPECT_EQ(*(std::uint32_t *)(bp + offset), static_cast(COLOR_LENGTH)); + offset += sizeof(std::uint32_t); + EXPECT_EQ(std::string(bp + offset, COLOR_LENGTH), COLOR); + offset += COLOR_LENGTH; EXPECT_EQ(sz, offset); } @@ -670,10 +690,10 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeHeaderPlusCarCorrectly) EXPECT_EQ(carEncodedLength, expectedCarEncodedLength); EXPECT_EQ(*((std::uint16_t *)bp), CGT(car_sbe_block_length)()); - const size_t activationCodePosition = hdrSz + carEncodedLength - ACTIVATION_CODE_LENGTH; - const size_t activationCodeLengthPosition = activationCodePosition - sizeof(std::uint16_t); - EXPECT_EQ(*(std::uint16_t *)(bp + activationCodeLengthPosition), ACTIVATION_CODE_LENGTH); - EXPECT_EQ(std::string(bp + activationCodePosition, ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); + const size_t colorPosition = hdrSz + carEncodedLength - COLOR_LENGTH; + const size_t colorLengthPosition = colorPosition - sizeof(std::uint32_t); + EXPECT_EQ(*(std::uint16_t *)(bp + colorLengthPosition), COLOR_LENGTH); + EXPECT_EQ(std::string(bp + colorPosition, COLOR_LENGTH), COLOR); } TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) @@ -845,6 +865,9 @@ TEST_F(CodeGenTest, shouldBeAbleToEncodeAndDecodeHeaderPlusCarCorrectly) EXPECT_EQ(CGT(car_activationCode_length)(&m_carDecoder), ACTIVATION_CODE_LENGTH); EXPECT_EQ(std::string(CGT(car_activationCode)(&m_carDecoder), ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); + EXPECT_EQ(CGT(car_color_length)(&m_carDecoder), COLOR_LENGTH); + EXPECT_EQ(std::string(CGT(car_color)(&m_carDecoder), COLOR_LENGTH), COLOR); + EXPECT_EQ(CGT(car_encoded_length)(&m_carDecoder), expectedCarEncodedLength); } @@ -968,9 +991,12 @@ TEST_F(CodeGenTest, shouldBeAbleUseOnStackCodecsAndGroupForEach) EXPECT_EQ(CGT(car_get_model)(&carDecoder, tmp, sizeof(tmp)), MODEL_LENGTH); EXPECT_EQ(std::string(tmp, MODEL_LENGTH), MODEL); - EXPECT_EQ(CGT(car_get_manufacturer)(&carDecoder, tmp, sizeof(tmp)), ACTIVATION_CODE_LENGTH); + EXPECT_EQ(CGT(car_get_activationCode)(&carDecoder, tmp, sizeof(tmp)), ACTIVATION_CODE_LENGTH); EXPECT_EQ(std::string(tmp, ACTIVATION_CODE_LENGTH), ACTIVATION_CODE); + EXPECT_EQ(CGT(car_get_color)(&carDecoder, tmp, sizeof(tmp)), COLOR_LENGTH); + EXPECT_EQ(std::string(tmp, COLOR_LENGTH), COLOR); + EXPECT_EQ(CGT(car_encoded_length)(&carDecoder), expectedCarEncodedLength); } @@ -997,6 +1023,7 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) std::string manufacturer(MANUFACTURER, MANUFACTURER_LENGTH); std::string model(MODEL, MODEL_LENGTH); std::string activationCode(ACTIVATION_CODE, ACTIVATION_CODE_LENGTH); + std::string color(COLOR, COLOR_LENGTH); char buffer[BUFFER_LEN] = {}; auto baseOffset = static_cast(CGT(messageHeader_encoded_length)()); @@ -1046,6 +1073,8 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode) CGT(car_put_model)(&car, model_c, static_cast(strlen(model_c))); const char *acti = activationCode.c_str(); CGT(car_put_activationCode)(&car, acti, static_cast(strlen(acti))); + const char *col = color.c_str(); + CGT(car_put_color)(&car, col, static_cast(strlen(col))); EXPECT_EQ(CGT(car_encoded_length)(&car), expectedCarEncodedLength); @@ -1179,6 +1208,18 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode) std::string(ptr, length), std::string(ACTIVATION_CODE, ACTIVATION_CODE_LENGTH)); } + { + const uint16_t length = CGT(car_color_length)(&carDecoder); + const char *const ptr = CGT(car_color)(&carDecoder); + if (!ptr) + { + throw std::runtime_error(sbe_strerror(errno)); + } + + EXPECT_EQ( + std::string(ptr, length), + std::string(COLOR, COLOR_LENGTH)); + } EXPECT_EQ(CGT(car_encoded_length)(&carDecoder), expectedCarEncodedLength); } From 2471de05c130d3d41de8077e6afe1dfb90cfe316 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 8 Dec 2025 13:30:23 +0100 Subject: [PATCH 1488/1594] [Java] Upgrade to `Shadow` 9.3.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 722f599e87..e5a20fe97c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20250517" junit = "6.0.1" mockito = "5.20.0" plexus = "3.3.0" -shadow = "9.2.2" +shadow = "9.3.0" versions = "0.53.0" [libraries] From b5a6cb29cc66e799bfe995f31e764317e58279cb Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Fri, 12 Dec 2025 14:12:40 +0100 Subject: [PATCH 1489/1594] [Java] Upgrade to `Mockito` 5.21.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e5a20fe97c..84779da7fc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ jqwik = "1.9.3" jmh = "1.37" json = "20250517" junit = "6.0.1" -mockito = "5.20.0" +mockito = "5.21.0" plexus = "3.3.0" shadow = "9.3.0" versions = "0.53.0" From 4c27d42071661a0ac85f6f6618cd9a86d2a32c16 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 22 Dec 2025 21:57:12 +0100 Subject: [PATCH 1490/1594] [CI] Upgrade to `CodeQL` v4. --- .github/workflows/codeql.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b5c633b1f1..b7e916b4fc 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -59,7 +59,7 @@ jobs: uses: gradle/actions/setup-gradle@v5 - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml @@ -68,7 +68,7 @@ jobs: run: ./gradlew - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 with: category: "/language:${{matrix.language}}" @@ -122,7 +122,7 @@ jobs: dotnet-version: ${{ matrix.dotnet }} - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml @@ -131,7 +131,7 @@ jobs: run: ./csharp/build.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 with: category: "/language:${{matrix.language}}" @@ -176,7 +176,7 @@ jobs: sudo apt-get install -y g++-${{ matrix.version }} - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml @@ -185,7 +185,7 @@ jobs: run: ./cppbuild/cppbuild - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 with: category: "/language:${{ matrix.language }}" upload: false @@ -200,6 +200,6 @@ jobs: output: sarif-results/${{ matrix.language }}.sarif - name: Upload SARIF - uses: github/codeql-action/upload-sarif@v3 + uses: github/codeql-action/upload-sarif@v4 with: sarif_file: sarif-results/${{ matrix.language }}.sarif From 149f9d06f19a2c40a28a29a6d47b6afecbe1fec0 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Dec 2025 14:47:38 +0100 Subject: [PATCH 1491/1594] [Java] Upgrade to `Checkstyle` 12.3.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 84779da7fc..bd97d1d2ef 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] agrona = "2.3.2" -checkstyle = "12.2.0" +checkstyle = "12.3.0" commons-codec = "1.15" commons-lang3 = "3.8.1" hamcrest = "3.0" From 08636256cafab42ef9e79f51c1baee99fb7d4178 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Dec 2025 14:48:03 +0100 Subject: [PATCH 1492/1594] [Java] Upgrade to `json` 20251224. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bd97d1d2ef..e657b94a0e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ hamcrest = "3.0" httpcore = "4.4.14" jqwik = "1.9.3" jmh = "1.37" -json = "20250517" +json = "20251224" junit = "6.0.1" mockito = "5.21.0" plexus = "3.3.0" From b702404b331236c8a3fe132a899663798db3857d Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Dec 2025 14:48:19 +0100 Subject: [PATCH 1493/1594] [Java] Upgrade to `Agrona` 2.4.0. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e657b94a0e..d85c88eafd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agrona = "2.3.2" +agrona = "2.4.0" checkstyle = "12.3.0" commons-codec = "1.15" commons-lang3 = "3.8.1" From 408dbc532231b1cd16c58925e7b8cd95bb8ddcdd Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Dec 2025 15:04:55 +0100 Subject: [PATCH 1494/1594] [C] Download and install `CMake` during build. --- .gitignore | 1 + cppbuild/cppbuild | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 554fcc27e0..02c31be8a8 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,7 @@ cppbuild/*.cache cppbuild/Debug cppbuild/Release cppbuild/Win32 +cppbuild/cmake # golang gocode/pkg diff --git a/cppbuild/cppbuild b/cppbuild/cppbuild index 28f48c15aa..26a8d8a345 100755 --- a/cppbuild/cppbuild +++ b/cppbuild/cppbuild @@ -4,16 +4,44 @@ SOURCE_DIR="$(pwd)" BUILD_DIR="${SOURCE_DIR}/cppbuild/Release" EXTRA_CMAKE_ARGS="" +BUILD_DELETE_CMAKE=false +BUILD_CMAKE_VERSION=4.2.1 +BUILD_CMAKE_DIR="${SOURCE_DIR}/cppbuild/cmake" + ncpus=1 case "$(uname)" in Darwin* ) ncpus=$(sysctl -n hw.ncpu) + BUILD_CMAKE_OS="macos-universal" + BUILD_CMAKE_PATH="${BUILD_CMAKE_DIR}/CMake.app/Contents/bin" ;; Linux*) ncpus=$(lscpu -p | grep -c -E -v '^#') + BUILD_CMAKE_OS="linux-$(arch)" + BUILD_CMAKE_PATH="${BUILD_CMAKE_DIR}/bin" ;; esac +function install_cmake() +{ + if [[ true = "${BUILD_DELETE_CMAKE}" ]] + then + echo "Removing old CMake installation" + rm -rf "${BUILD_CMAKE_DIR}" + fi + + local version_file="${BUILD_CMAKE_DIR}/version.txt" + local version_info="${BUILD_CMAKE_VERSION}-${BUILD_CMAKE_OS}" + if [[ "${version_info}" != "$(cat "${version_file}")" ]] + then + echo "Installing CMake ${version_info}" + rm -rf "${BUILD_CMAKE_DIR}" + mkdir -p "${BUILD_CMAKE_DIR}" + (curl -LJ "https://github.com/Kitware/CMake/releases/download/v${BUILD_CMAKE_VERSION}/cmake-${BUILD_CMAKE_VERSION}-${BUILD_CMAKE_OS}.tar.gz" | tar xzf - -C "${BUILD_CMAKE_DIR}" --strip-components 1 + echo "${version_info}" > "${version_file}") + fi +} + while [[ $# -gt 0 ]] do option="${1}" @@ -39,6 +67,16 @@ do echo "Enabling sanitise build" shift ;; + --rebuild-cmake) + BUILD_DELETE_CMAKE=true + shift + ;; + --cmake-version) + BUILD_CMAKE_VERSION=${2} + echo "Setting BUILD_CMAKE_VERSION=${2}" + shift + shift + ;; -h|--help) echo "${0} [--c-warnings-as-errors] [--cxx-warnings-as-errors] [--debug-build] [--sanitise-build]" exit @@ -59,6 +97,9 @@ if [ -d "${BUILD_DIR}" ] ; then fi mkdir -p "${BUILD_DIR}" + +install_cmake + cd "${BUILD_DIR}" || exit -(cmake -G "Unix Makefiles" ${EXTRA_CMAKE_ARGS} "${SOURCE_DIR}" && make clean && make -j ${ncpus} all && ctest -C Release --output-on-failure) +("${BUILD_CMAKE_PATH}/cmake" -G "Unix Makefiles" ${EXTRA_CMAKE_ARGS} "${SOURCE_DIR}" && make clean && make -j ${ncpus} all && "${BUILD_CMAKE_PATH}/ctest" -C Release --output-on-failure) From 17d700dcd327168533b3ddd892785509aebe2cce Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Dec 2025 15:28:49 +0100 Subject: [PATCH 1495/1594] [C/C++] Add complete list of keywords + add `assert` as keyword so it is escaped correctly. --- .../uk/co/real_logic/sbe/ValidationUtil.java | 191 +++++++++++++++--- 1 file changed, 161 insertions(+), 30 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java index 7ba93c7bd0..e6881b1276 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/ValidationUtil.java @@ -26,15 +26,67 @@ public class ValidationUtil private static final Pattern PATTERN = Pattern.compile("\\."); private static final Set C_KEYWORDS = Set.of( - "auto", "_Alignas", "_Alignof", "_Atomic", "bool", - "_Bool", "break", "case", "_Complex", - "char", "const", "continue", "default", - "do", "double", "else", "enum", "extern", "false", - "float", "for", "_Generic", "goto", "if", "_Imaginary", "inline", - "int", "long", "_Noreturn", "register", "restrict", "return", "short", - "signed", "sizeof", "static", "_Static_assert", - "struct", "switch", "_Thread_local", "true", "typedef", "union", - "unsigned", "void", "volatile", "wchar_t", "while"); + "alignas", + "alignof", + "assert", + "auto", + "bool", + "break", + "case", + "char", + "const", + "constexpr", + "continue", + "default", + "do", + "double", + "else", + "enum", + "extern", + "false", + "float", + "for", + "goto", + "if", + "inline", + "int", + "long", + "nullptr", + "register", + "restrict", + "return", + "short", + "signed", + "sizeof", + "static", + "static_assert", + "struct", + "switch", + "thread_local", + "true", + "typedef", + "typeof", + "typeof_unqual", + "union", + "unsigned", + "void", + "volatile", + "while", + "_Alignas", + "_Alignof", + "_Atomic", + "_BitInt", + "_Bool", + "_Complex", + "_Decimal128", + "_Decimal32", + "_Decimal64", + "_Generic", + "_Imaginary", + "_Noreturn", + "_Static_assert", + "_Thread_local" + ); /** * Check value for validity of usage as a C identifier. A programmatic variable @@ -113,26 +165,105 @@ private static boolean isSbeCIdentifierPart(final char c) } private static final Set CPP_KEYWORDS = Set.of( - "alignas", "and", "and_eq", "asm", "auto", - "bitand", "bitor", "bool", "break", "case", - "catch", "char", "class", "compl", "const", - "const_cast", "continue", "char16_t", "char32_t", "default", - "delete", "do", "double", "dynamic_cast", "else", - "enum", "explicit", "export", "extern", "false", - "float", "for", "friend", "goto", "if", - "inline", "int", "long", "mutable", "namespace", - "new", "not", "not_eq", "noexcept", "operator", - "or", "or_eq", "private", "protected", "public", - "register", "reinterpret_cast", "return", "short", "signed", - "sizeof", "static", "static_cast", "struct", "switch", - "template", "this", "throw", "true", "try", - "typedef", "typeid", "typename", "union", "unsigned", - "using", "virtual", "void", "volatile", "wchar_t", - "while", "xor", "xor_eq", "override", - // since C++11 - "alignof", "constexpr", "decltype", "nullptr", "static_assert", "thread_local", - // since C++11 have special meaning, so avoid - "final"); + "alignas", + "alignof", + "and", + "and_eq", + "assert", + "asm", + "atomic_cancel", + "atomic_commit", + "atomic_noexcept", + "auto", + "bitand", + "bitor", + "bool", + "break", + "case", + "catch", + "char", + "char8_t", + "char16_t", + "char32_t", + "class", + "compl", + "concept", + "const", + "consteval", + "constexpr", + "constinit", + "const_cast", + "continue", + "contract_assert", + "co_await", + "co_return", + "co_yield", + "decltype", + "default", + "delete", + "do", + "double", + "dynamic_cast", + "else", + "enum", + "explicit", + "export", + "extern", + "false", + "float", + "for", + "friend", + "goto", + "if", + "inline", + "int", + "long", + "mutable", + "namespace", + "new", + "noexcept", + "not", + "not_eq", + "nullptr", + "operator", + "or", + "or_eq", + "private", + "protected", + "public", + "reflexpr", + "register", + "reinterpret_cast", + "requires", + "return", + "short", + "signed", + "sizeof", + "static", + "static_assert", + "static_cast", + "struct", + "switch", + "synchronized", + "template", + "this", + "thread_local", + "throw", + "true", + "try", + "typedef", + "typeid", + "typename", + "union", + "unsigned", + "using", + "virtual", + "void", + "volatile", + "wchar_t", + "while", + "xor", + "xor_eq"); /** * Check value for validity of usage as a C++ identifier. A programmatic variable @@ -393,7 +524,7 @@ private static boolean isSbeGolangIdentifierPart(final char c) /** * C# keywords. * - * C# keywords + * C# keywords * Note this does not include the contextual keywords * Note "virtual" is no longer but was in early versions of C# */ From fefb1f0e1b80954eb1dd4ecf257e09ecde5b5340 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Dec 2025 16:01:40 +0100 Subject: [PATCH 1496/1594] [C++] Add test for handling keywords. --- sbe-tool/src/test/cpp/CodeGenTest.cpp | 30 ++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/test/cpp/CodeGenTest.cpp b/sbe-tool/src/test/cpp/CodeGenTest.cpp index 25c645248f..991e1f96f3 100644 --- a/sbe-tool/src/test/cpp/CodeGenTest.cpp +++ b/sbe-tool/src/test/cpp/CodeGenTest.cpp @@ -19,6 +19,7 @@ #include "gtest/gtest.h" #include "code_generation_test/MessageHeader.h" #include "code_generation_test/Car.h" +#include "code_generation_test/GlobalKeywords.h" using namespace code::generation::test; @@ -1144,4 +1145,31 @@ TEST_F(CodeGenTest, shouldBeAbleToResolveStringLiterals) car.sbeRewind(); EXPECT_EQ(car.getVehicleCodeAsStringView(), "ABCDE"); } -#endif \ No newline at end of file +#endif + +TEST_F(CodeGenTest, shouldComputeEncodedLengthCorrectlyForVarDataFields) +{ + char buffer[BUFFER_LEN] = {}; + + std::uint64_t baseOffset = MessageHeader::encodedLength(); + GlobalKeywords keywords; + keywords.wrapForEncode(buffer, baseOffset, sizeof(buffer)); + keywords.type(7); + keywords.assertX(16); + + GlobalKeywords::Data &data = keywords.dataCount(1); + + data.next() + .thisX(3); + + GlobalKeywords::Data::Super &super = data.superCount(2); + + super.next() + .mph(100); + + super.next() + .mph(200) + .putImport(std::string("this super long string value right here")); + + EXPECT_EQ(337, keywords.encodedLength()); +} From 7bfa96a2d84b9aab3420a94f4b4a1819a4827982 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Dec 2025 22:44:10 +0100 Subject: [PATCH 1497/1594] [C] Implement `--sanitise-build` support. --- CMakeLists.txt | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ce164c285b..b3ab7a0ef2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,10 +75,13 @@ endif () find_package(Threads) +# all UNIX-based platform compiler flags if (UNIX) - add_compile_options(-Wall -Wpedantic -Wextra -Wno-unused-parameter) + add_compile_options(-fstrict-aliasing -Wall -Wpedantic -Wextra -Wno-unused-parameter -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer) - if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "21.0") + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "11.0") + add_compile_options(-Wno-error=maybe-uninitialized) + elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "21.0") # See gtest: https://github.com/google/googletest/issues/4762 add_compile_options(-Wno-error=character-conversion) endif () @@ -90,13 +93,28 @@ if (UNIX) if (CXX_WARNINGS_AS_ERRORS) add_compile_options($<$:-Werror>) endif (CXX_WARNINGS_AS_ERRORS) + + if (SANITISE_BUILD) + if (NOT DEFINED APPLE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fsanitize=leak -fsanitize=undefined") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fsanitize=leak -fsanitize=undefined") + endif () + endif (SANITISE_BUILD) endif () +# platform specific flags if (APPLE) - # -Wall doesn't enable everything we want to see add_compile_options(-Wsign-compare) add_definitions(-DDarwin) add_compile_options(-Wno-deprecated-register) + + if (SANITISE_BUILD) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fsanitize=undefined") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fsanitize=undefined") + endif (SANITISE_BUILD) +elseif (CYGWIN) + add_definitions(-DWIN32) + set(CMAKE_CXX_EXTENSIONS ON) elseif (MSVC) add_definitions(-DWIN32) add_definitions(-D_CRT_SECURE_NO_WARNINGS) @@ -108,10 +126,15 @@ elseif (MSVC) add_definitions(-D_ENABLE_EXTENDED_ALIGNED_STORAGE) endif () - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd /Od /Zi /MP") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT /MP") - set(CMAKE_C_FLAGS_DEBUG "/MTd") - set(CMAKE_C_FLAGS_RELEASE "/MT") + add_compile_options(/Oy-) + add_compile_options($<$,$>:/MD>) + add_compile_options($<$,$>:/MDd>) + add_compile_options($<$:/MP>) + add_compile_options($<$:/wd4251>) + add_compile_options($<$,$>:/MD>) + add_compile_options($<$,$>:/MDd>) + add_compile_options($<$,$>:/Od>) + add_compile_options($<$,$>:/Zi>) if (C_WARNINGS_AS_ERRORS) add_compile_options($<$:/WX>) @@ -120,8 +143,12 @@ elseif (MSVC) if (CXX_WARNINGS_AS_ERRORS) add_compile_options($<$:/WX>) endif (CXX_WARNINGS_AS_ERRORS) -else () - add_definitions(-D_GNU_SOURCE) + + if (SANITISE_BUILD) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /Zi") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /Zi") + endif (SANITISE_BUILD) + endif () set(LIBPREFIX "${CMAKE_STATIC_LIBRARY_PREFIX}") From 4d5c43355adc523b0cb006edb64bef3ec23879f1 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Dec 2025 22:51:38 +0100 Subject: [PATCH 1498/1594] [C++] Add a test with an additional `varData` encoding with `char` as a primitive type. --- sbe-tool/src/test/cpp/DtoTest.cpp | 4 +++- sbe-tool/src/test/resources/dto-test-schema.xml | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/sbe-tool/src/test/cpp/DtoTest.cpp b/sbe-tool/src/test/cpp/DtoTest.cpp index f5d2d0cd58..c7eb7ce88c 100644 --- a/sbe-tool/src/test/cpp/DtoTest.cpp +++ b/sbe-tool/src/test/cpp/DtoTest.cpp @@ -48,6 +48,7 @@ static const char *MANUFACTURER = "Honda"; static const char *MODEL = "Civic VTi"; static const char *ACTIVATION_CODE = "deadbeef"; static const char *ADDED5 = "feedface"; +static const char *VARCHARDATA = "this is variable length data with `char` data type"; static const std::uint8_t PERFORMANCE_FIGURES_COUNT = 2; static const std::uint8_t FUEL_FIGURES_COUNT = 3; @@ -161,7 +162,8 @@ class DtoTest : public testing::Test car.putManufacturer(MANUFACTURER, static_cast(strlen(MANUFACTURER))) .putModel(MODEL, static_cast(strlen(MODEL))) .putActivationCode(ACTIVATION_CODE, static_cast(strlen(ACTIVATION_CODE))) - .putAdded5(ADDED5, static_cast(strlen(ADDED5))); + .putAdded5(ADDED5, static_cast(strlen(ADDED5))) + .putVarCharData(VARCHARDATA, static_cast(strlen(VARCHARDATA))); return car.encodedLength(); } diff --git a/sbe-tool/src/test/resources/dto-test-schema.xml b/sbe-tool/src/test/resources/dto-test-schema.xml index dd7bae3f8b..7cd26c57aa 100644 --- a/sbe-tool/src/test/resources/dto-test-schema.xml +++ b/sbe-tool/src/test/resources/dto-test-schema.xml @@ -28,6 +28,10 @@ + + + + @@ -122,6 +126,7 @@ + From ea3de439c7ad75030d18b913ecbd2e148c9c40ab Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Dec 2025 23:20:39 +0100 Subject: [PATCH 1499/1594] [Doc] Add release notes. --- CHANGELOG.adoc | 366 +++++++++++++++++++++++++------------------------ 1 file changed, 189 insertions(+), 177 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index d798f2bd60..79db065ce0 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,65 +1,77 @@ = Changelog +== 1.37.0 (2025-12-25) + +* **[C]** Implement `--sanitise-build` support. +* **[C/C{plus}{plus}]** Add complete list of keywords + add `assert` as keyword so it is escaped correctly. +* **[C]** Download and install `CMake` during the build. +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.4.0[Agrona 2.4.0]. +* **[Java]** Upgrade to `Checkstyle` 12.3.0. +* **[Java]** Upgrade to `json` 20251224. +* **[Java]** Upgrade to `Mockito` 5.21.0. +* **[Java]** Upgrade to `Shadow` 9.3.0. +* **[Java]** Upgrade to `Gradle` 9.2.1. + == 1.36.2 (2025-11-08) -* *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.3.2[Agrona 2.3.2]. +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.3.2[Agrona 2.3.2]. == 1.36.1 (2025-11-03) -* *[C#]* Handle case when `valueRef` is with enum type prefix. (https://github.com/aeron-io/simple-binary-encoding/pull/1092[#1092]) -* *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.3.1[Agrona 2.3.1]. -* *[Java]* Upgrade to `JUnit` 6.0.1. -* *[Java]* Upgrade to `Checkstyle` 12.1.1. +* **[C#]** Handle case when `valueRef` is with enum type prefix. (https://github.com/aeron-io/simple-binary-encoding/pull/1092[#1092]) +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.3.1[Agrona 2.3.1]. +* **[Java]** Upgrade to `JUnit` 6.0.1. +* **[Java]** Upgrade to `Checkstyle` 12.1.1. == 1.36.0 (2025-09-29) -* *[C{plus}{plus}]* Fix composite encode generation to use formatted property names, i.e. escape keywords. -* *[C{plus}{plus}]* Fix property name usage in display code generator. -* *[C{plus}{plus}]* Add getter for schema id on the `IrDecoder` (https://github.com/aeron-io/simple-binary-encoding/pull/1077[#1077]) -* *[Java]* Fix var data and composite code generation to use property name instead of plain name. Also use property name for access order check methods. (https://github.com/aeron-io/simple-binary-encoding/issues/1081[#1081]) -* *[Java]* Handle `null` values when encoding enums, i.e. use `Enum.NULL_VAL` if the value was not assigned. -* *[Java]* Handle primitive arrays correctly in the generated DTO code. -* *[Go]* Handle `_` and `String` as keywords and use property name when generating variable data section. -* *[C#]* Replaced empty array creation by `Array.Empty`, issue (https://github.com/aeron-io/simple-binary-encoding/issues/1079[#1079]). (https://github.com/aeron-io/simple-binary-encoding/pull/1080[#1080]) -* *[C/C{plus}{plus}]* Allow overriding Gradle wrapper location. (https://github.com/aeron-io/simple-binary-encoding/issues/1091[#1091]). -* *[Java/C{plus}{plus}/Go]* Preserve `packageName` in the IR. (https://github.com/aeron-io/simple-binary-encoding/issues/1089[#1089]) -* *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.3.0[Agrona 2.3.0]. -* *[Java]* Upgrade to `JUnit` 5.13.4. -* *[Java]* Upgrade to `Mockito` 5.20.0. -* *[Java]* Upgrade to `Checkstyle` 11.1.0. -* *[Java]* Upgrade to `Shadow` 9.2.2. -* *[Java]* Upgrade to `Version` 0.53.0. -* *[C]* Upgrade to `GoogleTest` to 1.14.0. -* *[C]* Bump minimium required CMake version to `3.30`. -* *[CI]* Add `Clang` 21 to the build matrix. -* *[CI]* Add `Java` 25 to the build matrix. +* **[C{plus}{plus}]** Fix composite encode generation to use formatted property names, i.e. escape keywords. +* **[C{plus}{plus}]** Fix property name usage in display code generator. +* **[C{plus}{plus}]** Add getter for schema id on the `IrDecoder` (https://github.com/aeron-io/simple-binary-encoding/pull/1077[#1077]) +* **[Java]** Fix var data and composite code generation to use property name instead of plain name. Also use property name for access order check methods. (https://github.com/aeron-io/simple-binary-encoding/issues/1081[#1081]) +* **[Java]** Handle `null` values when encoding enums, i.e. use `Enum.NULL_VAL` if the value was not assigned. +* **[Java]** Handle primitive arrays correctly in the generated DTO code. +* **[Go]** Handle `_` and `String` as keywords and use property name when generating variable data section. +* **[C#]** Replaced empty array creation by `Array.Empty`, issue (https://github.com/aeron-io/simple-binary-encoding/issues/1079[#1079]). (https://github.com/aeron-io/simple-binary-encoding/pull/1080[#1080]) +* **[C/C{plus}{plus}]** Allow overriding Gradle wrapper location. (https://github.com/aeron-io/simple-binary-encoding/issues/1091[#1091]). +* **[Java/C{plus}{plus}/Go]** Preserve `packageName` in the IR. (https://github.com/aeron-io/simple-binary-encoding/issues/1089[#1089]) +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.3.0[Agrona 2.3.0]. +* **[Java]** Upgrade to `JUnit` 5.13.4. +* **[Java]** Upgrade to `Mockito` 5.20.0. +* **[Java]** Upgrade to `Checkstyle` 11.1.0. +* **[Java]** Upgrade to `Shadow` 9.2.2. +* **[Java]** Upgrade to `Version` 0.53.0. +* **[C]** Upgrade to `GoogleTest` to 1.14.0. +* **[C]** Bump minimium required CMake version to `3.30`. +* **[CI]** Add `Clang` 21 to the build matrix. +* **[CI]** Add `Java` 25 to the build matrix. == 1.35.6 (2025-06-27) -* *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.4[Agrona 2.2.4]. -* *[Java]* Upgrade to `JUnit` 5.13.2. -* *[Java]* Upgrade to `Checkstyle` 10.26.0. -* *[Java]* Upgrade to `Shadow` 8.3.7. +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.4[Agrona 2.2.4]. +* **[Java]** Upgrade to `JUnit` 5.13.2. +* **[Java]** Upgrade to `Checkstyle` 10.26.0. +* **[Java]** Upgrade to `Shadow` 8.3.7. == 1.35.5 (2025-06-20) -* *[Java/C{plus}{plus}/C#]* Fix a bug in overzealous DTO validation. (https://github.com/aeron-io/simple-binary-encoding/pull/1073[#1073]) -* *[Java]* Improve JsonPrinter's conformance with the JSON specification (e.g., escaping control characters and using correct delimiters). -* *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.3[Agrona 2.2.3]. +* **[Java/C{plus}{plus}/C#]** Fix a bug in overzealous DTO validation. (https://github.com/aeron-io/simple-binary-encoding/pull/1073[#1073]) +* **[Java]** Improve JsonPrinter's conformance with the JSON specification (e.g., escaping control characters and using correct delimiters). +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.3[Agrona 2.2.3]. == 1.35.4 (2025-06-12) -* *[Rust]* Return None for optional primite field if its version is less than actingVersion. (https://github.com/aeron-io/simple-binary-encoding/pull/1067[#1067]) -* *[Java]* Adjust Java Dto generateComputeEncodedLength to account for character encoding. (https://github.com/aeron-io/simple-binary-encoding/pull/1072[#1072]) -* *[Java]* Upgrade to `JUnit` 5.13.1. -* *[Java]* Upgrade to `jqwik` 1.9.3. +* **[Rust]** Return None for optional primite field if its version is less than actingVersion. (https://github.com/aeron-io/simple-binary-encoding/pull/1067[#1067]) +* **[Java]** Adjust Java Dto generateComputeEncodedLength to account for character encoding. (https://github.com/aeron-io/simple-binary-encoding/pull/1072[#1072]) +* **[Java]** Upgrade to `JUnit` 5.13.1. +* **[Java]** Upgrade to `jqwik` 1.9.3. == 1.35.3 (2025-06-06) -* *[Java]* Publish release artifacts to Central Portal using OSSRH Staging API service. -* *[Java]* Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.2[Agrona 2.2.2]. -* *[Java]* Upgrade to `Checkstyle` 10.25.0. -* *[Java]* Upgrade to `Gradle` 8.14.2. +* **[Java]** Publish release artifacts to Central Portal using OSSRH Staging API service. +* **[Java]** Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.2[Agrona 2.2.2]. +* **[Java]** Upgrade to `Checkstyle` 10.25.0. +* **[Java]** Upgrade to `Gradle` 8.14.2. == 1.35.1 (2025-06-02) @@ -68,18 +80,18 @@ == 1.35.0 (2025-05-26) -* *[Java]* include field 'deprecated' in ir encoding and decoding. -* *[Java]* Adjust Java DTO Choice Set Access. (https://github.com/aeron-io/simple-binary-encoding/issues/1064[#1064]) -* *[Rust]* get proper version for composite types. (https://github.com/aeron-io/simple-binary-encoding/pull/1058[#1058]) -* *[C#]* Read NuGet package version from version file (https://github.com/aeron-io/simple-binary-encoding/pull/1061[#1061]) -* *[C#]* Enable dual build for netstandard2.0 & netstandard2.1. (https://github.com/aeron-io/simple-binary-encoding/pull/1062[#1062]) +* **[Java]** include field 'deprecated' in ir encoding and decoding. +* **[Java]** Adjust Java DTO Choice Set Access. (https://github.com/aeron-io/simple-binary-encoding/issues/1064[#1064]) +* **[Rust]** get proper version for composite types. (https://github.com/aeron-io/simple-binary-encoding/pull/1058[#1058]) +* **[C#]** Read NuGet package version from version file (https://github.com/aeron-io/simple-binary-encoding/pull/1061[#1061]) +* **[C#]** Enable dual build for netstandard2.0 & netstandard2.1. (https://github.com/aeron-io/simple-binary-encoding/pull/1062[#1062]) * Update `Implementation-Vendor`. -* *[Rust]* Elide explicit ActingVersion lifetime. (https://github.com/aeron-io/simple-binary-encoding/pull/1053[#1053]) -* *[CI]* Use `gradle/actions/setup-gradle` action for caching Gradle dependencies. -* *[CI]* Enable JDK 24 GA build. -* *[CI]* Simplify error log upload. -* *[CI]* Remove Ubuntu 20.04 based builds. -* *[CI]* Bump Go build to use 1.23.x and 1.24.x. +* **[Rust]** Elide explicit ActingVersion lifetime. (https://github.com/aeron-io/simple-binary-encoding/pull/1053[#1053]) +* **[CI]** Use `gradle/actions/setup-gradle` action for caching Gradle dependencies. +* **[CI]** Enable JDK 24 GA build. +* **[CI]** Simplify error log upload. +* **[CI]** Remove Ubuntu 20.04 based builds. +* **[CI]** Bump Go build to use 1.23.x and 1.24.x. * Upgrade to https://github.com/aeron-io/agrona/releases/tag/2.2.0[Agrona 2.2.0]. * Upgrade to `Gradle` 8.14.1. * Upgrade to `Checkstyle` 10.24.0. @@ -92,19 +104,19 @@ == 1.34.1 (2025-01-13) * *Doc:* Add `--add-opens java.base/jdk.internal.misc=ALL-UNNAMED` to the example execution. -* *[Rust]* encoding primitive arrays now supports slice instead of array (issue https://github.com/aeron-io/simple-binary-encoding/issues/[#1021]). (https://github.com/aeron-io/simple-binary-encoding/pull/1040[#1040]) -* *[C{plus}{plus}]* check for not wrapped state in `decodeLength()` when precedence checks are enabled. (https://github.com/aeron-io/simple-binary-encoding/pull/1046[#1046]) -* *[C{plus}{plus}]* use `m_actingBlockLength` in `decodeLength()`. (https://github.com/aeron-io/simple-binary-encoding/pull/1045[#1045]) +* **[Rust]** encoding primitive arrays now supports slice instead of array (issue https://github.com/aeron-io/simple-binary-encoding/issues/[#1021]). (https://github.com/aeron-io/simple-binary-encoding/pull/1040[#1040]) +* **[C{plus}{plus}]** check for not wrapped state in `decodeLength()` when precedence checks are enabled. (https://github.com/aeron-io/simple-binary-encoding/pull/1046[#1046]) +* **[C{plus}{plus}]** use `m_actingBlockLength` in `decodeLength()`. (https://github.com/aeron-io/simple-binary-encoding/pull/1045[#1045]) * Bump `json` to 20250107. * Upgrade to `Mockito` 5.15.2. == 1.34.0 (2024-12-17) -* *[C{plus}{plus}]* hide the m_codecStatePtr behind ifdefs to avoid overhead when precedence checking is disabled. (https://github.com/aeron-io/simple-binary-encoding/pull/1036[#1036]) -* *[C{plus}{plus}]* use constexpr to define precedence checks lookup tables. -* *[Rust]* Enhance enum supporting fromstr and display and into. (https://github.com/aeron-io/simple-binary-encoding/pull/1020[#1020]) -* *[Rust]* codegen of primitive enums now implement 'From' instead of 'Into'. (https://github.com/aeron-io/simple-binary-encoding/pull/1029[#1029]) -* *[Java]* Update Checkstyle rules and apply them. +* **[C{plus}{plus}]** hide the m_codecStatePtr behind ifdefs to avoid overhead when precedence checking is disabled. (https://github.com/aeron-io/simple-binary-encoding/pull/1036[#1036]) +* **[C{plus}{plus}]** use constexpr to define precedence checks lookup tables. +* **[Rust]** Enhance enum supporting fromstr and display and into. (https://github.com/aeron-io/simple-binary-encoding/pull/1020[#1020]) +* **[Rust]** codegen of primitive enums now implement 'From' instead of 'Into'. (https://github.com/aeron-io/simple-binary-encoding/pull/1029[#1029]) +* **[Java]** Update Checkstyle rules and apply them. * *Breaking:* Upgrade to `Agrona` 2.0.0. + _**Note:** `--add-opens java.base/jdk.internal.misc=ALL-UNNAMED` JVM option must be specified in order to generate codecs or use the generated Java classes. For example:_ @@ -114,15 +126,15 @@ _**Note:** `--add-opens java.base/jdk.internal.misc=ALL-UNNAMED` JVM option must $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=true -Dsbe.target.language=Cpp -Dsbe.target.namespace=sbe -Dsbe.output.dir=include/gen -Dsbe.errorLog=yes -jar sbe-all/build/libs/sbe-all-${SBE_TOOL_VERSION}.jar my-sbe-messages.xml ---- -* *[C{plus}{plus}]* Fix field precedence check issue https://github.com/aeron-io/simple-binary-encoding/issues/1031[#1031]. (https://github.com/aeron-io/simple-binary-encoding/pull/1033[#1033]) -* *[C{plus}{plus}]* respect the package override option for C{plus}{plus} codecs and DTOs. (https://github.com/aeron-io/simple-binary-encoding/pull/1024[#1024]) -* *[C#]* respect the package override option for C# codecs and DTOs. (https://github.com/aeron-io/simple-binary-encoding/pull/1024[#1024]) -* *[Go]* Fix warning about used args in GolangFlyweightGenerator. -* *[Rust]* Updated code generator to resolve Issue https://github.com/aeron-io/simple-binary-encoding/issues/1028[#1028]. (https://github.com/aeron-io/simple-binary-encoding/pull/1037[#1037]) -* *[Java]* Prevent collision when field name is 'value'. -* *[Java]* Preserve byte order throughout IR transformations. -* *[C{plus}{plus}]* Integrate std::span support for flyweight API. (https://github.com/aeron-io/simple-binary-encoding/pull/1038[#1038], https://github.com/aeron-io/simple-binary-encoding/pull/1027[#1027]) -* *[Rust]* generate message schema level info in lib.rs. (https://github.com/aeron-io/simple-binary-encoding/pull/1019[#1019]) +* **[C{plus}{plus}]** Fix field precedence check issue https://github.com/aeron-io/simple-binary-encoding/issues/1031[#1031]. (https://github.com/aeron-io/simple-binary-encoding/pull/1033[#1033]) +* **[C{plus}{plus}]** respect the package override option for C{plus}{plus} codecs and DTOs. (https://github.com/aeron-io/simple-binary-encoding/pull/1024[#1024]) +* **[C#]** respect the package override option for C# codecs and DTOs. (https://github.com/aeron-io/simple-binary-encoding/pull/1024[#1024]) +* **[Go]** Fix warning about used args in GolangFlyweightGenerator. +* **[Rust]** Updated code generator to resolve Issue https://github.com/aeron-io/simple-binary-encoding/issues/1028[#1028]. (https://github.com/aeron-io/simple-binary-encoding/pull/1037[#1037]) +* **[Java]** Prevent collision when field name is 'value'. +* **[Java]** Preserve byte order throughout IR transformations. +* **[C{plus}{plus}]** Integrate std::span support for flyweight API. (https://github.com/aeron-io/simple-binary-encoding/pull/1038[#1038], https://github.com/aeron-io/simple-binary-encoding/pull/1027[#1027]) +* **[Rust]** generate message schema level info in lib.rs. (https://github.com/aeron-io/simple-binary-encoding/pull/1019[#1019]) * Upgrade to `Gradle` 8.11.1. * Upgrade to `Checkstyle` 10.21.0. * Upgrade to `ByteBuddy` 1.15.11. @@ -131,21 +143,21 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru == 1.33.2 (2024-11-08) -* *[Rust]* Help decoding multiple messages using rust by resolving https://github.com/aeron-io/simple-binary-encoding/issues/987[#987]. -* *[Go]* SBE implementation in Go using flyweights. -* *[Java]* DTOs respect the optional package field in the schema definition. -* *[Java]* Fix bug in DTO `decodeFrom` signature. +* **[Rust]** Help decoding multiple messages using rust by resolving https://github.com/aeron-io/simple-binary-encoding/issues/987[#987]. +* **[Go]** SBE implementation in Go using flyweights. +* **[Java]** DTOs respect the optional package field in the schema definition. +* **[Java]** Fix bug in DTO `decodeFrom` signature. == 1.33.1 (2024-09-23) -* *[Java]* Fix #1012 DTO char array setter visibility. -* *[Rust]* Indicate the anonymous lifetime in set's Display impl (https://github.com/aeron-io/simple-binary-encoding/pull/1014[#1014]). -* *[Java]* Style consistency and add JavadocVariable Checkstyle test. -* *[Java]* Use version catalogs. -* *[Java]* Upgrade to JUnit 5.13.0. -* *[Java]* Upgrade to Gradle 8.10.1. -* *[Java]* Upgrade to Shadow 8.3.2. -* *[Java]* Upgrade to Checkstyle 10.18.1. +* **[Java]** Fix #1012 DTO char array setter visibility. +* **[Rust]** Indicate the anonymous lifetime in set's Display impl (https://github.com/aeron-io/simple-binary-encoding/pull/1014[#1014]). +* **[Java]** Style consistency and add JavadocVariable Checkstyle test. +* **[Java]** Use version catalogs. +* **[Java]** Upgrade to JUnit 5.13.0. +* **[Java]** Upgrade to Gradle 8.10.1. +* **[Java]** Upgrade to Shadow 8.3.2. +* **[Java]** Upgrade to Checkstyle 10.18.1. == 1.33.0 (2024-08-24) @@ -155,62 +167,62 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru === Changelog -* *[CI]* Execute tests using `ubuntu-24.04` and `macos-latest`. -* *[Java]* Upgrade to Agrona 1.23.0. -* *[Java]* Upgrade to Gradle 8.10. -* *[Java]* Upgrade to Shadow 8.3.0. -* *[Java]* Upgrade to Mockito 5.12.0. +* **[CI]** Execute tests using `ubuntu-24.04` and `macos-latest`. +* **[Java]** Upgrade to Agrona 1.23.0. +* **[Java]** Upgrade to Gradle 8.10. +* **[Java]** Upgrade to Shadow 8.3.0. +* **[Java]** Upgrade to Mockito 5.12.0. == 1.32.2 (2024-08-23) -* *[Rust]* Generate imports in alphabetical order. #997 -* *[Rust]* Make Rust crate version configurable. #996 -* *[C]* fix compilation error in C string view functions. #1010 -* *[Java]* Upgrade to JUnit 5.11.0. +* **[Rust]** Generate imports in alphabetical order. #997 +* **[Rust]** Make Rust crate version configurable. #996 +* **[C]** fix compilation error in C string view functions. #1010 +* **[Java]** Upgrade to JUnit 5.11.0. == 1.32.1 (2024-08-05) -* *[Java]* Upgrade to Agrona 1.22.0. -* *[Java]* Upgrade to Hamcrest 3.0. +* **[Java]** Upgrade to Agrona 1.22.0. +* **[Java]** Upgrade to Hamcrest 3.0. == 1.32.0 (2024-08-02) * [C#,C{plus}{plus},Java] Generate DTOs for non-perf-sensitive usecases. #957 * [C{plus}{plus}, C#] Only generate range validation code when specifying a range smaller than the associate type. -* *[C#]* Fix ToString() to avoid state changes on message. #992 -* *[C]* Add a #define for each template id. #1006 +* **[C#]** Fix ToString() to avoid state changes on message. #992 +* **[C]** Add a #define for each template id. #1006 * [Java, C#, C{plus}{plus}] Check enum value for language specific keywords and apply `sbe.keyword.append.token` when appropriate. #1009 #1008 == 1.31.0 (2024-04-03) -* *[Java]* Remove unused initialOffset member from generated codecs. -* *[Java]* Check for being in a composite when generating array access methods based on version. -* *[Java]* Captured types in IR should be for the minimum version used in a schema. https://github.com/aeron-io/simple-binary-encoding/pull/967[#967]. -* *[C{plus}{plus}]* Provide access to acting block length of repeating group via the sbeActingBlockLength() method. Issue #968. -* *[C{plus}{plus}]* message header members constexpr https://github.com/aeron-io/simple-binary-encoding/pull/971[#971]. -* *[C{plus}{plus}]* Code tidy up and address Issue #970. -* *[Java]* Cope with optional sets not being present when pretty printing decoders for debugging. https://github.com/aeron-io/simple-binary-encoding/pull/977[#977]. -* *[C{plus}{plus}]* small test fix https://github.com/aeron-io/simple-binary-encoding/pull/980[#980]. -* *[Rust]* Updated RustGenerator.generatePrimitiveOptionalDecoder() https://github.com/aeron-io/simple-binary-encoding/pull/981[#981]. -* *[Rust]* Take slices by reference https://github.com/aeron-io/simple-binary-encoding/pull/979[#979]. -* *[Rust]* updated code generator to prevent rust warning for "ambiguous glob re-exports" https://github.com/aeron-io/simple-binary-encoding/pull/982[#982]. -* *[Go]* Handle mixed case enums and BitSets. Fixes #983. -* *[Java]* Use `BYTE_ORDER` constant instead of accessing `java.nio.ByteOrder` directly. +* **[Java]** Remove unused initialOffset member from generated codecs. +* **[Java]** Check for being in a composite when generating array access methods based on version. +* **[Java]** Captured types in IR should be for the minimum version used in a schema. https://github.com/aeron-io/simple-binary-encoding/pull/967[#967]. +* **[C{plus}{plus}]** Provide access to acting block length of repeating group via the sbeActingBlockLength() method. Issue #968. +* **[C{plus}{plus}]** message header members constexpr https://github.com/aeron-io/simple-binary-encoding/pull/971[#971]. +* **[C{plus}{plus}]** Code tidy up and address Issue #970. +* **[Java]** Cope with optional sets not being present when pretty printing decoders for debugging. https://github.com/aeron-io/simple-binary-encoding/pull/977[#977]. +* **[C{plus}{plus}]** small test fix https://github.com/aeron-io/simple-binary-encoding/pull/980[#980]. +* **[Rust]** Updated RustGenerator.generatePrimitiveOptionalDecoder() https://github.com/aeron-io/simple-binary-encoding/pull/981[#981]. +* **[Rust]** Take slices by reference https://github.com/aeron-io/simple-binary-encoding/pull/979[#979]. +* **[Rust]** updated code generator to prevent rust warning for "ambiguous glob re-exports" https://github.com/aeron-io/simple-binary-encoding/pull/982[#982]. +* **[Go]** Handle mixed case enums and BitSets. Fixes #983. +* **[Java]** Use `BYTE_ORDER` constant instead of accessing `java.nio.ByteOrder` directly. * Upgrade .NET SDK to 8.0.201 (https://github.com/aeron-io/simple-binary-encoding/pull/978[#978]). -* *[Java]* Upgrade to Agrona 1.21.1. -* *[Java]* Upgrade to ASM 9.7. -* *[Java]* Upgrade to JUnit 5.10.2. -* *[Java]* Upgrade to Versions 0.51.0. +* **[Java]** Upgrade to Agrona 1.21.1. +* **[Java]** Upgrade to ASM 9.7. +* **[Java]** Upgrade to JUnit 5.10.2. +* **[Java]** Upgrade to Versions 0.51.0. == 1.30.0 (2023-12-06) * [Java, C{plus}{plus}, C#] Add support to https://github.com/aeron-io/simple-binary-encoding/wiki/Safe-Flyweight-Usage[check the safe usage of flyweights (w.r.t. field access order)]. https://github.com/aeron-io/simple-binary-encoding/pull/948[#948]. -* *[C#]* Fix invalid code generated when using some length types for var data https://github.com/aeron-io/simple-binary-encoding/issues/955[#955] -* *[Java]* Support valueRef with camelCase enum type identifiers https://github.com/aeron-io/simple-binary-encoding/pull/963[#963] -* *[Rust]* update how "use declarations" are generated, now deriving Defaults for enums https://github.com/aeron-io/simple-binary-encoding/pull/952[#952] -* *[C{plus}{plus}]* Rely on NAN from limits rather than pulling in cmath (https://github.com/aeron-io/simple-binary-encoding/issues/956) -* *[Java]* Fix javadoc link for JDK 21 GA -* *[Java]* Expose actingVersion https://github.com/aeron-io/simple-binary-encoding/pull/953[#953] +* **[C#]** Fix invalid code generated when using some length types for var data https://github.com/aeron-io/simple-binary-encoding/issues/955[#955] +* **[Java]** Support valueRef with camelCase enum type identifiers https://github.com/aeron-io/simple-binary-encoding/pull/963[#963] +* **[Rust]** update how "use declarations" are generated, now deriving Defaults for enums https://github.com/aeron-io/simple-binary-encoding/pull/952[#952] +* **[C{plus}{plus}]** Rely on NAN from limits rather than pulling in cmath (https://github.com/aeron-io/simple-binary-encoding/issues/956) +* **[Java]** Fix javadoc link for JDK 21 GA +* **[Java]** Expose actingVersion https://github.com/aeron-io/simple-binary-encoding/pull/953[#953] * Upgrade Agrona to 1.20.0 * Upgrade to ASM 9.6 * Upgrade to JMH 1.27 @@ -219,10 +231,10 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru == 1.29.0 (2023-07-21) -* *[Rust]* Add derive Copy Clone traits for decoders (PR #940). -* *[Rust]* Fix clippy lint (PR #941). -* *[Rust]* Fix array syntax error (PR #946). -* *[Rust]* Improve rust performance (PR #944). +* **[Rust]** Add derive Copy Clone traits for decoders (PR #940). +* **[Rust]** Fix clippy lint (PR #941). +* **[Rust]** Fix array syntax error (PR #946). +* **[Rust]** Improve rust performance (PR #944). * JsonPrinter remove trailing garbage after non-printable char (PR #950). * Upgrade to Agrona 1.19.0. * Upgrade to versions 0.47.0. @@ -248,17 +260,17 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru == 1.28.0 (2023-03-29) * Added semantic version as a static public member. PR #931. -* *[Rust]* Nested composite name should not be based on field name. PR #922. -* *[C/C{plus}{plus}]* Prevent clashing defines in C/C{plus}{plus} codecs when multiple generated schemas are used. Issue #884. -* *[C#]* Compare `PrimitiveValue` with doubles in the same way as Java by the raw bits, so NaN and Infinity are correctly handled. +* **[Rust]** Nested composite name should not be based on field name. PR #922. +* **[C/C{plus}{plus}]** Prevent clashing defines in C/C{plus}{plus} codecs when multiple generated schemas are used. Issue #884. +* **[C#]** Compare `PrimitiveValue` with doubles in the same way as Java by the raw bits, so NaN and Infinity are correctly handled. * Add CodeQL workflow. -* *[C#]* Add `ToString` for `PrimitiveType` -* *[C{plus}{plus}]* Pass by reference rather than value when streaming to a string. -* *[C{plus}{plus}]* Address duplicate guard issues. -* *[Java]* More efficient attribute parsing in XML with a more precise error message. -* *[Java]* Validate IR file for decoding is not greater than Integer.MAX_VALUE. -* *[C/C{plus}{plus}]* Move check for existing `SBE_BOUNDS_CHECK_EXPECT` define to outer condition to capture all platforms. -* *[Java]* Print warnings for undersize header fields. +* **[C#]** Add `ToString` for `PrimitiveType` +* **[C{plus}{plus}]** Pass by reference rather than value when streaming to a string. +* **[C{plus}{plus}]** Address duplicate guard issues. +* **[Java]** More efficient attribute parsing in XML with a more precise error message. +* **[Java]** Validate IR file for decoding is not greater than Integer.MAX_VALUE. +* **[C/C{plus}{plus}]** Move check for existing `SBE_BOUNDS_CHECK_EXPECT` define to outer condition to capture all platforms. +* **[Java]** Print warnings for undersize header fields. * Upgrade to Agrona 1.18.0. * Upgrade to Mockito 4.11.0. * Upgrade to Junit 5.9.2. @@ -268,10 +280,10 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru == 1.27.0 (2022-10-11) -* *[Java]* Add preview support for package override on types from SBE 2.0. https://github.com/aeron-io/simple-binary-encoding/pull/904[#904], https://github.com/aeron-io/simple-binary-encoding/pull/915[#915]. +* **[Java]** Add preview support for package override on types from SBE 2.0. https://github.com/aeron-io/simple-binary-encoding/pull/904[#904], https://github.com/aeron-io/simple-binary-encoding/pull/915[#915]. * Add support for transforming a schema to generate code for older versions when checking compatibility. -* *[Java]* Support binary var data in `JsonPrinter`. https://github.com/aeron-io/simple-binary-encoding/pull/914[#914]. -* *[Java]* Qualify methods with name `yield` to avoid warning in Java 17. https://github.com/aeron-io/simple-binary-encoding/pull/910[#910]. +* **[Java]** Support binary var data in `JsonPrinter`. https://github.com/aeron-io/simple-binary-encoding/pull/914[#914]. +* **[Java]** Qualify methods with name `yield` to avoid warning in Java 17. https://github.com/aeron-io/simple-binary-encoding/pull/910[#910]. * Carry down the the `sinceVersion` value into composite types to make parsing OTF easier. https://github.com/aeron-io/simple-binary-encoding/issues/908[Issue #908]. * Set the size for constant encoded data type to be zero in IR. * Upgrade to Google Test 1.21.1. @@ -282,12 +294,12 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru == 1.26.0 (2022-07-11) -* *[Java]* Provide raw access to type for bitset. https://github.com/aeron-io/simple-binary-encoding/issues/893[Issue #893]. -* *[C{plus}{plus}]* Generate `skip` function with loop rather than lambda to avoid compilation errors on some compilers. https://github.com/aeron-io/simple-binary-encoding/issues/903[Issue #903]. +* **[Java]** Provide raw access to type for bitset. https://github.com/aeron-io/simple-binary-encoding/issues/893[Issue #893]. +* **[C{plus}{plus}]** Generate `skip` function with loop rather than lambda to avoid compilation errors on some compilers. https://github.com/aeron-io/simple-binary-encoding/issues/903[Issue #903]. * Check `sinceVersion` is valid on elements against schema version. https://github.com/aeron-io/simple-binary-encoding/issues/902[Issue #902]. -* *[Rust]* Fix generated comparator when value is `NaN`. https://github.com/aeron-io/simple-binary-encoding/pull/896[#896]. -* *[Rust]* Fix resource leak in Rust generator running in Java SBE compiler. -* *[Java]* Generate `@SuppressWarnings` annotation on enums types. https://github.com/aeron-io/simple-binary-encoding/issues/894[Issue #894]. +* **[Rust]** Fix generated comparator when value is `NaN`. https://github.com/aeron-io/simple-binary-encoding/pull/896[#896]. +* **[Rust]** Fix resource leak in Rust generator running in Java SBE compiler. +* **[Java]** Generate `@SuppressWarnings` annotation on enums types. https://github.com/aeron-io/simple-binary-encoding/issues/894[Issue #894]. * Upgrade to Mockito 4.6.1. * Upgrade to Agrona 1.16.0. @@ -300,10 +312,10 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru == 1.25.2 (2022-03-18) -* *[Java]* Calling `toString()` on decoder should not disturb repeating group. https://github.com/aeron-io/simple-binary-encoding/pull/892[#892]. -* *[All]* Generate `NULL_VALUE` for enums based on correct type. https://github.com/aeron-io/simple-binary-encoding/issues/889[Issue #889]. -* *[C{plus}{plus}]* Check for version before outputting to stream for composites and bitsets. https://github.com/aeron-io/simple-binary-encoding/pull/888[#888]. -* *[Java]* Charset handling improvements for more efficient string decoding. https://github.com/aeron-io/simple-binary-encoding/pull/887[#887]. +* **[Java]** Calling `toString()` on decoder should not disturb repeating group. https://github.com/aeron-io/simple-binary-encoding/pull/892[#892]. +* **[All]** Generate `NULL_VALUE` for enums based on correct type. https://github.com/aeron-io/simple-binary-encoding/issues/889[Issue #889]. +* **[C{plus}{plus}]** Check for version before outputting to stream for composites and bitsets. https://github.com/aeron-io/simple-binary-encoding/pull/888[#888]. +* **[Java]** Charset handling improvements for more efficient string decoding. https://github.com/aeron-io/simple-binary-encoding/pull/887[#887]. * Add descriptions to schema for IR. * Set warnings as errors in build and clean up existing warnings. * Add ability to set the error stream in `ParserOptions`. @@ -324,11 +336,11 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru == 1.25.0 (2021-11-17) -* *[C#]* Add support for wrapping `ArraySegment` in `DirectBuffer`. https://github.com/aeron-io/simple-binary-encoding/pull/878[#878]. -* *[Java]* Add `@Deprecated` annotation to message codecs that have been marked as deprecated in SBE schema. https://github.com/aeron-io/simple-binary-encoding/pull/876[#876]. -* *[C{plus}{plus}]* Only generate necessary macros and includes for enum types. -* *[Rust]* Reinstate improved Rust codec generation. -* *[Java]* Add `sbeSkip` and `sbeDecodedLength` methods to codecs. https://github.com/aeron-io/simple-binary-encoding/pull/865[#865]. +* **[C#]** Add support for wrapping `ArraySegment` in `DirectBuffer`. https://github.com/aeron-io/simple-binary-encoding/pull/878[#878]. +* **[Java]** Add `@Deprecated` annotation to message codecs that have been marked as deprecated in SBE schema. https://github.com/aeron-io/simple-binary-encoding/pull/876[#876]. +* **[C{plus}{plus}]** Only generate necessary macros and includes for enum types. +* **[Rust]** Reinstate improved Rust codec generation. +* **[Java]** Add `sbeSkip` and `sbeDecodedLength` methods to codecs. https://github.com/aeron-io/simple-binary-encoding/pull/865[#865]. * Upgrade to JUnit 5.8.1. * Upgrade to Shadow 7.1.0. * Upgrade to Mockito 4.0.0. @@ -339,9 +351,9 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru == 1.24.0 (2021-08-06) -* *[Java]* Improve efficiency of encoding `CharSequence` when ASCII character encoding is used. -* *[Java]* Check that IR codecs are regenerated on codec change. -* *[Java/C{plus}{plus}/C]* Add `sbeRewind` to decoders so they can rewind to the beginning of a message and begin decoding again. +* **[Java]** Improve efficiency of encoding `CharSequence` when ASCII character encoding is used. +* **[Java]** Check that IR codecs are regenerated on codec change. +* **[Java/C{plus}{plus}/C]** Add `sbeRewind` to decoders so they can rewind to the beginning of a message and begin decoding again. * Upgrade to Google Test 1.11.0 * Upgrade to ByteBuddy 1.11.3 * Upgrade to Mockito 3.11.2. @@ -350,10 +362,10 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru == 1.23.0 (2021-06-13) -* *[C#]* Add `ToString()` method to generated codecs. https://github.com/aeron-io/simple-binary-encoding/pull/853[#853]. -* *[C#]* Add more string read and write methods to codecs. https://github.com/aeron-io/simple-binary-encoding/pull/845[#845]. -* *[Go]* Fix tokens passed when generating composites. https://github.com/aeron-io/simple-binary-encoding/pull/850[#850]. -* *[C/C{plus}{plus}]* Add Clang 12 to the matrix build. +* **[C#]** Add `ToString()` method to generated codecs. https://github.com/aeron-io/simple-binary-encoding/pull/853[#853]. +* **[C#]** Add more string read and write methods to codecs. https://github.com/aeron-io/simple-binary-encoding/pull/845[#845]. +* **[Go]** Fix tokens passed when generating composites. https://github.com/aeron-io/simple-binary-encoding/pull/850[#850]. +* **[C/C{plus}{plus}]** Add Clang 12 to the matrix build. * Upgrade to Versions 0.39.0. * Upgrade to JUnit 5.7.2. * Upgrade to Mockito 3.11.1. @@ -365,15 +377,15 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru == 1.22.0 (2021-04-16) -* *[C#]* Convert benchmarks to use DotNetBenchmark. https://github.com/aeron-io/agrona/pull/841[#841]. -* *[C#]* Help compiler to inline `DirectBuffer.CheckLimit` for better performance. https://github.com/aeron-io/simple-binary-encoding/pull/840[#840]. +* **[C#]** Convert benchmarks to use DotNetBenchmark. https://github.com/aeron-io/agrona/pull/841[#841]. +* **[C#]** Help compiler to inline `DirectBuffer.CheckLimit` for better performance. https://github.com/aeron-io/simple-binary-encoding/pull/840[#840]. * Add Java 17-ea to the build matrix. * Test with CME FixBinary version 9. -* *[C{plus}{plus}]* Capture `actingBlockLength` and use it for prettying printing output in version aware codecs. https://github.com/aeron-io/simple-binary-encoding/issues/839[Issue #839]. -* *[C{plus}{plus}]* Remove invalid use of `noexcept` on `resetCountToIndex`. https://github.com/aeron-io/simple-binary-encoding/issues/838[Issue #838]. -* *[Java]* Generate a `wrapAndApplyHeader` method for decoders to verify template then apply acting version and offset. -* *[C{plus}{plus}]* Clean up and improve samples. -* *[C{plus}{plus}]* Pass elements by reference rather than value in `forEach` for more efficient skip operations. +* **[C{plus}{plus}]** Capture `actingBlockLength` and use it for prettying printing output in version aware codecs. https://github.com/aeron-io/simple-binary-encoding/issues/839[Issue #839]. +* **[C{plus}{plus}]** Remove invalid use of `noexcept` on `resetCountToIndex`. https://github.com/aeron-io/simple-binary-encoding/issues/838[Issue #838]. +* **[Java]** Generate a `wrapAndApplyHeader` method for decoders to verify template then apply acting version and offset. +* **[C{plus}{plus}]** Clean up and improve samples. +* **[C{plus}{plus}]** Pass elements by reference rather than value in `forEach` for more efficient skip operations. * Upgrade to Version 0.38.0. * Upgrade to JMH 1.29. * Upgrade to JUnit 5.7.1. @@ -383,10 +395,10 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru == 1.21.0 (2021-01-15) -* *[Java]* Generate metadata methods to groups for min and max count values. https://github.com/aeron-io/simple-binary-encoding/pull/834[#834]. -* *[Java]* Declare generated classes as final to allow for better optimisation and increased performance. -* *[C{plus}{plus}]* Null terminate constant char arrays to avoid warnings. https://github.com/aeron-io/simple-binary-encoding/issues/832[Issue #832]. -* *[C{plus}{plus}]* Add support for decoding unknown enum values from later versions by enabling `sbe.decode.unknown.enum.values` and provide access to raw values. +* **[Java]** Generate metadata methods to groups for min and max count values. https://github.com/aeron-io/simple-binary-encoding/pull/834[#834]. +* **[Java]** Declare generated classes as final to allow for better optimisation and increased performance. +* **[C{plus}{plus}]** Null terminate constant char arrays to avoid warnings. https://github.com/aeron-io/simple-binary-encoding/issues/832[Issue #832]. +* **[C{plus}{plus}]** Add support for decoding unknown enum values from later versions by enabling `sbe.decode.unknown.enum.values` and provide access to raw values. * Clean up warnings in bash scripts. * Upgrade to Checkstyle 8.39. * Upgrade to Mockito 3.7.0. @@ -394,14 +406,14 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru == 1.20.4 (2020-12-22) * Add parsing of CME iLink order protocol to tests. -* *[C{plus}{plus}]* Generate literal marked up for correct type when shifting for bitsets using `uint64`. https://github.com/aeron-io/simple-binary-encoding/pull/829[#829]. -* *[Java]* Generate `@return` in javadoc for bitset values. https://github.com/aeron-io/simple-binary-encoding/issues/828[Issue #828]. -* *[Java]* Escape basic HTML characters for javadoc. https://github.com/aeron-io/simple-binary-encoding/issues/826[Issue #826]. -* *[Go]* Fix decoding into struct with pre-allocated slices. https://github.com/aeron-io/simple-binary-encoding/pull/825[#825]. -* *[C{plus}{plus}]* Fix spelling of `_cplusplus` macro. https://github.com/aeron-io/simple-binary-encoding/issues/823[Issue #821]. -* *[C#]* Fix repeating group encode overflow. https://github.com/aeron-io/simple-binary-encoding/pull/823[#823]. -* *[C]* Fix argument order for wrap_and_apply_header methods. https://github.com/aeron-io/simple-binary-encoding/pull/821[#821]. -* *[Java]* Generate bulk methods for fixed length `uint8` arrays. https://github.com/aeron-io/simple-binary-encoding/pull/819[#819]. +* **[C{plus}{plus}]** Generate literal marked up for correct type when shifting for bitsets using `uint64`. https://github.com/aeron-io/simple-binary-encoding/pull/829[#829]. +* **[Java]** Generate `@return` in javadoc for bitset values. https://github.com/aeron-io/simple-binary-encoding/issues/828[Issue #828]. +* **[Java]** Escape basic HTML characters for javadoc. https://github.com/aeron-io/simple-binary-encoding/issues/826[Issue #826]. +* **[Go]** Fix decoding into struct with pre-allocated slices. https://github.com/aeron-io/simple-binary-encoding/pull/825[#825]. +* **[C{plus}{plus}]** Fix spelling of `_cplusplus` macro. https://github.com/aeron-io/simple-binary-encoding/issues/823[Issue #821]. +* **[C#]** Fix repeating group encode overflow. https://github.com/aeron-io/simple-binary-encoding/pull/823[#823]. +* **[C]** Fix argument order for wrap_and_apply_header methods. https://github.com/aeron-io/simple-binary-encoding/pull/821[#821]. +* **[Java]** Generate bulk methods for fixed length `uint8` arrays. https://github.com/aeron-io/simple-binary-encoding/pull/819[#819]. * Add Java 16 EA to the build matrix. * Upgrade to JMH 1.27. * Upgrade to Checkstyle 8.38. @@ -614,10 +626,10 @@ $ java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED -Dsbe.generate.ir=tru == 1.13.0 (2019-08-02) -* *[C#]* Add system property to allow squashing of namespace generation. https://github.com/aeron-io/simple-binary-encoding/pull/702[#702]. -* *[C{plus}{plus}]* Use `*[nodiscard]*` attribute where applicable. https://github.com/aeron-io/simple-binary-encoding/pull/700[#700]. -* *[C#]* Use ThrowHelper and simplify bounds checks to improve inlining. https://github.com/aeron-io/simple-binary-encoding/pull/695[#695]. -* *[Java]* Javadoc to `MetaAttribute` generation. +* **[C#]** Add system property to allow squashing of namespace generation. https://github.com/aeron-io/simple-binary-encoding/pull/702[#702]. +* **[C{plus}{plus}]** Use `**[nodiscard]**` attribute where applicable. https://github.com/aeron-io/simple-binary-encoding/pull/700[#700]. +* **[C#]** Use ThrowHelper and simplify bounds checks to improve inlining. https://github.com/aeron-io/simple-binary-encoding/pull/695[#695]. +* **[Java]** Javadoc to `MetaAttribute` generation. * Upgrade to Agrona 1.0.6. * Upgrade to javadoc-links 3.8.1. * Upgrade to Checkstyle 8.23. From fdea523263b140581a2d2d0421f263cb25eabc49 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Dec 2025 23:20:58 +0100 Subject: [PATCH 1500/1594] 1.37.0 released. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 7991f09416..bf50e910e6 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.37.0-SNAPSHOT +1.37.0 From 002af637b0b9a9e64ea82a50ac2cdf92363cb3d1 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 25 Dec 2025 23:21:08 +0100 Subject: [PATCH 1501/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index bf50e910e6..860bd0396d 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.37.0 +1.38.0-SNAPSHOT From b0882e7f58dfdd16af8bcd96c0f55620bdf4d4f7 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 6 Jan 2026 14:40:32 +0100 Subject: [PATCH 1502/1594] [Java] Ensure Java code generation for precedence checks always produces the same code without re-orderings. --- .../common/FieldPrecedenceModel.java | 31 +++++--- .../java/JavaGeneratorDeterminismTest.java | 79 +++++++++++++++++++ 2 files changed, 100 insertions(+), 10 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorDeterminismTest.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java index cad644fedf..e9c8dcc1f9 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/common/FieldPrecedenceModel.java @@ -45,12 +45,12 @@ public final class FieldPrecedenceModel private final CodecInteraction.CodecInteractionFactory interactionFactory = new CodecInteraction.CodecInteractionFactory(groupPathsByField, topLevelBlockFields); private final Map> transitionsByInteraction = new LinkedHashMap<>(); - private final Map> transitionsByState = new HashMap<>(); + private final Map> transitionsByState = new TreeMap<>(); private final TreeMap versionWrappedStates = new TreeMap<>(); private final State notWrappedState = allocateState("NOT_WRAPPED"); private final String generatedRepresentationClassName; private State encoderWrappedState; - private Set terminalEncoderStates; + private SortedSet terminalEncoderStates; private FieldPrecedenceModel(final String generatedRepresentationClassName) { @@ -135,9 +135,7 @@ public void forEachTerminalEncoderState(final Consumer consumer) */ public void forEachStateOrderedByStateNumber(final Consumer consumer) { - transitionsByState.keySet().stream() - .sorted(Comparator.comparingInt((s) -> s.number)) - .forEach(consumer); + transitionsByState.keySet().forEach(consumer); } /** @@ -273,7 +271,7 @@ private void findTransitions( // Last writer (highest version) wins when there are multiple versions encoderWrappedState = versionWrappedState; - terminalEncoderStates = transitionCollector.exitStates(); + terminalEncoderStates = new TreeSet<>(transitionCollector.exitStates()); }); } @@ -459,7 +457,7 @@ public void onVarData(final Token token) private final class TransitionCollector implements SchemaConsumer { private final String statePrefix; - private final HashSet currentStates; + private final Set currentStates; private final State blockState; private final Predicate filter; @@ -470,7 +468,7 @@ private TransitionCollector( final Predicate filter) { this.statePrefix = statePrefix; - this.currentStates = new HashSet<>(fromStates); + this.currentStates = new TreeSet<>(fromStates); this.blockState = blockState; this.filter = filter; @@ -585,7 +583,7 @@ private Set exitStates() /** * A state in which a codec may reside. */ - public static final class State + public static final class State implements Comparable { private final int number; private final String name; @@ -615,6 +613,19 @@ public String name() return name; } + /** + * {@inheritDoc}. + */ + public int compareTo(final State other) + { + final int result = Integer.compare(number, other.number); + if (0 != result) + { + return result; + } + return name.compareTo(other.name); + } + /** * {@inheritDoc} */ @@ -642,7 +653,7 @@ private TransitionGroup( final State to) { this.interaction = interaction; - this.from = new HashSet<>(from); + this.from = new TreeSet<>(from); this.to = to; } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorDeterminismTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorDeterminismTest.java new file mode 100644 index 0000000000..2f093c6ff1 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/JavaGeneratorDeterminismTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2013-2025 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.co.real_logic.sbe.generation.java; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.generation.StringWriterOutputManager; +import org.junit.jupiter.api.Test; +import uk.co.real_logic.sbe.Tests; +import uk.co.real_logic.sbe.generation.common.PrecedenceChecks; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.xml.IrGenerator; +import uk.co.real_logic.sbe.xml.MessageSchema; +import uk.co.real_logic.sbe.xml.ParserOptions; + +import java.io.InputStream; +import java.util.Map; +import java.util.TreeMap; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +/** + * Tests that generated code is deterministic when precedence checks are enabled. + */ +class JavaGeneratorDeterminismTest +{ + private static final String BUFFER_NAME = MutableDirectBuffer.class.getName(); + private static final String READ_ONLY_BUFFER_NAME = DirectBuffer.class.getName(); + + @Test + void shouldGenerateDeterministicOutputWithPrecedenceChecks() throws Exception + { + final Map firstGeneration = generateWithPrecedenceChecks(); + final Map secondGeneration = generateWithPrecedenceChecks(); + + assertEquals(firstGeneration.keySet(), secondGeneration.keySet()); + + for (final String fileName : firstGeneration.keySet()) + { + final CharSequence firstSource = firstGeneration.get(fileName); + final CharSequence secondSource = secondGeneration.get(fileName); + assertEquals(firstSource, secondSource); + } + } + + private Map generateWithPrecedenceChecks() throws Exception + { + try (InputStream in = Tests.getLocalResource("field-order-check-schema.xml")) + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + final StringWriterOutputManager outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + final PrecedenceChecks.Context context = new PrecedenceChecks.Context() + .shouldGeneratePrecedenceChecks(true); + final PrecedenceChecks precedenceChecks = PrecedenceChecks.newInstance(context); + final JavaGenerator generator = new JavaGenerator( + ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, false, precedenceChecks, outputManager); + generator.generate(); + return new TreeMap<>(outputManager.getSources()); + } + } +} From ba8751caf0d4dc373e140b42abab53d9b3813f68 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 13 Jan 2026 12:22:51 +0100 Subject: [PATCH 1503/1594] [Java] Update to `Shadow` 9.3.1. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d85c88eafd..57b225fb25 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ json = "20251224" junit = "6.0.1" mockito = "5.21.0" plexus = "3.3.0" -shadow = "9.3.0" +shadow = "9.3.1" versions = "0.53.0" [libraries] From 3fc0169a2fe24236f873f96830dbb1f8a7401dbf Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 13 Jan 2026 12:23:04 +0100 Subject: [PATCH 1504/1594] [Java] Update to `JUnit` 6.0.2. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 57b225fb25..f5fc18e4e6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ httpcore = "4.4.14" jqwik = "1.9.3" jmh = "1.37" json = "20251224" -junit = "6.0.1" +junit = "6.0.2" mockito = "5.21.0" plexus = "3.3.0" shadow = "9.3.1" From c091c873bb932b775ae62550d0376968164afbb2 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Tue, 13 Jan 2026 12:24:45 +0100 Subject: [PATCH 1505/1594] [Doc] Update release notes. --- CHANGELOG.adoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 79db065ce0..897cda1814 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,5 +1,10 @@ = Changelog +== 1.37.1 (2026-01-13) +* **[Java]** Ensure Java code generation for precedence checks always produces the same code without re-orderings. +* **[Java]** Upgrade to `Shadow` 9.3.1. +* **[Java]** Upgrade to `JUnit` 6.0.2. + == 1.37.0 (2025-12-25) * **[C]** Implement `--sanitise-build` support. From 2e78afe5addbc5f701e2d7f4528a8444bf25dd5b Mon Sep 17 00:00:00 2001 From: Dan Shearer Date: Tue, 13 Jan 2026 13:53:14 +0000 Subject: [PATCH 1506/1594] 1.37.1 release --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 860bd0396d..9cf86ad0ff 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.38.0-SNAPSHOT +1.37.1 From f8bdee5730959d41f41a28b2b02d90fca0beeac7 Mon Sep 17 00:00:00 2001 From: Dan Shearer Date: Tue, 13 Jan 2026 13:55:17 +0000 Subject: [PATCH 1507/1594] post release bump --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 9cf86ad0ff..860bd0396d 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.37.1 +1.38.0-SNAPSHOT From d8232557dff8ca3002500df7fc72e2ac8a945f76 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Mon, 19 Jan 2026 09:58:23 +0100 Subject: [PATCH 1508/1594] [Java] Upgrade to `Gradle` 9.3.0. --- gradle/wrapper/gradle-wrapper.jar | Bin 45633 -> 46175 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f8e1ee3125fe0768e9a76ee977ac089eb657005e..61285a659d17295f1de7c53e24fdf13ad755c379 100644 GIT binary patch delta 37058 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 NNswbwE82Y!{{uvZmpcFe delta 36446 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

    19. eiA2GR@p!BxfkB$9OMKXKst*+I> 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 AyZ`_I literal 0 HcmV?d00001 From 56d7d3b2534c07c9a8b6329e02c156d33933c383 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Fri, 9 Sep 2022 09:42:30 +0100 Subject: [PATCH 0913/1594] [Java] Upgrade to Mockito 4.8.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 478167dfeb..ec7122c49c 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ def toolchainLauncher = javaToolchains.launcherFor { def checkstyleVersion = '9.3' def hamcrestVersion = '2.2' -def mockitoVersion = '4.7.0' +def mockitoVersion = '4.8.0' def junitVersion = '5.9.0' def jmhVersion = '1.35' def agronaVersion = '1.16.0' From e39a15d521880c65adabf0fc9504fca0986968cc Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 14 Sep 2022 17:14:35 +0100 Subject: [PATCH 0914/1594] [Java] Upgrade to Agrona 1.17.0. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ec7122c49c..60938e413c 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.8.0' def junitVersion = '5.9.0' def jmhVersion = '1.35' -def agronaVersion = '1.16.0' +def agronaVersion = '1.17.0' def agronaVersionRange = '[1.15.2,2.0[' // allow any release >= 1.15.2 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' From 6275f894b3a0298c67c902eefd39a6aa36845f81 Mon Sep 17 00:00:00 2001 From: mjpt777 Date: Wed, 14 Sep 2022 18:56:54 +0100 Subject: [PATCH 0915/1594] [Java] Upgrade to Agrona 1.17.1. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 60938e413c..582bed2752 100644 --- a/build.gradle +++ b/build.gradle @@ -47,8 +47,8 @@ def hamcrestVersion = '2.2' def mockitoVersion = '4.8.0' def junitVersion = '5.9.0' def jmhVersion = '1.35' -def agronaVersion = '1.17.0' -def agronaVersionRange = '[1.15.2,2.0[' // allow any release >= 1.15.2 and < 2.0.0 +def agronaVersion = '1.17.1' +def agronaVersionRange = '[1.17.1,2.0[' // allow any release >= 1.17.1 and < 2.0.0 def sbeGroup = 'uk.co.real-logic' def sbeVersion = file('version.txt').text.trim() From c23992114334f0e12d8a7da95ade4c19c0faa537 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Thu, 15 Sep 2022 13:45:45 +1200 Subject: [PATCH 0916/1594] [Java] Add support for transforming the schema to generate code for older versions. --- .gitignore | 2 + .../java/uk/co/real_logic/sbe/SbeTool.java | 32 ++++- .../sbe/xml/IdKeyedSchemaTransformer.java | 42 ++++++ .../co/real_logic/sbe/xml/MessageSchema.java | 34 ++++- .../real_logic/sbe/xml/SchemaTransformer.java | 35 +++++ .../sbe/xml/SchemaTransformerFactory.java | 88 ++++++++++++ .../xml/SinceVersionSchemaTransformer.java | 70 ++++++++++ ...onTransformedSchemaJavaGenerationTest.java | 73 ++++++++++ .../sbe/xml/SchemaTransformerFactoryTest.java | 67 +++++++++ .../SinceVersionSchemaTransformerTest.java | 132 ++++++++++++++++++ .../resources/since-version-filter-schema.xml | 118 ++++++++++++++++ 11 files changed, 687 insertions(+), 6 deletions(-) create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/IdKeyedSchemaTransformer.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java create mode 100644 sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SinceVersionTransformedSchemaJavaGenerationTest.java create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java create mode 100644 sbe-tool/src/test/resources/since-version-filter-schema.xml diff --git a/.gitignore b/.gitignore index c7dcc86189..117022a886 100644 --- a/.gitignore +++ b/.gitignore @@ -113,3 +113,5 @@ rust/Cargo.lock # Mac .DS_Store /sbe-tool/src/main/golang/uk_co_real_logic_sbe_ir_generated/ + +/generated/ diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java index 340de63f8f..cacf53a187 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java @@ -18,12 +18,20 @@ import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; import org.xml.sax.InputSource; -import uk.co.real_logic.sbe.generation.*; -import uk.co.real_logic.sbe.ir.*; +import uk.co.real_logic.sbe.generation.CodeGenerator; +import uk.co.real_logic.sbe.generation.TargetCodeGenerator; +import uk.co.real_logic.sbe.generation.TargetCodeGeneratorLoader; +import uk.co.real_logic.sbe.ir.Ir; +import uk.co.real_logic.sbe.ir.IrDecoder; +import uk.co.real_logic.sbe.ir.IrEncoder; import uk.co.real_logic.sbe.xml.*; -import java.io.*; -import java.nio.file.*; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; /** * A tool for running the SBE parser, validator, and code generator. @@ -176,6 +184,17 @@ public class SbeTool */ public static final String DECODE_UNKNOWN_ENUM_VALUES = "sbe.decode.unknown.enum.values"; + /** + * Configuration option used to manage sinceVersion based transformations. When set, parsed schemas will be + * transformed to discard messages and types higher than the specified version. This can be useful when needing + * to generate older versions of a schema to do version compatibility testing. + *

      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

    4-SGy}j^6Si(%tW01` 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�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

    U5iMt+?Msu5(H6ZU9Azc z6P+PYFASWmGb|GTx}LHb7JlWBAz=&5AuSHd8j@83oB9XCik);G+E_WXiXF4n)|Hhk zB|G<}1X_Mt3RARiM~j>mC%mO_&JG25;mvO?l)Q1ZzjeO0NbP%Pw;bKdK(y`?&#e1e ztED@rX^_8e-*@LulV5fbKN-Fad7)GX&fw#GBg%cM(~hOx8TNzDtF)*5Vcl3MdP zTz=krYI}vqgI>I>_#k0T58^r98VXBv!;m}^{~N%3_Z)IJ^5~lom}rD| zIq0ppXK$$8E-gIz&B-BiExBs}qj=`LB$g2%X9zgQmkrhrHs zG@uMZIsL9!@&-isBfKMVGk`SOeb3wiJbm?RNhA3FXB9+XMPD6cmGhOC102kGySxwWAfT!%MP6i(b-wm~Ug9?D!Y<$M+;hUB2@p*PnzA6ZrzorLG5W-yaG&?@43N#Nf?^)n~=kIDj)g~bi? zWj_-M`5Y0?qnuUT3_lj9^g@^zl+zai^cql?iyx^@_V)8D{QR*;@MO2}dsvlAA~Ti{ z?x?fZd(~KVtey%VSTMXoI1)+1h7}-LXFZ?DoEcmqnW2YMt`z>JI?ZyxGeeUwRuYro ztvhXYVVa|*@kd`~ z8k%E77vkT!tDMrqIn^>9-bNb5vYteY9mC;_2-x?~_SSm=M@)8pxR@e^=d_Hqi4S!1 zaK8!Q=Q!;Ku1;%hx2;WW$GFM&j-_>?L3T2_GC{~WT{+*oGpOX_(t-StHJ@5vp^0PPx<|}s zqpxcj-TPEy_rK&3dpnuhA>ZAn)3OpJ9|B0hV;;e_1-@h^DM>~|R+=OLM8$I|{)?<8L}N zDaSFK|F})eP7wu9G_zm|^#;f-6VVJJN|I;Te8||IHzgFr$nO{L3d55TkH-}q$P)zT zD2*mEQ9%s2e=rNjQb6Hjt8|%;C#o6|n5;dz6LKsHCN^cLqCnOsh*&`m@yg)!`PrpAQzq#5j(GKlTyyvNcmZU@&zKe112z4`5 zn{Ro%(yM+-g$f=Dve)>oPGo0`T(kYZIp8M$U6d%#HW z=RVdMDCJh%KCD{d+9nsFkdAT;unM}foN}5Fb4DnPi3)lv4h=CJ7%Vwa7&b+o7Xp{k zyt4h}(sQjPji^*?BRq8QO^p9jy^2ydS4qdwUYhph7`*Veof@~0k2mmM5%nweL;t_4A!riU9q3jiU{&ce>semEJ>&M{ru6Uhpiew&5z*?uZ$dTux` zzNeks!I$5$Mbla+3U$Jamo|8j}V9Y3&P#62z(LFboY0kZh?TM=}&DCVOkTlwY zTI4H)-drf{@F2J4A9U;7|(wV(}|KgA@~mjul&SgQHJ7;(j*&1ofU}>Qw|pHIi`0~Rx!!;1XuEI!%qu)vD{=JCE#_dW$0t2f;~TWF8R--A znvJH7i1`Y*u_ZW9W^NUfTI=QDG*aOWOTE#U&51AKn$2q>_BxIPuIQ79W#Je`#tvd} zC4;psraC&n?)mYw&a>1{(RIQN*GL0*Zv2Iziaz-boaia0Co^$&Y)4{Oarq_O{#{4d zEq$#Q`i9}P?+f*rA*ujkC$f)|3hm4_QV zhp(1GCqetrI#*TQ zLa&WMbXL+>EbetHK4R;PDA~Tv8&c__&EhqAV)qixb*d--rW@y5lg^r?ol6VmJz{`Y z5dR0|y6^wa+(1A=1w<7={@X$S|21=SGP1R|F?C}6-$~j3%m!5!S1TBxK|lhLKtOo^ z|F&uGXlZL|;A{l^?%=-_8C7fOscep+_&n8~WGA_w3uWvh8@WZHDQL9@ul35q(3 zsZ{C@ZaJJ(v7#*|8ktO6TC+>Dcl zNg=_b#%ZT2Zpie~jQlI1F^)`xQ#N3#`jlxZWZ}IX*-Q*^!PVS~s9GtOY1^|3cHh0> zQ9%(5lwnYY|8n{v~GIkRJ^q}Es+4^%T8T=1ux*|JtMWR|Rbr_{Gui6Xlm zyaSzeURFMa$CYcSYd<-j%{Pe`@s13+oV|g7GZ~;USMX!$(It`LOkCJV^k&CkFpSQ$ zSpZbPu4d9dC$bK5XZ_E^CvHu$S!Kvtn29B_^oEWl)uysEQ#5pT!;xi2b6$H>+B>Ar zw)?LKWk*`8iHN_E`D?kC>ipkrEZMxysrH)_=~s2X_vvSYV2T$;77ZK+SA%z#_PsVu za)x0L2@8b4Z;qaqyO`~(cH{TeAuN@)KXtvF(({AuwbQ$XKPTq|;s?Q|y7aE%`*gCO zy^v`BGN#pB4D}z)FJqV+-wZO^I}k0m)@r+w7;bff8ZnIF?^U z>E5i))0b({xt?72zyfP>G;j|njMl!q{lRY}I zUboqt-ceo$4;o+c@V=K=x#jIJc71}zYQf~P4>(W65UJs%5f0Q)yb4f}c-KJ`AcSR% z+WUYIgoah_v1M}EOKK!|ksj6S^yQV!!?*pY`PDkk@{k~sxo`{4M6DSAO1(v5EJ6ZC zuE0S}aF0t_v?jg}9Ri-PY`T)EP@xx#d!GZbcLcH4zo#|_^jjg>Gruw)GPgCU0ef;Q zfzl!pkYo;p(l$-VX$Xk)T4C0o6!V;1E~t_f(Fs0+rhwtC+Zvh40dqw>vv-#L2S zu9&A0S301_+c@@p`47Z!dQ3KP)UaLQDG}@%PDK0gEON+^-$sd4CE7Vea4cV1N|$RGo#5{j0L6(ffg za>CVsoj60z6+hsZ2CW>xLp`E;zlwtgYT#<*=R^HrvhN^k(CtqjFif~1p;K{NU&CC) z5S2t;P}`QGNuP2E49hfXN0sSd^=GF~_e-HnSSsC~ChpxwPXK<0n9EVzW7(k+d;&2= zjm@0H2j5E{(2Pal)>weU#raLA6^>9^Avs=zCe_WEpk8!e627cVwm&r01_CuyBXP;(3$ zJiy|wcZ>FmN7f6}X#exCKU$!DuGEapd$MjeP@ii~b-&N(?8M`~J>JK%4`VjcIgX(> zFCndUyK~ZD7Lw)MDj?wft-Z-j3-k&T2!x8+ID z!$sz&0p!Zw?#m~0|aC}k9WTuAuvP!RKom*58}PNKD4|D-{EZUlI06DQ#sI-6;_mw z(%24VrV-ep2j?1xTlrO&M%&%GKeSn!H7Ghfk{;af5q~oxK`?`K#ue;5azwmxO-uO_ z48>xTX0aL&rwJmpf0M`=@%Xq9phzKY0!X4U08AyqD{L7h_;afFxV$*Eg37Szyy z-HlA*@>GB9*Z4LS%K`3@tH{ue>l+vXKrw5Q6-)-S;dYf zU%eU2#8nDSaVnC*RZo;YVFckS3G-pxH|Ty z>|IJM`iIw>;B?dmev-BMuM%susDd-xa8!296>=sg55~xb z#OY6hUCfFeH9BL*3tN__?5C>K1i_e5s|E-pjp`VqEU3K?a(YN4|903I0uDmz zU{x5Smu{8OMIw`X-FM z&D3mpK-G}n)zSYe=;)~&lv)hxssHj7Lr_pUcU7|+C45bAS{Mb27lCOuTUrEvD3Jm` zj+dPiNMDuLl@_b@%|T|T<)K$K^)M-5tjg$n%l%P^vg7&gKKMcQOTXp{KQ%Sh^JnR* zymL@Y)nIrLwHORc>fp8IV|1W_sXX~1gl4+jRMQ)Ha%SD?8TR;6BGQ@Hi~X$WMRZFE zL+zN1^9h)0M-NQz`qqyAi*OD_w^E)9WPpFT$}cg4@3V^a%B#1O9sjwp%-q9{_lRww zq{l<}KuzJ#duQ?`$ zX>Gntzxw10IGqNpvHkoj@Mj2JK@P(Kf6F%?y1l!2rUoHImktgi-g|he@|4h5;Y#MB zp;ly1k?HX%gEsWHS-ce>`1k{``3ZVtkQCn*I1w+d;-UNkLUaCT1WHQ>ab*{V8txwW zL$-;tS(q9mq9CGkS^8G0=YD3--UiG`LsVoYTMn0CvCM8rJ_Qgqr=o2&(*lBj^cLai-Kf zYStD|my=wh@CJy{7)jYbUeJ0GGGP+NxKfa}kLlU*^);f^fp@(Hock$HThYQyZ1JxJ zOIv(A;Lp3GiCjqPE?+ZPh?ZRK%}oGH&9FT{52m#5HReV+LUSyxpzZ5ny{^D@7J4|a z%D}$ZukFF?Y-i^mDDWLuAs{+d?tq(v8hqeBkQmJ6=DDl#-mIb1@JH7<$etew_8y~~`Y;b@g!C08cE?o~Z zC>fswI46NynIHo$erSCV2iy&oK6$~IFV@yv3p2c=0gy9Z?tcO-G7-nTPXqyW&OVXQ z1v8XbefV64gWs#n*wo--==2`U;;txs`sR|^sPE&cB`*p<~S{h4!t9W zuvY1DlH2}d-GEDfL2(Iv1rl*%tn60js|ZkL!-K_K>tVBwB6c9aVGv}Uj_ktk1!tI^ zQ)A>z=Db7Qs9Ut=aE{}8T4IobI%(Gg0V&fy;wIwQb;Tc5jkv`(ufCNN2<8wgw#spoL|-xyyjM!B zT%Z&|jyK9dh+Dr^+QstTBaaxfX6&Qr zK97@PoG!9~n%Y8ibdG&k6fvwEA;yTgKwT_`!VD+3>!Cw|NP`l5te}ETGro^y=@SY^ zs2I}HaO$iccWiibt6&3}@fo%xzH2jNuba>{$0F)N?nJkAGD1(1ff=0rDAVGV`Llt6tV)6dv(bL}3I#}v_d;mO>DvjZpWpmBe8nIBdebC!WD3Um+Jp+LD>c;ip zH)-c_Km{VF@mnB)8wxp{T+;x30Ytq`t2@W%`gNrpF&q2(%sD7Tjw(>13g$?AOu+?lqKrp1zAYbsEGRFDqrNhl=6(f^9h7d_Ud%1rsr zoTY$Zc-EH<9@Q6puzz)ye4O7W412W9985L;>*@6Uf!?y{l0aEgXD4Qo7(FTr&{8h_ zln@!1J|gkC!y6JwAE_vhauyXplUF8>V4`$N4wV#Du}3@f)VScL0ei$r)tqnpTu~k) zFN@iC#sQ0B$Rki~RCLEmEs8Kpy(nSt7ixo*{FLvNK>ETl#fEZ58|p0El?nJaE?YPa1pS9aMU=BrAvsw9yHRRT$dI&znOqqUT*BU| z69gs^#?E3O+@1+_!Uk+6K&ein1T*REAZw6-HgdhbGGxIWaL!YMVj3SKU&0ts6tx6O zNy53T^cilRJ|JdPP{T05eh@!cCv_%^TgF7bPLc4}1sTe+<1kfHIZ=^kM!R+SnSLI1 zwD|;IXo8q=TzRvStAy0%Gng-^WAb&n+ThB)&N>@(;9)dHj+*vb>DGCTxnPi9d8}=t zay-6_ucUKax#xD!s=ql=#CAj2&0yMT?gU(GxN~BtGi?C|0-M6g6)1l0x-u-fff0VZ z$UfYh?K+CNxwX*QP~7lEiDzr(Gqh)mncyd#l38gPi7Y#t_u8Arogr$rHSjzrGvCon zBy{rAs^`^Y%I)NGq4xD-f zwl>k$+yiuIQH)z70>BsQJ+!rOiOdW)Q<|%0pLMPX|L*#muGL*z2Q{@kyRYcHB5iO@ ziELh|UmAFtJE<}_bJ%V6)C(pDA7v2XQP|K2s_(;6;bC)=}JssM2oMF{RyQMxl%lWo=7 z>OLqOFwbhvlF+SHEczEz_u*eJgym(@L#utO(8QGe!>7plRxkC!y;LSXf!r;K)>N!OUs2OqBD+0dLw^t4LSOE4MP6D}^)Ru(-y=CUN^T?7`WZA` z#>5@b^0U06bKU!g!zQ;*2HsLZX_w1$1yQShWB>>}iZEP`@_FbHjmWMmR}jOA;S%{x z{Q<3}JGg>UjqHIo3gBE) zeIT^Uea3#?e@stw@l;yZzN*B1XE@1z9hHW2&AcPoM{m(hhe(qF2gokbiOS@ zl*T8RMi+b$qWdy;qWJsB@(vxn>D9S9i4a0e9du<1p{bGEh8|$<+(Wo60e19SQfeJ6a*6YEB}{eS((ZqcaIms%l9t@qKF17%1^bxS;3l z#DsQ2+1CMC$eI>D$<=CQEGWJTCzL79Zz`pqnd}p8iM-;*RT;%{_E62p)-iJVORdGo zSS;bPwvK*TL52hbPB3f@_$cpmOOnEVy8*1OV`CVj2Liz1F`!p#J|pRankfw1#G$iQ zM;x5Rr0E7A;L%F;y4_(X?orW(2Dr&k%MNK4*?RA7qAF-#@b3iDcOKC~IsS^<^Fg%R zi|^%s0RG;{tD=BmTCWzRaZRDx5WmPo*dVrnpq1_jHc@SCHC>CnW6$fhT^u<8P3na{ z!x0*+E}RGOS7>1=C#8tD=-G25i7~62v8E_auw$|1z3{x>`nP8h*qNs4%37UJlMChlOoshi#*h6qJceo&3DOd>o?vF!(>^o~>PiA^oh*qpWbQER4(2{6PE`hZ@rGkA>M5$~`spc!4WnfnUId=lQxi@r5b<7+2lG^9Bi3kaIX< zaY|PWs3Z_bApmS}uy*><`sBF)nyaeMSc%KZ(N*pu;;nUPfU1TOxpDdYpdbEA@gYAb?VoRF<}-o*T?`KZ&vd;>=k zqP^%sTsT(+w8W1T6F1lK>ZE4$7z3j(8ee)R2>d(^8Q#*IyTasy(a6sNI&Q681zZc- z{2B6LqkL`Glt|AY!iv7_GL`yat~jER6;kfRYbCl4={w;nwMlI6(P})D1F-G~lS^=85Q#>rnlDIu zp9*?`zU8oDE@~O`c@j9F9_Yy-fss)}Lfp*e}B=LcJ7T6d_D&*KAWP=Uk zJfFy%{53n+9=V33dP$PlU`v1^BnzsAmXg)JF z?Bm?hY58N;9*yU1V}N9J!hUr!rVVuR`sjZn>( zImr^ql`$qL$%?9q5M7N)9~HRex6!H;OJOV1N}xa2R7;AgpD9f#6JZoe6~r~B3`r&z zNtKZrI6mn5hpQ|K#E zJ z?^VhEkwOMZo}k8ry8?p zN`UaVF=GWQXP&O#>^tk{e}tYQK7o&#C4N9DNl*kWuXLgqa|bt16BIKdoD$H(xqvS` zISNTEnWkp6Ot;hVm$UypY?g1EpfR+7PUGo@C5jkcx$8oI51L7|`{clQ1#b5Mm@D~q zyGHACtqoN@hV2EX_VdnrPY8AXSa*G~v%GzS+xE#|&@^qeL<3bP zI9D}mI1Z!@99_it*+F~%9m}Uc5lu2_uWI9Tcc^EenE^LO{WOf=WAE+AQ7{%SpQ3V9 z-iWaYZ_izGKR68x_D0sPMX>{%3|RpBYHbq`qmYJ<^c&8k<<WRx5$*;f33$5vO_ z-#Thc6unp6l>{Ucc1$TG#H3umIYp+Z^1#uhH@><&h-KvA&zdBaj)j&i`FLo+CIZg+ zv%TIGM?#ZU*fN->McKRT8XfF2HL_Et(Wc83oNn$hvEynwGW~GUb!2}r8^K-$ii^Ki z-HC?5^|PVwJy%#}A4vXOh_S^%!8}5f?3gTNnY%P%)j_VS*&lc$x}Z@Tkw$X7pyDVQ zRCXf7RC>vf+bUuR7s9C}-Ne{I9idnwP)y-S=n4 z1Ug=~a%HQzuWe7*|7rc$r63)~ox8uo=$}==_UrwM8tDX%q%p9LEaQWx48%QYyx~|U zE0Bw^21>hzA!#`dn)TL{pfx0=svCC2ZlZ9|7VdUHoEwqqkBA_r>C&{0YLl->N|zqT z7zmw_N`WS+8Uh)&m=l$KCfpCfdGtTb6!@I486riB)Y2ijx&l3)KcRW4;M*!hddT&6 zl@3Yy63jSu_p9b;IGJ+>rMUIB5Pmi52CZ8ovolF zEa*n89scQ4%**@8#)fAc(E46YD^{(@0O))1^3?;U-=%+8M z;SUxp2jV#P>A6jKS5 zP_M=>4?8#JzXnERPf}e+PdpDZQ?B!}o!gzj+L2!*m+spBT;Cp{Q>TQHU5bxO8sV}! zXhQTirafm2jiodQ^?ZqvvAC8v>-tC>wma>KmRqCb=&b5I%qK%Yo71y$#(9s%n@j*!2O9(H?7u_BE@osJP+Q!a=7`2pU;))EvF) z+8RHsU7UU3tDB{^+Y--Vp3G*JT3Ro*SQ;tpc&N_4>C@^qmZ66(=58!b2%XEBrlOl( zVgHm*t*#-aN%)WKNt8G@)3_%a0xb?NqW7p@gDY(-IEpg$8e!23SOoO)+l=d=BbY>`L}Ew^bnm1*h85cp{S zd~EKGy-B-$;38d&_%;Ua(nfWS+&7MWS3@Ariov_{^D_E9EaZw%6+GhBJYUM{akJww zdJb43^WEo(71NGyHGYi8^pG%EIX3~6y*>SVNx)-@B422O4>84Zs@JU$u!FQ@Bc$Cv z7t;(J?COY>_~OaF9qr3ZxnZv@<+`veOD#%nq>j4F_lL!HS@?09wkG1Fdd+{{mL zrLpzKT1#_>KTgu!1>FH~U>$n^zj<$+ZW#{7{^CWFd1F;^T8@I@;D+Nl+8$fS8k*Bh zPc6lAi_##`c>?3tRQovTl|3nz`K_#3Ik-dGs0XmL%$BOK%utqiGeRb#SD8nQOrx}iG*0JR zqN1=gwp%h9yW&N1TI=YSWR^Sc7SVgoMt`kj6DCQX3{{UR^xF|wqu?khq7Ikhz(xDe zI%uVNTioU&lu$oO$@2*mUv%aP(cspLk88m%p1$ni_Mtsqk5VtR1(aLDk{T-*Nw1z2 z`j9T+!D# zd`fKwPg&UA?+D7GC4{T|(zVnq1m?u8V-LxwG5Aug=XVhucHKJTm1a9P+8fEL*_T>@ zp(4M_MA!%Gy$NgBcOroUDM4>qJvd;xd>o>w*JA^ch(rYF)dk7EuMe;n!eBZNi02`& z|6q3pV8D+t1cG$S5US98jF3L z%V6q8p3vxg-+adcH#o_0hl?6XGk}!GiUp@tmthl~xJG%3goC*JWXO;WCfs0sQ1(r5 zGzCz%e%A010dbZm)hc4>AOWWpHU`&UA32i?6}D~7fu`HWbVLRH6-etR2KlEC|3lzD z-@DRl+v2Y;>)A(%OofnnPkRYz)oo#g-EbOM2^d^TbmNM zXr6Yw_F~@d9qHK)F^kBZr9giq({Y;k!667k51|;=RfM$GJhJ(wkKD^K=vP4AM5^K> zT%DP!RHpqCoULNk$KK)gE$Q#Zeu-eF_~Q#cs1>=9Lee~ZU&ZvUwbS;#k51MrtNY4G zuYcG?-xXSJ9@##922I+9?*K{;Uf1!LYQqQbdos;+q@v2;Nr%{=o@6G~lE#ZAGi1_K zcXy!n5HZ4U(EklxpM?V_7@z^*PHK}I>1>ad9; z873u=${{C%4(W>{;XEcy3=t-q2)J&!iAk^~scO;B#ovjH$Pw2^|;IvLo0<8U*EoYoQ|u~gq03s@dY8Wmh>R+z|E78NRnUR^>;3R%A_ z*J@8Lnpb}Upi;Cx2i&CU0Q*g!YiJ0nX9(6P zBQZ!JZOuTDNod$VopKx_U4<7^ z7_Hoflc&D)ALw%WbFq&}6P1>lzCLQ=GHxBP?cK`Fv@0jv^Un24H92YA#G5<7YR@Y zW!EB!)Qef}Kp0^XS}yMa+Vr6STaRxFi44>)yFPOeLfzBtMPiOVE95i8tV znh0+pECZmnW8ZYGo7ODYb%3Fm-fG)Kc0|agRvT?@^FyyP`YVZBA1c}RmCq%3-^R23 z{ad2S@A&^Lmvh5P%Jtl)!YVM-CXi`Zg`LH&_R`|r2EOg*7*yS>MwmJ`jFtVtm2GQnT2!&5{jp-B)I;K`~?uR z*$gjJy%m*%{-Zl=W{&^t^yiCi2`cRLRvZPT>+kN73bQMjP9f%Q-}v~k8qBSOmCZM+ zQ2Tgvpu z&ePq@f6Y&~gJpxYQ}=(ma;_-9)K4|O2+`35%WSXSZJP&1VrQ2jeEgs*aj_)JKCC$r^)Ed%I`gQIUD<*aW=R3xjg-ehIEdjS3$bX!Z5e%}oMKnDJQY=JTUA1$!o zHE7$7VI=RBnzRdEVGH%OF>BonAHQO=NIz;yV$>D#2tAo8R-$irJ2lb}d^h4`=(kDzO!f8Y+qS@sYp>$NP$i%GJL#(Um(B z0W<1JqXo<|+S@HMWvGzKe=UiVBcg0BwAK?p6vE%*Rob_)VxNs02(>qSoi}Pzs%XcR z)1jC5;!8=cjJjwtMbR27o<8b(Q%(M0d5NEvQFhTSWjIttB;aHE7_p2Ucfeu&c)J75 z#_8b39ks_bTFU^JU;z$RYHnV z0|j=q;`sG$6o9t=K~u2{dWfy9EuNkbJh@US7sW|%iSaTMw^)x5T`nq}RNS@hColr_ z#`l<>GB($3a3E<;(0_`6Xw5ZZ1vfU#G952lX!1W3YfshUvlC2I0+l66h03#X{xc>5 zZmb6Ir#wytp%xDtzEE{4C$gl1nvpBrQF~8&3{=%oghEww*a`3U!3wJ=X;^iwDmN(T zCX(0(Tc#gUds_fQ0fFv1;nX8zjyXrBpP0m#x9^Nws$jwxjf|p#<3W*|w}H{uM{I8< zl2}?X0y)A4tpVa)kKpb^9im}xkD@&n2x^{l*mBeOB-xE z;4XT$m^+ozG2yYl;ht6t@9lcV2%_-gfL70OaYZcIPhi-R(+vti#6Qigl0@52(C<1( z5~S$kaN=ySa65(cLhvu#_ds`GWKUNNTmmXZ!fjv`F~P|_-9)~5Qm{SdARN{ci`2G| zKw5W!TGo0u#oVk<`t!E}G#}J|0M@HVt2iE3pLwRASe>?>JSR5pK~oq)+`BVpRc*xa zd2LA+gUq!u<3PV*Z|;hD(7k`JN&bNYhoS)8=*yBmTu);p=d;M&jVH2tz#ZW}I1P16 z)SO-Lz95NCc$u9N$Ru^yRTisu%}JYw&UD5kwSelL%=XXl&XyR@KY3MNRU!;#>LE0l7SIu97B%3(d93ft4DQ!+DvN)00jSsGUDfzm8I#S$3%{O)Ed>7N z&Sne&N1X3e)C9Uup-OV}(qJV7Ve16O%AVd&G=Nm2vSNLG)#i4fgG$vn%^PlpySawE zax5PEF(^j-vIaT`5wexjAO0JSF*0n0Lu@>3?Czpd#DP9WWNbX-tur*IG9Bh?3MG_v z|M;HpPJOOCy48Z{N|z8iZt*rl)XMR7z=I{r{P7<{8_sBH=UugBr9W7;R8S*(1?M>s z7tIOvyXIW41xoHq1_s$}YTa12(;lIgK2A1#>U!=jWc1=brZn*mFp#64XiTlp0FL)l zhEQC4e<4b}h7H{ruC; z^l!{2I`MYnDkk;vYcmiPn5K6)Dh3ecj+%$1GwDnl>bfp=F%c%3q=npK;Ed^&Hs7oxw0IoR=2S$0cQFra|wHxb9(R>ZmeBWCG1u$Qp~XLs8N3MYY1%S;XNc4D$XpIG69xS>_N9PvEIP@NAf)XVHQiQrA65u=WKr${)(CT zmZ_3yl~=9KRZZKXjq@Hbg>hkqdtahy+2u^XmZ10p3Xoq*fZyy{@(`Z-kf!KzcW1(c zu4v0M#%7cSN2%&4Hu7Npp9V<5!11{<`LjbAK$$rzW3-E_L)VUH(HmoY|`t+yD*8@rhM~+)h6E%;( z*=xX!?bQ|ge5N&W?W-;|QYoX3ZHB}7c^7Z7?d>bms%mXOuHR?Vc+dF&Cro7A&2hG_ z1KkzdOpk?$Y+#*bsxwVFzWcYSk-B1!EM12%JYU%%m+lC)YQ7;OuViz&39A#a-aK9R zP-XOVeAvONzE~lOon=<-@=u65VK~Fc5iEw{-_c2}7A7Ftx({Kln*+0wO#>L*PI70r zSl<)`o31ch)jw3T`gd-xG!BCmH$P7uRjF;*9Ekpss_LSN zpYZc&s!<(XAtrF+Vl(7ufsn$%QzCyPO(qvgSzHp1X`Gj*tTG$LIin6pI6ifGNBjBW zm6D>VDf4J*jmZ6@)|}kQ$=rLvGGk@p z*b2%qril79m7-$eLPlLwCK{?(2{hCi=9x&5wZhbY9>tw;GhWJdDI$1e4@PKpF?b@u z#YMDe63S<3DI(pn2HZ+B^1;4X9`nq;67^&mN9tL(`3dmhq}txKv#&R9;Cd2oouaH0 zhBA@L>V0LDKnBaWJja&X^>=za>N+G$TLUf%3Q)$Ch1MLAu6lj@)X@pSw6Z<0AYhvI zW&XVzZlHFsXezV4Z<=aqiBF8vrWL`{<)yOgnD_C9C3zxBXGG!i4#;j27_9078=)zV zhS{U$Dmfz1Q?(i*Ae)&yV*(1v!wr+A6Ol;8x@Yo^U%la3PH2Y8j%5JjL^aImr+F}j zdcvslIM|h9`|`&R=fRO9Drm`4JO}OlZ9&l0yAk8k*2zUrezBo!HvImssM}oKMBF=X z+orCiAx>|8G9th?*L|)vwu0?P#%Xd;DuwexVkS8oMxB7l}3l#?S#ZaHDtvvatW>?E#vr` zyA_USF`Ksn(mHK>X;a$n-A*)H96qOTq<=LQVKqFRr^08q=V>~NDN_qi0{_$4W zi}yt{VOjsuYv)JZ{aR>qhf|r~VjB(xE7>-jwl1uoi{%3|KLVh`qM=A%Hdd>fs1{0= z!)IuYGInV$S=<0AY_{eJ7O%^XuT$K=zCqQNC|p8F(o})dki@@pO((D1X*Bk^VL8f zZ#QLJcrv!d*{*Toj9<+NO2!RNpyS_aDh#q&yt+;xCo@!C{eysS^63z}x|2|ROcVZO zL=BmMmR<>@Yv`2>-mD-1HuItx$(h~UU8W?ig z2m*-)#7i;laOADju=C$wk7;Ca05gY>N>;4&#JP!U4XYrM`jh0AO2>|S+{0x-_kT2w zA#rHZ*n&-;YLdynH2;F`tiTZ#L9V80XyPw{;^ZHlGsu|Wa~9lasBXL)t@nli3X%r> z>#hN97jrqIirrP7b7Q|+xXH#Xik5mpNThC92fL_)5U?za?TM^kf9<}63pf@IEg8o0 zZ`g)~il&pPHzF5(3}R@MnB{+!ZoB8y0jG!blrs8rHQfIjm)$&_!M9Ia+D5 z#emirg%-K5XnVn{T7ASDw#a3u+-+(`p9cTzc4GYaaJs6%9ah@8dbl5_2q{PPmmfho zyg7*rh!({pCv{I+S;0)B7_7o3LF5TJCmXah$mcR+l5&Ci=2qdhtV;6U5nh?mW5ARQ zGSER*;jS^)Si1VnSDXTqaFP@Km$)z{qQaM?F!xWI0diZ z%WJ2-W$&1JvMD<9(hDpp&*3Hc2uE!bK0kvKM;<1+ieux2(=q&?P-8=f=ofZD>{NLn z5K3g4tt|$1wtXA$9_dWD-zxXZW$=$|Tv-9dW^v;h=gRS|?YFsSIDq7K4w@3_A3V;_ z;`x`GmyNlRCx6l0B+3(8O@3A3 zSJ0|G$>65pQsG)o#}!t?bnmA3y?ltf{6U^)`uqG5Q6ZdiovNn^bhr*J#{ZlT?olb| z5=w|8=Viw0I~ggZ!S8OQg~4e-Rnb}CaTlx`FLhYdur1aaqs~wb3zw*$X5-ym$=fs) z7rj1Kw!O@!`b@H9*wn44bF~()wEtXX0B1VkS|7Ex#cF^$M`*OnTeqT-t*u}(g@bIM znOQVBBiEPu8#dj9nU6Kwsc=`@FMcn z`Ba9s>d^w_a=+)0Plh*>C51UJZgBA;@~A;=HRUNP%E6NtIIV{$>8!L-ABt(C&=gJz z>LgJ#)E1P|_mkc8ji1QTiZ#}9R#Bc5(jtD?WMmXnNa@f-NF_w&MkT|W%2h?HO-ia)DlPpq5&m86D`ElJK8B6j_$}IQ zKK|5gjw8M?wy8HMa-!MD!zIE4<4RT=(@+kkzJhau!(f&8UuVq7%D2`?)kl)?>e<8r zTOB+x0`i(C=`Q=y#`*8^lc-1VS@eQuI292Jpv9HaRY5|(dn^N@M)_)bfrs>X%hczv zB(XEp`YV)$o&8+_NYw>V^Rz9MPk6IWk3^Efj66~`f$S)+-4P`_h4So3C2XrOLv|j{ z$YLkxWvyv3V)|KOdW`+&#LYUNYNDs8)c5k>hpo!Rs-xri{iNex`h}t^Qe?|iX z*wg;Wr#%WYW5$>knmKGE#}Se)Bn3qkPLL0cIjtKm)!0UyrMJQy?1B1#mCUhA+NvF? zC&`L$tuY^$qpAvIi4Lr>hYc-JcW0316a0wEGva{H8MB`cfSsc5z1Ss091>x~=KgkV z7q2AJlj65uM=T(ufR!A?E!MRZlEZ~kv^9NT0SRMpT*v1fQsRidg3%IYLG5Sepl1f{ zn6QV+FhJ1;I=;64?92(og*32t5^n%XFmlPvlV=y@v**f+!FVDK?-c5%Wrf`_>+hOK zj1ETyFzY?V0qxoW?UXbS8$c9FU=810Qbrdi0uO#-LG;Z7w1`DLISKN1Y(kdY!G@D^ zvt#ktdm|d~kh)p7IZl z$0PpbGTfmstBoFTe&){h#L-5~4%d6+A^P}oKNLcGd(?joLC5?0&Y8fcQoTs1xUNp1 zLfL}CQT**=Ly$5&tD(E!yXlG4P~TSDtz1t#4@E{cSIs^rlLG#642OnX7ONWn6gZEP zR3B?EYoCl4%o{aQFVC{f@}Z5$bt339m4@-ShJh=F zg4t{XbtIn_*Q6wgbHgyKVcAM00F{K9j0hisq=^(7_@9CdT&gO)^tCbYQE;hXKY*)=v zZL&H^&7%y2&f*68GBNLnj^Ik;4hXUSWs3U~IFRZxc!-8MaV+E1%~SC-TUP7Z;8q4$ z!2&`wcMuiVK!8Zs24HYSjH{}k4o9@Ql$3SIcAS)dE<7fSbNu6{10byV zm)81NxqQtU1jIkXQdyKm#NUndA+hV*rC?9b+nYNUol2kL6koLs0t66W$y-e9)SJMj zmCYYTL#_P+wTq2 zP+W`BCmg6E=p-X&{Tmic_Coz`@_ zFRV7>YlXh0u(>O%!li!>PqAkz>5j6z?Lh`6vOWW%-yGQ>;?z z%@nNe<^-0^M*hl1u_d3W%hRGk#~jCm zv`qPNy900_iS)vB^A>S#p)}*(XS4NxlP_C(xP+fP?*;!=&ZF&z{ke{{`N;1k`}YzH zC%d_>*TU*%c*Ru1(-kaOZo~q_(*q_*dn@f0J+M6y#uMnTbwIl1!k>Wzk+=!amwh4& z<)4E6)r}_g)(gAUBTg_y@opLU)=2tJkDAuOgHJSe0|2O(jl~)e?^tM^jgz7 zjt7KF2uV`9B6>GZ{zbu>s9a&rFh+BsIFGHx_}pdcUvdKG-*W8*O++-ru0X!)kIt_U zKpRLX+nXW2p|6n|qs{@~w|S_qn0>JaYfqxCTMcAHmXWEH|BJJ84ALdsvUHtOwr$(C zZQDL&+qP}nwr!uXZM$mf_Vjdg-?$SobHDFzM&`erEBE`XwYCD1LvYtApb(^vPOV<7 zaN`j#E^!|+>z|I-B}$o-KmIgL7({tivW`D9#Q0m0r@3Qd8e~a?i=v)_gP=G+1@PG8 z=#Zr)VBhs! zmT?X3Dc+I<9xHmO2evJ07f7+9mX9yekKf8}Qwb6pi4FQYo9}^MXh{TX{|DcEXKZVw z`0TpP<9!BG1QzDL44+pZ9ZIxC`07|t_RgB_0r9M%EGaxV_wUf2;sPPl+j^zP*<&z%?bQHR`z zF&c4BUi`DgDq}um73l}Z;raJ*9H#$?Q*;zo9ZLrOj2V=UHj)2hEq{4<7w{2A2fI1_JA#@W`(Z<9hV|6zpOed z+};M~7`@7G<^aOP!;WL5rM^;OO?OSLUW;wvvZIFcc{5O(RqT<2H6C>EB| zX&xQN2+3W%az%1rb>T1iE}|zX6e-O@w(`hS2@LybuBQ-#V7%dEOf##MeDya41M~vz zG}hK$Duvf>oTVxmYd{-u3AW z@~E@w+b!Q%_q_(_!~jY#WCn{Q-q(S)lBx(aNCg8sw+*^M*B%S%tpgdGN9Jj5Ys|dm z0)H(nxt5zL#Y$LY`p;ow4PdbEA@#!m2JU~JOigny++dMFzIBzGRo`S6`!z7hZ?b86 z`N;9D+#{#pH3)m7LV&zOr%_B?9XY!n2T(%gATR?vX7)f4HE9DxJR%&YCs1@anW5WWovF8C9CkV&J%8zYPK15q;~w+h4ZOI%=P&hrt{P?LbXz`0`JCfe zuI@>$>_yw5w1Chg=apO!NaAQ~`6_n7UeKv>W4@F2f8=(Qqub7Wt#xQ*tnS;8nl8Y9 zAFu8^GJMh61q>03MC4;s4gm*28l2eT_bIMIwLY8m>^fDLdF;YCHG~aUnoYKMAC3H7 zW&dFQwRQpKCiJ?$w`X#9*t1x^)S=;R81<8qo9Vw%G)4dE|9+R`N^MhtS!yoM zcLNQrz!HufLBeTo8(rydu&7H-!4NL&a4`<8m>>9W0v3q-?`E93p(ga^4j>8gpC9<| zF~AFdp%irYfhAQ$cFvOP0zQ&XhVc0kwvo=Dp+>r7^TLn-?MCPy@Lx0be~154jV&_r z7Q9OT1O8KMWIH*_%_@8T(tc5+V?yXPhanw9UK?Bh+FHpX(IEYS|F*5_KuBH$O+J53 zbHwEJ^ad3Fz<*RH-9y^aKky$1CKJ|TAB$xip)>x)EFYUZtc}ZVQo88{)y+(M-Vgj2 zj4>@Q`WUix=RN5gUGXz-CW6`}fdI8^gxn?=llwd)L_o~jRw25z$kmeEh64i&M{Qf= z{AVbYA;jr&5W+%ug*6o{{XW~^r6kCJZyrgGe*hXG1+wV_B-gkj<>81!Bsjou1$eRP z6|KAyiW2&V8PYth-t;iXpqjDFV=XJgQD9ZzAk9RAEseiK0=JFhh`%xB8@7?A8(gPvK?yo0Ug?=(@df>NFT8m*wU{@LMBs4oO>nZhl(-e zAjEFeChlYW&@)N|%?t1<^}G}hf`mq69O?$q$KTa3DCAW@nusomLMjert>s7o#_A^W z&SQhrvT2=uor&_T67^yvl1c~zgb)xRIIY>L@uJ{vd8u$qBDeLez3JO|0;5cQ3+jvQ zRAk43*R=|k;OP&cOR4>v;k(^2ROr)*jz%d~r9N(B)Z;$NF~ zV>CbLOgvyrUmYQxC9*?FK7NZ@_0aPrSJV=4w=Yr0;h@jMhFWyx4$>gNUJ<{}+ z(y+dLI&?Q>r)U4Tf7T6%4GIyUZGo)s2U%atf@0LLt#^)Gt9l02Ahw^;vh`P!`VP=w zVPD&jm|@^N72`wt7t0i2%1jna?7r^_UfOo=oc#%oCcJqC*6QKU($(%=u}J`ooYl8w zb2V>e4sdwmCh1&!|7FTNWwgL5voJW+hHFB|>b=3$)B0*-TlEFnD)kN2Vi)YmBUC_7 zsT?dVgh#vF7($q8BUsd(<|$apm^o;I`ir-6;h)A0dZ5(d?oZsr#82GBzqx{9`qwL{ z{~SE$lpw2;T42uYRH%GU)#ZE$w6ASiO)Dpggd3L`kaq!H zcy13iG|iEYg8l5ixRoT7S@?^(z{796zBY?58p0KS<%9c!?v-4FanyFGnj}>*V}Yy` zly(aZ2Ws=InLrUb23FYYVNVMGCP)Jr8J8ms)6xf53a3P;k-D z1FPEK0#l66D6Iw6r8PI1dBNwU1#1pA?5q^I`+tUrM?Ld!2>JkWSP6QL!6o&&hwuW} zwk?5mtC1@2nDhk%5{X;W$@`9j#)F7bGsO0GF>xd6scU&z{KdiB0J^sdv2N-7LK%kA zp!`hjG>Et~gMHCr55xHsx{n}S%DEoOc(VgNe}v8+@>kRm*WsUYMVi)evP}ZiujPIc zgzynz4Di251__cNg|xd2GKAeGV@N;I6MD~7ig>E>>D?)kY_EdDK<2H2Q8{L){W8%8xSjWZWe}N^SzEurJ(hHbdG|Z zG8xDOmu%-{e3%Cg<16sImis=$7*`sRLY!<2nHknq@39+xTT85IIJmqe(o6&R^2aZ1 zfnxYX8 z`T}V7U);81Bx+nV=77&*KXb=ww@Gm>HiLF$&xjmk4)#WF56e z*&vI*-CZJs|^IumjSM1rk0O~qV47@X3R>@0+WR` zDO2V%iY~UFfx_mnvzgs;UBQ5$1nANB$8-G5XWOP;C)+K|zYXQ@o*N<<&c+XloWQg>pq7>~}t z{Cdg$+^nN_Q5auE9dk0$HpBDmjEftQtz(mLVxAV>kdPp2Wmom6NEK9Jk~Mr=cQRbJ zV@`-*ZgfX*%p{|joheEpoo}8jq7f!HC2Ud{nn=eXX%a7590!q5rFLRuyk>w{B$U6?&6RpBO-0cB-C zl%{h~KIen`gv2C33o&KlPBTQoNFFI6XeRY{SE*-K=?b=Ao+HYnKI(Kd6iqKsKBe-= z;}8EH6-+^r6o(DvZ$IW9q@OejH;_XKZLnOWBFC0HVJsHwcu21T%;?jUxn>YcY?-Gcfy}&L%5=0jbf@y87Lu}Ati;cUNGvy zbVDVDa=xS_nWEY)evIin!g@I>I)1hb*aFnk;CRxXUG}oQh+B{sJh7GldXc3ydV(h3 zdI07M>X$3rh6}go&igc`kJG!1t`@i6Jbc&fX27w|Hqf34*9B)bZF>Qah^XJOj zG2*2B%E%F6_IWf;;Qce_%&iywQ=o?jtD_(2FC7=8*63}Nt5Vj?hs`-BO#s2j;a`4G zo0_b><9Zt=b2TpEw|pBMI@ch)9jaHe&^T%bz0e{=)^txVi{TyBsI6UNwdY|SVJ@ss z*!)kA+C8in?JY7rfY^AdY`R(Ucpn*8wyhR4yOGzT(V{GiQ^=|?OqV*)*a#!bPuer5 zz(y*MO96;^2es0CUs($dx6nOobmiyVjSgztuMB-0QsLgu%^uL08Q-g%U@9_y zT6?n9AHC2deuUK{`#c?+E}b>jGqRXP@^HvcAaxl1I;{|`%U!6!NYOtuale2Mh!6kl|E(>Rc!^F zyYz7q|Muj*>vOq((0_ikw!e14fNqY2Rc_VTM=D{+q_%TRaThdYj2pbe59a5OIPpj) zmU{b1Z6oa1qH~)T2+&@r;;s`CBgycdbV1|k+40}Q+M>1NYT+0-6E1uLZgd;RIlF{e znsw36uR_iMbE4eWr6U481^Y{k2tE(IlMUP;2QS1gAg5W8`laSNOyl^-{0G_<8QBV$ z3ZcwdRYPPwkb*cxU6_bHku3^ON~#d%SE)DTi4dg48QKX4fX&!77NCVUbo{yY3)Cpp zm^6$&JwF-+MeUXQUcQtRA_b#EmAAMs)qp8{)iQ^;U%!T>G=-|tY8#D$wp%eozJjJ~ zvA9WcWn=|}0xaIZ8RH7^cfa;Il{EQJbTfh$7iyjNZ$Ls;ffMjE~WPA#SBHcrE{e~JaO&w^k0K{<>z+l?^Ewc}Hg$6dkv2QFoJT;`Y3<5wn#;WYnuRSx9aA3V6{#O~>PNC6i@PbtBxEyBj zxjivEQXz0aTDb>%qv+MG*HFXr;{sZBCXZq!Hh-2wSa^9$d86azVA=c3nh}31VyJc7 zL@m97QTRd-Qr?262-~D;Vt}?G5}oPa9T4F3j%`wUT0xjqW`u_Y)>Pc&&U1Z;ge<15HrM8Ilk7slFG38vskum+IR z1;|ho_Xn1bU|7vl@r0>G^rgtM8$|@M6m{sqXB-XQxpipS!s?ENMeh|*+((J{2|{t5 zmk6uek$UdWipTd{vq-8WZyVwy6ZGd-FpZZY7bCnysLsoSAzSMupfgHs-=Km25K=>x z4?zhj+A%V0@mWAGFJvf8q&G^;fiNfawkGG|ZNVxJ1&`(mQ6AiBj5}F;8A^B&uD^^A ziukQFw+_-ddKc7!il3WG)Q3;G$Y|lN`QJc9nhGby0)zs~vr&=K+s|#I;^R?Npkt)} zHX_`Asrdl>**F!C^k%S4&HKi1!oPoXyeuN*@J1Bqi5lOLV}DQ25$BH68B7tKsIM@e z@|aMYU%t+nU_2dcRfu<5esnfw^?LQyG0zt%vVt}gAq+B(E=Eos8OA!)R>D9n$g2Bv z7{`rAQllulHJ2bZ!tcrWc8CcjHWYn^eIyHui&Jicb+Dy{G?LAjIa&Ist;8~GK_&rd zl{T{+G|SoT46w!RdTMH=Pz2UzBJosApEfJLSqE~h+FJCX!lh+o3*ydq zF8{H`96kr#g-RjPnoO?}*?H;P&vnzY>CjlAm~47S9b$Wwl;G)W0xKC0%}h1BgL3R< zlC>b4ipkNans6zWbt$e1F!8!7TtXpz+QC*iIKUnwt$KE@ZVLO7M3i}^W~-RVzMT0| z$>HA4`FuS1xG3!2qix(XEkL1I*&r6;x(21tZ9*+(V2BfNszzr%f$=I)=eut6vbnp+ z65p`IvDuvKwt;R}k5h<%dA7fQE51l@nRQt*V4*CY-pc0KUMYsUde?b*v>KJYCVO4y zl*nEw5bp~5(BX{DH&=(93Z5il#mv3`YgUY)SW?WQwWb$NTc&u)#8s0X`9bdgN+P;_ z*`2J9Lpq_Pq{eYL{b0f*Ilm; zVeaJW@%p|;fGYP0z>_l2>||!lo(GtjvHMmP*W$(Lb-{LqsU9NL(`abA^mo;-?p~#f zLU&Hs6+Zvm@|sBlA`Jd;YFcS;SnyieU7vMnvh+y~oB05x8z;}IY?W?+SXSP6^Wycl#_Hu=aIwEB;@7P+Q z&q&M{I895VoWz+V=GL;lWp<-)?QMXZnFx5rMzbuR+D*sbQzf^F(+UFEzFu*2I25jGEMYp22AZ1kRL+|U)gZyF}mC2w=Bf}9mj7!!gt)aGVM(sdF6KXNa!uqxr#kQ~-&QP@|g z2;FqJkFbN?OI=efpT#o;oK~e$l;c_wz*E57D9M-gCK<<5<`o1mK>Y}epT&*+bll!XjD_*xLrhdvvGHjR$t%D zqioK-OgmXyd)aYfJXo$EF4u;X2yQ!7lYWgpicN(b>feI*Gz7c!e~tWY;+Bon+V#YN z#ri=%S1{h9FPnlGFJMTxOr||n7p<2h_-O?T2px}i@@t2ee`5Mi8Yh}lX@yK?Oed%r2-t0mQ zLKp+cdTZ%iZ2F3l5rP5)gYe?XeTxN?$M|5ik`?J?%ETo&-9sR7v)F%zGvdxv$bG(6 zCwhflR_toavbJ|#6?IG#lu}?K&&DNGbG|a9htPKrrTmU8_-?YZ@pqtF`ZuA%!_w^q zBhk#QSg-zmDOhUO%@(=&P1M4YO|nBq17&7+t-CJP-S%h!4%bK`Y)FlVMgF#VldGv` z>4ANaVkULGG|5ebj7c>BSA$U-kn4`v9@k+W&+>#*Vo0oMWnK{R_>G0XZ{!Ysq#uI= zcrIsBO#KsS+4MBWu(x(>E_7*KNiq!A07j-Z89Lm_7t(Np8MG^J->K<(Tt9U0rrvp@BCJ!i8kU{$R6{0yZGjPoO zQI1)|1S*(yw2n(}U%Y7OCFPU_tLcFOsMOqqZth<&yr!1QsES$>#f!pRus!^+0%P(N zndeyHIbU+8&*q;+YE>oh98l(hz*;(YhOVIwag-8M#GTATQcVE|!e-SQg)ZS?5Pp(j z8~gppTCE!V>OiAUj+7rTIILa#W;BoC?+ab7Z=qNMA$nl9IbBY880O(7wBDk=1WA|^ z&#L~Yy&th}w2HM+JVk7=oI&K-0%MpNtFvBRX}Mf^rhARZ{BY(x2_Qxz_S6flW7Zx!!C zTXD7kuwH6rB-+KGyrxhX0Al}8A6ERF`Xf$$oH|N; z5EIO!TJ^ObIjDv23cvMEN?VM!P$p#|S5}`oWegN`(|fZ<95w|<6O2?{s|H5sS$1E( zKDQ*hTyIBRZgGFE{;6V&c2VCkx(}a8)OXdo19uB;-y#Cy$3Rt7u3C~UkE%V-`h9d9 z*qjK?fh{%&-Uai}j|iA%#(zGlMQiUb)=OBG0w0fKIb;}l^?-4%d%lMUNHl=GhaYAb zW>)HmBG4B+>$?R{ssyamz`o#t@EPu#?+CnQjHK#};+=>ZMWOY)1@v){C@>#%1J?!= z6%hO@l(AQ=hOZ6;f;s+9rL@7kyq%gGl`_qM+Fty)Z`?7eHi+jwr5)JI4ZtCXdfY2< zR^(9Waba&dx1b@e%APK{^eF zJ8>hEptpX6kZ+w?-X;MF_2&py&x!*8C+5^VgK$Hnp2~Dz)Q@Uxt?zq6MFO@1 zTjL7<0PBz^3YC-@)TDuM6P{E|rJ;eh9j3}d`9jt>V*_%FVMz~>&Ar9q#qgs+GrsL8X6K1Bw>=XfAX6}&8FcWg&T--4yUybJGwZf%s z3FL>O)~!+~VHHFFb~v%0a0*_xqOW2sV$yY>Wdb@wfhfJk3Dsr)EcgYilS8atFwJ^+ezQ#sYHY#Zp9E7NrG;%$sURiaF%hVFsffURD(|GVPe=lwucf6q zb_oikVb3qeTuHMi8^ zU1%&icqMD%9Giw6{x|2~;+x2H=Ak72F%+oPx2WuZ|IYYxSomBSDpkt3K$k(q44}ud z?I~*iwb{c5pj+cXds~MhVz)Ru{NlGAaG5&{KgFcKQkuLFbPwYkpKJEmx$w;H!tO$g zu0DoEm6mR*syNzlQda)^9yA(6ORtx|sJ_u#kj|u`h>k>~tch`^I9-Cip1UJ+Acd<+ zdo<=giNifJBdH1KTgMOe4U}Z@hMExE?_Auqpv!TPw-``Kw^B=+(SUPdE&xrvc4gC% zt5pmE<(HD*z^77>Z#b+;L9<74=tB09C1s4$JXHy!pk*y9wR846ot&Ou!c0Q{1Y4Fz z)%?zPzBpNuh&}v)b$V#D_RU#%56p~!635KFcTp*29>IHLgTV>J%%;$!+(bymeAm0f z6oD^;ezIamJD5b6E11(hnB-4^y(O!dl1fkONryCl>g2ast|l-gMVTca&rCfpL)tof zvxftR>B;NEP<@b~_s$|}aV49XnpsA{MQWuj-0CtU@B4}TJH6r*1@VZ*dInK4BJ1=r zY)xRU%l51BE4AKv&;JCx;qo~tjebtnpb-A;?+Vs``CU<@_7hMz`VYW6@kp$L?(U%7 z!6a!Cee73)8Uc$%#=!x({RN5ZN^4vPb};r&N!4rl)DRI}n4>G+u+w*WdpSo)$YN51 za2mG^Qx+EXr%Z|h&yoKI0lOJCPJGre5}mRq|&VwT^qA z*Z%Zm`C^8$;{4fL3iFWB5TK$$^Ge~gp|&*u8w3ynO0(fvuxZ4!IFmzRF60Z9g3z7k zU=#aTb7fJL#WSNaJ$HUs|8r1&F$Cf87Jo_LYN;X=rJwHzsofuU_Ap*8PC!V!A@}i~ zx(Z5JnpkT!UW#2`l9s%%wx$F%q2BGuI5hdg`&<<^Ti~(&&UPzzi72WI9>?Nih>M?x z8}eKd?+H7g1V(5e>QGiyr0LV$WEl^M5;HnxOYx$K?ae4&X(+!@etgkm{3OEjG>htqnKn4qE!| zd=Q}QWrW|rkyIl$t8F`cNR!*yZy`4JS~Yn#$99@*zlea`i=AnWa_B5xksZJ|_opVW zFtl}>f&d~XQ9p;NZoqh3M|cryrf{tGhtF(3ZbyI2mh-@4rW--P4Kl|_MsCjfC^xfT zwmZG|Lu8K7fz_z&{B#&1)z?lx-fTP|Su3$;sO9bv`jw{rmp<$Y6D}zhs`f7X8y-DZ z=szq2@V~pP7mWhMea(Nb4@zb`u-npN*PPP@%!FHS&Yt4AS&u?h(?^HEz>UI*GW5E_UpeTy%z;fXeLH_SGqLveP;ipjZWr;moR1;FvmFvzw9NH0b|G# zlqfR6Vu@#xW-X1lYaDU__M9?PwO%maEpQ9qFJEf$r0zPkxE3?{XG|y(o@a{P*Hz%7N zRjeN7XCi7F%J=Akh{24p11%;YkZF7UrlgGT>`#65g<(Q|=I|a3;z;#0V-}0CJfHPs z9BLdz*L<7%gU)nv5gF#n!5ML58}Y<)a5JsDV1vf&Wc|^+i^Lr+kZ31koOHhtE0*f& zzk-Lp*cza~g%c5oTsf!2Y$;YhX3S+$%V0GpprQq(oc&|Ugn|SVgNRe0S>78>@_bRW ztr&JBtdmgV4&aMXtPW9F{KaSK&WDCPA)>Rgk;%!f5~CE^@Y`7oeG=Tfw^OaQ+D@6s zB)BdK-w=y_kaB<4twX6_WnaMb;&z-_1~v0-DN%~-!EE{J282HDl%X68*{IWSOKi|s zb~=K2fnSo==9HWXH@?#ie444 z+JZhWOD=mNp4V(WZ5t# zPa}T(W6-pj3irWZvF7R96>Z}CTTIhJ6JEhTU#oerTl&IOlEI%pNf>E|UzyqX4@3=) z*kS=qM|t0J@B1L5Fc21mOQYi=wL|Ay&Di&Us%lE_Jc}j0Bl34nbL|#|#^ISF?1(=i z9pKsZ9eFLULudMzCxOe})Wn2!le4LyGRh~AAyH7G-n+TMvYe~#7Fbo$lb=dvvZh}( zr9`iH*u6n#Y_4}+pFJ$G(POf=gCvwxpvGZ@^7S4xp2w0uv#3gJ8a%x-4ky;BMn-NJOKTQPZ`|?4}_@TQYO;d*2gI4zz?qu+-fkA0Q@_7*a_Ta^68*37J zv@I#WSG7o!cA@6N!WuIq)dHJ~_Ze~Z=R`O0E@}S63@tDAlkS{xbhlkwV|Lh!E>=ZW z!z1tie3kP+3J@v$c(oYN{_R&e+yCWNZe_F1hVXTzOTP~IbkQ%J{@|`nw26bHDGtQe ztQwy&K`NMhqUK8lk)ODz`r!S}Ehy1!$!_Hf87@S8oW(d}>*_86m}YhNVy8U&`u^-Q z8Pp60O1!2#hHo9Ub9~xS(#WMuY6Rs?`lj566 z6gOk{CYC2vkeY_XXfB@LS}L`l(*g=Y5kIk3FDK%^Ttq>JDhv>z?pzxy+o>EBa9CI$ zDmXXdTuJ6fmpr$aDFSN3Znt8qX|i}^b!s&z5AcfB;wPE%8@cRBNW0wr0=4SlRu zE20tXOptTPP3+>J5e6b|gg@WeZv`}18fEq&Z+Am&Fg+uvq)($(J?cNqT3#S_d6A}N z@T3mFOPCs9)3|K-;)U=kz$Fk;>JtL7VgIOGi2A8pFbFt2aV2Y`%4T;fpCm{Mi@k^N zq$kyyMo&uLP$<9iUH#M?A^cg2ZEIFbzht*3)J)If%r615SYb#N!&W;uoG)A&F*Rz( zRNlf>82&5;O}+*n)h00~0PiuoOrvl|zn&MHxMN6Y*j*Ol0NvzvGz_=vx_H?4`^;Dz zhgrS+p)h1UQ5fv6uy7N<3Tu>G*v;*wU4DqAA)hKr(}NdSjl-t>81>D^!6ju$#fitP zK1-uErmVJwFjK^LR>#i1QTwZlU2scZo%)_N!<&{=rp+Qs%w!E! z!i*(zn~-P=SWjn*XJ$S){e#jO|IRXQ+ncD?pV~=#+_xmPnJ)_v4$Jx3_6F-6!{?Q` zK744CYOj%ILZYpU@q28aqjg8dG$^OP-0PobP?p#6B8ak})<>&rsd^)h&> z&p#cn&KHP}(<^sXLoRDh;$X8Ci(+85cbdb$#7hde7le^38Gnj5#!Q7@hLY650Ahk? zw1_Z8(8pY3>V2dR2*k|NfMOny07Oy3iIiVhE7g`M?lmBPA!>wr?#D4jPQAtU`wWiF_9K-h~H1n-fF1OQ78X|E^KCpTHi2mo;-M;}PF z-{?QJMjDJ5KuifQGZu3DN`R%`tjN+R$&Ab1tUO@i{~ES zERE1|bN;vmNf99KSFNr`&o-~g-SQ)GfSzMUN+nF)x@I{_{ob@jal>L3(w0-9L1@ev zUVD~la-GXV5p}^g?!V+ka!8xreez7Re9Oc(3*J6Tt813p5m-Dw(SfAqoM$(k=!}5k zFfgsrwS!akr??Xg(yV`)=^>*|Afmj>nboodaWDea)WoD|{xti$w3dnc!+`Vl-fXMf zxCi==ImpakYZwqAAh}a=rA$qAiQP=cz<8fJ*e0TE9iEhMPt$hmTvmjpEN&w5_k5~{ zgnEBxDZF_Omc5HGQKLX0enN-g<~W$+sa<8wM~ko-nvS_3=KU)w zH|?~#kn?bLaiN4Eb zgNapVbfe``i(Mn-@9Qs9i6QNaJ^u`VZW@|LHo^(rfI_6RQIRD+ zT4{@F3>3m->p^w7N+dyX%;f9}@)4$qe#fmwE!tU3H59^joye&Vkj%x=Zvm~ZYTu?4 z>kWletOEbV3uRTd;Q>Ry?=M`oL)46N@PRqw59lzw@~0;((lBdieX{!B8xuvN zbBLO#0ah-o-Pd@!y5wp?lvvC=D|FrKdx-0PFI%r(!{Vg`{dS3FGdbwAOj161v>1C1 zQl$7=N1Yz=c0$=?ChC~^(Z9bAn~5~XjGH5m)EZ+udj~|4ASl(cqFyYFGvD0szCx(^|*0XtYoS$ckW6;y*1hff{2b(5G z7?zOAOCI+dDKC5_w5VR4@m=26KX#2af-Vb_O%Rx&60_ShrRcZm zp6wwkB)eaY6?`&0S?1+JEP-@s^3mpg4g`u!)4|MkcDviLmq5KOD@j@0TUZ>dYCC{+fZSgh%Hn>> zhHdruA6+0beY*lr@#+?wcQv1k)ZC5ENXitLz$n{$xh$i2beFu5jfLnYcz!UCmFOm9 zW_9@=4Xn-#(1FdHU~WeEeyToq$~KL5S$Fts;C6M@mviQsAR`r+}{#&SJ zp4Q%i1fp5iS)=@qW5?wHYVfjGEdBnyU=Ub{duwKZNC4Fxo^n_k_DU)pA^_?nTx!hJ z`}VJnewpa7t{sHZoB?b6iW%1>q7-9mELPOeELv#EwvO`-5$2pT9GK$=#olIf#t&OU zq#My5Br>ScHo3Q92hZw*5#aky%o`_tbrL7Awo6PZ!^2&PyF%<(4a}}wd_CE1E#-3H zVKr_^haE<5vc#jYdJvIJK_~wHHcO+&((#pSVQ$G4*nHj$GRgtBB8;M6(r8r`6c1`A*#D()>r%6@Ss#c0tk$Jhh8J~4 zVsG32LrQKI_LJokPa{6W><;ONqKcvzj?`MHv`_HeWonXwa40$-fdc(IZDS-Yjj@5T zfs4DyyW5*8KEznO$MfX|wSD|PL@6$1%HyDr{FSR{OjQFJ6Zu)Aq~s;$nQhKEZbQ{L z-W180URgsvK5n|gpxWqwXDoj&4#ll*UVDw?F#b;9>*%K_tAa}gWsJ)pl14ZvzllOc zT)jMXS-4x=fGcsLbTH<(O#0C}kw>mu_7J$ue5ZJY+0?p%ch3REWXR#MJBG9hnqow0@?Nw8a`uRvQsA(ACJB}DldftoAQsm$WWOdm z;6vx1x(J!9ZwXY9dX?eVPK~n4$Uh}n{kZHV5E{Zo6!BzB9(zOjsYbrV(9ruL6mgqS z*}{}Vf0zl$CY~Mk0ty$0>nD2;gMv>)+f}i6=?F-ZhR~F;DCCTjQo^A)!3NMc2q4V; zz=z>^9J|R{u((+2#cGx^_aWX9U|RhNDH!XDnworDLRNJ6`d%11ojg-+xNb*uyZktF zBRHkn7jb2;Jg?6<3eRtCciw)n7yJ?t&AZl?8mPmilUfI_ZKHOWK8fDwk@jQ-Gy5S> z7}4E(0|2(sgR(Il$1op57W`P-&wl#CnPAY3PBvZfRf6}cL%q8bhEp8(-##rmIZ(G| zA+LoFicq7~HV*%q;)RezD{8VMx_p}$p`dgT? zaWSRX4Yv@km|~_M%?CkBXGP>q>pW0-CN1#FPoyLqz$w_F{ea<={P&Cc|m`C4&e{+b|iUj6Mc zG&>UPoGV(lK;7qApsZw<5(RjA(|14@@|U8ww4sgKsK|3UjDDk`MPr<;LTw$f%|^ZX zEgMKkfagrn+^~?F(RzMIm)WtWeMd8f?)j+Z(}8mf=gQ(4*!|UH+_Um0%-Fs(e+i>R zjrP8ZmE^Su~l#?#H8oLv54Q{8c41pqNs^D_PA zoCM2kmC^ScM|4s*o7W=xWpBMm#n(&f^(vJj_JHiHTY&88>5Zj!PovEZ=t@kDhM64N z2fYCOP}QE=9nb-<)Q9m!Kef+s0$R<38Y$`g{D+`ORFuWeoE9R<8p6c9?X<@*a-g@~ zm}MVIn*4QR2HmxTNaG43NfmjCIf@#FYPsS&+q4GYufXqp6B!A_&Ts4ZNc*WD3o%l4+}Ka8OKC%sy*RT`Au#G_`9~&3=B_t%!;3sc}P(e%ih1h7bmR_W0kvx21k? zkvD62ZgF~PA>J*i#nW1Z(u5vALVuufmm1bhr!OayPv3EjbeWCGZqP|4A){R1ztpW5 z4&Z&gR}c`%C{;qgeZhIY1){BWQ4>aW`hBI(4D(t!$h0DtKE?F1<54rb89ziZKCk@b zdw<$nvKx`lhlh@1&Dew75gb8^MtAgvchPY3HwaKm74A!rEt<{kblDe*lI3z?x23s((P8lBd|^8}Var@#&rr zVq@dCAm1;ghp_m3zrY^cK3`{Ou8%ytGJ4?|ej?7+mjWsN(mb+|U1ykms+imeS}q<; z?O4wPI)WlGfi2!#+go0;4z}PVhps--Os9V6YNme-k^t_KIooY$pbRPq`N*1rKRJE^ z@_<~UXj|d!Wjum;6Do6ycJw`pQUs%(KgpA9*Qkl3YVF%!FTta?$3nJi@QEB}NT+?( zX`8aFF@@TBZ?WT3T&$Y{n87SB&?c?WU+gZv5~&i-4~wZ?M_YpPj|eT|F}HT{y1iN) zOVTdjrQS_rs;aZC3fXfQ(yve>wrXa|uxxhBFtw?&nm<(Amh(kXS<>74_MDPtK&8Qo zl%oAhG#kJ>VKjw$qk%aG3*UF`Ak)}NdYxMs5J#9ykx63~#n`QEzLtRO>?$fdGXfB= zXUc1kRwwRbvPnQ*i?TOZr*B8owu|nj!tOodwFCz`+{|pqJRK9tm^dbyWXf$BWBnQd z_ES^v#6lY`x?UAtmC4WVZ_*BHY?jEll-nA-S5DZOwud}|l5d_^xv6+mxkAR4C1nK* z;Y$q{dMwqgHpOCA$D6>5J!NZ^W9JP0L@I+|(*KOF@Xesg#PqRv>Y8Y}8Y{D8qeYdmperlX03wGeF9i5qK%ygET)4yR@LRej0F_Nog z^6~0@1?RX5X|?6?n3u+9gqzc9-f%M)P1PlO+o!D(bEKd^#Hn`a+*~wZo{&JU>kFv- z32FBH%lo;y`N5;&t4fmxe5$J`MCA`!%CLcVquO7K?o*hvdeC!uIi;*GA2^4~s?crR zGFbc28y#eI?#Zr!p8xWk0Q^VWJiveZQU5;&G#c8Q+d4YX{#Qft|5S_aO=7_TKOy#} z|6d{Y|9MYC8!IatYZ_a(|GIgRinPN|h<(?&>cwABiLl^5YZ;tr)v zf6Nf-|HcA=7FND(KU0^|l1@Fq;abA=c6+@$*PUBnoWCs{%&aGSf9wv(GA+Ed$q`j7 z64#KC9TWr$ERo&kGqkvDb_}Z~vsR7eI9pXyN|Z-BN9A|si(E^UUra0N5FaJ6tR+sx zKDl)eTV3dOS^QEsquM?&?}rnVh|JeWW3bUolDB%0%+{Z?PC)5F(hC>3zCTM-&^Bhr zWVRgSEAOgnd^z4kJ;0dHAgoX_4IkHDh?lqe-3*nsMV{WU$0E-b_-PDq-0PX7sTo`yuRvciQC{}&I$5665*1Z`*4t>l^PH58gbMw8 zwy+$kBm5kYOJbAaERg@u7%#NH02&6su*mG8c++7Bt2``Sqex4NZlY}zDn)(?S!u!X zK_6>-EHqyagV!|=uQEm7mX_2&pe2Uwr-?W@CNFby$Psmtlpu2Sp7ihIzT8&z9$uuc z{h@GeSG{QVx7c2bF4}5CXU4~E~J6lBbsN-y{ z&@f1l8;L!g7kXirEzd6&m0lp&ZZLM=3As}h-x3#2)Qibrj<`Iu5v&C_=3w7kHr(H& z8sT+=2Fj|NALz+1TFh&Jzu2A>HwGC@xe z^JE+&dCxi(HWSws53Z8yS#O>N2AOdLzS>eJtMgt=5XY)d{{{C6ocsmkHn0@(@Ou*P z6|b=l8#y!qZdzxZ5ANbX!AQ`|yv~F`7FoE{$=3^>fS63uEk4bcIcF;Cek^znbkr*` z35&>%9ysPy4ZmZOL1;|^fI%w(Y`A^d-#7+%&{d|WHlx0%O1;%WrA(~g&H7#X@SJiwE zN48$Xeb1Ht7W}_|*k($s>o?Y}mmp@* zudcvv7m*ttd+@oyEi-6cO*Ug)bPErlvMmMfh9Nlw$ctFF)e7$xHAsU8%L?dl<9P>F zVKi2ou|9xcFBcq<+}d(l@M8G&%h5Wwy6TbyVr~er%I+xGfcv47Ae9%$wkE(3a|uVi zvb4qBGh_fuehx;LvLDA?q$|}~V{wK|vA}zU6oM-^mRx*)QmH)$KIQQ*j=t%-g|1d~ z*XWbrbKMrrr7eTnldPZ0zw5|q} zyBi}5wO?&%{%s#lj(kT%U1*MEO3nM?KUN`!>*_{=&JdY<@mKM=Db|#CLCfKqrSH%%y;+u4u`@JD>`i*g$QF<6G z{03FAD~I3$mLLRojlIs$1#9Wbz7smg7-+QM@d7@xw^Vt@G@ZtBIxrsADu( z2S;3zSKkvtX3^1dSbt9+k|?V1kewqTAFhO<#R%-(KvQZxsL7&ZLR(I?Ru(Ft3+s^J z@nbZ!l)?kEcqx}L-}GeuPV|KbxxwSlwt07nj{s3LBU~0AHf{BM<9>2FwiY0nIe0@KuGS_Q89!hvPIAo zSHejoBvDam2~?R5v}A-eRIpBH3PY6+j~pGZ-lq%nAzwu2j6L&xniX%?v72ik>39Ha zIf9^mMOoE-T++qM>lNu+cn}$kG@LWxbIv(6dB=5kf)z~FL-;FtO=bSk5RDB zg?I23L07MSrwWoOBkOs)PuNn87j!^zQ9fr7>sZtO9!d{{Il3)8;yJrU)(+BmokAcd z9ya02f8ThYDn~cH&BJaln6Nyp`yR|#_6)d z7q)O0bmLPQP)pP2PIU2PcZ$qXbG!DQr6S79u0V!^LZj^RA0Y)C3Y8SS%&)2W zoe9DMhDmS{@4`8i8b2!1gM1`l=Q>FTjS&KzP9W_Yq43;UbK=TI{Kh_xZW@33Rmd9Av7mjoVaA?Lnk)(mL#2O;s+eP7b*j<3-Qd3!NT*6_D+n z0(Oq%wxJ*$45f$13{n#DUG|VphFxi$YXGkAqq~ZS|Uu_N~E5o zY;uoWx|BT>WS(lHi~w}?XutH+f{Q}2y@n~0GNex-;iyKnl~-Cu<-;hvsB9PTCbc5? zt)N-@xg-2MotkDgOmwZhRyg>TN;+hDt7bB9Tr^-4az*>%o+gjJt;cLOjCp-bk44S{ z#RZ;_nHDb%p~s%;IZEpZQ?zLMG(_zocSeI~I%O3l{KzR+ao@axh(KIROxM5rTI&nl zV!fa563$bFG!R$5=pzMQ#dz~P4&Y=$>S)-*hTq_26lvldA;vqoXd*WTmdYEFz-CEE zwlooLf+3q>re4N3)n2JpSVcDGscP0=m;^;|FiQEBe8GeZTxjH#r@F9Vf0&PCttTwK z!jFAul>Iox-`@5vcU-h&%5GPnJ)_s$GD#wKT9KY|*Y*;5NvwhzwfHekZy8 ze1Pb~ygmy|`ruE=WT*^^EGwQrRXh6t_bZbIehOcolNY4;{hNC|yT(Cc&cJ8*u=8sA9MdUHpP8D+kzgzbGt)Vrr;Zv`#;RCmu?3oeWRi`pY2_fNl ziGIRUjep$JL{)8(U>BEnbzp)L>Lcw8ZEgp{_whn9)BTKzS1M7BJ9!Q_Y*63^=w50z z!~LG_my!!DGtIisbAe~OmJ^P!+p@&pQaKr0kZah9LiL`Fdt_ZtUj(OBx=YXd`J(CL z9TSuXSG3fZKmXX>Xm3O}@0nYEk#I1hj=IL$o${@MI&&SaaWX_|sj6*FwP-K8D}*8$ zV(a8s_ITn5xb^qD^7$o`b7Pe?v|!ahkV|}P=p|*mT*4%YGYMK1Bzldl>x{msxA+=$nuxLy z2Id{T2+((izNYt1g>b$vbonFRs|VUuY#Z8ptQfjTnQiO7kPkz$Xb1iy&0b0n+x6LV z={`R=(*w&9?My-ya+D`GM?ty=-95bf%RWY~U*d<;-`&iIUllHH!kbQ|1d0dvFOGQ? zo_WAn6+e~{zGyhYj44&T8WjvUu~b6YEi9LL_ceCgPRsW#>;Jy%KVdUq-jms4Y`~;zfOlZ1t9SbKG?@(t9cGN#1gaen*SKr*mCUz@n4g`6 z>;pVsva;%W9ku{u#trB{&2C}2-Ra6?grZVEqhLyqah?)^vL$#4Utd-ZuLSUKE*2ey z8x2beBl0SaNggz5VQkQA`lvc|{BtPcGt&9njM$WEn%bHU8eY5XR2MBGgV}MGJMMP3 z`cyA>^;q*@X?MsxK%D4EI?nRJ*$6A6#k-hOQif;0^^B^89)l)nn3^rSWeGy}D3aSr z{%i^>6Z=TxLqEd~y>B9Pf!7JIjEf%orz$HpuPC)4f?t2d!@zhwGp_C+Fns|N#hPu0 zzznzYTrsBu_8Vlg5{gAQZBSJwm+j}uaZ}VaZ$f9DEruwe9%U`JgundHKi!MCZ5ARl zu~3<-ujKZoo=JgSYl(MZY2!|rLscK=I{{+W22(6usmA}91YU%qnbQ;ENzuA1@e%MD z6w8<4zu^i@E93ok{8)Hq8?B+;?sf3&H$phlwnJ^hNfDf8qy|LwmMq@3m~O!KTdsWW zw%XdO{p$GS_feJ{bh$jOfZ54NIhhGE*A7X`k>ZAc>^zFZh& z3`6d#d)h(YZa-_V|A`~x5d9Q`$e*QQ7tg{U&}^1L)ZfcjcXO2vJL(y;ivdD-F=m_W zez*BG;j&felqnI{(Yw>2pT}34YaJzvbMAxxewOT0-Zmg|*R&IBoj1@-vXptL{ z{w7;3USQCC3RxnpFpxC>tIlzJMBvs4IVTk~mRbok+d3^)vxmyQ8psn@l%6`i!3oC< zwIFa&HQxzpy%kodNPWkXE%*CvD-e-rt@WJ8^}(Le?A|SUUJ&TW%DIUtCdpzd$Qd67 zy)#Kfx2xp8N$joVf)Mg3FMc#Wuvw2B;Naq+h4-xzv1TvlVYi!8z1_YtCCD7|&OJHZ zygEnhX8BF2Nj#cfLK^mOiL>cOfN5YNPG-y;Y)eMG_z!pZ2`g5<1+TB)zu9@6PBX$Q z;?H$Plu<;pma1Pn4_n6qHCdm3h8=!KSVB|~_K#ZM>AaJfh6D}Xl$>f*#AQ1SGf^Kh z@wvx={~Ah!ka^eNPj(wh1Ym^Y^E6Cbe*Hg-3hMt_RB&Q{y;=S}JnEO z(ZLlG_+q8k11&lf>R=_Z1rh>je-KxHUq%XLKH2O;1}O(Iw8wxFaTuazD?GX2Bt@d^ zp@g!`DNl^jD!dpkyd4NrUulO=w4Y=k);tLhVNZGqWiA9OWsw-DM7ftty7!(+q>M-_ zlS&+MQ)-JCGH~81L>uVF0Q8;3L=3QjP-UE0Gt?4clJY=tqG+vQr!X=iJozspilbE- zmcV) zgq!@D`yb*B9}ync1Tn)2Sgs?=FNdacy!^P4&9`sAwyt8_&#)AEL-IX5xzGQ;2R5zT zn%-a_w(=5&eI&%>Z{5Y%D|+5B&hiI>ej0SM-f#P>dghfpPMJ2iY@z`X^Xvc{<@((9 z0#hJ#$xHO~D7h;B_G$NU4KKJ6z1zn1HH)R(Efif>=;G%oJ}lnB^_0vwyUFk9xYl?5 zs3$s&@BLoz+VZ(0Xcq!*gn2=1XGQvI{`=;Yr5SkPf8N1wQaE1Cjc`s9D3n<^^sB$; z#*3D>f#v>R?+i@PhApSY4MHOP`Hj&-Qw*1OQMl&Wj-6de5V@v(KdWd&ONRUxsV2H# z98txH6Zr7aOM%G2WcAJl;$!^$FA6)eNwP=!!Hg(u!h@aZm)t*(h8n@K-c2wdmxE<8 zqW{lac)@h( zig;E9X2sEfVVEy#g@#6&!DPCvhqHwcv`XC1t^bxV<$A(o3VLv)LI`y`i}-P$@mT`V zGyWNa7m`H!ffRJDl>ikg#!?_--b?*E+H#~q*_{9n%!aKHvrcu+1 z8(MNNl0vuTCgk-3D?-IG@;0QOjXmO z)%BjPNrGExSf-JPA;8wBt($*$=i7=~p8dh#-D#)CH(a2CZDLd5x4TJ{opH`g#~;+r zQe}DM>=oiV*tZYPLskoB*qqs++uKbmjN#UU>stnReqkY4Dn+yf6fziVbZbSFWsunf z@m5-BFDorrAVst_ki`V>HXx;V0PATVZHxJAK2aNZ?j3@CS~Z`zCoGd7!5+x?5?F_; zO##Uecy0x>6YzP2>2|bhpWrxnVMUa)wue98Gr>0vLoM&W*m%E`UExVg-&y1A6kjC*ntWm>!uHnzMgnbeUE*{Ua z98*A6q6A^fuX{E`A0PCiSzBo#%jQC)rI1IcM<_+f#XTzhs{)RY2oNu@;OD~Q&L(RF zU3ms-gk%8dBvq^M#o%q`E(Njd1W9#Yv>7=F>cNt%qYANJQ(s!$i2SRe2Q9{g23vRr zNoV&<7 z5}w@9w|B>PPvK5T7ZC&JOZix%y-^(r7>F@xKI$y;}*`dL5r$} z;Z2y-H(|+ne`tugL`OjbeglJYiKR|OQJF&@_4Z2fv!MAW((o^hMGp+z41OXS0#TDd zBgjqv6KMz~yiSnn&`ua|f3JzijJShy)qxcGDiS%*wm5z2+hY+A)o zGS43Aqy1E&c3yGmOrt8CfwWE(r2;bHR2Cy~L)Ez|LKzaHSbQhp&gDsPBB{mJxf-EG zCF+>_vuzyD9}EMYe{Lxv&+?}_o9cw{Vjc#2VsI85wfNn`BO`QL->=>gTwz_gg#*UyHPLXrfAX zQORvosuGi>v@xPaa~Ppb`@V23M-5AsRx5!#TwA=Sq}7wF;1a}0UJ*sRJ{Q^p3+wMu9p(kvc+ofU!Vk8kbwj*WNHI1?>_*pOJoa za=inF_4G4;LhC61H#4ZNRwx5mWl}i?Ec#x8dqfI@trA8zTPLNhYNw`+Kx2#CFcBK6 zH|Ch8cz8(w3m)8JFWi|9?a!TM-5v|y|FuG+&M<4FiEOt+o1dkvP*z1TYW9V{bpGIo zMsGBT@LMgs4abK3(K>On1%>jv%rox}pGv7UUopGW&KR?>M+k2IHx5fV@BvHLAM&kJ z6?$X>qnQiCdS03cO-*Y6{R-f?JXs$6^KuA&O|~({T|>B2{ya%}c7h|x3a-eqF~TY3?W4Bf`I8lQQ?Apb^zoMe2_${auV|+>y_+)=S-!jb1$Y1 zqVFyt!E$$4PRf*!Kz z6=(nX8U~|6t>TMDTq7Vp-jqHXAw=w*#dMVCABq)uiRq*(8#DYaeVd!OvGv#PkSzWe zJPE2r05i_u&*rRui83RFEFC@1Lj86T7gGw$*LqWXEjpm?1V%PZ?itxgOUr`WT;=>1 zDH*<&`hG$p?cfK8`sc^ac)LIVLOUD!XLoE!#3gv|-s>pjG%Pn&W_9Yd@tLe8zt=z) z$1$y>@5=MA^WSog9yBlvQz3i?jP%6l(jKuZnWf+MBZ|P=9xh)>HBHkFK?@Pi9cZH( z@S~4!A$00_OsoF+Yc*3xz;;X+3E}NS25cFB-E}+BDYbRgnY&9>JF9h8t<9PU3SN zuU3O=ZUwQHw904Rv&%oD617(CtQ>0*j#g&V zI#$cGa*e;tu;C}vprY?gayckkCUsA)Jb|EUE^&)*64y?>ty?aQVeQN7JPA&MLF1mv zBc;hZzt?u-Pfeuv`*2Q3m2(*_;>eePkvJS;l~|Dn zpAb;NMF*#Hj{t;k1t>kMML0Nhm)v43pAK@0D8H<7d(@7tSKWd; zY5WzP49sMWCx21?frK=MEMSP_fH%jQqym++tVA3yB=N$}CCmSk`{(6qZ9wun&X((e zgpFYO80R?Impg=dOrWM{0^}FGubGg6gx=T!K7IV}RI#C46$hkS3+Aqg&2BWis;e5~ zM56M3P>*}!CFZpY5SS9TGoe-@7J9f}8U~M<|$q%yV1@Xke%V&RVYk>Ff6Azi9%ke@c8y>BhV3tvHnh?R75KN@vE$u#a z`FN2U@E$NB!I`1;dj5&e;`6xtvo zL})$u*@Z^jI9gHJAt7<|XoVpmcq+(=-t(_*b0n^!ghf8ZP#PIx@&Lo>uxPt`Ll&Lg zzE)aLX;rkUkLv37?D|OB@{-Bf_AS0sUQ zpC<0k2_BG9sf($L)}0ikGpeR-l%(gl6w2%RQgkCwGl^%`qRHV&GXeP46l>I)W^H8+ zrJxece7)!k0Bb5Uop zCMszW*|BS4F806l;=nu>GTYp{kxA@y#ZsAFXx-u8WhQcsQF&H6Pc%@05 z1czgTBsFWz#bK%-8(42rK_j+Xp|cOm7X`A(ne}ghGvxK5jv=BrD_^pR5O4Ck_`&cxEL6$aY2#4=91}?p((XW6j zoXg?`-b=p&bp*l$1jLZt#xm!>-H0Qt&u#yIfmIwB4Y%KII2N0->6 zRk*^+$KN=8PY4G9GhPCF%1<6Vec<85whA7VS~`X#ZlPOWyqz%YGNesH76gi*<+YX9 zQMKnVx|q+WXA%9xzK~&dNdO>lykT7MV$qdr^6~+jSQ~S&v1BXk_Re<=ZhBrnTyCKa z;`s)i8DVs}g=3sGyOJ=)kY$}_saV_=Qi}FXL-z~4GJ5+mEagv3rZLWNngY@+n(F4K zyW*fgD;5Iw9#7iq3FZTxDtI%gh?0xa&aD=8lsJ^9z+g#^lcw@?o06(XdfdLRYK9Q> zM>G04r)fobOCMXa2``o(L-@%Sfv&$WQFvQ8f*Wi zosHJ^UM#R&Eo4rVRoMgep6h}w_gA>Z-CCB2f>|?F6TtuPUmI*~?hoZBWOeRD5HyO` zK@IOPY?2CbFT1!wJ*SVr(Z6eTx(f??9rfN@`^=Fru#<<2^13)pNphAipy%C-Z{-@y zF3KgBI9_RgK5Vejy~D-Qn=NZS*}pU!cx(HP7F5!y0zx!Oj1T|5dPsLZo_v~&#}qpn zw!k1Q|DHi=Id5t;N4~Dp*5&J9>y6Zpv37v|Ad4hUoo>`*yav6E_WV6((Aa2fU(78c z62=q2J4%g|Xg6aJ7FcFx%gKtax2_jvpb8+p0bTI#9Iv?anS4gSMOqrG#KSwF{TB3_ za6qoXv~77gI2vc<9>@LR*xy=uG7gQ3UZjk%p7A1!F!Us*LQRJ-+C5=nAeav_LzY|0 zI6k1#vokk9{w^&P!U6FgaaG??c{foWoK#VzQ-N6Wl>p!jq6?&rF1BIn&$+^z z@NktE;2D_%0}USC z@C?~VeT|2+{&^cpeoKO%qpVeB)8dy2<4!xkYuAvLsO!gse15!EHby*WkI&AVEYF@P zib{)Pap~jkhC{)gC za|m=Bg{a(=hKcY#zg7Egr6Tpb;UUBBNf@&yp6eV;Mt{(Mk|2%&X+Ey)8s)~N}OuxBY)F~NLyYHP_lBB?(HdJoPV`ZCb3D(>GN9e+FuCh~K9dJuM2Jxdf?y5t1# z;!74BwLDE)-xBg}pqudC3IvX@!6g0R6KR^#l}u2ThO|2<^pO1B?|SZQ8y6Bm#&Mez ziv{Z>CZ-)BlHejRk}5}*UJ3tu6i5V@kRkbB6v&bi2#D{0?alv33W(m+!QR5!lEK>k z{|7#CzEqDm{(AhNS4(%pk_X+m*`F3}5Bvg5ZMz>}yfeFaq^JYPm4DT#wFSZD{Cw^D zBm*X#h}ISvQl##574KxPeVv$+MufQ&it*ifG0Tiz^kfAl#3nj0V%O3py~t7X&1E^# zv?)|5U^%p#Y#6kPqpNaPfV3!d7^;=k?)7qiSFBl{{qTK!oA~38Y{ z<9`gB9>5cyWYON9Fu{;#6(Ch2f=ER7NnFYGYgmQ@n(P10-T|QmGP`42KNh~|_Tx|n z0y#Ybs7%p;kE&P~B2N_84*WKAR5k*kx= z%VpdEbDwJB7=!R0@IuW*&cKv~U;$p(vn?v45+21-pI}KO(v|S#5#RBJKuDdS7VSqO zt5vQdc@kmAYLup+sWL2CVa7lx&ST<0t|c8)9KBk3gg;5}+61^r zbkE8@C^KQcPtc}zHW;9%-Py2o?JthaK&Ods({hAIavN<`S4ppBNZQTSLsbA2jr6Ly zMOg$LWueQIcv@=t*o{tEF5b2PCbfUWn06S`d=J$yB1@TjrE;^&- zz2L~MtboJ@Gw5Pk0T+sX)6($pxabm`7F)qFN0Ycej6Z^d<&bvN46+j?KD*MOLPL1Gz~5!_ZX$!B6+&=2-gk+zYSYCM-9J1e3EVannW&aYM8l)L z0}18aH!l}iIxiODxSDkh`wPQgq1=6);vPWzEjQxCA?*M7a#Q4+!u%^K3#CB@;UT@d zKdkYL6&FNxFQfVPOf8DRq>At{q(X%38f{`KdOP6s7LH;vv z_D1^vf3yUwPc&)9I3)bROBmL337J)UMraTtoRm2V zmL{nt9`vhH5f&FfY=1;*f6T z52U@3o7RF!S!|BdH)2Yu9^{V=5eSJV(5yNyI6L}k9n5Pa)T%kiZJcBc3Z_?GFk8KR zHNVn)Vll2nd0!sxfKO78lgSiH6ADBu)4pLfB&r>;&D#Xpvg!I6kto{E*+JM_FmG@* zJ}p0LeH?ENy?&tt#zvK3n6_Yas=7vmkTmR6qwx5ceSQUv?Tu0m9*=8a+im0&0%yk) zqfqwK$>jy325WsXv+Stq7_`R{`)TV*Tq**X$-nneg7NF-VHbFE#m-bbEWq8Y8nRF`goNFsEdex{SA%pMuE{ruI%_nGJB4YO=AU<{>~#5grSs;rO00 zwm`H>8{2?rrV#adw3h44g%Ek8Hi1i4n}c^c2CbaB%80{XVXzBTFnCt8sbPK?Nnz}X zo*?1M_#}qBjMJ1Ofjv(3%;u;%g&}7G?nhHIdCB;45$OFvJvAK~3@BaJLqMpw^OVW3 zf~LDAubpjJP^bkLg7<{kUjo}S-NIYUoD%Q{;rvn*7)NsDxn7cUG_G`?bnBem-H+Z& z9^O_G)+`Abu~JRc;6Z%~A+)i&VzQ;E5|xJz0#nZ|FN>Hcch$s{SuiJd);FfyWw?Lj zt=m0WJevyoKAl_IhwQXHw;qUBfnmXYd2F%hm@r1+!}59;Xe57L)i;&{i6Hz&^F!v;LXpX97F)Zxp*uHwN4KjXvJ_Pf&2x9)3g zp3DQ;=B`Td!M5-G0t0JLwV7GhCz%rwaG@hx*?+zgc0}r)moj(n_3<#et7#z86Y=*t zvR;)H{p^bhuP}_c&1s+&v7Ey!A{EPsW)$liGL^Wp51=`H}P@B z6IXYA8FPPj)1_c8+wE-vu+!AxXEWcK(c{m2gJ`W$dVyx0qbfXIZ04yb2B*!pXkm%Q zNpqJ98J1WzlCjPrRb-vEb`-K2kVcPVkp)hJPDLgwyQ%ir>S`hP+OEY0k58b7ai1c9 zu(hb5mxvMJ;x+bIZ%I!tyoq?hTQKrw^7L+A3arH;{*=H$hMyg2z&s-^MqD%5I_(^O z_&O2XHSlkV#3&tk;4vR!<;ozO-TQg^TRieOpn?0;epD~?F&9)>fd4ZmFgPb4(`k#p z;x*bhV3k|V4F4Rgghyc0eB4>>rt#^7R?9%!y?uG$tx5y_%aobtb?0K&UY4#FOEF#J zqVbTq#}|dbP=ja8CxkpUvHP2TR7MtE}sDe*M%CIL899M*iKA800h-bSdMs401q!+@z{N(S|J zzGBIdXP(ucaL<@zO0?1AmS~mp^-auD?taX9T?MZ^VIkj#nMjKiXsKb=^YzN8W@QK+ zRWX#2-sS3n*UMf7>PvK&4-(QwuanNoeIUsscpS%uPfu4iK6c!S8m=K+-rFHBW~e}Z zq~DH93XlL1gn=x0um=z+&{YX+AUj|rJhm@zlU@TA!~Ed;*F}~x0)ztV=~zO^u`C%Y z1jRV_3wSSUP+mSO!Cxb_2FM`n`G3`?nz2v#x0n~TfVjv{)u(zS)pek@EL9$-U?FX^ zQGSoda_!f6Q^8Zn7g*vIVOjPI)AF+oJK$i0(l>a)k1e0NQGxhP04h$0t?`Ua`Bp(d z?|QMez7+3a3$Ql!?^A*taiu3A6#ckrOxrxAHtye5k5@(r7*c;z=9Mu*D!R|Xjvw#s zTdwr{Dsb9Yi)!*z4=O3Q-#2O8(nMcc5{*dM?N|KmsVy>NR8Hxrqs8UP7-D7_SmJP` z^eptM=n3n_a*I{8fS;~F+lmDWx7o@bzHpuu1cA?z&noN1jEX~;{*Sof>0hQ6zALdj zT{$e5KOm-a?3gl0ZJq55#JO6p#dlvQGXusmDgdBo$uA_Fh>l!HotCpUPT5^US?HPR z%4)m zDzsGz9ZXo-;lcHz5JP+yQAb07THn&0hZ{AFNzu~+N#QP!LIm`s=dn)^nck2jB51uT z+xwBnGLvFzWO!;|c^0Pw(A%sHxY;c2>+nHCDkPTIHtk<5z6*-6x-LNt+L}4#3T{zs z17ZdZ>>5}QoK=lVggzm4w_w<{HQ-okaxcxP-Z_;qQCTcj%leg0ZsfrDo>$(Af|}C% za)DA`DW?5_%_R~E)T0_&R4SBJJ%6`XxCeLt&(*!ov@Zk(|&&DOPx`GxOPi zp{~vyG}Zm9Bjzyrl>xKce|z{OAx-1v7aOQewIwGWRGx&^y^2N%$-JVG;2+)&d@Y|K zp9+?dT5w&V#{om)tRQ~XdUpl*TuRs!TCG`&3&&whZ|c<#da}}FO#As zIS;{u+ViBDSy_A8VdWOYo@X`mgI6N32vry~%zS33yQ|c1tn(!Y2T4RqDt8K$p$Sr3GC&v$W z)$@~zVkaKNe;f-zX=jMwjPYUo@|&W9L*fjcvf$D108hn_0FuDQBxuMs!Px81^Z&7i zz$vLx9`}#Y*}4_i1_;IZ`+Vg-md4u{r!m0;;u<6QHL$-HM-=} zcdpcqY$&FkFTuIRCu4#!3fnfr6=RZ4zU4Z50Skv&t_a8~y{erdDE^Emr~b+TxCk{V zU@Wj?M?@CS45c>1E3PT$KZ0+SPWZJ1Mtm|%A21?VY1AAOM>}lrMPVYlPd1{G9KI1J zg$3+lL{4cnsj1DRfLmVKrGxT%K`oOU-cxjrQBXq(p;CIWo!ME%v9y8cMGg_L8=y%A z1E19}={&Zm%0j?dN{b}{$1=1DWtW4!+v~|U zOB~R!qEti$OPo8f8e#FCAwP>RJ9V5&rIc|BwOEs0NP0==jeuw;TQJ?Cb{|x-4G0Z+ z_5?QIJ%gTWQF2>~Fco^i5+R`_&=&#ECsH+;WeFCJO4*rggwH8w73zk{q!;6ih!i!+ zB_ifg7C@MC5D+NVcaathK8{$uddNDe>-532Jl%7Bje`k=OO^%?-RPsQGy0+TZBCBUYG|s z`Y&1p2InDC1|GROa%2MSo2{1zP2q3cXXd??>{5E(_~YdwP#9YMJ{mm6ljJ3cpBLK@ z_h7?*Vo>ZRb$88~!6 zT?jJ>oRyUlIM#DA*4PEeq+@ZsKDqr;OVc3p)n7rxL{DghXeI)wR^o+c0qH>xoH)$} z1G}~>`0l+s-}CEces^F5<^YonY(sm^^TKs(PpQ}3?eYU}_sn!TQ-x0$wp-7Jp-cjdm5kkkpS3B8+ZwK^NC zw*G-%aWF!=PAbvYj!i*gr@8r7%Jd5UL*QT7z+`9Q9xxAk|5azx(uX{qFaVGHw2|a2 zR5)n?81-)_Dpw8i;h+^N{f8Jv9^F58wRt!Q1^QRQtpGiay?pQ%Y=bd`_#%nKE{DRU zr}wTE&J5uB8{GDK;1(L&rAfy8ypkACqE-h4b!+oSTv&S;O8F7JR-twJ&q_P$ zb-d;KZWwlVAyAyTVxxti`@9Zr91&FeJv%%|=Ip5`*3Vb^>h>(3HtQXshw*1>V3uB( zQ_Y5z*p+;;NK0ZBB~fcm$oVbbm{;x+Pky-rZ5U2;0p*G;Dr^Qotn>n|?^&2+L z6avGdtB5i%^#|v52(CD;FW<QBb+Fro4#oJ{Ob#i3~n7z+qgslLSLHfm3!C&EH9()$Ud z@(@VlA-aN3&M_F?u*y(fhOnZrvd&d=*9rr`2R|VKhlEBu{KZ`Ykvg zf*br6b45=8v}V{0{*aHD&}m6v=-lBT(do~k)l#?IVUW6I&L~G0Dd5H`89%qUE|Tl? zIg;3)01&AyB-EQZA~al|yz(KXY(tp_ZB*$6VnWUnw0zh4E5+lkSsjJXFdu2F2b}99N*Z~d zNTewN4Bo9A!63(m$i{XV6MNZ+YXs(^1>;kRH;Up!_vfZ0 zBOtf}aj@T~V9`Y)V4b^oA!O5)MDm-m={{zy@TC%S5#rz=7UX=e1eEAniK8SzR`*61 zn`3gx4Se;^%-kGM4$eVIannr&PBhvCcdG_gWL$11Sse zfxO2Dwbr_Dcq^&9ZDG@;`u$W}gc{_|LQw8PoSnY7->NdTb`1k7tg9p!yvmYz1EgDg zYT1?mJEPNh(Yh~+EOADm-g6$WE<{VP7rcxNg9e&-cN4y6OvT>9dm79En5ovho@ZEE zttaSX88R4!hGgK}?@6;y-!Fois(tl_f97q2@RD4o(%Ise+lFOfCc# z0E5CF?@Qq= z@WA#v9|)E4XzOo6WDK+Zn_Pnd6e1$Cz#F%g(TuSSy|OCWb$iH(damEhWG*Wr6Gub@ z#eB1yA@O3@xv8l$82%zBupSUL(TDz+cyXERK4sk|{_dw`{6~#ruH;ucR`*CEwJxlZ->h9} z%)I+lL>bAKuhu46vI-gLG-xUxLa&##xvW%PK00m6x;%}Ic;vkynf9i((3HQlmC%U0 z*!6BcM1xD-4luBEAkO*z_4t>^UZi-d6uqBZDtp_>5i&UzW;T(+bJ)3PUWrtK zKXCNUh|(!Nc5yw#G*V@tH&xY-*^D^=hyqxr%Tq)plFqEd%y`?}zy1LB55o|f%SB0G zB_21CU;0&jj3o~55cJbp>Ti?PT1}g=MVUnsn|;Q4|ISIwos6hl&H)dEi$g0mJp3k3 z?4yLl@_l>5%wgMzVx6U|dl<+}eslb9tP=ur@(_QfKZ>7wp)grGQM!HBul*V!_`+M` zgo?ojPL4cWFEvFx4gnAT-0u$_%Q+ZNSc?k6FKiv}Y?-fvuf2m>eLM!Ha||H>1>e)X=7RBG|4d#%Rtp( z$N`e(aqC4Tb^2dIOFiZA!bjelpO@XOW}Ld9bc?jo^-6G9KOO_%v)aV5G$iO#Yj`b8 zSXSQh=;!F?6i5};n9teYAbaS~bQ47|7*0*{nfAyBayliu0WvR&Xzaqst(^&0)PiS- zSjL3IB9vW8yGc^QB2OeLfEJmgG7e*SH~6*7s!6cJky7}?TgI_omv z;s6)2*3vOVkNs&XP0TNG6h}3M`dWPGsb|of^W@5m?3jwk1`Kvvx2~JBuIL zivwC1kQ#febarT9jZrRkVG`PG*l8zTGgPwF&hjC=@6l;=h~hydyB;`^(v7PJ3gpik zLR09_XEihr&3p;Z+F}V17{AR4r^@chkU+~iqGZd1=`jMrKDYB!Qj9y^?X|Vudv~E> zxn);p$s+PE-y7OB%^K+r;upel=`yVwZQ@A3-#<*uJ--Vvr1QbMG5!x{=g=$)&}G?c z+j!TuZQHhO+qP}nwr%rW+cxUeq@us*=t1=#$Wcbd$vAtjuY8oXhT!9F!*hHR35$s zlhZA=gwb&^j+|8xw3RLwcE}JNw~S&hG!%u7Ql?WmndICsMLmAHFkoIyTu`@cy{9~6 zw;=j7$Dm;YQew#Gjs!56=J+a0OdD*)t8a=u0R-a$%r$OldogDl2LkYn+Vf1GGw3u* zHXj%uq9Mwi>=A~Rvk(S`0nSWAk1wvk+~>TbdGgo5NgspXl|?2*IPuu?{=(<=oiD~A z+a)fKwmVwFOG14TV>!frl$e}BOos<+38HRp+XGWwd)J8ose<)jvBP@T?|^>GjHyb~SX7lwtvLj?buJ(96Z=4ysQJ6sBtN0Os(lLMZx46lj{Vn*_Vg z@o&2v+^n3U-0TCaEKO&xBatK*wK?UazB2GLfDnbUldvN@Y`Al?37(Q)E zRzrBa&z*RIOwi3{{Jt(M1wutf@!tDXD2!-`hr6rJ;T$r?2m%u5k=XS=?q74pf_j;u z&fTAHAr*6M#mx~!&8Aeez-(F#%OZY7)Ul}S&6HuN14$QVE34EGXNqxhsH3j)66f+w zAIwR4oraZ6oAYJ!#Rw5Ia;xu$`XV$n-D>uY3hGFy(~76kN?I=I(p5_OcSVMZBrw1O zK^wKvm|VirnaB%#Xp7yA;>klxW08oANy(aFd5BVrwDQ2kNTqa9?c|tYY4ip(Dw!6`fDQjG<4L5a z%1gp@!es%=p;V3;I4ur&Zgq>E=Q4<&fkqm$MYLKuhY!dV(!Ao>l|RiPafObkJP|Qb zK|>kUeyC#oP4BY^CFC889xLaH66!2YmxW6rJGZUOR9eglwT^F*S(~V(mNpcoTa?YT zwmah^@=wY;d!)zvYM!kN>)NVxmQY3wX@gqCmB_ZN?eE&bbf07*3JeJ3hSb@OXR&0s zx(iT^&bWKu5Iz?|+lT*lw=W)Mof3cnZa@LNz<(N%h@@D=obA?@OmN)*IRCx^m5@^e z%q|{$PQuK{j@_+d<4#R2H(y92!RYu}FK5H%9)fd2;p|SKru6;;M+uZZ6zBUd8L1Od zLX0d+mcmlHd{Qe+C?nHPJ?75L$;S>7RUPu1SU?{9fTX? z@}5iTW`kcevvPZJdc1cwV}mXwGJ+yI8II2oQk+gxm_|RCP8iV5 z!B~=k#sJvvt{{LEu5U+kzN&7LgN*R zZ^Z+-3r@QV0zhc_BmChV#eo;8Y;#WvDFI>*KHD>9!35#WWLEx5o&Hgxdi9n;}UNk>fASM%e!eN@45d0H) zynQ69fi){$Ez5EP(NZ1XC=6&gv}_k(iI)nt0f2CEmJH?g-8zF+g;npFdH~C{C^dND zw^;B_p!Mdt)Y!nXeLGK7Um($Z#*&t*Ru82x6q0j%v)oI3CR-cL;DfUIHHl<&6cRs< zO<tT z@%^cT7LLvK%GZRpG-Ek+@3=vgU^L?y@`8Ss3ZF1VNOd-9_lr(cA$?xUzeO>ctfJr5 zOV(rnu>DNKKKU4pX*50)Z-RVpMg*? zwW_txR~anz*7KX7x51Br1mENbj-SYI_Fq!AN}S+T(1KY>PV!G$y+@b(cwJ5>3O6Ow-ME`3Q@0G^l!&-`9skmlBg3LCVRS+@g zYKG-Wm$&e?tNi!6Po%Und_~52R14VKe~pX#8#!EY!D} z2KW^}ZI7qIUVB zoy6%2GQUqt-s$z*4eTphgCDrU;r=Qgb%nR%OdqC^^UYBi>NWi)wmm7twPOl3J3SX8 z_Cq53bGpwOq)z4OzIhN=F#sZX&@#(;(=IA~TUBB#w@u-WPg$EB#Nc#TjbNNna%HCN zUg<3Vm!qh@m$G)HkSuza+d$CzETicQ^6TiDb#Rv&^pE;9E2zM>P5<3H$ROZi|bf#&UO{F#njR!SarLJ zo!y3og@%hniqVp+2DZZHV!{XD1i6l?8Gj0zDDp^q~vbiaE*P(^9I8SQu~? z*f%%N_Gg`jNah7U+iRv_xg$2qrXW3a%jNv!eGeh4{!PIKrJ&m#x)?|4*`5u4ISCBB z!Kmz)li%`4UTKd4aU2Ys@y@!R zqX2)C;AT{(IM&vi-hYPMHr2}b=%D}rp8l23|JUI*M-yukgMX+iV>_e&U|f}`+t?k5 zBmKTE8CW3xd#@S*G)!!PD<=Zo)liIT z+z{TmYWy-vOrBj^=uX3UnPtka1Dmi2!_K)i*c?RC?pJ^O+XxZ}1#fol+=V8An=)WY z1V`b@s43Pleqc^QHLQ|fAMxn|PC52LsOqNSj8p@GUbnp4f zjF`=Ak57^?T~Eo*r$5Fy18Sik@4an>5oZEiXBuOIPgT*2uZFD$p?Z5R*w0sd~&=Rd*~jpJv|PWk1FofZh< zG9F0$g469^0Pr9IDGFb|1TeOL+KwEqFAKdc9yWJnEW7RexlLOz+@p2o=AQoRXwO!$ zp#-)+Z*UDxI%~I2)~`F~n)Lvh6CU;-fbVXub#7Nw!!V;hV@BW?wTmslT-TSmLzBr> zI%`gxfS<}fmjL|f>sA7>|5~NAy+Fv|xEni0Rq+>GeR1|MS<5ZA*IMl6KXS$hxwGR= zHyif-`*F43{jj0|LTy0;Y6Lf2J3(6xUvkUXZ&1w%xAhb{T=glA5P+ua{6}Q_j+gfG24(@*aj-$1=%!sUOr@*y}G0Og{369xApi}JfY-1AJiUuUF zp;tFSQ={l(2@t(n#W8`kPHF&lELdh{W7~+jBvrzTd(I&pwG`p zOQf3l@$bgM5$+{9S|XI;KQPh`kch!Ti_4#h1SLn{tv96Vz$IS6kb09^{X zHRp=ls$Vmfuo4GU;S>?7(uf<_U{M*;QVb4(K~?M?3d^8Yr}vWLQRdwsfZdUcrAAu< zQe{{EQ7lZF-aLqzh0NlS>y#`dFdZsd<|@{;ggxa4#geC9{$&dTNh+DW^R7yqRX!${ zZVH9KCCtfZ$e@u>Du1Lf5zkUMbS|3k7b@ZtNk6B6Z-o1n31@$#+cd!JF9%rl(ipTU z9n`-4E9Zo%i*S%>v<)GDgz_G&v%2RMg_}qZRY+j*$m;+1@do`uhps)H@JP1IOS&gDWchCLI->}=HM6FoRh_&u6B0mH}BuS9U zGun07hW*V9$1&Bqn^Rr?bC94XXUWYjA8%c>xKED(k9w^sXmXo z&!C#NccO>;stMGcnRz~RG{rRK3`uF-ax{XeVhtr4>CRRzDjU*HQ_1=h$$_1 z5OIKae4kD=MTr^bM{>&A=aLQ76OEFG7$Nl0N$l`KN|7twpo-%|fnv)d&D_;mXLQt6 zBam386mT}}Pj!*X4YndTw@7RmWu>gBxGQv&lmIT7p|WzbNJSzedf7Ch1+nbNH1vwL zSS`J7`J5=+(2>ri4n%7cqdDg+GrC8lnNU>#(i!>rK%f1aMwfo1MLH#*VEnPk0h^5J zX|N*Gp(>D+_K<8Ddno)pJQxUyLDPd=cA(!7*k0&ZGO9>eDKINOgWRxD42P0*zYIXO>jd{>*)_>dg7G*Loh*g77OCrcWJ)dip>)xgg zC>M}#=xdqYy_;Rn%`o@`*K~Dp3?zbwcmBhPfW03e`Ws)HA~hxz>o(Nzo3d_)1i8&et5SqeV+w z<8g0syDMre_XG-(dNPSOAX)tK+S+9X2}P+>#p3QPlY@h86p8gX(47|5!+U)<9OQ;fOp|EF~`rJ9i0oPmmb;RxEZF7gkVLGRk?I zar{s=e2d5|s-Z&tGSybnC8KbFPt(Os@N>AAqxxCVO6VfT4r>EcMhSD%0 zOl#qskl6Lgs%U=8m5v2LE1GvEveJUT;6_gVNf2;2QODTsxtbFzX)Y=fMd85N*ZwxyFb6k;eJ>Ai(F4A+YDYR`-q z08@Y^#^EFBl?P}Vv&tfi3aU`bU|?Hi zvUcD82fg}#{)FQO!(Dhf+e z5X4l(!5~E@o&vpPD%4jgcweQ+p9wQ|s+RN4;~Z1?u&N&2@OzbLxWY=}PiIo82^A@L z$3>$>ZFTU$=CcL=TxqkN#Yr)J;cHjlq$2xqe|bkdm#+nh8-sdAREx>UkzJ)DAomMU z+@;xPIoTxR4~O{Z14(LvhgiX~P696`Vm=+04(u=~za2peUc|WR1O?EhZ->l+p?4YX z`oFtwmt5*G$VMQ$4>JkIP>EMLg&bsD4B&a`T||@$SfjtJ1%3>y*qMq~_;wsT ztvbV-5~e|i92sF}F~nuX_3D+{TME$jK`{H!%5x`O_i?C6WGC_U;J8PJCaE+jv%KhV z=J3s<&%aCl0R87j&SMO^(u4y5AbJb{fc1ZSxn1n7?F@|n&&b}0kCofjXv>+~cO-=} zO&|m0q-$d9vt4?uho4vV@u2@!zD zb*3h>Ip4V(Jg})o4DFH){E3@oLzTZL8?!gFwVc!FRfIhqHOo!k-+UEn9==Rc%MPp& zXOCIViN+?3DpS^(D3zTu%L9bD{dn(-N`1s487CQ@XxCK;&>#;KXTIPx)ej|^V^k@} zDVnK}%n7L%oFTG_b4kVu70gOW-o5E14y+Q(KAL|O*%l%E3w|hNj?`3ON{q<+{L8G` zvLmU0Fn<54t{AdoZ13)hF#uv8kId+gf=&%&9S#+_nTh!Tq*r>6oBs155x##i(&(3~ zQK8ZSiiuO0jiN+YNTAOGC7t>4TT%M zLi0b5WJ3LuU2)jN|Ltt=>b)Ao>dV9H=ku_y{q1S*>3Mha^>!wmlU+HKkmN{kDz#sREMn<(L#Bdf2yF~is^ zu`J`8hJpzrMw4imo7$dE;?EYMYI@FHa}c@142F7r1tMUdd&*?#(~*9BkFu3fy0%t7 zD#9Dq(uw?(ex#wozu>5%I`M}LDJ%16-rO;b^p*W|{vZs=fHLjTL%TY3(HvyTCxH$k zR?21JRteqc+tln7l$+8+xgOUNF^z-{{UxvjapHuYGKP&gdjo3UBtHMK>DVv>mPVMojQs+ci^_^I3;;^gQM2I#(*F{hrP<&G=H=|c}zw=83L0I6hEsH zpbZRDdStKCU&lU55Ah`D4Gf{T8i6E@Brr1G?ZYR%F*cfQP{hB4bId1XNuoU!PZwau(B>%QgM`dc#|*-{OnF&kPm|ddc>yB z$8+1^iQ30MbmxBa<(P&qu+H|`*!vUqBU299ie*B2A$_8Vc5;LV zs~*&2?KD|l;v_ds9hwNQgtc3};KylWI*0!K64PnI=Vk@Kfc~?z+`TiHQX`S^dAcqh zs)(*W1s0}^Q=wR>xMND11?UXG{stZ;B`g<1R*gM;Wtor**p`__B?muLxX$9GnGk;c z8b|98T`v4e)RCnJk)3pxWpS=yncd-BrSxwC{tfK`6aq;71?8v>Y%uethu7WiA^h!b z_MdKye|3dhqVkutZ=dHB&(7bg%bc7X3&$E=l9dH+Su+CZEpG)E2Wfxy+w+Pe9Ki63 zb73fF(5NbRPLhj2b_L>j_g4dO{a(8w0|R)MUyDO7}rzLOoR|dI)qt_+Xe>rXDT?Li1`IQt!() z85=@!%tU7E#e>O<<#K%)Lbh}26~ zASBqLv7f=cUpPWa8;U&TDX#tx~mhuEWfO6(s z0~}>zf?o0zuqueVaZA<>)q;P^p+YI=>0LZl%b)DBQ$JgRgkk&Ca*PRiL1EwOVI8Orj zHf{$T4Vc=sia{&g5y~(vENeOU!rwp50Ic)A*h$scqRo` zlo7-K&h8?rWPR)GH0@6}Pv;x&0*KT$ILOO`9Qe_7zXBqx7?e&zQb|7~7>@Tka+5{3Sx3J|FS+N|LQNJ}aWQ z801wBm;4js1!Xy!m%l_kmZ3Wf$njOgGCPftUilQxynQ;-TvbUjyU(MakvZIiiEGkV z+LX~Ld4$Q96&2cHL(>8zdlWq(UBSejE6*g#k?OIb3;~TsXU1$yxwA6kQ566jR-;HT zCWyz(izHO9E@ymk`R&0tSD;t>-i84}rr!wI8}9Bg=wWW(ODrpR0)LObCIzCdvFr|J3|rY_ZyM71 z@8R5#5l!MMlz7z36p61p+1O~IRo&-x$@?~BWbub30vqvtNrm9`nrlt(0+65dX%4yT z2JyzYU&45sLiQvg!_hZ%@;-So0ppYmfQAF!aTaP(^DWa|;@zSO%B|V4vXF>Xa?-A~ zTe7LJB98?{=hLjTw|pr$xTVt{ldjChJoNa2l;B#_Z+Z^-rxS;r2_RT+F-^DsSXbD4 z2XgM@Toq51eiv^9VCvvJmeomw2ltbHvd6J7;-4m6%DH&YEZjqM#QBq*JaiAIVpex` zC(#f_50n|<4~rHJ13Vn6|NU^7=q;(rgy|e)v?NB5miN{#DL7KER~$B)ziPf7&qoYkN4~LigET z=0-6&&p{1v?;%EcG*5F5zx1dPy;H?5rH_M{A#p-(p|*Tqit@-aQ_b2Y0U^XV+^HRL zr%=9%7Nrw>#N*=nK$EP)4*sohEW2HyQyERUC8DL#%uX-}tiHnuVm;Fp3{+Th;T}#7 zkLMF|b9@63F@=aC$e^>(<~+nZ`T&7coo8B!(sC&Q9Q4YEMkEOqE6JG(z02$8iH-M# zsQ!&V(xl%u*0Sj96h#0lsU>GLG{nFboqyPcV5zHwKBL@pLHrV7Jo@kQaH&w@&)^3U ziE4hYc?ic)crB?be8z(Ka)`+_N7@9wi7aC7v=T^HbQrT4P!b)e56&rc_$%?i zh>BiVeTTi>VMfHRrPW3QF&u1|ZKcVhmQ6(gR6x;hs`DEUffe0~N085o79V2AEU$ge zg@N&6n%a27$JLkRx?YR3!tv)R!FE7SoXaQzaxrGb0DjePA=BT}K@nw@CWPW*T8sdz zyIto#0*U4@<01JGHfOXG6{4n6_eoby(BMX1ZxcmOXi)W75RA13?W4#4E68-mT4OzU z#q3$(sC{C1e~@AAqipz}JM!vHP(+k1Sf>K(@lR96Gn$`yju?*kEKEiMGa>!8v7VxCFXk6=H0@q-}Ths_HATmouVaBWk8AHJb| zgj9S1x+Au{0=S025pCor5gWMmMNe8c805Gj`8))NqAke&42kpX`jtKuHkf6kT;VP2Sp$hdu1BmVSez-Gu9@R%bvg5GUu3Fmewx6!LAME- zULFX0Tx(ovahO>(>y}F9T`I#rp9S#oCvb^%-SJ+r1Q05Jkl>{PXMaocaDV}#hx}r^`dA= z+#5Q_UWhB=HK()!tJx_EKx@APJ(o4KOfQR82XVRkStoy~TLL8q+_!dSL~% zw9g(GNRYkW3Fw&DB7@4_%%rcm{-W3ICqT=K#Jw1(9l|1j+L=RQ_WTRbc-)`2%*Qv( z-zOf>7NLg6n4g^olAdacV5fh$R}el6Z7v(Ta_xv~hPaRigRYcd!TO*+Ooee-)=~ui z{)2AK^4IWa0B}fJ7uij5D(h;-Cx>jLI~Wdr+-iUShBu$$ij}s4@AAUl*YPD>7W4#t zg1VyhTp7At69gZi7Abv~g6$sEr;LQt=BstKBu4DXca(5(wI{693t^Upq1jT^d@@i; zY;Lr#AE=v$5o#E(@ePhxu)6nevc;XE0IJR>R~Okb42?LpY23Tp&ov_7{yxsl-=rMo zTYE61F8YtcYOEri<}w#$YaIJBSPCUV#uIXcQ`}(_o7mieZe_Lke|j#x5}B#c1rL@-y*Pk!jNCI16#&) zgsAEi1Whq9nFL|-UfM-TcnP-HG3S5-(Ci6V)NU?=?QMd-^P=S&b%@lGa~)Faa=&_B zIL*w|U5W-Q`&$c;YSGloKvgw7pozeryXKq$6zu+m62YA8ir{9AheFM5L@!b#168?n!;L1SU}BIn*a$2x`@75$%3~uvoxL7NyXc{)n3h zE?^bAaRV|s+0YA-*!)P?($VSujt9~T?b4cPHAULDADZy0yhVUqr;t|O0P#IUR zvunDzjhlz~hYjayGDqTnIDV3G$qBN3y(6cMH)=m@AQYx3q87Tj*EVw#G06TzOxi~f zAMGcq1Y8Lzg0AV61P;ejU5Um#vcDal6RSd5=}qU(N@oFgLixGX36MAz);YqFl3Y~> zsWYc4PstlMa8RB*XqTK$jgEjlzWg&I-x!#WowYv!XqG?d+Cxer8FX3@&5Q-z&bw8o zH(q&-NZ_f#6L>2wnE~>qs^-_V_AjZ=Y)Ox&Hpx!qa|z_aM+^|eSKkn=hEf3F2}7WSIHEC;-`@= zD}dS`Jf1amUGb=Y2tJdKUpHP*5xQ{IG_UrWA92+luN+1y!d|Q2CuB-w($&NYpMN}J zt#GTzoRtQ!hLwmeVX=E=eiLR*8JL=WQJEfE4D6Ol>J%1vsC$A6V&5T3#17Z2_N+1e z=z0T4^Orfl*)PUfE49{Om$In}a)_>^V$tqHE<201ROke1^)Zu|g|H%fKemwC4R)f% z2Tu}|WU|l7rQ#xQDS10+`lyoQ?);VcoVexom>FDZ%cAj}k5)-hn9+h9&ammklCOl^D8FW19|?*KHB%EYxvon zttK00YmIDNY?C$&QU1u|+}{e0SgYxPo^#apzkyqVTvK;#o>TN7hA$$v*SFJXXJA zd3l|>ZFki4R(zUiIoF;3SV(E0Hz#wSEA+_jJdO&~bb-zLrj{LF00QLkIr{oj8SnaN zt}4Nq8z|iDk32`(=^iASWkjux@h64SU(DGU?Mc91A)=2&fsO;Bdhj$W19GtUMnx&u zyE=bNEm&wFW=71Pg$XnDM}AYriEE3N#ia|YC$G?kjvMHRUbbijTq>+tfTO!9Tr!hz z%N$+TyQUsph9cti@UZ(H<{Jv39vK#`o+U(TGZS6qQtX_&Z_h1N8j9#ZFV|sSXt{b? zf@kvC`eWkAwSvA2cUPz@Ja68AQ!gwe%!&+KBk)c>cTLcXJ=3_vC^z9iLrUS`&IF`q z^Q;Mc5t{jc=elck1T6Y;gMDOkcf(h#pM0|&lLP`vM<(mm>QK~8hk|-JIJ>%ge&HT| zw(7QlcI8r*!8<^&>Uy7@Mh}L`3FeyR;wovae!Ntq7aQlx!^yMd8UtTiE}B}J z;F3FMw4Pd?QGJmhBhm3vpC!Et6r0D&@9qAEArBAV7UZDjv*#qxx-r!Cz%$lmvzg+g zOBDgH!KMG`GgQ8do0Egn&AI7$W-A}*P*S0u#MhzY*9#iQiK&Q-zfbjL%mj9avvsA$ z)O^^~1g`}jZDG)wt#@zX>zC!IPT7y@v2$}~*lj`dT=woGD##2*Z95YSol&vk6HZ{Z z=eL-UV7_|#2Jsic%ZMZLB^4A((E094ujb?EY+_-WGdRZ@mS5WW@r=d3)Ax4(ZAYAA zGAtGx|Ib$Kh8zkPcfP*i-_}@SRnA2A;(qb;AoRXJxiz5JF+zu|H|GJ*j+ZuVs^(ln z5hLl&yyF?x@p%#Pe8G#t4V(<((#X=usVf)z;uKi`xtJPE-Vx4jxhFUNckK%GWoO&` z+hSX|q8t7Q@G?M>Gk{sn>DXTsXh{r*%jwTOM0$r+Es69X&8>KvX|eN`q*_A`Ywa|c z*VS;S$?xIT#3gWk!mZc}V~?a^Sfu3XIKe98vwXhHd=>^><)JG$ck~+FY_iHkIKMa( zyYW0x69Z6K+f-pt*basyA}sR|&Vv=3CVb*A`bSA$w$a^v)zF=$I%9cQsm(aCRzUX5 zzV_QPy2}G`rtdw$RsGx!B?(Z`LPq{B<3fMpE6Rt(w!LvJ(eLT7NT zp*;jWY`?dfSPFOoTEzq!B;nun#kS2G4UQ`StP434pPeCcF8J!E=V8V_CYlLdPR;)b z-a)&+LjJK~_mS{F&^)flx3Oq#X)RkJ>tJo8(eg{GI%ZAU`f3}|79Xa;_s*IX5rIzLkd1LAHsz`qGg^ zZYVTeK#0*)VjMU}4h!`Y6+qk$zn74zEo@KUE_KU}0m}uSd&%?d`bGKqJlXj9Spt-G z2rj$U2~^m+>K@%-n*=o5U0)b2%9G{o_HwZQQ0t$P{k8ec|E=`f=DT|R>>-tieb_gb|j#CxMgqj9mDj`czTDt%N(^p1xX|j9PyJ{rXg-}7uAK1kfz!C z<0kKuA#-TRasYVFOA}#zLq4_M6037IXSIi_fzY90IcH!|C5M2CZmXlzPISIzoE=fl z`)tS6vEDb_)Y~-6P~8+Hq0XBx)j%0wbL=g4{2-|amEg5lX8|S%79o6P_4Bj$#ezV! z{j>m=y=7F(S!fIrrJ=n)?9n~q6RE*$&MTX?fr<8u%1f`nDZGYqF8{z7{br(CIwJfRClvYO+8Lr68P(7ze^zJVPXX*>?_>a;BmZ&-VWjX?C=$SKb`n92!(&fp z?g-mxJv}jgmkj1X_TZxsSof){)Y`mFUQ>_?DZCq0MaslrV>v*ZbGyn``9(^@F;jM^Zr7xdVu;0I4^6rt{UQ_0LNw3dL69I=&!(}XzS zy~U85tasL-z~pSjTMx-+G<0aGje7GXfCPt2dT+-_LwHMFW+84d$T4AOoRVvd&`>%J zs9dYEP3pQ`L}V9*yf>cKkF1V(*{avnlfItCR;B(n;Q@NMBNs1@Lp^u}F2J)z@e*P4 zQYh9AGb9`$eDP=S#ns_6dFQjf`X1>A2@^HXWAr95<3N>mbSfuc>>Hi^7v~2oRy;YY zPA1V|U@pEUgLe=K7EkvSPv&?Hr{2w2cOqRB5UgxIYOG80k&5GOw z({d5yM@a#mZ00CeO;4gGnu_@ns5sO%eIz+slcNkHKCK{M3_Sl-1LY%wqDOZEvhGn2 zZ7}d!*$MKfb^;P+TKp3KrcQBWX|;%Sv2%}%dow?Mlm+z}tUqQ;N00RN`GDF!vG4GpRRlNJHxO^aoAB~TL`Uz=brPuz(KL}-J-yTEdPW2RqP z=e>-MQ*g?ZkaZUY!{1f3HMyPgmvGT+XW5*LAJa!wa^pC-r)20w&nRiQY^M_8!>-yM zR$pgUNQ{RAfNXt;20S#=XAf-wea1;?ZOqP%?%tDjQqM-wK46CERMUDe#~_dsmUxLauTN8PTx%ZMfzYYUJ+AD=QVw-z?&L6H+fOwoF|4tbH?*5^b#wc5z|<8nDM7vRMDF@ONo zUT|x2>Q19Bxp$mAg5FGngxohyLU&YyOoF!ayi7LR`BYJM6AxPtK3!sfIK5EbCq$H& zn36Ph!*JF1r+&8JJn_ky6O5XSjr!({v|^C6Vm^E(q{wOyW)OcWqS;MB|D0>zht_(Y zHnYzM%d*osmv;LF`bHndhEG8*jK#fxFp;n<5V&;h9Zxj(UWdot{v&DA(Gw}^WG_AE zWz4n3W5mWQKBR-fEDg}EB6Dmrr_>CqtEf0(YlieBHv1NGO6OS zwyKAZ-uI3+3lN%LAEU!YE$90o*28Vu>Bv}F)HegE8B&SvUFyviD7sk=is=_?d#QLh z7{c8G+*QbCudp$I$z&mmP9`5OSrhnYH^l+O7Hhe5nq!k^E}bRI9O5=33#<*}BLb&-#10L8()!ne-S;^@Q2W z*m{_$dl>|IV_za#Gq)-@4d~cpQpQb;Ufe401S-P1xh&EK!x zq_H^j7#YcdB1;l+ZXcy^8pD1M<$fj`-pMCKve*xQ>x9@6!A|6FKBWB#pnN)w-+dzU znPsh+`iyqww3G58hMPDctY-^w9m`F>#0?Y`!hMh0nIE$IeQ7DTjAl*oZAI!LEOpxs zN9g(1e5exKm+3uT2rYu1i`RYHe#v8sBDQ#2`Smev*~H&CY(RU|0ZdCQyT&IxdWzc$ zAlYI0H&r`@bRs7t^S2zB`4!hYR0$=1^1jWW27Y9Sm(64Mku9ND>gyz$tfS(b)Pz+u zZ)m<%4F7qEq{XA=x#a;$~2i%+p-Py+SiMcz^+A)y2RbX4p;_#<6C7947J=e=t~m zh^Qi2^7K`p+%0K5E4sqPZPPj59mbm$IZpEt{PvP9Iltq|?nLnxT9ax;Hfma~YbI}8 zN4lDFFu>?~;@d`7sf5=pD(4$rZyiUro6+v-7G`Q}U@Z=MSd1V0X7}TijTA`voCGOr z>{$u(i7N>WR{tr=N)pwvDGX=IyO!@kh~}c$smzj@RMHgH0CK>j%cdfi0WUnDPxzc( z8q->96Sv-IOF-hXZP^R&s)n{qULaQ`b;i!63v~_C-Q1xQbtWF7jU7)z$zSgRuSgkm zWzu)-FaC6LB8pZO*%QCKmvPgUN+uRR&|ph&r?uYLImPR3tW^&i;l*xI#s4Um=U8zl z1}m_3^bL-l$y0&N{XAXgR|R-NOOuN%=xt#F)n?T!)eqLE90x-03CKY1{eqIYDo6yw z#VRT3^*ZbJce{nUcsdQ-dR0D>(pCu#E>ZM!E)!QdQEpAw`55eew)|bY+p>T_zCRMd z35WjPu{$YCQF?Sik_(_*snkt>l}G(uhZ|ZR&Oh%WPdZImY_iV`PrVm7)}Of)*yh%jYUzcZ zqon2PwF6$CtlH9Y#z;VXT`=@c1uk`eb9;-?-W`dJvPW+|Mb1A4Z3`--Y0u-NQE%G3$azyu;aTGfy^oV@dAwedIYyN~<(vFTLr_x+sB zr6a0@-JPQxs{a^JT3r#2v{Xx462J*ZC69`$iXf544NiRjKHHX}b$NW22YpcHB<-%3 zx990i!tY67jbIi`r2Av8x&Azg{W?U%rk84B-i{(DL=(HzD{fZ28YNhx@j`Cq={)-J z-P-c&ZozAUIh^iZ^E&;}c;aPoA94{&DF|q329r+%ioFF_CUniHX#U zMwO^S>@vv|7Pe}r@zW6o7K1G>K_>d6-3$xVJ&3&C(a+ZB7Vl0XSB@tpq2@5MYIdiE zV}ibaD1&aHd`)bYL-pAqV0N44bLEKpS-2H*nMIQIREv+dP^#$LOi?GkpnRf3X)BlzzyoNznT=`o z6dw#FT8!~GfS+Lyb@<~3#0lTZAjJ=oh3wKt24LG+0C@&n46H|~2|(+vBe~9NT5(Rh zy*pis-)W!xDoELbFHIii6s40L^k6t^W=87_i*neHe@J0@b!;KCX=vF~t$xSi4}=VI zom;1{YC;ZaUF-=zl{YJ03XgkT%xiPD(nKp`g4;dp=^6OpCI?SrMLqzH5iA;|ti{0L z{l|6A4aP~Nu1%==zhiWw*%g<;vbHZxE*>s)#nm)8LvGPR`ko{>gxlMvyY~8il6G#% zWV?L-EVfX#RBa#x?DO-4MC_f<*Ldbv#s{*+N`nk8DOEV*;8Ssus z(;ZxwS2t6Q?Mu$QlVzBtphh|88KO`IA1msmZi60q67A4Wzv?nuR~H=G)+$@W$O~KC#%|`4F1P#*#CWu4)op zz}^MP(H!}Dx9cz8Z`qDz{s zAtfZIV@DatqnTdf#bGIW>}t{2%en_msx|)1P;itO(jPZ@^qL_>qGgg?91>@Kc)*4< zj%A2_1`4k>9+G~yV_Cl+u~m%^s<^)E(gx|*i)7$xw&{BEneV>N0AD*OWS54Z4y%~` zbJ7bW$vv|zfNoWs4h|aL3uHFY6pzhxi*8;p?fyV@$hm=-IH&-jVO{k|ZgRE|l(ePv z`_ryT@ayjtRhJKkbn@BS<;C~+@4ojj>UUZjAr_Hi6+;?U*}4mkUfnLV7!oRSR-5eQ zp*_5Z(oQHi(YJ?h=|85=%vJLKThE;BJ(wixx5L--e6zc#=B&{ZlXe=fF<+w3HgDg= zJcv<&52Y6J8!F9Birt1wzXK?imKaB^gZ7dcX>qvM8ffk5qRVBUTi3T}Frp+9IOrBk z(PLV;;>m2^f6bgq^#a4TByc>{|B1McXS(_!rFQv-IVb0Yv-CzK#gD5>*WEn9o*&++ zve}}sA8*SXrE`4p?Xds~?DZ4cx;HvZK`=~+~t1tBR zv@_8*n0b)2B1(xz2+A7ppYW51UyPXiYN_>5xJA2H&fzt>4XPbDtScG|83K;w4Gb^* z9F^O%G^M;^$#!0FNA|2Eza?+7r};y+O-_e<5aB z!g<*v?!bp&W}Iu}5#SDH?bC;J5?X%5+byBe(e;Yp`ZpJHJsoq*ui}KqKyZ2m8oRkny7!vi&m@M_y1U34*T4za5zskpyZqLhV5yjR zP~1;X_j{VUceXt9KCdgpI@eUh#0m_X;k5lQ`KA5eJtO^f%#FRz3xvs%WBk>P#7>L# zYV%SbA=)~C+Yy`>kJsLsN^H1G%X!S@@C}~Wtm-uQ{`UAYlF{H~86ld%55-bCx(iFL zCJ%(F_SJYlM?nt=N}=a<#UWTjVV!G`e+Il=ckOCa(rY!~gHliKk=rm{ zn`yhDYQhzZ@2?vqjyqLDMnbu{b=o9FqjdgYT7> zNWCTa?Z@sH0)@J2$k}Zp#pSaq%g0o3Ed#X$%$t$1eevJr@iO&$4c6u(2dcg?FiOq> zzkpgF7X{y-P|Po{^sKXA7B{I^>_PgcX!2SH{B4Z>{K?k4<~yn=E9ijf`qrOgKzilu za)uUD@a;0(BOH?Lwpe{752JT=VF()TvnzN~F_*j)B~! z$q`E}T;V`fp-@T6xNx5wA3ILJt60;drCy&wB~GPq)}eo4IiVZ1d-p5u^+Gxyks1mE z@-=#2%o|Ii$_`^9eqOZ-B>>j%QHI@-Wk&tIy<{95*8!;w`YgZLdq$u;As0EDJ4Ahf zyQ!CPwl}iJdjV*n)z_!*p{~px!_K3uT^-xhvu<^{EtZ6x%sWWZ-eRLuXEC$`hnqn4 zTFi29Zx$oql#njzV?D2^F6mNCo`LG7CTMDZ{}sHZbKZ8_NuP2*YmKPdbMU01aw=Wb zAywJ_K-rhKHe#3cYDd-kP$=4q)&i1qB#?(?Tqt00_kMuqd|q+H6cE9oOuT8!cKSJ#rZrx%b3_(~#p8apwBWN&2-=QhT1iq_&Fwjtwb1kDlU^?)FM;LJ znd5S^SBaxFuk^QE>(-+J&&V`+RJ_nAcHY=7K4ONu&UT5NJ5R!JpR08?#dFu(g8B71 zeuD-s%0aDSh-CzBAl;<=jbRlf#Q3?PQEY|-h6<&;K|8!5hq)hs-@P|gxOPKY&P_>I zgEj9cM)Jg5ij}2AT0kOzR9Q638dZIzn6*F}Lo!_#xAL*#9kTh@`9>nT?^PZ7)NG5+ z+V<(U_3tvBzs+4%M`T-!?y2nFqr}ZVkIe@fgjx8t2bE6cnolC*yIRj3Zc;+d<&0p1 zKz?jA%O0*<@IXB z2WHqG*R`sSCunoAXGYAWoMIZ6bhOi3PFHb6YIBD_L~a|T#Mzn2J@>4$C-&d6+`@?7 zP&=BjL5n-Bslq&6v@`1fAXc^K3X7~Dl;G~fu$_yDq6hleIJ&Hjk-FneR+Zo@Bs{bU zmd2vwOaAn&S(Xnh;gn0bOp3ubWWOmVi&Q8rOHi*Xk~2&a zliEHQIKPX#bv~%Ab^daF{K8vUrJ``qj<<_%@8zG3W?$!Muc$-aSOquVdN zay(Wp?#@|FP9wO_%z&9j_Ha!<5t*rf9M8?&b)yFOa$Pb8vCk|n6M@}kFT}iBt*c|o z5EF~n`V3}_G~(9?ePy1yDs_Cj&{05ANWg7uJgBYI;n242dad0a8@#hIM{G&Y2|=id zl*bE|DNnBrgPb&SuJh*hudYv9X4{*jsjU}e%Gg%!f|q_8uiyH(-vD(~a_7NGSfO{KKZhrTL`xViYCbbrC`!Igr`H zXwy&BlubPx_U<^5RtEk(M3ftkcDFA59m!NK#cxn z-OeHSj4y1+sk9gz)K`d8?16)#JSf*Zn^kwuc?VX1hGx9=)V9>F z36>r2O%~ua%g_BP^s;?jYZ@W%*{=X6L}iGSzLfNJ=#9%2U)dLV7{;0dh}Y77ou({E zh*uy@X;vpZt_qZW9(B6am$LiJw4Ivex{j05Sl=CH2MV~S2o8Yw&h(s`jTaLg(v4;q zIV<|NBssLQvX}ld%+1&jQy~KZGj+resscJh1(l0*xOTq`7rwk;JRO8Mxv3kEHN;(^ z>zP1r&EH{@BM1R3&X59Gc6iKatETMa0qx2P6u4uYSzMqY$y%wNG`+5`nNO>PtxrMA zk>Qhe)C-58gVcBH2UaI9^3g*&M?ouRR<7$jTuj7q=iXn)Ntd(Jd`G3(!Z>;n9qzZe zDsBn?dR?@^jA2cB|ObuPCFK(bp`*Nj#-Or%@&}AF@Cfswd*MnldtJ19R!*r zt%lt}1HB36L)Ls5`S=zE6VvpOdHkZ!O6?M%Kas{b)Pfw*{Z)<&GI*$vCFPH{E2cT= z&cLnQfiWs`-C$1eYbDP~*S5$g04*TEXxMZ&Gv_^VwJ~cmUf{_X{^IDlxQLI!!#M9y zD-)c<48$g}DPu_Tx?~B@O1*8hXkH^}`*i5J)>99Hg0m{0O^V}ezQ{7x|tLoORk^?SH7FO%t)p40jISGR^V3fvb z!p#O9#fO#GBUJ|)VVeJS?W>0j|2MWoQiTMbu~U0(G{pBM@KvMhtGnDe{9j{)RzT@E zGjp0~!yI-lv%swT zHyTb*UgB2Kx}7+>H-}%8wkr(dS`m22nrCqv^{Sk#o$1x{N+GUR5J_|I!?Wu02^+MEnRM_@{sawt>{zD`c7meXbbUDl|= zwO(tx$`jJ?+)Nhhzp4@LpW7z(mlIcQ{VE&T9Q~&v+OutLN<&8v_f9|S^Kr%B{y0lw zS0^$_H7=MMj;$oN>}s^dm$fu{xEPg1Z1Va7?edkhQ&qt_#T7LZ=WTOo`odi`yNe=g zwyY&;OZ+9Pv$8Z;;LF#p|;#aF|ROOQc=|Rnwz2*P|r~$PuYFGBqR<;%p z3{gDG+GxboL?%P?6P=Y?!6l(CQgH+}C9B2YO^SJoYMv<}`23Z3nd2NI{1E-UgvGj`YH6yV^{E@?PL`_iU9R$C!q?yHOX%M0c^} zsC)Ti)!{c#LaPIs`%u9X43gNl9_EyCu z&QxZ+KyV5!wklqHiZ3Hd=$SU!?qm|y;tObO@Tb!&(&VJP2QRoU$)bR@+ zbTJl{r9tdEtLD%v8oGnMPnF(WLG|uc= zk>8tEf&q(&Hi{RS3~kQ~aA92=2z>{N>Q^lbm)bKxeidpwo4F97@fGCG|7~5aA?BI6kHFyftNkgYtrqSK>KGD-Ve$OZsKi!VOF+EgY3;15DrMKO2 zh>bBKfWybU7wz(fd(?bRdMn;_8&2%(eHV0&i%%)jj)7J#r~XyAYpZe7to8YQ$Ee*3 z$jttu&3?{}AhXDBQNzubmFJANr#P$1 z2vf;cl40Yrlg=XlOrJE>kMJ4J(7q=gb{nIyN?qf68F!CC z*AM(Zwf+C>w4nZfPUpLr{@Ej75-ffSSeve(NX3r~QlKtOy4; zbUW?|&|x%Vm%Kh-&m0jCI2!hS3Ivt5CgefvasqNT;F9Y?tX}t9)^4TSTNEh@b&o<= zyIq;uBDx$8uGupQdic8~#`E$nZ2!RdUd8)^V4@-z>3_DK2~kOIW%pX!3}p)4u;sS! zW+S=5Qd<6&i-~cn0QI*Xx#00-{vu^-bA$)?hKZKq`D9ipo*(}W<DtgQjkQLITyx zkdS?`%ZB9m%O=LsD43Au3XEnO3&mMv1hkk6 z)!Z?dSJJ8aSj-6+5@@sv^1qycUST;6CG(3QX`$Xgc9dIKKnnMK=jK={Y#oeDJC%4( zYlC#?p>-N12uIp_YBKOjhI7^_v|+PdG#(RUgRcfvVl~-(09}UDR75az)j^kDCac*$ zltJRcq!k;JPF-#Fibfnc$xMKlsMDBwoc(gBp+d}#lC;JwK>a*IVj|hSX#_{`vz^CF z%9?yVyQ7$_DO+|_y%dXXnkA-5mg3fX>iBnJ1`CX)G{&S^l#GdwnDD^@=-QLaBNZ_t z8fwudl>vsQ*C}EJ5{o<&PmE3m_zK@M0_|vefpmfw4yuFU05~II{y(9SH2u(O5ivl+l_qrQKqun;058xpK(Oa zZ#NIhEB9mG4x^5-$%A=@zxy!{SV;apfn~SWU2xJ)Zu|Sg#9*(%jPd?U{K9$&U4-km z)-dvp{>;Asc@KFVaZJs~*B)|S{8rSg%tP%ixlIadJBb7W3ON)@f7UX0*-1?R+uvK? zXBuk<_wV|cBK(DGIS5>fxVf|6@)0TSj>AXi*TcSxA(~$ZVqO9ludR`e|5LP}fFcA$ z75xdRSENLMfUX|@D~9x+X#Ee7F*7%Iv!eeGL;9bz=H}Oj>(-dZ{oP+$Bnz4p1o16t z2MZbT+XWKy<|L`K5|VCCY&fw%6dDvGV5O$yj(`tOgYNawkfPk)8FP1CE*7qqrGwd|Zb1ltA5}~5 zM_8waYUa?zl8(ptS*AcJU~yabNS^}pcfyb|dOQ6aZy>WZ_bYRU%ULAgNIqOiqmhtd zs563TGd=@sjz>zvI32vNS>dpIA%bxuE@My-ctD%s=!2=t$LW_D-28?>5Yl;1n zkI{|E{V?ougYOm8vQ?TDOYKxR0lCc+eeZxa3o#URRGSNN^PWd8j~qx8%VIjo@EoIs z%h2b5MvCVJKL{euTNyuS@h|Rq?kz0H!p^(?FJUPb8Nqx<4dGO8n?-|vPUoJ&S;GK> ztgv0~DXJViBm-&yFNC>68A-(+jKI4ZsN0+f`I$FB(iX{rI)To_$vIgBfH#TiqOU!wy?=iVg!6YnazMlqm=OtKRuYG?$ybbEkd9Ix(shKk0+VEjJW?6? zNF#d+s^RbTj?<;wIA!znuG#*;pQp*UapQmm&t1R34A3(#zi(p}zYmAg9^BurkSUb_ z+?Rt3D-P_w&dfMURWQK0e4$Io?u!Ir?%>DMq!Ew%7^`g` z?!$={(;#!^u=_4tL3uA{IjCK{#1^3f#5gOS#`g^t1u~EKri2jSY48E5Z@34}NU3)+ zqAf5F;rj?=YEZU(kN2uKjG2S*H@;TMQOx8%+y{axORpDe9=s)HbI_9q-z}g;5i*4^ zVm#!c(3K~DX+&QRayiT2akcmq7)A~+HSo@np-eP;=)j62Q;uQIa`>SF+}0nO6^#Ez z_(ov%#Vgd*VjDY_k`Re)4zgBatJ9A&@C-HAAiI@7VI0lk&dUNLgucD5`}j`PISZ92kxCFSilESJ*7fgmdZd|aRZwByA zSr8suh!-&{Q!#I?U!S|M&6@_5Wib423ChNHws!(m;K8M^Kng(E<-_^lX4nS3T5ra1 zKWHD7hGEV(w8e<8TZRICnR{N!Xmqx_EHoPZGKb!YW$casFMr(Bs&5nur|Zh9hS1VW z6%dPnTl$QI-tcew;rHRA(&WGHYEQj?%pc6H8P#w9pvNEctallAk~JYNw(2vc=n! z>jAwNNn;y-P$_S`U#eO32xN6WH3+qXzBiFZ`76MLq=^VMZz?t7tvw(&MaIOtJWQ53 zPD@lYp|;~a4bSBAhx6bQ!Y2$U>Oom49TB0Sdq%XiaVzec0-8_o1w**FIfLYmL-HFs z9Qr(mtNj;20AYk+NLe}8TmR2B-lWVcBxP?5AgeL^*6sDc&8efk9CqO1>=CAOmf!5g zibWqUN;YMqth_2^=Qb7QHxTYC#ulEK=d45{!i=f=nGRenGgvO@DIwQz&KrStzZvS{ z^JN&^1Lyr@JCo>Bj+3+ru*2^JrSXdP}mm+(1grV zclAC`ED4r6?njVeE?4l$fM<5`%*Uz-gt{llLs`+g{K!qVD2Uv>DAtRL=b-LD%Mw%J zqDJ{54a2ND9^*7DsMnE6>EUKi&{8XHG0os1UEmhyD#+?@FFP$rw37y<<`7J9`KZztgYCuD|B#uO9)^Xy@eJb;q6$>NOdukSZp1- zUR%?D^&UJaL=$c)WFaScADGSpL}*rZK}u%Zv$&X+acVyTt`q+ zWp(m;+v5X{Is5Qj)mRc8aE{2B^@$3#CaDk5z^*VgOt4Z;{DVqidRo|=%%FUX(V6eYfHAXyz_~$(m5`0w=DmF6yq8lZflQ-=IA;pwXS1%r zXJ27_;%MZ@WT@143h4rDd9(r?kJC#bel4FIEB_D``e$9@wlgMuUZJ5fp_Af>_<~RI z$0?{0N+b{=4(=}@+dolr504-YM`^SfxQdkP*oCpM9}%H*yRWZZOV{C*1dz4_Qm5@w zq&0Qp1LrkNLLQlvpG6aPJRcupqNAM?L6K-nogTvz;+YU2UE9~ls@tJxqU0gy&^_#Eh=ECH@X~0B40L25^3kk3*+XFWZ)4q};t?bhCD;d}!t5YY*}aQ3 z)!4+0XWDp4(*^tDGNKb+wm_FVRbc=zEdZzOR}uqd&#fh#r4Krm;MLm>$-5;pm>QD_s(a; z7F+&L^e?LR79g9*NRPme*{C((M02}Tr^@vvpB=lCS`z8?5_;q0-;p*fK@dcG6@Eag zII;)R2b25!Rpr?lA42sE5ASZPIr?%pp6E=rrPot+{+qriSzrx<1A~Nbjs#^TP7RpL z{%bdz{nj?hijCR_HjkX`mH8F!bZiao_%ZOeZSh=2$VX<5Urc=b_|H3>gxeSQ^mw7S zZ{vezEZ2y7+lu{5`2`RuMBv=ViQeeF>{r#(=i6-?8Ewt;PCE2Kwax>fKh}sp5x1wd ze^U+4v_>7P?_uJ{uuwLYx{dCCCRxE-5%-Vn- z>Ls1;Kjt=i3~A%9R!m(+4otm&`<4&3gwGN!>lZ@8`&H-AAb)|d7u-_0Z2&t(nIQp* z)hI5<+6<4yMQd1C-A1CxPTNRW4-Mtx3EVLWsh>T1@nJtR&dsf4F5hjg3O$2Y&OdNg zyYIK-M66Y4N!$0hXF#4z{UOxr zH(jWj9gLX8c*jwiOErN_jzM*?QHPJkp`ge#jPud%6jWLMkfdsT1zN__r_wbt!-~Vn z<;dHQc#T0w#)f(KA0b6WiRGt)9mKMkUf@*tdWq{*+?$cnG1bS(gATN2l6< zrX#|0qgsh3-bUw;!UIEt<4vBs4NHURQW>ICV1I5N>;|CIQAgD;zoK{eBfSLN|S{EFv{AF`!vdi-@?CF5G-qmwIt$-nC zFZ(2}y<`c;O-QKoYLW zGA=axs|NCl2XhEo$w_b-_=JNeH2F_%k*b3w&x|~nvD17>!chyC;xh_)7*I3dRttxLuzRDVRmI_xBfZWF zA!YUnd73>_22Wl!kQ9m2w0+@0y`x6xFl}h%|6p}Y0>umq8<2d z2SpPvtpD)(cBH-+GVPiPWd*`y4{Ww@*yr!I1jzu9LBp`CfLyG#QCA3W|!sgKbXkR3JZY9#8>7(^LLVJ*zigga1_{Q_ZI5$tZHXbCr-cqy34tgI^ z-x(lyN-TRL04vA(R=F!5RjhthjoIVP*Pt@)^g|^o+b9A1)7w0qIANBaie`0P)Ti&} zS*TH*96p$21LXBmn7MnW+F9)XxMcj>uuSD8CFgCk(%JZ zPGU&+LDHw))2YG_%)EHK>h6!ACN4W(C|fTcM*y7|E=lOpyI96kgjmR?>Cs!MHL{ z-R42k;XVlejQM4W>GvsT{Skz`M`eYo;1kueL4(-aq$fFz%VD= z9h6MQIAy%4ZpG(6DY*f&Q|Uft(tN_?0(8&$9M|Pz~V38?? z8C7K)IPPevmd3Xf$#KLsZ0`NtTc4M*TjMFCOASO27VF;0Tw_0rzp3BoenBxQ-mv#+ zF63?nNkYbT$MP^`Nn^H3qqSroe+woN)<=$kD#TMC=2)$2)p%b({*OFq)&iT{>;K;J z6h!?Eg07?(cSCSH*;ne00%udz&RrdhqU(Cl4z98F{?{=eB;?+`4%JzWwTgvDnE&JA zq*>H^778p_AcM8#rD~^VqwA}7xyM3!2b4my{HWa_CB0U>%EWGE6#}gzM~_e3%@Z^! zs`6skX8;}}zw>Gx)8&)1x7_S5%LnHwq^o>0P824oKgD3;97Eu%)7VAn7ibQAG0GH@ z>p_tA1|c2xF};bKH?8X|NV2v$U3&AB zUgZc4CY9?^rh5VT9a|zKU;%NxCI~jQI}}|2p5yHF3DDrRa71Q=&S3W=#!HSxA0&4j zaj`jl>XsVaKuNmQY@Qbu0r(-}u`z||OtYwq_jZ7KV23))HO>)!{H5*T8^=ugR(F$0 zG}%~=fK$kYr#iOr^V!(}!1j5JR%aWh>$8pjF@BanQHdu+DX@ zLCkfOh8s`d!Hi}g?BGpGLS<7O>X57>^?f3*I&*zTx;*Uc>eLykEF?VA+Rrq#clDfa zq}9^8=p2)|4Gg5${&9#0{s*-$O+6^vbj-2@W0g)=^4;&0U652V*`;*J?;k%#FjuE; zmlZ0r7^F!2I>4l%*3Kc|?e|CF#8k&ZG&kzhVn^KiismCzb*|231Z6bt&M!ADvcgu{ zxEFk#X-kD=rRlvqR@q@_u8cr%k6g%%BKm@rbiygF#r-*UN=ij;~cpM{F)9uV{;!8sZql3UcqXkrD# zU7m$tShPyZy6;&?8S9#}L7C{olANNh07|TY01u55wK%+1uvl( zw(E`-qQsVAC2t-nfer*p@{94=1@$5?0l%DIo;B>~Qv6%##a4#vQUjFn+RWkfrFY>isf05mG7&!aOAn|fzsRnB8pikEjuE@h0P?=NGE zWON~_so;ob`gy9A)e({Smbo9HG!><1pc_&RIB^Qd7Ksz|ClG!3v947LiaVcG)gb*d z+9)ObBx_E^67B08uQH#40)nG?-v%l?&&L;wVtGBA;$I?jz2 zV07Lg#3*iy(cH&~ZLA>mLQyp)UVi)XL*f2++JR08Ri-KyMmJ+BgfdI-%wxnm(C%~IvzHrzjt z^&s3P5J_nbhX_P`qiyT{OIz6afz5mPua;E^sh@e)3te{lhB_5SG6Qp^S z_1B#ei?^uYk5b;qU4v;{tyCQW+#ihl){S zq5>jHF0zr|!`57JTYjtCkVE!fG`VqhFI-;4XN>}!o1HOXvzIhw2pE!`F!z~>9xO}n zAGcPq0g!Y3X?T5ID`}B^ogsh5L1p}n)y>N59Kct|r}{~&0NI@KgdxB9(fHhThN|=- z&?cI}SW07s!jCWsHwU*xf6s84w5GOMa?LiNx^2Qm*3@X`AiWWBp{YMB{XDmX8H>s& z%Huu1u=If#hnuITnvwWvNs7%NA*Gg>TC!)tOl{m(c<5 zH}HqzGt~%JF|MPlK5Te6<(9A}aB5D~hg}{GV#AQag8^Sv)Fp~T>2KYxP5I@F3>9voF%O^k*k=EG)pjUrSh##1r(AF-$+FJ#qitS3Pg2mfzwZ^0^pqoTunpYmgn8G;W1Bhgn$%$g zS=otB!CP{TMm^E7+QgE1wcf$pnRIfE44@J8i3jY_(FdGa3@EMy;wGAa|mb;IL2nwX&M(g=tong*!t}}F%Q(4cP4ctwzIAi`I1{wn-IzE zPJLX~VlU|usHUVB;{khA;Bm->{AWE~S>ugN$O~e|v>?rGd8MM$nZBLWREYaVbDAy_ zbE%41tK*3YFTlL37^*gS&OBK}(<73XFqySKyFmRtWEo9fwkJKX+oH2r+^|?0gTxR@ zf;{Q!=_2-+%Bc2OWiwe`cIE7{8I5Et;UZuzTZ;GSNYhtrO{b5dZm?1cm{3DZJh zPU@Ty&|r%YXeNI9N{zEJ7!OG+XhT7;7k5ki=2}IG`T&%4c^e%={Qy zjMh>!swphw{zB*s(YXuqrG`iE#y^JHWD4M7DU^X`ddP67@^Z&#GsCc~$uN_C!^G;j zPP{bPkuUdV&n1M@@@So_5#1@YVOH@!7RKl|>a{c&&XB_p%(~eQ!i{+~i|O|;Zw2vE zI=PZQPFQSpMdw%kV zq}9#tN7G*M<9LCw-qTd&ytRKFY@so6UdW!gb0aEDz~~Y(JUd&po^yD5Azz}tUS%SL zH{28W{x1AV$Un-`s(J3-{zKC%F3V85>B;uzwfSqi#-hFJ4>4bR)DI4#G^|(`^)P;Y z`KYXr+X+pvMliH3)=q(DpUU~AK-L`l`ira@?}Bn|eliI^1l)Bg^~CO5>)e*aiH7B3 znz%!H4lDm(Z6Fv#{>7C0xr1(m2Chbqp2!9 z1CX7J=p*1L*d@CoJ8^!N1{dhwZPb2-`SAh5=SotU2d>4IvdFGP#iX}XB9*evC;lKR zojVoNzEtX~DVy}OUDb>)PO#B;P-e|SyUKEaV9-Wd;C((IM2oE|a4zD?`>fOCIrT3kg zw@EcDW%t5uVf88fGSL#dbKvqC#FmQ(J3hQQsP?(@8eW*l`{^#^DC?t1_X*GaL1#7z z);7&Vdm|@nr)`6UZT1VQJ|vdjOy(GcWCBaM|9Mn>{>ye<&zi+YguLGK`nNB zH9Wg5QV(+EQV0P87yCJe-;#2EzN*(Qv^2?X?yq_aPr+7cyBNo1q39T``KYOWbyg`C z+sZwgtezq-n3gw2D|o_dMw30%Vz9qjadV1*n5)rV(LLrP2~%Www(=Cja%DSbH5C$W z!o(Pvy~5=A96d*M+Yy75e%Nk@*VptzNqyWCv+tC5P-o zOB;bFF~s}7FiUfRP=gg*kb)nLI}Zc|3=w41!n@ZSvaZQHhX_GW8$@BY5%>ie$h zs(#No&l%pb&^BL}3yvjyVFFcl+6ip53k=L<2d%;zn@HjEdWc5K?;U2_gmKEr* zU5Q>1IvhR=)V8Jwcn)3;My2QnKeu#t52MEKNaR00HX|$N`I<6s%JR=(MX_EK;pgCM zwXiu0gCQU?3{GMs7=pX~F^^vh0h^lJ^oS!Lg<^jjp_TR1=VB4cmsd|mc zBm{_#|5AMldN|EPvaO0Vy*-f^ zO$m9o*LOf4y^KWS+O7;msU=@0{`*FuXnQABqsW-wF<2QVVW1Kste&cadJBqGhLd|$ot``4?XKjs+6$5s{y&L9qsVtrGX#ql zmyt!v14{%l^Kpo!Q);)=BYsMNLGSHl$EDNxOR=vsdlhA9@2<1?>^J{@326DM1UN`*3MSLw$}@uZmS^PM|#V(g*Ol0RI{~O1&Xb*R(r$h4jt&CL6m{2r>sjQ z@0TErH;m8s7m&-3so5lbcnOD0jtB&;W3+z|yA*2=c5;#Q{RX46S}~OcSNU047L@LA)4B|UF~EiNUZU%BL#U$NYGcZD#ux;Eb4_5T3+Y_;j@$f8ZvM8R^njpIG$}4ZgEvCEt@Asl^ zhA85+YtZKfWc>X>#Jb)bhziz`iMKo=Mh-J>Vr{-@RP;jKd~gyU6k?Zu1(^Q0*@7{a zHU?KhNv$7o?KxI^AvMvxpQrIa$hZpNQ=Ofmp2*k8e2!z#jIF-2!K&8H>tmEl!K&J( z*Vl8aWE5ATJl*Z9wTJl$D=*Wz6_9HW>X4LL4fNAP2*Gr~^^v1|O^n#8i(}5&Dt{a+ zY>$g3wf)MYm3M~jR#xIUzOUJg8CYTEwYTO2{2M1uSv4G1h6?8)T0|y^dz7=ZP_67N zZVSCLpO@CEox3jEzjvhBHJ6z(s`-A#s%9vp9KhJyUV}vK#vSBufU6XC@Mj^RDkJH% zdm+9;yFZ3_Vu<)IJobN_S1`Rm=#UA`dJ{B9&Gzsm*9^X>nqSH?BBCSNl1DMU7Fn{L z;c?Zhi)pofn{6$+Xlrc+QA4Lt-TUV9Rf6_gQGK@OW0v8k5jO;cygUrmn#umAQwP?` z18wDss4ui4d9YMwr2%iAK36U#<8`l^e($Hj%6#NDn$u;5-r*1U{+P&pGPwt5?ExD~ z*o5?O`rFS+SFbe8RQ)7xdO(+>mJ+=np~paZhu8-?bhgS^B7*k1RngxOKtlKV4yZEo znRFk|BBp@sMayQAw@^$9R#@HqGbwGSf5;3^W{9Hsc~qc5sFNMOpBfvPh0OLTj%DBr z%csl;Jj30Bd8_&H`nM@Mo}CDf`{!*N|Hpt#qzz#q>dVo2hnC)C-F2J#ajbX^zrM`V zqE;!2<+;YDS`PPD9+y+6jVagp6jLMwL84DN=NA)?>qx;tA0a;jH}&cdGB(RTU~VSP z2<%T#gM89^pXFt~kj%)40G!#i$?U~~>1_`-;tXU^gqJr@PQO3+a4xU)1ac2k_kFyU zfS6P2EK{t|JPy3v6W32Icws4Qh@u!&9I}630Cp!G%C=?aQaZjtrs0hcPeDRjeA4m{ zl)Fgr#If~k(;ymf2rm3hbuU_#bGCyZ3fKxpJc9vD&k+W?D*s2-ye|Xjmq3{AZ@G# zN`st#W}L6OsnvTgl$_Cw5lo8;x_y32wNiifAG{x}>>SIaZ*K$|=#WB8YC+7g-_nVb za~BNQ(JjlVHahlnvcV?(B?G?G5>wVs=WEJaAtXsMC?R4!;MTK3JpMy6+|44k!l6wk zwf*sCpe0WrX{wujTI`BT1NP6%Cqr?psSc$|gLEwpn&Mi7uzLQu^}7GhWH?tXt;GMZ zcoNICvs7~I?0t?^RaO%%|Be@_LJ&AN-^~7z^oI+^u)FlHp?h>9xS9A5J=c(8SaEF3 zq=aJEk$*r?lrEzqKkQR)sp7{ItN{-xVpzh4A;qhwkdmL8>}GjX6w7z52iL zJN&QQ2ofY5Uq}9pTfk*>y5C3skADA7-tud<3=)3zMK@ESos-gOj5uOSg~#PfJ)6w@ z6ZoKz#JhBEa9@|mB~dm3?UPF#7V;7}0B5jpmB$=9i~r ziUOD6a76!e+;|-S&JI-yk zNRcROgS8DPT0L+V6J~(x&J3w2+2e3}u6okp@wp@|dQ^)a6J~)QlthXUH3^FDow!$} zXVCaU4ZYYPRW{P2|9b{#vmV2Y-8{ED@Y=eJ*~B}#eD!6P*S;)mzFSKWkBR#FJLL$azhgu|+Bo27}A39`qa?1YPJ(pK9D~#?;f(}_{ zu99jq*BGC%S6rMh1}AQU=jj=D%Z5yfw!&s@1*xOsld@^NRy&us|Hg;5M?!T%enxE{ z0XQ6Q(X=43G>ln`If$%j90^v!U#E$$)h{Y0(=K1^Vf4hlQ2ZE^WBn-VUP3R%5O+LTWTJX z5ig&wlUPXSwa$&_QX37?N{BfG^{!n+;BTZW_K1}F_=PNV580>8bJhbN5G#0AAX|tnX{t-9x3X6upBIOS0DXo5( z5~ABZIgLtro3Ld`g%!e&NKbY@_^)?Y_#w16+1DL|z_T3quL1T|$~L=!=WTAn=emjJ z-4i>MUt>qa8KbnWbU2GaMkxH$}{&X-JT=m+qbG{joY=ah+eLI7iJT` z+N0{uFMPi>c~PaDzLQQb#Gi78>CuzS9bl6e-+~pBqervktq2Gu1>=A#BmGrwCf>!C zTH8^u9@xm;=fcy6GN7RJpy1)lX8fo_xnZ+^n@a$*v3i3Lah8| zhct_#AF<>}5d^L&{}o7ApkPuy0Cg=WbZIUg;-r`H4!;b-*4Qyo9T0qt)j4Le0~6?* z+mdBUbW-U?)KtY=bZSXzrLAb;mtiffzNICHRuY)rtQZ%G9&Q<;fAqI*_Ks4yu4P7r z7PKTiPmZ@;y`>V^c)-eB2Zm;fvw;(>+Zi*}swh*Vzuqq|ClKKvfQsX4mN34DqOXG83Ji3(AE3Y>m zp^2ZN52KdUBQbe9gL=W+jf$Eqh9Y34I0cp(zfKNbgtaYx@0T4THvQ;#G$Uo)mo@}P z!;ZM&=I(ivmUWDlOXC#X6A{nB3tiY8e>^Ti=jQ>pB|lMKbY;<^+G^MGGnnP2eS}og zU;CmD>G1qIH}{YZ^?Bx%L~qxXHse;*QQ1fCOnKCTfy<#VswvCaNMhDby903^6QZb{ z%na;$;t8i|yqj?rrt2ouxrD8?D214Qsg9=*vCMGdL zt)biLX}T9YHbJNzF-jY0NAITW0CnI_5MvG!)UGM9tX1)LOG~ndpYT&1!bX7!B1lZY z>Rd(z6!PVNpoJrww87jMCDH{Q(K1ni3cUQwIHn221W-Rbb%>bqrmuNu84Mp-EA|Df z$=ovLOb%PBlktH#3R+$6LZ>>fW^@i=G%yS=`fpy!uv}a1u5D~ijU&Doc zwz1&doVS~P(Dvy3z{7THdIEocw*~#qLAeMB7$_Ck{|%4-M;#!)vz`a3l^z*qd%L<| z&143`|97$XIA)=zJ{(mDG@cIb zT+1d;Y^T{t;@?eizZr>VkWf7G%-&bJbz+Jw;-B9;!5keJEEac@{yF@`O6rt$yh4*V zLrX*okx!D&^Kg7n_K*|84-Ig+?j(DBd=gE%|GiVY>fi~8)6B{HWZyaDPT0GRM)SwO zF*CfTnz^M&z1o~xJhuzyZzh-%7AigoAt~MKd+=vWwJ$Ec=OL62yNRYPcZ2!9 z=NGk2`vmJ4q18i|k!lmJ*WC~erVdXmqiXf9!yV*Y6f46T%+;xQQ#LX|csQTV^s{)g z!`<9o0^un$+|d>{Jt#Fz#Vh2vn){qRb#IAxCF%k;-dT| za9&Oovc_J_>^$CaZDk5?lYvJH10RV^L3pjR4KP8Tp|UzpS=qUaW5uDz6tRW&@M;ey ztDtUccyEo!NW5=h-|lh4&`mBn2KOg^)la?@T^Ar5L^C5u7OZ1Lw|^LLBUWany0AQe3p2*2;3jO@Ki?}Id^YG!C9{|}72MpoOJt~n z?eiwK_sb6Yayp|FCL*1A_66xm8(Z(T#NQy_i6#jG5X*(BV|IpUN5U)Gl$_$%Ot1Bi zq0v&=?q49mq2*C=w_%yXv*a~HL ziv@YuNSE*MMFV73HX+o_xtwOwc!)u-^JMM`cKQiI^?94!2ncY*iH!15G(J2Hx+il7 zujN8v60vU=$;eh^~@3<_T7{2?m9VAsh?Zk%DF@QW~?=DwXfe1I1_3-?<`qun_ zPb+;2BvuWg36hnt@X9Y?CdlSxJu)&tajb6VQ2c)9vp6kUFL9FwNDuVLn!SF?f81^z zj7|F)#}I+pO$3Z|N?;Ma>LfrmOOXl;`gV4py(%LvG=2s8p7H~dNC}rja+Y7RWp}8! zQ=DdKtEZ67A=-ZdhEg3-^s|G#^Juo%x+4s%zU&#&)mu4v9*CX+>$vdd13!4Jvt_=7 zHChe=#(FRX->O(9ehpgjpmR=VGw}UO zGAxjGxM>8-3u5vCIUJ7cv|?gI?#{0bp6%|FHs<;iqeNWgR^*WB%E^33&IJRM{J&fS zpAsTxc!~J!LimNfqlHVOzr1HUgE^A|>CSBxh*1YtB&O?V4^i{04NVy&Ta~E#8Hlw` z72F^bc1k4R{WX)C_;mAqkR|3LZ7A9=Hi2f1*P%?R^Cm=4+o>UGnCN+TY20y@rkm!f z=qlBgPFP|BZsr5VhUMzX#i5z;^z)^SGaTxi#GaGU-4U4|maw-trCR(qe-Er=T-SOG z?^{_$M3~y96fQNBJ1y7FMB06;mY42lb$9;bRlY3be@2Ai67Ri6u7RNbaSToRr?;@> z=zyQMYcG7)n`ekyyR3e0o6ks2-mY0Y|BDfGbGK-fw(8mDct%~Auc%ZPZz_JA`i6SJ z$|4_=kN8Of{rE`%g~!9@8WAX^Lp$HBe2nzlchjaz3}WP-;sJv*;227|K^aL};Q-1H{jin|@QpgjLMmLb>uJ@&hsl-=V^@;G={CiH%PA6G^6eSj>f@movI z-ExrYS{ii!K$Da=u1}qzodsIa($D%uj&jimXVw$s${;#m5x`t!A|N9@6GVo(tzm-p z+V$rpw0hd9c%bDZ@h+nMFgVQs#^#pXJ$dRO0iBFwj8##bM+@$y@gbOJ@~+sPj0E4j z7!UQ9w?Mi#5517JT=iK3N!irI;+y5*+OFv6FsD;ti|7m#(JMJLBo2I-Sns9GEo{4d zkNpuqyxkh63f?A?tDzq#XOgyI=Ljx`sMcO z+6Y^G%1k3~p6)jIaL#^+z*~C{ z`z1luWKRvDvfrwkAf@X_!$re9Dq|rU(n6dISDEN246dA6lCTpf*f~twO_ix~4dmdu z{L9U&;O=x_?bWFKULrD2!FheKdn@sNKygUcrGXSBl0~(k)BdnhZCi`7o&9}fxG)<} z2k|k!TVF2ppHcHrmGcwVhc6e-?^1}Ih{-16Ywg?+K^Md-nEg&9zt@cqe0#*cNmFu! zZ`VJ40SF=3k-~Wl5=Y)R>`DtG9^Q78`K;v<8#bLSoMONVKXGuiSEPP~3!!otQ~- z#8n2tL@He>e-kB+Fh;MYQMc+ou;-q0s48`m78qM8~( zB}mVPWb?hAds6ZEvzL;hTl)T>f}-?tN=38)-XYtvyt=8!&SPxsZoU5VD2rzx0tXM% zac->hjpfE>NRs$c0-f`ImATlR( zqdqk$fjst|mtD$Rm+$tacP$+6UZ>(bS2(Gd-g(0+D2*L2;MatpwinB94tgCvi+4q* zU}M2*;f(`#ryHr?hWGRLia)fegSm0i`-sydckao7eoryflmvHPpARSspTsK+yQ;*E zLZcobuV?gz6wb|?JG>IjX|b0hEhSlI&fjU2p8G3hK2`QBfw&JR9%6P6+dKQLUyC|- z=xRzXZC^Ptb;li(Lq%GMKR_vAjYOg5O@x(iAWqpjW!Ew8`N>y0__AmTcFFNQ-J6~C zW&OAsEqS_Kx3fjRAT`E?%naizd=_x)+7lFaIdp26ImB@8S+-DsuywO?T=CkWfEfXU zl7Iqw)xf?n{(uevG{hUMGY70X_8j3Y9`@gs2VsauJ@B8K2nXy+|i*w;3Xr-@w8 z+-rQ`(>p#tIj1Sehac|cq8Q*ZW8FezYoJ@a)L|bUr@$Ji=x*0E**yIzH3qIr35;k{ z%SZSUmU%cf07CA3o{?a{LD5m+9Zf561imr?n28~&I-j#F61Z4{;Zm7JArnLJ#wXXOX(X6jAI4vzX<%9cz#YM2!l zyIa8L4P2>n^r$&Jl*#AJsh_IfeBF-3F`6P2t#dqs(V$w&#P(VVT6D4#i1w{Ka}GTZaRS&k z)sqCo4tfq8Gm=iDG&+eOEQ3?f50HT|);eN3+s1||%GUm#926Ct>kd0rVW3CTn~TuQ z<0(Is?^4vN;O}QveYWD|DOtVq`-ALqEw{t7@=i?8OuFNW*vPL0>E9h&%=U>={EBZi zADAZzc4rOMC9KybgaNC1PD4x6x${xY&fYdhe-Ha*iC`1xq>f?&2{D6koPJ$W%IBxe zUF0Ld>YA(9B;ZzfeNeAFP@_U>Ume=AoqUj*jwFJ!6_K^|FAt(jH6)`=>8y5#%n8C> zM)y8&0#>@A-53$kV6Vscf^4OWw5K2bOmuRSgA{q;kkFWlf8)f^TlhqeX@_>2MQ4P@ z2S4L$nk6TWiG}=m;k+Q<;+eFl%%bi-b%nKS-V5~ExxvV)Zf#0T7)7VFf`w|cjIMh4 z=>i5TzzVuWuoz}H!yrj4nW2^=+(F<1$2=(+IM}w{mGd$OZE=h8QfUjaSyLS5NXnVj zZ8_RFNT3&_!L{S-j__{cDdLUmuq(m=tFGQ*l1maWzR|*+D{SkvShVfKS=U(&G%MRY z{}h4a4DhB1y@3K@{$#HFXh0r6B+sesbumBs`8SoInE+|~yed=m?7!L;-Cq=T>)U>N zGgw@KG~EU{D+0-G;rBso@>HJ#>E)Ktl4NO(?gnrC>cYG;3 z<3GO|9B}QOK%0c7J1P&bmq6>-vW&X}KOTbbA8EK9wDMfj_Q<@w-49U<@^BnxX}Dam zvfBL|gmUM2Wb8LMb3)2>U;~J-uYTju%So%){NYQs5wqOp@)O=Ayq{uwF~qU3&17@; zdTK8mQHuJ}N}&XNgx%{D6cwvgpg+SrAL?vKdzvTSg(3zwZwuiSK1Hn0<~^))#CTZJZvMSDuFydj_jmC5 z|Lip1cEQ6`WFVlwoIpT4|2YrG%+lJ_{vWO4e?xJaegW(b#1eL%XlY=WQp`-or-3tr z@MnZc=Qted4^fXCj#)qhNVG9#(8@@u1rnzGcFNBw*2qLR61&)u!mh<#y7adeZU&gv z`A5FDctUbxV!j(7F%_LLp=yO!ES^4?pg?xdz>MOBr@4D7CuSh!K}>ISt^6wsAS*=ng(2wK+ZU9`xN~rTVTA- z9D%d*NlgF)&K#BBrQCAY^U|@O*>FO-O27 zLiTBdl8sV?k{(HBLiOkjXXw`tl6yw;r3&Y22~;o^AD{E}eK|QZc95*7w;!GyU)Ir+ z$lmXPi4<@pEBa>3Lq~WFB?s}`4TenEd#5J+4g6b^C9IjfjgTC+whx;I_u!NIHRi=O z1I`f3OHZr9?(V(TOzGOiTc7|Iyq&1ZF;PS$2$^Ch5SHfZO77|`c`t8gA4-{-z40t~ z#=Dt5N`UoL&u#q4vbXR^w!FD@lRaPBRMp;;J5$g_=GxODN5Cnr=CeI-ZS`b)0M~At zfiDN8Q!OLpfkV1ZAZu548f(4~B_@A*_}T8lYT-fJdOSO8m=j6GD-H=N@|Z&`(AvuJ zY`@*%p9m3nGks5(N}KN&`04>kEcj{&ObO!?m+QZAp`5G_k@n&#tDL!)ZR|binfA=t zF=ruvKH5SyQ&vC(F+BqUk#% zVMq(W*96QpC8+tD=P}&bKE$(wh$&)-wv4iPxyWAW08pc_=uO<|CsTJamPBaU(~t-c z=4OV;vDrd!We{h;ni*z@`C4P|{(vIs?J90@c5rBGUF-D3`KIw%pbJ9KocW(y^$SHp zYw0q?20Qn%R=Y+mf%iPz%UPl38>RR{9|4gTBp#vMA6}iefK{Heb&Zy$rXI2~%vWjS zue+wN4JtWHJD2nY!KMpoyQWR1f64-di1U1sx@`fll_&m zCT`76U_n#U>9gXa(wya*_j|GCCM`U*W`rTxL&T6SfyTNhFRs>HeG_)#O)2#AzP^God$1-=|FYY-^q;!&;P!Q)^K%8*3YO<$dmNuVC5w4KTFy1gdz`g;Eh{}>myZFB;v6rX` zV^_mUvnkdlptR!;&tBy#Q+f9v_3FV5kHfDWKjnj~;1R*hI_zCm3Oizc-^E%R^(?!| zqi;BJdG(rDTYPEeYpU;zP<5xSb?%dGxOB*hHNqz1d!~_TUV#*dwhPS?e{gZPAz2cK z%cbvUq(v02FFqYP_p|D2C*7%ITO^R`1m?gfZhd?fL>lqYtj^N#uZy0gUtY`@L zbJ#0YL(UrB-tJn+m55nkE#?pT8=s^pe}!(`?JH^&eR1%Yf}xk+N7e3<<~bdiFft{YOnSW?!@DTK^KICQ_=^xi-BGTpnGcrCnmZPT zttz)v9~~6+b|N==wUA?`H2(6=##sK)tcR3_-|3C#ul77pV^7GfUDTILUpPNxcj2sgTc57{i4KrSsZEdIR_ zp13vX3>wBG@=wiWa5H@llWP2+Gaf%u8jl#03R$F=NoEpAKBGI%f=r`RUMK>Rj*Em_ z9G%PDj2am{W-8D54)b3A0g?f1GUNfqTa#s2AL9$T;mvj2b#=Y zsUEzZ(Q*rd+D{(fB3evBu2RAkz{kX86vrx3u-iuQRr|QnZ|S1drzToUGfh{NT2a~1 z@7@013*YWi)>@|4P?$7wX0Z88V=XTqdS@x~rIDwu*4`Qg7cYr+(G4oHZQ3fd(%kWrojc<)(Pob9z+{o3u{_~Q&%OddX$b3_etrA zle=YfjaX;4VZCqyVo?$;ky0_sD|B8LP-fMr6@2VMk{1P-rO>x8QBCQZbH}m1X{?68 z0&&_tF;44pW~Nia!`S-`fKJY0Rb84@4Q<68AKIy*TaygQ5$vv=imQw)Ct=-?BIa7S zt`P8qZ%uugCMs+2XTvO)HJ(ZakehU|RYR%vCYm~gp<+@0%%!z@2y#SJi zSNwF-rTR8vA~JWDH__xcmgxj;#F41w z+c8LOE>0!AD}ialbyet|j(-yl$*5@NhaHZp^T!nLvi&qd6Rj6*=vpzw!7|wXVb`EK zAf&n>FD8NI0K&_MfQSj{m{LMo7T=s-Zph{UvBl)ZGIwm8`0Jp?*Mx2A9ror$a}zet z?pd-UiYFwF8QHyx?bK-9?XU{ zzcp=K>7(e0ezLZ;64u+*PNL%JLO6bMLff$P$fCR=jy8IU&IM#_=gBLkmrPpq! z{x^G@g#nZD&dw;kme2;(U9Oy*b(DGd)3j{56Ktd%j*N|Jb{s+H#EbpS*(oC%xn5ki zvSnH7P_>a{hzqI>st)5OQlJufg=slPtOD#rkq|h*7^*~<Ew&5rZE(ywC^%$4eR@H0eVEMI%Mi9$_Cdv-@}Af3UJ(<8fG6|_GD zAh-If-2-jW?e`Cf2&-8#Q@Nr*tf(7SZ*$}@9!HHYCm660)0 z4ZPLs7J0zFNRH^Ga;Z{g7OemnJ)>DK1lGkt+7m~Im99dyqrnr3^o$q*iFAK) zWmVJ90Pxy{*-8!-M}6S!Fw0?xeDL5)Rqi^8YtG{axbr4mRHeI}JCes}`M{L*H^+?AujgtxEe{X=ihE33uNs#X_3mR_pJT}0X@DjBsekY1$8oKQjZ zWgI0D2|~K0{gJibbPmh-*i15ZWUB_R%c2%Qn^qrvuM9u&(lO+_zU=De{!U3%_-$Kp zSo)#EA{m%gmHxX7CckwGa$2{6pb??;kVo!eUehso2h5%?)X^TGF-ptx*uU4%-d0s7 zm(Nf0JPFo*0`?H{cT!sF%$KOg;k9n?dR#V8YM&ZkIrCZkle9fMZucBU7ebTF{b?QB zG&FK0-d}IB4)A5TWle^4fNo}xmJB)Oa-z5kjqpWIPu0@gqmQ^cs)o*VH2a9bKC16< z!8a<5?0FtRDhle7VG`I(3aej#FdFZPGKMxf&|WrJdBPz^x{~LIEci&EKvCwrlh|0xlOO=R2 zSd)5lG!?G#_MG`}5%O(F) zQ9Y54%IJc>HtO*~maqYDsZvyh9}m@2nc+*|(O5sZ8f?E5BPnavg;mam&*4wGAx zhvE96!Wvj>+XdGm9l=i8I+T917p?09dbIBxY_vnjB?_;I`O9Px9D z+5G9>R}1wkf(gU zoHj<|PyaDW&5|Q!#?ee~Y?M3_s?g{aIWA0;Vhfi$lCATIP?GE+fFXd$FB~&_zTN@d zKymq9V_s|J6Jvui^8da3WM}T`cxKe(J-prY%Ww3%-hYdC&D3|0DFrz%Z~fv|>mpNp zY*X-15qbN~HnMZKz?Cr~nm*EU!7{CcUhLGwK!RRUKDzuym#=Soz&4q?NHUQsD$X~2 z)HUw-{7Z>p0rr&D!*Nt`o4c;ute|04oKDOo?l)ur4( zmp!st)++}_O(PG+{&`ayXpmPQGHjhPMcSl;NiI_k2W%XSzio#2DtQ`UKVKPTt_aCL z5+VhJ)o(8@cY@w%FsO+#JVAA1D+UJPe439Our|HopVbErjOFZ$$^a#4#yw+pVVabZ zr`Kq#5ewISXoa1kNDwAz2rUl_L5S@C3)0+ifU0;KiWfc=Isb?WdDo_A4rkD`k5w95 zCk2z~F|j>5&d&fPJ#wD=6Nk70h-RWP3QZYu)gFNh1hX96TaZg6mP9)#c9geYvs^=z z^^o=ylXT!{RFV2YO>q>i_TzEDAfKXO;;dx5wPyF`;_h^$PxME)>jRtrdFk!+{p4=< zE3E9DslEL)ma?3)(_cSq;cjF3OIGgoHOq7s6zrUn8C z5d!NabV0~(UNLCzZE0%A;I+E|C=@5A80ygK)`2M`WkE44wE9J*K>Ddpfd2>R=due| z2fkQfAucuO3@NMwFWPdY{9@akhpVUUJbLMA>eZ9&j5cd$$iUHe3D^5l-x(MZOa003 z60yYUKF`hNNFH-9iXZ;NI4kIv?o%~l+Vi&VlLJ@A)sVraK<<9yrT&Sah~RyBkUz!B z*8}h;yz|*Wq31#FFA&%HpB~Ox1pe|r+audvX~q{G=e;D^J5e8m$ZkYqhsRqcJZal9 zALm~d&O#=+k0SyI(;tb-F67yf`v-V_ve%8czljl-(s*8LDA z|1&pR<%N2x6QIzH_8#&(`cJVh1|hA0EPA0xLdeGvp0@+UkqM;2_e=M9amAI3Owh5d z?g@*w;D(^^zuF;Vx)30@zGn!q@C~15l@OC(|6HH}?)**$S37$wgcnUb#eM`;^_`d7 zH>lacX(wHVKsq}&K5&9a+d8t80n+tM`XNB%H0;*{bLa|NHXwv2ElV>Z25wn%V9-9y z?`#eq{coHz1b>FNAEm3DY$6|fxXOkR#fNB$u~~`Y{^jU`ViO;LT(^;$&&gW5)4idz z1iXL3R?cg@M#4J%{52P-GBDjIx5EC~PbMCQkG4VG-OfyML;bQ&8LWjrT|At=S=@8* zvWuObM{i1%eQ{fF!9->Q<%>oSAnT-kWPX8`|9%uLBN#|hrN$zqq>}*k+IK?xu#g2# zE{q8T&3Gq5^6N2+Ez>G-kmN!O^l;CdCF@_K1Mxnnhy4&3CslCXwKwAnj1RVh=_y4L ztWrzI`(kQU=&rEb2qOh-BHA|4L2Erw(cOSrBlp6A_qsFziHB4tM`(oZpITfq6zv~X0#VlKM z2MjeuJH68bZD*-#i_@+G$w|Mv70n&`c4?3yOo3MpbuHitfRXz` zAHS9@BQN`M$3(g)$+5N&eiIx%5>quuwVe6n@co-=MfBJmlUawK2Q}>8Pw?BN5ZK@{Xy&1m_p}b>uNgGJg)I2NSNIo^gty`iLg5jW z!kJQE{-kl9&LMLc??HF4%BViJxWGvS+)|*%Ue*ZXk|Y1C(dy74sRfhkrw9ljnGp@F z!x2B?k=GoZS@wu2AVS?YNp%3RCdkv(a7T)Ff;F5yc30Mc63TlNKzn4S;0*8oF$XUbJ@UT4S)UaMDfkKj( z(}+NpxF+)&3jS#1RicB%{@|4+%>R7ryR%nzVoFYiBX=T{5j&Un^M1lHq_=pCsS~^V z1@du2C+h#1?y_O{qWdB;wc>0w-d0I}%_bcyxCiJiovzer^6YIqq(_C;lHB=~_EUM) zw~Vu*Ap9y=g8>G{5iaJiW(7s=`uX9S96MS-Lgg1}7{#3*EFieS5&oQ*7~0F0RVbk5 z+R~3H4J%oXNhH^zByfM39j!N_#51XFvIp3(zrj?(xlnJXap|VW@TzA@`H30)yi=t{ z9vH5{20eM9OCNADOfn68^WKKdu)C|sczc6ccq2xH)hj1NsU_24nq5D~JE9zbo4*>N z3_{_9r;+@?zC7JSk`weSfZ4I>f9$2&7BFXz}&&U7b*THl7eDlym!6L*02~gnex~|^Sb_++NRW3?Yd4S@X z&KF%*`LSq``cuPoh^J%|^*6;1{=Y)%+yokirI{zab+xU{xjM5tMqKvfa*$Fj$A-(tO<>op&V4>f=fqC*TNu9f#C z1wNd><490hJ6qr-Iz`BIlaKC&>PF#gMRUzX zmqm|}^7>@cO_MB)Ea1aao3Y{dSBx28<$c^W6<1hwTyRHKb6}kovLoEcpiY{5%jty6+E)UpfFL-JqIY`)5F&1KVVhDDJWjO zF?8z;nGH8ziNoWxVEI^XidA!)bH;uE4)}@vGdTh`Huij9PHgbxYH2$!pIxxhGSoDd z-lmv}2(AwcZRgp1Tku8^V8gb`Z8Fm*L|fxyp=?2GK50IeG94G22sh!Fzp+$w(DT|Q zjad%P{M4|mau5GX4B-9cVTjB;JDST?NfQ1Yg;j^b9}9Bb0K;q%cJ4W8YtCf12tRYh zkr8srKE%GTrmJ9~{?F_&D1^UE@ zXmrI-q@WULf>FECq-)*6#ji$7vz*^SrLtf;_ZmoK!!;P1-R(1gM{nrtU0QpSqo2y3 zf-$jmaNZ>WFF8#=K9syDCaul+E9cA;dlxC|8F`vJ2wWzOa`kQ^ZOe4_GzC@NV2=G_ z?+5e&A5^`9_jidr7{&728D zkv8J4Qx9qnao@U_H_t_ENb&8xg>=^5-^dwfC~+6JfYlGimoHEAj$*uq7bZlD}052z^(t&rqj z!avP9+zoCv_gofP5JT^3&D>UGF^+Q%Csdj?Eb`pPg5Pm3VIYK9b9z+?X(6>GS;;7P zDGu#c!DQZ1u)8(lNpMuQ8V`L{Q;`XSF`2VC%{nc0(#SF> zXV#9y|HaukEeQf_S+s21w$WwVwr$(CZQHhO+paF#uIc-B=W!+@@)u5=$lPmfDpy-} zJaehdQ!XU9t@88F2aOw6CgE5?p{`et1aUz1GLhl#e4d*}bHu{XC;!lD3$e&RXS-t` z+UvnB8v1X2(7d&)6!3v%IegJ~5gZQ?&}M^SZS8wHB&Ly99E3r3xJBJqa!JY(m9u*G z(LPj#HX|ga1bM1lucmDj37VWctUEl4(X08feZs*~YbaO+G1MkfdkbIewDe;BEX$lx zKP@p7K1t&Edw*`mZJl6f!dzqHZhKcd3{1GwPZ-g&gjK?^U24Z#&d>XpG4CvO*KXN` zJ_gAQx0b%i%PFFrfEm7cNQAkNo22s;-T{DDmcJz<1lpExHeCdWlKxBEn`p_mEN3-=HLOG^68stw4WiazwnXXYIoYbelKX$4Gj4!tw$XFy=|5 z^p8;UnF{G5xdB!sIK^g%Q^JY}%H~0dq~iN^eL_|tG7D&#xq>)i(+)HJNuVcof_Y4L zwje+VaY){7Z|}h4&EDqH=#Lb;lKgA5Oe<@I-tu+s>Gc-ZtEZ+?T;{%kKySlG6}lFpLMTTmJom*LQho#XDr8FyI~nZhG$Cc-o8be2d}& z1A^C2Z~u-ey>dxj!Uf)DbMORF?w=V%;{p{A*2gPg%q1TTv<^UT4x|^S>hmY{7Ql-7 z%cy@;9zO#acpk1z2=n&OEZOqghY$~UQr}k5rw_=vMf|sm(YU@QU6jC0$T%Xp24z$| zIR+vQ9Q{Z}N*ad7g3oBU%!CI8M~4%|54^5!KiqE+Lq^ko4kPShAm%M`AM8qHX%jzZ z;xJE@*u^=0ejcOph;NqxHD?arNQEZPd^hl{2GDtQEd|D!HT|I4ASFm2INzk3wRkN)% z&}ESv&7P~VI`ad`!pV0~k5jh4(4v=A&w%-koL4r%d*hfvfs5$_*v4y5)^Q8_9J&N| z?3p1P+SRFhNWsJjKPz~9k%O41skswX#b zOE-K)Wq>6whcVR6n$CZ^cgwL5_{3Ic*O(zA{x#Rkt#B5Kvf`WrC$t4$n=SWfioI5w zrcD6K7QuoOfA!^y`2FgPfwr04V`2;KEf@M#|EWpE!0itQPM~A}1pkVz)T^Q`Z>PYk zpR5gNHmUm632ZE8aHs7A=n~l#!6_zWI{XN2pQt;m%}4E!Fp|8+b$}SEE|p1O;HCEp zFd1;0m=7;`1AJx4xO0A!^fVo?6=vv-o(r0G-G3C2h!Q_W>D3W6cgLUstI#wxR}0lg za)a@fY&ZhUH9wtyyNlrN@D8GrX6sa*AAfEXp(Fx%6%wONtN|U6`Gmwm1)mG=GhmWt;{c@8 zByn;(VQ`B`YV}xR)r>>A}hkk0fc*#-^dAIZs zJBLHUZQb}j(4aV7@dJXpVg%f=be4ISyCOH=8x}*3IfID6oVu30i?vPDNm;RS-Z(rFK@uxNmjang)QhPGtVT$nzp)sy6s!#+p# zT^iMi_q`y(*vytQgF`$<0T_f)SJ;AOs0+qAcGHqV`w~3a_wL&l zuwI*}oWq)dJX;txntg-p@FEO|pV!8g2Kr>G@YVXQ>&zBPyoHW8Rt!CjBp{fDf40_b zKa1lUFWqqO7;igq6hzP{#om+2Qx{2>Nme=_<6Z*3?A}6!WAYsmvnnzhBJ?}u5-0f0 z+DseaxY^tShI}KYC?0JSxLkN+dnpfc>Y+5t0iFx7+Z`47%0vVY(&6yy#t}S)yh492 zGnJ3y^$}pCTBq|msEJlCsiQ^=-47x3o=C~T-a>E^6bdOS0yW0_c-VP)J-WL-KfoV` z`R*lWsUfuU7|F8O3P0|xR^JbcLN@*E&Zr1<4;Pqrc8B98pxuu_3uGu5(O^iv;i>0E zmnLNMPOa)&tjV6~j?lwzaxsd7#T8np`ZVAd4?LCbQIpn(0wXPkTDcYOsI%;R-xwnc zf(_F-nmCW9$;GPh#$fZIA;)$8fbH$@G%08BWW02*- z3Dj93pcrv9M7~i3j7$e?4jrvn^C;WRKdmuB7FAf@XEK4iT@$GMZxEK(=q7NLZj4K_UYVcjyEaw#RGL$;MYc zXLptDLE$tCj{ys!G$zt_o2VYaKnLT0vM}}@KJ&>u1mz4Fei9W%W06Jt>x+)ESuF)g zGCYkL)E@8kFVP4;uKjpg&}j^L7n*fKp<;wTG@R{U@Jzu1OC?fSqHt@7^4ocCvZ@jQlwP_eA^qO#|;=LwswocHnUuy5^t{KFqL~i2g-nXQHZOaoU zo?-BGM))+Qg2E^Ag9|x*%j}vA0Rd=X+S~ZTFGHF5@F1FD2L&npG(R3PrRmsrLIT|K zb-k$NYAAqY)|m7DQd5l_K1|phRb5i#EskSrT;`2v&qY7YozN?nQJWq6)wBde;T?0$ zK236ydAYg;4f8f%-P_H?%^_@?Oo$uR3)IYuGiC)W+De91zhSK83e2KYo(U3klAjM> z=kMxi(yerGISa9g@)6xph=86=FVKPe$@7|A4;J7JSDEb>D$;GJwHGB?zicqZV0}f4 zAHhmrvNBeCgmWX7Oec+UKV-Jn2uiw0@BdDY!CXy^5D~$7!Q_QsKAgcJZ#z0KpD44H zcw`7CylHHAJll?Ez5(}3Q<%tlxkx~rS&|I87M?F@+(N3Q@}|!K{F2*rU{a!g^s+ts zz7~_Jg)!6lZ;I7^IkLhUhJM0PsNL<{{PA=)BsA^yB=6*^Z+ve?ms!fM|4H2p)e#Tj z$RLm(Y`;0jsmQ9Hv+>FPVpcpwi214sD>sOfP`=@%3H!(eq~&cfQ<%Q~sY5ns+OI-T zRyR~D{L|Jk?braVF3%Ews)ew4yy-A+N4D)1Q+$-L-w1qGe$>qK4u_+RdZ=`vdy)st)GO2b9F|# zXT6CUF-c@i@;iICeyIdF%IAwqVg`wgZl}ghCXk^N77@rvther5`+S+HnoXMR1&xG|A8kDCTT%scW))}H)&Zy%a)R$V73fXlT?^PmTZ%GG-{Z&Y!t+3I8 zfqUF?A&`Pt;zB@bPBqk_m(!37t8xzHSp8@EFO-Z(D+7(~0;>k(+S4s3)t=5G>yY+x zotRK7ZIJ+;LR1)q@-~o=EapYOBd&tpJL4BQENw4VO({skjNx}QGVPFuecntvAbwoU z%R)xRd2S^=y-B*}l}h_GgH4!o_c#}n@-!6rX$v9Wp$IABM%HW?@pC5gQ%jf&s;5vDX4Cc}DW1BBfRZwEFDHyJ_Hjk$b6cB=i%kBsD zv)T0s5cAp#UEs__NowTOG)DOa4T$Dg7*^wFp&BvQvWfT;kaDn);;<%Rxv9!nfdgB2<WgB7`1+6kCAv=aU{{3;CB+%-tFAZ}DEWaDK@~}G*<)niK9|k>T^L?4a zx=vcSix?b3Oy(k_vTkCw<}7;01d-t~l8wLq;Y!j63pbIlgmPe{v2WUekOxehEr`Fd z#(yLuk<8JyBlziu<`Rs~9@2BCCif*>7H!E}aPS0@qhWbcxiodbs0+T4Y8`K~~eoyz;B14}(S9 zXPC4DQ%*n8P2aad!$%C})IO~1H?8mA2s)aqTeMpCgyzCXYq6xJRvbMSj0`rViW2i~ zK%ws!tTk@oWLw`T!Ad_!aN-!?-VM~_ucP=-37ywln#<8Xng<$#DUhN5RVk#ss)5)c zXw3raTYJ~5Uk(s#AUJ6@ z2y3?pcln!wbhV!ex9&Ge%1IwN!d+<#|Ds^H5Y0sL1FI$$Cf(eeiMWf>y z#1L|>-EZtoKqo@-ex_G8!FpNGl4)T1#Flu~hICam{#VN!4`2E8VE-mxp``aiRHTP3 z&k9ng!B&S-6}yH@9MUi8d#QDu&5nV(li}b@Sc-^Qq*tR56_>#OXYm7;=8mOm4}zcA z!CYZYd$8hHgV)SboVC)uGOiw}P7Baq5~Nr=K-q1MxK}d2waj-5i@a7!0(d~$el|09 zDeQ_lRcrtNZ!MnTozlKO)-F`w_9F7lCa}y+-5i6A7-XtR{s41U_})b?D&9ErARx{~ z3`EidK-FPd2w>hb1U-SxKUxWPRL8T*2!-=#CZ=`(E}-FV{(uV(D|o*R=H8VKlL2GG z@Hw=O!pag{@EU*tvNNc#Pdi0U-RI?Y5OxMO08xwcHR(Y}WTHL%F|{{bwZr3W$4Q9u zD(n@Qek3cqpzsQ@W|Y8tPJu>og`h3oCT^B$3>|6h+Y$uJyWB2BhH18$o6`w>_6BWD zd3Ex=r3xEEd#t&-ADRYgdP_d9$XsM|-z;fDj4cXV8Af$MehYR9si{V|3&|Idif*KW z+R%WD415w>a4X}hL4|{^^$)Bz5k}MUMI6&X&b0d++7pev=4NWqcrff<40g#2s8esI zr}gj-;ucq7EN6o{*$u-udApRt-tm;k+3C!=_QHat4V66Q7Dp8HpUz7-{~3@$2Tj$& zu;;p%F+{AEpuOh{FpNt0K(MsZ`a4N2Sm$ojJ)k_3& zZt{RTA-RpkE3(^CZP56pMXgqyhIk2BEA(W>TFiDhk{|8kL&zC_phce`%7$82;(mW^~0T<8lc7$`dOhWAX2j z_CD9H6-!g6X@5Ez4K^V>)Do+y30;GhT&c-)e-P>3G!oRvZ1UpPjSMth@66nwa78{1(VEvH=0y zuldNL@T|{~lxn824$8s!CzgfLvvbfM(u4JP#fKOZ!OR+yBGN}40eYoT?PXAd(n~7~ zykbHZ3nnK()@Gk*Eg+pl_qx;&YIF?5fXV()H|bh8Tor z9i3lX4qmgMq{a6*zIkG$aG5M>(obzehcx7hC@h0Ror~=+C}Ju_j&zYzMg$^7?ah?C zLA$~*>FTl&=T*wfK?Uijc+vvQTIRH?A_y}ohqgQToks0hx26s8=ISzLWTL^^S_T%n z-_EmOPG*g*G?QHlRNH2{jvo}be_Ju&)uO0aDFj-?1%f)ABu&DrIpx(*H?cpG1p9Yr znX&?`g+}}<>(J6%2!2|tsG`V1NhpOCJeqZJg_fQmQXY85fH+UUF|Q=|?@6eyQ)26Z zadL6pk2-|y{a%}(!&O?~&PZTZo8BjIb#eDdo`?3YSj_x5SZXge!fG^=@~Leh8GElL zy=N$31wKL(`mvbBg8i`n7Vc&F60FEDKL8|0LO%gAv|VI+s#{RaB?jEB=U!Hnr;3io zAUZ4DQ)+!QU|NRPbz96oSx4o3G<;@Cj~E2OPaFu5D1zt@)f3U4*I->jnC=!i0-U+< z{|36eddsLuBG3l6N(7V3MEJ1HqB9CMo{JN6jVltv2RXKpcwYkUUh#t_&R z&K{@&vC;p$kUG5Ub4|oF4as^THXht;6rvgYc%G$hrsA#4$lEE5L_dzOQPOvbHw;)k$We$9&R((dUQIcXwbe~tx)J>Bmipi6eEs_vV3AE z&E7van#nyOqPl(2Q{wb=0w`9`9!|2vsA)K$FzVDC(RY*6`$`PmRujn%3={fgl%n;g z3SpJp;X~fnsk}zVPrUJTB}Wwfd5@i?i@Jj8E)7^5Kn~#ZX>%rHJZK_r3;wRNGK>aC zl7IB9KcSjzH~9&%YH@A;q?Dg=YZ@kcS*9Ix9#v>RdS!=OROK>V_5K+SNto2^&2xK} zaHtUJ2%|FTa<2L4ggQWNtSbwcxGTKbaR8;I<7lo(PEPY6+Ru@OswG!ZZhHDkEDPz? zH-C0uwZa%@BB?VO;N73Ei<5F?)~HqoO!?Yi-N+KF+q_SBe9H<#E<%ymrSy(=a#)-) zC4LORIZ-T{f^kkl!wz+9W_oPAYF(2u?n&ENEaoz&1WVQ{Qpo zX8tb@13g%C^B!DX>Of+Pj@a0!$E`D@$(A;c@l%g|qpZB5eT-{X=PS+17wAdV>6~j~ z*Ev_>zp$7kvPSk9SxfKWtKc5DST(c8Or7S)`L9?|v!NTSq4750CaR#K9#JL9Pe*E& zIFtfVWk`|B#7d-#r8caYZeaP4aw0$_(mXtJrC3TM%0f%zmrx}1S$=4Gx+K8UEJ+@p zwv_`N{A-7=>v=8tpA=$=56Nks5yj|)~cNQ$tEuR3I|Mjb4QSC2Hl{`VQsN$o7c zw5d=i3|4DyPH72+DN2}sd|k=gQ^jC_}FCOz_{F9MaU1 zt;}eL8mEosp`VUMQvMbj0fT9Vy0-_+Z=I%Z_o8NUmTiL2Wv7pX`oAxOHDo$o#-`UD5*&@W)us0xS-|6odw--2n zvEo8P4+@`u?>0*?Uxi-E<%!rW=ru$|s3~0ESlpj0k5NNvlAeT=DX*zA zo>lF5xgIbR-+nEE+#$VKM`p{tzsjZSsUF#~zAntRdXCFr^I5sN=Q6i9x<0bJYBz=j zfh>ZwO6TLu4+a94GqdArKhX!Ax4CYQykHJ!=2)?nXBbIbRuOO?qLb=gQQqG%H4!&2 z$Tw@uqqRnYC5P%44^h`f?Ot?-{>0ujKSK>j$)M}lrNFuo8x)*^-9{}pzeer(r$1U% zwa>+<&!POmmgmG*#p33SDuIbY_wLGgA|EimyZ@-fkN#BDj8;?J5ra&Px}OTf=6=?O z`Vcu)Q&6~}M`0MSu*Y5Q{&`r)$0$yRlzjFyd-ZkXO1rIbJ4bC|?**7ze%ji;!fM#v zw3e1j<%K_A;xRW%LQOsK>ZL7*J)JkVn!>;LiS}iLR@)+Y*?&uFh7AVQ` zeYqE<_@gTBs{1t3r4xTd56fdNZMjR$r;i!0S*C*~m0w+$7&@f}7reQPS+BJ?p9B$tpwcm_@a8$WYu*^*eF3@%(_4ffHN3S(S_ zE|(uo_kPXM-Q$gZ@;IF8UfifGpz7skX;aY_t6r zJ_)6cP&C@xED4`yx!2l6fU}{m6+z0`gq;dMO+)PO8!+t(%x{buIous4?ehmJB&Pgn zz_9=tIXSNqyF2q;`+E(+K57`hgoa0%JnL@VoEGt68j@Y)#8k;7Qzt@EZSk3@{;sGxvlm=rl0E+ zxe#$(deLXNGO5mnYl@XuVt?P7{lMJM+8x?JnhBD)vPs!2iYGJX;)@T7DF=8;Q4`eU zjrin5Whx1sTO*mqF4%jdjFK%*CnCR1wdYUq1o_=(?zy%-HXn`iMvtXNToBpuHhR&U zR2!UpU;B&oCRz`n)VrbxE#XupxU&kgQ(jch7+ZEK;R$vY)&<$EuiRpD@>WPg_4s}txm0-0_wkh zhjYUN({)J&U+di`;jr?_R^h(wh4E&E21KG3K)@VFb7yK-<#inB$V7|9;HuGks-4Kc zdmcoZ1AY}RznM2}9DZBcbO6Ps9K76SYY^fcrTgQuQGaO@4U%?J=d~I_D+ugdGeJ-q z8+rmg1jT7j1TG=0to7+T&oP_tf(eolSIZRokY(yoJWjr<){va zSXIwM&-n0&ro|v}cg-KxcDvO=5MNU`mO5OWacF$Q{d)y-fv@*SN8;TK`De(+>VenH z^E^7xf7{KWpG#*}b+Ip-mX$uAly20xulu&-o09u_pzJZTRF|APQ!@+6+5WR@+^LFi zm65KCUJz1RLpR(ahavn9JeCv!ej)vleQc4+-WQ;9(chb4g^-9hZ6Ab(Gxp*tNz<%3 z{Wk!b5U1CJ053`od;19 zyjkWkACx?iz8(|id4bCzP}WPVj45U8(w!v-A?zm|Tj5^oK!E&+v*Nc%xmgh={N63M z;iUn;+^CGGkCVIB29d+)l`{Ub70R~HajhS_-tM>+cUJYc4o-Li^dm>@7MB?EXbJ4- z_)lGGMF(`vfcUa*VkMVxw7D19_fH2t#g%Oy`ShW`RYLC$_;-L_s5khD52Vsz<3HlI(7D6Sh>>5ogqOY?IH9LIbz`P$$>?VBo#gHB!CF zfiJ*6#5qf6#154<=zeo3xbaQ7h#w4%36}HbxA}byFUtNg?q(n7 zR_61(jnk%r9%D_+YZXc@S&FpsmU>w%55OhH() zLJ?#xgfdN=>HhKsjG4C@>ubZ97+}{0R+_YQ@st89{$k9$i59l8m}d(g{!Nj)=t~2) zF`;MeG}+FOo=r!(jgb^D!`U4{$8t*>qBv89XwBgwk95STX5%KB0dt&@ET}f7NQ%%y z=mF4`6$ul6{#SUC=EoP8*OlJU`IYV*os+$NL_WOJo-d8-zFqJbm*17%etU|)#=tBU zeP*bg*U5*9OVw2#bS+@84G*GWhjrPRQ7*8mClw=qq%HA>1v=Zz9DLkX;CW?dfg481 z2cFM3{ayNFFT!qr?>Ye^Cf>OB`@n`Q{J5`l3|JQbLu&N>Z&a)sFPpm*1OUJX?*F9- zvN3QrGBGnhq-O>eOX{qKqYqbjx zxKhWjsS5Js;IU_AQ!>M5yed>`rRG_uDhCbqW4@Dj`Kd(=ACyDnV6_WJ&~$P~DS?y# zoWx2REXzliyTE*4hHZuknOeR223Az1lCkvqd5;HyQW5w;a_MS@Ws!y!1wu5#3v=2# zv}QUZwPKIF%4uDM{veM|t8o3McgS&WJ3>Elj^9W~d?uAsQVm*V^^(m}=Q?~)DioSU z4OI@BD|xpS1{S1#Uue%EQHjoLInXTXeH|P@*tyhVzF$&^uhr9Y`j(JOBPr;W)1x`s-liTb{Sx`1>uyejmFjr z|G~fU& z(brj`NWu%yL+7SQv){-JAy?}4=$&?18k4CyZ%4aB__1?BofJFAV;9Rbz=OJ(#&@ zWNjfcpX_(chi2jrJOm#&SGW^}@;!UE-G-7WN~x{Y=!LBj9sr}fMd26$ckBmd8$7h* zf!!t?h#0PiS7c>`Y-@GCPmi`;cR+W+>Dy0+`|ig)5V|q($@BQEmv5W34czszxUTv< zfE70~(V%M56DD{Uo%#kpyIEJn*sZuHF1@{~&J<-?axX?2<(utkz688vQ%qU1mhkdR z{He){{uW4S^DHH|<^?39VHE6>4jObqr;~@#y*DqmV^up%GPP6_`UHwsWoTKe4^+@K z8HP~*7^@Oj)C$or6<+H4?e@B!kpIgCWLExUZjEjhw;ne*dB|BcX8V}8Y)@)+R$_tj zae4S`uetnf-H7e`9JSFsV<*P1ck%V;82E%-bqeCTC!|%SsM;#HSfZj8huyM>VP(IC z2jr2mD^+~BUE!|6lgHfo0!Y&})0xh?BL{|G!q zmI&ND>Ogmp#`U9V$Z_;5!(QN8d230P9`7n3zv<3}&|7BcZ0KocxCuZ&K9G(Ar1n&6QcwtR6oVk5RvUVl#3#z+1 z&LxSrzUcEKX@EcxY-P1DyMYA#L7a}y5NLE=``ohYagm#Y7S|=`;7BuD3(UB=_|K{Q zcTeY3sI_^8f1YIu{~^#{4YjgEcb+#DwhR{5JbtyAj~#_;4UygJQ8(R`yklxYb{At3 z$9gqLd@#w_(koOi$@t~$+9Jqtx&I7O*gWML7_^6-ov%sQsG?77+N2OBh_c@qd=7}B zIvojRsk+T~NyAx{CMdh_N^gnV?T}wbfZ6Zd-LFAbERaDJaVdt?!tve5^72D-wr~UL zAB4roo4f^bD+z!D(rN0|#bPlMB zpXVZG`G*~|&kBwUs#gyN+^*|dR;%Y7P}f!2%Km<+-pi9!)htN2iy5cFv=3J9^T^{a6G#g6Q|-pDfXl8P3|CPC7L3a4SK%6{`+R@>2EH3tQRl^rR?n1co1dl{ zfY39z5y;|YuG^TrBX_yd(nzMIec>$E&?@Gab?^C0=MjGSMAA)r+)NHk=pU;U5hwPW zRywblg3fjvT^Lc^kZ&tDu^QbbuU!i^0C00PmtEHnBNk4p7tf6wqU?b#U$bzZ`mU;7 zXMm-XEM4%dqTSZ6Az7>F9m&2H|8Rffx>$cv^c+?6USJ*0`HGXfuugwmmmf#SzxySY zY;##<^J5oB%K-wGI&fU4;au^?&hMswZer=ja9ubtnj@}?X76m;RxoiZcJ+mWyKr0} zGF+Xui%$Td5a1;HU)j=%=o0F;@ZCa(rlK6&=IaL1`+)x;vNGj6WSa0F>t-i8v-)qq zfuf%C=F2NxO>o@!L>>{AG9+UVkrh9eUr;SMhQqn6R1&rhD0gx@}vOAo@(y(WFGXKqv(}c4J8elxcyN~dyL1?mYx3!}Yi-hyv&}u`hr@Rlr4x`AfxVZ?)2GEgzv2>O z#Jmx@HFR>G@3;6V@ckh5@npPy-i_J9JSY2^Hv7671+UdEoxb)x%dTf+zi>X(GJ8N7wQRE~@B2Wk?h7eGKRbu&5%J`9`q%<%Q4i`cph%?q zK|wO97f6QCwWg~PkX^sPmnW|*h18{wBjf154-L3Q;PrX8Itf>e;Hl}4XAHH)AYLCzAdg%3N zk#Y|Z;qE>T+)-m14yjy$?8!`{3YCwd&*-r4(4soz_{w&t ztOB|H)61y}4x_Aq>*Adq_yzMDhgzN_HBX^e1?*i4eXryVL^ezXH61jkl@}o%3ZrFB zV^EOJa!E-W$btCD=OJ4t+Y^jl zqS_9XNJXrdpG%nQDdVG5={cJOXW8vpLiOi8PwnorC5`60!Z)_cuw>QWR1~B_vx!p! zqfIS(#eoI48r`pw5H%k0(P|C(!=L(}LD>JexqYE%J!=jF)w4Cc4%e76EFyvhBA;0x zTwU51I0Ba~ayzUU0!vP;bU-Wp6wYl<0I73=Dl`=n9xt8hr@YFh%J(A*i)1*zO-1Lo z<)fGRiYs3u0E%-FC-fu|R4u?8bOz`c9&61wbJV&l!&N+T8+gv$8gqsyj%GL{0G;ZU z?y1c3rlZXv2yf_u_xX>tsBU`yk1!r&2kFyJM!UlURAt8!r9RS;zoz)|WaW{3D67OwaNk3JJ&R}K5d;e2|gq&VgV#+fT4g)gyJ`K?F`vv{Ng@$KX z=e4+@qEzvB~U}?f>gYRL#(bDf}5dj#+!7ZQnayre>-$-S4O%bQ{ zWTvY)n7bpsC>BikTja~9d<8Oi%L76iLrhy*yqH9=ZRHVkUY-EHI>#KPpWR$rSO=2s z?>K@DBz3909@S5J%SKuAeJ`(nIcvRS3ohfmZ*b{Q<(@p505n311C@nu`6ADo(UeXs z_Mw;jz0Uy%WQtF!m8i$B!PJ@{k|hc*P5F{*3mNh9@m6O3+A7z}?iuFlEj~;D=esL*$im$?8CVEHb zg3Xu`c%Ofr7U(WJ>;QPkqsDR^YE>K4QPm^UJx<>oKR@S5L*|?}!pk9$T}VuV#Gq)*JRZru`Wbd4 z=$t7F4_gta>-%RGE&{rhUI^U;aK^J~lSuoK2qQy#Y7T?`&Yz$HigY5@!H^q;Q(`b* z%3K#%L~L@LmR?=MeiE${<~JTwPJVEs!C_jejF6}PpWg1`byY9IHhtJITVpH!DKRxC zRFHH1NSR(?Vdt+@QfERgLVP)vZNIG>m#sNXrhPk?>~}|vz&6$3{eH#1c$wU^%fBn5 z{+j2<>{whs3DKgC(P+;#xYt7{1Ak2{pZ+MYURhmsjd9> zFgmTuKV1dz;a`(ch&J0~q2z#^U>M2K5zaLV`;<7ih_>uPHDxB+!qUs|$W7#a?&iNt zO0!+SIN4OuWDMemF8|CZG{SEKx}MB#EZ_whHTOT?CtZU;nHKT;S2e958>&hJ-$h)PapbIgi)7fU#ts`>W@V z8>)6&@qye9{frKyQ($Z5g zZPu^17Vm~vsX*H^<-DtS7L{Fur;@hxm*IhC#aG3&f+G{40T9S4?|_s*GEu$y@VT0i zSn|(pF7|dpE|Z%06{t$libc?f8wz12IERJV*uhCXDS7(;EmQ6kr|{KsuZGFPA{4bI zO+E`r(kcM9q9Q(%pZh)sl$grAI4}VB36~q9pTn5vrVX!A2`-G^I+LwJ3xXy~8~Ae2 z_V2%C=p|hzbjd=&j{f9-hfk(&j`dX4>8P(HZ5E>2ARV{r&okHKMKzUZ{SDGaRL0 zSq@lB_nIHI5AM_0ruTml8H(tM;zMryXzQbE8|N7tr&- z2+u70I?b&H7%mP~E~#_11ZH_{2^jbqdsOMIS#7k9oDg1{5d}5P6z#M5FyK0FG)E}C zh*W)({}5!};kmC*du!=Zli#E63OOg%pI&o-;nqOLRz6b208p$RSH@6>X^V+y8V)ML zl>h`{brPIDykB$F&Y8D8f`oz=an4yLA7u-3Db96WcnASA7Ke)gY~^R*N%AZ?A{F63 z`kiIpq#Cm+&{V5+sPY1 zt^!`Z?(1{`!-XDnu+DMLA}11FI1SEoH0qQ_Rg&B(h$u{r0avrca}6Jgdn#i$|A8k% zk2Um|0D}pzR$s~>pg?lJo*9tVQ7O~IQWV7C7>?fATI0KtWAOrjd)n=E(=2B>>hW@^ ziIk~BIiH-wU?>Yq{JS|;bIVlzM=Cck)xsC^p!g1M1T&sq%vKZ){rUzX%kxwpCKFh) zVhJb4e^$1o8<+xk?Mf=mW}p;GKpUm6dmejZ($s8R)x) zXNnHEX-f$_42&Jgx>bQ$>9yV!ubkShlw&Mu^irR5(_h0G9F)C{?Ghb9Y1A z6H#QyP(X;n3TwVux5@J1)a+3v%)TLbtud$691G7%n5TxCVuhKgr{2D}zfW5*mC*v~ z_B>H(?Je6NkY2&r28gz-`BmDx-6B80pWcI~3#>ywXdDj3o|%p$A}v;Zwt1t!9=p0h z%>CU2{vFdMnT28BWb>X{KX;2b>r&6S-4}(fyUPBf9}hgb9|1r7+)DJ7UGX02$SIM^qs`w{L&>O%L>F7*tT0DMWi;|lkm`G@hR zIcG8#-4yp)MN^(}_EP7DVbC1}+)s;v>j#AeP2d;05|ZcLP-zwZL{avLMXYMX;&E@u zg$aT`19XMLqakydmRq5sEV)cR+CD9A&X|hA2r_V*DEgp7FSkQyss;qo!8en9-wg`R zL#7qh9Q{mi8d(qeh=7+aFlvxS@Kk2k`h@4Zcl zQciMw;5|~9vW7i09<@v6ZYB$rPyRR*fRlQ6)Smq~RIsIN#Y={keva{*e>c*&9uPs< zeNp4HjRJC)Ly6YWq9d(rCQTPUOj@I%%H$`i@Ix0(3k@w=zD5x3{cy*;!arxR_>4oI z@A-#)Q|bpqzk9%n_|g(XIz8kG@NVu-EPiO0PuJ<4*r6}y?%TI%8tt8AwF=fp$VF4MFk8^J`I#AK;bM3mkmvIt7NObz-w$lNXK z^{eL8Fe(TM-D1JB@;VPVPgsf^qYtD}v^ulXs5-#d>H`Wvm$yU!VI;HbV`HI(0d*** zo(1D^U+x$2iO3yY4U{6_IVU4$re4r6tzV351$&|$8UP;;>qIl;n*|XZnXgd6+lgxe zw5wW(wUC%4(C;7%c?V(RSH;(Xv>~Cq-?d3pt)!ZBWL;mV+egsC;bK?(DHSgfK+#5g z>kuPTaUuR162c!{mKmhj+A=X8(p~!axu1qFU7>-s1brS3eDma?pike-IvVM`tQwqm zuUAw@N=RJ{@q&h~xD?}nxdc^>DEO-xEQCJ7+#I*&U z5ncz)v&DBJ9$)0hunK_~{!q}cWjbKTf-}Ah`>M!bH z5~LFHp&ET3n2MBDF@t5ZSPALQ&+VMtf7=ygQN(=XQ27fJu@D6VRh|{}1v#c53yoxu z#Gl6ME%n;NY%|Hwm-1pUF9a^rpi|wd}lVYVCwdo#M?T+IZm8UN{%ig7Tryr_uzk2;VaZqliYm zg4O^JL8F*$CZF~f z1AhIz-lvoZ7jBP$I|g*t0D&1nw?K#4X^R(tCGsmB+py40h@fJ!N^_S-pO zt1>-gJSO{Z$2E*^{!;GH6PZm!zd*6LL4Q2DRJ3UlD;L%VwT=&3o@|-IYB!}K$yS?Z zmE9eAlNWw*wUxL>)k$IyD(eLKJV)Eb5HVV*z0bdDf4_guY3P(}H!^5j)L?jW+wbJU z3hkk~-R@lHh8yuriRSiioWGX50$8jDi$J*}j#nFKsW$VYg}FD{%!dI<3L64y6uVAM)I7`QQ$00*uCyN7{P=z}TU^CG*lfC#WkD zhKYzdJ+Z&hgk)2##MlBqf<7Iq$BqkBBAk=th2KGwJc?}dhgtMnR;Z#nP39yTzMNW_ zgB`6p@5O^Iw7J)C2DHh(*RE%q$7(IiffquQa^=|f(s9ANv0X%GhV_?xZvJp#J4N03 zr`a;A4$1|4Wdg@yIPa=pVd;LgS3C{|)iX~c9{ zO@%cIDJTVSK!V3Q2r8^7bM630-45wU%<&!LfFd*hxs$WU;UkTSYVc%19K;o&32R=q3Q;Sw}jX>f$Qzls)JHnLp-d?E~I`7 zyeOvc2!+{CoX}Xz5=D;29sGmjJnlGKSX5tlXdny2RrPO=l4y%nOkRYINFXe`2*AD5 zX^GfPyb+hW!yOE4B~SseS#6Rsm4guz@+b`~nGr&5mEHjlk@qE17KsPtVNfXZgj`4) zEHJB&xIcopeExN=dzd&OiX>t;Nrdo2ZiXYl)PxVsrHBWRK?(bKSV@T{`YP+g}dR*sp?z|m4J~K~LHa+jfhEE1J ze1oCyA!^Qy$-+5JDW=fIDgQK6>Quw}^WaRd4NPG>6I)I#&D}dCFAP9iXn!X1U=2@u zO|mOshA^(sR)7qSjuuFEXZ%MXP-1r|1#(igM^{$+N~>g9^!H6#X|vIT49eVw!~Eq` z-amH?jYO1h#jUyd$}^Qc&P!-Ej-MJg37*$6nzTDR0+X912;oq~da0P3f=+sgO@KV8~bUS8Qp)q{6-n+qw1fo-RJKC^ne%RA5E$K1Z4U7J3ZIj9%=i9~9 zyUGAxgPZ+=W*)XnVGV7hAor^6V*u-0Cf|k7-y-Q-b}HnxPBj3$@&;l>Py01|7CkSa zweI_NXB2t`{kyMwfNqd;`B#;Lb^Lie#xYfDHb%aMXVdBLu)hfV3EDy@R$GM?FfuN| znMK+rB=<@}HH!#&2alRjm0G!dmF?u#dni;?&Rt9_{Mwr$e zgYd)(ErLuDvuDZAwEO;t&CfcUa3Ao)!U4|ddF5(2wKMv6$PJg@ItLJLqm>@MsOnXc zA%%y6@ipIv{M+%yj?Im-Rj1d}$irZvT5W9a#|<8z_v`8BPOjhEr&UN3CLqtFe%fT* z1i+WA8=U14yrr=Y^#C3i?HB_6M|d1!%VV^U+OF1JH!9|Qj4?PCSTMJu}>*Q4Tl z(v_ksHzbA-4gN|K4|IWh(&kogCASQq%-gyQKWMq6tlzQJNP@OBgcykMG`VHnE7hIp z=xJ?}iWf{)-@1hidk8o;j~O|$@1uN1<>Ddh`k(JOF;9PmDJg?&E}*imD)JOoDeKu9 zT7@~smRa9KuFO`ZEe`2+dZxRn8Duo;QqWu*S`H~Gs2%ULE8{4TVM2i#ab;@6qsSr9 zO{PZbu$8iZ0W!mhh943&U!8{Wo!apqgpp@|W}07XK>7vuq}`QG9gW2>O6tA<>Wxgk zA5vI4??qfOxftJa@6zUisep%&uBI~Sx|P2h7ydkin>J^<3u(9aZ;uQntKjhXt3F2zqC&9(nAw-$bW}}^9TS_PFVs#H6#9>iTbNIO7uj%WaR~DqW zk0-~1Nx?#0nQgeJxfZ_Ci|BqXJQ{;yIv)&kmL;I@&|Jf5NF!gR_|`fEIcA|GlIVHW z$4sc9Z}L=P%;qDWRjR4CAWQiE)wud_Eq>VLuaDe)XQB|M;@Cq4_7msI6(nGD%Etes z#HC*6`|TID5PqBZyt&%wIZk~9>l!Z|Sze9C^7(xi->Xb@BDn0!E`{BJS9*)qei=^1 zKnh4bHe#QAXTIx;3K~~cR*feHx9Z+Dt+l$o^Gs@L>@-LiBcp49&(AF`3ayh(!1G*r zl67Ywn35EFyQ~*f^_T`MoOcB5j=qP&I1fwPt2eFOOlnHMaP&jn8zj{9z>vJkqv8U! zKO**+8|{(UT8>sy(ij67)sm8Hd!U;J>waWS`}+cI^4j}oZwO7TBXY;NR1u8qKN7fv zkpJm6+aWsVC$)*a6p_dM^QV>oDYSvMUw#qNbCZ}KFXW>Smu%BBPx~^VA|4Tq*4rmm zYpUi{nWZy-NVO}I--V8nsqY6Ki~6Suudw@m1n&*Y*lSMtKU^a4UHwfJ?*Phrr7)+KVnQJQyNzxkH1tp7#T zfE&G{N1CBepY_GzVOiUE^sK9FY9L#f;2oXBj)(*vA4k+)mPxi(_Kt6W+{NkuYOWnd z+z4@8^0P)pZ59+a-iPA1ZD|901hz6%AzI(W%O)PpIQfqYX9uBsoZk!oXHi3xL%xvX zz5^Q;PV_&R;gz#a(13@NGgx_Z!G?K0sZ5g>T&YUP2C6Wp%fP)TC8yLUA%`L>e1Ao# z!pM3i{F)>B&1)I=-Y6l$5UazIeJh1P`ffyE(Ln7Vpd(D3QMfZO0N=;)8|78{L*PHu z)$lQ8W*%_-oFw6)MSdoLTIbH+Yl*H|_Pq<@N^#*#KZ(YgcBiXptEtbBc&kq?n=u88 zHB+O%`73UO=BFE>ModMfcuY}$ELqBh$aGV+0>#+r3Ye&);x?B3+1o*Y$6TXS{D1@^KS`7W!WXp18kijn>Zf zk~OiLgRF!bOT*T`jE;mfx;bbqf#R~jO!{rFNv!BA-1x( zy%P4Q4&-2&HL@zTR|coV5ARzAKd=1WfH5zLhnBQ09lP^BZvI}jdJ7$2WqUtZvV?8Y z2GYdLm6g{!N|{TG7~b(Gc{ztflXP86^m5JtCS7h=aU?pScuIy$g&%>rS`_6@Mg=zu zS6e$Q$7DJfbM@1sy%1pp@A^$BTt=@0>Mq})#|6U*ZPD@S>NeAvT87=bP-Kz4d@c^5 zq2-Wj{wQsry(f0hT+%vzYl%&;1GbmIi$l>9`QFk4F;Aa%xWZEbR3;w-;9On9?5KTx z3IaKQOTMGP;k-|XRet3sVomI3PT9C8$OGZG!`9P2gFXh5DZ(@l<^9J8@&N#aCP*cX zInoIr(MorblN$1TiY-cRC!+cR^kaUhRcj*+Zh}lhJ>rK4SSoEn5lT!n zRRVVcGL@f{+yj1&1c-1LJM<`MAkC#w`LtGm|T~8+AL)+FH=I? zYK{Bqe`J!Z>w8!2g3gObfi5ek4QygRK?9!B=#rRy35!xJg=c*@Ti`rBKT`Y7J!OSQ zKA)@Lo5m1X({EWbJ7%C^4}}C=`#5z$a1FY)R2`r?=_Ul;U&^uIpvD7iF!P8J0^IAG z^b$h%zHVMV%n&BlV+r(l^^iZ~^`c?N8NBT($aJHCPXIAU$o4LdCBJ6@ZsN`Q@S-LS zBwW?N&eB1as8F3t>Z&p$joIMwSnEI?>njfC_CzLbHM6_xZGud%#ncKkt~HhZSCI1tut? z9#Vgy=u#{^>so30&SGPLiAM&s0Fo-S4+_-CPB~mO!<$|(bJKbdk^FW3N+JE)jE(iY zlzM3{ep+Ln@J1A0zO}BuYA^^{!6$$$ofsNYh(4Yf`Ahlz-K-XlOp;Of@;bR0D8c;e z%;FERw$R33;%OONS4g%8igk8i3n6{vPHNUtCo#OHnhQMrVnbj@M-h*R5)(yn>t-zw zWd$gXYMALd{tAXE`3k{%%_U-wV7vv7-Rt5Pw4a?Tf+MNT7Z<=zzUO4y z6@luM9fK(nhgJwm6^J~Ed9laqp7Xn zy508?%xNAO%2P8YY`}a35^{~Up3Fa6j8Q{XQC~ZK=sz;yA!=5DLXzs>x)u)ZskP#paUgokylm*cxTpLicrc&hLivd;lhifqU?9d;LD>?m#ug@=hz#zX z3^)(Yo05-Gq?cD!G1V^rv-7xa=PK9G`!M$2$LMXwo*i8g7$DbA-{aF|0h`V178-JD z4~W0Ng4jGS0CYR;K<*4wgvdCtv%(pVd{9uDtsuQ8C8I)UP?Lx|z1FZg>LF540m5ZH zaPG?=W9kdv_`*C_)X-v#M-;}&*^gzAD*bHbS<=eNlvpWJLF%~S62mY8@~=M5ya$4Y zjJ2)=)ZkLg+_TX-495$Z0(uZjBqI19=bYY#&r#xKc7EmJ*FP+4mu*lAh^>?+ z9MzR)mJ&Z*Ri!8KR$3PKLu}o@qt>n`hW{*BMzdR-95^_gDp)>lCp4T6qelj1AFxr6 zUERhgey4Q;urp7BZ6<~H1s|t(9go--fO5Fe5>Az!Xlm$9Jkc1Z=2_6v2mm7E#AsG5 z@l#5Yyxk)_(c9;NWjL1t_z6HE@Shv{D!pfkbYtiXDv6lOmPHu1NrR@%&eCGOKOOS);488 znM>zaX*6F>W^(Lscb5JV)Z2l%YqElDV5RQyU%an|veng7{bdop zzu3+)-npHy3fH*w1$OVRX|5ahX@qiIR2L-y%lB?KVb7jr?-`(;JkZ#GjqLB-8q|xH zn6S9351SUi)6~p$WyrSHMwlh9fV#AXs6n#_XG1aML}pBBqWQnu0ZO!<5Krao9yZuT zO*rBHSp3n^ae2`A44_x`b2g=<-upP1_<42HB;VRIlN#+@9Qn-Wc4=FfPB@ooIsvFT zlOIX?>+IY(@SxY&4*~u*3oF8XUutlV8WYw0npe3W&fUOE^ZLZlQC4JlfuYBXKG-Dt zWeQk_r1B&1t@$$pUfMV36v+1!KSoE1WvgQnqS2n7Uw^Tk0k5d;0SAmq zq2v%YJ*>IQTMio)uenL_0Jp5Nbiu5T0{fxNhxg`Tw$B%6A-S74Tu$7#;pIH55ofrk z-N*SeWFl4i$`#kIKWBQE-JT~rFz&06v(|}oejl0D1s~t5UrWe|N1zlj zq`nWvVG~w>Yt=`8#P!ZRB1$abwR_FAC^@PKNLJigxE>|vV#i4rGzAiQP%^18)3tZ6ex6*gow9s;fCu1F}Uh+rb%p|Q=CJq8KIdaa|hT(ER)hj zIk!nyz)ePruG%Zvab4})RXy0v`U1gIbG9|npk#!A^g?`3Ub~@LE?#Bl@!mYdZfsgc zTE@vGu`UUj>Z-|^Yr}ubY3s!r@_{i7gRlfV;ycUP3&$xmVM^BqFH1iqm(b(90#SvU zb$V^0SelYlB85RiXRNN+!n%4zA3e#7L<>ZG=+6yGj2DL->=u?`1ME7NfJ-A~3HQnZ zj@{kx(HXQ4X@G(Gcip|$+Dj{!nCIdoIyfT;aw$AHQ!Z@{ST z=|Kq~Gqz2TgYIB*3WC= zx|q^&?2}jR1lEP^?Qf2Gv32PXXaIEJG8|c(y_cs3(2SW70-Ury7S*yU<2a9&`7`m7 z(|RbWIW@m9v8uG0*=8jB(i%C|70)i6ZEt{AYd0*T|LA0BLWrx8cYPT8fS-1nOi0j{ z+TfP{9M|BDZg{;xM-4MnFt&ZceJlM>s%Ov0#lIdF)nCoRNjj(5aMgOJq!|*=>3nCs ziZ(t=qt>Q#5j&UTRf!HmwKKhGJa~}763qA3?Ou}Ic&dH=DSO7eGKBTSwYxO0vDzgs zuD25e>gt9xu-*|hnN3N1$c5U%;!Rtbfth@|NTWnlgc!FFV2Ty&2ibbDq2aq)#2Lmw z30^PY(G~X$5u#uxk6Ht~#4_&`WcUfWu1KrZJgU8+@Sfm%dPp3JCn?f5Dwjr94o2g| z`xfl5)&&WF4b30PfO>;2*bvK($QO9=BIU(sgmdLE(1(ASS*6Gq=+Ir@YgPw;I0l)4 zc0V~{v%>(qm6gA1cP4fKU~vE6cu)<&gj-~4wcJsSE2QGd;E#KVj?kVirg^cml8eq> z^58)o(q^|yp`{6GXfkGL`H@CoGF5{G3%c^-@0`M3&yb9`VA{RWH0$G330aqV=Xg{< zf%9zD_Tp5IEvmEUv=Vr9PU5v!*dL|fG@it+5DRz?a^SKffaEETwNH#hv)V;dEbKo} z@Rx~=K!BN;VX2eFXex`ChVBO*U8vQm0&2qR6`{98D%A&R|z?Xj(ydtY_V z%?|rIUg)12*&2WuF3*Xh7Kbz;FZ%*;J@6ETJ_d8eE(MsT1fiA=62Sl^v`4$?sBq>| z+<1FyFbO-oNesvpww3G|?58s{=vFQwM{XR61?`g>o?R(^6bf@onXk~2S>xSop0Fcy z#(~#u3er1*Klb}hu!>Rx94EnR&-Q~a!vZwDVxeMhTk5IR2zARq;{cnvJS0h>i9V%Q z;zJ~EzDYs1&sQLx7Q&pmcbA~fbz@Q7YXWnd?cuc=Vg7W+f{~NA@>8<;j;0?Jewk>X z!O$NNN9=)E>!td~k}aIJt@Pc8-h3kt6AXuN0d1DVkZMP64C*BQS<}N9W?9`a)5ihL z*k-X~r6-&zV=(U{Y6MQgXL+Z@(2eq*6+yn1rn6u-^OXmd6Ck9j3&&Bb6>O)uoF~&S z=sl{>B^z>1gW+zxLBoFNi!=W`n9v`y68Cnoqjy@9dZjDptRj`$W2j%5 zJ8IhwFNU97RE_djcu*c&nkP|WhR}NH?IB&&YTH>0(Y>~6%tm8P>b7=`l4c1^aJ8r_ zS%)}bfsXLG#)b%aWfxthQgh8BSt+6&Z10HlR@(#+sP7B0=L#|@DRNZov@`iVoW{uc zHdgECCe7bp5Wo%-u z1qnFC^(|c2Km@ZJo+aF+dMD^s8qEe+TWw@zE#rAhKD1x2flCH%3^_BvpfPCyFvc{R z8iL+7R)QTZ(+|kH7_GB9Kur(ZH;U99r>ej@s7OfXTK#V7I(^01`B;SMM$uA@FjP4; z4jlg7a{sX_fBtyLNphT1C_|Gj3vfzFgsNb>mfOZo(eslvyJL41VWbZaq@NVpS9bBF znvgA#M%^hL{;V^^p=!CC1|?MT2mfrnC0096E+v9FI^-Iz7()Mtbl}24Yzz-Zg3xwH z+In{8)9`*t0F!NsM_GgiUz5&)veoEUvE0x|ql_IEy|I$i# zNZB#F8l9j}jYU0N65tHu4P8|gu0onTx{(er?V-vhxKm?R(&VmJb-F=fn(;9HXu|h? zNW_X6H&FL$tRk82(N4XkN8QX*S_4Q&yy#4{U8899WZ>w$NMCtnj>*B|EmSZbH6aUf}uhq018MXR)@#O1#W~0>_ev5bH+cCK= z$o8d_l`E>iq%R$#BYSkZUI> z%=n1-b{J3=Uiihg&Da*%lb05;Egb)@sPq@+%7g&{jY7pRwLNrbkre?FCV|zDuFLjt z4y#4xgO^1o>6zTPT}Pt^(1#G(;do@73&h##yIbYHz7z#vU3yI*09x{-z)w901aNfz zCeemZC|HQvbeL254L^!CS4vNEgzT&lkllOO^2hNeJp-xmc|7&B!+1=4JJ>CY&*b4>=SmLA3 zL#!(|BHp-!W5oCsoEMKr9K+hl%ck!gc}Y_96pw>yZ>N8;s4t~Yil90-IWn>~#?3SW z3``~sKi6!5K?9#-u?LdK3LfKcQycDz{EKbvbJA2gWfo0NDXrl7G9&o0;63&;Ccndf zfSp8sWNX3@Pyn}Zw59u)2EA3p_iy9I6!;0mIw7>Py?SE?dF+VY$(X8|Cqv_@zFutj z7mfm=4KKi3v!TlNU1#BoR6Y*|XMwZ3uR#Up3JuH9%Xfw?mI2CtvS9KmZuvLr0 z?KA@)1i+|I0opN2_|yU!(AwSwnosze5-rof#d+!SNqGOsGcsw_#<>)qO8vD%ByA`` zM7RxyC2G}1RrjMLIRxx}t`#-}KWrb5004P_Q$AYF_Y{m`S5J@dx2No-2QmM&>U=nw z=wE*<@5Hx> z(jGw{2TP23@k;MS&@B-PyQb+nfyQ|85=aDId0>w1@A)+Y_5i<7}y@AA2Q=q$5zcRst+j7W_o} zc2WLqDglU2(kd3Qxu|nX`t8q*8N4kLnd~~t^MKg2Yaz3=BNvE!0cf--2+q)LocDKb z?Im#KDx3lQRbe^mJN-IOFdv_H9RIF|ogA&{1jy3Tjy|Qq@N=4<_{|rn)xv^pOW=|< zB3(8-YO)MwL!1eAacfcoHazMkLhR*AgaqDkENHMwhbw-5T(3jwvE8NIW!^CFt}ch# zwlI*7R1gd7GCCZ{j%RnRF5i4Basf+ERv=B*OvV`Q__MhHpQerKkJ8KTs%K~1GTDBg(v`&OrVL&QvZ|-Q_Ld@0U@bh`9DSw$XBb!2PBq1)3!Qp|3$KdAWcCvTITKV{vlAz^=7HMUXP!Q8`|e zW@@M)vGnB+hP;HMS9ogYU}AVf2E)hCl}BK4A8I4fe8VTBJb>u)2=g)EFkGRAG$;RgkOw*3+u|Tq@Zf9aV$`1GGkKK? z1t^+mMP|8y;SO2-70{FQ{dYtf zMq*0Dxmn zLcrB&V=XwSJv9sA8u(WEJ4r9HhNvaAks(skf>&lCH^16@(=noWjy|G^S9wZ?lO-j4 z#QDUCdtN8;I9}9k7-XPo7yN7!A1nQgs&TGKSS$7zRx9jXG^?idb;Gdg*PsIdo^G({ zc6*#LdC(uN2_bxu>hJs8MGESmuEwT>iCZ((;kKRBy7}`Z_q3Wd0CR4V&xjv39|NeQ zf72X(^blZQ4aDjkie3q8|B}co{#d3A^>N{^iZry2i?DLi-r`jqYnu9`bDmhcrJs!A z+t~NywL!XZW4Z(agd9Q#u34L4{>A0fp~VwGhB#h_>ps=xw_y$gDpLwlMrts>HBso3 zc1Yh_M60=BOIA;(Vxc7^RDapaoBWGEZcwW?h{o-L=gSB?IllqObyp^V$m#GWKhAkL zIcs*@H~?-3Kd6eOApA=UGyXflJiJO+m5acw9e&pt4uv&vziRRtuui!~*cEX6f*AV` zP#1>NK8Z`pzhp*XWYYW40TGetV+TH`Um4z?({l@^U4Q)CrUSjAO} z3ZG=b@mNORd(Sm_xKdRf$fMv%;+8@OB3pR}Az%&EYXu#O>s3U&L_Hz!YM z1Pl*(sA#M{6)K1dk{hy?UGXkUhJLKuwie#-I0<4j5F`)9MV3 zBSIFx(xWacL-K-YJYleF+FsofXQy;SvEt5EaH%(vGw=APZuleIbkz>3ZK7sdu zd7!}@>wFIgQ1RNJs2kS0tkM!aOjHbM*eKZUG$aUW1p4AoX^~^~9O;YrRdksE0O~w$ z%S~Hjg9__^P`eO&orbTyH2!E5yx-Sh+W_cK+CyN{a`lY1mC@=Xd>Rvl9hev4u>Y`Q z)5Ohe25D3p!a0VVGl$i&9eil9u!D%D_0WU)y~>&#R1d3&uI^?FR5O#(mi zhKZhI{pyZ89rwSaa7XJEqi(TXLA5WepM@F!HW8?h<%shwUPy=p@JN?oP@*?4E0~Y} z6)gADbL2IL!jk!P9M^2fp&3o?tX_cq0enqX&{_$Jz2Hz5LS}b_6JLq=0vC{Fq)Iq4 zV0d4;R1f(iPY=nc_&hTo%uis$k#Jk5P|7TQSJ5pF9N{M1R7+4}mh3;{iaq>>(yQhy z*MLio|EZgoS(yLHsszR@Kz`Fp`tV36*;5q5LJyDX6KFDFiwm0!-lXGhjxTi2%E9r4 zmxD4U9|QQXhbm*VT(Uey~DeQHxdi=?-fD4Y2?>qw=X)884+71 zBm}d~m72p`Q%#s<^Xor<16egJCJzz?OM3slp?Bri4XrmSx@R)kT{pxo?(wHHZDk;v z|A(JDps?jaTxP~#+ zV()5_XCb|vkF633%ckcvgxDS#ww@6cPC)ixl!vlsw&rM-3IX-k&T?p^L=G!ogrYz) z{ApP0ThmoVEBJ6@)5C1L8jy3@|CUVdd1HZLz8E0w(1RhhbPZ;qY{WLT_3GwZs~avP z_5KJLieRkXZ~KY-Mz6@MgUyhwRN*oGuOym+vYMEp6s}=ZcHulS&_}(@^|y}}lIFH) z=>zd)^DM^%ypU*^{}K9-cK}CL7i@gCY&mA!b6(O+)PQIKjwZZzGu~-^N+BybAWC^B zCGCrdg=41SZJ?zFj#ScxIL0*=w7 zC(_0rG)ZpD7*}5v<9<2HQ5H0tDjklo9vy+U4n6S#fYLC>xJM&2ZX~N>Z9lUZ(3UZx zx8a4;rp1=SOwEJ9l+ov~&+T+azwkfa74IXldA$U4668NT7!m?!bg(f&3Yy}P2)VtV2xQPaWa#p| zmM(Av$~Ldz;N^Kr#|w(^UongIQ1WrMxh*z)jj z;v_L)>4l<30mfAp%_w9Weba(XplJhrdhdi z_T^lz?7*f3aDju$Bk>p`hAi$oL}@@rEV9qtq}RpiJC^`TF3}rV*2^1%X_UXsgbXl?1p1KUE8es==+7Lt)c9rrakK41Uw!V6!5$$9o||z#5Inz&rKX& zLYwrXOpu+0F-PYWOA3l(4|m~&h0%-v2#5aOwJuh#OY7|(LH|Ac3@rD*0(ZrKd;b>c zp>@4=xigwsefjzEuFmngl^ff|Af;t(`<|522G2Rw{xONVxFK2f^A5d8epa(IO4_to zA;dHO0jHEo51GbGK-1p(i~lny6%dbavdwrBer@=Kk?Apz3h(y>D)h(e&qk25JL1K3 zdg(r9IxwS`wh^05r@A^Zorf;Ig$j*V`a{=t`k1mAD$c9~cGm(i=UAC(WkGy$e2~1c z*`f0ipVb7bVg|MEN^p-5CD-%(@TYR2vAnJQcB^R$PnOQXPaa0D#gLv*sM@su#|ir_ z&k|k=Q>A6J>-Ou0Zy~MJ$~WA9Z=NX+V6$0)0RU9M0RV9QzblcPO`M!*><#|gi&U&; zV7I{v|8=eBa9bx}i&Ofqv|mDryagMnjzlgY5%fZT3^Ch0UL>d}!PM$y!%b|yexKbY z05hQQ^zY4fHy3XDff0K6bm5epEz9To^_HDZ8~lFBZr?=HDkm>kD|ufUig-<1*9k^9 znbKIJwnaJ}Rdy6&0%MS*!`JvU5ZEgn3y_byQ+@+*b@zeg>RH3(uAh*8>Jl5 zz^Nc1hjp9wiRQx}R>jQ|4BpcX;R7_WtO9sA4-epS^2RJw3Qgm?FGdX>h*D%uIS;hy_CTP1h(e6^sb_P8p(gQrmelUm2>rfL zS}npf8&!gKGFp&Z;ghg7_=IUjB#Y+bV%ZiEt`Sd&CUJGLj7e^aC0TbRdS*m^rZ7=Q z-q~qOAi6{rGR+v$|A^tr1!`2XH8chx%jqA9s5zeCND2H?F?x=cD8)@^n8P%2tOx&a z7@`e8!2}yU${QBrm3dg31+3pDy+f@YE!ihbr_Ory(>aS4@pS0 z$$kGPJs+!+l)E6${xo3rq74Nmh?t*_|aFeWJUtbQpK7-~Zqc8n28Fv7)QryH{NGc2k-++;5+0 zhO{j*D40!32)heU;)iIy@DFj=R}#B8t5@Va(os?V{(FuYVH-XE81uG4Eca@?3XMuA zcNvq);xkd)6%yd3VPa&3oEFCV-chYoe5`xAdZBB}No_Bgv+kylB?s(Fosh;+sa|C^ zceqa5OFI+^F#>W>aU3*=K;^WCSZKQ-?gpk|D9KK5ziv*NdH2EeJr!{IWdX)Qlb2+Q{d&TaFq7L<)%l31l#CFe(A>j&N>no8ZKP2=)1BTwLoXZ;l` z8Vh+N@KxwZZ#$4gI`^~Y3*qcDw|2wh2aEs1l`4~X)OLwtYZOUKw@pH651b6u%7bBS zRJZH)ZVa%PK>D5BZWos(sk_|Sqh^>89&r@#*_#*mi)PHf`p%HDV=DV|`qEoiUcVNG zS$p2YpS%PYLH^bZ#oDar(S+m|i2y_mM?NzgOq_lADBP3^E2A9rw5_-`h-5!OnN&f` zQFVpPQXNgI*U|zlqYiPTV!4P}!Q5qQEHVebov;mI8p-cE`VT{cm*D}8 zz2Ut9kwp8?RS*=R0%B2?=#zhqg_3 zU8`RPjg(FTFB`{r37b<7;IwxVt@~}kkdC+d2k^hc455aGAnP~GlzzjE`~M@%JnT)3 zY5o&w|I_kUtfnBhAr9|5Tbm}etVC{6c728{Ns@@JPVtXpBS46g!toNO>fF6>%Y}mT zZpY5_awrs8r}!S=B74oQ=gpMcN>*0CpjA$Ei;w;FV6l{MPx0bIFp#`a;pPyetH3|J z3YE~J_>I(QolJ??$s}8$a)LrfQ1e(`1F{07k}6SRTcezjMXqke)F|w>Y!ldg(9h)v z!lcltSye+4T}V78xSAR3C~L~V>X9w^V1TCx)=y%H0_v-5!fVVqor=@=44z1W&9-cQ zHcSnK=Je^WMu`(-<^(7GLh)Ey-D2{$Xo)E707bJ>I(C7E#(ylQ9r2T&C^XS&DCO(o zOrDt#V3(&2M1gC^CT#{gyTjJ`={q6pQ}h&VT^159$Wi>V1rS*)o1Tz!&qKYB=*hA9U%#Y+6-7*|9~ zmpT}y!*Cr4D`t4u3xlV19>oXdY*1G!rgJLpU!n0I7iEo?lx7()XYO`HhM_$X#|shO zT~FK)Hp6qdy-(N}Ug?219b(#A#5O21CBDdh=#n-p;&^sFVgqC(>7A%M`&=7cd+_g_ zhp|{A2qO5^hjf1KKkyy`grDvZglSW#N(kDpfDHH$NI>ZkR`Gdeh_D=wdlC?IyX&!} zYOkl+QR(8>?1v%ZKu~T7qMs`Rn^A}i8dF^m$5H0EBfRpyN(geMIc?9SM2G$k{k?ZV zAp2BytX}D~d%>*%cnYvv&U>3;CEIUPrS@4@%EI5o`AzG~AR@vEjRb(hPJV>;F&(dI zNoZRzSpWY0SOxsbPRre{bPWFn{iuOQF>45av;0Qc{;)?@xN-ceJw~Wf3eR&P7Q@|v zQd$TDbZfW|Dbo{T>>v>oR2Xg>uij7~39`Vx*t}s*I6eD7#!i9Y*wWyl(hBDv@{K~Xjxn+FzpWQw7M-1ah1^fKwW1s_}?*n&qCB0&jxR#YBBGHy0tH|$r=iK z!IwK+7F&=%-={e(j6dR&^Flu`WG%N*Ju(&vd#Er4eq3G^Lj+1Cptgiye3Nx<+LlRBUKsfN`xR)G-5(Mls2}#9?+=W}@x;Iwo%afV8i5kgXT@g~wKI zHT4U`0+&(e?A{4*tnC+JI5rgK6ql#P(}fZaf*->t7UDR!B0NDb0SFEVu)(KfgW-+Y zFBOi5R~{TFX=9R#&6akbY}1Cjyt#kMn6iKKK6I3Pg6`YoXOU;i%6I!adts~@yBx9s zieHdmlCydaYOq0a%7S&d>)TH}@66;?MH)tZa(*LquN7VDh6V9ln`^Cw9Z^pAz#9H( zmyxc3iry4%OR}{+)b!Cyl10Hm|NF5CwQ%o!?6|Y5uSeBI^xDF9k9&hEbM)JKi#s4MrHp~td{KeE4=ahF!kC-R|gbEe)-+lTpKB5nt`y+`sp1Gj2yb@VozXyp!RSG#!S zK2@4JHdOQvyjB~e<{WHu(9j{f{LtdY3^SZ_uMPuFobewERK~Vc+{o_q*1p!6Zs0?@ z4|vb;9zN4?5w_xb>mF1@67V(UzZbHO&y~A=ILJr;gM*Q_izCe^*`b{ayHuvvIro*i ze>A|R+!M|!9e^0I8$$4^8qJ=c(JuA0SCWSCQTYGT}CZu9NNnbc_ z8L|~c9dnCLu|HK!wDQGJy%#h3F}Wr&=^NFzN z^B9EQp98?{EQ2|gTl$?_$?<2aTL(^Td_adxG~zTYe=RI9tFc7*4d3|`x#zCf$F$Bi zh)=^V;_|Pl*6I#p4St10&5x9=NAA}w$bJf^xryym_ZPMoW8TlIlUrwz;oHBsG0BhK z?z2uCxc(|$(QD94-iYo#k*Nk>w0+5_bxj1)>|ZR?wVRu<>bsy$XDiRfc@v1Q7u4;I zZ+O~Uz3e5O-Pg>s_nmG59%u_#+!)3{Ol%lE-G48}& zA6j=jpR8~b`nD6jXS=f!SstC${?FCzd2~h6ILh47G1I-OrM1)2{UYJW0@E$PeO>i? z@2Ny7me))d)6~EdO|}l3FFPcWd~)&BFh@+{67+5;(<~otST|*A(Lwxw0Z%}%zaNj!BqAeec{rNV5SOhWH=p5-v8JOGRlc5sp0 z;U}R7!ikeS8i#H89A(}VfFTUK=Xg>;3wj(+gXlI)JN1Y_hZbEFA~4#?9FWtvAOMZd zXW@d7WR#O+JiiU&JW!MN3g#n$FR6DMp$}=8W%;1tVgRURFixBw-29bDSJb}^>Sp`tJP4duV>Hr%~07u|L?-D*B z9HK{-T;})4Ji=LCHVendSI{m(hD(v7V&<(ZlM!I^(TBm%8=f4DKK9P~9{hfKcJjku zzrXLj`w2ewy}gsupUwvFKa9K&Cx`p}v!T~J-iOlT(b?eL`RL?qh+rDMAvA8#x8Ctj zUjN6_v;J`Cot$}tqtn9yz=ICXddH(df7td0$9sq8`-9{6Z4Y30$0s8MayU2|jG*S| zq)lCyTY4u4-ckQ-?*shVdp9^7jDDgn4+f)S?C#*?j8?68+B+K!_RbG`XWr@g+3Cr! z@8S6N2gAL?-r%Ue-vJz;U$6f||9IpLKlBa{-QgmflaI&!GaQ3GT<={UFzvlN>|=K{ z+Wo;cAxJouBoO5O*NS@ci9yG#H(a`riAKlYJuluz&W$V6Q*i@eWUhM7Z-|pOD$_je68Q zKmo!*4fy@t`EWoa92}4OXJ_Z9qru5>3+DVIPzW&XLF;{@^~o`gnR%ywa`qE~Mtaa} zw7riX`cQs`Tqnq6;j;Pv)@7$E*qANXN75cVPR?R^mHch=OpfF&!- zc<<#)Zxm)Z$`q6`N6GjGe?LfJN#7^wjn|Z#SgW8eO<$ zIY>{pQ;i`=b#^h?9f; z-cP=_jde7v%W<4fVWdvyUSTlx-?Q;G=nw8^T#zB`Q=ndWcUcVbI?gYft&RsQ2$KCe z3_#+0@EdG^UT_yg)8GPF4K}Zj5o{CpS;y%C_LTT)5ekplt6P|b#WiH!Yii76n4;o1 zN=P8Z!>LX4|NCUP3c;7-LW@22{_*N$=-q?1FkvMim`)$PIE2knlL0jh{A(O!;rMp8 z0}(wU=dc z)C@^coK1tA&I5olDBLd2os}dKs*khT6eI!Y`r5ydG&;*wE_$E(-ak#kJyHCgmx}b!xUbQ%YZll0xrqJ%O%C*hj8Ax% z(KM%ZEk{vQ0w$!6qJ&H5aG*oc2`9cW_UECR=H2XbMbt|V2*A(3cyGN19E0%uvhQzn zH(r@P8apB+TM< zwvAwic6Zfd#4d4!Lxg1yb3=dXnqOZPhA9If0jfqA-i7HSO4h5&9?xSqfu~t8bvhHU zcyNH#7tE)*2Pg3v>_I5)fl;fGrP>W&VIQ*NsK(~-34hxY9&pkQ`yi(JKboPe z&})(hQ!k$1Ucj^@mlhUTEdnEKLs(=s2BQ-=fHNM$C!t^ljvdakdXnqm52>Odx=n-O zs5d$v`Ujvu;sh9(q(lY^CBZHS+02HZDE36cdQd+Lu5j%oI2C9wWJ4KXl#(S(j8r6F zJr=NQHl9QLFv9YqAiYsc`zaop2Hj7wu*a2u9ZqNdAEUS7eku3*A|gMGvrR;ppuyJ7XV) z+-$YI#(jfu{7pL3ZS`0cROa8qllOk}pa;vS<-K|1HO^yNEiefQP69UfJ~bNn&FYV; zLb2*84fA;#D@1qJep_4njdttuN}xG^7yKifdb1$Q!b}-%gY=3Fx7hdk<|fHBmfh># zT@+9qMETv>VE=vJXWi%ckPKB-E52eiZ+Nh+iwtGa-ehXnRrq)8{vwSgSD{as(6V?- zg!3##KqdsWh4`-7sKSru1LvX==2xYO5n@)=F3`KUQ4!&JUibS4gX6xBOV4i-SXgn1 z58Jb^lnVlzwb$Gcy@M79X>$7>1s@HnreUMatGLAw8fUQcYrTbPz)U7>oL+T)$Ej7~ z7wsLe8{&!nB1G*9RUD*M?Eo%dvD^R|d=Z-Mg;*DB7ttM6$h?5$G3q(Mm?>eLT_^MD z1T`DfeNcUcO{>8msEf^60%+7?K1Pkh=VK3EW3+{ZoS#MGC<1_Sptx>T0;(KULzen+ z@2Kxrwo;>{zC6B+V*D&5~DUY@AG!w8&sXs!t)1PBx=uH(P!u+;`} zR)l$J!NeU+%`kChCQ=Dx5MHm~cCId?M*Xv+YJEc>;O-a}TjLRv71C@znqNr9>w4wxI3Ien06{m97FelupC!I2*PUg3>%+m*W7z7`B zP)6Qgqoxp`Rxhv^0^MADX%K<3TT3>ablHh`aMgnC5P1X9V@^=lpfKgJu;49sAzF3} zi;k{FBhW3A6isHqC7uIG0iC7E7&LAg2%dN6S(h(-H#e_%vt>zO>#@|5Yl-3Id~|v~ zs$BhC?Z=}-sYEA(1vS^#7c6?lWtBzGH5-b8rm`FuVE{eY%=fOt@eMTiApmKhR7WEf zcw)V#97<`~eZuqVrv_PE#{nMkEu|m6U!a!ww=9W2HCkHs)=B}AJ1hWV`^>9tBoony zA3F+G&y?YmsWXxQgyT&##o0vFn}CQ^Nm31={}9~HrnpDYV7k~LR_)Np+EUup-Qc%Z zpBlRT0QCb02~B~vJ%~)(LdK-s>jj29OPd!iCk01*MzG-~dk|a%nOVdn+O*7r!$FQr zvz{@ffP!t5cyWl_93ZsYU=n)sIQlz?1tbkhgTP#rG}(6orx?VdNJg^GegZ|6c0OP}F(NDH)H!m$b(o@e3Ze9Cu> z*8w>N;I0EZ!ObJ@M71mkTzv1V!T4mh@h{P#VDUcpd22=)(zV%%%|+ZVPkEyf0CB43 z17(%6j7^IMO1ALD3r#8&6qqkNcwPe0KSUW_mu(-|k<7g{2TYp}d6sCr{shiI*DJ7O zsSS+r<|ueD_PBj4)yK|jw6i}%xAR-e1nNu^@GwmW&sPxZql`Y3;{0UfKoH`=Cz{AA zg*^$D)ENrZR!s}kCL>(AiJ+uLPmIZ3!O&$h$Gv=-jDsmc?SA|1x42&;Rg`5jyu5^c z78gA6Q=*A^7{&94#kxEa^4_*LEY;qNEsFa3N1V`H6UJ2`DvS@LNDxr6y{dD$*4Qtd zvwDh_Z#KVxyb2#8zAy$|_X-$`^$d`JaN_$%m?rEasx&n`XWxUK-ti8gE$t6f9eWi~ z!jeI`L^0{iW#aj;@1J};_74tw?@`&MU;IT!S)c%FJu4k%rS3`$rYiGZ5KNR3zp0h@ zjC?C;1f`3`nsL;d^xubZh{so$0Fgk7m$4J?XIO-^I6*DuTg1Qv-V1|Nt`4t2=7H!1 zcmfIN-#pxVk4M|RG|2E63mC2wkab?-Q00nr%ak2NVVY3noMDyD+Br!nkGFobO)`Q_ zDQ9fR*2rfiGK0t!CUFtnJJ1T{ztv^M)ik;ogYJpLY<}J9Fobhr7L>GfbI#~!jg+Ms z2w;$B^BB*C$etjNFX21@I$m%U!_tk$8A3yYZRmS%J+|EX;~>l5FxtD#?d`3vzuo@! z^*7(1A0BQ<)tBD(>#w1t<^7i-0a@C`tKdU_?=OCn#p5pMMY4mS{dzBm@yLHA^ue{k z6DJlXZiExK)#{L`y8`B$x29hkxKJHeYjWv;Mu22b7XVPX<=qG9e-27}mZL0aSdj3@ zMKS}=T_nXc#tbxbplWOwG9u3N1iW^Kas^lr&FQzvWDZ*cvNQW-BLiPVWPq6@_whYm zj$K3ns4IX0gNSmN{VYPs+ZOxHlz15#$T0GiX5MFze?FrzeQ9*l+eIv)%zR}+|c3*htv*)Az zr&1eqez1$CZrtr|FnTQ@5p}}y3~S+V-vZU(Pn_8%64HkWq(b=Tjp>H_ z{_?HY)RlgYe%ahL-4$+Npt|DJvn5PvIZV*S*Tm%vJ-Ac)D6}*5qV_(uXI!moA}-$C zWkne8YJe^;UO3+bZ0i~5vR+by?g4%L;^+$4)zH=L=+Q+Gp*ECz(=fm@Z7gF!y9?c* z%W1*#sG$)Jsr+mn>p^_>pcL{w(&#>f(^;4@zov6s4xKgoOSfzPMcjTGr1=@G*lu@3 zmj>{kg{#HB$u#QKf>nhAd}WB@robCr*P8@+;5Xy&-WlOOlr{-b#(=xfZIN<77I)torKd6rj$BSlssY}s3U_aftJ)ZEpzL_j!q3M_{bvOS-VT%gyi;z-nO_yy_Go@ zxGyx8GHk@-9E3Ib7~wVVfE1-Mh>gu%qC#&nac8PY2ygB(1>_GVg#59Hmbyki~Dx7Rnuy7caQBgCz(09_UUvnN@mUNx_0>Xs|Q)Zn&T$EvRI+W#9)q@~|uCq$&E~`EYb{gigGE@9g~#L%+3V9Vkj)0Sdkb z6VVYUk);d)x?j-p8ICIG@Ph$5w~bku%kZ*GF4cn>I+3Rlc@E)w4ei%}_nxrZ(i0Te z25a%!F%qqw8cl}NAsr4qPULUkT5@tBr)Xx3704vr>1nXeV@q2XHU`V&7@+SoKe-fB zIUK^!ABSHJDic0l7Vvh*J41wi_#xi*cGk3y4@|zSjJ~$Nvquj*6sdZwSnX81|9Zdv zYRXQAuW961zXQD6R4|%`(SF|gr6n#zeK>%}_@b|gHvkPyoAdr|eE?dK_;_G9Wh^1d2UD*y@GHLpJWO*^5C*wG*~> zkZ`k|Dr+5iY`m2B8Pfqz_TogPZ^3pdVeoy`TY6`5oiYOT&efH zz0k|>3bnh7YcJfr?UOXC!n=apW|=gtvbtqGdZjb5I-}Y*UNn`t<;IFvQlNJsAUxQH z54aqo9JDoU?^-^)y^AcF&U51GQDR(Pzt~KZ!NK4l*Pd^^5@#v@EphV=Z)Z7r=dl?} zwX&zE%IlXq{2bmw6sq}3xXyBG7irM#9>F12J0WUDDc5W|OjN5wBx!VoE-XIU0MVF- zzK<?1Y%WrBX4L?~ zS5a**iDCP|-?N28`=WF*V==y>h0$oitcD^pZ`WEzK9=;&s$nZr;W^zO7um+@#J=pQ z-yqd!OAAWRwJkGc2Quidc22#Irjs$+s>DIZdc_dRGr^8>3b~9@SaGnPP++Zp+FCca zvS>py5YiiNA7W>h^n6Oa8b&`O<)rKBN3de)qI;(B@)D#S9ZfFSn`}Hq8yR3u5-~yO z_aSJsVN5qQxCP#73zT{ug5f0SDg;fiaH_{QU!t#{yKH`D10ljJYhHuEgmYZ3u zAG>{~oKv&=2>qj)3Zk-_ptXbu+O_`du6If6=yUu8o9rbD(?tctR0jlM3+x;P9=6-D zpnosWWz^)eh04e@G?Q8d>MI6?_J&HjDJFn**hc=*!bNqwQPnYTAoS?gla3yq(?QAe+&J>{^9*+w=A5q}DA!G(A{OHc*R0ekjp*e|J?$&Vb+p27 z8Xq%x#bpb3l$2!9GtcYPm9iG1bt02lOJw4U?CKnJDnPrFc(TE zDfA3$rqOA@e>D_Gi^aJC4LjG~i$W~WOV>Bo+d|Ql`~wm+#o^_;OdW3I3B%AHvZ^`0 zJyiZOQicXKq+q2gJ98CoS&fU2R+AvRHmp8tBgRzKR?QV=#d3w6()}1%iLLd(7NW;5 z^RJVsQXA-vb&)CrP*dftCvRXpvU-%dvkwKcHVqa#qFqrxLGcBvXC|vZRMXz*JX2`RDou1lkuajGvb@RKvAs?iHHLUWx6P6SrEy!|b-j4>g ze&*Vz+Vcj+X*-a6Lh|aqr2W+rnU;6ATItp$V$*?WmDb;i z@2H3U54KR#@8A9YkNv&#Q6DND?;rNhDA0j*cPN(;>}sv<==eGgKpOWBI$|5B7l+WP&^brv}Wm^xR)ZG7g za<*>}^U)lsy$R}v7P#X9I&`^-=WTb)wd*}OA&^nCjlqaio!1>UCaW+h{1}Ly-q=L4 zT6|q>fl+=;|IHupZ@S7RGcrGL!HaRgv#o%@PcQ?ng&NaGad;4c>x_nMvZzfson+!6 z(agfoyUz1j_th(PDRCQ((*&b>b;ilb?E9^^^$>1-H~Hh&-+fJc0&RP87bR2hR+JNUw6tVl@sW|7E{pB8T0qhcfw+8t zvez)_yR&}pFQ+Gil}5S{lyxubRQP_ug6!5WD_rN5kq2({%LiZdKgIVODZATTJeD065a>GBUdN`;HP$!oPxrLTvkxpf z)wy^69dCdrA~7>owbVN^CV+8O{v7qV)I9&(8YCBY*S(*lJ(f7R33mDX>To;YE-!ApA#8 z#TO&2p3`Iu zyi|ab2^z%X)F>t8i5X)s8#{V4kmHXjGDDl_&!UV^=7 zM4-i7hABTi#HZ5UBt)W%KO?{5)NyW!R5s(-2pZhjMu?6I0D|h05>Fh98eE5L|JaC8 z1cU(S)g1Oqm{fj?#FN8&BU{ka8I1uu7;}4qm21A*`)j5T1&WYybhi{l=%Uh+s7u2xA&uqyav4)GU-G(~urbraGuq z0d{AN{qof+;}P7LDudX#!tkA@-CVtsWse7bO1a7B4V3s}d>|?@=S0iN)-B&UBa>+2 z<+YHQ@%i*hYlY2mDzvp5>c)U`PQBUuLS5R3_fAi_cCiTYJ_OlGOm2q&t!Z17UMbxs zgQLtW^)_CuXtFB+LEJwN0*~TZFe+3wB{i#qN0fh_=Q&tJ#4%3tfNE@)c)?Esj=cVG zyDegHbAYeIWzM|sYtd+I%R6%QfX3@Cs*7(~-1@YUDks6)>`JKwO79l8>aX5<+iLfR zTI4FyAse)y zYrBh*zSxXf#{8xQmR>Y!oe)++kl&0aLTP&j?CQJP(kfQk!Kr3S;%|l6HPzj(OycSv zhwv*^PxWXKXJA$|;H4drK2d~IxkW#jSlN2DYiu8>cS70_j5B(~D;OON8HhVwBR z_zI_H zD_3o`8B}f{DrgN;84e;9_`xx{qO@5nYB!!JYWe4L1up;8i(NUYtIbVGGvHs^sz~f= zX7-y}SX&3aaOq6mg{gW(Cp$Ln$ONHGD6@Ts55YL6x0Pm!2*kCRS2P%{6WCjSY2Wv} z0lQ?bv*nic(F`>~PFYcq`8wQ!dKNXQV}*ZJ@&YgP{*R~qy^()<*5CIJPR@>cqpzEe zrqT8`6#a$ln&7->#LH>X8M515p%R~-+!OE|{-Pi$Enoxvhu^fy|Ea7nE8+1u$2Qad z=C0Ta`A_jIYQcf7yWAU1Cn7hxu` z4VGZVwY~&K{C;o|Mk<)t0(2-+@k-d(ZuS6Y*Fj4Tcuzov6(~`Y%5NFv)qn21WvoEo zAf9ss&nHr|{3P-T%(oKT)gn~+p4i3ih5lFrcOkMj(QKvyl~!WP6}~W&=nWd}c zOJP`oxd_2xxL0IJ9SA;@aD-y?{PE~e%BqIKUl5oZW%hH%wdCw&k9u+UtCOH=XkTnR z4#rPJQznQ4^{Ho8Po0=Aihm{CRV3sxLH(r=EP`Btx+_ZLWwQ9Gh!$a1YWPagIT_kf zy~HKVvN@QC4y(keq7ZSMea4Lg&ps38U0^9n7C#Z>3oVq2jJk29AoGtC*T*7vGIMbd zv8pb8tPB%!S9*okhP)_VtA?S*e?TFW0uFT&UBcf9&J|rhy$dMRy4*0qDw>nOHGHC& zK8xQ`w*{1vlZJk=x(VT_!M7vS6PZjFLIr3E47mDD9dq8o_7pcmPlBUG5B+6ofm)^E#zD@v+utG!7;s1#bw!fp_@y`-s1Va1_12|76SIIo90AGE5Od(Z+WO`d zNZ;{w=Q_WgnyUbNSU3Mya2NEk(kS^DQKkj_z8_BWK*HeL^K7@pNKM~;^UXJZ{QA4| z!DzzbpzTr>9QU3_jV|j6M?`Mx0&I+Yr z0D9_je21z&U{=ugeII>3-uKVwGce+J-%tprFdqVl@D@>SzOX>*yAAVwl&FC_H9`K` zU23Ol-BIT-xyLggCYZ1)b|&}mVL!+TbFduHO8oTE!;kjd<2!7@#n|%H<^v{NAJ%Zk2f)p;M2qs*3bD znoslS-6M!65FV3o5BhKJo%+4KQ+(x3n6w4F=0OaphrmDXedwKSD99-J!h0_KxzHQv z1i#ST{u6quIRFaec40v3ZUT!6z5k*jiU|eftJ1SI%Q+lXWHx7_|4q#1F#J+xvl&V; z9I@IcLB4A$W}IW0PgjnH<*dR*e1{XJIm%O0I!g3B+q0`-w!O`5!%R=PWQCtCiw$j= zXjYCeA{P8?BdD10X=pM}T5y(PZexY*Y$S@jh@bdD(xQZ=EFL-J=LF2!OPJ{6yT?7*#)u7ERjK?XpHt5xxjsn18-h`3&_?Q0Q=fN~{Udwya>&$*v z3?=DxW~3>6cKk$C`~s&~KeI`zYnNZFFxjYY>h3MgbNQv&Xy3@rMk)e6aAiHNri6O_`6`}u}V_{RBaL%gqW7|bWM$^MC&fEb9{o+iO0qZz)p zB5DS_vFIJz#>YHn&>M^1RW$uxc$$zZ0w>^K+8Uq}f9z|AV-+;lVCUe5jCPh2iHYf~UN+W_NV~7w z%dW`gl;5k^Un%Fx(!R_CfCYVV+LskO<2f|DK*7&4JQ%ix#qBl@X0<0^x+%&$?tl5!E`*I!q71C$ZasiFIh$I0103E0`$Af z6;cM+KMR1R(bcsaR7xR_<#$n>yj_5k zuyYf0T~8RTTe4=qEFi^&`NlS=whPY2nufq z+=~~U{`*O|NUNuyW0szUk;73R(Fy3r5ES$MJ|R%pg+JN8*ZbZioXmAZ|IQjW8i>llr>G3+HG|b3jq%B_&>y2RPpU#YX6AwCU~&}9 zx?ME-an36ArGTz|wg{T=sT5iyMtVxo- zIHGjRVs~X*E7~tQoRkdE8xQTR=}4G-NZ!?ZR@jA>#1NxKtSB2Ix(Fim8Wu3_*Te zNZ7`mW3nm?lP`bprlvwP6evMA>eoT$hdd@_M$*m+NO4kY)a)0xIHILZ7D0$H&2ZNb zn-Cq+W-cpcnQhgh%OaXZz`9`+8cj&U2vTp8B3f8tkV@NBs+)nvEkecFBW=iXwyNsF zYZM#RRD8)XP%MdSBg0%)jfw8+&wm#7B^D@c27cQCzhmkU^tR^Uwr5GvRTnO^q0Nm2 zKCV&Nv~wAqyf|nwvnn*EyUcT&fhCiQzTe=@lLCqfZ|fKd7|_q+9WS`R0|2?u2e7Os zkED5Xc&a$0Fj1G$gR(cn79fe6aELLcr2{c-`KBc?X%HY%u~7DR2{sIWtdr}|L%xn@ zyp&RI@peB6vk1L?<}t&aNXM_T`6c|Lf~rwf7%}T0mt@mtlHigVPm@gFtg2`hQR+#j ze4{)KW_S%n3Aw{ZY=^M^mY{1sYZgWZ*jGM0A3}EY*RQfv)+ovKKP#!v%YX>O$}mg8 zno5d432o3|>orSR6p}2-F?gwyEc`-d-blGkr|AF2HZH&a5x!6Vm6V<_n$o=N$+j=C#UdxR!5 z(}?8zBpQhIg_{*@qj{!gf};>QwgE2 z^-Nak#LS3JOuy)$NJYv>B4T#1BNm#2K0ZbF2Ff;}R-PfYF(xZasK|B# z#zNFBn2?fJn4o1eG363Q`WQDSRR!6217RBGMFq_?6!XJdx0RC&raIjlCWdekZAk&z znkp%ylpf9*0aBhwf=xWuIw{Vj+^^pUk9JZ|M>SX5uw@9=7A*qz)?K@*9hvB|Pz5`s z(`0}ypKRQw*pw!-iD&Z*gH=?-%VqTq)(af$wszJm7Ae#QRaKX;C9F_XvdFs2sMI;` zlwD54p^f;3m1St;Ak>>op4K;=U(Dq|MK6Z9y~!Qj$$^jql{sshXrPqw8~ao_MDd4= ztU}taTtjwR_+%TErAP7yCtR(gf|H2?y~$FvyT+jyVDS}+I7`7?8!=lrk*ygr$a(BV zrotT?*V?SZDL$&a-kdwive{&$ecOzx!WY{T?oy(url6TecjA@tcXMMJkc9)|d(ey6 zFdGN6aMF>4EtGTs3C_jd`lomuv@c-nAdSMT;~j8B-q$*@ly=JQtkr1{ z++UwtJHDUQX3<(WqzziyF{#U<2GGkra#z&0PU2`N-}PRjfJ4XEE!v>h8|$h7zi*P^ zo{AM?ynIQpd8Riv!+4^ml}??CWL6%5;x5STJ-Qaa9RncPhB?BGp%`YY0ITYX*Dhii zuiMLzXj1L5DTXH8QJGSk>IzuPYa(A{U);!bg?k@k5VP?3^l9C-6)s1Gsm+!u+gvXb zTV5e$chHHnVa8M8_$UoGurfN-NBN`ia=`Y@uyfTBUr)dP*S7Lp8jjBJuP`6Cl-q;- z0-bfQOMEG&Uxu@ePs+ywz4@bzwDZhFG;n&Blu)4l^GcywQe`33Im3Abl zocUq7QHW4m3_)ua5pOb?+Ge^9yZWctzZrchdDMYcCMV1t*I%w zc@|x1?TbzpJchA-JVBK!1QeXt*D=;@iBSMV3%^*ioa$O2DzdySVQHcp@6-#LA0%YG z30rKBV@=OLEl?-ab@hnU(s!{#RZsGpww&eaHEmdGEcm5W5O6i|m8<#}HiNbu%NtuU zmt249*NDhZI{OzgitPKx{oYx5x7sJaqT?_~PoZN;V_f8f?PtV_$9Auu(Jr_Ev5GJ5 zNw}^EK)j=XVymKRTC9qsa`004*&Hn2$W)E`^+nc1TtFSg4)l3}zQ1{E!&nfmdXa#! z7duR<2fZ5E>h_318|HyL zY$6y$6KYv%^Ljy>*U}pd!D&~4QUw5Aiz;*)v~H}0lfx#dy)vDJb1+SU{ID-^ig=~q zpPe<`<_+2sD3R$|a8I`9(h4Ie0PYl1`a$z&EUss)D?w+)C1KTmtsi(PH+^wjM-HY5 z1b&%@>}nC~1%&L)(`x})7>(UrSt8vH>|lDEpott6MVv$gXVL^Z)O@3ej;afF-=f{R z>8v{V*69&Yc@m9}ke`I$agv87csO4u;l+$(6XAeY35NcH^@)9koEV&jl%x!V7#SlF z1jlWapKZ|Z_q|IQ(k3T;M3rQMY2Q;IL6l0!Ool-jL)8WWXOX*PddJV#0IGL8&vNG# zb_emVc*94C`FwdHzpnn+PSL#Z+Rjz45bDl?-d~&EU;i$>zg}5>nvJ+wkeMx%)uxce zP|FcP#e5l+&!AoijU|7^9Y|CIp|%CmWrgRgJT`HBDy>h7g;7{hZC+BIht!}arY6ZM zx}?z+eT4UBX&Wu#$kbVxt8IoZ>lI3NmZjZOq!}#@mSN`i*UnoG^8~FRXx~tS-KO-) zJqaw455N59cn`;~l*J*JoNav};;Q>Euy@|& zJZQ-*7ZmNtE5i`!CjItwpS8)$9-Gm@soFl8P{s~=(ykZzIxkwX19mW?e-A5 zee?WoN6+nc1l@Yi?e_h1NBbT|yZh|XzJKm$-@|BkVYF+1n8)})qPp6XwpO}{TCji8 z_h)aR-t%|SLer%?X}K%2n^p(E(%aU*eT$V#d}Bhd-U;1mwHvOxVLpKo_#SLAGjN^H zVTg*E`kdygFh)g}70eN2;ULcNXwE^+lqdAFTCa9ju$+SyNtG|pPzzP)<&0I$Lgp5lu9<6C zYIWwRH(AxZ-ZKZf(y?!l4d)j+1`!_T2HA0v4^>`8G{`fzVhV10j0Yz(73<52jh!i? zRymL0IdaOeVmVriO3(?gu7gL4nFhy0jw|cL?{q5@1j!x_paC^$@9!d11ZK%Az5s#S=}iM~_nQ(LOrv2JM7Sb)6_FXj$F7ys^KxF2UL zjR7MhajZ+cewLXSgFx0;Km25yzns)cNY=KRC}T5R4sMN)m{3@m^Clb z8*XdBrX|O2G+VwMt2Q!c85z5UHY~3sEv+t!KI?eVYVT0xDyna<^TfXheX}04&sJx_ zBv^c3D3nSwqIN9s5eK?`6$E%8m_8dA_8sT)Ec$buA|>opf9@MZQvP zO-=NiuR*-EY}?T{YwXdL`4s6-rtd8|!zP!~=g(Wekgv^7!F59bpbNgV^#4A`JF~Y% zfZuzKL)>dQh z;fe~Z3!Y-tSZhhCx7!-0R(DNTZJB&`i5K`J1cV;SXR>nl^O{RHKiT3)XD&3oOP}cV5B0C^6V~)almk$}6o>nylY> zR8QNHfA_IDEcfr9G_sofXO8TPOxzb7-xnQRAqclS#KOn_!#VVe5B1q|S|6bIe`dDt z7t-MVf7g6}$-zE%#+SzzuD+zN$~v_4m`4y1`x zWw51-&gc1?lA5++(`f<<%XM1FpYR87ae}+jr_m4oXfVPAB>dVB&Sc4b=I!-Wsz%D+ zm87}cEm|SY4f3oCk%RKj7%>YKJIp(U>8BX(VUpZr-h3v{jc)8IoL_P*!?POsO***JBOrRV$YAL0BEN^pkm>+7 zoR|Sg2E2o5aD^}M4^GaGdL#d+KOFYn_x*#jlOvxK-+8~*%~YYy;QjH*8793$o8xe& z*wefDMFQ3tf4W_VjJ+n)n_lcJ!^K?vefm0V`Hx!+j2KNMj_9JRSd$$Q| zpsk`9@@SujAcYZtqaKVs4UwvBa(eJ%)$k?>iba;f6+m~?U-J~SI!4-N07 zPD;e2_z*q};v9L-exPaPJXz6GQ#*x7upRpa1-p4KvAI{_h{#Yj zmC{~Tv)9PgUAM}6?zBu0G zD`_FUAo-V-QSq^GfuNE{U=$%rz(*6?w6aiSEm+0`025Ah#Pdv5$Nz{wHfQ&`3u*gJ zyw}^_MU-c3*?#Mz6ai!hnHeINCf5bo^ z=wZGHi~K(MJS<)>#-jNx2)OTBE1`0ohM!52ua_Y64LZVatcDK0JO4avzFC6J*MQB} zE;f7D$t?4dO9@3oag@<)jC@BKB?J5&V-@4!#LnA?)oERs7MNI%?&)wvhoB*hbAHR6 zq|sG`M;i;4N=Z(p&FkngS1DCOjw*s7!(s-z7R98=$e0o5!{q)Q2KL~h4O#w3$k=`Z zCM^I*|AM1WZP33jyygNz#Y7+ykX(It_pKM((F+8g^_En!;yJ>~^ijjj5sY- zfY(UTq+%o#S|RF$9aIBpk^wVSEyVz8-ucTd?DhQR_SOOXw9wOD<(?lil{lUVz65Iy zVz;ZUhacsqRY-lKd0aB%2`LQr=4!?o(QaXV6!yd_1S<6-?yYI}_ENnbC8r}gmSCie zZ+~I+^j&nNCP5wkrl7ClO5q;u*(l-t=50ap>fo!;g`*dGI>?E0jzD~NZG3m?^=iOY zZ);AZ_yq{Pwh?+=MrgYlp{<8MZF#>s3;2cUrHyi%$)|U;B_rH=*h7Fz28sX$;>siZ z+8*K8Xef^~e_-eNC<9hzHb zywQNl%v!D9ikf0JulKJ)^F@xk8K7H8yr*#Fbk7TO$| z5*WGo8GbG01+UUUNS6bOmIzu>u2vySVbD)7;+UT*Lb1|D@eT>HKQF8wrKizXD`7k} zVMw)Yq@$gpa(EkLH>fz16W#WfD93u%npM+QND%iusFO{F@e6|3QqX=?b7wxG_OSJ^ zjY&paI9>P8lB19?JS%&gv3;U%>2XvX^p>MWyMW{d<6@qp>3EhVcevUEk_{9zU-E{c zYD$rvDC}a#g(E|(P*5nWaS zD344-nEC34-%!KDD4su1^;4~i1Dd>?RG#bkbh^p1jDj3nW9hgp`oAe%*qLAt7N6*Yu_0Oj&B_2&nOY;|^ z%K;&?q=h`Y4dgze?l_P==R82}BcZ{cosdqXJ;?O`SZD0Bhrl zGjzdss3E6zbtseB_Oa?%h>v<(BMFU8u_&!VHp-CcJ0?pttlshMOeHTiDgax)V{{B8 z!Yb9dnYGaTMumi>B`7V|KoyjTtx_=>j^a%Mq#BSrFUK8Mlgeok)y77uu$m-mg5+^U zahm7}SFy0_(S32YQm1%F#n(%#YfJppHQNsz38-I?k;1$vKGz06%0ypk`%23#w*X~|JEmX?sLsrhB)p&jUoQ6FYt^evFal{)1vAXRhb)}^mJ-zIL0sZ z25;F5yrr#OmdUm&^MBh7On8Dq)7RD8gx(?Ap7W+_)eU1!d_fj$7|;Pie9oq!cj^D3 zO=IEXJj(^k**v7=IXlNH8;9o9S&~H$pnc>iqPbVQg)C45o<7M4P@i{~Xa&!iWWGp$ z-W)q)TRPFmO7FTHDOx>i3Y0<8>II($VFIDd%cgkU2ejai1mXlmuAJOylyHo`P9|)! z^nnTykU%0Lj@3j2<8hKsL_uaZ*{;zkUb#{dBrYZ&ddR?&1aBwwzGoia#L0aOZNp4o;z|?X z41NlTEdXFH>BA)D2Fj~RBAYOl!@*H8k#n)lO?R6cFp!roRW1O&U|-fGHBEj~iDam+ z7cZpGw>n{yxf-`W?AV?{K%y+1QZQ-}p^Ky<9^s&^q~yi5bOmf2OPZgegeCbFKURx2 zSfH4OfB<320G3w-r?6=H&>_aBE-ao>c3R~-PDjJ4asuw8#8UYyQgrZ>#1-sz)U-^} zsv5OdH5pU8vNlZ%xZSr_la{$tfS<(=;QcNSY)tJi~m0j#(VY zuEpg~MH#Qk6fBtUDy+MlmD32J!doY@l0lWtT^Ul< z17ejj#u63P6;(bStp2hf-rSk=ICMNym4e8lYg-C(wkn_4Yf$=|P8yk(Hdi}XT$>y` z@H?hE;|x3|F(0ZL8(2@G#G91ae2#zlmTA8up_VBFR)+J#n+Jcavg8^70AHDD-4n1H zw8T@K&1iSS`2|HU-NY;QDW=v`k08Vs?tPM6O~cJmnB|)$ou*E7Vw06&o&z)$8Lwh% zxZ|2Df?Ek~q4dO=8HGaZS#I0B7$bjhh)@Bl%3t$Byy+Kd^XdDgB<+<^K#ZH3y! zBpO0vJ-DLzL4QEMtxqvJc@-co59-V5zHuVh?Bia#E4{*e@2r{MyIu3UxX*V%)eG`# zpD?4mbAEHH)n*p<^9XRrgWDMwhSOk{;d6H=#u7^2jjj~ypiQ|Q{mbqN$Wu_Y@LaZu z8Wp;tVMtuXyTL8W8_fMhE|^r9b-W1Al?Z|F^XQ(7uJrOG$IJ|fEMecIi*vfBiidghYyFz_y$ceH_aDT>j-}L zZ}GctAM>odOg0j`-EKtbZh>@q!Qnjml!p|k;^RE3oJ|AQT+yaG8{ zeHBT~m~6EE5hn zM>qI#dAB~>Z7)rO$6odWeQK5m+Zu=oi;1xCUsGnt+;z|G;sDnzG0e!q%b# zDxRXSq3J=A_L-?`t(n#iXf{i$5G8rT$iGJM64;@_LP2Lo)?C=hQ~P*Y7nHnl^&VU% zEk_6CYlXcJ{k^~V95IA1xzFPiR>@Ti6F9Mnth{j5+iB~Q+TD}~Fu5C|$0vXafVI$J z7hQR?gsuv2XTaI1xkP|UQ|OKTI6Esao7oFb_D`CBo51-u4gb;V!udbF;#*0)=DaeT zWed>+Unyoc(Tuz@Z*f@RqbAm!vOexK-5TbkQz++ij*9~N6ImypsuqgKz5RV3<0+h<^~GID3qL&9DAlo` z0<~mmIK5V!wceP_qy>&GjK8iey60<^_TrIy!F1=X+*O~%>9ns~f@E!Y@T zI$U|4g`=ea%w-K)2b&f7fGE@ZUQ04m_`it#Pn#adOJfdC)xP54J)do{dU4`vu61X^MhsHV<9Y4CmZH%tI6lw7( z2dS}rYCuLFXwh!d7*3rXR6uo*KobsBd@qnD~-GK$g4ucv$j}yEoJaA ze55yk3XCc*rdCDD+F1%HnVZzY!(}YeTbnZ9jq#4t%P3A8KLDiKGGmt*zmIP~*=Vh= zSNYBtzx&uY^_y{cFACDZVeh>^?ETO`^UWP8CGDopFj!uaF6hsr%Isf`n)3}lxdjlD z1mB83Qac7Ev@RjzT}I(_(l(FT;Shun?jnAUi?R6Cu>Qs4(ufX`c_r{9%dF@jr{%=X z!aa=ty~$L@^A)DuNYRTI?{6%f0d~4DKc88UN2Fj(&@1utfg`Ye0A<1Np#d^ue*t|5 zh3X|=8PWSoG)rEfYKv+$W(ol+qAf1fW>~9_<+n%xz0ya|@-jM)qnyEkSQx~Z?0F3Q zy183`PN0-a(7$&;1)nW-a%F?3cw*po?G!k^WVK^cwe54D>)2Nvvz7*N7Gj_Xk=%p$ zoLyWGlQH>#H{BfvSOmiwvE=g6e7lmJ7LE;$Qhq_I=3a0InePk!5jTKzXa#Nq8{3-@qKq1NuHiSWJSZ(f)PWUPY6xq5bqvpdp55hIPH7n z`rT{g!+vn-08&}sIr;|G7rY!8gc@d|r929cVMfmTsiphun0(XtN%?9a=h<{nM{8g` zzB^|Kk{VvCL!<}|0owycb`NotW1YFARlJBXs?}u!zPi91AG#8-sa?(V|;G0k4(T9-)T((__hEC@QK=sYRC8!(X+qV`ro4dN4Y*fwG&s)Ekaah;Z zu*e1zfh7~|N9dVY0Kd7bz7iWi9lzSI(P~FIY$_m8Uf?>S*d(YQJZ_%O*ei&SU+mc{ zjhcWsgLc8LJZ95OhFpYWjTjG-#g4yvTbcoN?nDBWRvbTin8-VF)X=`SEQPcv7#?(k zU%fJXw3a$Nj}&IQG{td1buB(DtMp0(Go6+Qys%Gw&USJC^;ZY1G3f$+??8qSCbTuN zs)`9(K$F5HRS=cxxe&#|fZaSLy;%brh2qRd+R1ft?@?Tx2hr3_MROQJ_@c3DEUG^E z2bgv($wLE#Tz%Y;a%+o%;~=KkH8@Jph&Y8nkl8?tcpmI$WaBi~*ea49UPaLsq6S;$ zU_z3a*HS55^u8~x?QVhdcNW7xSl&ZnC3TBk?x<;SjLjB6G~)J_ZJD>25xul&DoUEL z%L*VZ|2C)@-fi@tm>)S!n69p$C@aH?rql2$nBv|T+jYqtU6dO}qH{9!;z-+N_ym%G z*)%5$IPiUW4Z|=l=J`@MOQ67TeoE$eI=%=lrjKQC6mcKpYhIH>r(Q8oBv@b~B{&?R zGC=RKFXgv7E_;N@R$O2>r6?cx-X&I5>iX7o%l$~C6nlOg0;u^_ z`Yk`|MOS;+Nh+9Hq@m&pl$YdNY@nM-M~(yyKF+3e7^^@oj>LH7zC}h5vLGa;lv)>{ zzw*`)S4^FH11q=zC(T4BQXG<($iTPt9p^5ye0NoGc~wZQ)Bj-IXT@H_oSpLP6i%cK z&oM+QKUzmw<0+t{hdN~_bsgy>j>30QfIWyym5JL+fp_3v6|MJ&y_YY=Q~NrisKR5k zd(m<3QjA`*tS8WWI>(z)dNj>vFW`F}+tEZZ^!+@2#0YaLciZ0UKW@Knbt*2#H{_mi z7+&`kHPk~9PM4vHM4^M8_Z(Q_pvZyWwN6-e3CkkUfXTAXwnPCPjMsY5bpbN6x&0k3 zVZzMCwp??I7rRV2(vQF?)Ho%96AK9KgBHP>6^4+S`1hLUmZkH-iv1t=`lqA8$?@>> zd9>aEV(;OhG|l!D0h5i>h(14Yrk^y?sQ+4BSy^C};%l=4tdSxs*o`H(v0Y>*Ikq=W z8>(2LJO{e=f3Rylfmte;qs}9RV}v-iA^mL6I&l=QV~VzYJW{YJ0c(nlP0ukLKx)4& z>P5IqS$eL$x7frIhAcf6&XwtgImO2Jep6 zGw)%#$6?dinFwZvg{X>au0yEYqX}&i!cK(m!Fh)Gg5hi~S0ntoT*5!_7KouVGS87t z8EJFKBcwuwPZrvwdBaW?T@L4z?SInQezMdLKdlFQt3 zmy#2d#QDG`6m)>M78^}V`%*OJTZ=RVOgMp*9R(COuABqNr>JifVj)q7^!C&tN2g`E z%F4A)+tc}ed8oTG;ky8T{t1fyqL|_j!DDqh2tyoiNt0*2r{5%FrnX*MyFmZaxo zJB&jWC)TPMzb%nlV|)S=W|HK0MvnxMW#I2uFrNToGs_>Rp(`-jT2|r_VntEL*UM#T zRuE-R7ZJa!e2_&t>T{GLI_YvaS4@UXSxeNjdmI)Ylx-8f>Gr34ykSu0EXXnR$@9>ZeM?*NM(mP-{2M#DPM;?x^<7iBt9VhM5@rV><14){DV6948m=2EZO>2zAA9r+|Jpj=B;RPXZEcnS5uMkwnZ0%k83EGXaXXqARb(l z+nP6W=HKRYBd%77zO-TCR7Dw5z4YK-cwr?KR@R&>-DqVcs@|*+cJ8l(+|lHU48(%| zKL%s%e^Eks6|GKbbYF0_Ejuq4tQ$+tFiSl%wECDUH<AbZ+^^DMwf3M|aQOM9L);2|I}<7zz+ow>4{ihkqHIHd`Hw zmIbF`3{*JCv@5#y+kOr?o=OnCh8)V^f8QmO$F|%%gmgWLCu#H(Qo-ifn4^59$<;{wrSYK1*>f@vSPhN= z*U`*z^}YZkFO*^)eD9I&)H_=FnQ@%=|r;=NHMegegmpKxFK67&oET{7_pTG2VcpG;?f8%{!t?I+lZf8Ere=uJ9b zei9&ySp_A^E3TthX}h?Eobt|B*wvwAkS<_H0P1maRs~^2CJTL?Xv_rcEvsFSxOs80 zbiKj8E6Qze5pI)(xj&!z`B=}Q@<5P#V{L>XPra=8hQ#899MlybAAx9S3qj=-k47wL zvQ8}KDnjE53~a2|3oF=~%`4{z4Y;tbVB1#fLa(q$T=Q9L=bf>3nv46TLa8VUHoT+Y zChWzNGg-7+FjzONymb|~Oy^^{q_`>C-|RimbGEsPO|EV)W0je%tq`dLm_oxd(p1z` zx01~b{JO4k(<23_X%z~lY#iOw85b{m8bGXNIlR*PnF z4^%VVl@kz0X!)nIC9U+fTAY?elMz*feDxOsLgyKskreu2qMyo%AKefk$pEKLi?2MKU(V1^X>nq!6xti31Q(DK? z*fM1nT>==N{OGtB%WUfEq-Tu7V(w4pYS}?s^ zhi1p%F0Xzv^Tbt78u)?}FP|LK{+Be+qwZ9Gt%iptehGzb`Y5pnqn5nQOW4JNV~sK7&D|4Le(^(d z!(cB01Gsn)9|7Z|yPqURa36qKHPrjKr(2&z{#Nr-M~G>w*bW*`uvaS+M%#N)Yu4&^ z84)bjFN2E*(e=!h{tZ0__nt|aR!vQHJEC687LD9^0FUCkU7YqowyThE zk~HaPy;AF@&RUL_EhUq#<)}vzZ<2%=BFne70SjW|KE#?t5UcNa)l06F6Xo<#=R$zZ z`3e}xw7E-*UEitD14|@d*>##MSS&Ltxa5EQvIsdu-F`4$!*F`(w=4O@I3`;6M`EDs zpfo8YLTGaKkDWp-J0Mka!CKVmL!Kl%9MOU54sCRJddjZ(a;Ydf`tigT9A$ybq8P8j zvSb_u>`I_r4kU^Tn?{sV4jYyhOIpPlzeqXjrAQ@LP8jH`4s z?R+Cg3yf*aWhGR(7$F(s`)A;NrortCv?q*V1l61rWYNuuefQR_yba;nPreg*>V1e>A{EyGU+5~}nb!c;Wb0p>?ltc- z?ul(ZWw~v8LF46SZ*`;ldtcLPoPA@9HvL!#`ArAC<#(x7S*7GtZEh*8pdl}7;&klk z{Fj+e?Z>S&QZ(jrJ}l$5JH`B;;#!T-PJ{7vS*DnoVNh?>F?e@Lt|d2x6-%21X_v}! zXIaiAbrFk;)=ss=R~{B!Bo+wWDwHxTX0yxw7t!3 z``&>YVS=Xb6$2?}14G51D^o0C%hoUdQADgG-_e|Qydo9q5m0Wt)-Kgh=}6uEaG4=*QH*6<`a${2m&!a-CB|Bgd8Zsu zdj%7Qh4ynTj9-%ECH2X2cr6qDGnR#ITKS(|6n5XwTM{)QsA#vbV!SI`kbQcpJQEki zE5Wc*fWjGN;$J6Y+vn8p?3r-ywW^rnTPw-pnVXexcs;+ooLUCR)ligXSdv+0yEDpS zw&8I$Gsa!2Hn|Mg&)JSFmC%aWOI>5M)s)Zd^zep`EEIGuV~}OE&g0BRtYxCBmotD= z?TXIwcPe1sjko12}drh%d^Z&fn)joJaYi3dc#$ z?*In+I?x>+y}uOy_}O%xqE#J>CK2Jc=YS6ZwSsKn?7ScLpdr*2wM&XFV zcuvoCujjWxyvb36r;n1*o!xP5&r(>M6t(f@IEn3BCEC?)+!7Q*5`c?cJu%z6d~LK< zC|bHwnrCx*?5!@H#@N_I6;-}GV_NeUVSXRV17h?>qSwTCQFyPe;)xLI+P9RL&)X7%S12|H?jphUjm1-Qi4;eb*m`QDusorpE5l`q>NO|%#(6USG>Xz#!?=*i{`!r z6B&{2J1(1z|H9~>Z6!ubM0n7UE~oSC8WVJZd{Pf42X2-LQf)y}?%LKzHAiwGe06@OU#DZ&O>{elD#5m1K@E8!lm|z?Me0r!|1^DJ377HK^ zJIdyG8jWvQyFwU$o8Qg^)|$jv0OdV{!xU*@5~AI4>$gLIQ!JH9f(Ec_T7~8X|H;t* zI5^%v`8XuMgJPk7bnimo*X(UNs@{ZGys;9yO7ERzKM@Asehp(z2{VJs*2$1J}keF#^lG)?Uq3IniXtQ zSr3C|>O+=unSBa^CVy1680K7J<}iISb@AILS`g(Lryov^`_+xlMm0bO$L~LujH!`}k$2So{51zkl4Vs!d-?^?&Lg9-e&cRzvrGtpT8RKud57fGxe_ z2`x||1X8?<@{`L;I6F6qI5b%QHpp&_`OuW1GQHKZK(d{~yHG$>7PI?n%&gF~o4&y0 zirijEX}<05f|AZ7c==KTQx+WQ&MG&fP&0ZQ-qQq@=CaLIlIg_f4v|wbeV1|=;%lWe zRIc>z-m~q>=x@{<&9+x5sK67UgZHkt_ZOl6yTkK7%!pM&GvfWa;`VAacc5+$Fe4tIKz5%eruA`PyHP8gb)DDcI!YkxI$t+jnd_c9 z#O$c0ZYloAib~3|r}TE*G;u;fSw_^*uZL6`By!VdkCO8&WPwR#th-=X{aoecEQjR3 z5{m^bQYQi%kzQ#Yn((9rz8MH47=*1IjQEgx*fCOEQ*q~J3M5l`DF27&E^joX7=Ize0!0^KtUha?IFV|>3yx~ z4exK1jHl0<@Ay;bPT}BrGB4S?yW!@Ve*nR_$IA0&77u^`MD7m$cqWq`&BJ#Q zO+;gZASrT1HN~7hQJ8>GjLoo0mKB>R)E-N6*I7I%$Teq;Q`(G90YI$w3ehb zQ;O}1!Um$*`w*tvV!`kwW{uA9ZPyYnQ9{h~3^UBE@Y@o>0#<5+XYS zqOi!O(J&6jR*=g@Yr=uToRM4wMAKj$F`)RNImDr2I4o6*)Sw;tP_+!%h7;-{1CW*3 zsGP~07oX3o$V?E`yexgA&=1-S9g?LccnY_Oja*06=bUsoMKMIu^y`Uwc}!}~_aPOM z4`(+RTCDy?Gjtt3XhLInQ+*GjmbL%!5Bt^s>GqtzJM=fn;w7TEY%e5n^)Y8nsJDCP zgY(nFzTzieH8z~rMzI@)DLBNeQYYXUR~LEQ9PSP~#R&@r6W|>6fu(yMl$JC zo2y2ti%+ya4${JZ2{nse%a?~|$7%>B^PCbL#h%`LL|zT`UjKN|z3iV~LPkAkZoCkT zkFw45^kJ?QG9VY6^}46+LGK8d@4@rSlauy^5>igOiYEix3y1!*Ac$;P4`1`=_%$UI zkf=3-$D(H=Cz&_O5&-D|6siSD%Yn@jt=-IypZwt`br2*=0NvnsZOCFem z#&y6JaGh*NkHXkhBgF_+5yz0ZM!y zfo@j~#`P*0jh0v8T!Kn|3(RuSO8BlpnLaz`U?306ih~z7LsKBFVt>2y-FI(x_P+Zj zo2Un|AYu~ch>-sRJ8&ktey74*A9nL%QIdoZ?GFzX{_^BP*AV_NmoXAf8eLjAE|vpt z>Gn499_Vm_=4H%JMhz5_^$h_))z9#>ay7=0wTX^uA8OWYM`kCv$Nw?EG=wZ_^`IS!eQn+qz{x zmgOL2N15PD_7tDX@{M*F8)FD>i3C%OKGcV;$w9`N{VoM*OC4I1l0xqrU@dc-Ba^@| zSOQ#zl7>iZsgupMs#^s@xvh6n(Fpk3cZZULprOK~e#neluj5-vCedq=q~U0pfy0-( zp{n^V=W_52?&Nu>fI(T(40q&OCn29hNlu$wUL*B+{=j^bwQz}LA8aS{h(c;7YXGDa z2$`)m4jG3xjRvVWOUfz(Bnt2*N4|5iLXv|kA*pBnIC#1RL7+&2ww^ZZK)411NM{a_ z%5j?b!5AP^qdV5EEyO(wubsS)XK8{*1szqFz+4Ro_$sb3yH!0S2ktspS7A%m;4>y` zpqiBE>X%MH5Wdd2a>S3t(Qtv7hbo7}Mhh2g1SaTP^sw=)6Q~#ONzQCV)wl$nJkGKEw`hcu;bp<_H6QNv!m^|}W8$3|yd$GIgC6Gec`eq_(&s>&#$Tmnz3EQ`PkXByALhG+2O19pvhmlxhaI}E9ysjYAHwccd*fYh>yU( zGvM%m*uWnhh@)y!LC=P@x5L_ZlKFSv1{t&(=;$u|>|~azi}t=dJC37z0Tf4gJ#f}K zcNe*f0$6o$-~uQ{1=hgRv*5@rPzF!mXTDB$rCdWveytkr0*hnF-szvV$>d}o|2H~^ z!pYktS9z`&2G!sqn*Jy#o4>ihEpp2rK%crm+=m(3F`EjHH~Z%2S7z4rmA+Ucs7i*D z2!V!$Ey%kyTTJi;b0gUso`iH>|Kl7Kaw;x?<#l<}DIk{+$P$jvOC)n|$nQ&6b=&;p zSM|j>y$Z*i;l!cFo*mAdZD5vc?4n9xz z%0;bOQ+q;dO~%ZeHanFT`La^X6=(8c{Dc&bIpqA(wcZ=2{zqQ)X0a6sc2Sb{4rwCL ziknV+{b7Zkvw z?brL^DjS6Q%Tj1|6c-vUu_^gw_E0yDMuf6d*Q8VwxtL6~id9!Z2#>j&;FBPwcaZC4 zZnJwiKGfjrj5(2_5!n0EnXF6E)Lpd4uF>z0AR^$Ny^s;DCD9pcL}7Scj5J?tlDKI{ zVUuUqtg-D;hiEiNaTyKKml#+wQ03jEWHD&y8d*LEdEu-MKSlNZ$5r3w6=e9|<$cF9 zXRCNnQmc9;e`Y8U^CR8An-kB3pbUB;Gu;yKkSFiFeVhkh-uI$?Og&EyJEy9n?fDt5 zW7(`o;?=q1MHmEB)I>{O&1y%*?NoLoFu9I*s#}s-AxuNo3 zlfhb|BhqL1QQ7K=EDZlPY#8q`MddeG;$Oy?3BjQ9SlE752jH{tQcKlyUuXBeHnX+* z_DS|@t^K2p>u%uZW|+#Aqkohb2+5?jA(>P)tJKjUh_~o=<$7JgyN-TBx%`N$uup4f zK64p>3YirZvutH~Pu@lS5_vj`;19>?#h?2_Xbfx?5D|17aS*xNLoqF9Dk!Z{uX@ih!>tzCr_UI z=D_rGOfWqGNT$a6%`xphvd?XPe&Q<+<6v;e&rHv4O>RfN-bGtwtCGuEkB4!`dYeeY z^~ZH@9ZLdhUb_{o2Dy7z%(LoTJYO1Cee-->{~x(}-t4pgPu{(PD6;P5s}NH@_4-v@ zr?qWZ)pkOUVtj=k*yyKQ#uT;Mqh78t7aY_qOj`efy7INfH0A+a%R?o5XK|{O&pcY8 zC0eQA{IJ)PkApaw$f1_6aY>$RiP9IOsRx#%u6_UP9GjF19gM`|^lsNX8 zv0Te?O69INB_pcAU9APX^h>W++#{2yTdv}=)Zu!=901n86lp^^&WMmW5Hef-8a7$>6TvtTpYbLGVlWGI)9T zQyXli$DQ8cbG;EI_EWhA%f4T-EjZP7k}YN&+9G2v*^xHRtcNvvdo(foS5xtn;S{T1 zL0}GtVU~%1>Mg9y!Qhr1KzF0t7VeDM}psLBDkvWsJ( zXB|>6^Y{>@9VJ|27NVQj>G7YwUIjOxLns3`suvO1()i;Z6~5mJE~0T1W>K;0Rv@}= z=t5lcSvtFD4ek{cLCRR<$A8&35*yp6{r$jt)JRFs)Y zS;e)nIoWk|l4t$)0^@B3$qqeG5IX$*eI6hWb1_lV%E>b+U*M&__||5kpRUJzd_ z`Q-{Oo-9HcpZgML!F7kK@&)yd^-y=uKgQehYwnm&_5Ve-%d4lZ-mI_f7rF*n_|hJs zUQ`@k(0>h5k7W$m|6XgBa;4PN!Hweg5hDk%(7y0Kf?@&R7oW5PfvPAl3VafK=icRgRAH! z2KCSrUq)M_h+$Si_mjGqjbbJe&Lx7l>Ume!FQNvPO9)KUXZfenB>+A zZCX~Pu_pghIe=wfoe`@0*yg}FE@^GK(q@iJU2#VocFVV)CHK-Vs5}^e;MUfH!R)qN zudi^LD$!wP`!k%W%3(CG?LAqQJuNpXmwMw*3uhJFuK92M1C;YhYYN-zSx`!1h5S_h zL9eI(?etDc3I_%!pS@}MDt$gH)2FYH_o+LuFP&$F_?7caYLzu&&03LSq1EH1gr3pG&#~JkbL13QF6n zZKPnYy72B2(ihT*tpjQ3wwXV47HV3x%F?Pk{jyem9E4{mg?=dU7O|h%fiX>oU8B%^dt1>^sRzkwN@e?Jtz9~--hLg`g_ z50gWL5TD>K8jrUjDW94Opf*Z}Sf#Rv(@&7AQfuKg84rMxR*c@V% zaV!xtkOu)R91$c4gUA0KiZqPFAz&1nB;fN~ab9K-7f_H#UHVD3ajI%nAB07rEtG37XQ3pb&{+%3PRS ztu|(CwNs^wp?YD0o+N)8maUY`h3mz|J&$&UaXHcaBG2C17-OZ>wXueTH4a5ziYY~| zN>qP}X1ba&gVtf3PoK2q(=&~uB!;Ja!>7E{)-1QFe?42cyV*L*^j75A{*kl|+?%4RAn zSXM9*P%cD=RQjph3(NuYsT%NI9Fw4&uVQ8bPx@tk=FLrb#YN{Ou_o!yr~-3RZY`~4bTyjm~~ zW6C59iQ;a#u8<_1Oll+GrGc|oXbi`T5n+zcF%v=56GJ?Ab3@mmV7xfO%hp8z7dFN1 zrJ`6u*~`qbEw900CP`o>Oj0>3-pV)Dx6tNz6HtP*!hN=QK9o4;&U?wE`X-My3q-!q z4hfY=`MR90Gt>WyXXTN`EH?C!2DWZ{zSI+Ll(?~T+eTeR@7TGud|`DypX zpnjqrjMD}d2Fi(*n34ld`c;H>3R{;cA2^DcJ+$x?M9D}yV3*JPOM9A@xS5`GPTO0- zhshYK!R!a!X_P?D(vx)ddKLqnah8oU&6p#^WRm`Y?+VoMv3@aKU$tv?&!T~wK@Ht{ z$$OJ7r19ls2)V$V;W*7A?k>!Adfj1$pp=I5$Hw&(^m4$Nw3C~045?TZ z1RD36UPT4EFY2b8)v1Y{2f~&HsclJ@^Qgr&%}Kc6}NB>Jtl3DvU7NgbyjC@;$KP8Xew~r zihv0Sao_xYbJx(-3DW<^X7_ zu>_xb4qA}D;)hiUONG*_g3@q`jROA*tIgD%pO?BNEA(a}@v$9ucX5OPF;nWx075{$ zzj#hWMmxgn!6%RCBXAWW>NKaLQg*BrZ)Oe?<73^1;LAO67&PiS*{n>C%4G(uiKI$I z*Gs%1|=GzJEL1O3{DKLMf_ zRzWv`z!)5oKMT!3Dnl%%($TO~>s->4{aUNlsvW5ReE*ccI`}%RtAAitP@DXHJc3G` zg{(K3S)QkQeHb=S$T9Rz8_roJsK^~?<1q;0atA-B!Ly4JE}r*P#tVyLY0K zr2y7{C(Pmpw6XZ737IRNW_d;EWWyB+o(9jixbmaa5cV~^oq)X(;-SKG(O z{oC8!$z(UnHe~UnLP`z`v8A^09wfyl!Lz@q@zlSy?OO1JUq_cm>m>8n@o0YgZ63me z^SVB;_b9x_uKl&Us@O_a1fun-j>cmVi=W>EX}*8^GDz-jKQ zBtV#KAKcBrz9E*tfRtBFUv$_##eW{S@V9j*>r*Xfs!;p&R}eqlDT~3>gdBk2uRR+_ zNnK9M$y()%z}+;^f~-&SSSELA~@0tz@69G(nbH8S@z_SsN%?9y|uID!q$F zI9Mhtz+SL=il$_Z5DDdf7hu`+%ej^^lM1&LCQ_Xu4yQaM8qx!PDit zVV(|J%79(6ReDhTg;w~vv7b|Syg1rC{XI67GZ6p}S~Z-OJPJA3`)_ObfyYsRcL7?x zt<^L=Tg}qw*i=_Nbf0Wwtt41$TU|?_`OL85s1^-DCew$LsAJD-2Eu&PI{%50o@%xp zjDZtp>fb?_U})|Db6i^!N-k52v;TpRtB@#pofSyqZP8KW76mVFa*qOXPB9w~Enam< z0mmDwjXx#Bniy;sH75b=!!fg9Rzb|00XCO=!QE{PyKe<*InWqrAwQddYU&pZ$yZkder>FC*6Eh6 zH)c6O`N5=-HOYAZLC(&BNDfn|Of*-2Rlrg0phoHp?HB7!2sqTT=~PMejCU?|OWDv4 zqvgRsZRKQY&{!%y@!(kIVqp4LjPD&7{f{N_vX21ME}IZHLwm-CKe?4o1&leLAm{Ir zoK`Yi8B+xBYY?36Nd!5|oL1156Q9T|PVm)}Cr(BXse6~V&fYnz&@MhUAbR7oEtwUY z%SWf5oJ=8l56U?}tfhME!Mu9PeHmFWtroIAuKk0sfR+rB1w^-r%uz+`wb#(Tore|f+G@sCo*O(Z_TPj#X%o1*G7abSFE*XN%~GlN#JZ)OZHE;>1p zz-8q{@@9uxmywKSvvh_<$#-gNcCBJlsu>kAA0M;wfORY~EGw`q0*w;3#kpS9{*nS% zI2zohL)sQCLK;cJM;v_&jDY7)Tl;n%9Qzl7dS@z4= zKQExvIYK1n>!a9fxD~HRw~Z&==ONoGrF8Yv?93tBSy9dN{SO}|W9@sSc#vnU9mSAD z$uNabL-oOB|782GZ)-p3^Wt>QEp)cGvb>f(fL?p^)D;QP%HuC1#+4|PQsQ;Qoy-&3mArSeoYZL5ueQVNs;x^by{o!X;m^ZRI5rb=B5-@5?H)`RHBs z!(btmybJ5>IP+-M@uQKa2Sg)E9+fpyKEo!I=5^jaD4_tDGnJRx$3@e;$`eL=pOnIb zlDRL+8r(d23UAPXE)P;#-K+UujrhmtHLUm7Rg;7Z@GCMi2zHCp37pPP_C<^B0}n64 zyY(33#@MCL61lXRS79~v%cja+OkPJO*JA}|XW5ZReeivWILA`ub(1o*EO|Flt&MgXR?Bmu+c z%MwtPCjh474@dZ;;8KBHvXYF1w+LEffp?~i%RVP@{N0Wr&-+KY! z`hMLN+i+v6i7q@i8-gYgpXRCaX`VT&Cq$^8?6QOidaj?A5n-*A2nDMBfRqUGE&4<% z{za1_5E!2FC`LmjSXKSxJTDXo!d~P!*U`q7UbQbA!e7cVl*RCuc4%#sezm*1K4*e! z_hrKP^Xyo896uiCifR3!LHfTbygp;RxpQHcgz59p4-Ply{=RtgH5e{=@GCZHIScj& z1sK15YvO71@wN2#(|lwwbjb&c`htV63L(XB-(D>VD4u)z%$M{@JbjWSeXc!yu9x(g zdHT%C`gj9})eflT3pU+IVGV1sv-7}cUyDP|Pu_t4Jb}F{gmjj28NQg#2M6L6o&pb>;ii###uu0Oxq`EhFr6HI_uY4YTPrrJWQ9CtBZmIJAzJ@)L$sjh|EbA% z(l`O{L+1c>kQ3C;(H#JzGop{bZCl50n@H;RR$^fs;k8_^D&Dy-5ouHUtrR$|VEI2U zFh}i9z#32!IP=yUmV@i5+m=M-ysZ_(a%iQc%3ln$8#wA$te7drkF9iSKV2_X{Q0~wWPfZFnYS^$aH=Ig zb_w?Vd&J!LehNh{>?AlK8My z(OSiExe}L>sIjIq+Decpa!f#?crXJ=re$_11H?HL&ezAPc(F=EN<+mgYWXO!i_0?% zz&h*p;a7L|D-2m0Ddr#2OEF5~!?^l0qIcANbq?8nj!WXhRFmH2`T0c~N@9DkS#wrC z-)H@^RHP~m+xjeMm10yP2Kyt}*52oeC^CD_3z*q+U*X$_3>~YjbA<8VBQmY{*3;*! zN37{bNU$H)jn^uOy4FY(xb5kg^2^8DNi!Ou?jSy`@ zb457tq7jg{wH3N(lJAc-GtQr$r$fT|wcyNH`o81?239u{F5^Z$hQo3}>T^eKt-#*> zrHs4#^Cxk4Zg9uCbe-HcC8QEZ;OZx2<%q6o#;7WOK%nRe6?g#i@cHc94R8jOFKXUZ z(eq~JVx#Pvxsme>G0ED#YM7W4$}TiH^i#$~6pTC4y(P~Mcys~!oOsC8k{C39G9}-` z{gIK zR}ev~qsqK5l%>@xPP-63;~ub8pSSE&-nXw8vGx@nJde1cSAI!2oRGFweBNpwS2ZLR zoynKVKwm00?vvi0KQ{1fwFgfOkW(N1u@|z$jY}+%&z%bk2w(yCW%?z$0afQ;4D}}d zwc%r;bIJ+N!Ou}UeFZ*?|Eu5obw%GgFAdKr`f^UO6|S!T7GZNuCPYPJr6-gQ&6fH1 zun<&-tM(a!={QEIbiXz*=QvxD56=d@{zd!n)!?GtyFBgp2IM+*8x7xOa0S%nz{)|5 zhAi0J-)usu67`>NHlaELIRA;#4J{}~bFXeQ)!M;Y4;dAExVjH&-+cH`gIb)kDEROJ zD?;2x@hrHFK7^xa7*E167vlux13;)RAQ@fL!m91psBT2@ii7S7`F zeE<`h0MJl^oIiqaH% z!st0=?uvCr1xm9Azbb;Z`F3Y>k3W9$B(rwIaxc|ya!#rHxxXLh{&t)~8Cxjyl#J@N zZ$NGAdPl9|WGTEXt35q=I9n$}_4fAt=-w&4yqc@p(Jwvs>9u2_Yu>DNBQ53ok!(-bJ8vKD0gm8o znvy#Q-JQ<)`#1MRTh41hvF5Al&++Q)h}MkclJCF39>5MCc%oORA#u=^^WFcxeE^K>^i zd6MKkkB59kZeZmVAQ;(>Z+Q&0ET?HYg(3{;;)d$~z&g>W8Ez_{DjiaI9naKy-N9i@ zT876odpKOo2Jjd7xbp(+1XVqo*H%z z3HZhHks{y?rV~=&!bk}QB&e8Oob6|>AZA3V>sb_;vt$n{MLMZ7Faob-d`q!_9C@Uw zmrNVIT-vqvNv5+4Yb6d>lWV(}qk3noe_#4xDKzpF@le zf#_yEc(MENU@LYCnWSPBfMTl-@Ke|7&)wa3?QuMcMkh0Hn|l?`-l>y8W?v}46Vw=y zv%^>I0VGmqE3n!nbP9wbJ$oAtuTUIrcb6-2*)NbAo`fF;qi6~qzwjqy^Cb?r;p~~B z$nBqxPA`w!$AkJr@s1w`x&jR~d3o3y96s-zmarXsF3f12L2AIu;Fcr%URKD^4tySvC~o0WfT+P>NOwJA5jZUA#*8x&r@#b^u=%fKOv zw2H4_S5DQ%1K)vn^~bzRbi;F<<(~ty;$9KSnN&f@weyI7h1>3o^Z2p3vX2~vYkD`( zhnRuW+BX~`dN>-Xw|heOf$1jl#mpzGcS+GGIAzqk&A z_lB6h0joYQ;sb6N5}_>NusZm{fP_C3!%+)@Z>GD!H<_AfGjK7WVH(;~4JG;~`v~8h zirnp_(nq*Kk33i3vf*%Q4|4ad_`M)FdmBzbNr4cXaWs?dqjHziG&zkz^d1ta|o2t)sGo7KNH%zC|=v+f@ zE8yUwRFZ$Bq_rd78cYX(DF&!cLv_CR=IoX=7}QI?2!1H#EX+??SH)k~^wv^E-7vr} zm|l686>?EUL#(l@-flxI9+e@U4@$MK9(S^#7o z!&;n5Tux_DYdj;daT7iAp{BKxD&bx+Kd<;c-2S`Bf>ErX54a0>Z z7AX}P)&!cOkEe+CzT(od_=6JWAqKf@ixd^RvsC(;Y9FaN;tf;(n{qB1{+>8r`Jv%# z|5*rOGg zqlG80nEhS;pq9~(o{q=BlZ2u~Gbtbkpu_O_vL9Ak3_+Y|?_xlvJt; z0z2U6+kKdf2OOT8ie|y@AN}b5(}!>HI}>Y*@?KCZ^{XD{WE9RwM}i5Ws2*t+L(z0# z451Zch8voWF}{@x%Lc)bF87T!fNfb{4KO41i#osA?P9LT#$BS}=@&+UwD8VSq;BDy zK$0y&kxp`8EW*cM01_VG3pHm@CMte0$*!?hv3j1=nCjQt*wm0!#A(L*B-{14N6yGa;n1Gu|H}-Kb1JU9zI8>4ZTM6R?@t?TW|o z{2u1V+b-9rrS}}boL!!t0tIpwkz=v06+<@CB_`p^R`JAbd6$eAe)*aK?K8tF$)V(S z(1k1c(q*8KFD(P>UM3f+`<)BaaKC1U^$a~*O#7wV(&@dLrQrw|UfQt2y3jeG81nHL z;AD%dY&eUrz$minvd;{;Q5Qasv%c`Xh>`Fwr%3c=xEHMKYNvNo7cl7@O2l(g7_=TSDdgnJsWB&z?Z|+6dt9}wb z!{I$jlld$iXJDVhI@wJ5ahI=<%eqr6m{mO5ha}bML@YPuJkIDg=G!{_`-A|iBhpUL zu@Y>C$dmu>ec`T6`$42TSktEWgm6K(+;H^*dz3|r+b@FG{(T<>mu`~Iz(+6i#V7f8 zo+jpd9bp|%iW@XPp|xHfo0!xXXdi8gj5eB`gtV(##{q({VZY$w!p>#Ua4}bWn+C(% zri+5}B{I?8PoF}=*Aa`yU_2swkQzv_R%%a4vlC#Ab6`U?>jky((hRS<9*eqNMQY(7 z)ffcl2k6b2HHp#?)tIIrjB@&FLJS~KEIpBu2#ij{+c3FN_g$~SmRSwdW_1z}28LQ9 z#)CVGUO;M=qbEfAY5Q9U;L`Np6btSW{nw$F# zocDK8G!1T2wRPRDh5}}NV((eFbo5QA$g@T3pLZ`#mDG4dRqHu5ik-4n+tXaJj`5xO zS}=aPg)RA>10`CRPLE|TqnGpJ_R&4x6kG=ylWZ{@sw;K97?U!Ez0EdYlkJAtRvr(~ z;w^`Tt~b;@tm?K`j+C~{l_MlQ$X7(Bv`YmdcrD7YDD#OeN21h=c4Zt`sjB^c)O)Mm z8@Q094ckB;1NAXQQU|j|Qo!1dK2IUkdIhx0x@f$E)95A~-Uo;09Uw6yaPAw1Xx>6^ zC7=u8d$j{ViQx_@>ZBFo7wuQwpW1`d_KU-#Uj}Rq?X?xC!IEPL9L#4ph2=+UwE-$m zR_TdZ4R+Om@oXys{VcmGNXiQPv>J6;N>|q2%jMUHE60|MPhYM&xTp1MRIHMI<;JZ# zUB+v)bWk1DLc*b=JM`=ww)*YOe3&kXo zCf8f0wO40FyfpQ%dV7`}AYWkOvUOPD1@TiEFOA7jm;C6+M|1jA?FD`_!_=>e{cK_) z#LTKL@l$ROa4yd}KU3aB#8d0YWwJtXoQ5;-^Q)uQhHm-n<8=O>r zaNKrzT_6OzfV2n#MVgH7wTx~m7@&l!(5%O;sFmj^01|!QU>VQicaEQzZ?FEopzU9Z z5mQIPC`%`iKnWo6_vsA3B-KN@m}l`Qa_$8;ETVqGxi`vC*WVY8W4sNPRf9|rPQaB~ zJ0(hXFo@A!IRiG~@lSu26jWf{fGbK?qSy54{6&~}b+rrynqf*A{ z%?%t&dlF-X)BAX|2y>!BF|x!igD+^XxDZ=>? zibIg!R_$-?TDr8HME1f(##+r8gguZ(jN&eE7hj|)xHAA=9$QEzch11CH@sUVzPHHU zz=yNUvA2c6%{aZ%hbBti$Fnp62U@EAtI(?G($nvUaQq>an|s-YHa!&E}{PL-K$-V0aJE zi-Dhd6e=X!b~Jg=4@V>MP2Fjw5VTrr^#>RabE)z8MCE<9;D8MjBOunf-Vh-q09h!9 z)SvqNDSR@{&SP^`X&t}T+6&@nG@XZP7sb^;OM-gtXGkk2;c%8_Y7(uRR&dzswJ-XE z{>5dx8MJ>sZy)ss?f<_SMDt;TuA3r{YITQfe8fFKClg$3in3yNe^#-gwi2R_G#|R4 z=nF3vpb1l3f-cv*aX7>%Ru9^Ie9vYFXOGN3N3xeFTzBXF*QIQq_!2dresr{j;t+fqoKcR{L& znOby?Am}5Jg(sEArY1SOxMpImtRW%@OPRmV?|P&^vQFbmJG_gh!gfgK2_3ixX)@5E zmGme9_Z*EP(DXy4Ikyi4H{FRoHZpXa-Wl@@I4(sL(K8M)%!7gOgNy{Ru9(qVB@e=f z{D`JV9tE+sG&0j5$afRWxX?qjF;4Aw>FiyD<4(b4lnjHw7lTs3F?eErg=B;~j@Nk< zT`g{I6e#OrD!lOXE7fp)p}W1o>(1G6_jM0Xd;Y`0`OEHE+yB)?-+G5$g1s&{227sA zfPnLB#h2s4()!{i;PRqWgLuKk!I}y<1zu}fDq_I&_TFM(DDiI;r+W**xh02z3fwUy z*-}xF;q4&$FpQ?SF~RjXydnFzb=Bprb~3<7{wW%x$EY>#Bq7)d2Nd=-7^rnst0aEj zBAj~N_85*8tFBrG|M-V661_OPJks5%Payhy`0HN=fBAEvQ~aI!Ty<)Q6@$ZtLp;41 z4z(w5IJ}M3^KUJe(e*X(U}}F9Xs|%X$@}yj$zk*F7+jc5>NWVg*02UK9_Lu`hu7-= z;gV@WY2pTh_o=!y;P8u9O1c=}r~n)eT^~wiY2hJfr+xogz%4Gcxo{TJO}T}MTq)Y4 z$g?`|gTd7z9;?d(^b{0G6x+%0NWX{fal53}(5EY7K6IGQh$(?5VyYqQecy6}7kD~q zGFu1MH*-ID=JCb1mxEp#>#8O$WS$H)iopqr!DyfNJKeJ$2Yq`UgLQH!4XZ(dO1VzJCsF8)%s0YY{7L4CW_$6+e9)Qd#hyZ5J0-xpN@k6uk{SJ z2$QY0M;yQ18fwCS@8^*c41}0KT5rBFNUbx0p-{ zp@jr@dxL2i-r{%BeG~r@R)3JPr%;_{RA9C*B6a3RCSiq#-35RZPT=rUR*{3nDdH<~ zBgs9jBhu8xisp+X%S*jNKdX0}JhLz_on5k)R7C7xCJJMm!hKOk5eUd#oJC(j7tz zLXb%5fTWN^T5eNCCc~>N9fMCFL2i?B;;1c3EF)Ql3oj}` zfiAGFA!D=+7;RIXddD7vf%uSkg_hw1>biyug%vTlrd$^|q9|yie~dn$e-ruMWD!12 zG0vSpz zHT%*4?_?4I=x}yVU@#&H2%S28*Q|?x)Y5PW7!5^KyZXjA-ElVzGl=W6fTJ0~tx_XC z9aAJ>;70u#3eBreAb_Q~Rj;vgHJpxkltT2s8b+jKfs50$o>IPWF-^nA(e)e&61tPB zS%iy>&W1Q$8}>0q+J$i)z6if796Ne$afR_-t1U%#mYCWNjz!>$S2QRcn|Ms7K*+j^+dVM5da-LVB7P1R7cxbly_} zhN^258pG)g^{wKg(c%{nZI)3{(5P394QTr$G8(=eGZV}jIS9ea9Lfc34!{hAV1pcE z!t~N^bcXB-y5eP;7??VCNYuv55Jk!LRrfhi z;0Fr4!5i@c@=Mg#`TTasMqXa}w3Lc#(3LvpVkGkyOx z46W07ABVh2B9gjN&&8JqcM+Fha23HLm(J?qUhRC?X;#ZU^aHQT7@VW$PJvZaAngix zgV*YUw+DyMyJ}rt^|MoV`a69V-zEncU`+q8>9eNO zcPd1+$S-jyI+%X1WKB3{;8$D|8qs${D2F}>2qO})SY;udOO5(gi@pW_Uzv#C=Vz$! zaoXhFB+sFaVFYS`|BgoHQjx9q;E+MY@vEN6unSPydfJf^zq zBjaBKQ=3TN)M_jqZ`cVtLunN@HCvtnDZf*dz)XpBt*lcb9~i&Q>bC@1rlN;X26M2L z{|%`FqiM!Cj!Zw&}?5&r^7&)b&8TfEpvugDaGEZ?jhy=8rBnuMm5U<;)7lkqq?>; zUwzu?RLuHo%_^PJq-Z|HgfD884VOD{&Y2AbBvql#>_UGH>inr@V{B5I=Zg6PNse<^ z_6Fydy_bXfpTGN${|KIL1*DWCRSGa$vAX7v`)w9%J(d0_I?|YoLv+co=pkF4I3#2? zpc|1-4x_edK-;u(*QzOW&j;%KSK)&21pbd#o`6AMHJp88tklzvQ%=4H^@>*6z&bh( zI3`)Q9)}8wP$`iUZhiZiX;FOgi>ZAIPhhc$#|UY0b{&QWH<+BO2xAJ_P(cEPh03A< zoI+Sb^cyKmO}vAH`c9)sW?|MkgP1srN25sV3{kSx>TTk-7g^MDVG$Vo5wJkeiZH&t zq<1c=1Houpu?VxE&t20vY8sFsG#AC})pdwM0_AGrOa`ceB11WT2>`7X`csx5uaMNs zjZ{xKA#Wd)B?bXBl~g*P-+Pnr6Tx#y+dm!JW+Jzb*+NCS8N)yTs!%6B9Nvn`XW5`B zs4{i6MNAHi65R#bmX5s^tQ7Eka78zU%rCe9i2FQdALbGOp}CxJO6#;eZUM+wW~F`s z5@d;2z|)7g1X#25x?TXT3xM_sSj7u~C3l}EfLvxSVWS5vRv3Vk84=l(;pw*9z!m2? zfhbu=?H+|w069Zm7{neks~KX1QVgs7i`3Iozg(bEs2d+hOw_lJJs=?z5UDQZ?y#;p z9{Rr8@V2n&lJNwQ7?@ryAUA(1%N;Nw?x^!@{hz#tT&F34PcV=q>s)t|o&jIC z5dbBQ74)jM6jgFOf{C$niF;W}lw7!!cl9<<=c!r8tPnxNZ#k?b#K3aR#nAPLzz9s9 zf0y2(Ph7vFG`Ws%7PIK*$(YJAIj$_OpFDm)pb#!~0&|$4*_L3CJ9pi9x#xPS!>vxC z$+BAVf;yRr-~m-1cwbM;U-~dQWM`9e;0{v857UDhXX!j$D5CpYmL_ZCTUvAH3nQ!! zu}xuHmZG2k*bNp5kmZ{M6&if(7*JK-QSfzlM&(qaoOrfXGkKD#>kBQp7Vv&#CZ#{= zhPYBioapjafB|}leV(geN(d~w5Q?{jY9#y8-5_83z}A1J*7>jk21{WYipz%t;neUt zPDb_3-A!5NUVZ;)Um~%)o2U=1ox?esoVp6mVxf9XokxMxgz8M~KxLEc0p;XfFbc+# zXQnt$u3%uU)B^*xlCqj7v zc`?Xe3j7-~q6h&5G~u=jX2WhWz6S;{)5j9oOZQL);WaA^IYm^u3|c}i863`#M5@h@ z5-T787rY4tGrmhYO`b$an0wR+y%^n^oL*$rx4E~133)|@5Yju0n(So8=^f&cI`8Qm zMG4QHJ5Om!FiW-PfUy;I+DXQqJ>fiugmFG$<4+C=?NRb*iP)^~&5~xO#HEvviqFwy zuit$|c8m5;?K5@2JH3AUtbM^LNkvd9dC4RrGKt3&=#;U8jAHVQiyfNRIja}v*e<)+ zOR>OUAWzP!70|C1$YHaL%xyU?&WYDyYXG!d&ZL!OyO;b^ZY{IGql#~lE69W*go@uA z&k$ppV&Tm=AtFKxc<&CY%PS90bQ*^sp5f*k{bI1u6Zz=XB^0 zd|$shcQ8i&@*)o+Xaf8$M?fw(efE&*F=8^AkkYw?!VDeWfI0!Zys>(TF<#k7Z*mGW z-j2CkeQc03cY=~Pru68%jsmqM7=ba@&V*r-CifG_Pil4cA{c0zj>ijAdQ=_E2+KK| zwgxXfgERF_C!-9G(|fq5y7olAiBofe&ZA8qD5_B8`uV~l0G&p#i~kPl^w;mYWZJS+ zD|#EO(627=d>*t_Q1y-#B^FUgYx=i`z+|c zY~vXNx)&T?w1cy5Kj^)@JUKaSAL|o%IJ;S(esh;U2*j#m`0cLU>f3x49o6`L8V&H> z*(K&!9u22G%n-t0%_G$mcK;0>-QaTCd~Jd439&b3?4e&hhG`n8MZmx_ZZRFqhlH4n z*+ccWUOGxf1!+zeQ~wmBa5jJ!hhbF$g2tJBp9Cy%>|Kt~$(|!5B=YLX?MBo6(yYG8 z51{?o9X;-e!qF~BzHLFti_PV&Y3_lnNGGClq2Ls{F15ktb+EL-R zW><>0NZ<~;9|H^Mm)P>;F1KtA8^i4q6%YJ|$+}{{)MkUTv;}F6(3OR1*Qompqz>k& z6S68Mb>NvU@UC{F3;QbeQf!sG4H}IO2Run7BOS9Ja;iUTFg6O8S45^y;xQ;@@_4K( z4!;u&F&rI)YB&mo>o1TJ2%I0InNG-NuoVIz*d`0J(J-{PLk7ipX4?N5DIWN&W!81h z_Qjx&h~jh*$W;`9fA!+}dW=bFOfU_cXsC7!a*Cn>HeN|+a2W>S8=_aH{g#-yCr|wL zRiVn(2Q9|caL+s+`QS;3nYMgq-1An{vg>n8GL&ISMfjA>Gwz^doi2PsY-~7h1th8( zy1ituu{w|kbzgJJ#LhZG_YC4_DCIh8UKGb0T0V_MWlB0&>`aDkwSrZ`D>4v}orrQ- z=tGf}sg2aZ0rHWB*O4MfifLa=h)FBMBE)!8u!Pb|VHz}@u^pDc$u(H;O1Ao>Ex|7fMw%>Wvpx~k#G2c)86c?I(G+k!&I2`n+2nIgxM5|T17z0tHjfofW8OgwQsehkT_U~eIeBVMmc79XmlvqLSjI2 zaqs2f#j%q35Brxr^1fH?{%aADr?`om;};Ko-MPE~54@qn+Aus47t?SBSi-%Z_MmA` zk*Wpo15xMt44qr-WPB&ghRTM*tcg_BzMbUhv<;VHJDcB+O&WdqXzI9e3k7T|;_Xw1 z3LQ`ODm8P}5cu6(*BZL#20qcy?VtM>hhp%-(aX-M+N5^>@*K6F#Cw&a;~J?d!PWVh zl|gQ6VY7mQQCxJ&gEqj!0|o5yPdp#>cX00ekh~H9&YA&!f`4?9QS@PTuCa1$OoVGX z0nbGaN?+)FvZy|>qQ*6{niLH-gv=ONL1IIMgF-;?BFPc7+c0BCIm#QX=1NQ}(N?(( zYx2TB1TVX1-3z+7owFB%^NVi3d(=H$6V7hXd773{k#L;fkA)Tu?%5Tt#No~qZ`az8ygQGV)HCb4o5H3q4l^h z#uwJM%FN&te&Rh_8jBuXt;~_6u?QClAJ?|Fyp2RG(A39|eb?368R$B~MYuqJT1Qm8 z>?HH=zCDn4c3|txYEr~`JFoEgMtY@mE*rWY9f+HRC8Y~uR7dEKHN2InVe+LcF&I0d zlO7J|CjT;K#Is;ngv8F;d6t*Zn8M(*k7j}U5fomUJK4&;$%O@FpG9mk#kkOL#zW<) zL2kO59w;$MY%ofbQ8;w6In#BTVO{4U^|SA&f4iNU&OKJ80_W^RNYW00&B-`g3;cyV zoS_(9plQ^n#5XrDqnq}XW3-b|j%vz9vKt@_AF~MG&jd74iXk!~+@O?r2Sr(DF$CmB zB1s<$&Fn5qnUnPrz;eRY?e2E69u)wQLA)eTOdwBB9Nr{K?1+b~?Q+0zIWNGV$!X6- z-8~5`Qoxu7vGKHJzP3c&}MA{zgRhH${C#(-x%& z$Iu8<&*90F-{gw;bBk)%UK>=AL)-BYZ52|4)_)UN3Qe&9*a8)89Suot-&`V37fr|H zW_(!-usLZ%-N7Otoz8W=_D%LSsWo+OuzU?}qAvg&W-?I(sj} z>;z6T8*tqdXtse z`H7)CAm#?=tft7jf=6q%j2>x~TnR}cJBDIsq5@$OmWf4Z&Q@8=$#jAR3tFvK@UaH* zEExO9Q3I*RU=|CTe96WcIX@ zbp#K=7@R>uw5Z8QYs}yRoQ>T%hu^fKWHdjEJ_wP~@ z$idTEe-K8{tpPI`>2nrC$ULSw5;Hl+y0_{+d;s3&uy=Tl?gO2E@Vaw)8ua>y7yY2$ z4Im3uORWKCp*icGcFy`jcX*=KlxON$e9xNOpPFJl$?I|y&DH(RnkXRL&gawJr%&(V zck$C#VVpeu38wG@_#*g|kSXfoTtq&K+$N8Re%Z7FAt%2pQw#eNMmC9FveSvq42Vul z*SyfwFu=T-m^}tduyEQ+9jb-iD_Ni&PR5+8zKMTg)R=aEz&*X2VO9{7&3J=b*Nj zNTUo}5n)o%2k^esukI`wNAJUg+_yaQWHrwgtzXNi4%aExhL}$>w4aOIk0r zFUeTBXx(Bx+rY(K-}Dxt{3;RBMNH^I>K z$w6UXeFw@o2PAx0IwdO`E{F6;LZTUnLNN;WS6Zm$t$~P@4ku#sU94<3xK9@(MbvDc zoVAI{pzKp26oHQzgq|0KgDGcg28=Lc5gf&#MsuKCdzB19peSUmy84KpaQVqr**ZU3 zx?^8@oeK-Z3oX%HX{GZU_J=RDT+;7@9nj@h(c#a#-ggly&SUjJ>;&KMFFoGh`_F7) zu$!5cf+9N5Hq7&FE-Q~eM24Ai3PIYn|xkLa8-ajR3= zlulAQUyIsK(GGo(xqE>#rKfsC$w(DgJH+w)dqHz`MqHTwqon4v-OS29LRfhsLjL%MIol zKQ2d!o_)y3!by;YxY;woIKTvW)=3Vserltp*B>qy+`wG2HZXxjD`l@cgx$iNp$rj) zs*I|!gtM!7K7%}wa5oo8{9kGSa2C~uN#u%dK+Tjv5Ds%k+8P6(CYZjm6&#`;8QX%8 zWVrN8UImA*x>%r=qMHzdg_>K@7W0@$So8sDEk;fzHP*k5f^Tw^ao<74BvX@a8#)NU zTAGaG1}K@ftxRG3IFMP@t{iy>C%GB8%LymfaFm1;kBVa=B_t=~WRy=%h%SB|J~i5Z zjTDAWCDP8w@edKpn4_hF1yJ)ryH{b9k>>ohAyC|mZO{)uD^L++yHB6qs1;aTwT9{B z=?(gm@jo!Y)2nfM^>h+~Q=Z}Vc2y)j^76R36)f?9F^(EVnpku$0$yiV{kNJg{yYNJ`AO7!{7ssjG*NIAL(nUSWFFd^-%NeS!i1?KPRn%D)0938 zhsJT*$mj93G|3YIomtm69bac*yyNUNFb}%YEe9*^j9xiG}3Y$wX!8Jhnziv+*eup>wp&G&4n4a`oFdqSBvN zXi6Q2!R9|}R2zh_REpE2?c4rfu zVlrtQKousaF!J!}N4t>#&ccTR>q;265CICu+TX`z_rZBfRxSN;33{iw-Y-wu@&CRgbJ`!d(*I#x+Ck*8XOwzUXwIq;}^QpiUVlO z&EOaGl!Rjw?&JEvzIzpZz)+)8I!^;NW8Fl&}t8WgU?}Baf6%zW!iN z$r#VPFPc1Ll*h(DP1k3rd@Zc&NA3t_ty^>X8&j`U@kK>F(dW`l)#pP z!y=Tz@Z=YbVE-;uVh5lkG4NxG0_KG(tY~~v_dTol$z*m&Anb}dQJvVqs!dEkeV79V z0A?RB=ebA3GvtHXa1#~+nuwm2*$5e0f=CCnzMnDIK858!5Zt^|Uh<^@6okxht$d~{ zSL{T!)T@X}UB|eJo6un>OijKHd9wjK&wmZzW5i3MfMq`FZVYjWtHzc%ywlJPm%AuS zErmNZ;Clw7!RW7^;BFsUU!5Zcw72K-s<0+%Z8}*SSXn6niwS>6CB96b4@VaPfH#a@ za&VT|8s#!P$aY&aM}`#u4#NJ-9UpE~=e`+_lSn3kbU=Gnso1SRQPFDnXU0B+ z{iNS!ND8wZ^KlHdv!&J0>X~O#uK*RY$+?W)zt6hNhD%1e+-YBdc5PQw$SLRVk#80W zl(8RAwvyEQt$`kd%oKo>DN6X)Mg=au9xcxX0n_xtDVeL_si~bKAl|4eF6=6dTNdet ze9*6D-|SAqrwBPB!$RC#fn9LwA&^>Z#u}HpDQn$@>~dd#4HFK1{}vq`nSyvMwjura14UNVWgr$(RUqVoF-n{92!V|5 z+&HUo5=)ms&(i!Oc)qp6Y);TpMNtnq<*LV!Mf>RiOdTC8 z*o!(r*6Rw`NIcGh(NuUWl<3QnW$%g=Yp{70f8g>n=@l25*SSS>e?dI);jspoE?`K3 z)jYh`(tML#Th7uFZA6ElQp>YTZ;p<|4m-D{1k-p|g1nMV6OkQ;LX=^2!G2e^V9BIR z391UyodwF!EjAb6Wp3Q-fCl1-Pwdz~o%Za&)+^)_NQ4?4Ky+^9<4dOIzOgG%e@{QZ zg_~!vbaV9Uq2hE6xC;oYB&VY5fyWoif6oHCc?UG6r$D;!7|i|E*l|`~HOCXEX)Dl% zkDlMNm>lu@f6~t;7v$j?dq9)HKEDwcgiCe6`Kyj@rTWWAt=Fx5Pnf6ALuP17xE=$E zq`_ClZ(Qa&PY9Ym?-2BVy|oIe*EA6QEKV zl@M;{r39_=Q?P9N^;!q>PPA^S;CRv-jvdo2lVNxa?$gK`P%0Rb<)c{*=~3?2S42`* z(^_q1lvv`Y8W>CreCkUvVJUp?BT(1;u6c2(c9fQDWL>MyQ}Sr` zbbrV=>Z1E9Pzvb1;%z-M#>L_v)yycJ%8VN|kZs&W_D7sm#X6 zmn+KS(`nJ+DCVKFKtXMzL4KAJm^RwSjf^HpL}9@!n1wI)5Z* zl~v(tqb7qo2sHo#zO3C<0yiG|tSv5w-wIyKfC4-91dXlwozO zb;QoA-ebUDaV4vbNt?1yfslFOiC%<3A1ByY!YMR7a_lCVh@~c z0MI6BUWJR6Yy8bsdP{>Ro-xjQhy*EU@qn5Tf2IZR;KC4CbjH{F;N#gykyIfSKkkLS zn!f3UABn!BcWk-JByyicg-2!kelM5ep!It(4o!=tbx!DcL?CfuZTHLJ>G`_Ib~+g$ z*!YWDThzM#MX+!dmM8@y{- z1OkEGYAv^5DlrTGp-Ge?Rnqhr$ajEZhSex(#KxI22K(HzFSo?@bTRr6v%^ zqQn8$y4Nm#B`89ON?aTz#J<@;@hO7-W0fT%`!@nWmjRQm9M}p}<2x!L92DS*J%(k6 z^Rk_O7EXSKhGa>P8B*SQ{PzRQ7*S#L7FEX{1s#ZDAr4J$)Ho31_T*&WF->oK>Eao# zMYM9Yi9n1H;Ijmetq(h*yKU0gKd7)f?x^BNvgPHXUzUg`^j@a+rXQ#{m9gY;u1Pr0 zb_&sbaYeNigM0(#euB%H&1%Ea7TI9PDHhBUu<93$m!XBD=fH_E;QuZiwoXez`vU$e zk5kU94fuBq-w;hX7@2dx=DWj^6pXIv{s^=sCDI51r8E)eT#Q}{duO_cVqwOQ($)=s zK*zP)xLkKqjEo9Iv;;VK?YZYpma@ar=*}oRZN*=KF`JdmSmcG1e9H0TKl-ab<{=if z%fIE}2wY2cx!50~^qmq7vXKZL!UmNUjLAAnb4# zu#_>T5oG2dhd7a-mmknE`H+PbsVoI@3_WvYxJ1?CJt6`*1tcv+oW-rOmzVt|SXG;Z z2HxKM38u1{IGU?2VGn3csXJIAU9kv%Gu*`3QocHjpf$q>pyi#*C=FpatL%o|8jC_Vl7EBmedrCdKAb@pSoV{D=pkqG zzKt2%!SL_HA9FEHMZsf7k7QXPHBFO6h2%!VC z(Kr#M0q784VsSNK=w&sXW8Of&2u zzr2S7!Xj%a6=c?VpSZ3km?Mq)yEdVrc+dyvj8{khG0Zy*WPfdZi&?}-XSZ#Fv|A!V zNoCL<<($9a6B;v$h$%bx{+u^DE%EO=(fR>JJ)ifWir7G)`7mDB&Y<8Ql_&cIG5Ou( zftRsEXoplkBY_Egk4 zv?=XQ2cW{VAuomzTm)uWR9(s?@hs@Znz?D~#1y14cKaC$9$ISwpJjg` znY>L&+3Z3~@G6jK7+<0Wwcp`>eh+N2jCRZhqW-KuPJsYlWhtC4Ux4IqO)}ON+Oj_| zTDjzea$;|y2PK^inpwL|1Nkhx2>%m31nMJ0D9M^@D?q*RGs?DU5>fI8#H=4{TTP^< zbAUX|Scll10F@q@GI?Ak0TTZTbb{=_B~j-of(ORhudgv>3|*#HGDoz2EhLPK*#uD;8UGA~l_ zRJ5`OR2<_ETn#XKj>;Nz@>Z7uqC~C~jiDydiZPl1lEu^Y0fv`MP5DCcno-@qgE90y z>x{AMe6VZva9n}?0JENU#pRE#_c|{{M(kNT9N%AU zz%l9&J80b$`{`4GtS(6NcRGAoxYY89sZkD~rUkaY2Cae*EoBT53ayU}4y%YA&=7oj zyIZTZA!8+08>Dxi)@?SF(-i5L!)(3UeQ-t~qEm!5r#lZ53Qty!v~{kWv!q|#H9(<5_>1=H?o+_PjjwUN(boE}3m&iNO2Dtu4{}{Y}J_gRN`IG+v#@xcUYv;IzJC7^}T7)TY$>I5@qm$ z98F|wm}(O|faLR{T&y_%DIY+ z%amA(%41lQV3j&|?}JgIjuSI=NWMMz5EzR@afrR8-(c~xJlDYH=KpF8B zccs8eRMDQC8yB8*B+fGm8(7jS7=2rKVPlA(kzxtzUfh?edA)nSZV zZ~-Wn#STyc9a8^_Ew8;Q60K1+@F_C4ep*~NZ2dXT+#`|@gPKe>$o`$dD&`c^*9$xb zLGw>f6Tk#+Fc#3CXf8b~7!pNoG}(y5WNy-Q_9Kd@>hVlkFZI*ft0R_NumJb6;2@)A z&SGHBV0fX#-0R=8+vg$<(|V)vkp~O?rJTKODG3QtzmHUk(0AB7c1abJ#^NIjj$+Ak zRH20|lrJv>t>Dp@wi>$^EV8^(!NI7f#4r&-hl(zFM#CFi^~XY7WY!r0dO>Hl)M*2l z!NmLNbUU{T60K5ZJR&MS^J@czqODrSAlI3bHb1!TVWA8t?h$82B@UpYMmPIG3exe% zXp=;_Zm_^`Jl3I{LTFUbGZ<4Bll8VUMg_A07oeZM&nfLMtjY9*A?Yh>jkgdbe4CoD z9=Z7=DGqmA*jcXx5+T-F_I@iS$nYIJ(^5C*3nYN8Z(dYI;JYW(7->_8u&f0WpF#ul ziYS2zu$k+R#cNnST)YABNMwP%^Ox5vPjHq4dbpQ&ro)p3sD#B>77|O6z$pnM2C}E z^s8(28Ttr5g%S7u=!JOitFr?O5Lp{OH*_68h}yMk%o`5?U*s)`x^Z_X5n1&HT`x^c z?nv|vo$^-v;OLn~p*NrXyZOyN_++YnB(Qh$L(QYy?dJ?pbu8O{M0qWum!?{yZsAXg zkB9VM4o?tzfH~9*e56kcb&D1?#8KP6u^jSmclrQJ7F&>>Ui&$c|0$&_U!7Xij1)9tFtZQ(M zjZu_^zd?xrtbn$pND+YNs7d>jzB16x;~dHW;+G`*k|q^z)YSdY5e>L8rmmi`xb;*| zjR(M=YPpTS>*~3?K5C?2j&3fFKnwYDtA2f%H!>q&Sox1%DPk?jQ6Xoi;dHL1H;$~& zN}bSiRU;DRa_4-#{A_lTt-_{K>N$cIE{mV%YM_EighFiEjr9G(>t3zr{%Qq3ym_%` zPKkW+gepsr+g)5>AXM&zY!O+NON||p!5d1#({1vM1rm7_8Iw!yhQQdPWDw}=%Pj+L z{>da{-@zQS7RM*pGd#AII=~Ii-94O1JvJ>_viEXoA{3xOKl*x#lI%YEZzei7>{5bO zRakuE*zRaLpIrQ(MbF9jM@ew0D%ba@4bC|8=gI0d`#)U#H#!}!7bM`Ru(lYVVN<osQ zQY8VK1yC3kcR1*De_&Bf^BGIp=}2}&h7$KA({-UQAY=4&5|?H-j_3Z9$R2HXs!?;W zWWxeuUR=(a{XOZ!nlE$yXk=Hto#&tnEd#uOUAANqk_L-(gCdVHVKb`P6+o3%fwSg{ zM7e;y1}B9K^9Gy`@ZeR*Kx)uNQ3!p;)4!1#TnFuxCt&D~K02n4d&I1|7TqX9k3j4> zj|o2;V=4y)G_Z*g0c`{My=bHi^l8j5Qf7l+xCQU3BH@NEcZp04X}{hQg+=6WNKq-=xj>MNXN)P$3Xwzcj%p+jOoq)^NhZ&p`{(2v9YQOC;%Wn zbee9d>VVx58$#~~H5i;0Ngx8f*RN0=C4qF4j6j-Bl9W}UUx9>+kRUlwf)pa^+uPj2 z{Ag#SDEysZDd!;j-)_v=1`N}`PqvJ)a)3WR?@!i1(x-Udu-k3y$r~_>ec>1{3>Nj_ z=sOF1p&>Uh@WGxK!H#HHTLWjT7|^@1!qrE!!HqL_VBYLFK0x(kJb~DU?byJDI6CGp zWwsE+foAh}HQ~XKg6?-b9q3C3L_Dm3_*jnbyS-Q+5Vg&@g~EAoq9nL>^2=w=U$BDk zc0aQGTOOhvNTaN^{=6l#}!@e9aF!$#{cr(iW;g61m872VC zvgSlmw?>vjZnJ^Qw#{3M=mJ z0K@$^LK(sv20`v=sN2`0^ng!d@QYT&fBDug7%lIs4BWpvRA`f4uLKuL%+ zpq?F6oQH;BQOS`EdEZoRnUg*pk^n3vl_(*ozH?AUm9+8cA9@i5Ovx4n3$TZ5tw}y!YQ4$RjZ~}IUqiz8`tVpR*R<0rGOVJn)j8J~< z9Enx$yPbQzqz27Kc6$LybFTETN)0AWHC23z6xp4}_<X$)mtpW#M=VdEH?|dwEnzzs)@Sof&G}O#HcNe zW;oFw!3Oqw@ZYcm>fQ-Lw`mt9;x~JHMC1oj#{1Tc3I2+skm~Hmp1LCcZ@d8b-+1v0 z9RGDu{eQ)a|3C%(e__P`1fb{b!Hrf(0Dx^4007qis{@5pC1phDj10X@ZT{=*6)kQ1 z!*L|Pxq6Glbd#{Duyo>MixSs<$sVE%<7|^63lmm1;9f?%zikr?;-`P|FWMl%d_dJU zXC#0-s{88RyQCKQI&|Q%5<;zsW2eW2184P5f1&28g1HDZYAqb#NmnvTv z04|7d5LoFxJJc*y73J}Iu-69*Lh*zEl-ztO zBJaFjO0m1dpDH&kfo8pvc(<(96kgqHu!$uWB^YU|*zhR8v7@6B?5ZR=m%nz&0tH!P-VO4}U65UZZDhK zkQ^rx*Oqsv9Et6cIQj4QyR5It(X++%M2>UP~`yV^&%Ou{L^GdMBJWVXV9sIsz|5%*pK*h>46{%%T%xoT|lzP&?h0&(Tyk~pW0?$P9S1?>A~ou#OC}W z#eM_AVw(dBA8O7VBV!DDE%w`9V1IgflldHJsHL|ZlU#16O&Z!hp}+R*6C*#bCqCfT z?{je*@wfS7M={<=^B~F@O79_AdK#MM*8kQqhlY?u+BIa9Coo0Ik<(s6^QK8dRVH?r zT%b{vhh0k=reQZCs7M7fg<-x6gg2oiH`BO7$~A2)h$?tkuSKmR=_17|aVoDaT|y2x za7%mAUY6mdC{T4_`&uUeGd(*+QDf8vkm}S^h3SJQTaH%=1Q!tiNsTL^)*dC)dNviC z1~lP-*AUNgj#?vGsO%4_*Fme8Y$rE=ZFWw^dVu9Cn&UAHS^xd9v3llWmz=fHA!=Xw z07$zfT1hd*@i3S&{Zn@&udyChM3W}SuJr{j%}R@X!h@Yg)@HiBzUslE@aJo_V$mM3 zU)Ff8qD1N;_b~mCend{pk=8C$eq0RSo70H$bC@dr{T5ZTN^BTuFxJ3*&pMr^bPR~O zZVY-I0g{rDds0%Hrnhk&I^y;^2a=K6a1pX069>HkI|{A4`A9pk3t|c%RfaaB3|W!f zfDOL!(M}!{+R%SL9M$}`-AX{T%nl-S14W=VoCN11v(St_*2({rvXS0&@xOujDHl(nm<5)~axH0V*O)2@2{=c|J%;v2Sd zWyq&EF$xN2+9*=ZTJCPq?PS>VhYSuh$ANh0l*7R`T+|PuXh-T8G zCv^EJa^?{5v6nSs`!9L*vIYH`cGh99s2aNSA+2$3m97nI6`4X4KIK*4yMS*M3Et$5 zV?^orb)fnO*e;%e_O#NARvnP$TXcU?!)zHfa-G?mv}M`2^dOJ(V6L&<5#+zBxei+X zO!7eh?%|UKr-`6D10Xptnr4EMX`7jhQzU$-_B}ZNn;J2@=xv{_BH*IK{n%YOmZ`;8& z(&u?znAPCB`SI(Y!2wz*==tP15^i)JGfoN7%A@{(lB{Ax_JjePp1Hv}UYdegy0&>X?uD)~jG-Huh**0SYUFfR)@i3E zV*0rcD~#X^Y4Dksj(s*doOg8$-Ud3KBA;nv)su%?tT4U1Z*m=M z)1pL6>k9p2Q?rd7)~V&%jmVd?llm_0(wi8hE~H)IrcmLEkCqiug80#Q%M4aCrJP;m zvqgQ=GW0((?DQYc-jhx>zmT_SP!JhrXgaSeY(>B2P8rhAM7K?}8~^>4>IXdf)tW?s zxOAoc%jx5XRk-qjIx?0!oKjaZ#B9(EK!1QkAz>Ehi^lFZc+*qTQIIkfSBxkTg)(~2 z;RME(cT&EMc~W>>X6l9C;@vE`*?_ZGF8Ca8#}CICGm*Q=qIU;z4sp}u-NPa{`tq)o zWIg@*iiEBfUhWd-2#3(Du0bN2O{zZpBPp|C1s!SBP(T;UWhs-uO}9ZgfU zbksEE>9{^>i@kuYPj)%tmY`DDF?92WQtfs@?ax0I&-3+`cJ;(K{#4pNbT#WR+CN4w z>Y7`;`K>$6w6IX;6`jR&!&Ka1buBm)}Jv`vkI+icxI$UC9?ydr z*}ya7Y=hRV=a0g=@4W%nj`t^vU2WhoZ}V8+G3rIbzG_DN$vpB+FC&J{7!>o%(!2{rfK|oeDu~>Xn?VvYT&p>!*;;W1 zo4hUpL_{#!RR?ji^#Ni|M#Q*7o_46}+UFX^5(9NAb~Rp#MroA-2wHCMdan#-T4z-uN;<24cr-XZ37&X@pZnf}M?_0|kt>$A)_W<1X{ zUK^qfc>{0`SehHgnU@5hlPpHt(@Yp-^qlZCk1qE6T|%==#^4Hv0iCsKxnOYwNkv;D zRN+TEgPqKwI>{rp4bLW>=ExRJI@yMGRw+QeF&vIk=y3|guWKSZN3GBmbg|n7qPr0n zlpt$V)1hV8Tj)dX*3FHL4GuWM8l)s3PO5+P;d`#MdPtZ)_SGG{(1R31Y{4qhG|U!5 zWJX8=qEG)Wh&G3{W*Z5jmF~Z(B+VHhmo#0*5#R!4go~|Ezd9ae)*kI~mtM>5;lKI} zVH51n2DCFOGDM_%KoKg^BSr#EDtGdbZSn=*sa~WLnkh2eL+&&P$Rs%E!i~Zp~T7sB|lGWRK7!#p;JmM9fXYIM^wfDQs zs!_Y)3);bqF+iE;tXqGuB-LAXF9*AS5f5{RhwpY>?@Xp#>3S2EYf2#^;*Z5@1$$23 zUe5j%RBo4b3mA%?9=0dNiyr`xL#mBI24LWgx z!Il}vLuN%p6sU_il`ChgfitdECR)zg8*!|G<{`Y0y{e#UQ;D90tbl`*cjjv`Yc{NP z6wlm32@fV-`ZfFb&DXkt?j#MPN<+!0%!w?A#twzM-7|JtsPGO7O6}&fewp7KQcpKB z;hp;)&*GjphDad>0a%a_Ofj0}gUOzCPnedw##M+0zKq2iP!_q;^}I)v`>d=YoNRSq zt*KdVVcB2vt+Uv=?hj5%#~?hWW#{ulliH0GA96tf>(hkR5y;@Jc9k0U&1tKYIC1Yz zdBU!nq68_e=ka~zOXLv@o5eynI2Jl7XoGK>Q3e&CYD1v2`_j%MV9Xr`o}(_wazuH& zMTvQJSlU8N<})Cue=!U?jFT$gsrF#FW_~TJGtm?khpe=PeeZ9&iNG6DI8`Q9<%Sxt zt04bb&=N{LAf3TLng7|cM^fUn>y4JpP;VLgr$~GBk_Y|O)eq(4eQG;EDh8&Gx#W=- zqU>9p&{nJR`o^7WZ=3SKqoLFvyb&eQ{t5b?U{axm5^0Z~(T42uOCR%V64 znO(l7!!o+>Hr^(;KNDMZ_9xiU()e4+mCao>x3jkGbI&uTx;fFovXgk57hOly9!?va zI}!fr<@f$of+=Ltp1B5{!=zn;!l+H|)Fm1z>8bTd`M(<~KS%g_#mSWTE;`fK1njSj z#h$M?dNrb!!plxMZI<8Q9P8#Bt=GFHO?*D1nw@>aD9^Ibj+9je1ngRC`~UXk{4_&ztvLMhutp6+xC_}!>=J;#_{XQY^{a4YI;7A8h*Wdc;aqUXB$!9;G5Jj6*?Ed zbHAhlm2ar>l2gm7T^fIpyB$<6d=Q#wHj@spF8WY!iFOcdXm-ZJKB}&d_06et>>2%(U%bqb?0Z1H zBspmD9E$^)4E#HfF1~d(zxs$Ki1E$G{@W}42t0~4v-tz?KRFo~-d(>k7yv*83;=-A z|8q{J|34-OYFl<&VhFx#>N3g%slXd@+6C~EiUCDxi$y4vPL$MsNEA+_v_g)cdRG{> zKfUH@DYayjQAM5(6}h?0<~QEn(tW(Vs%HKcXW{Mk{#Xmso4$pTX&W>9FKInR1mty< zi>-BdF0-dJQLc6uWlURbjBOfS z{`P#t8p%7knWk)OE;g57a;%gX%x+z+@H7`k101EcGG*cj*;!BljH9K;Og}MbG-je! zaa~<+=0pr0i0RCT9@*^#|E5C$^Ugo%>0*|>Gq-AZFPbFhB)diVXh?nqDq`wnv={09 z-64YG0O@=>9Oza@Etowr@mZF-D2N_^#&zIil-=`EadT>|GW?2aPu>HO(_Au-RGcdV zCKuSUy3PtpcG+o>NC(B+qu#6_|JIQ`J>8Ro8ai@ESau(4kgZ zWYzR)AoQg>x{#9_2_1PufW9p}@TE0-3O!O}L}(NR z$R7?dp-CyCB8XYY6MiW!+~Tw@5-6be1`0Jy*(g`B*2Kll%x%&zl!OAYjc7W>CCl=Db9Q-mo!UeT)TIVK$vd7Fa zHe_lna@pDMIep-&_{f0+weXlcWz7(2z%{1#S*kD%#ED!;|0*;rU|l(knnaGOpD@co z1!Sf^>n?}Y(di=lqc=;OuA8L%K<1wG_V1q}ywuC_(ctOa$JrhXSWF8QELh!W!axXD zyK~Uq-bzcY%lrLi+FJKA3au9$u}=Qh#1UQ{g*2n~MSObJ_FC(%a5XKK7mr0AUq{HL z9SS3snuxZs3*+L5Mkc8cX|^Lxk3PF%N2V8(zyl*Go{XtT&3G zY#-~%8jHp{Jx+VOoxSWK>a?r(aS^L#u}e{F*4MPzfBvIzy$EaqCef{`AZg_rDy?FaD0@Ans9`*YG> z&hoY?8B3RIPcx?>?9mXe>#FvWmvKzAS80z;^jB=O0)$KC>crqz)k5la$B#lHX>#P+ zte+H+L@nS7y`?1g6D-!t@f_Cg6blCd=xA;js}Q!s;QAeSdo;vr4;M4hg)ET2Hr-EPSrWY71dB9ImX#ryshNJa_O12ne6}4g(WTPrF97h zDUQX=eX*Uq;T9@&^)a^p`=nFysz&gAE)cOGb>}Rl0Lr0Z!ScL*u-E zN_R?c##*iYz9@O~JP26iRJeEGj%&N`lvwlPcZ%5DnV@+19B%7x`Mdv$rB&C%4ZBE6 z$(I-TKRjGbT-}?jQ}Qf0_1ga15eYq|#pqB+JlK(XX}mJyM# z&`w3EN7x})XGp^8B72AapS3Jh>(a>Zx4!^O4getg|F@PI8@d=<(3*M}n>x5y+S@tP z{-3>t8Lj{7EhK>-fJm@ux5Do}1k;4nQo+=aTy?nFSAxJ4L}eUUh1h<7<>5gR8rmH7 zx*73vFflLrc6~g7XZgHut+h(^#S!19Msv4qmOxWlHd$UO5u<_b+H%@J$1KuU@rgGQcJ-1XWldC`O|wpI3MnU?Puh2&xwW8l2OfsV6hqz} zwkpwp(IhFVQI+{eAb3CmS4=9uDL)v{l_cKAU~uLFYXORsL*MX8N`jE0&5@e?oD|Kn z4R%R=NYI$nV4Csp>!NCX?0`c-bL_L}pKaiaf6_#v9V8`}G2Mjd)Lz<+S1PSV%4Eo- zINNDpBwy?YnCQqjRF?Y$h%1%hoWcPHbQn|(ApahyJNZ&>jftw*k|qPBkr0tbE(~{IBw~W z1yh87S)qhPAeX02;D|Dr~bn1#ZYt9gx*P^YkV~nj% zAK?94zlMH#K%+hDYv{bBt!r>T&2pEJeio}`&=}(e4D$NMeT&yKDbVkBaC#F^{<2aE zK_Q&^1o{=8yv@TKE*UsmDzphy&Drz17!{!uPU+RNaZju^i(XbZSLI>iDQ2OiJpO_a z!g~t=LVG21JCESR8FBLy42CC>#sy_nlJQK7Z->FvT$GqY0+_hPv@qb< z%AE0xSaypZsx0Vn9LSL+ACd~ZMYfs;0ONBwWwFk(v$7d7$Z$8tx#z{qms#sraXw)p zolL$9zV-80KqXN5ugm>Sm+TsPP;ng!Y2eAVU^)GG!|@R6RM1a;?IM;9y{MlB5w`8z z<3b)w^OX{{N3kJ7sCIM@H_m}do!4lQUFvxHD_Tn!C`&*HRg2L)4u2?)Q#pKFMgdd& zI6WbK0DmZQrdQU7wp|FlBxw`T3YSXjKL!XAjgiEOc_)z@T2*hE&vX7hA912E#ZrvX zO*L0cqE{X`p6|;*Kk{;{i$$`iZyR3Q87>EFTjf4wn(B(n3OsqNt)zlxx^y{=T9&|g z@{0wA{S8XM%gPPkeRtOf-VnP)XF-^66O-|Y@f%#G<_o~4WBv=W6Bmc}c{aaIEFrz8YE>1y>Outwb zb$XDpRbihu<>k5JYiK?fJ~d@U#Xr6A^Zf9Ca(!?-pa}igv?_g9P4p7^qN+-NKAvhu zrD3+R=bAUn5Kv>gvwO-;!1+3@lK8>{@m_nH3@{7Tm_5xP9F%bt9!JqnrjwTg86lW5^MsRZ0fa8*|~_Y zSIe%}X`}(G8a3wEcor9wDBcTXj&yS+ zg8Xo%B|QDR|K`vtgsLQChNtwj3oe_FJRuNSY4j|KvDDwkOuxGfo7>pG%uofu)l>5) z7giN~ZQ`hvyvN(C0T0J)UG6YY$|1t2o^Yeu!cE29FA^<0^CgILE@c1dNdUMuXcic! zifCgi+z=1opAjy_C}>r_y%JC!lmz8oKDK&X>lJ9sTzoc?Y*=1};qpn*K$#|8!D<}wmPoaLG#V2DhK z-~1WWIx2bjKZZulEt^$izY@kl0ssKH|EHwxe>5k0HErz=C6K;n>nRw!P%}wQ+-~_8 zi<5DdAk%QNAElcT<%CA^_FvEG3L3tDrLFrifBGMLd8= zjS$WVMk}8gClH?mu{nc?jAfz=TDEUS+71TN*k}S8xNsOZtNg4{8^3+1%2@FN~ zXBmV(LPK?jFV3q;hPU_$XOu`z2}y~xnB}ohU$}63$s7PR>=H?X1{v;I2}PnR5|QB| zj_fEe+{!N@PZz~DpC&lJnl>ed5?0hbg+77oT4Uapmua=MU%TqA}= zc=MbQC#Y2srKwkmtW$e9L`j-c5;Ix7tyEaN5o>-tQvb zp6AL5V{ol+Ih;S*X{tR?%jRha3YXdK zz}stOXyOrQ8rF6&K=CA2Hy7{hp8k5!iLW7u!O-Ed6X@1G*JC|p^6lQBtItjMlnM5`xluSQbIrS%fwl*&Ehawo~^f06bL;hBWpwy|y7 z=;(`W+qP}HV_O~Dwr$(!*mgQM&wnT9oI5*rP&KGgO={O(@6vr(tQe+UDBO+rq23j1 z@Ya6e%TyjGyleprYdx#J!&(ww zro>rY9J30R5n>f%zxKqK?^P|EZ^QSv?%A)lSqD>R-)Qi?NoUF>c;(k@Nw=3u8k&yp zBA~E=d>Ayn_n%bdin*}T0HJZu+);UFg?t+qW}ATGC4u@qV7QpavtZnPLoP5={>~9; zR&I5n)TOo6L&!ycfoDdFZkJyrp{RiUgB=KlyCx=Z6K{H9-02mB>29>?^bbI_=|FSq0v4mp<=uzxW6*@l_OoOyau_G#V7M($ zD%p6LTq5QyyfaZln;Ko!86;x&i|_5<2U`_=)w5LKthtTl;)JY=K5@MhOgZUVm?-CX z9pkyaf6IC97se&#<)6OXJ<;-mO3rNmubmM4_gQG$k3;THn=cU)oF!57S}r<=pF-ac zxTYs(?rdOx`mEk(Xo5*Iu%c zY?N0N=(iFGL&E=l=`s9{D{euTZ3SOG0UyU))JN{3-y&n9V`8flx#3F@#Wsy;^VMi` z6Fqb7_k_JJ-VzTrhJ8PB5Dfs>jIkGIzQ{v;5^K;eX`rjCe|miFW=x~9nE4m1Jd=d0=O(@^Dx&fQC5?g!2F zIX(KwkAn$zvZMKbnLxQEZ4O6DxDAYLu<_@VXXv%XhUk%P*OfxWFg_w?& zVAd@^!1B(?k`IkLgIWClTulhbx`IOgp=M%*? zz;Q=Q5O;;hUGMlK@1g99O?_6 z7axRUm%%V^Cg1%$k%7y4$ievaPiYoe0mpP-0|2jj1GGfN;eCa7$)#lFCw~{BwJ~ ze!u9ilD~V2pH&RctI>~wmgPkPVWvT;m}FMRB-nq8O#v%#ckTRI4LWu~*>7D1Q11KmH=mNbu7 z5%YMC2V|l`s4eEnn#OjJc1{A52*O$^r-W(bsPzji9M7&o8Aw6CV(;O6jTIwNSZSsb z+c1YO$L#F;F~5AQ{k-`+eibPUeZZ?(<|1Hmq&Hc&uh01RE%y{H&8$vaK?NfC%B7d8 zO6g*iN~4^f*?K|zdn(1}EU&h~^w+N;kO!)1ZWrY7&NkRPxH3H`5k2YVZPr~l^^s93}Hr_CMdXJ1H{RyEw^w5wgnmaD!G+>2>Ugy-v< z(Nqm#tipFmZ`P1F@b_ndjdeUYy=)>>YG{18=Xsd=bvVe7OQY(eRrE%gz~5)4y)(J> zYTyH;ZPy~&(ZR4kc{1z&WI%O9gWC7d7Nbx5ezprdSUKncToIe4_G3sUp++f>ykzFB6$6h|Db08)|IfHcxoE0rWr zmY8q>jBw(kY={tK&?Li0<^g?(SzgIW=};t4PW!EQjX&`6`;T$w~rv5ROw1O|G|R3 ztR&U0?zCIBF*jAJaN@$CK_T587FMu85C}yiXRm_D*8tyI6Q(Re@Q7T42nI3LqK`2X zhCJhfoLc)r0u}3*oPK zDyqZrO91z?1=rq89V8YA9(x}aDc>=$9o$xq+~)@J7A_XcY|pTMwKd;Czm9p=exUHW zolcw>8bvCmgEvLUL3lCngPo(*xs&I;XJV#+}|C}DN-QY zGKc9pxeKo$s*F&sJ%UEifhPZk1OYn7r9qB=zt`~y6Hr6L>Fjr`3*IkpsO^MF;i~Fc zMFO(FO(8ao<$2jk1`-hby{;g6(jnkNYq;m4Kc=!Av)*<$Y_`|Ng8F_FT|y7cTYd?qdimmiZ3?iF*^`>+d56#u8|uv znWD;W6F9jo><6PI$nrOg!NcIiea7&z61Iyu+_%hiZE#;KL08KaVbWbI0+l=Kn5~wk z^TWM6s{8EwaHcrWcWuOpU%L`wN@jX&!*6g$hKGmYMy)aq0?tueGIj;_kWnWKkQ_5? z9UrA|^6=bwccQ#bi}}usGxqzQnPLr#E@J3zO_VxIRU-_AzChz*Ww0S$2Dy`?y-x%5Z*sgwNZYh&VyBLIW@;I$v zruSuNX$3~taDNjD> zDm#>!vkbIu6c%@_4=3p$%-e-qv*{a5zC+vmDKrRQyTr>jdU&yRCRxS;E7aZ4zYnekSvn^I_H*YG(7F zx9}Xa?G`t^JfFNaA99aR_u$O~w~w1UmmrJ7>tK8j*?@w-^zVHxsRu?t`C08w(}=}| zOU(bI>~Wg!6&ApNfX08Q4&nd*zuJF;!Nsbw_WyDDslzGdHG@_sZ7V1I6eghCcRdL2YZe$malF0}tF>QB=YuX=+pVWUWe#8@6>f3rPH9X{35D)qD zMh5y^mMZIO?EAh0a}q!&On<=BB#!J+J+!aM=ecM}4!_JEI2C4|6Mj6aY#6$|1C2%R z{X~GVmJwaa;vkjh4aw8xe&(tKQZ-_mIROqm#7g#SiD4EMjJ4pZvYOkRf*=+ZMO%IC z6$Iot*ZMuq!?SJ=7#4^&J<~JNI8C@lRvc`RGpp>oH=#Zf-4VJ;Vi}_?S&$9iof<~cHWk#n8mXlMxXdtPdXThe2w{S8$b&^Z*SQ*Wp=zh#8G@V%=S ze;Zv}hZV19=1C&v#sKADz`d{}u2y0s;&E1BMm!jwq6|L9k#ofx|1({ar($$7gD?uTgjITrElKyX2PBK+p@Rxq6R&joM} zYe9)?gJIQKP5lBW>yx~&sJVQ+TiOR{ts}*6R*kyy-5U49vN%8LnZ~ucHGDU)Cg5TR z-;3pH9QNzcV!6c4)Z>Wa4oocDP()KIhQCNE2Z)JUEtd+9HBITh0#fKDM&T<)1hE&=MJ(rvU zG?&4rbp#b8;ZSp>{}#-p1+uerkCS{tjV<_`aO^wmWI^6I z5o|9)FZP)d()6gKftYUbi4&a;6R>33m=Sww%v1WYLrV`5-ud;<6~sTLCt8e3Sw0)1 zcwG%xrE@_?e{mERKZsqH(`sIsB=0Wn%hMmp6uctou9GqQ?64>dSRgemSx0LU7#U6S&Dw$%Qo7?&D2D`(tv^ zE=R{xtinn!@P9`H<#tU833Na};_W}z|8{nom>RlR{09;IUs&*8T+&y**6z6MiKp&g zFmNwb!V^t;ZcaB+u`dcr(g&ImOSj0Blr#I539{v@ChYe7bkx{4_PtL)a{|2**Bu5tm|A zB@*9ts8A5fzsU(^j68#Gw&-viVTwaJS3U$Djojjm>NlXCNB~6%h3bFayx&Y11r8*P zWj5JQ7lzTqq1*OvANAgGwZ?wGl0Tv5g2QW(ITrCo`GBd>^3eC3sLFxEXQ> zwJ%GSYIh*o(;3b(uo%!U4QBA%f2uS4P|gN|xK$ixfh_~(VSZx)_epk~0}l5q+Q{Nv zam!h!Fw<62d$w!pS%PtSMsM`)L6;+Tg$SQ(yBvs8>JU)9)o-SGnOkhT8>X%CDc=+wF&_gtk-t z9IoK}(?_{|OMAd6L7ezkKTjDSuYwXP+|z=cUcX>po6w!`23SN&yjp`-Yf+(A619%pOo(yi*nP zTWReed@g@{VNMTfId1iA=Tl>6URQ&7xe?G47)QuNxY5x;MRx!J=RwylKY0UUcE9{K zs<{W*uMc68Ess+q=F)7%uuMoQ0S+qQ-MG=gUkP=axSYZLuU<=6FItSpH-SO{mXKDt zDAgalKcVWei-ey+c?kpn9NW8p1A!-?WDJVc!G~BNPjX^rOcp5NlK7MFv|clBrY~D( z*&G^qaREE-VREn#wcJA>x>k4`Aes2eyN+`}>^L?=_KAW!bUY3qxxOgr7~zNkIFW98NV!Q}_P z{+8R15*n@Rg;^O0b7ecmXn^?CCer_B$ZX8xeAsdMJi?E8D{U~IkWE7}pbEE#K{!mC zyGG`XE3W(|2T$*#i4;5++2CY2t`k!KP2`6b7DgT|zz_%X=>l?rNcVNu*ZD*Mnc+s$zNx?K{dJxZ^mOYj`qn9MqyKia&4ndi{- zVn(|Ugap(`VMB;=fQ8>XVL4|)qPkJ%(zVFE! za+$m{Vmlfb4m+#C-kT$E*APv&=Ii1hJ#kkUy3a#W#lrMwur0F33u=U+byVp^en3XH z4ANT!;!rNYxp3a5xlZ>L8k0rU8)PfH^5q;qAuzYhh&!S6c5BVLB^GKZ)YXW=GPBL- zXjc37PG8kmmBY`tNCrisN}>1ztbzssI{L-+&=Du-;0n&W%w ze#s-0#-?!O=K(v5CFJ1O3qTiT@bowlI48Q;hU2DTNcn?8$a z=|c(o^RA_|FNKr`fCJ7f55$Pu`4)kte&$DmiF?|)t5P6TigbA{h-E*-mUP&a6R=#6 z&cHG`9`{fTFn(Zbrc?}hFgAn%H}KjXIN+6nA#G-~mRO}av@On5c$2|Clm29z)WcsO zw|BAed)Oo0h$&xt%C8AkNl<|7c0!3ti%>rc#h1R?j?|$&-`)~-l&dtl2e{_x+?AOGKBJE>3adO-uc08 zGq99uFz!Mot>OexeH&t7T%R`Gjb%ef!jG&iMRUd+7MEA-jWF8>#jk}b=TI^AS6 zVlggnD0dK)g$&;LjXzU{z8@?0H1*=pWCD(pKL(iWL=)tVSlo zZE581!&u|zFf!%=3K4mf%l>=!wxVVzGG&IuK1nfaMZLm9bUCR@@+KE3dbD5VaRb?S z%ZEW3j7(*cM}q7=t?LgAs*8Bh7HwbyiZW`q)R&~7xdAjd%<;=!ye zB0H}I3g!Wh-P+*Tu$!Vs44gQob{V&7b7uLkpeUkg-fOX~)xX{P>sg%gS^CkoG$0(l zbg)n661NSdR>TyL+3LveAz3t)EZw=YGkmqjU{#uB+fP(IkR>p7b3mYYaQ)(vR&I>D zb1nGyR6;d<_im6sZknI-+`#wry?OSeAwBblJXH^aV=1=mwdhW>u`@8WNj!QpyE?9s zO?ALFnl$UbJn|HLFvpAF{%m+G4H;4Z{@A}n1ibEvDbE+kO4VB!*hh}1gz_S%i71;U z7felZt+=}RaTVvKiQFIMri)BJSWcitz%yS%7O-ge-LZJOpVRWeFVnmwtq^!d*4v23 zQZvSlgAfxz&h?{5WmP`@gr0lFF-zyz<2PPTxX-0lRJxml6xT^(O{0i zpR+mwgIETVw){Rh4mG=(lGdIkGE7jsTXPL~U|FozcnP^q_*0zv4oTlzCTPFJU+x=h zmZZ1@ZPNfM+K^c-8`RO5fwoy+l~iGQ8)j(}kYV$HDAi=rr75!~6s>Z->g7U{$H;oy zdY4i~iDPn43gOhI3{s}(Q_OJR-_C`fE|0!oEJp;06oLcBp`x`J_q96JW+ao3fd8G?(TMKc6sOXe)y z!v&?1D)+|^ea+`Co@WA${_YPKy_wyF-Dq<-ntbF<&EaKuIH#dBJ=Aq^w?1AXZHCTz@c+d}j5*l4B(sj7%+V(^2HeRtzed zUK}jK$Kt2TC=7WPm^qMnxI#Kp6JOt2uCCim)<}>26uE!$6()uBo0{lx7|U+jHF&%0 z2O7G{UO7;>tyoCymj56j!t8oTrg0{U*Dc2SjN80=?eo6ewL_E>8p1%ld&zyLT=YIG zgd}|SMZ|N`>SY!5*6&f);75d=r^KxKwwKs}myrh$C84r6O?dnSr}tUAzSkL`#uG)9 z3bYOzt_#2G*ywfjE4gu%I3bB6xkOBib;9xtY^xZy93i__eas@PVK;~a)c1v{(c4>faln~pw z^#}9H9#$#V{Oi*gDP#-14ayfA+2}JW$&9M?ek}3HDu(J4zrP1ih#;7{4nv+mrhJRO zZuB_pwHU}$zEhWmjfS(=vgx*83u(-H$LC(>2`(2F9zwivjmKw9fTk9(qlb2H5wT9} zZmRT)qJnmk{{-y7cB(_z9v=TDG?o$28K5p2-hm+YQbf0=UQJf{F0%hOLDMn{R+n#2=e6Xh?z}sf`#a9m~_1Zib?~=%1LY?;)2e zSW$}7FBpm7XJUfE{&dDA3jTSDB`d*wLyDKlQ>G-BDhh%XIE@St?ggNnLaJl2Yw6`9 z_~nh-$Om=>$JHq;n~gbohCzoXa$NyTv9b4*TTAdD{ZkQS2L1O`@d*W%FC5lIcDO!a zkoCTse=P6MHr<@NgZ@BQ?U|fkkoIDKu>7%USE5=<86;e9ZJdGPivH+4d&hd*4S2Zl zc3^R2FVe?OYch2d5fIo~etl&U=JqR>H)nxA{i!J2vpgN{W^`O**_3pMy8;2#W_h{R zUvVK^s)bftOt_fE{|)l)%y(q$VXRT9IIJVo`ZhojqPFhTq0O6xeRJd&5E!+^P4_fh zjoW7>{u}ppUK#;~&V!ikk&CG5U)Nxr98z+-ESWGOVdfajaQkzeGKpdPOc-L=ZLP}0 zac6Seg14Ufr9s8CP+J8^oy=p9c>f5H!Xc^{m7xH@`y3L1y0M<vPhI8@001s`1CH-C*lCpP> zhl;?c4yzyyFQVZxg%#>5jLsXMjQflc0#ZpYpO1y#>zoxD_DrlRuSL{qM=bX6JG_t@ zZRffgD$0NV<7wRpDXTPy3bp zkgWKbz^o|DfMr_kSCyyV=yU-iyxEA@`NQjp2*`x3swVGiu&~jG0a~m_rC6Bs-uOar z;ntwI$19Ou1Gn;_P$}VtP)`1!!!UeXB-^nE(NQRKx(MDax_0-_5!B0qwHNJEyYlW% z#pRQ?dA8ySic8k@k;fiDx&*;e+iMS}`Z=}i(~<~>i?K(Dz7E0aJ&L21zmnbDw>d(t z|JjwhK|}U>Nbl_qCGKp+y^*o*LPRW9Kij};^ZWf%J6Ig+7tP`6~cEeFxX}V zPLeFClA&K3%ZOqNmO0Zd^Pi0M#UQ%o*LQf|;Wrif&4S6G@r$(qprJ34!tw_D;c*42 zTFgil`7EgRIudY`Z7ZR`oY}K(=wT%mSrQG4Wx05g<;XzT*+Xd5HnuAV7}dpiA3s*I zCXX>;R>Bg!pQJ&7Caa>AfK~LQ!ngY)Vc6A1b_!PJVyxv) z+ZA)g-V+dU(^|^<4`_Efk{L;b&aoalWp5QUHPc1%ht(2b_|!5Pe+C5xsbKYM-W(8S zG^ocd@tsIWm`jrJK-YSrV1NMQ_G|PcpW&IIUbf6Ohi6p7g|0K=nFmIwyk@`(A3BZMfqjAS)PIo%vN|XbP%J-pI4=p~p^iOns4w|(_i5+k3i8Sbv7%rSl2pRU* zW_cp$0;)boiD)=FWW6Q_+w%YiadAo8A-Rf9&8GrjHhAsE+J z|Ko*WC|iz*$R@2;A(a}A@5xTq%23z7jfU!FM&8-BnNWJdo!Xg=jCRPe0FuJ|rK*3J ziXA=k;{_KEta|8Q!h@Z+IeJgQ2tvu7VR!?x9Ca<@7+dhRIYh-IaaWv)ZRs@ zk(QB@_Vpl%DvX-p9miR#tjM!2NQ3>6CUgc-jP#pH9WGy$-&hLwbjs1W6l4-!N1a?c zWttX@qy-C1Epz&E;LsOomh)+FC|*prI!c!BAB0YqxSocMemz)!Pi$V z>J{O?KNjD)KTp43W+R?^zc}ZAiW?#OHvvSHQpl~bEB4B0Bt#95^P~J}kc68g%aQ>k zyV9pAeC~u7I%q{u^%ryUHDwjqd^DJUHE<8hItmMx8!GG(tPV)eObhdcZ6YgZPG&P; zr_9FpXY1Km2m71=XG?UpJ5n+n3D_rn)hoWc{+8}Oy<3jy?cB=V-u?c^Ocgy^-#=;ER5PHkj`%Ece$ML!TL`#*3 z^h63jvt6&f^Obie{me&b&{S|w;Cjm|rinZjxY%tn9!>ED9J7^0t!pQerW3G};Maif zsqjHcF=Z1xt2gGJX`r)O^TWQYQfRJ@Tu+~}ir&Q4iP(?La?AN{#g3%aIkEEl{4=MR z8Gz(=h{i~3n1VjA|INNElmY zLHSy((L^SBTagPsWLBX9CPXm+CF$42?f4~G7ifH5UL*SpEF1@bGTiEFCB#gZf0KDM%O7LoPb++WbnXmHJhQ^->+j_!m z-8p7Blm*A(Fv)1=O)B~5XyqO@bbXAiQ`eqat8*x5_z<}@)!;T z(gv(LMvW>1RN^&MkzdlO)v1_iFfw)1(EI$H3!31&oplh&>VvkPl{`5Rxnu{Kx8-F+ zV?nGgxbkjwLXE>I<+M7@q=Q>jdfau+-f01E%W!Q*css1YEB1I{)$=3_0_fnky3k4^ za|%y^CnE;x3or0>fW8{x#Ev-nY_Ifv8?~W?p^@lax!8NliIW7x&}gcRGVv*l^kCG- zn-(c18OIKoSsnNu{+pfAO~gjBKULIm3=FP8&c}NZHilrR!Sdusdz!ZUtnSI3Y{t@_ zem0{NZLF9%>kv-0z}sW!uRI=8xey}8AaYA!hn+#EYw&vG#%_;0F_JIfkn zN>%o9169(Rc@_hnA!(hugI@p|lRCO9aUskq@Z@5~$q79dW!~2ha-P3@8$5GFZnhF_jsiK=uXZ zI11T5MopMv@$z-%+XPbRhoFAjqtfV}ORv0U4tHx-P}n#>46{z_-P5SE=Q~9+{gF)a zH*P|a%ck&aaoLc`xIrP1kh7&>^q27b&}W-@jv?O~s&rr3qlJV}UDYs8+6)pL>+vZk zPLX%+Rvf{dR{LiRTVQ1B=_tcUnly&B*r>DgCU=&D z9K%2tW>+_$v3uhk`bZ*}A&)wO~%~>_G!* zaUgPhUH_>fBJQa8*AW~kyabNc;^F4@ire9{oj1#-qr0|NoI)WOkyZi}Y=*HruC4fI zr3EhyLqL1bX}74<%gnYKq(ZBui=T+niJFQG1Pvxv_t05!Ob7`$`Z2I$1r&L_bWP3K znkMPVy-jVGh7#R?w#MVpn`1_ivOX*KzOJO)ZLWf!U*?`&dw8;7jn9(m(OPaX@)>VY z0G1^k6RU;WB3hGEM0zq6nHNv9lF^PG#fz{jF{!=48+h2}x!R0{Q}Qx{zEQ&kTw~(I z5@BuKDUvWVwi7>K5LY*|pg?o)Kw0RO!C2!cYw7(zOplLUfwT zT{Otszl`WnuO}k-dr1ETVmkvEpTiJRDW*We)1wV-cq4;!xf>N$2(mX)f!s^@6&Mq( znPJi>ytJsX!J{oWLT)o4jQuwb?%^v2UH){*C|JU=cN55o5tW9U&t~Vj_CO)7tY$oC ziFP%zjA~)!kZj8IHnmt>KeKBbpOt>_TuDMt7~?dV!a-r<-{ru(4o7tQFoiZ-svMxo zgpF!>67A0Fv92u6`iwfH*MM9b@%`8H>}m}K;7L&P zbB*K!1K0m}#fflj@eDGdNm7y|hLirIr0I zIx}6IR2mIoL^GU22IxE_1ZHp5M1ML1PSwXqdEumbDVFE7vw>kEoSF6u2D4}0O6DVW z`^L*<76jd|Xl(!!6c!jT#>c@OHrx>0?aO}dSLyAnAO5#VM(H#A-&`K;!_Ow~Sz|Vs zn2q172Q+4a{#d(gCIoR9@I}_a>EgppxSx%wp3m&2IgUvF%FpZHl!m!m0^cu=^7xo@ z3j`-3sU0j*1YMD?=|p$1yOJpR&%`o>kl7^t6*v{v@8*}@mk8IQbC_TERh_MqF_(scYwNS8MKm#1R|UFRejlW@c(f%w5|~R=cJ0(`(W2L#gsJCHCMB}3 z@X7&=>dqwCM6t*Se&5tUm2n&&y8?1?nsn-@*)_%WNHxK{Ea*>@*pQCw^;b)u_OTI- zBl9o>vxToklIKy~va!#fu_4Xw4~HV!?@~RU7#}W+3R^n%_?M9J&(w(xA;!bzqargR zx@U?(lmnt?N3f++Ky+go%xWVu?zhb5vT2f!)kv{)gE z#G;IN2Jl9sA<(KlOd<0;#8Z6|#Xh($Y9CL|m+j+m!6J9J%b_bsK(v!8cdkND9%&D~ zg!yXkZAQ7daBgRJE>{{60rnc$KP+Lv(2Qb~=BG$F+{EW9z+MHg^R_$YzZdxHUQcTvuZ^D-8AZ`J3ImAqHr@di468Wytf~u(dJ&04PoO4Wiox{(M zL(zYq$eQua1wv_qP&XNln2{SASoYNvVc8L=tlLw>`f`WnF5rrSqqbrzwJQ3|sRt5qLGDln1Sd?vA*T*I%L(o%8G2!^KlyEpe%_4Vq-xw9u zu9NNXay}4on<<|W^;X&Tx9?qv<trA9t`f;1@8|EULXZ&|; zTt0~0Poi%5_T2BpK)Wzn{b|3ckwoRxCsJbxQ5*B&H#pZeh112BDHjDx+`gebKdAwA zOewUm8KS1)snIDJ*e6eI^uShT`92(Fwhc~Poll2)b@Pw^C}eL`*}KxLpCbb9%!T)G zV+WvyUdbcW2|%$Qf!Esb5IF0-D;u=QV>U$q4t((v zgy|ZXCJhnZaoo_-ndXqcdBRhfUl&fg5=t1AP(a#rn z8`#l2GY!ox^D@BQ>?qyr;X7+X^0a8-7Vmg6yN8Ujm5TV*I?Ax?t}H=tlo~E!?x!!& z9eE$yR_kcHibza;ayjJTQx)U~Ww!l05^DBq4uUEt8?3vvja=D#NrWNEq|ufmGO@FR_a%HQk=h4WaqHW@9vFtGu5DbhcSYW8*s-;>AHfOE9o8LyDt3>4 zaG8#=F>JD6VCG#c$_rQie(OYVW>kSsEXp0FcMLh9J``J5cR@RHK5-j-HL(*Yeow^P z#zGl<@V3*?28E*~=XCt4^}b^O7=$eSiunUNGjDcBeIAa~PGd7R$))Lsk_a7@6|!4V z6lLd?ZfKtZ%3MpAgLg#4(_wfJPHB>WZ7TWt^&v802)&J|nkimQc{P~~JFe@_<=C2W z-`)MX_Yv-y-y8mD>V4{Hzgu8dY4pQMR21uQuQ3V}UVkVD8oXy~D3`a6+c`(4M~-f2 z!!zdMSX=qsB*WB4(h%$_ z;y)!4RqLQoM@5odjQO9>42V^$nv&#K*rnB%E)j}gr8C6B?CA+=$67D@z5)9av90*E z9G=;)-my+u%sdfKL=R$WU706h$OGX*zwp|@;lIvd9wJOROtRH$`gd*74kZi$T}P$vGnlMLt>&l+cbW^ z+^wY6fc{=Tm{KE`+eLK`sXr4=Oc!51>H{Q*npa$^&uN^^oD7{b!fvEVM#M|@P=A%` zWf#L$hDuciEwIg56>A=f3EEgUq}wj5nX%7p*(qVSQYYdw*N1y@{3{Hb}RfJZx9 zIYp~g`L(!M7wuWDC$TOnz)BUJ=bAvH$>d^p#Nd%mF+k5%Q}KMU^5??x&x&g(JiLxO zrVIEw4x3SdCKRw zeTs6u~{BR$f z_a zr{iLV2})yN{C*R1LNJ+h6ZYcWJ=PYM26N%lHuG63Q(G_!8AxmhnKFI|JzMBTxF=5@ z=l+^BC#YXv0R6Y~-*MGU_UnNZNE}bBZr{xrl9w+555C=}s03p?m?+A9)D}YyB}Zr> zgxMX14KYmN`92vWN(TMRz&amHV96&%gur5Q)AjYiay#Z+TBnkMPvWzRT375=waL_WQ zc@AZ%uOVx{HbmL(j>EGd`0N7&k0BV3Z#~Z1eQ@h6=QFOTh-lIknB%%4)BvBJgG#I@ zSgbu$zke9v)TRoGJF!DzPmTw3nt^6V6;LKh3RXonGP0KDIKrlgyN<_D>1m5BIe?Pd zwxv*-z^IdqUhYQ2^HSaiBmO&by;$4FAsk?slY;jqU5r>y~7j?R@uCX z1fbur1{m3$Q3U7+KO2rhsBF^eRi?Dd6c`=T)1Zm_5>KD&zwohPNf&pwMhiZTFM}`i zP7Tf<)4T-S*x&`sd@3wqtR^E$vkA_A1K5|)=~ltU0wxm+I-N_iyvvuU9HQ(Lz$8R= z`LPgR7m|&t7yz0$j)gl)nZrOM0^SFw+1`A}AO0>$u<>{791gX8M97>3qXv0YFJ7#? z9Nwwa+rq>5|Bye2b<^HM{1_sM5P*QB{{Q9A`lcTG|B1)?FAC^k^&9&GF{G~8Jln7?hD7v^wN-c~dF~n2iN;Q?_qf`=(eiu z;}ufHP4rP8bi=~Uk+eS4dsVB$!l}E8N{5ysQ2+*Ji3%?Jvb&RQ*r3eFqa018qDVGw zUE(qt2;-4h%wb-6Rxd_5Jr&IYi1ZmiHSh?Q?X2f}5C#v$1;=KY)2l6s!`gzWJlK2* zcRaU)VE|~h|8Ph`CeO`}J3+(6cE!$jZ>rlz0=6*Dy! z4+49%MJse<55f}}ga)bAgdzTrg`jI(N~wwk(Me}ib-3+_8wn(RpSj^;%|(cTMBM_|DAJ#k)F7myKj zcZ`(cujK7PIden+ce>(W#F{z5iVQG^M|AhW@rE60;lsKt=ANx&J#wJPp@)!UwIwxR z1bASnn3Bi{5?(Fb&PD75NQ`3-q!5lrDbWVlZ=iqQpQP@^UC2SagVZmSI+#0He~B~S zuWgSZPSq5bql+x$w5tg$YBD|v3*zOH3U4+arZ|M|0risAgkUOi)a$$ebVly%d5|68 zt{l#k0)B#iVcg6MTuq2B!w0$e){&6Owt+!IlnteMgfRp2s`lLG`a%y{u`d}VV_i*S zkd1F@mjx3qHHm7{xyhi-(+tT9HOVY~V!IM}(fXU4L_Gv+2yyn!@)=F=Xd9xv^8`3F z_THQ@q)780Nsz%BEy;XqfDkB2XEjExM~%!tTNg0Q2|EnIXW zNWVAUSSlQ-GB309=>+gx=u#-D?VD_{|{^L)FcYDby=ou+qN@L+Qv!S zwr$(CZQHhOpR}#Yj*gD#d+V*fdfq=^#a?U9G34~XXi1RtS#s6(w-8lW(jTZz{uxoB zAj8b#{X^c+(cu2Ke-4ey8)h5?hcJ|`Vldmjif=%;A>G1~XIsC#S!LpQuISYqOc_(> zc<_-oni?plU3_{PYENvfxte0M^&Oco+t%PVCfBsw6xH|yS8BU>a8VdnuVG@|4-P_^ zJ*2rTC~7J*0Ys_)>`0N8mrmHU*~KfS>50^l`q3k6Qpmj`D-l%4~Jfe(FhVh3CrK zP!##KYB?ek;Ss|9#hqu<8cW|*0dB{;aQRH{_bknEm5BNjGD!G|(agO&+{0Xh(Xm=8 zmpiAZX_+~v5TPp)inE3O1RKziZFmA3@~1y)&|Rt~)r3cMFx}lphuq^x<8WtE+50`Y zgDMu?GTG%UtAhjaB9*gd#<4UISk*G|D6p(<>l)26OQiIvZ(#-bR4w`t;f|!T%}We^ zjFF@)G^)aFFgTCKo*Z(Rz#qiw)!NCj>{9ex_CfY^ zx5Q5mU821ybOP>g`li!|c&A}6xRTiqJR=I<%Hghaw^HpP6cXJRY2O`k2w1F=E4cZd ziS7;fN$02!1HkUKNQ|OliyB3Ge>A9_sp(2#iMyDk=@c#QY&_r+Frj9P)w~+1ITNta z0>`}#YN~cuE%g2H4SK9sdVKK5eZ-%-z1hrm8(Oc^8=KD`qglSznYh;bHQx3-$`0j} zmsdi%n*@RG_1(Kk??u~}Afp`RC)|wX^Dm`M?7_&EZP##Ln>2{n8wUiTzA~kERsLHHZ-`>*{83MxjDGPS^ z810vbEYAy-yR*^<4b{`iF7DK0;H#Wz(d2BoY&jOC&Qq%1U5xkB;o;tQ7Wwm@xTEAV z0EJeHF-cZsg~@XP6JSfUF`Ctq3DxFtWeJIN`D)T*Qgdb1@+NACRHfM_m1UKeGe&l7 zh2*bV3t)21KFB5s>G)1W!S_GaT%RR?TTnIQ`u68IzY z&FBjMVhc6d5rSSs_IBNf84D`8AV6WihPC%(YKS|YONkMKj%LKvvc>#eo1;Dnf>N2; zgRat1+aI`)cG3JHgzkawO(M&|U2pN*9>$RMbGzQ`I&j<{By#rxPJBS{6>U#M{ziTF zzBH$j+HUo=b4aL?!MxU zxl#I~*-`dySe}HWHkeSdCdQ(*uyJJjFi~!Ont!DgIqb2*2sG&Nr?Z|E&$Md-IdoBC zDJH%%e%7-Pd~JrKQ^D0jxi+<+E5IfzOeajJglX8KqZVNhM3~Ef)YHR8=Q2ZH6l&Lv zxtjDSJW12g>iv!R^H5_svOUUT#6dcnY$+Z4&QhOw zi+{MdI{RBRPS^5W23kJY6EGOdE2z>l4$@s9*@{Q5y~e1O?;-L-K@JU+#d-W3h2ouaahRakzHt zv>rTKU%n3Dsk2UuzmA+Zg?!l#6|{4Naixp&X$~Yxn)kiX!`Gd%J)skyc!8Hp{obsi zvwlyz1y)Grd|=!Wod_;W?PRKlFf0eNHC_X4{fxni)U3`5k3BA7_pDc|XQh)W13(A) zN*Oi88h5JiB3zHqxSx+6qaMOGhFzMdq&lu|RC9fV@BVdh-285~b5l4Ry-RjBuzv*cA) ze#dIi#ltJd3itlR2z_J<^kSF~HsnA0ZF{@Tuw z%pL5HcmW1AW@q~q@^Yw=JL~g3bLieE)NJv<4c?P(8g<)n+B{hmyWE`P?jqP>npJjz z_nhKsnjwWVMBu(pdtfbbWhH6b)Vgw-;@49hIwznzlV8dqgOZNEmG%~(zHlL`OcGOqar%RM3xBO_9 zZTfS}!FWcNB3Hh(-g#f?RZYkC_5Em`aTr+ERy5Mq@WU~F_j~Li`9jR3k}%F9JUT(R z33!U-dfaTerM)=pioO*!?3NWpJ2FS*z@59dvg7o+w}Mo88C?E9t*^x zg7c6}8gu1M8q@k(k2wlA$eV7!JjUSh1N@(}6Cv~Vya*HkAPE)#K;-|%?EKHZzlwhB z0o(6ytu{@e+*t0ZZ-YKarMFS2N}qX&$AvX3q`PlWPOwunVe%3s{r zyh%$%v;ydWD7XTJ0GdL%7+K#mr6KGIPet;y7?5TTTyC?Sg`k)|UQ&1)+Qk&>qZZW1mDdZcX5 zK#5FjI1rO+Atoim15x@{lx(2iSY0qgFUTIJU0lvge~2W~n9k{CH(al;umdMduf;t0 zNT&^<4?6p2I5;kYMlo5bokH4ct;uo=KA0Noehq^5u*!?JYnwrf#P1L%CgCBdX$M4S zsGUGVOeUyHcl8oaTyZ5Gl{IUDG-PK`;qQ+g5|nWKK~q{g{wq8l zG)3s4Q~qpR`DQKylxZXGy&o)*%#L`= zL1HL0I9j`{+|aF*I8Q|AfH#_h9@k*cZ$DJQ5;_lf>uT>NcQHI z`C?q=cFlb1)#chYC@+w!+ibY6VeA*eeTlc#8x#XsAgE|k zh|_R|z2gvZR-koMXmeAk77ACnvH+A2M<)iTar(YNK@(c|_%p`7m^z7iFw&<0)e;Kg zX)m5k%PPvhjc*tBtHNLf@~1~l^*kk1`;fpWD-C6dDUa@jqHdi4D7#Gy_2Kmql5*IG zUTX)$`z;lZN=a%J75>}Ej>J*9=I;bx9T^IWv6vyWWTW=c%Lz&1ztvpR*(~%$^~MBH z=?oN=VJUgU+xk-VL}@s-=`*Ob5CuBB1-JYjTAx+~veKxBGMdXoxb+M~*(mE3n+2gW zX+(7fuK1Q%e;BIny?lc)y=|IZBuf~C3`~-SFW{)C8zk83eSoR62&e(t1K`lO##?bS zobtMbBjli!X;kW`sAxA-Z|{h=mQDbaL|$(JM}+klGujSk%14*0n}?*D7C@upr&@{j zpK`3w4it%6o*Ovv&z24k#HkeDf!vrnQJ9Cbw`j^pe^~*h=u5vZe8K~jcK+E9kJ|lk zvZ*7Q<1m?bUSS*83QCW=Dkt0))~=N2Des>8x6UWr_mx-0|6bpNjk#mBHnk%(GC15d zFru-V#Oo8;Pl3IT9n5JO=g;3dWgp5%TZwUTHoMmHQA$)4&e^-!rWXsJ2I1440k5mI zzXrtUjY}K${dj!gmb{Ps7$jb13uG9F$;~-$;-J8OVEF0xOPO{o_ODkWBm>oIkxNrL z*&pjF6>XwCd1BtRc2$b9vU4pwE!{jRNT>VZ@%O*X+czGVbRzMpX#Ki9ZzDV-Up6#7 z5BeNSt@dNBL^4s}NP}GIMZ5?fDi(zIVqJaL3)r98lb-&Ihbj^~^jU-m0N|kZKbQw5 z=2pgb{~yHQ|LAUa6D)bCK0AwOy?|Bu&(i2XMFn9FF8!rprzK*mf_=l$!dAAY_OwVxi!iJRWd z{)^lIyywt>JS3Zg6bsg1{`Qof6c7_KCEUnm?{C9K9R$A!ns`)G_2?e7%J4fsrw>9q z+m%4`WEl8RoM=wtP0|ohOp9qdH5S!V0Kj0D4w3*sbtB-uf_fZ3)r>#`K`}-#@>(Y9 z6EQWT2L2@?zl^wwim=e?y;_Nz4MUkQkUPvDJLL2G9r3MJ6_nwLKZs-5%l6o9h{$7J z0(20Vbw0$gC|}_GAVKeNNeWJ=2*#+wNf1|l*qj8!ZiMQBpbPu&di_iu0;l0Tk#(%i z^R;=ok#Oh*Vs8Vj7?Fs2t`DN@VT|2OH_Pdwdk@=I?~S|*qDS}0N)|>O-5)HAwYJg@ z%($^l=>kjR5R&94(!E)ki|PJGoE3oCTwSu+UPK%8uFTU6V@{%vo1OJ=kAD5q*=fIV z-Y{Owm{VeJhizj1Ku5wWK;LzOk^Wh z*6h17QrGjTrO=0ZPGZ-G_3foOhy(1i5xc7M)(vq$Oh5X0pA|APMw_L(HVE`H=^OG5 z7{;Uh1Swb&W%^O9hC?&4cWLYl2!y6TTmgD4KLyiV4@PyNk5QZr z0aDEJ)^k?9%j*?540DcL^HvJ3vY|9xtP-0UnP@G!QsNpHq0Fx;c-BK;OgY$^w)T8` zebI_?hi86J6mZ(ThvTiecBrTD@@bO?F2!8gnZA>kJi<7o;2q+ci!%^L=-v5}Mmce; zr~c}B;um(Tq}jjST9#B5g8)~s(_YMakP}CJOkG9=+ObcT)=W!v{V0&z7a=ZSBa5(B zdB3SV#6Fjq`oejBHk+Et0-SciVdid;N1_T^R9NQJiT? zjo2z02@r%gd;_ep#HHRpecJFmT;e!uj6xz*TJ|1VBxHDt)zGa2%^Yz1Zxw?)ggoJ0 zw|mpfQD1qk0TMkv&2L4td7>Xm)Ro&8&(+rM-)=tWeb7Re6bIETw|X>CQ5+kpc_4D# zXDhn6Uee##`5Rf;1u|UOvRs67=#FriJa0K33D<8vG1viQ)Z2P}YWE48 zE9BgYwX~XPsA35}M-xaG!2>^5Vu4_7=nN2TEy#aQaz&5U--$vx<7(_KaZ7Xxvj8&N z+MtO+-3Z%+UeNhsV9 z8WEq&glqf4w$TMHeaAhS2ySNTvj;85`FxR$>LEI;1@V8pINmy-$B4B2H>mlA?O_p; zj^P+da+1ThK@K7DLl0tULhR28Ajn-1ZULF_&+ zz<7`pl9T@f+P1`kW!HyzfFX!r+yTa0%P<}W>YkIR2m~PGVqm>TD;tS5f7AP$w|0C# zhyiUleISX8t--!4KcC*BA!dt1&Y}fA<&6syGP|by`Y+pJhvwIQ-cOkvRHvJz-33ho z-Ng)R$e>~v@cHej!p2JXmmi0auhVkGyNvlC#jk-={a}`UhG-@P8k}5!faJCzx4%&* zE66@J3r@B@sshk3ubsivv0C%$V_S?VJ$BSxCZN*%hl09{eE$RZ5Bh7+xFQg1H|oe2 zn>>`9z<{9(Iq|h@Jr8t@Q3$pNYEah!9c+mjLd+jVz1GD))NMnnv_`dh-;qw_{`BOu zTeOAN$ziK(N*QcT@3GODyxiQp+)Dd*$LfS7+c`Wr}s;jvsKom;|*1hlnbWM+>CNok76^nB7wKAP&L0topK zU?4H4T0&cUz6!}JW7-j<4k$QiB;`Jad=TZ~y-sY97R9NQIB8Def0ps+Ts5&TYd!x2 z5oZ9HbbJsi@Sx!!CnJ>L*+`cno?8*Q6=FdmA#_sN+UNM@IGO3dZp5?kp1{fjKWK&hO4;7E0Yf6cVbVKEB_v1xLEP7<4r zN9SfqjU)Hr{v8TT31V%@eOzW8ObI8T&YwDDfmUpQmeMa1BuNG-*$Y5bj^+l{7-&t+ z$J?Iy-Y%jT+jSewTYnp9Mx2uNvSAP*lO=3p{4u1!1St_jQ-BJc7$BQ0Sz#$cpWY{# zl!~o0JnBJuKMsSYEJG(XLMx`;eyJHW6D!O`B1Ueqr+c4ontAIP-B6t`KC+@^53E;l zgONF^0$~Y0Z_5JFDle&n%(Z_Akw!Oraaen7)U2|#vKSnt5SR`mjqKpb79q?vT;FUz z#WuBVZJ6I1x;P28jt2Ny9e0U6s2Q>W9PkQ|#Pw^@OWP8K2K@&QTiAj)MJuGM=$?26 zjDEiIu7wu#wCf!9p<(7Wg#!z!4>!2v z-2v7In1E1(dMz#o!5XgzN%0>}5rGYlV}XbYm<`&I=XY-VID?qNWa5*pFXX?}PVFDn zpy-;%!zNGAE^r0vX>6e_)>0O!P#@M#6zdW@1(LTP(%A>SJWiY~YE9a?_hFTrmu7f{ zrpdzgPPT_uj#w6z1YJN(FT>eR=U$3eIAyRg)I0~{GjxkYSIfqTm0Y>|r%W$NyX{lC zMMyq}6n`QSSG~X6+mwCx4}P8reN*F-GP-}Fb;TQqR(00)jQNPlb2}o*vF^aOneT!B zD9ep=`FNLYec^QG!pT;$qIaF_3n)CP%0GRxusfj8|DbH-Qj&g+!G%ethB6c!cU#!f zqrNmd9y_aK(%lU9`C{cqjY~2#>pGyr+*~kTKs$q^fD+7}JqL1Fb^=KuMTU85c&&1` z7m3H`2}X@U5!ajgykAi2G&T2t)Btm}pZ-cYM_+qg zZ-S_ScdiF~&#pMiZ-L-*xYqC7EvUh@@FU2_d&`n@BR zL0|gu-*_sU0=JNbS4ZPCa);z+OVDg{>E;@suW@RGgbdz- z4q!;R1deSf+t!P7Qg!U4CLelQpH?(wq*3~o2jZX-x9hk`eD{;3cJrkIV1GR70a)W{ zU0rC`%N?!B{#yK9Z8=qaFycwjjMHjUTEY!4WBuS^M&~t^09Opt{LK0uw0v)`cSZ`L zo^<@7-^uITc8l+Prl7&VXl6%r&c$ z!hW$4yo)`pOE&DhfH)%s7CksEk5j!1CiX#5dV4)04{?m+7tgJlyQ46)S7aY*N9Tn& zmSgHva#v_O!=Hm}gTIvvPvz#;(@FgZ`q1F{+MY!&f-K)<8f>226f24WY?_>VL$*q0 zd>J2gtzTrFu7(zKG8f1Sw>VGhC%HXrSjb5ymPEId;*OD^e%)eJUBBA1wGUCM8C9-^y3foogw<#eX(s2YUlzwo8qVrpMd(BiT_^wI~Y4s~Dz*y~)2?QB@Sq6pbV( zTZdNMbcJ?>n};ghCj!4ux^ODOOF=JD{ay~Pa|iegnCL4fNV#*a`}8jB^PR=*qHD_=!6OMq}{GMXknRLSNgYigQ#oI^m6SFSOCvC~kTO&6T2-VEQ*Aqx&=~%ne>NOfA9V zf-c(4PPET=%h#5I{JsaG$?0B;BxhF|h2;L@!Yv7}TQpmE1t;;Lknztf<9_fR^;Ckv zJv`(ho5)gUMpkO(Q0%!0HH)vr#aoK591Kt$S3DHeh`pW8*OO=yfOI%dY(e!^J% zkzTg|rZ5Ix?eQyIH7{bwKf}6PfD^$gEys7GmC|wfwQSmAUY!u7Jn}eb?bvA$QvsI< zBb)McJ(S-sBgV5VCGn>bWjGEI9^9z2?ZGg?P{C%kD;Bt^4FbHDXtV@Ko~8KJD_<54 z{~lB~am`(?8DKlmJyB zrDx`j_vg5!v~spEWy#|ZP`5PDnUee(hh^YpN&e7q8>O%c)awNOQEi^4 z`71-uzyhYL0-h3+#Tz5V4Ls~?ws^Jcomj?=mPJn_*>k6vX`ctG&gIHJn$E`&F@~_n zWnLQK4-;)e(148i_#yUGZ=qY;3C7TBYS*4?v7e%_!LII6*ymb>5}{2xo`hnknF@R} zopyxJl_!gg!uD3BUAj%9Mf}yF@&!FLe7$(81qEbP9MRnSf%CC5S36L#7c>hp?`m=T zBjn;h39zn62sRf_$t;n*w)PeMY6I{A(LUkS5P{gCYR_>PGv()T$ELpJs!!#X3u>`( z3=l$raTBQn#0xD*fDMQ$}vlTaLXsP)eVv1T4Lo4X1v-5lPSgd#j^1mSCL+R5Yz?sE z&4K4wntNFY^@!G;pgDC~EkZyTY3`Grb(att1ME_63bL2|cUt-uj?SGH`F4WyP z1c5UPN$pQ%t8mA<8%rV{uQw_w`_>j>C2`t zT4d|=Q01okcTlI9POSXtAgjZ8-bzV;rw)(eNDy0d|!!KKUa`_cvf7x+oI(_ zg&nxQRw$aWGZ${Qh6)K%GmaO3I+jqOU7OBr*q1C8u!eS@6$u)Z-+JNRX+7rzd`;2I z8(YnOILvkjEjEvDI`dV%zF#`%I_blk=kHoqZ*9aVU;g#32+B2Fs9s;5y?iJC$o1mX zDIoeL?v4NVeIUfu>Dd?+0AN`0e?YYS-3K`tJJ34Ym^=Nq?(j;>TJcak;rm)weiIkD z!Mv~}J@cy%r(VA<4;7Hja(#}*4o)9kZL{HM9-5`Q{^yISv7%@p(s=N3YfA(N5w@j* zidr{kVrqiw>7&<6`taXjH@eqRKeA>wNhE_=w{5rS=>9qBJsvvb=I-W4aCXRk;cPnY zl=RAjH`_o-TD03#AvrI*`Bd01p)S1ZgXM0(uf0F3n9)?H?|>oNBrB&+%jR(aZ@>)G zb-gi_Mh#yMW>nhj7dN8H`l?K(8x zIt|PT9$bVy0@A@aV0|zj7wL%s8ZSkS$$nPjFWr*nARKy&NdJY`Yk;gAlmIy>oc&PS z?8)E+n3g1e7Hdk1ray>z_bG*&X|(}x(Hu+O$}jH$MQxJ9{|=MBHxikEgfuI((P=zz zNO|NP!UZCq)If@TKmPRHzQ&#jg=N4^+fS7V2JH}?p zqVe-l8FT_xu`fPS%s?r2$h11}B=({(Fm~*Gl7Tbq^#?U)5Ac6PV$N*L8L_sxc_j zV5L8+AfS`{dOWDtbIc4)R+RA7Ch>(^6w`5TjDUaNfjas>4)m3JSbPC;H1Q>DZC6s| z(f1FK4guneml@Ae0zJ<{lRoaz#CYeJs6fuF@p$Hz(Zu>;+0a2=^R0T()aUx+&xx53 zI7;gSwK2(F_Urj0eh?=x+`WhSp?V3=XFaQE(ZtAl9vr8>HPt-ay+-iBkD`-(08p|i zwZVB-BvI`++>XohM$lQYGW7*Dc;$V+lbBHt_B2G4aE0TB27hM{lU$8JL+H&=@zV*H zD!8<1m%2b1MPL-Y6-daK6QG&7zvLnauH#ixy!zeW#nDrf*8m`+DRqR)xV|Y7?3&fC zH#;&w@Ho`qsX*7_)w_&7=vR~6FO@T1DUjCx?IxkbFXwTmmYx`ALDu z_(dZ|@P&r)eMm<`uc0+h7odusJSD%YOuj-2Y6zqkJd66_-f0fA^%8#-lwd>!t#*4h zxz7Y|l#&8n1iH^Qk#rFRa=L%xMYhnqA5dQ05a>Pk+d)8tK+xe#JzD-(=Lm?zNhZ*< zxxlz}Yf+<&u`(ky91=h%4CUhhAl-L}^Mepz5n|AYWc-fm&xL-%5HX9M5?G@`IDlX| z=-klGn9h25T?icV@Df4wlX-8uAP0U&>$%ZqbgUd9&eU1!U5ci8Z`hL>)sQAFb-q#GP$( zYRM2J#p;4nGLi%?p${!(eO$bM>W599w28DQFrAb1!+3QR$+Qudg5hz7D512GiOI+l zI|>ez7K(v`&I;jygI)P;)j~7_Fz*rwS<}FPt%=}8*2oXqd`v+5?A#D60k~R@Lc3WE z8pIaBsp2ACep*w-zP8+DyT*8gY(wZ5waTPlKsO+=5t zJn@OJZZol96altl>gE$u?jEhlaSUl*Gv6IDRSsP7q+DvY2CdZkgay3MdKguY~c+kN^E1GaQxPVi-}Jkhj*`@ zgVW8fj!@0+XxQvt@+dPY%G?SEFl-*<8Kca%>bt$Ob?wvEZP@w%AMnr%X>qlA3V#)Q zTlvr`ON_l~U*~e~2F?J~YkM=5t=Y(F$@2(+^e;BzBmVC&lTu4X0EDI6Khazs3_x)v zO;a|y86ccxI-pT=jHbXpDLMRt##Y`F9NPM~eFuS=G${Ak;J%!EjhBQrye_VV~P`Ng;#2onwe* z2etJ0FHtr^7o{O97bEqn!S%kjS*;rzEYBVGR=hXbmC89HYv zqjLv0MkB)O!ytY{kWW{-8!5K*;wQVCC&s(4obTMCqln^0z2P?kC=j|!v(gZ zbVVjYdl0=f^KuqrfH;`SP5Ky2i@_$|2;qlXfRR*=j~sla*2~FR9PmTNPydA)sWQST zzTc}+E>XaG^m`2@vOt9#?QPgRVn~rv&gZFSnKD+e1R@d@#8W7u`4(Xm6we=1*+z<@ zEDBb2wqH0I5A^PX3;$8_44UGyR8Zed7|WLbwg(e9xeB{?sM5}gN=&e?_ZEHfyPjf z{44FTGjfM}4$hCHP5nyUAdo#ZN+GR!C1+6PAd-A`{+pSgPOLW}T9)Kw+Fp(Te{h-E z0yjwmLw-{xA2r~@UI69ES1vVEZtkf zFGf~Vl{5v^yM1_A>z_A0_N9|oMi)`^p>TInFJYJ1h>xgn1J9;kfM zz-b8MzR$ycsu1LG&$j%c)$p3nDZLkfSS(V_0~3R;W86aQ9w&m6{c6@OD?{Lw_WFUe z27;gvjdy`nn~2G}@)@F((WhYfLD8x%7lSptoJ-kb9?avL)1#*#RSKruN)Wu$#p~>S zM@tgUAe_aog<*dXKWBF7-^BzzivKRHtX(cLIzl2sZq z2+;V(R7rA%B50+zND`7bFt?`85qeDW|Fj)anYgsV)S^T5nUqTlY|1%l!rcMm6-Pm^ zi}WuYU#D{C)Cvlq8HXOchcS}n=5UGK!r$&C&<@}$ad}T5tY?o*5JBd|kP5w4l5|z* z_tq1ELEpBGKi%9uSAW(%)b~4jFktv85PqOdQlQG;MoQJDXqk$Tn0cJ5X9v01JzcRS z5|uiD=|S;nlc@!3%fRIkmzMI9z^?0{rX-z`%0Rl4opi^PjzRxT+X8bFO}R(Dd8IB|AIbFmsdA~=IW!grKX8gF}sI`J#t zbewOgT-P>TYODcWiBw5whG#9j3=37vv7**5S62YZb25=w$dwVsTIwik0Z_lrn{vO5 zax0NK5M`OZm5ZPBSGLtHBED5~Cv=21^Ma4=PZMCtM=LK{yM$Zh1YqYCl&PIO3kjra zlZo8;H=y1-LF3iwq#XLg1DDnN_#eg_&Qr@2i>1Kj=EDPozkO z6ja5#EROF2P8cjg8)Xu{Nrx)oV_^CAP5bD@J+WwTh)?xw`mhTW+u5P+n32_4pZjvu z2}QW>(Wk$1PTy#Y#IOAa3CDt=%Jj(NT~TG&BQRG%Q4h8(=v96h6ahy)`>cz&n;Gc* zNA2k-c%x_P?C0NS8xGbZ#Y0OQ(J)FI9qRG=apl1@yu(NB^BUg@>Vk6YI8Ki?1$ToTXR^%9V?* zvt*7jcRlAw9(CeWcK-su>QQf!Rj)g|w(GlsWcCHT*#!8r$<(%4i<#wh^~qkr;`~*W zQh3wHXTQwXQ5gLeIenC5#5A?ZO9SvgE|KCLoS1v8bPBE2ibzRiZk03E>ln9pS2}Sr z^oiG)DtiNU)j}2QB`Q&*-jibbrZxC=uQNeP5)|?J^=5k+!iT+8x$;%p; zMUG)9G~ip^<|rsO#HSZ}rGG^i7|}Rrvh{>%|8`qVUul&hOehszi$lUnf+PUeg-|+s z<`lYf<60+J3K^xxb=fqnN7pR6`NbS3YedwC>pD<>9#obp-sv0tM}LAz^gJa|<1Nh2 z+(>BgyUQL@rrV}~o}Tx%DE%U?_3E(P7+jV<#C#kJJt7Mn0t>u64{W{!zjN#pWbPxL zvZ8mCFcbLN3Gi72Bwt*wS2PTysI6G~VoEwQ&#zL>MUpvFlJM>uVR$?r?0pfz(t_yS zDDPC)oslD9TT^uo9oV%4Ha;B}`GxiyWrx?xvRCc3aMT)wSJfV;ACg5)EY{rws`C|n zBxGDH+R8+ET6!Ww_+Tx3E74ZY^sqm>V&1Ij7LNrhNL`QL9xy?$xc=g~TelEIsLeX~ zZM<|1@Z7W!X)N&*IwC&Fypgt9B>EuM0Q^Rxo;WFWBP@FmR`dE=DQux@I~FTp%|-0b zz0Q)?ZXO3c&~>Mj(CJLdozB2t9}-MTdQzp;9eeM@(hXrzF()nu!D3jWP9wlP?nZw1kW2GL|J`tXn511dd_Vvyfl#eYfW zYmP~LW!!vW75^-a zLg4O;|M8UbQBmrtq8rMCUS^!;B&B*pf)#!Zew&?xu5e8``$g|p+=yIR>pnA3HDV-Z zmMya3ZIqS2vByp@9NV8`)Sk4sO+)vAE8l(70_5AAHCosDU4$wJybN4@Bv5FE5sC_k z*@qXE%(AWV_aOFxM6?2sa-I96_D;UZYUO@3GB*75f|J}UuMb9>t;?=Z6}8~FDY`c{ z!$sT-qY~vabsY}?cd?Py=k+E`20D!s0|~k`0*n|t4J=bdHGTm5b4zJwIH$4Oz%}M} ze)a~a(dRHiHb6ru^gpmn=p?Ij?LVb#_LUXe0k*486?+MG-EU3^BJLOx7-@+~Y!l|E zk=hhRvNs-p{Gs|$m8~~Nsa^ZLP2RnIHy@`3@Kx1+WEE91xk*RM@;`y=BG``=ti0#b zpU@qdsWn8K$%#N$oVYQ`U#Y|u*AIPcEN9x@1g8}L}yTwp$DN!D$r+TH77>=)EeZ9Whxz2P~BD3*`@@Is7u8_ z*#haSA_Y?u3Z@Nie$F~pQqa#G8~i$HyYAYE6KuL?&9Wr=Y6Q@rFBNO&6$;dC^!M31 z`$Em}sNa9X5=-86OkLxS)+HB964)?Fl(k!y{_U>2f=G?6f}2S6DAZL?LM2v^Fp*ic zPq`XdTnKQe>zoOzo2`%*L5N~(kFB3`X<#r)6z^0RJQ@;V)G4L{BTl&}6Soti192?8 z>1sigPdg-&KdBfebF*CGe8d+P`&CydBHm%F-rEgIcEMxxa z-prVJ=9JfsQdsTWrk3i1RAyp#&87Ji30DZc_h7c zY%Jb3C4wGzOPbZ#<(BwUn-w&ev`jQi`?ZKU((%78{u_bA+;c>DU)|D&i?W>`(>nlf zCCr^BPWz}C6a;KJ-K#(k_QDbKp@1l{h2Gj?XWQ%qeP)D6N7xJPs|89W#sh<}razEY z>+253=Gw|s_rutGL-cR^j1c>W`IZ9t~suFVxh00*qgkoSp0M^-ako5m~%hk?Gv`ap!>xalmnNQ(0_Vn}#ACxbo$lfGe? zD$kKvJt)K$PEkEt3WamKHYKkduLK)yYYMX_R7ppXHFJWn&Lgqx zB80F$jjVputKX10bvBJ%|7Z_+4i?=iZ2B+&rwuX&*5k{ZgidLH}ws= z*?uzA`!wo~(1nYy*fZW${av<7T*R?R(FP>~hI($7MeJdV<{Y6Qk2e!11K#QGvf{j(x~Y5n9A^4+1LppiS87v=Ye~n4J=|D4(D{B;1tdfS&2^P`4 zJWg7U79YPS4ph&=(Ul?S6NLR-kH*O0tP=S~ zIqk+NUyC)=)2HkbB@%|IK&@g|lW)p{6oZ>}7t<4cX}Pa^!n<$Y%DPqV$xeM#ZgW-< zv%4~#qdKRg3buy%ey5boV=FAnj(*uObm;oLSAQuqA~>KVnj_eGV-1*XDB7c#>DNBt z1gy?I)Zk&OMg@uaFz@JvhDtO-lG8@(ec}MJTG^;AXE=EEp@_I!;$r$lrd&!h9YWRC z7*H>dFaO(tbCO)lb^~T+3(cqjpN4G3Ln5p%+DTD7daZ>KaI2N*;hWkddE+y)Jk~NK zNyHv>hhw0Ewb#x?)q7>7VEBgYN{A_%&MT{w0vHF?KIqB#6Nyt>m?B|{Y%SHCNIYY!6|rEsYLV{8`gnECt+N?G(UE4Eu5PjJ4%-Wqf0t_ufIDy)8;dK zyQr1#uGz+S!$1A6avr;<!v>=P5n9&-vP#*~)9SZD0VGOgTLpod7pOte1ekeFAIgf`wMi6`AP>Kq zVc4x26hQ)qkB|y_#(+Hk_SNL#0m^0=QZkv4+hZ~ex`l8_NI)lvXd_4@m!S_!{vr(Y zWcNuKNX27l2Fw&n|CO%({VCEj4f+%$k5kq58RhT2gl|JxV381{j~P}$ox=~sOVFx` zz;M!w`k8UJ1OqUHK#{h-$8(lkla;s_2>n)UgEFe}*d{7N6e^(bNBWBonRmM(YOG_K zxof#!5}6N~U3`EEO%+|85C1$&`e}DWV!n8p(3`4hgXK8(z-i5bPn2H`J}-q`9>X5~ zXt-~^q+c+eS~S}MfP2mAfWf`cp3sy=K2535(1JmFcgpAtNi__>r_W)Mrgd-jf|iZ~s)d0{C^Q%fl!gu|erIld$0aJd7J zW1_5XMk?gJzh_yO2#lCNCUS`T_u110+)FHDb>;W+26b~k{E@4GXHIIkn4>GV`jxD zG7l3247CbT_nfVfN*xH9sFsF(kTpxHrrPzMFB66OSI^BrcFQ+M{<3#hh2!UDW##15 zJb++V_N6pbpFYL(1oKg+hhmiDmOybirAII}$;l>IkwZ_5Z*fa4b2m#*BfCU35nEN~ zP61zo6FO*C2O@}w(AURW&9&{2mH!R&u5OI$iB|!AVU@yOZiMPIWcXvlU=Ab8&~9eH z3q70ndI5Q5d+Zlvaog|pdsbJ5Zjnz&aYJk|y1~Y5nfS+sYM(2O0_xJr8$Kestw9gY z2e&~~TxjJgEZcdJ13`b$Cv4OFK!Gd+*f`tUqQup*{J%(hhv?9vFkLXVZRf_eZQHhO zCpWfj+qP}n=8c_~daHYNSM}>j)npIP=&b$k|KmYL+#2muVrC>(L2e8hshEWYsYg-{ za5iuT95bi$wUT4jZ!Ta+mXGbm=UxEBlgS@TTcmtVf@IpPb45%WyKZiTpj5_XQEr!d zVn^rA0L5fAvXLNf&tvy>swW&fKUgXmy|bqnl&F*SfUd;LMTO?FwDHj{^z&A_Wu~v6 zY8Kr@zR}8j7WX8-nAIP@F5S$0wUJuCu4gNCi<{WhqmPkFxoRfe#KS`u!vZ6xz;DP~ z+14fW$BUxd!5b|%>B>d%a72}xJpg(9Jqe4vH96iGz9&L`trP4H0AY)Q+=@nk!F-%l z$_e)};SOAt>AMh}Lt(t*pQ%8iz3TK`*Cm`co^gbBOUIRrs&~lM1#dnZK;l_NRdyt!`~BNMx6DqqAElOm!el^^6ac!GKWT?XkSL3 zvfl{38rqBV&yO}mrU>YEbpX^bjCpi+}zr^7r&|1Q?PWKs>_0WM?ucC+O?EpCuCt>~1+$|$*f*F8*`9OtXah^qf|gQO?|E8yJfZhBel)7fFRoqcML0~aUO z4R_weBL1`qn1!3>O!KFA_qr&w9E?bzh}HU(r6AWOW|GXO^DM_l#Hzsu^vHTi+Ukkx zQ1&PrgJ`&g&Md{eP=UWlwiu(7F(P!+6Indj9o6doOMN>8lXcMSX*X@Ootm-B?1wl6 zmE04F%`U2GpJ!+iG8uM|TJoNrS&V+8>OQn6?(I~dS>QE*=SxhSPvXvgM6LgL5Bh1) z%d#!#yB7#)2m1%~KW}yTdHO_-2mk;+zs4=;|L#`ze~)W>7w7*Uwa%sECVRtoZE2r7 zB`F0lRej?2#(nr{645-Xo3R9y;&>4bdL$ZQq!rX0q4?%Twa3dM?49hzfwpPZP=%y4 zVzlVXYV-}5$lhtL?%x4FhvNqHr0s-b$}}g{k96lZ$K%e`2Y;L%?pLwMEJxpKg@Q&4 zY)!5lG2==CUeu-DVz{l45C#`*#Mc`YjJ7PqOb!y1q_!vsymuwa+dlo4ULvL&I^oEz zUkQ)B-uJNqfHc~cgW1iJC>o97M-p{;uYHg|r}6oN)@neczAgA2J}7I>=&iP^Oi308 ztt-+RB<#81^S?H-WEbO$Plo7@~TNyfWlK^KgMQ^En(J^B2McoZzuy|5io;+_$v*Kcjp!&Q6R)rk*)0-}+x+6yX@(;{fQL0> zs3N6+pzQfm0i7scz(?wL{z#xO?m56ffrs&!%mCPs!F!E+a6EtR{}81(N6dh1YdbUI zZ--HY{@Nqpv!|K12}bUQymv9JKx)Je_qn=DpT;)f=gQ)5>>mxPa&yv;tk-TWjDnoO zc-pw=N8dNYIdHK1OlpnzcX`&AFue&jZVT&8F^t*&yuX#z0(0&0-M~oeFlh?oJAWkR z@Uq(=>I;AgA-g|5IccGiTNY+E+iDl%D{|Lyvo4k zXs-{H1_-F#n~l*SEQg=A;m(bj{%$`9V$=)n%s&I?d?S$-3aqUD9>t2|$3GGl+$0p) z#kaWkjS-(5=7InP9Cw+a!H9wAFI=stGtSR-eObDZS84Ep@Yb~oTMcQt2um_|Jhul$ ze<4iytIrw#)#rGS*-A7bef@Rzymdz5B?1?te;l(Rao%o(cy+CAX>DaQpaoHdA~Zpp zUbXr({nD~G?N8Dis0xI@^=yJ&YR>3XcjP001Bn6{kowGi=RN#~eub^)gsArhS+5@c zSHYCo15{uH`E6wCYoojzv&5y~rQdo*qSr|>M#9HW4{=5ten6dv=;HDYUl)^95GFsN zIxHM;Z+?gxkrKeLAjfqf{ZYvf*AxUnN)ntYd{tD$(9yna(cyFp%Xx-0+t8!;j;KX- zjGnu{+Y=TS2Dr^kPpHk+nDZ|^Es&Qd^6PWb1W9PPf0%vvo_r}QhGxk6`FDtKsm6#g zGZ5M2SzlW+V_ktSy{fQ9*-pxpEq^NPr@g-PCDnY(*QFNyZj^EZM+IWS8yr~Qo1G*8 zFC*|Up<+&9?3G8iD31V}3!nvImEhlb&lP?4x;#jnx3tgJ5DD@sDq_5GyH^hH?Fda% z{TPIaWND)XFv#hi`?ADqjMe}$A-IXAt|+a!UBKC4#zl;k+||Zws|@SWjE8d2aTrB~ zx(S7DUgZ+c6>^$A0gI>%9K|Pm6h|)byLo`WN#8k_pJEu6(G5~tu zQB49VW>S7B6wtlm@#J+6nbF$j1apn_fjTE7AoY3RVk7|+z;luCbVwphTY~^ zpXGqhdkk`nAR=t`-E&IK*eLKR_zg1iXqMkJfasO5+PXf|VVRA`rR+fthqS4F4RqWW z{+WjNnC&aCGWgLwmL=0^*Gf~qH#v>_khW-GsbdBxS*9n}5hqCBLhqDIi%x2W1}d<)*U z=8|0q&f#6vFUQ+)y9NU{-ge~eHSQ2_rrPC<G z+8zlV27J=wdgqsg<>y<29jkAlCkN#;|G>V6d*SoPeH+fs;kh~Q(!5em^+u01&ICrF zeI63di*|-82Cwgs*#FxP;b;x2x%LnQypJ9}svc8kx|vMX=3fpSIi42B41i~P{s5H{ z|B`gS#&eredA#}=o-D<;Awtet2Qt9yk1&{rT!PL#CJ7elX%@y>hunTv;8I;#$UUV1 zm&>{5$T@IGtKSW)^wyMTAo%0)C;|jKj9&Fqs6NrWu2lCn6EsbWcjv-=Nx|-O+HZl5 z{tC02&|F~r8N_Y2xt^|QjAS=4?655K{hr}ardHbn=|-96Q(8QVB|QPJ6p_|N%cu0F zOMgz^UJk{zr+77P!;4yQyBk?B=dJNU+&C+6Z9DIY-NGUK*2%c_=L3~;z%uxKgd% zea9{N?(IvzFvbH63Wcq;S+3lBSiH0Jx0uyI%$43Q=_P@MiK}f2p14o=#&PgkalE2A zhVNgBDE$CcnkR&tkffIaT9pW;+pJE@*plu66NeNC9KV~lp;sX5=0)qdX7!(HsBD8K zKd70dN$$2zgj;6Gg1zk;Se&^0 zry6;jlKfjGG;TWy3c|J(SZ6;eeVENY+ z*F;0E{gLsoztzMQV}7f9DBYj~?#yllYWx?NO+-byCvl92ZKP7MK=Ruh*#lK=nTy82 zen_WbxT$*o>H$H|k2^{90LU3t6x*0U*G&l*$|Qldh%(3GpPI*#MiG+`;(SpMJsOZW=@x6pePE2dIm(pIg?_Mf^J6b26SGj0WL&s z5oJR=P78sEUvs#tg8|DI^$J_WxO+zc!nhr(X|NE_W};Ys%I#Q_2M_(*)$6f7`E9g& z#YEdXoCVon>rRE{=HYD2_f$^28G4GSCxcwL7e*4v8nPrv9Ss)VFP>bVl2LSJ4G|kH z9=l73d>$j@Z6`^WceqJ58ZVS2kYU2pnee}AS3-vlIRik{45OaMc2D?X*e~e*yHNFI zchlf#LOj_v+;I9H&Ejs#YXy%c@0*uqWZrB)v|Tykd{6`F72&s6dyoN~bblVWyC5p6 zAtG{H>WmqepKmaZN#|>cKtj&5DeKIWY>59K6wRtZMalcs4iBnJw8?w-h?GJho~5< zWVv8}7;N5UjVNNcKQ4$0V;JfH8khmh&gKC_E@p5{RMyx%7ViXfM^kjl{xCwZAuSc3 zrtayGf-;?)9g_exJH`)`rwlbMM4fqyF+>n{pVYT7fARP+e=s;qZ9i!zX%fx7LF~9g z$Lc@{xAq#m1PJN^5XuN>t^&XtU##)`-Xt^5a~uhpLNS_LSybR&kBwKpw?^J>NCjF@ zrS0Q~zu%0Y>wU;p!Pp`bDLy2;X~NYP6oav`)S;;{&>iBUSVftHW#a-KoxDQcV63r; zZNU&d)H1bD z;o%vVS$e5sT^pmSyrs+NdE{;F`c}6X2Bm0c@iFT z5D7Qjunj3d%{D)Vn9;gA%el&q0Ls{YbHEzfpTa zmbN_yM3Xex#Y6$2*R4-T!tO&yrWKmH#L*NJ(=1GA5#Q%Az1sOcxg?y301+u^l2%Nh(ZN~uDH z91%tXZp=n)NHkLEac`_!ZK# zzjB~&O{#46o-C#7v5duql2G*Nlxx|I@p%OT014s7Q3?W2fP5v4$W;Vj$!sA(h5s;RMs2Y+cNhqMj%KN-YUrw7wIg9^lrB@Bz@!MvKw_7%< zJfbBco3r|xt=wjPTyGvXQZ5-9cSp>3-L6mO+_d4zy-L8hd3a2oYtx@D`yH+Se~_ zMxZcGE9}})`aH|3Ec)dd*Bi&u;F@hZRVPc+RPAUGAke*F_uPRiO%74B)WgP{Yq3cy z%)YE37^E9oJPceB^{+)t<8oH!nrX)z=JsJTbL>8Zb`5n#Ev!a(CcB%oQeL1hIdcBk zoM{|MZa&J`{0A=qx|V9Z?`^Vw)iFrA#*GOr&@^8`j$I{D!AtP(|$y_(ORp z0Y+MpJbK66Pqa@QwS`wuie{HV<4Ft2M9H)H0K9weO?UPL}-xEPUyO&D<-FyMPw){?H{tq?0BpQ3#J;e9Z9=vCf zTS7OHGCLJMRvA}Yluv*Oq7DvBi0_O`VD!e|80^g6OgtK}#Y}6*dq|b|PF3 z)sGk1$diY=L%<}600xF#bJgx=ShgBPE6V$Qv-Le%;75|Y(VKOZ zAl8krkfc-LgYAO_4WyC!>&@vacNQS)3JBu^-HA!&?emtH;t;HlH}}&B{J_w+P1$qz z%r&l;X$&_DKWv#c#ieLgIy9AgMy;(90WKB-KT>RVd&%~Kp0NJL;vZdb3_jun-qEy- zprIv&+kF_0*$Y9OaQO0}9X1N9o>A|c0B%)E|+DtZ%-@`&NU7I*o-N7ZFHLTC!_N^}V#N_(Smr7^`xy)6)^ z0{bHw{@#2x8da#97I!*)11gAM#pYc!t^V69GSMAo$}1K>!dyTt5XxU_=KR-4vlLBq zoh-s}6d42>to`Uu8@~{=_^9lBpO?B36Un@B&__K!f57gLG#XkuL)s}83yMy9Xv!#x zJ-|^^BFt@JUc8sH;%ubREr2K*XDGcJ4V18u(?z53Vho8%S5vbmcq(R*b1TH-GKBGnNxedd~LEE--XHBM1+ z!5Zr!>4Z>%t%8V88@HcLKH-@E5=Cqhxra=BY7$E>Cmji(dQ}Ut*A^-JhbTC8GAZ$} ztmXhr!;sr3V-%_7@!B=B_obkwic|Eyl9@5f8q$QP-?^c(hRi!!O&YNcNrRB^K&Fie z0!O8F9uAJTqOp+jW2^-(UQUZcbFUJ27vfq*eRP?~@#4?xceJptUP8SjMZCa#HFANA zZ{UJtl`_rbvGp=*YFsRe1*DkOR^EVkV_r+jx(=+6nqBp4O)Xo$rpm1$KI+?t0*mvz zlwBRn3vUHaM!wnMpYobjcxK`)?GZ(kcuVXi-yt;`c+J&eD=ieZmUWvt%1W%C6oqmA z!bhV+J!d%hfzJkmcXr6Z#MT|+%D#(pB4pr#8D9e{}Tqid8*@#+7-AEhZrT()*gRVBh z9!5B3e?F?HR2%%>;b$k7H=ZTVwW39HYWn$kF{uMh9tEbgW4wKh6a*0!QbrDPxbkB; zh}x;XpTyt`q6h`b*Hr#L{eQ(6W}KE`ZENa;eCa4Ke~8XfZLP<+VN7z)c5j+*P87an zOx}e^Y_{Nb1{OB5gCHvOXCZ;!Ww;<7(QrVN@JI#n+zzq}uRu>MpCb%aN@NKZs!!BpaTiL|q*0@`AUe3G&9nGCOzsY!;hLQi4) zj9RdWoJ2cGcIJ<#661vA=s0(}NR)v>5|w79cXCp3ghlqH4bow;wkYX0`Cd`EuVe%0 zv@;r+wQ^m&fTBsOYjkcSF*x+XL$?_dE|sQD1d>29BDd+4c||LA#hZSXbn3XY1_Bvq zF@RCj$&7~g5t?gOu|k8Q$ElB4ok37)H*py2PG5Tv9gMyGDgN7lxJy!fj*TiMRiV$q zOgucSgluJ*vIkP}Fw?(31_+G&Od+E7HIh**L1y!k^;*$HfxEMei9tow6=MxhvZtUe zJM+p8Ujz^`l#%rnZOVHSlBp4tuJR!a-omI0I6xx|-YA~Bybk}Cl0}9!r`u}uQ|*9C;E3 z!5qnl%>8DETYqgNbXj3R_4-BTy2`;Bzv{PirQ}a;>Ui~VG&47R$v=+*Z8_K6RW@xrUha(>FgEG#)JY&k4s%QsIj0`f zTTGH|GS@%|6*DqNe^KlcHjb}#%sp)&mAWX|V@I0j6rD+@!J#(I`%OI}HxVtCTG97e zeT~t&kqb|jr$lphkg;K03C`o_k09pZZveOR%yYq;$P2c?JehE zFM{A^`{-e5SB*&2n3{9|NA8lYQ*Y}}Wns0RZkS6yg#&0%tuqzm?`96 zi24q}Wf_EeyoL}#Xsv1xs)77FmT)lO1B8&T3N?xB&73{kDb!j>+ zeL{eiMD?f*8&g0Hbc|c4u4Gz7xK73dt=O(o3q2GFrfIiY>P#*PF8(XI+N1dSypKWp z`8prt5feGSXX&9B6RBad!sFQ_-!7ZIgpg3>zWkPFS&Sr21XaQQ^#K10kVd@8^4=k7&budsRz^Wy)~b6H?(s&bIXDCS|v# zNQb~!<2>B(P#L(9G$cm$-IH-!Vi?23L{X1Eo&aWXP^+kV(*<+xMUd3(>z$y+IA%v%KWH5sR)Lfe_1=p1@IChl!ejwWp01#`Thk6dR`H3%FQ3 z{_5o&PWMR_i{`YMUBjnHI_Z4W4WPi%%ZwWtodmIHPV^P$hVpPc`HgfoB$jt}iBGpY z(5V(*D^m!$>x$JY6pZ|-QyKZZT@{#zNU?l5V0HrPLpB!-{6amP%!XXE|5W6$8Co*f z0P5wnzjKRFdmykmJS*S!06WcAauz1bSIR~B{MrjDJD5+|UEyh(T*gY9S1o(x ztth+9H*PH-cW@@MHr-6`#g3on&(`HK3g_r?b=7;LF4f<4o$W5KjUI=iVeUv7-pn7c zeC>Q3m=|=l;N8%037PK)!7WfpH6~%cy#qS8tTB(BT|@9UEeqT_!Ba?R8<)ES;x%(A zp$k3xUsB!`4`R0=dk~_D1zbR1q5m^@u&)PqFb)j>P@wleh_?NYS!rVX8)oufi>ZEt zO#Va5_+6tnU%XTjSD1{vTbh`yZSdE|(nJE9Tw`@71!_>dBoG6Yz{5xD?RJ$17|FB0 zKE8_%k~S4~aB5NRpdTtr!P%xu?_OY*Abi>>F14` zFp1*jv;LOz?>q>ZA-&Q3k{r@WKlK6h?qKB6jKm$hP!_@7i!VE1YG{sJw4o(Qoce-n z`TXoWSU<)qyU~ebY`-%eS()+yfzg1g?OPyTaSK6K99hp~#_L)vAwT`Vm=s($tS0$9 zERNqqfhq$cN?N0oC`j|uiMZ`}FhGj)^MRmvc?zD}sS?^B*%gb?HGG_0VR{!Nv^QCV zS{OP`723-d2nAOscAvT(LxLnzCIe_9|2PKy179` z(V9Tz5^e*6>LA-QLa|3dj6>i7#OJU#_I9#U2_EPJOsDbMx@l$zAHawPEYU|ySsciO+R}htW-5t?Wa!M?I!+fm%1ji%#pXbn@qI+ zB^7Aw)nTS)H{f?VV5L^-vrK($_ztjxd;q2E^$=T@{xgehgV8e`RzQZl)mF$ND{XAn zm8K6FLeEapN4h;twq~j>mD%VTgI$Pt^pI_02XvoAe`Soa5*zcu8p{EFbGY{uxFWsL zx~3XS?aOR5NB;Iaza=kLbv4V@&KlbNN4_WLMCY+e=u=KcmDx_taO4eF7^PKfMJt!$ ze8hO;Rtf$U{#BSR(ay87B+DIUC3UGEkFcjZLgyu`CnOi;9$VZi5*zc2)gfFNL)clG z&AQMQxYRFSv9#@l>DZ7GtDfHj`-fF0SVSyooSnfW&O)v(6g=Uu}95`#D zy{mn^KY!5#ODJ1zAhce*iW(nryX|%mnAe3KMUi=R&ed%bJc5^%8AF3t7O%WnP{K!0 zBB~#Qb9~oXXrFRQl!AEyeHf{`1G3H3mHQC}=85I6z_|x*QjO5f1iTwCpTstJz@6ZyANkfmz+Az5Ijv`MIfn%cwc9%6hPkrzVJ;Ac}SB8DZiz>q#+<$yFu7xevZ7Xx!Fz>X; z2x>gr?uhXem$V{l1{mnvne7XPjQ?@3 zk$Qz?k7N{8MAm0zrl!qt7VG^~Ce{ zfgp`kyzNg(P`c2A&V{Dm(L_VdzyQ{afdh=7L1H`iZ|+qIN0R|-FD(6x9VTdI$?OIT z!1D)8?Pn2ySpPai_CmK)0WpIT3qtyLEQ-g=XsTxPNgfEQF&-gp+pPc}%1YEL$Y@}4 zo{Cb@R7maqt9i^S@xuLC8z6hF7~)K|FuWh*=I5&cYwWFPYs`m6yYV>a#(BoR^2w8Y zm*Q@Uk{z=wVu1N^IfgkKLo;81v=Tk}dp~VoIj6|xfzR~8TDm?G=}&INz$4hqOrCtG zOW@N87Pz&#+Qp+Cg+>y~MQQMgWN?do0V%iadW*E}F99wU(ujUtvAy8xyrwF`^Z3oI zNNy!@p3Dcw6XKCst@R9Xy8JEXv$Ra7a&1Zy!Mwb%9KfLI#yTCYv6G;I8ULq;7~SsK z<-Ir#RZANFiva+vv=&*{tZO_)@F<}=mhGd#$J)9k&^D&O!hYN+M5ItW=^B?ILB!kIhCAt@?h~Ui9ogmeOX=Xw0PHEFuNEY;>LwS(&hem!)y5}z z-Y9WJN=_s2rv~!!j!D(F!>?afGd1B7TbqS0>#ssi;^eVwnmLzU0t!*eRH1x{{2kau zHRpG6XK{gtw!(GOvxsSyYs(1qB-K&QvOaPv88jd4s!Snf1RSN%Wrz zX9u;2HWs2v=YJ-P!_irm97Ik^P2}1$^9Urpi)j{$(tDafs@Fb(-K>qpDkK7DdPDpig*kj6uDqnBGYv#JD=Mk>W0zEmgHR zH1N6gG^7TV4nBjKxf|$QVW~G!+bC+?gewc^l0BNpoLR%@SyI~;BK+F}zGgMtmLt|# z<3h%KAY#@8z&5~hnuJG?(kHS0-^jZiE##(M#_{mezMHcYPCVr*7Ht#y6_6 zeXT{pamAq9L%7sbNi(wYkReMy#Yd&Kl~Lq$T7YWtm#%uZoa;EN94!%~8XFruKa zhrfT;$Te!&3k288DKIt09TMA-!%FXT@66|$i8_$D`Y`OW4vpFj`_1fakIG^F`egc#_f!11DO;aWBe5!G z^ak;jdNINaaEy2{vvQQ%pT_2cE~+p&FX3shc2e5c``XQj({0*9?0`A}p4=%h9+1!< zG5Qw(9p^F1*jJzecBUy2HIz68h(;gpV3OMzH)R4|#Wa1HM8-+n#&Atr-cZfW=<_5* zZ#M}4&u{R30`(Y2&?|p@ojdAFA}j~N{?U2Z&YFr;gV=6ju_Okc(s^GPxs`$&KPKkR zlrSA7I{)$LmKnXN4qvxca&?wBc@;?y09tIKq0AL~5fj*FL_kdii_cd*2Z|~>h4NEV zf`zn~j=jIKH?qGVQV&cRxQ?qlSIagHDlO!|d z;f0-@k?ju|ZGy0nDW1C{7-?XdTOcy8vDm#YQltJ>1++&y0F8*A^Rg7FA=3#7Ig;#{ z_K|X0Pz>5x*KI$}v#4b&mFp}`gzGFjg7_l9`zO*Me-N1d<|h0oHn`~IERrzuWOyu) zdowPeFRG<+ke;7Vi(edHv#WIxPY-O%vrtYW9Z1Jm4+514Ys<$DtE6Qk{)}Ytmwk~g z=%(4M+7$r5Vk0oXwK^=WKR68yyngEG0LtT{lYy#j;wB_D8=R`y#PMgZ_J`PN&@sxo zSh$bjyg<@!p^q=5@{D8q^kM>HHx55-PAV|Dx_s)PJS|a@MSFwyTS{`P+Rk^i*T-th z<8vCrWM!@oZ^@^1r{7GSZ$*P1mJ*&7S0iO?vsdmrz4f!)(*zOfi}u@JyK8yN9~CLc zBwVYq!Mw5L*-qfMc&7w&a3elmwYU1_r#b(n^Wv<9vc8o4S>44Xku{jftb zd-cK-rA{qc>8!1u$H&XzwO`?|MKk|a>@-^!e^tyyMPUb-rE0b4ib2J)c#TbRuFBgw z9~EC^SNHw%?dWFZ@)+`Rg(~r|__D*Y67%~9t{Ts6<^9U;LJFD2CO2zLM+?f z^^z6NE$z?KwO#b_k@mi zU52nT7#|8m)!p+DMtqNlT<`aoSY2IO#VMR!|<?ncuSb`A~J?8tVE>f|U(NQrCHTTwYpH*(oR2AAfo4;rJuZ z-@16NVNZJOL+Ni8`8?obfHot`Q}#1z(mAxTOw&Ogqm z2f@QA*FgRQCzW2C1iG7W0BBtEW1zT3@9CD2S3sSh}UK{Zmp2 z72lXFQKSI@O_mHwky(`WBB#+E9L-a^NTC7A7 zJc2PL(vh@*$WwZQ;zZ~`8m_Vo;TKxF2zSq>&msYS!m#XbCz{_d=8jYi)L)K(aNwIh z#~}%3j5is{nnLaPhI0~l3K9@U(1G?O0E=PketKJW zfmq#fANvHbb_*-CJ$vYuxN|E1l8W`LmE zE~CtZZge&LS^J&@85vKI@d}L3G&Y`k{5JtG*&MX5=i01&Pz-O6V&jfRmq55w`)conn>S7_KZ5R=ADi! zoxt?4{PdXQM+uwS0^8-`BMg0(0bE_9~&~PD0Z@ej> z8j2&^F>gOs*!I&F`ct+s1fpgIud?=M?TGayxQ9y2-I6v+Xr&cDdX&(E0ZDG?l|#h>{{NYq*Qz6iIJl2{a2xndXN* z{QXK_AHF6<8}QL)B#%+HAeRta+kSGgk|Nm^yQLc57cW$Dsbq2l5PdgY0u96{ktWI| zpv`F3Dr+<(uKRJI28|0u3eX{vNghm3p^}CtTAtFK7R0<$# z?F}EMl`bClt8ieJYjl8lJTE4;LG$M3dE3O|Yyjb3=0+)= zls%lc$*NpY-3!XZD6UaH$O5oiXpe(;F?mAZM4Fi9lggsQgaiR-io_YUOl1*myKJul z{dRX{%hvt1y#pGZANyTy3M;W*#{}^uphq$egkh!ke*h;2V=4E03{cZgg#x)jcMt5Vcd2>&U zrVNRc;}XpwW=T2bMio=XwG3dJ+vq-fEtY(QP0T1*(f`Z^#S5Q;5|gL{sl6i^~IVEh{!XCTX&dU9;0ez+;8 z0oyp45pAkkVgX%meQLYyd93Jc<}T_EEQ-E;eZV{iG1f8WmN6K6;I#MFq9U+yp~kXG z{0m`R^s_lUKmiPmqd^?p`-w@~EaL$-2aDCZDppjxRc)eUy|Z#Evxms(o%ZbOVw(7e zKCxu4HW%%roe7HSg3>;w(GreTdm?_p*7&MguOTluOxg&)0R!=hqm?^p;fGb~UQ4an)2eDKK!1CY5^4trbx$=h#$K%0$O~a3FSx z8ZE1td;VaF2e!5`eSynpBDj+?TXvT%T<)rGl%1J6)0)YS*xCMHuH*k#h5WU;mEGnD(pQZhgMq(b zhr$s-E)>`A8&ZK4P(xXQG9mx~NTkNP1x0Od5WeZ__GK!eKsPB@f)+{{-`dg5>|`o^ zeO&_&S3!;THu3I)voIE)_j99!iK3QB!1T%uOH8at46*z?2`N6}NEC#7MyUm2fLUrl zBPW>g4;>u29B42@F{7M!zNo3e73m9e>Nt_jqD`7kqV$qqx>=P8VURuEJKm*vVk(4Y zgfXINI)r)pSSI~%mE5(-D{&rK#E}h#UOe3)fpLCPaMGW6+|;?(mt0(bit#t7bUI*x zNbc!9`ue zv9fdw7V@iDIvXeJ?NX;Jd1h;H=Yx2np*1!+F*=j3>d_@!2rEljyj>)Rmt(9rq12gE zk@J0jc`@pq@~yCBGp7vP=x@>o8(9UwVQEs6VWyxLhb31nsTMyHjGxX2>N-!|m*u7d z&UGmheHL*W+IvhYb)<;5U8ir{^ER2WHi;)0!oDukW!>^J(M4;4Vd|tt(2dR#oNC~~ zHg6j6tQeWCpA8muI9dFa`EW6;Wj!{TYzi+Mv@T0&#X-gdGEq5*3#|??yD;n}Tj@57 zHAi1uL#7q>ut2@UF8p=vNfKBR;Wt@U#-2W$GFsa2U7a0`R?(&6an zlO2pfreczBahUa$_Al&8owP(!r+Cl1>HZwjtrFwoG)m)(=)H6q`!&-{;9fy3r90r5 ze(KXiN+#}e=-A-z_&gv;EtBW}(yrtc^W3ptf`ZqV^r9Z&-Q)wRy}R}Egyu*u72lxx2+nHZp4FmbHgSMDWMAf3k5SU zxA6aRT=E!)nIRS2Y@zQ&B(z0!OJ-`|o=7%pVNhK{MKog3cXtiD2@s19WC|6k7f=!k zfo7XWn8;&m_S=*u(`D-ns=}GN>kwcH|D~uJ=GsD&XJ7uX?nIP{nmRck{2{1Pk9^RV z9lFA!ZwR1~`2<@3P_e#4ph&CGq~qxgqgs4E9a*z{TiMHnMNQ`3M-k}n6-(mu%ofFGj&c8%HumHgzFp}GHv*z))4Y=^wwp+x!64-wG-%Rv z^4>~jz=HCX&Ae1NyE%~vY^+89Gp*_+wk&aYI}ot2n_Z=LubM;iP!;?4uA%UWOWGL= z_N4R81rarfdZPq4Jtxh}BMG%G65t8^T|=pYh2~v4!!?j13$Ls|Ng4LAwWOpOA9T^$ z<&z@j)U@*M5KIfrX!$}hxA%aCuim6y_5E*U3%E4ISMeNALX zPm_ahVf&%nD5~Vjvc7$hnw^*SF0oDMFl5J1vn;LR{k#3qA~zP+jLMRAiG{_aL*&-A zda;uxr;JfP1>#Wl)#GHEhyi4Lnx$91`1(YtnyObm8+sOcOyb(1z8Sx>!-zoT!d=Uz zmvtGY!IrnG1*t}M(!he(vf{7CATK)N#xJ0ir70SjR36!@4?UJeHgrJ16TFk2gxCSO zi*BI_>fihkX|lFdqx_K{!>1v9$kUtGkW4^ncK%@Y&hPitTx%$$xh11lq#u!U7M##e zoIuvO9dzvNorcf4R}3Vo+dr3*km}G>dVooNJ;|F{%ByKOx&&|EEUTo!QF_uFZJ)DtN1ih!d`h{T6O3eemx~CS&OmJ^ zj06%m9||Ua7JmN8YyMI7k6)gp^gOj3Vt(*hndeSrR0-5PcVQ*QA(+9k^&ynl@lD4%`rJ3G%qSwxS_a-G#)~ zf4o#$H#|{>g-59!mA2ig2n@UwGk-05HSlG(b|+)QRm%+&$@@M*+`3QM0-w75XnJ&1 zFMavyBfV)P^yt81oAiDZO;XXj)mjeuqT2B{Cwntma@P-5ox1u53!Q(w;9vcAfOWI1 zsZQ0r9{mSHndbPupJ}wHdwskH;A}0QDtk9qv=lVK)$(}){}qxEZtK0_D)_F>RbLDR zr8Z1U=J7%jd8^Przn^t1N5oaw*l?$zV6{+8cIP2cINj!`K>6-{|A?XZM@I_F1pTyT zl=YzB_Nd_}zxJV#q z{IOKV?_)r`fY9!-eE?g6n~>T^PcVluaa`c_6J8{DY5}u=+mF&tkB1P_!UBizXCPrf zc=Hu8p)dd=CHVYg@4qES7=XL5aSTuSZ^68R$kBap8XLS{)l`wxKwxuzCy!gUYC5jZ`nd8bBH2{J*_%{sSt~nW4q9*JVt_J>nBg<%p%{T%d+Tca}IIKOfmUd z?_Pi#J$+*oxVc1Ubf%9V9n5X-?triOblnv5nY7}2>Pg4p*CSM6y_0^Es^o=c&rO0W zSOeevwC?Hz=z!1Pz|Q+fIDpvbN|`luQcc!8pc@|^Oq+oR2I=(OU0r|Iq#yYv<4;3J_-5vTfV8ZQHhuSGH~2cD=G~+vY3VQxm;tEPLh` z>tIgwU3L1a?{93PQ^hH7Ow%Xm13;)R7;|3I| z`V&%aM=|+!(7^}rbveUoHfzuqyc&VWzy1xRk=&7R_e{HXc>~wC**c=vl?y0hC>%!O z45GNFKiK9cOOivaTZ``J7+coARWeZe4}-hVYs^!W;R0Q$UkINEC=Q&5K|FtVxuT5k z>m^-jUO=_-o@OO!9@HnK`UhCj6eA@?eWJE%I?{kqCmuDSR57etW8yX8tgnmQ%?;Jo zr&{6$=VQzjp{tC3;KkS`h8MoQN46dvecxp5b z{HvIxL8qZL6OgdOO@KbM=tKhS(5M3S411-ON}^=|mS61X+WGi#Skq$G`ts{hwM@pj zQ+I=9A!HaNj$=_WYih@m zNvsL-3!NQKU-_}ho&pK;+J&#To{kQSe>6Dg9lC>~4wCF(8h6eZ% zR;-3Qw9QSOOpky=tYrLNmzh8P4HPa)L7hqVp&yG_TX`)b-AWi5oy|&<9zyk)ZFB=Y z4=DJ_J(}=RsK5hUBVv)S4e)=`yU^(Z(UO?^XOtWRaiG@|mFE;ftLk!$kMgHZj5RV73tX z@}vz2J~(4(ifd+j0_Yq=!8C5kRXQk%&d$;S%)wv%4k+3V{RQ+1r~TZ=kHs_}NI<;= z92xgHYjJ!&`H>Ia>FFSazza zn#)9dv?x*Nte%nT52JdPYZustp+pr>_ZUj0lRWu8`665&h zh_!(hVYHyvWoitqH4aD__fDZK9DDXgeV;^(8M!M@)cIHwQ?FQdL8Lk#VYLP`5aPl` zmIM!S-pMY204vI>GQplD$FFcdkL{&FQ>)63@#plA&yY78hlqn%W3S?0ZgRDv(%Y5G5H@F)}h4kdzyai#CWQTh6u_E6u_S z8IMA`B8lO}9YoU#flIgG5Zo$Uj54rcmICwEf%n-T0d5nkgVf7j@m&0gAx8p$Zg>Jt zrO+t{&OJR6RiXjK)6cmTcva#Y3jM6eB_)PoTyQU44#uF_vkGCTw}-_uvfQpm@NWic z9fxJWQQQYSU`p%H9SqwQ^S7m<6T`@()|(7j&OiGuo(ehNOp!iuxaI+bN=PAaiN~>x zfM8q{zEF8n!mH^PJF%%$vC*%GfJz1_B6?rv$| zOnZC!XT#N*u{AYM>o^blV|Iv5mX6Iw#Z;i)RxDI%ccZelDBi;utWM!{II_p0AkICe z{kW>Thgjc?pCJ$7)b7(bN>txsz7`vFoiA+r%(H*U1apJcC8QQv^V@z>f(Z-wyV)3p(T`#FVZ6PBkRv^GCAWZKDfkC^*%TGYM=pt&-l70mza* zk~o9HQ&DsqCZdE-1wS2Z!j4S88(y_u=S&z0Pw_;7ej_Y1Q!oJi3+aU@0aI}eSwkbB zM!#LCi>(sBM%K?b`5UB`39*- zMbZ@swSPisGWU>yUINQxC$`Yej%CA!<@_ND5y_){jjS-pRZ3?$DD!q+fyMa!nGkl# zT97Ntax4<$LlkR_f<7vn2IzfQu?p5D2+4)^yhlJWhBwG_vsksaJX@YJ#Rur@xg{9(?>hC{av6OBfqqE^tmWfD^D0mt_W_F`Cfl#QGyJ6-O>Oi`u<$E zA+s>&0ZRL3p>SA%xWa0OxBbMvENesDBVMzhBztEfQJ++e@~U1ElP{y&o-RMDit1Uo zL`B)57*$%MB-(2LA;$dTPKHg2uy zhN1C!m4ojHyn%p5rVI28ajT$ z^X80i@Ch^1fQgwTe*JBj?LudXO$=CS;UFJI^h|R7aDca~Xrn@NQRnI#Rp~etjr#nB z^2e5yRQGrA;REJRR1V4VkX*u@xsUSBwZ2$k%S0$P$hS1lpKMHirNNIK2%cV2Z+nmn z79dD!yA=Wphwz)2!IzQ!VHUXdT17T9**;Wlc6ZZrLa|D@VGH5WHv*-5pPqGA&59*- zJIS(^c5hUhSI#sUN=S)!ojSNr|s^@YR9fv3@eTPDd%1U#x`wqdFmXKt+1Q2G_6%7q! z`S66%tzKmRcv3OJd~hqCFg0YkzH+LjK=RqTU>!#%~^j}LZ=%ulp#I8Cz8V{LWTB@I^?k~tD zWwGg&7yph)9u^|VR-r%2&a|>9R`W<|5GU2;y4vstm9mo?%^CiIh<-9H1sZjL?8{5T z@3%kXpAo>%&Xpe>RYXjM%I~(vj}iDhXwcp)xF}R$jv16MdiB32Cr%J*gJM8apC4L) z2r^0JNT{crSaJWqQ%}XfAji^F1ZRXz#wP%u{b+An+ZCf!(k$Ycb?@4XB3D!v1A^s9 z-wc2M!X;G%X;SKIOK_5zyqt(BWtz?#0!^y&n3QP~g>dyic{^2+4ic$O^)SJebs^X- zq|Y?NDD?R2``sX3UzrJ5-+P!X{M0pEKh8mAP{CMd&i zG;hmmZ&j$k*#!8GaVhd4Cc99TB%|sK$S0+ujcYj90wod~I9Ex|NQxvCzOdLS@HkM$ zsheS)!hh+d{auO$Cf@2$TI(jSu;sfnzaZAS7hhR6$&9N3V)A+I+{RmG&nJ*>1{Pej z#MAnIG*+BqIwBAmd`C8DIZ_N5UUWHn$U94|4^}5%V#-L4)bQcpR4+qqee0wYm<;M( z6y%W~Fe`S0=EADk756b${EiVTsUsE{-wTffRb9ubQ|lG~zfbeHJB&`GzdSTaMgRce z{}0nV-GAYhPHWjZZ%8$M&(x)3ucj7*P>-+Ew{{&%jT3BE4)=)?$*mNt0KsZt6FRaa z+RjXWzie(ZdjbM_tk-NytK!6)d3JccAD`!Pe$=&wjP1-69ns3?u9;==mr9;iJCAst zn`Mbsjb?v6UvK-lt;=TC8qH*z7!GJt$6|J)(i{ew%k!{UZUl!Vj5S&49Vuqk6F_Pb zazr7KEf8rtcmhp=uBXy2+R%3V_yWb7{w93!owWb2sp{gqSOc&7z$di z<_Ppat@lkS=O3TQAcH=fN$#Owx1zlkhO%Q~gL}ji6{xXT)j5f+?e?-ZVt(bzjppO> z>71?Q8hr&25{)dfq>u%i>V~O*}dVOi)jTwAY=buzpVclRu2O z>abxkoY{8Y1K`Z(ZwSpb?$kYj@d~os#oYNtPZ$g)fU|(jBfmv(Dz2x%dTXfzW1|x*e#{JAdr&BU)qq2Rpn>b=AI4tg z0_zKsvq_l9^0}d^u72lH!UUyN+iz>K6XbvEPWL@OmLh+^VS>B1EmHqJ!&R6!WzCn% zW4T?8iSl0inVfMy(uYTaVmq&FwBt<9eJxyHJ%;6nGf zCTt{JyR}Q)n-)EuE>cE8InduNXY>hbQQk_&uxq!x9zypqV5l(6t`~;YKYeoowE4@{ z)d>zus@H-Mgu-X2VuWwoO;H}AW+Kav1p3m7eLn5%TK;`{>xnp?g(?2=V08uiYBi9$ zbs0vMEO>yK4{3VG6@v?3Nz~5HZp!>@C-IY$oQ$})j{NZ2UcW8%YoBE5If`0Fx)e*=bHsmy3AeRGC*d>a1H%_>gzB} zld-O^a`jAI?R>hD=gq2KdAiyc|0!a<3tP#FDYEC;eER${+<=2dJc0>DP+AgwNi8M2?mUk$l@n zBC}CK?6xqGylv|{?YO(WhVI4@k-RJ1U-E*WDe`i&cM1$nv63=`*Y0aqS@FOjHTw=+ z?EA1MTgl;X>C#Sb?G-$Mot>Y$LhqrtH^6&vjOV`)AN$A**l2b_djM#13>-7;7Hi1m zJf!E*77;RpSvobo9a3dlE(CG1MH=dP#j^DVFj7n z@ai~?zlNW>t}n`qq$@UyX9c$@%)$9V_IxjJ?QiwpJ9do+zjH+x79DXMonA!`a`_7+ zAK$CBAOtqNwJIKAnWJo^UImyc^;IoF&;!X*RzH0~FV#jrcbO>IJI!tK21%L~>4u7X z76Pwl=C?qX{;YSI>Ntok2$y!F>;07V4B!4rnBXTE?DISd2+&k|FAcAr3k7HZTx;>o z8-w%}zu5tD@u66Xt-+OKVadAae&a4-Gi5pKWF_FCtRe~h1jq{BFoFuJX6rP9Ap`nFZ_VDN z7+JTh0AGSs()b1JN($ozI7FO7TYW~XSZi9P!6BLorB*702gj(zX0qifc0^HXElB7k zpscCw2FczR#eVT<3F-04tf;JEmBGYY=atv_T;#f`%&d@@fHK|Pf56zTmO+o8UfH@k z8_5lvEm!b(vQ&$nMl66sv1KSRBd2Xyo5*~@jAbh3MnX-uP=$ZRR&s$gFF&U=On`DB{i8?pL6gNF7mmV zB-_x&V}AvGI>nbu)MSh|xBz!_x1zPkR=TVCdru^Y<$aXG43qkKx+Yvp(senv(U zOeFJnHjWgGL2wum={QO8CY|K&hAFH;jR;qRj1Q6lcb8d`ZwB_NXYSa<@M1uLkv8jY zRyV;knRdiE8oMZvtq}XAArD^oh8^%H|4M+s2o}T5NsQw~iDab)BT}nF*OY3^tGAq% z00?_=|0Y_C1lIop^YVub++niJ%<0|^X|7QzoYvc!HE#m{+SdQ(fsTQdJ$1-FUjFC?!iS22z6L<}?c(LJPJ7Y#E1soaeiduX zdYI)iDhh78yE_@`{u1M}GDfhCON;cem=6Ov{FfL$9z-YcsFbaEcAm7{cci08_|YgR z6KO4mWJWber;DdS6xtsIqu21Je~sYl9BetmD=HE>#XQ`m+$5z+ zOKy+tApirT;K@DGnE6;nevXXZg&n@bT))|Wq8uFxY}`uLKXBh`IP?_rGR|nNYCTA@ zcMS)W06fXl-7xpeL{2|amB4jT`4}`-{(S-DKGwf=&?JI_g3IJ#V`49m>`Xkvghf(O zW{JH98;{31<}UGogVl=w8Kr}xO0Qv`zA>MU>)o$S<2*J@G}mkhnUaT$rF9($l!Qc$ zglgnpq55$qzh3@vwS}u5Df+;#U=N4Gq-@Qp_w2(J&r?D9%6SxR%EMPyY#EP;N;DN^ zu_37q+Amek%y{#B?ju_)_~iWz!Dmv!LxsBTv7$iO+jmY2R0uga*D zrDVCIWqRgi*bG~1J%RdH4Qy>PjM%dpf7(w9@SQH0187(Fdmu)w%~~}C9LKj;fSc=x zBGVq;7HB|Amm3h@dP5vFwkb=KHWHBc88DxLIZ==0{j))|4>)m zvKeFzc@N=VNcX>YB~bTaKj@Q0oE#l z1cphHCOS|xF|sRAiQ8a)8)Pn| z+ewe$cQh?tL)Typ&`^|nX91RNG^jaBBHwFS{Ms1s*8s60?`;)ESUGQ{@~bNS(IarOi} zLvESW=|?w5w`s%Gb8G(&3)|fzh>iQt)N3R02eb2p8f`_j)!v{O&Wh^?Pv2SjBIfGN zCYn=?9Aq;e{Jpq{GnOtWh2`pD_pEWJe%vUWpu5xO)lkbj%Ze``Ohy&eB_7Y9*Hpd% za#`tOK%zXkl*Hi>BC?T`O`lx|rb$(qT$wrS7q*v$Jk9L$q%xB~%i10v1)s&gp?v^j zaM#$VQ0M$9Skkpe~YoI)q{FBq> z*{{ra{+>4IjNq`-~_`8DGCp7@vsrvZvn#6%c#cy|^a}8c__LKqz0BOyCpn#$T zYSwV_NupG}0zbz;ph!vEiS)La5YtV)Gt9c8NRa6^>w?ey|44mWRQAT-nh${q%~K{` z5Mlcd)~qW`7ckWnupn!$!ZIJZ7s#_m`_yDcVWiS6`;1%zl7LC-wLBbtw%ONY8{; z+Uu~t0*~qfD0cQJ*4_Q5!Dgn4#myt#qm~Ik&zUMNO)hB7Cdir(_2Fh9Zcn>x`{2D4 zaJQt4w^wP+VwRw=J3hMmPT6Z;V;w1rbIgTXoEwcn`|RspT3Wl|4?U5QSr8pH8kk1K z)oe=6^&SJNjk}FTIcPzzbahKlC#3BO!qJ>ccti)8GyVr(H#6i1FwDMxB*}qVSYqrH zR5x!8lAx^)0f}KD`5mY#NDGb1v>eH$#$I36-rM8YfaPgKIl_pwi0d=~(ed=v&wR1R z4c)-J{sjLV?r#mq4K!x`(=39IY?t7~CfLSK{SU_K1hsGCWsdu8)OBnKluhN0vCD%` zN8#~@HAGHNo$gprDe_uRz$Ja9jz9Sb5qm>|$%3rusgwo?F#PI{x8S2!U`_2WeF9;uX1RHm3QFQ1@JgI*W4s#><3m$>Vur~ebwF$&3&<3R}U`yTWEl4$(T zaKV2AbWHPFt8Yp)?!KXR=Qd$-8)pMDHJu6#aE`3)bq|@@BD0w{ii@w=&WWXVCE^U^ zjDJ6C$JtdpHN%>iy~g`5>FTQL)?L@qb$gO>ecuy0*xe8{{2a#dvkqt6>~<(Uc3WDX zE>q9{(G{!{MjTTB%R7e2JFH5`<}^g%V6Pgx<2CeRZh$Ir;6Z$^GN3vik2zfL4@&>& zC$fq3BJV)<75Mq6f+(Q*%wTpaWgD=7;*K|>3<^OObs|d*_*u{Br=QQk?dM0@YpeCU zac?!c@L~q%4q1yJ7(Y`e2<4||h6o+Vvz{vbmWdpuiuNxb1B*s%@j3JxQIEuj7=0i% zr^>qBfDD1|LkQ(;WS`6jC6?3O)EvuKjfH@*xD_P^TAESw*NKJ(3ZM5tqJxlBz*vG1BRF~lxI5y<(|KN~xI`L6 zx?_}MsCP~Z2SBOh(MHtJNT7dwoHud9?rT{(t>U_Xz521CHy>r&%8vJddVfUC-QNtC z___1KANGeW-B{4B`YCyEWyHRcs>U5y#2EfQV{omW>3ZD?y8L)>Uc`pcY0>UxWp7q?o zkr{dK^t4GNMLC4723-IJKIL#05hi@!?mv3eeXpY#dPTG~h z_X6v82&i~H7F6`bcK);l{<&4kZrS}i>p$}DdEH0iS}V5g7XEuJ_jYB;s^!3j zlaIJMygu{kUBtzYh}uubaAUnjVk*0m%nAjk=;N>e?9J1O`4}4bHdw%osih579hcO(ALd z&O}zj@S9E0b&b%V#9t6VHP{L$M+M!j~%3~-#UWRrS50U$hkt!w9~U!B-=IV-v~ucq&!7&5B(qrk$K>vW$7Mp?!4Sqz!&GqRW0 z82B?GPj*`k0^fgT$hPl>fSyFVi^>@Kf#bs)Ts>I%S}*Eeo`1;nx@FRBJB55T0~f`t z!xq8p2gaU>?(S8MPq`Ty0QB=Q3DJ&M2AGPC14t`;3TSGP4o&g2o?UVm;KVDuzs zJfF!UYw>!CW0H~K42jWy0uOHFHKmWs` z;p=Nb7mqB@!FBpo(0Egh)jf!Ip@xNlew~x<1supJ0T9dGIMlb}0)Cvd90q2G)Zn&M z>|c-p7`pHrm)qen!KIyepEli0K^VO7d%0rBdRvC;y9Has^^?d}U-Msh$-4h(en<%; zYuENrb{bRO1pTo_rZDa!I~+;O5rhAvq>N7eDvbroYag!@Fgdn>X~~-~~RU zI;Zm+#FLkm4SxdPC}Qg{tn3~(Qj z&-oe5kIGbj#mx_$Qt1lMcY!BOiUO4pwgwlPWI*Bd6^D{w!yvPDJrvqYIk2cMwg-4^ zczwD=R5sFGX+p>ZVK%7RHJ8;5PRhy#{r(FUbaR0qCSC zLk!Clp&K3*@S8$TWfK2jN!7r0*@UV!)3z?-$B<_bu$J#YOJMB@Q~(X{6gd;fku+J` zLNw*)G)rcWdHdM;qs|0^YJ+2HzVjTcLsJCqFgypQj@@w4FT%CgYyVF{X{pxbbGIIC zzg&y8D2=PKr5hYop;zf)SM-(~3Zh{91&O>6iT?A0s~4g{j=fOfR>C5y?Df1@eL_l!Z~3lL*43y4b7tf4+!Ndy6sGV{0%Fg zC##uXK+rarBm9QH;X2k2;FA{{6&@xW%KZ0G+up|Q3ux`m-PmGUn+I5dw-0luK9cdP z!F6%=J{r0>sGkG|0<=`FhF5IQ_{vV$6R3)=9Dhorq*zpIvI~UdX$!U#DP}{goS6DH zS1%`#TsEfMnzFDJh2-s~wSIIbs12_Yp}|1518a^{He?bpN@wT7ceI2M3?9U4Z#QYQ zV7Lr@oE`BVD>?H?AU2cyI~dMW;nnnpBfjkdjJ|(B*Vm+V^KY$4na?8f$1?J(^cC~_ zQwm72Z~V(0HK4j0pJnJyTd~#8@q0O3Gtw>t4GIq6=MLiAt7xR9^bbZtQ#JLZCA(h5 zuHMEN+i4g+78D^bmw*TLHy7}k?EW0UU3HG@r9WFt>};=@ktpRz&c5l((tvJMt;X77 z-)dAI_j%x^6dILtiJ?UCx->1bz*sG(MLI}50`YxUVEPQPNMgx6AHPx82A;hPpWVN$ zKC?xVJ-<;eU@882^_5%pI9l~oxY^q{GM>~bwy}RmQw(7!phYV>5FJ2sFwe<6KNV=9 z_%*B1{8lmEo83V{y_CxVVheg}>;ymagGy!t0QScnXruo2=W(VeNBN{N>5tFn6(OmY zR!gc=Zy%8afqx5*0YuZgLXf5482iuO`pFsE_F9=%qBG0Df?YRaydgrUd;5&=-2*qF zwDcdQaE**NJRzWA(MKQ3?I_vBu=zrh9=s9vRR(U_V3S411*sp_e}?1;W`Xr;t>bd4 zN!{0{2ig81#%cd)xqR+0aIkb9RZjf7Je!*}RgGP0W)`7}k3bAERi! zFgZmP9xDZ|g20QKlua>$zgLKV#JD0e|Fw)t7d}*i;cjsw;)L13X-#HYNoKUAhKx?@ z_5^NEDJnyF8=i>CF3CcBRY(%_3X}2?*3nIhRY_t^l(yv0t!KkdO(v?y35j{q$3z{@ zEQt%;QcI=f-577hiowcO(O8US%a3bz{2O?M_D?5VRyo_@G}aJq@iiOG;ec|jdh}Q& zqrEZblgceSRRKes6a6IsPTRQQ}2@yyKO!*&9EN2EWeTjxM72fgkp5eI+|AE2Rv-rq2W zhS_fsR!)RhXX6F09No=Z`|Dvd^Ti$$svm|`le~SuecA457T$X2hAG(#yFDCkWRrT0 z`jeJ8&7>3Lyn<`A?(=PW&1hNZV|yo5mzQfQAa`fSSxHAkAq%DrYt>+!&yAA6h@YPj zvgbq7h%K*WwxP3lgr5nroGnCAdj_{kt z)1Xo*2XDrq?&mQVky5)EllX4GbI(l>S)1gdfR;-Jdm4us3_q6Q_eJ9!!~~0!gV2bb ztL7|taP%rn8U77sikZ7r*!+VS1rCMa@szTh5vu1;nx8@yfB<||%N)Y#q_h5PhJJU? zo`f`rfrxy;TEV56uCkOVXD!>%>i2tCWNbXlTTeEY08wfr0#5oEj2nm}=3xE)SKb|A z*?dp@b(GE~9h;)!a249Z&PFt^yXsri-skD3sykb<>MY>b@~AlBUG2fGOHGy{aXsa* z3|3=uQSv?n4#M3jesP}=ct88Z{B`|8G_h=xR80}KjtNk_T@vo7h;X^NQL0Zg0uobe zc&y0mn>bbu;M6N=i!<6SH9Q--lg@13boO1PGjO3}t@hy}KMTPE6+$32CH+ezwX``8 z0-q6-fo^L5^CgQ==beLdySe`&Pl- z+&4n;{HvSxT57>yF);rMAsbx_ruK0VICD9=F04etniEp8>VClx_tMJfau1vn&2-!S zSYQ#i`6saym6Iy`g6Wp{;D8WR9Xp`P9Nqxt=3RNE^MuAzb83lYwHb1Lm$-fW&!8Xs z=sY+nw1SD>Hbz8VWJ0=W{GKp6rY^1Wpbg6qA8Y{^unh2l$VPvK-wiL^%PNS*;N02> zCVBUJX!fBCiIqW@qEj~@9=Ii5VZzk4h&}D;Eaj1W%Iy~sau2{i8ikW3_1As1X3R89k2XaF!z82#-!LixE@`oKIKF(}Y7TDQ`pbp7C*tQ{Y-*%8X+{W^_>NS# zEvT1I&3&(3zL{RKTQi>Bm1uoIW@0(XzTE+qRrltMqp*sl<~*LqYnn}! z18YyY)WnkVs71Sip>UBV7QogI-UCfPu)(JW-1{EYN7W5p4O_)FyIMtMjb><5_gGe{7kUfX^6%BgX*uU|HS*W(zV=j+fue0Lh}1jp zTz%H5{zSc@%_Dajfn9EJ=dkqqV`(x2PP%EiI&Vsp-0wGV5zP&7d^iWy;a5 zGRlu7+Re`L$Bws44o5z9K-~78<8J>9m!kWC(oV26{|XPiVP{R@xS{qiDD^0|&T&Zy zd<~Ol1vVw4uTfX)kPOOhvLX3_PgaC&-wYL!{9TU}V-wn^ZUZa|PF7L;j|ILpoLOee zL^@_BZ$ZagW4_m3GB9`AMQxMA-2&ULYjg_qL;T%6ls=8V2bcYt>$0qUQO)xbBb7mk z1Yfd)&0($M1g4|*EKQ}k6BrmrLjI1Ek$Os*n)BR1C9vXl(o1_%n35$=?P$-5sFZ)! zfv8najhS~#{-^J|Yn8&i)DQqK)lImR`gj+b8*NCJCD?2#0TtCaE=KPVt|LPnA2sc5 zK(PAN4JARXGjcvI__=OK)~ic`D98y!Db~LL>QhA;4(X@|bXIKrmb~*KrqKm2+clt6dxB+RP z4z1@5znz@Db7a?&{e`247vYk@8@Xq2PM4ThB8%4n#(|-M_B7u9{w%L{QGnC-1LQZr zW=h6$a#6V9yYQuM^qIY?4EL8nYdID`go>q&C@7dADF=+>lb#K)IxkOe5Vg$B6E+Wm z13&p;W+8xWuMXaws{z1Ijxn`cej*73Q@-jl_1#f>YLR#9MstwYMJgP)TDzVjoQUtH z+GM!J6Dk4UshPDnyh~44Ar_#!2H$Q$3PtjG?d^hjj^*Ac!zi!2%Cx0D)AqMI=-~zV zA?Ck|V2}_A#wF7B@BOCELGv*jm=nEYGYNtq|n}Vcan&+y?k=>IIX3=iQ=X%WqTwimY*o zEkD;}JlF=q6jutdjnxKUNHFs+p78oMt3v#$>il{gdI-v=B8;dsIq-y*7t)JB!*PMu zSq_TjdeiXK_60s5kgE0!XNqxy-@!n3vxDx8;`+>{UyL*)UkYd3&nis9ewtr@GybkT z(2T#G*C>RoAw3(Qa>#z0Vw0C`^biEjizZ;}}V2XoSyy%Nak7Yw}>cEF_33;3g= z+^-tP7EevR%3;l}wEXm9_%854!8%?`eTyjuFY4FlY*$B&~vgn#{g9?9GL1bqTs)79F(EGu5Fubg_qec{{3_ zK#|dZI}z}ESse`6BL($6ng;U3X-+ruxu>Co0WY8bbgx}`aI5BT|FCV>Uxo?Gn`M?> zd!;he9yFi08DjsLyq|h#f7M5O)T-UXCzA&AB^0l;(=n&lLT`lCyj9_13=ByxiC=(~ zQOsOop#UQugntTwy+U z2%4!BsY+I;Is7h#z2{AFGy4GK8A>yJ9G zySMwx)k3~#2PH1t6D!zbhdzN_d=_3q+TPPK26{(`>I{64E-YWph)_3KqqwI#Y_;ybl#BUzu+W83nJ&VA0Gw+z zo-|XGHyl#F+I{GvhV!@w>j;$8#@I36lXbLEzDkRnfH5`BEPE?!b1uiUSQ zcHinaxRY6DTB$IYS_ICqM?K~-4{w45&c)mP1nh^!iviL%ccQcFll4;q2UApfS<7>7 z$leY_%BJn=$xvA+5|-FXx~}Q6%#nUCW_wo=9Bls?Is5YokGIV6 zw8}VH=ZZyjP#w7n`oAp+llp398WPLl9Pj)po7>YFIExvi+52Jae*)kcNygm;(FAN9 z4N?7!z?Y8vMOI{d&=oA2#LL4rIz;dY1V%;894J5(h!Nc^{!kGFrGVPZ7RIVHGV#%| zkP2&u+4d-IToAk)@o|n}N})vj%sFkqCo>B0G8z!hU4@Zo1HL!0WI!X*!9>R`q+?tUn1r2Ob`qYn_Zs#^OJUzAeJI$onF+00cmA88~ z+HBe7GgQ$Wl%+-!E2s=(GA2b7k~DQQma6<$E##*WxD|XJtj=(2JzKl`s+SzB2I9wz zd&A}_$f&123lnHbqLfAXCCJx@FZtXqja*tD$*#q6>b=M%1!I3+$@XIcSWD7}J+!h6 zbWLG5S%@WfrIIv^PzAa&jZTF5J!rtHK;s!y#RyJYnGRW%ub6u%S6hNNFSBLOz4L8s z`AJ2u!ym4c0-vHEghzY_IjQFMfG{|JROd>AcUA37ktr@|XF9{o5Vt)vHQAp`xFa)7 zWPat|Ppux0x#f3+jDB*K`2RxuY~ezK>MBeh>twCV?XI0YFV%B|Yt^6c3VWy=vvsld z-{BsX?2GLtKbjO1wdu^L$4%+%)LPSFT|Wll5AvTn{>E_*FKE*?bNii+whvKeudA5L zbN?xKaQ?@m`UUDUSZ+6vorMVX!8qN~YQJbq+G9Ox#Cl^v85L^U4!o!arf`!OF5p|jF*}u z=D;PW5PRlPc~a3i#&s_VrObSQIqYa{H10+*((S#g2uC%izcLPWB|`2b)>6;YY4M%~ zaspQ#4NB1wZcHq^fq_>t-ibqPdY-G_FR@(3P>EzYw9kfMRdc?!!%brkj-$V2PfBse z(xeU*HS4s8U1SNY!n;LY7| z1R3q@!3__jU~ zJz}g&VeQNc1^Zmjbu-&PvlaHnq@z5&N9~vI_QIZcK}@~#0J^!P*EP@@vWq&OWiyhd zQ6I|(wE8=I={Rqaz2hhqFsMcD(j!e*>wPZ;SfZ^;#r2qRTPZ_7Pcd49LdFgCvdsAy zacI-V?s7D5OHi>xFE)O@Gm8w*(t#Fo(RqAZyla;miDgO?L%E9n^f#f;s4Q1)JSzEi zpr1$#+l=)P!NnWD+1I8iPKmkAvP!+DrGU`jz1_xVnsuP7FHi>MYg-d!xC-kmgkFQH zISB3}vCGCwEe|Ucl@Kfx*A3Fca_EVYY!<47g7SNLWamCVR#Fl}S1=d80uPaY|0A5{ zZTcjS6)fI=eWtn}jt*ErrM^>ha0qr4IIcl9T2uLx$5o*Up@>VScb^t&)V~CPP(gAu zaa+C;o#z077W&s6*6hc#MC?(I;Q-leBaIsnn(;gDq)Vj15dE|odO%r(w4&* zY&jAh^6Rd%Y-(%8=@+gbbrHcUP23XJT(x_5*yzV4Njs8WJ)q@6T}pmz-ShR&V4ldY z!GVa*fQXfbm8!NGpEKaYZw8V^@KFV9#+9ntcWwKzhqU!5=4PPI+La0UWv zMWws~%=(d;uh)}&v}@fgu^!^{${@&r{KGn%?C2sT3! zyS161QZs}}H2@G#QI_W0siZ|D(M{T=Kag!zvOy7!TfyYJq-C$pnA=-7ejW` zPH2sQhFG8=j+iWxc@E@I#uu3fNu#1vLRvN|@k^2Y3f+W9IkZ9%ng9sddVC^o8YgyG z9MVR`lCIgKEkzgSz#oRBPS|Tv!N6i2g3^A%m_>*LSq=m%hWq-tjExbnjLvJg3a%35 zg`SSkn_dP07rq#(1j&!>4GQR^;Z@FUuTK{WV6VDTSv^*^Ua!j#QcU}CBFa9EspI!B zc=Ya(7Iq3qluBheth0Y=Zj+jtVT>&TEHs{{Iv&a{l0fZK?n-n@DSeeXW9u;rUjs-9 z?DLxTKf;2^$P?Vc-lessv)91@sQCg1tEeJ> zI&~+8R&;~71v2mLl{NOB+8}&`0hjU1-Qc*D2KaXwc;fk-$flh`U$t++7J;i{9gl07 z6;3+X=)QoL4PG*86Z5f}og#S6m`vx=vGGp-Bolo#G{7`3pdqeG5 zEtJdHo}HRA&0`a2`pd={RA&5uX{Q3$o&?p=hL*aJoV{yD>NRf0r_h0cDYF8+9<3mz zaUrW(auNm%54>*YFdnE4)Rexq(&Q<18%c9ZePjY4dHZdxOyGRFV zj-+ARjqO(bvOO=S6!icyKu z{XZ%vYn!LR10cUbe#v>Sx^@WRE3u6{nd3Q`B#HuJ*H z5-4zQC*ACW`^)s~HNPu#bSN$(=gd4e)OJzdLwAWpz7IkEO7hb1lhQjyzUh5iiGl zXt$yfnC4st?U=(bmR2jeD9KjTsB-3HzDu6I*2iTG(}SiLmgl*;7W?QPXToFh4GB#6 zIyJwZuHuhjR>IR)KfBhJ+r)(6WChRyn|HoP2zNvKS6EfOSVfn!sQ^R~(lx2Q!6(N% z=$mw?Odsi65^RSM)3Xq;*b82zK+g0!z3IyUEKyHg`e;{9n9&b+2;y3aU{NtwVdeZE z+RiDulD<*%vDsnAwr$(CZQHi(bZoO@+qUhFlif)s@A+n(HQzaRGiR>qYG3WDXZ@=F z5717g9n~qo96y!%vg;Kr-O~!Hs#T`W8?7tfX-~FRS2$EvA=TI+JZGDgw^)!Ak}I96 zscsPOD6Ff>nIUr1g9)(W5ukuZGz~9;eNW=fJ0qtguYYGc$T%mnZi%U`DvY>1I&$ca zg(RJ^b-x%3zUqz6=jKHIl*LCvMHRUW*OhpRHgnmi|qJpiKs4b1YT5mLX=G{`w&p zWoJoxU=Zm4QK2*O*l*gEYB{!USA@yISM$M<+HZC~+PpJ#Nr60cV8#TU)}s@-4hENy zI+P2gEQS8*^wzD`C-PDdq1jiWk_B`3SSH;+p0ku0Bbv}y+Exby5p>`Lmt#T;5-ION z^lL00e}vbHsK=%rUNGy8+8-fs_3IpN0>#Ft!RVl#cwHu0r8HY*jwi}&=8wpbI}_4) zesjzZ^9?d&8Pk)p9%%$5k1+VxJi8y~Tgir02Odpwrl@fWSKjTQd3*@7In#<`LAtXM z6n+K<&jZVbGB2=!PZ_zcac?%FAg4i(PS{KX5^7JSsX~nU6ThKA`~O5Z-k1`JQDn<_ z1iMts!;Ez}4*b?J7zyq8=!qPyttPP_&)=3L+qD-bCTXqC*5jEQ2bN(cW+E_zvyRPN5Tc2Bw z_*ysV7OZ6YcJ)ZG-t*9_L*B!`ZeFf>a=srSp9iBnbc|Vx$d)qtb%1K1$||$-N~KG0 z0>y{xA1hkR(*~!Jl2rtUKss(}yA4%WmdAIz{e3iI86ltqa-BsAw+dhOlqk-EaHc9ZhKop&wrSX6tx4hVC#@ z4x)q2qcAd;6YHw=R-}&Zgn0M0dW(8zmGBdMGH@offxjk3aoBK4_35G7>I2mzJ^#%!SE8zGeJO_I zyIO~-L-8y+WLrSrQ$iqZ?Jbz*;;!x}ODUMhHWO6L`tAUg{`Y03I(O(LZBFQ8&&JJc zHpkh_jW=J|B7QcPlLz5$Ql9_oVsK+axF)deIF>zMSYdTtstrg^gAwm+~@U1WCkbSk`x+_c#N@=lxVoOKSM( zHAD(4iUdYOjF)GTf@u7Z#f|=yjnVq^g6|>n_S!AA-T8qiQ{4l%EmP=<*^O#%gab=Z1^Jx3}D+-J*he;=#OI?HX1FdFC*n18U zY1}Z55y&)k?_I_Q$zqAiNI)e)xucN2GO1T2fH6ap;N`VzBwPi4Btnys7K6O9MROh) z0wa?|F`t9V4{*eLG(H0}5=f#24*5)?nN=>imwb8tSU|JMgkpcSuRmf`_f~frRuwu{ zt8i#TZxo=wJ8>i+m=sNuf+(gxV2T0lF`b8Z>g(vU(<~IQ3*z`xquVd;41r#7pv6do z%Y>NBP~oAFv!FS12IW|WONCW=pJ7T2N zQw=j59A^}OWxr)4`1T4!i;lXsA3GIQYvDJD9q)N;Jl|ioyMH-pKC3KK*=h40c90Kj z9`SYH$&(m$!l!UGV>*FD4)oyZO=YD#9|=bJhUfF>DgMcE8g*x@7~hdEM+Y7ONJq}k z_hSOs18JIX2x>;kYkNC1M((+=2{+IKJ!aou6r37T_4t(LE)r36Y0^$9C;5VlK z&Tne}$!|@NqoJ#o7-y!@ykkF%QR+$mli$cHzxk~(`}4i0AZ4g?y)gV_Zw_ZBo83N4 zxEF9<%6vU7x5{4WSNxF7%i8iX<1H@e>}U1#$K-sFzV}n?p_DW2`_9Zy(oZ{*3DYuF z0hC8oJV>e(#M(a9Hg!}`*1=xH5a}jccDU7TAs8KBqu^$>GNHT|UPorFeAsirCR9>B z3f?-0Whm@WaaFZ0tW*Zg*gllQ(p*uty($DyPM$>9#y8tv2sI@el0zsx7ZnZr^ZSd> zC^&nVwb;Xms+!X*G;pplIrLcLt+SK^Wpp%n)sfX(36s`i9xz$y`iMgVznIoiFUx(U zLJa6q+{=JQqT`l#GX#FYrhg5C2?&RYHr-OGZvOqP!Co#5DlM&Qr&{%}&_#6v15W&x z9>qhJMrq@X$t71kic{B3cDrjM=Y0b!U3EK{wMKA@e1p;si)1dL687pJfGfwUD#w7x zRS)70S7Mq(=GioIO22g8D1GX3#^doM{{EH|$x_Nm z(5XrP;m{}lmm--cHz6kIm@H-9M=0PI#Y{j$3U%hb0lK`-URxaM?t&CaKZyQErq0Aw zzi3yg=Fq&|A=p3sMw0x^Z{*E8B$pg$L*t=L@c;0e0}Moj)PbDH&k|Vw-+$TE`-WZ; zB{%{nRV>N+7V~MrA)PD2n2-fWIJ;{>prE2Ap&b@lph(i@Li%;6==zj5Rmd|)jzB{R$2m7kGh^B`2|97a;Tl#>+!_}s?pVMv{u^})a) zn1h3?&$CrJUrJUaOEPJiF~Nydyz>5T2;$2TCU?eh9H=!H$>CvOu-?C5C;)`^`3+2P z4f~`Kg*pkkdBPzRl9)ebQHvV&q&Opk2VFBBZcVDhD6(bV1D^{Op&_{*{y23C{E2b# zyh)bV-k8)y%HNeNr5Yaze8Qa<4 zp4To-u0sMxB!eQ8+qLBX^6=BW$|nnC{K3W5PD@%G_N4~UH%1YA`UGl!Svo|Hg{zCo zclVjo=J~Wk>-qt;bikYczSr7HOdp|6O*dG^UcUIdaZ1@o6)D4MLJ#;vasq ztpDb>SDOFex9`|QHdgquwM6j-`ng{Gz>Us*Q^e0PBFenEYEJ1n#I4z)zYi8HW@QiY zs8XG{FwN>CU3WwCf^iQ^_bS!Mzt(Q@TE*}$yIc%j86A`Wy|00Vf2UYSHi7VXXVsz1 zqS}smuHmcM@oBps7G2X-%&c1sk&C!31J=OYB zAl7@B^}L;Aum5p@Dd6pCKG|;w&-ed(j)9-H!l#1ep)AvNjv7=6Vt(^$IoB@VMRInW z#Kp3shZRu3-Wu3NY53ii3BkqP9O@?jTsppq!LinQk2)(!k762@xyrMFkLLCvT?T5Ghl$Nq~KRv5KhvKxw+Nj?~f=0$mhF> z>iUu}uQM;2%GpFl!&7g7NNE#Z$l}@#>V|mJ`7fbwSew~O(VriP5lzk3YD>OF=?_uw z==#xbH3>Z4?MN8F&h-@yOPE_lW6QYIasIGcD%*gMPD{JwS*M+>zAfsp%E0oY&lO&M zm~^Av0>u7a3#F!tP-q7u`!evnQ`vMHdZrb()Gx5R^sS$W=B#w6EK3Z$VySi2K?!oS zUL=kq)Ik7rpM#gn`z+tmVgr9rGL3w6e-iShRKBYXb(BqrPEH$QHC8Xcjwh z=OIFrVYeVrFvHF*h+Z8=%@T)^kWhliCyS#0G*c>+Btwya(c{QQuo3hbAjUvRh}O57 zok5I8h9p?Xk<52T64MkxE{%@_nxuj(F}12wP$uP@{+^$hKxZ&5(mv4JpEIg+tuq0x z4qc*MJg}{`1}5}}AsQ4oTgFCdJm4a_9quroPLo9tAp>KLR~mIp6>0Q#k~GI9n?aCO zCmq%~OeWZKiXyk_KWJ^DBS#4JU$h4Q-4UjU5he<5beeBS3ZNC{XAwfJ4klgU__TMe zmoy|>%W5woVak>sRxQP(S!8i)lqS3J96Q1ts&E-FP2yxy`~{MZr>Ma3*!RGbyd^n? zG8{6-7F9M5|LhYDL%0Z3L|o>Yr7&H#ZdkE~%yPcpu|McGeD|BcGuH}uoKUe_LATRT z3Uv|9tpejmYs^~`DIsxqNkm z_VXLp@<&I>wZRtUml&aL z8U2oH>K=z?%=e?M(d|48RKKwQyIe6|gzjAu0RfSw0|ANu54>CcxA8~bkMBy? z#$G^OU&VtGr5Wm^+v1QMbJ191(TmME`M9HZH#Y8f!8~^4Qep~!ZSvR0H6#!SY6T*< zBw$CURF>q2#uc3#M)a`J(|w6WNK^P&Z;#~A&CHCocuvUv(-2CHfyTDio6-_FieQ~F zvS$OvwimHaTwTY`SbXwWZx*>9CKNknq~{ehKawLyd>9_@?|V>oFQh|;tdY3(hh%JI zu}6Cjd87#zoHt|tGa@+g_C#_sJ(j2BA?!#^)SY+Y*MzNh=)cFnIpZW<55d-qaKVZ3 zxkgta30+45g<<}A=14K39BLWxgNfv&4;;XSKQI`?)^1ciqU%Wbk>rrbKIfeGTJWQx zfrK$n#`-CO(PKDr+CP_~D~BWc0wDBJi3F}K5XLNZkOIWM|2zT`$zuwfnKHeEcB=)w z0iTdNvLDLqe~5N-hbRv%2lhxo7%UkgtiAc3#P$NYpO9#UBYLTMHwqrbCXpT|@QSs+ z^5a1;3PiwZw7-|e`fffDYx2%q;{fSTcFKLH4|b=x{C-n3_>le^S)^qc3sear$m=eBynDtlVdd?<(E=xZ;0YgoUD-U)v{ zuaKo1IM->-)-CQQQSY(`DSdh=lf{WE=e2Upj^#^A^|Jy(0UlR|1b&*yjz#x@=wS&g z_j|VCLV|#ew^(=eZK*E3wIc)?pMY3tz z!YCL4q{HSZ3oWBd4H3K9!XW_)^Et?3R1$Q{q9e}M(apk5^ipFfp05?je;x0rU^VGL z_{!QRVXMxLvir_RfvsL%D)SHUMJ@YJby56OyQ{%NZH3VW#HWt3K~RlPk? zx^oYYr|fW;>Z>h=7$T2^R*Z(1y5AUZyrxq+Oamvc^E?uLzXBPfQ84&|hND=2g(yOF z0{IFv;A7z_JmuoUkvlU0N~~>Ol0Iv9QubmM>UKJkFOg`5ryq0QmJs{zJZnFYXzQN{ zW-LP>nA=rQ*cV*8_0dQILhP2$dm6Ta`(=r_g3NufYRd! zhf8k<9g-f}k>v~<9-MY^JRPs}PP@-L1aF*04t|`R;#f|3e$D4jb+_M%QjZZU{`tEX z(3eLMISri5HZ3zoSQ*O^z77HHGE9pQ4x34>0k&l2y!HN8?Fkh9f$9ryC10LOeQ*P@ zQpW8deFsl7EUcj-iCm9QLvEl3`GNSv$3lvnZsmxMz`rjMmZlO~POgM6sM&XIq&@&| zf%`~f@nS&osp?m*f;7gEGvk0Jdn1%MWsagy>%A}x=`ejDDv~l=F#mxX;(h?}32DGw zEEiN^N4n#}2JDJvpB$bk9w+p*otDIBlr)Zbhaj*Gn9WE<`vXW5(6_|{7n+4&y$$ER z&^ZYU*Uq=3;?pu4UoI8+N#a0IiwEUyTM&We4s`<3g%sj=*|`LwF#^99Bxz;rb-Eo~ z6gW2kw2e_bkO3WX0MZ^2LXr<17xCfm9W2tkYr7rx8KLMuXGEcCIC--9*=bIBGLtq2 zAoiq~m_#NPaKUpe-{mG~ycD=f7#W4qh^e4BHXD5s$o8LTU^pRIIgWW& zC%I0lnzgv#2R9@5I|0tPK8QW1K5U@QFcB)}Een}9qD?uOk@_G01pIk`$mw8itTl}K z2`0qqwzx6iqAV<_=C#VCKv2+ASDn65!sFK+`JT}evR(E)mNAi_d_Mbi9!+_&v6cW{ ziYq;_cEMlQISUtcggDwP4M%PoYCxzPy``c^9|X>Wtbwj{X7Oi%+ZZ5$-K?b(eKdP# zgHa&a^a`bkjXYbtxbh*)>+Nt%KZ8=nKax5HghVwd!~SgQC?N+o7O8yt&z<9p6c0S( zmjIHfb@#9OLGo^Cj%wm++BtJc5v^&G^iBG;rv)3al5kZuqk?F!C zs9`c=;86&EG1Aoh+GH^J%|bm%O?l9=KyscyGn`etYT3-6V5b2w^4ZS3`_U(yEbZFC(YwScCxQEMniRlq1F`L6JeNi=Da; zS6l4)&M?PhWED=L+c!*UELew1XZ#3O?=QIQ9wG4C-j0`5G_U-eR-{AT zkUC}H|PX4qJBybD@(aVU9D&wWj(y+sACLpSC&S=-Z~UEuOci|aVL zhiWX(l~s}>!;S}*Z5vvvO2R{OS-yEFggk52GQO-JBR;=+xhc)Gor*A9z&MQXi z>1ODPSx!^J^xpw_WC*)u@*X2NF7c%}4wWfbCr36Ay(+KtK*#~uFs7r{RtaiumbIVWydQ3R1 zB6wKPYF`OMe_3iF##FBf>lL((Xz)5VzYbEZ3V`#;NLCq zQ(Thw9`0~1O8WYan4gNVzv~^-FYg151<2wKFa%(dpamQ=!O}LWGu5bpcGHQ@$BqNoYh*2ZG!NuS6KOF!w?Q~YK{KZ_G^)X=Y%m71b(97 zS6w>AMR~RB$_ih^>yHnW5J}S184MYm`mLNkB=|`Au*@~ug^EeOcR9}oc7JrAK%h_;I6blY9EcuK4)6%BVBE32?6@<6Y3R?n&;G-p9KxxRSedkJs zjm)dFZ`5!{^GhRpz4f(SI#Wbjx$KP+4K|>2SBFLojQVT}o@3=Qzj8{#0JXk)>Ni(v ziHZLa+q(y-jwSbUc!d>3xy42T)@2|MP~Yi2g#lZYap)#*a1Jqxa;-lv64gd9|-Ew##LrLkf=(&Xv`ygjBX61dYtHs4m@;$DQzM+Wqn> z#|={bE{`tUH#O$&UO+6l{a5rbdHOW==;GD7Hcw)6khAn@*nz3OrCbleEqnAs!H3}< zb{1(e`_X1C227H%Yq#fF5dIz zpr7}e{Vn`{9pKuy*Y~PTKE?2#OZ>-k!!FuE%1pFrSoY9Z*M(3Ve6kMODNS5?5ojL`pF5F=u;7XrmhZ&n1Wr zs8>v&BDiHY`A=5oc~xRxo4>shoaAh`kb@B=B(C!Mhlwp3e0HrIAcBu zI|V#!<6&e2{_wa_bu3%N3Wz}G@Re!8S{GrVA;iNuTG-fV1+|pq4>3J`ITX*?*4F{a ztNog7)K#=XpO_R&MLl|WV(}ZbF=iTlEkDUt44XNa^=Y~1Pr4Hx)GZmx*JQ||XVoE6 zZb*MK&+&+77{_yDQ+-`M8$eqxz{HdA^gi-li5OEp2_yGM5-SDMDLc8IAoO@e46P+p z5RzT-H7YAZA&z`54>7i-;3hk~mW3Sc*#f(fs@Os=OP!6N`OGrgzN%ln&Dh>_4rY&_ z=dJvyvL!)1_Zrk7Zj$@N8dU~+;pCuah+^V6D4Bbm!Fs0mZYeO=Vci*GcAQ|(SI3P$ z1N)B*PGQcb<}(TGm2r)YXSnQCYnv3<^j7awzrTzhuUsFmW-YxvY~4SKT4>1TV?0Zb z60Vg4Zc>T;T!yU0yEN^joO$1kG_bQ&X8J6`1E-p7%Wdf7j83=kxoM3>51r&dQ8V8J_{VWlJBwbEBMx*=Uy)+(KSol}$43I|zxdpKQJ02k!8w!I{ktAfk1qd+S; zUNZoz;xEf>_dZU0;48%&7Un&8{;43-+RllMM3B%AbJv(|6Ndcb7S%-yR{6bs12Fjq z@1b#k!(+lZGI=nyht<;<0*I{eTt3uoE~C4kik5Lltt&)y5h85qG#_1n0J>lml*Cdr zW(sbo2=M%T6tvcNmr1vqNT~_Fev4=uN(tX{(Apu)PnQlL2(Y>igz}$LB)BvQz$v28 z3T&}aV67Qi$IwnntFHH6k?2XKEH+ODOSzErZ#}(Mk(Mu+ApDS!qatfR)m8i0FCtVv z3ERQYCns|Qe`kBpM{8 z5;Is}V^~mtXC^L{zZske&qJtxR=!-7pXWvgsZr{vV2=-f(XDq`%u9jcBx#4GOrF%I ze_0B8Z;?X(1|wWv|7W*^j}w-ExDftHi)`cB&cycXI(rnflG`s zp1-!WctMZI0#dOOxS8%i-x&mqnH6p#^w3~G!eZc1IS{~pQV&x^SK!<1iA40;T!}@L zdH;Z@EfqKP{89CrVw>L1jtk?&&KDfBGjHw~e$%%DB%pSGVL6y?SEA*j@1-E%lo6I7GbL3>sx1RVpNtdqhS^YI7$@THiB5VG`;Z@g<3IUi3Eb)`xm zGpwY&)N&jn@57|m{CjzwR?$w>9scnHVjasFfM7ze{Xt}vS;1Xl}yLAEFUYwR|HbIvduB&4YEqQfbt0dAtPr{+O=wc`49 zBW{_Fap**TH;ebK)u(3_MVRVL!<8I@aT-OToDjW3I#oFJp!fPDlFKL$le`1xVMjz1 z%tajy6S1*d{Y1mNR6O((Z9?e&?oL7Oo-#v)3sG1s?Obog;tQ66~3gyE0=`V}1AyL7Ds^w7W$zU)LRq6=z|ugwEuG2edmz$yut>Q?MOeL~(sbVdgbC+f z&E}iSIHe?Z>@Jgv@l|r-s63)&L$Jx88oa^3`>Xo5kYysWHI)b<5Tw5iMOXASgm6!A zi-0DulRb#OQwtO;GZxrmG0ovEfW7-#>4tGN6)(R=Ph-RuAy(qui=|&aYQTG4qJVDDr5Y z?uEh^&aKDCWFWUAjwq6OY^~zGb+S?X)RfYoL}KQv9ou!k)aco#)UsKuHNrDSK&WnQ zEy`FGyooTx-hyeoJ;V`JDjUqPG>U8K?pCRY`$o9*18**Ic6{7is?L0KY{NVsWzuu< zew`CqNzgD_@qt`m@Y=vl+LZTpFZjc6u1VeuMudWn8aJBn9XB9R1GxC}vq8(LU8w=>cHq0r<-d z1;49gcM<9fCd^@Mmv5{AiLKxy_eL8t+oF`pnql^{AKQ4)Ja8ZPWNHl-{qm8BAJ)(h775~F!TmyH7<^#~A=tUeR!mdAlxr>lj$K_QXk6B_DJ6Z6k)e3E(O%mhu0 zvDEV@11Lhk7#$W{ExE@Off_c)VQpXwCmqnC#H$s=Q7EJwd%`UgLr+S#B+N87{6(wa zZ>1SDIgo%KR)#NdR{)J`P?wXVcBzLkIR-1`f}dmJGn7Va7rYsPI1;5dx2aT->B^%*^W_oram@UV%SD zQb}1orv)7+?%UrPoth~`-)9o~wK0#P&l17Q1QOYj^xg|D27vJhd*SwwLEv!HC+r3D zAL@cW-<ddyD1Ip|f%@<>-{BoRh4B^=A=FFM+Na**lVV za3i89ej+|N2JtByRDqnWbm2_LVfg$~=`N^M7NrIu8 z5n(O~VofO`+^q*IxlmzccL&RWHl=BdsH0MyYhOA?X%M$%B;m}cs1c$)0R=<-11R2? zmQc^-2enyJovRAVr&0h6qpF zKvGMeOzcaSwnk5T3P8I(_)^O}hfIM9?GlQSja=KlJ&X=gNS5Myak3Li~MqwvZ#HA4!3V~ck-hIol` zXwaZ&KJN75%PmP_Pa&V4Fm&TR1-s;@>-cIx1g%l|`QFcICjXu8((8WJI#5}p z{H2p8gpPQqLy_u3W9O4_YT@zlt9HEns7M1hYcZZPxKc3}EXy-BkAyyXZJdot@h8h{ z@9-jIX0CaUzH`9{w=tGxIm30sx%NtfNf0kN~v@$(GX%dXCOE=wNm2wJN#Gi z;?rCKk@vxy^Q%*p@)CVzGQP1#^ zv2~D^hxLg2#VH)W%yaIC@cg}LAF-X3M9#8{SDK$cC~3M%61!2AjnxM;!l&R%%%|*) znyF%6B(gm1DJ#q*nnzIPza0zEWhre&S-)4)33OJj(|gQMR(@tBe1ZSFu?D&=s+#`W z2RQZZ0~Gt8GS*o9=TvfuYQNn-88-km#JK4q>y@ayXe$MQbhE5Lnod&GrSdNc7olpI zpG2uP^=G~AVQNO^(aqW{kfA4VyIr2lIC5o3ZQ-XgTl^lcZ;NI6BlQ-W05QSZ=Xdeq={@d1GUaP&^zY z>3J2D^&N1|9fYv44ck;%!+Pa?%1EhCWIRB3yCKd5?}Zd++gknRY#di6&<>^>@zEmR~ofh{>x{h0! z?S{mM0uu{*k0-q8h{<-q5~S@|52dDwOlXH(yFBpEO-3f~Kuhl6+^j=cg+D_idUK7V zx^fjks_!K$&T>Cnbt17F;nkb~halqW&0iGO**VQUgpR_V0p~ER+M>9|(H$qdv4FTL z(sY7{-y0%9z_qJHz5CG82CbsR!5sSb;QBOZG!HC>LP9B|?b($5=AjecroU*3gZ*fO z=tkOl{*@p}=-)s+T4gwY7y=@ghBI+MXAhbsJX$e9jRexDK_uUzs2^3{I6^)Fl4Ga! zMnrlCvlb)DwXK9lIaM(O)6U3twAI7~9y-N|0j`8AzfA<*NOeXmhtz2@2_R!&ufj}W zj+mqt+s=Q;^^9ly!kJkN{V7~JPh*NoXOivEZzO7&tHu}=L9)mQJkA=;S^Mq!lN2@L z#xo!VbPIgD{(jUHf}gzZ?=JTf4Tl;~AH*e%8Ihr>hZ@z7J&=siWw!4#Cg&4Qn1Pv5G)|!VN2@2&=l8H2^@yyoNpJ1y%Wr}%lL2I4|loUXGrK^J6)B`8Rf$2&1r3nGd0HbPBx&I}lf}+!4G?cE4M8^`A>a*A7?7z})- zs7%2;wU;*TsCxVR$N^ZR z=^_uxP#oDP(kl%JJks_RS^n}`8^cYJV|!bA+m?WF3K`yEvi00Bw-ziZR~PH-3-{~zk4D1XF;&ckdU|z6NB8CK&tSMdNJiVWYEj^( zQ=_{JnBigoBKKMI;&#oqu}tW9ZOkRNGv{Mz%P$-7;6($PcDFOBYjwI<)ou0iO}lH5 zcIFS(=G?DM1m1$`&55N_l@R2B3zn@jJKJ|Xb%({4w$g$0PpzldxrjxU>)Zx)h1Tx` z+1NZ`d@q0%APJE$PXbiNrZfhIr#=9U#>$PkJC>%B_Ex(@3%Nv)kLn8M<%=&Pp$Sn+7(UN?QP5$Ueq~MRQM~1 zz;39uS5~MdOmtkc+H8G`Q^L16EnyPi+=g3Ue#T{)Z))z@xk&nkp2D%}h~t{FcOP%5 z0pq5_(g~Q5-_uO}+yhX}%6U#1W#k$s2&UA`IP>XCXqZS&IeiEB53Q)2`KV3OV1w2X z!SQxpzUw(4pHHdGg#^+-^=p5`d1MeEDvxJE1(Yc&4e{hc24E(bB?Ry!$GodFVngaSQX&B`w zz%wwnQ6)$tMDkvRZr{Y5a#C_ogKi3w3EmvK$VJa~${AfU>FE`{AX0(}8cL#CW9SdA zuOS81)NC+qwShlsJ7O?W_@qM|7UFjYJ31wmQ!B}hMI?opkdvka!~;!q_jS;58IREc zEJ^0w2wIRQlOu(2KAz$n$5!BNlaPZwp*-p2gAu7`8lKVg>>Qy9*1`FjcWz0s=OQ=F zIp1T0jBU@Hh`Lh{t&tyO&$6l3n?jp+J zZ0lO)@anVfopR}_b4|ozZDs7ZvUjDz@pYl)&cRi1o8mfc7KE_!Di02y?^RDqTWJ;q zu}?zYjZO5P*QigxmI1kSt>GtZ6sf;o=Hf4k+Z(^{7aV&Oe0VsBp@r%pA{+dHpH(wd zuEL=uZEATChuW&--z?8wbL*=I^iVS!xK zQ}f(D{qV^O>f_~?Z3TbN{skffz|WS?*C%|r|CIde@4EWA{=ds*IlYAn9x)J5L>3T` z;QzH;+B>=YE9v%s=;XGqwea^m#hJUGXk9Y6aSSLYv%5P1;V5I6#p+tM>43=y3cg`m zFk9V!EM6qVQa`kJM=wE^7$II_r< z4+?#Rq!g!f*(Iqv2sO(FbA320EuOX(@QaQ0{%90=uplv!f~i8trE|6yvD2uQlZmt= z(H^%QG4@&@J&7|I*Xl#yBWUOT89zbDWIJ%7L* z+g}ZnT)~s>!iRsSBf7sgi#vsrTL5Ku&HPwcb#-FF1(6n3wkTYyqaEM3d1vW3 zgs_>8&NEyeBv{z>=h#`6tl1-Xca?IH|BgvO@Dn7l$O1E646;BRge+0+^*Dt2RU!9P zS0MjpU2GnsmpI96j3WMcE_@h^)w-!S2NRci_j7`-9y~pyS$cs_S=jn{OKkLwC9DTf zM>U{z6QA)xwsTcFD%t~L_2UM~RAJb(uCvb);93`bB(b4vymlRtYGOzdYlH;$feT#TSU zhK(OQ7Kq$GyA&?GXGK#3?j6DV+#<2>1lBC;PuX-l_=R4Q*0w6)&>NRADhveB6D0jc zo|?VhJIphkA95JL5D{k^44s_@JcA-Y!4bjYKg zdP5-n8Q{O3@;2rj8o~*_`;g3=w%d6&!?RZSNT*Fm+syCI_=?ST)=-eZCQGd1$$^}| zE!Y=oO=HU`~1EGKo;5cLhs6rS;@+kc2-xi+mmdJy4!%>8sArwJ8c)7GRTgCfR zKDD&)-@x!In702=iqOVNJkrAy*si^(yEV?glr~bTK>Teapsn_W+n2{2(n)Qhb3&c?t_?X0Z4TeL~uFYyCFtG2nSP?z8M!sf=u!wKmF z+AO?lUPm+0A{empZEh$R*G7SBq!~bgRqA5}TBXWz+Qffw-BFAVh80`%lYKtSlo zC=TL8x}JLtVg+gOmlSzMCRHie(LdYme)j8--#q6X6zo}4i z`Ah7x1$DDV(zBRf6;8x-WtM0j)6nU6)D;cpMN5SV5u{thPv&~U$tin0R7h^CD2V(9 zfI0Z}!N{A=M{4k(I8~|CQfiKRi8CY)E{?&6FJT6P9YHe&>NCT5Nw6w`x~y=1qfsZW zO(Bxz$b;%`6PIv7lwHB_&jJHV`0wd-a>I;Z=4DN*rc>XHV$elN_1Wgpmo{CXGw^3? zPUfY*hVrRkY0PG&Pf4EmU9PxgCm+eir&yh_mrd$t_86LiO7Ceu z&sn_KtG-vulP&>lDmt9$3|dnkeo6w8H`}+gq=x?-^GDGWBPMTr(jfB- z&^%CEmY?{I1Q-0uy^ePqb|*2T6jO#{z7Q)TPEU+kz+M7^KH_`HxD>_^)wujTq90Y91DL9Sz#$i7yD_)iQ zbUFnpay1<`fvY|RTX zgw_j_af*t=I0pRVC&K#>?R!BlK=?2kA`tisYES^xp71Vbdj}jlD1HC1fqQ&4zZ5k` zus@G_PqZZjsR>pH_OP>_jihQ|+VIWAi48-qMSQ-HiFuv9!{gS+qG@Z#ReRa8wvtdQ z9^2m|kKzI9{^!02t8Sr=lt`BoANOr<@U;r5Ruo-}zJ}FVEI3TqyjPn`bj*zT>>Gt0wmuRrTs z*HVJ;(p~%lFL>GxKhM@MXvv^hJ7dkv+}d0V9o|gMVDg)2%8iad^nJxZ`Wv2!$kmb# z)=MUuht+9@;!wGGXSTkEy{9>g5i{f1`>F*amh<_8fADOcAoFIv@|A<2})Ti#c(U#1zTLm^~4#BukM`49OOGzit9i2uTgW zLjwE{oz`~w8g3FEK1-5eyD|8a?YFC28|>=IU<}yWD|&6eNIh9MZV#sWW?2&a7uS{C z9~;BhXPi@?7&H$w?YA|!2p}c zakD8u@9Tz4M#CI^$$VY3M$L?aFE;#10k6UeaS5gQacnanKW*bRRM*m7V#3 zJCKLo1251x*=`O5MC2V!X9v(g(8~R2YH1-BLPKQwu2bkMVi3ZA=-uc9(B$I)!2qS{to{BjDrz z1r)v>F>Y@+4_~7x-?SJxTC!ONIDm?n^*^U~?)$hJ(xbH_Oey(%7dD;wYleQ>7E;0vVzn})`$2D>t7 zg#(+zJbt#OM{KS5Z6Q-Bmo18A*sQ|;7Z5PWe=pzvJEnIy11t)Wt&@>ExqYjEQTZC^ zRwF`R^!CvHfI+tU(7}f{|2lTGTZ~1;lhs}~Q^(nflQA}*Y}gJny;u+a#sAZ$o=ip^ zEEdJ8dPZrd9UHS#EB21KB;d`=I7fE6dU9gGahbP<{Gtq&PEls$ z)5+QUPPkiE{=#mnj5Nj{O|#crsK!pH>ku?LJixfVOd0cDV*YCrbEzL?%^$jZd4?Dv!s|u^@e5f7ixF^b&3uVmtLajhI3L11#}U9vjKWH3=cQ6os;2C`HA3bt zR(QOhQ3owbTVdY|fPRv%hF9Jz8N-cFaLq`q_Y_<}%Es-8cH3>C_+Hu?;vGRjv%}Ap zI*9??=xC1`B1e^1NR$z+DAL_-F&s>bZj8qevXlhk(x2SjnMNn)A^j{1J!B}cZr+aL zm>?Q%@kQ52oyJfcqx6k=iUWnCh4ynSf5{P~iT>tUv4~x4;1;!`D2*m*eo14=RQp$_QPN%R@sFEO9)C)885jfbnW%v~eWL zAu{yI6_*i_m2qp;C>|@j&J_4oRV2wwZK{{%Q8QJ1fk-t&wX6LlV?yWXdAKR6Xk(5t;N=3P+2AOcYS?w4jP#z9hFbZPF zVuvAOSqtM*({4?f8NOXy#7tpBS7Yd{y|W^X+`>N~N5M%FL26j?XW6E4;?|7RqoUUv zTC7n!dLoFbD@ynk5#6GVxvjl%Oho3$Kh3-KNwPcf3e{I4$II zlP#3B9PyHJKoo%;(vdmGf|n7}Xs493+{bF_o{e~CnS_8RLHZ1&S` zHyGu^e^dsE?o|$)QL_W6piHQCO0u9!B%FuUjY6VxkHS(yl5(OP^+Y-fh_`h_J37@Q z>)D0QmpvkEsP7RW6i*2dH4Ax&DvKk?!l~G}(ewzYehnZ|+nhcv`0-#T}Fwf~!0$ZBw;vv)(7QFtKUZ6+JLOFP!_KjS(pUT#y z(LU*UHxaPLT;*z?r`;}4=lk@lm=p3q$P(2Ea#zg(R+2691+$ncl9|iGRRL`mbe(1@ zmJg>gc#s*-5(^1)WbBfElKa+{zU+Wa`f!hZILDTp61_Ob?M?~wCj|Z~YDRG%E)wP^ zF7nfY-%be4ILH4T;VKMv+o!9%J@vzh2RWyy2a$LwTql!lW5&DN@84q7*%0M^cJh*G z2zJYwxmXy2Q@hlrUy^RbFpedQ_Q+BR|F>P}Pc__blv$l&%T#UGyg5deJ^Hy*AZ!f` ztN^}Cq6_k;?D~?UraoU8mih?CZ%c4pIR{XR>!PWF`0eLnfr0`!;65n6>^qvjp z?yn5|o&})-RbT4?#SOAbYoOL1&}sQz0@nmrJ=WJ*8Jva9Rnd8H-&>+XAg;WF4*G%|b(luCDjeU)!*v`Ii+A6m8KeulgHU)OpvEwqV z2(~Y%N(@xm1PoD8gpc_gB{Hv%jt=3?jj`a6dZ}I=*vbrVyF@{;kqPn!!E)``$_PD6 z;5#ZDt2&p8m%`1JAs3c6>nVl{WO7owA}IY!jgO%Yk8X6lRHJmT5ZBI#P>Flfd6Rc^DXrFxBBU8r@Mb z7p_L9`QBV{lAy0fZI2M#p%~BIJfe&rpZg=S_2=p9r7Xs?`$00!`}lribuYtthU*<~ z9bfkU>r=UZBWd4Y%1ZeT^KZc2S@`q#tR4GOI{53w;qldy`m?0_v2XhMDqs6Uv#i#u zd-;SLD`+KdPkXc{bZ^#{vU~eV{92_-zg@qh*iAnxJ?``2cdD0)>{ZGU!$E>tju5{) zxj+aR_?eJCjTP#*O>tUye{;GwHm*+z?X99gF#&eEOs~h?GduN_;!x_bbh9Y^Da9#S zr3m-5mwl}gh#epF==rI_dEPG{TZV%0uLJ-Q`S-_!$6so1%Z%rb8Q)LF zR-srG<}C*FNf7!-E3gQ+=U|<-;}D+D4%-u0Oq~k7NW#3SZsd=DTMkVtXpU2Cz7O|R zdUZf(cFe8(DR-Ssu}eTIZ8t5w{0T$E$aA@5UyAZc!Q>UFWWss9C!zv?BBttv$ zd_39CIT(7v!?OjgWh4s@>P6M^YTqO$BcWmb>06sDWPkB+*5wQ;by-A&xP=}<7XF2g zXDxuy|L?yI8>}x?#(zf;m9JlOU^`#=O#6DEz-2aRIe%Rpl6+s7kyBzanEW$~v!PxC zD|M#4?1utb+P67FE^*w$u;kOSLw!)Fk0{dZ<6PivNOx&LZA4EiMu+14&o9*);B2OX z>XIoB?|7AEWPd*A)}q6uNP>b=&PN-RQLmA3%pv^WXrv>*+LC~^ywsd}Qv0>)7m^(s zC2GPY;LF2jU#P7Fk~SbZqZgu4+BNL!m^1h%V%e97KEe)j8m9JD(7I~}Oc8 zcZyVJfi!-cs#ZG+7au2^h6-OLA}yV6&xZPZK2vThD8RG}sf=mW zu1zOgS?MeC|2J7b-ntLNmkrOCGG|2bq5SFPv-r)+XPTyOqns#Yc>j4Ev)5!JL-+g8 zjkdT%SFI+74BdJSK& zxp&~+ZTiE%UghIK+c#VLe8A!xrwxnLKT!Lv`*NzUa<)MksA*q?vjJp`TFD(+B5_2i zP`l(D&}ub*a!@!SB5Clwr}?wP`P1tBxsmX`^FR6-+h=*OwX+kWhwbywd@lDI)F}xb z-k`MqyBUM?I#XiO{0Oll#kNmqe$>nrA1`$Bn~hJKMG((f;0PmhVoMov#IWH&y^!J9 znSY*NN2|5dQGgH(1!){=CGq{c0KlJVdnS)dNu8m1Zr9WEATNC_yhq9bS{`8g-*?Bt z1u%a3i=f2gv!cYo{Br4$+7dWGJUoa)CSOF68xU$4L_O6Ib6i;wc6R5S90A;RwzDTC z*3sItn$GhYm1|2I^RhL^W4KW&1iI$W?dtQ?V{q#n&PL%3@3Jp~Y9^#|T}ck_YN7g@ z@SLK0P!`Bks!q~6PE{%p9Un_I+koe$tA~ZSB~Lt=?Jwl~dm{trV5w9gO{~$7>$o-E ztx&;J0n%?kb?6~SFD4Wn{WFp|ByR*YHgF*5oyEh)AzZpx@?Z^#S>)5Bt*OPVO&-Acx^Gwx;6%0@W3<=W9QXtRby%x7EfP?Ifi(ivjXIm&w< z_7zu8^;z_*6dY{HCu(nxJt4l-a#L>4Jz23FlS3Ig?jGZDf4%L!$@eEL>t~v`U&~T? zm5A_b$gYN-?l@&$2sJf5fMx9nFZT;k@^D3v1G)V%;!A-gZKsn&)l@7}h5S&nJo*L` zBK&F#ZcSNWM5a}fEp0%9BTHK<@Ue%_0eOrg&-2Zi?u?IP1{uuTXi#1F5nvzuLSYzL zW%1G7gn6A^shVIvOIBZg((p4={d!x^lHhV?Z;Inbc5S*e5g3x#cU)S97_*~OuA$t> zVw>3)3=mtG)LP!G*c)A*)0P1>=7L7BpRqUnrgImwbR%Wm$s$ASZ6lPivARz1{y6xq zm^guQ#Ft>CBVroE+~V?Q+dkM1jFApbiEwZ0Z&>+4*~;_q6It^rC?1cNdgjJ<-+b>r ztp1ElSG(Xh?b6FSdua6$tbbh@N+610P>Rm!@7;^b6ljjq{leB;xqk3BVvO z3?COFk_>`ukxQ9lH0I-s7LRYEmm#*Cdt^X6HuN|@=6-V1I8W6>p5A%IbC523DE3+ z{g@YH-Wfz34TYre1OgEgea{^nJgS}`TDzX$6j>eCDCR`-1C1;??m1ljY%(4&CHJ00 z4C8LBA|w>V5#SSk%2hgL3vu4e$KW-d%*YP5BddE1w7q!RI+rxRZ7H02>Y47iE?68# zdA+0;0ytB&^Rys?KDlNzW#kzb&pMhT#Sr4D_68) z4ny5A7I^J06iAZB$^N22sx$bniF~YFF0sE-`raOtd)4~ik%9W4LS}xe^2}n`c~SGs z(|u)m|LCgd5M{kB!p)xj;mNMYFO6pz@zgdbC^=@((~rtwxAOxK9>i|1;GYhTFCN*! zyR(bQ2*(izAv`btubZ(7F>zdkAJN;^I$hGBNKP}{6TBPHqAus8NIB5@b2(D=@J}@o z*Mk}bjDvT~W$ititX0gN6tq2df*^x0yjICZ#T7{w@v*K26HoM21RXE?K&m%n^ebl4 z-0?&*6iRxT;zrpdKzwE_z3u>Xg8q4VlvuJNZ(Ec#>u%-k$_|nl3V2U=V+hu1+Zp&5 z`BY4yW@uq>66KcSP{aO0fNF1!dodDTF?$wH)Qy@M&{%6g;P6S~720g)O#yF^Ut}bE zj3H-pr9)*T4;Fu)3ZOEj=dV2%Vs*g?@+PFbXAHBw%E|cLu*)F#V_U=-c%|A2il@ad zbemFKpWF4n!Ak@N{gDj$k;q?<AgAGn(E?RxN#LER! z7^9?@wYdCaVwtT8H#dvTlv5BQRjw_1F=-1=c904cq;yb|k*5EQ2V9sdxPJ8&ZGE{f z4~L{BGx9Eq9=_a^3t=9I_@dyXSDKmmH!*=C5Z_p&uTsj3v$j^n&CAi%f#(jfTK&>6cXtBnqKqmtJhcpX6=ljbxBg^Q`Ej=CjW zw#0?4W>b^eOe4_+Wt=TOE<{3i4mUZ1Y?KO%s_Zp!o11pNAeOHZuuT`|Oi@-noVx)+ z1);2a>X>)oI8|B`nW;eeXwV{lVv5xDul6jNkLJXT&@3wn@$4NHfq84pQEJQx8Nrv= z^FC!M17sYjI#F9bw8Y&I1n6xKj>_FG0zPE_6prf{1hxu<rG4i>y}M zZg=7j@w7bSCzE?XFf}t3bU7_yEyXywkec<;@t69*FbamN?UEP2rak!4-Q;(Q3lF)< zL7(`0O`MEFCdk{5aamn%qI!mdlf3zqZ&zkb(e7qAxw^oZJXFwWo8j#ozQod8l5zh- z2O)s3+X6H6{$hU)2>z%4>9DBCPw1{7RNZ?>cV0rY%LQAioIksGK0 zJB!H{Q6Lzf#T94jlhE#QY?|?I!>?dpVSBU&%hU_QBzZE}L&(l7kWkX!DxFFSHTVa? zB22IFfZXkkY?}!oP*-d(A&c-5Wp)*S{C0#_6giMd-Fj5NA4i=phdn- zNZaSrH=D1x)JVibr-M8EWnvPVx7Oxjxo_I_%F_i1VP=nx?mZ%H zqoWO-xX6Wt8dr3j%3+x(L#G-kr7wS?P6$d8k*QGN__`oH3Lz~)H@d8BS-bXoa}35J z_~AQ7pUROMED)pHhL3(6sr?y((j}OP3%x|-#6e;$keFv;AU_lhOSv66WpAKx5k@E< zC`E=O)s^a7XQnwRl!eAbo632*1Ttv${y6QH@^x@cfWzqLLA|u(M5Du$>N^5r8w#pV z{l?om;6&&ZjS0yw-sNsW7mc6BGvGoBB9$!@IcZ))%s-7(GK-<)HLm+nh z39Fw+?B*Z)9<{VFOl{Sj8Pq%n$7nrfvtZ3<(pa0^wFzl!>yX z-X695MZhSLd9qVD$54-;m6ceY5jgFu7p?&ZO#OaLQ`Cm#M(_rF!v_Uqc!3(g;oo0v zU?o1!RB*JbKyk#E zTPv!dwqQb{NvCZ36eM+TpiTce>vwxX-2R*B5DM9UCZ1eoAa{R%LV)Z;zwKl%FZPhG z(Ao2R{pK6n*K$nVHuh@yk>>Aae|F(GS=zanIywI@P8?ll?CzwEZa+{u`&7}X6gWxAG@4DW zLeeQSR9a8bsXgViXjY=|rJ71iI`fM7qpKC)3494vyvH=2>-q_4yhrJzGg&|3E^K^Y z7zSabwTInqzH$nuvc+>d7A)9;#rG3*Hw;<4vcXl?A*|Ldxzyg+qUy%^tpfw&lXQIz zXCAX>E;D8R*YfsXg#4pwW`B&4NtTWrQb80ZdYmTB>t+HIN0w|jA1^1&kiF-?*rE$r z9aDEfr`aOPpI9?Uqt3{%K?)3yh~lZ9%6YQiXEF&S{|U0?b2f~j^y4k*{b6vPBS#nX z5Oo`b&|v`RQH=g5l!I`lD7{_zg@L?EDg(HJ&Q1)LJ;(UY(h2&@wkPh6r01i=TB8B5`1lkBm2hJF< zW^8^Lo=uB>0dJ9evnjitk$kW{4mnVHSTK6Tz`5YDok)BIOA$OTcD|%iO2mcSzG60r zqzq>?CznN*uqynG()dqc8Ic+I@cR{URX`=Xq7ic)u7WV(0>qYt*nQALLeG&!icaAZ z#H`W7NPdCdASXbo9TZlo<1W>iuO z;br*#+}3}6SB>uFxy5Um>8$c``xlaTH9x04?p|x6ETv}XQ0eEoPsi+QpX2c6wRY*b zd5y1M@VRXJ!BBHq zy8XzutKa3mYu(shUM5EJZg+ic^xe3;ZJx7C2XWuCMPwA8)l04dry<}72)MJK>$XKQ z{3`hm^uYbMV4a_*QZUOO7!t5VmcmD*nV&~6uj8&&Zr)F5l>*)>mg?)Z9&~0-p_inE zJh}*af&1#hP=OR88B_Y*l)Sbr_hox^+z<*-9&xVRyHzt zQGCk9w%RFGJH0htGjx8q6Rl-1&G$ zfD>bGkgN}z6du{{=v%;x1b_+1LD3HJDcQZ5=I7JgW7*%oZNqEpW>xe0O|RZ5f0li5-;=Mt5z*0-(N~#Em0pk#3Vz1{_;1kq zf|m>6)rE>EeT`AIVO4OI`%Bbl1CV=x0?Zy=E4h?Ffo;*27c9c4ByT#C4``bV8hC${>R->fQP;4DO9$s zP+&d;Y##^!(i}bA$Zs~NFepJZyl<%7Ojd%F<=(VH3`VD<18uljn4UO{o}BDS4h)dV zcffHkg({K`5pRS>_Q6%u3LS14HZ=~L&tnB(P$05qX@Ms26p7B}Uf#lbZ|@SwLiW9F zX~Y1B0PP2DUcjC7$o2qRbp(2a zugUYv+z2r_0ViIEvwm>GJ%Ew;C3N}F za`x(h-IG1AWs@*?zv9>l%V8=Y2N;)TC5BpW8{5s?5cXKuo6N7%Sl#B<{SK{1TIx*) zQYEJRO3Pb8thEnSDI)_)M*UgE!b+z*S(}e*S-rS;$YSkE3))K||GrMJ7NDN8vj>k0 zef}2eo0dj>uig*)_BuN17yq)g(cfm-zttwE{_pPmagu4Uo=4#>7-Z4D7N}YJ*zXHyI0{9Q$Uu~VoJe>JF;EU^R;o034}e8VO+l@D^=Aql!1d<3nYM7(*mqKkQX;5dw2G zrnD>8scHW55roUKVurAZ6(@n{N@q@6+HA?3w|gg)xJu|?3pXjhz4_u$QW3BgyvKU@ zSToIpR*@BoQ7K6RQnperFot@Xh?=iXtr=5ONct~vdDOT`p_HYkQ*+9e!$Nx6v|ARH zm^0zD(om-Xo5EW8TNp<&o?UXM&y6{09@$)9nsb1r+xJgk)}z3hEpc|@@KHeO$~^9E zsbU$8CfjULXOOxBFIED`OqB6u(&lmbbE-z+87G|V?GG2JaE&@*1bAMxIkS8N?sE67 z%Z8zx(Mg63zr>70y8^aaVC;o`disSBngq6_=JSgs?sI8U`?Qbh`;-qfW5n1;A@u0s z%)c&CS+(^OpS4uQMoHaD)1mH{`k{oh=}*3zFw9YV@Zrt`f!{5#0QQrnC}+Du$GinH&j z_wzplRlfKn`7&XX3(gs5Fq`9XD{Kk)5asfzBtsagbhG%o_sElDjxRosN$)=~bY*%h z6T}S}(__q+{d)7q^-}jYxMW~m@(gI#~V+{cA1k3wF9#i_*vtfRX2lC^MHOU&^_AOmu#1QFk z1b9}AzZbNltj~z;;DPll}*d4gw0@w>0JM4z6={|;O*7f92 z>22T;d6uV3&21Lr%^!N?n;~?nD11P+cmhU+T(~a=Piu1p_l_%)SS_44 zt`2Kk4ayjwBSbsK1!2pLZ>`Mrf|trgD8bNV#E8{pR)|w%Poa7a+JI;6B)l8 z7PVDTXolja*#Mfjrlzv%t7+c!H7YL_sOv6}g6t9Phk@xh4g5kC(6b@BJZS*`tV)6; z3{KHwL-hJqC_5g2ya8+xtT_ki0&Ud6xm|!@18U@6vQ^=61`31J5jrS?!{rVrgOFk3 zTns3aI|LCe3?h+l&>q$h&#`me*CN0Bon>S&hlIlC4va(WZ0xZG#On^gyab4>Rah>} z07luqIDrf5udpiY8TG)A45G@`Il1;o13*)B+F`TQfD3);%HX#J47}Ky3}>Xz2}Y1A z!I>TC;LU+fB+k_Si0q)H6~wY zam#6IOg6{irn}mhWQ@m6_q{&Go`_o(ay)I_OQ$@JLQ0u{hgI^=_DhXSngInhMLh-V9T(X#!8?B=nj&6}};c6mn!=i83>)WvGS+TOp*Fd#pYf8@jT$@|FJ&mqyVWTorNuyQ$ zx4Y%l*xahRy}47_yR%ovvg)Fi}o`Bj(Q7{c40J#?W3yM6^U=pJY`*N)L!+Tk=vB_2U5Hdc@rAH~0I% z@u*;R)e@*q0}LtsWzk3*9jk(T@D(vJ*d?w(HysNW!%uSKL$1~eOE<`YM*sTSa$?-K zFNm#V-QweP6iGnSNEumS@X4P^3Ns=|&CPLFQY-rcP*%vEY;Y~l=&~LT)>*oF4p1fS zkyGW*{{SAzzp@Y;M5$6+6nJ0_Q(p$OawJII)0xq#L)=Ep`nkSA;@>N#_AmeQ!6xVV z2QlTZlI?R1m9j`MEhX}@82-qC?H7k`*borsd z1kN*zB;f0;W+XdSZHvflP+B)7rA=lDurwnjnPR1Ku=D%)37zCvw}A!q4v54s4wT3X zEJBs=3D3JX?@pQp)48Aj^ z1%lz1VBbj#Y3Evh5c`#mj$RD?VDy=&vqSU`M%?t2mR8557LxD)qy)Vp|hgmJMM13<>z(u%ZKN_9KK%U;V`GMByOa^&~9MyhnO`F9^@8KN^sHCUC}0n4g`E`XoD;xlEGno zqEKHJkH~*4^uXj;Nygq}2%2wF4F-FLdtW2RB(8};zEb6R-M59&LH{^-3jo*qffzcbD zDKJ;4*aabz%r=Rs*zDrD$JdJH0>PvfP8%f4)Mp5)!wh$svBvcwwWx{rl zbJV6CA7_te@Man3@==RFh=Lq9#sjBCxq3gOo2_emMmPy}Www}2<36finKURC1wZ#D zE0@7GFT!63w}UG!xZ>wa`(Y!_m?2k(O8P_@PaRR?wD9RZe-5&T=`dN^a7p5H+ZZZw~6)e`wv&+}Ge= z?^D?TtiCfxBLM-5(M2Ww`r{c^Ua4<}@HZvBue~5Z|6WWRL$M?pYSclD{ku$sW~8fe zTr@_w6ou3V_AanWv>1_kVi>Sj{3fC~$w0MJq`(P1EKC(Ntl=C>D5K_T_!Vd_2XxWx z#1~?*Y$CfR*-9m@9>4?E~*z z&IK=(77BU#Gc5kAjKWe|O9T7Fj97$|F>dQ*!^l2@FKUbtrt$o|x9M4(^Ga^W#qjJK z4}Nq4zKfj=;f0umUsrq`Vrp8t0))7;RkHBS5t&6JHANC1Kor_4KG1I-N~;2X*1@BX zTOvnaj##Bqr*zH=J>v<2p*tcNuIMjUX>>ya{ZgYaPm4$5UzUa!^eNj5&iF70{O5#j zu}>WzzJusu=pl-_LZ;OLg>p-{}Qvl}?YB#V)wNZXT4u`N8 z1^q9sC}Nsd&F@r|FW-l8ZpYz~XY|VQydEC700h}TKoEtsTuO$b6AJiR5lV_aC4IJM ze!InI>{4~DqG^_DyQ;}HO>>4y^R6_zIQiDn))Adn27dr;as8c0f`qgYqB3fnzRIS2 z%B>nEIKrZ#!LtE+8}zJ6EMBw>%R$n|&hrrG)B>;kp@dUt?~DtbSJZ@a0(JguLD-mZ zQk@iU-;VU=(8zp-7#3;0=S`YORXz)9amMSDd0moz9rQ43z(;hKz+0)poOR?D~G~x+AOkN%+Q6+RU(# zW-*IQ9oIbC4b4``6no^EW1eVPdzR{)IOxqY`8fJZR8=iVY7Ehj6LO;!J=KPJ&^@y1 z9o_Il9S$}~eFpoF5vcW=r}?xrCdM*etHa2oD@xBObobGB1+E*jJI2&56G`n+o+3f1Kn zX|YXVwpSHy{;4gvZ0!Rvd-rtK)PXhH?1B4F4>MtD^e38q7WqBiY%njRaJk*6S(moY zVV+B_hmsZ4GEJfaE%udTNL4@r7;rzde=)`1HmLOgz@y?a&mJ`?<(|ciV?lXPw@4KG zGx)z@f3%?kDv9P`U;sm|2&C6=SzD#`L_drIfQnJ+Y!bwZPLCT%QI;kqo^cld{VTO5 zlbu~a9JDeGz%oCMiz+tEzv`Xliv=y&e*1V-S1@ctfa_mACO#UJETN^Z|8*H7;5mE*Q&W}dwr zue+1?-y+$+y3$>(Monw&pl%%HducMTbtq!J5jG9%sm|;PX-v5Gk(@E&v5)x(C6h8l zI&8H6_PX41c2yxNcM@^il3z8D6EE#?i-$QeniZmN*C${3n}b^3T%K>6B|w{)U730( zYY5u)OCo0S3U3a(TmLP(depIGZI2mH6kJIX zO;5TU(J4*2sOrp! zqjNx)x8<39!hsyG9#70qS6IpYsJ3b)`t!JKy3tPUACeKz_B7j6Tf=+%d&4p$UD4FS zG(9^>HCBjGYylh%23;0XXi3PTEx;juVMML!eoZjK|Dj-;XX5C`E7h8DsASStKZ=J(ho=0_uJ75Pe*R7*>?LQK#9S+L zwVnh}WakOI1J+c&G?^k_CO^kr1e0%_5E|ude#VkS&1(y+j*F;Tj^-(5Mk6SdS z21wl1ji#jKQ1w|w^kQtx6kY$7zPE3k89n=A#!RiCwYDjvo-tLGLeQKrx4dBg&|2oM z=kv423_psI8J74=#h)_1PYw#cuiqCC$K9hjH02sKvpVOh#=_Nj4U|OE#lWu&=txwJ zT#gXiBY7Z(V6-5pc@jxwAAEr}UJWgyWF@2^jS2bo>O&LX@CW$iS&jDiqBBQci znRF~N!;l3$0OFY^$0#@+@Cm!&ik#CH{R{FA`92g2=5K1Pp$43yyG#(GD+Y{`$|HEc z>q4C?`8~^aI#%V5nO8}=(q|S$MEwl9%I<`@gTh-C!#v-4$GHW3-(SO90_ICj!WF^x zkQC#;Xkh9v)f@kWat^o&J0E!B+4rqf9guGb;0ucT4@!Q;r`U9ux=~_HP-N9>=7n|$ zJaUea5o)6S8S?`e_6Ot6lR-to;90wNSFxLHQg`F)aP>)7%og>4Y4DNyG=JF*RXxzY z;Y@qY>sPP=H(UJQ?+aHncpl$h9kZU{_bM95{9yWxbhYqmBq>CnB`R>n$*OY>mU@H* z6)KFHR(b~rCD!RW0K*NP+FGcIyP5GHaZT4Pbes?=N<&jGceGlxk(%T4x6wb9boAr> zw7P|uHv?+pu<0vjtpShtE7W-Wl0|-}yRfplJO&{R3GoC+-Qy(MHXn)jZ`V88nY^Z!1V(M6cfCHX0kr^orw-1k~$Wp zAn4epr2^b$o^qo5&!YVjQHDb;=%xa%OI(Va5+UDOexVnp+kmF+9oT(5fPXZog&Z7H zR|=;NclR^aE!$naJ<~~NbrMZDagu%bO*c7AB@{cysL^mXOYeoqA^JatR!pu?`bf9B zue?VY=WitrN(aPr357x>5hFm*6ZgOt80FKI);2^c<4EydcA|;ss&9$k2#$NAPm*?s zU$w05%lRB)pf*^sC)=P9=OPEH>NbCyUPo~72!`KWolTSl0ogR_AcBK`nZ5O+(2oNl zq@fN#`M(OhEyoJ-+zP_zfW0;)xqPwx%VKUw3mBiMDX*7S9PI>Hrtl@ltRX_>P>Dkv z&qg-XV;hB-Nv~CM=SfOT!HBIb18sXYTrFbM1D%~BrGQ3G%)sfmV7i4WCHiy%U6|z> z5?)8qC3@8`qiv#YPoPn=gK#KFIIL;M6#ZDyqE7*BGb@q6&kVAkxC#UsLY9gnivF!* zsbFu|9}Av4er#=fXvW$oNMYKm5zSNfn-hgyh}U0LYTOdGj!gi7& z${%j3+rSKar5WsJ#%bs6E+__!(N+WNmZaLKKl>?uU{LWWy=JAmOMTg3bOKY1N~s?e z%$rRN%z21;_TSUf4XP)Uc~wN-%BtnHQ}D-{f#07oDm~Jdtdnf4b%|$Cm3$QTYE?ra ztL$y@)iBE9svnH37%e0+9z|U!{o6nMwF&6#ku*{N` zIi+d*gmNad#I0Y!s#VvnTiG~U_kM`^%zyAuWP%%|#+V^XOZYo?fngcW9W>rcF*EAr znd6`7)2Fx9`7P(BjVAqTN{htEVV>Zo5gp|9@+nuCx4bR+*9T}xcXOst5b#)T#g{vu z1E(;P%Z>_22VJC-bh2);>4tr&MMP%Ce69HTGOU zRM#&VpXg&}bLTVZsS{;GWl46|8ApOE%GGpC16@o0~XDp&efyZ9Vl=v2*B zxo6}?#b)1)Vpf&y*%gs0H9fm{(S zLwsr^3$K-JKHu_qx@+1>B%P`pWyTFUo876dsONfWZqGs7>?WJMq+U-!Uf8wSp5g3C zotA7Z*xgl3)33X{-O2<@O>8eC5^TxlquEp6#r&)8N!l4~Xo7bD)ylwV+nn`!JrDBxnjs90*xpdd+f=q@! z!Nt60&R&YRqQ1wLwT9=nR<~rd7Zy<(Yq*BGlZ^>&e=LuKVb1>lvG$JLxyH}7W|9@# zcCupIS+SE9Jh5%twr$(CZQHi(^xC7x=sy2_`ql39;&*?9x~pc*npae~=)2h++={S3 zBc-0DJ8Ve?A;ZT{|^?DcUyL2St-s$w;^%Enbc3bUU1cZMS(IU@2@T zfr&EoxBx&KM}{g9@%LaLthzRdOYOAjJjP&YBhS01MV+Sfj3|l|+vSc^KUK-65?8@* zQZmC%-Q)5&UWgN~UTfY<(0w?c_=-Lfm+fUvs>}r7;QETym5ZsBLw_1-za)LoW8=a_ z(fUM7L)mmg!=Zgn8IJv0A_qs!LqdVGYC}*icA2nDWl3jjcMK;ZZME>S;TYQ`Ro|*% z;xm=x*=)=H3W7y^lkwtS@ti^-XUdL z6kj*JI39}I+76sZZP@u|E10?MN{hFT?On|39_E(Gm0m$__Wt_2AuP>QIKLYGj+8cC zt7CUi2p_K*AN9*`SaK@Q@{F1%>buj%COu`dg8<+|_iwpIj8(zg_sEk2vVB}bhiUDR3a;uszF1+TeZcMjaT#Z>_Hq(urWc=O>2 zH2fIFNeqYWovH%m@Ok&$qe?Kl% z{W++Fi_XFTPTc(}4qER6uv>c+(r5Bh>C>Zs1^JfZu};*m24%yJIpBZL)o&~?xAb~h zn~1Zh6OCD>M95`nVOY?x;;OG)jh~GTHWRv>GgFybP*Ro^q#<)H%5sGidbfyHh%gt< zeJ2_l*RV7Lw*35+3FI+wc%r_&-d#$4hr1y7OM}3xBdNwCza?>&n&23XieJsJ%aDkd z0v_uhn9&}PhBbPavpkGpQmvWhxbzhQAJgGdf|iRT_^pdN#$t2o8f~s6;NoD7 zl`xR^1;M^k%BiNcLVu-{FfQqN%Ixi?oS#QW9d$AO#b$1iGK!X03=yaah~VP?DZ9TN z5e2zPECNyt{hZ5`hUTn`zBRU=<&ZAPUORxgBrhE%*I=(VCZhNoJq_0N^Hy$`QiB8k zK+Ia0P#$V$5~V1`#jhiisX3NO8)Pg++CA~Wk%TOwn5N@EG%+-1zr##*&r6vlX!-h- z7MLKn>o$K#!hC5$`^TM!(f}&+?6V4}x=4%z_IJkWK*ZQ9Nr^W6_R`8H$z3vRcDfc# z>cuIqgn`evg_TOkv@Q1!Q#pU-94!_mg10JiPG(e(uef(O2+uMT?{MDyWc)ya!oCkQ zzvL+2N<{k34NHj-4&`11V>QniLs--!Xm$wYD8Vzgg8Z=uUNW}MqCF_piZUz4VH^nH z=l1hss)&D31DWwBM4E_tI#x==Lz;P#U~R_0hXrS$yF0WzIb&Z-9@RMgOdHGEr|7G_ zzCWf$?(FpUFj%VFH4=~WE{TBN@)u=C+E63iq+;5`?_+@ak2W9$>ELpnAgZ+BTTL^b zGW69p*hTb3_Cqu3-H1wEX68A9vkduJ#F%o6G+M{W7v$pCtW?)R7K5*J?RiZ=|F4s)!5dd2` z&Cc1Xj;i51ND=G4Jdz+UOmy4I%w3CeG4JAKPUkd0sH8yjq#7LmQJ6f#t6)e>nY5)=Tt?3%jr(Vhk&^ zpkx>IvkdYNp9G4g?F#-b}$;hLR3hIZ(%iqL8uA?8x<01NNI5Q1)E4&wZ1b45@N_(XemD%)6f)^Ai4~>E2|6B&?6S4`Tow9;M3fB z?slI?q_&z^UG8;YErWZ?ufg89J%s)egSE-gf^&2M)|_*X`G=1zY;(?yFrmaK!w7k+9MtHWo9o3Jrk;EU1H(*)@1~~IP)MWx>?b^`Df1d zp~va*nMK2%LSxt`UYJpMu=~8uKB^V{V!T#XQ}9c$W(3Pj{$#0KJQXDj|AH5nAI1PI z=3MFr^>ZB_GU0?8JL13_>9rR$L88b8l5K*p`FWwF0gPeKR(j*yQPm6-Ugtq7-T)2O z*pZ>Ym%`iM@`Z6epj5W7B=2^T-*aHR10fjCgx@|t8$T?g7ypKM4#VO?T?@dz?+ z)RA6T2{NpyNYt1_ougQYVKCrkjY>Mjy0FL5<0>~&*M(Soh=tTsp~wr4RSbPAPI0TF z*med5F=mz+D}^110jKI;!Lw#c%#7V@jsM=H!L|aUP2fO3f`#hDH6g9m5-r?^kIxr% ze2XB_8#VC?p$N*Da6nBex@#%!Z>KcjbFQWCUA2*unO|vI3^P))5uiG`N=aA<=Q^W9 z-?A{V4YsE-_lQs?&zj)D&$|mJD20}$S>X>X(Oobm$`?DPVZ4v9a4&SVF<63F2gh266>XycaeZ>{q(dG}u>2shLAt zPqDTSTNV|~o@1z<2uf%8i^qK`(J`oM+l-V?^frvu5sEa|&jrgbR$9L}t0SR8e~Qx19w5DePbunY!v!>!n{#tlLfMYSjRNC+25XJPV_S1`=l zOzI)h%$bu+u<(+|^>nL=iDgr6YL7?85uUkU|8OPjb1;Bi&Iq~79b!zfF`HnRv%!6;&+HAIDG!+ zwK-P#>Ks<{*}_DYxq-N2w&kWxqF}s&YGM=3`yxWf-;TiN>guc$r*J8YyhEzy{3#$j zjdZ+FR*d3wyp27kJ!YH>q-um2*VgJx?hA?Kh2Fw~+A`{iAwSI8KZcFOigkE-kY z?CrrmC@9W{|CT%~^&JKK`IA+wPHtw9R>lIedC26IQZUxPzoodkDPDX|1(}-L18XLM zO3)IUz-v1Q+OT}u|9${1LL80KQ3A~&m^Vu)2{BtuP@MklUGx+*|K^{Y(EAZ}cFyP) zdG2Bb+^sGu85`mzg3$BQcWJf3B=d0QbB?RRrw@kQ{HzPfAJxl0S5ZWObNDi^KZ(!* zLKr{&^Ip&{Sp}jBPtmOaYG$Dw#1G~pGrw{?bSU!yWqY-!rxdPhL-$qgpBOGrBByQf z0@YK&nz7>;Ws*0zKRnG0CbTEjj!W+K_1T6tO7-{e78pn4%bR$tb6w12l58651+YV^ z9*pSfWzrAAf2L7xcsx?r!U6#uGXMbz|4)7J4yI1V#+F9^w+-Ib?f(hxT~gPu*$_qd zUa3hXqabZ!Nf2KRdFn@K6y5+e9FtOz4Y2$(yDv^A8AlZoX+iV8^ODKjnGjzzNZagQ zJJ#lT;(a^`yYqcZhj!Ni!S6XTP-FR$$s?+FV|7EDA>47Yy2C?e`S|_CzvhH$1u`9J zTf{^QnHr|$pQd^HO8uggZeTxyA#urH7)B5@3CEiZJ^dLQMiHfwsqUMM!{6Y9Y7^9- z{dpKC!uS<45BjG$?xf}`DFPAN!C=~%XZu~EpSL-ppr#uFVXPpdmjIqY0Fn1?FSsgy z_Q5W`R|0Y{!9gF!ho3bSg+~2Evx+#T!HNnQ{b3Ny8fn!lv|C@L7|a){U{J>n%-yRG zq*pMMYH8M@78F#)@508d^4jRvD1art0odQ2vR2s^h{GO=g?Jt`pgYJ?eeegbP%pS3(#7mtk9d$1a-?S47SZVk;ozt#j zN9LJ$q;M8?F<+g0@x2)cG$^_W^scJQ`=GDbY#2PU*)jQVp{7S4dOb|X`ZDJVtpMKu z4Ax)AX*4ol=vWX=suNNZY?nn<4HrZDlGrVd58J7y%RQ@>dU5l~$2sHvW!I;lB`m`(!De^*Cv@YZD( zY0RXB0IIodVOn_Lr~+{m07~kNixuVr^&C0JOC7>#v4QyzUABRKVDLC_m4Ch@WZWsR z%)GqnbJ@yRwKTh-#0l-hckSyYb?~48oK3i1-Zz^(NmVd749Az|M6e9rt9Fkjr8M5Y%@me`2@+W0pgEiJ)f zk z=^AyyCr9k7Wo~axE$puGh(!Z%feY4A1^m=c(^!n+$U0cCZg&z^oqDb6K-MAq16u>) z{QE;U* z5y6C~>SpvFm$&4!;wMMvIdxHt!4qx zTBgxy0#AT)UP?`p+wt!*oR0yX8vS{69<^(5e~1f9yqod;x81_SUAkoQaQ$p+0@qGe zlsqa#zVcp<7?iJ;ML2L^1PBoZ|K8W_==r_d-b=~AMxb&p2!?aMEn%}q{NA!R4V2>T zwW6M}0vzksKUK7~OsfT)B|<`%Arba>id@KA5f&vHGN4LsD(wz)M6JWts6ZFAcy_gN zD-flNElqz4mu*8uw-7_FeDxew(VNs8g>FXGt)z#xHl(`)m-FI``7EZZ)T^eXY29W0 zxUv$0tu#7W3T|0i7v9P~1R}CT8FE0Ej{pmh$Oeg{4RDf+Xes5(Hy`CG(S;9r)Qd}i z#9%12Q!P3&pDzME2jHa62=W&sE4{5)k-cz?5+=#w1?z2f)(NRg0CifA|3Ed>F&I8h z)09r1k=WZkNWxS8F`C=vMSTJ$Px8#$f{RBL^Js_)Iy?Li_o>S7x#9K~Ekhmq#CUTrBA#H=jeF5nXoVOUibxF+&7`h_$gSrnf7Q?owHjYYo6IF0R%)FL=w$f|&bH)(N)r83 z4qwF0M<{0iC$mxO4t1MyB%{HikcS|Pq-QdEN5F&UkDT%IV{S_D*pR@RoXKG%3@(X^s+&r)1IdcwPv#dyjs= zrM}gFpATTEB;(R~YnhUoDWvL+^S8&lKT?3bNX1zrR za_6>|4D7Du0h=0?_7fl2?U4c-Z34Z+M@~V1Rm06f#;BQsRSaQyObZPuPAd(-SzJ7W z#5VdG#_tiNMs=LO&sBJ;=;hp?eu>-d(h5IAjjW9n;8NcQPJ-w0RS*!G@KJD9*2v`1S~Z%wzEQcQx6X9E#`GNw`JGZ@90k{N~;*zJ%xIJBF*^i!#LEsfqJ0AJoE~x7^zW= z=~6|!!ZQd}`*}~UE)i*a!*tI+;a}C?(dVvh%9>__!Hk!{JzWw_#^^1ATyR6gczzEF z)6+XnHxN$k%grwP>8z$#xrQ>t+%ZLr)vrs(zyEL3-z`$(8adxPa3gs%f`TQD{JWK5 z#Pin!NThBjXYg23BH>|4DZ&hL5{1&i)$RI&m&>2Enh&beFL@P#wVPEVxp7C1u%9p{ zJeMw~OzDCbr#$$Q0e<T#+(1~iSPe9+UU^zFJb#dDq1!bqKIBEHJC;1aVT%= zDqa-@%Kf!=%J#irnJfywBYM|GF#?7J^H0yeU$WI|qYetaC=l+Lm_3dsN8mH&LNE1S zl#4H9M0&hGo;Q4pMe3$e$9V9cMM>)GBO}!n%NnV4l=|(J->4*<0L3#-N$8v+Zh}q9 ziN}Qz?U6}wJSA>Q-E-v>E$)A6%$oA@S$agY7{{B%=K zP*B`DMFMek3sp_N*PLjn7_f}QMyY}kw$Xd4t0DshRxXYZIfqJ-F?+ztoHApTEQ;TY zyoq_Na(ft!&2G5Dz!MHH^)&&geC#-iI9dyIsbz$ud;(sh9!T`5pt?XG2N^-TDxhYQ z$I2vbyDaqs`a{9GHJ+Qw#$D=y4P+aCd(0Q)hRw6lQ$Tgb>qda9KW_{r(cjYM`*7k+ zOWb9963P2d^2ML?;OltH)#+Ac+UyAB1mvj zEsti~LT)@nhS4WM@U$@xtbV3P@ZqO7*?a3V?bl~K?W(ZMvD>lM&ZNAFYir(}O!agP zZ;Gp-$$PWz+Y@cV&;tiU-5DA;`b;8@UivVIyg*-8M*7!>)(K9uLO>%!z*Le){7FZZ zWJm4pNe!8IsQLRKW(X-wd+97)&6{Fi?Jnl}jUwd0C(R1}=t@rb!r4V;fnGxL=lQbM z0z5^$80r#}zD=JiL2+;0AC3pyJ<+dK@XoLoe4ay0toN#aa9ZRSyJGdmf-`>Vd3@*Z z3AfnEo+dGV(0VI^1ip{zsqfkqgF*=0dO-NYy0mtXSpoZ#dD5Mx8}0ZFc5qLjTjo+~ zA%;aWW?Ij{lt_)q^gCTY!^hmkQaXFoNac_@5Bi4I6Z*bPr!L|YgR)Zfc!q;eS_yzz za`pXJfJc#2qcVXh-JRV#UN!6VD`xKu zmN71KJ^{atdmd!}krly~m6pJ)TTZGA$*D$kcsZQS`Fd6;IYGn~{P>~a!=d4fp-sEb zz~-Lc9!*xvP(I8jW7il~m#B4)>KZxEB?|sCR?I(daBUnxl$@sHP>9pSC`(Wo19bWL zam!gCAgV&Cq*Ek2PsR}~X;Zy0-_>C8SR<-y3S!;Um!$nQ`~)Ot?4EmvCLLaPn6CD? zszHd~)3etWT_eCQ=Cnv0<=%eb!ovnQ;p|`lHvU7lr*MvS$yE*edZj=h=KE-mZ#dWh zXr+L=|p zoTMr_^X(g;vLdby%^}d0BkXy%fl#X*L$bafy?P>|RDA$Elu=rEVbR&CiS<(wQ0}vq ziuDBtVQf9o0qZJ5Pil^~q~>IbqIl$TG-&0PkWZeDZvID>EbuIs2=zqhYF-m@D&Ctv z(Vi!piWHePWd!p5f&ikRTjEbXQ&7gT0M{eYpY?Y!2`SI8AF$VwqaCtaQ{yY=*8V4l zr+2<`GJ;m86(ia2ey#oOxUA47YMA(F)$t`TSir;q;hMYmHYjZ1Bv)+*@X zmxQ+uRpFlLTs5hcX!8w(!r&#dd|~t^l9z?p6aGi{EY9WFMI^@5!&Q&|jMp%ogW1v@ zh!^N0F}?Lo$s)n5%E@;Kq6huk`tVx^k}_sKrps}Fc<(yiIruG9KE8JtjRtBn_9iR^ zN{9#;ci0v&vk#;#y_dvgV6-ZLSg_}XDJ|g7EloW|Km3X{Fg2wW9{fjN2DZ} z*4m)Iz%YDrUJRc;T0b;cAj#YAon)uN-C+`#=LAnVwI;^jzTZmn^2!>SCrGpQC(12- zY~<5j=4QSt4ilecF-?q{Jh^`Z;y8V3AJ3|OwH#YksKSCmV0*s^{)ZnQ-mr0ZXysYBiwEM$K6=E=QGtgaQYjA&yG-EZ{9VN{gg_ zw<1qMZJI5gqW6@uze~H|7mkHpV;WlPtKXLewV89in=&fWrqWlonOXd~i*oW{QGDXI z;`u``OJ~Z@Isp8koHZ3a@EiAGdzL1Ak3q9_ZdUQhxHygz>q@nyF-}PDszy|tn2S>p zax~k51g|Cz11>pJr=faJemPJW2`9Cj9sCoRt-qNC%gx?vxvD zS9v#wXfoURLcI)C8RVBMj}nrP@#Uf6w+fO3fAxQ-oCaRK+M{oT3j&mV{Zy|~g;1i5q%9+f%OOH2GOiJ>;e!;r~|w@db!&!F)!;u zE-@)32W+Y1$zm(YYqJBa)}n}l0$*At#eiO)w%>X&?F#=!LcbLwKEF(JlXV`LHaBEG z@*!958k6-C1vwDQULPE$y-?D|Vh~*;-s=Z${kts#*1|tn-V0NRNdOfilr6f26BEU) z>iDfC>#(5VPKUwIQxCSCknwqUqb*-35C|EEqp;iml$`}C^)M}ytu|l71Z#$B*=$F= zDUR6r0_&fgYqU6RnHUyFa8*V>ukb}aMXw?-YACDTSQBi8?PeH2iNYrPY`S%U(D}Q# zVC7~)*OqMGQq|li`)`w4~r2XUB2B z0kd#=sEBQ{RVGeLN%v|(W@AKr#pKHa zP+-7YnI+dmGSN-5?rk{%w9U%L1P>hYCePXiL1=T8NJDes=H#9l&D1&7V-3%Z)Z3En zF2%ob|DjWJ#&#qIO_=60(<6QD|0YSqt9|CG4VgC`OGs4o{yfGj&acJ~?1=B0G`QHG zW8XXL&#yBpgRR8ZNFFw8dhy8@D)#hI{L2;k0MCakDtm}+&Et=KZOl#pZmK0~f)DWF zUmZ?1m^$9eHPeliWFx{pwyIkilu;gv<+TzSeb+qhtlb71(w!J>MM zHXR>%nPW>@En8DGJReF<^*3Ln0oF-c$^hYBuVV>z&Q+@hc8|(+HE-cB6~gh5v`Cm{ zc<8R2KlG{7GJoVZckB8_-yCg!yTCxYdN~g_{v9TZ0i#;etmD& zn~VOFE{O?`_r{KT1A4GBS5OuEB0=1n$3>m8eo}thDJuZL>tAfVdFH2GZjN4;Lom_K zs_jy|2W$fkV8qpsn}v6E1>pir8X~J5}Q{=+rlXGP82{UYh|Gw zF*L049Tc$7FwpK&PR_fXpT`x+qGevDKblZpUL+1Z(1$EE`-p#NvD*&k+@hHOe527# zw1gOihy2ioU;GJa9~C|J|~myxevW;!?P%N z=vX9|@?gx#NG^!-c-r*tI5i01aliRoeAnkRKEm_$4&MG6oO>hq&k44K5GJ7SA6fJB zA6ZlIf4ZFeuYQF|=fA%HF}?!+U#8}S-8e1zKc;3;RpL~-meiUd4)@>eSP9(PbSKly zUM(LllTNk&#?;&+5}vwRS=QWfw0*ogpa-T&KW<;{wPIZ3<_WB=?hC1GF<*ltt8W72fUea4W7RIWAz^WmrcfuN|B-; z@=p`CwNnS9R*6)rRR*`>zLZM=m#67q*~Rhpss#nM1~%8>X{^}%mSe7H&&v!Xm+8Mi z{d`JROZSz$QduH{er1&@ydZFX$PuT|poO$8QV_L2RXDnK_%rtHo;55Y-rP5?V{85{&}$7t>C9OmHaONR@G->9PaMc$Ndm zocb7oLBRcY-mS&w*JWuwNJH(K1Pq=flU;wLnjR142GH|SKIhe^m}31x%W=`bb}(n6RX&yc{P z2Jl|_Ccs|M?}h7WCRXB0#(GwHFaO$=*X zXi2$2+cC!O*rdaZ-SuMJiS!~;=~a;#*JF`qIWaDQB1XWhcKJA+L5ruloT;$wAC9=Z z)~Eey=x!AuPfRjj5kBe&Knd1IHZW)*UdTNxIZIRE#+T0f?sO5HTfQA#-_eGcID>YLo}BD zsVP708!ao`*!ByQw7VOQ?#1WY9SJGG26nY-0J##2el^nyjUa~;!yEas6x*(d+0?Sg zA;tg$#l6!Cs;&LSz-qwq(#GDJ#z7Aavgn4FApIC z^BY_on74lp@;6%2=Qrvt`|7y2i>K$UU<^o1nOXIZP(hL^8Z@~@9u3@P-1zXhO+^E$ zb5?zp{MK&hlTKuu60>t;bXVC#Kt26N`7MO4^o2$tlTJIn%ur3rKuyt)W@M^1zfjj^ z^Ppi2x!`;z?C*|5=~1b;gTYqK9*rj_6KjjB`SVwf)qoZ68U^=*$$&3l&u`CL0&@m7 z7t?=CiWd=qP0;?TmjVOS&$@2nAF~~ltj%l7_!u<@$@fAEdg`w$`%Z1Ryr1hP+Q&JZ z>TjTio0a2*Igd(sKK{3pnQqA+kpHZdPo0k3qYywqVCX16-E`x%;4wH)?G(Y#JnHeJWTNL8Kh(K}ob2`!iOg-P{BnwpB@lJ ztt1G0@jc?96pe&mzBpbsW2~oI__fffIy|Enq~fg29+G=T8=tD4qJr%ol7}i%GQXXj zo?h^`B-7a#3iYGtf;GKb zsaZ^@sZi^omUt&^p{5CAR=9gaK2Q#yNDK+2 z_pGuijj?8^4e|QF*+}m#;3D{a_&`d;=`56Bu%Og2sKhwjAR8??Jd-uH%R_zBl#cHN zA8T=_C3PcYSh|YmkVrW+N%cC>)9#31TP+wA2L9yA1DkS_&hF^F<;3>>Mbjh27*a2E zQzgGZc8gsdGsQb5ju;TW!deOICwt5QzWkLDu6j{_#-a%`yjY6kyM1H!e4u$&IzOK} ziTc?+*RY!}02D8btp~960vb_2_LtQE>xKlBe`^{BmpZ3J(Ke~mreAJO+=K)}M^-wd zX^52~ua2Im@Y|E(!=+g)oB5eQW`&q%M)RZ(UyTHtM{glNkJ-ciYJ)rHI&*B)o|mbF zq*B&v1%J|O#KV1q zBsI6}U|@K#yTuFgT~>~p4?t=n{gTYxIUwhtD`)v5;eosHo!AwHm!gqqTzs)H@HXgZ z#^z!YZGr^BUf;Dh*mzSF2Ml^Exg5ayG}ggPo-m-QH|&Ub=A-UNhMEvg%P|1shKS=6M*13IuXpAq;O*0k0| zwqF3e4d1QjM$QNN7T2^m^R?P_0B>U_PC7?6nbox#tdZe+u`@i$E-Z*E{v@wPgNdBi zgwqN0j&rdV=?Bs!PzlsgT=80(eQ&!l&4`!&z+}+0Pz?SJO=ZVqrSYU86%PaZV}|}M zBr#{XS0zi6HTiQDE1r7iO>LIgMnk)J##Nnfl~w`j?mvIxi6bx;xw)t6Aa9m({fJ>S zz9qO$SOFqW2NjOY)@?QMwrSJ!^t5N*tR`URKBigF#_0Y@uoz>4K^D4kB^{y|A96n? zXf;s?LXpT*_Lai)tsM(Pt#gdgviaVHP7ue-U33^-Cq< zC`&2o`lU1aeQDDA{z)Ss^9l2eOtxGej``*o91e3*`Uf5{8j8VMWSUgNCsZV^f#=s* zqibgi|IpmEImk(EprSZ~UzIq`7)o1`H9>!6fF{@m!^Iq%H1u3ou%03KM`oKb8IkV* z#CKX?ta9puS(&4dNVzJ}^x2chsROJrHge#2#yD!B#RaV=z#GZ#$q*GM6DW)BdH+Zo zuB2SKYZ*z(NGaC4YSB9YjCPU@#dJB?F8jJj>PnpSMy-^?E}~I!2_W+;`Hzs66}u-2 zB@@k?8WG(HM;MsFP+V9ev8$I+*pgA@ytAx|C>m9C8_P|j9?ela54Va5_?}M2beW9R zfezEQ$MGxs&61xAPeCcVU|AN8u#|8kBPLLJWJdlck}1m zyqy}IrhXPmPA3=aQZ>yu=cAn*09eH`-R#l#qxZh5K)C*LDGkc8-M!uF!Xzj{0Qt=O zBDt-6?Wc2zcPSt+gg{d^)@4 zA}b3#J0gO~YbFiS#|D&6=|3=5ANFwKJndw@R63^+FzmZ$n)+*R7{w z&SpUe-o^R)C5_{`3M

    ^VI)JU2!I2Y!>OE1HIWT~RVD`8$sn?L*)sLpg1fCv0 z@C%Tx5V+_Do*s8+lgn#oM|$Ut;EwCYeh$GWNtM^)hy%yn=>sZH^*)+h#OM zo<7)}LeVS3JyMA(86sM9hoC?R1hK5JtmWlUl}^vg$OJq~UHuErEts3=-Y!8S`}mll zP(#M6n=55+Qd*l%0RkZ?h_R@-Tp51v_>HmZDfy)`AqKafVnULV%Sy+>lT;%5`t=i& z8GoF`N}(f!1Tk@YJ9R^0{F$Dq)_3bBRGS^^14Fys9hzs>ScRgNO8SbGDG-=SRLY53 ztZ-9R18lzMW)1O-0#0eH>3etDU(99!w>Q;6Bs=DDYC5LcU+PC}A_nEFAk@HcttJ`b z=BL?EMpbaUt{z%F)sGzI5#bQY>`Cf-e;P~Cpc87y^fHQ7|Y&ytg%rhTY9BSg8o8EU332|SbsUUNJO zCP07cRwX>=Te76A>adh%G7=q9z5A~?Prq!RE-5x-nBKsjF7+_hlufMUA`Q4jAUgmU za;M`(670~U74tcu#T5oK+QdnJK=l(w-=_tl`@A8W(l;3s7JMI%OOpUF{%LnWC99$O z0J4aj%M(yMm9)-WQ%N#VK1*8Hg@Bw=9Lsb&vTH<>{Q|_n!A>T-t8Kg8Hm!EXHl)z~ z>RaRz?txGu(Re}7@QA4FxdRdG8J>$&xpHUG8$&OkK)bgYK&pkZ(0aijrXoh%Gs6%? zB6D1I@%4JTxa%KU*8$v_Qq4d}DX6X(7TeQfmpXRLn4!cy9HsJUik_Uf4mfPN=wOtF zz(e6s3*8V&fof3KVj-w0ML@m}Il(;uf*Dv3hy|LB5zu0JO8>Qxsf8~Gnq}oeSds?8 z9^%z-Uheh3-WbYYM63>VVfNUc7+(a-ROtiS6KWwA=8A4U#)>C_8#gwWDyhXo$%s9r zfZ6;2-&^+anw8Od)|QDveJ{k|OyV3^t44p7w3nT21uMThD|uyxz^TfNL~TZ*=PY$f z+F4TfbeuWQUQ~W7YF($zcDePy>+(>xcTI5zJ%k-am94%f^?Lf_&3s+e^@)UG!zxEZ z=hw&-PL$qao&hn>-fr!Yzg)ffjCCVkpQU*RD5oH*@|niOgcc2;!sX8gvx#6-cfC1T zj?=6T{}NCy$Z=f4`T!mwsb9?t9rL5<HNSJsY3X-u0;L`s4Sj8}`S}b(tQ`ZB#0?Fl^<}?)q;2Q@33@cL-{!bfQnou( zQ+ht8H_Krk+iC0bSnB9^&%FqWS3Y(nyMY{q6~A@$rL-h z#Qj6sukSnA)P0^iBYU5<$I_Ml-Y_0M9#JP7JgEY(LBVv%DVwZGh}#UqU=hD5V8JY0 zo(FC&k#e~cxQQ}LcGD?CgD1L0e3%}YQBxTG?p5E{akJL~XUCP!7ZAzO^%T3XZaJMd z)0x|>jEFX@5>9^Tos-`srv*iMC!-y@Nd~%WMs-+`bLhD=p1zV)s!0FBf-#s9OvMgN z(WF&m+`tt3nUaC97_lk3O*$Oy-Gj5<6umskd3iwVzVhKhYK4^$-?M3i76!ElC**tuQOd^b!r- z%{rMJ40fd1o*+UNyI*Hlx~L3u0enTl-fIY1@eyGliZ_pKWr#ar|IUb!GFX2X+i37r zwD=-Hz%s&(Ayh2t2JH(-?71c)$ZNGsjx>H57k6DRF>~#txi%F>% z(AlW?3%P5vXL$}$Ox6zMBTKeuvJmKJzy?MqX1R-t?@kB9RM1y@1xhwyV$*al!W(}2 zY%mjEVhUc!0OhfpKelA5dtP0v=)3)Xf&jx`@AOSzW-CT^l{r;V^QJ6-XtvYb5doYyfOjDEzK zH+><>0G}1Lrpo*nv$oueDR#FEJFSH>qai>n->4#6O3H~#lhNNYE07eb7Ul9eHGU&c zOyY&r*U~Pkq*fK5Y=E9Kb*_3{auXt@bK&#t4s4F2_4Zu^@9xf4sS>ET!A6s{m^8f- z6)6L+4k{!kHQpLs@Rc9~Qb7CbrHcvqd0iJ;TN2u}$Pb;>&_Ro2#JVmL)($4snrK+= z>e$UG>UzVY?8cr&u!K34AbwP6fM-=~duiJeL^I=JRb|ltNoHT(0MzSz5>)e`{u{OF zkev3a72L_ohnt+HW6Jh#x(&a&=fypTrxDyDrB{?SQjttgXCXcR1$|!mmOU(h26=$K&@(^lfo*IAZ$ENl`RhZ;OfI;R9 zV<%$6eWZ=t`c#?$NQ2Z#H}FM_vJ7Qd{DPMne$sjh7XiHnnK8?>6C@Nlt>$u^QDwG!jj~H2`11RVK zcOuf%R2BlMp?YACFQZ%4hZx0o=<{S3Z^bRdozej&H2)zP(HT|}FEO)yuQ#c(IRwvB zISVHM<1YK&4t)q%ckmIHNdWxy98Y9EC^+)2%m;6Z(ZU)l8-B`&tVP|hYlWfV2ubhH zbyvR3?+qtimYU=sn#v)p_|^)pg;@rM4hcR^I%@3Js}q z^*3n%8Hg#8)CfX_ONI5C`BcX0;YAGFO9Ogs0hCoew!6V1eM5PpME{^vcDXH+U*Y=f z>=QEOs+;bK(MIBK|3>H{*a1_4LSThWwIYFW(!$@Aib!qA z9cZk;y?YGVD*2aP$w+DlQJfi(hC(3XmDCnuU3{+Ia!j3-zrGLST8E2wEGXagwhqnFP;p zPZY>v|Cc&vSWi6qCn}KsEm_ za<^f;Xu7Ey>)zT1N>6=H-}hA47wa-TA$VB3n*BMlq)RP~S! zl+z>u^S5K567FexHmJscA3t%NzQC75^@#iY1igv0QIsa73k6ll$?N(2M|W6KYos3# zI#J}SUQE$Fj573oe(exW7|Yy+R$A6L8*>VgN<>Elo!lB_z>r=@RFu2kJly4{;d<$j#$F@ z*VEz#(ml?_N?V8e@L)~FA1!~!ay3Wc?ch5JpwO!|&Q=mjk!k)XF&vgJI(?mf*7E+4$i)!eCS_Ht1>a8>?h2K6c zrJYPB8$(gU!(VWDDPRyN00008fJcQJ@fIwH`2t`7fMYNK09F7<05dx~GiwuP6DMa{ zM-yuk11A$&Mmi2U2KxW`fZoZ`h~Df!w&>XySlH4T8L23P0swZ7hpCk)D?}Z#A^6VK zVK~Y+MoGl-J{i=ZplC^e#O6polm-aiZAub}7mujAYDoTinI&J@+{7-1oeU(f7TNXQ zW;Ku@i+?|AnZ1Sq@cI3GNdYRzem9axvT6a3;qN zwAk->q;DM&;aCR52XlxO`?cK0!@AX!3iISbNsxALS1j87r(^fJ>vA)Vv4hQ?_2E}2 z5FHKH;d@7i()lL9ISsOr4m9{Xgg5|k*xG2-R}_MpWn?2)iv9Zsk;eUS>JOsw-`s>P zH9C-gf7gBw1jW@-YV2mo4+Xz>njv3?jEaMlaHY*IjeZThtueqL_f&^s+6UL&Gy8RX zn1nA)!{cAYXkPk5e+s8{_Pp1O&e`3WSokOggB)mYu&_{z9UlhzM{se5&^QlJ2H}8% zk-yKr>ADy1w8^1A%$DZ0_c^72*A|33rmUa8RRD3hiqq*?XePN26#=Q4wrHDCmL$^@5vSuRxw)emRjvJh8xplCDM-VQsnEm2KuM^Z z_ox6Biak;y408bt`4udICPoy^rvX>B_gNlkclS zP?I!^Rc1-5sXC}o!57mYQ%D_rylK&kz_mQ+DTyB91SKDD6>wo zCq-H^;<;ByE{#$OBgC2HAjE6jsqABV?NLUK$T|k8e!N0FFoL6LH*i>EfBxcHD{4yg zlH8a_RF+CY>sY`&Hcl5_M^1?)I6i|uD2g0XjSy!0_8c*IiqxH~1FM4O->Q2H6B;hw;Lsp~XypnEU>lhh_3BD@&WQCG0OjBG5 z(W7|hMsdG`J-o$|i$*r=EG5-^#zZA6idcR$p+O@-%!Y94q;D-hcXgig(S(CQ94}pBe z*I+Lc-n_^F%@o}1{ov{8-t5%@&YzwQ+Oi~@ou0);zPsHUg+g?ee9D z{}0^L{|~_b*LnY)OlmpXVo3fGi5?sPfbjpzdH=~Kw8ka|&gQiLNh~JrdjGNhuiP@C zc58Paits(F$5^5WN-kMj<|}zq>oSd`>S%45Rs0@|<0V0ZX?MX&qLA|2W48(>P1n!+_Y?L?+&TYID^D`zy!D5Zu#93{7P~T8VMW!1 zdseAn(osq6{knA4MM5HDVU%K0ipf){WHNT^#6*#2Nm9*;dI^_O^G-UJ>}O{qv?oeJxZ z6A{Duf{7T&jwyEhUnc{9o*ciCkOWP7<{aDA%IYMYd07Pbn2g9(iJD4o%4q?2YzAp2 z{=*&vtkI^%fTfgxbF)sBY(9IzBr4`;Dp^!{jZ001 zBDh5cU@>FD8ioN5Rrn&cXJT@>EDd8k>?FQ9 zVMLJ>5E8nxJdoTN5V(A)L|6$=I(Cc+KO^D(0=@{$;pFrt(J2lLjir5C5(CL}B4@LA z7uiyBqwK3k%A>qlSzrY`Ei7(>>YdPYkQTiVrvfD5-&y11&o~~GWJdP>I!J1Rag>>y zxo%f#VPV14G=>k+^GS4!qasH2cD&j>7VDF5w9{do%o zO+OZ*Z~2yffb~i#&NnNwShZxxkiH@nEKhU%u+36 zmN(ANeQ_FbE;kdR|Af@G&WT*q3x5+iC$-krSk*joj3Rf43 zG##(}qd#EZv!QJ75*KV^K19}`^vzuAu=;7)eu^5~*kSETAXmhNj7!dW05O4@_o1CJ z#B<%>-6Cqf*k{ACd$AcMo>d7ktHg8jUDVCFXw6{VSdLw)mdC!`7T})b-7tkAi(zZ76!to0VQVA(e)S!{h+8)LVNz zYoC-MM(D1x?Dxe`_$v422k!SX_?T(_^kd8TCU?;_E{mF@iuJ8l!wx;yWz8q$tt>U-?!B_jIcGh`MbS!P*Sqi)W^Fay zexKeUqS?DBz~vVHe;-HaP2BsfQ~&@YbpQYY|6k+i|C~kFK2~nnoQ`L1-%vEK!==WV zp6g8=3EZ;gm8AE=L@nOy%o`g+OGH_UW5(=ud{5~evvz&Y0Q3BP!V@p1X2>yNg`EL{ z1@h%oC{Q8WIt#FC@CklCN#Q{~J@}djEHHIxxo4nFFRM4TXEbSnx?@BShV-4!CvP}< zust34>?CDV~FTwcX9MVM@Vsf=#{V{mMMA51aQd{p6F%ZNbxTTPS8X-=8 z`*YgC3rMy{5iRI7UnKV@hPWYZKRCT4?6yGoc>Nl5Lx1?%(V7_2Kh-HmB|#>n;7Bds znv#SV(Dnrl*q~2y)k_?JawN6;F$}uY_Gx<)pZGZh(%+ctK8MNR|IGgiF zHWr`NbeC&IL9kfP3K0T!W|jD54+8;Mxb#Ax1rvL+!BJ&=}eoA`8yJ9gYcq`N;+M zLI3HO2&(|7su=D;l)%^R;W&WMBSE|QIfUalv`O5?xf7d&yI)Ml)#T^ILZjk~fKF;S zQhE9>4x4twqru1z<#Gy$_dbv9?;6~$aH8P(hNQ%t!PEHQy~@mt9N0McTtkT$&hdwq ze%#kT88G2Pi9wdmqVpYtc3eLApij%D3Yf7X2IQaU=;pit;IS}VKMr%5EhBXMym&cp zp5?TF^uvGjqxomO(0dq@ao{zVof}FqvcsXx)_H>X{@{C__T0}cA4%A4jh)DX31zk% zG&1A7b|yW}%4^GprUfMs*ZYnA3ybbv>avgh>kr&aogF9ZMtBBZv7Xxvh zj5sWw^CtSwGB-cqpaA6Cj{(yKBBa-M12c{+-B^!+ANJ@MvOEOCHUG6y;d6eRkLivB z*iarK%VLmd5h-sD=bd->5ox7MJPvWbuA4Pl5LrO_azk}r;ca&At89+%+5iwR$WsNo zW2?d4zx2oXqR{~2{0+!wTyR+XqJ6H0jSi6_YESY)r>};vx2cDI_@Z26d?LM9X+=Gm zC|RgS3N92k+dI28maM-`_N1A=4u@dygb-l=MqHIeTBma2A^})ldEDR0J zKFs=r%kdX`h{dH~iBX~ix(ay5<;=cWNBRw77wEx?F3I&@2FVe-Q=ydJ zp7>f)NyFvo$~uZb)XeVX(pc1K+QAKAx>3RCA_gG+W6^nhpV8u^go5f~ zJG9O4BLYDp#hJl>vI3w$i&Lk-H$WcrIPm}l1^Uf1_Qq#>Lh#)aGt0rnS6$>OWJY== zRyZ=RQvpLLL5hJnj`>?##R=N!>ou6CpFNA?XSuJY5wLL^-GM;g3z*lS`P3J)o4 z6i3&_efXI zR~GYdZ6Wu!>-MpyCnFbUzJhQO-QAQT_FvGVnuIbpl!SdFmE1R{V?>?2u>XeS*>kG3 zl=YW&c-HMAW4=XDt;TkjoQ~=`eTMT}tCPPZmPSyk{xpK(|EjF0g&ewxPLc!+L)rY* zLdfPIVc1Ed2{zPZ-a}A}DKRc)Q?9x|!8mm|zU$3@u@my66Vz8k&;5RLhb=dRyOHgE zglHOPH*Je+?FC4uU*0%artFS?w6=<3;Cbnht7nThlq&Rchk%0TvzP4lMbs)JEdC+&cy!5$9{s0+lbSxd}<=pVBo9AJh~4D_|f_AO1(c*;y!%!caeg&dk| zFYdcHV{i7&3NyR`Thm1;WdsIL!PAy%fdkR=pBHzRu)vH|Po<8QH=vGzj=lmTxHjE) z+55d<#1KgUaOW9Z@xq#Dp{Kc2B%%!R%mAA&+lcXMIePw)V#qE8I0cmye*iF+GGXFE zvtTe{7sjG7kj9uNf=S~rhUec0jjhymB0kZ7W?}wB#0WfLHR^!hx+gX2(?tjpke~Ia zv@q?#sbfpm=TdN`A|p<%>1lF z(x(xf*y7;6+R^8M?qogf9nV-qWX$woPERj4XPzX0)jep|R05x`VtD1jVbTZ)H4)yW zFTaVXjx5JGT%n)_Mq!s%_o!FTd=!2tW_!6s&i!UUVfoYUVA-;c=Ys1&*$b(J;34l> z`BWSr2?!a4H0}prs1Q8MfC{G8KR0L&X22j-C>WQg4aO9pGR^e2p z+#YFh-Il0Rkw5^Wi|j9!1*k*%VQ_~Cb?UxiPNC*sG32OmMcuFr7$JEx`>?-=|n;?7;5B75pSq;Gs_?&UfTtfW zw*SX73e-M}v3Im7=L)|5Asm>1XS zjCcC1F(Zai8M}J$j7Vi}$$2s8b2>kJm&Nc&VPl^q2 zgWlg@|~ zRGAV03~gG-^}4aD(y{ye5%e47nsF_$!{|BpJSeiGA2MQX*6wC072d&LI4K&tTx^3Y z=gyDJebP=g((IzG#3St3r&q*8>k<=)8^|+P13CuH_r}i>lUJ#!ULFc+=m!dFZ9?^O zKQA;W7t&W+kPFFP9{FpjcUMm5*w?IOZ7B-RWc2kl(3dIbZXWaVTyzr(Hwi!rKln3B zlu76-b{F6f)(Y~D@1db^v*%H1!!>HNM2jn(-9dLW)8%qEE=O6uRLA}&=1z`D>Tj>x zuWsvQNiG4KG!|to@T}HN%4qZen~d)&im-f5)3izOumzSVm1N@OY10;{nhm?gneA*R z&*Ry`_*9IeXef3_H)o=`IpYL*WszN@LS%tk1~FwzEIoxel}1dbp>jYArHfzR9erxqP$6OA7!(P=3lS=?l< zJC-@z;b6RW;Z@_XrtOemRTk(cAfUR#n^p#as{HbZ;Pl9>@eE0V7)T3u=rPfSToAy! z@=D4)YtT`iDm>`7I|C2E&Dd0a^N%rH1gddWkU;9Kulsp6NjM-Pyh09#L{-n^r}}^VN8m3#9lt(Yu56vV(Y4ci?S-xFxy?5h z0RDy@=p5;Iy|#!e(( zct>7~Afd`dmT2GIGiur=nqaG5;vlt39WJ~q%KC~FEP@DL$c7su7AKKSyFr~UX0sLE z^B3JzWb--eR*JjFl24*^-oiG}pMNr3&hfo~`Rw_jl(%N$%3|BS`92S`$?j?Nsn0bp z94y?CNt-Bm>eC2PNpFK~JX~1mZ$YWYCSZHY7!j%kyqM1o)T2jd@rDGxWSZ~%fu$>( zxh|XxhiN_OTGE{ec^b zHbdd@5sQoH_$jZ)|2_xUbgqa*nbLV9zxYwf&U(7n@>j<6H#x8>6^-~YCJW`xRVr#c^N~obPvaJLd{X#3oE$|&9N=ga1*@O!iQkWp0ZfLM}F|9RE8g<>( z5qk9agec~E4@ld#}p&A1+oy4A?7)A4YwGX0xO=uph7SW1dM z^~NQd^v@EZy`&ij+AsXCzreq5PcV@}iZhuBurulguM!C2??d0{u6YN@xOhY#+~Bi% z73q?0{YA2p&SRRSGOjSG_292q?Uq-*sH)C>Y5vIT$Q!rh`G_~Cfe#8ji|18Zrj#i4~X2_QxQR~){hh+rQ-VMCBOE8>x%xj|Bz zv6Y;s$93HGBm^)`f&G61&ehRjq_cpn2w>@C?}wp72?`KBq_T7_Nkxb=w&;UWq!$}p z+|`-&OY zfW^8!kF|CfhB}|Ds-yIcv?rywH<#GFN%?vM$^A2eqb(y} zNfGL{g!YaVpuY|c8{|2V59IVRM>kI6%=x(obLeNtG-SqR``#d+el+a~v4lp2+Tf{7 zlR9V7TW{90nr%8iUzv5MeIkOPIo>uplOHq$)VxTw1LpZ2g|`GM848hu2x8N4!Bj=% zPuoyog1hYs*HX+5e7Z&)9dq@4IYRtOme}=5y`MFlx{Sa*Y|u29Q!$JS)4L;d3j#!L zc`6(jY17@}!Qe7E8VT@PscQuf;8b-ju;QwW7?MG;uDh8s+vN=B>;)Lcb!li30OPh` z5S8J?!F1+tH^vC7!KL86b&@{x6_{B!(ByT-Kt92QunO=v8_ZFTopH(;Y1ss|X9SfLml z;Jsr!0m{eZr=iq^zz4ZhLSo$LUnD4PQ)al=0k>@#XzzhHSSiDTMu*y-C^0*bPErG4 z@Nt=@m)ZB#xJ?lohb!qZk7VbJ%PjuzM_5?Z)u|srwmm;ugElJL+xVKcAu}wXZ17g6 z0pw3>sZFfJbo4e;)-(9q^F_+y0_(DO&n}WLBM|XBUp57XTMM=xL8LR{N0^yw;_4SxX8&)TQGNUh(a8; zJ*rLHJ^v)Gg!;Yxmb&#bQVW#r(%O?Mmhl)BoQ7)?-&vmXD8aidSI^_byhW-sE>qf5 zKWnR&R^dZgfcaVbCDgTT&eLO>gYB)F-PebuU#?-trK?v%=GJk~ozZ4p&8?|{K0Y!g zr>{$3M^E=!Sp^pNVEalOAwH!^m%M>H6ID)U2BKO2ej07Vp>BwRU?STj$L{1I{$`$Hkl(Dxi3RWH3t#M%b*&_pdg1 z5Fdw#e~x9MHj4`LBW2j9^0L5K=A|;Ob@FwS!RmBi)EH~Po<_xXGQpu%SrUOS2f0Em z{PjKWA=7*Udku7RX16#z!Wu7qoZ!#hkwWDbxZ?5%kMJhK*;w}V9J5!Yj*Dijq0;u3xv^6J{5MUM2I8+i_2-o^wEC}-XUq`ci*bd|h`hHya zaWH31El{$Yn`CiXYBu`f92PgGimvX)jb_XhmAoFrldWZAO)a9lNMR2GTSX7Q=Z<7W z&4q4g7BBod9<`jz_O)|Oc&iLNbHB4;wRnltaYq>AsuN>`T?HzRzr++gm*e2@v_mf^ zI@@osw}aiDED@X$3ZEYT#YZ3ZLxsdNQ$N@cl@P_ruq`L@l64Oexiy#@S5^kVEx5G% z=F|#&cTU}LjRG8KpV_CA{cX)J0d*}g^9zk?uW*a&j+ia7`RgF(Y+*}Xq!7}Y}oHe_Sc6!RJrnVv#k25vS$N=#>O)3!!-ozTQ=}@j~jX-}YGMnU{aqhv(k;BHA z8s6~=Z1zhLN$zFGY4oc|(UXr7$Z!%#*nD9oZ2_DE3KpZL-!X8}EUdE8El6M(CBVOA zZOU~b7V<_?tJ9N0lQU^E^8i?9oP7Xw8KI8<#rscp{we%q&) zvw{m#@cN%Ua&+aDS*}EAnaUU$#cc%x5{;EMa8?7Er^bcxYyYfLshYj2ELOf;?s5tH&nUc z*C|}VA!UcIJ$o)#w{+iC<1u)yr*3Y2zOp;BnfPMYemlFiUH2coIm86`f72+I;}2pG z+g({*ib7i;XhOuxqG7{dB8-cI1G^xGM17N4nkUTN<>6&g=hZtOtXECxo`|fjR@lYB z>!fUSEhIBr>G`3Ctmn=X43F>O*>-tc#->Y4g?lZVU)gTf4}BEr<}yvvGxxar9+P~R zHj$I5$uS~YC5rRmw3t(6<*Yi;w>qW#ezG|<5FqdJFpnOGbLOIjXn%)aF$un(gSTFT zSTxG!Vvp)B>W*3(A6s1&1)VjLx%RL<3o5=0JGG0Li*Wp_-aZg6s>=Kj1JNS{zf{ck zu#t?A%3s{&_U*({ccXXEXCodpaj?{CadjH)xwOCSQ?4NYSh8H-8J&%|>#K5i_8G{h zwS8JyDodfO z{QT^%H4bJW$OM#oc*%dh%rsSaR}2N^$sE^_8OdzWBor1{zezLNc}{)lqVHcd(G@U< zYssnb>11%8QyT9)J7MK2^2`sUTFAwqqtxAA(<8Itsbp zgP27M2Vx3!HwhI@{CK*^r?28r%_iQChc8vFfA&$1?HPD>kR;Z%K5b#FhCKBEp<-nasSle<8E*^ZkKvurXQD3fp zEfsmcY=Bm82X#~bCtC^%Huh^8t3fOUJlQF7A|l_(*xr>o zSKrh6T0_hu)5(+3?G+|eiGHz!X++>(5EhH15mMWTyK>fn9P$Bmrg*Zbq5~G!;UEey zkUm*rNIL8I6}r+E7|?!wHAfL!SEDf_+(UkKUAg__6E)C2HlZY|d&EWU!p4l^b>Gko zx=V7+AXQ6>{Dc?AZ1Y4Pqc?n+EHYo43lMik2OOTbtPK@IpM*zM)BNA|OO&Ur$;;Q( zH|$zS~=0d#?SDBV9R%&QwbE(IahQG1Oxk%<{l$y#^ zA^-egLR#%r6?&69%7Af)VG3SV)x-M+9R^Z9e9D>1qq9<~X0vR@yL&~CZrF`vZH!n^)73wuM+gh0?? zvR8%Sv~>kRPt8oCqvdT@=vUJAe2YUCWo$}5+#o1@g%f8l9i?x}QK{Exwn&<2NNdS* z@{emvf+uf<&o?;r(;j8;dJt!*hpy>cj9WV}9q0B2I!tz@X5(`gJnfJuZ#g#51nIwr zXGt#b$PqKOj$be)E*cc}U9BRSALB4mHU$3bhmsoaCKkI%OTCwWpHcsF!PRE&nY==; zX0^eit|4(upI+Tyo_2$lL~N*?u8N`KvyF$gj4_^=WwblJEuK1L1tWOI(G3k%&gitM z({?X!T|8x)Gxtnu#KCqDW)aVK78Y#}>iwIMqMU5VM5hj79>*S@t-#f#u!0eP6b10z zsisaHKk=Lj{}3uhM+Beb$m~5G52%i!mL?@wM7;)o;^+|uZ|tM#JUObov-jmAGT%`k z$dy%z6D3ZGL=sT*h!nC-onE7w3gv5h!|lBw0IoOw;sGU;CY?7V#M26*8>7jYmj*-; z-5zVNKWKCUnoPug<9Q7_dN1xmU&w`DwvC5rf80-NfidTfyvH1B6?)}%JOYRI)3Sx zdOF3Gm=w}51zH`sJ0Fw*_O5)0vLY~b+278wfZ5nl%^Z(7CvgN z>J9zk=-1Q32Yiy~2ITz-0 zX`!9Dw5$DEL>JB*^wC!2)0gj>Y z4saF2y(Oiam0k7tNk=_fP8eO3EdCOYxKA?5!3g7{lSS`Z?HLw7Zm^$U39Q)} zU}gmv7;93$Np|>!hP#c?hE+aUys?XPr9Y9qrq-+X*)IJmjDa!OAjoMHQ#8l zj_Je?Stf?+l1y_+W*6~))!>FTK}TNcc_tQqP#Is<=Zfu{-_Kqd4Y|ZRM3JR~V-o4@ zQE=q?wr$(C zZQIV3wr$(CZQHhO-F2%|&#v7%=P%6Ji1Ec35icM^WV;Sq&2u%On3VsaW!K$6%P1?v zzg&|I>KmNs%T_cJSwz6yTBKRLoS9s7XZvxr5aVN}rVRnQBdpU8Av~%VaX&qqR(*h6 z4fo&I%1~PVgOG?4Efsd}fy9R?EZiPIl>H|#dN~-yn32JrMQdhCf9BTe$TE~X9xPD% z?-F{-T7qI;*9Btk!l2!$!}VQJyBW^!Lnkp(P%z^pv8{HI_W=s_ansdaa)Q$So4Hfn zU!zm(AtIp60X!t~F?yFi`I(xrIs%JXQ6Nj0w9B5(CtnrQV5&dOt-|TP^L~c|YUx(p zw}B@Sa&?B`5^XU_409R zx4%x?^n9fOZrXOOY3AK|ZNLv8Jez3Gc5-Y+MYirc@*w6q!O?0@QGrBppXJKZ zaq{7;KVSWvZ@d_V82H77lk7FGx(Oh3NX48R67W9R|H}-8s>;r-q_9fiYP3W;OCm|; z$+<|NfdVtxW~Kmmnnql+Vrh7ks|)aS>))*>E%af~D}CLJ$Qi3%xd0dS?3VG=``(qb zK-^{^{qhwf)#3qB-p3%-;kk%+QLRielfv$lC94IiQuF+pG|uDrZRt=CcKYoOW5L`N zwtY*z%lVT#b}0H7eWhi<*v!rJ@8AwFSMa98GGaW69o?7C^^GW7qH3Zh6KFE3nl@yy zC8hwEr3Wh>v}*RrT^h3 z^zYk8s{xTTCd$`iGklq7F5&{fTHX&Uf;Hu@Ia8H5WJQ38Jmlt^ zFcXmxgLUMo?^AXu^HZC&?V0OjYjCrxbE}I;{ z7QUq^U}Lyn1O*|?;00T3<&a*qR3^h*T@rk$#}I%blkX_Rdh!zGsr#;JwvMnPSI6Kh zokbKjT}E_RYS6bMu4J=r!>@3<&bY_DYK_2gr}1cq(>Z=1Mr;#9DY54j%iSs%nPMPqU7!t#jhP7e#Y!= zF=I;hQapw;1RoM;n{+*(<7vJc*^|ypd5EBAJ!l>7#A}oqy!$&wy5i+RyKHf5%$cFB z3mal|>c0Bar)~#q&p8%0Hs(oegvO|bYliG%x6cwzn?8x}6NY3*qC=n~BIhQdOV7(< zgEK9v2g~;keAgJLg#*%d#?mN%eB_a~TeaSI!VC;5L$gwfjl$TUGf}JyLvkCo360nuR-xHqiVL=BWS3JulUqW&g8Um{F=r2qbs*1dyyEM! z&~X*z;tIy*#cpz4TN3XevbDOq^z4wi|Pg@lwVl-LaC@0hT#q>9w8ORLl%B*a>&9|tqk$Sk%+ z9%d6C6%J=p-sKN2I2De{h*!K0LKBIuY$A4aeSHPiBwFfDVUXU}&v?Q@M?eAsfJ+yZ z=YoP!ZUiay3p6qzc7}OcF(LOO&g^{HR>M@q&_Ab6cb-w9V)Pka9XX;fXwR+KV#Re^ zDe+7d+Zg2dVYjnZyd8P<16q!nBVf4EKrzlql_PtFSJ|m$&i~T$4>O%K7vGKZ3^#^2 zi!V7$?n6?Z!g)Jepst3LaAB3t);u}sv;yoR{8RyZ@W zf!Ug#s8XdE$Z9}~Li=}Zgk_2-;YtCbim|ReJW6#xFFbPxFz}W*i+b5P57m^Tp}US& z{x~gxzkK5BTe+o%I&z)i<$*&Bixf3KZzayIJ)X7n(=Y${4eBG>zJ|NpbDadYrh9BS zu<2G)Lz=oOlRNjedoT?emT|DLs?GmsdoryFC5!>uycFAl7SyBfLe^QYn^9j2hU7eNgn zn;%2yDAnw7<~_Im{1}y{0Av{CV*C^kv~=nX%a_O?BPk+!bI{Je72|e-*fQ}>827)k z#~z$bEE&+@r0i2H_=Z?)yYdC|^Sp#Z z*;4yy4}M8cOL-QAa(d6A*>I;b|93riZtlr}ku8&H_xkfR$l6}p_I-jIo4uu{V%Acb zK8VREl&6b1;2tab2=)tT|<Z(%dRG5yGuXjvL<17 z@+J*XF?XU&Z|_0rY4Cuj6^`WToJWEZ{J^UsENTG9cDva?T`*^$INbb4=@ArUC^B&EzQo{HJLKGDylq z0I;0hYdj#yFiBRw7IiDOYRKHCP7HvBKua9~PG=IyYB;e!4-vwc!MG2mU8+02&5njW zBH4j3&Pzv()t-nT{yjk(9#a2%!W8=(j2}4a6E?}w83o=1K{!j|+7F8ppU9mcQwU^% zz&lJIm#6S?C}(&mVe?FFZdN1|YQFIAxt8D%c-`mG27Nk5N7k0xC}-ep>*0K@sNQX3 zq?~+tb#$i{qVnz{~uA4Y=Q9IjtT&AsVhnw-`Ohc<|Q#*N9TW8)d#sEFi zzbbgLX&&1+&=27<-gys8v-PkZgw4Ne)a7-T>3>j+v>dn>jESv+rbR7{q!c$ZOA={5ZVMzY{2<6+G<%=J*%on-(fh)9vA4ElBj)aati50` z{zW=x+hjViAz>OHF}#?*f(vDE4Wg0TdYAINqR$B{9c8dcO{1&@4=ET5=il6P!KO@oS7#IQtrUi-tY;q06hytyTX{UO)*~Yu1JB)XH>%k=P*~0zk zW7dDheR!_cza-Y3)!@en&Ku-1bT!X;es3NQIPy%xqE@~0sgI4UTuN+l!@fa;HZi;L z^fcw+G6sWgO@!4e41_ z!B?*Hwc{Af)a6qDI%ESFcPvR(?f=Hs*m+Tr%@AB66sOnxor34zZqX8-`9N%oA%<*6 zwwO|_In|fcRL^~@q56J4{DXxB91@q9b2EKD z4Q?pI_rWj^{)sVSM&^#Xu}Bx?A2c`*urMnwq9Q{#v(s=xP9j^`MG$;|ey~hkW1#`$YgaG>;XB!neOfMjo zHJ7CR*Ys9BG&{$DE7WqG&nMNm9=xMk5bw8}@1p}|j9J@{MvC9q0R%qj7?pvTLZ9Y^ z7CqK{AjNfMq^L;(Tmxr=&;W^25Q@}z8fiLbz`E8$Q9j~ok&F&{V3o}RbX)tbkm#xM z1SQt9l0L{Cv>?q>vkyos(xqOQ&L!aj-%o>KD!-ee;$BE|=lqDARl+ANs=vtCa~&tm zlW9|dDX2$Xv^EF{lNM;d$CjYZY?@Ty5wZ zA-L&%T?g_ZU9>d6m{I&Rte1~#(S0kElbs7R->>BxIOpk#I7;)X%}JWkMJ5efrX=w` zdx!e8W#rauJvDR>vuY6y%>Dt)MeHdERv!LFO5Lj`2g8NlGH+6sZG>cuQ)eXI#g7fP zkc1@ZwT-_rM1cux>LSi4nvYP@7nM=&$t}C?Xov~K7etT-$DVBuXzSOLOjaG!2_tcZ z$3`VCewp!se}M2oH$+#KtW{*Ex2Q9;+}6A4V0G`jS%!x-2UK6|!cka7>L*Z;FsRrc zads8#&XLh|o3?O^%NL_epR0&NrIK{K;sEE1be4WJ4gy7F40&Eqr+SpvOc(ySKFn9^5RKdLa+ zc1lv2>=8J-5^oZ5bT<6+Q;h4$3h`T_(87v5yp}<+^GAKvZECp+bznl^2@7VxB`INf zNcD{!uw?T7;;oWHqZ+yO#o0i{A~YRP8i~=1IYW@^z24%u zAo!@7q069bn<(s+zn!JQ4KMN1oB-_GV63^19l@!i1IcL|~469Fnt9kUR|Lu4WjM4yrbOn^M5Zu(p9E zzcQp+i{Tfri6$;V5#o~aBcyI-=JFsTCmRo7gNImov2kdzUs^4rC<#m?{EN?U0&oXt z&DpJMcXMPoEQlDwf@p{LFVhLz(1}mUqh$RgC=&4{?VFtiJH zZvkR_H@-b^;a8lekvE2ES7eNg;-&<}zs==GsQlJ2z z{`~Ejp9)cLd!}BDsrMg!$-;eG)H0F_5qzF&zS0lIGB$VEq=RtLdzgTb<3?Q`d;U6~ zCvr(9=ZAo$=ZS7)70f29sOx19L%LyXQ7W*hb~`zK6PX?z1{8!O+RCI;yrfy7WE!T< zoQJ957&(#37@eiWgeAX#gH#-o;&K`O#tq2uc=gJ?O|aBX9WDEIl^i?OZhbQN&fxQ# zIaV798zqCz7+4gpaV%vBpI+6{uV>I~SZV~Dl~T@w3RW)H*!e`o0`|66gw3ds3rg@< zzpeL&20*u-a@Ut7(0xg~`>I@>5)n>Z6%>_Ov$OUop3=qUb+Ym(S!|M7!y|`WUunAz zJc+N}T{Af12Ej(R-bH_6D#z<`7~L19gpXnl?;`{j^PIZeHHX)-*1*XX~TJjpfC?wLxT5)nk3*$M6UP3WI@ z{@FPa%x_{z-+j9$25+slqPU`ZyQvoqH;J|5?Q%Vor@U{ayk^O+@?HT~oKWr08b5E4 zx#g4%q=jqSN9;$eeAetynH)BpB9pS?9NM9wQx6!U7!w~5lsXLrjZ{2zJbNiAX5My( z<*gBEWB!#v`N*c;1&+C2!D7_sd#tQqkMGD!L#$cz&B}7wR80P={v8cGIMYhc;<5q> z_T^<-hzd3@c2nB!vlKYe1h)5HAAyz|>Gdw?K~R%Uzic~sof;nTolor4=)kRN2<|+v zhWGTO(7z)t!p}iZ`h`}mZC|L`Kk(YiRJGRy!=kd$84S0$E!U!s#R5cADQ2=7SIe<+ zY!^>7$h~}_+0g`OQW9+@MmBUteUiSV{8W7v>VnG-w>soLzOYyvD_k*gxQy`BJ+06l zD7EVQ|HzIbWPA)+fxv=4=D{(e!C{#l1T)=tCG^{=7LL~nM2mcRNO5p;twU0{xb(G^ z-UHqgeBa)gWaLPSou(m`sjYD0I6&r^`HgaQoq}z#yt)BcG#;ipYo|_72hyreW{A*0 ze6&v&czdu8RQG(_{0IpYVJvZ=F%#l+JAwaLtI?Uoafg`ZLo`xuj0M%)PD1hCjP7oDiccnA@%X6^m zu^&l>gqZDS=6(1-`{k^x>EOFK^dkLNVJQ9rcgF@nfzxMH8N0$#Z-@%Y-hXPJv9?$R zP9S8(8NWqNry|&(?iZ0o6cRf9Ao^>#3fsZ{njQ^<+w`|O`<4pT%kX^WA6f` zww^YkU@q!WcQw)Ku`Z0COm%@6YuYsx4maq`z}R$1@5;N9g|6p&)wsg`SDC+b5YD?cp_|V$Q zA!pbm2-mmQt0Xwvb%DBbGC>5#5F?pA^JU@oL3yT})*ChO@R_a@9)Dz%FbK%e>5u!@ z>cCTNp0L}k$Le{rxO$()eBCjo4lCA{#1(i%kmbJ zp_*5d$jc%ZN3Yt%ZIdgvp{EO)7UL(_b@f$gN)3MAC#UE-nGFk=$k1?sntU68`G`qg zX8X!LW>ZYN^+bNpTw>H|2A^)awE3@UJs?0AFuKZ5`R&w?oXEF9a%6T7TyaH&S`Fau zQa)n$x{xGv{xFIekE&KfI}ARFr*j%NT9&DtE520j8m$s9Pi;Y{oxAGLG^(<(m^@iRXglFne4M*r2|&GgF4gvEt$MoAd_~|f^7Om34R*5gz8S~xh+1E^@glx4_j_$mCh$@uuh5-F zj|scvOZy%~oebg0h1Kr2qDOdhi1jhyW}hP6eQ`1&M4;k+ zJu?_6h_5DXu(2S|_o>AF?L`F8*?4|_K`KdtemwmqRJiuG*A?+fN($1x#LdPlqSj$} z6QsJl9wI5Dnf<22$H9n|{Hs-}(+GCk)at6h=@tFbDEp18x=ri54cmS6_^Y;T@`+H- z$@%kwxpPB4jC-9bc_!idEjg3Z!&&#n<=v}aPUwTNKmQB#pZ1uMLaV&gzb+FT`2SUS z+}gs{%EVaD-r4cL46MCN|QI;Iw&$RTr*5DjIrN)1b5mo^TcfNO>yJgV~ppEgyFe>cyQ~5nftlIS@co4f##yR*zbS1 zim!?Y$E&nbMtnb$0hJ=~Qj$ID=`376C z=}s;o0d#e%an7`UTxegW7I4SaI*I0m2fEl6peVD8xuy1YKb}kGzyzNpokrJRwx{l9 zbC8}qq4&ywIprx{jN(G{jiE8vG}bKAixuNMAn-57h@rhAJs0(5#yA_PlL!+CIk%6C z_o?QpbDk=Z?7oyZA<==V^aWA4JSW<2SE8VE8QpVEEh(0ziDsFc|4fWGop(2kmeGPg z#5!~JEjnK{oD+l@lR6MZhh10OFmHlMJxps2sY4$m)xLmGu6Py=SfpqI+D7yaHK@-0 zz(){?$-o}NjqHgryCVdUY`n=ZQP=vL-Ulm*X}-DvkABH#3YNK)tA3DS1xE5xWX9FO znWDDf)i@WyJX9J{vxTrZRm+&g}G=D*xl1;5t4+j^w0Jp5rP)` zkVp6K2PFmTShkt(J2_{?I-}&^1hgQ7(tOBl(;(%0Ffolh`Qs$BIw8C#aG7`7kP(ah;4j{bw|eN~mIQYyyJF;7yf> z7J}}6AW1FKv~Ji590hZj-tAB)TCBhlO6QEhY)W#22cFrT@6t6CJ-4+Qc;}eM4LdfRh`GhxL^Fk{UiU%b@x4CZ$21&RzB|5;${)aw8{@aBM5S3x67#^P`m`=dia( zoXoc$`={G^lz*lu^dC59Dv6P+vKzH(?Oi#ahT*kLOR#3(_PXTS8||(&_x?>JkL$-O zFRHYUUa^~D1`*7=aisBru(>PPW-_pG-HO8sai0;)tmlGbzr)$!Ry{Xj1-Q zTYaPqlv*=M5;~?X`*ZR`6<_<+m>7x8I3HXSSQjtQ={jHw*48xi4I71`u3JC;h!1KH zn$dHNNKS{0`-xLeIbssT79;^oD1#2Qjr)LxW-t_p9%G7dV3QNjiUwuwy2-FBLkIb% z{l*nj1oIUhKZSz@3uwC?O)t-GnwZ^OaU#6SYgVSw$>z6U#t$nR=W|f6iSGl%YcvB~ zSvVJ}V^vav1l%;LokKUGbGdCa+ARsMrJ}q7>S{MOFDZC` zqDb+!^qG~G?O~Ctgbc-8Yg~51lebH6RwBP@X>f}01&hNAjrqDPtNXQruUd}Fjx-Z> zPj0v7C@J~YOEp~V*!m~O{jYt#>9Xa%lFNQkhrOmonkyyLvv<;J#TxRIjYiMPgj0L- z1+HzR7?s0o*8%c9+=#W6)4cBR!9wxC=WS)bnqsIIl57#<_9ExxD?bIE>QSLhyITCd zp7b-Di284AfgZ)w@4Fy?l@#}mKt0Y?8zCO;@yW^M-ku>j6Bb`vfkyZI!_B>tEDmbi zwsr&sX+s?GXQuYd z&`N2*z#+j7O!meYUfl&kaV5<;Fs$47xu6J@E1R^ zgMF_oAg({wdmSot064JTC~hLrtH9BS9R2CNBJ)0jIIiF5LuxJ3LBo*`JsfwcJ9B?D zMwNOObVAU3UBo---93SaJ<^xq7#Z}t5j;)bVLaX(p+F=tSxS?V`4a~h0J+~RlQHfq z2K6eTKrtd30+QWpj-5GWGsu0oJED74_@cibd^$pG*U=cCUoc|#983zetqPEUKS!rA zzr2=j^j?d4SU>6voB@Gsc?$3AiWDk|?Mai<6WC}vdW!A9K_ATU%-wEpj7`uuAD+b71a@BZoQ6oi^%h zrmJ;a^w^sV_DY*^`kozyQukvZFrmnAe>s|EECij7&{J5l*-zY;_;Ys)g5k?!D!mp~ z4iV0)3`fzm+=eo)2)gHkHmQI{X&7spGGtHc<~?=D&H!O=?}g-mrC~WL_pzoG8fO?GM4sQ>quYA1#EjF9HzY{LK$vpOS1kKL z5YlNIIo8r48avVUYQa5k4-JQSq&e~~Sy~B@Z(a-U+qAmu;st%}z(DvT*aW1BB~fyT zEF3nPA`?qu94HIg8~;lysWO>?_47-_75>_0vD% zZoNt4%D@~+_cF7ckYY~lDgf=K{3k%CJX2}Lvbf)=BHeE1?=8VgzuL1 z^H=SfY1RWga~6hmS()c(q7V@Zr4j*zz;v85M%e(cHh-t$kgeP1dFnCQID2DtrX^%! zI1a<6t;6KJBm6b4w#ZSrA*6!Z^9Z2;he?iSv~oM;=@~NDnBg1dtAPY#GP^)SgUl#*>rfz4W z;_FDEH%g0$ZDj}2>u$-8UF&IGC#^9|l4>Jc1B=SwKLmxBAs=64!J0)FwH5wQt)}-!`-x5@7&o*Mn~d+*5DCOiBfMz()oV zuDuxOs22LxRl+E?kOQHgr=|! z%J&2LUfNWkZUL)mk3l)ee;={V=c|ySYlidhNn8O!rBhcocsT@XbLit)=$3NNq10z8 zEf-WaU(8&j>J7SJ`JnuUUv$bVp8_UNjSq7o_7e_>gL8;>pfX2D7MC}v76MwIgT{-( z*>>G!Fh1;GLF=(XN-X0_+F5Y60|)uIH)C!0mMrK}{3O&v7gcdvw$|%2FqmpXt5n}_ zhF&*kt(c!P)-)?CMSMm;rG99|qb&3N`zTE(f(sQ?+%h$M39CyF{!_=>RE3|n=_$I7 z#hv#&A@-=&$d)Pz7p|y)VVNAK2wpC?{y_rccinA?y0#s3KEd{d0q_w z-&g^Yg?DmhnCyOMn0%YJUsva!Zn>Q}XR%5Bh=7AFOP5sJIVvX0NjGmzRN_^vx#246 z2>&dn{H?*6W0{#8s4W<(VS*e2`ZnWK&2gHew0h=kF!5ROzlL0DMKthqNQZT+OMS=t z&k@s6`7832Iye||J%W8&mwU}o}PmdLQ0jorcjnJ~#67GSHmgXjqwgw_0dl6anj4wu57D2R0+h+)eb5M^7n7(4#7!)iCmY2{;fV>3B>9v4 z5^NXi#|03i7I(JLHBfNEX+k0}=>D(PibQ-=G(>*P=GohdK?d ziz{ZFke_)>7H`l`Y+{-U9ZE-56(C(84_jus=lnNdf>tmn2Q-QlHIKU^Rsr`{AR`?3 zE!DQgQO~okcik&sEG1k{J^~SIfeXGpELHIhF|_Y24eO5!I5RG%Noy~ zthM{w<{%1m;;Fv@gx&0&`dZp^=xJPH>sh9~>Qv$lc4dc@>VeBndv|X^+^FSB_% z#pJiSV$Qku()`C9$a<8Fh=})uSMnn!UkA@JfGLQ{G4ISR7#y`) z&9t;$QCsKcU|S|Bat1tn8sdZj*cirRne>r|Ob-L}`8s6 zKTC%hg0`PiE~QAhT&_q?K9SG_ib&018CIhuX^|TSF*PvA}JvF)04FrJSykn1+kzm^Uen z`HfJ2!B6(6$i9lXR{}>TALgGl*hoGzO$<)jVis_@LC5v*o-A#rk0CLA^+3lHhfW-^ zh^MC!5g}KP3$#y-@|ExWqM2cnESD{P!xKERjC!m2jLF?geEDi1%U2qH0)lepd5m!M zmA>SvQ>ZL0yK$!vlxo#HJ1Ter@c}*`K@xcK<*5U>XUd=q)CNZg>kU4q9r*o;cySb+ za{AoYE*8Yk4w|AM?2B@HZwV8Ot18 zq6K3y) zahYFhw{+%i_I@qc>Nt09N7Cg=1z6o(m{snaYrATl>UE%P%c1?&8Y>^ZfiX&qTh>6paT~{6)o2ege%1MAUPGdfcCX6~D)nA?1ZvQ=0 zY$|onat9N|+P*%d&WkVZp1CXBqjqmMOLlk7P#J!fp8)Fhywe%#`U8N_02C1Rg~y<% zQA_r(nRos&D~XZ{hw3F+wI>o5MRtGDtw(H&BoO#cxVJ>8J7q}=aeHH|vX2CJK?X!a zp|+rR*kx7{M!5{M5GvW{CXg8>=cZg_i>UhdjqFR+l{AV71y4DC*v`iLP!Z9Nn<|_w z7Et^9!o>5=&Z@;>DEU4FRvZuITWf5X0ZQf#TfI}Z|4NlYZM}vdmQ#F+l?3JA0I<)(g~Hk%g_<*wpOBP=8#{{6wBQ^ z8m422QmC;z%&FP>LNe#P(%HYc?ebrc82=^_jdt|t5a5Gc5*SydhvX#1K9Bm)g|DPs zw$evl&Fj08S%J2j|p2*t93@#?E3I9&c ztoaTbtWv|h*eqS)mJeuF$@^4~u2KtA9jt0?6G%3QkmX#F3sGp>#K zPo#@=#zzI44&1^3u?O7nTjhr^mWdkG3N{$_-YnF$pCz%5Yn{3mz5mqW;W?e2d2j## zK)nBz7Tei7TiDq;{g)PBt6SL>sv~~i=qVhEGrhD3dA=@Ep6kNYI|QsS;Pz$5EF}c* za~fa;y7+T5GyQtYZAaE0?m2(7Yg#HJAfES9LL$sdnzlLwg&vTS-^BvRCK$Up zc*+>0h%)F+ye9}E4m%WM{(jqt^=CBg;drs4aT2_9iR`02@}-R4|G7r^JpQzVRx?>EBH$y7(=xc z$+1T)rd(k}HA@Bc*5PaGb;Kd`yWmVS@HphMvkqj%U#hm&RCX&}qy2fcRqABMT&Ep7 zbq`Q!wA(EA|I0D-A}f!!Z6%M>Uy+s1a4Qd74%&6J#CRBPaQo?cJ1yPVD+ga@oVCM7 z+&_UMF|+tYp93!r3vQm0Pm7sH(B}h=pQmpYIU7Wqy^4gPEqta9LZd1gQb>!>*FVn2 z9n9$+NTZEm*H~-1zQ!A9D}8>jaZ)Q>R#%B`wlSiy(F8mw8W0`p8t;nyZ`B8xfvDY zb-i8tjq}0gOdC|LUI2l)<-rTT!*$fUDGpc4p)LdSV}93s;iMDPCGBFRI#W6<+|~2< zwGli7W3mC3mxXn9^c9oUR_mMJAb)C$nae)+<{?lEVoaFdT6sfuHt2RzXGrW|duf-{ zOWagHSLSo=3=uAOCnTPT-fx$oZ#JrFICsK3gZI%BtMT34qBFmA@&MYh-Zq~U|QWsMwn+970?6ZWpbDV;N*P+ zu@C`%M7Ro_qvJ0=Lh3f_AT|Nd?(#n!hM01~hrfaBFo}#66W}_HtfJ^I=p=2^2jWH! zDA}nFi1~=+s7Qa2L!|@B5E0B<9N6ByYSTWMC&9pf3`x?N56aMGf?EbD>uUic=pbD>pghs}7GH zRWKCx+IcXi?kgY}ce==z@LPnKH!JsQgXGJis9wERH?yo14(}$neknSxs0#Fl*oPH9&OTC8Ky_O-h3MN4e3})|SJM1kQ*)Xx-7S6e&9dx7*|`!Vxkm)d zeN5du@JS)ie`UF`R`%VbDh50VP;+hXz%EH#%GvOn+{zLtyk+{jJ)d7o+|Wnxt!bJGgKXIf_5Rb}NlHkw?^$e?MH)e65^ zsMI-sxgr}70 zs$Q%WgNclq{{B_yW68hjo!;(*O^e<*CG3xs)diC!D&#cI_@Yw>Bs>M_S(Az#$u`pn z_(KCNlCuh{{{&CdSs0oZ=f%9OGpuj}|yUE=^ec&~amu3lGz#Fm< zCYJ4kPeS^n_a@cXrJqvVcZX3y5Lt>#5pdS;zJt(Qx~rH-#TvrL(MC}H4*%pk-;RST zmxCqlfWwuYOG(uMX=}bgq#VR%SJus^S$R)f%8FNYR4G`g%U4#@ zlgPeg$0DARJO!DYH5%uQHCZt9RjiB3tst$2ldTYh!7`F56gPFl_>N$~IM~M{#Cwes zB)inCk}~@5Z`it5+n`@tdVk*(km~vXDeMmf%>z~^Ys8yWh-vP`W9)DhxVX_Hi>m04 zsFo_U^K?hPRBG?aO9o8fi2g+w6L3vkDdKLp@gQlD)CSR!D~(3mpFq+9G8>d_Wb$Gz z=hfpx87Kzr`ytUqL`Hj@COp!wq~D(|7;c7pm9xe!B~RzG=#o^KD$x zQral0S$F{-h}A7RUrgMUpR~K^aLIOmAu;YmER)l>*Sn5-32FZ>MIm^0-tc54-w;>o zc?C%p5BGZ3DBj~b`TZ67^QII%`iwTWz58soK!&xcTFk)KO7qwK_ve&gDyy@c#a=54 zw6qj{nI)($RMcyG>oQ@5BI$DBt%YG#$0`fNMCz;y)TqC+hQe9BomG`ZFVAs$1a7~- zsdX>oZq)h06Lp9ZYwarWEK*+07^J^hYY4xUm4U0UB1_tNB znH>MzwX0Axw^a|}X|IB(aUdC!HQP=>xiXHypwh}sE9wfh@ps5_X)&fxwT9^EVQT;95DQ=8Sct#Zs?HsVa0(90+Uq zVx(+?4+{@6L;>MUHU8KM+ot0J0Ivzt_KXSQA*Xz`<(u`}2ydUQ!|PgChP4;*YG zrLCe|C2nG*8MEa^A1h@Hp%b1G8eaBpu(QHD?_}Kt^^HqMUT>d62xe7YY~9ArqgRQ4 z^f(I&e!aab$`SOfYpM~7*F-5z+aOLLi>B6*H&ZIjY&_{0u)sN@vV7{@n50n~eoBG( z?oJ_0rcumStcFx`G=5ZEJ0a%KqL9h0n*Le5NxA6lGA0v|%pKAg*h6}nt6 zH|Po*l{)tHjVa?UXtFZyA!{;eA=}KOt+_7Bar{sP@wiU=cv6}k-&=|HfcOB46^8(9 z3hFAL7;%VOG9lFwf~-?oLl*PH(O@9Xf>{E+7|ODg+pL~gV^)qKBaAqa;7>S7BnNLH z9khtZ`?5V4)fyhvR;WOlXry@vW^C^*EGmWWv9-X~JYszY`1r9TW17i2^BS$XPrnf< zuTVm`{+47NzbWQ8d65`0GpyU*qcMqlU0i9x@w+93M@o+VG~GW47UurB#T}=V#AAz_ zdWs$b^E*NXL(nA0;B(d$OpSBFw*Gxv z9t=0}XiQ&IWnOkf$d+LHj9$wly)xPxhwvhl?3deTJs$ACd9;o$=XPsXFS2aVYbk2K zN7dx}Q>JaUaKL8o4Nwi=L3cOzsy6P$oz5ZY`j&@gj%C$_1u)K8;P!q+6%?#*k-S$G zx0X!yPZs6AVP{0&2RvNOyA?Bf7eh-KSJs*s8x3u4$nE^K0^h^GT9#7G=6{|2mph`^ zk_iy)Ibw#~yK5d3e@81NMvtM%cz@mol%~g1C=_m%JwYJH#baTOG zNr7G1KEYusC)BZ3+5e)z&Q&bH%;=h9nRs{O^k=i|>j*7YURVo6R^aB_yiww#wFo~E zndlL*rjc!JYyY;~0PgP5rT+vV`dkuyLuxgTnwgQ+8k2*EW#~fw&S{e}1`pJ0lS?gj zkj-d(+bE3KtK8 zZ5T1{mB%sb5seF~RUL}gJwLe5FITr$HqTc4f25sLaBo4or(@gx$H|WE9Va`sZQHiF zW81cE+qP{dv%i|DnmKju&fIj@x?0s$tKRDM_S4U=p5u`xqLLUXjI`d3!KbjX5r~fTej~FX z=*wYs6uax||-6IicxW)n8#F=oNo?oZd^!>s|7vDlWe@ zd_U~D@fM>hBjDL5-Rdy)Lcvv zEV*R!VNR_{%^rva*&K$nTw_h#$%Hw&gOsv9s?Y$b-MQQE55yK?!jTXgQ&banN zGD7#eE1|pUc##DB{f3yp%9{+VW4{wc=r4t#a2o1|KheSKFsy?L)U<^I?Bh~|=+gD3 zO$Bhz&PWW);Wu={Nh-Ro_7O{@Wd3cNkW zoDNDK<7UJg2-^?U?t`>KcaI21j8x4RqJXImE|&&bN1e*m8)Ddt+$txv3*1lSA>2pW zEp!~0NtPeXE!Z94LcpXIhIhnlD-wqX%=Yh_dlc#MWO`k_Yy$V{zI5huirE<1-=e>* zrPbJ)(Dle#cmciZ_H^02eiC`u$C99j=$h`R5NKKX!%$=bz)3k(f7r*I`+lomxqcC8 zq2M}6F~#?T#D7f343z26MbC;{UR$z1*>9u*3TZt>KpIs)>16gx541^YpKeCmLbcz% zZrUDLIqsNNH@$^*cAv-A(sQNQA`q`?wR(ogT3%9bprEVqNZIny+gFChx>R{7b_i|kxzBX$d$+3kPEbz3*qJCx^#mC&5ar8 zQse5(dFn(@#c%@f7xXhn)c~MYbzpLs9A~+-yub#CddylW4UN25Q{E7{hg(RK{sEM( z;G{0)N)nR8(_q)Mn&o6W%WPm)v8kLA=f-CFbbutRoEZiqI3wTzZ|Tgf+Rp>Ar&pt9 zWL2YyRB~hm_#2cnC%fPzh5Pkk;OT$5(*t zd$Oe)Z&wH}AcV^!ETboW$&p+Ev`O4>7S>FC4-^3cuR*&ohY-BLjxfym84KX3z}EZK zP~4ibvU)te&6>er<(cP+(Ocms z9Vm`URHPizhqrm9xPFrI93I(_MWkR(!HQl-o{aM?9fS>_(J8#WGmtj(MTxWb*i#40 zpB#&g+M;F+2#5u4UT&kHJoT^zgi*2a5vwS?_ylYt2Mg+USCdFJ&Au1G{;}lOl$uZ4 zNRti`Gh37n#WvFk*#{@dhN=MlczSzM&KW+Ah9X>a-qY7V!ng@p8e0#pxdHXk8hv=1 z!8|m@Hrs?J(-f{)^q38uaJ3y~@Tf6L({-cC=VLPrtwNwob$e$-r+2aB1wyn?@{z9E_-fx8vzT-&+ zSu??t5)aM?`85#d-WVK)xqMu?JZOV*DBz#6cHQa^AWeMjVp?_u_K1hESS?_%ftd4q9=*vw4HMlw|FVA_FsBy z5t=hZ1(-5p>^?4+AZ;VJ&~Vzf=53`BkgCoIBo3dDw_JOHk7ap^8nmfj@BTlPd>jWw z5NiDM@eE>WC~fT1v>Zix=J({S2z1@w^J?5%!g=hgFjT&Ciz(w|pP=oBQ`;N$V17r+ zd4R<#$fS8H8FfC&hly_$l1hU>TfTApJRc)?^}M^QQ9U0{hMrF~=~~7J-Bf3tbX}b^ zU7ZZwb5H6p>8?Y?P6Kmb}NnBV+FM2IX&7i(E(r&GkLqaOKw4tSd^?HCB8OkFJm~g!E+=fa!%^>n&$NY~8wevAzzmtgn~CrT ze>4Q;ee!GZP=X7_YcPNGM3>BrdIKQ~Lav7PO9~s-o4B96GNA;9%V_3aa_6^^Kix^_ zVg|3PM}GVLnF|#;)pMKYxoDYyngD}%P^%`L3{XTQ2;+8~17UP@QySMnkVRC$rhud= z60JAt!vY={6g>X5hX`ZNp$>=wAE|84@aXNadi`io>ht^y^z3di(i&$|euN-hs@VUjk;u<{>dRM|< z9Di=xhsVuQcZjX70R*<5F+UHJ@?=tK50NcB2>S`C6O9Vx5QA1M(Pv~w8atil&k&t- zymu__yH1a0ygLTeDkTb&HHkzeA;}oElk9+o48`qm^aGhTO(fNC^@GvQ*EWkjt>eFv zYKzY;@7Wy&U}K2a9onrbAv}v70saR|MGZ^SVhF78%$h!%YeB*xNI}ZRZI+2;rj5-5 z?5(JvsT499?A0HILC{Q8RLrzIhrMYtu|TmqT@412@C)dlJ!e7VUk`Hy7)|BG3S{G| zkc^#}M*xPkI(TF}OP!ZUgxI{d=G=5KR^Z-Oc6y+&;g5}4Nu^~z=!raunPmt6`Y@#B zl3=R0B(O)BdHIC%$ruNIdNKjG)6gUMw7tNO4Plntr=7{lj4mq1(@G+=5a{p$Xki#a zdezfMK5{g+$iMYOB6gBq%JaMbXr(GLhkl`U87~v(YUuu#eK-~|hh-z=* z*j^#6{UoRU*l9!I;}ZS{ds;OFVEz6fcoTvQ0;j;S0rmS$>cH1(%#9t0`5a3<tXYo*ul4xX;U0x zEfxgOoAa*Zs4532B}S^FL(}S5zphPXqoRr3NQ{jZCHxa7%mt;>$gqd)M_LfdCI@dN zYtTatI5VLOsK@w^%_{f3jA7wvC(A1hQdumqtDRaGE0r>qEJk9_aIaPII#3}~^8g)@ zwCJb2;($i#y+!Yn zia`P=Vdu!f5#|DPC&@~B1Dd;Cf?LX+GXJ&=zag+hoiOux$ZWZc08n`Jft-s3y~)IL z#J9SH$TjSk5nttQbzeNb%mKAly9H^eWU!0&K%W79xzOjey{f!;wJ=V4P_ojGPv0Hr zDoSSYB0^&92q%nVbi}i_i2j?v%tiJKzs|SY_t5hn=+xd1XeloBBB3{YnynrLvLs%@ z$gQ#4_L!R>gCZFnB_&Th(j?c)|78FsQIDl)e+HO{-y|hbH)SDD8j;2Xnmb0}>hPxw z-FqBIBj{uKF?xYq2uoT>|ekFL~$3CBR1o=H^7p%b@xvhFf~S@Nc|%<(jkKH$mmLs z3Npx(&SdtQ+amt7TT5y?i@}!e1(fe{9&k2Pg`CPHLKJ-Fj5Ha=xdkM-7Fal%0Vl$1 zslv`?eCQ&r9$4Rp2c20Xa=H~D1(?s4uGcQ)541Bnd?Kmmg0V~}at5O57UW&(E&Mw^ zW-Px%N*$fq3btv39u@fOvmvsK(AK}CL%n5uBKG2JH0XKpJ&>R^K1dCn@V6&*nYolH z4i1+mZtnnNC6KvCggcV{x*DY4{wEe!Vf{lBzd~LVm0i{+?vgusLckIi|5&%boW{E& zKcl7XucO@G@J~?PoW(?8b&%A-NVK@;8ydV+9l~Im?Mi^*Su(+n`eXUJ(c>s{%{-B) z<^+W;1K6{|CqH8O5kRm}{>rE|6W2y3PT_imlJq#M1Neg9Lz6J-q1g;duC*~T(4r%d z6`^}`L-9Y`d=JES6KcqGV4cF&s=0El8_rS-dBA}>G4gQDWrttMo1t>&yO$D+e~4k> zUE#C44VNd+`Q5w!I9<=ZnI_aCmcxFx_lo}seFs~rm6Wrq(K%98*CqI+XvIbn*gly> zMh4o$u)sk_!%(^&_*EP5(0d@WGdU2{zpQje2s7iOT0T4ct}cJ~QWcP2vE@a%`4$6n zYTyo_KodtQy$0A@aEysM$4i36uOpxP{}SR$D^d_IFiFX6ea~PV9>mqf9npg+s(ySk z9>+(O(0L327n;(e8u$i~m6O^cI&=?x$)SyOd!-e18)N{U4~O6PT_*3jcUcrSyA?we zs#CZl3zusX*J2udZAp$oclEX`6uNQG8$)k$KMc3DOY!2k_txyN;A7o|uRf+*9X?_A zVi5?*;HbQArgVm82~QZP7uBYXH3qTIp`&&@Zfgw@RulrGJM9S=i@w zPL5_88yP@l7M|q#Z4SWJmY$0dIM(8OtOZ=I*E3qaI6Il{b0MBX4uni-@{pA{SkQyL zMETG^y1hRsVYH&Y=8EpJ#)QjtKKQtcbt3o~i*?fYxJz})_!&#Os9Ib9jPZIM5Y3kV z?=WoHFVeCx;_?wh*!-Vq)dsL}W!T|u)$;SN<9UTpy9M0Log1g$0cz#y_kSMUqz$(> z#6-WPnG*i#C+HI04brg8hf&k$X337}Qm0v%vH}f$12wJP>Xyqi$79y->sb?!_-L3CGDH6GD+AMv-Niy%cV$veQr5Z!=oI;{y5rB}m38J#Pv2^`6PW@Jxh z%sTh%I}x{jLQiGkudndKm`c>3F3Nl%iKRu03ARDgLxkcRP91WGZJK6|kmE5S`AeV>d7yMzc%_=gc zWNfLntQQ&xaV)2X7a;Ov+Yd0$|4G9p9h$IwEs!PoV1v8o5J|IJOJRg^FZt)@bi)fg zMT=`3|I69Sc?T;YCzEO+B9i*1N9|rr8G!usn!m=R5Z|55V~cw`t270*?n-Pa0oM(q z-4lU!d$`z=XXztnGpLr<#_qNKy`4dSqOhRnD9088Nv-inT%Efk-1A#(u8acV`{3%_2jmhNq4=H_Rgazk{?Zuaa;d<- zOQ#KP{c%Mze26PhP%+xQ^RSsf4(L%txwA4tRr${2NpF6l*nmN^CT%6li_HnBbhwN+ zJ0HEc{fmP0nn_^F^D2P8wqOQ#ykiImLN~G)SbVO>LM-FS697*= z?7=B$5`3+PfWQnlu^f6z%blDP`!aC<4o+Bav+|4KV+&9<} zo04aFqW-+~YLPcj1zC+s0O{IV7PwZyLrGaezha~F&H@mY+LA|KTD+okYQ@psIJ6;l z&d!a$9jPU0`!k^b49#ZuBi%7PZcd=UuS;mWbJ7ZQ_m-BRGr0oO8#&HB2-uz**Tq?miG3b;V&~|vkwyL zt;wM2{D(FuW&~EIHcy5~X^Wz*`(9%Om}w_O zQY~1&M~E#e;#leze`B552CkWwMMh7q2pa1QHy#>P7qKWu3XNw3fzKz1=*|3ZWN!N{nAki$T`^@!C9NpP6n4gt|pu)VkaASUrDaEkx?K{gptU#+2a^ z1L0dz4n3Tq{BsXJoYWg^E0=-SA?sKP|J~b37Kg9FO@@zgpzt(noPH(H0okgn4fjYM zmn#_%AkGP>8GlHM_1!AqrsRFt7dIJ4o8Om)32*7Yhi94;wa__}DLCKL-!I_t>=-xH zt4;cS_*s$o@IlP^~Tn zeZo1ad>LDj952e7?CSk`qAV}U^Z$u-5qE*HKJL7Kvj1Wkt`NLKsRG<0yre-IJB7v4 zbx8}&U&uG9Nj3kTr)%84DorBoiRo254)&-Y#9J0+Myhw{E~I>$fQn2bP1X3uq@0(A zGt}X(%SirJ2D%8YNOuO|Z2(wl5W74>N&l$JfF3#b93ggw?@xsuJuSG1lca1PSJt7| zJ6hbECos7c-B$2Rfx}&CzXt(>U0A^-6aRY#Io5`<#^ihK^zk_&DpN$O`Zn-!R+7md zCaos9xo1WEazi+op}b_Pyeg4e4W;GH^+ud2(A@YI}ao1ZkywNU3xDijG0m zrO+G;YOR-ZZ%Qw2+g$Fu{R>Jb$??&HHI#11q14d{7O!Z0ZoO28OEoiQH{_TcouUvU zDled)x@Pxp99OL!O~<^lp#H-VEXnJ*3xbQkMf7d5@!tcG-A4jwptX*6ERd490^Z6% z@NI@czsyvpyH)TJmc%hu8dxEB;M#&zuWN}e%PsaLlg*?q0i%SDvs)`1{Z)Vu%HNRr~4;6~Y zXS^K}v|BHDX9J;XjQKQ!ATLww90o#@Jcg1!$onKfuHuEVcM@grbeCBA9>bA*{U;I!b`?)!jHJl}d54C#(scLEr zn*#$%0MGCcYBL3CJrQfxJ^UZMRaq+T2Zn=?bx3|TWM+$^1?vbc zV_R9`z4+qIHaibTFU#Mv7R3+Bv zZRgiAoA$M~(h?j{55=ku@(^>*pNV|C{pVw&^_lym>)~|blA9hbpOa(7_+>%1rxBZJp)Qb@LL*215)KpmHN>s9~>(JNmd_ji;)&%_sQEKIoB2zedvU1!?dxI5B7A_UGtg3Mo)t)EP6y2JPl$oKFV}QSpvU+a zhe1^Sh!Diue>hB}|<{MmtCO%&L_QqxeuR3Ty5*PqP{DJmuas z#tlF@&Hc(DOr$eHFbtCPDZnGw**{oa+8F8_sXVNv2T+%-PH&A{N+Ulz4SE&;1!ZO| zxVTH$UdQEGC003|lEEC;BDLuZQ$Z zW|*gjz$d3=1P$RD=~oBR?$d=lZ3s>G5%E{}W7Hfq3c_>|%$y==_o+1I0l8{6}A7N@yjUNQ(1p=ExNPu<#Ih-tS)BD6T75Qp>b(nr^|2- zE5byyh$I4Z7d0*>U39xF2{p~5Mr9-iOm?Y4Y?i@IE|)DR zs-4Qm#|>(IE9$(oG}=b1na&|jmF{Z`K2X4Jf2%!WcP2p~v0Qv*W}AG@GLsZNS#bkc z_+I}$8TG-lo~Sm2pi@ZC_Fe5YUG9Mim?lV?1y!Hb>`zM#A_(-L8kvTkn|eC~#^2!i z%pw!zRGvJ?ngS z0otARrm1e^FO%+FpkE^W!~)9O1Rf^=g7&vqfrEloByZzZ1vF4^(nUs0a`3bPl>G|} zjhVd&Nb0DH$+X?RXF&p$m@EhHtP{|5K#EDXNyTBSG!N4SUZQ??c~;W#W;zeWHjPxO z<82@kKynham)TH8IL3R+bw4?= zcoS-KetN8euqdvZ?fxMoi4Qe=nemRlLAcqv?tDI2GCunDbM(>ZZEvmt-$@N$Deu2n zcbZ~0C`xX)f1Y+sPcXM8dY;|`D-Z#`-$ysNEZY_A&xk%=clS#dUHWIR;U{me_ehaH z_vL|5={2S6=_HP?@;j-fas=&fR7~c5zmUeQ4}o@Kx}Z;1zijBCH+?+i{aiTG#$Xj@ z(lJX0mS^}@E;QDtpUzMNBxGkY-=0?MO7^413AmBXDPuDrLYiZ!(s*0aLAE@ez&_t& z=~pJ+_}bRFeomOD9Jw%eGHrMXg$`@OV$(u6nzOlwRKxj7*@uns+Dp*d2w&insV{za zlUVm`t{y|*8;^STa&a95YPTI_VhTCvwckq5|8DgWxSWi71lL$A6~^#qZ>w;L=x*F601u$TB2`80(3)D0c0^EDZmyr^?yO_W1NK`Kgw-#KoC0K9(%{nO|jQP*GXX@Gb)DpKiCX{v}S*WI+suj~Y_3FUnuaJ+7#4Q;<{q63!F~+S%C*ZB49rz_%QBmA^w55cPQ3pw@8F0H(e#qDWXuoSGR^=Rq zjkSFF!(GO1ZIUS%Qmf-Kx$Z8Q81i6?{Vrrg$qaw7$sDQ6xU@l4T5~_&oJfxi6^BVX zD03;3%*+iHFyq8Sd@>~|@%diQ8oQu%bi$j*;M15nf%Tm-3^MDr+FhJ%>-7`uLOVp~ zLcVa&>$vvy>%dhajV4O9u2^nuEKwj9DWTBGGqZWO7~*fknZD?5!(X(vkaQgs;DdAP zsBaUT?=&NVIg#;=`FCel;DkfZQ@?*zA$c;h%sulLEfV#wZCV5I?hHTO=E$-!77v)! z14}7yB6w^Qm!ai}tGgz`m?-LGd|$01Jk`+H#OxQo#&WOoBw2dHDT()?ml%(NJSFnP z`82$qvP7ZBxZ5nX+#qSGryYV%<$G(zZML z=an$pIFFj9@>S+F7lk#5V;zCUf?YC#XzT>H+8pifa^d$>O@s;?dXN2*NYGrQ(x18U zh(^3^UG~)|7y^Qwnw$22)7YQi%)wmDo4JqA2Mx0k@ehE(xW;^tUsa}Doz8J;9MAyJ zF+4WEh;3!maYhYaLy9g4yXQJ=!1-aMQ)tyhrp9#M1{}V~j#+%B*Yuxh#i{V>MGHzx z;BDGQ5riiws%`tjnH?VB?U6OkNWrd9tXgela8E>fRjsmf5@E-35yD-G51O*l4kuHT z3B4RrXxr<-)pn;_am&1$1oKnJ#s;bzD3HpX0WC~;F&vC>GdychNg z(PsKdsAe|R-uGgf6#hHdRWwlbG9q}GVr#5UVLN^Q>U0g`V@^UiF5fbv@GgWY?FC|g->$< zI{gP}6BZJ-1@W?os~=c_RHA`~eMOBx?XU@0LdEnVH0mPi5A1(saG(n-;1vI{jTHYR zApHM7Y~%lCaLkmIz=43oNak*)bh5*i1~cJ#^u}E5H^OU4D;|b-yV#_@8}j8_k~Dgl-EoZ`S|rO z=H>nt5XKg6obgA0`@BZvf_88-QCpSi@3dh=S~wa>t-f`66EEaK?kzU61``ylag-uO zF-$YB9H}-k7|I`+)MSi(2s7-Z(fuJ-vtA==Q>6pDl{oRWCo0SvpU2qJS+Vx9T8Dog z$S?Bu-aa2bOyY*V!3_}w;i%cGY!$`@Nbfp#uLxgQh5daQJNDGmSW#7Zv1_(ZeFwj0 zokGOW7g!<7w!lFztZ%6b(ZRqmeOI(V{kS>au{g-Zax&V@~i1k!iXiZ%E8=)#hd6@t84;5+^!8;QlxOda5Opbu#F#|+@YfW^z9NRO$jXBCSK zbKW<^#7=4rh_&`-^o9+qn|Y5iD}v^y6!&atD?#(zQiuHgoXMBVjQF2Kv_kBARcX=* z|HCyVlffJ^g&njUp~$q0r{>~JPXuEN75CAYBu=a1+V=^H7-ww@q9Kb98-m1JVmNsH z(Z<3+54&>nOS)`<`0ycF#{mTGO~=X&cVAmHS6E>Ny=Y$)J|E<=`hr z&NvI?alh<<^+FJEnh5{djeQ_|W8l^4w&N`I?ZglWeJQn9bSuBF ze}C%JJr&n~v2%{3K+-J9sg8Aps(GF`q;4QZz*o2Fx(s7eA7`Pk&Nur@VgkvH>0ce5iOG+kbUsQ!1x@=mTtkAV2IY-Fqb;xU%C zH>vTD=WCdD7%N>fC3tCb9XWZ$%MkUl`S3T@wFcR6PCc4j8$OwINxiY@#4e#wZ8mgA zwA%Ba?istj+6`$V_`0zH8LW3WdG60v4=Wg>iEUtgQE@@K<<#`N&iWmy8-Ppg=gYCH zPPgT`(PqNDlD4rrHX;)g4rx7x^Ub0F_dcl|lsUD@X<88t@RRcg$0M=181EV&FGCzW zX!ZYnAZ^y{-3(?FCRB7esb~c}v^HO_x@mdD3<8GU6%^&y_yEsmN@v! zUd(t-kgSV0{&#?E?=v ze}*?)4WDgR`L3d+ma#MY7y8_cI@_=i|B&aGIZK^t6*N!pnl68wc`Y(av*9rwe7Wxc zdGYHlVn;=1uNe*JZuD@lLfB@&+12*hMTxx+dm6(1J8XA$zm7X z!TOORor$^w8q0$J!(y@KZpy;ej`=kmmZcjt9cmJr=T#E2cI6uN(zSqb3*@AJBV@~9 za@--)lY@qN2S*Rtg*=`cF|qyVw=kXIgE$t~STbC?f?uF^XR9qo%&=xlO#INf!n*4^ zD~T9%9_3>r(P(l5zyyMfzHEHxe!wuQOtFNFTI|Al+9tWlMS0kd=42bjJRtDo#>T_1gym@$q%k$0-yvWVntN#XK=IY% zJat)X4xq>#F40igq24(QIgn60?Pb60=)d%AI;t{Iy&&eyHktng5OR9&oL%$iBP#*r zA^T_Zw*oUjRFd=Ij?F&)@yK1G$@J z6rArX4`)5#-_tBEN@xny!l3KGmx&?J;cv?MtuXi)Z3qdMT}4YT7jTC)%Tq9FS+guj zFa=CI9K}B=peOJT4}j}SBg8Go@lkKK0jfw959@PJ2%nYF$GiuF+Qryc3oQFR{CnmJ z=uPd`bjBvGtXBliGIj^p8z?mFMxN4i*$P4tfuTu@R}6(C{OrvR36^*`4eycr1a@O@ z-V2NE7mJe}oa|a$zT!^C@0C2TE?d0b{6BRK4R>*Ah1#)8CHs8{Qx2Av!BtuP%MJZ16}8R+RrU|+CAQ^PkYn3t#~1s@EsLMZ72U{)Y}p4n0uTcvvj>Ob>bgGY*(1L zO}bV~K56P7WG+`JSj|1r#`0;(m*pB)1XFDAGUuUsbzSAnF&IH^)e z`mU|$SNR{`Q-p;Pku`w!QE5thmGoB(A@U6nd>~O(xPgCzv*Lw%a3qO)Ygz~vq=x;0 z#%&Pagd#vLxXnrOyAB`&DUR2 zHESc?kNZ{TK}poxk{|C+xJveJsG*vjupmr_=P{3fo?wso7r8SB zu;6&62!a79%A^v}^iav0Ch~H!588XkGZL-!A2rbG9RVpoP>5Dygbm(~KJsV`7Bs>h zQM4a9hDxKW4~Kb(4#{J9DtINKq(@%oOjeI6xJBQugh#yQbY&@j z;ksx#0Wr_*^rCd^t`#vRLKeB_;XlZbZq8_)>|viSoKL5*XKZ%}$<)y^X0aHW#!cny z_wA9#8B0ayQ<94CV2K*Bap;ZNvda9*k4l_vSW}f4hZyK)#7YV6J9W>5OKt<$VYDti zGP}sm+t>P>tUq-1(uNxcobkh5)tRpO=g_!L+5_B%i=3~6?U<}G5{X>BC_e-52GU=A ze4*jkj7KGiy`c@{oN1G#k!}mOFkI@$NO@WZ)b(+I>QRxYSXkr?$%O6VLU)0Td7r8F zC-59EL$l!Z+h?t!X|h|T18t}U2uQ%?eJg1^6n`NR+npZui~MO@ zq}0W;uiF=qgZt@gBG@op&N8O|g|O#Yfi0!_aK?p1mNJ4VM={F{k@B~ac1Gh4NY@1@ zBv~#;JZlOdykY2YQrwa6){n~^xlnOl`x*GFd)~ngS)?w0Oes?`59hv8$ zU`V8HGF*yzMV+_Nf`xYIGKy&4qOA`}s(Zwr+JaYQz`k1wnxV)OgF9R!5;8@ng{713 zYInG^C2%czwnVmvnQ9#R1J1O)pjl}$X{1Us4#)pSBf}V}`P6vONxTo+kZ1Dd&n9XM zL*A-ns=A#L6y9nJ2G=$uB_Sr;OJB$?*=q>=C+z;vILvge?hZP=(-G1b8x(8UN%#6+ zwP{YklT3-}z}(05tH{>v)D(KRzf*NaWwYJZvXzRZMcDGea8IXLt6)cR znA6@S*L7Fm)f-AM5nbP?=wsmvnMX1N=GXTNlJtg$js49FVh2cZ%bMX6>nhAoV7!2KhYV=eA~dil9ta-?aI)>ic_6GQ z_V4&1Zi#})U>+nZ=dI`jt+ku>Y{*}{v^P+6BE=^gIsZIN(>#-LxmbbOy%s1*xorri z(0-ACx02tOX95a@eJuZ!H`e9Y!G@&Mbimi);q0XP;Qpabx4v`pj8ofTmp-df0c$b% zi>`MoU0qCSIgpM7Y7Mw7;Fw+MmtLPXix-(P9k(~F>|Yk;Fojnbdd}#H*ZYLdT8ZD_O9|pSU-D|@yFKRxh80$#J{(+%4`qz0reOEgCs1xDK zh?6I+o)aaZ{(6`=XxAnNat!6Rw_osr^OlIXQeJLwKV3$Acnx3P+)~(#zS7hfx>}_0 zNY#kriSge|DVa4p8ga2vGszm#!0P@@0UG%oyuO{s-^ zvP-7c3ybU6ge`C{)2SmT%Kl5zzNxU*6OXPV@~9B|g$E?AltKoqkFPHis36kYTGTt= z*pGnazU{V~6SCGMD4%>ty2DGuf_1Ej49OS~$u0jv5F6@zgQkz-t)ywhT$1!)n)N!r zZvV)pO*a&S?+~L3V@RdE+k8c~)ta^KE_9zbDdVpu{a|gLbU~x~c=E+xL@YpASm?E@ z1M1oM(3(|nx4A$i?Abe~~=dL8^lNpVaf; zb72y+{uU7U(`>SX7W}-m;-29KW-M72eQ2Ng%E2G&1cVKP zS*<3!S)3Gkqd# zVPf{Xx2i0=B3km0-#XWn1H#K?gc=IXEnj;XGQJVq6p*$B2*{N-P(~f4mVe8oT5k!? zY}T(*yV_^v6oc2fRgzKubeZzP;;U|D0~-vt60@Wid1^e#pTx+=`p*S~aw%|+3=Mfy zB~xAqpwW=!dJ*<6<1o>WDqeWbRbcsth@z?9ZQdTuFA<~CO0Q9176m?yD~POF^h!DP z^pp(Yu(BD?fbCDF)0itN6Au>n8q^zd|Gi#yly;lHa2MY45^^fI%MRNM+}o{WhN$7V z!1{`mmmPi(lMKdebk6(j=y@isu`X-72qVRd z_AaQ?Gm}#l#LY7|&3(?2IW}AH#<#v^#zCGEJge7m*?(yC3d+uq8S?-{yN(~dSn_S< z@Cp~8AWb3yW8|O)JX%iHqD2)Yq8X?C=l&G)&X}luTA64{eb8gv4tWq=P;2TK2T`hD zP4(BbIdy5h{$iLba0kNg6$gMTNs?Kcs=gZMs1K*uw2V4>p)!KOZ)!#0Zb(pgqoEWW z<+?Lhf(oQRMM!*!f}f=aZ(awJP9_B>ZzcuDC=KGN#0|k_nGRSLc!#x0{N`vP92!gV zD9X(yHELG}eL3V!6tX{^AC=uJtG3PAEwQ@YT<%{vJu>7y(mx*)0No#DZj z&KDT-DHk+w8>x@$2z7>8V+hzSnlx(1?XroH4 z=B(&q35Q`d!!YQa6NtZ{$vDyXIwR}^L|Qu{>|m?nwQOUi%N|hHly*r_@+XCeYXv<; z}qf)_JbxDHZ9i5*xohdZLhF-P5T0 z>ArzJqNycL3`$q|(`|F{o;9}!xMo5wK_3SGbu&4UN1-hIulw@g`2qz<(~a=i1@)Rz zq1?&LBrd43oAE!x!2?699L^PJ9F2-}QiByk*G4H+bA)q3s#%yWrA&L|T(z`~i47R( zp*!W*)!}qW`);cT=11*xb3!dRaVvYFrjN2u2t7OnzDh$1XV&1E&BIVl-A4#M%46Pb zIZX$XiWHZlS1d!^=7+;pc|~B@?@{`;HD*61@B;I=mV?QpQz7Z;<^FIa@lwEitd>k= zLvTxjBW?y2#0_>UbD6#de;(U32@tIU)X1CIsE>=ea5cL0_GV0yg*?=2+C<>y*(;|% z?-D6cPkiH=`O-GElH?Ive8L%LyuLp|xS0_=Lbnsv56*l))u>+o#A{lKNK5z()mTIJ zfVlB|sT>%V-TvqxWb@J%{jj8bv#)(0C|>wRHY(Gvczj_G=SGvXRNmVXxi+av*xY=? zeJoL>T(8_vZlz!r9d>*1In+pocd2BGX1c>Ig#EcWI`jPQ?K&cR5Y5|Rli)P_^yGZa ztJ59t_ff`xsR!nKnpi;qFg@^+;r-fX;clG&RzR4yNF4BLEdEf=B~Q>}TJzRM@OU*m zFb5CnQ33+V2l%E*WzS=Bc_xej5}>cA)1vq;SrPSprI8%wZt40uU?xHY3U3unbgJ1v`C z?-}D_B+}1Xduft^=_(q@xtK<$EQ^c~KIKPBC&1U@TlQn{=?VRMW__+O=pI2x^JUwoMCeEpl8oG)NzO#;j3?U^O049Z#7s_FF+(`ulA*B_c$UEFd89 zcsN`U?FtqD7|QpNRwC@HB_2fML*?IXhF;B@g#^1gv8oU;M3X=C2vimV@vAVc5et!M zEo!#a%vwC-(alRFuOYjcb>rJgnC+DVvc{qBl%-ykFnnoN1z%V`Ol2r8hX(nxv_3Em zG^y=M)VfVL%=0&s5hXDwGhy#q_%xsD1g_HqzkTj9egorq3wsrrzXnb@s85y(3lXW& zNG2;zI1W`GnfJ`h#eJksc2De4gWsUNGucM=wFJgcgj&Nh+dvecdL^Z2qb*0e{&k5>%=4fn2^ z*NzL?o>m!;Mfh8R|0C>R_3S!9idcog_4LLQOeUSJ^`>?&Y2t(iVsidd+ly~Z+CpRJbAPy zzH_G(a`Z5Vkqu2fe*C(Po`>giz1Fl$OLTLqVEHZN`Zu@6ge7^AV}~ScB3XPW8_GT& zsin6Y@74++?`hzPW8A}vSTY5%;edTmpd5Q%A1>cVYR031p&0U#*ei-+`VxfzKUced zQS6BwAvn(GGmGFaT}`~Z3L#ow%jT8&utw#Jo9^PDrZD5h{e*Mqiz3 zi&T^FtelSep^PumF9OQOq|)sP4kaq7x?8dAVmgo(NaSh`61tA+YEW&j^fl`UC&sIL z`8dUQ+!;-8WZYb11AjnLDT5oBBOq6C=-k_&{b$l8Ux8~-BbZ)~$=kY=v@vDC8WYk;;L-<~I8x{Hx7~Id5+X5UqW>;_Pkq%>WiC%j{Q2V)#0DLc zAaq&>8LPR<4Ix&%9w^Hn#7noZ$KyuOv77G0IQx+?+Qi~g86z& zJnia*`xg~@Tz;onN!`Vo|DI3~X{&oHa6u=IoWJ1r;ci}@`8Q1(ZYBQ6u-KeJ)&3F$N^mu z;o>m=s{oz38bvKeMWtP#;8DU&^BhU5WIsQnF>sj~fk8>8r4kf@H3qE3ff6T{jxGc+ zhHQMRZL*y%W+$k=M|)u_g1avjkaKB{*xBh5=WS}adWrHhRdn%1$stYa_-Q>^t;meC zQH_z@xADnAVu*hrY-b*6*^D%1kZG!%9cJ}1OQ30leVp^*?R9(DQ2}c|1gyg&*vIgr z_8)Xdplm$_?cqFqvZDz$mghbz5Fall8z)1$;HF*@I@({z18kn^8z`H;=}Xc`O8fbL z?_9W=nG5rJy3Fa-zq1>Ou8AaCn<%%@RL8_?Sp?t6m{s9<&*K6A9 z4R8g9$&KFng;E~p>ws$f&3|nO_-zk&V5-{Sb~S}(i81^(3_`f}ktZCiXB;w`i|66TD(O(J@w-xV{VwlbyXS_7=`aaJ{EUT+e-hx1t}|Ox*B-}>UtFo ze{7huE{)p5j>$LOEoVFSqx77B{3ZEh&ipUV+c!L=wMX%38S)o-&)%A7Gx9M5lm6+* z^edT#tRsRG9~_=dB@QilL1l|02miNz5TI_=IPIQ^oc%hAhW+SS`g@ zRK1Qo;Mu?2SaW91MA=>>WBrYAYE@61>TQE0<@wR!(|T2}<4fCO+!#k;8$Ia}9c%f| zeqY-`L8rft`yjW1b#aVm@~GjcPDl)UeyxND!U(~JPU9+^fY1;q&|H!+$$&CM*f!K>XyW~H zVeV)++EKhGc}<0sOtdYVS?1Ecl2d9?d;E4d%g=zKKb}a%*c_Ni4l8}RmynAKjaqv? zkMF+Nl()&{wpj-6S_P4^9J7O^xOb?j2#`OWO#%&`z2htLjUC$&S#yXimkIlEQ7vz@ z6n9(gZac8TXWw?Ws@M^@q#Lh`HdqWZ?8IXSbFr-|-YiA?_-AAeA6{49jFMpwD@UNh z_+?b4v8Mog8Q%bg&e*;x287$$A@P>E3Xmw<98%GD(E)qOz>FQmw$M>a=+4=q{d&42 zBnLHZ7blyJz}iu%b!O3s<8q>Hk17(%^6QJ7$*S>}puOUk(MczQK{90}Z%?Af|1^84YJLEvm7Z_E|M{7unG#c#Aj>GEDU>+r z^=#bE7rbE%_8(bea*YV2hsLa2%$AZCKnPXn*S|!d4ct>f%9N2_K#hhPd@cV*pfBP0 z)S5N-WIEsMgXT}oPIMe8F`Ia^QOu>d?c<4nlT<3D=Wa#$3qO8fl3YkCMM{6*r-D+I zv&prCll_IopE9FP+LIts+JZofRzOd$=L%cU*ktezR5Q8Q1(B%-3t1ap=o!8Q;S}t^ z0}@)wC^u&FAke)Z@p2`pEe{*xk7_%>C3OXKy-oIuJpz(8Y)DY=c-ilA(caP$Dm!#c zxt%**iD+9<$ZmmvcvJpTlKrr`Na8()gAb&T=>^hq4kS*yOZ>P{SQF(~vCLsA}N`&}@Wl=VYrM(0o zSBWfQiM%%)^lZwj2BnG2ElEpl-OCtHb9RKu!fRuJ1{5}XI2p3}1SF2;G8?- zAcXjLfz0IrCIuElGHih!fTcSxU#k_36Y*-i*aIEv2XqZh*csisRozXfSm+7nQ?k8e zlg@5f0fstGc)=(T<4)EMJsjGe*%yLKR9d;YtekY49(jip*$|Z_wM`8yf=pp#WUS*~ z2Dx6MwSv1jm+N(PTd~Hr^*u2itf*>ZGP7glv-0}l&%OVRqT)o z7G+Iq)ALuU*_GB|JlA~;W=DjG?t=gYcPv7XYDnFRqR)NUF9?JF5Sb|MM z;ozXq{%(UIKna_#7#=%JBV&4C$T?(tB&Hw=?hUyb&K|89ee{H*=-$5OrS@-bJ^Gno zGe!=R1=6Y)!;|h-(J&TSXO-eLx2dkH8Y(J;xMIN~$MXTfrtak29?JgH@%r}j#N5=5^D3?6&V|03jNvjoA|ERJ(9xdfPPyjQz(qBPsB4M{ zh2dW{FVf%LutC^j5Vb6>Fhkr9V^)VCamRpAE3jU($eYU2S6a8eo4e~yx!tsV5}6hu zO|LhvR32OUn-SCKlRMBC(6FCkLlHOaw#{I*nK4f8YU{IwzDcVCcP9yiscqVt?XZ{m zHg#0O!e9nUbdhpsc1Q{u&+%b0g}ICIPs$;`M|xyv=55@La&!a8`C=~*%Ic?)-gI4m zO7hNG_7bEr2ZXTxNw|GUZhM*BI6*ebhCqP~;h0dPJF@#km`e$_YJy@eg)LYZ$}Re1 z3i)wq!SU9H*=1%b4S~glqGHBT?F@o{*gM8+F%AM*I6*=q@V2s=8Zp6xxyWmr^znT$LU?*TNdE;=B_JjZVK>qGfJ9BmA*DU^2^uf7X@eh# z)Z0@`UN36|lx_nYHY@?841wS^*&>{wBEw3O>SUwqG9X7u_?F^IblO{8>J(o|}#>*;vEqVv<7b+DQed|fpokJa7? zj(aSguJiLx^vlEmx=`hLXL+(y;L3e-M!BT0|Fdk!1|$5%0cRm6p*obse; zyo=b#ztepkXZ%nGZ1is@=4-jdSV!|>z)a~4J%{|xU%tD?2^G(%2n(LvX{3$d4D%RT z3fB+#fAcQMBzweA0sw$c{l8+@>>SK(oQxg*7ZA6%rRzpZ!>Q{Jl(G(0isEqcp_&2N zwSpDLiss{iy2Ivnn^a^9c_tfDIgz5z<@NTCk0}^D5V5#KOJa*>_N9#mA$VYVzdk(x zSYWQN$;aNI{rS%3NR>jRwc1)KeHVs%70%iix`n;EfMPzp{>UW>@7zR=L?w6 zAGxm!jmuC#$3VbL5!?r0)Zj+*okFrzpIuqJwcqJyA!X;wfflOlnJs%H;v_rvt5EL^ zVGN~XDQ>3QVm;pIwx3MNUN)Z}-CZ@-U?{koXyNTPyp1{^3>YtJL>wZudrwUjQu%FI53Kaypiv* zr_pUEnp}i3`NT+KkT#qtKXwslLit1PNYo+XHte9UwSUkCYOL$CbGQUu=?(Q*o=Q77 zBH_E`{ktTDbMA9#Tz6iS(PO}_mjoIaNPt`8To%B5G3=&*Vra5NW$*Dio@IP}!ed?f z0CGIaDEP+MBe(|(fGpSm(RsmE5OfIe<3v!QcRZA_bJVCZUA*TgNe>EpC1nbLtJUO4 z*!p+Z3Y~+TrJ-As$L^8+FO3h2vsZyDfFG||T~_s9i;X)o8@VwZm#0e{X4$Ul4~GCb zIZm@1cyt}5Cpf}N7A|>q;oB^7K8DqLvol)Ra9lj5R|ia`u&;Rm562R%Tj$CeA4WUv z>}I)M6^woTva+3FL*{s`od9b*)r!k&373y?IIS};vAd=Zh8yOtzJ-+V8(YX#*SC*Z z9yDB*Ij$QYXtEDk**aOd*)EzeZ(L@s&)Fs)ZO(OI%>3O|PwmbN#@U4>2WgjtIg68t zD;)QEjg!1BehbH9rNPUHt>9M=D?Vszl08>}2>#-w5n-IB)nBY$;O$L*<;QQfD*i2t z?>EqXfvJ~y?wg+=+$kqg;F#t=`(4gaO@ZQ^Xn0&(E-wWe2D!3w@Zy)*D{m*yK9!A= zS&MLx*9D7&25=c$q$=?0{B{6%;@k60OcYKK3itxjD*t({uuY{N~7#cyU#7 za&e|LT-A#YI|wWjftrOAw6U7EpV-4vik1cJocP^eHE>`m0rcVZL3%C=?}tr%&9cv0 z5Oxt^v>Vx~pqRB=0)DJ2aF~G0x(GM_%=ocbR`bheR4jB>c#Wn5XRV9$`T}{K)&;%A zy*|VQ-y5`;P3K}uxGuM0zb`^O9yEUizWbkc=fF{fsL5h1WmN>l$EO-_)HB!%K{+(J zXW#emoB|5YEWw*z_)aM?gxjurQb*YCj*I=uN~1?SP$u39gzLRUqgreoSAc*g(l!XzDry-IZvuS zMiHnQlemlD0#{_EaE~d;c>UVINL~gaN!59a=O$GA{WMyD1d_{hXSk1j^a9}QryN%? z8ptqh^s+D>OJNTcV+Mp;s4?b689f+oLVSIQ(9E<0^;u0APu=Rd^}c)mu)tyu>`?pd z*szcjno-`@lWa9#FJe(fdRVobpZ&Yb)!t&kKFex9+o|jo7&xBWNu4WnfdrFMv2UY# zcTt*XXUjrFRXztOSutBU^8#LOG$0Jip(!&4HVB->Fd&+6gtclB3&?RVFN3-v& zn+q*#E9Sp3-t|z*pt<{#3VPT?fZ{_R(1Br|w!-7$(ts1hCWE?0_55J@+^739wH#xq zLjkQuNaHChQ;Sx0#!@RO0YgplT*<*nY&=t~p}MWv*cvD_V5SD;A(e4ktJ@CNG$3ui znaiDmhwG`L+Tme_qsy~|r3TOPZtHz;p8ppAL#eX10ad{r=)MS3{;t-d^jRr}kYVy< zyF~$fski;zQ;9OY+{9h7^JqH=VM2p>Ge=7gy}tr3<@KzyrKpiZ=FRT}*oXH3-l^d@ z;@+6&K8#y2wG+3qW9wEVb+O3#0zyXifamUkxB_H8 z;Fj9dl|rI9sWJ~Bi)Oqaka)RHc?`i66%}KrOAo4&gv9;F^|n&8QUQH)llHhdr?vQ) zWv2)h4MXC1UUIzw2Y>qCt4!7q^hDhnM+|T3P?7DD7M~QQzV!g#1R+}(?ssdu2Mk$q#n_Q+wOTg&FZ1I!;x8lCh_9?sdKyWdmb@vT zyEnsod3O)N2QFsF<}Nwz{y{rV7sJ<0_)%onbFsg65Q!6OOI*(dW8HU9Qmw&@9XA2o z&;)Xu=q8fWXG`AHL0q;dz0aaeWsqI-lsD~ck0rWubfk%s1e8JTaZDTuTS$31)qvD} zIn*;^xlGlhpi&JhQ#SbiE;O-?*&#w3T!!~C6JMv%Uidd{jXNKkoT~!< z%~>9aY-bhCj4kU*wV;4)1_D>&835K~sF?b?r;OV(QA8A)G5SsDVq73$`zu)ff7wu( z7C2#BG|~{Wc!76u(80Aw^PJmW?O{N#3ustj!*^`h`%@&xYX1!?xm3bw1M-)u_ zLh*#>G4aJi?vngS%PxRjz94P~L{9}P*NZ~TtO6zzF$YY~e4ez&y}dvhpRMk?H5Gky zG>cSd+lw@-wE)kk+ALH_i`s|-NGg737%#ANBh{x>8sg%}2AnU}PEq=+~SbCugx6TbH6U(@eD0?Z|y{n;n_ueHT zJZWvT{PE};){nb{i8J~y=6}L5nLQfL_h_4~iW!<>huOtejH_VuGz&GLlODp8IHet( z%Lm(NAbVGxGIrU>&a4jK0l%l>>OGuQv{aI+24bVE0F9iJlUH|CG_LaNb>{QbtmjBT zw()mEz_c6szJcON3O6z+ncN9Z4CjP0M-Z>n*B9^m(_4C)}UBG z>e=V46}X!Iz#ugQc1qxIReeezq!`$zeM(ezQG|2-22}rW_N$0yVmWWKQC|Ok#HBF> z1;bbOg+grp+hq2Gx9)>^@)KSuGoPCRim-mN!4haa$0WC9*aj#30V}P40j15MIy zg~eRq$^T+4dC}tE&6F`3Ov9NG2qQs)GwIjHr3D#F&_+*leB+n#eMt%0Oq&(QJbAL{ z5!h!yN5qstkE=EPCie-Hnh7`WfE$dTxfcsE2iNgK5Jd)H#D?EeIHZUn`P%@y*NEg6B{+b%k~03Q>Q6PWQmVi z7Uk3+I#aJMN;DXCMX47@Zo8>L702t4qXcOaP+HHf~ogphEX$Tq>EjD!vl z$(s17A|kOb+3G9nYf#~|U}<}fRkI$3nEJ{@L_?#BBm-h6R2XiBXXv+kW7hv9FhBXo zududz8g6i_Z!El`zXgR~NA-}QA~RGIjt;LD5C&cR8K*YEhtpi@cPF!^uK=fq#gY4r zXB(C`(thtMTrro_n28LZA zdy`^mINn~0G%0Kw#k;xJ;hMx+dJbst%*)-Rs4~wrk0qXB;1!<5RV)+dZnwiG8TC>$EsWPOQ|CRx+a=0m?jV#$8u4DXYtp_E@pc_3 zJjx%8!gU-sL)3R7-F3)7+`Q21gLbK{sSQ!ldrO|LIha}hoDN-9u zAUHvCtJ_TuD23!DehXIXs>ni}7Z%)rZjfu_W#?W+@56)n%3MnlOL(XTb&-pKanVVI zq2n&0<&`E)ny0zOtpld!uT%$wzTub6=gKSAq$S@&>OP+5pF_>V_=Dq%HzT^s*=9x@ zBoh$_fb1Le=N|MBP|*=SCeunfLMA6jf33FPq5Z1|ZJv?2-PsWSo7fsjEr?`(t)pN;QPzA1b5xC%1l)(LS=PJDo&>UP9fSq;(~h| zfFl^yjG#eUi1=v4I=-=s!2z{NG=VizfUvqjqnP@NV$w+b(R^gQ%&RAOB2HPqxX6kq z;R>&fTi%%dA~aU-7P#c}^=#pU#T)L7DR1`7!bTlv#scxsCYf}EnI~io>)U%A(R2waLoJdaby6ub(s5VgE3=hX|*=Wgfjc3Tz8Fz|GMduJCjeXylmiG$o2o zzIb)AnPc(d(IYD^*xOuzPW+tp3Bm&iPR4}u8S|w7Y2;nBxQ+=UV?0I0fVMsuqd@lO z!5pZZLMQlk(w`{?-4%Cw%?9dH1h;90cI&T;nVA#d>7>)Gz=J=8+~0pjcph} z)}Wyvl@w;e?z}X;eSch~KVL8gw@peQ@xRIHN|a z^yCTPNMpU*$qU$qB92SOSgBX+r@QORC61dWbTyDMUO82|B_FnE)dW?2c*>J%#{r;@ z=H;?!ip1Pvph-29YUt?Ch6*onrM(Tf&83kg(iGxP4jbs>5_xc0KyHP808LZFCSb<~ z8$esN6KcMa2 zsNNuHT#WG8s3#}ee#UfQr=)n!>vmC>_ zr>&D8z9AjP6T8x<2?o+5y37!9eNi0!xg~V|rWo+n{U+^w(4>dE8536A5X0; zz2)ihg`OBl0Qc9ZV0jsm47Z?WCIg!fR|p;g+}MY~H@wQ!6oDKX3#a^|*8<0Cbjqsj4`k#tnq z^vZwSuw87xcwv2iNc3Svio?H=Bx||>JmdTpppW#JUM5Ma@JI*UrB?oKYdBO28BP4h&_xoHcEqqfy4{|T$;eQRe zZ6(%a{^3lIUg`>Lyiml%T@7sqpf!`c;C==VM3mcQhUkW{Zbu8V;)iG@b=}nNL7G&J z9ZDegdauODsg)E{Q)9v7rb#m^UMrhI4!TESv8SelrnZC_B8BS)>j`#KnXK9WZ`-ln(GZf4I`29=8|y>K@fK5Mg8XH<{qgY0` zxzRRu@S#g5&)lSvOpaBNJy3*XDIA=RCZ}JIqEOH!^T6`Q1a+o>=tdxYYhihCW%L;G zGZqz28&XN6R}qAu?1_>WCEUPOl2ckok$4I^lnZ;062E8<`L;&Uh4g(L1Zx`b)@u!T zM}&l8@9rS4w)DMo#9n{*>5GBg82D!-b};}L@NYsSQd+#Tb>l{yFGe0f*^uM~31VA^ z+ZBW`OCuxq2r-z=p~`|$)F}TbYP|gw*ljO)F1nxhKOh5;-A3^Y8B%xR>?~ZW47bkX z#GpFiM0vkri2>(ha7*AXKdf$BpRw8xa1Xr+K7qPM$K2+)mtoR-#n$*24P?KK2PsTR z$JFidW-#yzFVjrcmf@b3zZln!RRgo-w};X}PlP6fjaNCH%ir8wRG?N8iZ13ca)HH| z__J`mX^+kU-`_IyY6hxGxO{ZP$R1+?oss|K7$}UB3PDmf-go-P(3{$zm z^)MEHVX~W8n5o3A(hIQ~MJVG+rX|)`8w0edlJOa@lx+;UrKW);Fc@>>VpB{A={NV7 zP1tmIW!!_R#lh8{SG$@I*@^>T-LIQ1+3r7h;$seZWYJ%%+PIv**w+hD#ahz{k56H* zf&fE6B9Ij{8u9Ezm}*o5$dlt`t&>R5Zf}L^W!7^)hITB+?;Y-I?e?Q{10s_})L9mq z;!vs8C5`O%M*3u#NH8588wl1SlN5DOTnp_mQ$v(IOBsiuf$l9F4o^yySxUbvH0>w( zy1J}7QH|f~6XT6cHCvXOL$`W$fulgArKkd_yR#IjD-a`C``TLbJjf$Z6%#?5goIDQ z3>*nP@qgDpBC~gtaofnsRhiJshPaeLYkJlj{mYr-+APv#&_ybf7`G1i)Wo1c@0o{b zgxiZ)2RB+4BBUzu0hPfQN?byH9DJj&euF3TsvpH;9p)C8?8KOfract z#crj-KtonL5i5<=z@b#)AhZ)S985 zEFKG4eAkK^rR~ucw7~F^yZ=628i0wF(L4118xV|vXQ>73h|$J8W{~b67X7%74(q^` z+aCqaYI69d7{H+SICAfc&LR8^5xR6$$t#dM?TiSalTZ5^#)pCV!6A;41caY^czgL3Te z^Z5>Hvq3c5>UP;PL#)yVA^Kv=x5ljedr>fDEqiBkxA<37^b+y0e3eF?cY4SfJ5SX zl@tWf2E(6kSBq8-rKmwwwd=lM1~2DMFs_V#+t}-!2(bnz(u#k^dC3IaG4==% zs>0mGqX8JAWx@_hv4w&y8QHQIS(?l;*Xv`@Hv1clr)>bK@L?)697Xh9T~J=35Bm)e z#<%`g>$IP5dqSA-++Sy<5&zmoZ~K`c^*(p%N2}pfNs)0Dd~^x&%9ZI+ z?bUV>iY!X>00#g%HMLOUd>P?g{~0fb|B3<0iUSjmvUHl$vFhUnI1xV-gZN|pd7$|i zqx#ZBA@yV(zkob#kCECB#I6a_Nc|9n6nF|kL@jk*fW*R9I>6HRcyn1u7*Rb}qdpRJ z5fl;Jv4E1vyJ;m)3nk|8Z-kZz&xc}9&fk>tU-OxCZAKbbk31QL?Vo?_o2=a@;Ga&8 zqlnb{cS~iO^eOjSgOcPUm@nakvY58J=Q1<9EKqyXS_hyyhwEVkUD%hZF@Tb%DCvYo@Gk?OVAW`=P z3zMYGP8oaD5Z$~L>=p>oy_hcA^E}RR$g_$By{q{Io)mNZ880`9c4q+KF%ag>*k3Q? zOVIT1t}OpJ*0p!NB%HL1H&F9R_INg!XFCy-Umi|(mV-5&cn{r_^j8}@hsJi*i0KFl zs8LrRT)8`eMAd`>m!Z(?Ks=@zw$93OU9NH@_QIhL&J!u$E@Kg|XrfJX8Jt(!#G8Z6 z*Dmfc2E>---TfgX!J(!%t;BZ*mqVm7odafnTj}W|6>MgjF3mBOb^oLCl8#Mb4(r9hp3+h|S`ie$3 zE)<@IA_)2Q5$yc0DBM#~Ae$57+@z>MQUZd;^cg;2bl#4Td27vPG>mZJWkAwq$lQl8 z0TOzoZd5}ALxWjJQFjG$M^Vz0+h3Y94^`V08qGqK-A(Pn1ptP2_tnW1K(Tz~B0W0( z4h%_cagPI6iEdSl2a%ktPKo>7-~l5a@3P^_VwGRVLCL z;le$z%@L{CJqo)+eA$%}x!&Uu^)yhBA2k+37wH$%X98hp99MXxmM!eI1J3V!8oatt=RAu7`qayE`;PBEi^>7vPZrVHukl_b&|FOZB zI+Z#HAR9u151DHi9Y#yW_3jwj)9}QR5UFb;Q#r2%ECu#wj>iP9LyT>qTE6jKjoh}& zZ;~rX!eq1+&8I_W0g;#I$7=;*HVu#A)KZx?XFO3yxkA1_fzD5IvO00=n?_djuS&>Z zO)eD?x26lG5eZYtE501xJ4=PMR<-r}(Fg+%kQiC<#KTBTws7AhDXAn|(@CNPkOo=v zh0-sp+MXn~3O`_gA}Q|h<|o`acfCuJzSX;vOHst>JJ4Mx z>Qcp#wi+a*S5ng1h##d4aW{;ZvwfzfhBQn(;H!#63|7#_QS$xMMX6NtL{jM{4VDpA zc5|hV)!yK)Vw}np7kNadJ+Qz@KLA<-`_QadWwiX(1P!5Cxkyk+?(~6pZrX;pvlRI1 zGBfCUhxJXEx>x&x`W+K9z&9xNs`s)RycziO1oOR;V99| z`g2kH)IsA=c`Iwg@U2&bcd{dwEiT_nsU_8C%QMAf8a}iT0g7h-AkO&3NlNv#Mx}hR z-~$K>MZUu*VT;pK&Zb`dT%u}tfn}S4H~f+%$CcZ5g}84W6@hP0Wr^r|tt<>ZO7IW& zM>Gu|qa}bVo`~+5o})q==Hqk+f$z4Jx~4j&t4;c(#JpG=1brbeqOFvZgY2iczWvM7 zV=D?m3KH@5A#oDp4lu-N5lvjmt7P?;pnLx!9E^qN%l0c(Qg&7(o*#krpKL`}rI*W| zpAo83QZTKGljI=*q(;Ev%mk2QeZ^_a%mVeQ&eh@~31pFUYw^)Au7<6tFUm1bHJWO= zKinT^#uraeh%~l}WU6r`ioB4vbwPFL>4rq0ho_{ltyF~hczO{Sru^m?wJ}Pe$Vnvs zm2(L7M84Tk@^Nz)HW1$cUl(}{j)DRopQtV3_73#cv~FA--*~Jm8&+gX;;TGE>elFh zOr%=5Y90SALhXz4yVA|o(>oB82X^xR_&ha{_)AS#6K46X%CbbC~!lof1|=J zgWXNGVl1-Crmek)2UhaH;@F_gVq8sYKVs*_*lMQ#?kg96Gb~rQ5ZPpsbt{RTQbT1+ ze57qBN57*kAQ8*cr?;#xNh!OXW|SN6US>zh#7D)dnd<@kq<%$$fscxv03 zN6!};iReAO%8&jCUxoD^tK=X$vCEGNBPS8tA9a#JtXpKAKj~UhGS86-dSWfXs5IYI zTB~8GIL(4Pv~mQyBY?l1p7=KL+*Skd(1Can&4xk-pswQyGqa$%TZI=yegGZgXd%tGQ$67{$E+u(>zoPvb`ZIsE>c@TvzE_J?3Qie(n|IHxyGk@yBZmo*4 zV2xqdMg?Rf%u}dO(2K;@pf9c5j8sPjV-{s{fq9&2meE@=Jy{mP>d`QiVlzbYi%8Am zy@$Junw#F;fl9RPL_;y$vJ`3?z_@cCx4Z`8>wW;eG&Z%Q${pl0^_uOlJ-{_0s&o<9t)oR@yy~Rtv)uyJcvz>rF|A2Ja0vjAp zjIYj5cxCm z*>zEjicDF;EK!~!)$4m+YEN~HN$Q~k+S#a2b4>U>ej$E$ui%v7@nH9SqDuGej9`h} zd}74yvzdjIBv7UIw9&!ZI58=+s)L_vlzMChZxzN36Y*Vr%E>8IiVs1L=<$bt#iLQy zq&^r0Or$;r)4VMcoJD17a@!OQ|7v?r&*G#Y_DMBHf;yH4(=9Bdy31H!OjFpLY*Kwq zYjP6-9P~F1+nHOxfgaxJX#SM5o>4f`P2jNN-METw~Ajd;XLRr2EpkevUyT_0ooyKTPY2{sRHh z%OQUxDSG;J7ch{{xww;HO1QYB(HC;y?zzFAOtmYJ>Gq=VN9CNuNI%8|Zm&P>%2H6D zK&LKUe#l;m9K)Is{WC>6Lop^^7en4L(nO93^C=EiF#$Cz!B*@ffew?(nFqKV4~ho~ zbrYV|@cX;TDEPeL?&#?hPw%Kebwb~&J^+f_vlqpmh~Z9D&Ttn_D-6b+Ol+0s&sPDCp5 zegA$S@4^d>Xphnj3I%$MxU-;zUV@oUw<=jN)dzH?i_Se6OvU8TQKM?2Y0yd~q>HkU z%&edSA<<51(X#UmzQYF|XIGaV>x@RhFkK{t`md%&H;u4{Y?YBKcj4Ulwj*WJ-dHud zPNoJx3p0Fn+tBix?n@yp4?G z2x=j@NQ@-NW5fV2z|Hl7Fc_WmzRxu;KhDNx_jT%hc-4sl#&Wo{l%hSqxGYqc@(`sG z5=)+J4r*v<_TFN5L!V)3e!P@WpxIba<$}2xI`ipfttA!UbHu76)v-kq$7u9v*~-(W zi3dfqPmQRrkg-n=uCEpf?UJq|P0@_u%M@_2WMf-w@-IK%!aYAA(})$7u<>ugTUN}i z%zGb@RGJzIc$Pi7W?z3B)Ge1K^~N>3PJJd#mJXs%1%PR716(DG)ahc#0NK2`r5mhi zPI#u2tx&43E>Qg^1Be^}-ut#0fZK<<6ZZNI#+zkKkCCtACl${WZN{qIz znozd0gDuVAAfOo@GvD^`P!U?%B=B|H>fuXn@u0vCRsdPHoDG;Cth zO%Gl}8hr&H27rpD7sW8YU-i@#2_s>$j9_A5Je#>3r0A-8&{M}*i$h+Gy9eYDU(0g4 z*&oEqITr{{I8!^Q{%0sz1P`~O86buxBzqWO*d{h!djW(_UJ{Wc_@6Sc<% zy1L=G$;&}hCT9yA`aDX5#+G!e8R(;bK-vtb#%trp(nr0yHf!2eQ3OoQ?hv9D-dkVJ zm0FByYIA6rt?cSGNNwFc-@u}R)IxC7_Z`udRC5Ce)EUY8_TvX=*Nf~j8k_J&NZ@kj zNMR70W1-3p5QK4r(L6PxIRRtQJNg9s&6jl{`P6x`be7Le{I zC1x8_Xu!*(?NenF!&`4 zpx8|ovPQTBh^y_{a&(aJDeg!{c0?)VFEF{Rd+=<8J|a9Zj$){chF^Uq3P)N9&w7YD z2vim!W?v{mWxNBms~DNI zhcacjbi=rgeDiW0Xr*Zfbzjzb>a>}va`OxRZ`ic0T(e7EJg0fECFpmyExSHk%S4HJ zodE_sm@Ps)xUFC=9Gc~8QqFRvZMd}J7aRx6pCvJ*`7w!5zsvG%)7Pl3)6*mq9v267 ztslz}2X;u{D_yMo*y@K%{kV4~sa~>;cqC63Q?99W4$dfP$2_xE=L@Whi)Xa7v=%}e zlZ%No|6?;ro&tP(a{pOZrc4T`^u5y*mQ2nm=5_Q3a3ctsWxFSSduzq- zyZnNA|IqrF1JwCS^~EqathEcSP=hk0apjn+FHj*onSbJJ@0^fnAdh`k-O>GqtiOaL zY$l-PnWURP%uO=Emg>?cF%h(N1ZIJ@QJ1qv40u*4rLhIId^2l1HqbP~-hW>7yZ6n< zezYrKx1NSDHD7E#vn0_Mg)@h+dcoq+O4JoICxa#rCBJ@(zO6Ue&uTKrjFzM+%hl)A zJ};lH+mo&nd?{kNUgbI1MNs}_F5GT5p^jc}q>2iu6hucBKYI!VBNi7`D2TZCol_XI zCH89s1dH6tC5$MW98~8lG}s7LQ$;VZo%WM@L)BB3+wNc~FC$(5t-WB$GZ3iUl2<`R z8)17;RmfZQY*CsO>foHyhOmD+9MPGzblE+|6uWQN%eaz-147tQ^+PAb>t)_%kcAa%&3>zMo{|EWqd{~b zvVtJ=LAYzQLe7jkfx`v8#}2q6^7?|3p}38zD+v2L*{2(NMdmfQjbC8gNK92O;Ndu% zJgye&)CfkHl^BSHPet?^Qy%GEEA8_ zzx{g^bUfwlpUgI^HqB1;NJ2OO$wuowGkvMIwss)&+-J2sx-fZCO|F|ZsLsI%9APSl z`C7TvI^dX7_efw4kX!BaX_siZOk^nD#5wh^ElkLy^TSDk9a(7e5bbyn6cTVctMr&a zCWd8Et37)QR#o^K%^lkU*^{omFRCmxOt>j;6LRPHB$$d=&c1zEr6DbeuY1oY=qPqh zXV!B>Xsvt#q6`5?LN#8C#$7>}@|F&6I=$_aU!E5;K5|e2IT9M!o)=2R&eT9Y+>7|z z#}0wAF)R7lM(2t!zDj*L>3i!hsFt@#cW;%}rfx@5)Ad7t2d61Krd0JPS9`#QyD52A z?$`$M6(#a4oP^O|g{qk;LCZ>(NB#zE0#4EdXR;6CiMh3Cak|MRj8@Bx=8z*rmCvh~ znso0_nKs!Q7sKU>Y|8uq)n*a#`7=_HKTA_Sv{Ng`YCR_w*4V!X(d~p2#Y&l3R@^*q z?erS92KC%o3@VVh^{?8IW72#|LyTy=${myzhSh8%vOO#LQj)aoP70pHtregohm1^xp-}C1Ji3-r^E8ComfUs*%ZBECTe5A-;M&;T{4D_1w511=LLBJ6VMQ@1lZ1b!n+ z7~S?1B%{CMT2r?k@Q2H;|sNR9G=h<6}8&S zZ+kaEpW7SJMmjYWoG&`O8~8ri!yRS~?kOqNllX)SmAN@<34xRN294ccTcq!6GbWwy!y6`lDi?OgVPDaMXWJ8EpLHo_ndDKh8>`K^yGuUgzGo?!8{pfE%43_glAsr(gP~^#YH3&yBoIFC_zeaZ_#?;MpFr z)DLj{e8e|;9IQX_{}f4lPkwC zsp6mQ7-gL@olUR=spV%8JuT_bwpmyf&&)b8kw7$FXGOW=-Rb$*VkF+sEOL34?(^AE zTH5LDG$h*p&f$~_&w%ylal?5@36YYcpJD6z5)+fQ?;bUV2rWW9Ahx&5nc%e7rhwhC zLh1sXYrpe1Q=ER)RG|*iT7W9$;^8)(CcqBG`ClRyUmbptZ=g(+wyOUDt#&3+EZjl9 zz9nMKCOayeR%n0WMPKNv|LCn40NyNgj<)akWuL1y_n$q2ed7JU1(@G2B?bCJ0U{OY zIP3w{tO_uq!`RHC+nZ3h@kzV>UZ40b*7JZ3SPbxK1hEB1JLP4dNY=5PRERE_D1iQ; z+KM85nx?=L#vS;9(%E;tKAw67%Y(3hvU(RWnaBhQq?J{Aj z^!*g8n+knhgqc5KRC+3_pmic$t|euQs=X}w7+KV;#p%n{v=rtF+iKXnz?}WO6`IRW zyVysegp9d5d92Wy?mm4>Rt49FB4gsW(pPRvE2W63#I`kj1yNT>R*(Zmz|I)0#a{v-5oY4bMCr-0K&NaW zJ_6fx^i+;{k&Q#1**;LLpO8r4GRs=L#NYO?dcu*zZL~wC!+88PFyx*5gAfmf77{cReFpd?7g&PMZPV`N>TBxB#twMQ*%vdCg3r-g zf{^be=JaC2y&)tJ{^PBiSpq)?n?KhMx2UJpEtY90LzwEbzNICcAsIGQ@e(G~VHF=P zm58rOL-%fHh!?W*-!<7Lw7mWw>urQKU$mHi<+m0bEDW*hQXuq3)_gU=?{ChrM8Iq! zV+|@O_Rm)0bXn=Vtp{Il7p@(*27jlg{b}uc(JhdL_}G1~u74ABvlPsAyc4)C%6j3r zXwoKFEyl+335@o98O5A*GC{^y?|{swM}_zL=tuz(oV#9FE=)7=p1r)ceLtToWI^@5WIL{tr|dBn8}Jc zNTF-{3DeSfggwGJ9csQ-fN8$;r35wv$&$zc1Up+b8($c$)0uYM37l1DB32g?eMd-! z9Jx-VwHS-_af|@;?8^A4uv90pRx=0b?6@J%#n!WZ;3j;c@WS&N4+wU+sk(`zkc$ZY zS|mQ$W4wyH(k){*MD2muVAhFviThLzxnLM}+0Ltk{Fk+$i~M0`w$WuXOK4^{JIuN) z_kYqcTE7#uYt*=WpbAGRsEgEtM3FE*0=~~rU|(dow)BMr-#9>S^+`Xp?E;qc1DX~< zDCW?Kg0wQQgwb#Og}W}n}Hr?2fmzr-4T zLFHAXe&zwO&ZbXnHzeX{ZG!pgBidK_XSHZQYI1Y`KsJB>xyY1%8@6+qD$y(gD@|4@ zNu~{k^_g`$%wpk=S3A@>0X3WBJ}^uiZar~44@_u2NBkTn#1@w04iYnM&;^%7Pr{YY z(tgf%ZbYLTwQC*?n+^@if21wA0tVq_5#v(t?!GUJ(MqG?noK3wo%Z2O6jp;nUD5dI zL~YsdTzsr+U~c9Qkg}&lei#ldp7b21PiIBcwh}OGaLubI>{Nr?y5^Gv0kO?<6rK={ zXMex8q`d%IE8+4F`y9ad28GDYKLS>ajK1MVUQB?+C`irTU|te_)q2otLR52Cj$2mbJZJonbF)p)AoK_J4+e@L(Z^&yToa+u}5{G^|oC(8YXh2c4 zAo^pLl?ko;qT4yvQpm=0zRyfk`u3QA+Ihc6bCWdHE-X+)?I}1ZRFTFyLJ0En_*8D?pc zG~ftbjXm+0KCBL}hiJ?sh{76kU;#0hkk{WiiDpmsAX?o~tXJxX8V~ewVCN!30i&SaR%;|dRq_Rq)EEcnOhR=%q%7IBOoTqX|DJ=HsCWi zW-3LC>$0Vn=1Is1m%t9{^b6ci7ap>}O)ND+aoOyJ3&vFo#{I5wOOvKfJQEa{_mg-9 zk~v8nOPSia1)sYj?Bor%iv_r5CEnZ+B425a=U5fx*%tluK)*9azf08_bn6KFSrz>> z6Qe9-`RCNPY))Dqb!ui16}%8lMsw$mDuy}WfTTxRmb6GSpvX2H40=~ zwmd_+K(q#~o3loa_J+(P)F-y96Jayu^Nv3DXC-hJ<+MrS5Hdg3-MT1A z9ylvRpI!xyTY-9zRWLQ=i+Yy=yfsLlda^>PKuY0~t&@_X`Hump(%4dQb4Q33T*=nx z@-(B;?$SH)FkJjP7pIR|N{0*?$rkShu*h0)N0Na*>r-46VQ!miyDvwfiGU?8SY55r z9?V5C{*L-Y5ffxU0ZnFdtTY~rUw6}t{&zoivkQd;Yr@&bwWjGpR zzkPd;HL44Zv9$RgV~nFs`N*Bh6c;`AcL6)uGACKz_TEW0Z)mmdB~Pn62>~~hZ1+7%2;WfG%@TC>2_*ZKfKHh4XffTUn)J#; zELL+oot}R1v)Ag+hX5S!t%b|BLS?4kQuXY?d#W{xLiH>C1rju=2qf?!HGs)2Y}o_> zi|xfd43dp11!?W^RC^dabR+xcIb|`NT-IeD&5vB;{;-IKD6^wot%4xRGF3Q1P#hA;+|5X8--N|aFSLsKc-9a|M7zmFC+jM{O79HJq^I}#>pzJ>sBiCx zFn*Or(7&)z=>MVm_pmoHrv0C|k?Fr?0F^%512%-N4{ES8Qc4uhIi)?=fO#Yv81a9IgRVczEtzKUJznpR)RUE4 z*05pKcyMCG`Wv(o^;~ho>EA;vjq+p`8Ov|o-dwNCt_m)&I9dM9z-I8?HvQ8|8!BJe zl{P(2h@H*fnAZ5;SAEFi(`;AmRn+}qdFQZ~vOQK^?68-fAMBjp@Lag%iYae zV3r%Kw78DW6a<+3e2V{eW_A#q^;d2tEjKV$akE0VU!gFOU7w8gMx7G^?YS;C)KqpqH*>+)g>7-t4NLw>4 zD9MVZi-^*wi*IjLYU`{)KVyX)iwIH)&_t;a;DIGlEc#SHh$0u55Z7pc2K{JOKoTN? zXHUx>D1yGfNe-3N?J;NWl4V7x9;t$|pt2QPE$9ZSf&(OJ_nAzPBL1MY?F+n-3Jp;r zL+8N60}q3K_cFs;PR~CYwFf2AGt*IqPBR4{VI(hwQ4bs-M@Cu_2c*d+=DuZODc0JYM%aaN;~pEGFH>( z3rnk*i94o(P@}>dC6Q@Bz*AJL{ex#;@z>^JauJ+$bacthV@-Ra=dn152`yODXE zk`nuf!KbJ5YBL>UEC4NsFqQ0+#r#yN1}cv?V8sYg{x6r?7YSzyr@v=Qjknq6J|;G|-@1=U-}o?ySk%;s-a$nHnE)5d`Uk26Ps{h+IFutg&y%TE7b zM~s8{-b??Z2$22lZe!z4-?!7W3vVZ8n2bgHxXi=Eq+#)^k;4~)NYt)ynmNGFJFz{^ z%R$|+-}UsHDG#6OLG{%q@8*t|n5;u#L8YJMr@(p-;D5vq*=ZZ5SFiv8^b7z1g8yGW zp#Sp!9BF#mZHOWL?Bp6&07WOwI##lT24=m-B$#J%X#9~J=R*es$b7q7&pUy-zT%dMZ@Xz?{UaqvQSG!@hR*!}eo z8jRB5pib@wki&0|yl@yh@FQ3tZC1|{#H3-rS(9==6Orw!>^uB*!WOZuH+|sHfQaS= zJL8Q+e)sK^LNr1A=;OK79-K|fv~NBfBa%?MZZJXO2jTmaxY z@rwkZBO=LhMYVXnc>?nf7j{rE%laz*i=ch{Sen`iWpu$9y*MUKd3sM%BC5l8R2V&i2 z+JbWho)(4~>*YQ%r|g#`n&n7V1Z;W=9IYR04F?=1e2;L)<1KQam@+h&;AyT_OD7O0 zJzGFzp(R8CXW!;zus(^G%em5S!tlylH>`Hti&47`3xie3pR=ic{1!YwH$32PuqJ~K zyL&ZSH@Urtsm0dM;*5>PZZ3nr#c+^|JW*@I)|}?SiJ9RCj;;Pa$_T4vbX>}x1vfd@ zHVhCLJq#BBGbO#?pFXYruc}3@{tmN)rScn;=bYEcoQu8jDE%zTzN4W|v?N8=d4lm{ zA>X!cY%wFsCXmnipy;oi z`L65WRc~Wdcc3+D&pUw#fnzCQ953TL*(X>VMsJesmO0cin@>(Z4~8-D*YD{xyi9p% z@TA3D&0*4cIHI}|-VMg=GNamuJ9h!Y7TAmNOYCPz>=+xQ%|*7bH2>?k@4evDddZ2JO0zKM20lxAGs|iW#qhw~vjFuf4pt03{}+ z9YB%G)gXVFy@Gz+I^aGzI0cAGPU((M^$ydbklEx*q_Y;?K<%1iaIVP$Um2-%Ev)fA zQ>u+ud#_@>UjM~I7cCX3Ord#3CCcwsCxA%6t{h6l3$G`C(zOw~yR7ql^bPM{buInP4JC+&IW`7%V!?%T;^FyoI;H2|03JgKdfIJxi$l+N+-i{7$07ep z4X79lI1H3rXV0I1y~Uusc|SxePqC}f?5r{7Dg(5FTE4y|Q* zl~xQLf_b|uOZZ?u0u!Trgmk>fdkLJ2e|KCdtX*5A=1*TqqwJ!)$ zq2iqf=53(Uc=hSZ*f9u)7=8dm-V_DsPp1KEldXpwU*n?IL4Am{m#q=DD; zMSmk-Aj)|x_9RsrSXsa)o6Ic%bN5XkC)68TRG0jDSZa(X_9x0AdyD~h1N2r7Cp)qc z!@!6QKWIe|Pzrm`25FLrgCrLcsEx1`c-ykgD0_Cgk!*CaF_+O1_nCnvxfYmKx?0^L#nrs{UN%|<18fRH9-9}C2$Lu*P5}W> zz#=D-06-bB12N)wfg>ttUPf0qJg)fWi#zq*8;#B}Dv9EQUu40v8rcDvn{sc#He2bW zxica_wgUy|(zc_+(Dxy%mI=8!=Ay~17aD!G-EgGy_Lb|0G8JB81g}hAUn2GFT#Hm) zG|XGR6f7lvqy@$8iN1k^9HO8fOrPW%iBjW|_KosZ6nu=gOb0s`zx3BEiD1MAROjEpV>poU|(F@dj^d!A`;K+^pp=phISBM4nV zD1a>J9D0tbnq<&V5HHKhk~*J%SYhVs#H#ha5v2E;R*^e^G_Ao|{ECJMJS2dP_xg?+ zAP<`xL*el8(nD*VmZrvgtKHFRTND7@SWGO>?F$&y1Ox zag1hp+#%J*?VTI5Rmt$O?(T>uf6rX~EGM5RnUyocUYj6F1Ba=@kTOnMOVoKm>J8h) zsqALjjiIUc>yvB!Qx~IZl+J~%*JmXUEP|mx5T)_NOilGia9n0La%$PO-A6sXbBnVQ zHk8zXGb~ZN{R6v;Qc|`>L~e+mCpy`9v+PI%j|-P=`IC}P? zV6y3mCs>~8&~$TaH-UujT!~t!jx;V_q^@U*6YaSET_|-PC{Th0Vp&y{h+iP68)-s0 zN1JD7SOU)UX9J0)QeO!R5}aDX^3+yZRt z@gA0Mj$M@OeP6a}OU>+o=V3r&DYYhpuE1!pkh8DMT5i)`@jGJ7+vVAry0W1+s2rZl zTl_Y(`9xuE;@}!N#jB-~F4pbp`ow;f*A3WU7db86LA;cf^43tGb+24eC?&d0>ye^u z{$4#j?-cz~k)&hSJwEX>xSfN;V*sS_N7(5C6L70I8Enmme5t^$ZN8@zo6@!oe3U}5 z%C7KAoUKk+xlU@0@v}gsiMFlZ>e#iOSdZ#u{LlnX0;+(;zQwAlUaiWZ?4t~C(B8|P zc8?GCYpxNvt|+ickXAKuj{Mwb$3dA=huiY`0D|7eUzYH%t3A8H#SM`__11b+MA1!E zgk;t0a70z0Qpg_D&a(z!gHWNWMmMd{3upbrKrvTeCJg@^`<0i?j&tVBd_GchF z)h5BVDVOPmPN?L5Ne<&7#kq#;{%tTu~`b4<1ZvdJ8LR-w_ji5D$Q+SUEPeJC zY_pMnH0vpA(hln0EN$qQLiXR%Y3RJ|CE+elz{S`n1^#Y;b8p_o56x0uv(Ra2Or7rC zN7QJMV#F31hu+gWUSREVrx9VN!^I33Hr0pFX-duQap}H)a+?JHm1iJV^&=`XoFNqT zs&Fd0H4b;nQ~jdo;e^5V-@!*rodhpf#@VKG+upXUP5EBp>=bh0J7&2D<);nF?qP0T zk7qn@bKpJmyXaXr%I4grewjfa%?mgK>AJ%|wEUC}T zork1MA>9A*z=Z31rK|*Ov1E>G3zbx({+0T^fa=t4Exr;Sbhe8JYR7`{?ANasi!+Hj zk}1-r&1XBYg`ycVJ+^<0J$UiuydEENJQ6&+&IYn*GO60DL5pm1PRZrai=YZjdIX8L z_F)6(P)nChNj0eBk5JOG4E;EOFd!$;==?($8J=+WDJXWY_a8&0(rYSY#xK=s`hOF3 zJO5v*^}j>qe-w3Zup#)Y)NmBi-{ohQwR(Gjd$3n(lG z%&NZVxd=a?AhlamU2H7vYAy&au`;N`+JG;^cvpQ*mS2^B11=ZutRq}&xq%nI^qATQ z)w9ZW*j_|12$lYY<=(Q>I&lW>*!Hr)#%b*s-%AzCni}40*`i%6w$fZTwn!A8zrGiU z=Ih}hHt(y%PhTpYtHrGh)b046RI7b8}y zR9_BO!u9)+b@0OVo2L8@ee4PS@SVTW(S^8_*V6v3o=>a9hPwKn7%RZf1an&5ry=`G zwVH=5RxADw)iUz4@5EcK+~Q@O$#3YrcK)SWAOD+bZM>v3g+iHkWH>=G<(B_;{(Bt= z@2zrbLCBzCn8F?m316+N^>a!fk&y~$`qpG1`6yNBNcw)0D|_yndJ?VQmj(nG=^@ao zO1$I$bajuTm@$Fm3|XY#TK@(FffQ;W$v0HB);~x2@?VbRhf1x6L^%gL=KV_5XnaRW z6;boDPQR{hlz0Umx&;XV#R#HQn9}Z`36AJjRO#VSzz3iX({v!t*!f3`wxGlvV;Ke5 zlB510!UgjLCaIGO*;f6!g8G<$7@{Hx77_yW`ivut=l!*%5;Xn5mBzW!+M$9H1r_EY ztT{j0xIBfeD3=kf|48byB!*PVFedML?&_t|23G z68|{T6V9L@7to;0G$7`@!BPdu5N~F?S3N{oZoj}y3fc+fIJVIZVduHR$8;y+wl@YM(ch3Y&I^Fzxr&!74GW{ zC|4*++iBldJ@$*>E#JHI7j5NzA2fx5{h}?>O|>ojmT$ILtA^kQdN-99{aJ0>a$6LT zn{}5J^Um7{$)-oW(7givv3m|~J+K>lgN?JFMl}D9zsz~kxm#Q|TfskgJK1kZ;9(vl z@-JwD4C?p1nh`yzsZij#KvZT@WR1Ced}Jw`#7Y58$jqmvsiCMA>axS<^~u) z58t?XLv{DSjw;G|#ggPewdgt9ZTkV$Yd7YQet3Q7!^Gy-4PBl5i=QD|jgs!%naEAT z0=s=bN#^>Arl)#_!)LbE=w0xvveBdQ_;CFEPxHfqjDkb>FaQ9N%m4tw|9z_FVr$|2 zzh;OH>@EHaS8KwuvRhYw=I+_I7R&HYA{B7ur;)61>6N5W99=D5D=m*R+5xE;7V{xN zR{6T|obGC_i-u*JQdWWfz3;L!l9k=Jy3zUe{6H0C(DQ@ede>c5}C3oz#3mkYYv z;P*y9dEPWVeM?_DSsystg8y&!S(`x{y1>u>N@!QKd+aq)e1r9q-TnU4Wj0uiTigHS z;irp&gvM&7KG%AI07r+x3k>_X=8C}>&D!f`sQFg7l}YF`ln`&^PS@rIQ)Z^g8VCv^ z%*b$$!Zi9j3k?IN*HemvnK!bJ3rYxuiY3md--hQey)z1R;BBj}d1htgh${db5iyR& zc(sZ?G-XDNK~4Hjg((Q6>0<&zz`Q0RQ|i4C#2;6maP)o@X$ue2MpIjJ5;1OJPj~nI zfpv&$>Z6eP1fb8)$#VY3!9l%*h>b4gf^h;6L5)lSUk)( zc&I%oiH9V0$*sEP1>m zs2!*Pbs(S>J5<=lwm&MRw zz@|>waWcs>5i#sf9;u1j!9j1VUMWj=v_8qzNo586_6aKye8i3`PRR(8_T**lOu90p zsMl!cTiS{KhnW=X?o^byN0RU!0__C8@n&4+E%VM9=&84pH)i!xOvXdO)R>&f)x}Kl z2lH|$DtH$p%g+lK$zd{b9YGQui6c-xVqK#YNrimQMvWPtCqOrQgffLQ^RVNqe3iH? z^X~cMx#4cg;mxh{&Z2s!Oq-J@$knd0sy!4&8XbOT+6NI@=1gX$L}y6kvFZvA?!f$d zv@F3D3h8I{<#gB1CVUrpQ#Xpjqh&#}$ki8bQO0Q9#4}6aLbC6>%cuQcRZ%l4f9O{- zM9yawJdJogVI>Qg+Vr(N49Iq5lCeG5QqKCb5Voi@HU$qTv2+wT93CM^I(F+5=i=CH zt1mja-P&9P+rTXDMG3zTK2G5?kUHSic3#<*eUQ-p1UVeW?hY~1ob=4_{%)2|F;TwuZRn}wRUIntc=n7lR^a=4%5X$xaL;EE}pmNugB zzRdx7{^kJV71IMhm~=$>k*=n`|?IQzFvkFDOP@i65y0E9QCOE3s*s95}=SNo|0!L6fkgiS<%Y zekc#&?{J9xC5S`BUe$}cNrMPIwB9zfR>1g}%jY^as&>OrGmxqeodratPxM^CxPyF? zm){Es#v)J80=W_)3^(o(4$4i*N{zM8;K7SVP!*&Ju_|z+zqupiuFlao3|Eq_Vbw3LVU+1zam~f0~C$Q zYX_|V`qqSlR(^q8@p*lwk@%yyX2P_FWiL94HbBVmH;`r07B5g4T}?rBo(x^uyqX7% zGJYCzQH-HRGY9o5r;wq%j8V%Y3wHb&3&(XuuznD5fgHIqNp3? zRo$*@DNYZ@>!YB2{M>*a>=A9nk3I|CoJ(tg>QD*HW(X82-g`eFCwiuJy zft+d{&f5n^FB-X`fuu$ko@3WLtM=nUW8L$t^+r^c#z z{j~OA5&rYnDHpR7LoVo-m2xrcf%}jQbHQTg9%2#>wZX)?19V{Q^1?m{%5~wO+`ox8<;6*xic^K%j!a(D;52VpH;i4j{9ECRf;<-0~d&@TmRcu&Y zv1@~qK%wVt>2X5ffz_n) z>B^&khKONUc5ZGpa;C2XXI^&qKJhs=ti2~1DX`y>wdI_5sh{_NE8s~sPQ2}D|G-W# zJl?BXwwRB-l4tKz9cOwf#tcIL7OXr5wjj4dcJRpDhsPEdxJ@f#o1XrX($bYylAYG3 zS*>RplQmR2?&L+aoD~5M9LB<6S?tx%1^Z)%_Hs^@$Fr@JA0o@bU|s2NAPfs*WvQ<& z4E(WCu3Y*+hQ(o5>HiRd#Zgn{|L_O)FoGdhB>{veWYb$m=*wDfOAsgZ$I69dNwt6| z2J2t|J6ceEXo@sNave;0Dg0nuq{ks0gM|h;P}5{zryK}1@Nd&@ocDGQ*CMmE_QC zBBtmpgCcbwJMIC9Ok!`i;JI2-kQgj=L?$TpxAhSH!0bZ58oeCvARO zBAKvc_}y=jB^kyV^&RM^LgC2HLl@r#RgoVFLi`i#8lPfvBX>Dg81(J0&sD|&o3`7= zFGJ6~sqk8l38ODUVi#C{<%7r#j5%)i*U(6aPo_Q7-Y3$@B9jGfKTuSz%+Ig6T@h4v zPfzk3rK`LPU;L5x|z`kE<98L&2!yQt4(<-2a{Y@9716=`L0wR zRGFTx8cy??Mcwu+)f;<&owG#2lhL-=D>_HyoWP~4I17x$wl2I#6VLfvU}78BYjc)d z{bL%|Z__w%mSYDD_~5K6b9Zb!-}t0kdBcr<(5_E;wF6bwI%pUN(pYuVm$Wlf z^d8?dd$!6PS8W7PZk*y1Ti}Ms4tQ0a#p%y7YR<6e&n>IZ%jwzXK5o^!@LMo={<5xm zajv@asyhj)d)I|*gKG%FU-0HiB&J&Q*y)XW(}=2h5w6fLb-5F#=AG}YKoN(#xu#cq z_AN6;Q0IN|iho7?*@_*s##8(=ZaLnKyUlHTmvM8qZI-C!l&a=kC&_oVGD9xQ9?H$I zrUx-^7w%KsgE#e)=X&DjXHhp_@VosDyK&T0$Mk8|FtNiua7O9lftVToS>wLZ6KVCS z{V6h7Z;Nv?XMf7k@NK?O(`_jAPq82RgVtW!`zbXnD}{^gk~$niXXC zfd7)1iQoAmuK#ur(KE2N{xA8XNTn}f|97tFM$K6kE`6-NwyDLMj{F}G%yuj}pE!HAwX1G}jn^{x%4 z4|}?R!piOdulf@8M*-DeIl_FZE$)hzz=h)Af-3z})Kj#-%&ULi$hEf6o*}r6GJQb6 zuX6g-f2_d7DWc0BsJk$K<)5us)G zl9oibda(XCd#T!!(k^J+k=?bKqbP7$5*htqJ)RNh_%5vE?ZezKIwQ75eS(i*$XkcX zrLsgVoX05HJ%npE2*#;{HV6gmzw>!CJ%L-~IhhXVRw8{uy6HKdS3z$L2q?zY16cUOPd1V;`$vxJfBI(-%MPlE1 zQ;)Ou`)Wgyk&*ztJ)$}e3k4O4GtL@Ayd{Zx2qS+$Bmg6^5F=pJyN6+Ja6Xj&@g^^1 zR%b$_yR~CDVw_>?K8!MhOwKIo-_cYDB|0#`0|!!VQ!h#YJd13FIq;*`U=f2;M_(nD zW{Qg>i0Mg{<~ZXr2w>5k2&NP+?qe}kp00>))i)5U*Ht6T2qQT_1RO(!=B%DW4=Dhu z!^}1y{U9FUfe}KX3FNfw?74!&`;!LUOmb}=K3T$appnCvR$_5zlPbe=A2+r`AXmgr zmpYjk9zb(@ga{fv0HZDMG}aZ&GnR(%Ms;9u?`PI678+;a*Fk*ak`Z^TbW^Kr4UzGA zTf!Ld6tL$c`22STs9w0h)4(-5gmg}Z{!)dW#2W8`Q(8z2k`l10%^2R@UHcEv%TOJ0 zt@U-&LOvn8uXe-DhR2~i`mY!JG#>fKiSIe^@Z|aKIXJT6Bh?BK#y$4Zj05HB#?v=* zq{w3TyXK^T7Ym2(qQJXVn{er%Yf#a(?Pc%d<(m*TKYhs4m*E+DGxr}#n{_f+Npo>u z-qwtBi>FN_E!iHzDqMT@?U#LqvsxzO9FBd4q6W|!ojQpdWc8c3iR>)I#>3Nycvl!9& zMPyfdya^ZosGYIPaC?hV4p(HQ^TLw6u(Z+5mA2AWsXLX{Ce=qDF1O0tVG7@FLy|nyuY-!;&)+M`oI6r7&@95Sn1i>>X{l?Si3ly==~o8LTB%x zq6`WE*ghJn)}^lJv_6gMeWGNYeFs2G=8FHm8)Zf%u$o~gLTWH_<;=oFlP7k`qzM^n zx8tOSg!F^sBR4-ug1ElrIm7#Mz1H#mSTa)yiNj5X_;%8tFBhf=D?vx za#^#o;%imsNqK^3mXg-UXeolY@GoLW`_6r;#HMR);^&I z2;}!31G4BnEs7Icydl;+k!a*7g1jv&&HKX%uYJUrhQB3INfxbAGC>vzfF=`8=Qu0u zkw|Y;oFvB{ZB$5vXssw&x$clNJQ9vv0fF{?t2YwZrV0k7KEbR7l(`m(de6|kl7v1* ztUVR^SwbWUMZy!NM;u1@8k2-O4p=-D=1O=!!Lk}K1u*u#LJjExk-B5Qav8QC-3ZHv zL4mU}5i^+)Xb<-Dc$qnZpRu;gU5b)7z{nr6ER(^!`(l8wej{d>-l$@sF^zjM)I>F8 zC2GEW!~XiX2%2IhBn?5zMtCudb0Y=Om@t7~;r%AkvPW@S99nZ&o^%rgw9_@(t51yUJ^KeGY3DSFvU*Ca7w&wk>}H-i$6bgkEaq+{yfrO>iTI)o4`H%ai;w1%M?5 zjS&#Jf6NSH>2OVEoTe-P(#A{ZAV3BMpl3nF1f3M`GS2dIdwduUm7DqInayHeBVIuQR3-msq#xt@S%H8tbf(l5+Mi*Eys7 zm}PpM%q}%Ec&$#;W0>(gQh2S2)@Jm8?(`wWVBCt8do0z!(ZSS zD=?YEpwK5>y3SeLLE=$VFsZRKUVtyQaa?7wTE?aujxuBmryMN;igf;=?7CC}mpB7r zl9u;q4bo<-nm(n^dDcUC@!}hpSQzv-d$;4?e81X2tiPX77D~fd|m9h>C~;H zf$vlowq}4DBpGH3mUE_HHX8hHY3C80Yq=oW7!IAN$B99DYT3_Y%Je(aav4K}3Y6z5 zHbwYsdKO>2;f}C;?`;V8*r@{_V*jm$GoqAeT;=i;=n~V!kw~eoJ_gxXA@HXB1UjUF zI<^_+p+!jK&^Ec-6X(*X)u18+Ar0#{R`T2uz*)J+mOOTF@}ZItX6VNPESuwjOVKhQ z+$vMqw==B|2euhD64D7LNIVPIraSwgK*3aADrQ-#B6-M?|NX^BRy zysHr^6P0bn-(gRx zqE+#N+Zjm-W1>0&^v(;ESk2xCVsn0g6zv)f#HFUKdz9EujYWGw%}d zPYfBcAiJ;*1VzEN5JDfje*&W^J1#WMYcLf3OR|t%sq|8I`zvO zyD(pq|Mt%Mzbrj`cCf6aTZcma*h@_&&7>tph;{2_wn$K+z}Dos57B)KRk>mvEWtvT zp&Hxy8}9T|01ZJf>Z2GUG)ZjNG*my*DtA^j#n&y(B^B4?S@b7UWwn^^Y#u$$4syL} zHnmV@yw_m!J2_WK(*qCL-Uf>dWfYCc}Cl|&{0t@64u%An>-to9=6=z=_IMBlRT>~qPN5*Ev! zwwYyy?9a(CUjRdWi&0(^9hSRKHwVEtbT=+;wDvT(c(tsxiNj1kfc!o;ks#as}+Gzbyh*wg886qpJFp4<4hC6lDMdpimGf(*{%2-GjOAG_3)mwQO zxA8U{(#ifZaWlT?p4{lRn_@>p=W``jqIS{Q$@O$`DZ8$|xJ*CCN8WJ7-%kj_vDQ}F$ zTrxWNG#vYtN97#VDz30cOS^=34E1>vFOk!Cv?`;g1&D?7DXM^i9I8&dZ!#4DS?2Gb zU;T{NM*VAQ5Ow9SV0*$Cv)~>$Wq+n<$dJA;kLqkcL>RkHXJ%V_FyzX_XV4u zee`ym>e;mUa$H^~J(vhn=Uv;-wkPG$ zz6)b~5UG`FKDEOVD~4Ri*Y1vbN9#0%=p0g~jtQIeL1ndsZ&bN;$Ka>r{5h6n*BJ^f z!CseV=mpTY@8t}c*n3Sx?et@U0HwPI`!Mk1o_H8*YW)Y`KbC802~lBIU;qF;zdb6M z{~yaWJvt+!|68vWscOZpi=q79y2&d3GcI;%n<3>bQC>a_!%$vVHbS%3O<)Ai5OGJK zmr}X@{o-Q=({cDmMdhKE(dljaihC!0L+k!(ua0R$N7zoc=i5O5*{UU&Ov9AD>-Qld zVAEALx!UC^&q?>BO8unRma4%P+elh!B5PeUk+Q7WCfTB;p3Ov)cYav)6kt(uabWdxv4yi-=r~^*4*nFK&8;|a3B~1HlGeC&I(E1618Hbs zW()bs>rTZCPUV>GbdCwzN~7Hcm>?@9kLjhe4ZizD68tcwjS&-XZ*y500EUsaCf&o# zX24LT#FVZY`_Cl=jPBvlB}BoL7RSpWG%!!wLywn1p;A)Y)Or_P=A(9_*5ZI+NrCtJ z>3E^&SC+dPgEdpH2@HB)@OtY8jBc^#l&wx2gb)8s8&+EJH4!y8ht?9qmxR^SryxR# zbGnfVv&!!HHd{vfrC$iA7YMXPAndTiTj^CXCzFTVWWjqL^D*i*CYkn76cxAa(i0_6 zcaBUE5o&Z|5ju4L3s21Tp+uCqd#tRW4@*z%k#WW>3zQg<>R~W(Wr!qAXe3Dl>Oki$ z3SE!Ar>?vF{ud9Llp;!E))X)#4@OuQL%a~IM2Jr<#+W@5fxZF;DGbtRx{N(jIN0=K zDmx|Cg3RDI3V&BVjIra5OpFOqeVYSHM|DvfI{CaFh_1|oC{Jt>L5v+qGQPVbnHc*m zpsVC&I0GT;Q^4+mJtnzk2+=VH-9S;kU&%HDg7vg0cS7AQGTg=6ggDZkF@rth+b1$d${Ai{J^5E*v%VnO#HxU~1GcKiKWWJPfy#$DCf%)NlwTKtF zcmB2_0%dAzFw%5-e5(62k3t+rR_}{_exYg(4;;8qYrpq3jTpj>+k0~kiWFpkI1%&dUj+sQq{{|T zBgj$l(m+ zw780o=(Sd+*weR^eqMAm`82~Om}qPMdO0d$nKy*s2~JLD=kC6^u~t!M`?NM6J(01B zMm`6vUyvhjUZa{&8kc_CdnA(PEo*IBMux<2PYDGJb6hJ&&N0ZYV^NJrphK}p21%(7 zsJr)67ud5t8w2DBDB#JMNTc!nl^}Gy=r5a)T(7Qa!RZ@+>!?3Ezq~1yXkizDw3-~= zh5L3R8mhZTU0!RSa*e9Dn27q4hF;*|JA>8>cDJc;hIi@b(0PdRs>PSX5~G~LkH1V< zcOo-TWMeoo{D2^};?gj#sb#M}a>Kx|fuszkQd_0huX(AWY$zBq_S`FIbMduvrFS=T z8kZ?lm3FphRPM4n^ZF)_irmDz$lRJqt#C<1H@!k595r3I;DqHb#Q5X;*pAfR|KKjx z)MMW?LiS-~H8*165-dH~58(GNPEk0Zvf#3P^jg==>$oC+7N+4A)ZN#v9y@2`{O{y&S9-B^yD zN5MItSTpQlTr#+-K~FsnPW36`61elFhWw?z3?!$9>;4753*R=6uLoqGN@lGibZG0@ zqrI%7p0L*|hiR7@a2Od0rRO)|s^&GndL7NV3bog}-jE(meeiz>Y`V6rru1O1`Mr5V zFvqH#W(sPkqgh6`8?;T}hjOXuHfwg*^q~p!s;TWlA%aI@W+iNg&zJv{I=Y#f?Q0?` zu(kiRBf{_;I8!ld1S?fFi-hNppu-YDPN zf;(#ZAFRDokY-`mrkS>F+qUhjv{h-_HY#l!m9~va`%T-not=No#6*AHbJG9J*^Yg< z<9YU4_ri7a-b~`mj9@8O@?wJ%Ft(MgJ?G&&B_6&k2Bz0Yo$mh1)*q?jpWO-G&A-W< zcjV5HY2#=e#C^;(M$y$%DuO zO|fdTDBv-nMhk0H2?I(C&0DjnLxT;UACbwyi__UbODaOID2V3DnpPWD&J7ik4H|@O&o3B&Mtdh%tI1td0D5=h5Xu$^A#Ew#BVEjr=hNP;AHMZ+BE{;(X^oZ>kk0rgzHtB&A z9=YbB3kegfX~1D4&H69ODDSM$p$nIFX%hJ%@XUz7wj^`BTnvIUuw2zAQf$nWp9 z+w^7YclT0jR=(%Wt!hAn&cz);Fh`@;r}uJu$J457EucX!E@Km8%guMW9q)yIIXD>= zFt~=wZ{l{H@mYPnmOJ9b;B5DX54lIQ&EDB#>fuVrt+@0DF!(c$;s3}z_b5p{UVOtb!3S5FZl!B5-8^W`5b-VbHQPgRZS2A`@NeHj z_Dt1yb*DbHnRm9vntFf#&dDvy;kdC0nrHD_33T4~OXNY`NVcpRtO|IDkRSZTz@nvj`y_tB9$t zvNmwdrtP#|W!oaVS!QYl-UbIpmkoGwAthV>q$o- z@lX)Pz2rIXaPVnV=jGFl&aY3 zGu?Qh_tzN;+-wV#Dn^tXyY*$PCpyvK`ZQ;vzgz0e&%V{jJ?Qq64`V(z7M>&nJA_WxoB}@@(&A-4Xf>mFg2J;WVqZ2$zC&lL6LDAJduS zo&XM;TQ&Qc0gTotj1`-*W0dYHX%|+7Ctu^gJr22Nd2Pf*&^wm}T#g1fD=da669Fj@>Bm zS7cw{3j@zYkve^k;k>;Ixxv6;IRw)Ig4C5HH9m}ZZlox4@z!5@#kT3_M*n6(;HBC( zPCm2YRS+(J>zI~ifX&X`f)<14cC_|apK@qwz{Ixwl7L9g^3D

    `$#ZX@S$I{>#+E2SYMg5o9lZSiLJI=q_unzGFE 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

    U5iMt+?Msu5(H6ZU9Azc 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